From 4c201bcaaa2cd3b9c4e228e2eb7db1836880da10 Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Tue, 12 Jun 2018 23:12:44 +0200 Subject: [PATCH 001/469] HttpModules able to get injection. UmbracoModule + rest (if implemented) gets dependencies injected through ContainerUmbracoModule. --- src/Umbraco.Web/Routing/PublishedRouter.cs | 2 +- src/Umbraco.Web/Runtime/WebRuntime.cs | 2 + src/Umbraco.Web/UmbracoModule.cs | 94 ++++++++++++++++++---- 3 files changed, 81 insertions(+), 17 deletions(-) diff --git a/src/Umbraco.Web/Routing/PublishedRouter.cs b/src/Umbraco.Web/Routing/PublishedRouter.cs index fdc8540aa0..8e7d786e93 100644 --- a/src/Umbraco.Web/Routing/PublishedRouter.cs +++ b/src/Umbraco.Web/Routing/PublishedRouter.cs @@ -20,7 +20,7 @@ namespace Umbraco.Web.Routing { // fixme - make this public // fixme - making sense to have an interface? - internal class PublishedRouter + public class PublishedRouter { private readonly IWebRoutingSection _webRoutingSection; private readonly ContentFinderCollection _contentFinders; diff --git a/src/Umbraco.Web/Runtime/WebRuntime.cs b/src/Umbraco.Web/Runtime/WebRuntime.cs index 78610c01b8..9d08a4d85b 100644 --- a/src/Umbraco.Web/Runtime/WebRuntime.cs +++ b/src/Umbraco.Web/Runtime/WebRuntime.cs @@ -56,6 +56,8 @@ namespace Umbraco.Web.Runtime { base.Compose(container); + container.Register(); + // replace CoreRuntime's IProfiler registration container.RegisterSingleton(_ => _webProfiler); diff --git a/src/Umbraco.Web/UmbracoModule.cs b/src/Umbraco.Web/UmbracoModule.cs index d5fb8dee92..d41ad9ccd0 100644 --- a/src/Umbraco.Web/UmbracoModule.cs +++ b/src/Umbraco.Web/UmbracoModule.cs @@ -4,8 +4,10 @@ using System.Collections.Generic; using System.IO; using System.Text; using System.Web; +using System.Web.Mvc; using System.Web.Routing; using LightInject; +using Microsoft.Web.Infrastructure.DynamicModuleHelper; using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.IO; @@ -22,8 +24,38 @@ using Umbraco.Core.Services; using Umbraco.Web.Composing; using Umbraco.Web.PublishedCache; +[assembly: PreApplicationStartMethod(typeof(Umbraco.Web.ContainerUmbracoModule), "Start")] namespace Umbraco.Web { + public class ContainerUmbracoModule : IHttpModule + { + private UmbracoModule umbracoModule; + + public static void Start() + { + DynamicModuleUtility.RegisterModule(typeof(ContainerUmbracoModule)); + } + + public ContainerUmbracoModule() + { + + } + + public void Init(HttpApplication context) + { + // Should be extended with lazy list of modules from registry + // Example here: https://haacked.com/archive/2011/06/03/dependency-injection-with-asp-net-httpmodules.aspx/ + + umbracoModule = Current.Container.GetInstance(); + umbracoModule.Init(context); + } + + public void Dispose() + { + umbracoModule.Dispose(); + } + } + // also look at IOHelper.ResolveUrlsFromTextString - nightmarish?! // context.RewritePath supports ~/ or else must begin with /vdir @@ -38,44 +70,74 @@ namespace Umbraco.Web // get our dependencies injected manually, through properties, in // Init(). works for dependencies that are singletons. - [Inject] public IUmbracoSettingsSection UmbracoSettings { get; set; } - [Inject] public IGlobalSettings GlobalSettings { get; set; } - [Inject] public IUmbracoContextAccessor UmbracoContextAccessor { get; set; } - [Inject] public IPublishedSnapshotService PublishedSnapshotService { get; set; } - [Inject] public IUserService UserService { get; set; } - [Inject] public UrlProviderCollection UrlProviders { get; set; } - [Inject] public IRuntimeState Runtime { get; set; } - [Inject] public ILogger Logger { get; set; } - [Inject] internal PublishedRouter PublishedRouter { get; set; } - [Inject] internal IUmbracoDatabaseFactory DatabaseFactory { get; set; } - [Inject] internal IVariationContextAccessor VariationContextAccessor { get; set; } - + #endregion - public UmbracoModule() + public UmbracoModule() + : this( + Current.Container.GetInstance(), + Current.Container.GetInstance(), + Current.Container.GetInstance(), + Current.Container.GetInstance(), + Current.Container.GetInstance(), + Current.Container.GetInstance(), + Current.Container.GetInstance(), + Current.Container.GetInstance(), + Current.Container.GetInstance(), + Current.Container.GetInstance(), + Current.Container.GetInstance() + ) + { + } + + public UmbracoModule( + IUmbracoSettingsSection umbracoSettings, + IGlobalSettings globalSettings, + IUmbracoContextAccessor umbracoContextAccessor, + IPublishedSnapshotService publishedSnapshotService, + IUserService userService, + UrlProviderCollection urlProviders, + IRuntimeState runtime, + ILogger logger, + PublishedRouter publishedRouter, + IUmbracoDatabaseFactory databaseFactory, + IVariationContextAccessor variationContextAccessor + ) { _combinedRouteCollection = new Lazy(CreateRouteCollection); + + UmbracoSettings = umbracoSettings; + GlobalSettings = globalSettings; + UmbracoContextAccessor = umbracoContextAccessor; + PublishedSnapshotService = publishedSnapshotService; + UserService = userService; + UrlProviders = urlProviders; + Runtime = runtime; + Logger = logger; + PublishedRouter = publishedRouter; + DatabaseFactory = databaseFactory; + VariationContextAccessor = variationContextAccessor; } #region HttpModule event handlers @@ -543,10 +605,10 @@ namespace Umbraco.Web }; return; } - - // modules are *not* instanciated by the container so we have to + + // modules **are** instanciated by the container so we **don't** have to // get our dependencies injected manually, through properties. - Core.Composing.Current.Container.InjectProperties(this); + //Core.Composing.Current.Container.InjectProperties(this); app.BeginRequest += (sender, e) => { From a8c5cd425d14e936eaefaa2c082b390187e52ce3 Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Thu, 14 Jun 2018 18:46:25 +0200 Subject: [PATCH 002/469] DataTypeValidateAttribute now uses bastard injection. Notes on the UmbracoModule. Need to abstract resolving via Current.Container to remove LightInject refs. --- .../Routing/UmbracoModuleTests.cs | 3 ++- .../Editors/DataTypeValidateAttribute.cs | 27 ++++++++++++++----- src/Umbraco.Web/UmbracoModule.cs | 3 ++- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs b/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs index 703179b184..b87f092a1d 100644 --- a/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs +++ b/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs @@ -23,7 +23,8 @@ namespace Umbraco.Tests.Routing public override void SetUp() { base.SetUp(); - + + // fixme - use the full injected ctor, then we can ditch this one. //create the module _module = new UmbracoModule { diff --git a/src/Umbraco.Web/Editors/DataTypeValidateAttribute.cs b/src/Umbraco.Web/Editors/DataTypeValidateAttribute.cs index f8f2b5ac23..43093f563c 100644 --- a/src/Umbraco.Web/Editors/DataTypeValidateAttribute.cs +++ b/src/Umbraco.Web/Editors/DataTypeValidateAttribute.cs @@ -5,14 +5,15 @@ using System.Net.Http; using System.Web.Http.Controllers; using System.Web.Http.Filters; using AutoMapper; -using LightInject; using Umbraco.Core; +using Umbraco.Core.Composing; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Services; -using Umbraco.Web.Composing; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.WebApi; + +using LightInject; namespace Umbraco.Web.Editors { @@ -21,13 +22,25 @@ namespace Umbraco.Web.Editors /// internal sealed class DataTypeValidateAttribute : ActionFilterAttribute { - // LightInject can inject dependencies into properties + public IDataTypeService DataTypeService { get; } - [Inject] - public IDataTypeService DataTypeService { get; set; } + public PropertyEditorCollection PropertyEditors { get; } - [Inject] - public PropertyEditorCollection PropertyEditors { get; set; } + public DataTypeValidateAttribute() + : this(Current.Container.GetInstance(), Current.Container.GetInstance()) + { + } + + /// + /// For use in unit tests. Not possible to use as attribute ctor. + /// + /// + /// + public DataTypeValidateAttribute(IDataTypeService dataTypeService, PropertyEditorCollection propertyEditors) + { + DataTypeService = dataTypeService; + PropertyEditors = propertyEditors; + } public override void OnActionExecuting(HttpActionContext actionContext) { diff --git a/src/Umbraco.Web/UmbracoModule.cs b/src/Umbraco.Web/UmbracoModule.cs index d41ad9ccd0..0efb2a2f85 100644 --- a/src/Umbraco.Web/UmbracoModule.cs +++ b/src/Umbraco.Web/UmbracoModule.cs @@ -93,7 +93,8 @@ namespace Umbraco.Web internal IVariationContextAccessor VariationContextAccessor { get; set; } #endregion - + + // fixme - delete, just one usage in a test. public UmbracoModule() : this( Current.Container.GetInstance(), From 9b1bd3be60764675d00557044fd8adbf0fedabfc Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Thu, 14 Jun 2018 19:14:39 +0200 Subject: [PATCH 003/469] UmbracoModule parameterless ctor removed. More notes / fixme. --- .../Routing/UmbracoModuleTests.cs | 31 ++++++++++++++----- src/Umbraco.Web/UmbracoModule.cs | 18 ----------- 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs b/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs index b87f092a1d..8cbb790d8e 100644 --- a/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs +++ b/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs @@ -10,8 +10,16 @@ using Umbraco.Web; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Sync; -using Umbraco.Core.Configuration.UmbracoSettings; +using Umbraco.Core.Configuration.UmbracoSettings; +using Umbraco.Core.Models.PublishedContent; +using Umbraco.Core.Persistence; +using Umbraco.Core.Services; +using Umbraco.Web.PublishedCache; +using Umbraco.Web.Routing; +// fixme - abstract container +using LightInject; + namespace Umbraco.Tests.Routing { [TestFixture] @@ -24,13 +32,22 @@ namespace Umbraco.Tests.Routing { base.SetUp(); - // fixme - use the full injected ctor, then we can ditch this one. + // fixme - be able to get the UmbracoModule from the container. any reason settings were from testobjects? //create the module - _module = new UmbracoModule - { - GlobalSettings = TestObjects.GetGlobalSettings(), - Logger = Mock.Of() - }; + _module = new UmbracoModule + ( + TestObjects.GetUmbracoSettings(), + TestObjects.GetGlobalSettings(), + Mock.Of(), + Container.GetInstance(), + Container.GetInstance(), + new UrlProviderCollection(new IUrlProvider[0]), + Container.GetInstance(), + Mock.Of(), + null, // fixme - PublishedRouter complexities... + Container.GetInstance(), + Mock.Of() + ); var runtime = new RuntimeState(_module.Logger, new Lazy(), new Lazy(), Mock.Of(), _module.GlobalSettings); _module.Runtime = runtime; diff --git a/src/Umbraco.Web/UmbracoModule.cs b/src/Umbraco.Web/UmbracoModule.cs index 0efb2a2f85..7a12fd1130 100644 --- a/src/Umbraco.Web/UmbracoModule.cs +++ b/src/Umbraco.Web/UmbracoModule.cs @@ -94,24 +94,6 @@ namespace Umbraco.Web #endregion - // fixme - delete, just one usage in a test. - public UmbracoModule() - : this( - Current.Container.GetInstance(), - Current.Container.GetInstance(), - Current.Container.GetInstance(), - Current.Container.GetInstance(), - Current.Container.GetInstance(), - Current.Container.GetInstance(), - Current.Container.GetInstance(), - Current.Container.GetInstance(), - Current.Container.GetInstance(), - Current.Container.GetInstance(), - Current.Container.GetInstance() - ) - { - } - public UmbracoModule( IUmbracoSettingsSection umbracoSettings, IGlobalSettings globalSettings, From e3d77fb012a0d28eafa0468d687234846e7371af Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Sat, 16 Jun 2018 13:13:29 +0200 Subject: [PATCH 004/469] Current.Container abstracted. Builds, but fails for collection builder tests. --- src/Umbraco.Core/Composing/Current.cs | 4 +- src/Umbraco.Core/Composing/IContainer.cs | 18 ++++++++ .../Composing/LightInject/ContainerAdapter.cs | 46 +++++++++++++++++++ .../Composing/LightInjectExtensions.cs | 2 +- src/Umbraco.Core/IO/MediaFileSystem.cs | 2 +- src/Umbraco.Core/Umbraco.Core.csproj | 2 + src/Umbraco.Tests/CoreThings/UdiTests.cs | 2 +- src/Umbraco.Tests/Models/VariationTests.cs | 3 +- .../Scoping/ScopeEventDispatcherTests.cs | 6 ++- .../Web/TemplateUtilitiesTests.cs | 3 +- src/Umbraco.Web/Composing/Current.cs | 2 +- src/Umbraco.Web/Editors/SectionController.cs | 3 +- src/Umbraco.Web/Security/MembershipHelper.cs | 4 +- 13 files changed, 84 insertions(+), 13 deletions(-) create mode 100644 src/Umbraco.Core/Composing/IContainer.cs create mode 100644 src/Umbraco.Core/Composing/LightInject/ContainerAdapter.cs diff --git a/src/Umbraco.Core/Composing/Current.cs b/src/Umbraco.Core/Composing/Current.cs index a763b22e36..9e07b42dfb 100644 --- a/src/Umbraco.Core/Composing/Current.cs +++ b/src/Umbraco.Core/Composing/Current.cs @@ -27,7 +27,7 @@ namespace Umbraco.Core.Composing /// public static class Current { - private static IServiceContainer _container; + private static IContainer _container; private static IShortStringHelper _shortStringHelper; private static ILogger _logger; @@ -38,7 +38,7 @@ namespace Umbraco.Core.Composing /// /// Gets or sets the DI container. /// - internal static IServiceContainer Container + internal static IContainer Container { get { diff --git a/src/Umbraco.Core/Composing/IContainer.cs b/src/Umbraco.Core/Composing/IContainer.cs new file mode 100644 index 0000000000..4e9d8df3c5 --- /dev/null +++ b/src/Umbraco.Core/Composing/IContainer.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Umbraco.Core.Composing +{ + public interface IContainer + { + T TryGetInstance(); + T GetInstance(); + object ConcreteContainer { get; } + void RegisterSingleton(Func factory); + void Register(Func factory); + T RegisterCollectionBuilder(); + } +} diff --git a/src/Umbraco.Core/Composing/LightInject/ContainerAdapter.cs b/src/Umbraco.Core/Composing/LightInject/ContainerAdapter.cs new file mode 100644 index 0000000000..62e07683a3 --- /dev/null +++ b/src/Umbraco.Core/Composing/LightInject/ContainerAdapter.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using LightInject; + +namespace Umbraco.Core.Composing.LightInject +{ + public class ContainerAdapter : IContainer + { + private readonly IServiceContainer container; + + public object ConcreteContainer => container; + + public void RegisterSingleton(Func factory) + { + container.RegisterSingleton(f => factory(this)); + } + + public void Register(Func factory) + { + container.Register(f => factory(this)); + } + + public T RegisterCollectionBuilder() + { + return container.RegisterCollectionBuilder(); + } + + public ContainerAdapter(IServiceContainer container) + { + this.container = container; + } + + public T TryGetInstance() + { + return container.TryGetInstance(); + } + + public T GetInstance() + { + return container.GetInstance(); + } + } +} diff --git a/src/Umbraco.Core/Composing/LightInjectExtensions.cs b/src/Umbraco.Core/Composing/LightInjectExtensions.cs index 68ba48c803..314e03af84 100644 --- a/src/Umbraco.Core/Composing/LightInjectExtensions.cs +++ b/src/Umbraco.Core/Composing/LightInjectExtensions.cs @@ -47,7 +47,7 @@ namespace Umbraco.Core.Composing container.Register(_ => container); // configure the current container - Current.Container = container; + Current.Container = new LightInject.ContainerAdapter(container); } private class AssemblyScanner : IAssemblyScanner diff --git a/src/Umbraco.Core/IO/MediaFileSystem.cs b/src/Umbraco.Core/IO/MediaFileSystem.cs index 2c9773a9cb..b3fc2ccb61 100644 --- a/src/Umbraco.Core/IO/MediaFileSystem.cs +++ b/src/Umbraco.Core/IO/MediaFileSystem.cs @@ -40,7 +40,7 @@ namespace Umbraco.Core.IO { // due to how FileSystems is written at the moment, the ctor cannot be used to inject // dependencies, so we have to rely on property injection for anything we might need - Current.Container.InjectProperties(this); + ((IServiceContainer)Current.Container.ConcreteContainer).InjectProperties(this); UploadAutoFillProperties = new UploadAutoFillProperties(this, Logger, ContentConfig); } diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index e3ae9e31d5..ac8afb010e 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -166,9 +166,11 @@ + + diff --git a/src/Umbraco.Tests/CoreThings/UdiTests.cs b/src/Umbraco.Tests/CoreThings/UdiTests.cs index 62aa56bd14..4300401e18 100644 --- a/src/Umbraco.Tests/CoreThings/UdiTests.cs +++ b/src/Umbraco.Tests/CoreThings/UdiTests.cs @@ -27,7 +27,7 @@ namespace Umbraco.Tests.CoreThings var globalSettings = SettingsForTests.GenerateMockGlobalSettings(); container.Setup(x => x.GetInstance(typeof (TypeLoader))).Returns( new TypeLoader(NullCacheProvider.Instance, globalSettings, new ProfilingLogger(Mock.Of(), Mock.Of()))); - Current.Container = container.Object; + Current.Container = new Core.Composing.LightInject.ContainerAdapter(container.Object); Udi.ResetUdiTypes(); } diff --git a/src/Umbraco.Tests/Models/VariationTests.cs b/src/Umbraco.Tests/Models/VariationTests.cs index 044f8fa0cd..0b0ad8c7ec 100644 --- a/src/Umbraco.Tests/Models/VariationTests.cs +++ b/src/Umbraco.Tests/Models/VariationTests.cs @@ -4,6 +4,7 @@ using Moq; using NUnit.Framework; using Umbraco.Core.Cache; using Umbraco.Core.Composing; +using Umbraco.Core.Composing.LightInject; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; @@ -29,7 +30,7 @@ namespace Umbraco.Tests.Models Current.Reset(); var container = Mock.Of(); - Current.Container = container; + Current.Container = new ContainerAdapter(container); var dataEditors = new DataEditorCollection(new IDataEditor[] { diff --git a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs index 842fe50e04..64fa0a46ab 100644 --- a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs @@ -13,6 +13,7 @@ using Umbraco.Core.Scoping; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Entities; using Umbraco.Core.Composing; +using Umbraco.Core.Composing.LightInject; using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Services; @@ -31,9 +32,10 @@ namespace Umbraco.Tests.Scoping DoThing2 = null; DoThing3 = null; - Current.Container = new ServiceContainer(); + var lightinjectContainer = new ServiceContainer(); + Current.Container = new ContainerAdapter(lightinjectContainer); - _testObjects = new TestObjects(Current.Container); + _testObjects = new TestObjects(lightinjectContainer); Current.Container.RegisterSingleton(f => Current.Container); Current.Container.RegisterSingleton(factory => new FileSystems(factory.TryGetInstance())); Current.Container.RegisterCollectionBuilder(); diff --git a/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs b/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs index c6f7d8551e..867d4574f1 100644 --- a/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs +++ b/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs @@ -8,6 +8,7 @@ using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; +using Umbraco.Core.Composing.LightInject; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Logging; using Umbraco.Core.Models; @@ -43,7 +44,7 @@ namespace Umbraco.Tests.Web container.Setup(x => x.GetInstance(typeof(TypeLoader))).Returns( new TypeLoader(NullCacheProvider.Instance, SettingsForTests.GenerateMockGlobalSettings(), new ProfilingLogger(Mock.Of(), Mock.Of()))); container.Setup(x => x.GetInstance(typeof (ServiceContext))).Returns(serviceContext); - Current.Container = container.Object; + Current.Container = new ContainerAdapter(container.Object); Umbraco.Web.Composing.Current.UmbracoContextAccessor = new TestUmbracoContextAccessor(); diff --git a/src/Umbraco.Web/Composing/Current.cs b/src/Umbraco.Web/Composing/Current.cs index d295cf3d55..8c7f4e87ce 100644 --- a/src/Umbraco.Web/Composing/Current.cs +++ b/src/Umbraco.Web/Composing/Current.cs @@ -58,7 +58,7 @@ namespace Umbraco.Web.Composing /// /// Gets the DI container. /// - internal static IServiceContainer Container + internal static IContainer Container => CoreCurrent.Container; #region Temp & Special diff --git a/src/Umbraco.Web/Editors/SectionController.cs b/src/Umbraco.Web/Editors/SectionController.cs index 76821cfc33..1bed96bc0f 100644 --- a/src/Umbraco.Web/Editors/SectionController.cs +++ b/src/Umbraco.Web/Editors/SectionController.cs @@ -3,6 +3,7 @@ using AutoMapper; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Mvc; using System.Linq; +using LightInject; using Umbraco.Core.Composing; using Umbraco.Core.Models; using Umbraco.Web.Trees; @@ -31,7 +32,7 @@ namespace Umbraco.Web.Editors // since tree's by nature are controllers and require request contextual data - and then we have to // remember to inject properties - nasty indeed var appTreeController = new ApplicationTreeController(); - Current.Container.InjectProperties(appTreeController); + ((IServiceContainer)Current.Container.ConcreteContainer).InjectProperties(appTreeController); appTreeController.ControllerContext = ControllerContext; var dashboards = dashboardHelper.GetDashboards(Security.CurrentUser); diff --git a/src/Umbraco.Web/Security/MembershipHelper.cs b/src/Umbraco.Web/Security/MembershipHelper.cs index 6d28680877..7a56679086 100644 --- a/src/Umbraco.Web/Security/MembershipHelper.cs +++ b/src/Umbraco.Web/Security/MembershipHelper.cs @@ -73,7 +73,7 @@ namespace Umbraco.Web.Security // helpers are *not* instanciated by the container so we have to // get our dependencies injected manually, through properties. - Current.Container.InjectProperties(this); + ((IServiceContainer)Current.Container.ConcreteContainer).InjectProperties(this); } // used everywhere @@ -96,7 +96,7 @@ namespace Umbraco.Web.Security // helpers are *not* instanciated by the container so we have to // get our dependencies injected manually, through properties. - Current.Container.InjectProperties(this); + ((IServiceContainer)Current.Container.ConcreteContainer).InjectProperties(this); } #endregion From 0e37b3b61b57c30fda197b9fd85d6ab4bc553b09 Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Tue, 19 Jun 2018 18:19:10 +0200 Subject: [PATCH 005/469] ScopeEventDispatcherTest needs IServiceContainer to be registered. --- src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs index 64fa0a46ab..b295edfb8b 100644 --- a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs @@ -36,6 +36,10 @@ namespace Umbraco.Tests.Scoping Current.Container = new ContainerAdapter(lightinjectContainer); _testObjects = new TestObjects(lightinjectContainer); + + // fixme - move to container factory? + Current.Container.RegisterSingleton(f => (IServiceContainer)Current.Container.ConcreteContainer); + Current.Container.RegisterSingleton(f => Current.Container); Current.Container.RegisterSingleton(factory => new FileSystems(factory.TryGetInstance())); Current.Container.RegisterCollectionBuilder(); From e4aca5f5d81bff5cc8969d7de2a2d012db6373d1 Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Tue, 19 Jun 2018 18:53:25 +0200 Subject: [PATCH 006/469] Several property injections removed from Mvc artifacts and base classes --- .../Controllers/UmbLoginController.cs | 14 +++++ .../Controllers/UmbLoginStatusController.cs | 15 +++++- .../Controllers/UmbProfileController.cs | 13 +++++ .../Controllers/UmbRegisterController.cs | 15 +++++- .../Editors/AuthenticationController.cs | 12 ++++- .../Editors/BackOfficeController.cs | 9 +++- .../Editors/DashboardController.cs | 13 ++++- src/Umbraco.Web/Mvc/PluginController.cs | 29 +++++++--- src/Umbraco.Web/Mvc/RenderMvcController.cs | 8 +++ src/Umbraco.Web/Mvc/SurfaceController.cs | 14 +++++ .../Mvc/UmbracoAuthorizedController.cs | 18 ++++++- src/Umbraco.Web/Mvc/UmbracoController.cs | 34 ++++++++---- .../Mvc/UmbracoViewPageOfTModel.cs | 17 ++++-- .../WebApi/UmbracoApiController.cs | 19 ++++++- .../WebApi/UmbracoApiControllerBase.cs | 53 +++++++++++++------ .../WebApi/UmbracoAuthorizedApiController.cs | 17 +++++- src/Umbraco.Web/WebServices/TagsController.cs | 15 ++++++ 17 files changed, 268 insertions(+), 47 deletions(-) diff --git a/src/Umbraco.Web/Controllers/UmbLoginController.cs b/src/Umbraco.Web/Controllers/UmbLoginController.cs index 2b70f927b7..54703e28bd 100644 --- a/src/Umbraco.Web/Controllers/UmbLoginController.cs +++ b/src/Umbraco.Web/Controllers/UmbLoginController.cs @@ -2,11 +2,25 @@ using Umbraco.Web.Models; using Umbraco.Web.Mvc; using Umbraco.Core; +using Umbraco.Core.Cache; +using Umbraco.Core.Logging; +using Umbraco.Core.Persistence; +using Umbraco.Core.Services; namespace Umbraco.Web.Controllers { public class UmbLoginController : SurfaceController { + // fixme - delete? + public UmbLoginController() + { + } + + public UmbLoginController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger) + : base(umbracoContext, databaseFactory, services, applicationCache, logger, profilingLogger) + { + } + [HttpPost] public ActionResult HandleLogin([Bind(Prefix = "loginModel")]LoginModel model) { diff --git a/src/Umbraco.Web/Controllers/UmbLoginStatusController.cs b/src/Umbraco.Web/Controllers/UmbLoginStatusController.cs index 0364359673..8df46078ff 100644 --- a/src/Umbraco.Web/Controllers/UmbLoginStatusController.cs +++ b/src/Umbraco.Web/Controllers/UmbLoginStatusController.cs @@ -3,12 +3,25 @@ using System.Web.Security; using Umbraco.Web.Models; using Umbraco.Web.Mvc; using Umbraco.Core; +using Umbraco.Core.Cache; +using Umbraco.Core.Logging; +using Umbraco.Core.Persistence; +using Umbraco.Core.Services; namespace Umbraco.Web.Controllers { [MemberAuthorize] public class UmbLoginStatusController : SurfaceController - { + { + // fixme - delete? + public UmbLoginStatusController() + { + } + + public UmbLoginStatusController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger) : base(umbracoContext, databaseFactory, services, applicationCache, logger, profilingLogger) + { + } + [HttpPost] public ActionResult HandleLogout([Bind(Prefix = "logoutModel")]PostRedirectModel model) { diff --git a/src/Umbraco.Web/Controllers/UmbProfileController.cs b/src/Umbraco.Web/Controllers/UmbProfileController.cs index 27c5c32a02..5cb5d1b83e 100644 --- a/src/Umbraco.Web/Controllers/UmbProfileController.cs +++ b/src/Umbraco.Web/Controllers/UmbProfileController.cs @@ -4,12 +4,25 @@ using Umbraco.Web.Models; using Umbraco.Web.Mvc; using Umbraco.Core.Security; using Umbraco.Core; +using Umbraco.Core.Cache; +using Umbraco.Core.Logging; +using Umbraco.Core.Persistence; +using Umbraco.Core.Services; namespace Umbraco.Web.Controllers { [MemberAuthorize] public class UmbProfileController : SurfaceController { + // fixme - delete? + public UmbProfileController() + { + } + + public UmbProfileController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger) : base(umbracoContext, databaseFactory, services, applicationCache, logger, profilingLogger) + { + } + [HttpPost] public ActionResult HandleUpdateProfile([Bind(Prefix = "profileModel")] ProfileModel model) { diff --git a/src/Umbraco.Web/Controllers/UmbRegisterController.cs b/src/Umbraco.Web/Controllers/UmbRegisterController.cs index 64f54dd465..a0960e21ee 100644 --- a/src/Umbraco.Web/Controllers/UmbRegisterController.cs +++ b/src/Umbraco.Web/Controllers/UmbRegisterController.cs @@ -2,13 +2,26 @@ using System.Web.Mvc; using System.Web.Security; using Umbraco.Core; +using Umbraco.Core.Cache; +using Umbraco.Core.Logging; +using Umbraco.Core.Persistence; +using Umbraco.Core.Services; using Umbraco.Web.Models; using Umbraco.Web.Mvc; namespace Umbraco.Web.Controllers { public class UmbRegisterController : SurfaceController - { + { + // fixme - delete? + public UmbRegisterController() + { + } + + public UmbRegisterController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger) : base(umbracoContext, databaseFactory, services, applicationCache, logger, profilingLogger) + { + } + [HttpPost] public ActionResult HandleRegisterMember([Bind(Prefix = "registerModel")]RegisterModel model) { diff --git a/src/Umbraco.Web/Editors/AuthenticationController.cs b/src/Umbraco.Web/Editors/AuthenticationController.cs index 50cad49657..f4066520e2 100644 --- a/src/Umbraco.Web/Editors/AuthenticationController.cs +++ b/src/Umbraco.Web/Editors/AuthenticationController.cs @@ -11,8 +11,8 @@ using System.Web.Mvc; using AutoMapper; using Microsoft.AspNet.Identity; using Microsoft.AspNet.Identity.Owin; -using Microsoft.Owin; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Models; using Umbraco.Core.Models.Identity; using Umbraco.Core.Security; @@ -26,6 +26,7 @@ using Umbraco.Web.WebApi; using Umbraco.Web.WebApi.Filters; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; +using Umbraco.Core.Persistence; using Umbraco.Web.Composing; using IUser = Umbraco.Core.Models.Membership.IUser; @@ -53,6 +54,15 @@ namespace Umbraco.Web.Editors get { return _signInManager ?? (_signInManager = TryGetOwinContext().Result.GetBackOfficeSignInManager()); } } + public AuthenticationController() + { + } + + public AuthenticationController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger, IRuntimeState runtimeState) + : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, profilingLogger, runtimeState) + { + } + /// /// Returns the configuration for the backoffice user membership provider - used to configure the change password dialog /// diff --git a/src/Umbraco.Web/Editors/BackOfficeController.cs b/src/Umbraco.Web/Editors/BackOfficeController.cs index 1988808d23..f251956649 100644 --- a/src/Umbraco.Web/Editors/BackOfficeController.cs +++ b/src/Umbraco.Web/Editors/BackOfficeController.cs @@ -23,6 +23,7 @@ using Umbraco.Core.Logging; using Umbraco.Core.Manifest; using Umbraco.Core.Models.Identity; using Umbraco.Core.Models.Membership; +using Umbraco.Core.Persistence; using Umbraco.Core.Security; using Umbraco.Web.Models; using Umbraco.Web.Mvc; @@ -55,7 +56,13 @@ namespace Umbraco.Web.Editors private const string TokenPasswordResetCode = "PasswordResetCode"; private static readonly string[] TempDataTokenNames = { TokenExternalSignInError, TokenPasswordResetCode }; - public BackOfficeController(ManifestParser manifestParser, UmbracoFeatures features) + //public BackOfficeController(ManifestParser manifestParser, UmbracoFeatures features) + //{ + // _manifestParser = manifestParser; + // _features = features; + //} + + public BackOfficeController(ManifestParser manifestParser, UmbracoFeatures features, IGlobalSettings globalSettings, UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger) : base(globalSettings, umbracoContext, databaseFactory, services, applicationCache, logger, profilingLogger) { _manifestParser = manifestParser; _features = features; diff --git a/src/Umbraco.Web/Editors/DashboardController.cs b/src/Umbraco.Web/Editors/DashboardController.cs index d23e262412..37c72d2e02 100644 --- a/src/Umbraco.Web/Editors/DashboardController.cs +++ b/src/Umbraco.Web/Editors/DashboardController.cs @@ -3,8 +3,6 @@ using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Mvc; -using System.Linq; -using Umbraco.Core.IO; using Newtonsoft.Json.Linq; using System.Threading.Tasks; using System.Net.Http; @@ -16,6 +14,8 @@ using Umbraco.Core.Cache; using Umbraco.Web.WebApi; using Umbraco.Web.WebApi.Filters; using Umbraco.Core.Logging; +using Umbraco.Core.Persistence; +using Umbraco.Core.Services; namespace Umbraco.Web.Editors { @@ -27,6 +27,15 @@ namespace Umbraco.Web.Editors [WebApi.UmbracoAuthorize] public class DashboardController : UmbracoApiController { + public DashboardController() + { + } + + public DashboardController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger, IRuntimeState runtimeState) + : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, profilingLogger, runtimeState) + { + } + //we have baseurl as a param to make previewing easier, so we can test with a dev domain from client side [ValidateAngularAntiForgeryToken] public async Task GetRemoteDashboardContent(string section, string baseUrl = "https://dashboard.umbraco.org/") diff --git a/src/Umbraco.Web/Mvc/PluginController.cs b/src/Umbraco.Web/Mvc/PluginController.cs index 6b5f111585..6e44cca112 100644 --- a/src/Umbraco.Web/Mvc/PluginController.cs +++ b/src/Umbraco.Web/Mvc/PluginController.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Concurrent; using System.Web.Mvc; -using LightInject; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Logging; @@ -36,37 +35,31 @@ namespace Umbraco.Web.Mvc /// /// Gets or sets the Umbraco context. /// - [Inject] public virtual UmbracoContext UmbracoContext { get; set; } /// /// Gets or sets the database context. /// - [Inject] public IUmbracoDatabaseFactory DatabaseFactory { get; set; } /// /// Gets or sets the services context. /// - [Inject] public ServiceContext Services { get; set; } /// /// Gets or sets the application cache. /// - [Inject] public CacheHelper ApplicationCache { get; set; } /// /// Gets or sets the logger. /// - [Inject] public ILogger Logger { get; set; } /// /// Gets or sets the profiling logger. /// - [Inject] public ProfilingLogger ProfilingLogger { get; set; } /// @@ -95,6 +88,28 @@ namespace Umbraco.Web.Mvc /// internal PluginControllerMetadata Metadata => GetMetadata(GetType()); + protected PluginController() + : this( + Current.Container.GetInstance(), + Current.Container.GetInstance(), + Current.Container.GetInstance(), + Current.Container.GetInstance(), + Current.Container.GetInstance(), + Current.Container.GetInstance() + ) + { + } + + protected PluginController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger) + { + UmbracoContext = umbracoContext; + DatabaseFactory = databaseFactory; + Services = services; + ApplicationCache = applicationCache; + Logger = logger; + ProfilingLogger = profilingLogger; + } + /// /// Gets metadata for a controller type. /// diff --git a/src/Umbraco.Web/Mvc/RenderMvcController.cs b/src/Umbraco.Web/Mvc/RenderMvcController.cs index e7f336dcde..8077dd48bf 100644 --- a/src/Umbraco.Web/Mvc/RenderMvcController.cs +++ b/src/Umbraco.Web/Mvc/RenderMvcController.cs @@ -2,8 +2,10 @@ using System.Web.Mvc; using Umbraco.Core; using Umbraco.Core.Cache; +using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Models.PublishedContent; +using Umbraco.Core.Persistence; using Umbraco.Core.Services; using Umbraco.Web.Models; using Umbraco.Web.Routing; @@ -18,11 +20,17 @@ namespace Umbraco.Web.Mvc { private PublishedRequest _publishedRequest; + // fixme - delete? public RenderMvcController() { ActionInvoker = new RenderActionInvoker(); } + public RenderMvcController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger) : base(globalSettings, umbracoContext, databaseFactory, services, applicationCache, logger, profilingLogger) + { + ActionInvoker = new RenderActionInvoker(); + } + /// /// Gets the Umbraco context. /// diff --git a/src/Umbraco.Web/Mvc/SurfaceController.cs b/src/Umbraco.Web/Mvc/SurfaceController.cs index 043841f279..bb7538ebe8 100644 --- a/src/Umbraco.Web/Mvc/SurfaceController.cs +++ b/src/Umbraco.Web/Mvc/SurfaceController.cs @@ -1,7 +1,11 @@ using System; using Umbraco.Core; using System.Collections.Specialized; +using Umbraco.Core.Cache; +using Umbraco.Core.Logging; using Umbraco.Core.Models.PublishedContent; +using Umbraco.Core.Persistence; +using Umbraco.Core.Services; namespace Umbraco.Web.Mvc { @@ -12,6 +16,16 @@ namespace Umbraco.Web.Mvc [MergeParentContextViewData] public abstract class SurfaceController : PluginController { + // fixme - delete? + protected SurfaceController() + { + } + + protected SurfaceController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger) + : base(umbracoContext, databaseFactory, services, applicationCache, logger, profilingLogger) + { + } + /// /// Redirects to the Umbraco page with the given id /// diff --git a/src/Umbraco.Web/Mvc/UmbracoAuthorizedController.cs b/src/Umbraco.Web/Mvc/UmbracoAuthorizedController.cs index d0e3ec7b61..e9d287f0df 100644 --- a/src/Umbraco.Web/Mvc/UmbracoAuthorizedController.cs +++ b/src/Umbraco.Web/Mvc/UmbracoAuthorizedController.cs @@ -1,4 +1,10 @@ -namespace Umbraco.Web.Mvc +using Umbraco.Core.Cache; +using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; +using Umbraco.Core.Persistence; +using Umbraco.Core.Services; + +namespace Umbraco.Web.Mvc { /// /// Provides a base class for authorized Umbraco controllers. @@ -10,5 +16,13 @@ [UmbracoAuthorize] [DisableBrowserCache] public abstract class UmbracoAuthorizedController : UmbracoController - { } + { + protected UmbracoAuthorizedController() + { + } + + protected UmbracoAuthorizedController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger) : base(globalSettings, umbracoContext, databaseFactory, services, applicationCache, logger, profilingLogger) + { + } + } } diff --git a/src/Umbraco.Web/Mvc/UmbracoController.cs b/src/Umbraco.Web/Mvc/UmbracoController.cs index 6f4034fe85..520724bcaf 100644 --- a/src/Umbraco.Web/Mvc/UmbracoController.cs +++ b/src/Umbraco.Web/Mvc/UmbracoController.cs @@ -1,10 +1,9 @@ using System; using System.Web; using System.Web.Mvc; -using LightInject; using Microsoft.Owin; -using Umbraco.Core; using Umbraco.Core.Cache; +using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Persistence; @@ -33,43 +32,36 @@ namespace Umbraco.Web.Mvc /// /// Gets or sets the Umbraco context. /// - [Inject] public virtual IGlobalSettings GlobalSettings { get; set; } /// /// Gets or sets the Umbraco context. /// - [Inject] public virtual UmbracoContext UmbracoContext { get; set; } /// /// Gets or sets the database context. /// - [Inject] public IUmbracoDatabaseFactory DatabaseFactory { get; set; } /// /// Gets or sets the services context. /// - [Inject] public ServiceContext Services { get; set; } /// /// Gets or sets the application cache. /// - [Inject] public CacheHelper ApplicationCache { get; set; } /// /// Gets or sets the logger. /// - [Inject] public ILogger Logger { get; set; } /// /// Gets or sets the profiling logger. /// - [Inject] public ProfilingLogger ProfilingLogger { get; set; } protected IOwinContext OwinContext => Request.GetOwinContext(); @@ -89,5 +81,29 @@ namespace Umbraco.Web.Mvc /// Gets the web security helper. /// public virtual WebSecurity Security => UmbracoContext.Security; + + protected UmbracoController() + : this( + Current.Container.GetInstance(), + Current.Container.GetInstance(), + Current.Container.GetInstance(), + Current.Container.GetInstance(), + Current.Container.GetInstance(), + Current.Container.GetInstance(), + Current.Container.GetInstance() + ) + { + } + + protected UmbracoController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger) + { + GlobalSettings = globalSettings; + UmbracoContext = umbracoContext; + DatabaseFactory = databaseFactory; + Services = services; + ApplicationCache = applicationCache; + Logger = logger; + ProfilingLogger = profilingLogger; + } } } diff --git a/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs b/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs index f817b74120..25987d6f30 100644 --- a/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs +++ b/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs @@ -3,7 +3,6 @@ using System.Text; using System.Web; using System.Web.Mvc; using System.Web.WebPages; -using LightInject; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; @@ -34,13 +33,11 @@ namespace Umbraco.Web.Mvc /// /// Gets or sets the database context. /// - [Inject] public ServiceContext Services { get; set; } /// /// Gets or sets the application cache. /// - [Inject] public CacheHelper ApplicationCache { get; set; } // fixme @@ -109,6 +106,20 @@ namespace Umbraco.Web.Mvc /// public MembershipHelper Members => Umbraco.MembershipHelper; + protected UmbracoViewPage() + : this( + Current.Container.GetInstance(), + Current.Container.GetInstance() + ) + { + } + + protected UmbracoViewPage(ServiceContext services, CacheHelper applicationCache) + { + Services = services; + ApplicationCache = applicationCache; + } + // view logic below: /// diff --git a/src/Umbraco.Web/WebApi/UmbracoApiController.cs b/src/Umbraco.Web/WebApi/UmbracoApiController.cs index 3616f032d8..61c3f89d41 100644 --- a/src/Umbraco.Web/WebApi/UmbracoApiController.cs +++ b/src/Umbraco.Web/WebApi/UmbracoApiController.cs @@ -1,4 +1,10 @@ -using Umbraco.Core.Composing; +using Umbraco.Core; +using Umbraco.Core.Cache; +using Umbraco.Core.Composing; +using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; +using Umbraco.Core.Persistence; +using Umbraco.Core.Services; namespace Umbraco.Web.WebApi { @@ -6,5 +12,14 @@ namespace Umbraco.Web.WebApi /// Provides a base class for auto-routed Umbraco API controllers. /// public abstract class UmbracoApiController : UmbracoApiControllerBase, IDiscoverable - { } + { + protected UmbracoApiController() + { + } + + protected UmbracoApiController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger, IRuntimeState runtimeState) + : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, profilingLogger, runtimeState) + { + } + } } diff --git a/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs b/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs index eff5a9cee7..45dedea4ab 100644 --- a/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs +++ b/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs @@ -1,10 +1,10 @@ using System; using System.Web; using System.Web.Http; -using LightInject; using Microsoft.Owin; using Umbraco.Core; using Umbraco.Core.Cache; +using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Persistence; @@ -36,50 +36,42 @@ namespace Umbraco.Web.WebApi /// /// Gets or sets the Umbraco context. /// - [Inject] - public virtual IGlobalSettings GlobalSettings { get; set; } + public virtual IGlobalSettings GlobalSettings { get; } /// /// Gets or sets the Umbraco context. /// - [Inject] - public virtual UmbracoContext UmbracoContext { get; set; } + public virtual UmbracoContext UmbracoContext { get; } /// /// Gets or sets the sql context. /// - [Inject] - public ISqlContext SqlContext { get; set; } + public ISqlContext SqlContext { get; } /// /// Gets or sets the services context. /// - [Inject] - public ServiceContext Services { get; set; } + public ServiceContext Services { get; } /// /// Gets or sets the application cache. /// - [Inject] - public CacheHelper ApplicationCache { get; set; } + public CacheHelper ApplicationCache { get; } /// /// Gets or sets the logger. /// - [Inject] - public ILogger Logger { get; set; } + public ILogger Logger { get; } /// /// Gets or sets the profiling logger. /// - [Inject] - public ProfilingLogger ProfilingLogger { get; set; } + public ProfilingLogger ProfilingLogger { get; } /// /// Gets or sets the runtime state. /// - [Inject] - internal IRuntimeState RuntimeState { get; set; } + internal IRuntimeState RuntimeState { get; } /// /// Gets the application url. @@ -102,6 +94,33 @@ namespace Umbraco.Web.WebApi /// public WebSecurity Security => UmbracoContext.Security; + protected UmbracoApiControllerBase() + : this( + Current.Container.GetInstance(), + Current.Container.GetInstance(), + Current.Container.GetInstance(), + Current.Container.GetInstance(), + Current.Container.GetInstance(), + Current.Container.GetInstance(), + Current.Container.GetInstance(), + Current.Container.GetInstance() + ) + { + } + + // fixme - Inject fewer things? (Aggregate more) + protected UmbracoApiControllerBase(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger, IRuntimeState runtimeState) + { + GlobalSettings = globalSettings; + UmbracoContext = umbracoContext; + SqlContext = sqlContext; + Services = services; + ApplicationCache = applicationCache; + Logger = logger; + ProfilingLogger = profilingLogger; + RuntimeState = runtimeState; + } + /// /// Tries to get the current HttpContext. /// diff --git a/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs b/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs index ad217b43fd..5d60200ed0 100644 --- a/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs +++ b/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs @@ -1,6 +1,12 @@ -using Umbraco.Web.WebApi.Filters; +using Umbraco.Core; +using Umbraco.Core.Cache; +using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; +using Umbraco.Web.WebApi.Filters; using Umbraco.Core.Models.Identity; +using Umbraco.Core.Persistence; using Umbraco.Core.Security; +using Umbraco.Core.Services; namespace Umbraco.Web.WebApi { @@ -25,5 +31,14 @@ namespace Umbraco.Web.WebApi protected BackOfficeUserManager UserManager => _userManager ?? (_userManager = TryGetOwinContext().Result.GetBackOfficeUserManager()); + + protected UmbracoAuthorizedApiController() + { + } + + protected UmbracoAuthorizedApiController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger, IRuntimeState runtimeState) + : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, profilingLogger, runtimeState) + { + } } } diff --git a/src/Umbraco.Web/WebServices/TagsController.cs b/src/Umbraco.Web/WebServices/TagsController.cs index 6241cfacf0..786bac2693 100644 --- a/src/Umbraco.Web/WebServices/TagsController.cs +++ b/src/Umbraco.Web/WebServices/TagsController.cs @@ -1,4 +1,10 @@ using System.Collections.Generic; +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.Models; using Umbraco.Web.WebApi; @@ -13,6 +19,15 @@ namespace Umbraco.Web.WebServices /// public class TagsController : UmbracoApiController { + public TagsController() + { + } + + public TagsController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger, IRuntimeState runtimeState) + : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, profilingLogger, runtimeState) + { + } + /// /// Get every tag stored in the database (with optional group) /// From ea9ab66ba7bc49a319312f3184d8e0f424704c5e Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Tue, 19 Jun 2018 18:59:57 +0200 Subject: [PATCH 007/469] Removed an extra using LI. :) --- src/Umbraco.Web/Editors/DataTypeValidateAttribute.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Umbraco.Web/Editors/DataTypeValidateAttribute.cs b/src/Umbraco.Web/Editors/DataTypeValidateAttribute.cs index 43093f563c..91bde1801c 100644 --- a/src/Umbraco.Web/Editors/DataTypeValidateAttribute.cs +++ b/src/Umbraco.Web/Editors/DataTypeValidateAttribute.cs @@ -13,8 +13,6 @@ using Umbraco.Core.Services; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.WebApi; -using LightInject; - namespace Umbraco.Web.Editors { /// From 7af04b0a2fc0f5b21d7f19a4321dfe606e86e550 Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Tue, 19 Jun 2018 19:59:12 +0200 Subject: [PATCH 008/469] Tests pass again --- src/Umbraco.Core/Composing/IContainer.cs | 1 + .../Composing/LightInject/ContainerAdapter.cs | 5 +++++ .../Routing/RenderRouteHandlerTests.cs | 8 +++++++ .../Stubs/TestControllerFactory.cs | 3 ++- ...RenderIndexActionSelectorAttributeTests.cs | 7 ++++-- .../Web/Mvc/SurfaceControllerTests.cs | 22 ++++++++++++++----- 6 files changed, 37 insertions(+), 9 deletions(-) diff --git a/src/Umbraco.Core/Composing/IContainer.cs b/src/Umbraco.Core/Composing/IContainer.cs index 4e9d8df3c5..a1206c5816 100644 --- a/src/Umbraco.Core/Composing/IContainer.cs +++ b/src/Umbraco.Core/Composing/IContainer.cs @@ -10,6 +10,7 @@ namespace Umbraco.Core.Composing { T TryGetInstance(); T GetInstance(); + object GetInstance(Type parameterType); object ConcreteContainer { get; } void RegisterSingleton(Func factory); void Register(Func factory); diff --git a/src/Umbraco.Core/Composing/LightInject/ContainerAdapter.cs b/src/Umbraco.Core/Composing/LightInject/ContainerAdapter.cs index 62e07683a3..906b66bcb1 100644 --- a/src/Umbraco.Core/Composing/LightInject/ContainerAdapter.cs +++ b/src/Umbraco.Core/Composing/LightInject/ContainerAdapter.cs @@ -42,5 +42,10 @@ namespace Umbraco.Core.Composing.LightInject { return container.GetInstance(); } + + public object GetInstance(Type type) + { + return container.GetInstance(type); + } } } diff --git a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs index c64c70e65a..7e32921363 100644 --- a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs +++ b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs @@ -6,6 +6,7 @@ using LightInject; using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Tests.TestHelpers; @@ -17,7 +18,10 @@ using Umbraco.Web.Routing; using Umbraco.Web.WebApi; using Umbraco.Core.Strings; using Umbraco.Core.Composing; +using Umbraco.Core.Configuration; using Umbraco.Core.Models.PublishedContent; +using Umbraco.Core.Persistence; +using Umbraco.Core.Services; using Umbraco.Tests.PublishedContent; using Umbraco.Tests.Testing; using Umbraco.Tests.Testing.Objects.Accessors; @@ -182,6 +186,10 @@ namespace Umbraco.Tests.Routing /// public class CustomDocumentController : RenderMvcController { + public CustomDocumentController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger) : base(globalSettings, umbracoContext, databaseFactory, services, applicationCache, logger, profilingLogger) + { + } + public ActionResult HomePage(ContentModel model) { return View(); diff --git a/src/Umbraco.Tests/TestHelpers/Stubs/TestControllerFactory.cs b/src/Umbraco.Tests/TestHelpers/Stubs/TestControllerFactory.cs index 5e2ce24863..23dc0d4347 100644 --- a/src/Umbraco.Tests/TestHelpers/Stubs/TestControllerFactory.cs +++ b/src/Umbraco.Tests/TestHelpers/Stubs/TestControllerFactory.cs @@ -47,7 +47,8 @@ namespace Umbraco.Tests.TestHelpers.Stubs var allParams = ctor.GetParameters().ToArray(); foreach (var parameter in allParams) { - var found = possibleParams.SingleOrDefault(x => x.GetType() == parameter.ParameterType); + var found = possibleParams.SingleOrDefault(x => x.GetType() == parameter.ParameterType) + ?? Current.Container.GetInstance(parameter.ParameterType); if (found != null) args.Add(found); } if (args.Count == allParams.Length) diff --git a/src/Umbraco.Tests/Web/Mvc/RenderIndexActionSelectorAttributeTests.cs b/src/Umbraco.Tests/Web/Mvc/RenderIndexActionSelectorAttributeTests.cs index f4c15f7c19..bf29f7e35e 100644 --- a/src/Umbraco.Tests/Web/Mvc/RenderIndexActionSelectorAttributeTests.cs +++ b/src/Umbraco.Tests/Web/Mvc/RenderIndexActionSelectorAttributeTests.cs @@ -9,6 +9,7 @@ using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; +using Umbraco.Core.Composing; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Logging; using Umbraco.Core.Profiling; @@ -17,12 +18,12 @@ using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Stubs; using Umbraco.Tests.Testing.Objects.Accessors; using Umbraco.Web; -using Umbraco.Web.Composing; using Umbraco.Web.Models; using Umbraco.Web.Mvc; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; using Umbraco.Web.Security; +using Current = Umbraco.Web.Composing.Current; namespace Umbraco.Tests.Web.Mvc { @@ -33,6 +34,7 @@ namespace Umbraco.Tests.Web.Mvc public void SetUp() { Current.UmbracoContextAccessor = new TestUmbracoContextAccessor(); + Core.Composing.Current.Container = Mock.Of(); } [TearDown] @@ -156,7 +158,8 @@ namespace Umbraco.Tests.Web.Mvc } public class MatchesDefaultIndexController : RenderMvcController - { } + { + } public class MatchesOverriddenIndexController : RenderMvcController { diff --git a/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs b/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs index 4186c56636..f9cff5af9b 100644 --- a/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs +++ b/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs @@ -7,6 +7,7 @@ using System.Web.Security; using Moq; using NUnit.Framework; using Umbraco.Core.Cache; +using Umbraco.Core.Composing; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Dictionary; using Umbraco.Core.Models.PublishedContent; @@ -16,11 +17,11 @@ using Umbraco.Tests.TestHelpers.Stubs; using Umbraco.Tests.Testing; using Umbraco.Tests.Testing.Objects.Accessors; using Umbraco.Web; -using Umbraco.Web.Composing; using Umbraco.Web.Mvc; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; using Umbraco.Web.Security; +using Current = Umbraco.Web.Composing.Current; namespace Umbraco.Tests.Web.Mvc { @@ -49,7 +50,7 @@ namespace Umbraco.Tests.Web.Mvc new TestVariationContextAccessor(), true); - var ctrl = new TestSurfaceController { UmbracoContext = umbracoContext }; + var ctrl = new TestSurfaceController(umbracoContext); var result = ctrl.Index(); @@ -71,7 +72,7 @@ namespace Umbraco.Tests.Web.Mvc new TestVariationContextAccessor(), true); - var ctrl = new TestSurfaceController { UmbracoContext = umbCtx }; + var ctrl = new TestSurfaceController(umbCtx); Assert.IsNotNull(ctrl.UmbracoContext); } @@ -91,7 +92,7 @@ namespace Umbraco.Tests.Web.Mvc new TestVariationContextAccessor(), true); - var controller = new TestSurfaceController { UmbracoContext = umbracoContext }; + var controller = new TestSurfaceController(umbracoContext); Container.Register(_ => umbracoContext); Container.InjectProperties(controller); @@ -132,7 +133,7 @@ namespace Umbraco.Tests.Web.Mvc new ServiceContext(), CacheHelper.CreateDisabledCacheHelper()); - var ctrl = new TestSurfaceController { UmbracoContext = umbracoContext, Umbraco = helper }; + var ctrl = new TestSurfaceController(umbracoContext, helper); var result = ctrl.GetContent(2) as PublishedContentResult; Assert.IsNotNull(result); @@ -171,7 +172,7 @@ namespace Umbraco.Tests.Web.Mvc var routeData = new RouteData(); routeData.DataTokens.Add(Core.Constants.Web.UmbracoRouteDefinitionDataToken, routeDefinition); - var ctrl = new TestSurfaceController { UmbracoContext = umbracoContext, Umbraco = new UmbracoHelper() }; + var ctrl = new TestSurfaceController(umbracoContext, new UmbracoHelper()); ctrl.ControllerContext = new ControllerContext(contextBase, routeData, ctrl); var result = ctrl.GetContentFromCurrentPage() as PublishedContentResult; @@ -181,6 +182,15 @@ namespace Umbraco.Tests.Web.Mvc public class TestSurfaceController : SurfaceController { + public TestSurfaceController(UmbracoContext ctx, UmbracoHelper helper = null) + : base(ctx, null, new ServiceContext(), Mock.Of(), null, null) + { + if (helper != null) + { + Umbraco = helper; + } + } + public ActionResult Index() { return View(); From db2ad8778455fbb3a06fdef30aff0459485dc2bd Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Wed, 20 Jun 2018 19:57:42 +0200 Subject: [PATCH 009/469] Removed named service reference from repo ctors. Now registered with factory method that looks up services by name instead. --- .../RepositoryCompositionRoot.cs | 29 +++++++++++++------ src/Umbraco.Core/IO/FileSystems.cs | 3 ++ .../Repositories/Implement/AuditRepository.cs | 4 +-- .../Implement/PartialViewMacroRepository.cs | 5 ++-- .../Implement/PartialViewRepository.cs | 3 +- .../Implement/RelationRepository.cs | 4 +-- .../Implement/ScriptRepository.cs | 3 +- .../Implement/StylesheetRepository.cs | 3 +- .../Repositories/Implement/TaskRepository.cs | 4 +-- .../Implement/TaskTypeRepository.cs | 4 +-- .../Implement/TemplateRepository.cs | 5 ++-- src/Umbraco.Web/Mvc/PluginController.cs | 12 ++++---- 12 files changed, 40 insertions(+), 39 deletions(-) diff --git a/src/Umbraco.Core/Composing/CompositionRoots/RepositoryCompositionRoot.cs b/src/Umbraco.Core/Composing/CompositionRoots/RepositoryCompositionRoot.cs index 26a95af801..2323da165a 100644 --- a/src/Umbraco.Core/Composing/CompositionRoots/RepositoryCompositionRoot.cs +++ b/src/Umbraco.Core/Composing/CompositionRoots/RepositoryCompositionRoot.cs @@ -1,8 +1,12 @@ using System; using LightInject; using Umbraco.Core.Cache; +using Umbraco.Core.Configuration.UmbracoSettings; +using Umbraco.Core.IO; +using Umbraco.Core.Logging; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Composing.CompositionRoots { @@ -36,7 +40,7 @@ namespace Umbraco.Core.Composing.CompositionRoots // some repositories have an annotated ctor parameter to pick the right cache helper // repositories - container.RegisterSingleton(); + container.RegisterSingleton(f => new AuditRepository(f.GetInstance(), f.GetInstance(DisabledCache), f.GetInstance())); container.RegisterSingleton(); container.RegisterSingleton(); container.RegisterSingleton(); @@ -59,23 +63,30 @@ namespace Umbraco.Core.Composing.CompositionRoots container.RegisterSingleton(); container.RegisterSingleton(); container.RegisterSingleton(); - container.RegisterSingleton(); + container.RegisterSingleton(f => new RelationRepository(f.GetInstance(), f.GetInstance(DisabledCache), f.GetInstance(), f.GetInstance())); container.RegisterSingleton(); container.RegisterSingleton(); container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); + container.RegisterSingleton(f => new TaskRepository(f.GetInstance(), f.GetInstance(DisabledCache), f.GetInstance())); + container.RegisterSingleton(f => new TaskTypeRepository(f.GetInstance(), f.GetInstance(DisabledCache), f.GetInstance())); + container.RegisterSingleton(f => new TemplateRepository( + f.GetInstance(), + f.GetInstance(), + f.GetInstance(), + f.GetInstance(), + f.GetInstance(Constants.Composing.FileSystems.MasterpageFileSystem), + f.GetInstance(Constants.Composing.FileSystems.ViewFileSystem) + )); container.RegisterSingleton(); container.RegisterSingleton(); container.RegisterSingleton(); // repositories that depend on a filesystem // these have an annotated ctor parameter to pick the right file system - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); + container.RegisterSingleton(f => new PartialViewMacroRepository(f.GetInstance("PartialViewMacroFileSystem"))); + container.RegisterSingleton(f => new PartialViewRepository(f.GetInstance("PartialViewFileSystem"))); + container.RegisterSingleton(f => new ScriptRepository(f.GetInstance("ScriptFileSystem"), f.GetInstance())); + container.RegisterSingleton(f => new StylesheetRepository(f.GetInstance("StylesheetFileSystem"))); } } } diff --git a/src/Umbraco.Core/IO/FileSystems.cs b/src/Umbraco.Core/IO/FileSystems.cs index 5d7088b0e1..2fb5941b17 100644 --- a/src/Umbraco.Core/IO/FileSystems.cs +++ b/src/Umbraco.Core/IO/FileSystems.cs @@ -302,6 +302,9 @@ namespace Umbraco.Core.IO // could be optimized by having FileSystemWrapper inherit from ShadowWrapper, maybe var innerFs = GetUnderlyingFileSystemNoCache(alias, fallback); var shadowWrapper = new ShadowWrapper(innerFs, "typed/" + alias, () => IsScoped()); + + // fixme - switch to using container. where are these registered? + var fs = (IFileSystem) Activator.CreateInstance(typeof(TFileSystem), shadowWrapper); _wrappers.Add(shadowWrapper); // keeping a reference to the wrapper return fs; diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/AuditRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/AuditRepository.cs index e171077bb7..d643e1f5a5 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/AuditRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/AuditRepository.cs @@ -1,10 +1,8 @@ using System; using System.Collections.Generic; using System.Linq; -using LightInject; using NPoco; using Umbraco.Core.Cache; -using Umbraco.Core.Composing.CompositionRoots; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Persistence.DatabaseModelDefinitions; @@ -16,7 +14,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { internal class AuditRepository : NPocoRepositoryBase, IAuditRepository { - public AuditRepository(IScopeAccessor scopeAccessor, [Inject(RepositoryCompositionRoot.DisabledCache)] CacheHelper cache, ILogger logger) + public AuditRepository(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger) : base(scopeAccessor, cache, logger) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/PartialViewMacroRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/PartialViewMacroRepository.cs index 741bb98e7c..879766fc81 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/PartialViewMacroRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/PartialViewMacroRepository.cs @@ -1,5 +1,4 @@ -using LightInject; -using Umbraco.Core.IO; +using Umbraco.Core.IO; using Umbraco.Core.Models; namespace Umbraco.Core.Persistence.Repositories.Implement @@ -7,7 +6,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement internal class PartialViewMacroRepository : PartialViewRepository, IPartialViewMacroRepository { - public PartialViewMacroRepository([Inject("PartialViewMacroFileSystem")] IFileSystem fileSystem) + public PartialViewMacroRepository(IFileSystem fileSystem) : base(fileSystem) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/PartialViewRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/PartialViewRepository.cs index 2aa63813e5..a996251927 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/PartialViewRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/PartialViewRepository.cs @@ -2,7 +2,6 @@ using System.IO; using System.Linq; using System.Text; -using LightInject; using Umbraco.Core.IO; using Umbraco.Core.Models; @@ -10,7 +9,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { internal class PartialViewRepository : FileRepository, IPartialViewRepository { - public PartialViewRepository([Inject("PartialViewFileSystem")] IFileSystem fileSystem) + public PartialViewRepository(IFileSystem fileSystem) : base(fileSystem) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/RelationRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/RelationRepository.cs index f79344028f..bb153beda9 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/RelationRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/RelationRepository.cs @@ -1,10 +1,8 @@ using System; using System.Collections.Generic; using System.Linq; -using LightInject; using NPoco; using Umbraco.Core.Cache; -using Umbraco.Core.Composing.CompositionRoots; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Entities; @@ -22,7 +20,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { private readonly IRelationTypeRepository _relationTypeRepository; - public RelationRepository(IScopeAccessor scopeAccessor, [Inject(RepositoryCompositionRoot.DisabledCache)] CacheHelper cache, ILogger logger, IRelationTypeRepository relationTypeRepository) + public RelationRepository(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger, IRelationTypeRepository relationTypeRepository) : base(scopeAccessor, cache, logger) { _relationTypeRepository = relationTypeRepository; diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/ScriptRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/ScriptRepository.cs index d5719554c9..735a1aa74f 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/ScriptRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/ScriptRepository.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using LightInject; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; using Umbraco.Core.Models; @@ -16,7 +15,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { private readonly IContentSection _contentConfig; - public ScriptRepository([Inject("ScriptFileSystem")] IFileSystem fileSystem, IContentSection contentConfig) + public ScriptRepository(IFileSystem fileSystem, IContentSection contentConfig) : base(fileSystem) { _contentConfig = contentConfig ?? throw new ArgumentNullException(nameof(contentConfig)); diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/StylesheetRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/StylesheetRepository.cs index 73dcb44fef..8139f4948e 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/StylesheetRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/StylesheetRepository.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using LightInject; using Umbraco.Core.IO; using Umbraco.Core.Models; @@ -12,7 +11,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement /// internal class StylesheetRepository : FileRepository, IStylesheetRepository { - public StylesheetRepository([Inject("StylesheetFileSystem")] IFileSystem fileSystem) + public StylesheetRepository(IFileSystem fileSystem) : base(fileSystem) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/TaskRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/TaskRepository.cs index f33a1c852a..fd79c14c93 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/TaskRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/TaskRepository.cs @@ -1,10 +1,8 @@ using System; using System.Collections.Generic; using System.Linq; -using LightInject; using NPoco; using Umbraco.Core.Cache; -using Umbraco.Core.Composing.CompositionRoots; using Umbraco.Core.Exceptions; using Umbraco.Core.Logging; using Umbraco.Core.Models; @@ -17,7 +15,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { internal class TaskRepository : NPocoRepositoryBase, ITaskRepository { - public TaskRepository(IScopeAccessor scopeAccessor, [Inject(RepositoryCompositionRoot.DisabledCache)] CacheHelper cache, ILogger logger) + public TaskRepository(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger) : base(scopeAccessor, cache, logger) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/TaskTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/TaskTypeRepository.cs index abd21002a1..465474a644 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/TaskTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/TaskTypeRepository.cs @@ -1,10 +1,8 @@ using System; using System.Collections.Generic; using System.Linq; -using LightInject; using NPoco; using Umbraco.Core.Cache; -using Umbraco.Core.Composing.CompositionRoots; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Persistence.Dtos; @@ -16,7 +14,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { internal class TaskTypeRepository : NPocoRepositoryBase, ITaskTypeRepository { - public TaskTypeRepository(IScopeAccessor scopeAccessor, [Inject(RepositoryCompositionRoot.DisabledCache)] CacheHelper cache, ILogger logger) + public TaskTypeRepository(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger) : base(scopeAccessor, cache, logger) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/TemplateRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/TemplateRepository.cs index 32080c4a12..4afc1bfbdb 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/TemplateRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/TemplateRepository.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; -using LightInject; using NPoco; using Umbraco.Core.Cache; using Umbraco.Core.Configuration.UmbracoSettings; @@ -31,8 +30,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement private readonly MasterPageHelper _masterPageHelper; public TemplateRepository(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger, ITemplatesSection templateConfig, - [Inject(Constants.Composing.FileSystems.MasterpageFileSystem)] IFileSystem masterpageFileSystem, - [Inject(Constants.Composing.FileSystems.ViewFileSystem)] IFileSystem viewFileSystem) + IFileSystem masterpageFileSystem, + IFileSystem viewFileSystem) : base(scopeAccessor, cache, logger) { _masterpagesFileSystem = masterpageFileSystem; diff --git a/src/Umbraco.Web/Mvc/PluginController.cs b/src/Umbraco.Web/Mvc/PluginController.cs index 6e44cca112..2e28e7fe2c 100644 --- a/src/Umbraco.Web/Mvc/PluginController.cs +++ b/src/Umbraco.Web/Mvc/PluginController.cs @@ -35,32 +35,32 @@ namespace Umbraco.Web.Mvc /// /// Gets or sets the Umbraco context. /// - public virtual UmbracoContext UmbracoContext { get; set; } + public virtual UmbracoContext UmbracoContext { get; } /// /// Gets or sets the database context. /// - public IUmbracoDatabaseFactory DatabaseFactory { get; set; } + public IUmbracoDatabaseFactory DatabaseFactory { get; } /// /// Gets or sets the services context. /// - public ServiceContext Services { get; set; } + public ServiceContext Services { get; } /// /// Gets or sets the application cache. /// - public CacheHelper ApplicationCache { get; set; } + public CacheHelper ApplicationCache { get; } /// /// Gets or sets the logger. /// - public ILogger Logger { get; set; } + public ILogger Logger { get; } /// /// Gets or sets the profiling logger. /// - public ProfilingLogger ProfilingLogger { get; set; } + public ProfilingLogger ProfilingLogger { get; } /// /// Gets the membership helper. From 590765e9c637be8756e8dd39192a6ed1714a5151 Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Wed, 20 Jun 2018 20:00:34 +0200 Subject: [PATCH 010/469] Tests build >< --- .../Web/Controllers/PluginControllerAreaTests.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Tests/Web/Controllers/PluginControllerAreaTests.cs b/src/Umbraco.Tests/Web/Controllers/PluginControllerAreaTests.cs index 669c607aea..01525f12da 100644 --- a/src/Umbraco.Tests/Web/Controllers/PluginControllerAreaTests.cs +++ b/src/Umbraco.Tests/Web/Controllers/PluginControllerAreaTests.cs @@ -54,8 +54,8 @@ namespace Umbraco.Tests.Web.Controllers public class Plugin1Controller : PluginController { public Plugin1Controller(UmbracoContext umbracoContext) + : base(umbracoContext, null, null, null, null, null) { - UmbracoContext = umbracoContext; } } @@ -63,8 +63,8 @@ namespace Umbraco.Tests.Web.Controllers public class Plugin2Controller : PluginController { public Plugin2Controller(UmbracoContext umbracoContext) + : base(umbracoContext, null, null, null, null, null) { - UmbracoContext = umbracoContext; } } @@ -72,16 +72,16 @@ namespace Umbraco.Tests.Web.Controllers public class Plugin3Controller : PluginController { public Plugin3Controller(UmbracoContext umbracoContext) + : base(umbracoContext, null, null, null, null, null) { - UmbracoContext = umbracoContext; } } public class Plugin4Controller : PluginController { public Plugin4Controller(UmbracoContext umbracoContext) + : base(umbracoContext, null, null, null, null, null) { - UmbracoContext = umbracoContext; } } From 34390dec12b38368bd402f19e4430748e47b97b9 Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Wed, 20 Jun 2018 22:00:41 +0200 Subject: [PATCH 011/469] Almost got MediaFileSystem in container. --- src/Umbraco.Core/Composing/IContainer.cs | 1 + src/Umbraco.Core/Composing/LightInject/ContainerAdapter.cs | 5 +++++ src/Umbraco.Core/IO/FileSystems.cs | 3 ++- src/Umbraco.Tests/IO/FileSystemsTests.cs | 3 +++ 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Core/Composing/IContainer.cs b/src/Umbraco.Core/Composing/IContainer.cs index a1206c5816..6583509d58 100644 --- a/src/Umbraco.Core/Composing/IContainer.cs +++ b/src/Umbraco.Core/Composing/IContainer.cs @@ -15,5 +15,6 @@ namespace Umbraco.Core.Composing void RegisterSingleton(Func factory); void Register(Func factory); T RegisterCollectionBuilder(); + T GetInstance(params object[] args); } } diff --git a/src/Umbraco.Core/Composing/LightInject/ContainerAdapter.cs b/src/Umbraco.Core/Composing/LightInject/ContainerAdapter.cs index 906b66bcb1..42a04b9a15 100644 --- a/src/Umbraco.Core/Composing/LightInject/ContainerAdapter.cs +++ b/src/Umbraco.Core/Composing/LightInject/ContainerAdapter.cs @@ -43,6 +43,11 @@ namespace Umbraco.Core.Composing.LightInject return container.GetInstance(); } + public T GetInstance(params object[] args) + { + return (T)container.GetInstance(typeof(T), args); + } + public object GetInstance(Type type) { return container.GetInstance(type); diff --git a/src/Umbraco.Core/IO/FileSystems.cs b/src/Umbraco.Core/IO/FileSystems.cs index 2fb5941b17..9749078923 100644 --- a/src/Umbraco.Core/IO/FileSystems.cs +++ b/src/Umbraco.Core/IO/FileSystems.cs @@ -305,7 +305,8 @@ namespace Umbraco.Core.IO // fixme - switch to using container. where are these registered? - var fs = (IFileSystem) Activator.CreateInstance(typeof(TFileSystem), shadowWrapper); + //var fs = (IFileSystem) Activator.CreateInstance(typeof(TFileSystem), shadowWrapper); + var fs = Current.Container.GetInstance((IFileSystem)shadowWrapper); _wrappers.Add(shadowWrapper); // keeping a reference to the wrapper return fs; }); diff --git a/src/Umbraco.Tests/IO/FileSystemsTests.cs b/src/Umbraco.Tests/IO/FileSystemsTests.cs index 79b1d8bf6c..83792b9a0b 100644 --- a/src/Umbraco.Tests/IO/FileSystemsTests.cs +++ b/src/Umbraco.Tests/IO/FileSystemsTests.cs @@ -33,6 +33,9 @@ namespace Umbraco.Tests.IO _container.Register(_ => Mock.Of()); _container.Register(_ => Mock.Of()); + _container.Register(); + _container.Register(); + // make sure we start clean // because some tests will create corrupt or weird filesystems FileSystems.Reset(); From 3a7d7e370e8616a132443a0491edc3531db67aa9 Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Tue, 26 Jun 2018 00:26:57 +0200 Subject: [PATCH 012/469] MediaFileSystem now purely injected. A bit messy, and probably leaves quite a bit of dead / useless code around that should be deleted. Needs some manual testing. --- src/Umbraco.Core/IO/FileSystems.cs | 2 +- src/Umbraco.Core/IO/MediaFileSystem.cs | 16 ++++++++-------- src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs | 3 +++ src/Umbraco.Tests/IO/FileSystemsTests.cs | 4 ++-- src/Umbraco.Tests/Models/ContentTests.cs | 8 +++++--- src/Umbraco.Tests/Models/MediaXmlTest.cs | 2 +- .../PropertyEditors/ImageCropperTest.cs | 2 +- src/Umbraco.Tests/TestHelpers/TestObjects.cs | 3 ++- src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 3 ++- 9 files changed, 25 insertions(+), 18 deletions(-) diff --git a/src/Umbraco.Core/IO/FileSystems.cs b/src/Umbraco.Core/IO/FileSystems.cs index 9749078923..061413d070 100644 --- a/src/Umbraco.Core/IO/FileSystems.cs +++ b/src/Umbraco.Core/IO/FileSystems.cs @@ -318,7 +318,7 @@ namespace Umbraco.Core.IO // validate the ctor var constructor = fsType.GetConstructors().SingleOrDefault(x - => x.GetParameters().Length == 1 && TypeHelper.IsTypeAssignableFrom(x.GetParameters().Single().ParameterType)); + => x.GetParameters().Length >= 1 && TypeHelper.IsTypeAssignableFrom(x.GetParameters().First().ParameterType)); if (constructor == null) throw new InvalidOperationException("Type " + fsType.FullName + " must inherit from FileSystemWrapper and have a constructor that accepts one parameter of type " + typeof(IFileSystem).FullName + "."); diff --git a/src/Umbraco.Core/IO/MediaFileSystem.cs b/src/Umbraco.Core/IO/MediaFileSystem.cs index b3fc2ccb61..b59d5b6924 100644 --- a/src/Umbraco.Core/IO/MediaFileSystem.cs +++ b/src/Umbraco.Core/IO/MediaFileSystem.cs @@ -6,10 +6,8 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; -using LightInject; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; -using Umbraco.Core.Composing; using Umbraco.Core.Exceptions; using Umbraco.Core.Logging; using Umbraco.Core.Media; @@ -35,21 +33,23 @@ namespace Umbraco.Core.IO // { 500, "big-thumb" } //}; - public MediaFileSystem(IFileSystem wrapped) + public MediaFileSystem(IFileSystem wrapped, IContentSection contentConfig, ILogger logger) : base(wrapped) { + ContentConfig = contentConfig; + Logger = logger; + + // fixme - remove obsolete comments // due to how FileSystems is written at the moment, the ctor cannot be used to inject // dependencies, so we have to rely on property injection for anything we might need - ((IServiceContainer)Current.Container.ConcreteContainer).InjectProperties(this); + //((IServiceContainer)Current.Container.ConcreteContainer).InjectProperties(this); UploadAutoFillProperties = new UploadAutoFillProperties(this, Logger, ContentConfig); } - [Inject] - internal IContentSection ContentConfig { get; set; } + internal IContentSection ContentConfig { get; } - [Inject] - internal ILogger Logger { get; set; } + internal ILogger Logger { get; } internal UploadAutoFillProperties UploadAutoFillProperties { get; } diff --git a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs index a90d5b5b4c..a9a1369a97 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs @@ -44,6 +44,9 @@ namespace Umbraco.Core.Runtime composition.Container.Register(); // register filesystems + + composition.Container.Register((f, wrappedFileSystem) => new MediaFileSystem(wrappedFileSystem, f.GetInstance(), f.GetInstance())); + composition.Container.RegisterSingleton(); composition.Container.RegisterSingleton(factory => factory.GetInstance().MediaFileSystem); composition.Container.RegisterSingleton(factory => factory.GetInstance().ScriptsFileSystem, Constants.Composing.FileSystems.ScriptFileSystem); diff --git a/src/Umbraco.Tests/IO/FileSystemsTests.cs b/src/Umbraco.Tests/IO/FileSystemsTests.cs index 83792b9a0b..c0f13c6e1b 100644 --- a/src/Umbraco.Tests/IO/FileSystemsTests.cs +++ b/src/Umbraco.Tests/IO/FileSystemsTests.cs @@ -33,8 +33,8 @@ namespace Umbraco.Tests.IO _container.Register(_ => Mock.Of()); _container.Register(_ => Mock.Of()); - _container.Register(); - _container.Register(); + _container.Register((f, x) => new MediaFileSystem(x, f.GetInstance(), f.GetInstance())); + _container.Register((f, x) => new NonConfiguredTypeFileSystem(x)); // make sure we start clean // because some tests will create corrupt or weird filesystems diff --git a/src/Umbraco.Tests/Models/ContentTests.cs b/src/Umbraco.Tests/Models/ContentTests.cs index 2e68873f77..41228eb89e 100644 --- a/src/Umbraco.Tests/Models/ContentTests.cs +++ b/src/Umbraco.Tests/Models/ContentTests.cs @@ -5,7 +5,8 @@ using System.Globalization; using System.IO; using System.Linq; using System.Web; -using Moq; +using Moq; +using LightInject; using NUnit.Framework; using Umbraco.Core.Cache; using Umbraco.Core.Configuration.UmbracoSettings; @@ -22,7 +23,7 @@ using Umbraco.Tests.Testing; namespace Umbraco.Tests.Models { - [TestFixture] + [TestFixture] public class ContentTests : UmbracoTestBase { public override void SetUp() @@ -36,8 +37,9 @@ namespace Umbraco.Tests.Models protected override void Compose() { base.Compose(); - + Container.Register(_ => Mock.Of()); + Container.Register((factory, fileSystem) => new MediaFileSystem(fileSystem, factory.GetInstance(), factory.GetInstance())); Container.Register(); Container.Register(_ => Mock.Of()); Container.Register(_ => Mock.Of()); diff --git a/src/Umbraco.Tests/Models/MediaXmlTest.cs b/src/Umbraco.Tests/Models/MediaXmlTest.cs index 6f28842f18..1f4eaf9d8a 100644 --- a/src/Umbraco.Tests/Models/MediaXmlTest.cs +++ b/src/Umbraco.Tests/Models/MediaXmlTest.cs @@ -29,7 +29,7 @@ namespace Umbraco.Tests.Models // reference, so static ctor runs, so event handlers register // and then, this will reset the width, height... because the file does not exist, of course ;-( - var ignored = new FileUploadPropertyEditor(Mock.Of(), new MediaFileSystem(Mock.Of())); + var ignored = new FileUploadPropertyEditor(Mock.Of(), new MediaFileSystem(Mock.Of(), Mock.Of(), Mock.Of())); var media = MockedMedia.CreateMediaImage(mediaType, -1); media.WriterId = -1; // else it's zero and that's not a user and it breaks the tests diff --git a/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs b/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs index 83d5fea1d1..8df585fb25 100644 --- a/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs +++ b/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs @@ -72,7 +72,7 @@ namespace Umbraco.Tests.PropertyEditors container.Register(f => Mock.Of()); container.Register(f => Mock.Of()); - var mediaFileSystem = new MediaFileSystem(Mock.Of()); + var mediaFileSystem = new MediaFileSystem(Mock.Of(), Mock.Of(), Mock.Of()); var dataTypeService = new TestObjects.TestDataTypeService( new DataType(new ImageCropperPropertyEditor(Mock.Of(), mediaFileSystem, Mock.Of())) { Id = 1 }); diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects.cs b/src/Umbraco.Tests/TestHelpers/TestObjects.cs index 485cce4c0a..7e3d887d77 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects.cs @@ -10,6 +10,7 @@ using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Events; using Umbraco.Core.IO; using Umbraco.Core.Logging; @@ -116,7 +117,7 @@ namespace Umbraco.Tests.TestHelpers if (logger == null) throw new ArgumentNullException(nameof(logger)); if (eventMessagesFactory == null) throw new ArgumentNullException(nameof(eventMessagesFactory)); - var mediaFileSystem = new MediaFileSystem(Mock.Of()); + var mediaFileSystem = new MediaFileSystem(Mock.Of(), Mock.Of(), Mock.Of()); var externalLoginService = GetLazyService(container, c => new ExternalLoginService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); var publicAccessService = GetLazyService(container, c => new PublicAccessService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index b5f3de72a4..2048b7cb58 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -13,6 +13,7 @@ using Umbraco.Core.Components; using Umbraco.Core.Composing; using Umbraco.Core.Composing.CompositionRoots; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Events; using Umbraco.Core.IO; using Umbraco.Core.Logging; @@ -267,7 +268,7 @@ namespace Umbraco.Tests.Testing Container.RegisterSingleton(factory => globalSettings); Container.RegisterSingleton(factory => umbracoSettings.Content); Container.RegisterSingleton(factory => umbracoSettings.Templates); - Container.Register(factory => new MediaFileSystem(Mock.Of())); + Container.Register((factory, fileSystem) => new MediaFileSystem(fileSystem, factory.GetInstance(), factory.GetInstance())); Container.RegisterSingleton(factory => ExamineManager.Instance); // replace some stuff From 49e95146090082b75b53d71f0eddc96c851cfaa7 Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Tue, 26 Jun 2018 00:33:38 +0200 Subject: [PATCH 013/469] Added "Slow" category to several fixtures, cutting test time in half for most regression runs. --- src/Umbraco.Tests/Integration/ContentEventsTests.cs | 1 + src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests.cs | 1 + src/Umbraco.Tests/Services/ContentServiceTests.cs | 1 + src/Umbraco.Tests/Services/ContentTypeServiceTests.cs | 1 + src/Umbraco.Tests/Services/Importing/PackageImportTests.cs | 1 + src/Umbraco.Tests/Services/MemberServiceTests.cs | 1 + 6 files changed, 6 insertions(+) diff --git a/src/Umbraco.Tests/Integration/ContentEventsTests.cs b/src/Umbraco.Tests/Integration/ContentEventsTests.cs index 73f95c44a7..c0b66de2a0 100644 --- a/src/Umbraco.Tests/Integration/ContentEventsTests.cs +++ b/src/Umbraco.Tests/Integration/ContentEventsTests.cs @@ -22,6 +22,7 @@ using static Umbraco.Tests.Cache.DistributedCache.DistributedCacheTests; namespace Umbraco.Tests.Integration { [TestFixture] + [Category("Slow")] [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)] public class ContentEventsTests : TestWithSomeContentBase { diff --git a/src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests.cs b/src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests.cs index 38990405c4..66f6e2f3ef 100644 --- a/src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests.cs +++ b/src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests.cs @@ -13,6 +13,7 @@ namespace Umbraco.Tests.Scheduling { [TestFixture] [Timeout(30000)] + [Category("Slow")] public class BackgroundTaskRunnerTests { private ILogger _logger; diff --git a/src/Umbraco.Tests/Services/ContentServiceTests.cs b/src/Umbraco.Tests/Services/ContentServiceTests.cs index 0326ce0a15..f1a4db949c 100644 --- a/src/Umbraco.Tests/Services/ContentServiceTests.cs +++ b/src/Umbraco.Tests/Services/ContentServiceTests.cs @@ -34,6 +34,7 @@ namespace Umbraco.Tests.Services /// as well as configuration. /// [TestFixture] + [Category("Slow")] [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest, PublishedRepositoryEvents = true, WithApplication = true)] public class ContentServiceTests : TestWithSomeContentBase { diff --git a/src/Umbraco.Tests/Services/ContentTypeServiceTests.cs b/src/Umbraco.Tests/Services/ContentTypeServiceTests.cs index c9f8ba52ad..8d316b7721 100644 --- a/src/Umbraco.Tests/Services/ContentTypeServiceTests.cs +++ b/src/Umbraco.Tests/Services/ContentTypeServiceTests.cs @@ -19,6 +19,7 @@ using Umbraco.Tests.Testing; namespace Umbraco.Tests.Services { [TestFixture] + [Category("Slow")] [Apartment(ApartmentState.STA)] [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest, PublishedRepositoryEvents = true)] public class ContentTypeServiceTests : TestWithSomeContentBase diff --git a/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs b/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs index a810d4c644..5e6bb18159 100644 --- a/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs +++ b/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs @@ -16,6 +16,7 @@ using LightInject; namespace Umbraco.Tests.Services.Importing { [TestFixture] + [Category("Slow")] [Apartment(ApartmentState.STA)] [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)] public class PackageImportTests : TestWithSomeContentBase diff --git a/src/Umbraco.Tests/Services/MemberServiceTests.cs b/src/Umbraco.Tests/Services/MemberServiceTests.cs index 968b27a4f9..ea6dd8248e 100644 --- a/src/Umbraco.Tests/Services/MemberServiceTests.cs +++ b/src/Umbraco.Tests/Services/MemberServiceTests.cs @@ -24,6 +24,7 @@ using Umbraco.Web.Security.Providers; namespace Umbraco.Tests.Services { [TestFixture] + [Category("Slow")] [Apartment(ApartmentState.STA)] [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest, PublishedRepositoryEvents = true, WithApplication = true)] public class MemberServiceTests : TestWithSomeContentBase From 3d2810e6b16b16a50c4a9c967f011a4ae661b05f Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Thu, 28 Jun 2018 22:38:14 +0200 Subject: [PATCH 014/469] Fixes constructor dependency conondrum for MediaFileSystem. It is Completely Broken (tm). Need to review whole lifetime & registration of it. --- src/Umbraco.Core/Composing/IContainer.cs | 3 ++- src/Umbraco.Core/Composing/LightInject/ContainerAdapter.cs | 7 ++++++- src/Umbraco.Core/IO/FileSystems.cs | 2 +- src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs | 1 + src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 4 ++++ 5 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Core/Composing/IContainer.cs b/src/Umbraco.Core/Composing/IContainer.cs index 6583509d58..331c1e9141 100644 --- a/src/Umbraco.Core/Composing/IContainer.cs +++ b/src/Umbraco.Core/Composing/IContainer.cs @@ -14,7 +14,8 @@ namespace Umbraco.Core.Composing object ConcreteContainer { get; } void RegisterSingleton(Func factory); void Register(Func factory); + void Register(Func factory); T RegisterCollectionBuilder(); - T GetInstance(params object[] args); + T GetInstance(object[] args); } } diff --git a/src/Umbraco.Core/Composing/LightInject/ContainerAdapter.cs b/src/Umbraco.Core/Composing/LightInject/ContainerAdapter.cs index 42a04b9a15..f7ffa68111 100644 --- a/src/Umbraco.Core/Composing/LightInject/ContainerAdapter.cs +++ b/src/Umbraco.Core/Composing/LightInject/ContainerAdapter.cs @@ -23,6 +23,11 @@ namespace Umbraco.Core.Composing.LightInject container.Register(f => factory(this)); } + public void Register(Func factory) + { + container.Register((f, x) => factory(this, x)); + } + public T RegisterCollectionBuilder() { return container.RegisterCollectionBuilder(); @@ -43,7 +48,7 @@ namespace Umbraco.Core.Composing.LightInject return container.GetInstance(); } - public T GetInstance(params object[] args) + public T GetInstance(object[] args) { return (T)container.GetInstance(typeof(T), args); } diff --git a/src/Umbraco.Core/IO/FileSystems.cs b/src/Umbraco.Core/IO/FileSystems.cs index 061413d070..af6d176794 100644 --- a/src/Umbraco.Core/IO/FileSystems.cs +++ b/src/Umbraco.Core/IO/FileSystems.cs @@ -306,7 +306,7 @@ namespace Umbraco.Core.IO // fixme - switch to using container. where are these registered? //var fs = (IFileSystem) Activator.CreateInstance(typeof(TFileSystem), shadowWrapper); - var fs = Current.Container.GetInstance((IFileSystem)shadowWrapper); + var fs = Current.Container.GetInstance(new object[] { (IFileSystem)shadowWrapper }); _wrappers.Add(shadowWrapper); // keeping a reference to the wrapper return fs; }); diff --git a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs index a9a1369a97..1744e8063f 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs @@ -46,6 +46,7 @@ namespace Umbraco.Core.Runtime // register filesystems composition.Container.Register((f, wrappedFileSystem) => new MediaFileSystem(wrappedFileSystem, f.GetInstance(), f.GetInstance())); + composition.Container.RegisterConstructorDependency((factory, parameterInfo) => factory.GetInstance().MediaFileSystem); composition.Container.RegisterSingleton(); composition.Container.RegisterSingleton(factory => factory.GetInstance().MediaFileSystem); diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index 2048b7cb58..d2a9481251 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -268,7 +268,11 @@ namespace Umbraco.Tests.Testing Container.RegisterSingleton(factory => globalSettings); Container.RegisterSingleton(factory => umbracoSettings.Content); Container.RegisterSingleton(factory => umbracoSettings.Templates); + + // fixme - The whole MediaFileSystem coupling thing seems broken. Container.Register((factory, fileSystem) => new MediaFileSystem(fileSystem, factory.GetInstance(), factory.GetInstance())); + Container.RegisterConstructorDependency((factory, parameterInfo) => factory.GetInstance().MediaFileSystem); + Container.RegisterSingleton(factory => ExamineManager.Instance); // replace some stuff From 91a5605341d8f3aa7eb6c7320143db534642b6d1 Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Thu, 28 Jun 2018 23:28:22 +0200 Subject: [PATCH 015/469] MembershipHelper presumably working without property injection. (But OMG! there's nearly no test coverage of Umbraco.Web :O ) --- .../TestControllerActivatorBase.cs | 3 +- .../Accessors/TestUmbracoContextAccessor.cs | 9 +++ .../Testing/TestingTests/MockTests.cs | 3 +- .../Web/Mvc/SurfaceControllerTests.cs | 3 +- .../CompositionRoots/HelperCompositionRoot.cs | 17 ++++ src/Umbraco.Web/HtmlHelperRenderExtensions.cs | 2 +- src/Umbraco.Web/Models/LoginStatusModel.cs | 2 +- src/Umbraco.Web/Models/ProfileModel.cs | 2 +- src/Umbraco.Web/Models/RegisterModel.cs | 2 +- src/Umbraco.Web/Routing/PublishedRouter.cs | 3 +- .../Runtime/WebRuntimeComponent.cs | 2 + src/Umbraco.Web/Security/MembershipHelper.cs | 81 ++++++++----------- src/Umbraco.Web/Security/WebSecurity.cs | 2 +- .../UI/Controls/UmbracoUserControl.cs | 2 +- src/Umbraco.Web/Umbraco.Web.csproj | 1 + src/Umbraco.Web/UmbracoHelper.cs | 2 +- 16 files changed, 76 insertions(+), 60 deletions(-) create mode 100644 src/Umbraco.Web/Composing/CompositionRoots/HelperCompositionRoot.cs diff --git a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs index ded14c40ab..c9f74d689d 100644 --- a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs +++ b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs @@ -29,6 +29,7 @@ using Umbraco.Web.Security; using Umbraco.Web.WebApi; using LightInject; using System.Globalization; +using Umbraco.Core.Logging; using Umbraco.Tests.Testing.Objects.Accessors; namespace Umbraco.Tests.TestHelpers.ControllerTesting @@ -157,7 +158,7 @@ namespace Umbraco.Tests.TestHelpers.ControllerTesting urlHelper.Setup(provider => provider.GetUrl(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Returns("/hello/world/1234"); - var membershipHelper = new MembershipHelper(umbCtx, Mock.Of(), Mock.Of()); + var membershipHelper = new MembershipHelper(new TestUmbracoContextAccessor(umbCtx), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), null); var mockedTypedContent = Mock.Of(); diff --git a/src/Umbraco.Tests/Testing/Objects/Accessors/TestUmbracoContextAccessor.cs b/src/Umbraco.Tests/Testing/Objects/Accessors/TestUmbracoContextAccessor.cs index da93218907..4f3b801af9 100644 --- a/src/Umbraco.Tests/Testing/Objects/Accessors/TestUmbracoContextAccessor.cs +++ b/src/Umbraco.Tests/Testing/Objects/Accessors/TestUmbracoContextAccessor.cs @@ -5,5 +5,14 @@ namespace Umbraco.Tests.Testing.Objects.Accessors public class TestUmbracoContextAccessor : IUmbracoContextAccessor { public UmbracoContext UmbracoContext { get; set; } + + public TestUmbracoContextAccessor() + { + } + + public TestUmbracoContextAccessor(UmbracoContext umbracoContext) + { + UmbracoContext = umbracoContext; + } } } diff --git a/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs b/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs index f21a953ae7..6b815bc434 100644 --- a/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs +++ b/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs @@ -7,6 +7,7 @@ using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Dictionary; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Services; @@ -65,7 +66,7 @@ namespace Umbraco.Tests.Testing.TestingTests Mock.Of(), Mock.Of(), Mock.Of(), - new MembershipHelper(umbracoContext, Mock.Of(), Mock.Of()), + new MembershipHelper(new TestUmbracoContextAccessor(umbracoContext), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), null), new ServiceContext(), CacheHelper.CreateDisabledCacheHelper()); Assert.Pass(); diff --git a/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs b/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs index f9cff5af9b..dfa917459f 100644 --- a/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs +++ b/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs @@ -10,6 +10,7 @@ using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Dictionary; +using Umbraco.Core.Logging; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Services; using Umbraco.Tests.TestHelpers; @@ -129,7 +130,7 @@ namespace Umbraco.Tests.Web.Mvc Mock.Of(), Mock.Of(), Mock.Of(), - new MembershipHelper(umbracoContext, Mock.Of(), Mock.Of()), + new MembershipHelper(new TestUmbracoContextAccessor(umbracoContext), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), null), new ServiceContext(), CacheHelper.CreateDisabledCacheHelper()); diff --git a/src/Umbraco.Web/Composing/CompositionRoots/HelperCompositionRoot.cs b/src/Umbraco.Web/Composing/CompositionRoots/HelperCompositionRoot.cs new file mode 100644 index 0000000000..d708493016 --- /dev/null +++ b/src/Umbraco.Web/Composing/CompositionRoots/HelperCompositionRoot.cs @@ -0,0 +1,17 @@ +using System.Web.Security; +using LightInject; +using Umbraco.Web.Security; +using Umbraco.Web.Security.Providers; + +namespace Umbraco.Web.Composing.CompositionRoots +{ + public class HelperCompositionRoot : ICompositionRoot + { + public void Compose(IServiceRegistry container) + { + container.Register((factory) => Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider()); + container.Register((factory) => Roles.Enabled ? Roles.Provider : new MembersRoleProvider(Core.Composing.Current.Services.MemberService)); + container.Register(); + } + } +} diff --git a/src/Umbraco.Web/HtmlHelperRenderExtensions.cs b/src/Umbraco.Web/HtmlHelperRenderExtensions.cs index 6b3581aeab..e39113c953 100644 --- a/src/Umbraco.Web/HtmlHelperRenderExtensions.cs +++ b/src/Umbraco.Web/HtmlHelperRenderExtensions.cs @@ -97,7 +97,7 @@ namespace Umbraco.Web } if (cacheByMember) { - var helper = new MembershipHelper(Current.UmbracoContext); + var helper = Current.Container.GetInstance(); var currentMember = helper.GetCurrentMember(); cacheKey.AppendFormat("m{0}-", currentMember == null ? 0 : currentMember.Id); } diff --git a/src/Umbraco.Web/Models/LoginStatusModel.cs b/src/Umbraco.Web/Models/LoginStatusModel.cs index 78425969dd..dd2b517b99 100644 --- a/src/Umbraco.Web/Models/LoginStatusModel.cs +++ b/src/Umbraco.Web/Models/LoginStatusModel.cs @@ -25,7 +25,7 @@ namespace Umbraco.Web.Models { if (doLookup && Current.UmbracoContext != null) { - var helper = new MembershipHelper(Current.UmbracoContext); + var helper = Current.Container.GetInstance(); var model = helper.GetCurrentLoginStatus(); if (model != null) { diff --git a/src/Umbraco.Web/Models/ProfileModel.cs b/src/Umbraco.Web/Models/ProfileModel.cs index c999657b6a..9c5bff0f7e 100644 --- a/src/Umbraco.Web/Models/ProfileModel.cs +++ b/src/Umbraco.Web/Models/ProfileModel.cs @@ -27,7 +27,7 @@ namespace Umbraco.Web.Models MemberProperties = new List(); if (doLookup && Current.UmbracoContext != null) { - var helper = new MembershipHelper(Current.UmbracoContext); + var helper = Current.Container.GetInstance(); var model = helper.GetCurrentMemberProfileModel(); MemberProperties = model.MemberProperties; } diff --git a/src/Umbraco.Web/Models/RegisterModel.cs b/src/Umbraco.Web/Models/RegisterModel.cs index 2851db54a4..e5a04b06bb 100644 --- a/src/Umbraco.Web/Models/RegisterModel.cs +++ b/src/Umbraco.Web/Models/RegisterModel.cs @@ -31,7 +31,7 @@ namespace Umbraco.Web.Models CreatePersistentLoginCookie = true; if (doLookup && Current.UmbracoContext != null) { - var helper = new MembershipHelper(Current.UmbracoContext); + var helper = Current.Container.GetInstance(); var model = helper.CreateRegistrationModel(MemberTypeAlias); MemberProperties = model.MemberProperties; } diff --git a/src/Umbraco.Web/Routing/PublishedRouter.cs b/src/Umbraco.Web/Routing/PublishedRouter.cs index 8e7d786e93..c6c4ef94c8 100644 --- a/src/Umbraco.Web/Routing/PublishedRouter.cs +++ b/src/Umbraco.Web/Routing/PublishedRouter.cs @@ -7,6 +7,7 @@ using System.IO; using System.Web.Security; using umbraco; using Umbraco.Core; +using Umbraco.Core.Composing; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; using Umbraco.Core.Logging; @@ -633,7 +634,7 @@ namespace Umbraco.Web.Routing { _logger.Debug(() => $"{tracePrefix}Page is protected, check for access"); - var membershipHelper = new MembershipHelper(request.UmbracoContext); + var membershipHelper = Current.Container.GetInstance(); if (membershipHelper.IsLoggedIn() == false) { diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs index a4e5db0767..91715fe016 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs @@ -70,6 +70,8 @@ namespace Umbraco.Web.Runtime //it still needs to use the install controller so we can't do that composition.Container.RegisterFrom(); + composition.Container.RegisterFrom(); + // register accessors for cultures composition.Container.RegisterSingleton(); composition.Container.RegisterSingleton(); diff --git a/src/Umbraco.Web/Security/MembershipHelper.cs b/src/Umbraco.Web/Security/MembershipHelper.cs index 7a56679086..a3923e9353 100644 --- a/src/Umbraco.Web/Security/MembershipHelper.cs +++ b/src/Umbraco.Web/Security/MembershipHelper.cs @@ -5,7 +5,6 @@ using System.Linq; using System.Text; using System.Web; using System.Web.Security; -using LightInject; using Umbraco.Core; using Umbraco.Core.Logging; using Umbraco.Core.Models; @@ -34,69 +33,53 @@ namespace Umbraco.Web.Security private readonly IPublishedMemberCache _memberCache; private readonly UmbracoContext _umbracoContext; - [Inject] - private IMemberService MemberService { get; set; } + private IMemberService MemberService { get; } - [Inject] - private IMemberTypeService MemberTypeService { get; set; } + private IMemberTypeService MemberTypeService { get; } - [Inject] - private IUserService UserService { get; set; } + private IUserService UserService { get; } - [Inject] - private IPublicAccessService PublicAccessService { get; set; } + private IPublicAccessService PublicAccessService { get; } + public CacheHelper CacheHelper { get; } - [Inject] - private CacheHelper ApplicationCache { get; set; } + private CacheHelper ApplicationCache { get; } - [Inject] - private ILogger Logger { get; set; } + private ILogger Logger { get; } - [Inject] - private PublishedRouter Router { get; set; } + private PublishedRouter Router { get; } #region Constructors - // used here and there for IMember operations (not front-end stuff, no need for _memberCache) - - [Obsolete("Use the constructor specifying an UmbracoContext")] - [EditorBrowsable(EditorBrowsableState.Never)] - public MembershipHelper(HttpContextBase httpContext) + public MembershipHelper + ( + IUmbracoContextAccessor accessor, + MembershipProvider membershipProvider, + RoleProvider roleProvider, + IMemberService memberService, + IMemberTypeService memberTypeService, + IUserService userService, + IPublicAccessService publicAccessService, + CacheHelper cacheHelper, + ILogger logger, + PublishedRouter router + ) { - if (httpContext == null) throw new ArgumentNullException(nameof(httpContext)); - _httpContext = httpContext; - _membershipProvider = MPE.GetMembersMembershipProvider(); - _roleProvider = Roles.Enabled ? Roles.Provider : new MembersRoleProvider(MemberService); - - // _memberCache remains null - not supposed to use it - // alternatively we'd need to get if from the 'current' UmbracoContext? - - // helpers are *not* instanciated by the container so we have to - // get our dependencies injected manually, through properties. - ((IServiceContainer)Current.Container.ConcreteContainer).InjectProperties(this); - } - - // used everywhere - public MembershipHelper(UmbracoContext umbracoContext) - : this(umbracoContext, MPE.GetMembersMembershipProvider(), Roles.Enabled ? Roles.Provider : new MembersRoleProvider(Current.Services.MemberService)) - { } - - // used in tests and (this) - public MembershipHelper(UmbracoContext umbracoContext, MembershipProvider membershipProvider, RoleProvider roleProvider) - { - if (umbracoContext == null) throw new ArgumentNullException(nameof(umbracoContext)); + if (accessor.UmbracoContext == null) throw new ArgumentNullException(nameof(accessor)); if (membershipProvider == null) throw new ArgumentNullException(nameof(membershipProvider)); if (roleProvider == null) throw new ArgumentNullException(nameof(roleProvider)); + MemberService = memberService; + MemberTypeService = memberTypeService; + UserService = userService; + PublicAccessService = publicAccessService; + CacheHelper = cacheHelper; + Logger = logger; + Router = router; - _httpContext = umbracoContext.HttpContext; - _umbracoContext = umbracoContext; + _httpContext = accessor.UmbracoContext.HttpContext; + _umbracoContext = accessor.UmbracoContext; _membershipProvider = membershipProvider; _roleProvider = roleProvider; - _memberCache = umbracoContext.PublishedSnapshot.Members; - - // helpers are *not* instanciated by the container so we have to - // get our dependencies injected manually, through properties. - ((IServiceContainer)Current.Container.ConcreteContainer).InjectProperties(this); + _memberCache = accessor.UmbracoContext.PublishedSnapshot.Members; } #endregion diff --git a/src/Umbraco.Web/Security/WebSecurity.cs b/src/Umbraco.Web/Security/WebSecurity.cs index 5de163b638..1dd0f6f34c 100644 --- a/src/Umbraco.Web/Security/WebSecurity.cs +++ b/src/Umbraco.Web/Security/WebSecurity.cs @@ -57,7 +57,7 @@ namespace Umbraco.Web.Security { return false; } - var helper = new MembershipHelper(Current.UmbracoContext); + var helper = Current.Container.GetInstance(); return helper.IsMemberAuthorized(allowAll, allowTypes, allowGroups, allowMembers); } diff --git a/src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs b/src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs index 2875cb82bd..919a614034 100644 --- a/src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs +++ b/src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs @@ -33,7 +33,7 @@ namespace Umbraco.Web.UI.Controls if (umbracoContext == null) throw new ArgumentNullException(nameof(umbracoContext)); UmbracoContext = umbracoContext; Umbraco = new UmbracoHelper(umbracoContext, services, appCache); - Members = new MembershipHelper(umbracoContext); + Members = Current.Container.GetInstance(); // fixme inject somehow Logger = Current.Logger; diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index f9708e5c04..2e06668954 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -109,6 +109,7 @@ + diff --git a/src/Umbraco.Web/UmbracoHelper.cs b/src/Umbraco.Web/UmbracoHelper.cs index 7375dac98d..a20a08fd76 100644 --- a/src/Umbraco.Web/UmbracoHelper.cs +++ b/src/Umbraco.Web/UmbracoHelper.cs @@ -160,7 +160,7 @@ namespace Umbraco.Web /// Gets the membership helper. /// public MembershipHelper MembershipHelper => _membershipHelper - ?? (_membershipHelper = new MembershipHelper(UmbracoContext)); + ?? (_membershipHelper = Current.Container.GetInstance()); /// /// Gets the url provider. From 9bc8ace8dbafb268a8ef29bc6552edb242ecf08a Mon Sep 17 00:00:00 2001 From: Stephan Date: Fri, 29 Jun 2018 13:17:46 +0200 Subject: [PATCH 016/469] TEMP --- .../RepositoryCompositionRoot.cs | 1 + src/Umbraco.Core/Composing/IContainer.cs | 54 +++++++- .../Composing/LightInject/ContainerAdapter.cs | 77 ++++++------ .../Composing/LightInjectExtensions.cs | 1 + .../Runtime/CoreRuntimeComponent.cs | 2 +- src/Umbraco.Tests/IO/FileSystemsTests.cs | 2 +- src/Umbraco.Tests/Models/ContentTests.cs | 2 +- src/Umbraco.Tests/Models/MediaXmlTest.cs | 2 +- .../PropertyEditors/ImageCropperTest.cs | 2 +- src/Umbraco.Tests/TestHelpers/TestObjects.cs | 2 +- src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 2 +- src/Umbraco.Web/UmbracoModule.cs | 115 ++++++++++++------ 12 files changed, 170 insertions(+), 92 deletions(-) diff --git a/src/Umbraco.Core/Composing/CompositionRoots/RepositoryCompositionRoot.cs b/src/Umbraco.Core/Composing/CompositionRoots/RepositoryCompositionRoot.cs index 2323da165a..42693f119d 100644 --- a/src/Umbraco.Core/Composing/CompositionRoots/RepositoryCompositionRoot.cs +++ b/src/Umbraco.Core/Composing/CompositionRoots/RepositoryCompositionRoot.cs @@ -22,6 +22,7 @@ namespace Umbraco.Core.Composing.CompositionRoots // register cache helpers // the main cache helper is registered by CoreBootManager and is used by most repositories // the disabled one is used by those repositories that have an annotated ctor parameter + // fixme refactor: use a DisabledCacheHelper class (or interface?) so that injection does not depend on name and we can have simple ctor injection container.RegisterSingleton(factory => CacheHelper.CreateDisabledCacheHelper(), DisabledCache); // resolve ctor dependency from GetInstance() runtimeArguments, if possible - 'factory' is diff --git a/src/Umbraco.Core/Composing/IContainer.cs b/src/Umbraco.Core/Composing/IContainer.cs index 331c1e9141..d31b57f564 100644 --- a/src/Umbraco.Core/Composing/IContainer.cs +++ b/src/Umbraco.Core/Composing/IContainer.cs @@ -6,16 +6,62 @@ using System.Threading.Tasks; namespace Umbraco.Core.Composing { + // fixme - must document! + + /// + /// Defines a container for Umbraco. + /// public interface IContainer { - T TryGetInstance(); + /// + /// Gets an instance. + /// + /// The type of the instance. + /// An instance of the specified type. + /// Throws an exception if the container failed to get an instance of the specified type. T GetInstance(); - object GetInstance(Type parameterType); - object ConcreteContainer { get; } + + /// + /// Gets an instance. + /// + /// The type of the instance. + /// An instance of the specified type. + /// Throws an exception if the container failed to get an instance of the specified type. + object GetInstance(Type type); + + /// + /// Tries to get an instance. + /// + /// The type of the instance. + /// An instance of the specified type, or null. + /// Returns null if the container does not know how to get an instance + /// of the specified type. Throws an exception if the container does know how + /// to get an instance of the specified type, but failed to do so. + T TryGetInstance(); + + // fixme document + T GetInstance(object[] args); + + // fixme register direct type? + // fixme register an instance? void RegisterSingleton(Func factory); void Register(Func factory); void Register(Func factory); + + /// + /// Registers and instanciates a collection builder. + /// + /// The type of the collection builder. + /// A collection builder of the specified type. T RegisterCollectionBuilder(); - T GetInstance(object[] args); + + // fixme move away! + object ConcreteContainer { get; } } + + // fixme would be nicer + //public interface IContainer : IContainer + //{ + // T ConcreteContainer { get; } + //} } diff --git a/src/Umbraco.Core/Composing/LightInject/ContainerAdapter.cs b/src/Umbraco.Core/Composing/LightInject/ContainerAdapter.cs index f7ffa68111..99ffb11ace 100644 --- a/src/Umbraco.Core/Composing/LightInject/ContainerAdapter.cs +++ b/src/Umbraco.Core/Composing/LightInject/ContainerAdapter.cs @@ -1,61 +1,56 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using LightInject; namespace Umbraco.Core.Composing.LightInject { - public class ContainerAdapter : IContainer + /// + /// Implements for LightInject. + /// + public class ContainerAdapter : IContainer // fixme rename LightInjectContainer? { - private readonly IServiceContainer container; - - public object ConcreteContainer => container; - - public void RegisterSingleton(Func factory) - { - container.RegisterSingleton(f => factory(this)); - } - - public void Register(Func factory) - { - container.Register(f => factory(this)); - } - - public void Register(Func factory) - { - container.Register((f, x) => factory(this, x)); - } - - public T RegisterCollectionBuilder() - { - return container.RegisterCollectionBuilder(); - } + private readonly IServiceContainer _container; + /// + /// Initializes a new instance of the with a LightInject container. + /// public ContainerAdapter(IServiceContainer container) { - this.container = container; + _container = container; } + // fixme + public object ConcreteContainer => _container; + + /// + public void RegisterSingleton(Func factory) + => _container.RegisterSingleton(f => factory(this)); + + /// + public void Register(Func factory) + => _container.Register(f => factory(this)); + + /// + public void Register(Func factory) + => _container.Register((f, x) => factory(this, x)); + + /// + public T RegisterCollectionBuilder() + => _container.RegisterCollectionBuilder(); + + /// public T TryGetInstance() - { - return container.TryGetInstance(); - } + => _container.TryGetInstance(); + /// public T GetInstance() - { - return container.GetInstance(); - } + => _container.GetInstance(); + /// public T GetInstance(object[] args) - { - return (T)container.GetInstance(typeof(T), args); - } + => (T) _container.GetInstance(typeof(T), args); + /// public object GetInstance(Type type) - { - return container.GetInstance(type); - } + => _container.GetInstance(type); } } diff --git a/src/Umbraco.Core/Composing/LightInjectExtensions.cs b/src/Umbraco.Core/Composing/LightInjectExtensions.cs index 314e03af84..914af001a8 100644 --- a/src/Umbraco.Core/Composing/LightInjectExtensions.cs +++ b/src/Umbraco.Core/Composing/LightInjectExtensions.cs @@ -44,6 +44,7 @@ namespace Umbraco.Core.Composing container.ScopeManagerProvider = new MixedLightInjectScopeManagerProvider(); // self-register + // fixme - WHERE is this used, and should it be a generic container, not LightInject's? container.Register(_ => container); // configure the current container diff --git a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs index a96b034d01..ce249d6b4a 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs @@ -46,7 +46,7 @@ namespace Umbraco.Core.Runtime // register filesystems - composition.Container.Register((f, wrappedFileSystem) => new MediaFileSystem(wrappedFileSystem, f.GetInstance(), f.GetInstance())); + composition.Container.Register((f, wrappedFileSystem) => new MediaFileSystem(wrappedFileSystem, f.GetInstance(), f.GetInstance(), f.GetInstance())); composition.Container.RegisterConstructorDependency((factory, parameterInfo) => factory.GetInstance().MediaFileSystem); composition.Container.RegisterSingleton(); diff --git a/src/Umbraco.Tests/IO/FileSystemsTests.cs b/src/Umbraco.Tests/IO/FileSystemsTests.cs index c0f13c6e1b..02d3d0a003 100644 --- a/src/Umbraco.Tests/IO/FileSystemsTests.cs +++ b/src/Umbraco.Tests/IO/FileSystemsTests.cs @@ -33,7 +33,7 @@ namespace Umbraco.Tests.IO _container.Register(_ => Mock.Of()); _container.Register(_ => Mock.Of()); - _container.Register((f, x) => new MediaFileSystem(x, f.GetInstance(), f.GetInstance())); + _container.Register((f, x) => new MediaFileSystem(x, f.GetInstance(), f.GetInstance(), f.GetInstance())); _container.Register((f, x) => new NonConfiguredTypeFileSystem(x)); // make sure we start clean diff --git a/src/Umbraco.Tests/Models/ContentTests.cs b/src/Umbraco.Tests/Models/ContentTests.cs index 41228eb89e..2d842cf741 100644 --- a/src/Umbraco.Tests/Models/ContentTests.cs +++ b/src/Umbraco.Tests/Models/ContentTests.cs @@ -39,7 +39,7 @@ namespace Umbraco.Tests.Models base.Compose(); Container.Register(_ => Mock.Of()); - Container.Register((factory, fileSystem) => new MediaFileSystem(fileSystem, factory.GetInstance(), factory.GetInstance())); + Container.Register((factory, fileSystem) => new MediaFileSystem(fileSystem, factory.GetInstance(), factory.GetInstance(), factory.GetInstance())); Container.Register(); Container.Register(_ => Mock.Of()); Container.Register(_ => Mock.Of()); diff --git a/src/Umbraco.Tests/Models/MediaXmlTest.cs b/src/Umbraco.Tests/Models/MediaXmlTest.cs index 1f4eaf9d8a..f97d6d1ada 100644 --- a/src/Umbraco.Tests/Models/MediaXmlTest.cs +++ b/src/Umbraco.Tests/Models/MediaXmlTest.cs @@ -29,7 +29,7 @@ namespace Umbraco.Tests.Models // reference, so static ctor runs, so event handlers register // and then, this will reset the width, height... because the file does not exist, of course ;-( - var ignored = new FileUploadPropertyEditor(Mock.Of(), new MediaFileSystem(Mock.Of(), Mock.Of(), Mock.Of())); + var ignored = new FileUploadPropertyEditor(Mock.Of(), new MediaFileSystem(Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of())); var media = MockedMedia.CreateMediaImage(mediaType, -1); media.WriterId = -1; // else it's zero and that's not a user and it breaks the tests diff --git a/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs b/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs index 8df585fb25..a1cf0ba281 100644 --- a/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs +++ b/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs @@ -72,7 +72,7 @@ namespace Umbraco.Tests.PropertyEditors container.Register(f => Mock.Of()); container.Register(f => Mock.Of()); - var mediaFileSystem = new MediaFileSystem(Mock.Of(), Mock.Of(), Mock.Of()); + var mediaFileSystem = new MediaFileSystem(Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of()); var dataTypeService = new TestObjects.TestDataTypeService( new DataType(new ImageCropperPropertyEditor(Mock.Of(), mediaFileSystem, Mock.Of())) { Id = 1 }); diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects.cs b/src/Umbraco.Tests/TestHelpers/TestObjects.cs index 7e3d887d77..e091cc8d49 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects.cs @@ -117,7 +117,7 @@ namespace Umbraco.Tests.TestHelpers if (logger == null) throw new ArgumentNullException(nameof(logger)); if (eventMessagesFactory == null) throw new ArgumentNullException(nameof(eventMessagesFactory)); - var mediaFileSystem = new MediaFileSystem(Mock.Of(), Mock.Of(), Mock.Of()); + var mediaFileSystem = new MediaFileSystem(Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of()); var externalLoginService = GetLazyService(container, c => new ExternalLoginService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); var publicAccessService = GetLazyService(container, c => new PublicAccessService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index d2a9481251..a457b76449 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -270,7 +270,7 @@ namespace Umbraco.Tests.Testing Container.RegisterSingleton(factory => umbracoSettings.Templates); // fixme - The whole MediaFileSystem coupling thing seems broken. - Container.Register((factory, fileSystem) => new MediaFileSystem(fileSystem, factory.GetInstance(), factory.GetInstance())); + Container.Register((factory, fileSystem) => new MediaFileSystem(fileSystem, factory.GetInstance(), factory.GetInstance(), factory.GetInstance())); Container.RegisterConstructorDependency((factory, parameterInfo) => factory.GetInstance().MediaFileSystem); Container.RegisterSingleton(factory => ExamineManager.Instance); diff --git a/src/Umbraco.Web/UmbracoModule.cs b/src/Umbraco.Web/UmbracoModule.cs index 7a12fd1130..e16e865ab9 100644 --- a/src/Umbraco.Web/UmbracoModule.cs +++ b/src/Umbraco.Web/UmbracoModule.cs @@ -4,10 +4,7 @@ using System.Collections.Generic; using System.IO; using System.Text; using System.Web; -using System.Web.Mvc; using System.Web.Routing; -using LightInject; -using Microsoft.Web.Infrastructure.DynamicModuleHelper; using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.IO; @@ -23,36 +20,76 @@ using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Web.Composing; using Umbraco.Web.PublishedCache; + + +// fixme +// need an UmbracoInjectedModules that is declared in web.config +// need a web.config configuration section w/ modules = umbraco.webServer/modules +// so it's all explicit [assembly: PreApplicationStartMethod(typeof(Umbraco.Web.ContainerUmbracoModule), "Start")] namespace Umbraco.Web -{ +{ + // fixme + // name that one UmbracoModule, and the nested one UmbracoRequestModule - deals with front-end requests + public class UmbracoModules : IHttpModule + { + private readonly List _modules = new List(); + + /// + public void Init(HttpApplication context) + { + // fixme - need to get moduleTypes from some sort of Umbraco configuration + + foreach (var moduleType in moduleTypes) + { + var module = (IHttpModule) Current.Container.GetInstance(moduleType); + _modules.Add(module); + module.Init(context); + } + } + + /// + public void Dispose() + { + foreach (var module in _modules) + module.Dispose(); + } + } + public class ContainerUmbracoModule : IHttpModule { - private UmbracoModule umbracoModule; + private static readonly Type[] ModuleTypes = + { + typeof(UmbracoModule) + }; + + private readonly List _modules = new List(); public static void Start() - { - DynamicModuleUtility.RegisterModule(typeof(ContainerUmbracoModule)); + { + // registers the ContainerUmbracoModule (without having to have it in web.config) + // fixme - in which order? is it going to be first or last? + // fixme - do we need to remove the original UmbracoModule from web.config then? + HttpApplication.RegisterModule(typeof(ContainerUmbracoModule)); } - public ContainerUmbracoModule() - { - - } - public void Init(HttpApplication context) { - // Should be extended with lazy list of modules from registry - // Example here: https://haacked.com/archive/2011/06/03/dependency-injection-with-asp-net-httpmodules.aspx/ + // see: https://haacked.com/archive/2011/06/03/dependency-injection-with-asp-net-httpmodules.aspx/ - umbracoModule = Current.Container.GetInstance(); - umbracoModule.Init(context); + foreach (var moduleType in ModuleTypes) + { + var module = (IHttpModule) Current.Container.GetInstance(moduleType); + _modules.Add(module); + module.Init(context); + } } public void Dispose() { - umbracoModule.Dispose(); + foreach (var module in _modules) + module.Dispose(); } } @@ -65,32 +102,30 @@ namespace Umbraco.Web public class UmbracoModule : IHttpModule { #region Dependencies - - // modules are *not* instanciated by the container so we have to - // get our dependencies injected manually, through properties, in - // Init(). works for dependencies that are singletons. - - public IUmbracoSettingsSection UmbracoSettings { get; set; } - - public IGlobalSettings GlobalSettings { get; set; } - - public IUmbracoContextAccessor UmbracoContextAccessor { get; set; } - - public IPublishedSnapshotService PublishedSnapshotService { get; set; } - - public IUserService UserService { get; set; } - public UrlProviderCollection UrlProviders { get; set; } + // fixme these dont need to be publish and properties anymore?! - public IRuntimeState Runtime { get; set; } + public IUmbracoSettingsSection UmbracoSettings { get; } - public ILogger Logger { get; set; } + public IGlobalSettings GlobalSettings { get; } - internal PublishedRouter PublishedRouter { get; set; } + public IUmbracoContextAccessor UmbracoContextAccessor { get; } - internal IUmbracoDatabaseFactory DatabaseFactory { get; set; } + public IPublishedSnapshotService PublishedSnapshotService { get; } + + public IUserService UserService { get; } - internal IVariationContextAccessor VariationContextAccessor { get; set; } + public UrlProviderCollection UrlProviders { get; } + + public IRuntimeState Runtime { get; } + + public ILogger Logger { get; } + + internal PublishedRouter PublishedRouter { get; } + + internal IUmbracoDatabaseFactory DatabaseFactory { get; } + + internal IVariationContextAccessor VariationContextAccessor { get; } #endregion @@ -105,8 +140,7 @@ namespace Umbraco.Web ILogger logger, PublishedRouter publishedRouter, IUmbracoDatabaseFactory databaseFactory, - IVariationContextAccessor variationContextAccessor - ) + IVariationContextAccessor variationContextAccessor) { _combinedRouteCollection = new Lazy(CreateRouteCollection); @@ -558,7 +592,7 @@ namespace Umbraco.Web /// public void Init(HttpApplication app) { - if (Core.Composing.Current.RuntimeState.Level == RuntimeLevel.BootFailed) + if (Core.Composing.Current.RuntimeState.Level == RuntimeLevel.BootFailed) // fixme inject the runtimeState! { // there's nothing we can do really app.BeginRequest += (sender, args) => @@ -589,6 +623,7 @@ namespace Umbraco.Web return; } + // fixme // modules **are** instanciated by the container so we **don't** have to // get our dependencies injected manually, through properties. //Core.Composing.Current.Container.InjectProperties(this); From eb8b3965b83d837081e7c33432f2c2a10502fc26 Mon Sep 17 00:00:00 2001 From: Stephan Date: Fri, 6 Jul 2018 18:37:07 +0200 Subject: [PATCH 017/469] Split UmbracoModule, UmbracoInjectedModule --- .../Routing/UmbracoModuleTests.cs | 18 +- src/Umbraco.Web/Composing/ModuleInjector.cs | 28 + src/Umbraco.Web/Runtime/WebRuntime.cs | 2 +- src/Umbraco.Web/Umbraco.Web.csproj | 4 +- src/Umbraco.Web/UmbracoInjectedModule.cs | 575 +++++++++++++++ src/Umbraco.Web/UmbracoModule.cs | 690 +----------------- 6 files changed, 642 insertions(+), 675 deletions(-) create mode 100644 src/Umbraco.Web/Composing/ModuleInjector.cs create mode 100644 src/Umbraco.Web/UmbracoInjectedModule.cs diff --git a/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs b/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs index 09a11ebf57..92c49b0950 100644 --- a/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs +++ b/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs @@ -26,7 +26,7 @@ namespace Umbraco.Tests.Routing [Apartment(ApartmentState.STA)] public class UmbracoModuleTests : BaseWebTest { - private UmbracoModule _module; + private UmbracoInjectedModule _module; public override void SetUp() { @@ -34,23 +34,23 @@ namespace Umbraco.Tests.Routing // fixme - be able to get the UmbracoModule from the container. any reason settings were from testobjects? //create the module - _module = new UmbracoModule + var logger = Mock.Of(); + var globalSettings = TestObjects.GetGlobalSettings(); + var runtime = new RuntimeState(logger, new Lazy(), new Lazy(), Mock.Of(), globalSettings); + + _module = new UmbracoInjectedModule ( - TestObjects.GetUmbracoSettings(), - TestObjects.GetGlobalSettings(), + globalSettings, Mock.Of(), Container.GetInstance(), Container.GetInstance(), new UrlProviderCollection(new IUrlProvider[0]), - Container.GetInstance(), - Mock.Of(), + runtime, + logger, null, // fixme - PublishedRouter complexities... - Container.GetInstance(), Mock.Of() ); - var runtime = new RuntimeState(_module.Logger, new Lazy(), new Lazy(), Mock.Of(), _module.GlobalSettings); - _module.Runtime = runtime; runtime.Level = RuntimeLevel.Run; diff --git a/src/Umbraco.Web/Composing/ModuleInjector.cs b/src/Umbraco.Web/Composing/ModuleInjector.cs new file mode 100644 index 0000000000..550cb8efc3 --- /dev/null +++ b/src/Umbraco.Web/Composing/ModuleInjector.cs @@ -0,0 +1,28 @@ +using System.Web; + +namespace Umbraco.Web.Composing +{ + /// + /// Provides a base class for module injectors. + /// + /// The type of the injected module. + public abstract class ModuleInjector : IHttpModule + where TModule : IHttpModule + { + protected TModule Module { get; private set; } + + /// + public void Init(HttpApplication context) + { + // using the service locator here - no other way, really + Module = Current.Container.GetInstance(); + Module.Init(context); + } + + /// + public void Dispose() + { + Module?.Dispose(); + } + } +} diff --git a/src/Umbraco.Web/Runtime/WebRuntime.cs b/src/Umbraco.Web/Runtime/WebRuntime.cs index 9d08a4d85b..0beacb1ee5 100644 --- a/src/Umbraco.Web/Runtime/WebRuntime.cs +++ b/src/Umbraco.Web/Runtime/WebRuntime.cs @@ -56,7 +56,7 @@ namespace Umbraco.Web.Runtime { base.Compose(container); - container.Register(); + container.Register(); // replace CoreRuntime's IProfiler registration container.RegisterSingleton(_ => _webProfiler); diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index dc21016e2c..35d6d240e9 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -262,6 +262,7 @@ + @@ -431,6 +432,7 @@ ASPXCodeBehind + @@ -1406,7 +1408,7 @@ - + True diff --git a/src/Umbraco.Web/UmbracoInjectedModule.cs b/src/Umbraco.Web/UmbracoInjectedModule.cs new file mode 100644 index 0000000000..2a85851e99 --- /dev/null +++ b/src/Umbraco.Web/UmbracoInjectedModule.cs @@ -0,0 +1,575 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Web; +using System.Web.Routing; +using Umbraco.Core; +using Umbraco.Core.Configuration; +using Umbraco.Core.IO; +using Umbraco.Core.Logging; +using Umbraco.Web.Routing; +using Umbraco.Web.Security; +using Umbraco.Core.Exceptions; +using Umbraco.Core.Models.PublishedContent; +using Umbraco.Core.Security; +using Umbraco.Core.Services; +using Umbraco.Web.Composing; +using Umbraco.Web.PublishedCache; + +namespace Umbraco.Web +{ + // notes + // + // also look at IOHelper.ResolveUrlsFromTextString - nightmarish?! + // + // context.RewritePath supports ~/ or else must begin with /vdir + // Request.RawUrl is still there + // response.Redirect does?! always remap to /vdir?! + + /// + /// Represents the main Umbraco module. + /// + /// + /// Is registered by the . + /// Do *not* try to use that one as a module in web.config. + /// + public class UmbracoInjectedModule : IHttpModule + { + private readonly IGlobalSettings _globalSettings; + private readonly IUmbracoContextAccessor _umbracoContextAccessor; + private readonly IPublishedSnapshotService _publishedSnapshotService; + private readonly IUserService _userService; + private readonly UrlProviderCollection _urlProviders; + private readonly IRuntimeState _runtime; + private readonly ILogger _logger; + private readonly PublishedRouter _publishedRouter; + private readonly IVariationContextAccessor _variationContextAccessor; + + public UmbracoInjectedModule( + IGlobalSettings globalSettings, + IUmbracoContextAccessor umbracoContextAccessor, + IPublishedSnapshotService publishedSnapshotService, + IUserService userService, + UrlProviderCollection urlProviders, + IRuntimeState runtime, + ILogger logger, + PublishedRouter publishedRouter, + IVariationContextAccessor variationContextAccessor) + { + _combinedRouteCollection = new Lazy(CreateRouteCollection); + + _globalSettings = globalSettings; + _umbracoContextAccessor = umbracoContextAccessor; + _publishedSnapshotService = publishedSnapshotService; + _userService = userService; + _urlProviders = urlProviders; + _runtime = runtime; + _logger = logger; + _publishedRouter = publishedRouter; + _variationContextAccessor = variationContextAccessor; + } + + #region HttpModule event handlers + + /// + /// Begins to process a request. + /// + /// + private void BeginRequest(HttpContextBase httpContext) + { + // ensure application url is initialized + ((RuntimeState) Current.RuntimeState).EnsureApplicationUrl(httpContext.Request); + + // do not process if client-side request + if (httpContext.Request.Url.IsClientSideRequest()) + return; + + // write the trace output for diagnostics at the end of the request + httpContext.Trace.Write("UmbracoModule", "Umbraco request begins"); + + // ok, process + + // create the LegacyRequestInitializer + // and initialize legacy stuff + var legacyRequestInitializer = new LegacyRequestInitializer(httpContext.Request.Url, httpContext); + legacyRequestInitializer.InitializeRequest(); + + // create the UmbracoContext singleton, one per request, and assign + // replace existing if any (eg during app startup, a temp one is created) + UmbracoContext.EnsureContext( + _umbracoContextAccessor, + httpContext, + _publishedSnapshotService, + new WebSecurity(httpContext, _userService, _globalSettings), + UmbracoConfig.For.UmbracoSettings(), + _urlProviders, + _globalSettings, + _variationContextAccessor, + true); + } + + /// + /// Processses the Umbraco Request + /// + /// + /// + /// + /// This will check if we are trying to route to the default back office page (i.e. ~/Umbraco/ or ~/Umbraco or ~/Umbraco/Default ) + /// and ensure that the MVC handler executes for that. This is required because the route for /Umbraco will never execute because + /// files/folders exist there and we cannot set the RouteCollection.RouteExistingFiles = true since that will muck a lot of other things up. + /// So we handle it here and explicitly execute the MVC controller. + /// + /// + void ProcessRequest(HttpContextBase httpContext) + { + // do not process if client-side request + if (httpContext.Request.Url.IsClientSideRequest()) + return; + + if (UmbracoContext.Current == null) + throw new InvalidOperationException("The UmbracoContext.Current is null, ProcessRequest cannot proceed unless there is a current UmbracoContext"); + + var umbracoContext = UmbracoContext.Current; + + // re-write for the default back office path + if (httpContext.Request.Url.IsDefaultBackOfficeRequest(_globalSettings)) + { + if (EnsureRuntime(httpContext, umbracoContext.OriginalRequestUrl)) + RewriteToBackOfficeHandler(httpContext); + return; + } + + // do not process if this request is not a front-end routable page + var isRoutableAttempt = EnsureUmbracoRoutablePage(umbracoContext, httpContext); + + // raise event here + UmbracoModule.OnRouteAttempt(this, new RoutableAttemptEventArgs(isRoutableAttempt.Result, umbracoContext, httpContext)); + if (isRoutableAttempt.Success == false) return; + + httpContext.Trace.Write("UmbracoModule", "Umbraco request confirmed"); + + // ok, process + + // note: requestModule.UmbracoRewrite also did some stripping of &umbPage + // from the querystring... that was in v3.x to fix some issues with pre-forms + // auth. Paul Sterling confirmed in jan. 2013 that we can get rid of it. + + // instanciate, prepare and process the published content request + // important to use CleanedUmbracoUrl - lowercase path-only version of the current url + var request = _publishedRouter.CreateRequest(umbracoContext); + umbracoContext.PublishedRequest = request; + _publishedRouter.PrepareRequest(request); + + // HandleHttpResponseStatus returns a value indicating that the request should + // not be processed any further, eg because it has been redirect. then, exit. + if (UmbracoModule.HandleHttpResponseStatus(httpContext, request, _logger)) + return; + + if (request.HasPublishedContent == false) + httpContext.RemapHandler(new PublishedContentNotFoundHandler()); + else + RewriteToUmbracoHandler(httpContext, request); + } + + #endregion + + #region Methods + + /// + /// Checks the current request and ensures that it is routable based on the structure of the request and URI + /// + /// + /// + /// + internal Attempt EnsureUmbracoRoutablePage(UmbracoContext context, HttpContextBase httpContext) + { + var uri = context.OriginalRequestUrl; + + var reason = EnsureRoutableOutcome.IsRoutable; + + // ensure this is a document request + if (EnsureDocumentRequest(httpContext, uri) == false) + { + reason = EnsureRoutableOutcome.NotDocumentRequest; + } + // ensure the runtime is in the proper state + // and deal with needed redirects, etc + else if (EnsureRuntime(httpContext, uri) == false) + { + reason = EnsureRoutableOutcome.NotReady; + } + // ensure Umbraco has documents to serve + else if (EnsureHasContent(context, httpContext) == false) + { + reason = EnsureRoutableOutcome.NoContent; + } + + return Attempt.If(reason == EnsureRoutableOutcome.IsRoutable, reason); + } + + /// + /// Ensures that the request is a document request (i.e. one that the module should handle) + /// + /// + /// + /// + private bool EnsureDocumentRequest(HttpContextBase httpContext, Uri uri) + { + var maybeDoc = true; + var lpath = uri.AbsolutePath.ToLowerInvariant(); + + // handle directory-urls used for asmx + // legacy - what's the point really? + if (/*maybeDoc &&*/ _globalSettings.UseDirectoryUrls) + { + var asmxPos = lpath.IndexOf(".asmx/", StringComparison.OrdinalIgnoreCase); + if (asmxPos >= 0) + { + // use uri.AbsolutePath, not path, 'cos path has been lowercased + httpContext.RewritePath(uri.AbsolutePath.Substring(0, asmxPos + 5), // filePath + uri.AbsolutePath.Substring(asmxPos + 5), // pathInfo + uri.Query.TrimStart('?')); + maybeDoc = false; + } + } + + // a document request should be + // /foo/bar/nil + // /foo/bar/nil/ + // /foo/bar/nil.aspx + // where /foo is not a reserved path + + // if the path contains an extension that is not .aspx + // then it cannot be a document request + var extension = Path.GetExtension(lpath); + if (maybeDoc && extension.IsNullOrWhiteSpace() == false && extension != ".aspx") + maybeDoc = false; + + // at that point, either we have no extension, or it is .aspx + + // if the path is reserved then it cannot be a document request + if (maybeDoc && _globalSettings.IsReservedPathOrUrl(lpath, httpContext, _combinedRouteCollection.Value)) + maybeDoc = false; + + //NOTE: No need to warn, plus if we do we should log the document, as this message doesn't really tell us anything :) + //if (!maybeDoc) + //{ + // Logger.Warn("Not a document"); + //} + + return maybeDoc; + } + + private bool EnsureRuntime(HttpContextBase httpContext, Uri uri) + { + var debug = _runtime.Debug; + var level = _runtime.Level; + switch (level) + { + case RuntimeLevel.Unknown: + case RuntimeLevel.Boot: + // not ready yet, but wait + ReportRuntime(level, "Umbraco is booting."); + + // let requests pile up and wait for 10s then show the splash anyway + if (UmbracoConfig.For.UmbracoSettings().Content.EnableSplashWhileLoading == false + && ((RuntimeState) _runtime).WaitForRunLevel(TimeSpan.FromSeconds(10))) return true; + + // redirect to booting page + httpContext.Response.StatusCode = 503; // temp not available + const string bootUrl = "~/config/splashes/booting.aspx"; + httpContext.Response.AddHeader("Retry-After", debug ? "1" : "30"); // seconds + httpContext.RewritePath(UriUtility.ToAbsolute(bootUrl) + "?url=" + HttpUtility.UrlEncode(uri.ToString())); + return false; // cannot serve content + + case RuntimeLevel.BootFailed: + // redirect to death page + ReportRuntime(level, "Umbraco has failed."); + + httpContext.Response.StatusCode = 503; // temp not available + const string deathUrl = "~/config/splashes/death.aspx"; + httpContext.Response.AddHeader("Retry-After", debug ? "1" : "300"); // seconds + httpContext.RewritePath(UriUtility.ToAbsolute(deathUrl) + "?url=" + HttpUtility.UrlEncode(uri.ToString())); + return false; // cannot serve content + + case RuntimeLevel.Run: + // ok + return true; + + case RuntimeLevel.Install: + case RuntimeLevel.Upgrade: + // redirect to install + ReportRuntime(level, "Umbraco must install or upgrade."); + var installPath = UriUtility.ToAbsolute(SystemDirectories.Install); + var installUrl = $"{installPath}/?redir=true&url={HttpUtility.UrlEncode(uri.ToString())}"; + httpContext.Response.Redirect(installUrl, true); + return false; // cannot serve content + + default: + throw new NotSupportedException($"Unexpected runtime level: {Current.RuntimeState.Level}."); + } + } + + private static bool _reported; + private static RuntimeLevel _reportedLevel; + + private void ReportRuntime(RuntimeLevel level, string message) + { + if (_reported && _reportedLevel == level) return; + _reported = true; + _reportedLevel = level; + _logger.Warn(message); + } + + // ensures Umbraco has at least one published node + // if not, rewrites to splash and return false + // if yes, return true + private bool EnsureHasContent(UmbracoContext context, HttpContextBase httpContext) + { + if (context.ContentCache.HasContent()) + return true; + + _logger.Warn("Umbraco has no content"); + + const string noContentUrl = "~/config/splashes/noNodes.aspx"; + httpContext.RewritePath(UriUtility.ToAbsolute(noContentUrl)); + + return false; + } + + /// + /// Rewrites to the default back office page. + /// + /// + private void RewriteToBackOfficeHandler(HttpContextBase context) + { + // GlobalSettings.Path has already been through IOHelper.ResolveUrl() so it begins with / and vdir (if any) + var rewritePath = _globalSettings.Path.TrimEnd('/') + "/Default"; + // rewrite the path to the path of the handler (i.e. /umbraco/RenderMvc) + context.RewritePath(rewritePath, "", "", false); + + //if it is MVC we need to do something special, we are not using TransferRequest as this will + //require us to rewrite the path with query strings and then reparse the query strings, this would + //also mean that we need to handle IIS 7 vs pre-IIS 7 differently. Instead we are just going to create + //an instance of the UrlRoutingModule and call it's PostResolveRequestCache method. This does: + // * Looks up the route based on the new rewritten URL + // * Creates the RequestContext with all route parameters and then executes the correct handler that matches the route + //we also cannot re-create this functionality because the setter for the HttpContext.Request.RequestContext is internal + //so really, this is pretty much the only way without using Server.TransferRequest and if we did that, we'd have to rethink + //a bunch of things! + var urlRouting = new UrlRoutingModule(); + urlRouting.PostResolveRequestCache(context); + } + + /// + /// Rewrites to the Umbraco handler - we always send the request via our MVC rendering engine, this will deal with + /// requests destined for webforms. + /// + /// + /// + private void RewriteToUmbracoHandler(HttpContextBase context, PublishedRequest pcr) + { + // NOTE: we do not want to use TransferRequest even though many docs say it is better with IIS7, turns out this is + // not what we need. The purpose of TransferRequest is to ensure that .net processes all of the rules for the newly + // rewritten url, but this is not what we want! + // read: http://forums.iis.net/t/1146511.aspx + + var query = pcr.Uri.Query.TrimStart('?'); + + // GlobalSettings.Path has already been through IOHelper.ResolveUrl() so it begins with / and vdir (if any) + var rewritePath = _globalSettings.Path.TrimEnd('/') + "/RenderMvc"; + // rewrite the path to the path of the handler (i.e. /umbraco/RenderMvc) + context.RewritePath(rewritePath, "", query, false); + + //if it is MVC we need to do something special, we are not using TransferRequest as this will + //require us to rewrite the path with query strings and then reparse the query strings, this would + //also mean that we need to handle IIS 7 vs pre-IIS 7 differently. Instead we are just going to create + //an instance of the UrlRoutingModule and call it's PostResolveRequestCache method. This does: + // * Looks up the route based on the new rewritten URL + // * Creates the RequestContext with all route parameters and then executes the correct handler that matches the route + //we also cannot re-create this functionality because the setter for the HttpContext.Request.RequestContext is internal + //so really, this is pretty much the only way without using Server.TransferRequest and if we did that, we'd have to rethink + //a bunch of things! + var urlRouting = new UrlRoutingModule(); + urlRouting.PostResolveRequestCache(context); + } + + + /// + /// Any object that is in the HttpContext.Items collection that is IDisposable will get disposed on the end of the request + /// + /// + private void DisposeHttpContextItems(HttpContext http) + { + // do not process if client-side request + if (http.Request.Url.IsClientSideRequest()) + return; + + //get a list of keys to dispose + var keys = new HashSet(); + foreach (DictionaryEntry i in http.Items) + { + if (i.Value is IDisposeOnRequestEnd || i.Key is IDisposeOnRequestEnd) + { + keys.Add(i.Key); + } + } + //dispose each item and key that was found as disposable. + foreach (var k in keys) + { + try + { + http.Items[k].DisposeIfDisposable(); + } + catch (Exception ex) + { + _logger.Error("Could not dispose item with key " + k, ex); + } + try + { + k.DisposeIfDisposable(); + } + catch (Exception ex) + { + _logger.Error("Could not dispose item key " + k, ex); + } + } + } + + #endregion + + #region IHttpModule + + /// + /// Initialize the module, this will trigger for each new application + /// and there may be more than 1 application per application domain + /// + /// + public void Init(HttpApplication app) + { + if (_runtime.Level == RuntimeLevel.BootFailed) + { + // there's nothing we can do really + app.BeginRequest += (sender, args) => + { + // would love to avoid throwing, and instead display a customized Umbraco 500 + // page - however if we don't throw here, something else might go wrong, and + // it's this later exception that would be reported. could not figure out how + // to prevent it, either with httpContext.Response.End() or .ApplicationInstance + // .CompleteRequest() + + // also, if something goes wrong with our DI setup, the logging subsystem may + // not even kick in, so here we try to give as much detail as possible + + Exception e = Core.Composing.Current.RuntimeState.BootFailedException; + if (e == null) + throw new BootFailedException(BootFailedException.DefaultMessage); + var m = new StringBuilder(); + m.Append(BootFailedException.DefaultMessage); + while (e != null) + { + m.Append($"\n\n-> {e.GetType().FullName}: {e.Message}"); + if (string.IsNullOrWhiteSpace(e.StackTrace) == false) + m.Append($"\n{e.StackTrace}"); + e = e.InnerException; + } + throw new BootFailedException(m.ToString()); + }; + return; + } + + app.BeginRequest += (sender, e) => + { + var httpContext = ((HttpApplication) sender).Context; + _logger.Debug(() => $"Begin request: {httpContext.Request.Url}."); + BeginRequest(new HttpContextWrapper(httpContext)); + }; + + //disable asp.net headers (security) + // This is the correct place to modify headers according to MS: + // https://our.umbraco.org/forum/umbraco-7/using-umbraco-7/65241-Heap-error-from-header-manipulation?p=0#comment220889 + app.PostReleaseRequestState += (sender, args) => + { + var httpContext = ((HttpApplication) sender).Context; + try + { + httpContext.Response.Headers.Remove("Server"); + //this doesn't normally work since IIS sets it but we'll keep it here anyways. + httpContext.Response.Headers.Remove("X-Powered-By"); + httpContext.Response.Headers.Remove("X-AspNet-Version"); + httpContext.Response.Headers.Remove("X-AspNetMvc-Version"); + } + catch (PlatformNotSupportedException) + { + // can't remove headers this way on IIS6 or cassini. + } + }; + + app.PostAuthenticateRequest += (sender, e) => + { + var httpContext = ((HttpApplication) sender).Context; + //ensure the thread culture is set + httpContext.User?.Identity?.EnsureCulture(); + }; + + app.PostResolveRequestCache += (sender, e) => + { + var httpContext = ((HttpApplication) sender).Context; + ProcessRequest(new HttpContextWrapper(httpContext)); + }; + + app.EndRequest += (sender, args) => + { + var httpContext = ((HttpApplication) sender).Context; + + if (UmbracoContext.Current != null && UmbracoContext.Current.IsFrontEndUmbracoRequest) + { + _logger.Debug(() => $"End Request. ({DateTime.Now.Subtract(UmbracoContext.Current.ObjectCreated).TotalMilliseconds}ms)"); + } + + UmbracoModule.OnEndRequest(this, new UmbracoRequestEventArgs(UmbracoContext.Current, new HttpContextWrapper(httpContext))); + + DisposeHttpContextItems(httpContext); + }; + } + + public void Dispose() + { } + + #endregion + + /// + /// This is used to be passed into the GlobalSettings.IsReservedPathOrUrl and will include some 'fake' routes + /// used to determine if a path is reserved. + /// + /// + /// This is basically used to reserve paths dynamically + /// + private readonly Lazy _combinedRouteCollection; + + private RouteCollection CreateRouteCollection() + { + var routes = new RouteCollection(); + + foreach (var route in RouteTable.Routes) + routes.Add(route); + + foreach (var reservedPath in UmbracoModule.ReservedPaths) + { + try + { + routes.Add("_umbreserved_" + reservedPath.ReplaceNonAlphanumericChars(""), + new Route(reservedPath.TrimStart('/'), new StopRoutingHandler())); + } + catch (Exception ex) + { + _logger.Error("Could not add reserved path route", ex); + } + } + + return routes; + } + } +} diff --git a/src/Umbraco.Web/UmbracoModule.cs b/src/Umbraco.Web/UmbracoModule.cs index ef348952a8..819c144f26 100644 --- a/src/Umbraco.Web/UmbracoModule.cs +++ b/src/Umbraco.Web/UmbracoModule.cs @@ -1,428 +1,46 @@ using System; -using System.Collections; -using System.Collections.Generic; -using System.IO; -using System.Text; using System.Web; -using System.Web.Routing; -using Umbraco.Core; -using Umbraco.Core.Configuration; -using Umbraco.Core.IO; -using Umbraco.Core.Logging; -using Umbraco.Web.Routing; -using Umbraco.Web.Security; using Umbraco.Core.Collections; -using Umbraco.Core.Configuration.UmbracoSettings; -using Umbraco.Core.Exceptions; -using Umbraco.Core.Models.PublishedContent; -using Umbraco.Core.Persistence; -using Umbraco.Core.Security; -using Umbraco.Core.Services; +using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; using Umbraco.Web.Composing; -using Umbraco.Web.PublishedCache; +using Umbraco.Web.Routing; - -// fixme -// need an UmbracoInjectedModules that is declared in web.config -// need a web.config configuration section w/ modules = umbraco.webServer/modules -// so it's all explicit - -[assembly: PreApplicationStartMethod(typeof(Umbraco.Web.ContainerUmbracoModule), "Start")] namespace Umbraco.Web { - // fixme - // name that one UmbracoModule, and the nested one UmbracoRequestModule - deals with front-end requests - public class UmbracoModules : IHttpModule + /// + /// Represents the main Umbraco module. + /// + /// + /// Register that one in web.config. + /// It will inject which contains most of the actual code. + /// + public class UmbracoModule : ModuleInjector { - private readonly List _modules = new List(); - - /// - public void Init(HttpApplication context) - { - // fixme - need to get moduleTypes from some sort of Umbraco configuration - - foreach (var moduleType in moduleTypes) - { - var module = (IHttpModule) Current.Container.GetInstance(moduleType); - _modules.Add(module); - module.Init(context); - } - } - - /// - public void Dispose() - { - foreach (var module in _modules) - module.Dispose(); - } - } - - public class ContainerUmbracoModule : IHttpModule - { - private static readonly Type[] ModuleTypes = - { - typeof(UmbracoModule) - }; - - private readonly List _modules = new List(); - - public static void Start() - { - // registers the ContainerUmbracoModule (without having to have it in web.config) - // fixme - in which order? is it going to be first or last? - // fixme - do we need to remove the original UmbracoModule from web.config then? - HttpApplication.RegisterModule(typeof(ContainerUmbracoModule)); - } - - public void Init(HttpApplication context) - { - // see: https://haacked.com/archive/2011/06/03/dependency-injection-with-asp-net-httpmodules.aspx/ - - foreach (var moduleType in ModuleTypes) - { - var module = (IHttpModule) Current.Container.GetInstance(moduleType); - _modules.Add(module); - module.Init(context); - } - } - - public void Dispose() - { - foreach (var module in _modules) - module.Dispose(); - } - } - - // also look at IOHelper.ResolveUrlsFromTextString - nightmarish?! - - // context.RewritePath supports ~/ or else must begin with /vdir - // Request.RawUrl is still there - // response.Redirect does?! always remap to /vdir?! - - public class UmbracoModule : IHttpModule - { - #region Dependencies - - // fixme these dont need to be publish and properties anymore?! - - public IUmbracoSettingsSection UmbracoSettings { get; } - - public IGlobalSettings GlobalSettings { get; } - - public IUmbracoContextAccessor UmbracoContextAccessor { get; } - - public IPublishedSnapshotService PublishedSnapshotService { get; } - - public IUserService UserService { get; } - - public UrlProviderCollection UrlProviders { get; } - - public IRuntimeState Runtime { get; } - - public ILogger Logger { get; } - - internal PublishedRouter PublishedRouter { get; } - - internal IUmbracoDatabaseFactory DatabaseFactory { get; } - - internal IVariationContextAccessor VariationContextAccessor { get; } - - #endregion - - public UmbracoModule( - IUmbracoSettingsSection umbracoSettings, - IGlobalSettings globalSettings, - IUmbracoContextAccessor umbracoContextAccessor, - IPublishedSnapshotService publishedSnapshotService, - IUserService userService, - UrlProviderCollection urlProviders, - IRuntimeState runtime, - ILogger logger, - PublishedRouter publishedRouter, - IUmbracoDatabaseFactory databaseFactory, - IVariationContextAccessor variationContextAccessor) - { - _combinedRouteCollection = new Lazy(CreateRouteCollection); - - UmbracoSettings = umbracoSettings; - GlobalSettings = globalSettings; - UmbracoContextAccessor = umbracoContextAccessor; - PublishedSnapshotService = publishedSnapshotService; - UserService = userService; - UrlProviders = urlProviders; - Runtime = runtime; - Logger = logger; - PublishedRouter = publishedRouter; - DatabaseFactory = databaseFactory; - VariationContextAccessor = variationContextAccessor; - } - - #region HttpModule event handlers + /// + /// Occurs when... + /// + internal static event EventHandler RouteAttempt; /// - /// Begins to process a request. + /// Occurs when... /// - /// - private void BeginRequest(HttpContextBase httpContext) + public static event EventHandler EndRequest; + + /// + /// Triggers the RouteAttempt event. + /// + internal static void OnRouteAttempt(object sender, RoutableAttemptEventArgs args) { - // ensure application url is initialized - ((RuntimeState) Current.RuntimeState).EnsureApplicationUrl(httpContext.Request); - - // do not process if client-side request - if (httpContext.Request.Url.IsClientSideRequest()) - return; - - // write the trace output for diagnostics at the end of the request - httpContext.Trace.Write("UmbracoModule", "Umbraco request begins"); - - // ok, process - - // create the LegacyRequestInitializer - // and initialize legacy stuff - var legacyRequestInitializer = new LegacyRequestInitializer(httpContext.Request.Url, httpContext); - legacyRequestInitializer.InitializeRequest(); - - // create the UmbracoContext singleton, one per request, and assign - // replace existing if any (eg during app startup, a temp one is created) - UmbracoContext.EnsureContext( - UmbracoContextAccessor, - httpContext, - PublishedSnapshotService, - new WebSecurity(httpContext, UserService, GlobalSettings), - UmbracoConfig.For.UmbracoSettings(), - UrlProviders, - GlobalSettings, - VariationContextAccessor, - true); + RouteAttempt?.Invoke(sender, args); } /// - /// Processses the Umbraco Request + /// Triggers the EndRequest event. /// - /// - /// - /// - /// This will check if we are trying to route to the default back office page (i.e. ~/Umbraco/ or ~/Umbraco or ~/Umbraco/Default ) - /// and ensure that the MVC handler executes for that. This is required because the route for /Umbraco will never execute because - /// files/folders exist there and we cannot set the RouteCollection.RouteExistingFiles = true since that will muck a lot of other things up. - /// So we handle it here and explicitly execute the MVC controller. - /// - /// - void ProcessRequest(HttpContextBase httpContext) + internal static void OnEndRequest(object sender, UmbracoRequestEventArgs args) { - // do not process if client-side request - if (httpContext.Request.Url.IsClientSideRequest()) - return; - - if (UmbracoContext.Current == null) - throw new InvalidOperationException("The UmbracoContext.Current is null, ProcessRequest cannot proceed unless there is a current UmbracoContext"); - - var umbracoContext = UmbracoContext.Current; - - // re-write for the default back office path - if (httpContext.Request.Url.IsDefaultBackOfficeRequest(GlobalSettings)) - { - if (EnsureRuntime(httpContext, umbracoContext.OriginalRequestUrl)) - RewriteToBackOfficeHandler(httpContext); - return; - } - - // do not process if this request is not a front-end routable page - var isRoutableAttempt = EnsureUmbracoRoutablePage(umbracoContext, httpContext); - - // raise event here - OnRouteAttempt(new RoutableAttemptEventArgs(isRoutableAttempt.Result, umbracoContext, httpContext)); - if (isRoutableAttempt.Success == false) return; - - httpContext.Trace.Write("UmbracoModule", "Umbraco request confirmed"); - - // ok, process - - // note: requestModule.UmbracoRewrite also did some stripping of &umbPage - // from the querystring... that was in v3.x to fix some issues with pre-forms - // auth. Paul Sterling confirmed in jan. 2013 that we can get rid of it. - - // instanciate, prepare and process the published content request - // important to use CleanedUmbracoUrl - lowercase path-only version of the current url - var request = PublishedRouter.CreateRequest(umbracoContext); - umbracoContext.PublishedRequest = request; - PublishedRouter.PrepareRequest(request); - - // HandleHttpResponseStatus returns a value indicating that the request should - // not be processed any further, eg because it has been redirect. then, exit. - if (HandleHttpResponseStatus(httpContext, request, Logger)) - return; - - if (request.HasPublishedContent == false) - httpContext.RemapHandler(new PublishedContentNotFoundHandler()); - else - RewriteToUmbracoHandler(httpContext, request); - } - - #endregion - - #region Methods - - /// - /// Checks the current request and ensures that it is routable based on the structure of the request and URI - /// - /// - /// - /// - internal Attempt EnsureUmbracoRoutablePage(UmbracoContext context, HttpContextBase httpContext) - { - var uri = context.OriginalRequestUrl; - - var reason = EnsureRoutableOutcome.IsRoutable; - - // ensure this is a document request - if (EnsureDocumentRequest(httpContext, uri) == false) - { - reason = EnsureRoutableOutcome.NotDocumentRequest; - } - // ensure the runtime is in the proper state - // and deal with needed redirects, etc - else if (EnsureRuntime(httpContext, uri) == false) - { - reason = EnsureRoutableOutcome.NotReady; - } - // ensure Umbraco has documents to serve - else if (EnsureHasContent(context, httpContext) == false) - { - reason = EnsureRoutableOutcome.NoContent; - } - - return Attempt.If(reason == EnsureRoutableOutcome.IsRoutable, reason); - } - - /// - /// Ensures that the request is a document request (i.e. one that the module should handle) - /// - /// - /// - /// - private bool EnsureDocumentRequest(HttpContextBase httpContext, Uri uri) - { - var maybeDoc = true; - var lpath = uri.AbsolutePath.ToLowerInvariant(); - - // handle directory-urls used for asmx - // legacy - what's the point really? - if (/*maybeDoc &&*/ GlobalSettings.UseDirectoryUrls) - { - var asmxPos = lpath.IndexOf(".asmx/", StringComparison.OrdinalIgnoreCase); - if (asmxPos >= 0) - { - // use uri.AbsolutePath, not path, 'cos path has been lowercased - httpContext.RewritePath(uri.AbsolutePath.Substring(0, asmxPos + 5), // filePath - uri.AbsolutePath.Substring(asmxPos + 5), // pathInfo - uri.Query.TrimStart('?')); - maybeDoc = false; - } - } - - // a document request should be - // /foo/bar/nil - // /foo/bar/nil/ - // /foo/bar/nil.aspx - // where /foo is not a reserved path - - // if the path contains an extension that is not .aspx - // then it cannot be a document request - var extension = Path.GetExtension(lpath); - if (maybeDoc && extension.IsNullOrWhiteSpace() == false && extension != ".aspx") - maybeDoc = false; - - // at that point, either we have no extension, or it is .aspx - - // if the path is reserved then it cannot be a document request - if (maybeDoc && GlobalSettings.IsReservedPathOrUrl(lpath, httpContext, _combinedRouteCollection.Value)) - maybeDoc = false; - - //NOTE: No need to warn, plus if we do we should log the document, as this message doesn't really tell us anything :) - //if (!maybeDoc) - //{ - // Logger.Warn("Not a document"); - //} - - return maybeDoc; - } - - private bool EnsureRuntime(HttpContextBase httpContext, Uri uri) - { - var debug = Runtime.Debug; - var level = Runtime.Level; - switch (level) - { - case RuntimeLevel.Unknown: - case RuntimeLevel.Boot: - // not ready yet, but wait - ReportRuntime(level, "Umbraco is booting."); - - // let requests pile up and wait for 10s then show the splash anyway - if (UmbracoConfig.For.UmbracoSettings().Content.EnableSplashWhileLoading == false - && ((RuntimeState) Runtime).WaitForRunLevel(TimeSpan.FromSeconds(10))) return true; - - // redirect to booting page - httpContext.Response.StatusCode = 503; // temp not available - const string bootUrl = "~/config/splashes/booting.aspx"; - httpContext.Response.AddHeader("Retry-After", debug ? "1" : "30"); // seconds - httpContext.RewritePath(UriUtility.ToAbsolute(bootUrl) + "?url=" + HttpUtility.UrlEncode(uri.ToString())); - return false; // cannot serve content - - case RuntimeLevel.BootFailed: - // redirect to death page - ReportRuntime(level, "Umbraco has failed."); - - httpContext.Response.StatusCode = 503; // temp not available - const string deathUrl = "~/config/splashes/death.aspx"; - httpContext.Response.AddHeader("Retry-After", debug ? "1" : "300"); // seconds - httpContext.RewritePath(UriUtility.ToAbsolute(deathUrl) + "?url=" + HttpUtility.UrlEncode(uri.ToString())); - return false; // cannot serve content - - case RuntimeLevel.Run: - // ok - return true; - - case RuntimeLevel.Install: - case RuntimeLevel.Upgrade: - // redirect to install - ReportRuntime(level, "Umbraco must install or upgrade."); - var installPath = UriUtility.ToAbsolute(SystemDirectories.Install); - var installUrl = $"{installPath}/?redir=true&url={HttpUtility.UrlEncode(uri.ToString())}"; - httpContext.Response.Redirect(installUrl, true); - return false; // cannot serve content - - default: - throw new NotSupportedException($"Unexpected runtime level: {Current.RuntimeState.Level}."); - } - } - - private static bool _reported; - private static RuntimeLevel _reportedLevel; - - private void ReportRuntime(RuntimeLevel level, string message) - { - if (_reported && _reportedLevel == level) return; - _reported = true; - _reportedLevel = level; - Logger.Warn(message); - } - - // ensures Umbraco has at least one published node - // if not, rewrites to splash and return false - // if yes, return true - private bool EnsureHasContent(UmbracoContext context, HttpContextBase httpContext) - { - if (context.ContentCache.HasContent()) - return true; - - Logger.Warn("Umbraco has no content"); - - const string noContentUrl = "~/config/splashes/noNodes.aspx"; - httpContext.RewritePath(UriUtility.ToAbsolute(noContentUrl)); - - return false; + EndRequest?.Invoke(sender, args); } // returns a value indicating whether redirection took place and the request has @@ -482,262 +100,6 @@ namespace Umbraco.Web return end; } - /// - /// Rewrites to the default back office page. - /// - /// - private void RewriteToBackOfficeHandler(HttpContextBase context) - { - // GlobalSettings.Path has already been through IOHelper.ResolveUrl() so it begins with / and vdir (if any) - var rewritePath = GlobalSettings.Path.TrimEnd('/') + "/Default"; - // rewrite the path to the path of the handler (i.e. /umbraco/RenderMvc) - context.RewritePath(rewritePath, "", "", false); - - //if it is MVC we need to do something special, we are not using TransferRequest as this will - //require us to rewrite the path with query strings and then reparse the query strings, this would - //also mean that we need to handle IIS 7 vs pre-IIS 7 differently. Instead we are just going to create - //an instance of the UrlRoutingModule and call it's PostResolveRequestCache method. This does: - // * Looks up the route based on the new rewritten URL - // * Creates the RequestContext with all route parameters and then executes the correct handler that matches the route - //we also cannot re-create this functionality because the setter for the HttpContext.Request.RequestContext is internal - //so really, this is pretty much the only way without using Server.TransferRequest and if we did that, we'd have to rethink - //a bunch of things! - var urlRouting = new UrlRoutingModule(); - urlRouting.PostResolveRequestCache(context); - } - - /// - /// Rewrites to the Umbraco handler - we always send the request via our MVC rendering engine, this will deal with - /// requests destined for webforms. - /// - /// - /// - private void RewriteToUmbracoHandler(HttpContextBase context, PublishedRequest pcr) - { - // NOTE: we do not want to use TransferRequest even though many docs say it is better with IIS7, turns out this is - // not what we need. The purpose of TransferRequest is to ensure that .net processes all of the rules for the newly - // rewritten url, but this is not what we want! - // read: http://forums.iis.net/t/1146511.aspx - - var query = pcr.Uri.Query.TrimStart('?'); - - // GlobalSettings.Path has already been through IOHelper.ResolveUrl() so it begins with / and vdir (if any) - var rewritePath = GlobalSettings.Path.TrimEnd('/') + "/RenderMvc"; - // rewrite the path to the path of the handler (i.e. /umbraco/RenderMvc) - context.RewritePath(rewritePath, "", query, false); - - //if it is MVC we need to do something special, we are not using TransferRequest as this will - //require us to rewrite the path with query strings and then reparse the query strings, this would - //also mean that we need to handle IIS 7 vs pre-IIS 7 differently. Instead we are just going to create - //an instance of the UrlRoutingModule and call it's PostResolveRequestCache method. This does: - // * Looks up the route based on the new rewritten URL - // * Creates the RequestContext with all route parameters and then executes the correct handler that matches the route - //we also cannot re-create this functionality because the setter for the HttpContext.Request.RequestContext is internal - //so really, this is pretty much the only way without using Server.TransferRequest and if we did that, we'd have to rethink - //a bunch of things! - var urlRouting = new UrlRoutingModule(); - urlRouting.PostResolveRequestCache(context); - } - - - /// - /// Any object that is in the HttpContext.Items collection that is IDisposable will get disposed on the end of the request - /// - /// - private void DisposeHttpContextItems(HttpContext http) - { - // do not process if client-side request - if (http.Request.Url.IsClientSideRequest()) - return; - - //get a list of keys to dispose - var keys = new HashSet(); - foreach (DictionaryEntry i in http.Items) - { - if (i.Value is IDisposeOnRequestEnd || i.Key is IDisposeOnRequestEnd) - { - keys.Add(i.Key); - } - } - //dispose each item and key that was found as disposable. - foreach (var k in keys) - { - try - { - http.Items[k].DisposeIfDisposable(); - } - catch (Exception ex) - { - Logger.Error("Could not dispose item with key " + k, ex); - } - try - { - k.DisposeIfDisposable(); - } - catch (Exception ex) - { - Logger.Error("Could not dispose item key " + k, ex); - } - } - } - - #endregion - - #region IHttpModule - - /// - /// Initialize the module, this will trigger for each new application - /// and there may be more than 1 application per application domain - /// - /// - public void Init(HttpApplication app) - { - if (Core.Composing.Current.RuntimeState.Level == RuntimeLevel.BootFailed) // fixme inject the runtimeState! - { - // there's nothing we can do really - app.BeginRequest += (sender, args) => - { - // would love to avoid throwing, and instead display a customized Umbraco 500 - // page - however if we don't throw here, something else might go wrong, and - // it's this later exception that would be reported. could not figure out how - // to prevent it, either with httpContext.Response.End() or .ApplicationInstance - // .CompleteRequest() - - // also, if something goes wrong with our DI setup, the logging subsystem may - // not even kick in, so here we try to give as much detail as possible - - Exception e = Core.Composing.Current.RuntimeState.BootFailedException; - if (e == null) - throw new BootFailedException(BootFailedException.DefaultMessage); - var m = new StringBuilder(); - m.Append(BootFailedException.DefaultMessage); - while (e != null) - { - m.Append($"\n\n-> {e.GetType().FullName}: {e.Message}"); - if (string.IsNullOrWhiteSpace(e.StackTrace) == false) - m.Append($"\n{e.StackTrace}"); - e = e.InnerException; - } - throw new BootFailedException(m.ToString()); - }; - return; - } - - // fixme - // modules **are** instanciated by the container so we **don't** have to - // get our dependencies injected manually, through properties. - //Core.Composing.Current.Container.InjectProperties(this); - - app.BeginRequest += (sender, e) => - { - var httpContext = ((HttpApplication) sender).Context; - Logger.Debug(() => $"Begin request: {httpContext.Request.Url}."); - BeginRequest(new HttpContextWrapper(httpContext)); - }; - - //disable asp.net headers (security) - // This is the correct place to modify headers according to MS: - // https://our.umbraco.org/forum/umbraco-7/using-umbraco-7/65241-Heap-error-from-header-manipulation?p=0#comment220889 - app.PostReleaseRequestState += (sender, args) => - { - var httpContext = ((HttpApplication) sender).Context; - try - { - httpContext.Response.Headers.Remove("Server"); - //this doesn't normally work since IIS sets it but we'll keep it here anyways. - httpContext.Response.Headers.Remove("X-Powered-By"); - httpContext.Response.Headers.Remove("X-AspNet-Version"); - httpContext.Response.Headers.Remove("X-AspNetMvc-Version"); - } - catch (PlatformNotSupportedException) - { - // can't remove headers this way on IIS6 or cassini. - } - }; - - app.PostAuthenticateRequest += (sender, e) => - { - var httpContext = ((HttpApplication) sender).Context; - //ensure the thread culture is set - httpContext.User?.Identity?.EnsureCulture(); - }; - - app.PostResolveRequestCache += (sender, e) => - { - var httpContext = ((HttpApplication) sender).Context; - ProcessRequest(new HttpContextWrapper(httpContext)); - }; - - app.EndRequest += (sender, args) => - { - var httpContext = ((HttpApplication) sender).Context; - - if (UmbracoContext.Current != null && UmbracoContext.Current.IsFrontEndUmbracoRequest) - { - Logger.Debug(() => $"End Request. ({DateTime.Now.Subtract(UmbracoContext.Current.ObjectCreated).TotalMilliseconds}ms)"); - } - - OnEndRequest(new UmbracoRequestEventArgs(UmbracoContext.Current, new HttpContextWrapper(httpContext))); - - DisposeHttpContextItems(httpContext); - }; - } - - public void Dispose() - { } - - #endregion - - #region Events - - public static event EventHandler RouteAttempt; - - private void OnRouteAttempt(RoutableAttemptEventArgs args) - { - RouteAttempt?.Invoke(this, args); - } - - public static event EventHandler EndRequest; - - private void OnEndRequest(UmbracoRequestEventArgs args) - { - EndRequest?.Invoke(this, args); - } - - #endregion - - /// - /// This is used to be passed into the GlobalSettings.IsReservedPathOrUrl and will include some 'fake' routes - /// used to determine if a path is reserved. - /// - /// - /// This is basically used to reserve paths dynamically - /// - private readonly Lazy _combinedRouteCollection; - - private RouteCollection CreateRouteCollection() - { - var routes = new RouteCollection(); - - foreach (var route in RouteTable.Routes) - routes.Add(route); - - foreach (var reservedPath in ReservedPaths) - { - try - { - routes.Add("_umbreserved_" + reservedPath.ReplaceNonAlphanumericChars(""), - new Route(reservedPath.TrimStart('/'), new StopRoutingHandler())); - } - catch (Exception ex) - { - Logger.Error("Could not add reserved path route", ex); - } - } - - return routes; - } - /// /// This is used internally to track any registered callback paths for Identity providers. If the request path matches /// any of the registered paths, then the module will let the request keep executing From 60d73c55d0732bb8a29616e13d1ca26240e9444d Mon Sep 17 00:00:00 2001 From: Stephan Date: Fri, 6 Jul 2018 18:37:35 +0200 Subject: [PATCH 018/469] Cleanup IContainer --- src/Umbraco.Core/Composing/IContainer.cs | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/Umbraco.Core/Composing/IContainer.cs b/src/Umbraco.Core/Composing/IContainer.cs index d31b57f564..55d8ead361 100644 --- a/src/Umbraco.Core/Composing/IContainer.cs +++ b/src/Umbraco.Core/Composing/IContainer.cs @@ -1,8 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Umbraco.Core.Composing { @@ -13,6 +9,11 @@ namespace Umbraco.Core.Composing /// public interface IContainer { + /// + /// Gets the concrete container. + /// + object ConcreteContainer { get; } + /// /// Gets an instance. /// @@ -54,14 +55,11 @@ namespace Umbraco.Core.Composing /// The type of the collection builder. /// A collection builder of the specified type. T RegisterCollectionBuilder(); - - // fixme move away! - object ConcreteContainer { get; } } - // fixme would be nicer - //public interface IContainer : IContainer - //{ - // T ConcreteContainer { get; } - //} + public interface IRegistry + { + // everything register should be here + // should a registry also be a container? + } } From f678c72c4d4cbc37b5b92b950a38858a980409dc Mon Sep 17 00:00:00 2001 From: Stephan Date: Fri, 6 Jul 2018 18:52:23 +0200 Subject: [PATCH 019/469] DisabledCacheHelper, LightInjectContainer --- src/Umbraco.Core/Cache/CacheHelper.cs | 31 ++++--------------- src/Umbraco.Core/Cache/DisabledCacheHelper.cs | 15 +++++++++ .../RepositoryCompositionRoot.cs | 15 +++++---- ...inerAdapter.cs => LightInjectContainer.cs} | 10 +++--- .../Composing/LightInjectExtensions.cs | 2 +- .../Repositories/Implement/AuditRepository.cs | 2 +- .../Implement/RelationRepository.cs | 2 +- .../Repositories/Implement/TaskRepository.cs | 12 +++---- .../Implement/TaskTypeRepository.cs | 12 +++---- src/Umbraco.Core/Umbraco.Core.csproj | 3 +- src/Umbraco.Tests/CoreThings/UdiTests.cs | 2 +- src/Umbraco.Tests/Models/VariationTests.cs | 2 +- .../Scoping/ScopeEventDispatcherTests.cs | 2 +- .../Web/TemplateUtilitiesTests.cs | 2 +- 14 files changed, 54 insertions(+), 58 deletions(-) create mode 100644 src/Umbraco.Core/Cache/DisabledCacheHelper.cs rename src/Umbraco.Core/Composing/LightInject/{ContainerAdapter.cs => LightInjectContainer.cs} (81%) diff --git a/src/Umbraco.Core/Cache/CacheHelper.cs b/src/Umbraco.Core/Cache/CacheHelper.cs index a85285e427..5480e199f5 100644 --- a/src/Umbraco.Core/Cache/CacheHelper.cs +++ b/src/Umbraco.Core/Cache/CacheHelper.cs @@ -7,7 +7,7 @@ using System.Web.Caching; namespace Umbraco.Core.Cache { /// - /// Class that is exposed by the ApplicationContext for application wide caching purposes + /// Represents the application-wide caches. /// public class CacheHelper { @@ -25,7 +25,7 @@ namespace Umbraco.Core.Cache // do *not* return NoCache // NoCache is a special instance that is detected by RepositoryBase and disables all cache policies // CreateDisabledCacheHelper is used in tests to use no cache, *but* keep all cache policies - return new CacheHelper(NullCacheProvider.Instance, NullCacheProvider.Instance, NullCacheProvider.Instance, new IsolatedRuntimeCache(_ => NullCacheProvider.Instance)); + return new DisabledCacheHelper(); } /// @@ -43,7 +43,6 @@ namespace Umbraco.Core.Cache /// /// Initializes a new instance for use in the web /// - /// public CacheHelper(System.Web.Caching.Cache cache) : this( new HttpRuntimeCacheProvider(cache), @@ -53,37 +52,19 @@ namespace Umbraco.Core.Cache { } - [Obsolete("Use the constructor the specifies all dependencies")] - [EditorBrowsable(EditorBrowsableState.Never)] - public CacheHelper( - IRuntimeCacheProvider httpCacheProvider, - ICacheProvider staticCacheProvider, - ICacheProvider requestCacheProvider) - : this(httpCacheProvider, staticCacheProvider, requestCacheProvider, new IsolatedRuntimeCache(t => new ObjectCacheRuntimeCacheProvider())) - { - } - /// /// Initializes a new instance based on the provided providers /// - /// - /// - /// - /// public CacheHelper( IRuntimeCacheProvider httpCacheProvider, ICacheProvider staticCacheProvider, ICacheProvider requestCacheProvider, IsolatedRuntimeCache isolatedCacheManager) { - if (httpCacheProvider == null) throw new ArgumentNullException("httpCacheProvider"); - if (staticCacheProvider == null) throw new ArgumentNullException("staticCacheProvider"); - if (requestCacheProvider == null) throw new ArgumentNullException("requestCacheProvider"); - if (isolatedCacheManager == null) throw new ArgumentNullException("isolatedCacheManager"); - RuntimeCache = httpCacheProvider; - StaticCache = staticCacheProvider; - RequestCache = requestCacheProvider; - IsolatedRuntimeCache = isolatedCacheManager; + RuntimeCache = httpCacheProvider ?? throw new ArgumentNullException(nameof(httpCacheProvider)); + StaticCache = staticCacheProvider ?? throw new ArgumentNullException(nameof(staticCacheProvider)); + RequestCache = requestCacheProvider ?? throw new ArgumentNullException(nameof(requestCacheProvider)); + IsolatedRuntimeCache = isolatedCacheManager ?? throw new ArgumentNullException(nameof(isolatedCacheManager)); } /// diff --git a/src/Umbraco.Core/Cache/DisabledCacheHelper.cs b/src/Umbraco.Core/Cache/DisabledCacheHelper.cs new file mode 100644 index 0000000000..104c6b8bc0 --- /dev/null +++ b/src/Umbraco.Core/Cache/DisabledCacheHelper.cs @@ -0,0 +1,15 @@ +namespace Umbraco.Core.Cache +{ + /// + /// Represent disabled application-wide caches. + /// + public class DisabledCacheHelper : CacheHelper + { + /// + /// Initializes a new instance of the . + /// + public DisabledCacheHelper() + : base(NullCacheProvider.Instance, NullCacheProvider.Instance, NullCacheProvider.Instance, new IsolatedRuntimeCache(_ => NullCacheProvider.Instance)) + { } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Composing/CompositionRoots/RepositoryCompositionRoot.cs b/src/Umbraco.Core/Composing/CompositionRoots/RepositoryCompositionRoot.cs index 42693f119d..fb90707fee 100644 --- a/src/Umbraco.Core/Composing/CompositionRoots/RepositoryCompositionRoot.cs +++ b/src/Umbraco.Core/Composing/CompositionRoots/RepositoryCompositionRoot.cs @@ -21,9 +21,8 @@ namespace Umbraco.Core.Composing.CompositionRoots { // register cache helpers // the main cache helper is registered by CoreBootManager and is used by most repositories - // the disabled one is used by those repositories that have an annotated ctor parameter - // fixme refactor: use a DisabledCacheHelper class (or interface?) so that injection does not depend on name and we can have simple ctor injection - container.RegisterSingleton(factory => CacheHelper.CreateDisabledCacheHelper(), DisabledCache); + // the disabled one is used by those repositories that require it + container.RegisterSingleton(); // resolve ctor dependency from GetInstance() runtimeArguments, if possible - 'factory' is // the container, 'info' describes the ctor argument, and 'args' contains the args that @@ -41,7 +40,7 @@ namespace Umbraco.Core.Composing.CompositionRoots // some repositories have an annotated ctor parameter to pick the right cache helper // repositories - container.RegisterSingleton(f => new AuditRepository(f.GetInstance(), f.GetInstance(DisabledCache), f.GetInstance())); + container.RegisterSingleton(); container.RegisterSingleton(); container.RegisterSingleton(); container.RegisterSingleton(); @@ -64,13 +63,13 @@ namespace Umbraco.Core.Composing.CompositionRoots container.RegisterSingleton(); container.RegisterSingleton(); container.RegisterSingleton(); - container.RegisterSingleton(f => new RelationRepository(f.GetInstance(), f.GetInstance(DisabledCache), f.GetInstance(), f.GetInstance())); + container.RegisterSingleton(); container.RegisterSingleton(); container.RegisterSingleton(); container.RegisterSingleton(); - container.RegisterSingleton(f => new TaskRepository(f.GetInstance(), f.GetInstance(DisabledCache), f.GetInstance())); - container.RegisterSingleton(f => new TaskTypeRepository(f.GetInstance(), f.GetInstance(DisabledCache), f.GetInstance())); - container.RegisterSingleton(f => new TemplateRepository( + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(f => new TemplateRepository( // fixme type the FS too! or? f.GetInstance(), f.GetInstance(), f.GetInstance(), diff --git a/src/Umbraco.Core/Composing/LightInject/ContainerAdapter.cs b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs similarity index 81% rename from src/Umbraco.Core/Composing/LightInject/ContainerAdapter.cs rename to src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs index 99ffb11ace..8eff2be60b 100644 --- a/src/Umbraco.Core/Composing/LightInject/ContainerAdapter.cs +++ b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs @@ -4,21 +4,21 @@ using LightInject; namespace Umbraco.Core.Composing.LightInject { /// - /// Implements for LightInject. + /// Implements with LightInject. /// - public class ContainerAdapter : IContainer // fixme rename LightInjectContainer? + public class LightInjectContainer : IContainer { private readonly IServiceContainer _container; /// - /// Initializes a new instance of the with a LightInject container. + /// Initializes a new instance of the with a LightInject container. /// - public ContainerAdapter(IServiceContainer container) + public LightInjectContainer(IServiceContainer container) { _container = container; } - // fixme + /// public object ConcreteContainer => _container; /// diff --git a/src/Umbraco.Core/Composing/LightInjectExtensions.cs b/src/Umbraco.Core/Composing/LightInjectExtensions.cs index 914af001a8..a64d3aff30 100644 --- a/src/Umbraco.Core/Composing/LightInjectExtensions.cs +++ b/src/Umbraco.Core/Composing/LightInjectExtensions.cs @@ -48,7 +48,7 @@ namespace Umbraco.Core.Composing container.Register(_ => container); // configure the current container - Current.Container = new LightInject.ContainerAdapter(container); + Current.Container = new LightInject.LightInjectContainer(container); } private class AssemblyScanner : IAssemblyScanner diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/AuditRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/AuditRepository.cs index d643e1f5a5..fe2a915c9f 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/AuditRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/AuditRepository.cs @@ -14,7 +14,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { internal class AuditRepository : NPocoRepositoryBase, IAuditRepository { - public AuditRepository(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger) + public AuditRepository(IScopeAccessor scopeAccessor, DisabledCacheHelper cache, ILogger logger) : base(scopeAccessor, cache, logger) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/RelationRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/RelationRepository.cs index bb153beda9..732d01a868 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/RelationRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/RelationRepository.cs @@ -20,7 +20,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { private readonly IRelationTypeRepository _relationTypeRepository; - public RelationRepository(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger, IRelationTypeRepository relationTypeRepository) + public RelationRepository(IScopeAccessor scopeAccessor, DisabledCacheHelper cache, ILogger logger, IRelationTypeRepository relationTypeRepository) : base(scopeAccessor, cache, logger) { _relationTypeRepository = relationTypeRepository; diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/TaskRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/TaskRepository.cs index b70523d5e1..972b528d76 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/TaskRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/TaskRepository.cs @@ -15,7 +15,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { internal class TaskRepository : NPocoRepositoryBase, ITaskRepository { - public TaskRepository(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger) + public TaskRepository(IScopeAccessor scopeAccessor, DisabledCacheHelper cache, ILogger logger) : base(scopeAccessor, cache, logger) { } @@ -27,7 +27,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement var taskDto = Database.Fetch(SqlContext.SqlSyntax.SelectTop(sql, 1)).FirstOrDefault(); if (taskDto == null) return null; - + var entity = TaskFactory.BuildEntity(taskDto); return entity; } @@ -40,7 +40,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { sql.Where("cmsTask.id IN (@ids)", new { ids = ids }); } - + var dtos = Database.Fetch(sql); return dtos.Select(TaskFactory.BuildEntity); } @@ -102,7 +102,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { entity.TaskType.Id = taskType.Id; } - + var dto = TaskFactory.BuildDto(entity); var id = Convert.ToInt32(Database.Insert(dto)); @@ -114,7 +114,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement protected override void PersistUpdatedItem(Task entity) { entity.UpdatingEntity(); - + var dto = TaskFactory.BuildDto(entity); Database.Update(dto); @@ -131,7 +131,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement } var dtos = Database.Fetch(sql); - + return dtos.Select(TaskFactory.BuildEntity); } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/TaskTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/TaskTypeRepository.cs index 57ddc68568..55f6905dde 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/TaskTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/TaskTypeRepository.cs @@ -14,7 +14,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { internal class TaskTypeRepository : NPocoRepositoryBase, ITaskTypeRepository { - public TaskTypeRepository(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger) + public TaskTypeRepository(IScopeAccessor scopeAccessor, DisabledCacheHelper cache, ILogger logger) : base(scopeAccessor, cache, logger) { } @@ -26,7 +26,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement var taskDto = Database.Fetch(SqlContext.SqlSyntax.SelectTop(sql, 1)).FirstOrDefault(); if (taskDto == null) return null; - + var entity = TaskTypeFactory.BuildEntity(taskDto); return entity; } @@ -39,7 +39,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { sql.Where("cmsTaskType.id IN (@ids)", new { ids }); } - + var dtos = Database.Fetch(sql); return dtos.Select(TaskTypeFactory.BuildEntity); } @@ -49,7 +49,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement var sqlClause = GetBaseQuery(false); var translator = new SqlTranslator(sqlClause, query); var sql = translator.Translate(); - + var dtos = Database.Fetch(sql); return dtos.Select(TaskTypeFactory.BuildEntity); } @@ -88,7 +88,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { throw new InvalidOperationException("A task type already exists with the given alias " + entity.Alias); } - + var dto = TaskTypeFactory.BuildDto(entity); var id = Convert.ToInt32(Database.Insert(dto)); @@ -100,7 +100,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement protected override void PersistUpdatedItem(TaskType entity) { entity.UpdatingEntity(); - + var dto = TaskTypeFactory.BuildDto(entity); Database.Update(dto); diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 7a22e21205..264fcc9420 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -106,6 +106,7 @@ + @@ -170,7 +171,7 @@ - + diff --git a/src/Umbraco.Tests/CoreThings/UdiTests.cs b/src/Umbraco.Tests/CoreThings/UdiTests.cs index 4300401e18..49c02d5688 100644 --- a/src/Umbraco.Tests/CoreThings/UdiTests.cs +++ b/src/Umbraco.Tests/CoreThings/UdiTests.cs @@ -27,7 +27,7 @@ namespace Umbraco.Tests.CoreThings var globalSettings = SettingsForTests.GenerateMockGlobalSettings(); container.Setup(x => x.GetInstance(typeof (TypeLoader))).Returns( new TypeLoader(NullCacheProvider.Instance, globalSettings, new ProfilingLogger(Mock.Of(), Mock.Of()))); - Current.Container = new Core.Composing.LightInject.ContainerAdapter(container.Object); + Current.Container = new Core.Composing.LightInject.LightInjectContainer(container.Object); Udi.ResetUdiTypes(); } diff --git a/src/Umbraco.Tests/Models/VariationTests.cs b/src/Umbraco.Tests/Models/VariationTests.cs index 0b0ad8c7ec..be7135715b 100644 --- a/src/Umbraco.Tests/Models/VariationTests.cs +++ b/src/Umbraco.Tests/Models/VariationTests.cs @@ -30,7 +30,7 @@ namespace Umbraco.Tests.Models Current.Reset(); var container = Mock.Of(); - Current.Container = new ContainerAdapter(container); + Current.Container = new LightInjectContainer(container); var dataEditors = new DataEditorCollection(new IDataEditor[] { diff --git a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs index b295edfb8b..ecb8e42c90 100644 --- a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs @@ -33,7 +33,7 @@ namespace Umbraco.Tests.Scoping DoThing3 = null; var lightinjectContainer = new ServiceContainer(); - Current.Container = new ContainerAdapter(lightinjectContainer); + Current.Container = new LightInjectContainer(lightinjectContainer); _testObjects = new TestObjects(lightinjectContainer); diff --git a/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs b/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs index 867d4574f1..a7a8c35fd1 100644 --- a/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs +++ b/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs @@ -44,7 +44,7 @@ namespace Umbraco.Tests.Web container.Setup(x => x.GetInstance(typeof(TypeLoader))).Returns( new TypeLoader(NullCacheProvider.Instance, SettingsForTests.GenerateMockGlobalSettings(), new ProfilingLogger(Mock.Of(), Mock.Of()))); container.Setup(x => x.GetInstance(typeof (ServiceContext))).Returns(serviceContext); - Current.Container = new ContainerAdapter(container.Object); + Current.Container = new LightInjectContainer(container.Object); Umbraco.Web.Composing.Current.UmbracoContextAccessor = new TestUmbracoContextAccessor(); From 9341278492e4e2ab32dad46667baea225912c952 Mon Sep 17 00:00:00 2001 From: Stephan Date: Fri, 13 Jul 2018 12:11:00 +0200 Subject: [PATCH 020/469] Cleanup CacheHelper --- src/Umbraco.Core/Cache/CacheHelper.cs | 35 ++++++++-------- src/Umbraco.Core/Cache/DisabledCacheHelper.cs | 15 ------- .../RepositoryCompositionRoot.cs | 5 --- .../Repositories/Implement/AuditRepository.cs | 4 +- .../Implement/RelationRepository.cs | 4 +- .../Implement/ServerRegistrationRepository.cs | 3 +- .../Repositories/Implement/TaskRepository.cs | 4 +- .../Implement/TaskTypeRepository.cs | 4 +- src/Umbraco.Core/Umbraco.Core.csproj | 1 - .../FrontEnd/UmbracoHelperTests.cs | 3 +- .../Models/Mapping/AutoMapperTests.cs | 2 +- .../Repositories/AuditRepositoryTest.cs | 15 +++---- .../Repositories/ContentTypeRepositoryTest.cs | 12 +++--- .../DataTypeDefinitionRepositoryTest.cs | 2 +- .../Repositories/DomainRepositoryTest.cs | 12 +++--- .../Repositories/LanguageRepositoryTest.cs | 2 +- .../Repositories/MacroRepositoryTest.cs | 36 ++++++++-------- .../Repositories/MediaTypeRepositoryTest.cs | 5 ++- .../Repositories/MemberRepositoryTest.cs | 9 ++-- .../Repositories/MemberTypeRepositoryTest.cs | 2 +- .../Repositories/RelationRepositoryTest.cs | 11 +++-- .../RelationTypeRepositoryTest.cs | 4 +- .../Repositories/TagRepositoryTest.cs | 19 +++++---- .../Repositories/TaskRepositoryTest.cs | 19 +++++---- .../Repositories/TaskTypeRepositoryTest.cs | 5 ++- .../Repositories/TemplateRepositoryTest.cs | 11 ++--- .../Repositories/UserGroupRepositoryTest.cs | 4 +- .../Repositories/UserRepositoryTest.cs | 6 +-- .../Services/ContentServicePerformanceTest.cs | 41 ++++++++++--------- .../Services/ContentServiceTests.cs | 11 ++--- .../Services/MacroServiceTests.cs | 2 +- .../TestHelpers/TestWithDatabaseBase.cs | 4 -- .../Testing/TestingTests/MockTests.cs | 4 +- src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 2 +- .../Web/Mvc/SurfaceControllerTests.cs | 2 +- 35 files changed, 152 insertions(+), 168 deletions(-) delete mode 100644 src/Umbraco.Core/Cache/DisabledCacheHelper.cs diff --git a/src/Umbraco.Core/Cache/CacheHelper.cs b/src/Umbraco.Core/Cache/CacheHelper.cs index 2b43e857f0..cd2225ae9d 100644 --- a/src/Umbraco.Core/Cache/CacheHelper.cs +++ b/src/Umbraco.Core/Cache/CacheHelper.cs @@ -8,23 +8,6 @@ namespace Umbraco.Core.Cache /// public class CacheHelper { - public static CacheHelper NoCache { get; } = new CacheHelper(NullCacheProvider.Instance, NullCacheProvider.Instance, NullCacheProvider.Instance, new IsolatedRuntimeCache(_ => NullCacheProvider.Instance)); - - /// - /// Creates a cache helper with disabled caches - /// - /// - /// - /// Good for unit testing - /// - public static CacheHelper CreateDisabledCacheHelper() - { - // do *not* return NoCache - // NoCache is a special instance that is detected by RepositoryBase and disables all cache policies - // CreateDisabledCacheHelper is used in tests to use no cache, *but* keep all cache policies - return new DisabledCacheHelper(); - } - /// /// Initializes a new instance for use in the web /// @@ -64,6 +47,24 @@ namespace Umbraco.Core.Cache IsolatedRuntimeCache = isolatedCacheManager ?? throw new ArgumentNullException(nameof(isolatedCacheManager)); } + /// + /// Gets the special disabled instance. + /// + /// + /// When used by repositories, all cache policies apply, but the underlying caches do not cache anything. + /// Used by tests. + /// + public static CacheHelper Disabled { get; } = new CacheHelper(NullCacheProvider.Instance, NullCacheProvider.Instance, NullCacheProvider.Instance, new IsolatedRuntimeCache(_ => NullCacheProvider.Instance)); + + /// + /// Gets the special no-cache instance. + /// + /// + /// When used by repositories, all cache policies are bypassed. + /// Used by repositories that do no cache. + /// + public static CacheHelper NoCache { get; } = new CacheHelper(NullCacheProvider.Instance, NullCacheProvider.Instance, NullCacheProvider.Instance, new IsolatedRuntimeCache(_ => NullCacheProvider.Instance)); + /// /// Returns the current Request cache /// diff --git a/src/Umbraco.Core/Cache/DisabledCacheHelper.cs b/src/Umbraco.Core/Cache/DisabledCacheHelper.cs deleted file mode 100644 index 104c6b8bc0..0000000000 --- a/src/Umbraco.Core/Cache/DisabledCacheHelper.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace Umbraco.Core.Cache -{ - /// - /// Represent disabled application-wide caches. - /// - public class DisabledCacheHelper : CacheHelper - { - /// - /// Initializes a new instance of the . - /// - public DisabledCacheHelper() - : base(NullCacheProvider.Instance, NullCacheProvider.Instance, NullCacheProvider.Instance, new IsolatedRuntimeCache(_ => NullCacheProvider.Instance)) - { } - } -} \ No newline at end of file diff --git a/src/Umbraco.Core/Composing/CompositionRoots/RepositoryCompositionRoot.cs b/src/Umbraco.Core/Composing/CompositionRoots/RepositoryCompositionRoot.cs index fb90707fee..afea71a074 100644 --- a/src/Umbraco.Core/Composing/CompositionRoots/RepositoryCompositionRoot.cs +++ b/src/Umbraco.Core/Composing/CompositionRoots/RepositoryCompositionRoot.cs @@ -19,11 +19,6 @@ namespace Umbraco.Core.Composing.CompositionRoots public void Compose(IServiceRegistry container) { - // register cache helpers - // the main cache helper is registered by CoreBootManager and is used by most repositories - // the disabled one is used by those repositories that require it - container.RegisterSingleton(); - // resolve ctor dependency from GetInstance() runtimeArguments, if possible - 'factory' is // the container, 'info' describes the ctor argument, and 'args' contains the args that // were passed to GetInstance() - use first arg if it is the right type, diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/AuditRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/AuditRepository.cs index 403efd7e59..cd9d37aa0f 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/AuditRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/AuditRepository.cs @@ -14,8 +14,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { internal class AuditRepository : NPocoRepositoryBase, IAuditRepository { - public AuditRepository(IScopeAccessor scopeAccessor, DisabledCacheHelper cache, ILogger logger) - : base(scopeAccessor, cache, logger) + public AuditRepository(IScopeAccessor scopeAccessor, ILogger logger) + : base(scopeAccessor, CacheHelper.NoCache, logger) { } protected override void PersistNewItem(IAuditItem entity) diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/RelationRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/RelationRepository.cs index 732d01a868..fb5ba00ea0 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/RelationRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/RelationRepository.cs @@ -20,8 +20,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { private readonly IRelationTypeRepository _relationTypeRepository; - public RelationRepository(IScopeAccessor scopeAccessor, DisabledCacheHelper cache, ILogger logger, IRelationTypeRepository relationTypeRepository) - : base(scopeAccessor, cache, logger) + public RelationRepository(IScopeAccessor scopeAccessor, ILogger logger, IRelationTypeRepository relationTypeRepository) + : base(scopeAccessor, CacheHelper.NoCache, logger) { _relationTypeRepository = relationTypeRepository; } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/ServerRegistrationRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/ServerRegistrationRepository.cs index 531df1ba13..2679f8f92f 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/ServerRegistrationRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/ServerRegistrationRepository.cs @@ -14,9 +14,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { internal class ServerRegistrationRepository : NPocoRepositoryBase, IServerRegistrationRepository { - // fixme - should we use NoCache instead of CreateDisabledCacheHelper?! public ServerRegistrationRepository(IScopeAccessor scopeAccessor, ILogger logger) - : base(scopeAccessor, CacheHelper.CreateDisabledCacheHelper(), logger) + : base(scopeAccessor, CacheHelper.NoCache, logger) { } protected override IRepositoryCachePolicy CreateCachePolicy() diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/TaskRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/TaskRepository.cs index 972b528d76..1b44fd8cc8 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/TaskRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/TaskRepository.cs @@ -15,8 +15,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { internal class TaskRepository : NPocoRepositoryBase, ITaskRepository { - public TaskRepository(IScopeAccessor scopeAccessor, DisabledCacheHelper cache, ILogger logger) - : base(scopeAccessor, cache, logger) + public TaskRepository(IScopeAccessor scopeAccessor, ILogger logger) + : base(scopeAccessor, CacheHelper.NoCache, logger) { } protected override Task PerformGet(int id) diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/TaskTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/TaskTypeRepository.cs index 55f6905dde..ada49b4ec7 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/TaskTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/TaskTypeRepository.cs @@ -14,8 +14,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { internal class TaskTypeRepository : NPocoRepositoryBase, ITaskTypeRepository { - public TaskTypeRepository(IScopeAccessor scopeAccessor, DisabledCacheHelper cache, ILogger logger) - : base(scopeAccessor, cache, logger) + public TaskTypeRepository(IScopeAccessor scopeAccessor, ILogger logger) + : base(scopeAccessor, CacheHelper.NoCache, logger) { } protected override TaskType PerformGet(int id) diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 31d4548198..7c362eef2c 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -106,7 +106,6 @@ - diff --git a/src/Umbraco.Tests/FrontEnd/UmbracoHelperTests.cs b/src/Umbraco.Tests/FrontEnd/UmbracoHelperTests.cs index 3d6d380fe9..8487e24768 100644 --- a/src/Umbraco.Tests/FrontEnd/UmbracoHelperTests.cs +++ b/src/Umbraco.Tests/FrontEnd/UmbracoHelperTests.cs @@ -8,6 +8,7 @@ using Umbraco.Core; using Umbraco.Tests.TestHelpers; using Umbraco.Core.Cache; using Umbraco.Core.Composing; +using Umbraco.Core.Composing.LightInject; using Umbraco.Core.Logging; using Umbraco.Web; @@ -631,7 +632,7 @@ namespace Umbraco.Tests.FrontEnd private void SetUpDependencyContainer() { // fixme - bad in a unit test - but Udi has a static ctor that wants it?! - var container = new Mock(); + var container = new Mock(); var globalSettings = SettingsForTests.GenerateMockGlobalSettings(); container diff --git a/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs b/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs index 23a9eafe76..edb9f2b97f 100644 --- a/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs +++ b/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs @@ -22,7 +22,7 @@ namespace Umbraco.Tests.Models.Mapping base.Compose(); var manifestBuilder = new ManifestParser( - CacheHelper.CreateDisabledCacheHelper().RuntimeCache, + CacheHelper.Disabled.RuntimeCache, new ManifestValueValidatorCollection(Enumerable.Empty()), Logger) { diff --git a/src/Umbraco.Tests/Persistence/Repositories/AuditRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/AuditRepositoryTest.cs index 3bb4a42ba4..a8cdbfcdac 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/AuditRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/AuditRepositoryTest.cs @@ -1,5 +1,6 @@ using System.Linq; using NUnit.Framework; +using Umbraco.Core.Cache; using Umbraco.Core.Models; using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Persistence.Dtos; @@ -22,7 +23,7 @@ namespace Umbraco.Tests.Persistence.Repositories var sp = TestObjects.GetScopeProvider(Logger); using (var scope = sp.CreateScope()) { - var repo = new AuditRepository((IScopeAccessor) sp, CacheHelper, Logger); + var repo = new AuditRepository((IScopeAccessor) sp, Logger); repo.Save(new AuditItem(-1, "This is a System audit trail", AuditType.System, 0)); var dtos = scope.Database.Fetch("WHERE id > -1"); @@ -38,7 +39,7 @@ namespace Umbraco.Tests.Persistence.Repositories var sp = TestObjects.GetScopeProvider(Logger); using (var scope = sp.CreateScope()) { - var repo = new AuditRepository((IScopeAccessor) sp, CacheHelper, Logger); + var repo = new AuditRepository((IScopeAccessor) sp, Logger); for (var i = 0; i < 100; i++) { @@ -51,7 +52,7 @@ namespace Umbraco.Tests.Persistence.Repositories using (var scope = sp.CreateScope()) { - var repo = new AuditRepository((IScopeAccessor) sp, CacheHelper, Logger); + var repo = new AuditRepository((IScopeAccessor) sp, Logger); var page = repo.GetPagedResultsByQuery(sp.SqlContext.Query(), 0, 10, out var total, Direction.Descending, null, null); @@ -66,7 +67,7 @@ namespace Umbraco.Tests.Persistence.Repositories var sp = TestObjects.GetScopeProvider(Logger); using (var scope = sp.CreateScope()) { - var repo = new AuditRepository((IScopeAccessor) sp, CacheHelper, Logger); + var repo = new AuditRepository((IScopeAccessor) sp, Logger); for (var i = 0; i < 100; i++) { @@ -79,7 +80,7 @@ namespace Umbraco.Tests.Persistence.Repositories using (var scope = sp.CreateScope()) { - var repo = new AuditRepository((IScopeAccessor) sp, CacheHelper, Logger); + var repo = new AuditRepository((IScopeAccessor) sp, Logger); var page = repo.GetPagedResultsByQuery(sp.SqlContext.Query(), 0, 9, out var total, Direction.Descending, new[] {AuditType.Publish}, null) @@ -97,7 +98,7 @@ namespace Umbraco.Tests.Persistence.Repositories var sp = TestObjects.GetScopeProvider(Logger); using (var scope = sp.CreateScope()) { - var repo = new AuditRepository((IScopeAccessor) sp, CacheHelper, Logger); + var repo = new AuditRepository((IScopeAccessor) sp, Logger); for (var i = 0; i < 100; i++) { @@ -110,7 +111,7 @@ namespace Umbraco.Tests.Persistence.Repositories using (var scope = sp.CreateScope()) { - var repo = new AuditRepository((IScopeAccessor) sp, CacheHelper, Logger); + var repo = new AuditRepository((IScopeAccessor) sp, Logger); var page = repo.GetPagedResultsByQuery(sp.SqlContext.Query(), 0, 8, out var total, Direction.Descending, null, sp.SqlContext.Query().Where(item => item.Comment == "Content created")) diff --git a/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs index 31105aa28e..9be7fe434a 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs @@ -35,7 +35,7 @@ namespace Umbraco.Tests.Persistence.Repositories private DocumentRepository CreateRepository(IScopeAccessor scopeAccessor, out ContentTypeRepository contentTypeRepository) { - var cacheHelper = CacheHelper.CreateDisabledCacheHelper(); + var cacheHelper = CacheHelper.Disabled; var templateRepository = new TemplateRepository(scopeAccessor, cacheHelper, Logger, Mock.Of(), Mock.Of(), Mock.Of()); var tagRepository = new TagRepository(scopeAccessor, cacheHelper, Logger); contentTypeRepository = new ContentTypeRepository(scopeAccessor, cacheHelper, Logger, templateRepository); @@ -46,20 +46,20 @@ namespace Umbraco.Tests.Persistence.Repositories private ContentTypeRepository CreateRepository(IScopeAccessor scopeAccessor) { - var templateRepository = new TemplateRepository(scopeAccessor, CacheHelper.CreateDisabledCacheHelper(), Logger, Mock.Of(), Mock.Of(), Mock.Of()); - var contentTypeRepository = new ContentTypeRepository(scopeAccessor, CacheHelper.CreateDisabledCacheHelper(), Logger, templateRepository); + var templateRepository = new TemplateRepository(scopeAccessor, CacheHelper.Disabled, Logger, Mock.Of(), Mock.Of(), Mock.Of()); + var contentTypeRepository = new ContentTypeRepository(scopeAccessor, CacheHelper.Disabled, Logger, templateRepository); return contentTypeRepository; } private MediaTypeRepository CreateMediaTypeRepository(IScopeAccessor scopeAccessor) { - var contentTypeRepository = new MediaTypeRepository(scopeAccessor, CacheHelper.CreateDisabledCacheHelper(), Logger); + var contentTypeRepository = new MediaTypeRepository(scopeAccessor, CacheHelper.Disabled, Logger); return contentTypeRepository; } private EntityContainerRepository CreateContainerRepository(IScopeAccessor scopeAccessor, Guid containerEntityType) { - return new EntityContainerRepository(scopeAccessor, CacheHelper.CreateDisabledCacheHelper(), Logger, containerEntityType); + return new EntityContainerRepository(scopeAccessor, CacheHelper.Disabled, Logger, containerEntityType); } //TODO Add test to verify SetDefaultTemplates updates both AllowedTemplates and DefaultTemplate(id). @@ -72,7 +72,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var templateRepo = new TemplateRepository((IScopeAccessor) provider, CacheHelper.CreateDisabledCacheHelper(), Logger, Mock.Of(), Mock.Of(), Mock.Of()); + var templateRepo = new TemplateRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, Mock.Of(), Mock.Of(), Mock.Of()); var repository = CreateRepository((IScopeAccessor) provider); var templates = new[] { diff --git a/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs index 41daa05022..4a40bfacd0 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs @@ -25,7 +25,7 @@ namespace Umbraco.Tests.Persistence.Repositories private EntityContainerRepository CreateContainerRepository(IScopeAccessor scopeAccessor) { - return new EntityContainerRepository(scopeAccessor, CacheHelper.CreateDisabledCacheHelper(), Logger, Constants.ObjectTypes.DataTypeContainer); + return new EntityContainerRepository(scopeAccessor, CacheHelper.Disabled, Logger, Constants.ObjectTypes.DataTypeContainer); } [Test] diff --git a/src/Umbraco.Tests/Persistence/Repositories/DomainRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DomainRepositoryTest.cs index e88b6e3f44..070ef781cf 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DomainRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DomainRepositoryTest.cs @@ -22,12 +22,12 @@ namespace Umbraco.Tests.Persistence.Repositories private DomainRepository CreateRepository(IScopeProvider provider, out ContentTypeRepository contentTypeRepository, out DocumentRepository documentRepository, out LanguageRepository languageRepository) { var accessor = (IScopeAccessor) provider; - var templateRepository = new TemplateRepository(accessor, DisabledCache, Logger, Mock.Of(), Mock.Of(), Mock.Of()); - var tagRepository = new TagRepository(accessor, DisabledCache, Logger); - contentTypeRepository = new ContentTypeRepository(accessor, DisabledCache, Logger, templateRepository); - languageRepository = new LanguageRepository(accessor, DisabledCache, Logger); - documentRepository = new DocumentRepository(accessor, DisabledCache, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, Mock.Of()); - var domainRepository = new DomainRepository(accessor, DisabledCache, Logger); + var templateRepository = new TemplateRepository(accessor, Core.Cache.CacheHelper.Disabled, Logger, Mock.Of(), Mock.Of(), Mock.Of()); + var tagRepository = new TagRepository(accessor, Core.Cache.CacheHelper.Disabled, Logger); + contentTypeRepository = new ContentTypeRepository(accessor, Core.Cache.CacheHelper.Disabled, Logger, templateRepository); + languageRepository = new LanguageRepository(accessor, Core.Cache.CacheHelper.Disabled, Logger); + documentRepository = new DocumentRepository(accessor, Core.Cache.CacheHelper.Disabled, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, Mock.Of()); + var domainRepository = new DomainRepository(accessor, Core.Cache.CacheHelper.Disabled, Logger); return domainRepository; } diff --git a/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs index cd1fe47f39..6edf85718d 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs @@ -26,7 +26,7 @@ namespace Umbraco.Tests.Persistence.Repositories private LanguageRepository CreateRepository(IScopeProvider provider) { - return new LanguageRepository((IScopeAccessor) provider, CacheHelper.CreateDisabledCacheHelper(), Mock.Of()); + return new LanguageRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); } [Test] diff --git a/src/Umbraco.Tests/Persistence/Repositories/MacroRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MacroRepositoryTest.cs index a3b9035c8d..b089f5418c 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MacroRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MacroRepositoryTest.cs @@ -35,7 +35,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.CreateDisabledCacheHelper(), Mock.Of()); + var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); var macro = new Macro("test1", "Test", "~/views/macropartials/test.cshtml", MacroTypes.PartialView); ; @@ -52,7 +52,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.CreateDisabledCacheHelper(), Mock.Of()); + var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); var macro = repository.Get(1); macro.Alias = "test2"; @@ -69,7 +69,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.CreateDisabledCacheHelper(), Mock.Of()); + var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); // Assert Assert.That(repository, Is.Not.Null); @@ -83,7 +83,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.CreateDisabledCacheHelper(), Mock.Of()); + var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); // Act var macro = repository.Get(1); @@ -111,7 +111,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.CreateDisabledCacheHelper(), Mock.Of()); + var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); // Act var macros = repository.GetMany(); @@ -129,7 +129,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.CreateDisabledCacheHelper(), Mock.Of()); + var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); // Act var query = scope.SqlContext.Query().Where(x => x.Alias.ToUpper() == "TEST1"); @@ -147,7 +147,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.CreateDisabledCacheHelper(), Mock.Of()); + var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); // Act var query = scope.SqlContext.Query().Where(x => x.Name.StartsWith("Test")); @@ -165,7 +165,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.CreateDisabledCacheHelper(), Mock.Of()); + var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); // Act var macro = new Macro("test", "Test", "~/views/macropartials/test.cshtml", MacroTypes.PartialView); @@ -186,7 +186,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.CreateDisabledCacheHelper(), Mock.Of()); + var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); // Act var macro = repository.Get(2); @@ -221,7 +221,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.CreateDisabledCacheHelper(), Mock.Of()); + var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); // Act var macro = repository.Get(3); @@ -242,7 +242,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.CreateDisabledCacheHelper(), Mock.Of()); + var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); // Act var exists = repository.Exists(3); @@ -261,7 +261,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.CreateDisabledCacheHelper(), Mock.Of()); + var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); var macro = repository.Get(1); macro.Properties.Add(new MacroProperty("new1", "New1", 3, "test")); @@ -288,7 +288,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.CreateDisabledCacheHelper(), Mock.Of()); + var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); var macro = new Macro("newmacro", "A new macro", "~/views/macropartials/test1.cshtml", MacroTypes.PartialView); macro.Properties.Add(new MacroProperty("blah1", "New1", 4, "test.editor")); @@ -313,7 +313,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.CreateDisabledCacheHelper(), Mock.Of()); + var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); var macro = new Macro("newmacro", "A new macro", "~/views/macropartials/test1.cshtml", MacroTypes.PartialView); macro.Properties.Add(new MacroProperty("blah1", "New1", 4, "test.editor")); @@ -337,7 +337,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.CreateDisabledCacheHelper(), Mock.Of()); + var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); var macro = new Macro("newmacro", "A new macro", "~/views/macropartials/test1.cshtml", MacroTypes.PartialView); var prop1 = new MacroProperty("blah1", "New1", 4, "test.editor"); @@ -368,7 +368,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.CreateDisabledCacheHelper(), Mock.Of()); + var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); var macro = repository.Get(1); macro.Properties.Add(new MacroProperty("new1", "New1", 3, "test")); @@ -395,7 +395,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.CreateDisabledCacheHelper(), Mock.Of()); + var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); var macro = repository.Get(1); macro.Properties.Add(new MacroProperty("new1", "New1", 3, "test")); @@ -423,7 +423,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.CreateDisabledCacheHelper(), Mock.Of()); + var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); repository.Save(new Macro("test1", "Test1", "~/views/macropartials/test1.cshtml", MacroTypes.PartialView)); repository.Save(new Macro("test2", "Test2", "~/views/macropartials/test2.cshtml", MacroTypes.PartialView)); diff --git a/src/Umbraco.Tests/Persistence/Repositories/MediaTypeRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MediaTypeRepositoryTest.cs index 85f49306d2..ae4308db55 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MediaTypeRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MediaTypeRepositoryTest.cs @@ -2,6 +2,7 @@ using System.Linq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Models; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Dtos; @@ -20,12 +21,12 @@ namespace Umbraco.Tests.Persistence.Repositories { private MediaTypeRepository CreateRepository(IScopeProvider provider) { - return new MediaTypeRepository((IScopeAccessor) provider, DisabledCache, Logger); + return new MediaTypeRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger); } private EntityContainerRepository CreateContainerRepository(IScopeProvider provider) { - return new EntityContainerRepository((IScopeAccessor) provider, DisabledCache, Logger, Constants.ObjectTypes.MediaTypeContainer); + return new EntityContainerRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, Constants.ObjectTypes.MediaTypeContainer); } diff --git a/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs index 38ecc6c8ae..18bfc4fcea 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs @@ -6,6 +6,7 @@ using Moq; using NPoco; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Logging; using Umbraco.Core.Models; @@ -28,10 +29,10 @@ namespace Umbraco.Tests.Persistence.Repositories private MemberRepository CreateRepository(IScopeProvider provider, out MemberTypeRepository memberTypeRepository, out MemberGroupRepository memberGroupRepository) { var accessor = (IScopeAccessor) provider; - memberTypeRepository = new MemberTypeRepository(accessor, DisabledCache, Logger); - memberGroupRepository = new MemberGroupRepository(accessor, DisabledCache, Logger); - var tagRepo = new TagRepository(accessor, DisabledCache, Logger); - var repository = new MemberRepository(accessor, DisabledCache, Logger, memberTypeRepository, memberGroupRepository, tagRepo, Mock.Of()); + memberTypeRepository = new MemberTypeRepository(accessor, CacheHelper.Disabled, Logger); + memberGroupRepository = new MemberGroupRepository(accessor, CacheHelper.Disabled, Logger); + var tagRepo = new TagRepository(accessor, CacheHelper.Disabled, Logger); + var repository = new MemberRepository(accessor, CacheHelper.Disabled, Logger, memberTypeRepository, memberGroupRepository, tagRepo, Mock.Of()); return repository; } diff --git a/src/Umbraco.Tests/Persistence/Repositories/MemberTypeRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MemberTypeRepositoryTest.cs index e3d15613c2..87d146f9f4 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MemberTypeRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MemberTypeRepositoryTest.cs @@ -22,7 +22,7 @@ namespace Umbraco.Tests.Persistence.Repositories { private MemberTypeRepository CreateRepository(IScopeProvider provider) { - return new MemberTypeRepository((IScopeAccessor) provider, CacheHelper.CreateDisabledCacheHelper(), Mock.Of()); + return new MemberTypeRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); } [Test] diff --git a/src/Umbraco.Tests/Persistence/Repositories/RelationRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/RelationRepositoryTest.cs index 9ffcfa4442..697951d021 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/RelationRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/RelationRepositoryTest.cs @@ -30,8 +30,8 @@ namespace Umbraco.Tests.Persistence.Repositories private RelationRepository CreateRepository(IScopeProvider provider, out RelationTypeRepository relationTypeRepository) { var accessor = (IScopeAccessor) provider; - relationTypeRepository = new RelationTypeRepository(accessor, CacheHelper.CreateDisabledCacheHelper(), Mock.Of()); - var repository = new RelationRepository(accessor, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), relationTypeRepository); + relationTypeRepository = new RelationTypeRepository(accessor, CacheHelper.Disabled, Mock.Of()); + var repository = new RelationRepository(accessor, Mock.Of(), relationTypeRepository); return repository; } @@ -266,12 +266,11 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var relationTypeRepository = new RelationTypeRepository((IScopeAccessor) provider, CacheHelper.CreateDisabledCacheHelper(), Mock.Of()); - var relationRepository = new RelationRepository((IScopeAccessor) provider, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), relationTypeRepository); + var relationTypeRepository = new RelationTypeRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); + var relationRepository = new RelationRepository((IScopeAccessor) provider, Mock.Of(), relationTypeRepository); relationTypeRepository.Save(relateContent); - relationTypeRepository.Save(relateContentType); - + relationTypeRepository.Save(relateContentType); //Create and Save ContentType "umbTextpage" -> (NodeDto.NodeIdSeed) ContentType contentType = MockedContentTypes.CreateSimpleContentType("umbTextpage", "Textpage"); diff --git a/src/Umbraco.Tests/Persistence/Repositories/RelationTypeRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/RelationTypeRepositoryTest.cs index 1925f3cb03..76a5a3726e 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/RelationTypeRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/RelationTypeRepositoryTest.cs @@ -28,7 +28,7 @@ namespace Umbraco.Tests.Persistence.Repositories private RelationTypeRepository CreateRepository(IScopeProvider provider) { - return new RelationTypeRepository((IScopeAccessor) provider, CacheHelper.CreateDisabledCacheHelper(), Mock.Of()); + return new RelationTypeRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); } @@ -232,7 +232,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = ScopeProvider.CreateScope()) { - var repository = new RelationTypeRepository((IScopeAccessor) provider, CacheHelper.CreateDisabledCacheHelper(), Mock.Of()); + var repository = new RelationTypeRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); repository.Save(relateContent);//Id 2 repository.Save(relateContentType);//Id 3 diff --git a/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs index d53d680e94..65156df08d 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs @@ -1,6 +1,7 @@ using System.Linq; using Moq; using NUnit.Framework; +using Umbraco.Core.Cache; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; using Umbraco.Core.Models; @@ -946,26 +947,26 @@ namespace Umbraco.Tests.Persistence.Repositories private TagRepository CreateRepository(IScopeProvider provider) { - return new TagRepository((IScopeAccessor) provider, DisabledCache, Logger); + return new TagRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger); } private DocumentRepository CreateContentRepository(IScopeProvider provider, out ContentTypeRepository contentTypeRepository) { var accessor = (IScopeAccessor) provider; - var templateRepository = new TemplateRepository(accessor, DisabledCache, Logger, Mock.Of(), Mock.Of(), Mock.Of()); - var tagRepository = new TagRepository(accessor, DisabledCache, Logger); - contentTypeRepository = new ContentTypeRepository(accessor, DisabledCache, Logger, templateRepository); - var languageRepository = new LanguageRepository(accessor, DisabledCache, Logger); - var repository = new DocumentRepository(accessor, DisabledCache, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, Mock.Of()); + var templateRepository = new TemplateRepository(accessor, CacheHelper.Disabled, Logger, Mock.Of(), Mock.Of(), Mock.Of()); + var tagRepository = new TagRepository(accessor, CacheHelper.Disabled, Logger); + contentTypeRepository = new ContentTypeRepository(accessor, CacheHelper.Disabled, Logger, templateRepository); + var languageRepository = new LanguageRepository(accessor, CacheHelper.Disabled, Logger); + var repository = new DocumentRepository(accessor, CacheHelper.Disabled, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, Mock.Of()); return repository; } private MediaRepository CreateMediaRepository(IScopeProvider provider, out MediaTypeRepository mediaTypeRepository) { var accessor = (IScopeAccessor) provider; - var tagRepository = new TagRepository(accessor, DisabledCache, Logger); - mediaTypeRepository = new MediaTypeRepository(accessor, DisabledCache, Logger); - var repository = new MediaRepository(accessor, DisabledCache, Logger, mediaTypeRepository, tagRepository, Mock.Of(), Mock.Of()); + var tagRepository = new TagRepository(accessor, CacheHelper.Disabled, Logger); + mediaTypeRepository = new MediaTypeRepository(accessor, CacheHelper.Disabled, Logger); + var repository = new MediaRepository(accessor, CacheHelper.Disabled, Logger, mediaTypeRepository, tagRepository, Mock.Of(), Mock.Of()); return repository; } } diff --git a/src/Umbraco.Tests/Persistence/Repositories/TaskRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/TaskRepositoryTest.cs index 1434fa6cea..a4b01aef9e 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/TaskRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/TaskRepositoryTest.cs @@ -2,6 +2,7 @@ using System.Linq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Models; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; @@ -21,7 +22,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = ScopeProvider.CreateScope()) { - var repo = new TaskRepository((IScopeAccessor) provider, CacheHelper, Logger); + var repo = new TaskRepository((IScopeAccessor) provider, Logger); var created = DateTime.Now; var task = new Task(new TaskType("asdfasdf")) @@ -49,7 +50,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = ScopeProvider.CreateScope()) { - var repo = new TaskRepository((IScopeAccessor) provider, CacheHelper, Logger); + var repo = new TaskRepository((IScopeAccessor) provider, Logger); var created = DateTime.Now; repo.Save(new Task(new TaskType("asdfasdf")) @@ -82,7 +83,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = ScopeProvider.CreateScope()) { - var repo = new TaskRepository((IScopeAccessor) provider, CacheHelper, Logger); + var repo = new TaskRepository((IScopeAccessor) provider, Logger); var task = new Task(new TaskType("asdfasdf")) { @@ -119,7 +120,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = ScopeProvider.CreateScope()) { - var repo = new TaskRepository((IScopeAccessor) provider, CacheHelper, Logger); + var repo = new TaskRepository((IScopeAccessor) provider, Logger); var task = new Task(new TaskType("asdfasdf")) { @@ -148,7 +149,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = ScopeProvider.CreateScope()) { - var repo = new TaskRepository((IScopeAccessor) provider, CacheHelper, Logger); + var repo = new TaskRepository((IScopeAccessor) provider, Logger); var found = repo.GetMany().ToArray(); Assert.AreEqual(20, found.Count()); @@ -164,7 +165,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = ScopeProvider.CreateScope()) { - var repo = new TaskRepository((IScopeAccessor) provider, CacheHelper, Logger); + var repo = new TaskRepository((IScopeAccessor) provider, Logger); var found = repo.GetTasks(includeClosed: true).ToArray(); Assert.AreEqual(15, found.Count()); @@ -180,7 +181,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = ScopeProvider.CreateScope()) { - var repo = new TaskRepository((IScopeAccessor) provider, CacheHelper, Logger); + var repo = new TaskRepository((IScopeAccessor) provider, Logger); var found = repo.GetTasks(itemId:-20).ToArray(); Assert.AreEqual(10, found.Count()); @@ -196,7 +197,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = ScopeProvider.CreateScope()) { - var repo = new TaskRepository((IScopeAccessor) provider, CacheHelper, Logger); + var repo = new TaskRepository((IScopeAccessor) provider, Logger); var found = repo.GetTasks(includeClosed: false); Assert.AreEqual(10, found.Count()); @@ -208,7 +209,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = ScopeProvider.CreateScope()) { - var repo = new TaskRepository((IScopeAccessor) provider, CacheHelper, Logger); + var repo = new TaskRepository((IScopeAccessor) provider, Logger); for (int i = 0; i < count; i++) { diff --git a/src/Umbraco.Tests/Persistence/Repositories/TaskTypeRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/TaskTypeRepositoryTest.cs index f37fa37dca..7f159215b7 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/TaskTypeRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/TaskTypeRepositoryTest.cs @@ -2,6 +2,7 @@ using System.Linq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Models; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; @@ -22,8 +23,8 @@ namespace Umbraco.Tests.Persistence.Repositories using (var scope = ScopeProvider.CreateScope()) { var taskType = new TaskType("asdfasdf"); - var repo = new TaskRepository((IScopeAccessor) provider, CacheHelper, Logger); - var taskTypeRepo = new TaskTypeRepository((IScopeAccessor) provider, CacheHelper, Logger); + var repo = new TaskRepository((IScopeAccessor) provider, Logger); + var taskTypeRepo = new TaskTypeRepository((IScopeAccessor) provider, Logger); var created = DateTime.Now; var task = new Task(taskType) diff --git a/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs index 39128eb60a..69bbc46b57 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs @@ -6,6 +6,7 @@ using System.Text; using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; using Umbraco.Core.Models; @@ -27,7 +28,7 @@ namespace Umbraco.Tests.Persistence.Repositories private ITemplateRepository CreateRepository(IScopeProvider provider, ITemplatesSection templatesSection = null) { - return new TemplateRepository((IScopeAccessor) provider, DisabledCache, Logger, + return new TemplateRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, templatesSection ?? Mock.Of(t => t.DefaultRenderingEngine == RenderingEngine.Mvc), _masterPageFileSystem, _viewsFileSystem); } @@ -404,10 +405,10 @@ namespace Umbraco.Tests.Persistence.Repositories { var templateRepository = CreateRepository(provider); - var tagRepository = new TagRepository((IScopeAccessor) provider, DisabledCache, Logger); - var contentTypeRepository = new ContentTypeRepository((IScopeAccessor) provider, DisabledCache, Logger, templateRepository); - var languageRepository = new LanguageRepository((IScopeAccessor) provider, DisabledCache, Logger); - var contentRepo = new DocumentRepository((IScopeAccessor) provider, DisabledCache, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, Mock.Of()); + var tagRepository = new TagRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger); + var contentTypeRepository = new ContentTypeRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, templateRepository); + var languageRepository = new LanguageRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger); + var contentRepo = new DocumentRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, Mock.Of()); var contentType = MockedContentTypes.CreateSimpleContentType("umbTextpage2", "Textpage"); ServiceContext.FileService.SaveTemplate(contentType.DefaultTemplate); // else, FK violation on contentType! diff --git a/src/Umbraco.Tests/Persistence/Repositories/UserGroupRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/UserGroupRepositoryTest.cs index aeec6065df..f0fb8cff88 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/UserGroupRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/UserGroupRepositoryTest.cs @@ -19,7 +19,7 @@ namespace Umbraco.Tests.Persistence.Repositories { private UserGroupRepository CreateRepository(IScopeProvider provider) { - return new UserGroupRepository((IScopeAccessor) provider, Core.Cache.CacheHelper.CreateDisabledCacheHelper(), Mock.Of()); + return new UserGroupRepository((IScopeAccessor) provider, Core.Cache.CacheHelper.Disabled, Mock.Of()); } [Test] @@ -131,7 +131,7 @@ namespace Umbraco.Tests.Persistence.Repositories var id = userGroup.Id; - var repository2 = new UserGroupRepository((IScopeAccessor) provider, Core.Cache.CacheHelper.CreateDisabledCacheHelper(), Logger); + var repository2 = new UserGroupRepository((IScopeAccessor) provider, Core.Cache.CacheHelper.Disabled, Logger); repository2.Delete(userGroup); scope.Complete(); diff --git a/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs index 1ee8d8fe00..5a46bc805f 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs @@ -50,14 +50,14 @@ namespace Umbraco.Tests.Persistence.Repositories private UserRepository CreateRepository(IScopeProvider provider) { var accessor = (IScopeAccessor) provider; - var repository = new UserRepository(accessor, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), Mock.Of(), TestObjects.GetGlobalSettings()); + var repository = new UserRepository(accessor, CacheHelper.Disabled, Mock.Of(), Mock.Of(), TestObjects.GetGlobalSettings()); return repository; } private UserGroupRepository CreateUserGroupRepository(IScopeProvider provider) { var accessor = (IScopeAccessor) provider; - return new UserGroupRepository(accessor, CacheHelper.CreateDisabledCacheHelper(), Mock.Of()); + return new UserGroupRepository(accessor, CacheHelper.Disabled, Mock.Of()); } [Test] @@ -205,7 +205,7 @@ namespace Umbraco.Tests.Persistence.Repositories var id = user.Id; - var repository2 = new UserRepository((IScopeAccessor) provider, CacheHelper.CreateDisabledCacheHelper(), Logger, Mock.Of(),TestObjects.GetGlobalSettings()); + var repository2 = new UserRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, Mock.Of(),TestObjects.GetGlobalSettings()); repository2.Delete(user); diff --git a/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs b/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs index 28021f1e22..b1d6934043 100644 --- a/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs +++ b/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs @@ -5,6 +5,7 @@ using System.Linq; using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; using Umbraco.Core.Logging; @@ -161,11 +162,11 @@ namespace Umbraco.Tests.Services var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var tRepository = new TemplateRepository((IScopeAccessor) provider, DisabledCache, Logger, Mock.Of(), Mock.Of(), Mock.Of()); - var tagRepo = new TagRepository((IScopeAccessor) provider, DisabledCache, Logger); - var ctRepository = new ContentTypeRepository((IScopeAccessor) provider, DisabledCache, Logger, tRepository); - var languageRepository = new LanguageRepository((IScopeAccessor) provider, DisabledCache, Logger); - var repository = new DocumentRepository((IScopeAccessor) provider, DisabledCache, Logger, ctRepository, tRepository, tagRepo, languageRepository, Mock.Of()); + var tRepository = new TemplateRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, Mock.Of(), Mock.Of(), Mock.Of()); + var tagRepo = new TagRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger); + var ctRepository = new ContentTypeRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, tRepository); + var languageRepository = new LanguageRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger); + var repository = new DocumentRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, ctRepository, tRepository, tagRepo, languageRepository, Mock.Of()); // Act Stopwatch watch = Stopwatch.StartNew(); @@ -194,11 +195,11 @@ namespace Umbraco.Tests.Services var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var tRepository = new TemplateRepository((IScopeAccessor) provider, DisabledCache, Logger, Mock.Of(), Mock.Of(), Mock.Of()); - var tagRepo = new TagRepository((IScopeAccessor) provider, DisabledCache, Logger); - var ctRepository = new ContentTypeRepository((IScopeAccessor) provider, DisabledCache, Logger, tRepository); - var languageRepository = new LanguageRepository((IScopeAccessor) provider, DisabledCache, Logger); - var repository = new DocumentRepository((IScopeAccessor) provider, DisabledCache, Logger, ctRepository, tRepository, tagRepo, languageRepository, Mock.Of()); + var tRepository = new TemplateRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, Mock.Of(), Mock.Of(), Mock.Of()); + var tagRepo = new TagRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger); + var ctRepository = new ContentTypeRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, tRepository); + var languageRepository = new LanguageRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger); + var repository = new DocumentRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, ctRepository, tRepository, tagRepo, languageRepository, Mock.Of()); // Act Stopwatch watch = Stopwatch.StartNew(); @@ -225,11 +226,11 @@ namespace Umbraco.Tests.Services var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var tRepository = new TemplateRepository((IScopeAccessor) provider, DisabledCache, Logger, Mock.Of(), Mock.Of(), Mock.Of()); - var tagRepo = new TagRepository((IScopeAccessor) provider, DisabledCache, Logger); - var ctRepository = new ContentTypeRepository((IScopeAccessor) provider, DisabledCache, Logger, tRepository); - var languageRepository = new LanguageRepository((IScopeAccessor) provider, DisabledCache, Logger); - var repository = new DocumentRepository((IScopeAccessor) provider, DisabledCache, Logger, ctRepository, tRepository, tagRepo, languageRepository, Mock.Of()); + var tRepository = new TemplateRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, Mock.Of(), Mock.Of(), Mock.Of()); + var tagRepo = new TagRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger); + var ctRepository = new ContentTypeRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, tRepository); + var languageRepository = new LanguageRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger); + var repository = new DocumentRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, ctRepository, tRepository, tagRepo, languageRepository, Mock.Of()); // Act var contents = repository.GetMany(); @@ -259,11 +260,11 @@ namespace Umbraco.Tests.Services var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var tRepository = new TemplateRepository((IScopeAccessor) provider, DisabledCache, Logger, Mock.Of(), Mock.Of(), Mock.Of()); - var tagRepo = new TagRepository((IScopeAccessor) provider, DisabledCache, Logger); - var ctRepository = new ContentTypeRepository((IScopeAccessor) provider, DisabledCache, Logger, tRepository); - var languageRepository = new LanguageRepository((IScopeAccessor) provider, DisabledCache, Logger); - var repository = new DocumentRepository((IScopeAccessor) provider, DisabledCache, Logger, ctRepository, tRepository, tagRepo, languageRepository, Mock.Of()); + var tRepository = new TemplateRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, Mock.Of(), Mock.Of(), Mock.Of()); + var tagRepo = new TagRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger); + var ctRepository = new ContentTypeRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, tRepository); + var languageRepository = new LanguageRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger); + var repository = new DocumentRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, ctRepository, tRepository, tagRepo, languageRepository, Mock.Of()); // Act var contents = repository.GetMany(); diff --git a/src/Umbraco.Tests/Services/ContentServiceTests.cs b/src/Umbraco.Tests/Services/ContentServiceTests.cs index 7a68b36c21..c3661c1a18 100644 --- a/src/Umbraco.Tests/Services/ContentServiceTests.cs +++ b/src/Umbraco.Tests/Services/ContentServiceTests.cs @@ -25,6 +25,7 @@ using Umbraco.Core.Services.Implement; using Umbraco.Tests.Testing; using Umbraco.Web.PropertyEditors; using System.Reflection; +using Umbraco.Core.Cache; namespace Umbraco.Tests.Services { @@ -2951,11 +2952,11 @@ namespace Umbraco.Tests.Services private DocumentRepository CreateRepository(IScopeProvider provider, out ContentTypeRepository contentTypeRepository) { var accessor = (IScopeAccessor) provider; - var templateRepository = new TemplateRepository(accessor, DisabledCache, Logger, Mock.Of(), Mock.Of(), Mock.Of()); - var tagRepository = new TagRepository(accessor, DisabledCache, Logger); - contentTypeRepository = new ContentTypeRepository(accessor, DisabledCache, Logger, templateRepository); - var languageRepository = new LanguageRepository(accessor, DisabledCache, Logger); - var repository = new DocumentRepository(accessor, DisabledCache, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, Mock.Of()); + var templateRepository = new TemplateRepository(accessor, CacheHelper.Disabled, Logger, Mock.Of(), Mock.Of(), Mock.Of()); + var tagRepository = new TagRepository(accessor, CacheHelper.Disabled, Logger); + contentTypeRepository = new ContentTypeRepository(accessor, CacheHelper.Disabled, Logger, templateRepository); + var languageRepository = new LanguageRepository(accessor, CacheHelper.Disabled, Logger); + var repository = new DocumentRepository(accessor, CacheHelper.Disabled, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, Mock.Of()); return repository; } } diff --git a/src/Umbraco.Tests/Services/MacroServiceTests.cs b/src/Umbraco.Tests/Services/MacroServiceTests.cs index fa86f4baab..730b80a9df 100644 --- a/src/Umbraco.Tests/Services/MacroServiceTests.cs +++ b/src/Umbraco.Tests/Services/MacroServiceTests.cs @@ -26,7 +26,7 @@ namespace Umbraco.Tests.Services var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.CreateDisabledCacheHelper(), Mock.Of()); + var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); repository.Save(new Macro("test1", "Test1", "~/views/macropartials/test1.cshtml", MacroTypes.PartialView)); repository.Save(new Macro("test2", "Test2", "~/views/macropartials/test2.cshtml", MacroTypes.PartialView)); diff --git a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs index 25a0dc72fa..38cd8f727d 100644 --- a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs +++ b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs @@ -49,13 +49,9 @@ namespace Umbraco.Tests.TestHelpers [UmbracoTest(WithApplication = true)] public abstract class TestWithDatabaseBase : UmbracoTestBase { - private CacheHelper _disabledCacheHelper; - private string _databasePath; private static byte[] _databaseBytes; - protected CacheHelper DisabledCache => _disabledCacheHelper ?? (_disabledCacheHelper = CacheHelper.CreateDisabledCacheHelper()); - protected PublishedContentTypeCache ContentTypesCache { get; private set; } protected override ISqlSyntaxProvider SqlSyntax => GetSyntaxProvider(); diff --git a/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs b/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs index 7769a3318e..e64eda1ab4 100644 --- a/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs +++ b/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs @@ -55,7 +55,7 @@ namespace Umbraco.Tests.Testing.TestingTests Container.Register(_ => Mock.Of()); Container.Register(_ => Mock.Of()); Container.Register(_ => Mock.Of()); - Container.Register(_ => CacheHelper.CreateDisabledCacheHelper()); + Container.Register(_ => CacheHelper.Disabled); Container.Register(); // ReSharper disable once UnusedVariable @@ -68,7 +68,7 @@ namespace Umbraco.Tests.Testing.TestingTests Mock.Of(), new MembershipHelper(new TestUmbracoContextAccessor(umbracoContext), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), null), new ServiceContext(), - CacheHelper.CreateDisabledCacheHelper()); + CacheHelper.Disabled); Assert.Pass(); } diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index 9778542a01..4005ea0607 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -196,7 +196,7 @@ namespace Umbraco.Tests.Testing protected virtual void ComposeCacheHelper() { - Container.RegisterSingleton(f => CacheHelper.CreateDisabledCacheHelper()); + Container.RegisterSingleton(f => CacheHelper.Disabled); Container.RegisterSingleton(f => f.GetInstance().RuntimeCache); } diff --git a/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs b/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs index dfa917459f..22bf9ef602 100644 --- a/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs +++ b/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs @@ -132,7 +132,7 @@ namespace Umbraco.Tests.Web.Mvc Mock.Of(), new MembershipHelper(new TestUmbracoContextAccessor(umbracoContext), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), null), new ServiceContext(), - CacheHelper.CreateDisabledCacheHelper()); + CacheHelper.Disabled); var ctrl = new TestSurfaceController(umbracoContext, helper); var result = ctrl.GetContent(2) as PublishedContentResult; From 77083f259d0b9b767d1d675717e79f0ea3ddee4d Mon Sep 17 00:00:00 2001 From: Stephan Date: Mon, 16 Jul 2018 14:03:41 +0200 Subject: [PATCH 021/469] WIP --- src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs | 3 ++- src/Umbraco.Web/Editors/BackOfficeController.cs | 3 ++- src/Umbraco.Web/Mvc/RenderMvcController.cs | 3 ++- src/Umbraco.Web/Mvc/UmbracoAuthorizedController.cs | 9 ++++----- src/Umbraco.Web/Mvc/UmbracoController.cs | 10 ++-------- src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs | 1 + 6 files changed, 13 insertions(+), 16 deletions(-) diff --git a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs index 93d23f31d1..fa4bb9b538 100644 --- a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs +++ b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs @@ -186,7 +186,8 @@ namespace Umbraco.Tests.Routing /// public class CustomDocumentController : RenderMvcController { - public CustomDocumentController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger) : base(globalSettings, umbracoContext, databaseFactory, services, applicationCache, logger, profilingLogger) + public CustomDocumentController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger) + : base(globalSettings, umbracoContext, services, applicationCache, logger, profilingLogger) { } diff --git a/src/Umbraco.Web/Editors/BackOfficeController.cs b/src/Umbraco.Web/Editors/BackOfficeController.cs index 30ccb3dbb7..f727c9e2d6 100644 --- a/src/Umbraco.Web/Editors/BackOfficeController.cs +++ b/src/Umbraco.Web/Editors/BackOfficeController.cs @@ -62,7 +62,8 @@ namespace Umbraco.Web.Editors // _features = features; //} - public BackOfficeController(ManifestParser manifestParser, UmbracoFeatures features, IGlobalSettings globalSettings, UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger) : base(globalSettings, umbracoContext, databaseFactory, services, applicationCache, logger, profilingLogger) + public BackOfficeController(ManifestParser manifestParser, UmbracoFeatures features, IGlobalSettings globalSettings, UmbracoContext umbracoContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger) + : base(globalSettings, umbracoContext, services, applicationCache, logger, profilingLogger) { _manifestParser = manifestParser; _features = features; diff --git a/src/Umbraco.Web/Mvc/RenderMvcController.cs b/src/Umbraco.Web/Mvc/RenderMvcController.cs index 21a0d312b2..bf0ea197b6 100644 --- a/src/Umbraco.Web/Mvc/RenderMvcController.cs +++ b/src/Umbraco.Web/Mvc/RenderMvcController.cs @@ -26,7 +26,8 @@ namespace Umbraco.Web.Mvc ActionInvoker = new RenderActionInvoker(); } - public RenderMvcController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger) : base(globalSettings, umbracoContext, databaseFactory, services, applicationCache, logger, profilingLogger) + public RenderMvcController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger) + : base(globalSettings, umbracoContext, services, applicationCache, logger, profilingLogger) { ActionInvoker = new RenderActionInvoker(); } diff --git a/src/Umbraco.Web/Mvc/UmbracoAuthorizedController.cs b/src/Umbraco.Web/Mvc/UmbracoAuthorizedController.cs index 64d3207558..aba498530a 100644 --- a/src/Umbraco.Web/Mvc/UmbracoAuthorizedController.cs +++ b/src/Umbraco.Web/Mvc/UmbracoAuthorizedController.cs @@ -18,11 +18,10 @@ namespace Umbraco.Web.Mvc public abstract class UmbracoAuthorizedController : UmbracoController { protected UmbracoAuthorizedController() - { - } + { } - protected UmbracoAuthorizedController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger) : base(globalSettings, umbracoContext, databaseFactory, services, applicationCache, logger, profilingLogger) - { - } + protected UmbracoAuthorizedController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger) + : base(globalSettings, umbracoContext, services, applicationCache, logger, profilingLogger) + { } } } diff --git a/src/Umbraco.Web/Mvc/UmbracoController.cs b/src/Umbraco.Web/Mvc/UmbracoController.cs index 3a5d3e0d18..50bfe166de 100644 --- a/src/Umbraco.Web/Mvc/UmbracoController.cs +++ b/src/Umbraco.Web/Mvc/UmbracoController.cs @@ -28,6 +28,7 @@ namespace Umbraco.Web.Mvc // don't need to implement complex constructors + need to refactor them each time we change ours. // this means that these properties have a setter. // what can go wrong? + // fixme clear this comment /// /// Gets or sets the Umbraco context. @@ -39,11 +40,6 @@ namespace Umbraco.Web.Mvc /// public virtual UmbracoContext UmbracoContext { get; set; } - /// - /// Gets or sets the database context. - /// - public IUmbracoDatabaseFactory DatabaseFactory { get; set; } - /// /// Gets or sets the services context. /// @@ -86,7 +82,6 @@ namespace Umbraco.Web.Mvc : this( Current.Container.GetInstance(), Current.Container.GetInstance(), - Current.Container.GetInstance(), Current.Container.GetInstance(), Current.Container.GetInstance(), Current.Container.GetInstance(), @@ -95,11 +90,10 @@ namespace Umbraco.Web.Mvc { } - protected UmbracoController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger) + protected UmbracoController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger) { GlobalSettings = globalSettings; UmbracoContext = umbracoContext; - DatabaseFactory = databaseFactory; Services = services; ApplicationCache = applicationCache; Logger = logger; diff --git a/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs b/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs index 45dedea4ab..c1ec6332ee 100644 --- a/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs +++ b/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs @@ -32,6 +32,7 @@ namespace Umbraco.Web.WebApi // don't need to implement complex constructors + need to refactor them each time we change ours. // this means that these properties have a setter. // what can go wrong? + // fixme remove that comment?! /// /// Gets or sets the Umbraco context. From e5f09a1420d350530478fac447664f4b4e444a77 Mon Sep 17 00:00:00 2001 From: Stephan Date: Thu, 19 Jul 2018 15:05:55 +0200 Subject: [PATCH 022/469] Fix SqlTemplates concurrency --- src/Umbraco.Core/Persistence/SqlTemplates.cs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Core/Persistence/SqlTemplates.cs b/src/Umbraco.Core/Persistence/SqlTemplates.cs index 06c985232e..021f3a4670 100644 --- a/src/Umbraco.Core/Persistence/SqlTemplates.cs +++ b/src/Umbraco.Core/Persistence/SqlTemplates.cs @@ -1,12 +1,12 @@ using System; -using System.Collections.Generic; +using System.Collections.Concurrent; using NPoco; namespace Umbraco.Core.Persistence { public class SqlTemplates { - private readonly Dictionary _templates = new Dictionary(); + private readonly ConcurrentDictionary _templates = new ConcurrentDictionary(); private readonly ISqlContext _sqlContext; public SqlTemplates(ISqlContext sqlContext) @@ -22,9 +22,13 @@ namespace Umbraco.Core.Persistence public SqlTemplate Get(string key, Func, Sql> sqlBuilder) { - if (_templates.TryGetValue(key, out var template)) return template; - var sql = sqlBuilder(new Sql(_sqlContext)); - return _templates[key] = new SqlTemplate(_sqlContext, sql.SQL, sql.Arguments); + SqlTemplate CreateTemplate(string _) + { + var sql = sqlBuilder(new Sql(_sqlContext)); + return new SqlTemplate(_sqlContext, sql.SQL, sql.Arguments); + } + + return _templates.GetOrAdd(key, CreateTemplate); } } } From 9e9a0d301ff303f368bb0d4cccdb69645e84dafc Mon Sep 17 00:00:00 2001 From: Stephan Date: Fri, 20 Jul 2018 09:49:05 +0200 Subject: [PATCH 023/469] Cleanup and Refactor --- .../Composers/ConfigurationComposer.cs | 25 ++ .../Composers/CoreMappingProfilesComposer.cs | 15 ++ .../Composers/FileSystemsComposer.cs | 28 +++ .../Composers/RepositoriesComposer.cs | 56 +++++ .../Composing/Composers/ServicesComposer.cs | 95 ++++++++ .../ConfigurationCompositionRoot.cs | 23 -- .../CoreMappingProfilesCompositionRoot.cs | 13 - .../RepositoryCompositionRoot.cs | 87 ------- .../ServicesCompositionRoot.cs | 93 -------- src/Umbraco.Core/Composing/Current.cs | 4 +- src/Umbraco.Core/Composing/IContainer.cs | 37 +-- .../LightInject/LightInjectContainer.cs | 28 +-- src/Umbraco.Core/Constants-Composing.cs | 16 +- src/Umbraco.Core/ContainerExtensions.cs | 45 ++++ src/Umbraco.Core/IO/FileSystems.cs | 37 ++- src/Umbraco.Core/IO/MediaFileSystem.cs | 4 - .../Implement/PartialViewMacroRepository.cs | 5 +- .../Implement/PartialViewRepository.cs | 6 +- .../Implement/ScriptRepository.cs | 4 +- .../Implement/StylesheetRepository.cs | 4 +- .../Implement/TemplateRepository.cs | 10 +- .../Persistence/UmbracoDatabaseFactory.cs | 2 +- src/Umbraco.Core/Runtime/CoreRuntime.cs | 4 +- .../Runtime/CoreRuntimeComponent.cs | 25 +- src/Umbraco.Core/Services/ServiceContext.cs | 2 +- src/Umbraco.Core/Umbraco.Core.csproj | 10 +- .../FrontEnd/UmbracoHelperTests.cs | 2 - src/Umbraco.Tests/Models/ContentTests.cs | 1 + .../Repositories/ContentRepositoryTest.cs | 2 +- .../Repositories/ContentTypeRepositoryTest.cs | 6 +- .../Repositories/DomainRepositoryTest.cs | 2 +- .../PartialViewRepositoryTests.cs | 6 +- .../PublicAccessRepositoryTest.cs | 2 +- .../Repositories/ScriptRepositoryTest.cs | 32 +-- .../Repositories/StylesheetRepositoryTest.cs | 65 ++--- .../Repositories/TagRepositoryTest.cs | 2 +- .../Repositories/TemplateRepositoryTest.cs | 223 ++++++------------ .../Repositories/UserRepositoryTest.cs | 2 +- .../Scoping/ScopeEventDispatcherTests.cs | 3 +- src/Umbraco.Tests/Scoping/ScopedXmlTests.cs | 1 + .../Services/ContentServicePerformanceTest.cs | 8 +- .../Services/ContentServiceTests.cs | 2 +- .../Templates/TemplateRepositoryTests.cs | 34 +-- .../TestHelpers/TestObjects-Mocks.cs | 20 ++ src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 16 +- .../Cache/CacheRefresherComponent.cs | 1 - .../InstallerComposer.cs} | 20 +- .../Composers/WebMappingProfilesComposer.cs | 46 ++++ .../CompositionRoots/HelperCompositionRoot.cs | 17 -- .../WebMappingProfilesCompositionRoot.cs | 44 ---- src/Umbraco.Web/Composing/Current.cs | 2 +- src/Umbraco.Web/Composing/ModuleInjector.cs | 1 + .../Editors/BackOfficeAssetsController.cs | 9 +- .../Editors/BackOfficeController.cs | 4 - src/Umbraco.Web/Editors/TourController.cs | 2 +- src/Umbraco.Web/HtmlHelperRenderExtensions.cs | 6 +- src/Umbraco.Web/Install/InstallHelper.cs | 7 - src/Umbraco.Web/Models/LoginStatusModel.cs | 4 +- src/Umbraco.Web/Models/ProfileModel.cs | 2 +- .../EnsurePublishedContentRequestAttribute.cs | 1 - src/Umbraco.Web/Mvc/RenderRouteHandler.cs | 1 - src/Umbraco.Web/Mvc/UmbracoController.cs | 2 +- .../Mvc/UmbracoVirtualNodeRouteHandler.cs | 2 +- .../Routing/UrlProviderExtensions.cs | 1 - .../Runtime/WebRuntimeComponent.cs | 18 +- .../Scheduling/BackgroundTaskRunner.cs | 1 - src/Umbraco.Web/Templates/TemplateRenderer.cs | 1 - src/Umbraco.Web/Umbraco.Web.csproj | 5 +- .../Filters/FeatureAuthorizeAttribute.cs | 19 +- 69 files changed, 623 insertions(+), 700 deletions(-) create mode 100644 src/Umbraco.Core/Composing/Composers/ConfigurationComposer.cs create mode 100644 src/Umbraco.Core/Composing/Composers/CoreMappingProfilesComposer.cs create mode 100644 src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs create mode 100644 src/Umbraco.Core/Composing/Composers/RepositoriesComposer.cs create mode 100644 src/Umbraco.Core/Composing/Composers/ServicesComposer.cs delete mode 100644 src/Umbraco.Core/Composing/CompositionRoots/ConfigurationCompositionRoot.cs delete mode 100644 src/Umbraco.Core/Composing/CompositionRoots/CoreMappingProfilesCompositionRoot.cs delete mode 100644 src/Umbraco.Core/Composing/CompositionRoots/RepositoryCompositionRoot.cs delete mode 100644 src/Umbraco.Core/Composing/CompositionRoots/ServicesCompositionRoot.cs create mode 100644 src/Umbraco.Core/ContainerExtensions.cs rename src/Umbraco.Web/Composing/{CompositionRoots/InstallerCompositionRoot.cs => Composers/InstallerComposer.cs} (64%) create mode 100644 src/Umbraco.Web/Composing/Composers/WebMappingProfilesComposer.cs delete mode 100644 src/Umbraco.Web/Composing/CompositionRoots/HelperCompositionRoot.cs delete mode 100644 src/Umbraco.Web/Composing/CompositionRoots/WebMappingProfilesCompositionRoot.cs diff --git a/src/Umbraco.Core/Composing/Composers/ConfigurationComposer.cs b/src/Umbraco.Core/Composing/Composers/ConfigurationComposer.cs new file mode 100644 index 0000000000..e2ba477045 --- /dev/null +++ b/src/Umbraco.Core/Composing/Composers/ConfigurationComposer.cs @@ -0,0 +1,25 @@ +using LightInject; +using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.UmbracoSettings; + +namespace Umbraco.Core.Composing.Composers +{ + /// + /// Sets up IoC container for Umbraco configuration classes + /// + public static class ConfigurationComposer + { + public static IServiceRegistry ComposeConfiguration(this IServiceRegistry registry) + { + registry.Register(factory => UmbracoConfig.For.UmbracoSettings()); + registry.Register(factory => factory.GetInstance().Content); + registry.Register(factory => factory.GetInstance().Templates); + registry.Register(factory => factory.GetInstance().RequestHandler); + registry.Register(factory => UmbracoConfig.For.GlobalSettings()); + + // fixme - other sections we need to add? + + return registry; + } + } +} diff --git a/src/Umbraco.Core/Composing/Composers/CoreMappingProfilesComposer.cs b/src/Umbraco.Core/Composing/Composers/CoreMappingProfilesComposer.cs new file mode 100644 index 0000000000..ce9f507b9f --- /dev/null +++ b/src/Umbraco.Core/Composing/Composers/CoreMappingProfilesComposer.cs @@ -0,0 +1,15 @@ +using LightInject; +using Umbraco.Core.Models.Identity; + +namespace Umbraco.Core.Composing.Composers + +{ + public static class CoreMappingProfilesComposer + { + public static IServiceRegistry ComposeCoreMappingProfiles(this IServiceRegistry registry) + { + registry.Register(); + return registry; + } + } +} diff --git a/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs b/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs new file mode 100644 index 0000000000..c7ed93680b --- /dev/null +++ b/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs @@ -0,0 +1,28 @@ +using LightInject; +using Umbraco.Core.Configuration.UmbracoSettings; +using Umbraco.Core.IO; +using Umbraco.Core.Logging; + +namespace Umbraco.Core.Composing.Composers +{ + public static class FileSystemsComposer + { + public static IServiceRegistry ComposeFileSystems(this IServiceRegistry registry) + { + // register FileSystems, which manages all filesystems + registry.RegisterSingleton(); + + // register IFileSystems, which gives access too all filesystems + registry.RegisterSingleton(factory => factory.GetInstance()); + + // register MediaFileSystem, which can be injected directly + registry.RegisterSingleton(factory => factory.GetInstance().MediaFileSystem); + + // register MediaFileSystem, so that FileSystems can create it + registry.Register((f, wrappedFileSystem) + => new MediaFileSystem(wrappedFileSystem, f.GetInstance(), f.GetInstance(), f.GetInstance())); + + return registry; + } + } +} diff --git a/src/Umbraco.Core/Composing/Composers/RepositoriesComposer.cs b/src/Umbraco.Core/Composing/Composers/RepositoriesComposer.cs new file mode 100644 index 0000000000..79b2b9c223 --- /dev/null +++ b/src/Umbraco.Core/Composing/Composers/RepositoriesComposer.cs @@ -0,0 +1,56 @@ +using LightInject; +using Umbraco.Core.Persistence.Repositories; +using Umbraco.Core.Persistence.Repositories.Implement; + +namespace Umbraco.Core.Composing.Composers +{ + /// + /// Composes repositories. + /// + public static class RepositoriesComposer + { + public static IServiceRegistry ComposeRepositories(this IServiceRegistry registry) + { + // repositories + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + + return registry; + } + } +} diff --git a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs new file mode 100644 index 0000000000..c774912f2e --- /dev/null +++ b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs @@ -0,0 +1,95 @@ +using System; +using System.IO; +using System.Linq; +using LightInject; +using Umbraco.Core.Cache; +using Umbraco.Core.Events; +using Umbraco.Core.IO; +using Umbraco.Core.Logging; +using Umbraco.Core.Services; +using Umbraco.Core.Services.Implement; + +namespace Umbraco.Core.Composing.Composers +{ + public static class ServicesComposer + { + public static IServiceRegistry ComposeServices(this IServiceRegistry registry) + { + // register a transient messages factory, which will be replaced by the web + // boot manager when running in a web context + registry.RegisterSingleton(); + + // register the service context + registry.RegisterSingleton(); + + // register the special idk map + registry.RegisterSingleton(); + + // register the services + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.RegisterSingleton(); + registry.Register(factory => + { + var mainLangFolder = new DirectoryInfo(IOHelper.MapPath(SystemDirectories.Umbraco + "/config/lang/")); + var appPlugins = new DirectoryInfo(IOHelper.MapPath(SystemDirectories.AppPlugins)); + var configLangFolder = new DirectoryInfo(IOHelper.MapPath(SystemDirectories.Config + "/lang/")); + + var pluginLangFolders = appPlugins.Exists == false + ? Enumerable.Empty() + : appPlugins.GetDirectories() + .SelectMany(x => x.GetDirectories("Lang")) + .SelectMany(x => x.GetFiles("*.xml", SearchOption.TopDirectoryOnly)) + .Where(x => Path.GetFileNameWithoutExtension(x.FullName).Length == 5) + .Select(x => new LocalizedTextServiceSupplementaryFileSource(x, false)); + + //user defined langs that overwrite the default, these should not be used by plugin creators + var userLangFolders = configLangFolder.Exists == false + ? Enumerable.Empty() + : configLangFolder + .GetFiles("*.user.xml", SearchOption.TopDirectoryOnly) + .Where(x => Path.GetFileNameWithoutExtension(x.FullName).Length == 10) + .Select(x => new LocalizedTextServiceSupplementaryFileSource(x, true)); + + return new LocalizedTextServiceFileSources( + factory.GetInstance(), + factory.GetInstance().RuntimeCache, + mainLangFolder, + pluginLangFolders.Concat(userLangFolders)); + }); + registry.RegisterSingleton(factory => new LocalizedTextService( + factory.GetInstance>(), + factory.GetInstance())); + + //TODO: These are replaced in the web project - we need to declare them so that + // something is wired up, just not sure this is very nice but will work for now. + registry.RegisterSingleton(); + registry.RegisterSingleton(); + + return registry; + } + } +} diff --git a/src/Umbraco.Core/Composing/CompositionRoots/ConfigurationCompositionRoot.cs b/src/Umbraco.Core/Composing/CompositionRoots/ConfigurationCompositionRoot.cs deleted file mode 100644 index 82912163b6..0000000000 --- a/src/Umbraco.Core/Composing/CompositionRoots/ConfigurationCompositionRoot.cs +++ /dev/null @@ -1,23 +0,0 @@ -using LightInject; -using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.UmbracoSettings; - -namespace Umbraco.Core.Composing.CompositionRoots -{ - /// - /// Sets up IoC container for Umbraco configuration classes - /// - public sealed class ConfigurationCompositionRoot : ICompositionRoot - { - public void Compose(IServiceRegistry container) - { - container.Register(factory => UmbracoConfig.For.UmbracoSettings()); - container.Register(factory => factory.GetInstance().Content); - container.Register(factory => factory.GetInstance().Templates); - container.Register(factory => factory.GetInstance().RequestHandler); - container.Register(factory => UmbracoConfig.For.GlobalSettings()); - - // fixme - other sections we need to add? - } - } -} diff --git a/src/Umbraco.Core/Composing/CompositionRoots/CoreMappingProfilesCompositionRoot.cs b/src/Umbraco.Core/Composing/CompositionRoots/CoreMappingProfilesCompositionRoot.cs deleted file mode 100644 index 6b55a4af7e..0000000000 --- a/src/Umbraco.Core/Composing/CompositionRoots/CoreMappingProfilesCompositionRoot.cs +++ /dev/null @@ -1,13 +0,0 @@ -using LightInject; -using Umbraco.Core.Models.Identity; - -namespace Umbraco.Core.Composing.CompositionRoots -{ - public sealed class CoreMappingProfilesCompositionRoot : ICompositionRoot - { - public void Compose(IServiceRegistry container) - { - container.Register(); - } - } -} diff --git a/src/Umbraco.Core/Composing/CompositionRoots/RepositoryCompositionRoot.cs b/src/Umbraco.Core/Composing/CompositionRoots/RepositoryCompositionRoot.cs deleted file mode 100644 index afea71a074..0000000000 --- a/src/Umbraco.Core/Composing/CompositionRoots/RepositoryCompositionRoot.cs +++ /dev/null @@ -1,87 +0,0 @@ -using System; -using LightInject; -using Umbraco.Core.Cache; -using Umbraco.Core.Configuration.UmbracoSettings; -using Umbraco.Core.IO; -using Umbraco.Core.Logging; -using Umbraco.Core.Persistence.Repositories; -using Umbraco.Core.Persistence.Repositories.Implement; -using Umbraco.Core.Scoping; - -namespace Umbraco.Core.Composing.CompositionRoots -{ - /// - /// Sets the IoC container for the umbraco data layer/repositories/sql/database/etc... - /// - public sealed class RepositoryCompositionRoot : ICompositionRoot - { - public const string DisabledCache = "DisabledCache"; - - public void Compose(IServiceRegistry container) - { - // resolve ctor dependency from GetInstance() runtimeArguments, if possible - 'factory' is - // the container, 'info' describes the ctor argument, and 'args' contains the args that - // were passed to GetInstance() - use first arg if it is the right type, - // - // for ... - //container.RegisterConstructorDependency((factory, info, args) => - //{ - // if (info.Member.DeclaringType != typeof(EntityContainerRepository)) return default; - // return args.Length > 0 && args[0] is Guid guid ? guid : default; - //}); - - // register repositories - // repos depend on various things, - // some repositories have an annotated ctor parameter to pick the right cache helper - - // repositories - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(f => new TemplateRepository( // fixme type the FS too! or? - f.GetInstance(), - f.GetInstance(), - f.GetInstance(), - f.GetInstance(), - f.GetInstance(Constants.Composing.FileSystems.MasterpageFileSystem), - f.GetInstance(Constants.Composing.FileSystems.ViewFileSystem) - )); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - - // repositories that depend on a filesystem - // these have an annotated ctor parameter to pick the right file system - container.RegisterSingleton(f => new PartialViewMacroRepository(f.GetInstance("PartialViewMacroFileSystem"))); - container.RegisterSingleton(f => new PartialViewRepository(f.GetInstance("PartialViewFileSystem"))); - container.RegisterSingleton(f => new ScriptRepository(f.GetInstance("ScriptFileSystem"), f.GetInstance())); - container.RegisterSingleton(f => new StylesheetRepository(f.GetInstance("StylesheetFileSystem"))); - } - } -} diff --git a/src/Umbraco.Core/Composing/CompositionRoots/ServicesCompositionRoot.cs b/src/Umbraco.Core/Composing/CompositionRoots/ServicesCompositionRoot.cs deleted file mode 100644 index d126cd6aa3..0000000000 --- a/src/Umbraco.Core/Composing/CompositionRoots/ServicesCompositionRoot.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using LightInject; -using Umbraco.Core.Cache; -using Umbraco.Core.Events; -using Umbraco.Core.IO; -using Umbraco.Core.Logging; -using Umbraco.Core.Services; -using Umbraco.Core.Services.Implement; - -namespace Umbraco.Core.Composing.CompositionRoots -{ - public sealed class ServicesCompositionRoot : ICompositionRoot - { - public void Compose(IServiceRegistry container) - { - // register a transient messages factory, which will be replaced by the web - // boot manager when running in a web context - container.RegisterSingleton(); - - // register the service context - container.RegisterSingleton(); - - // register the special idk map - container.RegisterSingleton(); - - // register the services - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.Register(factory => - { - var mainLangFolder = new DirectoryInfo(IOHelper.MapPath(SystemDirectories.Umbraco + "/config/lang/")); - var appPlugins = new DirectoryInfo(IOHelper.MapPath(SystemDirectories.AppPlugins)); - var configLangFolder = new DirectoryInfo(IOHelper.MapPath(SystemDirectories.Config + "/lang/")); - - var pluginLangFolders = appPlugins.Exists == false - ? Enumerable.Empty() - : appPlugins.GetDirectories() - .SelectMany(x => x.GetDirectories("Lang")) - .SelectMany(x => x.GetFiles("*.xml", SearchOption.TopDirectoryOnly)) - .Where(x => Path.GetFileNameWithoutExtension(x.FullName).Length == 5) - .Select(x => new LocalizedTextServiceSupplementaryFileSource(x, false)); - - //user defined langs that overwrite the default, these should not be used by plugin creators - var userLangFolders = configLangFolder.Exists == false - ? Enumerable.Empty() - : configLangFolder - .GetFiles("*.user.xml", SearchOption.TopDirectoryOnly) - .Where(x => Path.GetFileNameWithoutExtension(x.FullName).Length == 10) - .Select(x => new LocalizedTextServiceSupplementaryFileSource(x, true)); - - return new LocalizedTextServiceFileSources( - factory.GetInstance(), - factory.GetInstance().RuntimeCache, - mainLangFolder, - pluginLangFolders.Concat(userLangFolders)); - }); - container.RegisterSingleton(factory => new LocalizedTextService( - factory.GetInstance>(), - factory.GetInstance())); - - //TODO: These are replaced in the web project - we need to declare them so that - // something is wired up, just not sure this is very nice but will work for now. - container.RegisterSingleton(); - container.RegisterSingleton(); - } - } -} diff --git a/src/Umbraco.Core/Composing/Current.cs b/src/Umbraco.Core/Composing/Current.cs index 9e07b42dfb..fcff2c4b9e 100644 --- a/src/Umbraco.Core/Composing/Current.cs +++ b/src/Umbraco.Core/Composing/Current.cs @@ -101,8 +101,8 @@ namespace Umbraco.Core.Composing public static TypeLoader TypeLoader => Container.GetInstance(); - public static FileSystems FileSystems - => Container.GetInstance(); + public static IFileSystems FileSystems + => Container.GetInstance(); public static UrlSegmentProviderCollection UrlSegmentProviders => Container.GetInstance(); diff --git a/src/Umbraco.Core/Composing/IContainer.cs b/src/Umbraco.Core/Composing/IContainer.cs index 55d8ead361..7183a76af2 100644 --- a/src/Umbraco.Core/Composing/IContainer.cs +++ b/src/Umbraco.Core/Composing/IContainer.cs @@ -2,8 +2,6 @@ namespace Umbraco.Core.Composing { - // fixme - must document! - /// /// Defines a container for Umbraco. /// @@ -14,13 +12,7 @@ namespace Umbraco.Core.Composing /// object ConcreteContainer { get; } - /// - /// Gets an instance. - /// - /// The type of the instance. - /// An instance of the specified type. - /// Throws an exception if the container failed to get an instance of the specified type. - T GetInstance(); + #region Factory /// /// Gets an instance. @@ -30,18 +22,31 @@ namespace Umbraco.Core.Composing /// Throws an exception if the container failed to get an instance of the specified type. object GetInstance(Type type); + /// + /// Gets an instance with arguments. + /// + /// The type of the instance. + /// Arguments. + /// An instance of the specified type. + /// + /// Throws an exception if the container failed to get an instance of the specified type. + /// The arguments are used as dependencies by the container. + /// + object GetInstance(Type type, object[] args); + /// /// Tries to get an instance. /// - /// The type of the instance. + /// The type of the instance. /// An instance of the specified type, or null. /// Returns null if the container does not know how to get an instance /// of the specified type. Throws an exception if the container does know how /// to get an instance of the specified type, but failed to do so. - T TryGetInstance(); + object TryGetInstance(Type type); - // fixme document - T GetInstance(object[] args); + #endregion + + #region Registry // fixme register direct type? // fixme register an instance? @@ -55,11 +60,7 @@ namespace Umbraco.Core.Composing /// The type of the collection builder. /// A collection builder of the specified type. T RegisterCollectionBuilder(); - } - public interface IRegistry - { - // everything register should be here - // should a registry also be a container? + #endregion } } diff --git a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs index 8eff2be60b..72ebda62ee 100644 --- a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs +++ b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs @@ -21,6 +21,18 @@ namespace Umbraco.Core.Composing.LightInject /// public object ConcreteContainer => _container; + /// + public object GetInstance(Type type) + => _container.GetInstance(type); + + /// + public object GetInstance(Type type, object[] args) + => _container.GetInstance(type, args); + + /// + public object TryGetInstance(Type type) + => _container.TryGetInstance(type); + /// public void RegisterSingleton(Func factory) => _container.RegisterSingleton(f => factory(this)); @@ -36,21 +48,5 @@ namespace Umbraco.Core.Composing.LightInject /// public T RegisterCollectionBuilder() => _container.RegisterCollectionBuilder(); - - /// - public T TryGetInstance() - => _container.TryGetInstance(); - - /// - public T GetInstance() - => _container.GetInstance(); - - /// - public T GetInstance(object[] args) - => (T) _container.GetInstance(typeof(T), args); - - /// - public object GetInstance(Type type) - => _container.GetInstance(type); } } diff --git a/src/Umbraco.Core/Constants-Composing.cs b/src/Umbraco.Core/Constants-Composing.cs index 1e8c9886d2..e65629a278 100644 --- a/src/Umbraco.Core/Constants-Composing.cs +++ b/src/Umbraco.Core/Constants-Composing.cs @@ -9,20 +9,6 @@ /// Defines constants for composition. /// public static class Composing - { - /// - /// Defines file system names. - /// - public static class FileSystems - { - public const string ScriptFileSystem = "ScriptFileSystem"; - public const string PartialViewFileSystem = "PartialViewFileSystem"; - public const string PartialViewMacroFileSystem = "PartialViewMacroFileSystem"; - public const string StylesheetFileSystem = "StylesheetFileSystem"; - public const string MasterpageFileSystem = "MasterpageFileSystem"; - public const string ViewFileSystem = "ViewFileSystem"; - public const string JavascriptLibraryFileSystem = "JavascriptLibraryFileSystem"; - } - } + { } } } diff --git a/src/Umbraco.Core/ContainerExtensions.cs b/src/Umbraco.Core/ContainerExtensions.cs new file mode 100644 index 0000000000..351a3c26f1 --- /dev/null +++ b/src/Umbraco.Core/ContainerExtensions.cs @@ -0,0 +1,45 @@ +using Umbraco.Core.Composing; + +namespace Umbraco.Core +{ + /// + /// Provides extension methods to the class. + /// + public static class ContainerExtensions + { + /// + /// Gets an instance. + /// + /// The type of the instance. + /// The container. + /// An instance of the specified type. + /// Throws an exception if the container failed to get an instance of the specified type. + public static T GetInstance(this IContainer container) + => (T) container.GetInstance(typeof(T)); + + /// + /// Gets an instance with arguments. + /// + /// The type of the instance. + /// The container. + /// Arguments. + /// An instance of the specified type. + /// + /// Throws an exception if the container failed to get an instance of the specified type. + /// The arguments are used as dependencies by the container. + /// + public static T GetInstance(this IContainer container, object[] args) + => (T) container.GetInstance(typeof(T), args); + + /// + /// Tries to get an instance. + /// + /// The type of the instance. + /// An instance of the specified type, or null. + /// Returns null if the container does not know how to get an instance + /// of the specified type. Throws an exception if the container does know how + /// to get an instance of the specified type, but failed to do so. + public static T TryGetInstance(this IContainer container) + => (T) container.TryGetInstance(typeof(T)); + } +} diff --git a/src/Umbraco.Core/IO/FileSystems.cs b/src/Umbraco.Core/IO/FileSystems.cs index af6d176794..ab7f75a521 100644 --- a/src/Umbraco.Core/IO/FileSystems.cs +++ b/src/Umbraco.Core/IO/FileSystems.cs @@ -12,7 +12,18 @@ using Umbraco.Core.Composing; namespace Umbraco.Core.IO { - public class FileSystems + public interface IFileSystems // fixme move! + { + IFileSystem MacroPartialsFileSystem { get; } + IFileSystem PartialViewsFileSystem { get; } + IFileSystem StylesheetsFileSystem { get; } + IFileSystem ScriptsFileSystem { get; } + IFileSystem MasterPagesFileSystem { get; } + IFileSystem MvcViewsFileSystem { get; } + MediaFileSystem MediaFileSystem { get; } + } + + public class FileSystems : IFileSystems { private readonly IFileSystemProvidersSection _config; private readonly ConcurrentSet _wrappers = new ConcurrentSet(); @@ -36,10 +47,6 @@ namespace Umbraco.Core.IO private MediaFileSystem _mediaFileSystem; - - //fixme - is this needed to be a managed file system? seems irrelevant since it won't ever be moved and is only used in one place in code - private IFileSystem _javascriptLibraryFileSystem; - #region Constructor // DI wants a public ctor @@ -129,16 +136,6 @@ namespace Umbraco.Core.IO } } - //fixme - is this needed to be a managed file system? seems irrelevant since it won't ever be moved and is only used in one place in code - internal IFileSystem JavaScriptLibraryFileSystem - { - get - { - if (Volatile.Read(ref _wkfsInitialized) == false) EnsureWellKnownFileSystems(); - return _javascriptLibraryFileSystem; - } - } - private void EnsureWellKnownFileSystems() { LazyInitializer.EnsureInitialized(ref _wkfsObject, ref _wkfsInitialized, ref _wkfsLock, CreateWellKnownFileSystems); @@ -154,7 +151,6 @@ namespace Umbraco.Core.IO var scriptsFileSystem = new PhysicalFileSystem(SystemDirectories.Scripts); var masterPagesFileSystem = new PhysicalFileSystem(SystemDirectories.Masterpages); var mvcViewsFileSystem = new PhysicalFileSystem(SystemDirectories.MvcViews); - var javaScriptLibraryFileSystem = new PhysicalFileSystem(SystemDirectories.JavaScriptLibrary); _macroPartialFileSystem = new ShadowWrapper(macroPartialFileSystem, "Views/MacroPartials", () => IsScoped()); _partialViewsFileSystem = new ShadowWrapper(partialViewsFileSystem, "Views/Partials", () => IsScoped()); @@ -162,7 +158,6 @@ namespace Umbraco.Core.IO _scriptsFileSystem = new ShadowWrapper(scriptsFileSystem, "scripts", () => IsScoped()); _masterPagesFileSystem = new ShadowWrapper(masterPagesFileSystem, "masterpages", () => IsScoped()); _mvcViewsFileSystem = new ShadowWrapper(mvcViewsFileSystem, "Views", () => IsScoped()); - _javascriptLibraryFileSystem = new ShadowWrapper(javaScriptLibraryFileSystem, "Lib", () => IsScoped()); // filesystems obtained from GetFileSystemProvider are already wrapped and do not need to be wrapped again _mediaFileSystem = GetFileSystemProvider(); @@ -190,7 +185,7 @@ namespace Umbraco.Core.IO /// The alias of the strongly-typed filesystem. /// The non-typed filesystem supporting the strongly-typed filesystem with the specified alias. /// This method should not be used directly, used instead. - public IFileSystem GetUnderlyingFileSystemProvider(string alias) + internal IFileSystem GetUnderlyingFileSystemProvider(string alias) { return GetUnderlyingFileSystemProvider(alias, null); } @@ -303,10 +298,8 @@ namespace Umbraco.Core.IO var innerFs = GetUnderlyingFileSystemNoCache(alias, fallback); var shadowWrapper = new ShadowWrapper(innerFs, "typed/" + alias, () => IsScoped()); - // fixme - switch to using container. where are these registered? - - //var fs = (IFileSystem) Activator.CreateInstance(typeof(TFileSystem), shadowWrapper); - var fs = Current.Container.GetInstance(new object[] { (IFileSystem)shadowWrapper }); + // getting the fs from the container - see FileSystemsComposer + var fs = Current.Container.GetInstance(new object[] { (IFileSystem) shadowWrapper }); _wrappers.Add(shadowWrapper); // keeping a reference to the wrapper return fs; }); diff --git a/src/Umbraco.Core/IO/MediaFileSystem.cs b/src/Umbraco.Core/IO/MediaFileSystem.cs index 77638d171a..47f9f14423 100644 --- a/src/Umbraco.Core/IO/MediaFileSystem.cs +++ b/src/Umbraco.Core/IO/MediaFileSystem.cs @@ -1,15 +1,11 @@ using System; using System.Collections.Generic; using System.Drawing; -using System.Globalization; using System.IO; using System.Linq; -using System.Threading; using System.Threading.Tasks; -using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Exceptions; -using Umbraco.Core.IO.MediaPathSchemes; using Umbraco.Core.Logging; using Umbraco.Core.Media; using Umbraco.Core.Media.Exif; diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/PartialViewMacroRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/PartialViewMacroRepository.cs index 879766fc81..d707bcee10 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/PartialViewMacroRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/PartialViewMacroRepository.cs @@ -5,9 +5,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { internal class PartialViewMacroRepository : PartialViewRepository, IPartialViewMacroRepository { - - public PartialViewMacroRepository(IFileSystem fileSystem) - : base(fileSystem) + public PartialViewMacroRepository(IFileSystems fileSystems) + : base(fileSystems.MacroPartialsFileSystem) { } protected override PartialViewType ViewType => PartialViewType.PartialViewMacro; diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/PartialViewRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/PartialViewRepository.cs index a996251927..d04bc47cd8 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/PartialViewRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/PartialViewRepository.cs @@ -9,7 +9,11 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { internal class PartialViewRepository : FileRepository, IPartialViewRepository { - public PartialViewRepository(IFileSystem fileSystem) + public PartialViewRepository(IFileSystems fileSystems) + : base(fileSystems.PartialViewsFileSystem) + { } + + protected PartialViewRepository(IFileSystem fileSystem) : base(fileSystem) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/ScriptRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/ScriptRepository.cs index 735a1aa74f..85b41a2a1c 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/ScriptRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/ScriptRepository.cs @@ -15,8 +15,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { private readonly IContentSection _contentConfig; - public ScriptRepository(IFileSystem fileSystem, IContentSection contentConfig) - : base(fileSystem) + public ScriptRepository(IFileSystems fileSystems, IContentSection contentConfig) + : base(fileSystems.ScriptsFileSystem) { _contentConfig = contentConfig ?? throw new ArgumentNullException(nameof(contentConfig)); } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/StylesheetRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/StylesheetRepository.cs index 8139f4948e..4c02a8f4b5 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/StylesheetRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/StylesheetRepository.cs @@ -11,8 +11,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement /// internal class StylesheetRepository : FileRepository, IStylesheetRepository { - public StylesheetRepository(IFileSystem fileSystem) - : base(fileSystem) + public StylesheetRepository(IFileSystems fileSystems) + : base(fileSystems.StylesheetsFileSystem) { } #region Overrides of FileRepository diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/TemplateRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/TemplateRepository.cs index 6541876b67..ba4e22de41 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/TemplateRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/TemplateRepository.cs @@ -29,13 +29,11 @@ namespace Umbraco.Core.Persistence.Repositories.Implement private readonly ViewHelper _viewHelper; private readonly MasterPageHelper _masterPageHelper; - public TemplateRepository(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger, ITemplatesSection templateConfig, - IFileSystem masterpageFileSystem, - IFileSystem viewFileSystem) + public TemplateRepository(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger, ITemplatesSection templateConfig, IFileSystems fileSystems) : base(scopeAccessor, cache, logger) { - _masterpagesFileSystem = masterpageFileSystem; - _viewsFileSystem = viewFileSystem; + _masterpagesFileSystem = fileSystems.MasterPagesFileSystem; + _viewsFileSystem = fileSystems.MvcViewsFileSystem; _templateConfig = templateConfig; _viewHelper = new ViewHelper(_viewsFileSystem); _masterPageHelper = new MasterPageHelper(_masterpagesFileSystem); @@ -151,7 +149,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement //Save to db var template = (Template)entity; template.AddingEntity(); - + var dto = TemplateFactory.BuildDto(template, NodeObjectTypeId, template.Id); //Create the (base) node data - umbracoNode diff --git a/src/Umbraco.Core/Persistence/UmbracoDatabaseFactory.cs b/src/Umbraco.Core/Persistence/UmbracoDatabaseFactory.cs index 2b82ec7fac..8d2a230fec 100644 --- a/src/Umbraco.Core/Persistence/UmbracoDatabaseFactory.cs +++ b/src/Umbraco.Core/Persistence/UmbracoDatabaseFactory.cs @@ -50,7 +50,7 @@ namespace Umbraco.Core.Persistence /// /// Initializes a new instance of the . /// - /// Used by LightInject. + /// Used by injection. public UmbracoDatabaseFactory(IEnumerable sqlSyntaxProviders, ILogger logger, IMapperCollection mappers) : this(Constants.System.UmbracoConnectionName, sqlSyntaxProviders, logger, mappers) { diff --git a/src/Umbraco.Core/Runtime/CoreRuntime.cs b/src/Umbraco.Core/Runtime/CoreRuntime.cs index 93f475f7a6..94004c6ae3 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntime.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntime.cs @@ -7,7 +7,7 @@ using LightInject; using Umbraco.Core.Cache; using Umbraco.Core.Components; using Umbraco.Core.Composing; -using Umbraco.Core.Composing.CompositionRoots; +using Umbraco.Core.Composing.Composers; using Umbraco.Core.Configuration; using Umbraco.Core.Exceptions; using Umbraco.Core.IO; @@ -195,7 +195,7 @@ namespace Umbraco.Core.Runtime container.RegisterSingleton(); container.RegisterSingleton(); - container.RegisterFrom(); + container.ComposeConfiguration(); // register caches // need the deep clone runtime cache profiver to ensure entities are cached properly, ie diff --git a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs index ce249d6b4a..4d1fd28462 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs @@ -7,7 +7,7 @@ using LightInject; using Umbraco.Core.Cache; using Umbraco.Core.Components; using Umbraco.Core.Composing; -using Umbraco.Core.Composing.CompositionRoots; +using Umbraco.Core.Composing.Composers; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; @@ -35,29 +35,16 @@ namespace Umbraco.Core.Runtime { base.Compose(composition); - // register from roots - composition.Container.RegisterFrom(); - composition.Container.RegisterFrom(); - composition.Container.RegisterFrom(); + // composers + composition.Container.ComposeRepositories(); + composition.Container.ComposeServices(); + composition.Container.ComposeCoreMappingProfiles(); + composition.Container.ComposeFileSystems(); // register database builder // *not* a singleton, don't want to keep it around composition.Container.Register(); - // register filesystems - - composition.Container.Register((f, wrappedFileSystem) => new MediaFileSystem(wrappedFileSystem, f.GetInstance(), f.GetInstance(), f.GetInstance())); - composition.Container.RegisterConstructorDependency((factory, parameterInfo) => factory.GetInstance().MediaFileSystem); - - composition.Container.RegisterSingleton(); - composition.Container.RegisterSingleton(factory => factory.GetInstance().MediaFileSystem); - composition.Container.RegisterSingleton(factory => factory.GetInstance().ScriptsFileSystem, Constants.Composing.FileSystems.ScriptFileSystem); - composition.Container.RegisterSingleton(factory => factory.GetInstance().PartialViewsFileSystem, Constants.Composing.FileSystems.PartialViewFileSystem); - composition.Container.RegisterSingleton(factory => factory.GetInstance().MacroPartialsFileSystem, Constants.Composing.FileSystems.PartialViewMacroFileSystem); - composition.Container.RegisterSingleton(factory => factory.GetInstance().StylesheetsFileSystem, Constants.Composing.FileSystems.StylesheetFileSystem); - composition.Container.RegisterSingleton(factory => factory.GetInstance().MasterPagesFileSystem, Constants.Composing.FileSystems.MasterpageFileSystem); - composition.Container.RegisterSingleton(factory => factory.GetInstance().MvcViewsFileSystem, Constants.Composing.FileSystems.ViewFileSystem); - // register manifest parser, will be injected in collection builders where needed composition.Container.RegisterSingleton(); diff --git a/src/Umbraco.Core/Services/ServiceContext.cs b/src/Umbraco.Core/Services/ServiceContext.cs index aa618e7927..b14158efd5 100644 --- a/src/Umbraco.Core/Services/ServiceContext.cs +++ b/src/Umbraco.Core/Services/ServiceContext.cs @@ -134,7 +134,7 @@ namespace Umbraco.Core.Services if (redirectUrlService != null) _redirectUrlService = new Lazy(() => redirectUrlService); if (consentService != null) _consentService = new Lazy(() => consentService); } - + /// /// Gets the /// diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 7bcd3dccae..49990db5de 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -158,10 +158,11 @@ - - - - + + + + + @@ -305,6 +306,7 @@ + diff --git a/src/Umbraco.Tests/FrontEnd/UmbracoHelperTests.cs b/src/Umbraco.Tests/FrontEnd/UmbracoHelperTests.cs index 74a47300ff..3d33604870 100644 --- a/src/Umbraco.Tests/FrontEnd/UmbracoHelperTests.cs +++ b/src/Umbraco.Tests/FrontEnd/UmbracoHelperTests.cs @@ -1,14 +1,12 @@ using System; using System.Collections.Generic; using System.Text; -using LightInject; using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Tests.TestHelpers; using Umbraco.Core.Cache; using Umbraco.Core.Composing; -using Umbraco.Core.Composing.LightInject; using Umbraco.Core.Logging; using Umbraco.Web; diff --git a/src/Umbraco.Tests/Models/ContentTests.cs b/src/Umbraco.Tests/Models/ContentTests.cs index 01b08d9ae9..ba1a4e739c 100644 --- a/src/Umbraco.Tests/Models/ContentTests.cs +++ b/src/Umbraco.Tests/Models/ContentTests.cs @@ -41,6 +41,7 @@ namespace Umbraco.Tests.Models Container.Register(_ => Mock.Of()); Container.Register((factory, fileSystem) => new MediaFileSystem(fileSystem, factory.GetInstance(), factory.GetInstance(), factory.GetInstance())); Container.Register(); + Container.Register(factory => factory.GetInstance()); Container.Register(_ => Mock.Of()); Container.Register(_ => Mock.Of()); } diff --git a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs index 29de77e6d8..2a3b197218 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs @@ -63,7 +63,7 @@ namespace Umbraco.Tests.Persistence.Repositories { cacheHelper = cacheHelper ?? CacheHelper; - templateRepository = new TemplateRepository(scopeAccessor, cacheHelper, Logger, Mock.Of(), Mock.Of(), Mock.Of()); + templateRepository = new TemplateRepository(scopeAccessor, cacheHelper, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); var tagRepository = new TagRepository(scopeAccessor, cacheHelper, Logger); contentTypeRepository = new ContentTypeRepository(scopeAccessor, cacheHelper, Logger, templateRepository); var languageRepository = new LanguageRepository(scopeAccessor, cacheHelper, Logger); diff --git a/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs index 9be7fe434a..e4f794763d 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs @@ -36,7 +36,7 @@ namespace Umbraco.Tests.Persistence.Repositories private DocumentRepository CreateRepository(IScopeAccessor scopeAccessor, out ContentTypeRepository contentTypeRepository) { var cacheHelper = CacheHelper.Disabled; - var templateRepository = new TemplateRepository(scopeAccessor, cacheHelper, Logger, Mock.Of(), Mock.Of(), Mock.Of()); + var templateRepository = new TemplateRepository(scopeAccessor, cacheHelper, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); var tagRepository = new TagRepository(scopeAccessor, cacheHelper, Logger); contentTypeRepository = new ContentTypeRepository(scopeAccessor, cacheHelper, Logger, templateRepository); var languageRepository = new LanguageRepository(scopeAccessor, cacheHelper, Logger); @@ -46,7 +46,7 @@ namespace Umbraco.Tests.Persistence.Repositories private ContentTypeRepository CreateRepository(IScopeAccessor scopeAccessor) { - var templateRepository = new TemplateRepository(scopeAccessor, CacheHelper.Disabled, Logger, Mock.Of(), Mock.Of(), Mock.Of()); + var templateRepository = new TemplateRepository(scopeAccessor, CacheHelper.Disabled, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); var contentTypeRepository = new ContentTypeRepository(scopeAccessor, CacheHelper.Disabled, Logger, templateRepository); return contentTypeRepository; } @@ -72,7 +72,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var templateRepo = new TemplateRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, Mock.Of(), Mock.Of(), Mock.Of()); + var templateRepo = new TemplateRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); var repository = CreateRepository((IScopeAccessor) provider); var templates = new[] { diff --git a/src/Umbraco.Tests/Persistence/Repositories/DomainRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DomainRepositoryTest.cs index 070ef781cf..a5402f964e 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DomainRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DomainRepositoryTest.cs @@ -22,7 +22,7 @@ namespace Umbraco.Tests.Persistence.Repositories private DomainRepository CreateRepository(IScopeProvider provider, out ContentTypeRepository contentTypeRepository, out DocumentRepository documentRepository, out LanguageRepository languageRepository) { var accessor = (IScopeAccessor) provider; - var templateRepository = new TemplateRepository(accessor, Core.Cache.CacheHelper.Disabled, Logger, Mock.Of(), Mock.Of(), Mock.Of()); + var templateRepository = new TemplateRepository(accessor, Core.Cache.CacheHelper.Disabled, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); var tagRepository = new TagRepository(accessor, Core.Cache.CacheHelper.Disabled, Logger); contentTypeRepository = new ContentTypeRepository(accessor, Core.Cache.CacheHelper.Disabled, Logger, templateRepository); languageRepository = new LanguageRepository(accessor, Core.Cache.CacheHelper.Disabled, Logger); diff --git a/src/Umbraco.Tests/Persistence/Repositories/PartialViewRepositoryTests.cs b/src/Umbraco.Tests/Persistence/Repositories/PartialViewRepositoryTests.cs index cf307d2ea9..79cb1dd4f1 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/PartialViewRepositoryTests.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/PartialViewRepositoryTests.cs @@ -1,4 +1,5 @@ using System.Linq; +using Moq; using NUnit.Framework; using Umbraco.Core.IO; using Umbraco.Core.Models; @@ -37,10 +38,13 @@ namespace Umbraco.Tests.Persistence.Repositories { // unless noted otherwise, no changes / 7.2.8 + var fileSystems = Mock.Of(); + Mock.Get(fileSystems).Setup(x => x.PartialViewsFileSystem).Returns(_fileSystem); + var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = new PartialViewRepository(_fileSystem); + var repository = new PartialViewRepository(fileSystems); var partialView = new PartialView(PartialViewType.PartialView, "test-path-1.cshtml") { Content = "// partialView" }; repository.Save(partialView); diff --git a/src/Umbraco.Tests/Persistence/Repositories/PublicAccessRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/PublicAccessRepositoryTest.cs index 39b3b0f797..e76d794e69 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/PublicAccessRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/PublicAccessRepositoryTest.cs @@ -307,7 +307,7 @@ namespace Umbraco.Tests.Persistence.Repositories private DocumentRepository CreateRepository(IScopeProvider provider, out ContentTypeRepository contentTypeRepository) { var accessor = (IScopeAccessor) provider; - var templateRepository = new TemplateRepository(accessor, CacheHelper, Logger, Mock.Of(), Mock.Of(), Mock.Of()); + var templateRepository = new TemplateRepository(accessor, CacheHelper, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); var tagRepository = new TagRepository(accessor, CacheHelper, Logger); contentTypeRepository = new ContentTypeRepository(accessor, CacheHelper, Logger, templateRepository); var languageRepository = new LanguageRepository(accessor, CacheHelper, Logger); diff --git a/src/Umbraco.Tests/Persistence/Repositories/ScriptRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ScriptRepositoryTest.cs index 755682a913..e414fc1c3a 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ScriptRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ScriptRepositoryTest.cs @@ -7,10 +7,8 @@ using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Composing; using Umbraco.Core.IO; using Umbraco.Core.Models; -using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.PropertyEditors; -using Umbraco.Core.Scoping; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; @@ -20,13 +18,16 @@ namespace Umbraco.Tests.Persistence.Repositories [UmbracoTest(WithApplication = true, Database = UmbracoTestOptions.Database.NewEmptyPerFixture)] public class ScriptRepositoryTest : TestWithDatabaseBase { + private IFileSystems _fileSystems; private IFileSystem _fileSystem; public override void SetUp() { base.SetUp(); + _fileSystems = Mock.Of(); _fileSystem = new PhysicalFileSystem(SystemDirectories.Scripts); + Mock.Get(_fileSystems).Setup(x => x.ScriptsFileSystem).Returns(_fileSystem); using (var stream = CreateStream("Umbraco.Sys.registerNamespace(\"Umbraco.Utils\");")) { _fileSystem.AddFile("test-script.js", stream); @@ -47,9 +48,8 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = ScopeProvider.CreateScope()) { - // Act - var repository = new ScriptRepository(_fileSystem, Mock.Of()); + var repository = new ScriptRepository(_fileSystems, Mock.Of()); // Assert Assert.That(repository, Is.Not.Null); @@ -63,7 +63,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = ScopeProvider.CreateScope()) { - var repository = new ScriptRepository(_fileSystem, Mock.Of()); + var repository = new ScriptRepository(_fileSystems, Mock.Of()); // Act var script = new Script("test-add-script.js") { Content = "/// " }; @@ -82,7 +82,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = ScopeProvider.CreateScope()) { - var repository = new ScriptRepository(_fileSystem, Mock.Of()); + var repository = new ScriptRepository(_fileSystems, Mock.Of()); // Act var script = new Script("test-updated-script.js") { Content = "/// " }; @@ -108,7 +108,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = ScopeProvider.CreateScope()) { - var repository = new ScriptRepository(_fileSystem, Mock.Of()); + var repository = new ScriptRepository(_fileSystems, Mock.Of()); // Act var script = repository.Get("test-script.js"); @@ -128,7 +128,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = ScopeProvider.CreateScope()) { - var repository = new ScriptRepository(_fileSystem, Mock.Of()); + var repository = new ScriptRepository(_fileSystems, Mock.Of()); // Act var exists = repository.Get("test-script.js"); @@ -147,7 +147,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = ScopeProvider.CreateScope()) { - var repository = new ScriptRepository(_fileSystem, Mock.Of()); + var repository = new ScriptRepository(_fileSystems, Mock.Of()); var script = new Script("test-script1.js") { Content = "/// " }; repository.Save(script); @@ -175,7 +175,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = ScopeProvider.CreateScope()) { - var repository = new ScriptRepository(_fileSystem, Mock.Of()); + var repository = new ScriptRepository(_fileSystems, Mock.Of()); var script = new Script("test-script1.js") { Content = "/// " }; repository.Save(script); @@ -203,7 +203,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = ScopeProvider.CreateScope()) { - var repository = new ScriptRepository(_fileSystem, Mock.Of()); + var repository = new ScriptRepository(_fileSystems, Mock.Of()); // Act var exists = repository.Exists("test-script.js"); @@ -222,7 +222,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = ScopeProvider.CreateScope()) { - var repository = new ScriptRepository(_fileSystem, Mock.Of()); + var repository = new ScriptRepository(_fileSystems, Mock.Of()); var script = new Script("test-move-script.js") { Content = content }; repository.Save(script); @@ -255,7 +255,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = ScopeProvider.CreateScope()) { - var repository = new ScriptRepository(_fileSystem, Mock.Of()); + var repository = new ScriptRepository(_fileSystems, Mock.Of()); var script = new Script("test-path-1.js") { Content = "// script" }; repository.Save(script); @@ -328,11 +328,11 @@ namespace Umbraco.Tests.Persistence.Repositories base.TearDown(); //Delete all files - Purge((PhysicalFileSystem) _fileSystem, ""); - _fileSystem = null; + Purge(_fileSystems.ScriptsFileSystem, ""); + _fileSystems = null; } - private void Purge(PhysicalFileSystem fs, string path) + private void Purge(IFileSystem fs, string path) { var files = fs.GetFiles(path, "*.js"); foreach (var file in files) diff --git a/src/Umbraco.Tests/Persistence/Repositories/StylesheetRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/StylesheetRepositoryTest.cs index c87a976ab8..61fcd8aabe 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/StylesheetRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/StylesheetRepositoryTest.cs @@ -1,17 +1,12 @@ -using System; -using System.Data; +using System.Data; using System.IO; using System.Linq; using System.Text; using Moq; using NUnit.Framework; using Umbraco.Core.IO; -using Umbraco.Core.Logging; using Umbraco.Core.Models; -using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; -using Umbraco.Core.Scoping; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; @@ -21,13 +16,16 @@ namespace Umbraco.Tests.Persistence.Repositories [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerFixture)] public class StylesheetRepositoryTest : TestWithDatabaseBase { + private IFileSystems _fileSystems; private IFileSystem _fileSystem; public override void SetUp() { base.SetUp(); + _fileSystems = Mock.Of(); _fileSystem = new PhysicalFileSystem(SystemDirectories.Css); + Mock.Get(_fileSystems).Setup(x => x.StylesheetsFileSystem).Returns(_fileSystem); var stream = CreateStream("body {background:#EE7600; color:#FFF;}"); _fileSystem.AddFile("styles.css", stream); } @@ -36,11 +34,10 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Instantiate_Repository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + using (ScopeProvider.CreateScope()) { // Act - var repository = new StylesheetRepository(_fileSystem); + var repository = new StylesheetRepository(_fileSystems); // Assert @@ -52,10 +49,9 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + using (ScopeProvider.CreateScope()) { - var repository = new StylesheetRepository(_fileSystem); + var repository = new StylesheetRepository(_fileSystems); // Act var stylesheet = new Stylesheet("test-add.css") { Content = "body { color:#000; } .bold {font-weight:bold;}" }; @@ -71,10 +67,9 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + using (ScopeProvider.CreateScope()) { - var repository = new StylesheetRepository(_fileSystem); + var repository = new StylesheetRepository(_fileSystems); // Act var stylesheet = new Stylesheet("test-update.css") { Content = "body { color:#000; } .bold {font-weight:bold;}" }; @@ -99,10 +94,9 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_With_Property() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + using (ScopeProvider.CreateScope()) { - var repository = new StylesheetRepository(_fileSystem); + var repository = new StylesheetRepository(_fileSystems); // Act var stylesheet = new Stylesheet("test-update.css") { Content = "body { color:#000; } .bold {font-weight:bold;}" }; @@ -130,10 +124,9 @@ p{font-size:2em;}")); public void Throws_When_Adding_Duplicate_Properties() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + using (ScopeProvider.CreateScope()) { - var repository = new StylesheetRepository(_fileSystem); + var repository = new StylesheetRepository(_fileSystems); // Act var stylesheet = new Stylesheet("test-update.css") { Content = "body { color:#000; } .bold {font-weight:bold;}" }; @@ -150,10 +143,9 @@ p{font-size:2em;}")); public void Can_Perform_Delete() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + using (ScopeProvider.CreateScope()) { - var repository = new StylesheetRepository(_fileSystem); + var repository = new StylesheetRepository(_fileSystems); // Act var stylesheet = new Stylesheet("test-delete.css") { Content = "body { color:#000; } .bold {font-weight:bold;}" }; @@ -172,10 +164,9 @@ p{font-size:2em;}")); public void Can_Perform_Get() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + using (ScopeProvider.CreateScope()) { - var repository = new StylesheetRepository(_fileSystem); + var repository = new StylesheetRepository(_fileSystems); // Act var stylesheet = repository.Get("styles.css"); @@ -192,10 +183,9 @@ p{font-size:2em;}")); public void Can_Perform_GetAll() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + using (ScopeProvider.CreateScope()) { - var repository = new StylesheetRepository(_fileSystem); + var repository = new StylesheetRepository(_fileSystems); var stylesheet = new Stylesheet("styles-v2.css") { Content = "body { color:#000; } .bold {font-weight:bold;}" }; repository.Save(stylesheet); @@ -216,10 +206,9 @@ p{font-size:2em;}")); public void Can_Perform_GetAll_With_Params() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + using (ScopeProvider.CreateScope()) { - var repository = new StylesheetRepository(_fileSystem); + var repository = new StylesheetRepository(_fileSystems); var stylesheet = new Stylesheet("styles-v2.css") { Content = "body { color:#000; } .bold {font-weight:bold;}" }; repository.Save(stylesheet); @@ -240,10 +229,9 @@ p{font-size:2em;}")); public void Can_Perform_Exists() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + using (ScopeProvider.CreateScope()) { - var repository = new StylesheetRepository(_fileSystem); + var repository = new StylesheetRepository(_fileSystems); // Act var exists = repository.Exists("styles.css"); @@ -258,10 +246,9 @@ p{font-size:2em;}")); { // unless noted otherwise, no changes / 7.2.8 - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + using (ScopeProvider.CreateScope()) { - var repository = new StylesheetRepository(_fileSystem); + var repository = new StylesheetRepository(_fileSystems); var stylesheet = new Stylesheet("test-path-1.css") { Content = "body { color:#000; } .bold {font-weight:bold;}" }; repository.Save(stylesheet); diff --git a/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs index 65156df08d..78eb736007 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs @@ -953,7 +953,7 @@ namespace Umbraco.Tests.Persistence.Repositories private DocumentRepository CreateContentRepository(IScopeProvider provider, out ContentTypeRepository contentTypeRepository) { var accessor = (IScopeAccessor) provider; - var templateRepository = new TemplateRepository(accessor, CacheHelper.Disabled, Logger, Mock.Of(), Mock.Of(), Mock.Of()); + var templateRepository = new TemplateRepository(accessor, CacheHelper.Disabled, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); var tagRepository = new TagRepository(accessor, CacheHelper.Disabled, Logger); contentTypeRepository = new ContentTypeRepository(accessor, CacheHelper.Disabled, Logger, templateRepository); var languageRepository = new LanguageRepository(accessor, CacheHelper.Disabled, Logger); diff --git a/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs index 69bbc46b57..b9bbfbb363 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs @@ -23,47 +23,46 @@ namespace Umbraco.Tests.Persistence.Repositories [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)] public class TemplateRepositoryTest : TestWithDatabaseBase { - private IFileSystem _masterPageFileSystem; - private IFileSystem _viewsFileSystem; + private IFileSystems _fileSystems; private ITemplateRepository CreateRepository(IScopeProvider provider, ITemplatesSection templatesSection = null) { return new TemplateRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, templatesSection ?? Mock.Of(t => t.DefaultRenderingEngine == RenderingEngine.Mvc), - _masterPageFileSystem, _viewsFileSystem); + _fileSystems); } public override void SetUp() { base.SetUp(); - _masterPageFileSystem = new PhysicalFileSystem(SystemDirectories.Masterpages); - _viewsFileSystem = new PhysicalFileSystem(SystemDirectories.MvcViews); + _fileSystems = Mock.Of(); + var masterPageFileSystem = new PhysicalFileSystem(SystemDirectories.Masterpages); + Mock.Get(_fileSystems).Setup(x => x.MasterPagesFileSystem).Returns(masterPageFileSystem); + var viewsFileSystem = new PhysicalFileSystem(SystemDirectories.MvcViews); + Mock.Get(_fileSystems).Setup(x => x.MvcViewsFileSystem).Returns(viewsFileSystem); } [Test] public void Can_Instantiate_Repository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + using (ScopeProvider.CreateScope()) { - var repository = CreateRepository(provider); + var repository = CreateRepository(ScopeProvider); // Assert Assert.That(repository, Is.Not.Null); } - } [Test] public void Can_Perform_Add_MasterPage_Detect_Content() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + using (ScopeProvider.CreateScope()) { - var repository = CreateRepository(provider); + var repository = CreateRepository(ScopeProvider); // Act var template = new Template("test", "test") @@ -71,32 +70,28 @@ namespace Umbraco.Tests.Persistence.Repositories Content = @"<%@ Master Language=""C#"" %>" }; repository.Save(template); - //Assert Assert.That(repository.Get("test"), Is.Not.Null); - Assert.That(_masterPageFileSystem.FileExists("test.master"), Is.True); + Assert.That(_fileSystems.MasterPagesFileSystem.FileExists("test.master"), Is.True); } - } [Test] public void Can_Perform_Add_MasterPage_With_Default_Content() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + using (ScopeProvider.CreateScope()) { - var repository = CreateRepository(provider, Mock.Of(x => x.DefaultRenderingEngine == RenderingEngine.WebForms)); + var repository = CreateRepository(ScopeProvider, Mock.Of(x => x.DefaultRenderingEngine == RenderingEngine.WebForms)); // Act var template = new Template("test", "test"); repository.Save(template); - //Assert Assert.That(repository.Get("test"), Is.Not.Null); - Assert.That(_masterPageFileSystem.FileExists("test.master"), Is.True); + Assert.That(_fileSystems.MasterPagesFileSystem.FileExists("test.master"), Is.True); Assert.AreEqual(@"<%@ Master Language=""C#"" MasterPageFile=""~/umbraco/masterpages/default.master"" AutoEventWireup=""true"" %> @@ -104,47 +99,41 @@ namespace Umbraco.Tests.Persistence.Repositories ".StripWhitespace(), template.Content.StripWhitespace()); } - } [Test] public void Can_Perform_Add_MasterPage_With_Default_Content_With_Parent() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + using (ScopeProvider.CreateScope()) { - var repository = CreateRepository(provider, Mock.Of(x => x.DefaultRenderingEngine == RenderingEngine.WebForms)); + var repository = CreateRepository(ScopeProvider, Mock.Of(x => x.DefaultRenderingEngine == RenderingEngine.WebForms)); //NOTE: This has to be persisted first var template = new Template("test", "test"); repository.Save(template); - // Act var template2 = new Template("test2", "test2"); template2.SetMasterTemplate(template); repository.Save(template2); - //Assert Assert.That(repository.Get("test2"), Is.Not.Null); - Assert.That(_masterPageFileSystem.FileExists("test2.master"), Is.True); + Assert.That(_fileSystems.MasterPagesFileSystem.FileExists("test2.master"), Is.True); Assert.AreEqual(@"<%@ Master Language=""C#"" MasterPageFile=""~/masterpages/test.master"" AutoEventWireup=""true"" %> ".StripWhitespace(), template2.Content.StripWhitespace()); } - } [Test] public void Can_Perform_Add_View() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + using (ScopeProvider.CreateScope()) { - var repository = CreateRepository(provider); + var repository = CreateRepository(ScopeProvider); // Act var template = new Template("test", "test"); @@ -153,19 +142,17 @@ namespace Umbraco.Tests.Persistence.Repositories //Assert Assert.That(repository.Get("test"), Is.Not.Null); - Assert.That(_viewsFileSystem.FileExists("test.cshtml"), Is.True); + Assert.That(_fileSystems.MvcViewsFileSystem.FileExists("test.cshtml"), Is.True); } - } [Test] public void Can_Perform_Add_View_With_Default_Content() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + using (ScopeProvider.CreateScope()) { - var repository = CreateRepository(provider); + var repository = CreateRepository(ScopeProvider); // Act var template = new Template("test", "test") @@ -173,41 +160,36 @@ namespace Umbraco.Tests.Persistence.Repositories Content = ViewHelper.GetDefaultFileContent() }; repository.Save(template); - //Assert Assert.That(repository.Get("test"), Is.Not.Null); - Assert.That(_viewsFileSystem.FileExists("test.cshtml"), Is.True); + Assert.That(_fileSystems.MvcViewsFileSystem.FileExists("test.cshtml"), Is.True); Assert.AreEqual( @"@inherits Umbraco.Web.Mvc.UmbracoViewPage @{ Layout = null;}".StripWhitespace(), template.Content.StripWhitespace()); } - } [Test] public void Can_Perform_Add_View_With_Default_Content_With_Parent() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + using (ScopeProvider.CreateScope()) { - var repository = CreateRepository(provider); + var repository = CreateRepository(ScopeProvider); //NOTE: This has to be persisted first var template = new Template("test", "test"); repository.Save(template); - // Act var template2 = new Template("test2", "test2"); template2.SetMasterTemplate(template); repository.Save(template2); - //Assert Assert.That(repository.Get("test2"), Is.Not.Null); - Assert.That(_viewsFileSystem.FileExists("test2.cshtml"), Is.True); + Assert.That(_fileSystems.MvcViewsFileSystem.FileExists("test2.cshtml"), Is.True); Assert.AreEqual( "@inherits Umbraco.Web.Mvc.UmbracoViewPage @{ Layout = \"test.cshtml\";}".StripWhitespace(), template2.Content.StripWhitespace()); @@ -218,10 +200,9 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_Unique_Alias() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + using (ScopeProvider.CreateScope()) { - var repository = CreateRepository(provider); + var repository = CreateRepository(ScopeProvider); // Act var template = new Template("test", "test") @@ -229,29 +210,25 @@ namespace Umbraco.Tests.Persistence.Repositories Content = ViewHelper.GetDefaultFileContent() }; repository.Save(template); - var template2 = new Template("test", "test") { Content = ViewHelper.GetDefaultFileContent() }; repository.Save(template2); - //Assert Assert.AreEqual("test1", template2.Alias); } - } [Test] public void Can_Perform_Update_Unique_Alias() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + using (ScopeProvider.CreateScope()) { - var repository = CreateRepository(provider); + var repository = CreateRepository(ScopeProvider); // Act var template = new Template("test", "test") @@ -259,35 +236,30 @@ namespace Umbraco.Tests.Persistence.Repositories Content = ViewHelper.GetDefaultFileContent() }; repository.Save(template); - var template2 = new Template("test1", "test1") { Content = ViewHelper.GetDefaultFileContent() }; repository.Save(template2); - template.Alias = "test1"; repository.Save(template); - //Assert Assert.AreEqual("test11", template.Alias); - Assert.That(_viewsFileSystem.FileExists("test11.cshtml"), Is.True); - Assert.That(_viewsFileSystem.FileExists("test.cshtml"), Is.False); + Assert.That(_fileSystems.MvcViewsFileSystem.FileExists("test11.cshtml"), Is.True); + Assert.That(_fileSystems.MvcViewsFileSystem.FileExists("test.cshtml"), Is.False); } - } [Test] public void Can_Perform_Update_MasterPage() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + using (ScopeProvider.CreateScope()) { - var repository = CreateRepository(provider); + var repository = CreateRepository(ScopeProvider); // Act var template = new Template("test", "test") @@ -295,30 +267,25 @@ namespace Umbraco.Tests.Persistence.Repositories Content = @"<%@ Master Language=""C#"" %>" }; repository.Save(template); - template.Content = @"<%@ Master Language=""VB"" %>"; repository.Save(template); - var updated = repository.Get("test"); // Assert - Assert.That(_masterPageFileSystem.FileExists("test.master"), Is.True); + Assert.That(_fileSystems.MasterPagesFileSystem.FileExists("test.master"), Is.True); Assert.That(updated.Content, Is.EqualTo(@"<%@ Master Language=""VB"" %>")); } - - } [Test] public void Can_Perform_Update_View() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + using (ScopeProvider.CreateScope()) { - var repository = CreateRepository(provider); + var repository = CreateRepository(ScopeProvider); // Act var template = new Template("test", "test") @@ -326,16 +293,14 @@ namespace Umbraco.Tests.Persistence.Repositories Content = ViewHelper.GetDefaultFileContent() }; repository.Save(template); - template.Content += ""; repository.Save(template); - var updated = repository.Get("test"); // Assert - Assert.That(_viewsFileSystem.FileExists("test.cshtml"), Is.True); + Assert.That(_fileSystems.MvcViewsFileSystem.FileExists("test.cshtml"), Is.True); Assert.That(updated.Content, Is.EqualTo(ViewHelper.GetDefaultFileContent() + "")); } } @@ -344,27 +309,24 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_MasterPage() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + using (ScopeProvider.CreateScope()) { - var repository = CreateRepository(provider); + var repository = CreateRepository(ScopeProvider); var template = new Template("test", "test") { Content = @"<%@ Master Language=""C#"" %>" }; repository.Save(template); - // Act var templates = repository.Get("test"); - Assert.That(_masterPageFileSystem.FileExists("test.master"), Is.True); + Assert.That(_fileSystems.MasterPagesFileSystem.FileExists("test.master"), Is.True); repository.Delete(templates); - // Assert Assert.IsNull(repository.Get("test")); - Assert.That(_masterPageFileSystem.FileExists("test.master"), Is.False); + Assert.That(_fileSystems.MasterPagesFileSystem.FileExists("test.master"), Is.False); } } @@ -372,27 +334,24 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_View() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + using (ScopeProvider.CreateScope()) { - var repository = CreateRepository(provider); + var repository = CreateRepository(ScopeProvider); var template = new Template("test", "test") { Content = ViewHelper.GetDefaultFileContent() }; repository.Save(template); - // Act var templates = repository.Get("test"); - Assert.That(_viewsFileSystem.FileExists("test.cshtml"), Is.True); + Assert.That(_fileSystems.MvcViewsFileSystem.FileExists("test.cshtml"), Is.True); repository.Delete(templates); - // Assert Assert.IsNull(repository.Get("test")); - Assert.That(_viewsFileSystem.FileExists("test.cshtml"), Is.False); + Assert.That(_fileSystems.MvcViewsFileSystem.FileExists("test.cshtml"), Is.False); } } @@ -400,39 +359,33 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_When_Assigned_To_Doc() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + using (ScopeProvider.CreateScope()) { - var templateRepository = CreateRepository(provider); + var templateRepository = CreateRepository(ScopeProvider); - var tagRepository = new TagRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger); - var contentTypeRepository = new ContentTypeRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, templateRepository); - var languageRepository = new LanguageRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger); - var contentRepo = new DocumentRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, Mock.Of()); + var tagRepository = new TagRepository((IScopeAccessor) ScopeProvider, CacheHelper.Disabled, Logger); + var contentTypeRepository = new ContentTypeRepository((IScopeAccessor) ScopeProvider, CacheHelper.Disabled, Logger, templateRepository); + var languageRepository = new LanguageRepository((IScopeAccessor) ScopeProvider, CacheHelper.Disabled, Logger); + var contentRepo = new DocumentRepository((IScopeAccessor) ScopeProvider, CacheHelper.Disabled, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, Mock.Of()); var contentType = MockedContentTypes.CreateSimpleContentType("umbTextpage2", "Textpage"); ServiceContext.FileService.SaveTemplate(contentType.DefaultTemplate); // else, FK violation on contentType! contentTypeRepository.Save(contentType); var textpage = MockedContent.CreateSimpleContent(contentType); contentRepo.Save(textpage); - - var template = new Template("test", "test") { Content = @"<%@ Master Language=""C#"" %>" }; templateRepository.Save(template); - textpage.Template = template; contentRepo.Save(textpage); - // Act var templates = templateRepository.Get("test"); templateRepository.Delete(templates); - // Assert Assert.IsNull(templateRepository.Get("test")); @@ -443,10 +396,9 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_On_Nested_Templates() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + using (ScopeProvider.CreateScope()) { - var repository = CreateRepository(provider); + var repository = CreateRepository(ScopeProvider); var parent = new Template("parent", "parent") { @@ -467,12 +419,10 @@ namespace Umbraco.Tests.Persistence.Repositories repository.Save(parent); repository.Save(child); repository.Save(baby); - // Act var templates = repository.Get("parent"); repository.Delete(templates); - // Assert Assert.IsNull(repository.Get("test")); @@ -483,10 +433,9 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Get_Template_Tree() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + using (ScopeProvider.CreateScope()) { - var repository = CreateRepository(provider); + var repository = CreateRepository(ScopeProvider); CreateHierarchy(repository); @@ -510,10 +459,9 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Get_All() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + using (ScopeProvider.CreateScope()) { - var repository = CreateRepository(provider); + var repository = CreateRepository(ScopeProvider); var created = CreateHierarchy(repository).ToArray(); @@ -538,10 +486,9 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Get_Children() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + using (ScopeProvider.CreateScope()) { - var repository = CreateRepository(provider); + var repository = CreateRepository(ScopeProvider); var created = CreateHierarchy(repository).ToArray(); @@ -549,7 +496,6 @@ namespace Umbraco.Tests.Persistence.Repositories var childrenById = repository.GetChildren(created[1].Id); var childrenByAlias = repository.GetChildren(created[1].Alias); - // Assert Assert.AreEqual(2, childrenById.Count()); Assert.AreEqual(2, childrenById.DistinctBy(x => x.Id).Count()); @@ -562,17 +508,15 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Get_Children_At_Root() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + using (ScopeProvider.CreateScope()) { - var repository = CreateRepository(provider); + var repository = CreateRepository(ScopeProvider); CreateHierarchy(repository).ToArray(); // Act var children = repository.GetChildren(-1); - // Assert Assert.AreEqual(1, children.Count()); Assert.AreEqual(1, children.DistinctBy(x => x.Id).Count()); @@ -583,18 +527,15 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Get_Descendants() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + using (ScopeProvider.CreateScope()) { - var repository = CreateRepository(provider); - + var repository = CreateRepository(ScopeProvider); var created = CreateHierarchy(repository).ToArray(); // Act var descendantsById = repository.GetDescendants(created[1].Id); var descendantsByAlias = repository.GetDescendants(created[1].Alias); - // Assert Assert.AreEqual(3, descendantsById.Count()); Assert.AreEqual(3, descendantsById.DistinctBy(x => x.Id).Count()); @@ -608,10 +549,9 @@ namespace Umbraco.Tests.Persistence.Repositories public void Path_Is_Set_Correctly_On_Creation() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + using (ScopeProvider.CreateScope()) { - var repository = CreateRepository(provider); + var repository = CreateRepository(ScopeProvider); var parent = new Template("parent", "parent"); var child1 = new Template("child1", "child1"); @@ -640,7 +580,6 @@ namespace Umbraco.Tests.Persistence.Repositories baby2.MasterTemplateAlias = toddler4.Alias; baby2.MasterTemplateId = new Lazy(() => toddler4.Id); - // Act repository.Save(parent); repository.Save(child1); @@ -651,7 +590,6 @@ namespace Umbraco.Tests.Persistence.Repositories repository.Save(toddler4); repository.Save(baby1); repository.Save(baby2); - // Assert Assert.AreEqual(string.Format("-1,{0}", parent.Id), parent.Path); @@ -671,10 +609,9 @@ namespace Umbraco.Tests.Persistence.Repositories public void Path_Is_Set_Correctly_On_Update() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + using (ScopeProvider.CreateScope()) { - var repository = CreateRepository(provider); + var repository = CreateRepository(ScopeProvider); var parent = new Template("parent", "parent"); var child1 = new Template("child1", "child1"); @@ -696,12 +633,10 @@ namespace Umbraco.Tests.Persistence.Repositories repository.Save(child2); repository.Save(toddler1); repository.Save(toddler2); - //Act toddler2.SetMasterTemplate(child2); repository.Save(toddler2); - //Assert Assert.AreEqual($"-1,{parent.Id},{child2.Id},{toddler2.Id}", toddler2.Path); @@ -712,10 +647,9 @@ namespace Umbraco.Tests.Persistence.Repositories public void Path_Is_Set_Correctly_On_Update_With_Master_Template_Removal() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + using (ScopeProvider.CreateScope()) { - var repository = CreateRepository(provider); + var repository = CreateRepository(ScopeProvider); var parent = new Template("parent", "parent"); var child1 = new Template("child1", "child1"); @@ -725,12 +659,10 @@ namespace Umbraco.Tests.Persistence.Repositories repository.Save(parent); repository.Save(child1); - //Act child1.SetMasterTemplate(null); repository.Save(child1); - //Assert Assert.AreEqual($"-1,{child1.Id}", child1.Path); @@ -742,21 +674,18 @@ namespace Umbraco.Tests.Persistence.Repositories { base.TearDown(); - _masterPageFileSystem = null; - _viewsFileSystem = null; + _fileSystems = null; + //Delete all files var fsMaster = new PhysicalFileSystem(SystemDirectories.Masterpages); var masterPages = fsMaster.GetFiles("", "*.master"); foreach (var file in masterPages) - { fsMaster.DeleteFile(file); - } + var fsViews = new PhysicalFileSystem(SystemDirectories.MvcViews); - var views = fsMaster.GetFiles("", "*.cshtml"); + var views = fsViews.GetFiles("", "*.cshtml"); foreach (var file in views) - { - fsMaster.DeleteFile(file); - } + fsViews.DeleteFile(file); } protected Stream CreateStream(string contents = null) diff --git a/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs index 5a46bc805f..64615c1950 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs @@ -39,7 +39,7 @@ namespace Umbraco.Tests.Persistence.Repositories private DocumentRepository CreateContentRepository(IScopeProvider provider, out IContentTypeRepository contentTypeRepository, out ITemplateRepository templateRepository) { var accessor = (IScopeAccessor) provider; - templateRepository = new TemplateRepository(accessor, CacheHelper, Logger, Mock.Of(), Mock.Of(), Mock.Of()); + templateRepository = new TemplateRepository(accessor, CacheHelper, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); var tagRepository = new TagRepository(accessor, CacheHelper, Logger); contentTypeRepository = new ContentTypeRepository(accessor, CacheHelper, Logger, templateRepository); var languageRepository = new LanguageRepository(accessor, CacheHelper, Logger); diff --git a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs index ecb8e42c90..b270fe8e22 100644 --- a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs @@ -1,10 +1,9 @@ using System; -using System.Collections.Generic; using System.Linq; using LightInject; using Moq; using NUnit.Framework; -using Umbraco.Core.Collections; +using Umbraco.Core; using Umbraco.Core.Events; using Umbraco.Core.Models; using Umbraco.Core.IO; diff --git a/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs b/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs index 5f4e653735..948b0f6378 100644 --- a/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs @@ -4,6 +4,7 @@ using System.Xml; using Moq; using NUnit.Framework; using LightInject; +using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Events; diff --git a/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs b/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs index b1d6934043..5f41031a0b 100644 --- a/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs +++ b/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs @@ -162,7 +162,7 @@ namespace Umbraco.Tests.Services var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var tRepository = new TemplateRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, Mock.Of(), Mock.Of(), Mock.Of()); + var tRepository = new TemplateRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); var tagRepo = new TagRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger); var ctRepository = new ContentTypeRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, tRepository); var languageRepository = new LanguageRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger); @@ -195,7 +195,7 @@ namespace Umbraco.Tests.Services var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var tRepository = new TemplateRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, Mock.Of(), Mock.Of(), Mock.Of()); + var tRepository = new TemplateRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); var tagRepo = new TagRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger); var ctRepository = new ContentTypeRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, tRepository); var languageRepository = new LanguageRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger); @@ -226,7 +226,7 @@ namespace Umbraco.Tests.Services var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var tRepository = new TemplateRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, Mock.Of(), Mock.Of(), Mock.Of()); + var tRepository = new TemplateRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); var tagRepo = new TagRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger); var ctRepository = new ContentTypeRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, tRepository); var languageRepository = new LanguageRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger); @@ -260,7 +260,7 @@ namespace Umbraco.Tests.Services var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var tRepository = new TemplateRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, Mock.Of(), Mock.Of(), Mock.Of()); + var tRepository = new TemplateRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); var tagRepo = new TagRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger); var ctRepository = new ContentTypeRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, tRepository); var languageRepository = new LanguageRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger); diff --git a/src/Umbraco.Tests/Services/ContentServiceTests.cs b/src/Umbraco.Tests/Services/ContentServiceTests.cs index c3661c1a18..ff1678fa3f 100644 --- a/src/Umbraco.Tests/Services/ContentServiceTests.cs +++ b/src/Umbraco.Tests/Services/ContentServiceTests.cs @@ -2952,7 +2952,7 @@ namespace Umbraco.Tests.Services private DocumentRepository CreateRepository(IScopeProvider provider, out ContentTypeRepository contentTypeRepository) { var accessor = (IScopeAccessor) provider; - var templateRepository = new TemplateRepository(accessor, CacheHelper.Disabled, Logger, Mock.Of(), Mock.Of(), Mock.Of()); + var templateRepository = new TemplateRepository(accessor, CacheHelper.Disabled, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); var tagRepository = new TagRepository(accessor, CacheHelper.Disabled, Logger); contentTypeRepository = new ContentTypeRepository(accessor, CacheHelper.Disabled, Logger, templateRepository); var languageRepository = new LanguageRepository(accessor, CacheHelper.Disabled, Logger); diff --git a/src/Umbraco.Tests/Templates/TemplateRepositoryTests.cs b/src/Umbraco.Tests/Templates/TemplateRepositoryTests.cs index 340f0ea79f..795d79ced1 100644 --- a/src/Umbraco.Tests/Templates/TemplateRepositoryTests.cs +++ b/src/Umbraco.Tests/Templates/TemplateRepositoryTests.cs @@ -6,9 +6,6 @@ using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models; -using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.Querying; -using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.Scoping; using Umbraco.Tests.TestHelpers; @@ -19,12 +16,11 @@ namespace Umbraco.Tests.Templates public class TemplateRepositoryTests { private readonly Mock _cacheMock = new Mock(); - private readonly Mock _viewFileSystemMock = new Mock(); - private readonly Mock _masterpageFileSystemMock = new Mock(); private readonly Mock _templateConfigMock = new Mock(); + private readonly IFileSystems _fileSystems = Mock.Of(); private TemplateRepository _templateRepository; - private readonly TestObjects TestObjects = new TestObjects(null); + private readonly TestObjects _testObjects = new TestObjects(null); [SetUp] public void Setup() @@ -33,12 +29,16 @@ namespace Umbraco.Tests.Templates var accessorMock = new Mock(); var scopeMock = new Mock(); - var database = TestObjects.GetUmbracoSqlCeDatabase(logger); + var database = _testObjects.GetUmbracoSqlCeDatabase(logger); scopeMock.Setup(x => x.Database).Returns(database); accessorMock.Setup(x => x.AmbientScope).Returns(scopeMock.Object); - _templateRepository = new TemplateRepository(accessorMock.Object, _cacheMock.Object, logger, _templateConfigMock.Object, _masterpageFileSystemMock.Object, _viewFileSystemMock.Object); + var mvcFs = Mock.Of(); + var masterFs = Mock.Of(); + Mock.Get(_fileSystems).Setup(x => x.MvcViewsFileSystem).Returns(mvcFs); + Mock.Get(_fileSystems).Setup(x => x.MasterPagesFileSystem).Returns(masterFs); + _templateRepository = new TemplateRepository(accessorMock.Object, _cacheMock.Object, logger, _templateConfigMock.Object, _fileSystems); } [Test] @@ -53,7 +53,8 @@ namespace Umbraco.Tests.Templates templateMock.Setup(x => x.Content).Returns(""); // but MVC View already exists - _viewFileSystemMock.Setup(x => x.FileExists(It.IsAny())).Returns(true); + Mock.Get(_fileSystems.MvcViewsFileSystem) + .Setup(x => x.FileExists(It.IsAny())).Returns(true); var res = _templateRepository.DetermineTemplateRenderingEngine(templateMock.Object); Assert.AreEqual(RenderingEngine.Mvc, res); @@ -71,7 +72,8 @@ namespace Umbraco.Tests.Templates templateMock.Setup(x => x.Content).Returns(""); // MVC View doesn't exist - _viewFileSystemMock.Setup(x => x.FileExists(It.IsAny())).Returns(false); + Mock.Get(_fileSystems.MvcViewsFileSystem) + .Setup(x => x.FileExists(It.IsAny())).Returns(false); var res = _templateRepository.DetermineTemplateRenderingEngine(templateMock.Object); Assert.AreEqual(RenderingEngine.WebForms, res); @@ -87,8 +89,10 @@ namespace Umbraco.Tests.Templates templateMock.Setup(x => x.Alias).Returns("Something"); // but masterpage already exists - _viewFileSystemMock.Setup(x => x.FileExists(It.IsAny())).Returns(false); - _masterpageFileSystemMock.Setup(x => x.FileExists(It.IsAny())).Returns(true); + Mock.Get(_fileSystems.MvcViewsFileSystem) + .Setup(x => x.FileExists(It.IsAny())).Returns(false); + Mock.Get(_fileSystems.MasterPagesFileSystem) + .Setup(x => x.FileExists(It.IsAny())).Returns(true); var res = _templateRepository.DetermineTemplateRenderingEngine(templateMock.Object); Assert.AreEqual(RenderingEngine.WebForms, res); @@ -104,8 +108,10 @@ namespace Umbraco.Tests.Templates templateMock.Setup(x => x.Alias).Returns("Something"); // but MVC View already exists - _viewFileSystemMock.Setup(x => x.FileExists(It.IsAny())).Returns(true); - _masterpageFileSystemMock.Setup(x => x.FileExists(It.IsAny())).Returns(false); + Mock.Get(_fileSystems.MvcViewsFileSystem) + .Setup(x => x.FileExists(It.IsAny())).Returns(true); + Mock.Get(_fileSystems.MasterPagesFileSystem) + .Setup(x => x.FileExists(It.IsAny())).Returns(false); var res = _templateRepository.DetermineTemplateRenderingEngine(templateMock.Object); Assert.AreEqual(RenderingEngine.Mvc, res); diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs b/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs index 6750ad9792..1cf39532a2 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Data; using System.Data.Common; using System.Linq; +using System.Linq.Expressions; using System.Web; using LightInject; using Moq; @@ -10,6 +11,7 @@ using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Events; +using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Persistence; @@ -140,6 +142,24 @@ namespace Umbraco.Tests.TestHelpers return SettingsForTests.GetDefaultGlobalSettings(); } + public IFileSystems GetFileSystemsMock() + { + var fileSystems = Mock.Of(); + MockFs(fileSystems, x => x.MasterPagesFileSystem); + MockFs(fileSystems, x => x.MacroPartialsFileSystem); + MockFs(fileSystems, x => x.MvcViewsFileSystem); + MockFs(fileSystems, x => x.PartialViewsFileSystem); + MockFs(fileSystems, x => x.ScriptsFileSystem); + MockFs(fileSystems, x => x.StylesheetsFileSystem); + return fileSystems; + } + + private void MockFs(IFileSystems fileSystems, Expression> fileSystem) + { + var fs = Mock.Of(); + Mock.Get(fileSystems).Setup(fileSystem).Returns(fs); + } + #region Inner classes private class MockDbConnection : DbConnection diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index ef2ba7133e..1b839a642e 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -11,7 +11,7 @@ using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Components; using Umbraco.Core.Composing; -using Umbraco.Core.Composing.CompositionRoots; +using Umbraco.Core.Composing.Composers; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Events; @@ -22,7 +22,6 @@ using Umbraco.Core.Manifest; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Mappers; -using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.PropertyEditors; @@ -34,9 +33,8 @@ using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Stubs; using Umbraco.Web; using Umbraco.Web.Services; -using Umbraco.Examine; using Umbraco.Tests.Testing.Objects.Accessors; -using Umbraco.Web.Composing.CompositionRoots; +using Umbraco.Web.Composing.Composers; using Umbraco.Web._Legacy.Actions; using Current = Umbraco.Core.Composing.Current; using Umbraco.Web.Routing; @@ -218,8 +216,8 @@ namespace Umbraco.Tests.Testing { if (configure == false) return; - Container.RegisterFrom(); - Container.RegisterFrom(); + Container.ComposeCoreMappingProfiles(); + Container.ComposeWebMappingProfiles(); } protected virtual void ComposePluginManager(UmbracoTestOptions.PluginManager pluginManager) @@ -278,7 +276,7 @@ namespace Umbraco.Tests.Testing SettingsForTests.ConfigureSettings(globalSettings); // default Datalayer/Repositories/SQL/Database/etc... - Container.RegisterFrom(); + Container.ComposeRepositories(); // register basic stuff that might need to be there for some container resolvers to work Container.RegisterSingleton(factory => umbracoSettings); @@ -325,11 +323,13 @@ namespace Umbraco.Tests.Testing Container.RegisterCollectionBuilder(); // empty Container.RegisterSingleton(factory => new FileSystems(factory.TryGetInstance())); + Container.RegisterSingleton(factory => factory.GetInstance()); Container.RegisterSingleton(factory => TestObjects.GetScopeProvider(factory.TryGetInstance(), factory.TryGetInstance(), factory.TryGetInstance())); Container.RegisterSingleton(factory => (IScopeAccessor) factory.GetInstance()); - Container.RegisterFrom(); + Container.ComposeServices(); + // composition root is doing weird things, fix Container.RegisterSingleton(); Container.RegisterSingleton(); diff --git a/src/Umbraco.Web/Cache/CacheRefresherComponent.cs b/src/Umbraco.Web/Cache/CacheRefresherComponent.cs index 2ee0ff5f84..591a54f611 100644 --- a/src/Umbraco.Web/Cache/CacheRefresherComponent.cs +++ b/src/Umbraco.Web/Cache/CacheRefresherComponent.cs @@ -20,7 +20,6 @@ using Umbraco.Core.Services.Implement; using Umbraco.Web.Composing; using Umbraco.Web.Security; using Umbraco.Web.Services; -using LightInject; using ApplicationTree = Umbraco.Core.Models.ApplicationTree; namespace Umbraco.Web.Cache diff --git a/src/Umbraco.Web/Composing/CompositionRoots/InstallerCompositionRoot.cs b/src/Umbraco.Web/Composing/Composers/InstallerComposer.cs similarity index 64% rename from src/Umbraco.Web/Composing/CompositionRoots/InstallerCompositionRoot.cs rename to src/Umbraco.Web/Composing/Composers/InstallerComposer.cs index b4f7d435f4..265272cef2 100644 --- a/src/Umbraco.Web/Composing/CompositionRoots/InstallerCompositionRoot.cs +++ b/src/Umbraco.Web/Composing/Composers/InstallerComposer.cs @@ -1,20 +1,16 @@ using LightInject; using Umbraco.Web.Install; -using Umbraco.Web.Install.Controllers; using Umbraco.Web.Install.InstallSteps; using Umbraco.Web.Install.Models; -namespace Umbraco.Web.Composing.CompositionRoots +namespace Umbraco.Web.Composing.Composers { - /// - /// A composition root for dealing with the installer and installer steps - /// - public sealed class InstallerCompositionRoot : ICompositionRoot + public static class InstallerComposer { - public void Compose(IServiceRegistry container) + public static IServiceRegistry ComposeInstaller(this IServiceRegistry registry) { //register the installer steps in order - container.RegisterOrdered(typeof(InstallSetupStep), + registry.RegisterOrdered(typeof(InstallSetupStep), new[] { typeof(NewInstallStep), @@ -33,10 +29,10 @@ namespace Umbraco.Web.Composing.CompositionRoots typeof(SetUmbracoVersionStep) }, type => new PerScopeLifetime()); - container.Register(); - container.Register(); - - + registry.Register(); + registry.Register(); + + return registry; } } } diff --git a/src/Umbraco.Web/Composing/Composers/WebMappingProfilesComposer.cs b/src/Umbraco.Web/Composing/Composers/WebMappingProfilesComposer.cs new file mode 100644 index 0000000000..65fdd7fb72 --- /dev/null +++ b/src/Umbraco.Web/Composing/Composers/WebMappingProfilesComposer.cs @@ -0,0 +1,46 @@ +using LightInject; +using Umbraco.Core.Models; +using Umbraco.Web.Models.ContentEditing; +using Umbraco.Web.Models.Mapping; +using Umbraco.Web.Trees; + +namespace Umbraco.Web.Composing.Composers +{ + public static class WebMappingProfilesComposer + { + public static IServiceRegistry ComposeWebMappingProfiles(this IServiceRegistry registry) + { + //register the profiles + registry.Register(); + registry.Register(); + registry.Register(); + registry.Register(); + registry.Register(); + registry.Register(); + registry.Register(); + registry.Register(); + registry.Register(); + registry.Register(); + registry.Register(); + registry.Register(); + registry.Register(); + registry.Register(); + registry.Register(); + registry.Register(); + registry.Register(); + registry.Register(); + + //register any resolvers, etc.. that the profiles use + registry.Register(); + registry.Register>(); + registry.Register>(); + registry.Register>(); + registry.Register>(); + registry.Register(); + registry.Register(); + registry.Register(); + + return registry; + } + } +} diff --git a/src/Umbraco.Web/Composing/CompositionRoots/HelperCompositionRoot.cs b/src/Umbraco.Web/Composing/CompositionRoots/HelperCompositionRoot.cs deleted file mode 100644 index d708493016..0000000000 --- a/src/Umbraco.Web/Composing/CompositionRoots/HelperCompositionRoot.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.Web.Security; -using LightInject; -using Umbraco.Web.Security; -using Umbraco.Web.Security.Providers; - -namespace Umbraco.Web.Composing.CompositionRoots -{ - public class HelperCompositionRoot : ICompositionRoot - { - public void Compose(IServiceRegistry container) - { - container.Register((factory) => Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider()); - container.Register((factory) => Roles.Enabled ? Roles.Provider : new MembersRoleProvider(Core.Composing.Current.Services.MemberService)); - container.Register(); - } - } -} diff --git a/src/Umbraco.Web/Composing/CompositionRoots/WebMappingProfilesCompositionRoot.cs b/src/Umbraco.Web/Composing/CompositionRoots/WebMappingProfilesCompositionRoot.cs deleted file mode 100644 index e865019790..0000000000 --- a/src/Umbraco.Web/Composing/CompositionRoots/WebMappingProfilesCompositionRoot.cs +++ /dev/null @@ -1,44 +0,0 @@ -using LightInject; -using Umbraco.Core.Models; -using Umbraco.Web.Models.ContentEditing; -using Umbraco.Web.Models.Mapping; -using Umbraco.Web.Trees; - -namespace Umbraco.Web.Composing.CompositionRoots -{ - public sealed class WebMappingProfilesCompositionRoot : ICompositionRoot - { - public void Compose(IServiceRegistry container) - { - //register the profiles - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - - //register any resolvers, etc.. that the profiles use - container.Register(); - container.Register>(); - container.Register>(); - container.Register>(); - container.Register>(); - container.Register(); - container.Register(); - container.Register(); - } - } -} diff --git a/src/Umbraco.Web/Composing/Current.cs b/src/Umbraco.Web/Composing/Current.cs index 8c7f4e87ce..f6d8053305 100644 --- a/src/Umbraco.Web/Composing/Current.cs +++ b/src/Umbraco.Web/Composing/Current.cs @@ -241,7 +241,7 @@ namespace Umbraco.Web.Composing public static IScopeProvider ScopeProvider => CoreCurrent.ScopeProvider; - public static FileSystems FileSystems => CoreCurrent.FileSystems; + public static IFileSystems FileSystems => CoreCurrent.FileSystems; public static ISqlContext SqlContext=> CoreCurrent.SqlContext; diff --git a/src/Umbraco.Web/Composing/ModuleInjector.cs b/src/Umbraco.Web/Composing/ModuleInjector.cs index 550cb8efc3..f183cf528e 100644 --- a/src/Umbraco.Web/Composing/ModuleInjector.cs +++ b/src/Umbraco.Web/Composing/ModuleInjector.cs @@ -1,4 +1,5 @@ using System.Web; +using Umbraco.Core; namespace Umbraco.Web.Composing { diff --git a/src/Umbraco.Web/Editors/BackOfficeAssetsController.cs b/src/Umbraco.Web/Editors/BackOfficeAssetsController.cs index eb38957633..8b260bf19a 100644 --- a/src/Umbraco.Web/Editors/BackOfficeAssetsController.cs +++ b/src/Umbraco.Web/Editors/BackOfficeAssetsController.cs @@ -10,19 +10,18 @@ namespace Umbraco.Web.Editors [PluginController("UmbracoApi")] public class BackOfficeAssetsController : UmbracoAuthorizedJsonController { - private readonly FileSystems _fileSystems; + private readonly IFileSystem _jsFileSystem; - public BackOfficeAssetsController(FileSystems fileSystems) + public BackOfficeAssetsController() { - _fileSystems = fileSystems; + _jsFileSystem = new PhysicalFileSystem(SystemDirectories.JavaScriptLibrary); } [HttpGet] public IEnumerable GetSupportedMomentLocales() { const string momentLocaleFolder = "moment"; - var fileSystem = _fileSystems.JavaScriptLibraryFileSystem; - var cultures = fileSystem.GetFiles(momentLocaleFolder, "*.js").ToList(); + var cultures = _jsFileSystem.GetFiles(momentLocaleFolder, "*.js").ToList(); for (var i = 0; i < cultures.Count; i++) { cultures[i] = cultures[i] diff --git a/src/Umbraco.Web/Editors/BackOfficeController.cs b/src/Umbraco.Web/Editors/BackOfficeController.cs index f727c9e2d6..0a4c741bdc 100644 --- a/src/Umbraco.Web/Editors/BackOfficeController.cs +++ b/src/Umbraco.Web/Editors/BackOfficeController.cs @@ -9,12 +9,10 @@ using System.Threading.Tasks; using System.Web; using System.Web.Mvc; using System.Web.UI; -using LightInject; using Microsoft.AspNet.Identity; using Microsoft.AspNet.Identity.Owin; using Microsoft.Owin.Security; using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; @@ -22,8 +20,6 @@ using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Manifest; using Umbraco.Core.Models.Identity; -using Umbraco.Core.Models.Membership; -using Umbraco.Core.Persistence; using Umbraco.Core.Security; using Umbraco.Web.Models; using Umbraco.Web.Mvc; diff --git a/src/Umbraco.Web/Editors/TourController.cs b/src/Umbraco.Web/Editors/TourController.cs index 483a910788..5b3c3ab283 100644 --- a/src/Umbraco.Web/Editors/TourController.cs +++ b/src/Umbraco.Web/Editors/TourController.cs @@ -2,8 +2,8 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using LightInject; using Newtonsoft.Json; +using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.IO; diff --git a/src/Umbraco.Web/HtmlHelperRenderExtensions.cs b/src/Umbraco.Web/HtmlHelperRenderExtensions.cs index 5a4cd97e92..cc625b068c 100644 --- a/src/Umbraco.Web/HtmlHelperRenderExtensions.cs +++ b/src/Umbraco.Web/HtmlHelperRenderExtensions.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.ComponentModel; using System.Linq; using System.Text; using System.Web; @@ -11,12 +10,9 @@ using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.Exceptions; using Umbraco.Core.IO; -using Umbraco.Core.Models.PublishedContent; using Umbraco.Web.Composing; -using Umbraco.Web.Models; using Umbraco.Web.Mvc; using Umbraco.Web.Security; -using Constants = Umbraco.Core.Constants; namespace Umbraco.Web { @@ -819,7 +815,7 @@ namespace Umbraco.Web } #endregion - + } } diff --git a/src/Umbraco.Web/Install/InstallHelper.cs b/src/Umbraco.Web/Install/InstallHelper.cs index 00630d6485..35906a4df5 100644 --- a/src/Umbraco.Web/Install/InstallHelper.cs +++ b/src/Umbraco.Web/Install/InstallHelper.cs @@ -1,13 +1,10 @@ using System; -using System.Collections; using System.Collections.Generic; using System.Configuration; using System.IO; using System.Linq; using System.Net.Http; using System.Web; -using LightInject; -using Semver; using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.IO; @@ -15,11 +12,7 @@ using Umbraco.Core.Logging; using Umbraco.Core.Migrations.Install; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.SqlSyntax; -using Umbraco.Core.Scoping; -using Umbraco.Core.Services; -using Umbraco.Web.Cache; using Umbraco.Web.Composing; -using Umbraco.Web.Install.InstallSteps; using Umbraco.Web.Install.Models; namespace Umbraco.Web.Install diff --git a/src/Umbraco.Web/Models/LoginStatusModel.cs b/src/Umbraco.Web/Models/LoginStatusModel.cs index 8578055fae..456564c7f5 100644 --- a/src/Umbraco.Web/Models/LoginStatusModel.cs +++ b/src/Umbraco.Web/Models/LoginStatusModel.cs @@ -1,6 +1,4 @@ -using System; -using System.ComponentModel.DataAnnotations; -using System.Web; +using System.ComponentModel.DataAnnotations; using Umbraco.Core; using Umbraco.Web.Composing; using Umbraco.Web.Security; diff --git a/src/Umbraco.Web/Models/ProfileModel.cs b/src/Umbraco.Web/Models/ProfileModel.cs index c7329aa2f5..d62f85bd04 100644 --- a/src/Umbraco.Web/Models/ProfileModel.cs +++ b/src/Umbraco.Web/Models/ProfileModel.cs @@ -2,10 +2,10 @@ using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.DataAnnotations; -using System.Web; using System.Web.Mvc; using Umbraco.Web.Composing; using Umbraco.Web.Security; +using Umbraco.Core; namespace Umbraco.Web.Models { diff --git a/src/Umbraco.Web/Mvc/EnsurePublishedContentRequestAttribute.cs b/src/Umbraco.Web/Mvc/EnsurePublishedContentRequestAttribute.cs index 92625afdde..b046a0d89a 100644 --- a/src/Umbraco.Web/Mvc/EnsurePublishedContentRequestAttribute.cs +++ b/src/Umbraco.Web/Mvc/EnsurePublishedContentRequestAttribute.cs @@ -3,7 +3,6 @@ using System.Web.Mvc; using Umbraco.Web.Routing; using Umbraco.Core; using Umbraco.Core.Models.PublishedContent; -using LightInject; using Umbraco.Web.Composing; namespace Umbraco.Web.Mvc diff --git a/src/Umbraco.Web/Mvc/RenderRouteHandler.cs b/src/Umbraco.Web/Mvc/RenderRouteHandler.cs index 13aef3a01e..e3c797bead 100644 --- a/src/Umbraco.Web/Mvc/RenderRouteHandler.cs +++ b/src/Umbraco.Web/Mvc/RenderRouteHandler.cs @@ -12,7 +12,6 @@ using Umbraco.Web.Models; using Umbraco.Web.Routing; using System.Collections.Generic; using Current = Umbraco.Web.Composing.Current; -using LightInject; using Umbraco.Web.Features; namespace Umbraco.Web.Mvc diff --git a/src/Umbraco.Web/Mvc/UmbracoController.cs b/src/Umbraco.Web/Mvc/UmbracoController.cs index 50bfe166de..b3c62abec0 100644 --- a/src/Umbraco.Web/Mvc/UmbracoController.cs +++ b/src/Umbraco.Web/Mvc/UmbracoController.cs @@ -6,7 +6,7 @@ using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; -using Umbraco.Core.Persistence; +using Umbraco.Core; using Umbraco.Core.Services; using Umbraco.Web.Security; diff --git a/src/Umbraco.Web/Mvc/UmbracoVirtualNodeRouteHandler.cs b/src/Umbraco.Web/Mvc/UmbracoVirtualNodeRouteHandler.cs index ab474fa699..52fcb0a4cb 100644 --- a/src/Umbraco.Web/Mvc/UmbracoVirtualNodeRouteHandler.cs +++ b/src/Umbraco.Web/Mvc/UmbracoVirtualNodeRouteHandler.cs @@ -4,7 +4,7 @@ using System.Web.Routing; using Umbraco.Core.Models.PublishedContent; using Umbraco.Web.Models; using Umbraco.Web.Routing; -using LightInject; +using Umbraco.Core; namespace Umbraco.Web.Mvc { diff --git a/src/Umbraco.Web/Routing/UrlProviderExtensions.cs b/src/Umbraco.Web/Routing/UrlProviderExtensions.cs index ce09bdc645..3ef69da05d 100644 --- a/src/Umbraco.Web/Routing/UrlProviderExtensions.cs +++ b/src/Umbraco.Web/Routing/UrlProviderExtensions.cs @@ -5,7 +5,6 @@ using Umbraco.Core.Models; using Umbraco.Core.Services; using Umbraco.Core; using Umbraco.Core.Logging; -using LightInject; namespace Umbraco.Web.Routing { diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs index 72b08da4ec..31deac6b68 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs @@ -10,6 +10,7 @@ using System.Web.Http; using System.Web.Http.Dispatcher; using System.Web.Mvc; using System.Web.Routing; +using System.Web.Security; using ClientDependency.Core.CompositeFiles.Providers; using ClientDependency.Core.Config; using Examine; @@ -23,28 +24,26 @@ using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Dictionary; using Umbraco.Core.Events; using Umbraco.Core.Logging; -using Umbraco.Core.Macros; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Profiling; using Umbraco.Core.PropertyEditors; using Umbraco.Core.PropertyEditors.ValueConverters; using Umbraco.Core.Runtime; using Umbraco.Core.Services; -using Umbraco.Examine; using Umbraco.Web.Cache; -using Umbraco.Web.Composing.CompositionRoots; +using Umbraco.Web.Composing.Composers; using Umbraco.Web.Dictionary; using Umbraco.Web.Editors; using Umbraco.Web.Features; using Umbraco.Web.HealthCheck; using Umbraco.Web.Install; -using Umbraco.Web.Media; using Umbraco.Web.Models.PublishedContent; using Umbraco.Web.Mvc; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; using Umbraco.Web.Search; using Umbraco.Web.Security; +using Umbraco.Web.Security.Providers; using Umbraco.Web.Services; using Umbraco.Web.SignalR; using Umbraco.Web.Tour; @@ -63,14 +62,17 @@ namespace Umbraco.Web.Runtime { base.Compose(composition); - composition.Container.RegisterFrom(); + composition.Container.ComposeWebMappingProfiles(); //register the install components //NOTE: i tried to not have these registered if we weren't installing or upgrading but post install when the site restarts //it still needs to use the install controller so we can't do that - composition.Container.RegisterFrom(); + composition.Container.ComposeInstaller(); - composition.Container.RegisterFrom(); + // register membership stuff + composition.Container.Register(factory => Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider()); + composition.Container.Register(factory => Roles.Enabled ? Roles.Provider : new MembersRoleProvider(factory.GetInstance())); + composition.Container.Register(); // register accessors for cultures composition.Container.RegisterSingleton(); @@ -180,7 +182,7 @@ namespace Umbraco.Web.Runtime .Append(); composition.Container.RegisterSingleton(); - + composition.Container.RegisterSingleton(); // register *all* checks, except those marked [HideFromTypeFinder] of course diff --git a/src/Umbraco.Web/Scheduling/BackgroundTaskRunner.cs b/src/Umbraco.Web/Scheduling/BackgroundTaskRunner.cs index 630d00c95c..76751b6390 100644 --- a/src/Umbraco.Web/Scheduling/BackgroundTaskRunner.cs +++ b/src/Umbraco.Web/Scheduling/BackgroundTaskRunner.cs @@ -6,7 +6,6 @@ using System.Web.Hosting; using Umbraco.Core; using Umbraco.Core.Events; using Umbraco.Core.Logging; -using LightInject; namespace Umbraco.Web.Scheduling { diff --git a/src/Umbraco.Web/Templates/TemplateRenderer.cs b/src/Umbraco.Web/Templates/TemplateRenderer.cs index f2fe2f9a80..18a4db7118 100644 --- a/src/Umbraco.Web/Templates/TemplateRenderer.cs +++ b/src/Umbraco.Web/Templates/TemplateRenderer.cs @@ -12,7 +12,6 @@ using Umbraco.Web.Routing; using umbraco; using Umbraco.Core.Configuration; using Umbraco.Core.Services; -using LightInject; using Umbraco.Web.Composing; namespace Umbraco.Web.Templates diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 203782e125..3ba65cd568 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -109,8 +109,7 @@ - - + @@ -160,7 +159,7 @@ - + diff --git a/src/Umbraco.Web/WebApi/Filters/FeatureAuthorizeAttribute.cs b/src/Umbraco.Web/WebApi/Filters/FeatureAuthorizeAttribute.cs index 0046770599..df5f1a58c4 100644 --- a/src/Umbraco.Web/WebApi/Filters/FeatureAuthorizeAttribute.cs +++ b/src/Umbraco.Web/WebApi/Filters/FeatureAuthorizeAttribute.cs @@ -1,8 +1,8 @@ using System.Web.Http; using System.Web.Http.Controllers; -using LightInject; using Umbraco.Core.Composing; using Umbraco.Web.Features; +using Umbraco.Core; namespace Umbraco.Web.WebApi.Filters { @@ -12,18 +12,27 @@ namespace Umbraco.Web.WebApi.Filters /// Else returns unauthorized. public sealed class FeatureAuthorizeAttribute : AuthorizeAttribute { + private readonly UmbracoFeatures _features; + + /// + /// Initializes a new instance of the class. + /// + public FeatureAuthorizeAttribute() + { + // attributes have to use Current.Container + _features = Current.Container?.TryGetInstance(); + } + protected override bool IsAuthorized(HttpActionContext actionContext) { // if no features resolver has been set then return true, this will occur in unit // tests and we don't want users to have to set a resolver //just so their unit tests work. - // fixme inject? - var features = Current.Container?.TryGetInstance(); - if (features == null) return true; + if (_features == null) return true; var controllerType = actionContext.ControllerContext.ControllerDescriptor.ControllerType; - return features.IsControllerEnabled(controllerType); + return _features.IsControllerEnabled(controllerType); } } } From 5836cd05cbf7085c5f44a3e3c756cc44d56a5837 Mon Sep 17 00:00:00 2001 From: Stephan Date: Fri, 20 Jul 2018 15:45:01 +0200 Subject: [PATCH 024/469] Abstract container (in progress) --- src/Umbraco.Core/Components/BootLoader.cs | 14 +- src/Umbraco.Core/Components/Composition.cs | 6 +- .../Components/CompositionExtensions.cs | 14 +- .../Composing/CollectionBuilderBase.cs | 2 +- .../Composers/ConfigurationComposer.cs | 17 +- .../Composers/CoreMappingProfilesComposer.cs | 9 +- .../Composers/FileSystemsComposer.cs | 15 +- .../Composers/RepositoriesComposer.cs | 81 +++--- .../Composing/Composers/ServicesComposer.cs | 127 ++++----- src/Umbraco.Core/Composing/Current.cs | 3 +- src/Umbraco.Core/Composing/IContainer.cs | 87 +++++- src/Umbraco.Core/Composing/Lifetime.cs | 28 ++ .../LightInject/LightInjectContainer.cs | 226 +++++++++++++++- .../Composing/LightInjectExtensions.cs | 252 ++++-------------- src/Umbraco.Core/ContainerExtensions.cs | 29 +- src/Umbraco.Core/IRuntime.cs | 6 +- .../Migrations/MigrationBuilder.cs | 5 +- src/Umbraco.Core/Runtime/CoreRuntime.cs | 10 +- .../Runtime/CoreRuntimeComponent.cs | 3 +- src/Umbraco.Core/Umbraco.Core.csproj | 1 + src/Umbraco.Core/UmbracoApplicationBase.cs | 18 +- .../DistributedCache/DistributedCacheTests.cs | 8 +- .../PublishedMediaCacheTests.cs | 2 - .../Components/ComponentTests.cs | 6 +- .../Composing/CollectionBuildersTests.cs | 31 ++- .../Composing/LazyCollectionBuilderTests.cs | 6 + .../Composing/PackageActionCollectionTests.cs | 5 +- src/Umbraco.Tests/CoreThings/UdiTests.cs | 6 +- src/Umbraco.Tests/IO/FileSystemsTests.cs | 10 +- .../Models/Mapping/AutoMapperTests.cs | 2 - src/Umbraco.Tests/Models/VariationTests.cs | 6 +- .../PropertyEditors/ImageCropperTest.cs | 11 +- .../PropertyEditorValueEditorTests.cs | 6 +- .../Published/ConvertersTests.cs | 6 +- .../PublishedContentMoreTests.cs | 5 +- .../PublishedContentTestBase.cs | 3 - .../PublishedContent/PublishedContentTests.cs | 5 +- .../Routing/ContentFinderByIdTests.cs | 2 +- .../ContentFinderByUrlAndTemplateTests.cs | 2 - .../Routing/RenderRouteHandlerTests.cs | 5 +- .../Routing/UmbracoModuleTests.cs | 7 +- .../Runtimes/CoreRuntimeTests.cs | 6 +- .../Scoping/ScopeEventDispatcherTests.cs | 10 +- .../Scoping/ScopedRepositoryTests.cs | 1 + .../Services/ContentServiceTests.cs | 6 - .../Services/Importing/PackageImportTests.cs | 4 +- .../Strings/DefaultShortStringHelperTests.cs | 3 - .../TestHelpers/BaseUsingSqlCeSyntax.cs | 8 +- src/Umbraco.Tests/TestHelpers/BaseWebTest.cs | 7 +- .../TestControllerActivatorBase.cs | 8 - .../TestHelpers/TestObjects-Mocks.cs | 8 +- src/Umbraco.Tests/TestHelpers/TestObjects.cs | 14 +- src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 28 +- .../UmbracoExamine/ExamineBaseTest.cs | 8 +- .../Web/Mvc/UmbracoViewPageTests.cs | 5 - .../Web/TemplateUtilitiesTests.cs | 8 +- ...aseServerRegistrarAndMessengerComponent.cs | 1 - .../Composers/ControllersComposer.cs} | 22 +- .../Composing/Composers/InstallerComposer.cs | 15 +- .../Composers/WebMappingProfilesComposer.cs | 59 ++-- .../LightInject/LightInjectContainer.cs | 32 +++ src/Umbraco.Web/CompositionExtensions.cs | 11 +- .../NuCache/NuCacheComponent.cs | 1 + .../XmlPublishedCache/XmlCacheComponent.cs | 1 - src/Umbraco.Web/Runtime/WebRuntime.cs | 12 +- .../Runtime/WebRuntimeComponent.cs | 23 +- .../SignalR/PreviewHubComponent.cs | 3 +- src/Umbraco.Web/Umbraco.Web.csproj | 3 +- src/Umbraco.Web/UmbracoApplication.cs | 6 + 69 files changed, 757 insertions(+), 643 deletions(-) create mode 100644 src/Umbraco.Core/Composing/Lifetime.cs rename src/Umbraco.Web/{LightInjectExtensions.cs => Composing/Composers/ControllersComposer.cs} (65%) create mode 100644 src/Umbraco.Web/Composing/LightInject/LightInjectContainer.cs diff --git a/src/Umbraco.Core/Components/BootLoader.cs b/src/Umbraco.Core/Components/BootLoader.cs index ee38864933..b80fa93500 100644 --- a/src/Umbraco.Core/Components/BootLoader.cs +++ b/src/Umbraco.Core/Components/BootLoader.cs @@ -3,8 +3,8 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; -using LightInject; using Umbraco.Core.Collections; +using Umbraco.Core.Composing; using Umbraco.Core.Exceptions; using Umbraco.Core.Logging; using Umbraco.Core.Scoping; @@ -15,7 +15,7 @@ namespace Umbraco.Core.Components internal class BootLoader { - private readonly IServiceContainer _container; + private readonly IContainer _container; private readonly ProfilingLogger _proflog; private readonly ILogger _logger; private IUmbracoComponent[] _components; @@ -27,7 +27,7 @@ namespace Umbraco.Core.Components /// Initializes a new instance of the class. /// /// The application container. - public BootLoader(IServiceContainer container) + public BootLoader(IContainer container) { _container = container ?? throw new ArgumentNullException(nameof(container)); _proflog = container.GetInstance(); @@ -247,15 +247,16 @@ namespace Umbraco.Core.Components private static void GatherRequirementsFromRequiredAttribute(Type type, ICollection types, IDictionary> requirements) { // get 'required' attributes - // fixme explain + // these attributes are *not* inherited because we want to "custom-inherit" for interfaces only var requiredAttributes = type - .GetInterfaces().SelectMany(x => x.GetCustomAttributes()) - .Concat(type.GetCustomAttributes()); + .GetInterfaces().SelectMany(x => x.GetCustomAttributes()) // those marking interfaces + .Concat(type.GetCustomAttributes()); // those marking the component foreach (var attr in requiredAttributes) { if (attr.RequiringType == type) continue; // ignore self-requirements (+ exclude in implems, below) + // required by an interface = by any enabled component implementing this that interface if (attr.RequiringType.IsInterface) { var implems = types.Where(x => x != type && attr.RequiringType.IsAssignableFrom(x)).ToList(); @@ -265,6 +266,7 @@ namespace Umbraco.Core.Components requirements[implem].Add(type); } } + // required by a class else { if (types.Contains(attr.RequiringType)) diff --git a/src/Umbraco.Core/Components/Composition.cs b/src/Umbraco.Core/Components/Composition.cs index 671469c73a..91fa519694 100644 --- a/src/Umbraco.Core/Components/Composition.cs +++ b/src/Umbraco.Core/Components/Composition.cs @@ -1,4 +1,4 @@ -using LightInject; +using Umbraco.Core.Composing; namespace Umbraco.Core.Components { @@ -17,7 +17,7 @@ namespace Umbraco.Core.Components /// /// A container. /// The runtime level. - public Composition(IServiceContainer container, RuntimeLevel level) + public Composition(IContainer container, RuntimeLevel level) { Container = container; RuntimeLevel = level; @@ -27,7 +27,7 @@ namespace Umbraco.Core.Components /// Gets the container. /// /// Use with care! - public IServiceContainer Container { get; } + public IContainer Container { get; } /// /// Gets the runtime level. diff --git a/src/Umbraco.Core/Components/CompositionExtensions.cs b/src/Umbraco.Core/Components/CompositionExtensions.cs index 7e94e4dc2b..abc0fa3862 100644 --- a/src/Umbraco.Core/Components/CompositionExtensions.cs +++ b/src/Umbraco.Core/Components/CompositionExtensions.cs @@ -1,6 +1,4 @@ using System; -using System.Runtime.CompilerServices; -using LightInject; using Umbraco.Core.Cache; using Umbraco.Core.Dictionary; using Umbraco.Core.Composing; @@ -97,7 +95,7 @@ namespace Umbraco.Core.Components /// /// The composition. /// A function creating a culture dictionary factory. - public static void SetCultureDictionaryFactory(this Composition composition, Func factory) + public static void SetCultureDictionaryFactory(this Composition composition, Func factory) { composition.Container.RegisterSingleton(factory); } @@ -128,7 +126,7 @@ namespace Umbraco.Core.Components /// /// The composition. /// A function creating a published content model factory. - public static void SetPublishedContentModelFactory(this Composition composition, Func factory) + public static void SetPublishedContentModelFactory(this Composition composition, Func factory) { composition.Container.RegisterSingleton(factory); } @@ -159,7 +157,7 @@ namespace Umbraco.Core.Components /// /// The composition. /// A function creating a server registar. - public static void SetServerRegistrar(this Composition composition, Func factory) + public static void SetServerRegistrar(this Composition composition, Func factory) { composition.Container.RegisterSingleton(factory); } @@ -182,7 +180,7 @@ namespace Umbraco.Core.Components public static void SetServerMessenger(this Composition composition) where T : IServerMessenger { - composition.Container.RegisterSingleton(); + composition.Container.Register(Lifetime.Singleton); } /// @@ -190,7 +188,7 @@ namespace Umbraco.Core.Components /// /// The composition. /// A function creating a server messenger. - public static void SetServerMessenger(this Composition composition, Func factory) + public static void SetServerMessenger(this Composition composition, Func factory) { composition.Container.RegisterSingleton(factory); } @@ -221,7 +219,7 @@ namespace Umbraco.Core.Components /// /// The composition. /// A function creating a short string helper. - public static void SetShortStringHelper(this Composition composition, Func factory) + public static void SetShortStringHelper(this Composition composition, Func factory) { composition.Container.RegisterSingleton(factory); } diff --git a/src/Umbraco.Core/Composing/CollectionBuilderBase.cs b/src/Umbraco.Core/Composing/CollectionBuilderBase.cs index 3fac2d3255..2dbefc860f 100644 --- a/src/Umbraco.Core/Composing/CollectionBuilderBase.cs +++ b/src/Umbraco.Core/Composing/CollectionBuilderBase.cs @@ -140,7 +140,7 @@ namespace Umbraco.Core.Composing var type = typeof (TItem); return _registrations - .Select(x => (TItem) Container.GetInstanceOrThrow(type, x.ServiceName, x.ImplementingType, args)) + .Select(x => (TItem) Container.GetInstance(type, x.ServiceName, args)) .ToArray(); // safe } diff --git a/src/Umbraco.Core/Composing/Composers/ConfigurationComposer.cs b/src/Umbraco.Core/Composing/Composers/ConfigurationComposer.cs index e2ba477045..4e8f2ec65c 100644 --- a/src/Umbraco.Core/Composing/Composers/ConfigurationComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/ConfigurationComposer.cs @@ -1,5 +1,4 @@ -using LightInject; -using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; namespace Umbraco.Core.Composing.Composers @@ -9,17 +8,17 @@ namespace Umbraco.Core.Composing.Composers /// public static class ConfigurationComposer { - public static IServiceRegistry ComposeConfiguration(this IServiceRegistry registry) + public static IContainer ComposeConfiguration(this IContainer container) { - registry.Register(factory => UmbracoConfig.For.UmbracoSettings()); - registry.Register(factory => factory.GetInstance().Content); - registry.Register(factory => factory.GetInstance().Templates); - registry.Register(factory => factory.GetInstance().RequestHandler); - registry.Register(factory => UmbracoConfig.For.GlobalSettings()); + container.Register(factory => UmbracoConfig.For.UmbracoSettings()); + container.Register(factory => factory.GetInstance().Content); + container.Register(factory => factory.GetInstance().Templates); + container.Register(factory => factory.GetInstance().RequestHandler); + container.Register(factory => UmbracoConfig.For.GlobalSettings()); // fixme - other sections we need to add? - return registry; + return container; } } } diff --git a/src/Umbraco.Core/Composing/Composers/CoreMappingProfilesComposer.cs b/src/Umbraco.Core/Composing/Composers/CoreMappingProfilesComposer.cs index ce9f507b9f..a1fc36a8c4 100644 --- a/src/Umbraco.Core/Composing/Composers/CoreMappingProfilesComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/CoreMappingProfilesComposer.cs @@ -1,15 +1,14 @@ -using LightInject; -using Umbraco.Core.Models.Identity; +using Umbraco.Core.Models.Identity; namespace Umbraco.Core.Composing.Composers { public static class CoreMappingProfilesComposer { - public static IServiceRegistry ComposeCoreMappingProfiles(this IServiceRegistry registry) + public static IContainer ComposeCoreMappingProfiles(this IContainer container) { - registry.Register(); - return registry; + container.Register(); + return container; } } } diff --git a/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs b/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs index c7ed93680b..565db9c623 100644 --- a/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs @@ -1,5 +1,4 @@ -using LightInject; -using Umbraco.Core.Configuration.UmbracoSettings; +using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; using Umbraco.Core.Logging; @@ -7,22 +6,22 @@ namespace Umbraco.Core.Composing.Composers { public static class FileSystemsComposer { - public static IServiceRegistry ComposeFileSystems(this IServiceRegistry registry) + public static IContainer ComposeFileSystems(this IContainer container) { // register FileSystems, which manages all filesystems - registry.RegisterSingleton(); + container.RegisterSingleton(); // register IFileSystems, which gives access too all filesystems - registry.RegisterSingleton(factory => factory.GetInstance()); + container.RegisterSingleton(factory => factory.GetInstance()); // register MediaFileSystem, which can be injected directly - registry.RegisterSingleton(factory => factory.GetInstance().MediaFileSystem); + container.RegisterSingleton(factory => factory.GetInstance().MediaFileSystem); // register MediaFileSystem, so that FileSystems can create it - registry.Register((f, wrappedFileSystem) + container.Register((f, wrappedFileSystem) => new MediaFileSystem(wrappedFileSystem, f.GetInstance(), f.GetInstance(), f.GetInstance())); - return registry; + return container; } } } diff --git a/src/Umbraco.Core/Composing/Composers/RepositoriesComposer.cs b/src/Umbraco.Core/Composing/Composers/RepositoriesComposer.cs index 79b2b9c223..25399af5c7 100644 --- a/src/Umbraco.Core/Composing/Composers/RepositoriesComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/RepositoriesComposer.cs @@ -1,5 +1,4 @@ -using LightInject; -using Umbraco.Core.Persistence.Repositories; +using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; namespace Umbraco.Core.Composing.Composers @@ -9,48 +8,48 @@ namespace Umbraco.Core.Composing.Composers /// public static class RepositoriesComposer { - public static IServiceRegistry ComposeRepositories(this IServiceRegistry registry) + public static IContainer ComposeRepositories(this IContainer container) { // repositories - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); - return registry; + return container; } } } diff --git a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs index c774912f2e..fc898dd3b6 100644 --- a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs @@ -1,7 +1,6 @@ using System; using System.IO; using System.Linq; -using LightInject; using Umbraco.Core.Cache; using Umbraco.Core.Events; using Umbraco.Core.IO; @@ -13,83 +12,85 @@ namespace Umbraco.Core.Composing.Composers { public static class ServicesComposer { - public static IServiceRegistry ComposeServices(this IServiceRegistry registry) + public static IContainer ComposeServices(this IContainer container) { // register a transient messages factory, which will be replaced by the web // boot manager when running in a web context - registry.RegisterSingleton(); + container.RegisterSingleton(); // register the service context - registry.RegisterSingleton(); + container.RegisterSingleton(); // register the special idk map - registry.RegisterSingleton(); + container.RegisterSingleton(); // register the services - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.Register(factory => - { - var mainLangFolder = new DirectoryInfo(IOHelper.MapPath(SystemDirectories.Umbraco + "/config/lang/")); - var appPlugins = new DirectoryInfo(IOHelper.MapPath(SystemDirectories.AppPlugins)); - var configLangFolder = new DirectoryInfo(IOHelper.MapPath(SystemDirectories.Config + "/lang/")); - - var pluginLangFolders = appPlugins.Exists == false - ? Enumerable.Empty() - : appPlugins.GetDirectories() - .SelectMany(x => x.GetDirectories("Lang")) - .SelectMany(x => x.GetFiles("*.xml", SearchOption.TopDirectoryOnly)) - .Where(x => Path.GetFileNameWithoutExtension(x.FullName).Length == 5) - .Select(x => new LocalizedTextServiceSupplementaryFileSource(x, false)); - - //user defined langs that overwrite the default, these should not be used by plugin creators - var userLangFolders = configLangFolder.Exists == false - ? Enumerable.Empty() - : configLangFolder - .GetFiles("*.user.xml", SearchOption.TopDirectoryOnly) - .Where(x => Path.GetFileNameWithoutExtension(x.FullName).Length == 10) - .Select(x => new LocalizedTextServiceSupplementaryFileSource(x, true)); - - return new LocalizedTextServiceFileSources( - factory.GetInstance(), - factory.GetInstance().RuntimeCache, - mainLangFolder, - pluginLangFolders.Concat(userLangFolders)); - }); - registry.RegisterSingleton(factory => new LocalizedTextService( + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.Register(SourcesFactory); + container.RegisterSingleton(factory => new LocalizedTextService( factory.GetInstance>(), factory.GetInstance())); //TODO: These are replaced in the web project - we need to declare them so that // something is wired up, just not sure this is very nice but will work for now. - registry.RegisterSingleton(); - registry.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); - return registry; + return container; + } + + private static LocalizedTextServiceFileSources SourcesFactory(IContainer container) + { + var mainLangFolder = new DirectoryInfo(IOHelper.MapPath(SystemDirectories.Umbraco + "/config/lang/")); + var appPlugins = new DirectoryInfo(IOHelper.MapPath(SystemDirectories.AppPlugins)); + var configLangFolder = new DirectoryInfo(IOHelper.MapPath(SystemDirectories.Config + "/lang/")); + + var pluginLangFolders = appPlugins.Exists == false + ? Enumerable.Empty() + : appPlugins.GetDirectories() + .SelectMany(x => x.GetDirectories("Lang")) + .SelectMany(x => x.GetFiles("*.xml", SearchOption.TopDirectoryOnly)) + .Where(x => Path.GetFileNameWithoutExtension(x.FullName).Length == 5) + .Select(x => new LocalizedTextServiceSupplementaryFileSource(x, false)); + + //user defined langs that overwrite the default, these should not be used by plugin creators + var userLangFolders = configLangFolder.Exists == false + ? Enumerable.Empty() + : configLangFolder + .GetFiles("*.user.xml", SearchOption.TopDirectoryOnly) + .Where(x => Path.GetFileNameWithoutExtension(x.FullName).Length == 10) + .Select(x => new LocalizedTextServiceSupplementaryFileSource(x, true)); + + return new LocalizedTextServiceFileSources( + container.GetInstance(), + container.GetInstance().RuntimeCache, + mainLangFolder, + pluginLangFolders.Concat(userLangFolders)); } } } diff --git a/src/Umbraco.Core/Composing/Current.cs b/src/Umbraco.Core/Composing/Current.cs index fcff2c4b9e..d0025c0c8b 100644 --- a/src/Umbraco.Core/Composing/Current.cs +++ b/src/Umbraco.Core/Composing/Current.cs @@ -1,5 +1,4 @@ using System; -using LightInject; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; using Umbraco.Core.Dictionary; @@ -20,7 +19,7 @@ namespace Umbraco.Core.Composing /// Provides a static service locator for most singletons. /// /// - /// This class is initialized with the container via LightInjectExtensions.ConfigureUmbracoCore, + /// This class is initialized with the container in UmbracoApplicationBase, /// right after the container is created in UmbracoApplicationBase.HandleApplicationStart. /// Obviously, this is a service locator, which some may consider an anti-pattern. And yet, /// practically, it works. diff --git a/src/Umbraco.Core/Composing/IContainer.cs b/src/Umbraco.Core/Composing/IContainer.cs index 7183a76af2..ba611063e2 100644 --- a/src/Umbraco.Core/Composing/IContainer.cs +++ b/src/Umbraco.Core/Composing/IContainer.cs @@ -1,11 +1,12 @@ using System; +using System.Collections.Generic; namespace Umbraco.Core.Composing { /// /// Defines a container for Umbraco. /// - public interface IContainer + public interface IContainer : IDisposable { /// /// Gets the concrete container. @@ -22,6 +23,15 @@ namespace Umbraco.Core.Composing /// Throws an exception if the container failed to get an instance of the specified type. object GetInstance(Type type); + /// + /// Gets a named instance. + /// + /// The type of the instance. + /// The name of the instance. + /// An instance of the specified type. + /// Throws an exception if the container failed to get an instance of the specified type. + object GetInstance(Type type, string name); + /// /// Gets an instance with arguments. /// @@ -44,16 +54,62 @@ namespace Umbraco.Core.Composing /// to get an instance of the specified type, but failed to do so. object TryGetInstance(Type type); + /// + /// Gets all instances of a service. + /// + /// The type of the service. + IEnumerable GetAllInstances(Type serviceType); + + /// + /// Gets all instances of a service. + /// + /// The type of the service. + IEnumerable GetAllInstances(); + #endregion #region Registry - // fixme register direct type? - // fixme register an instance? - void RegisterSingleton(Func factory); - void Register(Func factory); + /// + /// Registers a service as its own implementation. + /// + void Register(Type serviceType, Lifetime lifetime = Lifetime.Transient); + + /// + /// Registers a service with an implementation type. + /// + void Register(Type serviceType, Type implementingType, Lifetime lifetime = Lifetime.Transient); + + /// + /// Registers a service with a named implementation type. + /// + void Register(Type serviceType, Type implementingType, string name, Lifetime lifetime = Lifetime.Transient); + + /// + /// Registers a service with an implementation factory. + /// + void Register(Func factory, Lifetime lifetime = Lifetime.Transient); + + /// + /// Registers a service with an implementation factory accepting an argument. + /// void Register(Func factory); + /// + /// Registers a service with an implementing instance. + /// + void RegisterInstance(Type serviceType, object instance); + + /// + /// Registers a base type for auto-registration. + /// + void RegisterAuto(Type serviceBaseType); + + /// + /// Registers a service with an ordered set of implementation types. + /// + void RegisterOrdered(Type serviceType, Type[] implementingTypes, Lifetime lifetime = Lifetime.Transient); + /// /// Registers and instanciates a collection builder. /// @@ -62,5 +118,26 @@ namespace Umbraco.Core.Composing T RegisterCollectionBuilder(); #endregion + + #region Control + + /// + /// Begins a scope. + /// + /// + /// When the scope is disposed, scoped instances that have been created during the scope are disposed. + /// Scopes can be nested. Each instance is disposed individually. + /// + IDisposable BeginScope(); + + // fixme - document all these + + void ConfigureForUmbraco(); + + void ConfigureForWeb(); + + void EnablePerWebRequestScope(); + + #endregion } } diff --git a/src/Umbraco.Core/Composing/Lifetime.cs b/src/Umbraco.Core/Composing/Lifetime.cs new file mode 100644 index 0000000000..a7ae1d4179 --- /dev/null +++ b/src/Umbraco.Core/Composing/Lifetime.cs @@ -0,0 +1,28 @@ +namespace Umbraco.Core.Composing +{ + /// + /// Specifies the lifetime of a registered instance. + /// + public enum Lifetime + { + /// + /// Always get a new instance. + /// + Transient, + + /// + /// One unique instance per request. + /// + Request, + + /// + /// One unique instance per container scope. + /// + Scope, + + /// + /// One unique instance per container. + /// + Singleton + } +} diff --git a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs index 72ebda62ee..0cc7700888 100644 --- a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs +++ b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Reflection; using LightInject; namespace Umbraco.Core.Composing.LightInject @@ -8,45 +10,241 @@ namespace Umbraco.Core.Composing.LightInject /// public class LightInjectContainer : IContainer { - private readonly IServiceContainer _container; - /// /// Initializes a new instance of the with a LightInject container. /// - public LightInjectContainer(IServiceContainer container) + public LightInjectContainer(ServiceContainer container) { - _container = container; + Container = container; } + /// + /// Gets the LightInject container. + /// + protected ServiceContainer Container { get; } + /// - public object ConcreteContainer => _container; + public object ConcreteContainer => Container; + + /// + public void Dispose() + => Container.Dispose(); + + #region Factory /// public object GetInstance(Type type) - => _container.GetInstance(type); + => Container.GetInstance(type); + + /// + public object GetInstance(Type type, string name) + => Container.GetInstance(type, name); /// public object GetInstance(Type type, object[] args) - => _container.GetInstance(type, args); + => Container.GetInstance(type, args); /// public object TryGetInstance(Type type) - => _container.TryGetInstance(type); + => Container.TryGetInstance(type); /// - public void RegisterSingleton(Func factory) - => _container.RegisterSingleton(f => factory(this)); + public IEnumerable GetAllInstances() + => Container.GetAllInstances(); /// - public void Register(Func factory) - => _container.Register(f => factory(this)); + public IEnumerable GetAllInstances(Type type) + => Container.GetAllInstances(type); + + #endregion + + #region Registry + + /// + public void Register(Type serviceType, Lifetime lifetime = Lifetime.Transient) + { + switch (lifetime) + { + case Lifetime.Transient: + case Lifetime.Request: + case Lifetime.Scope: + Container.Register(serviceType, GetLifetime(lifetime)); + break; + case Lifetime.Singleton: + Container.RegisterSingleton(serviceType); + break; + default: + throw new NotSupportedException($"Lifetime {lifetime} is not supported."); + } + } + + /// + public void Register(Type serviceType, Type implementingType, Lifetime lifetime = Lifetime.Transient) + { + switch (lifetime) + { + case Lifetime.Transient: + case Lifetime.Request: + case Lifetime.Scope: + Container.Register(serviceType, implementingType, GetLifetime(lifetime)); + break; + case Lifetime.Singleton: + Container.RegisterSingleton(serviceType, implementingType); + break; + default: + throw new NotSupportedException($"Lifetime {lifetime} is not supported."); + } + } + + /// + public void Register(Type serviceType, Type implementingType, string name, Lifetime lifetime = Lifetime.Transient) + { + switch (lifetime) + { + case Lifetime.Transient: + case Lifetime.Request: + case Lifetime.Scope: + Container.Register(serviceType, implementingType, name, GetLifetime(lifetime)); + break; + case Lifetime.Singleton: + Container.RegisterSingleton(serviceType, implementingType, name); + break; + default: + throw new NotSupportedException($"Lifetime {lifetime} is not supported."); + } + } + + /// + public void Register(Func factory, Lifetime lifetime = Lifetime.Transient) + { + switch (lifetime) + { + case Lifetime.Transient: + case Lifetime.Request: + case Lifetime.Scope: + Container.Register(f => factory(this), GetLifetime(lifetime)); + break; + case Lifetime.Singleton: + Container.RegisterSingleton(f => factory(this)); + break; + default: + throw new NotSupportedException($"Lifetime {lifetime} is not supported."); + } + } /// public void Register(Func factory) - => _container.Register((f, x) => factory(this, x)); + => Container.Register((f, x) => factory(this, x)); + + private ILifetime GetLifetime(Lifetime lifetime) + { + switch (lifetime) + { + case Lifetime.Transient: + return null; + case Lifetime.Request: + return new PerRequestLifeTime(); + case Lifetime.Scope: + return new PerScopeLifetime(); + case Lifetime.Singleton: + return new PerContainerLifetime(); + default: + throw new NotSupportedException($"Lifetime {lifetime} is not supported."); + } + } + + /// + public void RegisterInstance(Type serviceType, object instance) + => Container.RegisterInstance(serviceType, instance); + + /// + public void RegisterAuto(Type serviceBaseType) + { + Container.RegisterFallback((serviceType, serviceName) => + { + // https://github.com/seesharper/LightInject/issues/173 + if (serviceBaseType.IsAssignableFromGtd(serviceType)) + Container.Register(serviceType); + return false; + }, null); + } + + /// + public void RegisterOrdered(Type serviceType, Type[] implementingTypes, Lifetime lifetime = Lifetime.Transient) + => Container.RegisterOrdered(serviceType, implementingTypes, _ => GetLifetime(lifetime)); /// public T RegisterCollectionBuilder() - => _container.RegisterCollectionBuilder(); + => Container.RegisterCollectionBuilder(); + + #endregion + + #region Control + + /// + public IDisposable BeginScope() + => Container.BeginScope(); + + /// + public void ConfigureForUmbraco() + { + // supports annotated constructor injections + // eg to specify the service name on some services + Container.EnableAnnotatedConstructorInjection(); + + // from the docs: "LightInject considers all read/write properties a dependency, but implements + // a loose strategy around property dependencies, meaning that it will NOT throw an exception + // in the case of an unresolved property dependency." + // + // in Umbraco we do NOT want to do property injection by default, so we have to disable it. + // from the docs, the following line will cause the container to "now only try to inject + // dependencies for properties that is annotated with the InjectAttribute." + // + // could not find it documented, but tests & code review shows that LightInject considers a + // property to be "injectable" when its setter exists and is not static, nor private, nor + // it is an index property. which means that eg protected or internal setters are OK. + Container.EnableAnnotatedPropertyInjection(); + + // ensure that we do *not* scan assemblies + // we explicitely RegisterFrom our own composition roots and don't want them scanned + Container.AssemblyScanner = new AssemblyScanner(/*container.AssemblyScanner*/); + + // see notes in MixedLightInjectScopeManagerProvider + Container.ScopeManagerProvider = new MixedLightInjectScopeManagerProvider(); + } + + private class AssemblyScanner : IAssemblyScanner + { + //private readonly IAssemblyScanner _scanner; + + //public AssemblyScanner(IAssemblyScanner scanner) + //{ + // _scanner = scanner; + //} + + public void Scan(Assembly assembly, IServiceRegistry serviceRegistry, Func lifetime, Func shouldRegister, Func serviceNameProvider) + { + // nothing - we *could* scan non-Umbraco assemblies, though + } + + public void Scan(Assembly assembly, IServiceRegistry serviceRegistry) + { + // nothing - we *could* scan non-Umbraco assemblies, though + } + } + + /// + public virtual void ConfigureForWeb() + { } + + /// + public void EnablePerWebRequestScope() + { + if (!(Container.ScopeManagerProvider is MixedLightInjectScopeManagerProvider smp)) + throw new Exception("Container.ScopeManagerProvider is not MixedLightInjectScopeManagerProvider."); + smp.EnablePerWebRequestScope(); + } + + #endregion } } diff --git a/src/Umbraco.Core/Composing/LightInjectExtensions.cs b/src/Umbraco.Core/Composing/LightInjectExtensions.cs index a64d3aff30..446b2850f7 100644 --- a/src/Umbraco.Core/Composing/LightInjectExtensions.cs +++ b/src/Umbraco.Core/Composing/LightInjectExtensions.cs @@ -12,107 +12,10 @@ namespace Umbraco.Core.Composing /// public static class LightInjectExtensions { - /// - /// Configure the container for Umbraco Core usage and assign to Current. - /// - /// The container. - /// The container is now the unique application container and is now accessible via Current.Container. - internal static void ConfigureUmbracoCore(this ServiceContainer container) + // fixme temp + internal static ServiceContainer AsLightInject(this IContainer container) { - // supports annotated constructor injections - // eg to specify the service name on some services - container.EnableAnnotatedConstructorInjection(); - - // from the docs: "LightInject considers all read/write properties a dependency, but implements - // a loose strategy around property dependencies, meaning that it will NOT throw an exception - // in the case of an unresolved property dependency." - // - // in Umbraco we do NOT want to do property injection by default, so we have to disable it. - // from the docs, the following line will cause the container to "now only try to inject - // dependencies for properties that is annotated with the InjectAttribute." - // - // could not find it documented, but tests & code review shows that LightInject considers a - // property to be "injectable" when its setter exists and is not static, nor private, nor - // it is an index property. which means that eg protected or internal setters are OK. - container.EnableAnnotatedPropertyInjection(); - - // ensure that we do *not* scan assemblies - // we explicitely RegisterFrom our own composition roots and don't want them scanned - container.AssemblyScanner = new AssemblyScanner(/*container.AssemblyScanner*/); - - // see notes in MixedLightInjectScopeManagerProvider - container.ScopeManagerProvider = new MixedLightInjectScopeManagerProvider(); - - // self-register - // fixme - WHERE is this used, and should it be a generic container, not LightInject's? - container.Register(_ => container); - - // configure the current container - Current.Container = new LightInject.LightInjectContainer(container); - } - - private class AssemblyScanner : IAssemblyScanner - { - //private readonly IAssemblyScanner _scanner; - - //public AssemblyScanner(IAssemblyScanner scanner) - //{ - // _scanner = scanner; - //} - - public void Scan(Assembly assembly, IServiceRegistry serviceRegistry, Func lifetime, Func shouldRegister, Func serviceNameProvider) - { - // nothing - we *could* scan non-Umbraco assemblies, though - } - - public void Scan(Assembly assembly, IServiceRegistry serviceRegistry) - { - // nothing - we *could* scan non-Umbraco assemblies, though - } - } - - /// - /// Registers a service implementation with a specified lifetime. - /// - /// The type of the service. - /// The type of the implementation. - /// The type of the lifetime. - /// The container. - public static void Register(this IServiceContainer container) - where TImplementation : TService - where TLifetime : ILifetime, new() - { - container.Register(new TLifetime()); - } - - /// - /// Registers a service implementation with a specified lifetime. - /// - /// The type of the service. - /// The type of the lifetime. - /// The container. - /// A factory. - public static void Register(this IServiceContainer container, Func factory) - where TLifetime : ILifetime, new() - { - container.Register(factory, new TLifetime()); - } - - /// - /// Registers several service implementations with a specified lifetime. - /// - /// The type of the service. - /// The type of the lifetime. - /// The container. - /// The types of the implementations. - public static void RegisterMany(this IServiceContainer container, IEnumerable implementations) - where TLifeTime : ILifetime, new() - { - foreach (var implementation in implementations) - { - // if "typeof (TService)" is there then "implementation.FullName" MUST be there too - container.Register(typeof(TService), implementation, implementation.FullName, new TLifeTime()); - } + return (ServiceContainer) container.ConcreteContainer; } /// @@ -139,17 +42,39 @@ namespace Umbraco.Core.Composing public static void RegisterSingleton(this IServiceRegistry container) where TImplementation : TService { - var registration = container.GetAvailableService(); + container.RegisterSingleton(typeof(TService), typeof(TImplementation)); + } + + // fixme + public static void RegisterSingleton(this IServiceRegistry container, Type serviceType, Type implementingType) + { + var registration = container.GetAvailableService(serviceType); if (registration == null) { - container.Register(new PerContainerLifetime()); + container.Register(serviceType, implementingType, new PerContainerLifetime()); } else { if (registration.Lifetime is PerContainerLifetime == false) throw new InvalidOperationException("Existing registration lifetime is not PerContainer."); - UpdateRegistration(registration, typeof(TImplementation), null); + UpdateRegistration(registration, implementingType, null); + } + } + + public static void RegisterSingleton(this IServiceRegistry container, Type serviceType, Type implementingType, string name) + { + var registration = container.GetAvailableServices(serviceType).FirstOrDefault(x => x.ServiceName == name); + + if (registration == null) + { + container.Register(serviceType, implementingType, name, new PerContainerLifetime()); + } + else + { + if (registration.Lifetime is PerContainerLifetime == false) + throw new InvalidOperationException("Existing registration lifetime is not PerContainer."); + UpdateRegistration(registration, implementingType, null); } } @@ -158,18 +83,22 @@ namespace Umbraco.Core.Composing /// public static void RegisterSingleton(this IServiceRegistry container) { - var registration = container.GetAvailableService(); + container.RegisterSingleton(typeof(TImplementation)); + } + + public static void RegisterSingleton(this IServiceRegistry container, Type serviceType) + { + var registration = container.GetAvailableService(serviceType); if (registration == null) { - container.Register(new PerContainerLifetime()); + container.Register(serviceType, new PerContainerLifetime()); } else { if (registration.Lifetime is PerContainerLifetime == false) throw new InvalidOperationException("Existing registration lifetime is not PerContainer."); - UpdateRegistration(registration, typeof(TImplementation), null); + UpdateRegistration(registration, serviceType, null); } - } /// @@ -240,10 +169,10 @@ namespace Umbraco.Core.Composing /// The container. /// The service registrations for the service type. public static IEnumerable GetAvailableServices(this IServiceRegistry container) - { - var typeofTService = typeof(TService); - return container.AvailableServices.Where(x => x.ServiceType == typeofTService); - } + => container.GetAvailableServices(typeof(TService)); + + public static IEnumerable GetAvailableServices(this IServiceRegistry container, Type serviceType) + => container.AvailableServices.Where(x => x.ServiceType == serviceType); /// /// Gets the unique available service registration for a service type. @@ -258,6 +187,12 @@ namespace Umbraco.Core.Composing return container.AvailableServices.SingleOrDefault(x => x.ServiceType == typeofTService); } + // fixme + public static ServiceRegistration GetAvailableService(this IServiceRegistry container, Type serviceType) + { + return container.AvailableServices.SingleOrDefault(x => x.ServiceType == serviceType); + } + /// /// Gets the unique available service registration for a service type and a name. /// @@ -272,101 +207,6 @@ namespace Umbraco.Core.Composing return container.AvailableServices.SingleOrDefault(x => x.ServiceType == typeofTService && x.ServiceName == name); } - /// - /// Gets an instance of a TService or throws a meaningful exception. - /// - /// The service type. - /// The container. - /// The instance. - public static TService GetInstanceOrThrow(this IServiceFactory factory) - { - if (factory == null) - throw new ArgumentNullException(nameof(factory)); - - try - { - return factory.GetInstance(); - } - catch (Exception e) - { - LightInjectException.TryThrow(e); - throw; - } - } - - /// - /// Gets an instance of a TService or throws a meaningful exception. - /// - /// The container. - /// The type of the service. - /// The name of the service. - /// The implementing type. - /// Arguments. - /// The instance. - internal static object GetInstanceOrThrow(this IServiceFactory factory, Type tService, string serviceName, Type implementingType, object[] args) - { - if (factory == null) - throw new ArgumentNullException(nameof(factory)); - - // fixme temp - STOP doing this, it confuses LightInject and then we get ugly exception traces - // we HAVE to let LightInject throw - and catch at THE OUTERMOST if InvalidOperationException in LightInject.Anything! - - return factory.GetInstance(tService, serviceName, args); - //try - //{ - // return factory.GetInstance(tService, serviceName, args); - //} - //catch (Exception e) - //{ - // LightInjectException.TryThrow(e, implementingType); - // throw; - //} - } - - /// - /// Registers a base type for auto-registration. - /// - /// The base type. - /// The container. - /// - /// Any type that inherits/implements the base type will be auto-registered on-demand. - /// This methods works with actual types. Use the other overload for eg generic definitions. - /// - public static void RegisterAuto(this IServiceContainer container) - { - container.RegisterFallback((serviceType, serviceName) => - { - //Current.Logger.Debug(typeof(LightInjectExtensions), $"Fallback for type {serviceType.FullName}."); - // https://github.com/seesharper/LightInject/issues/173 - - if (typeof(T).IsAssignableFrom(serviceType)) - container.Register(serviceType); - return false; - }, null); - } - - /// - /// Registers a base type for auto-registration. - /// - /// The container. - /// The base type. - /// - /// Any type that inherits/implements the base type will be auto-registered on-demand. - /// This methods works with actual types, as well as generic definitions eg typeof(MyBase{}). - /// - public static void RegisterAuto(this IServiceContainer container, Type type) - { - container.RegisterFallback((serviceType, serviceName) => - { - //Current.Logger.Debug(typeof(LightInjectExtensions), $"Fallback for type {serviceType.FullName}."); - // https://github.com/seesharper/LightInject/issues/173 - - if (type.IsAssignableFromGtd(serviceType)) - container.Register(serviceType); - return false; - }, null); - } - /// /// Registers and instanciates a collection builder. /// diff --git a/src/Umbraco.Core/ContainerExtensions.cs b/src/Umbraco.Core/ContainerExtensions.cs index 351a3c26f1..ddaab485c1 100644 --- a/src/Umbraco.Core/ContainerExtensions.cs +++ b/src/Umbraco.Core/ContainerExtensions.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Composing; +using System; +using Umbraco.Core.Composing; namespace Umbraco.Core { @@ -41,5 +42,31 @@ namespace Umbraco.Core /// to get an instance of the specified type, but failed to do so. public static T TryGetInstance(this IContainer container) => (T) container.TryGetInstance(typeof(T)); + + // fixme - document all these + + public static void Register(this IContainer container, Lifetime lifetime = Lifetime.Transient) + => container.Register(typeof(TService), typeof(TImplementing), lifetime); + + public static void Register(this IContainer container, string name, Lifetime lifetime = Lifetime.Transient) + => container.Register(typeof(TService), typeof(TImplementing), name, lifetime); + + public static void Register(this IContainer container, Lifetime lifetime = Lifetime.Transient) + => container.Register(typeof(TService), lifetime); + + public static void RegisterSingleton(this IContainer container) + => container.Register(typeof(TService), Lifetime.Singleton); + + public static void RegisterSingleton(this IContainer container) + => container.Register(typeof(TService), typeof(TImplementing), Lifetime.Singleton); + + public static void RegisterSingleton(this IContainer container, Func factory) + => container.Register(factory, Lifetime.Singleton); + + public static void RegisterInstance(this IContainer container, TService instance) + => container.RegisterInstance(typeof(TService), instance); + + public static void RegisterAuto(this IContainer container) + => container.RegisterAuto(typeof(TServiceBase)); } } diff --git a/src/Umbraco.Core/IRuntime.cs b/src/Umbraco.Core/IRuntime.cs index 37b265ad77..f11bafbf2f 100644 --- a/src/Umbraco.Core/IRuntime.cs +++ b/src/Umbraco.Core/IRuntime.cs @@ -1,4 +1,4 @@ -using LightInject; +using Umbraco.Core.Composing; namespace Umbraco.Core { @@ -10,8 +10,8 @@ namespace Umbraco.Core /// /// Boots the runtime. /// - /// The application service container. - void Boot(ServiceContainer container); + /// The application container. + void Boot(IContainer container); /// /// Terminates the runtime. diff --git a/src/Umbraco.Core/Migrations/MigrationBuilder.cs b/src/Umbraco.Core/Migrations/MigrationBuilder.cs index 3d8c88c771..fb01afc35a 100644 --- a/src/Umbraco.Core/Migrations/MigrationBuilder.cs +++ b/src/Umbraco.Core/Migrations/MigrationBuilder.cs @@ -1,13 +1,14 @@ using System; using LightInject; +using Umbraco.Core.Composing; namespace Umbraco.Core.Migrations { public class MigrationBuilder : IMigrationBuilder { - private readonly IServiceContainer _container; + private readonly IContainer _container; - public MigrationBuilder(IServiceContainer container) + public MigrationBuilder(IContainer container) { _container = container; diff --git a/src/Umbraco.Core/Runtime/CoreRuntime.cs b/src/Umbraco.Core/Runtime/CoreRuntime.cs index 94004c6ae3..7ab87029a5 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntime.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntime.cs @@ -1,9 +1,7 @@ using System; using System.Collections.Generic; -using System.Configuration; using System.Threading; using System.Web; -using LightInject; using Umbraco.Core.Cache; using Umbraco.Core.Components; using Umbraco.Core.Composing; @@ -42,7 +40,7 @@ namespace Umbraco.Core.Runtime } /// - public virtual void Boot(ServiceContainer container) + public virtual void Boot(IContainer container) { // some components may want to initialize with the UmbracoApplicationBase // well, they should not - we should not do this @@ -114,7 +112,7 @@ namespace Umbraco.Core.Runtime //sa.Scope?.Dispose(); } - private void AquireMainDom(IServiceFactory container) + private void AquireMainDom(IContainer container) { using (var timer = ProfilingLogger.DebugDuration("Acquiring MainDom.", "Aquired.")) { @@ -132,7 +130,7 @@ namespace Umbraco.Core.Runtime } // internal for tests - internal void DetermineRuntimeLevel(IServiceFactory container) + internal void DetermineRuntimeLevel(IContainer container) { using (var timer = ProfilingLogger.DebugDuration("Determining runtime level.", "Determined.")) { @@ -185,7 +183,7 @@ namespace Umbraco.Core.Runtime /// /// Composes the runtime. /// - public virtual void Compose(ServiceContainer container) + public virtual void Compose(IContainer container) { // compose the very essential things that are needed to bootstrap, before anything else, // and only these things - the rest should be composed in runtime components diff --git a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs index 4d1fd28462..6320401681 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Configuration; -using System.IO; using AutoMapper; using LightInject; using Umbraco.Core.Cache; @@ -94,7 +93,7 @@ namespace Umbraco.Core.Runtime composition.Container.RegisterCollectionBuilder() .Append(factory => factory.GetInstance().GetTypes()); - composition.Container.Register(new PerContainerLifetime()); + composition.Container.RegisterSingleton(); composition.Container.RegisterSingleton(factory => new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(factory.GetInstance()))); diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 6084580ff0..efea4bdd22 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -167,6 +167,7 @@ + diff --git a/src/Umbraco.Core/UmbracoApplicationBase.cs b/src/Umbraco.Core/UmbracoApplicationBase.cs index 9930f43ca4..98ddbc883f 100644 --- a/src/Umbraco.Core/UmbracoApplicationBase.cs +++ b/src/Umbraco.Core/UmbracoApplicationBase.cs @@ -4,7 +4,6 @@ using System.Threading; using System.Web; using System.Web.Hosting; using log4net; -using LightInject; using Umbraco.Core.Composing; using Umbraco.Core.Logging; @@ -30,6 +29,16 @@ namespace Umbraco.Core return Logger.CreateWithDefaultLog4NetConfiguration(); } + /// + /// Gets the application container. + /// + protected virtual IContainer GetContainer() + { + // note: the actual, web UmbracoApplication is overriding this + // with a web-supporting container + return new Composing.LightInject.LightInjectContainer(new LightInject.ServiceContainer()); + } + // events - in the order they trigger // were part of the BootManager architecture, would trigger only for the initial @@ -60,8 +69,9 @@ namespace Umbraco.Core // create the container for the application, and configure. // the boot manager is responsible for registrations - var container = new ServiceContainer(); - container.ConfigureUmbracoCore(); // also sets Current.Container + var container = GetContainer(); + container.ConfigureForUmbraco(); + Current.Container = container; // register the essential stuff, // ie the global application logger @@ -163,7 +173,7 @@ namespace Umbraco.Core // dispose the container and everything // but first, capture the looger! var logger = Current.Logger; - Current.Reset(); + Current.Reset(); if (SystemUtilities.GetCurrentTrustLevel() != AspNetHostingPermissionLevel.Unrestricted) return; diff --git a/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs b/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs index dc67bb532f..d8f3e615ec 100644 --- a/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs +++ b/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs @@ -1,8 +1,8 @@ using System; using System.Collections.Generic; using System.Linq; -using LightInject; using NUnit.Framework; +using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Sync; @@ -20,11 +20,11 @@ namespace Umbraco.Tests.Cache.DistributedCache [SetUp] public void Setup() { - var container = new ServiceContainer(); - container.ConfigureUmbracoCore(); + var container = Current.Container = new Core.Composing.LightInject.LightInjectContainer(new LightInject.ServiceContainer()); + container.ConfigureForUmbraco(); container.Register(_ => new TestServerRegistrar()); - container.Register(_ => new TestServerMessenger(), new PerContainerLifetime()); + container.RegisterSingleton(_ => new TestServerMessenger()); container.RegisterCollectionBuilder() .Add(); diff --git a/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs b/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs index 64194ebb47..d0924aa1a6 100644 --- a/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs +++ b/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs @@ -1,5 +1,4 @@ using System; -using System.Collections; using System.Collections.Generic; using System.Linq; using System.Xml; @@ -13,7 +12,6 @@ using Umbraco.Tests.TestHelpers; using Umbraco.Web.PublishedCache.XmlPublishedCache; using Umbraco.Tests.Testing; using Current = Umbraco.Web.Composing.Current; -using LightInject; using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; using Umbraco.Tests.PublishedContent; diff --git a/src/Umbraco.Tests/Components/ComponentTests.cs b/src/Umbraco.Tests/Components/ComponentTests.cs index 995350f80e..b0e0d308b8 100644 --- a/src/Umbraco.Tests/Components/ComponentTests.cs +++ b/src/Umbraco.Tests/Components/ComponentTests.cs @@ -1,11 +1,11 @@ using System; using System.Collections.Generic; using System.Linq; -using LightInject; using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Components; +using Umbraco.Core.Composing; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Persistence; @@ -21,7 +21,7 @@ namespace Umbraco.Tests.Components private static readonly List Composed = new List(); private static readonly List Initialized = new List(); - private static IServiceContainer MockContainer(Action> setup = null) + private static IContainer MockContainer(Action> setup = null) { // fixme use IUmbracoDatabaseFactory vs UmbracoDatabaseFactory, clean it all up! @@ -32,7 +32,7 @@ namespace Umbraco.Tests.Components var fs = new FileSystems(logger); var p = new ScopeProvider(f, fs, logger); - var mock = new Mock(); + var mock = new Mock(); mock.Setup(x => x.GetInstance(typeof (ILogger))).Returns(logger); mock.Setup(x => x.GetInstance(typeof (ProfilingLogger))).Returns(new ProfilingLogger(Mock.Of(), Mock.Of())); mock.Setup(x => x.GetInstance(typeof (IUmbracoDatabaseFactory))).Returns(f); diff --git a/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs b/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs index 87b0cd5173..3ab554b28e 100644 --- a/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs +++ b/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs @@ -1,24 +1,24 @@ using System; using System.Collections.Generic; using System.Linq; -using LightInject; using NUnit.Framework; using Umbraco.Core.Composing; +using Umbraco.Core; namespace Umbraco.Tests.Composing { [TestFixture] public class CollectionBuildersTests { - private ServiceContainer _container; + private IContainer _container; [SetUp] public void Setup() { Current.Reset(); - _container = new ServiceContainer(); - _container.ConfigureUmbracoCore(); + _container = Current.Container = new Core.Composing.LightInject.LightInjectContainer(new LightInject.ServiceContainer()); + _container.ConfigureForUmbraco(); } [TearDown] @@ -344,24 +344,27 @@ namespace Umbraco.Tests.Composing // but the container manages the scope, so to test the scope // the collection must come from the container - var scope1 = _container.BeginScope(); + TestCollection col1A, col1B; + + using (_container.BeginScope()) + { + col1A = _container.GetInstance(); + col1B = _container.GetInstance(); + } - var col1A = _container.GetInstance(); AssertCollection(col1A, typeof(Resolved1), typeof(Resolved2)); - var col1B = _container.GetInstance(); AssertCollection(col1B, typeof(Resolved1), typeof(Resolved2)); - AssertSameCollection(col1A, col1B); - _container.ScopeManagerProvider.GetScopeManager(_container).CurrentScope.Dispose(); - var scope2 = _container.BeginScope(); + TestCollection col2; + + using (_container.BeginScope()) + { + col2 = _container.GetInstance(); + } - var col2 = _container.GetInstance(); AssertCollection(col2, typeof(Resolved1), typeof(Resolved2)); - AssertNotSameCollection(col1A, col2); - - _container.ScopeManagerProvider.GetScopeManager(_container).CurrentScope.Dispose(); } [Test] diff --git a/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs b/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs index 7a39186fea..a9b7dd5ba0 100644 --- a/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs +++ b/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs @@ -5,6 +5,7 @@ using LightInject; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Composing; +using Umbraco.Core.Composing.LightInject; namespace Umbraco.Tests.Composing { @@ -32,6 +33,7 @@ namespace Umbraco.Tests.Composing { var container = new ServiceContainer(); container.ConfigureUmbracoCore(); + Current.Container = new LightInjectContainer(container); container.RegisterCollectionBuilder() .Add() @@ -56,6 +58,7 @@ namespace Umbraco.Tests.Composing { var container = new ServiceContainer(); container.ConfigureUmbracoCore(); + Current.Container = new LightInjectContainer(container); container.RegisterCollectionBuilder() .Add(() => new[] { typeof(TransientObject3), typeof(TransientObject2) }) @@ -79,6 +82,7 @@ namespace Umbraco.Tests.Composing { var container = new ServiceContainer(); container.ConfigureUmbracoCore(); + Current.Container = new LightInjectContainer(container); container.RegisterCollectionBuilder() .Add() @@ -103,6 +107,7 @@ namespace Umbraco.Tests.Composing { var container = new ServiceContainer(); container.ConfigureUmbracoCore(); + Current.Container = new LightInjectContainer(container); container.RegisterCollectionBuilder() .Add() @@ -125,6 +130,7 @@ namespace Umbraco.Tests.Composing { var container = new ServiceContainer(); container.ConfigureUmbracoCore(); + Current.Container = new LightInjectContainer(container); container.RegisterCollectionBuilder() .Add() diff --git a/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs b/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs index e2145f557a..0b318f80cf 100644 --- a/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs +++ b/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs @@ -1,7 +1,6 @@ using System; using System.Linq; using System.Xml; -using LightInject; using NUnit.Framework; using Umbraco.Core.Composing; using Umbraco.Core._Legacy.PackageActions; @@ -14,8 +13,8 @@ namespace Umbraco.Tests.Composing [Test] public void PackageActionCollectionBuilderWorks() { - var container = new ServiceContainer(); - container.ConfigureUmbracoCore(); + var container = Current.Container = new Core.Composing.LightInject.LightInjectContainer(new LightInject.ServiceContainer()); + container.ConfigureForUmbraco(); container.RegisterCollectionBuilder() .Add(() => TypeLoader.GetPackageActions()); diff --git a/src/Umbraco.Tests/CoreThings/UdiTests.cs b/src/Umbraco.Tests/CoreThings/UdiTests.cs index 49c02d5688..12ce3227e1 100644 --- a/src/Umbraco.Tests/CoreThings/UdiTests.cs +++ b/src/Umbraco.Tests/CoreThings/UdiTests.cs @@ -23,11 +23,11 @@ namespace Umbraco.Tests.CoreThings public void SetUp() { // fixme - bad in a unit test - but Udi has a static ctor that wants it?! - var container = new Mock(); + var container = new Mock(); var globalSettings = SettingsForTests.GenerateMockGlobalSettings(); - container.Setup(x => x.GetInstance(typeof (TypeLoader))).Returns( + container.Setup(x => x.GetInstance(typeof(TypeLoader))).Returns( new TypeLoader(NullCacheProvider.Instance, globalSettings, new ProfilingLogger(Mock.Of(), Mock.Of()))); - Current.Container = new Core.Composing.LightInject.LightInjectContainer(container.Object); + Current.Container = container.Object; Udi.ResetUdiTypes(); } diff --git a/src/Umbraco.Tests/IO/FileSystemsTests.cs b/src/Umbraco.Tests/IO/FileSystemsTests.cs index f31b587062..75a41560cf 100644 --- a/src/Umbraco.Tests/IO/FileSystemsTests.cs +++ b/src/Umbraco.Tests/IO/FileSystemsTests.cs @@ -1,7 +1,6 @@ using System; using System.IO; using System.Text; -using LightInject; using Moq; using NUnit.Framework; using Umbraco.Core; @@ -18,7 +17,7 @@ namespace Umbraco.Tests.IO [TestFixture] public class FileSystemsTests { - private ServiceContainer _container; + private IContainer _container; [SetUp] public void Setup() @@ -27,8 +26,9 @@ namespace Umbraco.Tests.IO var config = SettingsForTests.GetDefaultUmbracoSettings(); SettingsForTests.ConfigureSettings(config); - _container = new ServiceContainer(); - _container.ConfigureUmbracoCore(); + _container = Current.Container = new Core.Composing.LightInject.LightInjectContainer(new LightInject.ServiceContainer()); + _container.ConfigureForUmbraco(); + _container.Register(_ => Mock.Of()); _container.Register(); _container.Register(_ => Mock.Of()); @@ -37,7 +37,7 @@ namespace Umbraco.Tests.IO _container.Register((f, x) => new MediaFileSystem(x, f.GetInstance(), f.GetInstance(), f.GetInstance())); _container.Register((f, x) => new NonConfiguredTypeFileSystem(x)); - + // make sure we start clean // because some tests will create corrupt or weird filesystems FileSystems.Reset(); diff --git a/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs b/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs index edb9f2b97f..349804a432 100644 --- a/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs +++ b/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.IO; using System.Linq; using AutoMapper; using NUnit.Framework; @@ -9,7 +8,6 @@ using Umbraco.Core.Manifest; using Umbraco.Core.PropertyEditors; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; -using LightInject; namespace Umbraco.Tests.Models.Mapping { diff --git a/src/Umbraco.Tests/Models/VariationTests.cs b/src/Umbraco.Tests/Models/VariationTests.cs index 194e3c5c43..0e4ec81a44 100644 --- a/src/Umbraco.Tests/Models/VariationTests.cs +++ b/src/Umbraco.Tests/Models/VariationTests.cs @@ -1,10 +1,8 @@ using System; -using LightInject; using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Composing; -using Umbraco.Core.Composing.LightInject; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; @@ -28,8 +26,8 @@ namespace Umbraco.Tests.Models // need to be able to retrieve them all... Current.Reset(); - var container = Mock.Of(); - Current.Container = new LightInjectContainer(container); + var container = Mock.Of(); + Current.Container = container; var dataEditors = new DataEditorCollection(new IDataEditor[] { diff --git a/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs b/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs index 27138bbccf..3576e3aa60 100644 --- a/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs +++ b/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs @@ -1,6 +1,5 @@ using System; using System.Globalization; -using LightInject; using Moq; using Newtonsoft.Json; using NUnit.Framework; @@ -9,7 +8,6 @@ using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; -using Umbraco.Core.IO.MediaPathSchemes; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; @@ -67,12 +65,13 @@ namespace Umbraco.Tests.PropertyEditors { try { - var container = new ServiceContainer(); - container.ConfigureUmbracoCore(); + var container = Current.Container = new Core.Composing.LightInject.LightInjectContainer(new LightInject.ServiceContainer()); + container.ConfigureForUmbraco(); + container.RegisterCollectionBuilder(); - container.Register(f => Mock.Of()); - container.Register(f => Mock.Of()); + Current.Container.RegisterSingleton(f => Mock.Of()); + Current.Container.RegisterSingleton(f => Mock.Of()); var mediaFileSystem = new MediaFileSystem(Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of()); var dataTypeService = new TestObjects.TestDataTypeService( diff --git a/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs b/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs index f7d09bd2c0..c7924f12a6 100644 --- a/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs +++ b/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs @@ -1,6 +1,5 @@ using System; using System.Threading; -using LightInject; using Moq; using NUnit.Framework; using Umbraco.Core; @@ -22,8 +21,9 @@ namespace Umbraco.Tests.PropertyEditors //normalize culture Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture; - var container = new ServiceContainer(); - container.ConfigureUmbracoCore(); + var container = Current.Container = new Core.Composing.LightInject.LightInjectContainer(new LightInject.ServiceContainer()); + container.ConfigureForUmbraco(); + container.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 edc4face17..112dda9c17 100644 --- a/src/Umbraco.Tests/Published/ConvertersTests.cs +++ b/src/Umbraco.Tests/Published/ConvertersTests.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using LightInject; using Moq; using NUnit.Framework; using Umbraco.Core; @@ -172,8 +171,9 @@ namespace Umbraco.Tests.Published public void SimpleConverter3Test() { Current.Reset(); - var container = new ServiceContainer(); - container.ConfigureUmbracoCore(); + var container = Current.Container = new Core.Composing.LightInject.LightInjectContainer(new LightInject.ServiceContainer()); + container.ConfigureForUmbraco(); + Current.Container.RegisterCollectionBuilder() .Append() diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentMoreTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentMoreTests.cs index 101c7827c3..0f7212a0b4 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentMoreTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentMoreTests.cs @@ -11,11 +11,10 @@ using Umbraco.Web.Routing; using Umbraco.Web.Security; using Umbraco.Core.Composing; using Current = Umbraco.Core.Composing.Current; -using LightInject; +using Umbraco.Core; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; -using Umbraco.Core.Services; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; using Umbraco.Tests.Testing.Objects.Accessors; @@ -45,7 +44,7 @@ namespace Umbraco.Tests.PublishedContent Container.RegisterSingleton(f => new PublishedModelFactory(f.GetInstance().GetTypes())); } - protected override TypeLoader CreatePluginManager(IServiceFactory f) + protected override TypeLoader CreatePluginManager(IContainer f) { var pluginManager = base.CreatePluginManager(f); diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs index b1fbc43f08..09665a4a7b 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs @@ -1,14 +1,11 @@ using Umbraco.Core; -using Umbraco.Core.Composing; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.PropertyEditors; using Umbraco.Core.PropertyEditors.ValueConverters; using Umbraco.Tests.TestHelpers; -using LightInject; using Moq; using Umbraco.Core.Logging; using Umbraco.Core.Models; -using Umbraco.Core.Services; using Umbraco.Web.PropertyEditors; namespace Umbraco.Tests.PublishedContent diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs index fa120065bf..c52a3c73b0 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs @@ -9,7 +9,6 @@ using Umbraco.Core.PropertyEditors; using Umbraco.Web; using Umbraco.Web.PublishedCache; using Umbraco.Core.Composing; -using LightInject; using Moq; using Umbraco.Core.Logging; using Umbraco.Core.Models; @@ -72,7 +71,7 @@ namespace Umbraco.Tests.PublishedContent ContentTypesCache.GetPublishedContentTypeByAlias = alias => type; } - protected override TypeLoader CreatePluginManager(IServiceFactory f) + protected override TypeLoader CreatePluginManager(IContainer f) { var pluginManager = base.CreatePluginManager(f); @@ -448,7 +447,7 @@ namespace Umbraco.Tests.PublishedContent public void FirstChildAsT() { var doc = GetNode(1046); // has child nodes - + var model = doc.FirstChild(x => true); // predicate Assert.IsNotNull(model); diff --git a/src/Umbraco.Tests/Routing/ContentFinderByIdTests.cs b/src/Umbraco.Tests/Routing/ContentFinderByIdTests.cs index 224b4a7934..239bfc7ad5 100644 --- a/src/Umbraco.Tests/Routing/ContentFinderByIdTests.cs +++ b/src/Umbraco.Tests/Routing/ContentFinderByIdTests.cs @@ -1,8 +1,8 @@ using NUnit.Framework; +using Umbraco.Core; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Tests.TestHelpers; using Umbraco.Web.Routing; -using LightInject; namespace Umbraco.Tests.Routing { diff --git a/src/Umbraco.Tests/Routing/ContentFinderByUrlAndTemplateTests.cs b/src/Umbraco.Tests/Routing/ContentFinderByUrlAndTemplateTests.cs index 5080ab339d..dab0f15917 100644 --- a/src/Umbraco.Tests/Routing/ContentFinderByUrlAndTemplateTests.cs +++ b/src/Umbraco.Tests/Routing/ContentFinderByUrlAndTemplateTests.cs @@ -1,12 +1,10 @@ using Moq; using NUnit.Framework; -using LightInject; using Umbraco.Tests.TestHelpers; using Umbraco.Web.Routing; using Umbraco.Core.Models; using Umbraco.Tests.Testing; using Current = Umbraco.Web.Composing.Current; -using Umbraco.Core.Configuration.UmbracoSettings; namespace Umbraco.Tests.Routing { diff --git a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs index fa4bb9b538..f4cf3f76a9 100644 --- a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs +++ b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs @@ -2,7 +2,6 @@ using System.Linq; using System.Web.Mvc; using System.Web.Routing; -using LightInject; using Moq; using NUnit.Framework; using Umbraco.Core; @@ -14,13 +13,11 @@ using Umbraco.Tests.TestHelpers.Stubs; using Umbraco.Web; using Umbraco.Web.Models; using Umbraco.Web.Mvc; -using Umbraco.Web.Routing; using Umbraco.Web.WebApi; using Umbraco.Core.Strings; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Models.PublishedContent; -using Umbraco.Core.Persistence; using Umbraco.Core.Services; using Umbraco.Tests.PublishedContent; using Umbraco.Tests.Testing; @@ -51,7 +48,7 @@ namespace Umbraco.Tests.Routing : base(umbracoApplication) { } - public override void Boot(ServiceContainer container) + public override void Boot(IContainer container) { // do it before anything else - this is the only place where it's possible var logger = Mock.Of(); diff --git a/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs b/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs index 92c49b0950..504cbfb6ef 100644 --- a/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs +++ b/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs @@ -4,7 +4,6 @@ using System.Threading; using Moq; using NUnit.Framework; using Umbraco.Core; -using Umbraco.Core.Configuration; using Umbraco.Tests.TestHelpers; using Umbraco.Web; using Umbraco.Core.IO; @@ -12,14 +11,10 @@ using Umbraco.Core.Logging; using Umbraco.Core.Sync; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Models.PublishedContent; -using Umbraco.Core.Persistence; using Umbraco.Core.Services; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; -// fixme - abstract container -using LightInject; - namespace Umbraco.Tests.Routing { [TestFixture] @@ -52,7 +47,7 @@ namespace Umbraco.Tests.Routing ); runtime.Level = RuntimeLevel.Run; - + //SettingsForTests.ReservedPaths = "~/umbraco,~/install/"; //SettingsForTests.ReservedUrls = "~/config/splashes/booting.aspx,~/install/default.aspx,~/config/splashes/noNodes.aspx,~/VSEnterpriseHelper.axd"; diff --git a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs index 770dead600..2c39f29b3b 100644 --- a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs +++ b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Web.Hosting; using Examine; -using LightInject; using Moq; using NUnit.Framework; using Umbraco.Core; @@ -13,7 +12,6 @@ using Umbraco.Core.Persistence; using Umbraco.Core.Runtime; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Stubs; -using Umbraco.Examine; namespace Umbraco.Tests.Runtimes { @@ -83,7 +81,7 @@ namespace Umbraco.Tests.Runtimes : base(umbracoApplication) { } - public override void Compose(ServiceContainer container) + public override void Compose(IContainer container) { base.Compose(container); @@ -116,7 +114,7 @@ namespace Umbraco.Tests.Runtimes private MainDom _mainDom; - public override void Boot(ServiceContainer container) + public override void Boot(IContainer container) { base.Boot(container); _mainDom = container.GetInstance(); diff --git a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs index b270fe8e22..0505072e5c 100644 --- a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs @@ -1,6 +1,5 @@ using System; using System.Linq; -using LightInject; using Moq; using NUnit.Framework; using Umbraco.Core; @@ -12,7 +11,6 @@ using Umbraco.Core.Scoping; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Entities; using Umbraco.Core.Composing; -using Umbraco.Core.Composing.LightInject; using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Services; @@ -31,13 +29,9 @@ namespace Umbraco.Tests.Scoping DoThing2 = null; DoThing3 = null; - var lightinjectContainer = new ServiceContainer(); - Current.Container = new LightInjectContainer(lightinjectContainer); + var container = Current.Container = new Core.Composing.LightInject.LightInjectContainer(new LightInject.ServiceContainer()); - _testObjects = new TestObjects(lightinjectContainer); - - // fixme - move to container factory? - Current.Container.RegisterSingleton(f => (IServiceContainer)Current.Container.ConcreteContainer); + _testObjects = new TestObjects(container); Current.Container.RegisterSingleton(f => Current.Container); Current.Container.RegisterSingleton(factory => new FileSystems(factory.TryGetInstance())); diff --git a/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs b/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs index 48bbdb1e22..875eabb13c 100644 --- a/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; +using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Models; diff --git a/src/Umbraco.Tests/Services/ContentServiceTests.cs b/src/Umbraco.Tests/Services/ContentServiceTests.cs index ff1678fa3f..f88abb37a7 100644 --- a/src/Umbraco.Tests/Services/ContentServiceTests.cs +++ b/src/Umbraco.Tests/Services/ContentServiceTests.cs @@ -1,5 +1,4 @@ using System; -using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; @@ -8,22 +7,17 @@ using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Configuration.UmbracoSettings; -using Umbraco.Core.IO; using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; -using LightInject; -using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Services; using Umbraco.Tests.TestHelpers.Entities; using Umbraco.Core.Events; -using Umbraco.Core.Logging; using Umbraco.Core.Persistence.Dtos; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Scoping; using Umbraco.Core.Services.Implement; using Umbraco.Tests.Testing; -using Umbraco.Web.PropertyEditors; using System.Reflection; using Umbraco.Core.Cache; diff --git a/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs b/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs index 2cbbfa6ebc..d925caa23f 100644 --- a/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs +++ b/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using System.Threading; using System.Xml.Linq; @@ -11,7 +10,6 @@ using Umbraco.Core.Logging; using Umbraco.Core.Persistence.Dtos; using Umbraco.Core.PropertyEditors; using Umbraco.Tests.Testing; -using LightInject; namespace Umbraco.Tests.Services.Importing { diff --git a/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs b/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs index 36e5874e14..934d06840c 100644 --- a/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs +++ b/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs @@ -1,15 +1,12 @@ using System.Collections.Generic; using System.Diagnostics; -using System.Globalization; using System.Linq; using System.Text; using System.Text.RegularExpressions; -using LightInject; using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Configuration.UmbracoSettings; -using Umbraco.Core.Composing; using Umbraco.Core.Strings; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; diff --git a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs index bc29139918..1078a49299 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs @@ -1,5 +1,4 @@ -using LightInject; -using Moq; +using Moq; using NPoco; using NUnit.Framework; using Umbraco.Core; @@ -7,7 +6,6 @@ using Umbraco.Core.Cache; using Umbraco.Core.Logging; using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Persistence.SqlSyntax; -using Umbraco.Core.Profiling; using Umbraco.Core.Composing; using Umbraco.Core.Persistence; @@ -34,8 +32,8 @@ namespace Umbraco.Tests.TestHelpers var sqlSyntax = new SqlCeSyntaxProvider(); - var container = new ServiceContainer(); - container.ConfigureUmbracoCore(); + var container = Current.Container = new Core.Composing.LightInject.LightInjectContainer(new LightInject.ServiceContainer()); + container.ConfigureForUmbraco(); container.RegisterSingleton(factory => Mock.Of()); container.RegisterSingleton(factory => Mock.Of()); diff --git a/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs b/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs index 5eea6bcf72..421870c969 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs @@ -1,10 +1,9 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Threading; -using LightInject; using Moq; using NUnit.Framework; +using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Logging; @@ -86,12 +85,12 @@ namespace Umbraco.Tests.TestHelpers "; } - internal PublishedRouter CreatePublishedRouter(IServiceContainer container = null, ContentFinderCollection contentFinders = null) + internal PublishedRouter CreatePublishedRouter(IContainer container = null, ContentFinderCollection contentFinders = null) { return CreatePublishedRouter(TestObjects.GetUmbracoSettings().WebRouting, container, contentFinders); } - internal static PublishedRouter CreatePublishedRouter(IWebRoutingSection webRoutingSection, IServiceContainer container = null, ContentFinderCollection contentFinders = null) + internal static PublishedRouter CreatePublishedRouter(IWebRoutingSection webRoutingSection, IContainer container = null, ContentFinderCollection contentFinders = null) { return new PublishedRouter( webRoutingSection, diff --git a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs index c9f74d689d..fb59ebee72 100644 --- a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs +++ b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs @@ -1,5 +1,4 @@ using System; -using System.Collections; using System.Collections.Generic; using System.Linq; using System.Net.Http; @@ -9,26 +8,19 @@ using System.Web.Http.Controllers; using System.Web.Http.Dispatcher; using System.Web.Security; using Moq; -using Semver; -using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; -using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Dictionary; -using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Security; using Umbraco.Core.Services; -using Umbraco.Tests.TestHelpers.Stubs; using Umbraco.Web; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; using Umbraco.Web.Security; using Umbraco.Web.WebApi; -using LightInject; -using System.Globalization; using Umbraco.Core.Logging; using Umbraco.Tests.Testing.Objects.Accessors; diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs b/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs index 1cf39532a2..da96c40299 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs @@ -5,18 +5,16 @@ using System.Data.Common; using System.Linq; using System.Linq.Expressions; using System.Web; -using LightInject; using Moq; using Umbraco.Core; +using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; -using Umbraco.Core.Events; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Persistence; using Umbraco.Core.Services; -using Umbraco.Tests.TestHelpers.Stubs; using Umbraco.Tests.Testing.Objects.Accessors; using Umbraco.Web; using Umbraco.Web.PublishedCache; @@ -55,7 +53,7 @@ namespace Umbraco.Tests.TestHelpers /// Gets a mocked service context built with mocked services. /// /// A ServiceContext. - public ServiceContext GetServiceContextMock(IServiceFactory container = null) + public ServiceContext GetServiceContextMock(IContainer container = null) { return new ServiceContext( MockService(), @@ -83,7 +81,7 @@ namespace Umbraco.Tests.TestHelpers MockService()); } - private T MockService(IServiceFactory container = null) + private T MockService(IContainer container = null) where T : class { return container?.TryGetInstance() ?? new Mock().Object; diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects.cs b/src/Umbraco.Tests/TestHelpers/TestObjects.cs index e091cc8d49..00a193b40a 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects.cs @@ -1,9 +1,7 @@ using System; -using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; -using LightInject; using Moq; using NPoco; using Umbraco.Core; @@ -32,9 +30,9 @@ namespace Umbraco.Tests.TestHelpers /// internal partial class TestObjects { - private readonly IServiceContainer _container; + private readonly IContainer _container; - public TestObjects(IServiceContainer container) + public TestObjects(IContainer container) { _container = container; } @@ -85,7 +83,7 @@ namespace Umbraco.Tests.TestHelpers return new UmbracoDatabase(connection, sqlContext, logger); } - public void RegisterServices(IServiceContainer container) + public void RegisterServices(IContainer container) { } /// @@ -109,7 +107,7 @@ namespace Umbraco.Tests.TestHelpers IGlobalSettings globalSettings, IEventMessagesFactory eventMessagesFactory, IEnumerable urlSegmentProviders, - IServiceFactory container = null) + IContainer container = null) { if (scopeProvider == null) throw new ArgumentNullException(nameof(scopeProvider)); if (scopeAccessor == null) throw new ArgumentNullException(nameof(scopeAccessor)); @@ -220,13 +218,13 @@ namespace Umbraco.Tests.TestHelpers consentService); } - private Lazy GetLazyService(IServiceFactory container, Func ctor) + private Lazy GetLazyService(IContainer container, Func ctor) where T : class { return new Lazy(() => container?.TryGetInstance() ?? ctor(container)); } - private T GetRepo(IServiceFactory container) + private T GetRepo(IContainer container) where T : class, IRepository { return container?.TryGetInstance() ?? Mock.Of(); diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index 1b839a642e..f3029b3a35 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -4,7 +4,6 @@ using System.Linq; using System.Reflection; using AutoMapper; using Examine; -using LightInject; using Moq; using NUnit.Framework; using Umbraco.Core; @@ -75,7 +74,7 @@ namespace Umbraco.Tests.Testing // test feature, and no test "base" class should be. only actual test feature classes // should be marked with that attribute. - protected ServiceContainer Container { get; private set; } + protected IContainer Container { get; private set; } protected UmbracoTestAttribute Options { get; private set; } @@ -114,8 +113,8 @@ namespace Umbraco.Tests.Testing // but hey, never know, better avoid garbage-in Reset(); - Container = new ServiceContainer(); - Container.ConfigureUmbracoCore(); + Container = Current.Container = new Core.Composing.LightInject.LightInjectContainer(new LightInject.ServiceContainer()); + Container.ConfigureForUmbraco(); TestObjects = new TestObjects(Container); @@ -238,12 +237,12 @@ namespace Umbraco.Tests.Testing }); } - protected virtual TypeLoader CreatePluginManager(IServiceFactory f) + protected virtual TypeLoader CreatePluginManager(IContainer f) { return CreateCommonPluginManager(f); } - private static TypeLoader CreateCommonPluginManager(IServiceFactory f) + private static TypeLoader CreateCommonPluginManager(IContainer f) { return new TypeLoader(f.GetInstance().RuntimeCache, f.GetInstance(), f.GetInstance(), false) { @@ -284,26 +283,9 @@ namespace Umbraco.Tests.Testing Container.RegisterSingleton(factory => umbracoSettings.Content); Container.RegisterSingleton(factory => umbracoSettings.Templates); Container.RegisterSingleton(factory => umbracoSettings.WebRouting); - - // fixme - The whole MediaFileSystem coupling thing seems broken. - Container.Register((factory, fileSystem) => new MediaFileSystem(fileSystem, factory.GetInstance(), factory.GetInstance(), factory.GetInstance())); - Container.RegisterConstructorDependency((factory, parameterInfo) => factory.GetInstance().MediaFileSystem); Container.RegisterSingleton(factory => ExamineManager.Instance); - // replace some stuff - Container.RegisterSingleton(factory => Mock.Of(), "ScriptFileSystem"); - Container.RegisterSingleton(factory => Mock.Of(), "PartialViewFileSystem"); - Container.RegisterSingleton(factory => Mock.Of(), "PartialViewMacroFileSystem"); - Container.RegisterSingleton(factory => Mock.Of(), "StylesheetFileSystem"); - - // need real file systems here as templates content is on-disk only - //Container.RegisterSingleton(factory => Mock.Of(), "MasterpageFileSystem"); - //Container.RegisterSingleton(factory => Mock.Of(), "ViewFileSystem"); - Container.RegisterSingleton(factory => new PhysicalFileSystem("Views", "/views"), "ViewFileSystem"); - Container.RegisterSingleton(factory => new PhysicalFileSystem("MasterPages", "/masterpages"), "MasterpageFileSystem"); - Container.RegisterSingleton(factory => new PhysicalFileSystem("Xslt", "/xslt"), "XsltFileSystem"); - // no factory (noop) Container.RegisterSingleton(); diff --git a/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs b/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs index 154b587a47..2597eab631 100644 --- a/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs +++ b/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs @@ -1,15 +1,9 @@ -using Moq; -using System.IO; -using LightInject; +using System.IO; using NUnit.Framework; using Umbraco.Core; -using Umbraco.Core.Composing; using Umbraco.Core.Logging; -using Umbraco.Core.Persistence.Mappers; -using Umbraco.Core.Profiling; using Umbraco.Core.Strings; using Umbraco.Tests.TestHelpers; -using Umbraco.Examine; namespace Umbraco.Tests.UmbracoExamine { diff --git a/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs b/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs index a4b210dbef..0ad3bff109 100644 --- a/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs +++ b/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs @@ -3,18 +3,13 @@ using System.Globalization; using System.Linq; using System.Web.Mvc; using System.Web.Routing; -using LightInject; using Moq; using NUnit.Framework; -using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Logging; using Umbraco.Core.Models.PublishedContent; -using Umbraco.Core.Persistence; -using Umbraco.Core.PropertyEditors; -using Umbraco.Core.Scoping; using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Tests.TestHelpers; diff --git a/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs b/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs index b2f18736a2..e60a4d9397 100644 --- a/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs +++ b/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs @@ -1,21 +1,17 @@ using System; -using System.Globalization; using System.Linq; using System.Web; -using LightInject; using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; -using Umbraco.Core.Composing.LightInject; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Services; using Umbraco.Tests.TestHelpers; -using Umbraco.Tests.TestHelpers.Stubs; using Umbraco.Tests.Testing.Objects.Accessors; using Umbraco.Web; using Umbraco.Web.PublishedCache; @@ -40,11 +36,11 @@ namespace Umbraco.Tests.Web var serviceContext = new ServiceContext(entityService: entityService.Object); // fixme - bad in a unit test - but Udi has a static ctor that wants it?! - var container = new Mock(); + var container = new Mock(); container.Setup(x => x.GetInstance(typeof(TypeLoader))).Returns( new TypeLoader(NullCacheProvider.Instance, SettingsForTests.GenerateMockGlobalSettings(), new ProfilingLogger(Mock.Of(), Mock.Of()))); container.Setup(x => x.GetInstance(typeof (ServiceContext))).Returns(serviceContext); - Current.Container = new LightInjectContainer(container.Object); + Current.Container = container.Object; Umbraco.Web.Composing.Current.UmbracoContextAccessor = new TestUmbracoContextAccessor(); diff --git a/src/Umbraco.Web/Components/DatabaseServerRegistrarAndMessengerComponent.cs b/src/Umbraco.Web/Components/DatabaseServerRegistrarAndMessengerComponent.cs index 480227f251..7a03fb3457 100644 --- a/src/Umbraco.Web/Components/DatabaseServerRegistrarAndMessengerComponent.cs +++ b/src/Umbraco.Web/Components/DatabaseServerRegistrarAndMessengerComponent.cs @@ -1,7 +1,6 @@ using System; using System.Threading; using Examine; -using LightInject; using Umbraco.Core; using Umbraco.Core.Components; using Umbraco.Core.Configuration; diff --git a/src/Umbraco.Web/LightInjectExtensions.cs b/src/Umbraco.Web/Composing/Composers/ControllersComposer.cs similarity index 65% rename from src/Umbraco.Web/LightInjectExtensions.cs rename to src/Umbraco.Web/Composing/Composers/ControllersComposer.cs index 580dc4117d..889ef195a5 100644 --- a/src/Umbraco.Web/LightInjectExtensions.cs +++ b/src/Umbraco.Web/Composing/Composers/ControllersComposer.cs @@ -1,49 +1,43 @@ using System.Reflection; using System.Web.Http.Controllers; using System.Web.Mvc; -using LightInject; -using Umbraco.Core; using Umbraco.Core.Composing; -namespace Umbraco.Web +namespace Umbraco.Web.Composing.Composers { - internal static class LightInjectExtensions + internal static class ControllersComposer { /// /// Registers all IControllers using the TypeLoader for scanning and caching found instances for the calling assembly /// - /// - /// - /// - public static void RegisterMvcControllers(this IServiceRegistry container, TypeLoader typeLoader, Assembly assembly) + public static IContainer ComposeMvcControllers(this IContainer container, TypeLoader typeLoader, Assembly assembly) { //TODO: We've already scanned for UmbracoApiControllers and SurfaceControllers - should we scan again // for all controllers? Seems like we should just do this once and then filter. That said here we are // only scanning our own single assembly. Hrm. container.RegisterControllers(typeLoader, assembly); + return container; } /// /// Registers all IHttpController using the TypeLoader for scanning and caching found instances for the calling assembly /// - /// - /// - /// - public static void RegisterApiControllers(this IServiceRegistry container, TypeLoader typeLoader, Assembly assembly) + public static IContainer ComposeApiControllers(this IContainer container, TypeLoader typeLoader, Assembly assembly) { //TODO: We've already scanned for UmbracoApiControllers and SurfaceControllers - should we scan again // for all controllers? Seems like we should just do this once and then filter. That said here we are // only scanning our own single assembly. Hrm. container.RegisterControllers(typeLoader, assembly); + return container; } - private static void RegisterControllers(this IServiceRegistry container, TypeLoader typeLoader, Assembly assembly) + private static void RegisterControllers(this IContainer container, TypeLoader typeLoader, Assembly assembly) { var types = typeLoader.GetTypes(specificAssemblies: new[] { assembly }); foreach (var type in types) - container.Register(type, new PerRequestLifeTime()); + container.Register(type, Lifetime.Request); } } } diff --git a/src/Umbraco.Web/Composing/Composers/InstallerComposer.cs b/src/Umbraco.Web/Composing/Composers/InstallerComposer.cs index 265272cef2..9c701495fd 100644 --- a/src/Umbraco.Web/Composing/Composers/InstallerComposer.cs +++ b/src/Umbraco.Web/Composing/Composers/InstallerComposer.cs @@ -1,4 +1,5 @@ -using LightInject; +using Umbraco.Core; +using Umbraco.Core.Composing; using Umbraco.Web.Install; using Umbraco.Web.Install.InstallSteps; using Umbraco.Web.Install.Models; @@ -7,10 +8,10 @@ namespace Umbraco.Web.Composing.Composers { public static class InstallerComposer { - public static IServiceRegistry ComposeInstaller(this IServiceRegistry registry) + public static IContainer ComposeInstaller(this IContainer container) { //register the installer steps in order - registry.RegisterOrdered(typeof(InstallSetupStep), + container.RegisterOrdered(typeof(InstallSetupStep), new[] { typeof(NewInstallStep), @@ -27,12 +28,12 @@ namespace Umbraco.Web.Composing.Composers //typeof(StarterKitCleanupStep), typeof(SetUmbracoVersionStep) - }, type => new PerScopeLifetime()); + }, Lifetime.Scope); - registry.Register(); - registry.Register(); + container.Register(); + container.Register(); - return registry; + return container; } } } diff --git a/src/Umbraco.Web/Composing/Composers/WebMappingProfilesComposer.cs b/src/Umbraco.Web/Composing/Composers/WebMappingProfilesComposer.cs index 65fdd7fb72..b20b6348dd 100644 --- a/src/Umbraco.Web/Composing/Composers/WebMappingProfilesComposer.cs +++ b/src/Umbraco.Web/Composing/Composers/WebMappingProfilesComposer.cs @@ -1,4 +1,5 @@ -using LightInject; +using Umbraco.Core; +using Umbraco.Core.Composing; using Umbraco.Core.Models; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Models.Mapping; @@ -8,39 +9,39 @@ namespace Umbraco.Web.Composing.Composers { public static class WebMappingProfilesComposer { - public static IServiceRegistry ComposeWebMappingProfiles(this IServiceRegistry registry) + public static IContainer ComposeWebMappingProfiles(this IContainer container) { //register the profiles - registry.Register(); - registry.Register(); - registry.Register(); - registry.Register(); - registry.Register(); - registry.Register(); - registry.Register(); - registry.Register(); - registry.Register(); - registry.Register(); - registry.Register(); - registry.Register(); - registry.Register(); - registry.Register(); - registry.Register(); - registry.Register(); - registry.Register(); - registry.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); //register any resolvers, etc.. that the profiles use - registry.Register(); - registry.Register>(); - registry.Register>(); - registry.Register>(); - registry.Register>(); - registry.Register(); - registry.Register(); - registry.Register(); + container.Register(); + container.Register>(); + container.Register>(); + container.Register>(); + container.Register>(); + container.Register(); + container.Register(); + container.Register(); - return registry; + return container; } } } diff --git a/src/Umbraco.Web/Composing/LightInject/LightInjectContainer.cs b/src/Umbraco.Web/Composing/LightInject/LightInjectContainer.cs new file mode 100644 index 0000000000..1cc30be73f --- /dev/null +++ b/src/Umbraco.Web/Composing/LightInject/LightInjectContainer.cs @@ -0,0 +1,32 @@ +using System; +using System.Web.Http; +using LightInject; +using Umbraco.Core.Composing; + +namespace Umbraco.Web.Composing.LightInject +{ + /// + /// Implements with LightInject. + /// + public class LightInjectContainer : Core.Composing.LightInject.LightInjectContainer + { + /// + /// Initializes a new instance of the with a LightInject container. + /// + public LightInjectContainer(ServiceContainer container) + : base(container) + { } + + /// + public override void ConfigureForWeb() + { + // IoC setup for LightInject for MVC/WebApi + // see comments on MixedLightInjectScopeManagerProvider for explainations of what we are doing here + if (!(Container.ScopeManagerProvider is MixedLightInjectScopeManagerProvider smp)) + throw new Exception("Container.ScopeManagerProvider is not MixedLightInjectScopeManagerProvider."); + Container.EnableMvc(); // does container.EnablePerWebRequestScope() + Container.ScopeManagerProvider = smp; // reverts - we will do it last (in WebRuntime) + Container.EnableWebApi(GlobalConfiguration.Configuration); + } + } +} diff --git a/src/Umbraco.Web/CompositionExtensions.cs b/src/Umbraco.Web/CompositionExtensions.cs index 332380009d..4e22907218 100644 --- a/src/Umbraco.Web/CompositionExtensions.cs +++ b/src/Umbraco.Web/CompositionExtensions.cs @@ -1,11 +1,8 @@ using System; -using LightInject; using Umbraco.Core.Composing; using Current = Umbraco.Web.Composing.Current; -using Umbraco.Core.Macros; using Umbraco.Web.Editors; using Umbraco.Web.HealthCheck; -using Umbraco.Web.Media; using Umbraco.Web.Mvc; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; @@ -32,7 +29,7 @@ namespace Umbraco.Core.Components /// internal static ActionCollectionBuilder Actions(this Composition composition) => composition.Container.GetInstance(); - + /// /// Gets the content finders collection builder. /// @@ -91,7 +88,7 @@ namespace Umbraco.Core.Components /// /// The composition. /// A function creating a last chance finder. - public static void SetContentLastChanceFinder(this Composition composition, Func factory) + public static void SetContentLastChanceFinder(this Composition composition, Func factory) { composition.Container.RegisterSingleton(factory); } @@ -132,7 +129,7 @@ namespace Umbraco.Core.Components /// /// The composition. /// A function creating a published snapshot service. - public static void SetPublishedSnapshotService(this Composition composition, Func factory) + public static void SetPublishedSnapshotService(this Composition composition, Func factory) { composition.Container.RegisterSingleton(factory); } @@ -163,7 +160,7 @@ namespace Umbraco.Core.Components /// /// The composition. /// A function creating a helper. - public static void SetSiteDomainHelper(this Composition composition, Func factory) + public static void SetSiteDomainHelper(this Composition composition, Func factory) { composition.Container.RegisterSingleton(factory); } diff --git a/src/Umbraco.Web/PublishedCache/NuCache/NuCacheComponent.cs b/src/Umbraco.Web/PublishedCache/NuCache/NuCacheComponent.cs index 1d497d73e0..e526d3853a 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/NuCacheComponent.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/NuCacheComponent.cs @@ -1,4 +1,5 @@ using Umbraco.Core.Components; +using Umbraco.Core; using Umbraco.Web.PublishedCache.NuCache.DataSource; namespace Umbraco.Web.PublishedCache.NuCache diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlCacheComponent.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlCacheComponent.cs index 496818ab28..ae3b442931 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlCacheComponent.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlCacheComponent.cs @@ -6,7 +6,6 @@ using Umbraco.Core.Strings; using Umbraco.Core.Logging; using Umbraco.Core.Scoping; using Umbraco.Web.HealthCheck.Checks.DataIntegrity; -using LightInject; using Umbraco.Core.Configuration; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Persistence.Repositories; diff --git a/src/Umbraco.Web/Runtime/WebRuntime.cs b/src/Umbraco.Web/Runtime/WebRuntime.cs index 0beacb1ee5..38c0c5ad50 100644 --- a/src/Umbraco.Web/Runtime/WebRuntime.cs +++ b/src/Umbraco.Web/Runtime/WebRuntime.cs @@ -1,6 +1,4 @@ -using System; -using System.Web; -using LightInject; +using System.Web; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; @@ -27,7 +25,7 @@ namespace Umbraco.Web.Runtime { } /// - public override void Boot(ServiceContainer container) + public override void Boot(IContainer container) { // create and start asap to profile boot var debug = GlobalSettings.DebugMode; @@ -46,13 +44,11 @@ namespace Umbraco.Web.Runtime base.Boot(container); // now (and only now) is the time to switch over to perWebRequest scopes - if (!(container.ScopeManagerProvider is MixedLightInjectScopeManagerProvider smp)) - throw new Exception("Container.ScopeManagerProvider is not MixedLightInjectScopeManagerProvider."); - smp.EnablePerWebRequestScope(); + container.EnablePerWebRequestScope(); } /// - public override void Compose(ServiceContainer container) + public override void Compose(IContainer container) { base.Compose(container); diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs index 31deac6b68..29d40c0ce9 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs @@ -14,7 +14,6 @@ using System.Web.Security; using ClientDependency.Core.CompositeFiles.Providers; using ClientDependency.Core.Config; using Examine; -using LightInject; using Microsoft.AspNet.SignalR; using Umbraco.Core; using Umbraco.Core.Components; @@ -93,17 +92,17 @@ namespace Umbraco.Web.Runtime // register a per-request HttpContextBase object // is per-request so only one wrapper is created per request - composition.Container.Register(factory => new HttpContextWrapper(factory.GetInstance().HttpContext), new PerRequestLifeTime()); + composition.Container.RegisterSingleton(factory => new HttpContextWrapper(factory.GetInstance().HttpContext)); // register the published snapshot accessor - the "current" published snapshot is in the umbraco context composition.Container.RegisterSingleton(); // register a per-request UmbracoContext object // no real need to be per request but assuming it is faster - composition.Container.Register(factory => factory.GetInstance().UmbracoContext, new PerRequestLifeTime()); + composition.Container.RegisterSingleton(factory => factory.GetInstance().UmbracoContext); // register the umbraco helper - composition.Container.Register(new PerRequestLifeTime()); + composition.Container.RegisterSingleton(); // register distributed cache composition.Container.RegisterSingleton(f => new DistributedCache()); @@ -116,16 +115,10 @@ namespace Umbraco.Web.Runtime composition.Container.RegisterSingleton(factory => ExamineManager.Instance); - // IoC setup for LightInject for MVC/WebApi - // see comments on MixedLightInjectScopeManagerProvider for explainations of what we are doing here - if (!(composition.Container.ScopeManagerProvider is MixedLightInjectScopeManagerProvider smp)) - throw new Exception("Container.ScopeManagerProvider is not MixedLightInjectScopeManagerProvider."); - composition.Container.EnableMvc(); // does container.EnablePerWebRequestScope() - composition.Container.ScopeManagerProvider = smp; // reverts - we will do it last (in WebRuntime) - - composition.Container.RegisterMvcControllers(typeLoader, GetType().Assembly); - composition.Container.EnableWebApi(GlobalConfiguration.Configuration); - composition.Container.RegisterApiControllers(typeLoader, GetType().Assembly); + // configure the container for web + composition.Container.ConfigureForWeb(); + composition.Container.ComposeMvcControllers(typeLoader, GetType().Assembly); + composition.Container.ComposeApiControllers(typeLoader, GetType().Assembly); composition.Container.RegisterCollectionBuilder() .Add(() => typeLoader.GetTypes()); // fixme which searchable trees?! @@ -200,7 +193,7 @@ namespace Umbraco.Web.Runtime composition.Container.Register(_ => UmbracoConfig.For.UmbracoSettings().WebRouting); // register preview SignalR hub - composition.Container.Register(_ => GlobalHost.ConnectionManager.GetHubContext(), new PerContainerLifetime()); + composition.Container.RegisterSingleton(_ => GlobalHost.ConnectionManager.GetHubContext()); // register properties fallback composition.Container.RegisterSingleton(); diff --git a/src/Umbraco.Web/SignalR/PreviewHubComponent.cs b/src/Umbraco.Web/SignalR/PreviewHubComponent.cs index 07467d3bfa..20d7ec34cf 100644 --- a/src/Umbraco.Web/SignalR/PreviewHubComponent.cs +++ b/src/Umbraco.Web/SignalR/PreviewHubComponent.cs @@ -1,5 +1,4 @@ using System; -using LightInject; using Microsoft.AspNet.SignalR; using Umbraco.Core; using Umbraco.Core.Components; @@ -14,7 +13,7 @@ namespace Umbraco.Web.SignalR public override void Compose(Composition composition) { base.Compose(composition); - composition.Container.Register(_ => GlobalHost.ConnectionManager.GetHubContext(), new PerContainerLifetime()); + composition.Container.RegisterSingleton(_ => GlobalHost.ConnectionManager.GetHubContext()); } // using a lazy arg here means that we won't create the hub until necessary diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 3ba65cd568..07850275d3 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -110,6 +110,7 @@ + @@ -165,7 +166,7 @@ - + diff --git a/src/Umbraco.Web/UmbracoApplication.cs b/src/Umbraco.Web/UmbracoApplication.cs index 136f09f83d..bd790cdfb2 100644 --- a/src/Umbraco.Web/UmbracoApplication.cs +++ b/src/Umbraco.Web/UmbracoApplication.cs @@ -1,4 +1,5 @@ using Umbraco.Core; +using Umbraco.Core.Composing; using Umbraco.Web.Runtime; namespace Umbraco.Web @@ -12,5 +13,10 @@ namespace Umbraco.Web { return new WebRuntime(this); } + + protected override IContainer GetContainer() + { + return new Web.Composing.LightInject.LightInjectContainer(new LightInject.ServiceContainer()); + } } } From 97da0829a2c49bca345eca18e89eb6ec8cd14558 Mon Sep 17 00:00:00 2001 From: Stephan Date: Fri, 20 Jul 2018 16:36:46 +0200 Subject: [PATCH 025/469] Refactor collection builders for IContainer --- .../Cache/CacheRefresherCollectionBuilder.cs | 6 ++-- .../Composing/CollectionBuilderBase.cs | 26 +++++++++------- src/Umbraco.Core/Composing/IContainer.cs | 14 +++++++-- .../Composing/LazyCollectionBuilderBase.cs | 7 ++--- .../LightInject/LightInjectContainer.cs | 26 +++++++++++++--- .../MixedLightInjectScopeManagerProvider.cs | 2 +- .../Composing/LightInjectExtensions.cs | 2 +- .../Composing/OrderedCollectionBuilderBase.cs | 5 ++- src/Umbraco.Core/Composing/Registration.cs | 31 +++++++++++++++++++ .../WeightedCollectionBuilderBase.cs | 3 +- src/Umbraco.Core/ContainerExtensions.cs | 4 +++ .../Migrations/MigrationBuilder.cs | 1 - .../PostMigrationCollectionBuilder.cs | 7 ++--- .../Mappers/MapperCollectionBuilder.cs | 5 ++- .../DataEditorCollectionBuilder.cs | 5 ++- ...ManifestValueValidatorCollectionBuilder.cs | 5 ++- ...PropertyValueConverterCollectionBuilder.cs | 5 ++- .../UrlSegmentProviderCollectionBuilder.cs | 5 ++- src/Umbraco.Core/Umbraco.Core.csproj | 3 +- .../PackageActionCollectionBuilder.cs | 5 ++- .../Composing/CollectionBuildersTests.cs | 12 +++---- .../Composing/LazyCollectionBuilderTests.cs | 29 ++++++----------- .../Integration/ContentEventsTests.cs | 2 +- src/Umbraco.Tests/Issues/U9560.cs | 2 +- src/Umbraco.Tests/Models/ContentTests.cs | 2 +- .../Models/Mapping/AutoMapperTests.cs | 1 + .../Repositories/DictionaryRepositoryTest.cs | 3 +- .../PartialViewRepositoryTests.cs | 4 +-- .../Repositories/ScriptRepositoryTest.cs | 26 ++++++++-------- .../Routing/DomainsAndCulturesTests.cs | 4 +-- src/Umbraco.Tests/Routing/UrlProviderTests.cs | 1 + .../Routing/UrlRoutingTestBase.cs | 2 +- .../Routing/UrlsProviderWithDomainsTests.cs | 2 +- .../Routing/UrlsWithNestedDomains.cs | 2 +- .../Web/Controllers/UsersControllerTests.cs | 6 ++-- .../Web/Mvc/SurfaceControllerTests.cs | 3 +- .../LightInject/LightInjectContainer.cs | 5 ++- .../EditorValidatorCollectionBuilder.cs | 5 ++- ...heckNotificationMethodCollectionBuilder.cs | 5 ++- .../HeathCheckCollectionBuilder.cs | 7 ++--- ...teredControllerFactoryCollectionBuilder.cs | 5 ++- .../Routing/ContentFinderCollectionBuilder.cs | 5 ++- .../Routing/UrlProviderCollectionBuilder.cs | 5 ++- .../Search/SearchableTreeCollectionBuilder.cs | 5 ++- .../Tour/TourFilterCollectionBuilder.cs | 7 ++--- 45 files changed, 175 insertions(+), 142 deletions(-) rename src/Umbraco.Core/Composing/{ => LightInject}/MixedLightInjectScopeManagerProvider.cs (97%) create mode 100644 src/Umbraco.Core/Composing/Registration.cs diff --git a/src/Umbraco.Core/Cache/CacheRefresherCollectionBuilder.cs b/src/Umbraco.Core/Cache/CacheRefresherCollectionBuilder.cs index 11ac05844b..bb4a14c147 100644 --- a/src/Umbraco.Core/Cache/CacheRefresherCollectionBuilder.cs +++ b/src/Umbraco.Core/Cache/CacheRefresherCollectionBuilder.cs @@ -1,12 +1,10 @@ -using System.Collections.Generic; -using LightInject; -using Umbraco.Core.Composing; +using Umbraco.Core.Composing; namespace Umbraco.Core.Cache { public class CacheRefresherCollectionBuilder : LazyCollectionBuilderBase { - public CacheRefresherCollectionBuilder(IServiceContainer container) + public CacheRefresherCollectionBuilder(IContainer container) : base(container) { } diff --git a/src/Umbraco.Core/Composing/CollectionBuilderBase.cs b/src/Umbraco.Core/Composing/CollectionBuilderBase.cs index 2dbefc860f..ecbd9533ee 100644 --- a/src/Umbraco.Core/Composing/CollectionBuilderBase.cs +++ b/src/Umbraco.Core/Composing/CollectionBuilderBase.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; -using LightInject; namespace Umbraco.Core.Composing { @@ -19,14 +18,14 @@ namespace Umbraco.Core.Composing private readonly List _types = new List(); private readonly object _locker = new object(); private Func, TCollection> _collectionCtor; - private ServiceRegistration[] _registrations; + private Registration[] _registrations; /// /// Initializes a new instance of the /// class with a service container. /// - /// A service container. - protected CollectionBuilderBase(IServiceContainer container) + /// A container. + protected CollectionBuilderBase(IContainer container) { Container = container; // ReSharper disable once DoNotCallOverridableMethodsInConstructor @@ -34,9 +33,9 @@ namespace Umbraco.Core.Composing } /// - /// Gets the service container. + /// Gets the container. /// - protected IServiceContainer Container { get; } + protected IContainer Container { get; } /// /// Gets the internal list of types as an IEnumerable (immutable). @@ -64,7 +63,7 @@ namespace Umbraco.Core.Composing // else _collectionCtor remains null, assuming CreateCollection has been overriden // we just don't want to support re-registering collections here - var registration = Container.GetAvailableService(); + var registration = Container.GetRegistered().FirstOrDefault(); if (registration != null) throw new InvalidOperationException("Collection builders cannot be registered once the collection itself has been registered."); @@ -75,8 +74,7 @@ namespace Umbraco.Core.Composing /// /// Gets the collection lifetime. /// - /// Return null for transient collections. - protected virtual ILifetime CollectionLifetime => new PerContainerLifetime(); + protected virtual Lifetime CollectionLifetime => Lifetime.Singleton; /// /// Configures the internal list of types. @@ -122,7 +120,11 @@ namespace Umbraco.Core.Composing Container.Register(typeof(TItem), type, name); } - _registrations = Container.AvailableServices + // note: we do this, because we don't want to get "all", + // because other types implementing TItem may be registered, + // and we only want those for *this* builder + + _registrations = Container.GetRegistered(typeof(TItem)) .Where(x => x.ServiceName.StartsWith(prefix)) .OrderBy(x => x.ServiceName) .ToArray(); @@ -134,13 +136,13 @@ namespace Umbraco.Core.Composing /// /// The arguments. /// The collection items. - protected virtual IEnumerable CreateItems(params object[] args) + protected virtual IEnumerable CreateItems(/*params object[] args*/) { RegisterTypes(); // will do it only once var type = typeof (TItem); return _registrations - .Select(x => (TItem) Container.GetInstance(type, x.ServiceName, args)) + .Select(x => (TItem) Container.GetInstance(type, x.ServiceName/*, args*/)) .ToArray(); // safe } diff --git a/src/Umbraco.Core/Composing/IContainer.cs b/src/Umbraco.Core/Composing/IContainer.cs index ba611063e2..6e0417a334 100644 --- a/src/Umbraco.Core/Composing/IContainer.cs +++ b/src/Umbraco.Core/Composing/IContainer.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Reflection; namespace Umbraco.Core.Composing { @@ -66,6 +67,9 @@ namespace Umbraco.Core.Composing /// The type of the service. IEnumerable GetAllInstances(); + // fixme + IEnumerable GetRegistered(Type serviceType); + #endregion #region Registry @@ -117,6 +121,10 @@ namespace Umbraco.Core.Composing /// A collection builder of the specified type. T RegisterCollectionBuilder(); + // fixme - very LightInject specific? or? + void RegisterConstructorDependency(Func factory); + void RegisterConstructorDependency(Func factory); + #endregion #region Control @@ -132,11 +140,11 @@ namespace Umbraco.Core.Composing // fixme - document all these - void ConfigureForUmbraco(); + IContainer ConfigureForUmbraco(); - void ConfigureForWeb(); + IContainer ConfigureForWeb(); - void EnablePerWebRequestScope(); + IContainer EnablePerWebRequestScope(); #endregion } diff --git a/src/Umbraco.Core/Composing/LazyCollectionBuilderBase.cs b/src/Umbraco.Core/Composing/LazyCollectionBuilderBase.cs index 52e5a764fd..04110b2070 100644 --- a/src/Umbraco.Core/Composing/LazyCollectionBuilderBase.cs +++ b/src/Umbraco.Core/Composing/LazyCollectionBuilderBase.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using LightInject; namespace Umbraco.Core.Composing { @@ -16,13 +15,13 @@ namespace Umbraco.Core.Composing where TCollection : IBuilderCollection { private readonly List>> _producers1 = new List>>(); - private readonly List>> _producers2 = new List>>(); + private readonly List>> _producers2 = new List>>(); private readonly List _excluded = new List(); /// /// Initializes a new instance of the class. /// - protected LazyCollectionBuilderBase(IServiceContainer container) + protected LazyCollectionBuilderBase(IContainer container) : base(container) { } @@ -125,7 +124,7 @@ namespace Umbraco.Core.Composing /// /// The types producer. /// The builder. - public TBuilder Add(Func> producer) + public TBuilder Add(Func> producer) { Configure(types => { diff --git a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs index 0cc7700888..de942c1e4c 100644 --- a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs +++ b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Reflection; +using System.Linq; using LightInject; namespace Umbraco.Core.Composing.LightInject @@ -56,6 +57,10 @@ namespace Umbraco.Core.Composing.LightInject public IEnumerable GetAllInstances(Type type) => Container.GetAllInstances(type); + /// + public IEnumerable GetRegistered(Type type) + => Container.GetAvailableServices(type).Select(x => new Registration(x.ServiceType, x.ServiceName)); + #endregion #region Registry @@ -173,6 +178,14 @@ namespace Umbraco.Core.Composing.LightInject public void RegisterOrdered(Type serviceType, Type[] implementingTypes, Lifetime lifetime = Lifetime.Transient) => Container.RegisterOrdered(serviceType, implementingTypes, _ => GetLifetime(lifetime)); + /// + public void RegisterConstructorDependency(Func factory) + => Container.RegisterConstructorDependency((f, x) => factory(this, x)); + + /// + public void RegisterConstructorDependency(Func factory) + => Container.RegisterConstructorDependency((f, x, a) => factory(this, x, a)); + /// public T RegisterCollectionBuilder() => Container.RegisterCollectionBuilder(); @@ -186,7 +199,7 @@ namespace Umbraco.Core.Composing.LightInject => Container.BeginScope(); /// - public void ConfigureForUmbraco() + public IContainer ConfigureForUmbraco() { // supports annotated constructor injections // eg to specify the service name on some services @@ -211,6 +224,8 @@ namespace Umbraco.Core.Composing.LightInject // see notes in MixedLightInjectScopeManagerProvider Container.ScopeManagerProvider = new MixedLightInjectScopeManagerProvider(); + + return this; } private class AssemblyScanner : IAssemblyScanner @@ -234,15 +249,18 @@ namespace Umbraco.Core.Composing.LightInject } /// - public virtual void ConfigureForWeb() - { } + public virtual IContainer ConfigureForWeb() + { + return this; + } /// - public void EnablePerWebRequestScope() + public IContainer EnablePerWebRequestScope() { if (!(Container.ScopeManagerProvider is MixedLightInjectScopeManagerProvider smp)) throw new Exception("Container.ScopeManagerProvider is not MixedLightInjectScopeManagerProvider."); smp.EnablePerWebRequestScope(); + return this; } #endregion diff --git a/src/Umbraco.Core/Composing/MixedLightInjectScopeManagerProvider.cs b/src/Umbraco.Core/Composing/LightInject/MixedLightInjectScopeManagerProvider.cs similarity index 97% rename from src/Umbraco.Core/Composing/MixedLightInjectScopeManagerProvider.cs rename to src/Umbraco.Core/Composing/LightInject/MixedLightInjectScopeManagerProvider.cs index 05bdbc446d..470079c6c0 100644 --- a/src/Umbraco.Core/Composing/MixedLightInjectScopeManagerProvider.cs +++ b/src/Umbraco.Core/Composing/LightInject/MixedLightInjectScopeManagerProvider.cs @@ -1,7 +1,7 @@ using LightInject; using LightInject.Web; -namespace Umbraco.Core.Composing +namespace Umbraco.Core.Composing.LightInject { // by default, the container's scope manager provider is PerThreadScopeManagerProvider, // and then container.EnablePerWebRequestScope() replaces it with PerWebRequestScopeManagerProvider, diff --git a/src/Umbraco.Core/Composing/LightInjectExtensions.cs b/src/Umbraco.Core/Composing/LightInjectExtensions.cs index 446b2850f7..6c8961ec66 100644 --- a/src/Umbraco.Core/Composing/LightInjectExtensions.cs +++ b/src/Umbraco.Core/Composing/LightInjectExtensions.cs @@ -134,7 +134,7 @@ namespace Umbraco.Core.Composing /// /// Updates a registration. /// - private static void UpdateRegistration(Registration registration, Type implementingType, Delegate factoryExpression) + private static void UpdateRegistration(ServiceRegistration registration, Type implementingType, Delegate factoryExpression) { // if the container has compiled already then the registrations have been captured, // and re-registering - although updating available services - does not modify the diff --git a/src/Umbraco.Core/Composing/OrderedCollectionBuilderBase.cs b/src/Umbraco.Core/Composing/OrderedCollectionBuilderBase.cs index 4811551cd2..6dd6945ee1 100644 --- a/src/Umbraco.Core/Composing/OrderedCollectionBuilderBase.cs +++ b/src/Umbraco.Core/Composing/OrderedCollectionBuilderBase.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using LightInject; namespace Umbraco.Core.Composing { @@ -18,7 +17,7 @@ namespace Umbraco.Core.Composing /// Initializes a new instance of the class. /// /// - protected OrderedCollectionBuilderBase(IServiceContainer container) + protected OrderedCollectionBuilderBase(IContainer container) : base (container) { } @@ -92,7 +91,7 @@ namespace Umbraco.Core.Composing /// /// The types to append. /// The builder. - public TBuilder Append(Func> types) + public TBuilder Append(Func> types) { Configure(list => { diff --git a/src/Umbraco.Core/Composing/Registration.cs b/src/Umbraco.Core/Composing/Registration.cs new file mode 100644 index 0000000000..a3cb62522b --- /dev/null +++ b/src/Umbraco.Core/Composing/Registration.cs @@ -0,0 +1,31 @@ +using System; + +namespace Umbraco.Core.Composing +{ + /// + /// Represents a service registration in the container. + /// + public class Registration + { + /// + /// Initializes a new instance of the class. + /// + /// + /// + public Registration(Type serviceType, string serviceName) + { + ServiceType = serviceType; + ServiceName = serviceName; + } + + /// + /// Gets the service type. + /// + public Type ServiceType { get; } + + /// + /// Gets the service name. + /// + public string ServiceName { get; } + } +} diff --git a/src/Umbraco.Core/Composing/WeightedCollectionBuilderBase.cs b/src/Umbraco.Core/Composing/WeightedCollectionBuilderBase.cs index 99fa2d3eb9..499984a931 100644 --- a/src/Umbraco.Core/Composing/WeightedCollectionBuilderBase.cs +++ b/src/Umbraco.Core/Composing/WeightedCollectionBuilderBase.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using LightInject; namespace Umbraco.Core.Composing { @@ -19,7 +18,7 @@ namespace Umbraco.Core.Composing /// Initializes a new instance of the class. /// /// - protected WeightedCollectionBuilderBase(IServiceContainer container) + protected WeightedCollectionBuilderBase(IContainer container) : base(container) { } diff --git a/src/Umbraco.Core/ContainerExtensions.cs b/src/Umbraco.Core/ContainerExtensions.cs index ddaab485c1..0a45de4f15 100644 --- a/src/Umbraco.Core/ContainerExtensions.cs +++ b/src/Umbraco.Core/ContainerExtensions.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using Umbraco.Core.Composing; namespace Umbraco.Core @@ -45,6 +46,9 @@ namespace Umbraco.Core // fixme - document all these + public static IEnumerable GetRegistered(this IContainer container) + => container.GetRegistered(typeof(TService)); + public static void Register(this IContainer container, Lifetime lifetime = Lifetime.Transient) => container.Register(typeof(TService), typeof(TImplementing), lifetime); diff --git a/src/Umbraco.Core/Migrations/MigrationBuilder.cs b/src/Umbraco.Core/Migrations/MigrationBuilder.cs index fb01afc35a..c4a06f4789 100644 --- a/src/Umbraco.Core/Migrations/MigrationBuilder.cs +++ b/src/Umbraco.Core/Migrations/MigrationBuilder.cs @@ -1,5 +1,4 @@ using System; -using LightInject; using Umbraco.Core.Composing; namespace Umbraco.Core.Migrations diff --git a/src/Umbraco.Core/Migrations/PostMigrationCollectionBuilder.cs b/src/Umbraco.Core/Migrations/PostMigrationCollectionBuilder.cs index 63cdaf4454..ba3eb96ce9 100644 --- a/src/Umbraco.Core/Migrations/PostMigrationCollectionBuilder.cs +++ b/src/Umbraco.Core/Migrations/PostMigrationCollectionBuilder.cs @@ -1,16 +1,15 @@ -using LightInject; -using Umbraco.Core.Composing; +using Umbraco.Core.Composing; namespace Umbraco.Core.Migrations { public class PostMigrationCollectionBuilder : LazyCollectionBuilderBase { - public PostMigrationCollectionBuilder(IServiceContainer container) + public PostMigrationCollectionBuilder(IContainer container) : base(container) { } protected override PostMigrationCollectionBuilder This => this; - protected override ILifetime CollectionLifetime => null; // transient + protected override Lifetime CollectionLifetime => Lifetime.Transient; } } diff --git a/src/Umbraco.Core/Persistence/Mappers/MapperCollectionBuilder.cs b/src/Umbraco.Core/Persistence/Mappers/MapperCollectionBuilder.cs index 82085027ab..f861c450aa 100644 --- a/src/Umbraco.Core/Persistence/Mappers/MapperCollectionBuilder.cs +++ b/src/Umbraco.Core/Persistence/Mappers/MapperCollectionBuilder.cs @@ -1,11 +1,10 @@ -using LightInject; -using Umbraco.Core.Composing; +using Umbraco.Core.Composing; namespace Umbraco.Core.Persistence.Mappers { public class MapperCollectionBuilder : LazyCollectionBuilderBase { - public MapperCollectionBuilder(IServiceContainer container) + public MapperCollectionBuilder(IContainer container) : base(container) { } diff --git a/src/Umbraco.Core/PropertyEditors/DataEditorCollectionBuilder.cs b/src/Umbraco.Core/PropertyEditors/DataEditorCollectionBuilder.cs index 2a53142a1c..c23972c684 100644 --- a/src/Umbraco.Core/PropertyEditors/DataEditorCollectionBuilder.cs +++ b/src/Umbraco.Core/PropertyEditors/DataEditorCollectionBuilder.cs @@ -1,11 +1,10 @@ -using LightInject; -using Umbraco.Core.Composing; +using Umbraco.Core.Composing; namespace Umbraco.Core.PropertyEditors { public class DataEditorCollectionBuilder : LazyCollectionBuilderBase { - public DataEditorCollectionBuilder(IServiceContainer container) + public DataEditorCollectionBuilder(IContainer container) : base(container) { } diff --git a/src/Umbraco.Core/PropertyEditors/ManifestValueValidatorCollectionBuilder.cs b/src/Umbraco.Core/PropertyEditors/ManifestValueValidatorCollectionBuilder.cs index d616ecf715..3ba6f4e402 100644 --- a/src/Umbraco.Core/PropertyEditors/ManifestValueValidatorCollectionBuilder.cs +++ b/src/Umbraco.Core/PropertyEditors/ManifestValueValidatorCollectionBuilder.cs @@ -1,11 +1,10 @@ -using LightInject; -using Umbraco.Core.Composing; +using Umbraco.Core.Composing; namespace Umbraco.Core.PropertyEditors { internal class ManifestValueValidatorCollectionBuilder : LazyCollectionBuilderBase { - public ManifestValueValidatorCollectionBuilder(IServiceContainer container) + public ManifestValueValidatorCollectionBuilder(IContainer container) : base(container) { } diff --git a/src/Umbraco.Core/PropertyEditors/PropertyValueConverterCollectionBuilder.cs b/src/Umbraco.Core/PropertyEditors/PropertyValueConverterCollectionBuilder.cs index 5c5a8c16c8..e95159ed0b 100644 --- a/src/Umbraco.Core/PropertyEditors/PropertyValueConverterCollectionBuilder.cs +++ b/src/Umbraco.Core/PropertyEditors/PropertyValueConverterCollectionBuilder.cs @@ -1,11 +1,10 @@ -using LightInject; -using Umbraco.Core.Composing; +using Umbraco.Core.Composing; namespace Umbraco.Core.PropertyEditors { public class PropertyValueConverterCollectionBuilder : OrderedCollectionBuilderBase { - public PropertyValueConverterCollectionBuilder(IServiceContainer container) + public PropertyValueConverterCollectionBuilder(IContainer container) : base(container) { } diff --git a/src/Umbraco.Core/Strings/UrlSegmentProviderCollectionBuilder.cs b/src/Umbraco.Core/Strings/UrlSegmentProviderCollectionBuilder.cs index a9b8234e14..7c45bf0884 100644 --- a/src/Umbraco.Core/Strings/UrlSegmentProviderCollectionBuilder.cs +++ b/src/Umbraco.Core/Strings/UrlSegmentProviderCollectionBuilder.cs @@ -1,11 +1,10 @@ -using LightInject; -using Umbraco.Core.Composing; +using Umbraco.Core.Composing; namespace Umbraco.Core.Strings { public class UrlSegmentProviderCollectionBuilder : OrderedCollectionBuilderBase { - public UrlSegmentProviderCollectionBuilder(IServiceContainer container) + public UrlSegmentProviderCollectionBuilder(IContainer container) : base(container) { } diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index efea4bdd22..8d24625f6d 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -170,8 +170,9 @@ - + + diff --git a/src/Umbraco.Core/_Legacy/PackageActions/PackageActionCollectionBuilder.cs b/src/Umbraco.Core/_Legacy/PackageActions/PackageActionCollectionBuilder.cs index 42ab3ec7c2..a92d340b48 100644 --- a/src/Umbraco.Core/_Legacy/PackageActions/PackageActionCollectionBuilder.cs +++ b/src/Umbraco.Core/_Legacy/PackageActions/PackageActionCollectionBuilder.cs @@ -1,11 +1,10 @@ -using LightInject; -using Umbraco.Core.Composing; +using Umbraco.Core.Composing; namespace Umbraco.Core._Legacy.PackageActions { internal class PackageActionCollectionBuilder : LazyCollectionBuilderBase { - public PackageActionCollectionBuilder(IServiceContainer container) + public PackageActionCollectionBuilder(IContainer container) : base(container) { } diff --git a/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs b/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs index 3ab554b28e..d34df9b8b2 100644 --- a/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs +++ b/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs @@ -435,7 +435,7 @@ namespace Umbraco.Tests.Composing // ReSharper disable once ClassNeverInstantiated.Local private class TestCollectionBuilder : OrderedCollectionBuilderBase { - public TestCollectionBuilder(IServiceContainer container) + public TestCollectionBuilder(IContainer container) : base(container) { } @@ -445,31 +445,31 @@ namespace Umbraco.Tests.Composing // ReSharper disable once ClassNeverInstantiated.Local private class TestCollectionBuilderTransient : OrderedCollectionBuilderBase { - public TestCollectionBuilderTransient(IServiceContainer container) + public TestCollectionBuilderTransient(IContainer container) : base(container) { } protected override TestCollectionBuilderTransient This => this; - protected override ILifetime CollectionLifetime => null; // transient + protected override Lifetime CollectionLifetime => Lifetime.Transient; // transient } // ReSharper disable once ClassNeverInstantiated.Local private class TestCollectionBuilderScope : OrderedCollectionBuilderBase { - public TestCollectionBuilderScope(IServiceContainer container) + public TestCollectionBuilderScope(IContainer container) : base(container) { } protected override TestCollectionBuilderScope This => this; - protected override ILifetime CollectionLifetime => new PerScopeLifetime(); + protected override Lifetime CollectionLifetime => Lifetime.Scope; } // ReSharper disable once ClassNeverInstantiated.Local private class TestCollectionBuilderWeighted : WeightedCollectionBuilderBase { - public TestCollectionBuilderWeighted(IServiceContainer container) + public TestCollectionBuilderWeighted(IContainer container) : base(container) { } diff --git a/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs b/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs index a9b7dd5ba0..97dde9e43a 100644 --- a/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs +++ b/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs @@ -1,11 +1,9 @@ using System; using System.Collections.Generic; using System.Linq; -using LightInject; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Composing; -using Umbraco.Core.Composing.LightInject; namespace Umbraco.Tests.Composing { @@ -24,6 +22,9 @@ namespace Umbraco.Tests.Composing Current.Reset(); } + private IContainer CreateContainer() + => Current.Container = (new Core.Composing.LightInject.LightInjectContainer(new LightInject.ServiceContainer())).ConfigureForUmbraco(); + // note // lazy collection builder does not throw on duplicate, just uses distinct types // so we don't have a test for duplicates as we had with resolvers in v7 @@ -31,9 +32,7 @@ namespace Umbraco.Tests.Composing [Test] public void LazyCollectionBuilderHandlesTypes() { - var container = new ServiceContainer(); - container.ConfigureUmbracoCore(); - Current.Container = new LightInjectContainer(container); + var container = CreateContainer(); container.RegisterCollectionBuilder() .Add() @@ -56,9 +55,7 @@ namespace Umbraco.Tests.Composing [Test] public void LazyCollectionBuilderHandlesProducers() { - var container = new ServiceContainer(); - container.ConfigureUmbracoCore(); - Current.Container = new LightInjectContainer(container); + var container = CreateContainer(); container.RegisterCollectionBuilder() .Add(() => new[] { typeof(TransientObject3), typeof(TransientObject2) }) @@ -80,9 +77,7 @@ namespace Umbraco.Tests.Composing [Test] public void LazyCollectionBuilderHandlesTypesAndProducers() { - var container = new ServiceContainer(); - container.ConfigureUmbracoCore(); - Current.Container = new LightInjectContainer(container); + var container = CreateContainer(); container.RegisterCollectionBuilder() .Add() @@ -105,9 +100,7 @@ namespace Umbraco.Tests.Composing [Test] public void LazyCollectionBuilderThrowsOnIllegalTypes() { - var container = new ServiceContainer(); - container.ConfigureUmbracoCore(); - Current.Container = new LightInjectContainer(container); + var container = CreateContainer(); container.RegisterCollectionBuilder() .Add() @@ -128,9 +121,7 @@ namespace Umbraco.Tests.Composing [Test] public void LazyCollectionBuilderCanExcludeTypes() { - var container = new ServiceContainer(); - container.ConfigureUmbracoCore(); - Current.Container = new LightInjectContainer(container); + var container = CreateContainer(); container.RegisterCollectionBuilder() .Add() @@ -171,13 +162,13 @@ namespace Umbraco.Tests.Composing // ReSharper disable once ClassNeverInstantiated.Local private class TestCollectionBuilder : LazyCollectionBuilderBase { - public TestCollectionBuilder(IServiceContainer container) + public TestCollectionBuilder(IContainer container) : base(container) { } protected override TestCollectionBuilder This => this; - protected override ILifetime CollectionLifetime => null; // transient + protected override Lifetime CollectionLifetime => Lifetime.Transient; // transient } // ReSharper disable once ClassNeverInstantiated.Local diff --git a/src/Umbraco.Tests/Integration/ContentEventsTests.cs b/src/Umbraco.Tests/Integration/ContentEventsTests.cs index 05708a88a3..4356d3733f 100644 --- a/src/Umbraco.Tests/Integration/ContentEventsTests.cs +++ b/src/Umbraco.Tests/Integration/ContentEventsTests.cs @@ -54,7 +54,7 @@ namespace Umbraco.Tests.Integration base.Compose(); Container.Register(_ => new TestServerRegistrar()); // localhost-only - Container.Register(new PerContainerLifetime()); + Container.RegisterSingleton(); Container.RegisterCollectionBuilder() .Add() diff --git a/src/Umbraco.Tests/Issues/U9560.cs b/src/Umbraco.Tests/Issues/U9560.cs index c5748e21e0..34cf23bbb8 100644 --- a/src/Umbraco.Tests/Issues/U9560.cs +++ b/src/Umbraco.Tests/Issues/U9560.cs @@ -3,7 +3,7 @@ using NUnit.Framework; using Umbraco.Core.Models; using Umbraco.Core.Persistence; using Umbraco.Tests.Testing; -using LightInject; +using Umbraco.Core; using Umbraco.Tests.TestHelpers; namespace Umbraco.Tests.Issues diff --git a/src/Umbraco.Tests/Models/ContentTests.cs b/src/Umbraco.Tests/Models/ContentTests.cs index ba1a4e739c..7704854471 100644 --- a/src/Umbraco.Tests/Models/ContentTests.cs +++ b/src/Umbraco.Tests/Models/ContentTests.cs @@ -6,7 +6,7 @@ using System.IO; using System.Linq; using System.Web; using Moq; -using LightInject; +using Umbraco.Core; using NUnit.Framework; using Umbraco.Core.Cache; using Umbraco.Core.Configuration.UmbracoSettings; diff --git a/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs b/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs index 349804a432..0196a86b9a 100644 --- a/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs +++ b/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using AutoMapper; using NUnit.Framework; +using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Manifest; using Umbraco.Core.PropertyEditors; diff --git a/src/Umbraco.Tests/Persistence/Repositories/DictionaryRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DictionaryRepositoryTest.cs index 8e8306095f..04a000b4f3 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DictionaryRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DictionaryRepositoryTest.cs @@ -6,8 +6,7 @@ using Umbraco.Core.Models; using Umbraco.Core.Persistence.Repositories; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; -using LightInject; -using Umbraco.Core.Scoping; +using Umbraco.Core; namespace Umbraco.Tests.Persistence.Repositories { diff --git a/src/Umbraco.Tests/Persistence/Repositories/PartialViewRepositoryTests.cs b/src/Umbraco.Tests/Persistence/Repositories/PartialViewRepositoryTests.cs index 79cb1dd4f1..99b5972c45 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/PartialViewRepositoryTests.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/PartialViewRepositoryTests.cs @@ -1,13 +1,11 @@ using System.Linq; using Moq; using NUnit.Framework; +using Umbraco.Core; using Umbraco.Core.IO; using Umbraco.Core.Models; -using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.PropertyEditors; -using Umbraco.Core.Composing; using Umbraco.Core.Persistence.Repositories.Implement; -using Umbraco.Core.Scoping; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; diff --git a/src/Umbraco.Tests/Persistence/Repositories/ScriptRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ScriptRepositoryTest.cs index e414fc1c3a..2f346ff976 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ScriptRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ScriptRepositoryTest.cs @@ -3,8 +3,8 @@ using System.Linq; using System.Text; using Moq; using NUnit.Framework; +using Umbraco.Core; using Umbraco.Core.Configuration.UmbracoSettings; -using Umbraco.Core.Composing; using Umbraco.Core.IO; using Umbraco.Core.Models; using Umbraco.Core.Persistence.Repositories.Implement; @@ -68,7 +68,7 @@ namespace Umbraco.Tests.Persistence.Repositories // Act var script = new Script("test-add-script.js") { Content = "/// " }; repository.Save(script); - + //Assert Assert.That(_fileSystem.FileExists("test-add-script.js"), Is.True); @@ -87,11 +87,11 @@ namespace Umbraco.Tests.Persistence.Repositories // Act var script = new Script("test-updated-script.js") { Content = "/// " }; repository.Save(script); - + script.Content = "/// "; repository.Save(script); - + var scriptUpdated = repository.Get("test-updated-script.js"); @@ -113,7 +113,7 @@ namespace Umbraco.Tests.Persistence.Repositories // Act var script = repository.Get("test-script.js"); repository.Delete(script); - + // Assert @@ -155,7 +155,7 @@ namespace Umbraco.Tests.Persistence.Repositories repository.Save(script2); var script3 = new Script("test-script3.js") { Content = "/// " }; repository.Save(script3); - + // Act var scripts = repository.GetMany(); @@ -183,7 +183,7 @@ namespace Umbraco.Tests.Persistence.Repositories repository.Save(script2); var script3 = new Script("test-script3.js") { Content = "/// " }; repository.Save(script3); - + // Act var scripts = repository.GetMany("test-script1.js", "test-script2.js"); @@ -226,13 +226,13 @@ namespace Umbraco.Tests.Persistence.Repositories var script = new Script("test-move-script.js") { Content = content }; repository.Save(script); - + // Act script = repository.Get("test-move-script.js"); script.Path = "moved/test-move-script.js"; repository.Save(script); - + var existsOld = repository.Exists("test-move-script.js"); var existsNew = repository.Exists("moved/test-move-script.js"); @@ -259,7 +259,7 @@ namespace Umbraco.Tests.Persistence.Repositories var script = new Script("test-path-1.js") { Content = "// script" }; repository.Save(script); - + Assert.IsTrue(_fileSystem.FileExists("test-path-1.js")); Assert.AreEqual("test-path-1.js", script.Path); Assert.AreEqual("/scripts/test-path-1.js", script.VirtualPath); @@ -267,14 +267,14 @@ namespace Umbraco.Tests.Persistence.Repositories //ensure you can prefix the same path as the root path name script = new Script("scripts/path-2/test-path-2.js") { Content = "// script" }; repository.Save(script); - + Assert.IsTrue(_fileSystem.FileExists("scripts/path-2/test-path-2.js")); Assert.AreEqual("scripts\\path-2\\test-path-2.js", script.Path); Assert.AreEqual("/scripts/scripts/path-2/test-path-2.js", script.VirtualPath); script = new Script("path-2/test-path-2.js") { Content = "// script" }; repository.Save(script); - + Assert.IsTrue(_fileSystem.FileExists("path-2/test-path-2.js")); Assert.AreEqual("path-2\\test-path-2.js", script.Path); // fixed in 7.3 - 7.2.8 does not update the path Assert.AreEqual("/scripts/path-2/test-path-2.js", script.VirtualPath); @@ -286,7 +286,7 @@ namespace Umbraco.Tests.Persistence.Repositories script = new Script("path-2\\test-path-3.js") { Content = "// script" }; repository.Save(script); - + Assert.IsTrue(_fileSystem.FileExists("path-2/test-path-3.js")); Assert.AreEqual("path-2\\test-path-3.js", script.Path); Assert.AreEqual("/scripts/path-2/test-path-3.js", script.VirtualPath); diff --git a/src/Umbraco.Tests/Routing/DomainsAndCulturesTests.cs b/src/Umbraco.Tests/Routing/DomainsAndCulturesTests.cs index 987fa0a869..a4bc1e9a12 100644 --- a/src/Umbraco.Tests/Routing/DomainsAndCulturesTests.cs +++ b/src/Umbraco.Tests/Routing/DomainsAndCulturesTests.cs @@ -1,9 +1,9 @@ -using System; -using Moq; +using Moq; using NUnit.Framework; using Umbraco.Core.Models; using Umbraco.Tests.TestHelpers; using Umbraco.Web.Routing; +using Umbraco.Core; namespace Umbraco.Tests.Routing { diff --git a/src/Umbraco.Tests/Routing/UrlProviderTests.cs b/src/Umbraco.Tests/Routing/UrlProviderTests.cs index 2f1e4e3476..f5637118c3 100644 --- a/src/Umbraco.Tests/Routing/UrlProviderTests.cs +++ b/src/Umbraco.Tests/Routing/UrlProviderTests.cs @@ -4,6 +4,7 @@ using System.Globalization; using System.Linq; using Moq; using NUnit.Framework; +using Umbraco.Core; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; diff --git a/src/Umbraco.Tests/Routing/UrlRoutingTestBase.cs b/src/Umbraco.Tests/Routing/UrlRoutingTestBase.cs index 6965c4dce9..bf94d2ffbf 100644 --- a/src/Umbraco.Tests/Routing/UrlRoutingTestBase.cs +++ b/src/Umbraco.Tests/Routing/UrlRoutingTestBase.cs @@ -2,7 +2,7 @@ using System.Linq; using Moq; using NUnit.Framework; -using Umbraco.Core.Composing; +using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Services; using Umbraco.Tests.TestHelpers; diff --git a/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs b/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs index c6bd0fdb88..face9b8c05 100644 --- a/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs +++ b/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs @@ -3,12 +3,12 @@ using System.Collections.Generic; using System.Linq; using Moq; using NUnit.Framework; +using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Services; using Umbraco.Tests.TestHelpers; using Umbraco.Web.PublishedCache.XmlPublishedCache; using Umbraco.Web.Routing; -using Umbraco.Core.Composing; namespace Umbraco.Tests.Routing { diff --git a/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs b/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs index 6b2737a3d1..f23ca66f99 100644 --- a/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs +++ b/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs @@ -1,12 +1,12 @@ using System; using Moq; using NUnit.Framework; +using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Tests.TestHelpers; using Umbraco.Web.PublishedCache.XmlPublishedCache; using Umbraco.Web.Routing; using Umbraco.Core.Services; -using Umbraco.Core.Composing; namespace Umbraco.Tests.Routing { diff --git a/src/Umbraco.Tests/Web/Controllers/UsersControllerTests.cs b/src/Umbraco.Tests/Web/Controllers/UsersControllerTests.cs index 6604e25aa2..4292cffdb0 100644 --- a/src/Umbraco.Tests/Web/Controllers/UsersControllerTests.cs +++ b/src/Umbraco.Tests/Web/Controllers/UsersControllerTests.cs @@ -6,6 +6,7 @@ using System.Web.Http; using Moq; using Newtonsoft.Json; using NUnit.Framework; +using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; @@ -41,7 +42,7 @@ namespace Umbraco.Tests.Web.Controllers // kill the true IEntityService too Container.RegisterSingleton(f => Mock.Of()); - + Container.RegisterSingleton(); } @@ -68,7 +69,6 @@ namespace Umbraco.Tests.Web.Controllers .Returns((int id) => id == 1234 ? new User(1234, "Test", "test@test.com", "test@test.com", "", new List(), new int[0], new int[0]) : null); var usersController = new UsersController(); - Container.InjectProperties(usersController); return usersController; } @@ -125,7 +125,6 @@ namespace Umbraco.Tests.Web.Controllers ApiController Factory(HttpRequestMessage message, UmbracoHelper helper) { var usersController = new UsersController(); - Container.InjectProperties(usersController); return usersController; } @@ -153,7 +152,6 @@ namespace Umbraco.Tests.Web.Controllers .Returns(() => users); var usersController = new UsersController(); - Container.InjectProperties(usersController); return usersController; } diff --git a/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs b/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs index 22bf9ef602..bd68325e06 100644 --- a/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs +++ b/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs @@ -95,7 +95,6 @@ namespace Umbraco.Tests.Web.Mvc var controller = new TestSurfaceController(umbracoContext); Container.Register(_ => umbracoContext); - Container.InjectProperties(controller); Assert.IsNotNull(controller.Umbraco); } @@ -187,7 +186,7 @@ namespace Umbraco.Tests.Web.Mvc : base(ctx, null, new ServiceContext(), Mock.Of(), null, null) { if (helper != null) - { + { Umbraco = helper; } } diff --git a/src/Umbraco.Web/Composing/LightInject/LightInjectContainer.cs b/src/Umbraco.Web/Composing/LightInject/LightInjectContainer.cs index 1cc30be73f..cf6a949fac 100644 --- a/src/Umbraco.Web/Composing/LightInject/LightInjectContainer.cs +++ b/src/Umbraco.Web/Composing/LightInject/LightInjectContainer.cs @@ -2,6 +2,7 @@ using System.Web.Http; using LightInject; using Umbraco.Core.Composing; +using Umbraco.Core.Composing.LightInject; namespace Umbraco.Web.Composing.LightInject { @@ -18,7 +19,7 @@ namespace Umbraco.Web.Composing.LightInject { } /// - public override void ConfigureForWeb() + public override IContainer ConfigureForWeb() { // IoC setup for LightInject for MVC/WebApi // see comments on MixedLightInjectScopeManagerProvider for explainations of what we are doing here @@ -27,6 +28,8 @@ namespace Umbraco.Web.Composing.LightInject Container.EnableMvc(); // does container.EnablePerWebRequestScope() Container.ScopeManagerProvider = smp; // reverts - we will do it last (in WebRuntime) Container.EnableWebApi(GlobalConfiguration.Configuration); + + return this; } } } diff --git a/src/Umbraco.Web/Editors/EditorValidatorCollectionBuilder.cs b/src/Umbraco.Web/Editors/EditorValidatorCollectionBuilder.cs index e05c85a1b6..3189f2e71f 100644 --- a/src/Umbraco.Web/Editors/EditorValidatorCollectionBuilder.cs +++ b/src/Umbraco.Web/Editors/EditorValidatorCollectionBuilder.cs @@ -1,11 +1,10 @@ -using LightInject; -using Umbraco.Core.Composing; +using Umbraco.Core.Composing; namespace Umbraco.Web.Editors { internal class EditorValidatorCollectionBuilder : LazyCollectionBuilderBase { - public EditorValidatorCollectionBuilder(IServiceContainer container) + public EditorValidatorCollectionBuilder(IContainer container) : base(container) { } diff --git a/src/Umbraco.Web/HealthCheck/HealthCheckNotificationMethodCollectionBuilder.cs b/src/Umbraco.Web/HealthCheck/HealthCheckNotificationMethodCollectionBuilder.cs index 4f958da9a0..76a93fe217 100644 --- a/src/Umbraco.Web/HealthCheck/HealthCheckNotificationMethodCollectionBuilder.cs +++ b/src/Umbraco.Web/HealthCheck/HealthCheckNotificationMethodCollectionBuilder.cs @@ -1,12 +1,11 @@ -using LightInject; -using Umbraco.Core.Composing; +using Umbraco.Core.Composing; using Umbraco.Web.HealthCheck.NotificationMethods; namespace Umbraco.Web.HealthCheck { internal class HealthCheckNotificationMethodCollectionBuilder : LazyCollectionBuilderBase { - public HealthCheckNotificationMethodCollectionBuilder(IServiceContainer container) + public HealthCheckNotificationMethodCollectionBuilder(IContainer container) : base(container) { } diff --git a/src/Umbraco.Web/HealthCheck/HeathCheckCollectionBuilder.cs b/src/Umbraco.Web/HealthCheck/HeathCheckCollectionBuilder.cs index 9528f9a9dd..7e600d9238 100644 --- a/src/Umbraco.Web/HealthCheck/HeathCheckCollectionBuilder.cs +++ b/src/Umbraco.Web/HealthCheck/HeathCheckCollectionBuilder.cs @@ -1,11 +1,10 @@ -using LightInject; -using Umbraco.Core.Composing; +using Umbraco.Core.Composing; namespace Umbraco.Web.HealthCheck { public class HealthCheckCollectionBuilder : LazyCollectionBuilderBase { - public HealthCheckCollectionBuilder(IServiceContainer container) + public HealthCheckCollectionBuilder(IContainer container) : base(container) { } @@ -13,6 +12,6 @@ namespace Umbraco.Web.HealthCheck // note: in v7 they were per-request, not sure why? // the collection is injected into the controller & there's only 1 controller per request anyways - protected override ILifetime CollectionLifetime => null; // transient! + protected override Lifetime CollectionLifetime => Lifetime.Transient; // transient! } } diff --git a/src/Umbraco.Web/Mvc/FilteredControllerFactoryCollectionBuilder.cs b/src/Umbraco.Web/Mvc/FilteredControllerFactoryCollectionBuilder.cs index 930b5a1eb2..4ec48bac3f 100644 --- a/src/Umbraco.Web/Mvc/FilteredControllerFactoryCollectionBuilder.cs +++ b/src/Umbraco.Web/Mvc/FilteredControllerFactoryCollectionBuilder.cs @@ -1,11 +1,10 @@ -using LightInject; -using Umbraco.Core.Composing; +using Umbraco.Core.Composing; namespace Umbraco.Web.Mvc { public class FilteredControllerFactoryCollectionBuilder : OrderedCollectionBuilderBase { - public FilteredControllerFactoryCollectionBuilder(IServiceContainer container) + public FilteredControllerFactoryCollectionBuilder(IContainer container) : base(container) { } diff --git a/src/Umbraco.Web/Routing/ContentFinderCollectionBuilder.cs b/src/Umbraco.Web/Routing/ContentFinderCollectionBuilder.cs index 7d9ef952c4..47186dbb74 100644 --- a/src/Umbraco.Web/Routing/ContentFinderCollectionBuilder.cs +++ b/src/Umbraco.Web/Routing/ContentFinderCollectionBuilder.cs @@ -1,11 +1,10 @@ -using LightInject; -using Umbraco.Core.Composing; +using Umbraco.Core.Composing; namespace Umbraco.Web.Routing { public class ContentFinderCollectionBuilder : OrderedCollectionBuilderBase { - public ContentFinderCollectionBuilder(IServiceContainer container) + public ContentFinderCollectionBuilder(IContainer container) : base(container) { } diff --git a/src/Umbraco.Web/Routing/UrlProviderCollectionBuilder.cs b/src/Umbraco.Web/Routing/UrlProviderCollectionBuilder.cs index 196c8a7a25..d66a7554b8 100644 --- a/src/Umbraco.Web/Routing/UrlProviderCollectionBuilder.cs +++ b/src/Umbraco.Web/Routing/UrlProviderCollectionBuilder.cs @@ -1,11 +1,10 @@ -using LightInject; -using Umbraco.Core.Composing; +using Umbraco.Core.Composing; namespace Umbraco.Web.Routing { public class UrlProviderCollectionBuilder : OrderedCollectionBuilderBase { - public UrlProviderCollectionBuilder(IServiceContainer container) + public UrlProviderCollectionBuilder(IContainer container) : base(container) { } diff --git a/src/Umbraco.Web/Search/SearchableTreeCollectionBuilder.cs b/src/Umbraco.Web/Search/SearchableTreeCollectionBuilder.cs index ae83cc5eab..e64738329b 100644 --- a/src/Umbraco.Web/Search/SearchableTreeCollectionBuilder.cs +++ b/src/Umbraco.Web/Search/SearchableTreeCollectionBuilder.cs @@ -1,5 +1,4 @@ -using LightInject; -using Umbraco.Core.Composing; +using Umbraco.Core.Composing; using Umbraco.Core.Services; using Umbraco.Web.Trees; @@ -9,7 +8,7 @@ namespace Umbraco.Web.Search { private readonly IApplicationTreeService _treeService; - public SearchableTreeCollectionBuilder(IServiceContainer container, IApplicationTreeService treeService) + public SearchableTreeCollectionBuilder(IContainer container, IApplicationTreeService treeService) : base(container) { _treeService = treeService; diff --git a/src/Umbraco.Web/Tour/TourFilterCollectionBuilder.cs b/src/Umbraco.Web/Tour/TourFilterCollectionBuilder.cs index 5084975bbd..f521b91f26 100644 --- a/src/Umbraco.Web/Tour/TourFilterCollectionBuilder.cs +++ b/src/Umbraco.Web/Tour/TourFilterCollectionBuilder.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; -using LightInject; using Umbraco.Core; using Umbraco.Core.Composing; @@ -18,14 +17,14 @@ namespace Umbraco.Web.Tour /// /// Initializes a new instance of the class. /// - public TourFilterCollectionBuilder(IServiceContainer container) + public TourFilterCollectionBuilder(IContainer container) : base(container) { } /// - protected override IEnumerable CreateItems(params object[] args) + protected override IEnumerable CreateItems(/*params object[] args*/) { - return base.CreateItems(args).Concat(_instances); + return base.CreateItems(/*args*/).Concat(_instances); } /// From 981152b6938fe5006ff13b09269219e91aa20563 Mon Sep 17 00:00:00 2001 From: Stephan Date: Fri, 20 Jul 2018 16:39:39 +0200 Subject: [PATCH 026/469] Move IContainer extension methods --- .../{ => Composing}/ContainerExtensions.cs | 3 +-- src/Umbraco.Core/Umbraco.Core.csproj | 2 +- .../PublishedCache/PublishedMediaCacheTests.cs | 1 + src/Umbraco.Tests/Issues/U9560.cs | 1 + src/Umbraco.Tests/Models/ContentTests.cs | 1 + src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs | 1 + .../DataTypeDefinitionRepositoryTest.cs | 1 + .../Repositories/DictionaryRepositoryTest.cs | 1 + .../Repositories/PartialViewRepositoryTests.cs | 1 + .../Repositories/ScriptRepositoryTest.cs | 1 + .../PublishedContent/PublishedContentTestBase.cs | 1 + .../PublishedContent/PublishedMediaTests.cs | 1 + src/Umbraco.Tests/Routing/ContentFinderByIdTests.cs | 1 + .../Routing/DomainsAndCulturesTests.cs | 1 + src/Umbraco.Tests/Routing/UmbracoModuleTests.cs | 1 + src/Umbraco.Tests/Routing/UrlProviderTests.cs | 1 + src/Umbraco.Tests/Routing/UrlRoutingTestBase.cs | 1 + .../Routing/UrlsProviderWithDomainsTests.cs | 1 + src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs | 1 + .../Services/ContentServicePerformanceTest.cs | 1 + src/Umbraco.Tests/Services/ContentServiceTests.cs | 1 + .../Strings/DefaultShortStringHelperTests.cs | 1 + src/Umbraco.Tests/Testing/TestingTests/MockTests.cs | 1 + src/Umbraco.Tests/TreesAndSections/SectionTests.cs | 1 + src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs | 1 + src/Umbraco.Web/Cache/CacheRefresherComponent.cs | 3 ++- .../DatabaseServerRegistrarAndMessengerComponent.cs | 13 +++++++------ src/Umbraco.Web/Composing/ModuleInjector.cs | 1 + src/Umbraco.Web/HtmlHelperRenderExtensions.cs | 3 ++- src/Umbraco.Web/Models/LoginStatusModel.cs | 3 ++- src/Umbraco.Web/Models/ProfileModel.cs | 3 ++- src/Umbraco.Web/Models/RegisterModel.cs | 3 ++- .../Mvc/EnsurePublishedContentRequestAttribute.cs | 3 ++- src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs | 5 +++-- .../Mvc/UmbracoVirtualNodeRouteHandler.cs | 1 + .../PublishedCache/NuCache/NuCacheComponent.cs | 1 + .../XmlPublishedCache/XmlCacheComponent.cs | 1 + src/Umbraco.Web/Scheduling/BackgroundTaskRunner.cs | 1 + src/Umbraco.Web/Security/WebSecurity.cs | 3 ++- src/Umbraco.Web/SignalR/PreviewHubComponent.cs | 1 + src/Umbraco.Web/Templates/TemplateRenderer.cs | 3 ++- src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs | 3 ++- src/Umbraco.Web/UmbracoHelper.cs | 3 ++- 43 files changed, 61 insertions(+), 21 deletions(-) rename src/Umbraco.Core/{ => Composing}/ContainerExtensions.cs (98%) diff --git a/src/Umbraco.Core/ContainerExtensions.cs b/src/Umbraco.Core/Composing/ContainerExtensions.cs similarity index 98% rename from src/Umbraco.Core/ContainerExtensions.cs rename to src/Umbraco.Core/Composing/ContainerExtensions.cs index 0a45de4f15..8fb8208c4a 100644 --- a/src/Umbraco.Core/ContainerExtensions.cs +++ b/src/Umbraco.Core/Composing/ContainerExtensions.cs @@ -1,8 +1,7 @@ using System; using System.Collections.Generic; -using Umbraco.Core.Composing; -namespace Umbraco.Core +namespace Umbraco.Core.Composing { /// /// Provides extension methods to the class. diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 8d24625f6d..412b55ea71 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -305,7 +305,7 @@ - + diff --git a/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs b/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs index d0924aa1a6..e4a15a2ac2 100644 --- a/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs +++ b/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs @@ -6,6 +6,7 @@ using Examine; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; +using Umbraco.Core.Composing; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Strings; using Umbraco.Tests.TestHelpers; diff --git a/src/Umbraco.Tests/Issues/U9560.cs b/src/Umbraco.Tests/Issues/U9560.cs index 34cf23bbb8..830a1fb84d 100644 --- a/src/Umbraco.Tests/Issues/U9560.cs +++ b/src/Umbraco.Tests/Issues/U9560.cs @@ -4,6 +4,7 @@ using Umbraco.Core.Models; using Umbraco.Core.Persistence; using Umbraco.Tests.Testing; using Umbraco.Core; +using Umbraco.Core.Composing; using Umbraco.Tests.TestHelpers; namespace Umbraco.Tests.Issues diff --git a/src/Umbraco.Tests/Models/ContentTests.cs b/src/Umbraco.Tests/Models/ContentTests.cs index 7704854471..d1e8b3f29d 100644 --- a/src/Umbraco.Tests/Models/ContentTests.cs +++ b/src/Umbraco.Tests/Models/ContentTests.cs @@ -9,6 +9,7 @@ using Moq; using Umbraco.Core; using NUnit.Framework; using Umbraco.Core.Cache; +using Umbraco.Core.Composing; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; using Umbraco.Core.Logging; diff --git a/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs b/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs index 0196a86b9a..2bf8aeead3 100644 --- a/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs +++ b/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs @@ -5,6 +5,7 @@ using AutoMapper; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; +using Umbraco.Core.Composing; using Umbraco.Core.Manifest; using Umbraco.Core.PropertyEditors; using Umbraco.Tests.TestHelpers; diff --git a/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs index 4a40bfacd0..8b3af9838c 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs @@ -7,6 +7,7 @@ using Umbraco.Core.Persistence.Repositories; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; using LightInject; +using Umbraco.Core.Composing; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Scoping; diff --git a/src/Umbraco.Tests/Persistence/Repositories/DictionaryRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DictionaryRepositoryTest.cs index 04a000b4f3..bd66b83677 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DictionaryRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DictionaryRepositoryTest.cs @@ -7,6 +7,7 @@ using Umbraco.Core.Persistence.Repositories; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; using Umbraco.Core; +using Umbraco.Core.Composing; namespace Umbraco.Tests.Persistence.Repositories { diff --git a/src/Umbraco.Tests/Persistence/Repositories/PartialViewRepositoryTests.cs b/src/Umbraco.Tests/Persistence/Repositories/PartialViewRepositoryTests.cs index 99b5972c45..da9e49876b 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/PartialViewRepositoryTests.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/PartialViewRepositoryTests.cs @@ -2,6 +2,7 @@ using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Composing; using Umbraco.Core.IO; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; diff --git a/src/Umbraco.Tests/Persistence/Repositories/ScriptRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ScriptRepositoryTest.cs index 2f346ff976..98bccaa313 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ScriptRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ScriptRepositoryTest.cs @@ -4,6 +4,7 @@ using System.Text; using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Composing; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; using Umbraco.Core.Models; diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs index 09665a4a7b..a1df9e3720 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs @@ -4,6 +4,7 @@ using Umbraco.Core.PropertyEditors; using Umbraco.Core.PropertyEditors.ValueConverters; using Umbraco.Tests.TestHelpers; using Moq; +using Umbraco.Core.Composing; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Web.PropertyEditors; diff --git a/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs index b9d106ca1b..5f0831bfc6 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs @@ -21,6 +21,7 @@ using Umbraco.Examine; using Current = Umbraco.Web.Composing.Current; using Umbraco.Tests.Testing; using LightInject; +using Umbraco.Core.Composing; using Umbraco.Core.Models.Membership; using Umbraco.Core.Services; diff --git a/src/Umbraco.Tests/Routing/ContentFinderByIdTests.cs b/src/Umbraco.Tests/Routing/ContentFinderByIdTests.cs index 239bfc7ad5..0708287160 100644 --- a/src/Umbraco.Tests/Routing/ContentFinderByIdTests.cs +++ b/src/Umbraco.Tests/Routing/ContentFinderByIdTests.cs @@ -1,5 +1,6 @@ using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Composing; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Tests.TestHelpers; using Umbraco.Web.Routing; diff --git a/src/Umbraco.Tests/Routing/DomainsAndCulturesTests.cs b/src/Umbraco.Tests/Routing/DomainsAndCulturesTests.cs index a4bc1e9a12..df18ec0966 100644 --- a/src/Umbraco.Tests/Routing/DomainsAndCulturesTests.cs +++ b/src/Umbraco.Tests/Routing/DomainsAndCulturesTests.cs @@ -4,6 +4,7 @@ using Umbraco.Core.Models; using Umbraco.Tests.TestHelpers; using Umbraco.Web.Routing; using Umbraco.Core; +using Umbraco.Core.Composing; namespace Umbraco.Tests.Routing { diff --git a/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs b/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs index 504cbfb6ef..e808c577a4 100644 --- a/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs +++ b/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs @@ -4,6 +4,7 @@ using System.Threading; using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Composing; using Umbraco.Tests.TestHelpers; using Umbraco.Web; using Umbraco.Core.IO; diff --git a/src/Umbraco.Tests/Routing/UrlProviderTests.cs b/src/Umbraco.Tests/Routing/UrlProviderTests.cs index f5637118c3..daac1492e4 100644 --- a/src/Umbraco.Tests/Routing/UrlProviderTests.cs +++ b/src/Umbraco.Tests/Routing/UrlProviderTests.cs @@ -5,6 +5,7 @@ using System.Linq; using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Composing; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; diff --git a/src/Umbraco.Tests/Routing/UrlRoutingTestBase.cs b/src/Umbraco.Tests/Routing/UrlRoutingTestBase.cs index bf94d2ffbf..663daf3083 100644 --- a/src/Umbraco.Tests/Routing/UrlRoutingTestBase.cs +++ b/src/Umbraco.Tests/Routing/UrlRoutingTestBase.cs @@ -3,6 +3,7 @@ using System.Linq; using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Composing; using Umbraco.Core.Models; using Umbraco.Core.Services; using Umbraco.Tests.TestHelpers; diff --git a/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs b/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs index face9b8c05..7ef0f69dda 100644 --- a/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs +++ b/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs @@ -4,6 +4,7 @@ using System.Linq; using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Composing; using Umbraco.Core.Models; using Umbraco.Core.Services; using Umbraco.Tests.TestHelpers; diff --git a/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs b/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs index f23ca66f99..dda9005506 100644 --- a/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs +++ b/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs @@ -2,6 +2,7 @@ using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Composing; using Umbraco.Core.Models; using Umbraco.Tests.TestHelpers; using Umbraco.Web.PublishedCache.XmlPublishedCache; diff --git a/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs b/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs index 5f41031a0b..2b73b3385b 100644 --- a/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs +++ b/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs @@ -6,6 +6,7 @@ using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; +using Umbraco.Core.Composing; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; using Umbraco.Core.Logging; diff --git a/src/Umbraco.Tests/Services/ContentServiceTests.cs b/src/Umbraco.Tests/Services/ContentServiceTests.cs index f88abb37a7..c743cd16a6 100644 --- a/src/Umbraco.Tests/Services/ContentServiceTests.cs +++ b/src/Umbraco.Tests/Services/ContentServiceTests.cs @@ -20,6 +20,7 @@ using Umbraco.Core.Services.Implement; using Umbraco.Tests.Testing; using System.Reflection; using Umbraco.Core.Cache; +using Umbraco.Core.Composing; namespace Umbraco.Tests.Services { diff --git a/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs b/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs index 934d06840c..5e8acf03bd 100644 --- a/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs +++ b/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs @@ -6,6 +6,7 @@ using System.Text.RegularExpressions; using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Composing; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Strings; using Umbraco.Tests.TestHelpers; diff --git a/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs b/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs index e64eda1ab4..a00f527c2c 100644 --- a/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs +++ b/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs @@ -6,6 +6,7 @@ using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; +using Umbraco.Core.Composing; using Umbraco.Core.Dictionary; using Umbraco.Core.Logging; using Umbraco.Core.Models; diff --git a/src/Umbraco.Tests/TreesAndSections/SectionTests.cs b/src/Umbraco.Tests/TreesAndSections/SectionTests.cs index e35bd5fd45..077245fb82 100644 --- a/src/Umbraco.Tests/TreesAndSections/SectionTests.cs +++ b/src/Umbraco.Tests/TreesAndSections/SectionTests.cs @@ -5,6 +5,7 @@ using Umbraco.Tests.TestHelpers; using System; using System.Linq; using Umbraco.Core; +using Umbraco.Core.Composing; using Umbraco.Tests.Testing; using Umbraco.Web.Services; diff --git a/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs b/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs index 2597eab631..b56ad43ff5 100644 --- a/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs +++ b/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs @@ -1,6 +1,7 @@ using System.IO; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Composing; using Umbraco.Core.Logging; using Umbraco.Core.Strings; using Umbraco.Tests.TestHelpers; diff --git a/src/Umbraco.Web/Cache/CacheRefresherComponent.cs b/src/Umbraco.Web/Cache/CacheRefresherComponent.cs index 591a54f611..eedaa8cb11 100644 --- a/src/Umbraco.Web/Cache/CacheRefresherComponent.cs +++ b/src/Umbraco.Web/Cache/CacheRefresherComponent.cs @@ -21,6 +21,7 @@ using Umbraco.Web.Composing; using Umbraco.Web.Security; using Umbraco.Web.Services; using ApplicationTree = Umbraco.Core.Models.ApplicationTree; +using ContainerExtensions = Umbraco.Core.Composing.ContainerExtensions; namespace Umbraco.Web.Cache { @@ -236,7 +237,7 @@ namespace Umbraco.Web.Cache UmbracoConfig.For.UmbracoSettings(), Current.UrlProviders, UmbracoConfig.For.GlobalSettings(), - Current.Container.GetInstance(), + ContainerExtensions.GetInstance(Current.Container), true); } diff --git a/src/Umbraco.Web/Components/DatabaseServerRegistrarAndMessengerComponent.cs b/src/Umbraco.Web/Components/DatabaseServerRegistrarAndMessengerComponent.cs index 7a03fb3457..0577c6cdd9 100644 --- a/src/Umbraco.Web/Components/DatabaseServerRegistrarAndMessengerComponent.cs +++ b/src/Umbraco.Web/Components/DatabaseServerRegistrarAndMessengerComponent.cs @@ -15,6 +15,7 @@ using Umbraco.Web.Composing; using Umbraco.Web.Routing; using Umbraco.Web.Scheduling; using Umbraco.Web.Search; +using ContainerExtensions = Umbraco.Core.Composing.ContainerExtensions; namespace Umbraco.Web.Components { @@ -53,12 +54,12 @@ namespace Umbraco.Web.Components { composition.SetServerMessenger(factory => { - var runtime = factory.GetInstance(); - var databaseFactory = factory.GetInstance(); - var globalSettings = factory.GetInstance(); - var proflog = factory.GetInstance(); - var scopeProvider = factory.GetInstance(); - var sqlContext = factory.GetInstance(); + var runtime = ContainerExtensions.GetInstance(factory); + var databaseFactory = ContainerExtensions.GetInstance(factory); + var globalSettings = ContainerExtensions.GetInstance(factory); + var proflog = ContainerExtensions.GetInstance(factory); + var scopeProvider = ContainerExtensions.GetInstance(factory); + var sqlContext = ContainerExtensions.GetInstance(factory); return new BatchedDatabaseServerMessenger( runtime, databaseFactory, scopeProvider, sqlContext, proflog, globalSettings, diff --git a/src/Umbraco.Web/Composing/ModuleInjector.cs b/src/Umbraco.Web/Composing/ModuleInjector.cs index f183cf528e..5938a8060a 100644 --- a/src/Umbraco.Web/Composing/ModuleInjector.cs +++ b/src/Umbraco.Web/Composing/ModuleInjector.cs @@ -1,5 +1,6 @@ using System.Web; using Umbraco.Core; +using Umbraco.Core.Composing; namespace Umbraco.Web.Composing { diff --git a/src/Umbraco.Web/HtmlHelperRenderExtensions.cs b/src/Umbraco.Web/HtmlHelperRenderExtensions.cs index cc625b068c..11ef966a33 100644 --- a/src/Umbraco.Web/HtmlHelperRenderExtensions.cs +++ b/src/Umbraco.Web/HtmlHelperRenderExtensions.cs @@ -13,6 +13,7 @@ using Umbraco.Core.IO; using Umbraco.Web.Composing; using Umbraco.Web.Mvc; using Umbraco.Web.Security; +using ContainerExtensions = Umbraco.Core.Composing.ContainerExtensions; namespace Umbraco.Web { @@ -93,7 +94,7 @@ namespace Umbraco.Web } if (cacheByMember) { - var helper = Current.Container.GetInstance(); + var helper = ContainerExtensions.GetInstance(Current.Container); var currentMember = helper.GetCurrentMember(); cacheKey.AppendFormat("m{0}-", currentMember == null ? 0 : currentMember.Id); } diff --git a/src/Umbraco.Web/Models/LoginStatusModel.cs b/src/Umbraco.Web/Models/LoginStatusModel.cs index 456564c7f5..3d9a1090f9 100644 --- a/src/Umbraco.Web/Models/LoginStatusModel.cs +++ b/src/Umbraco.Web/Models/LoginStatusModel.cs @@ -2,6 +2,7 @@ using Umbraco.Core; using Umbraco.Web.Composing; using Umbraco.Web.Security; +using ContainerExtensions = Umbraco.Core.Composing.ContainerExtensions; namespace Umbraco.Web.Models { @@ -23,7 +24,7 @@ namespace Umbraco.Web.Models { if (doLookup && Current.UmbracoContext != null) { - var helper = Current.Container.GetInstance(); + var helper = ContainerExtensions.GetInstance(Current.Container); var model = helper.GetCurrentLoginStatus(); if (model != null) { diff --git a/src/Umbraco.Web/Models/ProfileModel.cs b/src/Umbraco.Web/Models/ProfileModel.cs index d62f85bd04..17ca54687e 100644 --- a/src/Umbraco.Web/Models/ProfileModel.cs +++ b/src/Umbraco.Web/Models/ProfileModel.cs @@ -6,6 +6,7 @@ using System.Web.Mvc; using Umbraco.Web.Composing; using Umbraco.Web.Security; using Umbraco.Core; +using ContainerExtensions = Umbraco.Core.Composing.ContainerExtensions; namespace Umbraco.Web.Models { @@ -27,7 +28,7 @@ namespace Umbraco.Web.Models MemberProperties = new List(); if (doLookup && Current.UmbracoContext != null) { - var helper = Current.Container.GetInstance(); + var helper = ContainerExtensions.GetInstance(Current.Container); var model = helper.GetCurrentMemberProfileModel(); MemberProperties = model.MemberProperties; } diff --git a/src/Umbraco.Web/Models/RegisterModel.cs b/src/Umbraco.Web/Models/RegisterModel.cs index dc1707aa2d..76d02244b7 100644 --- a/src/Umbraco.Web/Models/RegisterModel.cs +++ b/src/Umbraco.Web/Models/RegisterModel.cs @@ -7,6 +7,7 @@ using System.Web.Mvc; using Umbraco.Core; using Umbraco.Web.Composing; using Umbraco.Web.Security; +using ContainerExtensions = Umbraco.Core.Composing.ContainerExtensions; namespace Umbraco.Web.Models { @@ -31,7 +32,7 @@ namespace Umbraco.Web.Models CreatePersistentLoginCookie = true; if (doLookup && Current.UmbracoContext != null) { - var helper = Current.Container.GetInstance(); + var helper = ContainerExtensions.GetInstance(Current.Container); var model = helper.CreateRegistrationModel(MemberTypeAlias); MemberProperties = model.MemberProperties; } diff --git a/src/Umbraco.Web/Mvc/EnsurePublishedContentRequestAttribute.cs b/src/Umbraco.Web/Mvc/EnsurePublishedContentRequestAttribute.cs index b046a0d89a..56f2d9a55e 100644 --- a/src/Umbraco.Web/Mvc/EnsurePublishedContentRequestAttribute.cs +++ b/src/Umbraco.Web/Mvc/EnsurePublishedContentRequestAttribute.cs @@ -4,6 +4,7 @@ using Umbraco.Web.Routing; using Umbraco.Core; using Umbraco.Core.Models.PublishedContent; using Umbraco.Web.Composing; +using ContainerExtensions = Umbraco.Core.Composing.ContainerExtensions; namespace Umbraco.Web.Mvc { @@ -73,7 +74,7 @@ namespace Umbraco.Web.Mvc protected UmbracoContext UmbracoContext => _umbracoContext ?? (_umbracoContext = UmbracoContext.Current); // todo - try lazy property injection? - private PublishedRouter PublishedRouter => Core.Composing.Current.Container.GetInstance(); + private PublishedRouter PublishedRouter => ContainerExtensions.GetInstance(Core.Composing.Current.Container); /// /// Exposes an UmbracoHelper diff --git a/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs b/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs index e99b3bb410..7f9c07365a 100644 --- a/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs +++ b/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs @@ -13,6 +13,7 @@ using Umbraco.Web.Composing; using Umbraco.Web.Models; using Umbraco.Web.Routing; using Umbraco.Web.Security; +using ContainerExtensions = Umbraco.Core.Composing.ContainerExtensions; namespace Umbraco.Web.Mvc { @@ -108,8 +109,8 @@ namespace Umbraco.Web.Mvc protected UmbracoViewPage() : this( - Current.Container.GetInstance(), - Current.Container.GetInstance() + ContainerExtensions.GetInstance(Current.Container), + ContainerExtensions.GetInstance(Current.Container) ) { } diff --git a/src/Umbraco.Web/Mvc/UmbracoVirtualNodeRouteHandler.cs b/src/Umbraco.Web/Mvc/UmbracoVirtualNodeRouteHandler.cs index 52fcb0a4cb..c4f5acde19 100644 --- a/src/Umbraco.Web/Mvc/UmbracoVirtualNodeRouteHandler.cs +++ b/src/Umbraco.Web/Mvc/UmbracoVirtualNodeRouteHandler.cs @@ -5,6 +5,7 @@ using Umbraco.Core.Models.PublishedContent; using Umbraco.Web.Models; using Umbraco.Web.Routing; using Umbraco.Core; +using Umbraco.Core.Composing; namespace Umbraco.Web.Mvc { diff --git a/src/Umbraco.Web/PublishedCache/NuCache/NuCacheComponent.cs b/src/Umbraco.Web/PublishedCache/NuCache/NuCacheComponent.cs index e526d3853a..0b0effcce9 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/NuCacheComponent.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/NuCacheComponent.cs @@ -1,5 +1,6 @@ using Umbraco.Core.Components; using Umbraco.Core; +using Umbraco.Core.Composing; using Umbraco.Web.PublishedCache.NuCache.DataSource; namespace Umbraco.Web.PublishedCache.NuCache diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlCacheComponent.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlCacheComponent.cs index ae3b442931..d6a970e30d 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlCacheComponent.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlCacheComponent.cs @@ -1,6 +1,7 @@ using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Components; +using Umbraco.Core.Composing; using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Core.Logging; diff --git a/src/Umbraco.Web/Scheduling/BackgroundTaskRunner.cs b/src/Umbraco.Web/Scheduling/BackgroundTaskRunner.cs index 76751b6390..b464e4fb31 100644 --- a/src/Umbraco.Web/Scheduling/BackgroundTaskRunner.cs +++ b/src/Umbraco.Web/Scheduling/BackgroundTaskRunner.cs @@ -4,6 +4,7 @@ using System.Threading.Tasks; using System.Threading.Tasks.Dataflow; using System.Web.Hosting; using Umbraco.Core; +using Umbraco.Core.Composing; using Umbraco.Core.Events; using Umbraco.Core.Logging; diff --git a/src/Umbraco.Web/Security/WebSecurity.cs b/src/Umbraco.Web/Security/WebSecurity.cs index ee345e9938..0d089662f8 100644 --- a/src/Umbraco.Web/Security/WebSecurity.cs +++ b/src/Umbraco.Web/Security/WebSecurity.cs @@ -18,6 +18,7 @@ using Umbraco.Core.IO; using Umbraco.Core.Models; using Umbraco.Core.Models.Identity; using Umbraco.Web.Composing; +using ContainerExtensions = Umbraco.Core.Composing.ContainerExtensions; using GlobalSettings = Umbraco.Core.Configuration.GlobalSettings; namespace Umbraco.Web.Security @@ -57,7 +58,7 @@ namespace Umbraco.Web.Security { return false; } - var helper = Current.Container.GetInstance(); + var helper = ContainerExtensions.GetInstance(Current.Container); return helper.IsMemberAuthorized(allowAll, allowTypes, allowGroups, allowMembers); } diff --git a/src/Umbraco.Web/SignalR/PreviewHubComponent.cs b/src/Umbraco.Web/SignalR/PreviewHubComponent.cs index 20d7ec34cf..d80eb05004 100644 --- a/src/Umbraco.Web/SignalR/PreviewHubComponent.cs +++ b/src/Umbraco.Web/SignalR/PreviewHubComponent.cs @@ -2,6 +2,7 @@ using Microsoft.AspNet.SignalR; using Umbraco.Core; using Umbraco.Core.Components; +using Umbraco.Core.Composing; using Umbraco.Core.Sync; using Umbraco.Web.Cache; diff --git a/src/Umbraco.Web/Templates/TemplateRenderer.cs b/src/Umbraco.Web/Templates/TemplateRenderer.cs index 18a4db7118..44e9cca5a5 100644 --- a/src/Umbraco.Web/Templates/TemplateRenderer.cs +++ b/src/Umbraco.Web/Templates/TemplateRenderer.cs @@ -13,6 +13,7 @@ using umbraco; using Umbraco.Core.Configuration; using Umbraco.Core.Services; using Umbraco.Web.Composing; +using ContainerExtensions = Umbraco.Core.Composing.ContainerExtensions; namespace Umbraco.Web.Templates { @@ -40,7 +41,7 @@ namespace Umbraco.Web.Templates } // todo - inject! - private PublishedRouter PublishedRouter => Core.Composing.Current.Container.GetInstance(); + private PublishedRouter PublishedRouter => ContainerExtensions.GetInstance(Core.Composing.Current.Container); /// diff --git a/src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs b/src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs index ba63d59d68..62e94ddded 100644 --- a/src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs +++ b/src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs @@ -11,6 +11,7 @@ using Umbraco.Core.Services; using Umbraco.Web.Composing; using Umbraco.Web.Security; using Umbraco.Web.UI.Pages; +using ContainerExtensions = Umbraco.Core.Composing.ContainerExtensions; namespace Umbraco.Web.UI.Controls { @@ -33,7 +34,7 @@ namespace Umbraco.Web.UI.Controls if (umbracoContext == null) throw new ArgumentNullException(nameof(umbracoContext)); UmbracoContext = umbracoContext; Umbraco = new UmbracoHelper(umbracoContext, services, appCache); - Members = Current.Container.GetInstance(); + Members = ContainerExtensions.GetInstance(Current.Container); // fixme inject somehow Logger = Current.Logger; diff --git a/src/Umbraco.Web/UmbracoHelper.cs b/src/Umbraco.Web/UmbracoHelper.cs index 1d12ae4565..e1845e5f8b 100644 --- a/src/Umbraco.Web/UmbracoHelper.cs +++ b/src/Umbraco.Web/UmbracoHelper.cs @@ -14,6 +14,7 @@ using Umbraco.Web.Composing; using Umbraco.Core.Cache; using Umbraco.Web.Routing; using Umbraco.Web.Security; +using ContainerExtensions = Umbraco.Core.Composing.ContainerExtensions; namespace Umbraco.Web { @@ -155,7 +156,7 @@ namespace Umbraco.Web /// Gets the membership helper. /// public MembershipHelper MembershipHelper => _membershipHelper - ?? (_membershipHelper = Current.Container.GetInstance()); + ?? (_membershipHelper = ContainerExtensions.GetInstance(Current.Container)); /// /// Gets the url provider. From a00f2f0bb9b7648a2ad39800529ccfdd997c8852 Mon Sep 17 00:00:00 2001 From: Stephan Date: Sat, 21 Jul 2018 10:47:29 +0200 Subject: [PATCH 027/469] Refactor, fix collection builders, fix tests --- .../Composing/CollectionBuilderBase.cs | 3 +- .../Composing/ContainerExtensions.cs | 22 +++++++ src/Umbraco.Core/Composing/IContainer.cs | 8 +-- .../LightInject/LightInjectContainer.cs | 44 ++++++++++--- .../Composing/LightInjectExtensions.cs | 23 ------- .../Runtime/CoreRuntimeComponent.cs | 1 - src/Umbraco.Core/UmbracoApplicationBase.cs | 2 +- .../DistributedCache/DistributedCacheTests.cs | 2 +- .../Composing/CollectionBuildersTests.cs | 2 +- .../Composing/LazyCollectionBuilderTests.cs | 2 +- .../Composing/PackageActionCollectionTests.cs | 2 +- src/Umbraco.Tests/IO/FileSystemsTests.cs | 2 +- .../PropertyEditors/ImageCropperTest.cs | 2 +- .../PropertyEditorValueEditorTests.cs | 2 +- .../Published/ConvertersTests.cs | 2 +- .../Scoping/ScopeEventDispatcherTests.cs | 2 +- .../TestHelpers/BaseUsingSqlCeSyntax.cs | 2 +- .../TestHelpers/TestObjects-Mocks.cs | 5 ++ src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 9 ++- src/Umbraco.Web/Composing/Current.cs | 4 -- .../LightInject/LightInjectContainer.cs | 8 ++- src/Umbraco.Web/Editors/SectionController.cs | 11 +--- src/Umbraco.Web/UmbracoApplication.cs | 2 +- .../_Legacy/Actions/ActionCollection.cs | 63 +++++++++++++++++-- .../Actions/ActionCollectionBuilder.cs | 53 +++------------- 25 files changed, 159 insertions(+), 119 deletions(-) diff --git a/src/Umbraco.Core/Composing/CollectionBuilderBase.cs b/src/Umbraco.Core/Composing/CollectionBuilderBase.cs index ecbd9533ee..efdef82114 100644 --- a/src/Umbraco.Core/Composing/CollectionBuilderBase.cs +++ b/src/Umbraco.Core/Composing/CollectionBuilderBase.cs @@ -63,8 +63,7 @@ namespace Umbraco.Core.Composing // else _collectionCtor remains null, assuming CreateCollection has been overriden // we just don't want to support re-registering collections here - var registration = Container.GetRegistered().FirstOrDefault(); - if (registration != null) + if (Container.GetRegistered().Any()) throw new InvalidOperationException("Collection builders cannot be registered once the collection itself has been registered."); // register the collection diff --git a/src/Umbraco.Core/Composing/ContainerExtensions.cs b/src/Umbraco.Core/Composing/ContainerExtensions.cs index 8fb8208c4a..e51fc07aa4 100644 --- a/src/Umbraco.Core/Composing/ContainerExtensions.cs +++ b/src/Umbraco.Core/Composing/ContainerExtensions.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; namespace Umbraco.Core.Composing { @@ -71,5 +72,26 @@ namespace Umbraco.Core.Composing public static void RegisterAuto(this IContainer container) => container.RegisterAuto(typeof(TServiceBase)); + + /// + /// Registers and instanciates a collection builder. + /// + /// The type of the collection builder. + /// A collection builder of the specified type. + public static TBuilder RegisterCollectionBuilder(this IContainer container) + { + // make sure it's not already registered + // we just don't want to support re-registering collection builders + if (container.GetRegistered().Any()) + throw new InvalidOperationException("Collection builders should be registered only once."); + + // register the builder - per container + container.RegisterSingleton(); + + // initialize and return the builder + // note: see notes in IContainer - cannot pass the container as a parameter to a singleton + // and so, for now, the container is registered into itself + return container.GetInstance(/*new object[] { container }*/); + } } } diff --git a/src/Umbraco.Core/Composing/IContainer.cs b/src/Umbraco.Core/Composing/IContainer.cs index 6e0417a334..9d77a9b379 100644 --- a/src/Umbraco.Core/Composing/IContainer.cs +++ b/src/Umbraco.Core/Composing/IContainer.cs @@ -114,14 +114,8 @@ namespace Umbraco.Core.Composing /// void RegisterOrdered(Type serviceType, Type[] implementingTypes, Lifetime lifetime = Lifetime.Transient); - /// - /// Registers and instanciates a collection builder. - /// - /// The type of the collection builder. - /// A collection builder of the specified type. - T RegisterCollectionBuilder(); - // fixme - very LightInject specific? or? + // beware! does NOT work on singletons, see https://github.com/seesharper/LightInject/issues/294 void RegisterConstructorDependency(Func factory); void RegisterConstructorDependency(Func factory); diff --git a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs index de942c1e4c..8d8197f10c 100644 --- a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs +++ b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Reflection; using System.Linq; +using System.Threading; using LightInject; namespace Umbraco.Core.Composing.LightInject @@ -11,14 +12,28 @@ namespace Umbraco.Core.Composing.LightInject /// public class LightInjectContainer : IContainer { + private int _disposed; + /// /// Initializes a new instance of the with a LightInject container. /// - public LightInjectContainer(ServiceContainer container) + protected LightInjectContainer(ServiceContainer container) { Container = container; } + /// + /// Creates a new instance of the class. + /// + public static LightInjectContainer Create() + => new LightInjectContainer(CreateServiceContainer()); + + /// + /// Creates a new instance of the LightInject service container. + /// + protected static ServiceContainer CreateServiceContainer() + => new ServiceContainer(new ContainerOptions { EnablePropertyInjection = false }); + /// /// Gets the LightInject container. /// @@ -29,7 +44,12 @@ namespace Umbraco.Core.Composing.LightInject /// public void Dispose() - => Container.Dispose(); + { + if (Interlocked.Exchange(ref _disposed, 1) == 1) + return; + + Container.Dispose(); + } #region Factory @@ -186,10 +206,6 @@ namespace Umbraco.Core.Composing.LightInject public void RegisterConstructorDependency(Func factory) => Container.RegisterConstructorDependency((f, x, a) => factory(this, x, a)); - /// - public T RegisterCollectionBuilder() - => Container.RegisterCollectionBuilder(); - #endregion #region Control @@ -205,6 +221,9 @@ namespace Umbraco.Core.Composing.LightInject // eg to specify the service name on some services Container.EnableAnnotatedConstructorInjection(); + // note: the block below is disabled, we do not allow property injection at all anymore + // (see options in CreateServiceContainer) + // // from the docs: "LightInject considers all read/write properties a dependency, but implements // a loose strategy around property dependencies, meaning that it will NOT throw an exception // in the case of an unresolved property dependency." @@ -216,7 +235,7 @@ namespace Umbraco.Core.Composing.LightInject // could not find it documented, but tests & code review shows that LightInject considers a // property to be "injectable" when its setter exists and is not static, nor private, nor // it is an index property. which means that eg protected or internal setters are OK. - Container.EnableAnnotatedPropertyInjection(); + //Container.EnableAnnotatedPropertyInjection(); // ensure that we do *not* scan assemblies // we explicitely RegisterFrom our own composition roots and don't want them scanned @@ -225,6 +244,17 @@ namespace Umbraco.Core.Composing.LightInject // see notes in MixedLightInjectScopeManagerProvider Container.ScopeManagerProvider = new MixedLightInjectScopeManagerProvider(); + // note: the block below is disabled, because it does not work, because collection builders + // are singletons, and constructor dependencies don't work on singletons, see + // https://github.com/seesharper/LightInject/issues/294 + // + // if looking for a IContainer, and one was passed in args, use it + // this is for collection builders which require the IContainer + //Container.RegisterConstructorDependency((c, i, a) => a.OfType().FirstOrDefault()); + + // which means that the only way to inject the container into builders is to register it + Container.RegisterInstance(this); + return this; } diff --git a/src/Umbraco.Core/Composing/LightInjectExtensions.cs b/src/Umbraco.Core/Composing/LightInjectExtensions.cs index 6c8961ec66..30a4c0efb5 100644 --- a/src/Umbraco.Core/Composing/LightInjectExtensions.cs +++ b/src/Umbraco.Core/Composing/LightInjectExtensions.cs @@ -206,28 +206,5 @@ namespace Umbraco.Core.Composing var typeofTService = typeof(TService); return container.AvailableServices.SingleOrDefault(x => x.ServiceType == typeofTService && x.ServiceName == name); } - - /// - /// Registers and instanciates a collection builder. - /// - /// The type of the collection builder. - /// The container. - /// The collection builder. - public static TBuilder RegisterCollectionBuilder(this IServiceContainer container) - { - // make sure it's not already registered - // we just don't want to support re-registering collection builders - var registration = container.GetAvailableService(); - if (registration != null) - throw new InvalidOperationException("Collection builders should be registered only once."); - - // register the builder - per container - var builderLifetime = new PerContainerLifetime(); - container.Register(builderLifetime); - - // return the builder - // (also initializes the builder) - return container.GetInstance(); - } } } diff --git a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs index 6320401681..d06b6215b3 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Configuration; using AutoMapper; -using LightInject; using Umbraco.Core.Cache; using Umbraco.Core.Components; using Umbraco.Core.Composing; diff --git a/src/Umbraco.Core/UmbracoApplicationBase.cs b/src/Umbraco.Core/UmbracoApplicationBase.cs index 98ddbc883f..20b2131217 100644 --- a/src/Umbraco.Core/UmbracoApplicationBase.cs +++ b/src/Umbraco.Core/UmbracoApplicationBase.cs @@ -36,7 +36,7 @@ namespace Umbraco.Core { // note: the actual, web UmbracoApplication is overriding this // with a web-supporting container - return new Composing.LightInject.LightInjectContainer(new LightInject.ServiceContainer()); + return Composing.LightInject.LightInjectContainer.Create(); } // events - in the order they trigger diff --git a/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs b/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs index d8f3e615ec..750768eb1d 100644 --- a/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs +++ b/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs @@ -20,7 +20,7 @@ namespace Umbraco.Tests.Cache.DistributedCache [SetUp] public void Setup() { - var container = Current.Container = new Core.Composing.LightInject.LightInjectContainer(new LightInject.ServiceContainer()); + var container = Current.Container = Core.Composing.LightInject.LightInjectContainer.Create(); container.ConfigureForUmbraco(); container.Register(_ => new TestServerRegistrar()); diff --git a/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs b/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs index d34df9b8b2..6516d2fbfd 100644 --- a/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs +++ b/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs @@ -17,7 +17,7 @@ namespace Umbraco.Tests.Composing { Current.Reset(); - _container = Current.Container = new Core.Composing.LightInject.LightInjectContainer(new LightInject.ServiceContainer()); + _container = Current.Container = Core.Composing.LightInject.LightInjectContainer.Create(); _container.ConfigureForUmbraco(); } diff --git a/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs b/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs index 97dde9e43a..51f38cebf0 100644 --- a/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs +++ b/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs @@ -23,7 +23,7 @@ namespace Umbraco.Tests.Composing } private IContainer CreateContainer() - => Current.Container = (new Core.Composing.LightInject.LightInjectContainer(new LightInject.ServiceContainer())).ConfigureForUmbraco(); + => Current.Container = Core.Composing.LightInject.LightInjectContainer.Create().ConfigureForUmbraco(); // note // lazy collection builder does not throw on duplicate, just uses distinct types diff --git a/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs b/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs index 0b318f80cf..01fa9e7835 100644 --- a/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs +++ b/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs @@ -13,7 +13,7 @@ namespace Umbraco.Tests.Composing [Test] public void PackageActionCollectionBuilderWorks() { - var container = Current.Container = new Core.Composing.LightInject.LightInjectContainer(new LightInject.ServiceContainer()); + var container = Current.Container = Core.Composing.LightInject.LightInjectContainer.Create(); container.ConfigureForUmbraco(); container.RegisterCollectionBuilder() diff --git a/src/Umbraco.Tests/IO/FileSystemsTests.cs b/src/Umbraco.Tests/IO/FileSystemsTests.cs index 75a41560cf..eb437d6a51 100644 --- a/src/Umbraco.Tests/IO/FileSystemsTests.cs +++ b/src/Umbraco.Tests/IO/FileSystemsTests.cs @@ -26,7 +26,7 @@ namespace Umbraco.Tests.IO var config = SettingsForTests.GetDefaultUmbracoSettings(); SettingsForTests.ConfigureSettings(config); - _container = Current.Container = new Core.Composing.LightInject.LightInjectContainer(new LightInject.ServiceContainer()); + _container = Current.Container = Core.Composing.LightInject.LightInjectContainer.Create(); _container.ConfigureForUmbraco(); _container.Register(_ => Mock.Of()); diff --git a/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs b/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs index 3576e3aa60..4c73ed8409 100644 --- a/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs +++ b/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs @@ -65,7 +65,7 @@ namespace Umbraco.Tests.PropertyEditors { try { - var container = Current.Container = new Core.Composing.LightInject.LightInjectContainer(new LightInject.ServiceContainer()); + var container = Current.Container = Core.Composing.LightInject.LightInjectContainer.Create(); container.ConfigureForUmbraco(); container.RegisterCollectionBuilder(); diff --git a/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs b/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs index c7924f12a6..38a37f0083 100644 --- a/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs +++ b/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs @@ -21,7 +21,7 @@ namespace Umbraco.Tests.PropertyEditors //normalize culture Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture; - var container = Current.Container = new Core.Composing.LightInject.LightInjectContainer(new LightInject.ServiceContainer()); + var container = Current.Container = Core.Composing.LightInject.LightInjectContainer.Create(); container.ConfigureForUmbraco(); container.Register(_ diff --git a/src/Umbraco.Tests/Published/ConvertersTests.cs b/src/Umbraco.Tests/Published/ConvertersTests.cs index 112dda9c17..44e84e98fb 100644 --- a/src/Umbraco.Tests/Published/ConvertersTests.cs +++ b/src/Umbraco.Tests/Published/ConvertersTests.cs @@ -171,7 +171,7 @@ namespace Umbraco.Tests.Published public void SimpleConverter3Test() { Current.Reset(); - var container = Current.Container = new Core.Composing.LightInject.LightInjectContainer(new LightInject.ServiceContainer()); + var container = Current.Container = Core.Composing.LightInject.LightInjectContainer.Create(); container.ConfigureForUmbraco(); diff --git a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs index 0505072e5c..89d361e789 100644 --- a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs @@ -29,7 +29,7 @@ namespace Umbraco.Tests.Scoping DoThing2 = null; DoThing3 = null; - var container = Current.Container = new Core.Composing.LightInject.LightInjectContainer(new LightInject.ServiceContainer()); + var container = Current.Container = Core.Composing.LightInject.LightInjectContainer.Create(); _testObjects = new TestObjects(container); diff --git a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs index 1078a49299..1549de8554 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs @@ -32,7 +32,7 @@ namespace Umbraco.Tests.TestHelpers var sqlSyntax = new SqlCeSyntaxProvider(); - var container = Current.Container = new Core.Composing.LightInject.LightInjectContainer(new LightInject.ServiceContainer()); + var container = Current.Container = Core.Composing.LightInject.LightInjectContainer.Create(); container.ConfigureForUmbraco(); container.RegisterSingleton(factory => Mock.Of()); diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs b/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs index da96c40299..19e5d12650 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs @@ -143,12 +143,17 @@ namespace Umbraco.Tests.TestHelpers public IFileSystems GetFileSystemsMock() { var fileSystems = Mock.Of(); + MockFs(fileSystems, x => x.MasterPagesFileSystem); MockFs(fileSystems, x => x.MacroPartialsFileSystem); MockFs(fileSystems, x => x.MvcViewsFileSystem); MockFs(fileSystems, x => x.PartialViewsFileSystem); MockFs(fileSystems, x => x.ScriptsFileSystem); MockFs(fileSystems, x => x.StylesheetsFileSystem); + + var mediaFs = new MediaFileSystem(Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of()); + Mock.Get(fileSystems).Setup(x => x.MediaFileSystem).Returns(mediaFs); + return fileSystems; } diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index f3029b3a35..04b22831a4 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -113,7 +113,7 @@ namespace Umbraco.Tests.Testing // but hey, never know, better avoid garbage-in Reset(); - Container = Current.Container = new Core.Composing.LightInject.LightInjectContainer(new LightInject.ServiceContainer()); + Container = Current.Container = Core.Composing.LightInject.LightInjectContainer.Create(); Container.ConfigureForUmbraco(); TestObjects = new TestObjects(Container); @@ -286,6 +286,10 @@ namespace Umbraco.Tests.Testing Container.RegisterSingleton(factory => ExamineManager.Instance); + // register filesystems + Container.RegisterSingleton(factory => TestObjects.GetFileSystemsMock()); + Container.RegisterSingleton(factory => factory.GetInstance().MediaFileSystem); + // no factory (noop) Container.RegisterSingleton(); @@ -304,8 +308,7 @@ namespace Umbraco.Tests.Testing Container.RegisterSingleton(f => f.TryGetInstance().SqlContext); Container.RegisterCollectionBuilder(); // empty - Container.RegisterSingleton(factory => new FileSystems(factory.TryGetInstance())); - Container.RegisterSingleton(factory => factory.GetInstance()); + Container.RegisterSingleton(factory => TestObjects.GetScopeProvider(factory.TryGetInstance(), factory.TryGetInstance(), factory.TryGetInstance())); Container.RegisterSingleton(factory => (IScopeAccessor) factory.GetInstance()); diff --git a/src/Umbraco.Web/Composing/Current.cs b/src/Umbraco.Web/Composing/Current.cs index f6d8053305..cf1a419769 100644 --- a/src/Umbraco.Web/Composing/Current.cs +++ b/src/Umbraco.Web/Composing/Current.cs @@ -1,18 +1,15 @@ using System; using System.Threading; using System.Web; -using LightInject; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Dictionary; using Umbraco.Core.Events; using Umbraco.Core.IO; using Umbraco.Core.Logging; -using Umbraco.Core.Macros; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Persistence; using Umbraco.Core.Composing; -using Umbraco.Core.Migrations; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Scoping; using Umbraco.Core.Services; @@ -22,7 +19,6 @@ using Umbraco.Core._Legacy.PackageActions; using Umbraco.Web.Cache; using Umbraco.Web.Editors; using Umbraco.Web.HealthCheck; -using Umbraco.Web.Media; using Umbraco.Web.Mvc; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; diff --git a/src/Umbraco.Web/Composing/LightInject/LightInjectContainer.cs b/src/Umbraco.Web/Composing/LightInject/LightInjectContainer.cs index cf6a949fac..0237e2a641 100644 --- a/src/Umbraco.Web/Composing/LightInject/LightInjectContainer.cs +++ b/src/Umbraco.Web/Composing/LightInject/LightInjectContainer.cs @@ -14,10 +14,16 @@ namespace Umbraco.Web.Composing.LightInject /// /// Initializes a new instance of the with a LightInject container. /// - public LightInjectContainer(ServiceContainer container) + protected LightInjectContainer(ServiceContainer container) : base(container) { } + /// + /// Creates a new instance of the class. + /// + public new static LightInjectContainer Create() + => new LightInjectContainer(CreateServiceContainer()); + /// public override IContainer ConfigureForWeb() { diff --git a/src/Umbraco.Web/Editors/SectionController.cs b/src/Umbraco.Web/Editors/SectionController.cs index 51c356558f..d9578d4877 100644 --- a/src/Umbraco.Web/Editors/SectionController.cs +++ b/src/Umbraco.Web/Editors/SectionController.cs @@ -1,10 +1,7 @@ using System.Collections.Generic; using AutoMapper; -using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Mvc; using System.Linq; -using LightInject; -using Umbraco.Core.Composing; using Umbraco.Core.Models; using Umbraco.Web.Trees; using Section = Umbraco.Web.Models.ContentEditing.Section; @@ -19,7 +16,6 @@ namespace Umbraco.Web.Editors { public IEnumerable
GetSections() { - var sections = Services.SectionService.GetAllowedSections(Security.GetUserId().ResultOr(0)); var sectionModels = sections.Select(Mapper.Map).ToArray(); @@ -29,11 +25,8 @@ namespace Umbraco.Web.Editors var dashboardHelper = new DashboardHelper(Services.SectionService); // this is a bit nasty since we'll be proxying via the app tree controller but we sort of have to do that - // since tree's by nature are controllers and require request contextual data - and then we have to - // remember to inject properties - nasty indeed - var appTreeController = new ApplicationTreeController(); - ((IServiceContainer)Current.Container.ConcreteContainer).InjectProperties(appTreeController); - appTreeController.ControllerContext = ControllerContext; + // since tree's by nature are controllers and require request contextual data + var appTreeController = new ApplicationTreeController { ControllerContext = ControllerContext }; var dashboards = dashboardHelper.GetDashboards(Security.CurrentUser); //now we can add metadata for each section so that the UI knows if there's actually anything at all to render for diff --git a/src/Umbraco.Web/UmbracoApplication.cs b/src/Umbraco.Web/UmbracoApplication.cs index bd790cdfb2..40ebac4536 100644 --- a/src/Umbraco.Web/UmbracoApplication.cs +++ b/src/Umbraco.Web/UmbracoApplication.cs @@ -16,7 +16,7 @@ namespace Umbraco.Web protected override IContainer GetContainer() { - return new Web.Composing.LightInject.LightInjectContainer(new LightInject.ServiceContainer()); + return Composing.LightInject.LightInjectContainer.Create(); } } } diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionCollection.cs b/src/Umbraco.Web/_Legacy/Actions/ActionCollection.cs index 849fb3b619..afd6c2c1af 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionCollection.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionCollection.cs @@ -1,16 +1,24 @@ -using System.Collections.Generic; +using System; +using System.Collections; +using System.Collections.Generic; using System.Globalization; using System.Linq; +using System.Reflection; using Umbraco.Core; using Umbraco.Core.Composing; namespace Umbraco.Web._Legacy.Actions { - public class ActionCollection : BuilderCollectionBase + public class ActionCollection : IBuilderCollection { - public ActionCollection(IEnumerable items) - : base(items) - { } + private Func> _producer; + private readonly object _locker = new object(); + private IAction[] _items; + + internal ActionCollection(Func> producer) + { + _producer = producer; + } internal T GetAction() where T : IAction @@ -25,5 +33,50 @@ namespace Umbraco.Web._Legacy.Actions .WhereNotNull() .ToArray(); } + + private IAction[] Items + { + get + { + lock (_locker) + { + if (_items != null) return _items; + + var actions = new List(); + foreach (var type in _producer()) + { + var getter = type.GetProperty("Instance", BindingFlags.Public | BindingFlags.Static); + var instance = getter == null + ? Activator.CreateInstance(type) as IAction + : getter.GetValue(null, null) as IAction; + if (instance == null) continue; + actions.Add(instance); + } + + return _items = actions.ToArray(); + } + } + } + + internal void Reset(Func> producer) + { + lock (_locker) + { + _items = null; + _producer = producer; + } + } + + public int Count => Items.Length; + + public IEnumerator GetEnumerator() + { + return ((IEnumerable) Items).GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } } } diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionCollectionBuilder.cs b/src/Umbraco.Web/_Legacy/Actions/ActionCollectionBuilder.cs index 39058d6836..1789e57e2d 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionCollectionBuilder.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionCollectionBuilder.cs @@ -1,71 +1,34 @@ using System; using System.Collections.Generic; -using System.Reflection; -using LightInject; using Umbraco.Core.Composing; namespace Umbraco.Web._Legacy.Actions { internal class ActionCollectionBuilder : ICollectionBuilder { - private static Func> _producer; + private Func> _producer; + private ActionCollection _collection; // for tests only - does not register the collection public ActionCollectionBuilder() { } - public ActionCollectionBuilder(IServiceContainer container) + public ActionCollectionBuilder(IContainer container) { - var collectionLifetime = CollectionLifetime; - - // register the collection - special lifetime - // the lifetime here is custom ResettablePerContainerLifetime which will manage one - // single instance of the collection (much alike PerContainerLifetime) but can be resetted - // to force a new collection to be created. - // this is needed because of the weird things we do during install, where we'd use the - // infamous DirtyBackdoorToConfiguration to reset the ActionResolver way after Resolution - // had frozen. This has been replaced by the possibility here to set the producer at any - // time - but the builder is internal - and all this will be gone eventually. - container.Register(factory => factory.GetInstance().CreateCollection(), collectionLifetime); + // register the collection + container.RegisterSingleton(factory => factory.GetInstance().CreateCollection()); } public ActionCollection CreateCollection() { - var actions = new List(); - foreach (var type in _producer()) - { - var getter = type.GetProperty("Instance", BindingFlags.Public | BindingFlags.Static); - var instance = getter == null - ? Activator.CreateInstance(type) as IAction - : getter.GetValue(null, null) as IAction; - if (instance == null) continue; - actions.Add(instance); - } - return new ActionCollection(actions); + // create a special collection that can be resetted (ouch) + return _collection = new ActionCollection(_producer); } public void SetProducer(Func> producer) { _producer = producer; - CollectionLifetime.Reset(); - } - - private ResettablePerContainerLifetime CollectionLifetime { get; } = new ResettablePerContainerLifetime(); - - private class ResettablePerContainerLifetime : ILifetime - { - private object _instance; - - public object GetInstance(Func createInstance, Scope scope) - { - // not dealing with disposable instances, actions are not disposable - return _instance ?? (_instance = createInstance()); - } - - public void Reset() - { - _instance = null; - } + _collection?.Reset(producer); } } } From d2376bf4e387ea1f3be14c64fe6565a3f109c4f6 Mon Sep 17 00:00:00 2001 From: Stephan Date: Mon, 23 Jul 2018 08:56:08 +0200 Subject: [PATCH 028/469] Cleanup registrations --- src/Umbraco.Core/Components/BootLoader.cs | 2 +- .../Composers/FileSystemsComposer.cs | 9 ++-- .../Composing/ContainerExtensions.cs | 2 +- src/Umbraco.Core/Composing/IContainer.cs | 36 +++++++++++--- .../LightInject/LightInjectContainer.cs | 49 ++++++++++++++----- src/Umbraco.Core/IO/FileSystems.cs | 2 +- .../Migrations/MigrationBuilder.cs | 17 +------ src/Umbraco.Tests/CoreThings/UdiTests.cs | 1 - .../Integration/ContentEventsTests.cs | 4 -- .../Membership/MembershipProviderBaseTests.cs | 8 --- .../Misc/ApplicationUrlHelperTests.cs | 21 +++----- .../DataTypeDefinitionRepositoryTest.cs | 1 - .../PublishedContent/PublishedMediaTests.cs | 3 -- .../Scoping/ScopeFileSystemsTests.cs | 12 ++++- .../Scoping/ScopedNuCacheTests.cs | 2 - .../Scoping/ScopedRepositoryTests.cs | 2 - src/Umbraco.Tests/Scoping/ScopedXmlTests.cs | 2 - .../Services/Importing/PackageImportTests.cs | 11 +++++ .../TestHelpers/TestWithDatabaseBase.cs | 2 - 19 files changed, 102 insertions(+), 84 deletions(-) diff --git a/src/Umbraco.Core/Components/BootLoader.cs b/src/Umbraco.Core/Components/BootLoader.cs index b80fa93500..70e62c799f 100644 --- a/src/Umbraco.Core/Components/BootLoader.cs +++ b/src/Umbraco.Core/Components/BootLoader.cs @@ -313,7 +313,7 @@ namespace Umbraco.Core.Components { var componentType = component.GetType(); var initializers = componentType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) - .Where(x => x.Name == "Initialize" && x.IsGenericMethod == false); + .Where(x => x.Name == "Initialize" && x.IsGenericMethod == false && x.IsStatic == false); using (_proflog.DebugDuration($"Initializing {componentType.FullName}.", $"Initialised {componentType.FullName}.", thresholdMilliseconds: LogThresholdMilliseconds)) { foreach (var initializer in initializers) diff --git a/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs b/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs index 565db9c623..cb8466bd13 100644 --- a/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Configuration.UmbracoSettings; +using System.Linq; +using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; using Umbraco.Core.Logging; @@ -15,11 +16,7 @@ namespace Umbraco.Core.Composing.Composers container.RegisterSingleton(factory => factory.GetInstance()); // register MediaFileSystem, which can be injected directly - container.RegisterSingleton(factory => factory.GetInstance().MediaFileSystem); - - // register MediaFileSystem, so that FileSystems can create it - container.Register((f, wrappedFileSystem) - => new MediaFileSystem(wrappedFileSystem, f.GetInstance(), f.GetInstance(), f.GetInstance())); + container.Register/*Singleton*/(factory => factory.GetInstance().MediaFileSystem); return container; } diff --git a/src/Umbraco.Core/Composing/ContainerExtensions.cs b/src/Umbraco.Core/Composing/ContainerExtensions.cs index e51fc07aa4..db040393bc 100644 --- a/src/Umbraco.Core/Composing/ContainerExtensions.cs +++ b/src/Umbraco.Core/Composing/ContainerExtensions.cs @@ -30,7 +30,7 @@ namespace Umbraco.Core.Composing /// Throws an exception if the container failed to get an instance of the specified type. /// The arguments are used as dependencies by the container. /// - public static T GetInstance(this IContainer container, object[] args) + public static T GetInstance(this IContainer container, params object[] args) => (T) container.GetInstance(typeof(T), args); /// diff --git a/src/Umbraco.Core/Composing/IContainer.cs b/src/Umbraco.Core/Composing/IContainer.cs index 9d77a9b379..2be539551e 100644 --- a/src/Umbraco.Core/Composing/IContainer.cs +++ b/src/Umbraco.Core/Composing/IContainer.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Reflection; namespace Umbraco.Core.Composing { @@ -43,7 +42,10 @@ namespace Umbraco.Core.Composing /// Throws an exception if the container failed to get an instance of the specified type. /// The arguments are used as dependencies by the container. /// - object GetInstance(Type type, object[] args); + // fixme - some restrictions: + // method is not optimized, .Invoke-ing the ctor, no compiled dynamic method + // uses the ctor with most args, always, not trying to figure out which one to use + object GetInstance(Type type, params object[] args); /// /// Tries to get an instance. @@ -67,13 +69,23 @@ namespace Umbraco.Core.Composing /// The type of the service. IEnumerable GetAllInstances(); - // fixme + /// + /// Gets registration for a service. + /// + /// The type of the service. + /// The registrations for the service. IEnumerable GetRegistered(Type serviceType); #endregion #region Registry + // notes + // when implementing IContainer, the following rules apply + // - it is possible to register a service, even after some instances of other services have been created + // - it is possible to re-register a service, as long as an instance of that service has not been created + // - once an instance of a service has been created, it is not possible to change its registration + /// /// Registers a service as its own implementation. /// @@ -107,6 +119,13 @@ namespace Umbraco.Core.Composing /// /// Registers a base type for auto-registration. /// + /// + /// Auto-registration means that anytime the container is asked to create an instance + /// of a type deriving from , it will first register that + /// type automatically. + /// This can be used for instance for views or controllers. Then, one just needs to + /// register a common base class or interface, and the container knows how to create instances. + /// void RegisterAuto(Type serviceBaseType); /// @@ -114,11 +133,6 @@ namespace Umbraco.Core.Composing /// void RegisterOrdered(Type serviceType, Type[] implementingTypes, Lifetime lifetime = Lifetime.Transient); - // fixme - very LightInject specific? or? - // beware! does NOT work on singletons, see https://github.com/seesharper/LightInject/issues/294 - void RegisterConstructorDependency(Func factory); - void RegisterConstructorDependency(Func factory); - #endregion #region Control @@ -134,6 +148,12 @@ namespace Umbraco.Core.Composing // fixme - document all these + /// + /// Configures the container for Umbraco. + /// + /// + /// + /// IContainer ConfigureForUmbraco(); IContainer ConfigureForWeb(); diff --git a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs index 8d8197f10c..6e4b08eaed 100644 --- a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs +++ b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs @@ -62,8 +62,26 @@ namespace Umbraco.Core.Composing.LightInject => Container.GetInstance(type, name); /// - public object GetInstance(Type type, object[] args) - => Container.GetInstance(type, args); + public object GetInstance(Type type, params object[] args) + { + // LightInject has this, but then it requires RegisterConstructorDependency etc and has various oddities + //return Container.GetInstance(type, args); + + var ctor = type.GetConstructors(BindingFlags.Instance | BindingFlags.Public).OrderByDescending(x => x.GetParameters().Length).FirstOrDefault(); + if (ctor == null) throw new InvalidOperationException($"Could not find a public constructor for type {type.FullName}."); + + var ctorParameters = ctor.GetParameters(); + var ctorArgs = new object[ctorParameters.Length]; + var i = 0; + foreach (var parameter in ctorParameters) + { + // no! IsInstanceOfType is not ok here + // ReSharper disable once UseMethodIsInstanceOfType + var arg = args?.FirstOrDefault(a => parameter.ParameterType.IsAssignableFrom(a.GetType())); + ctorArgs[i++] = arg ?? GetInstance(parameter.ParameterType); + } + return ctor.Invoke(ctorArgs); + } /// public object TryGetInstance(Type type) @@ -198,13 +216,16 @@ namespace Umbraco.Core.Composing.LightInject public void RegisterOrdered(Type serviceType, Type[] implementingTypes, Lifetime lifetime = Lifetime.Transient) => Container.RegisterOrdered(serviceType, implementingTypes, _ => GetLifetime(lifetime)); - /// - public void RegisterConstructorDependency(Func factory) - => Container.RegisterConstructorDependency((f, x) => factory(this, x)); - - /// - public void RegisterConstructorDependency(Func factory) - => Container.RegisterConstructorDependency((f, x, a) => factory(this, x, a)); + // was the Light-Inject specific way of dealing with args, but we've replaced it with our own + // beware! does NOT work on singletons, see https://github.com/seesharper/LightInject/issues/294 + // + ///// + //public void RegisterConstructorDependency(Func factory) + // => Container.RegisterConstructorDependency((f, x) => factory(this, x)); + // + ///// + //public void RegisterConstructorDependency(Func factory) + // => Container.RegisterConstructorDependency((f, x, a) => factory(this, x, a)); #endregion @@ -251,9 +272,13 @@ namespace Umbraco.Core.Composing.LightInject // if looking for a IContainer, and one was passed in args, use it // this is for collection builders which require the IContainer //Container.RegisterConstructorDependency((c, i, a) => a.OfType().FirstOrDefault()); - - // which means that the only way to inject the container into builders is to register it - Container.RegisterInstance(this); + // + // and, the block below is also disabled, because it is ugly + // + //// which means that the only way to inject the container into builders is to register it + //Container.RegisterInstance(this); + // + // instead, we use an explicit GetInstance with arguments implementation return this; } diff --git a/src/Umbraco.Core/IO/FileSystems.cs b/src/Umbraco.Core/IO/FileSystems.cs index ab7f75a521..e9114d5310 100644 --- a/src/Umbraco.Core/IO/FileSystems.cs +++ b/src/Umbraco.Core/IO/FileSystems.cs @@ -299,7 +299,7 @@ namespace Umbraco.Core.IO var shadowWrapper = new ShadowWrapper(innerFs, "typed/" + alias, () => IsScoped()); // getting the fs from the container - see FileSystemsComposer - var fs = Current.Container.GetInstance(new object[] { (IFileSystem) shadowWrapper }); + var fs = Current.Container.GetInstance((IFileSystem) shadowWrapper); _wrappers.Add(shadowWrapper); // keeping a reference to the wrapper return fs; }); diff --git a/src/Umbraco.Core/Migrations/MigrationBuilder.cs b/src/Umbraco.Core/Migrations/MigrationBuilder.cs index c4a06f4789..fa22c96595 100644 --- a/src/Umbraco.Core/Migrations/MigrationBuilder.cs +++ b/src/Umbraco.Core/Migrations/MigrationBuilder.cs @@ -10,27 +10,12 @@ namespace Umbraco.Core.Migrations public MigrationBuilder(IContainer container) { _container = container; - - // because the builder should be "per container" this ctor should run only once per container. - // - // note: constructor dependencies do NOT work with lifetimes other than transient - // see https://github.com/seesharper/LightInject/issues/294 - // - // resolve ctor dependency from GetInstance() runtimeArguments, if possible - 'factory' is - // the container, 'info' describes the ctor argument, and 'args' contains the args that - // were passed to GetInstance() - use first arg if it is the right type. - // - // for IMigrationContext - container.RegisterConstructorDependency((factory, info, args) => args.Length > 0 ? args[0] as IMigrationContext : null); } public IMigration Build(Type migrationType, IMigrationContext context) { - // LightInject .Create() is a shortcut for .Register() + .GetInstance() - // but it does not support parameters, so we do it ourselves here - _container.Register(migrationType); - return (IMigration) _container.GetInstance(migrationType, new object[] { context }); + return (IMigration) _container.GetInstance(migrationType, context); } } } diff --git a/src/Umbraco.Tests/CoreThings/UdiTests.cs b/src/Umbraco.Tests/CoreThings/UdiTests.cs index 12ce3227e1..77f3b10a2f 100644 --- a/src/Umbraco.Tests/CoreThings/UdiTests.cs +++ b/src/Umbraco.Tests/CoreThings/UdiTests.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; -using LightInject; using Moq; using Newtonsoft.Json; using NUnit.Framework; diff --git a/src/Umbraco.Tests/Integration/ContentEventsTests.cs b/src/Umbraco.Tests/Integration/ContentEventsTests.cs index 4356d3733f..6075ab3371 100644 --- a/src/Umbraco.Tests/Integration/ContentEventsTests.cs +++ b/src/Umbraco.Tests/Integration/ContentEventsTests.cs @@ -1,20 +1,16 @@ using System; using System.Collections.Generic; using System.Linq; -using LightInject; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Logging; using Umbraco.Core.Models; -using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.Sync; -using Umbraco.Tests.Cache.DistributedCache; using Umbraco.Tests.Services; using Umbraco.Tests.TestHelpers.Entities; -using Umbraco.Tests.TestHelpers.Stubs; using Umbraco.Tests.Testing; using Umbraco.Web.Cache; using static Umbraco.Tests.Cache.DistributedCache.DistributedCacheTests; diff --git a/src/Umbraco.Tests/Membership/MembershipProviderBaseTests.cs b/src/Umbraco.Tests/Membership/MembershipProviderBaseTests.cs index 2a5b76e1bd..f1f46133c3 100644 --- a/src/Umbraco.Tests/Membership/MembershipProviderBaseTests.cs +++ b/src/Umbraco.Tests/Membership/MembershipProviderBaseTests.cs @@ -3,17 +3,9 @@ using System.Collections.Specialized; using System.Configuration.Provider; using System.Security.Cryptography; using System.Web.Security; -using LightInject; using Moq; using NUnit.Framework; -using Umbraco.Core; -using Umbraco.Core.Composing; -using Umbraco.Core.IO; -using Umbraco.Core.Logging; -using Umbraco.Core.Persistence; -using Umbraco.Core.Scoping; using Umbraco.Core.Security; -using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; namespace Umbraco.Tests.Membership diff --git a/src/Umbraco.Tests/Misc/ApplicationUrlHelperTests.cs b/src/Umbraco.Tests/Misc/ApplicationUrlHelperTests.cs index 9c0560351b..ae72d996a8 100644 --- a/src/Umbraco.Tests/Misc/ApplicationUrlHelperTests.cs +++ b/src/Umbraco.Tests/Misc/ApplicationUrlHelperTests.cs @@ -1,7 +1,4 @@ using System; -using System.Configuration; -using System.Linq; -using LightInject; using Moq; using NUnit.Framework; using Umbraco.Core; @@ -11,8 +8,6 @@ using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Sync; using Umbraco.Tests.TestHelpers; -using Umbraco.Tests.Cache.DistributedCache; -using Umbraco.Tests.TestHelpers.Stubs; namespace Umbraco.Tests.Misc @@ -75,7 +70,7 @@ namespace Umbraco.Tests.Misc ApplicationUrlHelper.ApplicationUrlProvider = request => "http://server1.com/umbraco"; - + var state = new RuntimeState(Mock.Of(), new Lazy(Mock.Of), new Lazy(Mock.Of), settings, globalConfig.Object); @@ -101,7 +96,7 @@ namespace Umbraco.Tests.Misc // still NOT set Assert.IsNull(url); } - + [Test] public void SetApplicationUrlFromStSettingsNoSsl() { @@ -112,8 +107,8 @@ namespace Umbraco.Tests.Misc var globalConfig = Mock.Get(SettingsForTests.GenerateMockGlobalSettings()); globalConfig.Setup(x => x.UseHttps).Returns(false); - - + + var url = ApplicationUrlHelper.TryGetApplicationUrl(settings, Mock.Of(), globalConfig.Object, Mock.Of()); Assert.AreEqual("http://mycoolhost.com/umbraco", url); @@ -129,8 +124,8 @@ namespace Umbraco.Tests.Misc var globalConfig = Mock.Get(SettingsForTests.GenerateMockGlobalSettings()); globalConfig.Setup(x => x.UseHttps).Returns(true); - - + + var url = ApplicationUrlHelper.TryGetApplicationUrl(settings, Mock.Of(), globalConfig.Object, Mock.Of()); Assert.AreEqual("https://mycoolhost.com/umbraco", url); @@ -146,13 +141,13 @@ namespace Umbraco.Tests.Misc var globalConfig = Mock.Get(SettingsForTests.GenerateMockGlobalSettings()); globalConfig.Setup(x => x.UseHttps).Returns(true); - + var url = ApplicationUrlHelper.TryGetApplicationUrl(settings, Mock.Of(), globalConfig.Object, Mock.Of()); Assert.AreEqual("httpx://whatever.com/umbraco", url); } - + } } diff --git a/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs index 8b3af9838c..f9b8281285 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs @@ -6,7 +6,6 @@ using Umbraco.Core.Models; using Umbraco.Core.Persistence.Repositories; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; -using LightInject; using Umbraco.Core.Composing; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.PropertyEditors; diff --git a/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs index 5f0831bfc6..e9d133c901 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs @@ -1,7 +1,6 @@ using System.Web; using System.Xml.Linq; using System.Xml.XPath; -using Lucene.Net.Store; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Models; @@ -20,10 +19,8 @@ using Umbraco.Core.Strings; using Umbraco.Examine; using Current = Umbraco.Web.Composing.Current; using Umbraco.Tests.Testing; -using LightInject; using Umbraco.Core.Composing; using Umbraco.Core.Models.Membership; -using Umbraco.Core.Services; namespace Umbraco.Tests.PublishedContent { diff --git a/src/Umbraco.Tests/Scoping/ScopeFileSystemsTests.cs b/src/Umbraco.Tests/Scoping/ScopeFileSystemsTests.cs index ae16ba484f..f095e30553 100644 --- a/src/Umbraco.Tests/Scoping/ScopeFileSystemsTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopeFileSystemsTests.cs @@ -4,8 +4,8 @@ using System.Text; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Composing; +using Umbraco.Core.Composing.Composers; using Umbraco.Core.IO; -using Umbraco.Core.Scoping; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; @@ -23,6 +23,16 @@ namespace Umbraco.Tests.Scoping ClearFiles(); } + protected override void ComposeApplication(bool withApplication) + { + base.ComposeApplication(withApplication); + + if (!withApplication) return; + + // re-register with actual media fs + Container.ComposeFileSystems(); + } + public override void TearDown() { base.TearDown(); diff --git a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs index cf3285cd7e..9308e9bbaf 100644 --- a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Web.Routing; -using LightInject; using Moq; using NUnit.Framework; using Umbraco.Core; @@ -14,7 +13,6 @@ using Umbraco.Core.Events; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Persistence.Repositories; -using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Services; using Umbraco.Core.Services.Implement; diff --git a/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs b/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs index 875eabb13c..4f6fafbbbf 100644 --- a/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; -using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Models; @@ -11,7 +10,6 @@ using Umbraco.Core.Scoping; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; using Umbraco.Web.Cache; -using LightInject; using Moq; using Umbraco.Core.Events; using Umbraco.Core.Sync; diff --git a/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs b/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs index 948b0f6378..65bc5762c7 100644 --- a/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs @@ -3,8 +3,6 @@ using System.Collections.Generic; using System.Xml; using Moq; using NUnit.Framework; -using LightInject; -using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Events; diff --git a/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs b/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs index d925caa23f..002306fdc2 100644 --- a/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs +++ b/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs @@ -6,6 +6,7 @@ using NUnit.Framework; using Umbraco.Core.Models; using Umbraco.Core; using Umbraco.Core.Composing; +using Umbraco.Core.Composing.Composers; using Umbraco.Core.Logging; using Umbraco.Core.Persistence.Dtos; using Umbraco.Core.PropertyEditors; @@ -53,6 +54,16 @@ namespace Umbraco.Tests.Services.Importing .Add(); } + protected override void ComposeApplication(bool withApplication) + { + base.ComposeApplication(withApplication); + + if (!withApplication) return; + + // re-register with actual media fs + Container.ComposeFileSystems(); + } + [Test] public void PackagingService_Can_Import_uBlogsy_ContentTypes_And_Verify_Structure() { diff --git a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs index 38cd8f727d..00457d510d 100644 --- a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs +++ b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs @@ -26,9 +26,7 @@ using File = System.IO.File; using Umbraco.Core.Composing; using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Scoping; -using Umbraco.Tests.TestHelpers.Stubs; using Umbraco.Tests.Testing; -using LightInject; using Umbraco.Core.Migrations.Install; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Persistence.Repositories; From 6d40269ade234641b6851e47c8c7d7711a773511 Mon Sep 17 00:00:00 2001 From: Stephan Date: Mon, 23 Jul 2018 09:21:55 +0200 Subject: [PATCH 029/469] More cleanup --- .../Composers/FileSystemsComposer.cs | 9 +- .../Composing/ContainerExtensions.cs | 69 +++++--- src/Umbraco.Core/Composing/IContainer.cs | 55 +++--- .../LightInject/LightInjectContainer.cs | 157 +++++++++--------- .../Composing/LightInjectExtensions.cs | 45 ++--- src/Umbraco.Core/IO/FileSystems.cs | 2 +- .../Migrations/MigrationBuilder.cs | 3 +- src/Umbraco.Core/UmbracoApplicationBase.cs | 1 - .../DistributedCache/DistributedCacheTests.cs | 1 - .../Composing/CollectionBuildersTests.cs | 1 - .../Composing/ContainerImplementationTests.cs | 66 ++++++++ .../Composing/LazyCollectionBuilderTests.cs | 2 +- .../Composing/PackageActionCollectionTests.cs | 1 - src/Umbraco.Tests/IO/FileSystemsTests.cs | 4 - src/Umbraco.Tests/Models/ContentTests.cs | 2 +- .../PropertyEditors/ImageCropperTest.cs | 1 - .../PropertyEditorValueEditorTests.cs | 1 - .../Published/ConvertersTests.cs | 1 - .../TestHelpers/BaseUsingSqlCeSyntax.cs | 1 - src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 2 +- src/Umbraco.Tests/Umbraco.Tests.csproj | 1 + 21 files changed, 247 insertions(+), 178 deletions(-) create mode 100644 src/Umbraco.Tests/Composing/ContainerImplementationTests.cs diff --git a/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs b/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs index cb8466bd13..d72e9028b1 100644 --- a/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs @@ -1,7 +1,4 @@ -using System.Linq; -using Umbraco.Core.Configuration.UmbracoSettings; -using Umbraco.Core.IO; -using Umbraco.Core.Logging; +using Umbraco.Core.IO; namespace Umbraco.Core.Composing.Composers { @@ -16,7 +13,9 @@ namespace Umbraco.Core.Composing.Composers container.RegisterSingleton(factory => factory.GetInstance()); // register MediaFileSystem, which can be injected directly - container.Register/*Singleton*/(factory => factory.GetInstance().MediaFileSystem); + // note: the actual MediaFileSystem implementation is created by FileSystems directly, + // without being registered in the container - this just gives access to it + container.Register(factory => factory.GetInstance().MediaFileSystem); return container; } diff --git a/src/Umbraco.Core/Composing/ContainerExtensions.cs b/src/Umbraco.Core/Composing/ContainerExtensions.cs index db040393bc..423af98691 100644 --- a/src/Umbraco.Core/Composing/ContainerExtensions.cs +++ b/src/Umbraco.Core/Composing/ContainerExtensions.cs @@ -19,20 +19,6 @@ namespace Umbraco.Core.Composing public static T GetInstance(this IContainer container) => (T) container.GetInstance(typeof(T)); - /// - /// Gets an instance with arguments. - /// - /// The type of the instance. - /// The container. - /// Arguments. - /// An instance of the specified type. - /// - /// Throws an exception if the container failed to get an instance of the specified type. - /// The arguments are used as dependencies by the container. - /// - public static T GetInstance(this IContainer container, params object[] args) - => (T) container.GetInstance(typeof(T), args); - /// /// Tries to get an instance. /// @@ -44,32 +30,73 @@ namespace Umbraco.Core.Composing public static T TryGetInstance(this IContainer container) => (T) container.TryGetInstance(typeof(T)); - // fixme - document all these - + /// + /// Gets registration for a service. + /// + /// The type of the service. + /// The registrations for the service. public static IEnumerable GetRegistered(this IContainer container) => container.GetRegistered(typeof(TService)); + /// + /// Creates an instance with arguments. + /// + /// The type of the instance. + /// The container. + /// Arguments. + /// An instance of the specified type. + /// + /// Throws an exception if the container failed to get an instance of the specified type. + /// The arguments are used as dependencies by the container. + /// + public static T CreateInstance(this IContainer container, params object[] args) + => (T) container.CreateInstance(typeof(T), args); + + /// + /// Registers a service with an implementation type. + /// public static void Register(this IContainer container, Lifetime lifetime = Lifetime.Transient) => container.Register(typeof(TService), typeof(TImplementing), lifetime); + /// + /// Registers a service with a named implementation type. + /// public static void Register(this IContainer container, string name, Lifetime lifetime = Lifetime.Transient) => container.Register(typeof(TService), typeof(TImplementing), name, lifetime); + /// + /// Registers a service as its own implementation. + /// public static void Register(this IContainer container, Lifetime lifetime = Lifetime.Transient) => container.Register(typeof(TService), lifetime); + /// + /// Registers a singleton service as its own implementation. + /// public static void RegisterSingleton(this IContainer container) => container.Register(typeof(TService), Lifetime.Singleton); + /// + /// Registers a singleton service with an implementation type. + /// public static void RegisterSingleton(this IContainer container) => container.Register(typeof(TService), typeof(TImplementing), Lifetime.Singleton); + /// + /// Registers a singleton service with an implementation factory. + /// public static void RegisterSingleton(this IContainer container, Func factory) => container.Register(factory, Lifetime.Singleton); + /// + /// Registers a service with an implementing instance. + /// public static void RegisterInstance(this IContainer container, TService instance) => container.RegisterInstance(typeof(TService), instance); + /// + /// Registers a base type for auto-registration. + /// public static void RegisterAuto(this IContainer container) => container.RegisterAuto(typeof(TServiceBase)); @@ -85,13 +112,11 @@ namespace Umbraco.Core.Composing if (container.GetRegistered().Any()) throw new InvalidOperationException("Collection builders should be registered only once."); - // register the builder - per container - container.RegisterSingleton(); + // register the builder - passing the container as an arg to the factory + container.RegisterSingleton(c => c.CreateInstance(container)); - // initialize and return the builder - // note: see notes in IContainer - cannot pass the container as a parameter to a singleton - // and so, for now, the container is registered into itself - return container.GetInstance(/*new object[] { container }*/); + // initialize and return the builder + return container.GetInstance(); } } } diff --git a/src/Umbraco.Core/Composing/IContainer.cs b/src/Umbraco.Core/Composing/IContainer.cs index 2be539551e..dab5dd159c 100644 --- a/src/Umbraco.Core/Composing/IContainer.cs +++ b/src/Umbraco.Core/Composing/IContainer.cs @@ -15,6 +15,11 @@ namespace Umbraco.Core.Composing #region Factory + // notes + // when implementing IContainer, the following rules apply + // - always pick the constructor with the most parameters + // - always prefer Lazy parameters over non-Lazy in constructors + /// /// Gets an instance. /// @@ -32,21 +37,6 @@ namespace Umbraco.Core.Composing /// Throws an exception if the container failed to get an instance of the specified type. object GetInstance(Type type, string name); - /// - /// Gets an instance with arguments. - /// - /// The type of the instance. - /// Arguments. - /// An instance of the specified type. - /// - /// Throws an exception if the container failed to get an instance of the specified type. - /// The arguments are used as dependencies by the container. - /// - // fixme - some restrictions: - // method is not optimized, .Invoke-ing the ctor, no compiled dynamic method - // uses the ctor with most args, always, not trying to figure out which one to use - object GetInstance(Type type, params object[] args); - /// /// Tries to get an instance. /// @@ -76,6 +66,19 @@ namespace Umbraco.Core.Composing /// The registrations for the service. IEnumerable GetRegistered(Type serviceType); + /// + /// Creates an instance with arguments. + /// + /// The type of the instance. + /// Arguments. + /// An instance of the specified type. + /// + /// The instance type does not need to be registered into the container. + /// The arguments are used as dependencies by the container. Other dependencies + /// are retrieved from the container. + /// + object CreateInstance(Type type, params object[] args); + #endregion #region Registry @@ -106,11 +109,6 @@ namespace Umbraco.Core.Composing /// void Register(Func factory, Lifetime lifetime = Lifetime.Transient); - /// - /// Registers a service with an implementation factory accepting an argument. - /// - void Register(Func factory); - /// /// Registers a service with an implementing instance. /// @@ -146,18 +144,23 @@ namespace Umbraco.Core.Composing /// IDisposable BeginScope(); - // fixme - document all these - /// - /// Configures the container for Umbraco. + /// Configures the container for web support. /// + /// The container. /// - /// + /// Enables support for MVC, WebAPI, but *not* per-request scope. This is used early in the boot + /// process, where anything "scoped" should not be linked to a web request. /// - IContainer ConfigureForUmbraco(); - IContainer ConfigureForWeb(); + /// + /// Enables per-request scope. + /// + /// The container. + /// + /// Ties scopes to web requests. + /// IContainer EnablePerWebRequestScope(); #endregion diff --git a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs index 6e4b08eaed..35aba24c59 100644 --- a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs +++ b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs @@ -32,7 +32,53 @@ namespace Umbraco.Core.Composing.LightInject /// Creates a new instance of the LightInject service container. /// protected static ServiceContainer CreateServiceContainer() - => new ServiceContainer(new ContainerOptions { EnablePropertyInjection = false }); + { + var container = new ServiceContainer(new ContainerOptions { EnablePropertyInjection = false }); + + // supports annotated constructor injections + // eg to specify the service name on some services + container.EnableAnnotatedConstructorInjection(); + + // note: the block below is disabled, we do not allow property injection at all anymore + // (see options in CreateServiceContainer) + // + // from the docs: "LightInject considers all read/write properties a dependency, but implements + // a loose strategy around property dependencies, meaning that it will NOT throw an exception + // in the case of an unresolved property dependency." + // + // in Umbraco we do NOT want to do property injection by default, so we have to disable it. + // from the docs, the following line will cause the container to "now only try to inject + // dependencies for properties that is annotated with the InjectAttribute." + // + // could not find it documented, but tests & code review shows that LightInject considers a + // property to be "injectable" when its setter exists and is not static, nor private, nor + // it is an index property. which means that eg protected or internal setters are OK. + //Container.EnableAnnotatedPropertyInjection(); + + // ensure that we do *not* scan assemblies + // we explicitely RegisterFrom our own composition roots and don't want them scanned + container.AssemblyScanner = new AssemblyScanner(/*container.AssemblyScanner*/); + + // see notes in MixedLightInjectScopeManagerProvider + container.ScopeManagerProvider = new MixedLightInjectScopeManagerProvider(); + + // note: the block below is disabled, because it does not work, because collection builders + // are singletons, and constructor dependencies don't work on singletons, see + // https://github.com/seesharper/LightInject/issues/294 + // + // if looking for a IContainer, and one was passed in args, use it + // this is for collection builders which require the IContainer + //container.RegisterConstructorDependency((c, i, a) => a.OfType().FirstOrDefault()); + // + // and, the block below is also disabled, because it is ugly + // + //// which means that the only way to inject the container into builders is to register it + //container.RegisterInstance(this); + // + // instead, we use an explicit GetInstance with arguments implementation + + return container; + } /// /// Gets the LightInject container. @@ -62,11 +108,32 @@ namespace Umbraco.Core.Composing.LightInject => Container.GetInstance(type, name); /// - public object GetInstance(Type type, params object[] args) + public object TryGetInstance(Type type) + => Container.TryGetInstance(type); + + /// + public IEnumerable GetAllInstances() + => Container.GetAllInstances(); + + /// + public IEnumerable GetAllInstances(Type type) + => Container.GetAllInstances(type); + + /// + public IEnumerable GetRegistered(Type type) + => Container.AvailableServices.Where(x => x.ServiceType == type).Select(x => new Registration(x.ServiceType, x.ServiceName)); + + /// + public object CreateInstance(Type type, params object[] args) { // LightInject has this, but then it requires RegisterConstructorDependency etc and has various oddities + // including the most annoying one, which is that it does not work on singletons (hard to fix) //return Container.GetInstance(type, args); + // this method is essentially used to build singleton instances, so it is assumed that it would be + // more expensive to build and cache a dynamic method ctor than to simply invoke the ctor, as we do + // here - this can be discussed + var ctor = type.GetConstructors(BindingFlags.Instance | BindingFlags.Public).OrderByDescending(x => x.GetParameters().Length).FirstOrDefault(); if (ctor == null) throw new InvalidOperationException($"Could not find a public constructor for type {type.FullName}."); @@ -83,22 +150,6 @@ namespace Umbraco.Core.Composing.LightInject return ctor.Invoke(ctorArgs); } - /// - public object TryGetInstance(Type type) - => Container.TryGetInstance(type); - - /// - public IEnumerable GetAllInstances() - => Container.GetAllInstances(); - - /// - public IEnumerable GetAllInstances(Type type) - => Container.GetAllInstances(type); - - /// - public IEnumerable GetRegistered(Type type) - => Container.GetAvailableServices(type).Select(x => new Registration(x.ServiceType, x.ServiceName)); - #endregion #region Registry @@ -175,10 +226,6 @@ namespace Umbraco.Core.Composing.LightInject } } - /// - public void Register(Func factory) - => Container.Register((f, x) => factory(this, x)); - private ILifetime GetLifetime(Lifetime lifetime) { switch (lifetime) @@ -236,50 +283,17 @@ namespace Umbraco.Core.Composing.LightInject => Container.BeginScope(); /// - public IContainer ConfigureForUmbraco() + public virtual IContainer ConfigureForWeb() { - // supports annotated constructor injections - // eg to specify the service name on some services - Container.EnableAnnotatedConstructorInjection(); - - // note: the block below is disabled, we do not allow property injection at all anymore - // (see options in CreateServiceContainer) - // - // from the docs: "LightInject considers all read/write properties a dependency, but implements - // a loose strategy around property dependencies, meaning that it will NOT throw an exception - // in the case of an unresolved property dependency." - // - // in Umbraco we do NOT want to do property injection by default, so we have to disable it. - // from the docs, the following line will cause the container to "now only try to inject - // dependencies for properties that is annotated with the InjectAttribute." - // - // could not find it documented, but tests & code review shows that LightInject considers a - // property to be "injectable" when its setter exists and is not static, nor private, nor - // it is an index property. which means that eg protected or internal setters are OK. - //Container.EnableAnnotatedPropertyInjection(); - - // ensure that we do *not* scan assemblies - // we explicitely RegisterFrom our own composition roots and don't want them scanned - Container.AssemblyScanner = new AssemblyScanner(/*container.AssemblyScanner*/); - - // see notes in MixedLightInjectScopeManagerProvider - Container.ScopeManagerProvider = new MixedLightInjectScopeManagerProvider(); - - // note: the block below is disabled, because it does not work, because collection builders - // are singletons, and constructor dependencies don't work on singletons, see - // https://github.com/seesharper/LightInject/issues/294 - // - // if looking for a IContainer, and one was passed in args, use it - // this is for collection builders which require the IContainer - //Container.RegisterConstructorDependency((c, i, a) => a.OfType().FirstOrDefault()); - // - // and, the block below is also disabled, because it is ugly - // - //// which means that the only way to inject the container into builders is to register it - //Container.RegisterInstance(this); - // - // instead, we use an explicit GetInstance with arguments implementation + return this; + } + /// + public IContainer EnablePerWebRequestScope() + { + if (!(Container.ScopeManagerProvider is MixedLightInjectScopeManagerProvider smp)) + throw new Exception("Container.ScopeManagerProvider is not MixedLightInjectScopeManagerProvider."); + smp.EnablePerWebRequestScope(); return this; } @@ -303,21 +317,6 @@ namespace Umbraco.Core.Composing.LightInject } } - /// - public virtual IContainer ConfigureForWeb() - { - return this; - } - - /// - public IContainer EnablePerWebRequestScope() - { - if (!(Container.ScopeManagerProvider is MixedLightInjectScopeManagerProvider smp)) - throw new Exception("Container.ScopeManagerProvider is not MixedLightInjectScopeManagerProvider."); - smp.EnablePerWebRequestScope(); - return this; - } - #endregion } } diff --git a/src/Umbraco.Core/Composing/LightInjectExtensions.cs b/src/Umbraco.Core/Composing/LightInjectExtensions.cs index 30a4c0efb5..d552cf756e 100644 --- a/src/Umbraco.Core/Composing/LightInjectExtensions.cs +++ b/src/Umbraco.Core/Composing/LightInjectExtensions.cs @@ -1,9 +1,6 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Reflection; using LightInject; -using Umbraco.Core.Exceptions; namespace Umbraco.Core.Composing { @@ -12,12 +9,6 @@ namespace Umbraco.Core.Composing /// public static class LightInjectExtensions { - // fixme temp - internal static ServiceContainer AsLightInject(this IContainer container) - { - return (ServiceContainer) container.ConcreteContainer; - } - /// /// Registers the TService with the factory that describes the dependencies of the service, as a singleton. /// @@ -37,7 +28,7 @@ namespace Umbraco.Core.Composing } /// - /// Registers the TService with the TImplementation as a singleton. + /// Registers a servuice with an implementation as a singleton. /// public static void RegisterSingleton(this IServiceRegistry container) where TImplementation : TService @@ -45,7 +36,9 @@ namespace Umbraco.Core.Composing container.RegisterSingleton(typeof(TService), typeof(TImplementation)); } - // fixme + /// + /// Registers a servuice with an implementation as a singleton. + /// public static void RegisterSingleton(this IServiceRegistry container, Type serviceType, Type implementingType) { var registration = container.GetAvailableService(serviceType); @@ -62,9 +55,12 @@ namespace Umbraco.Core.Composing } } + /// + /// Registers a servuice with a named implementation as a singleton. + /// public static void RegisterSingleton(this IServiceRegistry container, Type serviceType, Type implementingType, string name) { - var registration = container.GetAvailableServices(serviceType).FirstOrDefault(x => x.ServiceName == name); + var registration = container.AvailableServices.FirstOrDefault(x => x.ServiceType == serviceType && x.ServiceName == name); if (registration == null) { @@ -86,6 +82,9 @@ namespace Umbraco.Core.Composing container.RegisterSingleton(typeof(TImplementation)); } + /// + /// Registers a concrete type as a singleton service. + /// public static void RegisterSingleton(this IServiceRegistry container, Type serviceType) { var registration = container.GetAvailableService(serviceType); @@ -162,18 +161,6 @@ namespace Umbraco.Core.Composing // }); } - /// - /// Gets the available service registrations for a service type. - /// - /// The service type. - /// The container. - /// The service registrations for the service type. - public static IEnumerable GetAvailableServices(this IServiceRegistry container) - => container.GetAvailableServices(typeof(TService)); - - public static IEnumerable GetAvailableServices(this IServiceRegistry container, Type serviceType) - => container.AvailableServices.Where(x => x.ServiceType == serviceType); - /// /// Gets the unique available service registration for a service type. /// @@ -181,14 +168,16 @@ namespace Umbraco.Core.Composing /// The container. /// The unique service registration for the service type. /// Can return null, but throws if more than one registration exist for the service type. - public static ServiceRegistration GetAvailableService(this IServiceRegistry container) + private static ServiceRegistration GetAvailableService(this IServiceRegistry container) { var typeofTService = typeof(TService); return container.AvailableServices.SingleOrDefault(x => x.ServiceType == typeofTService); } - // fixme - public static ServiceRegistration GetAvailableService(this IServiceRegistry container, Type serviceType) + /// + /// Gets the unique available service registration for a service type. + /// + private static ServiceRegistration GetAvailableService(this IServiceRegistry container, Type serviceType) { return container.AvailableServices.SingleOrDefault(x => x.ServiceType == serviceType); } @@ -201,7 +190,7 @@ namespace Umbraco.Core.Composing /// The name. /// The unique service registration for the service type and the name. /// Can return null, but throws if more than one registration exist for the service type and the name. - public static ServiceRegistration GetAvailableService(this IServiceRegistry container, string name) + private static ServiceRegistration GetAvailableService(this IServiceRegistry container, string name) { var typeofTService = typeof(TService); return container.AvailableServices.SingleOrDefault(x => x.ServiceType == typeofTService && x.ServiceName == name); diff --git a/src/Umbraco.Core/IO/FileSystems.cs b/src/Umbraco.Core/IO/FileSystems.cs index e9114d5310..5a4ee92e15 100644 --- a/src/Umbraco.Core/IO/FileSystems.cs +++ b/src/Umbraco.Core/IO/FileSystems.cs @@ -299,7 +299,7 @@ namespace Umbraco.Core.IO var shadowWrapper = new ShadowWrapper(innerFs, "typed/" + alias, () => IsScoped()); // getting the fs from the container - see FileSystemsComposer - var fs = Current.Container.GetInstance((IFileSystem) shadowWrapper); + var fs = Current.Container.CreateInstance((IFileSystem) shadowWrapper); _wrappers.Add(shadowWrapper); // keeping a reference to the wrapper return fs; }); diff --git a/src/Umbraco.Core/Migrations/MigrationBuilder.cs b/src/Umbraco.Core/Migrations/MigrationBuilder.cs index fa22c96595..aebd8bd1ee 100644 --- a/src/Umbraco.Core/Migrations/MigrationBuilder.cs +++ b/src/Umbraco.Core/Migrations/MigrationBuilder.cs @@ -14,8 +14,7 @@ namespace Umbraco.Core.Migrations public IMigration Build(Type migrationType, IMigrationContext context) { - _container.Register(migrationType); - return (IMigration) _container.GetInstance(migrationType, context); + return (IMigration) _container.CreateInstance(migrationType, context); } } } diff --git a/src/Umbraco.Core/UmbracoApplicationBase.cs b/src/Umbraco.Core/UmbracoApplicationBase.cs index 20b2131217..5d40a64002 100644 --- a/src/Umbraco.Core/UmbracoApplicationBase.cs +++ b/src/Umbraco.Core/UmbracoApplicationBase.cs @@ -70,7 +70,6 @@ namespace Umbraco.Core // create the container for the application, and configure. // the boot manager is responsible for registrations var container = GetContainer(); - container.ConfigureForUmbraco(); Current.Container = container; // register the essential stuff, diff --git a/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs b/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs index 750768eb1d..07cb2b8319 100644 --- a/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs +++ b/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs @@ -21,7 +21,6 @@ namespace Umbraco.Tests.Cache.DistributedCache public void Setup() { var container = Current.Container = Core.Composing.LightInject.LightInjectContainer.Create(); - container.ConfigureForUmbraco(); container.Register(_ => new TestServerRegistrar()); container.RegisterSingleton(_ => new TestServerMessenger()); diff --git a/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs b/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs index 6516d2fbfd..4e254ce425 100644 --- a/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs +++ b/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs @@ -18,7 +18,6 @@ namespace Umbraco.Tests.Composing Current.Reset(); _container = Current.Container = Core.Composing.LightInject.LightInjectContainer.Create(); - _container.ConfigureForUmbraco(); } [TearDown] diff --git a/src/Umbraco.Tests/Composing/ContainerImplementationTests.cs b/src/Umbraco.Tests/Composing/ContainerImplementationTests.cs new file mode 100644 index 0000000000..46a2d08256 --- /dev/null +++ b/src/Umbraco.Tests/Composing/ContainerImplementationTests.cs @@ -0,0 +1,66 @@ +using NUnit.Framework; +using Umbraco.Core.Composing; + +namespace Umbraco.Tests.Composing +{ + // TODO + // this class should contain everything to ensure that a container implementation + // complies with Umbraco's requirements. + + [TestFixture] + public class ContainerImplementationTests + { + private IContainer CreateContainer() => Core.Composing.LightInject.LightInjectContainer.Create(); + + [Test] + public void CanRegisterSingletonInterface() + { + var container = CreateContainer(); + container.RegisterSingleton(); + var s1 = container.GetInstance(); + var s2 = container.GetInstance(); + Assert.AreSame(s1, s2); + } + + [Test] + public void CanRegisterSingletonClass() + { + var container = CreateContainer(); + container.RegisterSingleton(); + var s1 = container.GetInstance(); + var s2 = container.GetInstance(); + Assert.AreSame(s1, s2); + } + + [Test] + public void CanReRegisterSingletonInterface() + { + var container = CreateContainer(); + container.RegisterSingleton(); + container.RegisterSingleton(); + var s = container.GetInstance(); + Assert.IsInstanceOf(s); + } + + [Test] + public void CanRegisterSingletonWithCreate() + { + var container = CreateContainer(); + container.RegisterSingleton(c => c.CreateInstance(new TestClass1())); + var s1 = container.GetInstance(); + var s2 = container.GetInstance(); + Assert.AreSame(s1, s2); + } + + public interface ITestInterface{} + + public class TestClass1 : ITestInterface{} + + public class TestClass2 : ITestInterface{} + + public class TestClass3 + { + public TestClass3(TestClass1 c) {} + } + } +} diff --git a/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs b/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs index 51f38cebf0..d28820f59f 100644 --- a/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs +++ b/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs @@ -23,7 +23,7 @@ namespace Umbraco.Tests.Composing } private IContainer CreateContainer() - => Current.Container = Core.Composing.LightInject.LightInjectContainer.Create().ConfigureForUmbraco(); + => Current.Container = Core.Composing.LightInject.LightInjectContainer.Create(); // note // lazy collection builder does not throw on duplicate, just uses distinct types diff --git a/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs b/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs index 01fa9e7835..c49dd4b83f 100644 --- a/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs +++ b/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs @@ -14,7 +14,6 @@ namespace Umbraco.Tests.Composing public void PackageActionCollectionBuilderWorks() { var container = Current.Container = Core.Composing.LightInject.LightInjectContainer.Create(); - container.ConfigureForUmbraco(); container.RegisterCollectionBuilder() .Add(() => TypeLoader.GetPackageActions()); diff --git a/src/Umbraco.Tests/IO/FileSystemsTests.cs b/src/Umbraco.Tests/IO/FileSystemsTests.cs index eb437d6a51..e265793239 100644 --- a/src/Umbraco.Tests/IO/FileSystemsTests.cs +++ b/src/Umbraco.Tests/IO/FileSystemsTests.cs @@ -27,7 +27,6 @@ namespace Umbraco.Tests.IO SettingsForTests.ConfigureSettings(config); _container = Current.Container = Core.Composing.LightInject.LightInjectContainer.Create(); - _container.ConfigureForUmbraco(); _container.Register(_ => Mock.Of()); _container.Register(); @@ -35,9 +34,6 @@ namespace Umbraco.Tests.IO _container.Register(_ => Mock.Of()); _container.RegisterSingleton(); - _container.Register((f, x) => new MediaFileSystem(x, f.GetInstance(), f.GetInstance(), f.GetInstance())); - _container.Register((f, x) => new NonConfiguredTypeFileSystem(x)); - // make sure we start clean // because some tests will create corrupt or weird filesystems FileSystems.Reset(); diff --git a/src/Umbraco.Tests/Models/ContentTests.cs b/src/Umbraco.Tests/Models/ContentTests.cs index d1e8b3f29d..1eccb5f2aa 100644 --- a/src/Umbraco.Tests/Models/ContentTests.cs +++ b/src/Umbraco.Tests/Models/ContentTests.cs @@ -40,9 +40,9 @@ namespace Umbraco.Tests.Models base.Compose(); Container.Register(_ => Mock.Of()); - Container.Register((factory, fileSystem) => new MediaFileSystem(fileSystem, factory.GetInstance(), factory.GetInstance(), factory.GetInstance())); Container.Register(); Container.Register(factory => factory.GetInstance()); + Container.Register(factory => factory.GetInstance().MediaFileSystem); Container.Register(_ => Mock.Of()); Container.Register(_ => Mock.Of()); } diff --git a/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs b/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs index 4c73ed8409..cb739edd92 100644 --- a/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs +++ b/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs @@ -66,7 +66,6 @@ namespace Umbraco.Tests.PropertyEditors try { var container = Current.Container = Core.Composing.LightInject.LightInjectContainer.Create(); - container.ConfigureForUmbraco(); container.RegisterCollectionBuilder(); diff --git a/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs b/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs index 38a37f0083..7efb8734c4 100644 --- a/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs +++ b/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs @@ -22,7 +22,6 @@ namespace Umbraco.Tests.PropertyEditors Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture; var container = Current.Container = Core.Composing.LightInject.LightInjectContainer.Create(); - container.ConfigureForUmbraco(); container.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 44e84e98fb..5447a8b368 100644 --- a/src/Umbraco.Tests/Published/ConvertersTests.cs +++ b/src/Umbraco.Tests/Published/ConvertersTests.cs @@ -172,7 +172,6 @@ namespace Umbraco.Tests.Published { Current.Reset(); var container = Current.Container = Core.Composing.LightInject.LightInjectContainer.Create(); - container.ConfigureForUmbraco(); Current.Container.RegisterCollectionBuilder() diff --git a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs index 1549de8554..9ae9fd4700 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs @@ -33,7 +33,6 @@ namespace Umbraco.Tests.TestHelpers var sqlSyntax = new SqlCeSyntaxProvider(); var container = Current.Container = Core.Composing.LightInject.LightInjectContainer.Create(); - container.ConfigureForUmbraco(); container.RegisterSingleton(factory => Mock.Of()); container.RegisterSingleton(factory => Mock.Of()); diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index 04b22831a4..60c55f6406 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -114,7 +114,6 @@ namespace Umbraco.Tests.Testing Reset(); Container = Current.Container = Core.Composing.LightInject.LightInjectContainer.Create(); - Container.ConfigureForUmbraco(); TestObjects = new TestObjects(Container); @@ -325,6 +324,7 @@ namespace Umbraco.Tests.Testing // note - don't register collections, use builders Container.RegisterCollectionBuilder(); + var temp = Container.GetInstance(); Container.RegisterSingleton(); Container.RegisterSingleton(); } diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index fc70e6ae9e..f2a59d03a5 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -115,6 +115,7 @@ + From 0eb1ba56a44e3017272af9e4ed4450786b5a3fd8 Mon Sep 17 00:00:00 2001 From: Stephan Date: Mon, 23 Jul 2018 12:19:26 +0200 Subject: [PATCH 030/469] Comments --- .../Composing/LightInject/LightInjectContainer.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs index 35aba24c59..0a81f0e9eb 100644 --- a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs +++ b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs @@ -150,6 +150,12 @@ namespace Umbraco.Core.Composing.LightInject return ctor.Invoke(ctorArgs); } + // notes: + // we may want to look into MS code, eg: + // TypeActivatorCache in MVC at https://github.com/aspnet/Mvc/blob/dev/src/Microsoft.AspNetCore.Mvc.Core/Internal/TypeActivatorCache.cs + // which relies onto + // ActivatorUtilities at https://github.com/aspnet/DependencyInjection/blob/master/shared/Microsoft.Extensions.ActivatorUtilities.Sources/ActivatorUtilities.cs + #endregion #region Registry From caa2802c16acaf214db00ec13bddc745ef149c26 Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Fri, 27 Jul 2018 21:16:11 +0200 Subject: [PATCH 031/469] Moved creation of container into ContainerFactory --- .../Composing/ContainerFactory.cs | 37 +++++++++++++++++++ src/Umbraco.Core/Umbraco.Core.csproj | 1 + src/Umbraco.Core/UmbracoApplicationBase.cs | 2 +- .../DistributedCache/DistributedCacheTests.cs | 2 +- .../Composing/CollectionBuildersTests.cs | 2 +- .../Composing/ContainerImplementationTests.cs | 2 +- .../Composing/LazyCollectionBuilderTests.cs | 2 +- .../Composing/PackageActionCollectionTests.cs | 2 +- src/Umbraco.Tests/IO/FileSystemsTests.cs | 2 +- .../PropertyEditors/ImageCropperTest.cs | 2 +- .../PropertyEditorValueEditorTests.cs | 2 +- .../Published/ConvertersTests.cs | 2 +- .../Scoping/ScopeEventDispatcherTests.cs | 2 +- .../TestHelpers/BaseUsingSqlCeSyntax.cs | 2 +- src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 2 +- 15 files changed, 51 insertions(+), 13 deletions(-) create mode 100644 src/Umbraco.Core/Composing/ContainerFactory.cs diff --git a/src/Umbraco.Core/Composing/ContainerFactory.cs b/src/Umbraco.Core/Composing/ContainerFactory.cs new file mode 100644 index 0000000000..70e04eb2ed --- /dev/null +++ b/src/Umbraco.Core/Composing/ContainerFactory.cs @@ -0,0 +1,37 @@ +using System; +using System.Configuration; +using System.Reflection; +using Umbraco.Core.Composing.LightInject; + +namespace Umbraco.Core.Composing +{ + public class ContainerFactory + { + /// + /// Creates a new instance of the configured container. + /// To override the default LightInjectContainer, add an appSetting named umbracoContainerType with + /// a fully qualified type name to a class with a static method "Create" returning an IContainer. + /// + public static IContainer Create() + { + var configuredTypeName = ConfigurationManager.AppSettings["umbracoContainerType"] + ?? typeof(LightInjectContainer).AssemblyQualifiedName; + var type = Type.GetType(configuredTypeName); + if (type == null) + { + throw new Exception($"Cannot find container factory class named '${configuredTypeName}'"); + } + var factoryMethod = type.GetMethod("Create", BindingFlags.Static); + if (factoryMethod == null) + { + throw new Exception($"Container factory class '${configuredTypeName}' does not have a public static method named Create"); + } + var container = factoryMethod.Invoke(null, new object[0]) as IContainer; + if (container == null) + { + throw new Exception($"Container factory '${configuredTypeName}' did not return an IContainer implementation."); + } + return container; + } + } +} diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 412b55ea71..b9b682de33 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -160,6 +160,7 @@ + diff --git a/src/Umbraco.Core/UmbracoApplicationBase.cs b/src/Umbraco.Core/UmbracoApplicationBase.cs index 5d40a64002..2e08814e1f 100644 --- a/src/Umbraco.Core/UmbracoApplicationBase.cs +++ b/src/Umbraco.Core/UmbracoApplicationBase.cs @@ -36,7 +36,7 @@ namespace Umbraco.Core { // note: the actual, web UmbracoApplication is overriding this // with a web-supporting container - return Composing.LightInject.LightInjectContainer.Create(); + return ContainerFactory.Create(); } // events - in the order they trigger diff --git a/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs b/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs index 07cb2b8319..554194fd91 100644 --- a/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs +++ b/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs @@ -20,7 +20,7 @@ namespace Umbraco.Tests.Cache.DistributedCache [SetUp] public void Setup() { - var container = Current.Container = Core.Composing.LightInject.LightInjectContainer.Create(); + var container = Current.Container = ContainerFactory.Create(); container.Register(_ => new TestServerRegistrar()); container.RegisterSingleton(_ => new TestServerMessenger()); diff --git a/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs b/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs index 4e254ce425..1bddbdfbb2 100644 --- a/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs +++ b/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs @@ -17,7 +17,7 @@ namespace Umbraco.Tests.Composing { Current.Reset(); - _container = Current.Container = Core.Composing.LightInject.LightInjectContainer.Create(); + _container = Current.Container = ContainerFactory.Create(); } [TearDown] diff --git a/src/Umbraco.Tests/Composing/ContainerImplementationTests.cs b/src/Umbraco.Tests/Composing/ContainerImplementationTests.cs index 46a2d08256..818bf47cd0 100644 --- a/src/Umbraco.Tests/Composing/ContainerImplementationTests.cs +++ b/src/Umbraco.Tests/Composing/ContainerImplementationTests.cs @@ -10,7 +10,7 @@ namespace Umbraco.Tests.Composing [TestFixture] public class ContainerImplementationTests { - private IContainer CreateContainer() => Core.Composing.LightInject.LightInjectContainer.Create(); + private IContainer CreateContainer() => ContainerFactory.Create(); [Test] public void CanRegisterSingletonInterface() diff --git a/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs b/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs index d28820f59f..e0dde277f9 100644 --- a/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs +++ b/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs @@ -23,7 +23,7 @@ namespace Umbraco.Tests.Composing } private IContainer CreateContainer() - => Current.Container = Core.Composing.LightInject.LightInjectContainer.Create(); + => Current.Container = ContainerFactory.Create(); // note // lazy collection builder does not throw on duplicate, just uses distinct types diff --git a/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs b/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs index c49dd4b83f..236d92b94e 100644 --- a/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs +++ b/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs @@ -13,7 +13,7 @@ namespace Umbraco.Tests.Composing [Test] public void PackageActionCollectionBuilderWorks() { - var container = Current.Container = Core.Composing.LightInject.LightInjectContainer.Create(); + var container = Current.Container = ContainerFactory.Create(); container.RegisterCollectionBuilder() .Add(() => TypeLoader.GetPackageActions()); diff --git a/src/Umbraco.Tests/IO/FileSystemsTests.cs b/src/Umbraco.Tests/IO/FileSystemsTests.cs index e265793239..f97bdc4189 100644 --- a/src/Umbraco.Tests/IO/FileSystemsTests.cs +++ b/src/Umbraco.Tests/IO/FileSystemsTests.cs @@ -26,7 +26,7 @@ namespace Umbraco.Tests.IO var config = SettingsForTests.GetDefaultUmbracoSettings(); SettingsForTests.ConfigureSettings(config); - _container = Current.Container = Core.Composing.LightInject.LightInjectContainer.Create(); + _container = Current.Container = ContainerFactory.Create(); _container.Register(_ => Mock.Of()); _container.Register(); diff --git a/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs b/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs index cb739edd92..2c5bc621eb 100644 --- a/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs +++ b/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs @@ -65,7 +65,7 @@ namespace Umbraco.Tests.PropertyEditors { try { - var container = Current.Container = Core.Composing.LightInject.LightInjectContainer.Create(); + var container = Current.Container = ContainerFactory.Create(); container.RegisterCollectionBuilder(); diff --git a/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs b/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs index 7efb8734c4..00ca646360 100644 --- a/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs +++ b/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs @@ -21,7 +21,7 @@ namespace Umbraco.Tests.PropertyEditors //normalize culture Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture; - var container = Current.Container = Core.Composing.LightInject.LightInjectContainer.Create(); + var container = Current.Container = ContainerFactory.Create(); container.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 5447a8b368..c0ae68d7d5 100644 --- a/src/Umbraco.Tests/Published/ConvertersTests.cs +++ b/src/Umbraco.Tests/Published/ConvertersTests.cs @@ -171,7 +171,7 @@ namespace Umbraco.Tests.Published public void SimpleConverter3Test() { Current.Reset(); - var container = Current.Container = Core.Composing.LightInject.LightInjectContainer.Create(); + var container = Current.Container = ContainerFactory.Create(); Current.Container.RegisterCollectionBuilder() diff --git a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs index 89d361e789..9d08229563 100644 --- a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs @@ -29,7 +29,7 @@ namespace Umbraco.Tests.Scoping DoThing2 = null; DoThing3 = null; - var container = Current.Container = Core.Composing.LightInject.LightInjectContainer.Create(); + var container = Current.Container = ContainerFactory.Create(); _testObjects = new TestObjects(container); diff --git a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs index 9ae9fd4700..4314af38b5 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs @@ -32,7 +32,7 @@ namespace Umbraco.Tests.TestHelpers var sqlSyntax = new SqlCeSyntaxProvider(); - var container = Current.Container = Core.Composing.LightInject.LightInjectContainer.Create(); + var container = Current.Container = ContainerFactory.Create(); container.RegisterSingleton(factory => Mock.Of()); container.RegisterSingleton(factory => Mock.Of()); diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index 60c55f6406..7d9dd34491 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -113,7 +113,7 @@ namespace Umbraco.Tests.Testing // but hey, never know, better avoid garbage-in Reset(); - Container = Current.Container = Core.Composing.LightInject.LightInjectContainer.Create(); + Container = Current.Container = ContainerFactory.Create(); TestObjects = new TestObjects(Container); From c885f850e9dcb09da349252d71f68e191eef6155 Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Sat, 28 Jul 2018 01:05:07 +0200 Subject: [PATCH 032/469] Container should be registered with itself --- src/Umbraco.Core/Composing/ContainerFactory.cs | 1 + src/Umbraco.Core/UmbracoApplicationBase.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/Umbraco.Core/Composing/ContainerFactory.cs b/src/Umbraco.Core/Composing/ContainerFactory.cs index 70e04eb2ed..5c85072298 100644 --- a/src/Umbraco.Core/Composing/ContainerFactory.cs +++ b/src/Umbraco.Core/Composing/ContainerFactory.cs @@ -31,6 +31,7 @@ namespace Umbraco.Core.Composing { throw new Exception($"Container factory '${configuredTypeName}' did not return an IContainer implementation."); } + return container; } } diff --git a/src/Umbraco.Core/UmbracoApplicationBase.cs b/src/Umbraco.Core/UmbracoApplicationBase.cs index 2e08814e1f..12bb63f83b 100644 --- a/src/Umbraco.Core/UmbracoApplicationBase.cs +++ b/src/Umbraco.Core/UmbracoApplicationBase.cs @@ -70,6 +70,7 @@ namespace Umbraco.Core // create the container for the application, and configure. // the boot manager is responsible for registrations var container = GetContainer(); + container.RegisterSingleton(x => container); Current.Container = container; // register the essential stuff, From ce490a4c5bcefb98155b99ff8bd499361e7b794c Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Sat, 28 Jul 2018 01:12:14 +0200 Subject: [PATCH 033/469] Adding null check to avoid nullref exception on 292 in WebSecurity during install. Still getting nullref on line 115 during install. --- src/Umbraco.Web/Security/WebSecurity.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web/Security/WebSecurity.cs b/src/Umbraco.Web/Security/WebSecurity.cs index 0d089662f8..cee2c56d5f 100644 --- a/src/Umbraco.Web/Security/WebSecurity.cs +++ b/src/Umbraco.Web/Security/WebSecurity.cs @@ -289,7 +289,7 @@ namespace Umbraco.Web.Security /// public bool IsAuthenticated() { - return _httpContext.User.Identity.IsAuthenticated && _httpContext.GetCurrentIdentity(false) != null; + return _httpContext.User != null && _httpContext.User.Identity.IsAuthenticated && _httpContext.GetCurrentIdentity(false) != null; } protected override void DisposeResources() From ec95017e2ca2c4a15576cb44f0f4d3c47548d40c Mon Sep 17 00:00:00 2001 From: Stephan Date: Mon, 30 Jul 2018 11:37:20 +0200 Subject: [PATCH 034/469] Cleanup DI --- .../Composing/ContainerFactory.cs | 52 +++++++++++++------ .../Runtime/CoreRuntimeComponent.cs | 2 +- src/Umbraco.Core/UmbracoApplicationBase.cs | 1 - src/Umbraco.Web/UmbracoApplication.cs | 6 --- 4 files changed, 36 insertions(+), 25 deletions(-) diff --git a/src/Umbraco.Core/Composing/ContainerFactory.cs b/src/Umbraco.Core/Composing/ContainerFactory.cs index 5c85072298..fb2c5f6eb7 100644 --- a/src/Umbraco.Core/Composing/ContainerFactory.cs +++ b/src/Umbraco.Core/Composing/ContainerFactory.cs @@ -1,36 +1,54 @@ using System; using System.Configuration; using System.Reflection; -using Umbraco.Core.Composing.LightInject; namespace Umbraco.Core.Composing { - public class ContainerFactory + /// + /// Creates the container. + /// + public static class ContainerFactory { + // cannot use typeof().AssemblyQualifiedName on the web container - we don't reference it + // a normal Umbraco site should run on the web container, but an app may run on the core one + private const string CoreLightInjectContainerTypeName = "Umbraco.Core.Composing.LightInject.LightInjectContainer,Umbraco.Core"; + private const string WebLightInjectContainerTypeName = "Umbraco.Web.Composing.LightInject.LightInjectContainer,Umbraco.Web"; + /// /// Creates a new instance of the configured container. + /// + /// /// To override the default LightInjectContainer, add an appSetting named umbracoContainerType with /// a fully qualified type name to a class with a static method "Create" returning an IContainer. - /// + /// public static IContainer Create() { - var configuredTypeName = ConfigurationManager.AppSettings["umbracoContainerType"] - ?? typeof(LightInjectContainer).AssemblyQualifiedName; - var type = Type.GetType(configuredTypeName); + Type type; + + var configuredTypeName = ConfigurationManager.AppSettings["umbracoContainerType"]; + if (configuredTypeName.IsNullOrWhiteSpace()) + { + // try to get the web LightInject container type, + // else the core LightInject container type + type = Type.GetType(configuredTypeName = WebLightInjectContainerTypeName) ?? + Type.GetType(configuredTypeName = CoreLightInjectContainerTypeName); + } + else + { + // try to get the configured container type + type = Type.GetType(configuredTypeName); + } + if (type == null) - { - throw new Exception($"Cannot find container factory class named '${configuredTypeName}'"); - } - var factoryMethod = type.GetMethod("Create", BindingFlags.Static); + throw new Exception($"Cannot find container factory class '{configuredTypeName}'."); + + var factoryMethod = type.GetMethod("Create", BindingFlags.Public | BindingFlags.Static); if (factoryMethod == null) - { - throw new Exception($"Container factory class '${configuredTypeName}' does not have a public static method named Create"); - } - var container = factoryMethod.Invoke(null, new object[0]) as IContainer; + throw new Exception($"Container factory class '{configuredTypeName}' does not have a public static method named Create."); + + var container = factoryMethod.Invoke(null, Array.Empty()) as IContainer; if (container == null) - { - throw new Exception($"Container factory '${configuredTypeName}' did not return an IContainer implementation."); - } + throw new Exception($"Container factory '{configuredTypeName}' did not return an IContainer implementation."); return container; } diff --git a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs index d06b6215b3..efd9bde0b5 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs @@ -103,7 +103,7 @@ namespace Umbraco.Core.Runtime composition.Container.RegisterCollectionBuilder() .Add(factory => factory.GetInstance().GetTypes()); - composition.Container.RegisterSingleton(); + composition.Container.RegisterSingleton(factory => new MigrationBuilder(composition.Container)); // by default, register a noop factory composition.Container.RegisterSingleton(); diff --git a/src/Umbraco.Core/UmbracoApplicationBase.cs b/src/Umbraco.Core/UmbracoApplicationBase.cs index 12bb63f83b..2e08814e1f 100644 --- a/src/Umbraco.Core/UmbracoApplicationBase.cs +++ b/src/Umbraco.Core/UmbracoApplicationBase.cs @@ -70,7 +70,6 @@ namespace Umbraco.Core // create the container for the application, and configure. // the boot manager is responsible for registrations var container = GetContainer(); - container.RegisterSingleton(x => container); Current.Container = container; // register the essential stuff, diff --git a/src/Umbraco.Web/UmbracoApplication.cs b/src/Umbraco.Web/UmbracoApplication.cs index 40ebac4536..136f09f83d 100644 --- a/src/Umbraco.Web/UmbracoApplication.cs +++ b/src/Umbraco.Web/UmbracoApplication.cs @@ -1,5 +1,4 @@ using Umbraco.Core; -using Umbraco.Core.Composing; using Umbraco.Web.Runtime; namespace Umbraco.Web @@ -13,10 +12,5 @@ namespace Umbraco.Web { return new WebRuntime(this); } - - protected override IContainer GetContainer() - { - return Composing.LightInject.LightInjectContainer.Create(); - } } } From 865d3f6e30fbcc139624d27b9d434f99a547d215 Mon Sep 17 00:00:00 2001 From: Stephan Date: Mon, 30 Jul 2018 16:16:10 +0200 Subject: [PATCH 035/469] Cleanup and Fix DI --- .../TestControllerActivatorBase.cs | 2 +- .../Testing/TestingTests/MockTests.cs | 2 +- .../Web/Mvc/SurfaceControllerTests.cs | 2 +- .../Runtime/WebRuntimeComponent.cs | 2 +- src/Umbraco.Web/Security/MembershipHelper.cs | 103 +++++++----------- src/Umbraco.Web/Security/WebSecurity.cs | 11 +- 6 files changed, 47 insertions(+), 75 deletions(-) diff --git a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs index fb59ebee72..6ea7fa58e2 100644 --- a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs +++ b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs @@ -150,7 +150,7 @@ namespace Umbraco.Tests.TestHelpers.ControllerTesting urlHelper.Setup(provider => provider.GetUrl(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Returns("/hello/world/1234"); - var membershipHelper = new MembershipHelper(new TestUmbracoContextAccessor(umbCtx), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), null); + var membershipHelper = new MembershipHelper(new TestUmbracoContextAccessor(umbCtx), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), null, Mock.Of(), Mock.Of()); var mockedTypedContent = Mock.Of(); diff --git a/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs b/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs index a00f527c2c..1c4df69e54 100644 --- a/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs +++ b/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs @@ -67,7 +67,7 @@ namespace Umbraco.Tests.Testing.TestingTests Mock.Of(), Mock.Of(), Mock.Of(), - new MembershipHelper(new TestUmbracoContextAccessor(umbracoContext), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), null), + new MembershipHelper(new TestUmbracoContextAccessor(umbracoContext), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), null, Mock.Of(), Mock.Of()), new ServiceContext(), CacheHelper.Disabled); Assert.Pass(); diff --git a/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs b/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs index bd68325e06..ada96a3895 100644 --- a/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs +++ b/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs @@ -129,7 +129,7 @@ namespace Umbraco.Tests.Web.Mvc Mock.Of(), Mock.Of(), Mock.Of(), - new MembershipHelper(new TestUmbracoContextAccessor(umbracoContext), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), null), + new MembershipHelper(new TestUmbracoContextAccessor(umbracoContext), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), null, Mock.Of(), Mock.Of()), new ServiceContext(), CacheHelper.Disabled); diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs index 29d40c0ce9..e007ca322e 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs @@ -92,7 +92,7 @@ namespace Umbraco.Web.Runtime // register a per-request HttpContextBase object // is per-request so only one wrapper is created per request - composition.Container.RegisterSingleton(factory => new HttpContextWrapper(factory.GetInstance().HttpContext)); + composition.Container.Register(factory => new HttpContextWrapper(factory.GetInstance().HttpContext), Lifetime.Request); // register the published snapshot accessor - the "current" published snapshot is in the umbraco context composition.Container.RegisterSingleton(); diff --git a/src/Umbraco.Web/Security/MembershipHelper.cs b/src/Umbraco.Web/Security/MembershipHelper.cs index 8b6edb7e15..bed6099964 100644 --- a/src/Umbraco.Web/Security/MembershipHelper.cs +++ b/src/Umbraco.Web/Security/MembershipHelper.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.ComponentModel; using System.Linq; using System.Text; using System.Web; @@ -16,9 +15,7 @@ using Umbraco.Core.Composing; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Services; using Umbraco.Web.Editors; -using Umbraco.Web.Security.Providers; using Umbraco.Web.Routing; -using MPE = global::Umbraco.Core.Security.MembershipProviderExtensions; namespace Umbraco.Web.Security { @@ -27,26 +24,16 @@ namespace Umbraco.Web.Security /// public class MembershipHelper { + private readonly IUmbracoContextAccessor _umbracoContextAccessor; private readonly MembershipProvider _membershipProvider; private readonly RoleProvider _roleProvider; - private readonly HttpContextBase _httpContext; - private readonly IPublishedMemberCache _memberCache; - private readonly UmbracoContext _umbracoContext; - - private IMemberService MemberService { get; } - - private IMemberTypeService MemberTypeService { get; } - - private IUserService UserService { get; } - - private IPublicAccessService PublicAccessService { get; } - public CacheHelper CacheHelper { get; } - - private CacheHelper ApplicationCache { get; } - - private ILogger Logger { get; } - - private PublishedRouter Router { get; } + private readonly IMemberService _memberService; + private readonly IMemberTypeService _memberTypeService; + private readonly IUserService _userService; + private readonly IPublicAccessService _publicAccessService; + private readonly PublishedRouter _publishedRouter; + private readonly CacheHelper _appCaches; + private readonly ILogger _logger; #region Constructors @@ -59,40 +46,30 @@ namespace Umbraco.Web.Security IMemberTypeService memberTypeService, IUserService userService, IPublicAccessService publicAccessService, - CacheHelper cacheHelper, - ILogger logger, - PublishedRouter router + PublishedRouter publishedRouter, + CacheHelper appCaches, + ILogger logger ) { - if (accessor.UmbracoContext == null) throw new ArgumentNullException(nameof(accessor)); - if (membershipProvider == null) throw new ArgumentNullException(nameof(membershipProvider)); - if (roleProvider == null) throw new ArgumentNullException(nameof(roleProvider)); - MemberService = memberService; - MemberTypeService = memberTypeService; - UserService = userService; - PublicAccessService = publicAccessService; - CacheHelper = cacheHelper; - Logger = logger; - Router = router; + _umbracoContextAccessor = accessor ?? throw new ArgumentNullException(nameof(accessor)); - _httpContext = accessor.UmbracoContext.HttpContext; - _umbracoContext = accessor.UmbracoContext; - _membershipProvider = membershipProvider; - _roleProvider = roleProvider; - _memberCache = accessor.UmbracoContext.PublishedSnapshot.Members; + _memberService = memberService; + _memberTypeService = memberTypeService; + _userService = userService; + _publicAccessService = publicAccessService; + _publishedRouter = publishedRouter; + _appCaches = appCaches; + _logger = logger; + + _membershipProvider = membershipProvider ?? throw new ArgumentNullException(nameof(membershipProvider)); + _roleProvider = roleProvider ?? throw new ArgumentNullException(nameof(roleProvider)); } #endregion - protected IPublishedMemberCache MemberCache - { - get - { - if (_memberCache == null) - throw new InvalidOperationException("No MemberCache."); - return _memberCache; - } - } + protected UmbracoContext UmbracoContext => _umbracoContextAccessor.UmbracoContext ?? throw new InvalidOperationException("No UmbracoContext."); + protected HttpContextBase HttpContext => UmbracoContext.HttpContext ?? throw new InvalidOperationException("No UmbracoContext.HttpContext."); + protected IPublishedMemberCache MemberCache => UmbracoContext.PublishedSnapshot.Members ?? throw new InvalidOperationException("No UmbracoContext.PUblishedSnapshot.Members."); /// /// Check if a document object is protected by the "Protect Pages" functionality in umbraco @@ -102,7 +79,7 @@ namespace Umbraco.Web.Security public virtual bool IsProtected(string path) { //this is a cached call - return PublicAccessService.IsProtected(path); + return _publicAccessService.IsProtected(path); } /// @@ -113,7 +90,7 @@ namespace Umbraco.Web.Security public virtual bool MemberHasAccess(string path) { //cache this in the request cache - return ApplicationCache.RequestCache.GetCacheItem(string.Format("{0}.{1}-{2}", typeof(MembershipHelper), "MemberHasAccess", path), () => + return _appCaches.RequestCache.GetCacheItem($"{typeof(MembershipHelper)}.MemberHasAccess-{path}", () => { if (IsProtected(path)) { @@ -137,9 +114,9 @@ namespace Umbraco.Web.Security /// private bool HasAccess(string path, RoleProvider roleProvider) { - return _umbracoContext.PublishedRequest == null - ? PublicAccessService.HasAccess(path, CurrentUserName, roleProvider.GetRolesForUser) - : PublicAccessService.HasAccess(path, CurrentUserName, Router.GetRolesForLogin); + return UmbracoContext.PublishedRequest == null + ? _publicAccessService.HasAccess(path, CurrentUserName, roleProvider.GetRolesForUser) + : _publicAccessService.HasAccess(path, CurrentUserName, _publishedRouter.GetRolesForLogin); } /// @@ -170,7 +147,7 @@ namespace Umbraco.Web.Security var provider = _membershipProvider; var membershipUser = provider.GetCurrentUser(); //NOTE: This should never happen since they are logged in - if (membershipUser == null) throw new InvalidOperationException("Could not find member with username " + _httpContext.User.Identity.Name); + if (membershipUser == null) throw new InvalidOperationException("Could not find member with username " + HttpContext.User.Identity.Name); try { @@ -210,7 +187,7 @@ namespace Umbraco.Web.Security } } - MemberService.Save(member); + _memberService.Save(member); //reset the FormsAuth cookie since the username might have changed FormsAuthentication.SetAuthCookie(member.Username, true); @@ -245,7 +222,7 @@ namespace Umbraco.Web.Security if (status != MembershipCreateStatus.Success) return null; - var member = MemberService.GetByUsername(membershipUser.UserName); + var member = _memberService.GetByUsername(membershipUser.UserName); member.Name = model.Name; if (model.MemberProperties != null) @@ -257,7 +234,7 @@ namespace Umbraco.Web.Security } } - MemberService.Save(member); + _memberService.Save(member); } else { @@ -460,7 +437,7 @@ namespace Umbraco.Web.Security if (provider.IsUmbracoMembershipProvider()) { memberTypeAlias = memberTypeAlias ?? Constants.Conventions.MemberTypes.DefaultAlias; - var memberType = MemberTypeService.Get(memberTypeAlias); + var memberType = _memberTypeService.Get(memberTypeAlias); if (memberType == null) throw new InvalidOperationException("Could not find a member type with alias " + memberTypeAlias); @@ -596,13 +573,13 @@ namespace Umbraco.Web.Security /// public bool IsLoggedIn() { - return _httpContext.User != null && _httpContext.User.Identity.IsAuthenticated; + return HttpContext.User != null && HttpContext.User.Identity.IsAuthenticated; } /// /// Returns the currently logged in username /// - public string CurrentUserName => _httpContext.User.Identity.Name; + public string CurrentUserName => HttpContext.User.Identity.Name; /// /// Returns true or false if the currently logged in member is authorized based on the parameters provided @@ -706,7 +683,7 @@ namespace Umbraco.Web.Security /// public virtual Attempt ChangePassword(string username, ChangingPasswordModel passwordModel, MembershipProvider membershipProvider) { - var passwordChanger = new PasswordChanger(Logger, UserService, Web.Composing.Current.UmbracoContext.HttpContext); + var passwordChanger = new PasswordChanger(_logger, _userService, Web.Composing.Current.UmbracoContext.HttpContext); return passwordChanger.ChangePasswordWithMembershipProvider(username, passwordModel, membershipProvider); } @@ -771,7 +748,7 @@ namespace Umbraco.Web.Security /// private IMember GetCurrentPersistedMember() { - return ApplicationCache.RequestCache.GetCacheItem( + return _appCaches.RequestCache.GetCacheItem( GetCacheKey("GetCurrentPersistedMember"), () => { var provider = _membershipProvider; @@ -781,7 +758,7 @@ namespace Umbraco.Web.Security throw new NotSupportedException("An IMember model can only be retreived when using the built-in Umbraco membership providers"); } var username = provider.GetCurrentUserName(); - var member = MemberService.GetByUsername(username); + var member = _memberService.GetByUsername(username); return member; }); } diff --git a/src/Umbraco.Web/Security/WebSecurity.cs b/src/Umbraco.Web/Security/WebSecurity.cs index cee2c56d5f..4b2baf127d 100644 --- a/src/Umbraco.Web/Security/WebSecurity.cs +++ b/src/Umbraco.Web/Security/WebSecurity.cs @@ -1,25 +1,20 @@ using System; using System.Collections.Generic; -using System.ComponentModel; using System.Linq; using System.Security; using System.Web; -using System.Web.Security; -using AutoMapper; using Umbraco.Core; using Umbraco.Core.Services; -using Umbraco.Core.Logging; using Umbraco.Core.Models.Membership; using Umbraco.Core.Security; using Microsoft.AspNet.Identity.Owin; using Microsoft.Owin; using Umbraco.Core.Configuration; +using Umbraco.Core.Composing; using Umbraco.Core.IO; using Umbraco.Core.Models; using Umbraco.Core.Models.Identity; -using Umbraco.Web.Composing; -using ContainerExtensions = Umbraco.Core.Composing.ContainerExtensions; -using GlobalSettings = Umbraco.Core.Configuration.GlobalSettings; +using Current = Umbraco.Web.Composing.Current; namespace Umbraco.Web.Security { @@ -58,7 +53,7 @@ namespace Umbraco.Web.Security { return false; } - var helper = ContainerExtensions.GetInstance(Current.Container); + var helper = Current.Container.GetInstance(); return helper.IsMemberAuthorized(allowAll, allowTypes, allowGroups, allowMembers); } From f0241a91b2bdb57cd2bb84400e4c34687f8a651e Mon Sep 17 00:00:00 2001 From: Stephan Date: Tue, 31 Jul 2018 14:51:56 +0200 Subject: [PATCH 036/469] Post-merge --- src/Umbraco.Web/UmbracoInjectedModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web/UmbracoInjectedModule.cs b/src/Umbraco.Web/UmbracoInjectedModule.cs index 2a85851e99..84a5e98102 100644 --- a/src/Umbraco.Web/UmbracoInjectedModule.cs +++ b/src/Umbraco.Web/UmbracoInjectedModule.cs @@ -489,7 +489,7 @@ namespace Umbraco.Web //disable asp.net headers (security) // This is the correct place to modify headers according to MS: - // https://our.umbraco.org/forum/umbraco-7/using-umbraco-7/65241-Heap-error-from-header-manipulation?p=0#comment220889 + // https://our.umbraco.com/forum/umbraco-7/using-umbraco-7/65241-Heap-error-from-header-manipulation?p=0#comment220889 app.PostReleaseRequestState += (sender, args) => { var httpContext = ((HttpApplication) sender).Context; From 00b1dda2fe86b6902fa54a0fbda5fb8622691435 Mon Sep 17 00:00:00 2001 From: Stephan Date: Mon, 27 Aug 2018 18:08:59 +0200 Subject: [PATCH 037/469] Get rid of container TryGetInstance --- src/Umbraco.Core/Components/BootLoader.cs | 13 ++++--------- src/Umbraco.Core/Composing/ContainerExtensions.cs | 11 ----------- src/Umbraco.Core/Composing/Current.cs | 15 +++++++++++---- src/Umbraco.Core/Composing/IContainer.cs | 10 ---------- .../Composing/LightInject/LightInjectContainer.cs | 4 ---- 5 files changed, 15 insertions(+), 38 deletions(-) diff --git a/src/Umbraco.Core/Components/BootLoader.cs b/src/Umbraco.Core/Components/BootLoader.cs index 70e62c799f..fd09ce839d 100644 --- a/src/Umbraco.Core/Components/BootLoader.cs +++ b/src/Umbraco.Core/Components/BootLoader.cs @@ -319,7 +319,7 @@ namespace Umbraco.Core.Components foreach (var initializer in initializers) { var parameters = initializer.GetParameters() - .Select(x => GetParameter(componentType, x.ParameterType)) + .Select(x => GetParameter(componentType, x.ParameterType, x.Name)) .ToArray(); initializer.Invoke(component, parameters); } @@ -328,21 +328,16 @@ namespace Umbraco.Core.Components } } - private object GetParameter(Type componentType, Type parameterType) + private object GetParameter(Type componentType, Type parameterType, string parameterName) { - object param; - try { - param = _container.TryGetInstance(parameterType); + return _container.GetInstance(parameterType); } catch (Exception e) { - throw new BootFailedException($"Could not get parameter of type {parameterType.FullName} for component {componentType.FullName}.", e); + throw new BootFailedException($"Could not get parameter '{parameterName}' of type {parameterType.FullName} for component {componentType.FullName}.", e); } - - if (param == null) throw new BootFailedException($"Could not get parameter of type {parameterType.FullName} for component {componentType.FullName}."); - return param; } public void Terminate() diff --git a/src/Umbraco.Core/Composing/ContainerExtensions.cs b/src/Umbraco.Core/Composing/ContainerExtensions.cs index 423af98691..c01dbe911e 100644 --- a/src/Umbraco.Core/Composing/ContainerExtensions.cs +++ b/src/Umbraco.Core/Composing/ContainerExtensions.cs @@ -19,17 +19,6 @@ namespace Umbraco.Core.Composing public static T GetInstance(this IContainer container) => (T) container.GetInstance(typeof(T)); - /// - /// Tries to get an instance. - /// - /// The type of the instance. - /// An instance of the specified type, or null. - /// Returns null if the container does not know how to get an instance - /// of the specified type. Throws an exception if the container does know how - /// to get an instance of the specified type, but failed to do so. - public static T TryGetInstance(this IContainer container) - => (T) container.TryGetInstance(typeof(T)); - /// /// Gets registration for a service. /// diff --git a/src/Umbraco.Core/Composing/Current.cs b/src/Umbraco.Core/Composing/Current.cs index d0025c0c8b..f2c694658f 100644 --- a/src/Umbraco.Core/Composing/Current.cs +++ b/src/Umbraco.Core/Composing/Current.cs @@ -78,20 +78,27 @@ namespace Umbraco.Core.Composing // registered we setup a default one. We should really refactor our tests so that it does // not happen. Will do when we get rid of IShortStringHelper. + private static T TryGetInstance(IContainer container) + where T : class + { + var registration = container?.GetRegistered(); + return registration == null ? null : container.GetInstance(); + } + public static IShortStringHelper ShortStringHelper - => _shortStringHelper ?? (_shortStringHelper = _container?.TryGetInstance() + => _shortStringHelper ?? (_shortStringHelper = TryGetInstance(_container) ?? new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(UmbracoConfig.For.UmbracoSettings()))); public static ILogger Logger - => _logger ?? (_logger = _container?.TryGetInstance() + => _logger ?? (_logger = TryGetInstance(_container) ?? new DebugDiagnosticsLogger()); public static IProfiler Profiler - => _profiler ?? (_profiler = _container?.TryGetInstance() + => _profiler ?? (_profiler = TryGetInstance(_container) ?? new LogProfiler(Logger)); public static ProfilingLogger ProfilingLogger - => _profilingLogger ?? (_profilingLogger = _container?.TryGetInstance()) + => _profilingLogger ?? (_profilingLogger = TryGetInstance(_container)) ?? new ProfilingLogger(Logger, Profiler); public static IRuntimeState RuntimeState diff --git a/src/Umbraco.Core/Composing/IContainer.cs b/src/Umbraco.Core/Composing/IContainer.cs index dab5dd159c..1ec1dbe44f 100644 --- a/src/Umbraco.Core/Composing/IContainer.cs +++ b/src/Umbraco.Core/Composing/IContainer.cs @@ -37,16 +37,6 @@ namespace Umbraco.Core.Composing /// Throws an exception if the container failed to get an instance of the specified type. object GetInstance(Type type, string name); - /// - /// Tries to get an instance. - /// - /// The type of the instance. - /// An instance of the specified type, or null. - /// Returns null if the container does not know how to get an instance - /// of the specified type. Throws an exception if the container does know how - /// to get an instance of the specified type, but failed to do so. - object TryGetInstance(Type type); - /// /// Gets all instances of a service. /// diff --git a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs index 0a81f0e9eb..502dc91ff8 100644 --- a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs +++ b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs @@ -107,10 +107,6 @@ namespace Umbraco.Core.Composing.LightInject public object GetInstance(Type type, string name) => Container.GetInstance(type, name); - /// - public object TryGetInstance(Type type) - => Container.TryGetInstance(type); - /// public IEnumerable GetAllInstances() => Container.GetAllInstances(); From 2319617fed4c066c142b505249a7da491f608ae3 Mon Sep 17 00:00:00 2001 From: Stephan Date: Mon, 27 Aug 2018 18:09:10 +0200 Subject: [PATCH 038/469] Cleanup LightInjectContainer --- .../Composing/LightInject/LightInjectContainer.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs index 502dc91ff8..b8ba597578 100644 --- a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs +++ b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs @@ -35,9 +35,11 @@ namespace Umbraco.Core.Composing.LightInject { var container = new ServiceContainer(new ContainerOptions { EnablePropertyInjection = false }); - // supports annotated constructor injections + // note: the block below is disabled, as it is too LightInject-specific + // + // supports annotated constructor injections // eg to specify the service name on some services - container.EnableAnnotatedConstructorInjection(); + //container.EnableAnnotatedConstructorInjection(); // note: the block below is disabled, we do not allow property injection at all anymore // (see options in CreateServiceContainer) @@ -56,7 +58,7 @@ namespace Umbraco.Core.Composing.LightInject //Container.EnableAnnotatedPropertyInjection(); // ensure that we do *not* scan assemblies - // we explicitely RegisterFrom our own composition roots and don't want them scanned + // we explicitly RegisterFrom our own composition roots and don't want them scanned container.AssemblyScanner = new AssemblyScanner(/*container.AssemblyScanner*/); // see notes in MixedLightInjectScopeManagerProvider From fed9e2733211af37baff1572e52f3a3d30fd71d9 Mon Sep 17 00:00:00 2001 From: Stephan Date: Wed, 29 Aug 2018 18:50:08 +0200 Subject: [PATCH 039/469] Revert "Get rid of container TryGetInstance" This reverts commit 00b1dda2fe86b6902fa54a0fbda5fb8622691435. --- src/Umbraco.Core/Components/BootLoader.cs | 13 +++++++++---- src/Umbraco.Core/Composing/ContainerExtensions.cs | 11 +++++++++++ src/Umbraco.Core/Composing/Current.cs | 15 ++++----------- src/Umbraco.Core/Composing/IContainer.cs | 10 ++++++++++ .../Composing/LightInject/LightInjectContainer.cs | 4 ++++ 5 files changed, 38 insertions(+), 15 deletions(-) diff --git a/src/Umbraco.Core/Components/BootLoader.cs b/src/Umbraco.Core/Components/BootLoader.cs index 87d4cdac75..e28b6a38b8 100644 --- a/src/Umbraco.Core/Components/BootLoader.cs +++ b/src/Umbraco.Core/Components/BootLoader.cs @@ -319,7 +319,7 @@ namespace Umbraco.Core.Components foreach (var initializer in initializers) { var parameters = initializer.GetParameters() - .Select(x => GetParameter(componentType, x.ParameterType, x.Name)) + .Select(x => GetParameter(componentType, x.ParameterType)) .ToArray(); initializer.Invoke(component, parameters); } @@ -328,16 +328,21 @@ namespace Umbraco.Core.Components } } - private object GetParameter(Type componentType, Type parameterType, string parameterName) + private object GetParameter(Type componentType, Type parameterType) { + object param; + try { - return _container.GetInstance(parameterType); + param = _container.TryGetInstance(parameterType); } catch (Exception e) { - throw new BootFailedException($"Could not get parameter '{parameterName}' of type {parameterType.FullName} for component {componentType.FullName}.", e); + throw new BootFailedException($"Could not get parameter of type {parameterType.FullName} for component {componentType.FullName}.", e); } + + if (param == null) throw new BootFailedException($"Could not get parameter of type {parameterType.FullName} for component {componentType.FullName}."); + return param; } public void Terminate() diff --git a/src/Umbraco.Core/Composing/ContainerExtensions.cs b/src/Umbraco.Core/Composing/ContainerExtensions.cs index c01dbe911e..423af98691 100644 --- a/src/Umbraco.Core/Composing/ContainerExtensions.cs +++ b/src/Umbraco.Core/Composing/ContainerExtensions.cs @@ -19,6 +19,17 @@ namespace Umbraco.Core.Composing public static T GetInstance(this IContainer container) => (T) container.GetInstance(typeof(T)); + /// + /// Tries to get an instance. + /// + /// The type of the instance. + /// An instance of the specified type, or null. + /// Returns null if the container does not know how to get an instance + /// of the specified type. Throws an exception if the container does know how + /// to get an instance of the specified type, but failed to do so. + public static T TryGetInstance(this IContainer container) + => (T) container.TryGetInstance(typeof(T)); + /// /// Gets registration for a service. /// diff --git a/src/Umbraco.Core/Composing/Current.cs b/src/Umbraco.Core/Composing/Current.cs index f2c694658f..d0025c0c8b 100644 --- a/src/Umbraco.Core/Composing/Current.cs +++ b/src/Umbraco.Core/Composing/Current.cs @@ -78,27 +78,20 @@ namespace Umbraco.Core.Composing // registered we setup a default one. We should really refactor our tests so that it does // not happen. Will do when we get rid of IShortStringHelper. - private static T TryGetInstance(IContainer container) - where T : class - { - var registration = container?.GetRegistered(); - return registration == null ? null : container.GetInstance(); - } - public static IShortStringHelper ShortStringHelper - => _shortStringHelper ?? (_shortStringHelper = TryGetInstance(_container) + => _shortStringHelper ?? (_shortStringHelper = _container?.TryGetInstance() ?? new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(UmbracoConfig.For.UmbracoSettings()))); public static ILogger Logger - => _logger ?? (_logger = TryGetInstance(_container) + => _logger ?? (_logger = _container?.TryGetInstance() ?? new DebugDiagnosticsLogger()); public static IProfiler Profiler - => _profiler ?? (_profiler = TryGetInstance(_container) + => _profiler ?? (_profiler = _container?.TryGetInstance() ?? new LogProfiler(Logger)); public static ProfilingLogger ProfilingLogger - => _profilingLogger ?? (_profilingLogger = TryGetInstance(_container)) + => _profilingLogger ?? (_profilingLogger = _container?.TryGetInstance()) ?? new ProfilingLogger(Logger, Profiler); public static IRuntimeState RuntimeState diff --git a/src/Umbraco.Core/Composing/IContainer.cs b/src/Umbraco.Core/Composing/IContainer.cs index 1ec1dbe44f..dab5dd159c 100644 --- a/src/Umbraco.Core/Composing/IContainer.cs +++ b/src/Umbraco.Core/Composing/IContainer.cs @@ -37,6 +37,16 @@ namespace Umbraco.Core.Composing /// Throws an exception if the container failed to get an instance of the specified type. object GetInstance(Type type, string name); + /// + /// Tries to get an instance. + /// + /// The type of the instance. + /// An instance of the specified type, or null. + /// Returns null if the container does not know how to get an instance + /// of the specified type. Throws an exception if the container does know how + /// to get an instance of the specified type, but failed to do so. + object TryGetInstance(Type type); + /// /// Gets all instances of a service. /// diff --git a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs index b8ba597578..ecb8f0a460 100644 --- a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs +++ b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs @@ -109,6 +109,10 @@ namespace Umbraco.Core.Composing.LightInject public object GetInstance(Type type, string name) => Container.GetInstance(type, name); + /// + public object TryGetInstance(Type type) + => Container.TryGetInstance(type); + /// public IEnumerable GetAllInstances() => Container.GetAllInstances(); From 6692f3e7b72b879393ef424d3a237351e689b7d1 Mon Sep 17 00:00:00 2001 From: Stephan Date: Wed, 29 Aug 2018 19:02:35 +0200 Subject: [PATCH 040/469] Post-merge fixes --- src/Umbraco.Tests/Manifest/ManifestParserTests.cs | 4 +--- src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs | 3 --- src/Umbraco.Web/UmbracoInjectedModule.cs | 4 ++-- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Tests/Manifest/ManifestParserTests.cs b/src/Umbraco.Tests/Manifest/ManifestParserTests.cs index 2bbd70e367..a399e75cff 100644 --- a/src/Umbraco.Tests/Manifest/ManifestParserTests.cs +++ b/src/Umbraco.Tests/Manifest/ManifestParserTests.cs @@ -2,7 +2,6 @@ using System.Linq; using Moq; using System.Text; -using LightInject; using NUnit.Framework; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -19,14 +18,13 @@ namespace Umbraco.Tests.Manifest [TestFixture] public class ManifestParserTests { - private ManifestParser _parser; [SetUp] public void Setup() { Current.Reset(); - var container = Mock.Of(); + var container = Mock.Of(); Current.Container = container; var serviceContext = new ServiceContext( diff --git a/src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs b/src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs index 881fe79053..a74b8e3869 100644 --- a/src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs +++ b/src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs @@ -152,7 +152,6 @@ namespace Umbraco.Tests.Web.Controllers var publishedSnapshot = Mock.Of(); var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty())); var usersController = new ContentController(publishedSnapshot, propertyEditorCollection); - Container.InjectProperties(usersController); return usersController; } @@ -180,7 +179,6 @@ namespace Umbraco.Tests.Web.Controllers var publishedSnapshot = Mock.Of(); var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty())); var usersController = new ContentController(publishedSnapshot, propertyEditorCollection); - Container.InjectProperties(usersController); return usersController; } @@ -220,7 +218,6 @@ namespace Umbraco.Tests.Web.Controllers var publishedSnapshot = Mock.Of(); var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty())); var usersController = new ContentController(publishedSnapshot, propertyEditorCollection); - Container.InjectProperties(usersController); return usersController; } diff --git a/src/Umbraco.Web/UmbracoInjectedModule.cs b/src/Umbraco.Web/UmbracoInjectedModule.cs index 84a5e98102..39f1ff3599 100644 --- a/src/Umbraco.Web/UmbracoInjectedModule.cs +++ b/src/Umbraco.Web/UmbracoInjectedModule.cs @@ -483,7 +483,7 @@ namespace Umbraco.Web app.BeginRequest += (sender, e) => { var httpContext = ((HttpApplication) sender).Context; - _logger.Debug(() => $"Begin request: {httpContext.Request.Url}."); + _logger.Verbose("Begin request {RequestUrl}", httpContext.Request.Url); BeginRequest(new HttpContextWrapper(httpContext)); }; @@ -526,7 +526,7 @@ namespace Umbraco.Web if (UmbracoContext.Current != null && UmbracoContext.Current.IsFrontEndUmbracoRequest) { - _logger.Debug(() => $"End Request. ({DateTime.Now.Subtract(UmbracoContext.Current.ObjectCreated).TotalMilliseconds}ms)"); + _logger.Verbose("End Request {RequestUrl} ({RequestDuration}ms)", httpContext.Request.Url, DateTime.Now.Subtract(UmbracoContext.Current.ObjectCreated).TotalMilliseconds); } UmbracoModule.OnEndRequest(this, new UmbracoRequestEventArgs(UmbracoContext.Current, new HttpContextWrapper(httpContext))); From 557bea5f95ad06e3072364976299f37a945aad87 Mon Sep 17 00:00:00 2001 From: Stephan Date: Thu, 30 Aug 2018 09:30:49 +0200 Subject: [PATCH 041/469] Move LightInjectExtensions to proper space --- .../Composing/{ => LightInject}/LightInjectExtensions.cs | 8 ++++---- src/Umbraco.Core/Umbraco.Core.csproj | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) rename src/Umbraco.Core/Composing/{ => LightInject}/LightInjectExtensions.cs (97%) diff --git a/src/Umbraco.Core/Composing/LightInjectExtensions.cs b/src/Umbraco.Core/Composing/LightInject/LightInjectExtensions.cs similarity index 97% rename from src/Umbraco.Core/Composing/LightInjectExtensions.cs rename to src/Umbraco.Core/Composing/LightInject/LightInjectExtensions.cs index d552cf756e..d9651ef1a1 100644 --- a/src/Umbraco.Core/Composing/LightInjectExtensions.cs +++ b/src/Umbraco.Core/Composing/LightInject/LightInjectExtensions.cs @@ -2,7 +2,7 @@ using System.Linq; using LightInject; -namespace Umbraco.Core.Composing +namespace Umbraco.Core.Composing.LightInject { /// /// Provides extensions to LightInject. @@ -28,7 +28,7 @@ namespace Umbraco.Core.Composing } /// - /// Registers a servuice with an implementation as a singleton. + /// Registers a service with an implementation as a singleton. /// public static void RegisterSingleton(this IServiceRegistry container) where TImplementation : TService @@ -37,7 +37,7 @@ namespace Umbraco.Core.Composing } /// - /// Registers a servuice with an implementation as a singleton. + /// Registers a service with an implementation as a singleton. /// public static void RegisterSingleton(this IServiceRegistry container, Type serviceType, Type implementingType) { @@ -56,7 +56,7 @@ namespace Umbraco.Core.Composing } /// - /// Registers a servuice with a named implementation as a singleton. + /// Registers a service with a named implementation as a singleton. /// public static void RegisterSingleton(this IServiceRegistry container, Type serviceType, Type implementingType, string name) { diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 01432b7e31..099664ecde 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -188,7 +188,7 @@ - + From 7e68f4724f15cf7c1f5143e5edf2d9ac19c1cf46 Mon Sep 17 00:00:00 2001 From: Stephan Date: Fri, 7 Sep 2018 09:32:42 +0200 Subject: [PATCH 042/469] Fix merge --- src/Umbraco.Tests/Models/MediaXmlTest.cs | 2 +- src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs | 3 --- src/Umbraco.Web/Umbraco.Web.csproj | 1 - 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Umbraco.Tests/Models/MediaXmlTest.cs b/src/Umbraco.Tests/Models/MediaXmlTest.cs index b56a2257f1..bcf649dcac 100644 --- a/src/Umbraco.Tests/Models/MediaXmlTest.cs +++ b/src/Umbraco.Tests/Models/MediaXmlTest.cs @@ -29,7 +29,7 @@ namespace Umbraco.Tests.Models // reference, so static ctor runs, so event handlers register // and then, this will reset the width, height... because the file does not exist, of course ;-( - var ignored = new FileUploadPropertyEditor(Mock.Of(), new MediaFileSystem(Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of())); + var ignored = new FileUploadPropertyEditor(Mock.Of(), new MediaFileSystem(Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of()), Mock.Of()); var media = MockedMedia.CreateMediaImage(mediaType, -1); media.WriterId = -1; // else it's zero and that's not a user and it breaks the tests diff --git a/src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs b/src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs index eba501c329..4089f9a426 100644 --- a/src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs +++ b/src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs @@ -272,7 +272,6 @@ namespace Umbraco.Tests.Web.Controllers var publishedSnapshot = Mock.Of(); var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty())); var usersController = new ContentController(publishedSnapshot, propertyEditorCollection); - Container.InjectProperties(usersController); return usersController; } @@ -343,7 +342,6 @@ namespace Umbraco.Tests.Web.Controllers var publishedSnapshot = Mock.Of(); var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty())); var usersController = new ContentController(publishedSnapshot, propertyEditorCollection); - Container.InjectProperties(usersController); return usersController; } @@ -380,7 +378,6 @@ namespace Umbraco.Tests.Web.Controllers var publishedSnapshot = Mock.Of(); var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty())); var usersController = new ContentController(publishedSnapshot, propertyEditorCollection); - Container.InjectProperties(usersController); return usersController; } diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 1b7dee2586..f27cce9dda 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -152,7 +152,6 @@ - From bc80affcf1e11894660d0614eee1c709e809fe18 Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Sun, 2 Sep 2018 22:09:37 +0200 Subject: [PATCH 043/469] Dictionary params & error handling --- .../Composing/ContainerExtensions.cs | 23 ++++++++++++++++--- src/Umbraco.Core/Composing/IContainer.cs | 9 ++++++-- .../LightInject/LightInjectContainer.cs | 22 ++++++++++++++++-- src/Umbraco.Core/IO/FileSystems.cs | 2 +- .../Migrations/MigrationBuilder.cs | 3 ++- .../Composing/ContainerImplementationTests.cs | 5 ++-- src/Umbraco.Web/Composing/ModuleInjector.cs | 20 ++++++++++++---- 7 files changed, 69 insertions(+), 15 deletions(-) diff --git a/src/Umbraco.Core/Composing/ContainerExtensions.cs b/src/Umbraco.Core/Composing/ContainerExtensions.cs index 423af98691..5d839c9c8e 100644 --- a/src/Umbraco.Core/Composing/ContainerExtensions.cs +++ b/src/Umbraco.Core/Composing/ContainerExtensions.cs @@ -19,6 +19,17 @@ namespace Umbraco.Core.Composing public static T GetInstance(this IContainer container) => (T) container.GetInstance(typeof(T)); + /// + /// Gets a named instance. + /// + /// The type of the instance. + /// The container. + /// The name of the instance. + /// An instance of the specified type and name. + /// Throws an exception if the container failed to get an instance of the specified type. + public static T GetInstance(this IContainer container, string name) + => (T) container.GetInstance(typeof(T), name); + /// /// Tries to get an instance. /// @@ -49,7 +60,7 @@ namespace Umbraco.Core.Composing /// Throws an exception if the container failed to get an instance of the specified type. /// The arguments are used as dependencies by the container. /// - public static T CreateInstance(this IContainer container, params object[] args) + public static T CreateInstance(this IContainer container, IDictionary args) => (T) container.CreateInstance(typeof(T), args); /// @@ -64,6 +75,12 @@ namespace Umbraco.Core.Composing public static void Register(this IContainer container, string name, Lifetime lifetime = Lifetime.Transient) => container.Register(typeof(TService), typeof(TImplementing), name, lifetime); + /// + /// Registers a service with a named implementation type and factory. + /// + public static void Register(this IContainer container, string name, Func factory, Lifetime lifetime = Lifetime.Transient) + => container.Register(factory, name, lifetime); + /// /// Registers a service as its own implementation. /// @@ -112,8 +129,8 @@ namespace Umbraco.Core.Composing if (container.GetRegistered().Any()) throw new InvalidOperationException("Collection builders should be registered only once."); - // register the builder - passing the container as an arg to the factory - container.RegisterSingleton(c => c.CreateInstance(container)); + // register the builder + container.RegisterSingleton(); // initialize and return the builder return container.GetInstance(); diff --git a/src/Umbraco.Core/Composing/IContainer.cs b/src/Umbraco.Core/Composing/IContainer.cs index dab5dd159c..9a5452bf65 100644 --- a/src/Umbraco.Core/Composing/IContainer.cs +++ b/src/Umbraco.Core/Composing/IContainer.cs @@ -70,14 +70,14 @@ namespace Umbraco.Core.Composing /// Creates an instance with arguments. /// /// The type of the instance. - /// Arguments. + /// Named arguments. /// An instance of the specified type. /// /// The instance type does not need to be registered into the container. /// The arguments are used as dependencies by the container. Other dependencies /// are retrieved from the container. /// - object CreateInstance(Type type, params object[] args); + object CreateInstance(Type type, IDictionary args); #endregion @@ -104,6 +104,11 @@ namespace Umbraco.Core.Composing /// void Register(Type serviceType, Type implementingType, string name, Lifetime lifetime = Lifetime.Transient); + /// + /// Registers a named service with an implementation factory. + /// + void Register(Func factory, string name, Lifetime lifetime = Lifetime.Transient); + /// /// Registers a service with an implementation factory. /// diff --git a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs index ecb8f0a460..f9dd0028b2 100644 --- a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs +++ b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs @@ -126,7 +126,7 @@ namespace Umbraco.Core.Composing.LightInject => Container.AvailableServices.Where(x => x.ServiceType == type).Select(x => new Registration(x.ServiceType, x.ServiceName)); /// - public object CreateInstance(Type type, params object[] args) + public object CreateInstance(Type type, IDictionary args) { // LightInject has this, but then it requires RegisterConstructorDependency etc and has various oddities // including the most annoying one, which is that it does not work on singletons (hard to fix) @@ -146,7 +146,7 @@ namespace Umbraco.Core.Composing.LightInject { // no! IsInstanceOfType is not ok here // ReSharper disable once UseMethodIsInstanceOfType - var arg = args?.FirstOrDefault(a => parameter.ParameterType.IsAssignableFrom(a.GetType())); + var arg = args?.Values.FirstOrDefault(a => parameter.ParameterType.IsAssignableFrom(a.GetType())); ctorArgs[i++] = arg ?? GetInstance(parameter.ParameterType); } return ctor.Invoke(ctorArgs); @@ -234,6 +234,24 @@ namespace Umbraco.Core.Composing.LightInject } } + /// + public void Register(Func factory, string name, Lifetime lifetime = Lifetime.Transient) + { + switch (lifetime) + { + case Lifetime.Transient: + case Lifetime.Request: + case Lifetime.Scope: + Container.Register(f => factory(this), name, GetLifetime(lifetime)); + break; + case Lifetime.Singleton: + Container.RegisterSingleton(f => factory(this), name); + break; + default: + throw new NotSupportedException($"Lifetime {lifetime} is not supported."); + } + } + private ILifetime GetLifetime(Lifetime lifetime) { switch (lifetime) diff --git a/src/Umbraco.Core/IO/FileSystems.cs b/src/Umbraco.Core/IO/FileSystems.cs index 5a4ee92e15..43ac94624e 100644 --- a/src/Umbraco.Core/IO/FileSystems.cs +++ b/src/Umbraco.Core/IO/FileSystems.cs @@ -299,7 +299,7 @@ namespace Umbraco.Core.IO var shadowWrapper = new ShadowWrapper(innerFs, "typed/" + alias, () => IsScoped()); // getting the fs from the container - see FileSystemsComposer - var fs = Current.Container.CreateInstance((IFileSystem) shadowWrapper); + var fs = Current.Container.CreateInstance(new Dictionary{{ "wrapped", (IFileSystem) shadowWrapper }}); _wrappers.Add(shadowWrapper); // keeping a reference to the wrapper return fs; }); diff --git a/src/Umbraco.Core/Migrations/MigrationBuilder.cs b/src/Umbraco.Core/Migrations/MigrationBuilder.cs index aebd8bd1ee..65e40f6e75 100644 --- a/src/Umbraco.Core/Migrations/MigrationBuilder.cs +++ b/src/Umbraco.Core/Migrations/MigrationBuilder.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using Umbraco.Core.Composing; namespace Umbraco.Core.Migrations @@ -14,7 +15,7 @@ namespace Umbraco.Core.Migrations public IMigration Build(Type migrationType, IMigrationContext context) { - return (IMigration) _container.CreateInstance(migrationType, context); + return (IMigration) _container.CreateInstance(migrationType, new Dictionary{{"context", context}}); } } } diff --git a/src/Umbraco.Tests/Composing/ContainerImplementationTests.cs b/src/Umbraco.Tests/Composing/ContainerImplementationTests.cs index 818bf47cd0..f16c6534fc 100644 --- a/src/Umbraco.Tests/Composing/ContainerImplementationTests.cs +++ b/src/Umbraco.Tests/Composing/ContainerImplementationTests.cs @@ -1,4 +1,5 @@ -using NUnit.Framework; +using System.Collections.Generic; +using NUnit.Framework; using Umbraco.Core.Composing; namespace Umbraco.Tests.Composing @@ -46,7 +47,7 @@ namespace Umbraco.Tests.Composing public void CanRegisterSingletonWithCreate() { var container = CreateContainer(); - container.RegisterSingleton(c => c.CreateInstance(new TestClass1())); + container.RegisterSingleton(c => c.CreateInstance(new Dictionary{{"c", new TestClass1()}})); var s1 = container.GetInstance(); var s2 = container.GetInstance(); Assert.AreSame(s1, s2); diff --git a/src/Umbraco.Web/Composing/ModuleInjector.cs b/src/Umbraco.Web/Composing/ModuleInjector.cs index 5938a8060a..8ff8f407e1 100644 --- a/src/Umbraco.Web/Composing/ModuleInjector.cs +++ b/src/Umbraco.Web/Composing/ModuleInjector.cs @@ -1,4 +1,5 @@ -using System.Web; +using System; +using System.Web; using Umbraco.Core; using Umbraco.Core.Composing; @@ -16,9 +17,20 @@ namespace Umbraco.Web.Composing /// public void Init(HttpApplication context) { - // using the service locator here - no other way, really - Module = Current.Container.GetInstance(); - Module.Init(context); + try + { + // using the service locator here - no other way, really + Module = Current.Container.GetInstance(); + Module.Init(context); + } + catch + { + var runtimeState = Current.Container.GetInstance(); + if (runtimeState.BootFailedException != null) + { + throw new Exception("Failed to boot", runtimeState.BootFailedException); + } + } } /// From 9da750c5c90b84a8522a23e00a1dbc6ae1047351 Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Sun, 9 Sep 2018 22:46:14 +0200 Subject: [PATCH 044/469] Support registering named singleton --- src/Umbraco.Core/Composing/ContainerExtensions.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Umbraco.Core/Composing/ContainerExtensions.cs b/src/Umbraco.Core/Composing/ContainerExtensions.cs index 5d839c9c8e..33925e010b 100644 --- a/src/Umbraco.Core/Composing/ContainerExtensions.cs +++ b/src/Umbraco.Core/Composing/ContainerExtensions.cs @@ -105,6 +105,13 @@ namespace Umbraco.Core.Composing public static void RegisterSingleton(this IContainer container, Func factory) => container.Register(factory, Lifetime.Singleton); + /// + /// Registers a named singleton service with an implementation factory. + /// Note to implementors: The last registered component must be the default. + /// + public static void RegisterSingleton(this IContainer container, string name, Func factory) + => container.Register(factory, name, Lifetime.Singleton); + /// /// Registers a service with an implementing instance. /// From ee654d089600952ae23167df2f02e6541a7eca7d Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Sun, 2 Sep 2018 22:38:32 +0200 Subject: [PATCH 045/469] Profiles should implement a base class. Castle hiccups. :) --- .../Composers/WebMappingProfilesComposer.cs | 39 ++++++++++--------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/src/Umbraco.Web/Composing/Composers/WebMappingProfilesComposer.cs b/src/Umbraco.Web/Composing/Composers/WebMappingProfilesComposer.cs index eb2ff04ac9..c5629b983e 100644 --- a/src/Umbraco.Web/Composing/Composers/WebMappingProfilesComposer.cs +++ b/src/Umbraco.Web/Composing/Composers/WebMappingProfilesComposer.cs @@ -1,4 +1,5 @@ -using Umbraco.Core; +using AutoMapper; +using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Core.Models; using Umbraco.Web.Models.ContentEditing; @@ -12,24 +13,24 @@ namespace Umbraco.Web.Composing.Composers public static IContainer ComposeWebMappingProfiles(this IContainer container) { //register the profiles - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); //register any resolvers, etc.. that the profiles use container.Register(); From 97318ace1d2d3a7d593c1e18e96464853be6376b Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Sun, 2 Sep 2018 22:56:55 +0200 Subject: [PATCH 046/469] MediaFileSystem created with reflection due to chicken and egg situation with registration --- .../Composing/Composers/FileSystemsComposer.cs | 7 ++++++- src/Umbraco.Core/IO/FileSystems.cs | 3 +-- src/Umbraco.Core/IO/MediaFileSystem.cs | 9 +++++---- src/Umbraco.Tests/Models/MediaXmlTest.cs | 2 +- src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs | 2 +- src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs | 2 +- src/Umbraco.Tests/TestHelpers/TestObjects.cs | 2 +- 7 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs b/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs index d72e9028b1..15c4bd0eea 100644 --- a/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs @@ -12,10 +12,15 @@ namespace Umbraco.Core.Composing.Composers // register IFileSystems, which gives access too all filesystems container.RegisterSingleton(factory => factory.GetInstance()); + + // fixme - review registering mediafilesystem. it seems to create cyclic dependencies for castle. + // let's try naming it so the default is overwritten... + // register MediaFileSystem, which can be injected directly // note: the actual MediaFileSystem implementation is created by FileSystems directly, // without being registered in the container - this just gives access to it - container.Register(factory => factory.GetInstance().MediaFileSystem); + container.Register(f => f.GetInstance().MediaFileSystem); + return container; } diff --git a/src/Umbraco.Core/IO/FileSystems.cs b/src/Umbraco.Core/IO/FileSystems.cs index 43ac94624e..cc52487018 100644 --- a/src/Umbraco.Core/IO/FileSystems.cs +++ b/src/Umbraco.Core/IO/FileSystems.cs @@ -298,8 +298,7 @@ namespace Umbraco.Core.IO var innerFs = GetUnderlyingFileSystemNoCache(alias, fallback); var shadowWrapper = new ShadowWrapper(innerFs, "typed/" + alias, () => IsScoped()); - // getting the fs from the container - see FileSystemsComposer - var fs = Current.Container.CreateInstance(new Dictionary{{ "wrapped", (IFileSystem) shadowWrapper }}); + var fs = (IFileSystem)Activator.CreateInstance(typeof(TFileSystem), shadowWrapper); _wrappers.Add(shadowWrapper); // keeping a reference to the wrapper return fs; }); diff --git a/src/Umbraco.Core/IO/MediaFileSystem.cs b/src/Umbraco.Core/IO/MediaFileSystem.cs index 4ecb44cfb9..794f7f5c20 100644 --- a/src/Umbraco.Core/IO/MediaFileSystem.cs +++ b/src/Umbraco.Core/IO/MediaFileSystem.cs @@ -4,6 +4,7 @@ using System.Drawing; using System.IO; using System.Linq; using System.Threading.Tasks; +using Umbraco.Core.Composing; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Exceptions; using Umbraco.Core.Logging; @@ -19,12 +20,12 @@ namespace Umbraco.Core.IO [FileSystemProvider("media")] public class MediaFileSystem : FileSystemWrapper { - public MediaFileSystem(IFileSystem wrapped, IContentSection contentConfig, IMediaPathScheme mediaPathScheme, ILogger logger) + public MediaFileSystem(IFileSystem wrapped) : base(wrapped) { - ContentConfig = contentConfig; - Logger = logger; - MediaPathScheme = mediaPathScheme; + ContentConfig = Current.Container.GetInstance(); + Logger = Current.Container.GetInstance(); + MediaPathScheme = Current.Container.GetInstance(); MediaPathScheme.Initialize(this); UploadAutoFillProperties = new UploadAutoFillProperties(this, Logger, ContentConfig); diff --git a/src/Umbraco.Tests/Models/MediaXmlTest.cs b/src/Umbraco.Tests/Models/MediaXmlTest.cs index b56a2257f1..29c936adb9 100644 --- a/src/Umbraco.Tests/Models/MediaXmlTest.cs +++ b/src/Umbraco.Tests/Models/MediaXmlTest.cs @@ -29,7 +29,7 @@ namespace Umbraco.Tests.Models // reference, so static ctor runs, so event handlers register // and then, this will reset the width, height... because the file does not exist, of course ;-( - var ignored = new FileUploadPropertyEditor(Mock.Of(), new MediaFileSystem(Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of())); + var ignored = new FileUploadPropertyEditor(Mock.Of(), new MediaFileSystem(Mock.Of())); var media = MockedMedia.CreateMediaImage(mediaType, -1); media.WriterId = -1; // else it's zero and that's not a user and it breaks the tests diff --git a/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs b/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs index 2c5bc621eb..f9093ad6fe 100644 --- a/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs +++ b/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs @@ -71,7 +71,7 @@ namespace Umbraco.Tests.PropertyEditors Current.Container.RegisterSingleton(f => Mock.Of()); Current.Container.RegisterSingleton(f => Mock.Of()); - var mediaFileSystem = new MediaFileSystem(Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of()); + var mediaFileSystem = new MediaFileSystem(Mock.Of()); var dataTypeService = new TestObjects.TestDataTypeService( new DataType(new ImageCropperPropertyEditor(Mock.Of(), mediaFileSystem, Mock.Of())) { Id = 1 }); diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs b/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs index 19e5d12650..cc9418cc50 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs @@ -151,7 +151,7 @@ namespace Umbraco.Tests.TestHelpers MockFs(fileSystems, x => x.ScriptsFileSystem); MockFs(fileSystems, x => x.StylesheetsFileSystem); - var mediaFs = new MediaFileSystem(Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of()); + var mediaFs = new MediaFileSystem(Mock.Of()); Mock.Get(fileSystems).Setup(x => x.MediaFileSystem).Returns(mediaFs); return fileSystems; diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects.cs b/src/Umbraco.Tests/TestHelpers/TestObjects.cs index 00a193b40a..61860e29aa 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects.cs @@ -115,7 +115,7 @@ namespace Umbraco.Tests.TestHelpers if (logger == null) throw new ArgumentNullException(nameof(logger)); if (eventMessagesFactory == null) throw new ArgumentNullException(nameof(eventMessagesFactory)); - var mediaFileSystem = new MediaFileSystem(Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of()); + var mediaFileSystem = new MediaFileSystem(Mock.Of()); var externalLoginService = GetLazyService(container, c => new ExternalLoginService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); var publicAccessService = GetLazyService(container, c => new PublicAccessService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); From 6bb507037b716ea5c3c89647e8c5dc9ff2e583e7 Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Mon, 3 Sep 2018 00:16:38 +0200 Subject: [PATCH 047/469] Initializer interface for components. Supports both reflected and injected versions for now. --- src/Umbraco.Core/Components/BootLoader.cs | 22 +++++++++- .../Components/IUmbracoComponent.cs | 14 ++++++- .../Components/UmbracoComponentBase.cs | 6 ++- .../Runtime/CoreRuntimeComponent.cs | 42 ++++++++++++------- .../Components/ComponentTests.cs | 34 +++++++++++++++ 5 files changed, 99 insertions(+), 19 deletions(-) diff --git a/src/Umbraco.Core/Components/BootLoader.cs b/src/Umbraco.Core/Components/BootLoader.cs index e28b6a38b8..c0b9915fbd 100644 --- a/src/Umbraco.Core/Components/BootLoader.cs +++ b/src/Umbraco.Core/Components/BootLoader.cs @@ -46,8 +46,9 @@ namespace Umbraco.Core.Components var orderedComponentTypes = PrepareComponentTypes(componentTypes, level); - InstanciateComponents(orderedComponentTypes); + InstantiateComponents(orderedComponentTypes); ComposeComponents(level); + RegisterInitializers(); using (var scope = _container.GetInstance().CreateScope()) { @@ -278,7 +279,7 @@ namespace Umbraco.Core.Components } } - private void InstanciateComponents(IEnumerable types) + private void InstantiateComponents(IEnumerable types) { using (_proflog.DebugDuration("Instanciating components.", "Instanciated components.")) { @@ -302,6 +303,17 @@ namespace Umbraco.Core.Components } } + private void RegisterInitializers() + { + foreach (var component in _components) + { + if (component.InitializerType != null) + { + _container.Register(component.InitializerType); + } + } + } + private void InitializeComponents() { // use a container scope to ensure that PerScope instances are disposed @@ -323,6 +335,12 @@ namespace Umbraco.Core.Components .ToArray(); initializer.Invoke(component, parameters); } + + if (component.InitializerType != null) + { + var initializer = (IComponentInitializer) _container.GetInstance(component.InitializerType); + initializer.Initialize(); + } } } } diff --git a/src/Umbraco.Core/Components/IUmbracoComponent.cs b/src/Umbraco.Core/Components/IUmbracoComponent.cs index d25b97c270..6d51ebe30d 100644 --- a/src/Umbraco.Core/Components/IUmbracoComponent.cs +++ b/src/Umbraco.Core/Components/IUmbracoComponent.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Composing; +using System; +using Umbraco.Core.Composing; namespace Umbraco.Core.Components { @@ -13,9 +14,20 @@ namespace Umbraco.Core.Components /// The composition. void Compose(Composition composition); + /// + /// An optional that will be executed after composition is done. + /// The initializer will be registered with the DI container and can have constructor dependencies. + /// + Type InitializerType { get; } + /// /// Terminates the component. /// void Terminate(); } + + public interface IComponentInitializer + { + void Initialize(); + } } diff --git a/src/Umbraco.Core/Components/UmbracoComponentBase.cs b/src/Umbraco.Core/Components/UmbracoComponentBase.cs index 476c4c6d59..f96e2aed12 100644 --- a/src/Umbraco.Core/Components/UmbracoComponentBase.cs +++ b/src/Umbraco.Core/Components/UmbracoComponentBase.cs @@ -1,4 +1,6 @@ -namespace Umbraco.Core.Components +using System; + +namespace Umbraco.Core.Components { /// /// Provides a base class for implementations. @@ -9,6 +11,8 @@ public virtual void Compose(Composition composition) { } + public virtual Type InitializerType => null; + /// public virtual void Terminate() { } diff --git a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs index efd9bde0b5..9d7c3e5a6a 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs @@ -111,22 +111,34 @@ namespace Umbraco.Core.Runtime composition.Container.RegisterSingleton(); } - internal void Initialize(IEnumerable mapperProfiles) - { - // mapper profiles have been registered & are created by the container - Mapper.Initialize(configuration => - { - foreach (var profile in mapperProfiles) - configuration.AddProfile(profile); - }); + public override Type InitializerType => typeof(Initializer); - // ensure we have some essential directories - // every other component can then initialize safely - IOHelper.EnsurePathExists("~/App_Data"); - IOHelper.EnsurePathExists(SystemDirectories.Media); - IOHelper.EnsurePathExists(SystemDirectories.MvcViews); - IOHelper.EnsurePathExists(SystemDirectories.MvcViews + "/Partials"); - IOHelper.EnsurePathExists(SystemDirectories.MvcViews + "/MacroPartials"); + internal class Initializer : IComponentInitializer + { + private readonly IEnumerable mapperProfiles; + + public Initializer(IEnumerable mapperProfiles) + { + this.mapperProfiles = mapperProfiles; + } + + public void Initialize() + { + // mapper profiles have been registered & are created by the container + Mapper.Initialize(configuration => + { + foreach (var profile in mapperProfiles) + configuration.AddProfile(profile); + }); + + // ensure we have some essential directories + // every other component can then initialize safely + IOHelper.EnsurePathExists("~/App_Data"); + IOHelper.EnsurePathExists(SystemDirectories.Media); + IOHelper.EnsurePathExists(SystemDirectories.MvcViews); + IOHelper.EnsurePathExists(SystemDirectories.MvcViews + "/Partials"); + IOHelper.EnsurePathExists(SystemDirectories.MvcViews + "/MacroPartials"); + } } } } diff --git a/src/Umbraco.Tests/Components/ComponentTests.cs b/src/Umbraco.Tests/Components/ComponentTests.cs index b0e0d308b8..9483b94c82 100644 --- a/src/Umbraco.Tests/Components/ComponentTests.cs +++ b/src/Umbraco.Tests/Components/ComponentTests.cs @@ -37,6 +37,9 @@ namespace Umbraco.Tests.Components mock.Setup(x => x.GetInstance(typeof (ProfilingLogger))).Returns(new ProfilingLogger(Mock.Of(), Mock.Of())); mock.Setup(x => x.GetInstance(typeof (IUmbracoDatabaseFactory))).Returns(f); mock.Setup(x => x.GetInstance(typeof (IScopeProvider))).Returns(p); + + + setup?.Invoke(mock); return mock.Object; } @@ -231,6 +234,24 @@ namespace Umbraco.Tests.Components Assert.AreEqual(typeof(Component8), Composed[1]); } + [Test] + public void Runs_Initializers_When_Defined() + { + var container = MockContainer(); + Mock.Get(container).Setup(x => x.GetInstance(typeof(TestComponentWithInitializer.Initializer))) + .Returns(new TestComponentWithInitializer.Initializer()); + + var thing = new BootLoader(container); + Composed.Clear(); + Initialized.Clear(); + thing.Boot(new[] { typeof(TestComponentWithInitializer) }, RuntimeLevel.Unknown); // 8 disables 7 which is not in the list + + Mock.Get(container).Verify(x => x.Register(typeof(TestComponentWithInitializer.Initializer), Lifetime.Transient)); + + Assert.AreEqual(1, Initialized.Count); + Assert.AreEqual("Initializer", Initialized[0]); + } + #region Components public class TestComponentBase : UmbracoComponentBase @@ -242,6 +263,19 @@ namespace Umbraco.Tests.Components } } + public class TestComponentWithInitializer : TestComponentBase + { + public override Type InitializerType => typeof(Initializer); + + public class Initializer : IComponentInitializer + { + public void Initialize() + { + Initialized.Add(GetType().Name); + } + } + } + public class Component1 : TestComponentBase { } From 51c4962477005e9b98edaf7d1053e890cb958f96 Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Mon, 3 Sep 2018 00:38:53 +0200 Subject: [PATCH 048/469] Registering lightinject with itself again due to mapper collection builder. It now fails becuse it doesn't support last registered as default ootb when instantiating cachehelper. Castle fails on missing mapper collection builder when examine starts indexing. --- src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs index f9dd0028b2..92054bce4f 100644 --- a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs +++ b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs @@ -20,6 +20,8 @@ namespace Umbraco.Core.Composing.LightInject protected LightInjectContainer(ServiceContainer container) { Container = container; + + container.RegisterSingleton(_ => this); } /// From 04944f2c0ca87096c1cb7fa7053c37a804985fbd Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Mon, 3 Sep 2018 22:48:04 +0200 Subject: [PATCH 049/469] Virtualizing registration of the cache helper # Conflicts: # src/Umbraco.Core/Runtime/CoreRuntime.cs # src/Umbraco.Web/Runtime/WebRuntime.cs --- src/Umbraco.Core/Runtime/CoreRuntime.cs | 26 +++++++++++++++--------- src/Umbraco.Web/Runtime/WebRuntime.cs | 27 +++++++++++++++---------- 2 files changed, 33 insertions(+), 20 deletions(-) diff --git a/src/Umbraco.Core/Runtime/CoreRuntime.cs b/src/Umbraco.Core/Runtime/CoreRuntime.cs index 3e86003b9d..3afbb9f9ed 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntime.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntime.cs @@ -195,15 +195,7 @@ namespace Umbraco.Core.Runtime container.ComposeConfiguration(); - // register caches - // need the deep clone runtime cache profiver to ensure entities are cached properly, ie - // are cloned in and cloned out - no request-based cache here since no web-based context, - // will be overriden later or - container.RegisterSingleton(_ => new CacheHelper( - new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()), - new StaticCacheProvider(), - NullCacheProvider.Instance, - new IsolatedRuntimeCache(type => new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider())))); + RegisterCacheHelper(container); container.RegisterSingleton(f => f.GetInstance().RuntimeCache); // register the plugin manager @@ -236,6 +228,22 @@ namespace Umbraco.Core.Runtime container.RegisterSingleton(); } + protected virtual void RegisterCacheHelper(IContainer container) + { +// register caches + // need the deep clone runtime cache profiver to ensure entities are cached properly, ie + // are cloned in and cloned out - no request-based cache here since no web-based context, + // will be overriden later or + container.RegisterSingleton( + "CacheHelper", + _ => new CacheHelper( + new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()), + new StaticCacheProvider(), + NullCacheProvider.Instance, + new IsolatedRuntimeCache(type => + new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider())))); + } + protected virtual void ComposeMapperCollection(MapperCollectionBuilder builder) { builder.AddCore(); diff --git a/src/Umbraco.Web/Runtime/WebRuntime.cs b/src/Umbraco.Web/Runtime/WebRuntime.cs index 38c0c5ad50..424a3e4504 100644 --- a/src/Umbraco.Web/Runtime/WebRuntime.cs +++ b/src/Umbraco.Web/Runtime/WebRuntime.cs @@ -57,20 +57,25 @@ namespace Umbraco.Web.Runtime // replace CoreRuntime's IProfiler registration container.RegisterSingleton(_ => _webProfiler); + container.RegisterSingleton(); // required for hybrid accessors + } + + protected override void RegisterCacheHelper(IContainer container) + { // replace CoreRuntime's CacheHelper registration - container.RegisterSingleton(_ => new CacheHelper( - // we need to have the dep clone runtime cache provider to ensure - // all entities are cached properly (cloned in and cloned out) - new DeepCloneRuntimeCacheProvider(new HttpRuntimeCacheProvider(HttpRuntime.Cache)), - new StaticCacheProvider(), - // we need request based cache when running in web-based context - new HttpRequestCacheProvider(), - new IsolatedRuntimeCache(type => + container.RegisterSingleton( + "CacheHelper", + _ => new CacheHelper( // we need to have the dep clone runtime cache provider to ensure // all entities are cached properly (cloned in and cloned out) - new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider())))); - - container.RegisterSingleton(); // required for hybrid accessors + new DeepCloneRuntimeCacheProvider(new HttpRuntimeCacheProvider(HttpRuntime.Cache)), + new StaticCacheProvider(), + // we need request based cache when running in web-based context + new HttpRequestCacheProvider(), + new IsolatedRuntimeCache(type => + // we need to have the dep clone runtime cache provider to ensure + // all entities are cached properly (cloned in and cloned out) + new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider())))); } #region Getters From 236a755f78bff0aa3b7ae0483f227f6da2b1d300 Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Sat, 8 Sep 2018 14:45:44 +0200 Subject: [PATCH 050/469] Registration changes for LI when registereing transients. Can now boot backoffice and can log in when using LightInject. Before this, the automapper profiles weren't there on the container even if registered. These changes seem to have solved it. No real proof or testing back and forth, but it makes LI work... # Conflicts: # src/Umbraco.Web/Runtime/WebRuntimeComponent.cs --- .../Composing/LightInject/LightInjectContainer.cs | 10 ++++++++++ src/Umbraco.Core/UmbracoApplicationBase.cs | 1 + src/Umbraco.Web/Runtime/WebRuntimeComponent.cs | 13 ++++++++----- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs index 92054bce4f..269873a3de 100644 --- a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs +++ b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs @@ -170,6 +170,8 @@ namespace Umbraco.Core.Composing.LightInject switch (lifetime) { case Lifetime.Transient: + Container.Register(serviceType); + break; case Lifetime.Request: case Lifetime.Scope: Container.Register(serviceType, GetLifetime(lifetime)); @@ -188,6 +190,8 @@ namespace Umbraco.Core.Composing.LightInject switch (lifetime) { case Lifetime.Transient: + Container.Register(serviceType, implementingType, implementingType.Name); + break; case Lifetime.Request: case Lifetime.Scope: Container.Register(serviceType, implementingType, GetLifetime(lifetime)); @@ -206,6 +210,8 @@ namespace Umbraco.Core.Composing.LightInject switch (lifetime) { case Lifetime.Transient: + Container.Register(serviceType, implementingType, name); + break; case Lifetime.Request: case Lifetime.Scope: Container.Register(serviceType, implementingType, name, GetLifetime(lifetime)); @@ -224,6 +230,8 @@ namespace Umbraco.Core.Composing.LightInject switch (lifetime) { case Lifetime.Transient: + Container.Register(f => factory(this)); + break; case Lifetime.Request: case Lifetime.Scope: Container.Register(f => factory(this), GetLifetime(lifetime)); @@ -242,6 +250,8 @@ namespace Umbraco.Core.Composing.LightInject switch (lifetime) { case Lifetime.Transient: + Container.Register(f => factory(this), name); + break; case Lifetime.Request: case Lifetime.Scope: Container.Register(f => factory(this), name, GetLifetime(lifetime)); diff --git a/src/Umbraco.Core/UmbracoApplicationBase.cs b/src/Umbraco.Core/UmbracoApplicationBase.cs index 979bc380ff..18884eb459 100644 --- a/src/Umbraco.Core/UmbracoApplicationBase.cs +++ b/src/Umbraco.Core/UmbracoApplicationBase.cs @@ -70,6 +70,7 @@ namespace Umbraco.Core // create the container for the application, and configure. // the boot manager is responsible for registrations var container = GetContainer(); + container.RegisterInstance(container); Current.Container = container; // register the essential stuff, diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs index e007ca322e..c43fec6382 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs @@ -87,8 +87,9 @@ namespace Umbraco.Web.Runtime // let's use an hybrid accessor that can fall back to a ThreadStatic context. composition.Container.RegisterSingleton(); - // register the 'current' umbraco context - transient - for eg controllers - composition.Container.Register(factory => factory.GetInstance().UmbracoContext); + // review - Let's just keep the one, eh? (Line 104) + //// register the 'current' umbraco context - transient - for eg controllers + //composition.Container.Register(factory => factory.GetInstance().UmbracoContext, "TransientUmbracoContext"); // register a per-request HttpContextBase object // is per-request so only one wrapper is created per request @@ -97,9 +98,11 @@ namespace Umbraco.Web.Runtime // register the published snapshot accessor - the "current" published snapshot is in the umbraco context composition.Container.RegisterSingleton(); - // register a per-request UmbracoContext object - // no real need to be per request but assuming it is faster - composition.Container.RegisterSingleton(factory => factory.GetInstance().UmbracoContext); + // review - making the umbraco context and actual per request thing. See 9a4eecab0177a67b8e7670edadb4547f5c3271b9 + // register a per-request UmbracoContext object + // no real need to be per request but assuming it is faster + // fixme - this second registration really bugs me. re-purposing a (nameless) service? can't we force everything to use the accessor now? + composition.Container.Register(factory => factory.GetInstance().UmbracoContext, Lifetime.Request); // register the umbraco helper composition.Container.RegisterSingleton(); From 1198191e051fd40891177ee30ffe8e9d33a3c856 Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Sun, 9 Sep 2018 16:41:28 +0200 Subject: [PATCH 051/469] Wrapping server messenger factory to avoid re-registering for now. --- .../Components/CompositionExtensions.cs | 43 +++++++++++++------ .../Runtime/CoreRuntimeComponent.cs | 3 +- 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/src/Umbraco.Core/Components/CompositionExtensions.cs b/src/Umbraco.Core/Components/CompositionExtensions.cs index abc0fa3862..1bbb3faff0 100644 --- a/src/Umbraco.Core/Components/CompositionExtensions.cs +++ b/src/Umbraco.Core/Components/CompositionExtensions.cs @@ -172,16 +172,23 @@ namespace Umbraco.Core.Components composition.Container.RegisterSingleton(_ => registrar); } - /// - /// Sets the server messenger. - /// - /// The type of the server registrar. - /// The composition. - public static void SetServerMessenger(this Composition composition) - where T : IServerMessenger - { - composition.Container.Register(Lifetime.Singleton); - } + + // review since only one is called in the core for now, I remove this + // it allows us to wrap the factory to "allow re-registration". + ///// + ///// Sets the server messenger. + ///// + ///// The type of the server registrar. + ///// The composition. + //public static void SetServerMessenger(this Composition composition) + // where T : IServerMessenger + //{ + // composition.Container.Register(Lifetime.Singleton); + //} + + private static Func serverMessengerFactory = null; + private static bool serverMessengerIsRegistered = false; + private static Func wrappedServerMessengerFactory = c => serverMessengerFactory(c); /// /// Sets the server messenger. @@ -190,7 +197,13 @@ namespace Umbraco.Core.Components /// A function creating a server messenger. public static void SetServerMessenger(this Composition composition, Func factory) { - composition.Container.RegisterSingleton(factory); + if (!serverMessengerIsRegistered) + { + serverMessengerIsRegistered = true; + composition.Container.RegisterSingleton(wrappedServerMessengerFactory); + } + + serverMessengerFactory = factory; } /// @@ -200,7 +213,13 @@ namespace Umbraco.Core.Components /// A server messenger. public static void SetServerMessenger(this Composition composition, IServerMessenger registrar) { - composition.Container.RegisterSingleton(_ => registrar); + if (!serverMessengerIsRegistered) + { + serverMessengerIsRegistered = true; + composition.Container.RegisterSingleton(wrappedServerMessengerFactory); + } + + serverMessengerFactory = c => registrar; } /// diff --git a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs index 9d7c3e5a6a..ae9955706c 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs @@ -74,7 +74,8 @@ namespace Umbraco.Core.Runtime // by default we'll use the database server messenger with default options (no callbacks), // this will be overridden by either the legacy thing or the db thing in the corresponding // components in the web project - fixme - should obsolete the legacy thing - composition.Container.RegisterSingleton(factory + composition.SetServerMessenger( + factory => new DatabaseServerMessenger( factory.GetInstance(), factory.GetInstance(), From b4b09bc116593333b96cf90879a0e490c97fac5b Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Sun, 9 Sep 2018 20:05:06 +0200 Subject: [PATCH 052/469] Changes to allow using container from third party tests --- src/Umbraco.Core/Composing/Current.cs | 2 +- src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs | 5 +++++ src/Umbraco.Web/Composing/Current.cs | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Core/Composing/Current.cs b/src/Umbraco.Core/Composing/Current.cs index 49bb44db47..215840023a 100644 --- a/src/Umbraco.Core/Composing/Current.cs +++ b/src/Umbraco.Core/Composing/Current.cs @@ -37,7 +37,7 @@ namespace Umbraco.Core.Composing /// /// Gets or sets the DI container. /// - internal static IContainer Container + public static IContainer Container { get { diff --git a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs index 4314af38b5..d9769cfb35 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs @@ -34,6 +34,8 @@ namespace Umbraco.Tests.TestHelpers var container = Current.Container = ContainerFactory.Create(); + PreSetUp(); + container.RegisterSingleton(factory => Mock.Of()); container.RegisterSingleton(factory => Mock.Of()); @@ -55,6 +57,9 @@ namespace Umbraco.Tests.TestHelpers SetUp(); } + public virtual void PreSetUp() + {} + public virtual void SetUp() {} diff --git a/src/Umbraco.Web/Composing/Current.cs b/src/Umbraco.Web/Composing/Current.cs index cf1a419769..8d36028667 100644 --- a/src/Umbraco.Web/Composing/Current.cs +++ b/src/Umbraco.Web/Composing/Current.cs @@ -54,7 +54,7 @@ namespace Umbraco.Web.Composing /// /// Gets the DI container. /// - internal static IContainer Container + public static IContainer Container => CoreCurrent.Container; #region Temp & Special From 1418d3124d277ca7925f4eda31a525abfb51d583 Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Sun, 9 Sep 2018 21:51:37 +0200 Subject: [PATCH 053/469] Registering IdentityMapperProfile as a Profile as well --- .../Composing/Composers/CoreMappingProfilesComposer.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Core/Composing/Composers/CoreMappingProfilesComposer.cs b/src/Umbraco.Core/Composing/Composers/CoreMappingProfilesComposer.cs index a1fc36a8c4..fbb653b3e9 100644 --- a/src/Umbraco.Core/Composing/Composers/CoreMappingProfilesComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/CoreMappingProfilesComposer.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Models.Identity; +using AutoMapper; +using Umbraco.Core.Models.Identity; namespace Umbraco.Core.Composing.Composers @@ -7,7 +8,7 @@ namespace Umbraco.Core.Composing.Composers { public static IContainer ComposeCoreMappingProfiles(this IContainer container) { - container.Register(); + container.Register(); return container; } } From 57d22a87c03d715cce9ede4e4f8bb92a7b5617e9 Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Sun, 9 Sep 2018 22:00:26 +0200 Subject: [PATCH 054/469] REVIEW/FIX: Just removing placeholder IApplicationTreeService and ISectionService registrations until we figure defaulting. --- src/Umbraco.Core/Composing/Composers/ServicesComposer.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs index fc898dd3b6..3455c4693e 100644 --- a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs @@ -58,8 +58,9 @@ namespace Umbraco.Core.Composing.Composers //TODO: These are replaced in the web project - we need to declare them so that // something is wired up, just not sure this is very nice but will work for now. - container.RegisterSingleton(); - container.RegisterSingleton(); + // fixme - we need to get rid of re-registering, and I need this gone for now. >< + //container.RegisterSingleton(); + //container.RegisterSingleton(); return container; } From 4ffcdf6943ed219098c734a374d00b36d1dd56f0 Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Sun, 9 Sep 2018 22:34:20 +0200 Subject: [PATCH 055/469] Replaced base controller factory with one using the container o:) --- src/Umbraco.Core/Composing/IContainer.cs | 2 ++ .../LightInject/LightInjectContainer.cs | 5 ++++ .../Mvc/ContainerControllerFactory.cs | 28 +++++++++++++++++++ .../Mvc/MasterControllerFactory.cs | 4 ++- .../Mvc/UmbracoControllerFactory.cs | 8 +++++- src/Umbraco.Web/Umbraco.Web.csproj | 1 + 6 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 src/Umbraco.Web/Mvc/ContainerControllerFactory.cs diff --git a/src/Umbraco.Core/Composing/IContainer.cs b/src/Umbraco.Core/Composing/IContainer.cs index 9a5452bf65..2937fb2b02 100644 --- a/src/Umbraco.Core/Composing/IContainer.cs +++ b/src/Umbraco.Core/Composing/IContainer.cs @@ -169,5 +169,7 @@ namespace Umbraco.Core.Composing IContainer EnablePerWebRequestScope(); #endregion + + void Release(object instance); } } diff --git a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs index 269873a3de..d4b88e862c 100644 --- a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs +++ b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs @@ -314,6 +314,11 @@ namespace Umbraco.Core.Composing.LightInject #endregion + public void Release(object instance) + { + // fixme - no idea how to do this with LI + } + #region Control /// diff --git a/src/Umbraco.Web/Mvc/ContainerControllerFactory.cs b/src/Umbraco.Web/Mvc/ContainerControllerFactory.cs new file mode 100644 index 0000000000..d37054fda1 --- /dev/null +++ b/src/Umbraco.Web/Mvc/ContainerControllerFactory.cs @@ -0,0 +1,28 @@ +using System; +using System.Web.Mvc; +using System.Web.Routing; +using System.Web.SessionState; +using Umbraco.Core.Composing; + +namespace Umbraco.Web.Mvc +{ + public class ContainerControllerFactory : DefaultControllerFactory + { + private readonly IContainer container; + + public ContainerControllerFactory(IContainer container) + { + this.container = container; + } + + protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) + { + return (IController)container.GetInstance(controllerType); + } + + public override void ReleaseController(IController controller) + { + container.Release(controller); + } + } +} diff --git a/src/Umbraco.Web/Mvc/MasterControllerFactory.cs b/src/Umbraco.Web/Mvc/MasterControllerFactory.cs index 20c5c1cfd5..3d1e450c93 100644 --- a/src/Umbraco.Web/Mvc/MasterControllerFactory.cs +++ b/src/Umbraco.Web/Mvc/MasterControllerFactory.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Web.Mvc; using System.Web.Routing; +using Umbraco.Web.Composing; namespace Umbraco.Web.Mvc { @@ -11,7 +12,7 @@ namespace Umbraco.Web.Mvc /// request. Allows circumvention of MVC3's singly registered IControllerFactory. /// /// - internal class MasterControllerFactory : DefaultControllerFactory + internal class MasterControllerFactory : ContainerControllerFactory { private readonly Func _factoriesAccessor; private FilteredControllerFactoryCollection _factories; @@ -21,6 +22,7 @@ namespace Umbraco.Web.Mvc /// /// The factories accessor. public MasterControllerFactory(Func factoriesAccessor) + : base(Current.Container) { // note // because the MasterControllerFactory needs to be ctored to be assigned to diff --git a/src/Umbraco.Web/Mvc/UmbracoControllerFactory.cs b/src/Umbraco.Web/Mvc/UmbracoControllerFactory.cs index 2c68718ec2..330031976d 100644 --- a/src/Umbraco.Web/Mvc/UmbracoControllerFactory.cs +++ b/src/Umbraco.Web/Mvc/UmbracoControllerFactory.cs @@ -65,8 +65,14 @@ namespace Umbraco.Web.Mvc /// this nested class changes the visibility of 's internal methods in order to not have to rely on a try-catch. /// /// - internal class OverridenDefaultControllerFactory : DefaultControllerFactory + internal class OverridenDefaultControllerFactory : ContainerControllerFactory + // DefaultControllerFactory { + public OverridenDefaultControllerFactory() + : base(Current.Container) + { + } + public new IController GetControllerInstance(RequestContext requestContext, Type controllerType) { return base.GetControllerInstance(requestContext, controllerType); diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index cc477c3224..79f0fbdafb 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -116,6 +116,7 @@ + From a9e0f90ef0280d8f1a9993c44f349d3a468715ed Mon Sep 17 00:00:00 2001 From: Stephan Date: Mon, 8 Oct 2018 19:27:32 +0200 Subject: [PATCH 056/469] Fix merge --- .../Persistence/Repositories/AuditRepositoryTest.cs | 4 ++-- .../PublishedContent/PublishedContentSnapshotTestBase.cs | 2 +- .../ContentApps/ContentAppDefinitionCollectionBuilder.cs | 7 +++---- src/Umbraco.Web/UmbracoInjectedModule.cs | 5 ----- 4 files changed, 6 insertions(+), 12 deletions(-) diff --git a/src/Umbraco.Tests/Persistence/Repositories/AuditRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/AuditRepositoryTest.cs index e57a1ebbbc..62407d1ec5 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/AuditRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/AuditRepositoryTest.cs @@ -69,7 +69,7 @@ namespace Umbraco.Tests.Persistence.Repositories var sp = TestObjects.GetScopeProvider(Logger); using (var scope = sp.CreateScope()) { - var repo = new AuditRepository((IScopeAccessor)sp, CacheHelper, Logger); + var repo = new AuditRepository((IScopeAccessor)sp, Logger); for (var i = 0; i < 100; i++) { @@ -82,7 +82,7 @@ namespace Umbraco.Tests.Persistence.Repositories using (var scope = sp.CreateScope()) { - var repo = new AuditRepository((IScopeAccessor)sp, CacheHelper, Logger); + var repo = new AuditRepository((IScopeAccessor)sp, Logger); var query = sp.SqlContext.Query().Where(x => x.UserId == -1); diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs index 623472a023..dc88f8bea1 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs @@ -40,7 +40,7 @@ namespace Umbraco.Tests.PublishedContent Container.RegisterSingleton(f => new PublishedModelFactory(f.GetInstance().GetTypes())); } - protected override TypeLoader CreatePluginManager(IServiceFactory f) + protected override TypeLoader CreatePluginManager(IContainer f) { var pluginManager = base.CreatePluginManager(f); diff --git a/src/Umbraco.Web/ContentApps/ContentAppDefinitionCollectionBuilder.cs b/src/Umbraco.Web/ContentApps/ContentAppDefinitionCollectionBuilder.cs index 267dd2d0e7..6fcaea87a3 100644 --- a/src/Umbraco.Web/ContentApps/ContentAppDefinitionCollectionBuilder.cs +++ b/src/Umbraco.Web/ContentApps/ContentAppDefinitionCollectionBuilder.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Linq; -using LightInject; using Umbraco.Core.Composing; using Umbraco.Core.Logging; using Umbraco.Core.Manifest; @@ -10,7 +9,7 @@ namespace Umbraco.Web.ContentApps { public class ContentAppDefinitionCollectionBuilder : OrderedCollectionBuilderBase { - public ContentAppDefinitionCollectionBuilder(IServiceContainer container) + public ContentAppDefinitionCollectionBuilder(IContainer container) : base(container) { } @@ -25,14 +24,14 @@ namespace Umbraco.Web.ContentApps return new ContentAppDefinitionCollection(CreateItems(), logger); } - protected override IEnumerable CreateItems(params object[] args) + protected override IEnumerable CreateItems() { // 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 = Container.GetInstance(); - return base.CreateItems(args).Concat(manifestParser.Manifest.ContentApps); + return base.CreateItems().Concat(manifestParser.Manifest.ContentApps); } } } diff --git a/src/Umbraco.Web/UmbracoInjectedModule.cs b/src/Umbraco.Web/UmbracoInjectedModule.cs index 421a949813..11670df51b 100644 --- a/src/Umbraco.Web/UmbracoInjectedModule.cs +++ b/src/Umbraco.Web/UmbracoInjectedModule.cs @@ -91,11 +91,6 @@ namespace Umbraco.Web // ok, process - // create the LegacyRequestInitializer - // and initialize legacy stuff - var legacyRequestInitializer = new LegacyRequestInitializer(httpContext.Request.Url, httpContext); - legacyRequestInitializer.InitializeRequest(); - // create the UmbracoContext singleton, one per request, and assign // replace existing if any (eg during app startup, a temp one is created) UmbracoContext.EnsureContext( From 8894df919ef91a54f388bb78bf9c1e51d622ed02 Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Sun, 21 Oct 2018 12:37:14 +0200 Subject: [PATCH 057/469] Should not have package-lock in git --- src/Umbraco.Web.UI.Client/package-lock.json | 16926 ------------------ 1 file changed, 16926 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/package-lock.json diff --git a/src/Umbraco.Web.UI.Client/package-lock.json b/src/Umbraco.Web.UI.Client/package-lock.json deleted file mode 100644 index 2bbe8d726d..0000000000 --- a/src/Umbraco.Web.UI.Client/package-lock.json +++ /dev/null @@ -1,16926 +0,0 @@ -{ - "requires": true, - "lockfileVersion": 1, - "dependencies": { - "@babel/code-frame": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", - "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", - "dev": true, - "requires": { - "@babel/highlight": "^7.0.0" - } - }, - "@babel/core": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.1.2.tgz", - "integrity": "sha512-IFeSSnjXdhDaoysIlev//UzHZbdEmm7D0EIH2qtse9xK7mXEZQpYjs2P00XlP1qYsYvid79p+Zgg6tz1mp6iVw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.1.2", - "@babel/helpers": "^7.1.2", - "@babel/parser": "^7.1.2", - "@babel/template": "^7.1.2", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.1.2", - "convert-source-map": "^1.1.0", - "debug": "^3.1.0", - "json5": "^0.5.0", - "lodash": "^4.17.10", - "resolve": "^1.3.2", - "semver": "^5.4.1", - "source-map": "^0.5.0" - }, - "dependencies": { - "debug": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.5.tgz", - "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, - "semver": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", - "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==", - "dev": true - } - } - }, - "@babel/generator": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.1.2.tgz", - "integrity": "sha512-70A9HWLS/1RHk3Ck8tNHKxOoKQuSKocYgwDN85Pyl/RBduss6AKxUR7RIZ/lzduQMSYfWEM4DDBu6A+XGbkFig==", - "dev": true, - "requires": { - "@babel/types": "^7.1.2", - "jsesc": "^2.5.1", - "lodash": "^4.17.10", - "source-map": "^0.5.0", - "trim-right": "^1.0.1" - } - }, - "@babel/helper-annotate-as-pure": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz", - "integrity": "sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz", - "integrity": "sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w==", - "dev": true, - "requires": { - "@babel/helper-explode-assignable-expression": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-call-delegate": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.1.0.tgz", - "integrity": "sha512-YEtYZrw3GUK6emQHKthltKNZwszBcHK58Ygcis+gVUrF4/FmTVr5CCqQNSfmvg2y+YDEANyYoaLz/SHsnusCwQ==", - "dev": true, - "requires": { - "@babel/helper-hoist-variables": "^7.0.0", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-define-map": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.1.0.tgz", - "integrity": "sha512-yPPcW8dc3gZLN+U1mhYV91QU3n5uTbx7DUdf8NnPbjS0RMwBuHi9Xt2MUgppmNz7CJxTBWsGczTiEp1CSOTPRg==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/types": "^7.0.0", - "lodash": "^4.17.10" - } - }, - "@babel/helper-explode-assignable-expression": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz", - "integrity": "sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA==", - "dev": true, - "requires": { - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-function-name": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", - "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.0.0", - "@babel/template": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", - "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.0.0.tgz", - "integrity": "sha512-Ggv5sldXUeSKsuzLkddtyhyHe2YantsxWKNi7A+7LeD12ExRDWTRk29JCXpaHPAbMaIPZSil7n+lq78WY2VY7w==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-member-expression-to-functions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.0.0.tgz", - "integrity": "sha512-avo+lm/QmZlv27Zsi0xEor2fKcqWG56D5ae9dzklpIaY7cQMK5N8VSpaNVPPagiqmy7LrEjK1IWdGMOqPu5csg==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-module-imports": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz", - "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-module-transforms": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.1.0.tgz", - "integrity": "sha512-0JZRd2yhawo79Rcm4w0LwSMILFmFXjugG3yqf+P/UsKsRS1mJCmMwwlHDlMg7Avr9LrvSpp4ZSULO9r8jpCzcw==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-simple-access": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.0.0", - "@babel/template": "^7.1.0", - "@babel/types": "^7.0.0", - "lodash": "^4.17.10" - } - }, - "@babel/helper-optimise-call-expression": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz", - "integrity": "sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", - "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==", - "dev": true - }, - "@babel/helper-regex": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.0.0.tgz", - "integrity": "sha512-TR0/N0NDCcUIUEbqV6dCO+LptmmSQFQ7q70lfcEB4URsjD0E1HzicrwUH+ap6BAQ2jhCX9Q4UqZy4wilujWlkg==", - "dev": true, - "requires": { - "lodash": "^4.17.10" - } - }, - "@babel/helper-remap-async-to-generator": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz", - "integrity": "sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-wrap-function": "^7.1.0", - "@babel/template": "^7.1.0", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-replace-supers": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.1.0.tgz", - "integrity": "sha512-BvcDWYZRWVuDeXTYZWxekQNO5D4kO55aArwZOTFXw6rlLQA8ZaDicJR1sO47h+HrnCiDFiww0fSPV0d713KBGQ==", - "dev": true, - "requires": { - "@babel/helper-member-expression-to-functions": "^7.0.0", - "@babel/helper-optimise-call-expression": "^7.0.0", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-simple-access": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz", - "integrity": "sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w==", - "dev": true, - "requires": { - "@babel/template": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz", - "integrity": "sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-wrap-function": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.1.0.tgz", - "integrity": "sha512-R6HU3dete+rwsdAfrOzTlE9Mcpk4RjU3aX3gi9grtmugQY0u79X7eogUvfXA5sI81Mfq1cn6AgxihfN33STjJA==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/template": "^7.1.0", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/helpers": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.1.2.tgz", - "integrity": "sha512-Myc3pUE8eswD73aWcartxB16K6CGmHDv9KxOmD2CeOs/FaEAQodr3VYGmlvOmog60vNQ2w8QbatuahepZwrHiA==", - "dev": true, - "requires": { - "@babel/template": "^7.1.2", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.1.2" - } - }, - "@babel/highlight": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", - "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "@babel/parser": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.1.2.tgz", - "integrity": "sha512-x5HFsW+E/nQalGMw7hu+fvPqnBeBaIr0lWJ2SG0PPL2j+Pm9lYvCrsZJGIgauPIENx0v10INIyFjmSNUD/gSqQ==", - "dev": true - }, - "@babel/plugin-proposal-async-generator-functions": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.1.0.tgz", - "integrity": "sha512-Fq803F3Jcxo20MXUSDdmZZXrPe6BWyGcWBPPNB/M7WaUYESKDeKMOGIxEzQOjGSmW/NWb6UaPZrtTB2ekhB/ew==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-remap-async-to-generator": "^7.1.0", - "@babel/plugin-syntax-async-generators": "^7.0.0" - } - }, - "@babel/plugin-proposal-json-strings": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.0.0.tgz", - "integrity": "sha512-kfVdUkIAGJIVmHmtS/40i/fg/AGnw/rsZBCaapY5yjeO5RA9m165Xbw9KMOu2nqXP5dTFjEjHdfNdoVcHv133Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-json-strings": "^7.0.0" - } - }, - "@babel/plugin-proposal-object-rest-spread": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.0.0.tgz", - "integrity": "sha512-14fhfoPcNu7itSen7Py1iGN0gEm87hX/B+8nZPqkdmANyyYWYMY2pjA3r8WXbWVKMzfnSNS0xY8GVS0IjXi/iw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-object-rest-spread": "^7.0.0" - } - }, - "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.0.0.tgz", - "integrity": "sha512-JPqAvLG1s13B/AuoBjdBYvn38RqW6n1TzrQO839/sIpqLpbnXKacsAgpZHzLD83Sm8SDXMkkrAvEnJ25+0yIpw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.0.0" - } - }, - "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.0.0.tgz", - "integrity": "sha512-tM3icA6GhC3ch2SkmSxv7J/hCWKISzwycub6eGsDrFDgukD4dZ/I+x81XgW0YslS6mzNuQ1Cbzh5osjIMgepPQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.0.0", - "regexpu-core": "^4.2.0" - } - }, - "@babel/plugin-syntax-async-generators": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.0.0.tgz", - "integrity": "sha512-im7ged00ddGKAjcZgewXmp1vxSZQQywuQXe2B1A7kajjZmDeY/ekMPmWr9zJgveSaQH0k7BcGrojQhcK06l0zA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-syntax-json-strings": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.0.0.tgz", - "integrity": "sha512-UlSfNydC+XLj4bw7ijpldc1uZ/HB84vw+U6BTuqMdIEmz/LDe63w/GHtpQMdXWdqQZFeAI9PjnHe/vDhwirhKA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.0.0.tgz", - "integrity": "sha512-5A0n4p6bIiVe5OvQPxBnesezsgFJdHhSs3uFSvaPdMqtsovajLZ+G2vZyvNe10EzJBWWo3AcHGKhAFUxqwp2dw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.0.0.tgz", - "integrity": "sha512-Wc+HVvwjcq5qBg1w5RG9o9RVzmCaAg/Vp0erHCKpAYV8La6I94o4GQAmFYNmkzoMO6gzoOSulpKeSSz6mPEoZw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-arrow-functions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.0.0.tgz", - "integrity": "sha512-2EZDBl1WIO/q4DIkIp4s86sdp4ZifL51MoIviLY/gG/mLSuOIEg7J8o6mhbxOTvUJkaN50n+8u41FVsr5KLy/w==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-async-to-generator": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.1.0.tgz", - "integrity": "sha512-rNmcmoQ78IrvNCIt/R9U+cixUHeYAzgusTFgIAv+wQb9HJU4szhpDD6e5GCACmj/JP5KxuCwM96bX3L9v4ZN/g==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-remap-async-to-generator": "^7.1.0" - } - }, - "@babel/plugin-transform-block-scoped-functions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.0.0.tgz", - "integrity": "sha512-AOBiyUp7vYTqz2Jibe1UaAWL0Hl9JUXEgjFvvvcSc9MVDItv46ViXFw2F7SVt1B5k+KWjl44eeXOAk3UDEaJjQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-block-scoping": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.0.0.tgz", - "integrity": "sha512-GWEMCrmHQcYWISilUrk9GDqH4enf3UmhOEbNbNrlNAX1ssH3MsS1xLOS6rdjRVPgA7XXVPn87tRkdTEoA/dxEg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "lodash": "^4.17.10" - } - }, - "@babel/plugin-transform-classes": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.1.0.tgz", - "integrity": "sha512-rNaqoD+4OCBZjM7VaskladgqnZ1LO6o2UxuWSDzljzW21pN1KXkB7BstAVweZdxQkHAujps5QMNOTWesBciKFg==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-define-map": "^7.1.0", - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-optimise-call-expression": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.0.0", - "globals": "^11.1.0" - } - }, - "@babel/plugin-transform-computed-properties": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.0.0.tgz", - "integrity": "sha512-ubouZdChNAv4AAWAgU7QKbB93NU5sHwInEWfp+/OzJKA02E6Woh9RVoX4sZrbRwtybky/d7baTUqwFx+HgbvMA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-destructuring": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.1.2.tgz", - "integrity": "sha512-cvToXvp/OsYxtEn57XJu9BvsGSEYjAh9UeUuXpoi7x6QHB7YdWyQ4lRU/q0Fu1IJNT0o0u4FQ1DMQBzJ8/8vZg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-dotall-regex": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.0.0.tgz", - "integrity": "sha512-00THs8eJxOJUFVx1w8i1MBF4XH4PsAjKjQ1eqN/uCH3YKwP21GCKfrn6YZFZswbOk9+0cw1zGQPHVc1KBlSxig==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.0.0", - "regexpu-core": "^4.1.3" - } - }, - "@babel/plugin-transform-duplicate-keys": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.0.0.tgz", - "integrity": "sha512-w2vfPkMqRkdxx+C71ATLJG30PpwtTpW7DDdLqYt2acXU7YjztzeWW2Jk1T6hKqCLYCcEA5UQM/+xTAm+QCSnuQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-exponentiation-operator": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.1.0.tgz", - "integrity": "sha512-uZt9kD1Pp/JubkukOGQml9tqAeI8NkE98oZnHZ2qHRElmeKCodbTZgOEUtujSCSLhHSBWbzNiFSDIMC4/RBTLQ==", - "dev": true, - "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-for-of": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.0.0.tgz", - "integrity": "sha512-TlxKecN20X2tt2UEr2LNE6aqA0oPeMT1Y3cgz8k4Dn1j5ObT8M3nl9aA37LLklx0PBZKETC9ZAf9n/6SujTuXA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-function-name": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.1.0.tgz", - "integrity": "sha512-VxOa1TMlFMtqPW2IDYZQaHsFrq/dDoIjgN098NowhexhZcz3UGlvPgZXuE1jEvNygyWyxRacqDpCZt+par1FNg==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-literals": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.0.0.tgz", - "integrity": "sha512-1NTDBWkeNXgpUcyoVFxbr9hS57EpZYXpje92zv0SUzjdu3enaRwF/l3cmyRnXLtIdyJASyiS6PtybK+CgKf7jA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-modules-amd": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.1.0.tgz", - "integrity": "sha512-wt8P+xQ85rrnGNr2x1iV3DW32W8zrB6ctuBkYBbf5/ZzJY99Ob4MFgsZDFgczNU76iy9PWsy4EuxOliDjdKw6A==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-modules-commonjs": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.1.0.tgz", - "integrity": "sha512-wtNwtMjn1XGwM0AXPspQgvmE6msSJP15CX2RVfpTSTNPLhKhaOjaIfBaVfj4iUZ/VrFSodcFedwtPg/NxwQlPA==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-simple-access": "^7.1.0" - } - }, - "@babel/plugin-transform-modules-systemjs": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.0.0.tgz", - "integrity": "sha512-8EDKMAsitLkiF/D4Zhe9CHEE2XLh4bfLbb9/Zf3FgXYQOZyZYyg7EAel/aT2A7bHv62jwHf09q2KU/oEexr83g==", - "dev": true, - "requires": { - "@babel/helper-hoist-variables": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-modules-umd": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.1.0.tgz", - "integrity": "sha512-enrRtn5TfRhMmbRwm7F8qOj0qEYByqUvTttPEGimcBH4CJHphjyK1Vg7sdU7JjeEmgSpM890IT/efS2nMHwYig==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-new-target": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.0.0.tgz", - "integrity": "sha512-yin069FYjah+LbqfGeTfzIBODex/e++Yfa0rH0fpfam9uTbuEeEOx5GLGr210ggOV77mVRNoeqSYqeuaqSzVSw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-object-super": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.1.0.tgz", - "integrity": "sha512-/O02Je1CRTSk2SSJaq0xjwQ8hG4zhZGNjE8psTsSNPXyLRCODv7/PBozqT5AmQMzp7MI3ndvMhGdqp9c96tTEw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.1.0" - } - }, - "@babel/plugin-transform-parameters": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.1.0.tgz", - "integrity": "sha512-vHV7oxkEJ8IHxTfRr3hNGzV446GAb+0hgbA7o/0Jd76s+YzccdWuTU296FOCOl/xweU4t/Ya4g41yWz80RFCRw==", - "dev": true, - "requires": { - "@babel/helper-call-delegate": "^7.1.0", - "@babel/helper-get-function-arity": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-regenerator": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.0.0.tgz", - "integrity": "sha512-sj2qzsEx8KDVv1QuJc/dEfilkg3RRPvPYx/VnKLtItVQRWt1Wqf5eVCOLZm29CiGFfYYsA3VPjfizTCV0S0Dlw==", - "dev": true, - "requires": { - "regenerator-transform": "^0.13.3" - } - }, - "@babel/plugin-transform-shorthand-properties": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.0.0.tgz", - "integrity": "sha512-g/99LI4vm5iOf5r1Gdxq5Xmu91zvjhEG5+yZDJW268AZELAu4J1EiFLnkSG3yuUsZyOipVOVUKoGPYwfsTymhw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-spread": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.0.0.tgz", - "integrity": "sha512-L702YFy2EvirrR4shTj0g2xQp7aNwZoWNCkNu2mcoU0uyzMl0XRwDSwzB/xp6DSUFiBmEXuyAyEN16LsgVqGGQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-sticky-regex": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.0.0.tgz", - "integrity": "sha512-LFUToxiyS/WD+XEWpkx/XJBrUXKewSZpzX68s+yEOtIbdnsRjpryDw9U06gYc6klYEij/+KQVRnD3nz3AoKmjw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.0.0" - } - }, - "@babel/plugin-transform-template-literals": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.0.0.tgz", - "integrity": "sha512-vA6rkTCabRZu7Nbl9DfLZE1imj4tzdWcg5vtdQGvj+OH9itNNB6hxuRMHuIY8SGnEt1T9g5foqs9LnrHzsqEFg==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-typeof-symbol": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.0.0.tgz", - "integrity": "sha512-1r1X5DO78WnaAIvs5uC48t41LLckxsYklJrZjNKcevyz83sF2l4RHbw29qrCPr/6ksFsdfRpT/ZgxNWHXRnffg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-unicode-regex": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.0.0.tgz", - "integrity": "sha512-uJBrJhBOEa3D033P95nPHu3nbFwFE9ZgXsfEitzoIXIwqAZWk7uXcg06yFKXz9FSxBH5ucgU/cYdX0IV8ldHKw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.0.0", - "regexpu-core": "^4.1.3" - } - }, - "@babel/preset-env": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.1.0.tgz", - "integrity": "sha512-ZLVSynfAoDHB/34A17/JCZbyrzbQj59QC1Anyueb4Bwjh373nVPq5/HMph0z+tCmcDjXDe+DlKQq9ywQuvWrQg==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-async-generator-functions": "^7.1.0", - "@babel/plugin-proposal-json-strings": "^7.0.0", - "@babel/plugin-proposal-object-rest-spread": "^7.0.0", - "@babel/plugin-proposal-optional-catch-binding": "^7.0.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.0.0", - "@babel/plugin-syntax-async-generators": "^7.0.0", - "@babel/plugin-syntax-object-rest-spread": "^7.0.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.0.0", - "@babel/plugin-transform-arrow-functions": "^7.0.0", - "@babel/plugin-transform-async-to-generator": "^7.1.0", - "@babel/plugin-transform-block-scoped-functions": "^7.0.0", - "@babel/plugin-transform-block-scoping": "^7.0.0", - "@babel/plugin-transform-classes": "^7.1.0", - "@babel/plugin-transform-computed-properties": "^7.0.0", - "@babel/plugin-transform-destructuring": "^7.0.0", - "@babel/plugin-transform-dotall-regex": "^7.0.0", - "@babel/plugin-transform-duplicate-keys": "^7.0.0", - "@babel/plugin-transform-exponentiation-operator": "^7.1.0", - "@babel/plugin-transform-for-of": "^7.0.0", - "@babel/plugin-transform-function-name": "^7.1.0", - "@babel/plugin-transform-literals": "^7.0.0", - "@babel/plugin-transform-modules-amd": "^7.1.0", - "@babel/plugin-transform-modules-commonjs": "^7.1.0", - "@babel/plugin-transform-modules-systemjs": "^7.0.0", - "@babel/plugin-transform-modules-umd": "^7.1.0", - "@babel/plugin-transform-new-target": "^7.0.0", - "@babel/plugin-transform-object-super": "^7.1.0", - "@babel/plugin-transform-parameters": "^7.1.0", - "@babel/plugin-transform-regenerator": "^7.0.0", - "@babel/plugin-transform-shorthand-properties": "^7.0.0", - "@babel/plugin-transform-spread": "^7.0.0", - "@babel/plugin-transform-sticky-regex": "^7.0.0", - "@babel/plugin-transform-template-literals": "^7.0.0", - "@babel/plugin-transform-typeof-symbol": "^7.0.0", - "@babel/plugin-transform-unicode-regex": "^7.0.0", - "browserslist": "^4.1.0", - "invariant": "^2.2.2", - "js-levenshtein": "^1.1.3", - "semver": "^5.3.0" - }, - "dependencies": { - "browserslist": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.2.0.tgz", - "integrity": "sha512-Berls1CHL7qfQz8Lct6QxYA5d2Tvt4doDWHcjvAISybpd+EKZVppNtXgXhaN6SdrPKo7YLTSZuYBs5cYrSWN8w==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30000889", - "electron-to-chromium": "^1.3.73", - "node-releases": "^1.0.0-alpha.12" - } - }, - "semver": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", - "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==", - "dev": true - } - } - }, - "@babel/template": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.1.2.tgz", - "integrity": "sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.1.2", - "@babel/types": "^7.1.2" - } - }, - "@babel/traverse": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.1.0.tgz", - "integrity": "sha512-bwgln0FsMoxm3pLOgrrnGaXk18sSM9JNf1/nHC/FksmNGFbYnPWY4GYCfLxyP1KRmfsxqkRpfoa6xr6VuuSxdw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.0.0", - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.0.0", - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0", - "debug": "^3.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.10" - }, - "dependencies": { - "debug": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.5.tgz", - "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - } - } - }, - "@babel/types": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.1.2.tgz", - "integrity": "sha512-pb1I05sZEKiSlMUV9UReaqsCPUpgbHHHu2n1piRm7JkuBkm6QxcaIzKu6FMnMtCbih/cEYTR+RGYYC96Yk9HAg==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.10", - "to-fast-properties": "^2.0.0" - } - }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha1-+PLIh60Qv2f2NPAFtph/7TF5qsg=", - "dev": true - }, - "accepts": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.2.13.tgz", - "integrity": "sha1-5fHzkoxtlf2WVYw27D2dDeSm7Oo=", - "dev": true, - "requires": { - "mime-types": "~2.1.6", - "negotiator": "0.5.3" - } - }, - "accord": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/accord/-/accord-0.28.0.tgz", - "integrity": "sha1-vsUWovci59UPX59C+Bt387lUSLo=", - "dev": true, - "requires": { - "convert-source-map": "^1.5.0", - "glob": "^7.0.5", - "indx": "^0.2.3", - "lodash.clone": "^4.3.2", - "lodash.defaults": "^4.0.1", - "lodash.flatten": "^4.2.0", - "lodash.merge": "^4.4.0", - "lodash.partialright": "^4.1.4", - "lodash.pick": "^4.2.1", - "lodash.uniq": "^4.3.0", - "resolve": "^1.5.0", - "semver": "^5.3.0", - "uglify-js": "^2.8.22", - "when": "^3.7.8" - }, - "dependencies": { - "semver": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", - "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==", - "dev": true - } - } - }, - "acorn": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", - "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", - "dev": true - }, - "acorn-jsx": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-4.1.1.tgz", - "integrity": "sha1-6OQeSOov4MiWdAYQq2pP/YrdIl4=", - "dev": true, - "requires": { - "acorn": "^5.0.3" - } - }, - "addressparser": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/addressparser/-/addressparser-1.0.1.tgz", - "integrity": "sha1-R6++GiqSYhkdtoOOT9HTm0CCF0Y=", - "dev": true, - "optional": true - }, - "after": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", - "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", - "dev": true - }, - "agent-base": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", - "integrity": "sha1-2J5ZmfeXh1Z0wH2H8mD8Qeg+jKk=", - "dev": true, - "requires": { - "es6-promisify": "^5.0.0" - } - }, - "ajv": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.4.tgz", - "integrity": "sha512-4Wyjt8+t6YszqaXnLDfMmG/8AlO5Zbcsy3ATHncCzjW/NoPzAId8AK6749Ybjmdt+kUY1gP60fCu46oDxPv/mg==", - "dev": true, - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", - "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", - "dev": true - }, - "align-text": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", - "dev": true, - "requires": { - "kind-of": "^3.0.2", - "longest": "^1.0.1", - "repeat-string": "^1.5.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "alphanum-sort": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", - "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", - "dev": true - }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true - }, - "amqplib": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.5.2.tgz", - "integrity": "sha1-0tcxPH/6pNELzx5iUt5FkbbMe2M=", - "dev": true, - "optional": true, - "requires": { - "bitsyntax": "~0.0.4", - "bluebird": "^3.4.6", - "buffer-more-ints": "0.0.2", - "readable-stream": "1.x >=1.1.9", - "safe-buffer": "^5.0.1" - } - }, - "angular": { - "version": "1.3.20", - "resolved": "http://registry.npmjs.org/angular/-/angular-1.3.20.tgz", - "integrity": "sha1-sjo9fF5/mffZW5tNSbmsNVJpuu4=", - "dev": true - }, - "angular-animate": { - "version": "1.3.20", - "resolved": "http://registry.npmjs.org/angular-animate/-/angular-animate-1.3.20.tgz", - "integrity": "sha1-0XB8cn+K0N8hxKLewgzX/ElFtSo=", - "dev": true - }, - "ansi-colors": { - "version": "1.1.0", - "resolved": "http://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true, - "requires": { - "ansi-wrap": "^0.1.0" - } - }, - "ansi-cyan": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-cyan/-/ansi-cyan-0.1.1.tgz", - "integrity": "sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM=", - "dev": true, - "requires": { - "ansi-wrap": "0.1.0" - } - }, - "ansi-escapes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", - "integrity": "sha1-9zIHu4EgfXX9bIPxJa8m7qN4yjA=", - "dev": true - }, - "ansi-gray": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", - "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "dev": true, - "requires": { - "ansi-wrap": "0.1.0" - } - }, - "ansi-red": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz", - "integrity": "sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw=", - "dev": true, - "requires": { - "ansi-wrap": "0.1.0" - } - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "ansi-wrap": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", - "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", - "dev": true - }, - "anymatch": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", - "integrity": "sha1-VT3Lj5HjyImEXf26NMd3IbkLnXo=", - "dev": true, - "requires": { - "micromatch": "^2.1.5", - "normalize-path": "^2.0.0" - }, - "dependencies": { - "arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true, - "requires": { - "arr-flatten": "^1.0.1" - } - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, - "braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true, - "requires": { - "expand-range": "^1.8.1", - "preserve": "^0.2.0", - "repeat-element": "^1.1.2" - } - }, - "expand-brackets": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "dev": true, - "requires": { - "is-posix-bracket": "^0.1.0" - } - }, - "extglob": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - }, - "micromatch": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true, - "requires": { - "arr-diff": "^2.0.0", - "array-unique": "^0.2.1", - "braces": "^1.8.2", - "expand-brackets": "^0.1.4", - "extglob": "^0.3.1", - "filename-regex": "^2.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.1", - "kind-of": "^3.0.2", - "normalize-path": "^2.0.1", - "object.omit": "^2.0.0", - "parse-glob": "^3.0.4", - "regex-cache": "^0.4.2" - } - } - } - }, - "archive-type": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/archive-type/-/archive-type-3.2.0.tgz", - "integrity": "sha1-nNnABpV+vpX62tW9YJiUKoE3N/Y=", - "dev": true, - "requires": { - "file-type": "^3.1.0" - }, - "dependencies": { - "file-type": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", - "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=", - "dev": true - } - } - }, - "archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha1-vNZ5HqWuCXJeF+WtmIE0zUCz2RE=", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=", - "dev": true - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true - }, - "array-differ": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", - "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", - "dev": true - }, - "array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", - "dev": true - }, - "array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", - "dev": true - }, - "array-slice": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha1-42jqFfibxwaff/uJrsOmx9SsItQ=", - "dev": true - }, - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, - "requires": { - "array-uniq": "^1.0.1" - } - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "arraybuffer.slice": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", - "integrity": "sha1-O7xCdd1YTMGxCAm4nU6LY6aednU=", - "dev": true - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true - }, - "asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", - "dev": true, - "optional": true - }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "dev": true, - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", - "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", - "dev": true - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true - }, - "ast-types": { - "version": "0.11.5", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.11.5.tgz", - "integrity": "sha1-mJCCXWYMA8KDOfMV6foKNg4x7Cg=", - "dev": true, - "optional": true - }, - "async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", - "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", - "dev": true, - "requires": { - "lodash": "^4.17.10" - } - }, - "async-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", - "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", - "dev": true - }, - "async-each-series": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/async-each-series/-/async-each-series-1.1.0.tgz", - "integrity": "sha1-9C/YFV048hpbjqB8KOBj7RcAsTg=", - "dev": true, - "optional": true - }, - "async-limiter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", - "integrity": "sha1-ePrtjD0HSrgfIrTphdeehzj3IPg=", - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true - }, - "autoprefixer": { - "version": "6.7.7", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-6.7.7.tgz", - "integrity": "sha1-Hb0cg1ZY41zj+ZhAmdsAWFx4IBQ=", - "dev": true, - "requires": { - "browserslist": "^1.7.6", - "caniuse-db": "^1.0.30000634", - "normalize-range": "^0.1.2", - "num2fraction": "^1.2.2", - "postcss": "^5.2.16", - "postcss-value-parser": "^3.2.3" - } - }, - "aws-sign2": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", - "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", - "dev": true - }, - "aws4": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", - "dev": true - }, - "axios": { - "version": "0.15.3", - "resolved": "http://registry.npmjs.org/axios/-/axios-0.15.3.tgz", - "integrity": "sha1-LJ1jiy4ZGgjqHWzJiOrda6W9wFM=", - "dev": true, - "optional": true, - "requires": { - "follow-redirects": "1.0.0" - }, - "dependencies": { - "follow-redirects": { - "version": "1.0.0", - "resolved": "http://registry.npmjs.org/follow-redirects/-/follow-redirects-1.0.0.tgz", - "integrity": "sha1-jjQpjL0uF28lTv/sdaHHjMhJ/Tc=", - "dev": true, - "optional": true, - "requires": { - "debug": "^2.2.0" - } - } - } - }, - "backo2": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", - "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=", - "dev": true - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha1-e95c7RRbbVUakNuH+DxVi060io8=", - "dev": true, - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "base64-arraybuffer": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", - "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", - "dev": true - }, - "base64-url": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/base64-url/-/base64-url-1.2.1.tgz", - "integrity": "sha1-GZ/WYXAqDnt9yubgaYuwicUvbXg=", - "dev": true - }, - "base64id": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", - "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=", - "dev": true - }, - "basic-auth": { - "version": "1.0.4", - "resolved": "http://registry.npmjs.org/basic-auth/-/basic-auth-1.0.4.tgz", - "integrity": "sha1-Awk1sB3nyblKgksp8/zLdQ06UpA=", - "dev": true - }, - "basic-auth-connect": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz", - "integrity": "sha1-/bC0OWLKe0BFanwrtI/hc9otISI=", - "dev": true - }, - "batch": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.5.3.tgz", - "integrity": "sha1-PzQU84AyF0O/wQQvmoP/HVgk1GQ=", - "dev": true - }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dev": true, - "optional": true, - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "beeper": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", - "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", - "dev": true - }, - "better-assert": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", - "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", - "dev": true, - "requires": { - "callsite": "1.0.0" - } - }, - "bin-build": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/bin-build/-/bin-build-2.2.0.tgz", - "integrity": "sha1-EfjdYfcP/Por3KpbRvXo/t1CIcw=", - "dev": true, - "optional": true, - "requires": { - "archive-type": "^3.0.1", - "decompress": "^3.0.0", - "download": "^4.1.2", - "exec-series": "^1.0.0", - "rimraf": "^2.2.6", - "tempfile": "^1.0.0", - "url-regex": "^3.0.0" - }, - "dependencies": { - "tempfile": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/tempfile/-/tempfile-1.1.1.tgz", - "integrity": "sha1-W8xOrsxKsscH2LwR2ZzMmiyyh/I=", - "dev": true, - "optional": true, - "requires": { - "os-tmpdir": "^1.0.0", - "uuid": "^2.0.1" - } - }, - "uuid": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", - "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=", - "dev": true, - "optional": true - } - } - }, - "bin-check": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/bin-check/-/bin-check-2.0.0.tgz", - "integrity": "sha1-hvjm9CU4k99g3DFpV/WvAqywWTA=", - "dev": true, - "optional": true, - "requires": { - "executable": "^1.0.0" - } - }, - "bin-version": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/bin-version/-/bin-version-1.0.4.tgz", - "integrity": "sha1-nrSY7m/Xb3q5p8FgQ2+JV5Q1144=", - "dev": true, - "optional": true, - "requires": { - "find-versions": "^1.0.0" - } - }, - "bin-version-check": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/bin-version-check/-/bin-version-check-2.1.0.tgz", - "integrity": "sha1-5OXfKQuQaffRETJAMe/BP90RpbA=", - "dev": true, - "optional": true, - "requires": { - "bin-version": "^1.0.0", - "minimist": "^1.1.0", - "semver": "^4.0.3", - "semver-truncate": "^1.0.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true, - "optional": true - } - } - }, - "bin-wrapper": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/bin-wrapper/-/bin-wrapper-3.0.2.tgz", - "integrity": "sha1-Z9MwYmLksaXy+I7iNGT2plVneus=", - "dev": true, - "optional": true, - "requires": { - "bin-check": "^2.0.0", - "bin-version-check": "^2.1.0", - "download": "^4.0.0", - "each-async": "^1.1.1", - "lazy-req": "^1.0.0", - "os-filter-obj": "^1.0.0" - } - }, - "binary-extensions": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.12.0.tgz", - "integrity": "sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg==", - "dev": true - }, - "bitsyntax": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/bitsyntax/-/bitsyntax-0.0.4.tgz", - "integrity": "sha1-6xDMb4K4xJDj6FaY8H6D1G4MuoI=", - "dev": true, - "optional": true, - "requires": { - "buffer-more-ints": "0.0.2" - } - }, - "bl": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", - "integrity": "sha1-oWCRFxcQPAdBDO9j71Gzl8Alr5w=", - "dev": true, - "requires": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "blob": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz", - "integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE=", - "dev": true - }, - "bluebird": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.2.tgz", - "integrity": "sha512-dhHTWMI7kMx5whMQntl7Vr9C6BvV10lFXDAasnqnrMYhXVCzzk6IO9Fo2L75jXHT07WrOngL1WDXOp+yYS91Yg==", - "dev": true - }, - "body-parser": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.13.3.tgz", - "integrity": "sha1-wIzzMMM1jhUQFqBXRvE/ApyX+pc=", - "dev": true, - "requires": { - "bytes": "2.1.0", - "content-type": "~1.0.1", - "debug": "~2.2.0", - "depd": "~1.0.1", - "http-errors": "~1.3.1", - "iconv-lite": "0.4.11", - "on-finished": "~2.3.0", - "qs": "4.0.0", - "raw-body": "~2.1.2", - "type-is": "~1.6.6" - }, - "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "http://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "0.7.1" - } - }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - } - } - }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", - "dev": true - }, - "boom": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", - "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", - "dev": true, - "requires": { - "hoek": "2.x.x" - } - }, - "bower": { - "version": "1.8.4", - "resolved": "https://registry.npmjs.org/bower/-/bower-1.8.4.tgz", - "integrity": "sha1-54dqB23rgTf30GUl3F6MZtuC8oo=", - "dev": true - }, - "bower-installer": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/bower-installer/-/bower-installer-1.3.6.tgz", - "integrity": "sha1-z3g5tlQh0rJwqyLHT8hYpV46E3A=", - "dev": true, - "requires": { - "async": "^2.1.4", - "bower": "^1.8.0", - "colors": "^1.1.2", - "glob": "^7.1.1", - "lodash": "^4.17.2", - "mkdirp": "^0.5.1", - "node-fs": "~0.1.7", - "nopt": "^3.0.6" - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha1-WXn9PxTNUxVl5fot8av/8d+u5yk=", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "browserslist": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", - "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", - "dev": true, - "requires": { - "caniuse-db": "^1.0.30000639", - "electron-to-chromium": "^1.2.7" - } - }, - "buffer-alloc": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", - "integrity": "sha1-iQ3ZDZI6hz4I4Q5f1RpX5bfM4Ow=", - "dev": true, - "requires": { - "buffer-alloc-unsafe": "^1.1.0", - "buffer-fill": "^1.0.0" - } - }, - "buffer-alloc-unsafe": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", - "integrity": "sha1-vX3CauKXLQ7aJTvgYdupkjScGfA=", - "dev": true - }, - "buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", - "dev": true - }, - "buffer-fill": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", - "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", - "dev": true - }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "buffer-more-ints": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-0.0.2.tgz", - "integrity": "sha1-JrOIXRD6E9t/wBquOquHAZngEkw=", - "dev": true - }, - "buffer-to-vinyl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-to-vinyl/-/buffer-to-vinyl-1.1.0.tgz", - "integrity": "sha1-APFfruOreh3aLN5tkSG//dB7ImI=", - "dev": true, - "requires": { - "file-type": "^3.1.0", - "readable-stream": "^2.0.2", - "uuid": "^2.0.1", - "vinyl": "^1.0.0" - }, - "dependencies": { - "file-type": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", - "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "uuid": { - "version": "2.0.3", - "resolved": "http://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", - "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=", - "dev": true - }, - "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, - "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", - "replace-ext": "0.0.1" - } - } - } - }, - "bufferstreams": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/bufferstreams/-/bufferstreams-1.0.1.tgz", - "integrity": "sha1-z7GtlWjTujz+k1upq92VLeiKqyo=", - "dev": true, - "requires": { - "readable-stream": "^1.0.33" - } - }, - "buildmail": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/buildmail/-/buildmail-4.0.1.tgz", - "integrity": "sha1-h393OLeHKYccmhBeO4N9K+EaenI=", - "dev": true, - "optional": true, - "requires": { - "addressparser": "1.0.1", - "libbase64": "0.1.0", - "libmime": "3.0.0", - "libqp": "1.1.0", - "nodemailer-fetch": "1.6.0", - "nodemailer-shared": "1.1.0", - "punycode": "1.4.1" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true, - "optional": true - } - } - }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true - }, - "bytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz", - "integrity": "sha1-rJPEEOL/ycx89LRks4KJBn9eR7Q=", - "dev": true - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha1-Cn9GQWgxyLZi7jb+TnxZ129marI=", - "dev": true, - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - } - }, - "caller-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", - "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", - "dev": true, - "requires": { - "callsites": "^0.2.0" - } - }, - "callsite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", - "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", - "dev": true - }, - "callsites": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", - "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", - "dev": true - }, - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "dev": true - }, - "camelcase-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", - "dev": true, - "requires": { - "camelcase": "^2.0.0", - "map-obj": "^1.0.0" - } - }, - "caniuse-api": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.6.1.tgz", - "integrity": "sha1-tTTnxzTE+B7F++isoq0kNUuWLGw=", - "dev": true, - "requires": { - "browserslist": "^1.3.6", - "caniuse-db": "^1.0.30000529", - "lodash.memoize": "^4.1.2", - "lodash.uniq": "^4.5.0" - } - }, - "caniuse-db": { - "version": "1.0.30000889", - "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000889.tgz", - "integrity": "sha512-Rf9Sbm2KS7s6Rk8iNeI5zJdquqctXBXAfy/bb1tCCYRds5RAaHNdyt2D4z8TSRToDkYsAwiSBV/bFHR+4IgTiw==", - "dev": true - }, - "caniuse-lite": { - "version": "1.0.30000889", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000889.tgz", - "integrity": "sha512-MFxcQ6x/LEEoaIhO7Zdb7Eg8YyNONN+WBnS5ERJ0li2yRw51+i4xXUNxnLaveTb/4ZoJqsWKEmlomhG2pYzlQA==", - "dev": true - }, - "canonical-path": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/canonical-path/-/canonical-path-0.0.2.tgz", - "integrity": "sha1-4x65N6jJPuKgHfGDl5RyGQKHRXQ=", - "dev": true - }, - "capture-stack-trace": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz", - "integrity": "sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw==", - "dev": true - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, - "caw": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/caw/-/caw-1.2.0.tgz", - "integrity": "sha1-/7Im/n78VHKI3GLuPpcHPCEtEDQ=", - "dev": true, - "requires": { - "get-proxy": "^1.0.1", - "is-obj": "^1.0.0", - "object-assign": "^3.0.0", - "tunnel-agent": "^0.4.0" - }, - "dependencies": { - "object-assign": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", - "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", - "dev": true - } - } - }, - "center-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", - "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "dev": true, - "requires": { - "align-text": "^0.1.3", - "lazy-cache": "^1.0.3" - } - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true - }, - "chokidar": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", - "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", - "dev": true, - "requires": { - "anymatch": "^1.3.0", - "async-each": "^1.0.0", - "fsevents": "^1.0.0", - "glob-parent": "^2.0.0", - "inherits": "^2.0.1", - "is-binary-path": "^1.0.0", - "is-glob": "^2.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0" - }, - "dependencies": { - "glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true, - "requires": { - "is-glob": "^2.0.0" - } - }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - } - } - }, - "circular-json": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", - "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", - "dev": true - }, - "clap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/clap/-/clap-1.2.3.tgz", - "integrity": "sha1-TzZ0WzIAhJJVf0ZBLWbVDLmbzlE=", - "dev": true, - "requires": { - "chalk": "^1.1.3" - } - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha1-+TNprouafOAv1B+q0MqDAzGQxGM=", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "dev": true, - "requires": { - "restore-cursor": "^2.0.0" - } - }, - "cli-width": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", - "dev": true - }, - "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "dev": true, - "requires": { - "center-align": "^0.1.1", - "right-align": "^0.1.1", - "wordwrap": "0.0.2" - }, - "dependencies": { - "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "dev": true - } - } - }, - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true - }, - "clone-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", - "dev": true - }, - "clone-stats": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", - "dev": true - }, - "cloneable-readable": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.2.tgz", - "integrity": "sha1-1ZHe5Kj4vBXaQ86X3O66E9Q+KmU=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "process-nextick-args": "^2.0.0", - "readable-stream": "^2.3.5" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "co": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/co/-/co-3.1.0.tgz", - "integrity": "sha1-TqVOpaCJOBUxheFSEMaNkJK8G3g=", - "dev": true - }, - "coa": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/coa/-/coa-1.0.4.tgz", - "integrity": "sha1-qe8VNmDWqGqL3sAomlxoTSF0Mv0=", - "dev": true, - "requires": { - "q": "^1.1.2" - } - }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } - }, - "color": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/color/-/color-0.11.4.tgz", - "integrity": "sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q=", - "dev": true, - "requires": { - "clone": "^1.0.2", - "color-convert": "^1.3.0", - "color-string": "^0.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "color-string": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-0.3.0.tgz", - "integrity": "sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE=", - "dev": true, - "requires": { - "color-name": "^1.0.0" - } - }, - "color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha1-k4NDeaHMmgxh+C9S8NBDIiUb1aI=", - "dev": true - }, - "colormin": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colormin/-/colormin-1.1.2.tgz", - "integrity": "sha1-6i90IKcrlogaOKrlnsEkpvcpgTM=", - "dev": true, - "requires": { - "color": "^0.11.0", - "css-color-names": "0.0.4", - "has": "^1.0.1" - } - }, - "colors": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.2.tgz", - "integrity": "sha512-rhP0JSBGYvpcNQj4s5AdShMeE5ahMop96cTeDl/v9qQQm2fYClE2QXZRi8wLzc+GmXSxdIqqbOIAhyObEXDbfQ==", - "dev": true - }, - "combine-lists": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/combine-lists/-/combine-lists-1.0.1.tgz", - "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=", - "dev": true, - "requires": { - "lodash": "^4.5.0" - } - }, - "combined-stream": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", - "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", - "dev": true, - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "commander": { - "version": "2.8.1", - "resolved": "http://registry.npmjs.org/commander/-/commander-2.8.1.tgz", - "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", - "dev": true, - "requires": { - "graceful-readlink": ">= 1.0.0" - } - }, - "component-bind": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", - "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=", - "dev": true - }, - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", - "dev": true - }, - "component-inherit": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", - "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=", - "dev": true - }, - "compressible": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.15.tgz", - "integrity": "sha512-4aE67DL33dSW9gw4CI2H/yTxqHLNcxp0yS6jB+4h+wr3e43+1z7vm0HU9qXOH8j+qjKuL8+UtkOxYQSMq60Ylw==", - "dev": true, - "requires": { - "mime-db": ">= 1.36.0 < 2" - } - }, - "compression": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.5.2.tgz", - "integrity": "sha1-sDuNhub4rSloPLqN+R3cb/x3s5U=", - "dev": true, - "requires": { - "accepts": "~1.2.12", - "bytes": "2.1.0", - "compressible": "~2.0.5", - "debug": "~2.2.0", - "on-headers": "~1.0.0", - "vary": "~1.0.1" - }, - "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "http://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "0.7.1" - } - }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - } - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "concat-with-sourcemaps": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz", - "integrity": "sha1-1OqT8FriV5CVG5nns7CeOQikCC4=", - "dev": true, - "requires": { - "source-map": "^0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", - "dev": true - } - } - }, - "connect": { - "version": "2.30.2", - "resolved": "https://registry.npmjs.org/connect/-/connect-2.30.2.tgz", - "integrity": "sha1-jam8vooFTT0xjXTf7JA7XDmhtgk=", - "dev": true, - "requires": { - "basic-auth-connect": "1.0.0", - "body-parser": "~1.13.3", - "bytes": "2.1.0", - "compression": "~1.5.2", - "connect-timeout": "~1.6.2", - "content-type": "~1.0.1", - "cookie": "0.1.3", - "cookie-parser": "~1.3.5", - "cookie-signature": "1.0.6", - "csurf": "~1.8.3", - "debug": "~2.2.0", - "depd": "~1.0.1", - "errorhandler": "~1.4.2", - "express-session": "~1.11.3", - "finalhandler": "0.4.0", - "fresh": "0.3.0", - "http-errors": "~1.3.1", - "method-override": "~2.3.5", - "morgan": "~1.6.1", - "multiparty": "3.3.2", - "on-headers": "~1.0.0", - "parseurl": "~1.3.0", - "pause": "0.1.0", - "qs": "4.0.0", - "response-time": "~2.3.1", - "serve-favicon": "~2.3.0", - "serve-index": "~1.7.2", - "serve-static": "~1.10.0", - "type-is": "~1.6.6", - "utils-merge": "1.0.0", - "vhost": "~3.0.1" - }, - "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "http://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "0.7.1" - } - }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - } - } - }, - "connect-livereload": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/connect-livereload/-/connect-livereload-0.5.4.tgz", - "integrity": "sha1-gBV9E3HJ83zBQDmrGJWXDRGdw7w=", - "dev": true - }, - "connect-timeout": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/connect-timeout/-/connect-timeout-1.6.2.tgz", - "integrity": "sha1-3ppexh4zoStu2qt7XwYumMWZuI4=", - "dev": true, - "requires": { - "debug": "~2.2.0", - "http-errors": "~1.3.1", - "ms": "0.7.1", - "on-headers": "~1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "http://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "0.7.1" - } - }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - } - } - }, - "console-stream": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/console-stream/-/console-stream-0.1.1.tgz", - "integrity": "sha1-oJX+B7IEZZVfL6/Si11yvM2UnUQ=", - "dev": true, - "optional": true - }, - "consolidate": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.14.5.tgz", - "integrity": "sha1-WiUEe8dvcwcmZ8jLUsmJiI9JTGM=", - "dev": true, - "requires": { - "bluebird": "^3.1.1" - } - }, - "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js=", - "dev": true - }, - "convert-source-map": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", - "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } - }, - "cookie": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.3.tgz", - "integrity": "sha1-5zSlwUF/zkctWu+Cw4HKu2TRpDU=", - "dev": true - }, - "cookie-parser": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.3.5.tgz", - "integrity": "sha1-nXVVcPtdF4kHcSJ6AjFNm+fPg1Y=", - "dev": true, - "requires": { - "cookie": "0.1.3", - "cookie-signature": "1.0.6" - } - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", - "dev": true - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true - }, - "core-js": { - "version": "2.5.7", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", - "integrity": "sha1-+XJgj/DOrWi4QaFqky0LGDeRgU4=", - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "cosmiconfig": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-2.2.2.tgz", - "integrity": "sha1-YXPOvVb6wELB9DkO33r2wHx8uJI=", - "dev": true, - "requires": { - "is-directory": "^0.3.1", - "js-yaml": "^3.4.3", - "minimist": "^1.2.0", - "object-assign": "^4.1.0", - "os-homedir": "^1.0.1", - "parse-json": "^2.2.0", - "require-from-string": "^1.1.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, - "crc": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/crc/-/crc-3.3.0.tgz", - "integrity": "sha1-+mIuG8OIvyVzCQgta2UgDOZwkLo=", - "dev": true - }, - "create-error-class": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", - "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", - "dev": true, - "requires": { - "capture-stack-trace": "^1.0.0" - } - }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "dependencies": { - "semver": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", - "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==", - "dev": true - } - } - }, - "cryptiles": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", - "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", - "dev": true, - "requires": { - "boom": "2.x.x" - } - }, - "csrf": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/csrf/-/csrf-3.0.6.tgz", - "integrity": "sha1-thEg3c7q/JHnbtUxO7XAsmZ7cQo=", - "dev": true, - "requires": { - "rndm": "1.2.0", - "tsscmp": "1.0.5", - "uid-safe": "2.1.4" - } - }, - "css-color-names": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", - "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=", - "dev": true - }, - "css-select": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.0.0.tgz", - "integrity": "sha512-MGhoq1S9EyPgZIGnts8Yz5WwUOyHmPMdlqeifsYs/xFX7AAm3hY0RJe1dqVlXtYPI66Nsk39R/sa5/ree6L2qg==", - "dev": true, - "optional": true, - "requires": { - "boolbase": "^1.0.0", - "css-what": "2.1", - "domutils": "^1.7.0", - "nth-check": "^1.0.1" - } - }, - "css-select-base-adapter": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.0.tgz", - "integrity": "sha1-AQKz0UYw34bD65+p9UVicBBs+ZA=", - "dev": true, - "optional": true - }, - "css-tree": { - "version": "1.0.0-alpha.28", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.28.tgz", - "integrity": "sha512-joNNW1gCp3qFFzj4St6zk+Wh/NBv0vM5YbEreZk0SD4S23S+1xBKb6cLDg2uj4P4k/GUMlIm6cKIDqIG+vdt0w==", - "dev": true, - "optional": true, - "requires": { - "mdn-data": "~1.1.0", - "source-map": "^0.5.3" - } - }, - "css-url-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/css-url-regex/-/css-url-regex-1.1.0.tgz", - "integrity": "sha1-g4NCMMyfdMRX3lnuvRVD/uuDt+w=", - "dev": true, - "optional": true - }, - "css-what": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.0.tgz", - "integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0=", - "dev": true, - "optional": true - }, - "cssnano": { - "version": "3.10.0", - "resolved": "http://registry.npmjs.org/cssnano/-/cssnano-3.10.0.tgz", - "integrity": "sha1-Tzj2zqK5sX+gFJDyPx3GjqZcHDg=", - "dev": true, - "requires": { - "autoprefixer": "^6.3.1", - "decamelize": "^1.1.2", - "defined": "^1.0.0", - "has": "^1.0.1", - "object-assign": "^4.0.1", - "postcss": "^5.0.14", - "postcss-calc": "^5.2.0", - "postcss-colormin": "^2.1.8", - "postcss-convert-values": "^2.3.4", - "postcss-discard-comments": "^2.0.4", - "postcss-discard-duplicates": "^2.0.1", - "postcss-discard-empty": "^2.0.1", - "postcss-discard-overridden": "^0.1.1", - "postcss-discard-unused": "^2.2.1", - "postcss-filter-plugins": "^2.0.0", - "postcss-merge-idents": "^2.1.5", - "postcss-merge-longhand": "^2.0.1", - "postcss-merge-rules": "^2.0.3", - "postcss-minify-font-values": "^1.0.2", - "postcss-minify-gradients": "^1.0.1", - "postcss-minify-params": "^1.0.4", - "postcss-minify-selectors": "^2.0.4", - "postcss-normalize-charset": "^1.1.0", - "postcss-normalize-url": "^3.0.7", - "postcss-ordered-values": "^2.1.0", - "postcss-reduce-idents": "^2.2.2", - "postcss-reduce-initial": "^1.0.0", - "postcss-reduce-transforms": "^1.0.3", - "postcss-svgo": "^2.1.1", - "postcss-unique-selectors": "^2.0.2", - "postcss-value-parser": "^3.2.3", - "postcss-zindex": "^2.0.1" - } - }, - "csso": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/csso/-/csso-2.3.2.tgz", - "integrity": "sha1-3dUsWHAz9J6Utx/FVWnyUuj/X4U=", - "dev": true, - "requires": { - "clap": "^1.0.9", - "source-map": "^0.5.3" - } - }, - "csurf": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/csurf/-/csurf-1.8.3.tgz", - "integrity": "sha1-I/KhO/HY/OHQyZZYg5RELLqGpWo=", - "dev": true, - "requires": { - "cookie": "0.1.3", - "cookie-signature": "1.0.6", - "csrf": "~3.0.0", - "http-errors": "~1.3.1" - } - }, - "currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "dev": true, - "requires": { - "array-find-index": "^1.0.1" - } - }, - "custom-event": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", - "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", - "dev": true - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } - } - }, - "data-uri-to-buffer": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz", - "integrity": "sha1-dxY+qcINhkG0cH6PGKvfmnjzSDU=", - "dev": true, - "optional": true - }, - "date-format": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz", - "integrity": "sha1-YV6CjiM90aubua4JUODOzPpuytg=", - "dev": true - }, - "dateformat": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", - "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", - "dev": true - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true - }, - "decompress": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/decompress/-/decompress-3.0.0.tgz", - "integrity": "sha1-rx3VDQbjv8QyRh033hGzjA2ZG+0=", - "dev": true, - "requires": { - "buffer-to-vinyl": "^1.0.0", - "concat-stream": "^1.4.6", - "decompress-tar": "^3.0.0", - "decompress-tarbz2": "^3.0.0", - "decompress-targz": "^3.0.0", - "decompress-unzip": "^3.0.0", - "stream-combiner2": "^1.1.1", - "vinyl-assign": "^1.0.1", - "vinyl-fs": "^2.2.0" - }, - "dependencies": { - "arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true, - "requires": { - "arr-flatten": "^1.0.1" - } - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, - "braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true, - "requires": { - "expand-range": "^1.8.1", - "preserve": "^0.2.0", - "repeat-element": "^1.1.2" - } - }, - "expand-brackets": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "dev": true, - "requires": { - "is-posix-bracket": "^0.1.0" - } - }, - "extglob": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - }, - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-stream": { - "version": "5.3.5", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz", - "integrity": "sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=", - "dev": true, - "requires": { - "extend": "^3.0.0", - "glob": "^5.0.3", - "glob-parent": "^3.0.0", - "micromatch": "^2.3.7", - "ordered-read-streams": "^0.3.0", - "through2": "^0.6.0", - "to-absolute-glob": "^0.1.1", - "unique-stream": "^2.0.2" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" - } - } - } - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - }, - "micromatch": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true, - "requires": { - "arr-diff": "^2.0.0", - "array-unique": "^0.2.1", - "braces": "^1.8.2", - "expand-brackets": "^0.1.4", - "extglob": "^0.3.1", - "filename-regex": "^2.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.1", - "kind-of": "^3.0.2", - "normalize-path": "^2.0.1", - "object.omit": "^2.0.0", - "parse-glob": "^3.0.4", - "regex-cache": "^0.4.2" - } - }, - "ordered-read-streams": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", - "integrity": "sha1-cTfmmzKYuzQiR6G77jiByA4v14s=", - "dev": true, - "requires": { - "is-stream": "^1.0.1", - "readable-stream": "^2.0.1" - } - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } - }, - "unique-stream": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", - "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", - "dev": true, - "requires": { - "json-stable-stringify": "^1.0.0", - "through2-filter": "^2.0.0" - } - }, - "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, - "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", - "replace-ext": "0.0.1" - } - }, - "vinyl-fs": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz", - "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=", - "dev": true, - "requires": { - "duplexify": "^3.2.0", - "glob-stream": "^5.3.2", - "graceful-fs": "^4.0.0", - "gulp-sourcemaps": "1.6.0", - "is-valid-glob": "^0.3.0", - "lazystream": "^1.0.0", - "lodash.isequal": "^4.0.0", - "merge-stream": "^1.0.0", - "mkdirp": "^0.5.0", - "object-assign": "^4.0.0", - "readable-stream": "^2.0.4", - "strip-bom": "^2.0.0", - "strip-bom-stream": "^1.0.0", - "through2": "^2.0.0", - "through2-filter": "^2.0.0", - "vali-date": "^1.0.0", - "vinyl": "^1.0.0" - } - } - } - }, - "decompress-tar": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-3.1.0.tgz", - "integrity": "sha1-IXx4n5uURQ76rcXF5TeXj8MzxGY=", - "dev": true, - "requires": { - "is-tar": "^1.0.0", - "object-assign": "^2.0.0", - "strip-dirs": "^1.0.0", - "tar-stream": "^1.1.1", - "through2": "^0.6.1", - "vinyl": "^0.4.3" - }, - "dependencies": { - "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", - "dev": true - }, - "object-assign": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz", - "integrity": "sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" - } - }, - "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "dev": true, - "requires": { - "clone": "^0.2.0", - "clone-stats": "^0.0.1" - } - } - } - }, - "decompress-tarbz2": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-3.1.0.tgz", - "integrity": "sha1-iyOTVoE1X58YnYclag+L3ZbZZm0=", - "dev": true, - "requires": { - "is-bzip2": "^1.0.0", - "object-assign": "^2.0.0", - "seek-bzip": "^1.0.3", - "strip-dirs": "^1.0.0", - "tar-stream": "^1.1.1", - "through2": "^0.6.1", - "vinyl": "^0.4.3" - }, - "dependencies": { - "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", - "dev": true - }, - "object-assign": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz", - "integrity": "sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" - } - }, - "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "dev": true, - "requires": { - "clone": "^0.2.0", - "clone-stats": "^0.0.1" - } - } - } - }, - "decompress-targz": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-3.1.0.tgz", - "integrity": "sha1-ssE9+YFmJomRtxXWRH9kLpaW9aA=", - "dev": true, - "requires": { - "is-gzip": "^1.0.0", - "object-assign": "^2.0.0", - "strip-dirs": "^1.0.0", - "tar-stream": "^1.1.1", - "through2": "^0.6.1", - "vinyl": "^0.4.3" - }, - "dependencies": { - "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", - "dev": true - }, - "object-assign": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz", - "integrity": "sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" - } - }, - "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "dev": true, - "requires": { - "clone": "^0.2.0", - "clone-stats": "^0.0.1" - } - } - } - }, - "decompress-unzip": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-3.4.0.tgz", - "integrity": "sha1-YUdbQVIGa74/7hL51inRX+ZHjus=", - "dev": true, - "requires": { - "is-zip": "^1.0.0", - "read-all-stream": "^3.0.0", - "stat-mode": "^0.2.0", - "strip-dirs": "^1.0.0", - "through2": "^2.0.0", - "vinyl": "^1.0.0", - "yauzl": "^2.2.1" - }, - "dependencies": { - "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, - "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", - "replace-ext": "0.0.1" - } - } - } - }, - "deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha1-xPp8lUBKF6nD6Mp+FTcxK3NjMKw=", - "dev": true - }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "dev": true, - "requires": { - "clone": "^1.0.2" - } - }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "requires": { - "object-keys": "^1.0.12" - } - }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha1-1Flono1lS6d+AqgX+HENcCyxbp0=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "defined": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", - "dev": true - }, - "degenerator": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-1.0.4.tgz", - "integrity": "sha1-/PSQo37OJmRk2cxDGrmMWBnO0JU=", - "dev": true, - "optional": true, - "requires": { - "ast-types": "0.x.x", - "escodegen": "1.x.x", - "esprima": "3.x.x" - }, - "dependencies": { - "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", - "dev": true, - "optional": true - } - } - }, - "del": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", - "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", - "dev": true, - "requires": { - "globby": "^5.0.0", - "is-path-cwd": "^1.0.0", - "is-path-in-cwd": "^1.0.0", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "rimraf": "^2.2.8" - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true - }, - "depd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.0.1.tgz", - "integrity": "sha1-gK7GTJ1tl+ZcwqnKqTwKpqv3Oqo=", - "dev": true - }, - "deprecated": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", - "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=", - "dev": true - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", - "dev": true - }, - "detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", - "dev": true - }, - "di": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", - "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", - "dev": true - }, - "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha1-XNAfwQFiG0LEzX9dGmYkNxbT850=", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "dom-serialize": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", - "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", - "dev": true, - "requires": { - "custom-event": "~1.0.0", - "ent": "~2.2.0", - "extend": "^3.0.0", - "void-elements": "^2.0.0" - } - }, - "dom-serializer": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", - "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", - "dev": true, - "optional": true, - "requires": { - "domelementtype": "~1.1.1", - "entities": "~1.1.1" - }, - "dependencies": { - "domelementtype": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", - "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", - "dev": true, - "optional": true - } - } - }, - "domelementtype": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", - "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=", - "dev": true, - "optional": true - }, - "domutils": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", - "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", - "dev": true, - "optional": true, - "requires": { - "dom-serializer": "0", - "domelementtype": "1" - } - }, - "double-ended-queue": { - "version": "2.1.0-0", - "resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz", - "integrity": "sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw=", - "dev": true, - "optional": true - }, - "download": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/download/-/download-4.4.3.tgz", - "integrity": "sha1-qlX9rTktldS2jowr4D4MKqIbqaw=", - "dev": true, - "requires": { - "caw": "^1.0.1", - "concat-stream": "^1.4.7", - "each-async": "^1.0.0", - "filenamify": "^1.0.1", - "got": "^5.0.0", - "gulp-decompress": "^1.2.0", - "gulp-rename": "^1.2.0", - "is-url": "^1.2.0", - "object-assign": "^4.0.1", - "read-all-stream": "^3.0.0", - "readable-stream": "^2.0.2", - "stream-combiner2": "^1.1.1", - "vinyl": "^1.0.0", - "vinyl-fs": "^2.2.0", - "ware": "^1.2.0" - }, - "dependencies": { - "arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true, - "requires": { - "arr-flatten": "^1.0.1" - } - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, - "braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true, - "requires": { - "expand-range": "^1.8.1", - "preserve": "^0.2.0", - "repeat-element": "^1.1.2" - } - }, - "expand-brackets": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "dev": true, - "requires": { - "is-posix-bracket": "^0.1.0" - } - }, - "extglob": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - }, - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-stream": { - "version": "5.3.5", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz", - "integrity": "sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=", - "dev": true, - "requires": { - "extend": "^3.0.0", - "glob": "^5.0.3", - "glob-parent": "^3.0.0", - "micromatch": "^2.3.7", - "ordered-read-streams": "^0.3.0", - "through2": "^0.6.0", - "to-absolute-glob": "^0.1.1", - "unique-stream": "^2.0.2" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" - } - } - } - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - }, - "micromatch": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true, - "requires": { - "arr-diff": "^2.0.0", - "array-unique": "^0.2.1", - "braces": "^1.8.2", - "expand-brackets": "^0.1.4", - "extglob": "^0.3.1", - "filename-regex": "^2.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.1", - "kind-of": "^3.0.2", - "normalize-path": "^2.0.1", - "object.omit": "^2.0.0", - "parse-glob": "^3.0.4", - "regex-cache": "^0.4.2" - } - }, - "ordered-read-streams": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", - "integrity": "sha1-cTfmmzKYuzQiR6G77jiByA4v14s=", - "dev": true, - "requires": { - "is-stream": "^1.0.1", - "readable-stream": "^2.0.1" - } - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } - }, - "unique-stream": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", - "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", - "dev": true, - "requires": { - "json-stable-stringify": "^1.0.0", - "through2-filter": "^2.0.0" - } - }, - "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, - "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", - "replace-ext": "0.0.1" - } - }, - "vinyl-fs": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz", - "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=", - "dev": true, - "requires": { - "duplexify": "^3.2.0", - "glob-stream": "^5.3.2", - "graceful-fs": "^4.0.0", - "gulp-sourcemaps": "1.6.0", - "is-valid-glob": "^0.3.0", - "lazystream": "^1.0.0", - "lodash.isequal": "^4.0.0", - "merge-stream": "^1.0.0", - "mkdirp": "^0.5.0", - "object-assign": "^4.0.0", - "readable-stream": "^2.0.4", - "strip-bom": "^2.0.0", - "strip-bom-stream": "^1.0.0", - "through2": "^2.0.0", - "through2-filter": "^2.0.0", - "vali-date": "^1.0.0", - "vinyl": "^1.0.0" - } - } - } - }, - "duplexer": { - "version": "0.1.1", - "resolved": "http://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", - "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", - "dev": true - }, - "duplexer2": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", - "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", - "dev": true, - "requires": { - "readable-stream": "~1.1.9" - } - }, - "duplexify": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.0.tgz", - "integrity": "sha1-WSkD9dgLONA3IgVBJk1poZj7NBA=", - "dev": true, - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - }, - "dependencies": { - "end-of-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha1-7SljTRm6ukY7bOa4CjchPqtx7EM=", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "each-async": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/each-async/-/each-async-1.1.1.tgz", - "integrity": "sha1-3uUim98KtrogEqOV4bhpq/iBNHM=", - "dev": true, - "requires": { - "onetime": "^1.0.0", - "set-immediate-shim": "^1.0.0" - }, - "dependencies": { - "onetime": { - "version": "1.1.0", - "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", - "dev": true - } - } - }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dev": true, - "optional": true, - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", - "dev": true - }, - "electron-to-chromium": { - "version": "1.3.73", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.73.tgz", - "integrity": "sha512-6PIg7v9zRoVGh6EheRF8h6Plti+3Yo/qtHobS4/Htyt53DNHmKKGFqSae1AIk0k1S4gCQvt7I2WgpbuZNcDY+g==", - "dev": true - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "dev": true - }, - "end-of-stream": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", - "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", - "dev": true, - "requires": { - "once": "~1.3.0" - }, - "dependencies": { - "once": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", - "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", - "dev": true, - "requires": { - "wrappy": "1" - } - } - } - }, - "engine.io": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.1.5.tgz", - "integrity": "sha1-Dn751pDrCzVZfx1K0Comyi26OEU=", - "dev": true, - "requires": { - "accepts": "~1.3.4", - "base64id": "1.0.0", - "cookie": "0.3.1", - "debug": "~3.1.0", - "engine.io-parser": "~2.1.0", - "uws": "~9.14.0", - "ws": "~3.3.1" - }, - "dependencies": { - "accepts": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", - "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", - "dev": true, - "requires": { - "mime-types": "~2.1.18", - "negotiator": "0.6.1" - } - }, - "cookie": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", - "dev": true - }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "negotiator": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", - "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", - "dev": true - } - } - }, - "engine.io-client": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.1.6.tgz", - "integrity": "sha1-W96xMPi5SlCsXL63JYPnpKBj3f0=", - "dev": true, - "requires": { - "component-emitter": "1.2.1", - "component-inherit": "0.0.3", - "debug": "~3.1.0", - "engine.io-parser": "~2.1.1", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "ws": "~3.3.1", - "xmlhttprequest-ssl": "~1.5.4", - "yeast": "0.1.2" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, - "engine.io-parser": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.2.tgz", - "integrity": "sha1-TA9M/3mq7su9z96maoI8YIVAkZY=", - "dev": true, - "requires": { - "after": "0.8.2", - "arraybuffer.slice": "~0.0.7", - "base64-arraybuffer": "0.1.5", - "blob": "0.0.4", - "has-binary2": "~1.0.2" - } - }, - "ent": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", - "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", - "dev": true - }, - "entities": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", - "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=", - "dev": true, - "optional": true - }, - "errno": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha1-RoTXF3mtOa8Xfj8AeZb3xnyFJhg=", - "dev": true, - "optional": true, - "requires": { - "prr": "~1.0.1" - } - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "errorhandler": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.4.3.tgz", - "integrity": "sha1-t7cO2PNZ6duICS8tIMD4MUIK2D8=", - "dev": true, - "requires": { - "accepts": "~1.3.0", - "escape-html": "~1.0.3" - }, - "dependencies": { - "accepts": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", - "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", - "dev": true, - "requires": { - "mime-types": "~2.1.18", - "negotiator": "0.6.1" - } - }, - "negotiator": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", - "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", - "dev": true - } - } - }, - "es-abstract": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz", - "integrity": "sha1-nbvdJ8aFbwABQhyhh4LXhr+KYWU=", - "dev": true, - "requires": { - "es-to-primitive": "^1.1.1", - "function-bind": "^1.1.1", - "has": "^1.0.1", - "is-callable": "^1.1.3", - "is-regex": "^1.0.4" - } - }, - "es-to-primitive": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", - "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "es6-promise": { - "version": "3.3.1", - "resolved": "http://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", - "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=", - "dev": true - }, - "es6-promisify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", - "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", - "dev": true, - "requires": { - "es6-promise": "^4.0.3" - }, - "dependencies": { - "es6-promise": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.5.tgz", - "integrity": "sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg==", - "dev": true - } - } - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "escodegen": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.0.tgz", - "integrity": "sha512-IeMV45ReixHS53K/OmfKAIztN/igDHzTJUhZM3k1jMhIZWjk45SMwAtBsEXiJp3vSPmTcu6CXn7mDvFHRN66fw==", - "dev": true, - "requires": { - "esprima": "^3.1.3", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" - }, - "dependencies": { - "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", - "dev": true, - "optional": true - } - } - }, - "eslint": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.6.1.tgz", - "integrity": "sha512-hgrDtGWz368b7Wqf+v1Z69O3ZebNR0+GA7PtDdbmuz4rInFVUV9uw7whjZEiWyLzCjVb5Rs5WRN1TAS6eo7AYA==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "ajv": "^6.5.3", - "chalk": "^2.1.0", - "cross-spawn": "^6.0.5", - "debug": "^4.0.1", - "doctrine": "^2.1.0", - "eslint-scope": "^4.0.0", - "eslint-utils": "^1.3.1", - "eslint-visitor-keys": "^1.0.0", - "espree": "^4.0.0", - "esquery": "^1.0.1", - "esutils": "^2.0.2", - "file-entry-cache": "^2.0.0", - "functional-red-black-tree": "^1.0.1", - "glob": "^7.1.2", - "globals": "^11.7.0", - "ignore": "^4.0.6", - "imurmurhash": "^0.1.4", - "inquirer": "^6.1.0", - "is-resolvable": "^1.1.0", - "js-yaml": "^3.12.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.3.0", - "lodash": "^4.17.5", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", - "natural-compare": "^1.4.0", - "optionator": "^0.8.2", - "path-is-inside": "^1.0.2", - "pluralize": "^7.0.0", - "progress": "^2.0.0", - "regexpp": "^2.0.0", - "require-uncached": "^1.0.3", - "semver": "^5.5.1", - "strip-ansi": "^4.0.0", - "strip-json-comments": "^2.0.1", - "table": "^4.0.3", - "text-table": "^0.2.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "debug": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.0.1.tgz", - "integrity": "sha512-K23FHJ/Mt404FSlp6gSZCevIbTMLX0j3fmHhUEhQ3Wq0FMODW3+cUSoLdy1Gx4polAf4t/lphhmHH35BB8cLYw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "js-yaml": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", - "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, - "semver": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", - "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==", - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "eslint-scope": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", - "integrity": "sha1-UL8wcekzi83EMzF5Sgy1M/ATYXI=", - "dev": true, - "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } - }, - "eslint-utils": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.3.1.tgz", - "integrity": "sha1-moUbqJ7nxGA0b5fPiTnHKYgn5RI=", - "dev": true - }, - "eslint-visitor-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", - "integrity": "sha1-PzGA+y4pEBdxastMnW1bXDSmqB0=", - "dev": true - }, - "espree": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-4.0.0.tgz", - "integrity": "sha1-JTmY8goPgttdhmOFeZ2RKoOjZjQ=", - "dev": true, - "requires": { - "acorn": "^5.6.0", - "acorn-jsx": "^4.1.1" - } - }, - "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true - }, - "esquery": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", - "integrity": "sha1-QGxRZYsfWZGl+bYrHcJbAOPlxwg=", - "dev": true, - "requires": { - "estraverse": "^4.0.0" - } - }, - "esrecurse": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", - "integrity": "sha1-AHo7n9vCs7uH5IeeoZyS/b05Qs8=", - "dev": true, - "requires": { - "estraverse": "^4.1.0" - } - }, - "estemplate": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/estemplate/-/estemplate-0.5.1.tgz", - "integrity": "sha1-FxSp1GGQc4rJWLyv1J4CnNpWo54=", - "dev": true, - "requires": { - "esprima": "^2.7.2", - "estraverse": "^4.1.1" - } - }, - "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true - }, - "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", - "dev": true - }, - "etag": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz", - "integrity": "sha1-A9MLX2fdbmMtKUXTDWZScxo01dg=", - "dev": true - }, - "event-stream": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.6.tgz", - "integrity": "sha512-dGXNg4F/FgVzlApjzItL+7naHutA3fDqbV/zAZqDDlXTjiMnQmZKu+prImWKszeBM5UQeGvAl3u1wBiKeDh61g==", - "dev": true, - "requires": { - "duplexer": "^0.1.1", - "flatmap-stream": "^0.1.0", - "from": "^0.1.7", - "map-stream": "0.0.7", - "pause-stream": "^0.0.11", - "split": "^1.0.1", - "stream-combiner": "^0.2.2", - "through": "^2.3.8" - } - }, - "eventemitter3": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz", - "integrity": "sha1-CQtNbNvWRe0Qv3UNS1QHlC17oWM=", - "dev": true - }, - "exec-buffer": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/exec-buffer/-/exec-buffer-3.2.0.tgz", - "integrity": "sha1-sWhtvZBMfPmC5lLB9aebHlVzCCs=", - "dev": true, - "optional": true, - "requires": { - "execa": "^0.7.0", - "p-finally": "^1.0.0", - "pify": "^3.0.0", - "rimraf": "^2.5.4", - "tempfile": "^2.0.0" - }, - "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true, - "optional": true - } - } - }, - "exec-series": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/exec-series/-/exec-series-1.0.3.tgz", - "integrity": "sha1-bSV6m+rEgqhyx3g7yGFYOfx3FDo=", - "dev": true, - "optional": true, - "requires": { - "async-each-series": "^1.1.0", - "object-assign": "^4.1.0" - } - }, - "execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "dev": true, - "optional": true, - "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "dependencies": { - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "optional": true, - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "lru-cache": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", - "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", - "dev": true, - "optional": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - } - } - }, - "executable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/executable/-/executable-1.1.0.tgz", - "integrity": "sha1-h3mA6REvM5EGbaNyZd562ENKtNk=", - "dev": true, - "optional": true, - "requires": { - "meow": "^3.1.0" - } - }, - "expand-braces": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz", - "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=", - "dev": true, - "requires": { - "array-slice": "^0.2.3", - "array-unique": "^0.2.1", - "braces": "^0.1.2" - }, - "dependencies": { - "array-slice": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", - "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", - "dev": true - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, - "braces": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz", - "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=", - "dev": true, - "requires": { - "expand-range": "^0.1.0" - } - }, - "expand-range": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz", - "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=", - "dev": true, - "requires": { - "is-number": "^0.1.1", - "repeat-string": "^0.2.2" - } - }, - "is-number": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz", - "integrity": "sha1-aaevEWlj1HIG7JvZtIoUIW8eOAY=", - "dev": true - }, - "repeat-string": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-0.2.2.tgz", - "integrity": "sha1-x6jTI2BoNiBZp+RlH8aITosftK4=", - "dev": true - } - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "expand-range": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", - "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", - "dev": true, - "requires": { - "fill-range": "^2.1.0" - }, - "dependencies": { - "fill-range": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", - "integrity": "sha1-6x53OrsFbc2N8r/favWbizqTZWU=", - "dev": true, - "requires": { - "is-number": "^2.1.0", - "isobject": "^2.0.0", - "randomatic": "^3.0.0", - "repeat-element": "^1.1.2", - "repeat-string": "^1.5.2" - } - }, - "is-number": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", - "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, - "express-session": { - "version": "1.11.3", - "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.11.3.tgz", - "integrity": "sha1-XMmPP1/4Ttg1+Ry/CqvQxxB0AK8=", - "dev": true, - "requires": { - "cookie": "0.1.3", - "cookie-signature": "1.0.6", - "crc": "3.3.0", - "debug": "~2.2.0", - "depd": "~1.0.1", - "on-headers": "~1.0.0", - "parseurl": "~1.3.0", - "uid-safe": "~2.0.0", - "utils-merge": "1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "http://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "0.7.1" - } - }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - }, - "uid-safe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.0.0.tgz", - "integrity": "sha1-p/PGymSh9qXQTsDvPkw9U2cxcTc=", - "dev": true, - "requires": { - "base64-url": "1.2.1" - } - } - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "external-editor": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz", - "integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==", - "dev": true, - "requires": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - }, - "dependencies": { - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha1-rQD+TcYSqSMuhxhxHcXLWrAoVUM=", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "extract-zip": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.7.tgz", - "integrity": "sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k=", - "dev": true, - "requires": { - "concat-stream": "1.6.2", - "debug": "2.6.9", - "mkdirp": "0.5.1", - "yauzl": "2.4.1" - }, - "dependencies": { - "fd-slicer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", - "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", - "dev": true, - "requires": { - "pend": "~1.2.0" - } - }, - "yauzl": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", - "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", - "dev": true, - "requires": { - "fd-slicer": "~1.0.1" - } - } - } - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true - }, - "fancy-log": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", - "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", - "dev": true, - "requires": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "time-stamp": "^1.0.0" - } - }, - "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", - "dev": true - }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "faye-websocket": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", - "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", - "dev": true, - "requires": { - "websocket-driver": ">=0.5.1" - } - }, - "fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", - "dev": true, - "requires": { - "pend": "~1.2.0" - } - }, - "figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, - "file-entry-cache": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", - "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", - "dev": true, - "requires": { - "flat-cache": "^1.2.1", - "object-assign": "^4.0.1" - } - }, - "file-type": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-4.4.0.tgz", - "integrity": "sha1-G2AOX8ofvcboDApwxxyNul95BsU=", - "dev": true - }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha1-VTp7hEb/b2hDWcRF8eN6BdrMM90=", - "dev": true, - "optional": true - }, - "filename-regex": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", - "dev": true - }, - "filename-reserved-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-1.0.0.tgz", - "integrity": "sha1-5hz4BfDeHJhFZ9A4bcXfUO5a9+Q=", - "dev": true - }, - "filenamify": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-1.2.1.tgz", - "integrity": "sha1-qfL/0RxQO+0wABUCknI3jx8TZaU=", - "dev": true, - "requires": { - "filename-reserved-regex": "^1.0.0", - "strip-outer": "^1.0.0", - "trim-repeated": "^1.0.0" - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "finalhandler": { - "version": "0.4.0", - "resolved": "http://registry.npmjs.org/finalhandler/-/finalhandler-0.4.0.tgz", - "integrity": "sha1-llpS2ejQXSuFdUhUH7ibU6JJfZs=", - "dev": true, - "requires": { - "debug": "~2.2.0", - "escape-html": "1.0.2", - "on-finished": "~2.3.0", - "unpipe": "~1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "http://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "0.7.1" - } - }, - "escape-html": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.2.tgz", - "integrity": "sha1-130y+pjjjC9BroXpJ44ODmuhAiw=", - "dev": true - }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - } - } - }, - "find-index": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", - "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=", - "dev": true - }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "find-versions": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-1.2.1.tgz", - "integrity": "sha1-y96fEuOFdaCvG+G5osXV/Y8Ya2I=", - "dev": true, - "optional": true, - "requires": { - "array-uniq": "^1.0.0", - "get-stdin": "^4.0.1", - "meow": "^3.5.0", - "semver-regex": "^1.0.0" - } - }, - "findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - }, - "fined": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", - "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^2.0.3", - "object.defaults": "^1.1.0", - "object.pick": "^1.2.0", - "parse-filepath": "^1.0.1" - } - }, - "first-chunk-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", - "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", - "dev": true - }, - "flagged-respawn": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz", - "integrity": "sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c=", - "dev": true - }, - "flat-cache": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", - "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", - "dev": true, - "requires": { - "circular-json": "^0.3.1", - "del": "^2.0.2", - "graceful-fs": "^4.1.2", - "write": "^0.2.1" - }, - "dependencies": { - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - } - } - }, - "flatmap-stream": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/flatmap-stream/-/flatmap-stream-0.1.0.tgz", - "integrity": "sha512-Nlic4ZRYxikqnK5rj3YoxDVKGGtUjcNDUtvQ7XsdGLZmMwdUYnXf10o1zcXtzEZTBgc6GxeRpQxV/Wu3WPIIHA==", - "dev": true - }, - "flatpickr": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-4.5.2.tgz", - "integrity": "sha512-jDy4QYGpmiy7+Qk8QvKJ4spjDdxcx9cxMydmq1x427HkKWBw0qizLYeYM2F6tMcvvqGjU5VpJS55j4LnsaBblA==" - }, - "flatten": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz", - "integrity": "sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=", - "dev": true - }, - "follow-redirects": { - "version": "1.5.8", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.8.tgz", - "integrity": "sha512-sy1mXPmv7kLAMKW/8XofG7o9T+6gAjzdZK4AJF6ryqQYUa/hnzgiypoeUecZ53x7XiqKNEpNqLtS97MshW2nxg==", - "dev": true, - "requires": { - "debug": "=3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "requires": { - "for-in": "^1.0.1" - } - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true - }, - "form-data": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", - "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.5", - "mime-types": "^2.1.12" - } - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "map-cache": "^0.2.2" - } - }, - "fresh": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz", - "integrity": "sha1-ZR+DjiJCTnVm3hYdg1jKoZn4PU8=", - "dev": true - }, - "from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", - "dev": true - }, - "fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha1-a+Dem+mYzhavivwkSXue6bfM2a0=", - "dev": true - }, - "fs-extra": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz", - "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "klaw": "^1.0.0" - }, - "dependencies": { - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - } - } - }, - "fs-readfile-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fs-readfile-promise/-/fs-readfile-promise-2.0.1.tgz", - "integrity": "sha1-gAI4I5gfn//+AWCei+Zo9prknnA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2" - }, - "dependencies": { - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - } - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fsevents": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", - "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", - "dev": true, - "optional": true, - "requires": { - "nan": "^2.9.2", - "node-pre-gyp": "^0.10.0" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "1.0.0", - "readable-stream": "2.3.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "balanced-match": "1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "debug": { - "version": "2.6.9", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "2.0.0" - } - }, - "deep-extend": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "2.2.4" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aproba": "1.2.0", - "console-control-strings": "1.1.0", - "has-unicode": "2.0.1", - "object-assign": "4.1.1", - "signal-exit": "3.0.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wide-align": "1.1.2" - } - }, - "glob": { - "version": "7.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.21", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safer-buffer": "2.1.2" - } - }, - "ignore-walk": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimatch": "3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "number-is-nan": "1.0.1" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "brace-expansion": "1.1.11" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true, - "optional": true - }, - "minipass": { - "version": "2.2.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "5.1.1", - "yallist": "3.0.2" - } - }, - "minizlib": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "2.2.4" - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "needle": { - "version": "2.2.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "debug": "2.6.9", - "iconv-lite": "0.4.21", - "sax": "1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.10.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "detect-libc": "1.0.3", - "mkdirp": "0.5.1", - "needle": "2.2.0", - "nopt": "4.0.1", - "npm-packlist": "1.1.10", - "npmlog": "4.1.2", - "rc": "1.2.7", - "rimraf": "2.6.2", - "semver": "5.5.0", - "tar": "4.4.1" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "abbrev": "1.1.1", - "osenv": "0.1.5" - } - }, - "npm-bundled": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.1.10", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ignore-walk": "3.0.1", - "npm-bundled": "1.0.3" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "1.1.4", - "console-control-strings": "1.1.0", - "gauge": "2.7.4", - "set-blocking": "2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "wrappy": "1.0.2" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.7", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "deep-extend": "0.5.1", - "ini": "1.3.5", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.1.1", - "util-deprecate": "1.0.2" - } - }, - "rimraf": { - "version": "2.6.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "glob": "7.1.2" - } - }, - "safe-buffer": { - "version": "5.1.1", - "bundled": true, - "dev": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "5.5.0", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "5.1.1" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "requires": { - "ansi-regex": "2.1.1" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "4.4.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "chownr": "1.0.1", - "fs-minipass": "1.2.5", - "minipass": "2.2.4", - "minizlib": "1.1.0", - "mkdirp": "0.5.1", - "safe-buffer": "5.1.1", - "yallist": "3.0.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "string-width": "1.0.2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "yallist": { - "version": "3.0.2", - "bundled": true, - "dev": true - } - } - }, - "ftp": { - "version": "0.3.10", - "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", - "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", - "dev": true, - "optional": true, - "requires": { - "readable-stream": "1.1.x", - "xregexp": "2.0.0" - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=", - "dev": true - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "gaze": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", - "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", - "dev": true, - "requires": { - "globule": "~0.1.0" - } - }, - "generate-function": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", - "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", - "dev": true, - "optional": true, - "requires": { - "is-property": "^1.0.2" - } - }, - "generate-object-property": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", - "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", - "dev": true, - "optional": true, - "requires": { - "is-property": "^1.0.0" - } - }, - "get-proxy": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-1.1.0.tgz", - "integrity": "sha1-iUhUSRvFkbDxR9euVw9cZ4tyVus=", - "dev": true, - "requires": { - "rc": "^1.1.2" - } - }, - "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", - "dev": true - }, - "get-stream": { - "version": "3.0.0", - "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true, - "optional": true - }, - "get-uri": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.2.tgz", - "integrity": "sha1-XHlecTJvbKEoby/IJXXNK6sq9Xg=", - "dev": true, - "optional": true, - "requires": { - "data-uri-to-buffer": "1", - "debug": "2", - "extend": "3", - "file-uri-to-path": "1", - "ftp": "~0.3.10", - "readable-stream": "2" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true, - "optional": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } - } - }, - "gifsicle": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/gifsicle/-/gifsicle-3.0.4.tgz", - "integrity": "sha1-9Fy17RAWW2ZdySng6TKLbIId+js=", - "dev": true, - "optional": true, - "requires": { - "bin-build": "^2.0.0", - "bin-wrapper": "^3.0.0", - "logalot": "^2.0.0" - } - }, - "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-base": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", - "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", - "dev": true, - "requires": { - "glob-parent": "^2.0.0", - "is-glob": "^2.0.0" - }, - "dependencies": { - "glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true, - "requires": { - "is-glob": "^2.0.0" - } - }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - } - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - } - }, - "glob-stream": { - "version": "3.1.18", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", - "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", - "dev": true, - "requires": { - "glob": "^4.3.1", - "glob2base": "^0.0.12", - "minimatch": "^2.0.1", - "ordered-read-streams": "^0.1.0", - "through2": "^0.6.1", - "unique-stream": "^1.0.0" - }, - "dependencies": { - "glob": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", - "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", - "dev": true, - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^2.0.1", - "once": "^1.3.0" - } - }, - "minimatch": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", - "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", - "dev": true, - "requires": { - "brace-expansion": "^1.0.0" - } - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" - } - } - } - }, - "glob-watcher": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", - "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", - "dev": true, - "requires": { - "gaze": "^0.5.1" - } - }, - "glob2base": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", - "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", - "dev": true, - "requires": { - "find-index": "^0.1.1" - } - }, - "global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha1-bXcPDrUjrHgWTXK15xqIdyZcw+o=", - "dev": true, - "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - } - }, - "global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - } - }, - "globals": { - "version": "11.8.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.8.0.tgz", - "integrity": "sha512-io6LkyPVuzCHBSQV9fmOwxZkUk6nIaGmxheLDgmuFv89j0fm2aqDbIXKAGfzCMHqz3HLF2Zf8WSG6VqMh2qFmA==", - "dev": true - }, - "globby": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", - "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", - "dev": true, - "requires": { - "array-union": "^1.0.1", - "arrify": "^1.0.0", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "globule": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", - "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", - "dev": true, - "requires": { - "glob": "~3.1.21", - "lodash": "~1.0.1", - "minimatch": "~0.2.11" - }, - "dependencies": { - "glob": { - "version": "3.1.21", - "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", - "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", - "dev": true, - "requires": { - "graceful-fs": "~1.2.0", - "inherits": "1", - "minimatch": "~0.2.11" - } - }, - "graceful-fs": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", - "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", - "dev": true - }, - "inherits": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", - "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", - "dev": true - }, - "lodash": { - "version": "1.0.2", - "resolved": "http://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", - "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", - "dev": true - }, - "minimatch": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", - "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", - "dev": true, - "requires": { - "lru-cache": "2", - "sigmund": "~1.0.0" - } - } - } - }, - "glogg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.1.tgz", - "integrity": "sha1-3PdY5EeJzD89MsHzVio2duajSBA=", - "dev": true, - "requires": { - "sparkles": "^1.0.0" - } - }, - "got": { - "version": "5.7.1", - "resolved": "http://registry.npmjs.org/got/-/got-5.7.1.tgz", - "integrity": "sha1-X4FjWmHkplifGAVp6k44FoClHzU=", - "dev": true, - "requires": { - "create-error-class": "^3.0.1", - "duplexer2": "^0.1.4", - "is-redirect": "^1.0.0", - "is-retry-allowed": "^1.0.0", - "is-stream": "^1.0.0", - "lowercase-keys": "^1.0.0", - "node-status-codes": "^1.0.0", - "object-assign": "^4.0.1", - "parse-json": "^2.1.0", - "pinkie-promise": "^2.0.0", - "read-all-stream": "^3.0.0", - "readable-stream": "^2.0.5", - "timed-out": "^3.0.0", - "unzip-response": "^1.0.2", - "url-parse-lax": "^1.0.0" - }, - "dependencies": { - "duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", - "dev": true, - "requires": { - "readable-stream": "^2.0.2" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "graceful-fs": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", - "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", - "dev": true, - "requires": { - "natives": "^1.1.0" - } - }, - "graceful-readlink": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", - "dev": true - }, - "gulp": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", - "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", - "dev": true, - "requires": { - "archy": "^1.0.0", - "chalk": "^1.0.0", - "deprecated": "^0.0.1", - "gulp-util": "^3.0.0", - "interpret": "^1.0.0", - "liftoff": "^2.1.0", - "minimist": "^1.1.0", - "orchestrator": "^0.3.0", - "pretty-hrtime": "^1.0.0", - "semver": "^4.1.0", - "tildify": "^1.0.0", - "v8flags": "^2.0.2", - "vinyl-fs": "^0.3.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, - "gulp-babel": { - "version": "8.0.0-beta.2", - "resolved": "http://registry.npmjs.org/gulp-babel/-/gulp-babel-8.0.0-beta.2.tgz", - "integrity": "sha512-GTC2PxAXWkp6u1fP+C5+kn5biQ0dKGhkOSSXvKAf3ykF0+R3tevmLm/zSIkc1+S7U1JwH3XTvuMwRL6LD+sEiw==", - "dev": true, - "requires": { - "plugin-error": "^1.0.1", - "replace-ext": "^1.0.0", - "through2": "^2.0.0", - "vinyl-sourcemaps-apply": "^0.2.0" - }, - "dependencies": { - "replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true - } - } - }, - "gulp-concat": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz", - "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", - "dev": true, - "requires": { - "concat-with-sourcemaps": "^1.0.0", - "through2": "^2.0.0", - "vinyl": "^2.0.0" - }, - "dependencies": { - "clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", - "dev": true - }, - "clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", - "dev": true - }, - "replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true - }, - "vinyl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", - "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", - "dev": true, - "requires": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" - } - } - } - }, - "gulp-connect": { - "version": "5.0.0", - "resolved": "http://registry.npmjs.org/gulp-connect/-/gulp-connect-5.0.0.tgz", - "integrity": "sha1-8v3zBq6RFGg2jCKF8teC8T7dr04=", - "dev": true, - "requires": { - "connect": "^2.30.0", - "connect-livereload": "^0.5.4", - "event-stream": "^3.3.2", - "gulp-util": "^3.0.6", - "tiny-lr": "^0.2.1" - } - }, - "gulp-decompress": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gulp-decompress/-/gulp-decompress-1.2.0.tgz", - "integrity": "sha1-jutlpeAV+O2FMsr+KEVJYGJvDcc=", - "dev": true, - "requires": { - "archive-type": "^3.0.0", - "decompress": "^3.0.0", - "gulp-util": "^3.0.1", - "readable-stream": "^2.0.2" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "gulp-eslint": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/gulp-eslint/-/gulp-eslint-5.0.0.tgz", - "integrity": "sha1-KiaECV93Syz3kxAmIHjFbMehK1I=", - "dev": true, - "requires": { - "eslint": "^5.0.1", - "fancy-log": "^1.3.2", - "plugin-error": "^1.0.1" - } - }, - "gulp-imagemin": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/gulp-imagemin/-/gulp-imagemin-4.1.0.tgz", - "integrity": "sha1-XONH8dFwb+08yPF3fKkJSlg7ULc=", - "dev": true, - "requires": { - "chalk": "^2.1.0", - "fancy-log": "^1.3.2", - "imagemin": "^5.3.1", - "imagemin-gifsicle": "^5.2.0", - "imagemin-jpegtran": "^5.0.2", - "imagemin-optipng": "^5.2.1", - "imagemin-svgo": "^6.0.0", - "plugin-error": "^0.1.2", - "plur": "^2.1.2", - "pretty-bytes": "^4.0.2", - "through2-concurrent": "^1.1.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0=", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "arr-diff": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz", - "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", - "dev": true, - "requires": { - "arr-flatten": "^1.0.1", - "array-slice": "^0.2.3" - } - }, - "arr-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz", - "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=", - "dev": true - }, - "array-slice": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", - "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", - "dev": true - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha1-GMSasWoDe26wFSzIPjRxM4IVtm4=", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "extend-shallow": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz", - "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", - "dev": true, - "requires": { - "kind-of": "^1.1.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "kind-of": { - "version": "1.1.0", - "resolved": "http://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", - "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=", - "dev": true - }, - "plugin-error": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", - "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", - "dev": true, - "requires": { - "ansi-cyan": "^0.1.1", - "ansi-red": "^0.1.1", - "arr-diff": "^1.0.1", - "arr-union": "^2.0.1", - "extend-shallow": "^1.1.2" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "gulp-less": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/gulp-less/-/gulp-less-3.5.0.tgz", - "integrity": "sha1-gBT0ad38ZUTX3aUAmN7wNxu7T3g=", - "dev": true, - "requires": { - "accord": "^0.28.0", - "less": "2.6.x || ^2.7.1", - "object-assign": "^4.0.1", - "plugin-error": "^0.1.2", - "replace-ext": "^1.0.0", - "through2": "^2.0.0", - "vinyl-sourcemaps-apply": "^0.2.0" - }, - "dependencies": { - "arr-diff": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz", - "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", - "dev": true, - "requires": { - "arr-flatten": "^1.0.1", - "array-slice": "^0.2.3" - } - }, - "arr-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz", - "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=", - "dev": true - }, - "array-slice": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", - "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", - "dev": true - }, - "extend-shallow": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz", - "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", - "dev": true, - "requires": { - "kind-of": "^1.1.0" - } - }, - "kind-of": { - "version": "1.1.0", - "resolved": "http://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", - "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=", - "dev": true - }, - "plugin-error": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", - "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", - "dev": true, - "requires": { - "ansi-cyan": "^0.1.1", - "ansi-red": "^0.1.1", - "arr-diff": "^1.0.1", - "arr-union": "^2.0.1", - "extend-shallow": "^1.1.2" - } - }, - "replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true - } - } - }, - "gulp-ngdocs": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/gulp-ngdocs/-/gulp-ngdocs-0.3.0.tgz", - "integrity": "sha1-J7Z6Ql6zh1ImNFq4lgTXN/Y1fCE=", - "dev": true, - "requires": { - "angular": "~1.3.1", - "angular-animate": "~1.3.1", - "canonical-path": "0.0.2", - "extend": "1.3.0", - "gulp-util": "3.0.0", - "lodash": "2.4.1", - "marked": "0.3.2", - "merge-stream": "0.1.5", - "path": "0.4.9", - "string_decoder": "0.10.31", - "through2": "0.6.1", - "vinyl-fs": "0.3.7" - }, - "dependencies": { - "ansi-regex": { - "version": "0.2.1", - "resolved": "http://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", - "integrity": "sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk=", - "dev": true - }, - "ansi-styles": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", - "integrity": "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94=", - "dev": true - }, - "chalk": { - "version": "0.5.1", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", - "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=", - "dev": true, - "requires": { - "ansi-styles": "^1.1.0", - "escape-string-regexp": "^1.0.0", - "has-ansi": "^0.1.0", - "strip-ansi": "^0.3.0", - "supports-color": "^0.2.0" - } - }, - "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", - "dev": true - }, - "dateformat": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", - "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", - "dev": true, - "requires": { - "get-stdin": "^4.0.1", - "meow": "^3.3.0" - } - }, - "extend": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extend/-/extend-1.3.0.tgz", - "integrity": "sha1-0VFvsP9WJNLr+RI+odrFoZlABPg=", - "dev": true - }, - "gulp-util": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.0.tgz", - "integrity": "sha1-b+7cR9aXKCO6zplH/F9GvYo0Zuc=", - "dev": true, - "requires": { - "chalk": "^0.5.0", - "dateformat": "^1.0.7-1.2.3", - "lodash": "^2.4.1", - "lodash._reinterpolate": "^2.4.1", - "lodash.template": "^2.4.1", - "minimist": "^0.2.0", - "multipipe": "^0.1.0", - "through2": "^0.5.0", - "vinyl": "^0.2.1" - }, - "dependencies": { - "through2": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", - "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", - "dev": true, - "requires": { - "readable-stream": "~1.0.17", - "xtend": "~3.0.0" - } - } - } - }, - "has-ansi": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", - "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=", - "dev": true, - "requires": { - "ansi-regex": "^0.2.0" - } - }, - "lodash": { - "version": "2.4.1", - "resolved": "http://registry.npmjs.org/lodash/-/lodash-2.4.1.tgz", - "integrity": "sha1-W3cjA03aTSYuWkb7LFjXzCL3FCA=", - "dev": true - }, - "lodash._reinterpolate": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz", - "integrity": "sha1-TxInqlqHEfxjL1sHofRgequLMiI=", - "dev": true - }, - "lodash.defaults": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz", - "integrity": "sha1-p+iIXwXmiFEUS24SqPNngCa8TFQ=", - "dev": true, - "requires": { - "lodash._objecttypes": "~2.4.1", - "lodash.keys": "~2.4.1" - } - }, - "lodash.escape": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz", - "integrity": "sha1-LOEsXghNsKV92l5dHu659dF1o7Q=", - "dev": true, - "requires": { - "lodash._escapehtmlchar": "~2.4.1", - "lodash._reunescapedhtml": "~2.4.1", - "lodash.keys": "~2.4.1" - } - }, - "lodash.keys": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", - "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", - "dev": true, - "requires": { - "lodash._isnative": "~2.4.1", - "lodash._shimkeys": "~2.4.1", - "lodash.isobject": "~2.4.1" - } - }, - "lodash.template": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-2.4.1.tgz", - "integrity": "sha1-nmEQB+32KRKal0qzxIuBez4c8g0=", - "dev": true, - "requires": { - "lodash._escapestringchar": "~2.4.1", - "lodash._reinterpolate": "~2.4.1", - "lodash.defaults": "~2.4.1", - "lodash.escape": "~2.4.1", - "lodash.keys": "~2.4.1", - "lodash.templatesettings": "~2.4.1", - "lodash.values": "~2.4.1" - } - }, - "lodash.templatesettings": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-2.4.1.tgz", - "integrity": "sha1-6nbHXRHrhtTb6JqDiTu4YZKaxpk=", - "dev": true, - "requires": { - "lodash._reinterpolate": "~2.4.1", - "lodash.escape": "~2.4.1" - } - }, - "merge-stream": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-0.1.5.tgz", - "integrity": "sha1-5oIPet267gA/SMpKWMfFolPV4Fw=", - "dev": true, - "requires": { - "through2": "^0.5.1" - }, - "dependencies": { - "through2": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", - "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", - "dev": true, - "requires": { - "readable-stream": "~1.0.17", - "xtend": "~3.0.0" - } - } - } - }, - "minimist": { - "version": "0.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.2.0.tgz", - "integrity": "sha1-Tf/lJdriuGTGbC4jxicdev3s784=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "strip-ansi": { - "version": "0.3.0", - "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", - "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", - "dev": true, - "requires": { - "ansi-regex": "^0.2.1" - } - }, - "supports-color": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", - "integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=", - "dev": true - }, - "through2": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.1.tgz", - "integrity": "sha1-90KzKJPovSYUbnieT9LMssB6cX4=", - "dev": true, - "requires": { - "readable-stream": ">=1.0.27-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" - }, - "dependencies": { - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true - } - } - }, - "vinyl": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.2.3.tgz", - "integrity": "sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI=", - "dev": true, - "requires": { - "clone-stats": "~0.0.1" - } - }, - "vinyl-fs": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.7.tgz", - "integrity": "sha1-LiXP5t9cgIGPl/9Be/XCGkHkpJs=", - "dev": true, - "requires": { - "glob-stream": "^3.1.5", - "glob-watcher": "^0.0.6", - "graceful-fs": "^3.0.0", - "lodash": "^2.4.1", - "mkdirp": "^0.5.0", - "strip-bom": "^1.0.0", - "through2": "^0.6.1", - "vinyl": "^0.4.0" - }, - "dependencies": { - "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "dev": true, - "requires": { - "clone": "^0.2.0", - "clone-stats": "^0.0.1" - } - } - } - }, - "xtend": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", - "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=", - "dev": true - } - } - }, - "gulp-open": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/gulp-open/-/gulp-open-2.1.0.tgz", - "integrity": "sha1-rAHu6JjXenrAgS+tTz1T0IaH1Bw=", - "dev": true, - "requires": { - "colors": "^1.1.2", - "open": "0.0.5", - "plugin-log": "^0.1.0", - "through2": "^2.0.1" - } - }, - "gulp-postcss": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/gulp-postcss/-/gulp-postcss-6.4.0.tgz", - "integrity": "sha1-eKMuPIeqbNzsWuHJBeGW1HjoxdU=", - "dev": true, - "requires": { - "gulp-util": "^3.0.8", - "postcss": "^5.2.12", - "postcss-load-config": "^1.2.0", - "vinyl-sourcemaps-apply": "^0.2.1" - } - }, - "gulp-rename": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.4.0.tgz", - "integrity": "sha512-swzbIGb/arEoFK89tPY58vg3Ok1bw+d35PfUNwWqdo7KM4jkmuGA78JiDNqR+JeZFaeeHnRg9N7aihX3YPmsyg==", - "dev": true - }, - "gulp-sort": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/gulp-sort/-/gulp-sort-2.0.0.tgz", - "integrity": "sha1-xnYqLx8N4KP8WVohWZ0/rI26Gso=", - "dev": true, - "requires": { - "through2": "^2.0.1" - } - }, - "gulp-sourcemaps": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz", - "integrity": "sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw=", - "dev": true, - "requires": { - "convert-source-map": "^1.1.1", - "graceful-fs": "^4.1.2", - "strip-bom": "^2.0.0", - "through2": "^2.0.0", - "vinyl": "^1.0.0" - }, - "dependencies": { - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } - }, - "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, - "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", - "replace-ext": "0.0.1" - } - } - } - }, - "gulp-util": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", - "dev": true, - "requires": { - "array-differ": "^1.0.0", - "array-uniq": "^1.0.2", - "beeper": "^1.0.0", - "chalk": "^1.0.0", - "dateformat": "^2.0.0", - "fancy-log": "^1.1.0", - "gulplog": "^1.0.0", - "has-gulplog": "^0.1.0", - "lodash._reescape": "^3.0.0", - "lodash._reevaluate": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.template": "^3.0.0", - "minimist": "^1.1.0", - "multipipe": "^0.1.2", - "object-assign": "^3.0.0", - "replace-ext": "0.0.1", - "through2": "^2.0.0", - "vinyl": "^0.5.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "object-assign": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", - "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", - "dev": true - } - } - }, - "gulp-watch": { - "version": "4.3.11", - "resolved": "https://registry.npmjs.org/gulp-watch/-/gulp-watch-4.3.11.tgz", - "integrity": "sha1-Fi/FY96fx3DpH5p845VVE6mhGMA=", - "dev": true, - "requires": { - "anymatch": "^1.3.0", - "chokidar": "^1.6.1", - "glob-parent": "^3.0.1", - "gulp-util": "^3.0.7", - "object-assign": "^4.1.0", - "path-is-absolute": "^1.0.1", - "readable-stream": "^2.2.2", - "slash": "^1.0.0", - "vinyl": "^1.2.0", - "vinyl-file": "^2.0.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, - "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", - "replace-ext": "0.0.1" - } - } - } - }, - "gulp-wrap": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/gulp-wrap/-/gulp-wrap-0.13.0.tgz", - "integrity": "sha1-kPsLSieiZkM4Mv98YSLbXB7olMY=", - "dev": true, - "requires": { - "consolidate": "^0.14.1", - "es6-promise": "^3.1.2", - "fs-readfile-promise": "^2.0.1", - "gulp-util": "^3.0.3", - "js-yaml": "^3.2.6", - "lodash": "^4.11.1", - "node.extend": "^1.1.2", - "through2": "^2.0.1", - "tryit": "^1.0.1", - "vinyl-bufferstream": "^1.0.1" - } - }, - "gulp-wrap-js": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/gulp-wrap-js/-/gulp-wrap-js-0.4.1.tgz", - "integrity": "sha1-3uYqpISqupVHqT0f9c0MPQvtwDE=", - "dev": true, - "requires": { - "escodegen": "^1.6.1", - "esprima": "^2.3.0", - "estemplate": "*", - "gulp-util": "~3.0.5", - "through2": "*", - "vinyl-sourcemaps-apply": "^0.1.4" - }, - "dependencies": { - "source-map": { - "version": "0.1.43", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", - "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", - "dev": true, - "requires": { - "amdefine": ">=0.0.4" - } - }, - "vinyl-sourcemaps-apply": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.1.4.tgz", - "integrity": "sha1-xfy9Q+LyOEI8LcmL3db3m3K8NFs=", - "dev": true, - "requires": { - "source-map": "^0.1.39" - } - } - } - }, - "gulplog": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true, - "requires": { - "glogg": "^1.0.0" - } - }, - "har-schema": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", - "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", - "dev": true - }, - "har-validator": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", - "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", - "dev": true, - "requires": { - "ajv": "^4.9.1", - "har-schema": "^1.0.5" - }, - "dependencies": { - "ajv": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", - "dev": true, - "requires": { - "co": "^4.6.0", - "json-stable-stringify": "^1.0.1" - } - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true - } - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "has-binary2": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", - "integrity": "sha1-d3asYn8+p3JQz8My2rfd9eT10R0=", - "dev": true, - "requires": { - "isarray": "2.0.1" - }, - "dependencies": { - "isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", - "dev": true - } - } - }, - "has-cors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", - "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=", - "dev": true - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "has-gulplog": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", - "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", - "dev": true, - "requires": { - "sparkles": "^1.0.0" - } - }, - "has-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", - "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", - "dev": true - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "hasha": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/hasha/-/hasha-2.2.0.tgz", - "integrity": "sha1-eNfL/B5tZjA/55g3NlmEUXsvbuE=", - "dev": true, - "requires": { - "is-stream": "^1.0.1", - "pinkie-promise": "^2.0.0" - } - }, - "hawk": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", - "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", - "dev": true, - "requires": { - "boom": "2.x.x", - "cryptiles": "2.x.x", - "hoek": "2.x.x", - "sntp": "1.x.x" - } - }, - "hipchat-notifier": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/hipchat-notifier/-/hipchat-notifier-1.1.0.tgz", - "integrity": "sha1-ttJJdVQ3wZEII2d5nTupoPI7Ix4=", - "dev": true, - "optional": true, - "requires": { - "lodash": "^4.0.0", - "request": "^2.0.0" - } - }, - "hoek": { - "version": "2.16.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", - "dev": true - }, - "homedir-polyfill": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", - "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", - "dev": true, - "requires": { - "parse-passwd": "^1.0.0" - } - }, - "hosted-git-info": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", - "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", - "dev": true - }, - "html-comment-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.1.tgz", - "integrity": "sha1-ZouTd26q5V696POtRkswekljYl4=", - "dev": true - }, - "http-errors": { - "version": "1.3.1", - "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", - "integrity": "sha1-GX4izevUGYWF6GlO9nhhl7ke2UI=", - "dev": true, - "requires": { - "inherits": "~2.0.1", - "statuses": "1" - } - }, - "http-parser-js": { - "version": "0.4.13", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.13.tgz", - "integrity": "sha1-O9bW/ebjFyyTNMOzO2wZPYD+ETc=", - "dev": true - }, - "http-proxy": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", - "integrity": "sha1-etOElGWPhGBeL220Q230EPTlvpo=", - "dev": true, - "requires": { - "eventemitter3": "^3.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - } - }, - "http-proxy-agent": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", - "integrity": "sha1-5IIb7vWyFCogJr1zkm/lN2McVAU=", - "dev": true, - "requires": { - "agent-base": "4", - "debug": "3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, - "http-signature": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", - "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", - "dev": true, - "requires": { - "assert-plus": "^0.2.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "httpntlm": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.6.1.tgz", - "integrity": "sha1-rQFScUOi6Hc8+uapb1hla7UqNLI=", - "dev": true, - "requires": { - "httpreq": ">=0.4.22", - "underscore": "~1.7.0" - } - }, - "httpreq": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/httpreq/-/httpreq-0.4.24.tgz", - "integrity": "sha1-QzX/2CzZaWaKOUZckprGHWOTYn8=", - "dev": true - }, - "https-proxy-agent": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", - "integrity": "sha1-UVUpcPoE1yPgTFbQQXjD+SWSu8A=", - "dev": true, - "requires": { - "agent-base": "^4.1.0", - "debug": "^3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.5.tgz", - "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - } - } - }, - "iconv-lite": { - "version": "0.4.11", - "resolved": "http://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.11.tgz", - "integrity": "sha1-LstC/SlHRJIiCaLnxATayHk9it4=", - "dev": true - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - }, - "image-size": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", - "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=", - "dev": true, - "optional": true - }, - "imagemin": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/imagemin/-/imagemin-5.3.1.tgz", - "integrity": "sha1-8Zwu7h5xumxlWMUV+fyWaAGJptQ=", - "dev": true, - "requires": { - "file-type": "^4.1.0", - "globby": "^6.1.0", - "make-dir": "^1.0.0", - "p-pipe": "^1.1.0", - "pify": "^2.3.0", - "replace-ext": "^1.0.0" - }, - "dependencies": { - "globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", - "dev": true, - "requires": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true - } - } - }, - "imagemin-gifsicle": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/imagemin-gifsicle/-/imagemin-gifsicle-5.2.0.tgz", - "integrity": "sha1-N4FSTEV2Eu8EkWrzQkGitCv8tAo=", - "dev": true, - "optional": true, - "requires": { - "exec-buffer": "^3.0.0", - "gifsicle": "^3.0.0", - "is-gif": "^1.0.0" - } - }, - "imagemin-jpegtran": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/imagemin-jpegtran/-/imagemin-jpegtran-5.0.2.tgz", - "integrity": "sha1-5ogiY7j3kW/duABkDPddLpcNKtY=", - "dev": true, - "optional": true, - "requires": { - "exec-buffer": "^3.0.0", - "is-jpg": "^1.0.0", - "jpegtran-bin": "^3.0.0" - } - }, - "imagemin-optipng": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/imagemin-optipng/-/imagemin-optipng-5.2.1.tgz", - "integrity": "sha1-0i2kEsCfX/AKQzmWC5ioix2+hpU=", - "dev": true, - "optional": true, - "requires": { - "exec-buffer": "^3.0.0", - "is-png": "^1.0.0", - "optipng-bin": "^3.0.0" - } - }, - "imagemin-svgo": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/imagemin-svgo/-/imagemin-svgo-6.0.0.tgz", - "integrity": "sha1-LdjIKUa+Qqjiy8rjxb8Ae8K4ueg=", - "dev": true, - "optional": true, - "requires": { - "buffer-from": "^0.1.1", - "is-svg": "^2.0.0", - "svgo": "^1.0.0" - }, - "dependencies": { - "buffer-from": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-0.1.2.tgz", - "integrity": "sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg==", - "dev": true, - "optional": true - }, - "coa": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.1.tgz", - "integrity": "sha1-8/iwsVBz411wJj+xBCyywCPbOK8=", - "dev": true, - "optional": true, - "requires": { - "q": "^1.1.2" - } - }, - "colors": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", - "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", - "dev": true, - "optional": true - }, - "csso": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/csso/-/csso-3.5.1.tgz", - "integrity": "sha1-e564vmFiiXPBsmHhadLwJACOdYs=", - "dev": true, - "optional": true, - "requires": { - "css-tree": "1.0.0-alpha.29" - }, - "dependencies": { - "css-tree": { - "version": "1.0.0-alpha.29", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.29.tgz", - "integrity": "sha1-P6nU7zFCy9HDAedmTB81K9gvWjk=", - "dev": true, - "optional": true, - "requires": { - "mdn-data": "~1.1.0", - "source-map": "^0.5.3" - } - } - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha1-E7BM2z5sXRnfkatph6hpVhmwqnE=", - "dev": true, - "optional": true - }, - "js-yaml": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", - "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", - "dev": true, - "optional": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "svgo": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.1.1.tgz", - "integrity": "sha512-GBkJbnTuFpM4jFbiERHDWhZc/S/kpHToqmZag3aEBjPYK44JAN2QBjvrGIxLOoCyMZjuFQIfTO2eJd8uwLY/9g==", - "dev": true, - "optional": true, - "requires": { - "coa": "~2.0.1", - "colors": "~1.1.2", - "css-select": "^2.0.0", - "css-select-base-adapter": "~0.1.0", - "css-tree": "1.0.0-alpha.28", - "css-url-regex": "^1.1.0", - "csso": "^3.5.0", - "js-yaml": "^3.12.0", - "mkdirp": "~0.5.1", - "object.values": "^1.0.4", - "sax": "~1.2.4", - "stable": "~0.1.6", - "unquote": "~1.1.1", - "util.promisify": "~1.0.0" - } - } - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "dev": true, - "requires": { - "repeating": "^2.0.0" - } - }, - "indexes-of": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", - "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", - "dev": true - }, - "indexof": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", - "dev": true - }, - "indx": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/indx/-/indx-0.2.3.tgz", - "integrity": "sha1-Fdz1bunPZcAjTFE8J/vVgOcPvFA=", - "dev": true - }, - "inflection": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", - "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=", - "dev": true, - "optional": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha1-7uJfVtscnsYIXgwid4CD9Zar+Sc=", - "dev": true - }, - "inquirer": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.0.tgz", - "integrity": "sha512-QIEQG4YyQ2UYZGDC4srMZ7BjHOmNk1lR2JQj5UknBapklm6WHA+VVH7N+sUdX3A7NeCfGF8o4X1S3Ao7nAcIeg==", - "dev": true, - "requires": { - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.0", - "cli-cursor": "^2.1.0", - "cli-width": "^2.0.0", - "external-editor": "^3.0.0", - "figures": "^2.0.0", - "lodash": "^4.17.10", - "mute-stream": "0.0.7", - "run-async": "^2.2.0", - "rxjs": "^6.1.0", - "string-width": "^2.1.0", - "strip-ansi": "^4.0.0", - "through": "^2.3.6" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "interpret": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", - "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", - "dev": true - }, - "invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dev": true, - "requires": { - "loose-envify": "^1.0.0" - } - }, - "ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", - "dev": true - }, - "ip-regex": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-1.0.3.tgz", - "integrity": "sha1-3FiQdvZZ9BnCIgOaMzFvHHOH7/0=", - "dev": true, - "optional": true - }, - "irregular-plurals": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-1.4.0.tgz", - "integrity": "sha1-LKmwM2UREYVUEvFr5dd8YqRYp2Y=", - "dev": true - }, - "is": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/is/-/is-3.2.1.tgz", - "integrity": "sha1-0Kwq1V63sL7JJqUmb2xmKqqD3KU=", - "dev": true - }, - "is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha1-OV4a6EsR8mrReV5zwXN45IowFXY=", - "dev": true, - "requires": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" - } - }, - "is-absolute-url": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", - "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=", - "dev": true - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "requires": { - "binary-extensions": "^1.0.0" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=", - "dev": true - }, - "is-builtin-module": { - "version": "1.0.0", - "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", - "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", - "dev": true, - "requires": { - "builtin-modules": "^1.0.0" - } - }, - "is-bzip2": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-bzip2/-/is-bzip2-1.0.0.tgz", - "integrity": "sha1-XuWOqlounIDiFAe+3yOuWsCRs/w=", - "dev": true - }, - "is-callable": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", - "integrity": "sha1-HhrfIZ4e62hNaR+dagX/DTCiTXU=", - "dev": true - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-date-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", - "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", - "dev": true - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=", - "dev": true - } - } - }, - "is-directory": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", - "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", - "dev": true - }, - "is-dotfile": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", - "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", - "dev": true - }, - "is-equal-shallow": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", - "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", - "dev": true, - "requires": { - "is-primitive": "^2.0.0" - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-finite": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", - "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "is-gif": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-gif/-/is-gif-1.0.0.tgz", - "integrity": "sha1-ptKumIkwB7/6l6HYwB1jIFgyCX4=", - "dev": true, - "optional": true - }, - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - }, - "is-gzip": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-gzip/-/is-gzip-1.0.0.tgz", - "integrity": "sha1-bKiwe5nHeZgCWQDlVc7Y7YCHmoM=", - "dev": true - }, - "is-jpg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-jpg/-/is-jpg-1.0.1.tgz", - "integrity": "sha1-KW1X/dmc4BBDSnKD40armhA16XU=", - "dev": true, - "optional": true - }, - "is-my-ip-valid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", - "integrity": "sha1-ezUbjo7dTTmV1NBmaA5mTZRpaCQ=", - "dev": true, - "optional": true - }, - "is-my-json-valid": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.19.0.tgz", - "integrity": "sha512-mG0f/unGX1HZ5ep4uhRaPOS8EkAY8/j6mDRMJrutq4CqhoJWYp7qAlonIPy3TV7p3ju4TK9fo/PbnoksWmsp5Q==", - "dev": true, - "optional": true, - "requires": { - "generate-function": "^2.0.0", - "generate-object-property": "^1.1.0", - "is-my-ip-valid": "^1.0.0", - "jsonpointer": "^4.0.0", - "xtend": "^4.0.0" - } - }, - "is-natural-number": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-2.1.1.tgz", - "integrity": "sha1-fUxXKDd+84bD4ZSpkRv1fG3DNec=", - "dev": true - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-obj": { - "version": "1.0.1", - "resolved": "http://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", - "dev": true - }, - "is-path-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", - "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", - "dev": true - }, - "is-path-in-cwd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", - "integrity": "sha1-WsSLNF72dTOb1sekipEhELJBz1I=", - "dev": true, - "requires": { - "is-path-inside": "^1.0.0" - } - }, - "is-path-inside": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", - "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", - "dev": true, - "requires": { - "path-is-inside": "^1.0.1" - } - }, - "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", - "dev": true - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "is-png": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-png/-/is-png-1.1.0.tgz", - "integrity": "sha1-1XSxK/J1wDUEVVcLDltXqwYgd84=", - "dev": true, - "optional": true - }, - "is-posix-bracket": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", - "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", - "dev": true - }, - "is-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", - "dev": true - }, - "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", - "dev": true - }, - "is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", - "dev": true - }, - "is-redirect": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", - "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", - "dev": true - }, - "is-regex": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", - "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", - "dev": true, - "requires": { - "has": "^1.0.1" - } - }, - "is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha1-obtpNc6MXboei5dUubLcwCDiJg0=", - "dev": true, - "requires": { - "is-unc-path": "^1.0.0" - } - }, - "is-resolvable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", - "integrity": "sha1-+xj4fOH+uSUWnJpAfBkxijIG7Yg=", - "dev": true - }, - "is-retry-allowed": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", - "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=", - "dev": true - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true - }, - "is-svg": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-2.1.0.tgz", - "integrity": "sha1-z2EJDaDZ77yrhyLeum8DIgjbsOk=", - "dev": true, - "requires": { - "html-comment-regex": "^1.1.0" - } - }, - "is-symbol": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", - "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", - "dev": true, - "requires": { - "has-symbols": "^1.0.0" - } - }, - "is-tar": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-tar/-/is-tar-1.0.0.tgz", - "integrity": "sha1-L2suF5LB9bs2UZrKqdZcDSb+hT0=", - "dev": true - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha1-1zHoiY7QkKEsNSrS6u1Qla0yLJ0=", - "dev": true, - "requires": { - "unc-path-regex": "^0.1.2" - } - }, - "is-url": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", - "integrity": "sha1-BKTfRtKMTP89c9Af8Gq+sxihqlI=", - "dev": true - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "is-valid-glob": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-0.3.0.tgz", - "integrity": "sha1-1LVcafUYhvm2XHDWwmItN+KfSP4=", - "dev": true - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha1-0YUOuXkezRjmGCzhKjDzlmNLsZ0=", - "dev": true - }, - "is-zip": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-zip/-/is-zip-1.0.0.tgz", - "integrity": "sha1-R7Co/004p2QxzP2ZqOFaTIa6IyU=", - "dev": true - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "isbinaryfile": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", - "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", - "dev": true, - "requires": { - "buffer-alloc": "^1.2.0" - } - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true - }, - "jasmine-core": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.1.0.tgz", - "integrity": "sha1-pHheE11d9lAk38kiSVPfWFvSdmw=", - "dev": true - }, - "jpegtran-bin": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jpegtran-bin/-/jpegtran-bin-3.2.0.tgz", - "integrity": "sha1-9g7PSumZwL2tLp+83ytvCYHnops=", - "dev": true, - "optional": true, - "requires": { - "bin-build": "^2.0.0", - "bin-wrapper": "^3.0.0", - "logalot": "^2.0.0" - } - }, - "js-base64": { - "version": "2.4.9", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.9.tgz", - "integrity": "sha512-xcinL3AuDJk7VSzsHgb9DvvIXayBbadtMZ4HFPx8rUszbW1MuNMlwYVC4zzCZ6e1sqZpnNS5ZFYOhXqA39T7LQ==", - "dev": true - }, - "js-levenshtein": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.4.tgz", - "integrity": "sha512-PxfGzSs0ztShKrUYPIn5r0MtyAhYcCwmndozzpz8YObbPnD1jFxzlBGbRnX2mIu6Z13xN6+PTu05TQFnZFlzow==", - "dev": true - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.7.0.tgz", - "integrity": "sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A=", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^2.6.0" - } - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true, - "optional": true - }, - "jsesc": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.1.tgz", - "integrity": "sha1-5CGiqOINawgZ3yiQj3glJrlt0f4=", - "dev": true - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha1-afaofZUTq4u4/mO9sJecRI5oRmA=", - "dev": true - }, - "json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true, - "requires": { - "jsonify": "~0.0.0" - } - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true - }, - "json5": { - "version": "0.5.1", - "resolved": "http://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", - "dev": true - }, - "jsonfile": { - "version": "2.4.0", - "resolved": "http://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", - "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - }, - "dependencies": { - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true, - "optional": true - } - } - }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true - }, - "jsonpointer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", - "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", - "dev": true, - "optional": true - }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "dev": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } - } - }, - "karma": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/karma/-/karma-2.0.5.tgz", - "integrity": "sha1-NxDHoucbHEOTE/KDhG2I4E5PkYw=", - "dev": true, - "requires": { - "bluebird": "^3.3.0", - "body-parser": "^1.16.1", - "chokidar": "^2.0.3", - "colors": "^1.1.0", - "combine-lists": "^1.0.0", - "connect": "^3.6.0", - "core-js": "^2.2.0", - "di": "^0.0.1", - "dom-serialize": "^2.2.0", - "expand-braces": "^0.1.1", - "glob": "^7.1.1", - "graceful-fs": "^4.1.2", - "http-proxy": "^1.13.0", - "isbinaryfile": "^3.0.0", - "lodash": "^4.17.4", - "log4js": "^2.5.3", - "mime": "^1.3.4", - "minimatch": "^3.0.2", - "optimist": "^0.6.1", - "qjobs": "^1.1.4", - "range-parser": "^1.2.0", - "rimraf": "^2.6.0", - "safe-buffer": "^5.0.1", - "socket.io": "2.0.4", - "source-map": "^0.6.1", - "tmp": "0.0.33", - "useragent": "2.2.1" - }, - "dependencies": { - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha1-vLJLTzeTTZqnrBe0ra+J58du8us=", - "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - } - }, - "body-parser": { - "version": "1.18.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", - "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", - "dev": true, - "requires": { - "bytes": "3.0.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "~1.6.3", - "iconv-lite": "0.4.23", - "on-finished": "~2.3.0", - "qs": "6.5.2", - "raw-body": "2.3.3", - "type-is": "~1.6.16" - } - }, - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", - "dev": true - }, - "chokidar": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", - "integrity": "sha1-NW/04rDo5D4yLRijckYLvPOszSY=", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.0", - "braces": "^2.3.0", - "fsevents": "^1.2.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.1", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "lodash.debounce": "^4.0.8", - "normalize-path": "^2.1.1", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0", - "upath": "^1.0.5" - } - }, - "connect": { - "version": "3.6.6", - "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz", - "integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=", - "dev": true, - "requires": { - "debug": "2.6.9", - "finalhandler": "1.1.0", - "parseurl": "~1.3.2", - "utils-merge": "1.0.1" - } - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true - }, - "finalhandler": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", - "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", - "dev": true, - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.1", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.2", - "statuses": "~1.3.1", - "unpipe": "~1.0.0" - }, - "dependencies": { - "statuses": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", - "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", - "dev": true - } - } - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "http-errors": { - "version": "1.6.3", - "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - } - }, - "iconv-lite": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", - "integrity": "sha1-KXhx9jvlB63Pv8pxXQzQ7thOmmM=", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "is-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", - "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha1-yzroBuh0BERYTvFUzo7pjUA/PjY=", - "dev": true - }, - "range-parser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", - "dev": true - }, - "raw-body": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", - "integrity": "sha1-GzJOzmtXBuFThVvBFIxlu39uoMM=", - "dev": true, - "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.3", - "iconv-lite": "0.4.23", - "unpipe": "1.0.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", - "dev": true - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", - "dev": true - } - } - }, - "karma-jasmine": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-1.1.2.tgz", - "integrity": "sha1-OU8rJf+0pkS5rabyLUQ+L9CIhsM=", - "dev": true - }, - "karma-phantomjs-launcher": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/karma-phantomjs-launcher/-/karma-phantomjs-launcher-1.0.4.tgz", - "integrity": "sha1-0jyjSAG9qYY60xjju0vUBisTrNI=", - "dev": true, - "requires": { - "lodash": "^4.0.1", - "phantomjs-prebuilt": "^2.1.7" - } - }, - "kew": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/kew/-/kew-0.7.0.tgz", - "integrity": "sha1-edk9LTM2PW/dKXCzNdkUGtWR15s=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha1-ARRrNqYhjmTljzqNZt5df8b20FE=", - "dev": true - }, - "klaw": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", - "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.9" - }, - "dependencies": { - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true, - "optional": true - } - } - }, - "lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "dev": true - }, - "lazy-req": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/lazy-req/-/lazy-req-1.1.0.tgz", - "integrity": "sha1-va6+rTD42CQDnODOFJ1Nqge6H6w=", - "dev": true, - "optional": true - }, - "lazystream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", - "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", - "dev": true, - "requires": { - "readable-stream": "^2.0.5" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "less": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/less/-/less-2.7.3.tgz", - "integrity": "sha1-zBJg9RyQCp7A2R+2mYE54CUHtjs=", - "dev": true, - "requires": { - "errno": "^0.1.1", - "graceful-fs": "^4.1.2", - "image-size": "~0.5.0", - "mime": "^1.2.11", - "mkdirp": "^0.5.0", - "promise": "^7.1.1", - "request": "2.81.0", - "source-map": "^0.5.3" - }, - "dependencies": { - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true, - "optional": true - } - } - }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "libbase64": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-0.1.0.tgz", - "integrity": "sha1-YjUag5VjrF/1vSbxL2Dpgwu3UeY=", - "dev": true - }, - "libmime": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/libmime/-/libmime-3.0.0.tgz", - "integrity": "sha1-UaGp50SOy9Ms2lRCFnW7IbwJPaY=", - "dev": true, - "requires": { - "iconv-lite": "0.4.15", - "libbase64": "0.1.0", - "libqp": "1.1.0" - }, - "dependencies": { - "iconv-lite": { - "version": "0.4.15", - "resolved": "http://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", - "integrity": "sha1-/iZaIYrGpXz+hUkn6dBMGYJe3es=", - "dev": true - } - } - }, - "libqp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/libqp/-/libqp-1.1.0.tgz", - "integrity": "sha1-9ebgatdLeU+1tbZpiL9yjvHe2+g=", - "dev": true - }, - "liftoff": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", - "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", - "dev": true, - "requires": { - "extend": "^3.0.0", - "findup-sync": "^2.0.0", - "fined": "^1.0.1", - "flagged-respawn": "^1.0.0", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.0", - "rechoir": "^0.6.2", - "resolve": "^1.1.7" - } - }, - "livereload-js": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.3.0.tgz", - "integrity": "sha1-w6si6Kr1vzUF2A0JjLrWdyZUjJo=", - "dev": true - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - }, - "dependencies": { - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } - } - } - }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - }, - "lodash._basecopy": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", - "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", - "dev": true - }, - "lodash._basetostring": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", - "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", - "dev": true - }, - "lodash._basevalues": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", - "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", - "dev": true - }, - "lodash._escapehtmlchar": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._escapehtmlchar/-/lodash._escapehtmlchar-2.4.1.tgz", - "integrity": "sha1-32fDu2t+jh6DGrSL+geVuSr+iZ0=", - "dev": true, - "requires": { - "lodash._htmlescapes": "~2.4.1" - } - }, - "lodash._escapestringchar": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._escapestringchar/-/lodash._escapestringchar-2.4.1.tgz", - "integrity": "sha1-7P4iYYoq3lC/7qQ5N+Ud9m8O23I=", - "dev": true - }, - "lodash._getnative": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", - "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", - "dev": true - }, - "lodash._htmlescapes": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz", - "integrity": "sha1-MtFL8IRLbeb4tioFG09nwii2JMs=", - "dev": true - }, - "lodash._isiterateecall": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", - "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", - "dev": true - }, - "lodash._isnative": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", - "integrity": "sha1-PqZAS3hKe+g2x7V1gOHN95sUgyw=", - "dev": true - }, - "lodash._objecttypes": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz", - "integrity": "sha1-fAt/admKH3ZSn4kLDNsbTf7BHBE=", - "dev": true - }, - "lodash._reescape": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", - "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", - "dev": true - }, - "lodash._reevaluate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", - "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", - "dev": true - }, - "lodash._reinterpolate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", - "dev": true - }, - "lodash._reunescapedhtml": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz", - "integrity": "sha1-dHxPxAED6zu4oJduVx96JlnpO6c=", - "dev": true, - "requires": { - "lodash._htmlescapes": "~2.4.1", - "lodash.keys": "~2.4.1" - }, - "dependencies": { - "lodash.keys": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", - "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", - "dev": true, - "requires": { - "lodash._isnative": "~2.4.1", - "lodash._shimkeys": "~2.4.1", - "lodash.isobject": "~2.4.1" - } - } - } - }, - "lodash._root": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", - "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", - "dev": true - }, - "lodash._shimkeys": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", - "integrity": "sha1-bpzJZm/wgfC1psl4uD4kLmlJ0gM=", - "dev": true, - "requires": { - "lodash._objecttypes": "~2.4.1" - } - }, - "lodash.clone": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", - "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=", - "dev": true - }, - "lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", - "dev": true - }, - "lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=", - "dev": true - }, - "lodash.escape": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", - "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", - "dev": true, - "requires": { - "lodash._root": "^3.0.0" - } - }, - "lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", - "dev": true - }, - "lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", - "dev": true - }, - "lodash.isarray": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", - "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", - "dev": true - }, - "lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", - "dev": true - }, - "lodash.isobject": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", - "integrity": "sha1-Wi5H/mmVPx7mMafrof5k0tBlWPU=", - "dev": true, - "requires": { - "lodash._objecttypes": "~2.4.1" - } - }, - "lodash.keys": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", - "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", - "dev": true, - "requires": { - "lodash._getnative": "^3.0.0", - "lodash.isarguments": "^3.0.0", - "lodash.isarray": "^3.0.0" - } - }, - "lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", - "dev": true - }, - "lodash.merge": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.1.tgz", - "integrity": "sha1-rcJdnLmbk5HFliTzefu6YNcRHVQ=", - "dev": true - }, - "lodash.partialright": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/lodash.partialright/-/lodash.partialright-4.2.1.tgz", - "integrity": "sha1-ATDYDoM2MmTUAHTzKbij56ihzEs=", - "dev": true - }, - "lodash.pick": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", - "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=", - "dev": true - }, - "lodash.restparam": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", - "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", - "dev": true - }, - "lodash.template": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", - "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", - "dev": true, - "requires": { - "lodash._basecopy": "^3.0.0", - "lodash._basetostring": "^3.0.0", - "lodash._basevalues": "^3.0.0", - "lodash._isiterateecall": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.escape": "^3.0.0", - "lodash.keys": "^3.0.0", - "lodash.restparam": "^3.0.0", - "lodash.templatesettings": "^3.0.0" - } - }, - "lodash.templatesettings": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", - "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", - "dev": true, - "requires": { - "lodash._reinterpolate": "^3.0.0", - "lodash.escape": "^3.0.0" - } - }, - "lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", - "dev": true - }, - "lodash.values": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.values/-/lodash.values-2.4.1.tgz", - "integrity": "sha1-q/UUQ2s8twUAFieXjLzzCxKA7qQ=", - "dev": true, - "requires": { - "lodash.keys": "~2.4.1" - }, - "dependencies": { - "lodash.keys": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", - "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", - "dev": true, - "requires": { - "lodash._isnative": "~2.4.1", - "lodash._shimkeys": "~2.4.1", - "lodash.isobject": "~2.4.1" - } - } - } - }, - "log4js": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-2.11.0.tgz", - "integrity": "sha1-vzkC7/ZcaSPZzpz70ttUFg40AFo=", - "dev": true, - "requires": { - "amqplib": "^0.5.2", - "axios": "^0.15.3", - "circular-json": "^0.5.4", - "date-format": "^1.2.0", - "debug": "^3.1.0", - "hipchat-notifier": "^1.1.0", - "loggly": "^1.1.0", - "mailgun-js": "^0.18.0", - "nodemailer": "^2.5.0", - "redis": "^2.7.1", - "semver": "^5.5.0", - "slack-node": "~0.2.0", - "streamroller": "0.7.0" - }, - "dependencies": { - "circular-json": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.7.tgz", - "integrity": "sha512-/pXoV1JA847qRKPrHbBK6YIBGFF8GOP4wzSgUOA7q0ew0vAv0iJswP+2/nZQ9uzA3Azi7eTrg9L2yzXc/7ZMIA==", - "dev": true - }, - "debug": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.5.tgz", - "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, - "semver": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", - "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==", - "dev": true - } - } - }, - "logalot": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/logalot/-/logalot-2.1.0.tgz", - "integrity": "sha1-X46MkNME7fElMJUaVVSruMXj9VI=", - "dev": true, - "optional": true, - "requires": { - "figures": "^1.3.5", - "squeak": "^1.0.0" - }, - "dependencies": { - "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true, - "optional": true, - "requires": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" - } - } - } - }, - "loggly": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/loggly/-/loggly-1.1.1.tgz", - "integrity": "sha1-Cg/B0/o6XsRP3HuJe+uipGlc6+4=", - "dev": true, - "optional": true, - "requires": { - "json-stringify-safe": "5.0.x", - "request": "2.75.x", - "timespan": "2.3.x" - }, - "dependencies": { - "bl": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.1.2.tgz", - "integrity": "sha1-/cqHGplxOqANGeO7ukHER4emU5g=", - "dev": true, - "optional": true, - "requires": { - "readable-stream": "~2.0.5" - } - }, - "caseless": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", - "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", - "dev": true, - "optional": true - }, - "commander": { - "version": "2.18.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.18.0.tgz", - "integrity": "sha512-6CYPa+JP2ftfRU2qkDK+UTVeQYosOg/2GbcjIcKPHfinyOLPVGXu/ovN86RP49Re5ndJK1N0kuiidFFuepc4ZQ==", - "dev": true, - "optional": true - }, - "form-data": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.0.0.tgz", - "integrity": "sha1-bwrrrcxdoWwT4ezBETfYX5uIOyU=", - "dev": true, - "optional": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.5", - "mime-types": "^2.1.11" - } - }, - "har-validator": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", - "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", - "dev": true, - "optional": true, - "requires": { - "chalk": "^1.1.1", - "commander": "^2.9.0", - "is-my-json-valid": "^2.12.4", - "pinkie-promise": "^2.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true, - "optional": true - }, - "node-uuid": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", - "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=", - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", - "dev": true, - "optional": true - }, - "qs": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.3.tgz", - "integrity": "sha1-HPyyXBCpsrSDBT/zn138kjOQjP4=", - "dev": true, - "optional": true - }, - "readable-stream": { - "version": "2.0.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", - "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "~1.0.0", - "process-nextick-args": "~1.0.6", - "string_decoder": "~0.10.x", - "util-deprecate": "~1.0.1" - } - }, - "request": { - "version": "2.75.0", - "resolved": "http://registry.npmjs.org/request/-/request-2.75.0.tgz", - "integrity": "sha1-0rgmiihtoT6qXQGt9dGMyQ9lfZM=", - "dev": true, - "optional": true, - "requires": { - "aws-sign2": "~0.6.0", - "aws4": "^1.2.1", - "bl": "~1.1.2", - "caseless": "~0.11.0", - "combined-stream": "~1.0.5", - "extend": "~3.0.0", - "forever-agent": "~0.6.1", - "form-data": "~2.0.0", - "har-validator": "~2.0.6", - "hawk": "~3.1.3", - "http-signature": "~1.1.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.7", - "node-uuid": "~1.4.7", - "oauth-sign": "~0.8.1", - "qs": "~6.2.0", - "stringstream": "~0.0.4", - "tough-cookie": "~2.3.0", - "tunnel-agent": "~0.4.1" - } - } - } - }, - "longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", - "dev": true - }, - "loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" - } - }, - "loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "dev": true, - "requires": { - "currently-unhandled": "^0.4.1", - "signal-exit": "^3.0.0" - } - }, - "lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha1-b54wtHCE2XGnyCD/FabFFnt0wm8=", - "dev": true - }, - "lpad-align": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/lpad-align/-/lpad-align-1.1.2.tgz", - "integrity": "sha1-IfYArBwwlcPG5JfuZyce4ISB/p4=", - "dev": true, - "optional": true, - "requires": { - "get-stdin": "^4.0.1", - "indent-string": "^2.1.0", - "longest": "^1.0.0", - "meow": "^3.3.0" - } - }, - "lru-cache": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", - "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", - "dev": true - }, - "mailcomposer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/mailcomposer/-/mailcomposer-4.0.1.tgz", - "integrity": "sha1-DhxEsqB890DuF9wUm6AJ8Zyt/rQ=", - "dev": true, - "optional": true, - "requires": { - "buildmail": "4.0.1", - "libmime": "3.0.0" - } - }, - "mailgun-js": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/mailgun-js/-/mailgun-js-0.18.1.tgz", - "integrity": "sha1-7jmqGNe7WYpc6e3oSvtoHe/IprA=", - "dev": true, - "optional": true, - "requires": { - "async": "~2.6.0", - "debug": "~3.1.0", - "form-data": "~2.3.0", - "inflection": "~1.12.0", - "is-stream": "^1.1.0", - "path-proxy": "~1.0.0", - "promisify-call": "^2.0.2", - "proxy-agent": "~3.0.0", - "tsscmp": "~1.0.0" - }, - "dependencies": { - "combined-stream": { - "version": "1.0.6", - "resolved": "http://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", - "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", - "dev": true, - "optional": true, - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", - "dev": true, - "optional": true, - "requires": { - "ms": "2.0.0" - } - }, - "form-data": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", - "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", - "dev": true, - "optional": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "1.0.6", - "mime-types": "^2.1.12" - } - } - } - }, - "make-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", - "integrity": "sha1-ecEDO4BRW9bSTsmTPoYMp17ifww=", - "dev": true, - "requires": { - "pify": "^3.0.0" - }, - "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } - } - }, - "make-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", - "integrity": "sha1-KbM/MSqo9UfEpeSQ9Wr87JkTOtY=", - "dev": true, - "requires": { - "kind-of": "^6.0.2" - } - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true - }, - "map-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", - "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=", - "dev": true - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "requires": { - "object-visit": "^1.0.0" - } - }, - "marked": { - "version": "0.3.2", - "resolved": "http://registry.npmjs.org/marked/-/marked-0.3.2.tgz", - "integrity": "sha1-AV2xWIZEOPJKZL3WGgQotBhwbQk=", - "dev": true - }, - "math-expression-evaluator": { - "version": "1.2.17", - "resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz", - "integrity": "sha1-3oGf282E3M2PrlnGrreWFbnSZqw=", - "dev": true - }, - "math-random": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz", - "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=", - "dev": true - }, - "mdn-data": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-1.1.4.tgz", - "integrity": "sha1-ULXU/8RXUnZXPE7tuHgIEqhBnwE=", - "dev": true - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", - "dev": true - }, - "meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", - "dev": true, - "requires": { - "camelcase-keys": "^2.0.0", - "decamelize": "^1.1.2", - "loud-rejection": "^1.0.0", - "map-obj": "^1.0.1", - "minimist": "^1.1.3", - "normalize-package-data": "^2.3.4", - "object-assign": "^4.0.1", - "read-pkg-up": "^1.0.1", - "redent": "^1.0.0", - "trim-newlines": "^1.0.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, - "merge-stream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", - "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", - "dev": true, - "requires": { - "readable-stream": "^2.0.1" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "method-override": { - "version": "2.3.10", - "resolved": "https://registry.npmjs.org/method-override/-/method-override-2.3.10.tgz", - "integrity": "sha1-49r41d7hDdLc59SuiNYrvud0drQ=", - "dev": true, - "requires": { - "debug": "2.6.9", - "methods": "~1.1.2", - "parseurl": "~1.3.2", - "vary": "~1.1.2" - }, - "dependencies": { - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", - "dev": true - } - } - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha1-cIWbyVyYQJUvNZoGij/En57PrCM=", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "mime": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", - "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=", - "dev": true - }, - "mime-db": { - "version": "1.36.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz", - "integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw==", - "dev": true - }, - "mime-types": { - "version": "2.1.20", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz", - "integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==", - "dev": true, - "requires": { - "mime-db": "~1.36.0" - } - }, - "mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha1-ggyGo5M0ZA6ZUWkovQP8qIBX0CI=", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - }, - "mixin-deep": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", - "integrity": "sha1-pJ5yaNzhoNlpjkUybFYm3zVD0P4=", - "dev": true, - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, - "requires": { - "minimist": "0.0.8" - } - }, - "morgan": { - "version": "1.6.1", - "resolved": "http://registry.npmjs.org/morgan/-/morgan-1.6.1.tgz", - "integrity": "sha1-X9gYOYxoGcuiinzWZk8pL+HAu/I=", - "dev": true, - "requires": { - "basic-auth": "~1.0.3", - "debug": "~2.2.0", - "depd": "~1.0.1", - "on-finished": "~2.3.0", - "on-headers": "~1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "http://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "0.7.1" - } - }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - } - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "multiparty": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/multiparty/-/multiparty-3.3.2.tgz", - "integrity": "sha1-Nd5oBNwZZD5SSfPT473GyM4wHT8=", - "dev": true, - "requires": { - "readable-stream": "~1.1.9", - "stream-counter": "~0.2.0" - } - }, - "multipipe": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", - "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", - "dev": true, - "requires": { - "duplexer2": "0.0.2" - } - }, - "mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", - "dev": true - }, - "nan": { - "version": "2.11.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.11.1.tgz", - "integrity": "sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA==", - "dev": true, - "optional": true - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - } - }, - "natives": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.5.tgz", - "integrity": "sha512-1pJ+02gl2KJgCPFtpZGtuD4lGSJnIZvvFHCQTOeDRMSXjfu2GmYWuhI8NFMA4W2I5NNFRbfy/YCiVt4CgNpP8A==", - "dev": true - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "negotiator": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.5.3.tgz", - "integrity": "sha1-Jp1cR2gQ7JLtvntsLygxY4T5p+g=", - "dev": true - }, - "netmask": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz", - "integrity": "sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU=", - "dev": true, - "optional": true - }, - "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, - "node-fs": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/node-fs/-/node-fs-0.1.7.tgz", - "integrity": "sha1-MjI8zLRsn78PwRgS1FAhzDHTJbs=", - "dev": true - }, - "node-releases": { - "version": "1.0.0-alpha.12", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.0.0-alpha.12.tgz", - "integrity": "sha512-VPB4rTPqpVyWKBHbSa4YPFme3+8WHsOSpvbp0Mfj0bWsC8TEjt4HQrLl1hsBDELlp1nB4lflSgSuGTYiuyaP7Q==", - "dev": true, - "requires": { - "semver": "^5.3.0" - }, - "dependencies": { - "semver": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", - "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==", - "dev": true - } - } - }, - "node-status-codes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-status-codes/-/node-status-codes-1.0.0.tgz", - "integrity": "sha1-WuVUHQJGRdMqWPzdyc7s6nrjrC8=", - "dev": true - }, - "node.extend": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/node.extend/-/node.extend-1.1.6.tgz", - "integrity": "sha1-p7iCyC1sk6SGOlUEvV3o7IYli5Y=", - "dev": true, - "requires": { - "is": "^3.1.0" - } - }, - "nodemailer": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-2.7.2.tgz", - "integrity": "sha1-8kLmSa7q45tsftdA73sGHEBNMPk=", - "dev": true, - "optional": true, - "requires": { - "libmime": "3.0.0", - "mailcomposer": "4.0.1", - "nodemailer-direct-transport": "3.3.2", - "nodemailer-shared": "1.1.0", - "nodemailer-smtp-pool": "2.8.2", - "nodemailer-smtp-transport": "2.7.2", - "socks": "1.1.9" - }, - "dependencies": { - "smart-buffer": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-1.1.15.tgz", - "integrity": "sha1-fxFLW2X6s+KjWqd1uxLw0cZJvxY=", - "dev": true, - "optional": true - }, - "socks": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/socks/-/socks-1.1.9.tgz", - "integrity": "sha1-Yo1+TQSRJDVEWsC25Fk3bLPm1pE=", - "dev": true, - "optional": true, - "requires": { - "ip": "^1.1.2", - "smart-buffer": "^1.0.4" - } - } - } - }, - "nodemailer-direct-transport": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/nodemailer-direct-transport/-/nodemailer-direct-transport-3.3.2.tgz", - "integrity": "sha1-6W+vuQNYVglH5WkBfZfmBzilCoY=", - "dev": true, - "optional": true, - "requires": { - "nodemailer-shared": "1.1.0", - "smtp-connection": "2.12.0" - } - }, - "nodemailer-fetch": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/nodemailer-fetch/-/nodemailer-fetch-1.6.0.tgz", - "integrity": "sha1-ecSQihwPXzdbc/6IjamCj23JY6Q=", - "dev": true - }, - "nodemailer-shared": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", - "integrity": "sha1-z1mU4v0mjQD1zw+nZ6CBae2wfsA=", - "dev": true, - "requires": { - "nodemailer-fetch": "1.6.0" - } - }, - "nodemailer-smtp-pool": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/nodemailer-smtp-pool/-/nodemailer-smtp-pool-2.8.2.tgz", - "integrity": "sha1-LrlNbPhXgLG0clzoU7nL1ejajHI=", - "dev": true, - "optional": true, - "requires": { - "nodemailer-shared": "1.1.0", - "nodemailer-wellknown": "0.1.10", - "smtp-connection": "2.12.0" - } - }, - "nodemailer-smtp-transport": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/nodemailer-smtp-transport/-/nodemailer-smtp-transport-2.7.2.tgz", - "integrity": "sha1-A9ccdjFPFKx9vHvwM6am0W1n+3c=", - "dev": true, - "optional": true, - "requires": { - "nodemailer-shared": "1.1.0", - "nodemailer-wellknown": "0.1.10", - "smtp-connection": "2.12.0" - } - }, - "nodemailer-wellknown": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/nodemailer-wellknown/-/nodemailer-wellknown-0.1.10.tgz", - "integrity": "sha1-WG24EB2zDLRDjrVGc3pBqtDPE9U=", - "dev": true - }, - "nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, - "requires": { - "abbrev": "1" - } - }, - "normalize-package-data": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha1-EvlaMH1YNSB1oEkHuErIvpisAS8=", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "is-builtin-module": "^1.0.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - }, - "normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", - "dev": true - }, - "normalize-url": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", - "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", - "dev": true, - "requires": { - "object-assign": "^4.0.1", - "prepend-http": "^1.0.0", - "query-string": "^4.1.0", - "sort-keys": "^1.0.0" - } - }, - "npm": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/npm/-/npm-6.4.1.tgz", - "integrity": "sha512-mXJL1NTVU136PtuopXCUQaNWuHlXCTp4McwlSW8S9/Aj8OEPAlSBgo8og7kJ01MjCDrkmqFQTvN5tTEhBMhXQg==", - "requires": { - "JSONStream": "^1.3.4", - "abbrev": "~1.1.1", - "ansicolors": "~0.3.2", - "ansistyles": "~0.1.3", - "aproba": "~1.2.0", - "archy": "~1.0.0", - "bin-links": "^1.1.2", - "bluebird": "~3.5.1", - "byte-size": "^4.0.3", - "cacache": "^11.2.0", - "call-limit": "~1.1.0", - "chownr": "~1.0.1", - "ci-info": "^1.4.0", - "cli-columns": "^3.1.2", - "cli-table3": "^0.5.0", - "cmd-shim": "~2.0.2", - "columnify": "~1.5.4", - "config-chain": "~1.1.11", - "debuglog": "*", - "detect-indent": "~5.0.0", - "detect-newline": "^2.1.0", - "dezalgo": "~1.0.3", - "editor": "~1.0.0", - "figgy-pudding": "^3.4.1", - "find-npm-prefix": "^1.0.2", - "fs-vacuum": "~1.2.10", - "fs-write-stream-atomic": "~1.0.10", - "gentle-fs": "^2.0.1", - "glob": "~7.1.2", - "graceful-fs": "~4.1.11", - "has-unicode": "~2.0.1", - "hosted-git-info": "^2.7.1", - "iferr": "^1.0.2", - "imurmurhash": "*", - "inflight": "~1.0.6", - "inherits": "~2.0.3", - "ini": "^1.3.5", - "init-package-json": "^1.10.3", - "is-cidr": "^2.0.6", - "json-parse-better-errors": "^1.0.2", - "lazy-property": "~1.0.0", - "libcipm": "^2.0.2", - "libnpmhook": "^4.0.1", - "libnpx": "^10.2.0", - "lock-verify": "^2.0.2", - "lockfile": "^1.0.4", - "lodash._baseindexof": "*", - "lodash._baseuniq": "~4.6.0", - "lodash._bindcallback": "*", - "lodash._cacheindexof": "*", - "lodash._createcache": "*", - "lodash._getnative": "*", - "lodash.clonedeep": "~4.5.0", - "lodash.restparam": "*", - "lodash.union": "~4.6.0", - "lodash.uniq": "~4.5.0", - "lodash.without": "~4.4.0", - "lru-cache": "^4.1.3", - "meant": "~1.0.1", - "mississippi": "^3.0.0", - "mkdirp": "~0.5.1", - "move-concurrently": "^1.0.1", - "node-gyp": "^3.8.0", - "nopt": "~4.0.1", - "normalize-package-data": "~2.4.0", - "npm-audit-report": "^1.3.1", - "npm-cache-filename": "~1.0.2", - "npm-install-checks": "~3.0.0", - "npm-lifecycle": "^2.1.0", - "npm-package-arg": "^6.1.0", - "npm-packlist": "^1.1.11", - "npm-pick-manifest": "^2.1.0", - "npm-profile": "^3.0.2", - "npm-registry-client": "^8.6.0", - "npm-registry-fetch": "^1.1.0", - "npm-user-validate": "~1.0.0", - "npmlog": "~4.1.2", - "once": "~1.4.0", - "opener": "^1.5.0", - "osenv": "^0.1.5", - "pacote": "^8.1.6", - "path-is-inside": "~1.0.2", - "promise-inflight": "~1.0.1", - "qrcode-terminal": "^0.12.0", - "query-string": "^6.1.0", - "qw": "~1.0.1", - "read": "~1.0.7", - "read-cmd-shim": "~1.0.1", - "read-installed": "~4.0.3", - "read-package-json": "^2.0.13", - "read-package-tree": "^5.2.1", - "readable-stream": "^2.3.6", - "readdir-scoped-modules": "*", - "request": "^2.88.0", - "retry": "^0.12.0", - "rimraf": "~2.6.2", - "safe-buffer": "^5.1.2", - "semver": "^5.5.0", - "sha": "~2.0.1", - "slide": "~1.1.6", - "sorted-object": "~2.0.1", - "sorted-union-stream": "~2.1.3", - "ssri": "^6.0.0", - "stringify-package": "^1.0.0", - "tar": "^4.4.6", - "text-table": "~0.2.0", - "tiny-relative-date": "^1.3.0", - "uid-number": "0.0.6", - "umask": "~1.1.0", - "unique-filename": "~1.1.0", - "unpipe": "~1.0.0", - "update-notifier": "^2.5.0", - "uuid": "^3.3.2", - "validate-npm-package-license": "^3.0.4", - "validate-npm-package-name": "~3.0.0", - "which": "^1.3.1", - "worker-farm": "^1.6.0", - "write-file-atomic": "^2.3.0" - }, - "dependencies": { - "JSONStream": { - "version": "1.3.4", - "bundled": true, - "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - } - }, - "abbrev": { - "version": "1.1.1", - "bundled": true - }, - "agent-base": { - "version": "4.2.0", - "bundled": true, - "requires": { - "es6-promisify": "^5.0.0" - } - }, - "agentkeepalive": { - "version": "3.4.1", - "bundled": true, - "requires": { - "humanize-ms": "^1.2.1" - } - }, - "ajv": { - "version": "5.5.2", - "bundled": true, - "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" - } - }, - "ansi-align": { - "version": "2.0.0", - "bundled": true, - "requires": { - "string-width": "^2.0.0" - } - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true - }, - "ansi-styles": { - "version": "3.2.1", - "bundled": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "ansicolors": { - "version": "0.3.2", - "bundled": true - }, - "ansistyles": { - "version": "0.1.3", - "bundled": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true - }, - "archy": { - "version": "1.0.0", - "bundled": true - }, - "are-we-there-yet": { - "version": "1.1.4", - "bundled": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "asap": { - "version": "2.0.6", - "bundled": true - }, - "asn1": { - "version": "0.2.4", - "bundled": true, - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "bundled": true - }, - "asynckit": { - "version": "0.4.0", - "bundled": true - }, - "aws-sign2": { - "version": "0.7.0", - "bundled": true - }, - "aws4": { - "version": "1.8.0", - "bundled": true - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true - }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "bundled": true, - "optional": true, - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "bin-links": { - "version": "1.1.2", - "bundled": true, - "requires": { - "bluebird": "^3.5.0", - "cmd-shim": "^2.0.2", - "gentle-fs": "^2.0.0", - "graceful-fs": "^4.1.11", - "write-file-atomic": "^2.3.0" - } - }, - "block-stream": { - "version": "0.0.9", - "bundled": true, - "requires": { - "inherits": "~2.0.0" - } - }, - "bluebird": { - "version": "3.5.1", - "bundled": true - }, - "boxen": { - "version": "1.3.0", - "bundled": true, - "requires": { - "ansi-align": "^2.0.0", - "camelcase": "^4.0.0", - "chalk": "^2.0.1", - "cli-boxes": "^1.0.0", - "string-width": "^2.0.0", - "term-size": "^1.2.0", - "widest-line": "^2.0.0" - } - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "buffer-from": { - "version": "1.0.0", - "bundled": true - }, - "builtin-modules": { - "version": "1.1.1", - "bundled": true - }, - "builtins": { - "version": "1.0.3", - "bundled": true - }, - "byline": { - "version": "5.0.0", - "bundled": true - }, - "byte-size": { - "version": "4.0.3", - "bundled": true - }, - "cacache": { - "version": "11.2.0", - "bundled": true, - "requires": { - "bluebird": "^3.5.1", - "chownr": "^1.0.1", - "figgy-pudding": "^3.1.0", - "glob": "^7.1.2", - "graceful-fs": "^4.1.11", - "lru-cache": "^4.1.3", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "promise-inflight": "^1.0.1", - "rimraf": "^2.6.2", - "ssri": "^6.0.0", - "unique-filename": "^1.1.0", - "y18n": "^4.0.0" - } - }, - "call-limit": { - "version": "1.1.0", - "bundled": true - }, - "camelcase": { - "version": "4.1.0", - "bundled": true - }, - "capture-stack-trace": { - "version": "1.0.0", - "bundled": true - }, - "caseless": { - "version": "0.12.0", - "bundled": true - }, - "chalk": { - "version": "2.4.1", - "bundled": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "chownr": { - "version": "1.0.1", - "bundled": true - }, - "ci-info": { - "version": "1.4.0", - "bundled": true - }, - "cidr-regex": { - "version": "2.0.9", - "bundled": true, - "requires": { - "ip-regex": "^2.1.0" - } - }, - "cli-boxes": { - "version": "1.0.0", - "bundled": true - }, - "cli-columns": { - "version": "3.1.2", - "bundled": true, - "requires": { - "string-width": "^2.0.0", - "strip-ansi": "^3.0.1" - } - }, - "cli-table3": { - "version": "0.5.0", - "bundled": true, - "requires": { - "colors": "^1.1.2", - "object-assign": "^4.1.0", - "string-width": "^2.1.1" - } - }, - "cliui": { - "version": "4.1.0", - "bundled": true, - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "bundled": true - }, - "strip-ansi": { - "version": "4.0.0", - "bundled": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "clone": { - "version": "1.0.4", - "bundled": true - }, - "cmd-shim": { - "version": "2.0.2", - "bundled": true, - "requires": { - "graceful-fs": "^4.1.2", - "mkdirp": "~0.5.0" - } - }, - "co": { - "version": "4.6.0", - "bundled": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true - }, - "color-convert": { - "version": "1.9.1", - "bundled": true, - "requires": { - "color-name": "^1.1.1" - } - }, - "color-name": { - "version": "1.1.3", - "bundled": true - }, - "colors": { - "version": "1.1.2", - "bundled": true, - "optional": true - }, - "columnify": { - "version": "1.5.4", - "bundled": true, - "requires": { - "strip-ansi": "^3.0.0", - "wcwidth": "^1.0.0" - } - }, - "combined-stream": { - "version": "1.0.6", - "bundled": true, - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "concat-map": { - "version": "0.0.1", - "bundled": true - }, - "concat-stream": { - "version": "1.6.2", - "bundled": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "config-chain": { - "version": "1.1.11", - "bundled": true, - "requires": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, - "configstore": { - "version": "3.1.2", - "bundled": true, - "requires": { - "dot-prop": "^4.1.0", - "graceful-fs": "^4.1.2", - "make-dir": "^1.0.0", - "unique-string": "^1.0.0", - "write-file-atomic": "^2.0.0", - "xdg-basedir": "^3.0.0" - } - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true - }, - "copy-concurrently": { - "version": "1.0.5", - "bundled": true, - "requires": { - "aproba": "^1.1.1", - "fs-write-stream-atomic": "^1.0.8", - "iferr": "^0.1.5", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.0" - }, - "dependencies": { - "iferr": { - "version": "0.1.5", - "bundled": true - } - } - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true - }, - "create-error-class": { - "version": "3.0.2", - "bundled": true, - "requires": { - "capture-stack-trace": "^1.0.0" - } - }, - "cross-spawn": { - "version": "5.1.0", - "bundled": true, - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "crypto-random-string": { - "version": "1.0.0", - "bundled": true - }, - "cyclist": { - "version": "0.2.2", - "bundled": true - }, - "dashdash": { - "version": "1.14.1", - "bundled": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, - "debug": { - "version": "3.1.0", - "bundled": true, - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "bundled": true - } - } - }, - "debuglog": { - "version": "1.0.1", - "bundled": true - }, - "decamelize": { - "version": "1.2.0", - "bundled": true - }, - "decode-uri-component": { - "version": "0.2.0", - "bundled": true - }, - "deep-extend": { - "version": "0.5.1", - "bundled": true - }, - "defaults": { - "version": "1.0.3", - "bundled": true, - "requires": { - "clone": "^1.0.2" - } - }, - "delayed-stream": { - "version": "1.0.0", - "bundled": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true - }, - "detect-indent": { - "version": "5.0.0", - "bundled": true - }, - "detect-newline": { - "version": "2.1.0", - "bundled": true - }, - "dezalgo": { - "version": "1.0.3", - "bundled": true, - "requires": { - "asap": "^2.0.0", - "wrappy": "1" - } - }, - "dot-prop": { - "version": "4.2.0", - "bundled": true, - "requires": { - "is-obj": "^1.0.0" - } - }, - "dotenv": { - "version": "5.0.1", - "bundled": true - }, - "duplexer3": { - "version": "0.1.4", - "bundled": true - }, - "duplexify": { - "version": "3.6.0", - "bundled": true, - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "ecc-jsbn": { - "version": "0.1.2", - "bundled": true, - "optional": true, - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "editor": { - "version": "1.0.0", - "bundled": true - }, - "encoding": { - "version": "0.1.12", - "bundled": true, - "requires": { - "iconv-lite": "~0.4.13" - } - }, - "end-of-stream": { - "version": "1.4.1", - "bundled": true, - "requires": { - "once": "^1.4.0" - } - }, - "err-code": { - "version": "1.1.2", - "bundled": true - }, - "errno": { - "version": "0.1.7", - "bundled": true, - "requires": { - "prr": "~1.0.1" - } - }, - "es6-promise": { - "version": "4.2.4", - "bundled": true - }, - "es6-promisify": { - "version": "5.0.0", - "bundled": true, - "requires": { - "es6-promise": "^4.0.3" - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "bundled": true - }, - "execa": { - "version": "0.7.0", - "bundled": true, - "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "extend": { - "version": "3.0.2", - "bundled": true - }, - "extsprintf": { - "version": "1.3.0", - "bundled": true - }, - "fast-deep-equal": { - "version": "1.1.0", - "bundled": true - }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "bundled": true - }, - "figgy-pudding": { - "version": "3.4.1", - "bundled": true - }, - "find-npm-prefix": { - "version": "1.0.2", - "bundled": true - }, - "find-up": { - "version": "2.1.0", - "bundled": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "flush-write-stream": { - "version": "1.0.3", - "bundled": true, - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.4" - } - }, - "forever-agent": { - "version": "0.6.1", - "bundled": true - }, - "form-data": { - "version": "2.3.2", - "bundled": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "1.0.6", - "mime-types": "^2.1.12" - } - }, - "from2": { - "version": "2.3.0", - "bundled": true, - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" - } - }, - "fs-minipass": { - "version": "1.2.5", - "bundled": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "fs-vacuum": { - "version": "1.2.10", - "bundled": true, - "requires": { - "graceful-fs": "^4.1.2", - "path-is-inside": "^1.0.1", - "rimraf": "^2.5.2" - } - }, - "fs-write-stream-atomic": { - "version": "1.0.10", - "bundled": true, - "requires": { - "graceful-fs": "^4.1.2", - "iferr": "^0.1.5", - "imurmurhash": "^0.1.4", - "readable-stream": "1 || 2" - }, - "dependencies": { - "iferr": { - "version": "0.1.5", - "bundled": true - } - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true - }, - "fstream": { - "version": "1.0.11", - "bundled": true, - "requires": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - } - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - }, - "dependencies": { - "string-width": { - "version": "1.0.2", - "bundled": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - } - } - }, - "genfun": { - "version": "4.0.1", - "bundled": true - }, - "gentle-fs": { - "version": "2.0.1", - "bundled": true, - "requires": { - "aproba": "^1.1.2", - "fs-vacuum": "^1.2.10", - "graceful-fs": "^4.1.11", - "iferr": "^0.1.5", - "mkdirp": "^0.5.1", - "path-is-inside": "^1.0.2", - "read-cmd-shim": "^1.0.1", - "slide": "^1.1.6" - }, - "dependencies": { - "iferr": { - "version": "0.1.5", - "bundled": true - } - } - }, - "get-caller-file": { - "version": "1.0.2", - "bundled": true - }, - "get-stream": { - "version": "3.0.0", - "bundled": true - }, - "getpass": { - "version": "0.1.7", - "bundled": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, - "glob": { - "version": "7.1.2", - "bundled": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "global-dirs": { - "version": "0.1.1", - "bundled": true, - "requires": { - "ini": "^1.3.4" - } - }, - "got": { - "version": "6.7.1", - "bundled": true, - "requires": { - "create-error-class": "^3.0.0", - "duplexer3": "^0.1.4", - "get-stream": "^3.0.0", - "is-redirect": "^1.0.0", - "is-retry-allowed": "^1.0.0", - "is-stream": "^1.0.0", - "lowercase-keys": "^1.0.0", - "safe-buffer": "^5.0.1", - "timed-out": "^4.0.0", - "unzip-response": "^2.0.1", - "url-parse-lax": "^1.0.0" - } - }, - "graceful-fs": { - "version": "4.1.11", - "bundled": true - }, - "har-schema": { - "version": "2.0.0", - "bundled": true - }, - "har-validator": { - "version": "5.1.0", - "bundled": true, - "requires": { - "ajv": "^5.3.0", - "har-schema": "^2.0.0" - } - }, - "has-flag": { - "version": "3.0.0", - "bundled": true - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true - }, - "hosted-git-info": { - "version": "2.7.1", - "bundled": true - }, - "http-cache-semantics": { - "version": "3.8.1", - "bundled": true - }, - "http-proxy-agent": { - "version": "2.1.0", - "bundled": true, - "requires": { - "agent-base": "4", - "debug": "3.1.0" - } - }, - "http-signature": { - "version": "1.2.0", - "bundled": true, - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "https-proxy-agent": { - "version": "2.2.1", - "bundled": true, - "requires": { - "agent-base": "^4.1.0", - "debug": "^3.1.0" - } - }, - "humanize-ms": { - "version": "1.2.1", - "bundled": true, - "requires": { - "ms": "^2.0.0" - } - }, - "iconv-lite": { - "version": "0.4.23", - "bundled": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "iferr": { - "version": "1.0.2", - "bundled": true - }, - "ignore-walk": { - "version": "3.0.1", - "bundled": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "import-lazy": { - "version": "2.1.0", - "bundled": true - }, - "imurmurhash": { - "version": "0.1.4", - "bundled": true - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true - }, - "ini": { - "version": "1.3.5", - "bundled": true - }, - "init-package-json": { - "version": "1.10.3", - "bundled": true, - "requires": { - "glob": "^7.1.1", - "npm-package-arg": "^4.0.0 || ^5.0.0 || ^6.0.0", - "promzard": "^0.3.0", - "read": "~1.0.1", - "read-package-json": "1 || 2", - "semver": "2.x || 3.x || 4 || 5", - "validate-npm-package-license": "^3.0.1", - "validate-npm-package-name": "^3.0.0" - } - }, - "invert-kv": { - "version": "1.0.0", - "bundled": true - }, - "ip": { - "version": "1.1.5", - "bundled": true - }, - "ip-regex": { - "version": "2.1.0", - "bundled": true - }, - "is-builtin-module": { - "version": "1.0.0", - "bundled": true, - "requires": { - "builtin-modules": "^1.0.0" - } - }, - "is-ci": { - "version": "1.1.0", - "bundled": true, - "requires": { - "ci-info": "^1.0.0" - } - }, - "is-cidr": { - "version": "2.0.6", - "bundled": true, - "requires": { - "cidr-regex": "^2.0.8" - } - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "is-installed-globally": { - "version": "0.1.0", - "bundled": true, - "requires": { - "global-dirs": "^0.1.0", - "is-path-inside": "^1.0.0" - } - }, - "is-npm": { - "version": "1.0.0", - "bundled": true - }, - "is-obj": { - "version": "1.0.1", - "bundled": true - }, - "is-path-inside": { - "version": "1.0.1", - "bundled": true, - "requires": { - "path-is-inside": "^1.0.1" - } - }, - "is-redirect": { - "version": "1.0.0", - "bundled": true - }, - "is-retry-allowed": { - "version": "1.1.0", - "bundled": true - }, - "is-stream": { - "version": "1.1.0", - "bundled": true - }, - "is-typedarray": { - "version": "1.0.0", - "bundled": true - }, - "isarray": { - "version": "1.0.0", - "bundled": true - }, - "isexe": { - "version": "2.0.0", - "bundled": true - }, - "isstream": { - "version": "0.1.2", - "bundled": true - }, - "jsbn": { - "version": "0.1.1", - "bundled": true, - "optional": true - }, - "json-parse-better-errors": { - "version": "1.0.2", - "bundled": true - }, - "json-schema": { - "version": "0.2.3", - "bundled": true - }, - "json-schema-traverse": { - "version": "0.3.1", - "bundled": true - }, - "json-stringify-safe": { - "version": "5.0.1", - "bundled": true - }, - "jsonparse": { - "version": "1.3.1", - "bundled": true - }, - "jsprim": { - "version": "1.4.1", - "bundled": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "latest-version": { - "version": "3.1.0", - "bundled": true, - "requires": { - "package-json": "^4.0.0" - } - }, - "lazy-property": { - "version": "1.0.0", - "bundled": true - }, - "lcid": { - "version": "1.0.0", - "bundled": true, - "requires": { - "invert-kv": "^1.0.0" - } - }, - "libcipm": { - "version": "2.0.2", - "bundled": true, - "requires": { - "bin-links": "^1.1.2", - "bluebird": "^3.5.1", - "find-npm-prefix": "^1.0.2", - "graceful-fs": "^4.1.11", - "lock-verify": "^2.0.2", - "mkdirp": "^0.5.1", - "npm-lifecycle": "^2.0.3", - "npm-logical-tree": "^1.2.1", - "npm-package-arg": "^6.1.0", - "pacote": "^8.1.6", - "protoduck": "^5.0.0", - "read-package-json": "^2.0.13", - "rimraf": "^2.6.2", - "worker-farm": "^1.6.0" - } - }, - "libnpmhook": { - "version": "4.0.1", - "bundled": true, - "requires": { - "figgy-pudding": "^3.1.0", - "npm-registry-fetch": "^3.0.0" - }, - "dependencies": { - "npm-registry-fetch": { - "version": "3.1.1", - "bundled": true, - "requires": { - "bluebird": "^3.5.1", - "figgy-pudding": "^3.1.0", - "lru-cache": "^4.1.2", - "make-fetch-happen": "^4.0.0", - "npm-package-arg": "^6.0.0" - } - } - } - }, - "libnpx": { - "version": "10.2.0", - "bundled": true, - "requires": { - "dotenv": "^5.0.1", - "npm-package-arg": "^6.0.0", - "rimraf": "^2.6.2", - "safe-buffer": "^5.1.0", - "update-notifier": "^2.3.0", - "which": "^1.3.0", - "y18n": "^4.0.0", - "yargs": "^11.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "bundled": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "lock-verify": { - "version": "2.0.2", - "bundled": true, - "requires": { - "npm-package-arg": "^5.1.2 || 6", - "semver": "^5.4.1" - } - }, - "lockfile": { - "version": "1.0.4", - "bundled": true, - "requires": { - "signal-exit": "^3.0.2" - } - }, - "lodash._baseindexof": { - "version": "3.1.0", - "bundled": true - }, - "lodash._baseuniq": { - "version": "4.6.0", - "bundled": true, - "requires": { - "lodash._createset": "~4.0.0", - "lodash._root": "~3.0.0" - } - }, - "lodash._bindcallback": { - "version": "3.0.1", - "bundled": true - }, - "lodash._cacheindexof": { - "version": "3.0.2", - "bundled": true - }, - "lodash._createcache": { - "version": "3.1.2", - "bundled": true, - "requires": { - "lodash._getnative": "^3.0.0" - } - }, - "lodash._createset": { - "version": "4.0.3", - "bundled": true - }, - "lodash._getnative": { - "version": "3.9.1", - "bundled": true - }, - "lodash._root": { - "version": "3.0.1", - "bundled": true - }, - "lodash.clonedeep": { - "version": "4.5.0", - "bundled": true - }, - "lodash.restparam": { - "version": "3.6.1", - "bundled": true - }, - "lodash.union": { - "version": "4.6.0", - "bundled": true - }, - "lodash.uniq": { - "version": "4.5.0", - "bundled": true - }, - "lodash.without": { - "version": "4.4.0", - "bundled": true - }, - "lowercase-keys": { - "version": "1.0.1", - "bundled": true - }, - "lru-cache": { - "version": "4.1.3", - "bundled": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "make-dir": { - "version": "1.3.0", - "bundled": true, - "requires": { - "pify": "^3.0.0" - } - }, - "make-fetch-happen": { - "version": "4.0.1", - "bundled": true, - "requires": { - "agentkeepalive": "^3.4.1", - "cacache": "^11.0.1", - "http-cache-semantics": "^3.8.1", - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.1", - "lru-cache": "^4.1.2", - "mississippi": "^3.0.0", - "node-fetch-npm": "^2.0.2", - "promise-retry": "^1.1.1", - "socks-proxy-agent": "^4.0.0", - "ssri": "^6.0.0" - } - }, - "meant": { - "version": "1.0.1", - "bundled": true - }, - "mem": { - "version": "1.1.0", - "bundled": true, - "requires": { - "mimic-fn": "^1.0.0" - } - }, - "mime-db": { - "version": "1.35.0", - "bundled": true - }, - "mime-types": { - "version": "2.1.19", - "bundled": true, - "requires": { - "mime-db": "~1.35.0" - } - }, - "mimic-fn": { - "version": "1.2.0", - "bundled": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true - }, - "minipass": { - "version": "2.3.3", - "bundled": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - }, - "dependencies": { - "yallist": { - "version": "3.0.2", - "bundled": true - } - } - }, - "minizlib": { - "version": "1.1.0", - "bundled": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "mississippi": { - "version": "3.0.0", - "bundled": true, - "requires": { - "concat-stream": "^1.5.0", - "duplexify": "^3.4.2", - "end-of-stream": "^1.1.0", - "flush-write-stream": "^1.0.0", - "from2": "^2.1.0", - "parallel-transform": "^1.1.0", - "pump": "^3.0.0", - "pumpify": "^1.3.3", - "stream-each": "^1.1.0", - "through2": "^2.0.0" - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "requires": { - "minimist": "0.0.8" - } - }, - "move-concurrently": { - "version": "1.0.1", - "bundled": true, - "requires": { - "aproba": "^1.1.1", - "copy-concurrently": "^1.0.0", - "fs-write-stream-atomic": "^1.0.8", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.3" - } - }, - "ms": { - "version": "2.1.1", - "bundled": true - }, - "mute-stream": { - "version": "0.0.7", - "bundled": true - }, - "node-fetch-npm": { - "version": "2.0.2", - "bundled": true, - "requires": { - "encoding": "^0.1.11", - "json-parse-better-errors": "^1.0.0", - "safe-buffer": "^5.1.1" - } - }, - "node-gyp": { - "version": "3.8.0", - "bundled": true, - "requires": { - "fstream": "^1.0.0", - "glob": "^7.0.3", - "graceful-fs": "^4.1.2", - "mkdirp": "^0.5.0", - "nopt": "2 || 3", - "npmlog": "0 || 1 || 2 || 3 || 4", - "osenv": "0", - "request": "^2.87.0", - "rimraf": "2", - "semver": "~5.3.0", - "tar": "^2.0.0", - "which": "1" - }, - "dependencies": { - "nopt": { - "version": "3.0.6", - "bundled": true, - "requires": { - "abbrev": "1" - } - }, - "semver": { - "version": "5.3.0", - "bundled": true - }, - "tar": { - "version": "2.2.1", - "bundled": true, - "requires": { - "block-stream": "*", - "fstream": "^1.0.2", - "inherits": "2" - } - } - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "normalize-package-data": { - "version": "2.4.0", - "bundled": true, - "requires": { - "hosted-git-info": "^2.1.4", - "is-builtin-module": "^1.0.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "npm-audit-report": { - "version": "1.3.1", - "bundled": true, - "requires": { - "cli-table3": "^0.5.0", - "console-control-strings": "^1.1.0" - } - }, - "npm-bundled": { - "version": "1.0.5", - "bundled": true - }, - "npm-cache-filename": { - "version": "1.0.2", - "bundled": true - }, - "npm-install-checks": { - "version": "3.0.0", - "bundled": true, - "requires": { - "semver": "^2.3.0 || 3.x || 4 || 5" - } - }, - "npm-lifecycle": { - "version": "2.1.0", - "bundled": true, - "requires": { - "byline": "^5.0.0", - "graceful-fs": "^4.1.11", - "node-gyp": "^3.8.0", - "resolve-from": "^4.0.0", - "slide": "^1.1.6", - "uid-number": "0.0.6", - "umask": "^1.1.0", - "which": "^1.3.1" - } - }, - "npm-logical-tree": { - "version": "1.2.1", - "bundled": true - }, - "npm-package-arg": { - "version": "6.1.0", - "bundled": true, - "requires": { - "hosted-git-info": "^2.6.0", - "osenv": "^0.1.5", - "semver": "^5.5.0", - "validate-npm-package-name": "^3.0.0" - } - }, - "npm-packlist": { - "version": "1.1.11", - "bundled": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } - }, - "npm-pick-manifest": { - "version": "2.1.0", - "bundled": true, - "requires": { - "npm-package-arg": "^6.0.0", - "semver": "^5.4.1" - } - }, - "npm-profile": { - "version": "3.0.2", - "bundled": true, - "requires": { - "aproba": "^1.1.2 || 2", - "make-fetch-happen": "^2.5.0 || 3 || 4" - } - }, - "npm-registry-client": { - "version": "8.6.0", - "bundled": true, - "requires": { - "concat-stream": "^1.5.2", - "graceful-fs": "^4.1.6", - "normalize-package-data": "~1.0.1 || ^2.0.0", - "npm-package-arg": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0", - "npmlog": "2 || ^3.1.0 || ^4.0.0", - "once": "^1.3.3", - "request": "^2.74.0", - "retry": "^0.10.0", - "safe-buffer": "^5.1.1", - "semver": "2 >=2.2.1 || 3.x || 4 || 5", - "slide": "^1.1.3", - "ssri": "^5.2.4" - }, - "dependencies": { - "retry": { - "version": "0.10.1", - "bundled": true - }, - "ssri": { - "version": "5.3.0", - "bundled": true, - "requires": { - "safe-buffer": "^5.1.1" - } - } - } - }, - "npm-registry-fetch": { - "version": "1.1.0", - "bundled": true, - "requires": { - "bluebird": "^3.5.1", - "figgy-pudding": "^2.0.1", - "lru-cache": "^4.1.2", - "make-fetch-happen": "^3.0.0", - "npm-package-arg": "^6.0.0", - "safe-buffer": "^5.1.1" - }, - "dependencies": { - "cacache": { - "version": "10.0.4", - "bundled": true, - "requires": { - "bluebird": "^3.5.1", - "chownr": "^1.0.1", - "glob": "^7.1.2", - "graceful-fs": "^4.1.11", - "lru-cache": "^4.1.1", - "mississippi": "^2.0.0", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "promise-inflight": "^1.0.1", - "rimraf": "^2.6.2", - "ssri": "^5.2.4", - "unique-filename": "^1.1.0", - "y18n": "^4.0.0" - }, - "dependencies": { - "mississippi": { - "version": "2.0.0", - "bundled": true, - "requires": { - "concat-stream": "^1.5.0", - "duplexify": "^3.4.2", - "end-of-stream": "^1.1.0", - "flush-write-stream": "^1.0.0", - "from2": "^2.1.0", - "parallel-transform": "^1.1.0", - "pump": "^2.0.1", - "pumpify": "^1.3.3", - "stream-each": "^1.1.0", - "through2": "^2.0.0" - } - } - } - }, - "figgy-pudding": { - "version": "2.0.1", - "bundled": true - }, - "make-fetch-happen": { - "version": "3.0.0", - "bundled": true, - "requires": { - "agentkeepalive": "^3.4.1", - "cacache": "^10.0.4", - "http-cache-semantics": "^3.8.1", - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.0", - "lru-cache": "^4.1.2", - "mississippi": "^3.0.0", - "node-fetch-npm": "^2.0.2", - "promise-retry": "^1.1.1", - "socks-proxy-agent": "^3.0.1", - "ssri": "^5.2.4" - } - }, - "pump": { - "version": "2.0.1", - "bundled": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "smart-buffer": { - "version": "1.1.15", - "bundled": true - }, - "socks": { - "version": "1.1.10", - "bundled": true, - "requires": { - "ip": "^1.1.4", - "smart-buffer": "^1.0.13" - } - }, - "socks-proxy-agent": { - "version": "3.0.1", - "bundled": true, - "requires": { - "agent-base": "^4.1.0", - "socks": "^1.1.10" - } - }, - "ssri": { - "version": "5.3.0", - "bundled": true, - "requires": { - "safe-buffer": "^5.1.1" - } - } - } - }, - "npm-run-path": { - "version": "2.0.2", - "bundled": true, - "requires": { - "path-key": "^2.0.0" - } - }, - "npm-user-validate": { - "version": "1.0.0", - "bundled": true - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true - }, - "oauth-sign": { - "version": "0.9.0", - "bundled": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "requires": { - "wrappy": "1" - } - }, - "opener": { - "version": "1.5.0", - "bundled": true - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true - }, - "os-locale": { - "version": "2.1.0", - "bundled": true, - "requires": { - "execa": "^0.7.0", - "lcid": "^1.0.0", - "mem": "^1.1.0" - } - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "p-finally": { - "version": "1.0.0", - "bundled": true - }, - "p-limit": { - "version": "1.2.0", - "bundled": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "bundled": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "bundled": true - }, - "package-json": { - "version": "4.0.1", - "bundled": true, - "requires": { - "got": "^6.7.1", - "registry-auth-token": "^3.0.1", - "registry-url": "^3.0.3", - "semver": "^5.1.0" - } - }, - "pacote": { - "version": "8.1.6", - "bundled": true, - "requires": { - "bluebird": "^3.5.1", - "cacache": "^11.0.2", - "get-stream": "^3.0.0", - "glob": "^7.1.2", - "lru-cache": "^4.1.3", - "make-fetch-happen": "^4.0.1", - "minimatch": "^3.0.4", - "minipass": "^2.3.3", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", - "normalize-package-data": "^2.4.0", - "npm-package-arg": "^6.1.0", - "npm-packlist": "^1.1.10", - "npm-pick-manifest": "^2.1.0", - "osenv": "^0.1.5", - "promise-inflight": "^1.0.1", - "promise-retry": "^1.1.1", - "protoduck": "^5.0.0", - "rimraf": "^2.6.2", - "safe-buffer": "^5.1.2", - "semver": "^5.5.0", - "ssri": "^6.0.0", - "tar": "^4.4.3", - "unique-filename": "^1.1.0", - "which": "^1.3.0" - } - }, - "parallel-transform": { - "version": "1.1.0", - "bundled": true, - "requires": { - "cyclist": "~0.2.2", - "inherits": "^2.0.3", - "readable-stream": "^2.1.5" - } - }, - "path-exists": { - "version": "3.0.0", - "bundled": true - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true - }, - "path-is-inside": { - "version": "1.0.2", - "bundled": true - }, - "path-key": { - "version": "2.0.1", - "bundled": true - }, - "performance-now": { - "version": "2.1.0", - "bundled": true - }, - "pify": { - "version": "3.0.0", - "bundled": true - }, - "prepend-http": { - "version": "1.0.4", - "bundled": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true - }, - "promise-inflight": { - "version": "1.0.1", - "bundled": true - }, - "promise-retry": { - "version": "1.1.1", - "bundled": true, - "requires": { - "err-code": "^1.0.0", - "retry": "^0.10.0" - }, - "dependencies": { - "retry": { - "version": "0.10.1", - "bundled": true - } - } - }, - "promzard": { - "version": "0.3.0", - "bundled": true, - "requires": { - "read": "1" - } - }, - "proto-list": { - "version": "1.2.4", - "bundled": true - }, - "protoduck": { - "version": "5.0.0", - "bundled": true, - "requires": { - "genfun": "^4.0.1" - } - }, - "prr": { - "version": "1.0.1", - "bundled": true - }, - "pseudomap": { - "version": "1.0.2", - "bundled": true - }, - "psl": { - "version": "1.1.29", - "bundled": true - }, - "pump": { - "version": "3.0.0", - "bundled": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "pumpify": { - "version": "1.5.1", - "bundled": true, - "requires": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - }, - "dependencies": { - "pump": { - "version": "2.0.1", - "bundled": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - } - } - }, - "punycode": { - "version": "1.4.1", - "bundled": true - }, - "qrcode-terminal": { - "version": "0.12.0", - "bundled": true - }, - "qs": { - "version": "6.5.2", - "bundled": true - }, - "query-string": { - "version": "6.1.0", - "bundled": true, - "requires": { - "decode-uri-component": "^0.2.0", - "strict-uri-encode": "^2.0.0" - } - }, - "qw": { - "version": "1.0.1", - "bundled": true - }, - "rc": { - "version": "1.2.7", - "bundled": true, - "requires": { - "deep-extend": "^0.5.1", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true - } - } - }, - "read": { - "version": "1.0.7", - "bundled": true, - "requires": { - "mute-stream": "~0.0.4" - } - }, - "read-cmd-shim": { - "version": "1.0.1", - "bundled": true, - "requires": { - "graceful-fs": "^4.1.2" - } - }, - "read-installed": { - "version": "4.0.3", - "bundled": true, - "requires": { - "debuglog": "^1.0.1", - "graceful-fs": "^4.1.2", - "read-package-json": "^2.0.0", - "readdir-scoped-modules": "^1.0.0", - "semver": "2 || 3 || 4 || 5", - "slide": "~1.1.3", - "util-extend": "^1.0.1" - } - }, - "read-package-json": { - "version": "2.0.13", - "bundled": true, - "requires": { - "glob": "^7.1.1", - "graceful-fs": "^4.1.2", - "json-parse-better-errors": "^1.0.1", - "normalize-package-data": "^2.0.0", - "slash": "^1.0.0" - } - }, - "read-package-tree": { - "version": "5.2.1", - "bundled": true, - "requires": { - "debuglog": "^1.0.1", - "dezalgo": "^1.0.0", - "once": "^1.3.0", - "read-package-json": "^2.0.0", - "readdir-scoped-modules": "^1.0.0" - } - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "readdir-scoped-modules": { - "version": "1.0.2", - "bundled": true, - "requires": { - "debuglog": "^1.0.1", - "dezalgo": "^1.0.0", - "graceful-fs": "^4.1.2", - "once": "^1.3.0" - } - }, - "registry-auth-token": { - "version": "3.3.2", - "bundled": true, - "requires": { - "rc": "^1.1.6", - "safe-buffer": "^5.0.1" - } - }, - "registry-url": { - "version": "3.1.0", - "bundled": true, - "requires": { - "rc": "^1.0.1" - } - }, - "request": { - "version": "2.88.0", - "bundled": true, - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.0", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - } - }, - "require-directory": { - "version": "2.1.1", - "bundled": true - }, - "require-main-filename": { - "version": "1.0.1", - "bundled": true - }, - "resolve-from": { - "version": "4.0.0", - "bundled": true - }, - "retry": { - "version": "0.12.0", - "bundled": true - }, - "rimraf": { - "version": "2.6.2", - "bundled": true, - "requires": { - "glob": "^7.0.5" - } - }, - "run-queue": { - "version": "1.0.3", - "bundled": true, - "requires": { - "aproba": "^1.1.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "bundled": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true - }, - "semver": { - "version": "5.5.0", - "bundled": true - }, - "semver-diff": { - "version": "2.1.0", - "bundled": true, - "requires": { - "semver": "^5.0.3" - } - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true - }, - "sha": { - "version": "2.0.1", - "bundled": true, - "requires": { - "graceful-fs": "^4.1.2", - "readable-stream": "^2.0.2" - } - }, - "shebang-command": { - "version": "1.2.0", - "bundled": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "bundled": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true - }, - "slash": { - "version": "1.0.0", - "bundled": true - }, - "slide": { - "version": "1.1.6", - "bundled": true - }, - "smart-buffer": { - "version": "4.0.1", - "bundled": true - }, - "socks": { - "version": "2.2.0", - "bundled": true, - "requires": { - "ip": "^1.1.5", - "smart-buffer": "^4.0.1" - } - }, - "socks-proxy-agent": { - "version": "4.0.1", - "bundled": true, - "requires": { - "agent-base": "~4.2.0", - "socks": "~2.2.0" - } - }, - "sorted-object": { - "version": "2.0.1", - "bundled": true - }, - "sorted-union-stream": { - "version": "2.1.3", - "bundled": true, - "requires": { - "from2": "^1.3.0", - "stream-iterate": "^1.1.0" - }, - "dependencies": { - "from2": { - "version": "1.3.0", - "bundled": true, - "requires": { - "inherits": "~2.0.1", - "readable-stream": "~1.1.10" - } - }, - "isarray": { - "version": "0.0.1", - "bundled": true - }, - "readable-stream": { - "version": "1.1.14", - "bundled": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "bundled": true - } - } - }, - "spdx-correct": { - "version": "3.0.0", - "bundled": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.1.0", - "bundled": true - }, - "spdx-expression-parse": { - "version": "3.0.0", - "bundled": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.0", - "bundled": true - }, - "sshpk": { - "version": "1.14.2", - "bundled": true, - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, - "ssri": { - "version": "6.0.0", - "bundled": true - }, - "stream-each": { - "version": "1.2.2", - "bundled": true, - "requires": { - "end-of-stream": "^1.1.0", - "stream-shift": "^1.0.0" - } - }, - "stream-iterate": { - "version": "1.2.0", - "bundled": true, - "requires": { - "readable-stream": "^2.1.5", - "stream-shift": "^1.0.0" - } - }, - "stream-shift": { - "version": "1.0.0", - "bundled": true - }, - "strict-uri-encode": { - "version": "2.0.0", - "bundled": true - }, - "string-width": { - "version": "2.1.1", - "bundled": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "bundled": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "bundled": true - }, - "strip-ansi": { - "version": "4.0.0", - "bundled": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "stringify-package": { - "version": "1.0.0", - "bundled": true - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-eof": { - "version": "1.0.0", - "bundled": true - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true - }, - "supports-color": { - "version": "5.4.0", - "bundled": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "tar": { - "version": "4.4.6", - "bundled": true, - "requires": { - "chownr": "^1.0.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.3.3", - "minizlib": "^1.1.0", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.2" - }, - "dependencies": { - "yallist": { - "version": "3.0.2", - "bundled": true - } - } - }, - "term-size": { - "version": "1.2.0", - "bundled": true, - "requires": { - "execa": "^0.7.0" - } - }, - "text-table": { - "version": "0.2.0", - "bundled": true - }, - "through": { - "version": "2.3.8", - "bundled": true - }, - "through2": { - "version": "2.0.3", - "bundled": true, - "requires": { - "readable-stream": "^2.1.5", - "xtend": "~4.0.1" - } - }, - "timed-out": { - "version": "4.0.1", - "bundled": true - }, - "tiny-relative-date": { - "version": "1.3.0", - "bundled": true - }, - "tough-cookie": { - "version": "2.4.3", - "bundled": true, - "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - } - }, - "tunnel-agent": { - "version": "0.6.0", - "bundled": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "bundled": true, - "optional": true - }, - "typedarray": { - "version": "0.0.6", - "bundled": true - }, - "uid-number": { - "version": "0.0.6", - "bundled": true - }, - "umask": { - "version": "1.1.0", - "bundled": true - }, - "unique-filename": { - "version": "1.1.0", - "bundled": true, - "requires": { - "unique-slug": "^2.0.0" - } - }, - "unique-slug": { - "version": "2.0.0", - "bundled": true, - "requires": { - "imurmurhash": "^0.1.4" - } - }, - "unique-string": { - "version": "1.0.0", - "bundled": true, - "requires": { - "crypto-random-string": "^1.0.0" - } - }, - "unpipe": { - "version": "1.0.0", - "bundled": true - }, - "unzip-response": { - "version": "2.0.1", - "bundled": true - }, - "update-notifier": { - "version": "2.5.0", - "bundled": true, - "requires": { - "boxen": "^1.2.1", - "chalk": "^2.0.1", - "configstore": "^3.0.0", - "import-lazy": "^2.1.0", - "is-ci": "^1.0.10", - "is-installed-globally": "^0.1.0", - "is-npm": "^1.0.0", - "latest-version": "^3.0.0", - "semver-diff": "^2.0.0", - "xdg-basedir": "^3.0.0" - } - }, - "url-parse-lax": { - "version": "1.0.0", - "bundled": true, - "requires": { - "prepend-http": "^1.0.1" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true - }, - "util-extend": { - "version": "1.0.3", - "bundled": true - }, - "uuid": { - "version": "3.3.2", - "bundled": true - }, - "validate-npm-package-license": { - "version": "3.0.4", - "bundled": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "validate-npm-package-name": { - "version": "3.0.0", - "bundled": true, - "requires": { - "builtins": "^1.0.3" - } - }, - "verror": { - "version": "1.10.0", - "bundled": true, - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "wcwidth": { - "version": "1.0.1", - "bundled": true, - "requires": { - "defaults": "^1.0.3" - } - }, - "which": { - "version": "1.3.1", - "bundled": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "bundled": true - }, - "wide-align": { - "version": "1.1.2", - "bundled": true, - "requires": { - "string-width": "^1.0.2" - }, - "dependencies": { - "string-width": { - "version": "1.0.2", - "bundled": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - } - } - }, - "widest-line": { - "version": "2.0.0", - "bundled": true, - "requires": { - "string-width": "^2.1.1" - } - }, - "worker-farm": { - "version": "1.6.0", - "bundled": true, - "requires": { - "errno": "~0.1.7" - } - }, - "wrap-ansi": { - "version": "2.1.0", - "bundled": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - }, - "dependencies": { - "string-width": { - "version": "1.0.2", - "bundled": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - } - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true - }, - "write-file-atomic": { - "version": "2.3.0", - "bundled": true, - "requires": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" - } - }, - "xdg-basedir": { - "version": "3.0.0", - "bundled": true - }, - "xtend": { - "version": "4.0.1", - "bundled": true - }, - "y18n": { - "version": "4.0.0", - "bundled": true - }, - "yallist": { - "version": "2.1.2", - "bundled": true - }, - "yargs": { - "version": "11.0.0", - "bundled": true, - "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.1.1", - "find-up": "^2.1.0", - "get-caller-file": "^1.0.1", - "os-locale": "^2.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^9.0.2" - }, - "dependencies": { - "y18n": { - "version": "3.2.1", - "bundled": true - } - } - }, - "yargs-parser": { - "version": "9.0.2", - "bundled": true, - "requires": { - "camelcase": "^4.1.0" - } - } - } - }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "optional": true, - "requires": { - "path-key": "^2.0.0" - } - }, - "nth-check": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz", - "integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=", - "dev": true, - "optional": true, - "requires": { - "boolbase": "~1.0.0" - } - }, - "num2fraction": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", - "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", - "dev": true - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "object-component": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", - "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=", - "dev": true - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "object-keys": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", - "integrity": "sha1-CcU4VTd1dTEMymL1W7M0q/97PtI=", - "dev": true - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "requires": { - "isobject": "^3.0.0" - } - }, - "object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "dev": true, - "requires": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "object.getownpropertydescriptors": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", - "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", - "dev": true, - "optional": true, - "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.5.1" - } - }, - "object.map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", - "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", - "dev": true, - "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } - }, - "object.omit": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", - "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", - "dev": true, - "requires": { - "for-own": "^0.1.4", - "is-extendable": "^0.1.1" - }, - "dependencies": { - "for-own": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", - "dev": true, - "requires": { - "for-in": "^1.0.1" - } - } - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "object.values": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.0.4.tgz", - "integrity": "sha1-5STaCbT2b/Bd9FdUbscqyZ8TBpo=", - "dev": true, - "optional": true, - "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.6.1", - "function-bind": "^1.1.0", - "has": "^1.0.1" - } - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dev": true, - "requires": { - "ee-first": "1.1.1" - } - }, - "on-headers": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", - "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "dev": true, - "requires": { - "mimic-fn": "^1.0.0" - } - }, - "open": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/open/-/open-0.0.5.tgz", - "integrity": "sha1-QsPhjslUZra/DcQvOilFw/DK2Pw=", - "dev": true - }, - "optimist": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "dev": true, - "requires": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" - }, - "dependencies": { - "wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", - "dev": true - } - } - }, - "optionator": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", - "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "dev": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.4", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "wordwrap": "~1.0.0" - } - }, - "optipng-bin": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/optipng-bin/-/optipng-bin-3.1.4.tgz", - "integrity": "sha1-ldNPLEiHBPb9cGBr/qDGWfHZXYQ=", - "dev": true, - "optional": true, - "requires": { - "bin-build": "^2.0.0", - "bin-wrapper": "^3.0.0", - "logalot": "^2.0.0" - } - }, - "orchestrator": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", - "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", - "dev": true, - "requires": { - "end-of-stream": "~0.1.5", - "sequencify": "~0.0.7", - "stream-consume": "~0.1.0" - } - }, - "ordered-read-streams": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", - "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=", - "dev": true - }, - "os-filter-obj": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/os-filter-obj/-/os-filter-obj-1.0.3.tgz", - "integrity": "sha1-WRUzDZDs7VV9LZOKMcbdIU2cY60=", - "dev": true, - "optional": true - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true - }, - "p-pipe": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/p-pipe/-/p-pipe-1.2.0.tgz", - "integrity": "sha1-SxoROZoRUgpneQ7loMHViB1r7+k=", - "dev": true - }, - "pac-proxy-agent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-3.0.0.tgz", - "integrity": "sha512-AOUX9jES/EkQX2zRz0AW7lSx9jD//hQS8wFXBvcnd/J2Py9KaMJMqV/LPqJssj1tgGufotb2mmopGPR15ODv1Q==", - "dev": true, - "optional": true, - "requires": { - "agent-base": "^4.2.0", - "debug": "^3.1.0", - "get-uri": "^2.0.0", - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.1", - "pac-resolver": "^3.0.0", - "raw-body": "^2.2.0", - "socks-proxy-agent": "^4.0.1" - }, - "dependencies": { - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", - "dev": true, - "optional": true - }, - "debug": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.5.tgz", - "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", - "dev": true, - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true, - "optional": true - }, - "http-errors": { - "version": "1.6.3", - "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "dev": true, - "optional": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - } - }, - "iconv-lite": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", - "integrity": "sha1-KXhx9jvlB63Pv8pxXQzQ7thOmmM=", - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true, - "optional": true - }, - "raw-body": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", - "integrity": "sha1-GzJOzmtXBuFThVvBFIxlu39uoMM=", - "dev": true, - "optional": true, - "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.3", - "iconv-lite": "0.4.23", - "unpipe": "1.0.0" - } - } - } - }, - "pac-resolver": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-3.0.0.tgz", - "integrity": "sha1-auoweH2wqJFwTet4AKcip2FabyY=", - "dev": true, - "optional": true, - "requires": { - "co": "^4.6.0", - "degenerator": "^1.0.4", - "ip": "^1.1.5", - "netmask": "^1.0.6", - "thunkify": "^2.1.2" - }, - "dependencies": { - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true, - "optional": true - } - } - }, - "parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", - "dev": true, - "requires": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" - } - }, - "parse-glob": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", - "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", - "dev": true, - "requires": { - "glob-base": "^0.3.0", - "is-dotfile": "^1.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.0" - }, - "dependencies": { - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - } - } - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true - }, - "parseqs": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", - "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", - "dev": true, - "requires": { - "better-assert": "~1.0.0" - } - }, - "parseuri": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", - "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", - "dev": true, - "requires": { - "better-assert": "~1.0.0" - } - }, - "parseurl": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", - "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", - "dev": true - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true - }, - "path": { - "version": "0.4.9", - "resolved": "https://registry.npmjs.org/path/-/path-0.4.9.tgz", - "integrity": "sha1-OAxo0BJz5D+TaNetUP7l4+jUd/A=", - "dev": true - }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true - }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, - "path-proxy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/path-proxy/-/path-proxy-1.0.0.tgz", - "integrity": "sha1-GOijaFn8nS8aU7SN7hOFQ8Ag3l4=", - "dev": true, - "optional": true, - "requires": { - "inflection": "~1.3.0" - }, - "dependencies": { - "inflection": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.3.8.tgz", - "integrity": "sha1-y9Fg2p91sUw8xjV41POWeEvzAU4=", - "dev": true, - "optional": true - } - } - }, - "path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "dev": true, - "requires": { - "path-root-regex": "^0.1.0" - } - }, - "path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", - "dev": true - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "dependencies": { - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - } - } - }, - "pause": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/pause/-/pause-0.1.0.tgz", - "integrity": "sha1-68ikqGGf8LioGsFRPDQ0/0af23Q=", - "dev": true - }, - "pause-stream": { - "version": "0.0.11", - "resolved": "http://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", - "dev": true, - "requires": { - "through": "~2.3" - } - }, - "pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", - "dev": true - }, - "performance-now": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", - "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", - "dev": true - }, - "phantomjs-prebuilt": { - "version": "2.1.16", - "resolved": "https://registry.npmjs.org/phantomjs-prebuilt/-/phantomjs-prebuilt-2.1.16.tgz", - "integrity": "sha1-79ISpKOWbTZHaE6ouniFSb4q7+8=", - "dev": true, - "requires": { - "es6-promise": "^4.0.3", - "extract-zip": "^1.6.5", - "fs-extra": "^1.0.0", - "hasha": "^2.2.0", - "kew": "^0.7.0", - "progress": "^1.1.8", - "request": "^2.81.0", - "request-progress": "^2.0.1", - "which": "^1.2.10" - }, - "dependencies": { - "es6-promise": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.5.tgz", - "integrity": "sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg==", - "dev": true - }, - "progress": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", - "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", - "dev": true - } - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "^2.0.0" - } - }, - "plugin-error": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", - "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", - "dev": true, - "requires": { - "ansi-colors": "^1.0.1", - "arr-diff": "^4.0.0", - "arr-union": "^3.1.0", - "extend-shallow": "^3.0.2" - } - }, - "plugin-log": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/plugin-log/-/plugin-log-0.1.0.tgz", - "integrity": "sha1-hgSc9qsQgzOYqTHzaJy67nteEzM=", - "dev": true, - "requires": { - "chalk": "^1.1.1", - "dateformat": "^1.0.11" - }, - "dependencies": { - "dateformat": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", - "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", - "dev": true, - "requires": { - "get-stdin": "^4.0.1", - "meow": "^3.3.0" - } - } - } - }, - "plur": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/plur/-/plur-2.1.2.tgz", - "integrity": "sha1-dIJFLBoPUI4+NE6uwxLJHCncZVo=", - "dev": true, - "requires": { - "irregular-plurals": "^1.0.0" - } - }, - "pluralize": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", - "integrity": "sha1-KYuJ34uTsCIdv0Ia0rGx6iP8Z3c=", - "dev": true - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha1-ut+hSX1GJE9jkPWLMZgw2RB4U8U=", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "postcss-calc": { - "version": "5.3.1", - "resolved": "http://registry.npmjs.org/postcss-calc/-/postcss-calc-5.3.1.tgz", - "integrity": "sha1-d7rnypKK2FcW4v2kLyYb98HWW14=", - "dev": true, - "requires": { - "postcss": "^5.0.2", - "postcss-message-helpers": "^2.0.0", - "reduce-css-calc": "^1.2.6" - } - }, - "postcss-colormin": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-2.2.2.tgz", - "integrity": "sha1-ZjFBfV8OkJo9fsJrJMio0eT5bks=", - "dev": true, - "requires": { - "colormin": "^1.0.5", - "postcss": "^5.0.13", - "postcss-value-parser": "^3.2.3" - } - }, - "postcss-convert-values": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-2.6.1.tgz", - "integrity": "sha1-u9hZPFwf0uPRwyK7kl3K6Nrk1i0=", - "dev": true, - "requires": { - "postcss": "^5.0.11", - "postcss-value-parser": "^3.1.2" - } - }, - "postcss-discard-comments": { - "version": "2.0.4", - "resolved": "http://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz", - "integrity": "sha1-vv6J+v1bPazlzM5Rt2uBUUvgDj0=", - "dev": true, - "requires": { - "postcss": "^5.0.14" - } - }, - "postcss-discard-duplicates": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-2.1.0.tgz", - "integrity": "sha1-uavye4isGIFYpesSq8riAmO5GTI=", - "dev": true, - "requires": { - "postcss": "^5.0.4" - } - }, - "postcss-discard-empty": { - "version": "2.1.0", - "resolved": "http://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz", - "integrity": "sha1-0rS9nVztXr2Nyt52QMfXzX9PkrU=", - "dev": true, - "requires": { - "postcss": "^5.0.14" - } - }, - "postcss-discard-overridden": { - "version": "0.1.1", - "resolved": "http://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz", - "integrity": "sha1-ix6vVU9ob7KIzYdMVWZ7CqNmjVg=", - "dev": true, - "requires": { - "postcss": "^5.0.16" - } - }, - "postcss-discard-unused": { - "version": "2.2.3", - "resolved": "http://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz", - "integrity": "sha1-vOMLLMWR/8Y0Mitfs0ZLbZNPRDM=", - "dev": true, - "requires": { - "postcss": "^5.0.14", - "uniqs": "^2.0.0" - } - }, - "postcss-filter-plugins": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/postcss-filter-plugins/-/postcss-filter-plugins-2.0.3.tgz", - "integrity": "sha512-T53GVFsdinJhgwm7rg1BzbeBRomOg9y5MBVhGcsV0CxurUdVj1UlPdKtn7aqYA/c/QVkzKMjq2bSV5dKG5+AwQ==", - "dev": true, - "requires": { - "postcss": "^5.0.4" - } - }, - "postcss-load-config": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-1.2.0.tgz", - "integrity": "sha1-U56a/J3chiASHr+djDZz4M5Q0oo=", - "dev": true, - "requires": { - "cosmiconfig": "^2.1.0", - "object-assign": "^4.1.0", - "postcss-load-options": "^1.2.0", - "postcss-load-plugins": "^2.3.0" - } - }, - "postcss-load-options": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postcss-load-options/-/postcss-load-options-1.2.0.tgz", - "integrity": "sha1-sJixVZ3awt8EvAuzdfmaXP4rbYw=", - "dev": true, - "requires": { - "cosmiconfig": "^2.1.0", - "object-assign": "^4.1.0" - } - }, - "postcss-load-plugins": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/postcss-load-plugins/-/postcss-load-plugins-2.3.0.tgz", - "integrity": "sha1-dFdoEWWZrKLwCfrUJrABdQSdjZI=", - "dev": true, - "requires": { - "cosmiconfig": "^2.1.1", - "object-assign": "^4.1.0" - } - }, - "postcss-merge-idents": { - "version": "2.1.7", - "resolved": "http://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz", - "integrity": "sha1-TFUwMTwI4dWzu/PSu8dH4njuonA=", - "dev": true, - "requires": { - "has": "^1.0.1", - "postcss": "^5.0.10", - "postcss-value-parser": "^3.1.1" - } - }, - "postcss-merge-longhand": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-2.0.2.tgz", - "integrity": "sha1-I9kM0Sewp3mUkVMyc5A0oaTz1lg=", - "dev": true, - "requires": { - "postcss": "^5.0.4" - } - }, - "postcss-merge-rules": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-2.1.2.tgz", - "integrity": "sha1-0d9d+qexrMO+VT8OnhDofGG19yE=", - "dev": true, - "requires": { - "browserslist": "^1.5.2", - "caniuse-api": "^1.5.2", - "postcss": "^5.0.4", - "postcss-selector-parser": "^2.2.2", - "vendors": "^1.0.0" - } - }, - "postcss-message-helpers": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz", - "integrity": "sha1-pPL0+rbk/gAvCu0ABHjN9S+bpg4=", - "dev": true - }, - "postcss-minify-font-values": { - "version": "1.0.5", - "resolved": "http://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz", - "integrity": "sha1-S1jttWZB66fIR0qzUmyv17vey2k=", - "dev": true, - "requires": { - "object-assign": "^4.0.1", - "postcss": "^5.0.4", - "postcss-value-parser": "^3.0.2" - } - }, - "postcss-minify-gradients": { - "version": "1.0.5", - "resolved": "http://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz", - "integrity": "sha1-Xb2hE3NwP4PPtKPqOIHY11/15uE=", - "dev": true, - "requires": { - "postcss": "^5.0.12", - "postcss-value-parser": "^3.3.0" - } - }, - "postcss-minify-params": { - "version": "1.2.2", - "resolved": "http://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz", - "integrity": "sha1-rSzgcTc7lDs9kwo/pZo1jCjW8fM=", - "dev": true, - "requires": { - "alphanum-sort": "^1.0.1", - "postcss": "^5.0.2", - "postcss-value-parser": "^3.0.2", - "uniqs": "^2.0.0" - } - }, - "postcss-minify-selectors": { - "version": "2.1.1", - "resolved": "http://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz", - "integrity": "sha1-ssapjAByz5G5MtGkllCBFDEXNb8=", - "dev": true, - "requires": { - "alphanum-sort": "^1.0.2", - "has": "^1.0.1", - "postcss": "^5.0.14", - "postcss-selector-parser": "^2.0.0" - } - }, - "postcss-normalize-charset": { - "version": "1.1.1", - "resolved": "http://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz", - "integrity": "sha1-757nEhLX/nWceO0WL2HtYrXLk/E=", - "dev": true, - "requires": { - "postcss": "^5.0.5" - } - }, - "postcss-normalize-url": { - "version": "3.0.8", - "resolved": "http://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-3.0.8.tgz", - "integrity": "sha1-EI90s/L82viRov+j6kWSJ5/HgiI=", - "dev": true, - "requires": { - "is-absolute-url": "^2.0.0", - "normalize-url": "^1.4.0", - "postcss": "^5.0.14", - "postcss-value-parser": "^3.2.3" - } - }, - "postcss-ordered-values": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-2.2.3.tgz", - "integrity": "sha1-7sbCpntsQSqNsgQud/6NpD+VwR0=", - "dev": true, - "requires": { - "postcss": "^5.0.4", - "postcss-value-parser": "^3.0.1" - } - }, - "postcss-reduce-idents": { - "version": "2.4.0", - "resolved": "http://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz", - "integrity": "sha1-wsbSDMlYKE9qv75j92Cb9AkFmtM=", - "dev": true, - "requires": { - "postcss": "^5.0.4", - "postcss-value-parser": "^3.0.2" - } - }, - "postcss-reduce-initial": { - "version": "1.0.1", - "resolved": "http://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz", - "integrity": "sha1-aPgGlfBF0IJjqHmtJA343WT2ROo=", - "dev": true, - "requires": { - "postcss": "^5.0.4" - } - }, - "postcss-reduce-transforms": { - "version": "1.0.4", - "resolved": "http://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz", - "integrity": "sha1-/3b02CEkN7McKYpC0uFEQCV3GuE=", - "dev": true, - "requires": { - "has": "^1.0.1", - "postcss": "^5.0.8", - "postcss-value-parser": "^3.0.1" - } - }, - "postcss-selector-parser": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz", - "integrity": "sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A=", - "dev": true, - "requires": { - "flatten": "^1.0.2", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - }, - "postcss-svgo": { - "version": "2.1.6", - "resolved": "http://registry.npmjs.org/postcss-svgo/-/postcss-svgo-2.1.6.tgz", - "integrity": "sha1-tt8YqmE7Zm4TPwittSGcJoSsEI0=", - "dev": true, - "requires": { - "is-svg": "^2.0.0", - "postcss": "^5.0.14", - "postcss-value-parser": "^3.2.3", - "svgo": "^0.7.0" - } - }, - "postcss-unique-selectors": { - "version": "2.0.2", - "resolved": "http://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz", - "integrity": "sha1-mB1X0p3csz57Hf4f1DuGSfkzyh0=", - "dev": true, - "requires": { - "alphanum-sort": "^1.0.1", - "postcss": "^5.0.4", - "uniqs": "^2.0.0" - } - }, - "postcss-value-parser": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz", - "integrity": "sha1-h/OPnxj3dKSrTIojL1xc6IcqnRU=", - "dev": true - }, - "postcss-zindex": { - "version": "2.2.0", - "resolved": "http://registry.npmjs.org/postcss-zindex/-/postcss-zindex-2.2.0.tgz", - "integrity": "sha1-0hCd3AVbka9n/EyzsCWUZjnSryI=", - "dev": true, - "requires": { - "has": "^1.0.1", - "postcss": "^5.0.4", - "uniqs": "^2.0.0" - } - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true - }, - "prepend-http": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", - "dev": true - }, - "preserve": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", - "dev": true - }, - "pretty-bytes": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-4.0.2.tgz", - "integrity": "sha1-sr+C5zUNZcbDOqlaqlpPYyf2HNk=", - "dev": true - }, - "pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", - "dev": true - }, - "private": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha1-o31zL0JxtKsa0HDTVQjoKQeI/6o=", - "dev": true - }, - "progress": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", - "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", - "dev": true - }, - "promise": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "integrity": "sha1-BktyYCsY+Q8pGSuLG8QY/9Hr078=", - "dev": true, - "optional": true, - "requires": { - "asap": "~2.0.3" - } - }, - "promisify-call": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/promisify-call/-/promisify-call-2.0.4.tgz", - "integrity": "sha1-1IwtRWUszM1SgB3ey9UzptS9X7o=", - "dev": true, - "optional": true, - "requires": { - "with-callback": "^1.0.2" - } - }, - "proxy-agent": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-3.0.3.tgz", - "integrity": "sha512-PXVVVuH9tiQuxQltFJVSnXWuDtNr+8aNBP6XVDDCDiUuDN8eRCm+ii4/mFWmXWEA0w8jjJSlePa4LXlM4jIzNA==", - "dev": true, - "optional": true, - "requires": { - "agent-base": "^4.2.0", - "debug": "^3.1.0", - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.1", - "lru-cache": "^4.1.2", - "pac-proxy-agent": "^3.0.0", - "proxy-from-env": "^1.0.0", - "socks-proxy-agent": "^4.0.1" - }, - "dependencies": { - "debug": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.5.tgz", - "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", - "dev": true, - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "lru-cache": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", - "integrity": "sha1-oRdc80lt/IQ2wVbDNLSVWZK85pw=", - "dev": true, - "optional": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true, - "optional": true - } - } - }, - "proxy-from-env": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", - "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=", - "dev": true, - "optional": true - }, - "prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "dev": true, - "optional": true - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true, - "optional": true - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - }, - "q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", - "dev": true - }, - "qjobs": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", - "integrity": "sha1-xF6cYYAL0IfviNfiVkI73Unl0HE=", - "dev": true - }, - "qs": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-4.0.0.tgz", - "integrity": "sha1-wx2bdOwn33XlQ6hseHKO2NRiNgc=", - "dev": true - }, - "query-string": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", - "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", - "dev": true, - "requires": { - "object-assign": "^4.1.0", - "strict-uri-encode": "^1.0.0" - } - }, - "random-bytes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", - "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=", - "dev": true - }, - "randomatic": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.0.tgz", - "integrity": "sha512-KnGPVE0lo2WoXxIZ7cPR8YBpiol4gsSuOwDSg410oHh80ZMp5EiypNqL2K4Z77vJn6lB5rap7IkAmcUlalcnBQ==", - "dev": true, - "requires": { - "is-number": "^4.0.0", - "kind-of": "^6.0.0", - "math-random": "^1.0.1" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - } - } - }, - "range-parser": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.3.tgz", - "integrity": "sha1-aHKCNTXGkuLCoBA4Jq/YLC4P8XU=", - "dev": true - }, - "raw-body": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz", - "integrity": "sha1-rf6s4uT7MJgFgBTQjActzFl1h3Q=", - "dev": true, - "requires": { - "bytes": "2.4.0", - "iconv-lite": "0.4.13", - "unpipe": "1.0.0" - }, - "dependencies": { - "bytes": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", - "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=", - "dev": true - }, - "iconv-lite": { - "version": "0.4.13", - "resolved": "http://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", - "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=", - "dev": true - } - } - }, - "rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha1-zZJL9SAKB1uDwYjNa54hG3/A0+0=", - "dev": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, - "read-all-stream": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/read-all-stream/-/read-all-stream-3.1.0.tgz", - "integrity": "sha1-NcPhd/IHjveJ7kv6+kNzB06u9Po=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0", - "readable-stream": "^2.0.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - } - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - }, - "dependencies": { - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "requires": { - "resolve": "^1.1.6" - } - }, - "redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "dev": true, - "requires": { - "indent-string": "^2.1.0", - "strip-indent": "^1.0.1" - } - }, - "redis": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/redis/-/redis-2.8.0.tgz", - "integrity": "sha1-ICKI4/WMSfYHnZevehDhMDrhSwI=", - "dev": true, - "optional": true, - "requires": { - "double-ended-queue": "^2.1.0-0", - "redis-commands": "^1.2.0", - "redis-parser": "^2.6.0" - } - }, - "redis-commands": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.3.5.tgz", - "integrity": "sha1-RJWIlBTx6IYmEYCxRC5ylWAtg6I=", - "dev": true, - "optional": true - }, - "redis-parser": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-2.6.0.tgz", - "integrity": "sha1-Uu0J2srBCPGmMcB+m2mUHnoZUEs=", - "dev": true, - "optional": true - }, - "reduce-css-calc": { - "version": "1.3.0", - "resolved": "http://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz", - "integrity": "sha1-dHyRTgSWFKTJz7umKYca0dKSdxY=", - "dev": true, - "requires": { - "balanced-match": "^0.4.2", - "math-expression-evaluator": "^1.2.14", - "reduce-function-call": "^1.0.1" - }, - "dependencies": { - "balanced-match": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", - "dev": true - } - } - }, - "reduce-function-call": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/reduce-function-call/-/reduce-function-call-1.0.2.tgz", - "integrity": "sha1-WiAL+S4ON3UXUv5FsKszD9S2vpk=", - "dev": true, - "requires": { - "balanced-match": "^0.4.2" - }, - "dependencies": { - "balanced-match": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", - "dev": true - } - } - }, - "regenerate": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", - "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", - "dev": true - }, - "regenerate-unicode-properties": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-7.0.0.tgz", - "integrity": "sha512-s5NGghCE4itSlUS+0WUj88G6cfMVMmH8boTPNvABf8od+2dhT9WDlWu8n01raQAJZMOK8Ch6jSexaRO7swd6aw==", - "dev": true, - "requires": { - "regenerate": "^1.4.0" - } - }, - "regenerator-transform": { - "version": "0.13.3", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.13.3.tgz", - "integrity": "sha512-5ipTrZFSq5vU2YoGoww4uaRVAK4wyYC4TSICibbfEPOruUu8FFP7ErV0BjmbIOEpn3O/k9na9UEdYR/3m7N6uA==", - "dev": true, - "requires": { - "private": "^0.1.6" - } - }, - "regex-cache": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", - "integrity": "sha1-db3FiioUls7EihKDW8VMjVYjNt0=", - "dev": true, - "requires": { - "is-equal-shallow": "^0.1.3" - } - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha1-H07OJ+ALC2XgJHpoEOaoXYOldSw=", - "dev": true, - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - } - }, - "regexpp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.0.tgz", - "integrity": "sha1-sqdTSoXKGwM7z1zp/45W1OB1U2U=", - "dev": true - }, - "regexpu-core": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.2.0.tgz", - "integrity": "sha512-Z835VSnJJ46CNBttalHD/dB+Sj2ezmY6Xp38npwU87peK6mqOzOpV8eYktdkLTEkzzD+JsTcxd84ozd8I14+rw==", - "dev": true, - "requires": { - "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^7.0.0", - "regjsgen": "^0.4.0", - "regjsparser": "^0.3.0", - "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.0.2" - } - }, - "regjsgen": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.4.0.tgz", - "integrity": "sha512-X51Lte1gCYUdlwhF28+2YMO0U6WeN0GLpgpA7LK7mbdDnkQYiwvEpmpe0F/cv5L14EbxgrdayAG3JETBv0dbXA==", - "dev": true - }, - "regjsparser": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.3.0.tgz", - "integrity": "sha512-zza72oZBBHzt64G7DxdqrOo/30bhHkwMUoT0WqfGu98XLd7N+1tsy5MJ96Bk4MD0y74n629RhmrGW6XlnLLwCA==", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true - } - } - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, - "repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true, - "requires": { - "is-finite": "^1.0.0" - } - }, - "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true - }, - "request": { - "version": "2.81.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", - "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", - "dev": true, - "requires": { - "aws-sign2": "~0.6.0", - "aws4": "^1.2.1", - "caseless": "~0.12.0", - "combined-stream": "~1.0.5", - "extend": "~3.0.0", - "forever-agent": "~0.6.1", - "form-data": "~2.1.1", - "har-validator": "~4.2.1", - "hawk": "~3.1.3", - "http-signature": "~1.1.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.7", - "oauth-sign": "~0.8.1", - "performance-now": "^0.2.0", - "qs": "~6.4.0", - "safe-buffer": "^5.0.1", - "stringstream": "~0.0.4", - "tough-cookie": "~2.3.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.0.0" - }, - "dependencies": { - "qs": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", - "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", - "dev": true - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "requires": { - "safe-buffer": "^5.0.1" - } - } - } - }, - "request-progress": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-2.0.1.tgz", - "integrity": "sha1-XTa7V5YcZzqlt4jbyBQf3yO0Tgg=", - "dev": true, - "requires": { - "throttleit": "^1.0.0" - } - }, - "requestretry": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/requestretry/-/requestretry-1.13.0.tgz", - "integrity": "sha1-IT7BAG7rdQ6LjOVBdig9FajVXZQ=", - "dev": true, - "optional": true, - "requires": { - "extend": "^3.0.0", - "lodash": "^4.15.0", - "request": "^2.74.0", - "when": "^3.7.7" - } - }, - "require-from-string": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz", - "integrity": "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg=", - "dev": true - }, - "require-uncached": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", - "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", - "dev": true, - "requires": { - "caller-path": "^0.1.0", - "resolve-from": "^1.0.0" - } - }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", - "dev": true - }, - "resolve": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", - "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", - "dev": true, - "requires": { - "path-parse": "^1.0.5" - } - }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - } - }, - "resolve-from": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", - "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", - "dev": true - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, - "response-time": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/response-time/-/response-time-2.3.2.tgz", - "integrity": "sha1-/6cbq5UtYvfB1Jt0NDVfvGjf/Fo=", - "dev": true, - "requires": { - "depd": "~1.1.0", - "on-headers": "~1.0.1" - }, - "dependencies": { - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true - } - } - }, - "restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "dev": true, - "requires": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" - } - }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha1-uKSCXVvbH8P29Twrwz+BOIaBx7w=", - "dev": true - }, - "right-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", - "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "dev": true, - "requires": { - "align-text": "^0.1.1" - } - }, - "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=", - "dev": true, - "requires": { - "glob": "^7.0.5" - } - }, - "rndm": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz", - "integrity": "sha1-8z/pz7Urv9UgqhgyO8ZdsRCht2w=", - "dev": true - }, - "run-async": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", - "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "dev": true, - "requires": { - "is-promise": "^2.1.0" - } - }, - "run-sequence": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/run-sequence/-/run-sequence-2.2.1.tgz", - "integrity": "sha1-HOZD2jb9jH6n4akynaM/wriJhJU=", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "fancy-log": "^1.3.2", - "plugin-error": "^0.1.2" - }, - "dependencies": { - "arr-diff": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz", - "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", - "dev": true, - "requires": { - "arr-flatten": "^1.0.1", - "array-slice": "^0.2.3" - } - }, - "arr-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz", - "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=", - "dev": true - }, - "array-slice": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", - "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", - "dev": true - }, - "extend-shallow": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz", - "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", - "dev": true, - "requires": { - "kind-of": "^1.1.0" - } - }, - "kind-of": { - "version": "1.1.0", - "resolved": "http://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", - "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=", - "dev": true - }, - "plugin-error": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", - "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", - "dev": true, - "requires": { - "ansi-cyan": "^0.1.1", - "ansi-red": "^0.1.1", - "arr-diff": "^1.0.1", - "arr-union": "^2.0.1", - "extend-shallow": "^1.1.2" - } - } - } - }, - "rxjs": { - "version": "6.3.3", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz", - "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0=", - "dev": true - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "requires": { - "ret": "~0.1.10" - } - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo=", - "dev": true - }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha1-KBYjTiN4vdxOU1T6tcqold9xANk=", - "dev": true - }, - "seek-bzip": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz", - "integrity": "sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=", - "dev": true, - "requires": { - "commander": "~2.8.1" - } - }, - "semver": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", - "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", - "dev": true - }, - "semver-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-1.0.0.tgz", - "integrity": "sha1-kqSWkGX5xwxpR1PVUkj8aPj2Usk=", - "dev": true, - "optional": true - }, - "semver-truncate": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/semver-truncate/-/semver-truncate-1.1.2.tgz", - "integrity": "sha1-V/Qd5pcHpicJp+AQS6IRcQnqR+g=", - "dev": true, - "optional": true, - "requires": { - "semver": "^5.3.0" - }, - "dependencies": { - "semver": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", - "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==", - "dev": true, - "optional": true - } - } - }, - "send": { - "version": "0.13.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.13.2.tgz", - "integrity": "sha1-dl52B8gFVFK7pvCwUllTUJhgNt4=", - "dev": true, - "requires": { - "debug": "~2.2.0", - "depd": "~1.1.0", - "destroy": "~1.0.4", - "escape-html": "~1.0.3", - "etag": "~1.7.0", - "fresh": "0.3.0", - "http-errors": "~1.3.1", - "mime": "1.3.4", - "ms": "0.7.1", - "on-finished": "~2.3.0", - "range-parser": "~1.0.3", - "statuses": "~1.2.1" - }, - "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "http://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "0.7.1" - } - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true - }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - }, - "statuses": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz", - "integrity": "sha1-3e1FzBglbVHtQK7BQkidXGECbSg=", - "dev": true - } - } - }, - "sequencify": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", - "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", - "dev": true - }, - "serve-favicon": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.3.2.tgz", - "integrity": "sha1-3UGeJo3gEqtysxnTN/IQUBP5OB8=", - "dev": true, - "requires": { - "etag": "~1.7.0", - "fresh": "0.3.0", - "ms": "0.7.2", - "parseurl": "~1.3.1" - }, - "dependencies": { - "ms": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", - "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", - "dev": true - } - } - }, - "serve-index": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.7.3.tgz", - "integrity": "sha1-egV/xu4o3GP2RWbl+lexEahq7NI=", - "dev": true, - "requires": { - "accepts": "~1.2.13", - "batch": "0.5.3", - "debug": "~2.2.0", - "escape-html": "~1.0.3", - "http-errors": "~1.3.1", - "mime-types": "~2.1.9", - "parseurl": "~1.3.1" - }, - "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "http://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "0.7.1" - } - }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - } - } - }, - "serve-static": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.10.3.tgz", - "integrity": "sha1-zlpuzTEB/tXsCYJ9rCKpwpv7BTU=", - "dev": true, - "requires": { - "escape-html": "~1.0.3", - "parseurl": "~1.3.1", - "send": "0.13.2" - } - }, - "set-immediate-shim": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", - "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", - "dev": true - }, - "set-value": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", - "integrity": "sha1-ca5KiPD+77v1LR6mBPP7MV67YnQ=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha1-0L2FU2iHtv58DYGMuWLZ2RxU5lY=", - "dev": true - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, - "sigmund": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", - "dev": true - }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true - }, - "slack-node": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/slack-node/-/slack-node-0.2.0.tgz", - "integrity": "sha1-3kuN3aqLeT9h29KTgQT9q/N9+jA=", - "dev": true, - "optional": true, - "requires": { - "requestretry": "^1.2.2" - } - }, - "slash": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", - "dev": true - }, - "slice-ansi": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", - "integrity": "sha1-BE8aSdiEL/MHqta1Be0Xi9lQE00=", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0" - } - }, - "smart-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.0.1.tgz", - "integrity": "sha512-RFqinRVJVcCAL9Uh1oVqE6FZkqsyLiVOYEZ20TqIOjuX7iFVJ+zsbs4RIghnw/pTs7mZvt8ZHhvm1ZUrR4fykg==", - "dev": true - }, - "smtp-connection": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.12.0.tgz", - "integrity": "sha1-1275EnyyPCJZ7bHoNJwujV4tdME=", - "dev": true, - "requires": { - "httpntlm": "1.6.1", - "nodemailer-shared": "1.1.0" - } - }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha1-ZJIufFZbDhQgS6GqfWlkJ40lGC0=", - "dev": true, - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha1-bBdfhv8UvbByRWPo88GwIaKGhTs=", - "dev": true, - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI=", - "dev": true, - "requires": { - "kind-of": "^3.2.0" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "sntp": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", - "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", - "dev": true, - "requires": { - "hoek": "2.x.x" - } - }, - "socket.io": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.0.4.tgz", - "integrity": "sha1-waRZDO/4fs8TxyZS8Eb3FrKeYBQ=", - "dev": true, - "requires": { - "debug": "~2.6.6", - "engine.io": "~3.1.0", - "socket.io-adapter": "~1.1.0", - "socket.io-client": "2.0.4", - "socket.io-parser": "~3.1.1" - } - }, - "socket.io-adapter": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", - "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=", - "dev": true - }, - "socket.io-client": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.0.4.tgz", - "integrity": "sha1-CRilUkBtxeVAs4Dc2Xr8SmQzL44=", - "dev": true, - "requires": { - "backo2": "1.0.2", - "base64-arraybuffer": "0.1.5", - "component-bind": "1.0.0", - "component-emitter": "1.2.1", - "debug": "~2.6.4", - "engine.io-client": "~3.1.0", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "object-component": "0.0.3", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "socket.io-parser": "~3.1.1", - "to-array": "0.1.4" - } - }, - "socket.io-parser": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.1.3.tgz", - "integrity": "sha1-7S2l7nnxCVUDbj2kE7/X8eTYbI4=", - "dev": true, - "requires": { - "component-emitter": "1.2.1", - "debug": "~3.1.0", - "has-binary2": "~1.0.2", - "isarray": "2.0.1" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", - "dev": true - } - } - }, - "socks": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.2.1.tgz", - "integrity": "sha512-0GabKw7n9mI46vcNrVfs0o6XzWzjVa3h6GaSo2UPxtWAROXUWavfJWh1M4PR5tnE0dcnQXZIDFP4yrAysLze/w==", - "dev": true, - "requires": { - "ip": "^1.1.5", - "smart-buffer": "^4.0.1" - } - }, - "socks-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.1.tgz", - "integrity": "sha1-WTa/i3B6mTB5xvN9sgkYIb/6ZHM=", - "dev": true, - "requires": { - "agent-base": "~4.2.0", - "socks": "~2.2.0" - } - }, - "sort-keys": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", - "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", - "dev": true, - "requires": { - "is-plain-obj": "^1.0.0" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "source-map-resolve": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", - "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", - "dev": true, - "requires": { - "atob": "^2.1.1", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, - "sparkles": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", - "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", - "dev": true - }, - "spdx-correct": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.1.tgz", - "integrity": "sha512-hxSPZbRZvSDuOvADntOElzJpenIR7wXJkuoUcUtS0erbgt2fgeaoPIYretfKpslMhfFDY4k0MZ2F5CUzhBsSvQ==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha1-meEZt6XaAOBUkcn6M4t5BII7QdA=", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.1.tgz", - "integrity": "sha512-TfOfPcYGBB5sDuPn3deByxPhmfegAhpDYKSOXZQN81Oyrrif8ZCodOLzK3AesELnCx03kikhyDwh0pfvvQvF8w==", - "dev": true - }, - "split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "dev": true, - "requires": { - "through": "2" - } - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha1-fLCd2jqGWFcFxks5pkZgOGguj+I=", - "dev": true, - "requires": { - "extend-shallow": "^3.0.0" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "squeak": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/squeak/-/squeak-1.3.0.tgz", - "integrity": "sha1-MwRQN7ZDiLVnZ0uEMiplIQc5FsM=", - "dev": true, - "optional": true, - "requires": { - "chalk": "^1.0.0", - "console-stream": "^0.1.1", - "lpad-align": "^1.0.1" - } - }, - "sshpk": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz", - "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", - "dev": true, - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } - } - }, - "stable": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha1-g26zyDgv4pNv6vVEYxAXzn1Ho88=", - "dev": true, - "optional": true - }, - "stat-mode": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-0.2.2.tgz", - "integrity": "sha1-5sgLYjEj19gM8TLOU480YokHJQI=", - "dev": true - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true - }, - "stream-combiner": { - "version": "0.2.2", - "resolved": "http://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", - "integrity": "sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=", - "dev": true, - "requires": { - "duplexer": "~0.1.1", - "through": "~2.3.4" - } - }, - "stream-combiner2": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", - "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", - "dev": true, - "requires": { - "duplexer2": "~0.1.0", - "readable-stream": "^2.0.2" - }, - "dependencies": { - "duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", - "dev": true, - "requires": { - "readable-stream": "^2.0.2" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "stream-consume": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.1.tgz", - "integrity": "sha1-0721mMK9CugrjKx6xQsRB6eZbEg=", - "dev": true - }, - "stream-counter": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/stream-counter/-/stream-counter-0.2.0.tgz", - "integrity": "sha1-3tJmVWMZyLDiIoErnPOyb6fZR94=", - "dev": true, - "requires": { - "readable-stream": "~1.1.8" - } - }, - "stream-shift": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", - "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", - "dev": true - }, - "streamroller": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", - "integrity": "sha1-odG3z4PTmvsNYwSaWsv5NJO99ks=", - "dev": true, - "requires": { - "date-format": "^1.2.0", - "debug": "^3.1.0", - "mkdirp": "^0.5.1", - "readable-stream": "^2.3.0" - }, - "dependencies": { - "debug": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.5.tgz", - "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "strict-uri-encode": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", - "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "stringstream": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz", - "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==", - "dev": true - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-bom": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", - "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", - "dev": true, - "requires": { - "first-chunk-stream": "^1.0.0", - "is-utf8": "^0.2.0" - } - }, - "strip-bom-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz", - "integrity": "sha1-5xRDmFd9Uaa+0PoZlPoF9D/ZiO4=", - "dev": true, - "requires": { - "first-chunk-stream": "^1.0.0", - "strip-bom": "^2.0.0" - }, - "dependencies": { - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } - } - } - }, - "strip-dirs": { - "version": "1.1.1", - "resolved": "http://registry.npmjs.org/strip-dirs/-/strip-dirs-1.1.1.tgz", - "integrity": "sha1-lgu9EoeETzl1pFWKoQOoJV4kVqA=", - "dev": true, - "requires": { - "chalk": "^1.0.0", - "get-stdin": "^4.0.1", - "is-absolute": "^0.1.5", - "is-natural-number": "^2.0.0", - "minimist": "^1.1.0", - "sum-up": "^1.0.1" - }, - "dependencies": { - "is-absolute": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-0.1.7.tgz", - "integrity": "sha1-hHSREZ/MtftDYhfMc39/qtUPYD8=", - "dev": true, - "requires": { - "is-relative": "^0.1.0" - } - }, - "is-relative": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.1.3.tgz", - "integrity": "sha1-kF/uiuhvRbPsYUvDwVyGnfCHboI=", - "dev": true - }, - "minimist": { - "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true, - "optional": true - }, - "strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "dev": true, - "requires": { - "get-stdin": "^4.0.1" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true - }, - "strip-outer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", - "integrity": "sha1-sv0qv2YEudHmATBXGV34Nrip1jE=", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.2" - } - }, - "sum-up": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sum-up/-/sum-up-1.0.3.tgz", - "integrity": "sha1-HGYfZnBX9jvLeHWqFDi8FiUlFW4=", - "dev": true, - "requires": { - "chalk": "^1.0.0" - } - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - }, - "svgo": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-0.7.2.tgz", - "integrity": "sha1-n1dyQTlSE1xv779Ar+ak+qiLS7U=", - "dev": true, - "requires": { - "coa": "~1.0.1", - "colors": "~1.1.2", - "csso": "~2.3.1", - "js-yaml": "~3.7.0", - "mkdirp": "~0.5.1", - "sax": "~1.2.1", - "whet.extend": "~0.9.9" - }, - "dependencies": { - "colors": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", - "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", - "dev": true - } - } - }, - "table": { - "version": "4.0.3", - "resolved": "http://registry.npmjs.org/table/-/table-4.0.3.tgz", - "integrity": "sha512-S7rnFITmBH1EnyKcvxBh1LjYeQMmnZtCXSEbHcH6S0NoKit24ZuFO/T1vDcLdYsLQkM188PVVhQmzKIuThNkKg==", - "dev": true, - "requires": { - "ajv": "^6.0.1", - "ajv-keywords": "^3.0.0", - "chalk": "^2.1.0", - "lodash": "^4.17.4", - "slice-ansi": "1.0.0", - "string-width": "^2.1.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "tar-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", - "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", - "dev": true, - "requires": { - "bl": "^1.0.0", - "buffer-alloc": "^1.2.0", - "end-of-stream": "^1.0.0", - "fs-constants": "^1.0.0", - "readable-stream": "^2.3.0", - "to-buffer": "^1.1.1", - "xtend": "^4.0.0" - }, - "dependencies": { - "end-of-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha1-7SljTRm6ukY7bOa4CjchPqtx7EM=", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "temp-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz", - "integrity": "sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0=", - "dev": true, - "optional": true - }, - "tempfile": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/tempfile/-/tempfile-2.0.0.tgz", - "integrity": "sha1-awRGhWqbERTRhW/8vlCczLCXcmU=", - "dev": true, - "optional": true, - "requires": { - "temp-dir": "^1.0.0", - "uuid": "^3.0.1" - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "throttleit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", - "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=", - "dev": true - }, - "through": { - "version": "2.3.8", - "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "through2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "dev": true, - "requires": { - "readable-stream": "^2.1.5", - "xtend": "~4.0.1" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "through2-concurrent": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/through2-concurrent/-/through2-concurrent-1.1.1.tgz", - "integrity": "sha1-EctOpMnjG8puTB5tukjRxyjDUks=", - "dev": true, - "requires": { - "through2": "^2.0.0" - } - }, - "through2-filter": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz", - "integrity": "sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=", - "dev": true, - "requires": { - "through2": "~2.0.0", - "xtend": "~4.0.0" - } - }, - "thunkify": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/thunkify/-/thunkify-2.1.2.tgz", - "integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0=", - "dev": true, - "optional": true - }, - "tildify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", - "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", - "dev": true, - "requires": { - "os-homedir": "^1.0.0" - } - }, - "time-stamp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", - "dev": true - }, - "timed-out": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-3.1.3.tgz", - "integrity": "sha1-lYYL/MXHbCd/j4Mm/Q9bLiDrohc=", - "dev": true - }, - "timespan": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/timespan/-/timespan-2.3.0.tgz", - "integrity": "sha1-SQLOBAvRPYRcj1myfp1ZutbzmSk=", - "dev": true, - "optional": true - }, - "tiny-lr": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-0.2.1.tgz", - "integrity": "sha1-s/26gC5dVqM8L28QeUsy5Hescp0=", - "dev": true, - "requires": { - "body-parser": "~1.14.0", - "debug": "~2.2.0", - "faye-websocket": "~0.10.0", - "livereload-js": "^2.2.0", - "parseurl": "~1.3.0", - "qs": "~5.1.0" - }, - "dependencies": { - "body-parser": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.14.2.tgz", - "integrity": "sha1-EBXLH+LEQ4WCWVgdtTMy+NDPUPk=", - "dev": true, - "requires": { - "bytes": "2.2.0", - "content-type": "~1.0.1", - "debug": "~2.2.0", - "depd": "~1.1.0", - "http-errors": "~1.3.1", - "iconv-lite": "0.4.13", - "on-finished": "~2.3.0", - "qs": "5.2.0", - "raw-body": "~2.1.5", - "type-is": "~1.6.10" - }, - "dependencies": { - "qs": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-5.2.0.tgz", - "integrity": "sha1-qfMRQq9GjLcrJbMBNrokVoNJFr4=", - "dev": true - } - } - }, - "bytes": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.2.0.tgz", - "integrity": "sha1-/TVGSkA/b5EXwt42Cez/nK4ABYg=", - "dev": true - }, - "debug": { - "version": "2.2.0", - "resolved": "http://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "0.7.1" - } - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true - }, - "iconv-lite": { - "version": "0.4.13", - "resolved": "http://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", - "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=", - "dev": true - }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - }, - "qs": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-5.1.0.tgz", - "integrity": "sha1-TZMuXH6kEcynajEtOaYGIA/VDNk=", - "dev": true - } - } - }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha1-bTQzWIl2jSGyvNoKonfO07G/rfk=", - "dev": true, - "requires": { - "os-tmpdir": "~1.0.2" - } - }, - "to-absolute-glob": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz", - "integrity": "sha1-HN+kcqnvUMI57maZm2YsoOs5k38=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "to-array": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", - "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", - "dev": true - }, - "to-buffer": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", - "integrity": "sha1-STvUj2LXxD/N7TE6A9ytsuEhOoA=", - "dev": true - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha1-E8/dmzNlUvMLUfM6iuG0Knp1mc4=", - "dev": true, - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - }, - "tough-cookie": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", - "integrity": "sha1-7GDO44rGdQY//JelwYlwV47oNlU=", - "dev": true, - "requires": { - "punycode": "^1.4.1" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - } - } - }, - "trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", - "dev": true - }, - "trim-repeated": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", - "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.2" - } - }, - "trim-right": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", - "dev": true - }, - "tryit": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz", - "integrity": "sha1-OTvnMKlEb9Hq1tpZoBQwjzbCics=", - "dev": true - }, - "tslib": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", - "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", - "dev": true - }, - "tsscmp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.5.tgz", - "integrity": "sha1-fcSjOvcVgatDN9qR2FylQn69mpc=", - "dev": true - }, - "tunnel-agent": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", - "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", - "dev": true - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true, - "optional": true - }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2" - } - }, - "type-is": { - "version": "1.6.16", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", - "integrity": "sha1-+JzjQVQcZysl7nrjxz3uOyvlAZQ=", - "dev": true, - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.18" - } - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "uglify-js": { - "version": "2.8.29", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", - "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", - "dev": true, - "requires": { - "source-map": "~0.5.1", - "uglify-to-browserify": "~1.0.0", - "yargs": "~3.10.0" - } - }, - "uglify-to-browserify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", - "dev": true, - "optional": true - }, - "uid-safe": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.4.tgz", - "integrity": "sha1-Otbzg2jG1MjHXsF2I/t5qh0HHYE=", - "dev": true, - "requires": { - "random-bytes": "~1.0.0" - } - }, - "ultron": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", - "integrity": "sha1-n+FTahCmZKZSZqHjzPhf02MCvJw=", - "dev": true - }, - "unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", - "dev": true - }, - "underscore": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", - "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=", - "dev": true - }, - "unicode-canonical-property-names-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", - "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", - "dev": true - }, - "unicode-match-property-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", - "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", - "dev": true, - "requires": { - "unicode-canonical-property-names-ecmascript": "^1.0.4", - "unicode-property-aliases-ecmascript": "^1.0.4" - } - }, - "unicode-match-property-value-ecmascript": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.0.2.tgz", - "integrity": "sha512-Rx7yODZC1L/T8XKo/2kNzVAQaRE88AaMvI1EF/Xnj3GW2wzN6fop9DDWuFAKUVFH7vozkz26DzP0qyWLKLIVPQ==", - "dev": true - }, - "unicode-property-aliases-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.4.tgz", - "integrity": "sha512-2WSLa6OdYd2ng8oqiGIWnJqyFArvhn+5vgx5GTxMbUYjCYKUcuKS62YLFF0R/BDGlB1yzXjQOLtPAfHsgirEpg==", - "dev": true - }, - "union-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", - "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^0.4.3" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "set-value": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", - "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.1", - "to-object-path": "^0.3.0" - } - } - } - }, - "uniq": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", - "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", - "dev": true - }, - "uniqs": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", - "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=", - "dev": true - }, - "unique-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", - "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=", - "dev": true - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "dev": true - }, - "unquote": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", - "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=", - "dev": true, - "optional": true - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - } - } - }, - "unzip-response": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-1.0.2.tgz", - "integrity": "sha1-uYTwh3/AqJwsdzzB73tbIytbBv4=", - "dev": true - }, - "upath": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", - "integrity": "sha1-NSVll+RqWB20eT0M5H+prr/J+r0=", - "dev": true - }, - "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha1-lMVA4f93KVbiKZUHwBCupsiDjrA=", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, - "url-parse-lax": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", - "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", - "dev": true, - "requires": { - "prepend-http": "^1.0.1" - } - }, - "url-regex": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/url-regex/-/url-regex-3.2.0.tgz", - "integrity": "sha1-260eDJ4p4QXdCx8J9oYvf9tIJyQ=", - "dev": true, - "optional": true, - "requires": { - "ip-regex": "^1.0.1" - } - }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true - }, - "user-home": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", - "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", - "dev": true - }, - "useragent": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.2.1.tgz", - "integrity": "sha1-z1k+9PLRdYdei7ZY6pLhik/QbY4=", - "dev": true, - "requires": { - "lru-cache": "2.2.x", - "tmp": "0.0.x" - }, - "dependencies": { - "lru-cache": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.2.4.tgz", - "integrity": "sha1-bGWGGb7PFAMdDQtZSxYELOTcBj0=", - "dev": true - } - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "util.promisify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", - "integrity": "sha1-RA9xZaRZyaFtwUXrjnLzVocJcDA=", - "dev": true, - "optional": true, - "requires": { - "define-properties": "^1.1.2", - "object.getownpropertydescriptors": "^2.0.3" - } - }, - "utils-merge": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", - "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=", - "dev": true - }, - "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", - "dev": true - }, - "uws": { - "version": "9.14.0", - "resolved": "https://registry.npmjs.org/uws/-/uws-9.14.0.tgz", - "integrity": "sha1-+sg4a+/DOno3BcvVjcR7Qwyk3ZU=", - "dev": true, - "optional": true - }, - "v8flags": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", - "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", - "dev": true, - "requires": { - "user-home": "^1.1.1" - } - }, - "vali-date": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz", - "integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=", - "dev": true - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "vary": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.0.1.tgz", - "integrity": "sha1-meSYFWaihhGN+yuBc1ffeZM3bRA=", - "dev": true - }, - "vendors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.2.tgz", - "integrity": "sha1-f8te759WI7FWvOqJ7DfWNnbyGAE=", - "dev": true - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } - } - }, - "vhost": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/vhost/-/vhost-3.0.2.tgz", - "integrity": "sha1-L7HezUxGaqiLD5NBrzPcGv8keNU=", - "dev": true - }, - "vinyl": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", - "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", - "dev": true, - "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", - "replace-ext": "0.0.1" - } - }, - "vinyl-assign": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/vinyl-assign/-/vinyl-assign-1.2.1.tgz", - "integrity": "sha1-TRmIkbVRWRHXcajNnFSApGoHSkU=", - "dev": true, - "requires": { - "object-assign": "^4.0.1", - "readable-stream": "^2.0.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "vinyl-bufferstream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/vinyl-bufferstream/-/vinyl-bufferstream-1.0.1.tgz", - "integrity": "sha1-BTeGn1gO/6TKRay0dXnkuf5jCBo=", - "dev": true, - "requires": { - "bufferstreams": "1.0.1" - } - }, - "vinyl-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/vinyl-file/-/vinyl-file-2.0.0.tgz", - "integrity": "sha1-p+v1/779obfRjRQPyweyI++2dRo=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.3.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0", - "strip-bom-stream": "^2.0.0", - "vinyl": "^1.1.0" - }, - "dependencies": { - "first-chunk-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-2.0.0.tgz", - "integrity": "sha1-G97NuOCDwGZLkZRVgVd6Q6nzHXA=", - "dev": true, - "requires": { - "readable-stream": "^2.0.2" - } - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } - }, - "strip-bom-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-2.0.0.tgz", - "integrity": "sha1-+H217yYT9paKpUWr/h7HKLaoKco=", - "dev": true, - "requires": { - "first-chunk-stream": "^2.0.0", - "strip-bom": "^2.0.0" - } - }, - "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, - "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", - "replace-ext": "0.0.1" - } - } - } - }, - "vinyl-fs": { - "version": "0.3.14", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", - "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", - "dev": true, - "requires": { - "defaults": "^1.0.0", - "glob-stream": "^3.1.5", - "glob-watcher": "^0.0.6", - "graceful-fs": "^3.0.0", - "mkdirp": "^0.5.0", - "strip-bom": "^1.0.0", - "through2": "^0.6.1", - "vinyl": "^0.4.0" - }, - "dependencies": { - "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" - } - }, - "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "dev": true, - "requires": { - "clone": "^0.2.0", - "clone-stats": "^0.0.1" - } - } - } - }, - "vinyl-sourcemaps-apply": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", - "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", - "dev": true, - "requires": { - "source-map": "^0.5.1" - } - }, - "void-elements": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", - "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", - "dev": true - }, - "ware": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ware/-/ware-1.3.0.tgz", - "integrity": "sha1-0bFPOdLiy0q4xAmPdW/ksWTkc9Q=", - "dev": true, - "requires": { - "wrap-fn": "^0.1.0" - } - }, - "websocket-driver": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", - "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", - "dev": true, - "requires": { - "http-parser-js": ">=0.4.0", - "websocket-extensions": ">=0.1.1" - } - }, - "websocket-extensions": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", - "integrity": "sha1-XS/yKXcAPsaHpLhwc9+7rBRszyk=", - "dev": true - }, - "when": { - "version": "3.7.8", - "resolved": "https://registry.npmjs.org/when/-/when-3.7.8.tgz", - "integrity": "sha1-xxMLan6gRpPoQs3J56Hyqjmjn4I=", - "dev": true - }, - "whet.extend": { - "version": "0.9.9", - "resolved": "https://registry.npmjs.org/whet.extend/-/whet.extend-0.9.9.tgz", - "integrity": "sha1-+HfVv2SMl+WqVC+twW1qJZucEaE=", - "dev": true - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "window-size": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", - "dev": true - }, - "with-callback": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/with-callback/-/with-callback-1.0.2.tgz", - "integrity": "sha1-oJYpuakgAo1yFAT7Q1vc/1yRvCE=", - "dev": true, - "optional": true - }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true - }, - "wrap-fn": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/wrap-fn/-/wrap-fn-0.1.5.tgz", - "integrity": "sha1-8htuQQFv9KfjFyDbxjoJAWvfmEU=", - "dev": true, - "requires": { - "co": "3.1.0" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "write": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", - "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", - "dev": true, - "requires": { - "mkdirp": "^0.5.1" - } - }, - "ws": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", - "integrity": "sha1-8c+E/i1ekB686U767OeF8YeiKPI=", - "dev": true, - "requires": { - "async-limiter": "~1.0.0", - "safe-buffer": "~5.1.0", - "ultron": "~1.1.0" - } - }, - "xmlhttprequest-ssl": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", - "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", - "dev": true - }, - "xregexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", - "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=", - "dev": true, - "optional": true - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true, - "optional": true - }, - "yargs": { - "version": "3.10.0", - "resolved": "http://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true, - "requires": { - "camelcase": "^1.0.2", - "cliui": "^2.1.0", - "decamelize": "^1.0.0", - "window-size": "0.1.0" - }, - "dependencies": { - "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", - "dev": true - } - } - }, - "yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", - "dev": true, - "requires": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, - "yeast": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", - "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=", - "dev": true - } - } -} From ae88932bb89fee439d7329c9f14d0bbd5cf03b6e Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Sun, 21 Oct 2018 12:38:01 +0200 Subject: [PATCH 058/469] Revert "Virtualizing registration of the cache helper" This reverts commit 04944f2c0ca87096c1cb7fa7053c37a804985fbd. --- src/Umbraco.Core/Runtime/CoreRuntime.cs | 26 +++++++++--------------- src/Umbraco.Web/Runtime/WebRuntime.cs | 27 ++++++++++--------------- 2 files changed, 20 insertions(+), 33 deletions(-) diff --git a/src/Umbraco.Core/Runtime/CoreRuntime.cs b/src/Umbraco.Core/Runtime/CoreRuntime.cs index dfe9c5d9f9..0ad621b97c 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntime.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntime.cs @@ -195,7 +195,15 @@ namespace Umbraco.Core.Runtime container.ComposeConfiguration(); - RegisterCacheHelper(container); + // register caches + // need the deep clone runtime cache profiver to ensure entities are cached properly, ie + // are cloned in and cloned out - no request-based cache here since no web-based context, + // will be overriden later or + container.RegisterSingleton(_ => new CacheHelper( + new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()), + new StaticCacheProvider(), + NullCacheProvider.Instance, + new IsolatedRuntimeCache(type => new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider())))); container.RegisterSingleton(f => f.GetInstance().RuntimeCache); // register the plugin manager @@ -228,22 +236,6 @@ namespace Umbraco.Core.Runtime container.RegisterSingleton(); } - protected virtual void RegisterCacheHelper(IContainer container) - { -// register caches - // need the deep clone runtime cache profiver to ensure entities are cached properly, ie - // are cloned in and cloned out - no request-based cache here since no web-based context, - // will be overriden later or - container.RegisterSingleton( - "CacheHelper", - _ => new CacheHelper( - new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()), - new StaticCacheProvider(), - NullCacheProvider.Instance, - new IsolatedRuntimeCache(type => - new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider())))); - } - protected virtual void ComposeMapperCollection(MapperCollectionBuilder builder) { builder.AddCore(); diff --git a/src/Umbraco.Web/Runtime/WebRuntime.cs b/src/Umbraco.Web/Runtime/WebRuntime.cs index 424a3e4504..38c0c5ad50 100644 --- a/src/Umbraco.Web/Runtime/WebRuntime.cs +++ b/src/Umbraco.Web/Runtime/WebRuntime.cs @@ -57,25 +57,20 @@ namespace Umbraco.Web.Runtime // replace CoreRuntime's IProfiler registration container.RegisterSingleton(_ => _webProfiler); - container.RegisterSingleton(); // required for hybrid accessors - } - - protected override void RegisterCacheHelper(IContainer container) - { // replace CoreRuntime's CacheHelper registration - container.RegisterSingleton( - "CacheHelper", - _ => new CacheHelper( + container.RegisterSingleton(_ => new CacheHelper( + // we need to have the dep clone runtime cache provider to ensure + // all entities are cached properly (cloned in and cloned out) + new DeepCloneRuntimeCacheProvider(new HttpRuntimeCacheProvider(HttpRuntime.Cache)), + new StaticCacheProvider(), + // we need request based cache when running in web-based context + new HttpRequestCacheProvider(), + new IsolatedRuntimeCache(type => // we need to have the dep clone runtime cache provider to ensure // all entities are cached properly (cloned in and cloned out) - new DeepCloneRuntimeCacheProvider(new HttpRuntimeCacheProvider(HttpRuntime.Cache)), - new StaticCacheProvider(), - // we need request based cache when running in web-based context - new HttpRequestCacheProvider(), - new IsolatedRuntimeCache(type => - // we need to have the dep clone runtime cache provider to ensure - // all entities are cached properly (cloned in and cloned out) - new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider())))); + new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider())))); + + container.RegisterSingleton(); // required for hybrid accessors } #region Getters From fbd73dd5969e82a483554c272e077d78cac52b3a Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Mon, 22 Oct 2018 23:21:27 +0200 Subject: [PATCH 059/469] Revert "REVIEW/FIX: Just removing placeholder IApplicationTreeService and ISectionService registrations until we figure defaulting." This reverts commit 57d22a87c03d715cce9ede4e4f8bb92a7b5617e9. --- src/Umbraco.Core/Composing/Composers/ServicesComposer.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs index ed8bece0e1..16b824e481 100644 --- a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs @@ -57,9 +57,8 @@ namespace Umbraco.Core.Composing.Composers //TODO: These are replaced in the web project - we need to declare them so that // something is wired up, just not sure this is very nice but will work for now. - // fixme - we need to get rid of re-registering, and I need this gone for now. >< - //container.RegisterSingleton(); - //container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); return container; } From 026f10f38af4928eeb7c0b02b139dd4d7cad12f0 Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Tue, 23 Oct 2018 21:31:20 +0200 Subject: [PATCH 060/469] Register instance by name --- src/Umbraco.Core/Composing/IContainer.cs | 5 +++++ .../Composing/LightInject/LightInjectContainer.cs | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/src/Umbraco.Core/Composing/IContainer.cs b/src/Umbraco.Core/Composing/IContainer.cs index 2937fb2b02..97a9d47437 100644 --- a/src/Umbraco.Core/Composing/IContainer.cs +++ b/src/Umbraco.Core/Composing/IContainer.cs @@ -119,6 +119,11 @@ namespace Umbraco.Core.Composing /// void RegisterInstance(Type serviceType, object instance); + /// + /// Registers a service with a named implementing instance. + /// + void RegisterInstance(Type serviceType, object instance, string name); + /// /// Registers a base type for auto-registration. /// diff --git a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs index d4b88e862c..1302676514 100644 --- a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs +++ b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs @@ -285,6 +285,10 @@ namespace Umbraco.Core.Composing.LightInject public void RegisterInstance(Type serviceType, object instance) => Container.RegisterInstance(serviceType, instance); + /// + public void RegisterInstance(Type serviceType, object instance, string name) + => Container.RegisterInstance(serviceType, instance, name); + /// public void RegisterAuto(Type serviceBaseType) { From 25718dbe5ac492d8eda634ac480b7387a299ed1b Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Wed, 24 Oct 2018 12:05:25 +0200 Subject: [PATCH 061/469] Add content app badges --- .../less/components/umb-editor-navigation.less | 18 +++++++++++++++++- .../editor/umb-editor-navigation.html | 1 + 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation.less index 407cfaf6a7..c58162bb5d 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation.less @@ -19,6 +19,7 @@ align-items: center; justify-content: center; height: @editorHeaderHeight; + position: relative; } .umb-sub-views-nav-item:focus { @@ -46,6 +47,21 @@ margin-bottom: 5px; } +.umb-sub-views-nav-item .badge { + position: absolute; + top: 6px; + right: 6px; + min-width: 16px; + background-color: @turquoise-d1; + border-radius: 50%; + color: @white; + text-align: center; + font-size: 10px; + font-weight: bold; + padding: 2px; + line-height: 16px; +} + .umb-sub-views-nav-item-text { font-size: 12px; line-height: 1em; @@ -80,4 +96,4 @@ grid-template-columns: 1fr 1fr 1fr; min-width: auto; margin-top: 10px; -} \ No newline at end of file +} diff --git a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-navigation.html b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-navigation.html index ee46a89490..f6ce09515e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-navigation.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-navigation.html @@ -12,6 +12,7 @@ ng-class="{'is-active': item.active, '-has-error': item.hasError}"> {{ item.name }} +
{{item.badge.count}}
From 634c2072ca24fb25a790612fc826c377be0bd44f Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Wed, 24 Oct 2018 15:49:35 +0200 Subject: [PATCH 062/469] Add optional alert color --- .../src/less/components/umb-editor-navigation.less | 4 ++++ .../src/views/components/editor/umb-editor-navigation.html | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation.less index c58162bb5d..f94a874892 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation.less @@ -60,6 +60,10 @@ font-weight: bold; padding: 2px; line-height: 16px; + + &.-alert { + background-color: @red-l1; + } } .umb-sub-views-nav-item-text { diff --git a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-navigation.html b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-navigation.html index f6ce09515e..c7dfa26b3c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-navigation.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-navigation.html @@ -12,7 +12,7 @@ ng-class="{'is-active': item.active, '-has-error': item.hasError}"> {{ item.name }} -
{{item.badge.count}}
+
{{item.badge.count}}
From abcdfc27c56e2df30643764b00bfa79d9f05659f Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Wed, 24 Oct 2018 20:15:17 +0200 Subject: [PATCH 063/469] Add a white border around the badge to make it stand out if it overlaps the app icon --- .../src/less/components/umb-editor-navigation.less | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation.less index f94a874892..cb2d0c8be4 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation.less @@ -52,10 +52,10 @@ top: 6px; right: 6px; min-width: 16px; - background-color: @turquoise-d1; - border-radius: 50%; color: @white; - text-align: center; + background-color: @turquoise-d1; + border: 2px solid @white; + border-radius: 50%; font-size: 10px; font-weight: bold; padding: 2px; From ccd3354b8ad0d8dd06da40603830ebfc8e4e3186 Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Wed, 24 Oct 2018 21:06:52 +0200 Subject: [PATCH 064/469] Revert "Wrapping server messenger factory to avoid re-registering for now." This reverts commit 1198191e051fd40891177ee30ffe8e9d33a3c856. --- .../Components/CompositionExtensions.cs | 43 ++++++------------- .../Runtime/CoreRuntimeComponent.cs | 3 +- 2 files changed, 13 insertions(+), 33 deletions(-) diff --git a/src/Umbraco.Core/Components/CompositionExtensions.cs b/src/Umbraco.Core/Components/CompositionExtensions.cs index 1bbb3faff0..abc0fa3862 100644 --- a/src/Umbraco.Core/Components/CompositionExtensions.cs +++ b/src/Umbraco.Core/Components/CompositionExtensions.cs @@ -172,23 +172,16 @@ namespace Umbraco.Core.Components composition.Container.RegisterSingleton(_ => registrar); } - - // review since only one is called in the core for now, I remove this - // it allows us to wrap the factory to "allow re-registration". - ///// - ///// Sets the server messenger. - ///// - ///// The type of the server registrar. - ///// The composition. - //public static void SetServerMessenger(this Composition composition) - // where T : IServerMessenger - //{ - // composition.Container.Register(Lifetime.Singleton); - //} - - private static Func serverMessengerFactory = null; - private static bool serverMessengerIsRegistered = false; - private static Func wrappedServerMessengerFactory = c => serverMessengerFactory(c); + /// + /// Sets the server messenger. + /// + /// The type of the server registrar. + /// The composition. + public static void SetServerMessenger(this Composition composition) + where T : IServerMessenger + { + composition.Container.Register(Lifetime.Singleton); + } /// /// Sets the server messenger. @@ -197,13 +190,7 @@ namespace Umbraco.Core.Components /// A function creating a server messenger. public static void SetServerMessenger(this Composition composition, Func factory) { - if (!serverMessengerIsRegistered) - { - serverMessengerIsRegistered = true; - composition.Container.RegisterSingleton(wrappedServerMessengerFactory); - } - - serverMessengerFactory = factory; + composition.Container.RegisterSingleton(factory); } /// @@ -213,13 +200,7 @@ namespace Umbraco.Core.Components /// A server messenger. public static void SetServerMessenger(this Composition composition, IServerMessenger registrar) { - if (!serverMessengerIsRegistered) - { - serverMessengerIsRegistered = true; - composition.Container.RegisterSingleton(wrappedServerMessengerFactory); - } - - serverMessengerFactory = c => registrar; + composition.Container.RegisterSingleton(_ => registrar); } /// diff --git a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs index ae9955706c..9d7c3e5a6a 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs @@ -74,8 +74,7 @@ namespace Umbraco.Core.Runtime // by default we'll use the database server messenger with default options (no callbacks), // this will be overridden by either the legacy thing or the db thing in the corresponding // components in the web project - fixme - should obsolete the legacy thing - composition.SetServerMessenger( - factory + composition.Container.RegisterSingleton(factory => new DatabaseServerMessenger( factory.GetInstance(), factory.GetInstance(), From 06876777187ed9a7c27b7baf52349b946b770694 Mon Sep 17 00:00:00 2001 From: Stephan Date: Thu, 25 Oct 2018 10:57:57 +0200 Subject: [PATCH 065/469] Fix merge --- src/Umbraco.Web/Umbraco.Web.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 4273cee9a4..6a7fea511c 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -521,7 +521,6 @@ ASPXCodeBehind - From 5c077c3e5d0eb6a15610f87c4927bca81604c0b4 Mon Sep 17 00:00:00 2001 From: Stephan Date: Thu, 25 Oct 2018 11:04:49 +0200 Subject: [PATCH 066/469] Fix merge --- src/Umbraco.Core/Services/Implement/ContentService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Core/Services/Implement/ContentService.cs b/src/Umbraco.Core/Services/Implement/ContentService.cs index 2cd9051e72..200c5af096 100644 --- a/src/Umbraco.Core/Services/Implement/ContentService.cs +++ b/src/Umbraco.Core/Services/Implement/ContentService.cs @@ -1994,7 +1994,7 @@ namespace Umbraco.Core.Services.Implement if (raiseEvents && published.Any()) scope.Events.Dispatch(Published, this, new PublishEventArgs(published, false, false), "Published"); - Audit(AuditType.Sort, "Sorting content performed by user", userId, 0); + Audit(AuditType.Sort, userId, 0, "Sorting content performed by user"); return true; } From d3a894b7a300a97c28f9b661971cf26013f19e97 Mon Sep 17 00:00:00 2001 From: Stephan Date: Thu, 25 Oct 2018 14:47:18 +0200 Subject: [PATCH 067/469] Add package-lock.json back --- src/Umbraco.Web.UI.Client/package-lock.json | 17546 ++++++++++++++++++ 1 file changed, 17546 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/package-lock.json diff --git a/src/Umbraco.Web.UI.Client/package-lock.json b/src/Umbraco.Web.UI.Client/package-lock.json new file mode 100644 index 0000000000..3ae35a0de8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/package-lock.json @@ -0,0 +1,17546 @@ +{ + "requires": true, + "lockfileVersion": 1, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/core": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.1.2.tgz", + "integrity": "sha512-IFeSSnjXdhDaoysIlev//UzHZbdEmm7D0EIH2qtse9xK7mXEZQpYjs2P00XlP1qYsYvid79p+Zgg6tz1mp6iVw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.1.2", + "@babel/helpers": "^7.1.2", + "@babel/parser": "^7.1.2", + "@babel/template": "^7.1.2", + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.1.2", + "convert-source-map": "^1.1.0", + "debug": "^3.1.0", + "json5": "^0.5.0", + "lodash": "^4.17.10", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "debug": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.5.tgz", + "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "semver": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", + "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.1.2.tgz", + "integrity": "sha512-70A9HWLS/1RHk3Ck8tNHKxOoKQuSKocYgwDN85Pyl/RBduss6AKxUR7RIZ/lzduQMSYfWEM4DDBu6A+XGbkFig==", + "dev": true, + "requires": { + "@babel/types": "^7.1.2", + "jsesc": "^2.5.1", + "lodash": "^4.17.10", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz", + "integrity": "sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz", + "integrity": "sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w==", + "dev": true, + "requires": { + "@babel/helper-explode-assignable-expression": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-call-delegate": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.1.0.tgz", + "integrity": "sha512-YEtYZrw3GUK6emQHKthltKNZwszBcHK58Ygcis+gVUrF4/FmTVr5CCqQNSfmvg2y+YDEANyYoaLz/SHsnusCwQ==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.0.0", + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-define-map": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.1.0.tgz", + "integrity": "sha512-yPPcW8dc3gZLN+U1mhYV91QU3n5uTbx7DUdf8NnPbjS0RMwBuHi9Xt2MUgppmNz7CJxTBWsGczTiEp1CSOTPRg==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.1.0", + "@babel/types": "^7.0.0", + "lodash": "^4.17.10" + } + }, + "@babel/helper-explode-assignable-expression": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz", + "integrity": "sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA==", + "dev": true, + "requires": { + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-function-name": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", + "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.0.0.tgz", + "integrity": "sha512-Ggv5sldXUeSKsuzLkddtyhyHe2YantsxWKNi7A+7LeD12ExRDWTRk29JCXpaHPAbMaIPZSil7n+lq78WY2VY7w==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.0.0.tgz", + "integrity": "sha512-avo+lm/QmZlv27Zsi0xEor2fKcqWG56D5ae9dzklpIaY7cQMK5N8VSpaNVPPagiqmy7LrEjK1IWdGMOqPu5csg==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-module-imports": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz", + "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-module-transforms": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.1.0.tgz", + "integrity": "sha512-0JZRd2yhawo79Rcm4w0LwSMILFmFXjugG3yqf+P/UsKsRS1mJCmMwwlHDlMg7Avr9LrvSpp4ZSULO9r8jpCzcw==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-simple-access": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0", + "lodash": "^4.17.10" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz", + "integrity": "sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", + "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==", + "dev": true + }, + "@babel/helper-regex": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.0.0.tgz", + "integrity": "sha512-TR0/N0NDCcUIUEbqV6dCO+LptmmSQFQ7q70lfcEB4URsjD0E1HzicrwUH+ap6BAQ2jhCX9Q4UqZy4wilujWlkg==", + "dev": true, + "requires": { + "lodash": "^4.17.10" + } + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz", + "integrity": "sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-wrap-function": "^7.1.0", + "@babel/template": "^7.1.0", + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-replace-supers": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.1.0.tgz", + "integrity": "sha512-BvcDWYZRWVuDeXTYZWxekQNO5D4kO55aArwZOTFXw6rlLQA8ZaDicJR1sO47h+HrnCiDFiww0fSPV0d713KBGQ==", + "dev": true, + "requires": { + "@babel/helper-member-expression-to-functions": "^7.0.0", + "@babel/helper-optimise-call-expression": "^7.0.0", + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-simple-access": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz", + "integrity": "sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w==", + "dev": true, + "requires": { + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz", + "integrity": "sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-wrap-function": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.1.0.tgz", + "integrity": "sha512-R6HU3dete+rwsdAfrOzTlE9Mcpk4RjU3aX3gi9grtmugQY0u79X7eogUvfXA5sI81Mfq1cn6AgxihfN33STjJA==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.1.0", + "@babel/template": "^7.1.0", + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helpers": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.1.2.tgz", + "integrity": "sha512-Myc3pUE8eswD73aWcartxB16K6CGmHDv9KxOmD2CeOs/FaEAQodr3VYGmlvOmog60vNQ2w8QbatuahepZwrHiA==", + "dev": true, + "requires": { + "@babel/template": "^7.1.2", + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.1.2" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/parser": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.1.2.tgz", + "integrity": "sha512-x5HFsW+E/nQalGMw7hu+fvPqnBeBaIr0lWJ2SG0PPL2j+Pm9lYvCrsZJGIgauPIENx0v10INIyFjmSNUD/gSqQ==", + "dev": true + }, + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.1.0.tgz", + "integrity": "sha512-Fq803F3Jcxo20MXUSDdmZZXrPe6BWyGcWBPPNB/M7WaUYESKDeKMOGIxEzQOjGSmW/NWb6UaPZrtTB2ekhB/ew==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-remap-async-to-generator": "^7.1.0", + "@babel/plugin-syntax-async-generators": "^7.0.0" + } + }, + "@babel/plugin-proposal-json-strings": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.0.0.tgz", + "integrity": "sha512-kfVdUkIAGJIVmHmtS/40i/fg/AGnw/rsZBCaapY5yjeO5RA9m165Xbw9KMOu2nqXP5dTFjEjHdfNdoVcHv133Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-json-strings": "^7.0.0" + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.0.0.tgz", + "integrity": "sha512-14fhfoPcNu7itSen7Py1iGN0gEm87hX/B+8nZPqkdmANyyYWYMY2pjA3r8WXbWVKMzfnSNS0xY8GVS0IjXi/iw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-object-rest-spread": "^7.0.0" + } + }, + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.0.0.tgz", + "integrity": "sha512-JPqAvLG1s13B/AuoBjdBYvn38RqW6n1TzrQO839/sIpqLpbnXKacsAgpZHzLD83Sm8SDXMkkrAvEnJ25+0yIpw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.0.0" + } + }, + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.0.0.tgz", + "integrity": "sha512-tM3icA6GhC3ch2SkmSxv7J/hCWKISzwycub6eGsDrFDgukD4dZ/I+x81XgW0YslS6mzNuQ1Cbzh5osjIMgepPQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.0.0", + "regexpu-core": "^4.2.0" + } + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.0.0.tgz", + "integrity": "sha512-im7ged00ddGKAjcZgewXmp1vxSZQQywuQXe2B1A7kajjZmDeY/ekMPmWr9zJgveSaQH0k7BcGrojQhcK06l0zA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.0.0.tgz", + "integrity": "sha512-UlSfNydC+XLj4bw7ijpldc1uZ/HB84vw+U6BTuqMdIEmz/LDe63w/GHtpQMdXWdqQZFeAI9PjnHe/vDhwirhKA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.0.0.tgz", + "integrity": "sha512-5A0n4p6bIiVe5OvQPxBnesezsgFJdHhSs3uFSvaPdMqtsovajLZ+G2vZyvNe10EzJBWWo3AcHGKhAFUxqwp2dw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.0.0.tgz", + "integrity": "sha512-Wc+HVvwjcq5qBg1w5RG9o9RVzmCaAg/Vp0erHCKpAYV8La6I94o4GQAmFYNmkzoMO6gzoOSulpKeSSz6mPEoZw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.0.0.tgz", + "integrity": "sha512-2EZDBl1WIO/q4DIkIp4s86sdp4ZifL51MoIviLY/gG/mLSuOIEg7J8o6mhbxOTvUJkaN50n+8u41FVsr5KLy/w==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.1.0.tgz", + "integrity": "sha512-rNmcmoQ78IrvNCIt/R9U+cixUHeYAzgusTFgIAv+wQb9HJU4szhpDD6e5GCACmj/JP5KxuCwM96bX3L9v4ZN/g==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-remap-async-to-generator": "^7.1.0" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.0.0.tgz", + "integrity": "sha512-AOBiyUp7vYTqz2Jibe1UaAWL0Hl9JUXEgjFvvvcSc9MVDItv46ViXFw2F7SVt1B5k+KWjl44eeXOAk3UDEaJjQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.0.0.tgz", + "integrity": "sha512-GWEMCrmHQcYWISilUrk9GDqH4enf3UmhOEbNbNrlNAX1ssH3MsS1xLOS6rdjRVPgA7XXVPn87tRkdTEoA/dxEg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "lodash": "^4.17.10" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.1.0.tgz", + "integrity": "sha512-rNaqoD+4OCBZjM7VaskladgqnZ1LO6o2UxuWSDzljzW21pN1KXkB7BstAVweZdxQkHAujps5QMNOTWesBciKFg==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-define-map": "^7.1.0", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-optimise-call-expression": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-replace-supers": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.0.0", + "globals": "^11.1.0" + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.0.0.tgz", + "integrity": "sha512-ubouZdChNAv4AAWAgU7QKbB93NU5sHwInEWfp+/OzJKA02E6Woh9RVoX4sZrbRwtybky/d7baTUqwFx+HgbvMA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.1.2.tgz", + "integrity": "sha512-cvToXvp/OsYxtEn57XJu9BvsGSEYjAh9UeUuXpoi7x6QHB7YdWyQ4lRU/q0Fu1IJNT0o0u4FQ1DMQBzJ8/8vZg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.0.0.tgz", + "integrity": "sha512-00THs8eJxOJUFVx1w8i1MBF4XH4PsAjKjQ1eqN/uCH3YKwP21GCKfrn6YZFZswbOk9+0cw1zGQPHVc1KBlSxig==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.0.0", + "regexpu-core": "^4.1.3" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.0.0.tgz", + "integrity": "sha512-w2vfPkMqRkdxx+C71ATLJG30PpwtTpW7DDdLqYt2acXU7YjztzeWW2Jk1T6hKqCLYCcEA5UQM/+xTAm+QCSnuQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.1.0.tgz", + "integrity": "sha512-uZt9kD1Pp/JubkukOGQml9tqAeI8NkE98oZnHZ2qHRElmeKCodbTZgOEUtujSCSLhHSBWbzNiFSDIMC4/RBTLQ==", + "dev": true, + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.0.0.tgz", + "integrity": "sha512-TlxKecN20X2tt2UEr2LNE6aqA0oPeMT1Y3cgz8k4Dn1j5ObT8M3nl9aA37LLklx0PBZKETC9ZAf9n/6SujTuXA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.1.0.tgz", + "integrity": "sha512-VxOa1TMlFMtqPW2IDYZQaHsFrq/dDoIjgN098NowhexhZcz3UGlvPgZXuE1jEvNygyWyxRacqDpCZt+par1FNg==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.0.0.tgz", + "integrity": "sha512-1NTDBWkeNXgpUcyoVFxbr9hS57EpZYXpje92zv0SUzjdu3enaRwF/l3cmyRnXLtIdyJASyiS6PtybK+CgKf7jA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.1.0.tgz", + "integrity": "sha512-wt8P+xQ85rrnGNr2x1iV3DW32W8zrB6ctuBkYBbf5/ZzJY99Ob4MFgsZDFgczNU76iy9PWsy4EuxOliDjdKw6A==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.1.0.tgz", + "integrity": "sha512-wtNwtMjn1XGwM0AXPspQgvmE6msSJP15CX2RVfpTSTNPLhKhaOjaIfBaVfj4iUZ/VrFSodcFedwtPg/NxwQlPA==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-simple-access": "^7.1.0" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.0.0.tgz", + "integrity": "sha512-8EDKMAsitLkiF/D4Zhe9CHEE2XLh4bfLbb9/Zf3FgXYQOZyZYyg7EAel/aT2A7bHv62jwHf09q2KU/oEexr83g==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.1.0.tgz", + "integrity": "sha512-enrRtn5TfRhMmbRwm7F8qOj0qEYByqUvTttPEGimcBH4CJHphjyK1Vg7sdU7JjeEmgSpM890IT/efS2nMHwYig==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.0.0.tgz", + "integrity": "sha512-yin069FYjah+LbqfGeTfzIBODex/e++Yfa0rH0fpfam9uTbuEeEOx5GLGr210ggOV77mVRNoeqSYqeuaqSzVSw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.1.0.tgz", + "integrity": "sha512-/O02Je1CRTSk2SSJaq0xjwQ8hG4zhZGNjE8psTsSNPXyLRCODv7/PBozqT5AmQMzp7MI3ndvMhGdqp9c96tTEw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-replace-supers": "^7.1.0" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.1.0.tgz", + "integrity": "sha512-vHV7oxkEJ8IHxTfRr3hNGzV446GAb+0hgbA7o/0Jd76s+YzccdWuTU296FOCOl/xweU4t/Ya4g41yWz80RFCRw==", + "dev": true, + "requires": { + "@babel/helper-call-delegate": "^7.1.0", + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.0.0.tgz", + "integrity": "sha512-sj2qzsEx8KDVv1QuJc/dEfilkg3RRPvPYx/VnKLtItVQRWt1Wqf5eVCOLZm29CiGFfYYsA3VPjfizTCV0S0Dlw==", + "dev": true, + "requires": { + "regenerator-transform": "^0.13.3" + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.0.0.tgz", + "integrity": "sha512-g/99LI4vm5iOf5r1Gdxq5Xmu91zvjhEG5+yZDJW268AZELAu4J1EiFLnkSG3yuUsZyOipVOVUKoGPYwfsTymhw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.0.0.tgz", + "integrity": "sha512-L702YFy2EvirrR4shTj0g2xQp7aNwZoWNCkNu2mcoU0uyzMl0XRwDSwzB/xp6DSUFiBmEXuyAyEN16LsgVqGGQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.0.0.tgz", + "integrity": "sha512-LFUToxiyS/WD+XEWpkx/XJBrUXKewSZpzX68s+yEOtIbdnsRjpryDw9U06gYc6klYEij/+KQVRnD3nz3AoKmjw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.0.0" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.0.0.tgz", + "integrity": "sha512-vA6rkTCabRZu7Nbl9DfLZE1imj4tzdWcg5vtdQGvj+OH9itNNB6hxuRMHuIY8SGnEt1T9g5foqs9LnrHzsqEFg==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.0.0.tgz", + "integrity": "sha512-1r1X5DO78WnaAIvs5uC48t41LLckxsYklJrZjNKcevyz83sF2l4RHbw29qrCPr/6ksFsdfRpT/ZgxNWHXRnffg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.0.0.tgz", + "integrity": "sha512-uJBrJhBOEa3D033P95nPHu3nbFwFE9ZgXsfEitzoIXIwqAZWk7uXcg06yFKXz9FSxBH5ucgU/cYdX0IV8ldHKw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.0.0", + "regexpu-core": "^4.1.3" + } + }, + "@babel/preset-env": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.1.0.tgz", + "integrity": "sha512-ZLVSynfAoDHB/34A17/JCZbyrzbQj59QC1Anyueb4Bwjh373nVPq5/HMph0z+tCmcDjXDe+DlKQq9ywQuvWrQg==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-async-generator-functions": "^7.1.0", + "@babel/plugin-proposal-json-strings": "^7.0.0", + "@babel/plugin-proposal-object-rest-spread": "^7.0.0", + "@babel/plugin-proposal-optional-catch-binding": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.0.0", + "@babel/plugin-syntax-async-generators": "^7.0.0", + "@babel/plugin-syntax-object-rest-spread": "^7.0.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.0.0", + "@babel/plugin-transform-arrow-functions": "^7.0.0", + "@babel/plugin-transform-async-to-generator": "^7.1.0", + "@babel/plugin-transform-block-scoped-functions": "^7.0.0", + "@babel/plugin-transform-block-scoping": "^7.0.0", + "@babel/plugin-transform-classes": "^7.1.0", + "@babel/plugin-transform-computed-properties": "^7.0.0", + "@babel/plugin-transform-destructuring": "^7.0.0", + "@babel/plugin-transform-dotall-regex": "^7.0.0", + "@babel/plugin-transform-duplicate-keys": "^7.0.0", + "@babel/plugin-transform-exponentiation-operator": "^7.1.0", + "@babel/plugin-transform-for-of": "^7.0.0", + "@babel/plugin-transform-function-name": "^7.1.0", + "@babel/plugin-transform-literals": "^7.0.0", + "@babel/plugin-transform-modules-amd": "^7.1.0", + "@babel/plugin-transform-modules-commonjs": "^7.1.0", + "@babel/plugin-transform-modules-systemjs": "^7.0.0", + "@babel/plugin-transform-modules-umd": "^7.1.0", + "@babel/plugin-transform-new-target": "^7.0.0", + "@babel/plugin-transform-object-super": "^7.1.0", + "@babel/plugin-transform-parameters": "^7.1.0", + "@babel/plugin-transform-regenerator": "^7.0.0", + "@babel/plugin-transform-shorthand-properties": "^7.0.0", + "@babel/plugin-transform-spread": "^7.0.0", + "@babel/plugin-transform-sticky-regex": "^7.0.0", + "@babel/plugin-transform-template-literals": "^7.0.0", + "@babel/plugin-transform-typeof-symbol": "^7.0.0", + "@babel/plugin-transform-unicode-regex": "^7.0.0", + "browserslist": "^4.1.0", + "invariant": "^2.2.2", + "js-levenshtein": "^1.1.3", + "semver": "^5.3.0" + }, + "dependencies": { + "browserslist": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.2.0.tgz", + "integrity": "sha512-Berls1CHL7qfQz8Lct6QxYA5d2Tvt4doDWHcjvAISybpd+EKZVppNtXgXhaN6SdrPKo7YLTSZuYBs5cYrSWN8w==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30000889", + "electron-to-chromium": "^1.3.73", + "node-releases": "^1.0.0-alpha.12" + } + }, + "semver": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", + "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==", + "dev": true + } + } + }, + "@babel/template": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.1.2.tgz", + "integrity": "sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.1.2", + "@babel/types": "^7.1.2" + } + }, + "@babel/traverse": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.1.0.tgz", + "integrity": "sha512-bwgln0FsMoxm3pLOgrrnGaXk18sSM9JNf1/nHC/FksmNGFbYnPWY4GYCfLxyP1KRmfsxqkRpfoa6xr6VuuSxdw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.0.0", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.0.0", + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0", + "debug": "^3.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.10" + }, + "dependencies": { + "debug": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.5.tgz", + "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.1.2.tgz", + "integrity": "sha512-pb1I05sZEKiSlMUV9UReaqsCPUpgbHHHu2n1piRm7JkuBkm6QxcaIzKu6FMnMtCbih/cEYTR+RGYYC96Yk9HAg==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.10", + "to-fast-properties": "^2.0.0" + } + }, + "@types/angular": { + "version": "1.6.51", + "resolved": "https://registry.npmjs.org/@types/angular/-/angular-1.6.51.tgz", + "integrity": "sha512-wYU+/zlJWih7ZmonWVjGQ18tG7GboI9asMNjRBM5fpIFJWXSioQttCTw9qGL44cP82ghM8sCV9apEqm1zBDq2w==" + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha1-+PLIh60Qv2f2NPAFtph/7TF5qsg=", + "dev": true + }, + "accepts": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.2.13.tgz", + "integrity": "sha1-5fHzkoxtlf2WVYw27D2dDeSm7Oo=", + "dev": true, + "requires": { + "mime-types": "~2.1.6", + "negotiator": "0.5.3" + } + }, + "accord": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/accord/-/accord-0.28.0.tgz", + "integrity": "sha1-vsUWovci59UPX59C+Bt387lUSLo=", + "dev": true, + "requires": { + "convert-source-map": "^1.5.0", + "glob": "^7.0.5", + "indx": "^0.2.3", + "lodash.clone": "^4.3.2", + "lodash.defaults": "^4.0.1", + "lodash.flatten": "^4.2.0", + "lodash.merge": "^4.4.0", + "lodash.partialright": "^4.1.4", + "lodash.pick": "^4.2.1", + "lodash.uniq": "^4.3.0", + "resolve": "^1.5.0", + "semver": "^5.3.0", + "uglify-js": "^2.8.22", + "when": "^3.7.8" + }, + "dependencies": { + "semver": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", + "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==", + "dev": true + } + } + }, + "ace-builds": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.3.3.tgz", + "integrity": "sha512-PbSdoHw42kt5vaXkEVSfUYCd3K1BCfAvyXW9TvR/2ATkk65oImjS1v0evHmzHhOYPSTUO8BprvmpfYT9Vp2akA==" + }, + "acorn": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", + "dev": true + }, + "acorn-jsx": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-4.1.1.tgz", + "integrity": "sha1-6OQeSOov4MiWdAYQq2pP/YrdIl4=", + "dev": true, + "requires": { + "acorn": "^5.0.3" + } + }, + "addressparser": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/addressparser/-/addressparser-1.0.1.tgz", + "integrity": "sha1-R6++GiqSYhkdtoOOT9HTm0CCF0Y=", + "dev": true, + "optional": true + }, + "after": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", + "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", + "dev": true + }, + "agent-base": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", + "integrity": "sha1-2J5ZmfeXh1Z0wH2H8mD8Qeg+jKk=", + "dev": true, + "requires": { + "es6-promisify": "^5.0.0" + } + }, + "ajv": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.4.tgz", + "integrity": "sha512-4Wyjt8+t6YszqaXnLDfMmG/8AlO5Zbcsy3ATHncCzjW/NoPzAId8AK6749Ybjmdt+kUY1gP60fCu46oDxPv/mg==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", + "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", + "dev": true + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "dev": true, + "requires": { + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "alphanum-sort": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", + "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", + "dev": true + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true + }, + "amqplib": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.5.2.tgz", + "integrity": "sha1-0tcxPH/6pNELzx5iUt5FkbbMe2M=", + "dev": true, + "optional": true, + "requires": { + "bitsyntax": "~0.0.4", + "bluebird": "^3.4.6", + "buffer-more-ints": "0.0.2", + "readable-stream": "1.x >=1.1.9", + "safe-buffer": "^5.0.1" + } + }, + "angular": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/angular/-/angular-1.7.5.tgz", + "integrity": "sha512-760183yxtGzni740IBTieNuWLtPNAoMqvmC0Z62UoU0I3nqk+VJuO3JbQAXOyvo3Oy/ZsdNQwrSTh/B0OQZjNw==" + }, + "angular-animate": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/angular-animate/-/angular-animate-1.7.5.tgz", + "integrity": "sha512-kU/fHIGf2a4a3bH7E1tzALTHk+QfoUSCK9fEcMFisd6ZWvNDwPzXWAilItqOC3EDiAXPmGHaNc9/aXiD9xrAxQ==" + }, + "angular-cookies": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/angular-cookies/-/angular-cookies-1.7.5.tgz", + "integrity": "sha512-/8xvvSl/Z9Vwu8ChRm+OQE3vmli8Icwl8uTYkHqD7j7cknJP9kNaf7SgsENlsLVtOqLE/I7TCFYrSx3bmSeNQA==" + }, + "angular-dynamic-locale": { + "version": "0.1.37", + "resolved": "https://registry.npmjs.org/angular-dynamic-locale/-/angular-dynamic-locale-0.1.37.tgz", + "integrity": "sha512-m5Kyk8W8/mOZSqRxuByOwHBjv8labLBAgvl0Z3iQx2xT/tWCqb94imKUPwumudszdPDjxeopwyucQvm8Sw7ogw==", + "requires": { + "@types/angular": "^1.6.25" + } + }, + "angular-i18n": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/angular-i18n/-/angular-i18n-1.7.5.tgz", + "integrity": "sha512-52+Jpt8HRJV2bqSbSU6fWkwOvGzj/DxbNpKXxnTuCS9heuJrlm77BS/lhrF4BA8+Uudnh7npr5/yRELobP+8Yw==" + }, + "angular-local-storage": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/angular-local-storage/-/angular-local-storage-0.7.1.tgz", + "integrity": "sha1-+9JzB2PCn6mvVyXgGGx4BiHozdI=" + }, + "angular-messages": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/angular-messages/-/angular-messages-1.7.5.tgz", + "integrity": "sha512-YDpJpFLyrIgZjE/sIAjgww1y6r3QqXBJbNDI0QjftD37vHXLkwvAOo3A4bxPw8BikyGLcJrFrgf6hRAzntJIWA==" + }, + "angular-mocks": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/angular-mocks/-/angular-mocks-1.7.5.tgz", + "integrity": "sha512-I+Ue2Bkx6R9W5178DYrNvzjIdGh4wKKoCWsgz8dc7ysH4mA70Q3M9v5xRF0RUu7r+2CZj+nDeUecvh2paxcYvg==" + }, + "angular-route": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/angular-route/-/angular-route-1.7.5.tgz", + "integrity": "sha512-7KfyEVVOWTI+jTY/j5rUNCIHGRyeCOx7YqZI/Ci3IbDK7GIsy6xH+hS5ai0Xi0sLjzDZ0PUDO4gBn+K0dVtlOg==" + }, + "angular-sanitize": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/angular-sanitize/-/angular-sanitize-1.7.5.tgz", + "integrity": "sha512-wjKCJOIwrkEvfD0keTnKGi6We13gtoCAQIHcdoqyoo3gwvcgNfYymVQIS3+iCGVcjfWz0jHuS3KgB4ysRWsTTA==" + }, + "angular-touch": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/angular-touch/-/angular-touch-1.7.5.tgz", + "integrity": "sha512-XNAZNG0RA1mtdwBJheViCF1H/7wOygp4MLIfs5y1K+rne6AeaYKZcV6EJs9fvgfLKLO6ecm1+3J8hoCkdhhxQw==" + }, + "angular-ui-sortable": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/angular-ui-sortable/-/angular-ui-sortable-0.15.0.tgz", + "integrity": "sha1-8kLlH4Uic34+9ndUC3J4dyxQzCA=" + }, + "animejs": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/animejs/-/animejs-2.2.0.tgz", + "integrity": "sha1-Ne79/FNbgZScnLBvCz5gwC5v3IA=" + }, + "ansi-colors": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "dev": true, + "requires": { + "ansi-wrap": "^0.1.0" + } + }, + "ansi-cyan": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-cyan/-/ansi-cyan-0.1.1.tgz", + "integrity": "sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-escapes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", + "integrity": "sha1-9zIHu4EgfXX9bIPxJa8m7qN4yjA=", + "dev": true + }, + "ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-red": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz", + "integrity": "sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", + "dev": true + }, + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha1-VT3Lj5HjyImEXf26NMd3IbkLnXo=", + "dev": true, + "requires": { + "micromatch": "^2.1.5", + "normalize-path": "^2.0.0" + }, + "dependencies": { + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1" + } + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" + } + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "^0.1.0" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" + } + } + } + }, + "archive-type": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/archive-type/-/archive-type-3.2.0.tgz", + "integrity": "sha1-nNnABpV+vpX62tW9YJiUKoE3N/Y=", + "dev": true, + "requires": { + "file-type": "^3.1.0" + }, + "dependencies": { + "file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=", + "dev": true + } + } + }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha1-vNZ5HqWuCXJeF+WtmIE0zUCz2RE=", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", + "dev": true + }, + "array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", + "dev": true + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "dev": true + }, + "array-slice": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha1-42jqFfibxwaff/uJrsOmx9SsItQ=", + "dev": true + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "arraybuffer.slice": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", + "integrity": "sha1-O7xCdd1YTMGxCAm4nU6LY6aednU=", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", + "dev": true, + "optional": true + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "ast-types": { + "version": "0.11.5", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.11.5.tgz", + "integrity": "sha1-mJCCXWYMA8KDOfMV6foKNg4x7Cg=", + "dev": true, + "optional": true + }, + "async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "dev": true, + "requires": { + "lodash": "^4.17.10" + } + }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "dev": true + }, + "async-each-series": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/async-each-series/-/async-each-series-1.1.0.tgz", + "integrity": "sha1-9C/YFV048hpbjqB8KOBj7RcAsTg=", + "dev": true, + "optional": true + }, + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha1-ePrtjD0HSrgfIrTphdeehzj3IPg=", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "autoprefixer": { + "version": "6.7.7", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-6.7.7.tgz", + "integrity": "sha1-Hb0cg1ZY41zj+ZhAmdsAWFx4IBQ=", + "dev": true, + "requires": { + "browserslist": "^1.7.6", + "caniuse-db": "^1.0.30000634", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "postcss": "^5.2.16", + "postcss-value-parser": "^3.2.3" + } + }, + "aws-sign2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", + "dev": true + }, + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", + "dev": true + }, + "axios": { + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.15.3.tgz", + "integrity": "sha1-LJ1jiy4ZGgjqHWzJiOrda6W9wFM=", + "dev": true, + "optional": true, + "requires": { + "follow-redirects": "1.0.0" + }, + "dependencies": { + "follow-redirects": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.0.0.tgz", + "integrity": "sha1-jjQpjL0uF28lTv/sdaHHjMhJ/Tc=", + "dev": true, + "optional": true, + "requires": { + "debug": "^2.2.0" + } + } + } + }, + "backo2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha1-e95c7RRbbVUakNuH+DxVi060io8=", + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "base64-arraybuffer": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", + "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", + "dev": true + }, + "base64-url": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/base64-url/-/base64-url-1.2.1.tgz", + "integrity": "sha1-GZ/WYXAqDnt9yubgaYuwicUvbXg=", + "dev": true + }, + "base64id": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", + "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=", + "dev": true + }, + "basic-auth": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.4.tgz", + "integrity": "sha1-Awk1sB3nyblKgksp8/zLdQ06UpA=", + "dev": true + }, + "basic-auth-connect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz", + "integrity": "sha1-/bC0OWLKe0BFanwrtI/hc9otISI=", + "dev": true + }, + "batch": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.5.3.tgz", + "integrity": "sha1-PzQU84AyF0O/wQQvmoP/HVgk1GQ=", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "beeper": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", + "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", + "dev": true + }, + "better-assert": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", + "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", + "dev": true, + "requires": { + "callsite": "1.0.0" + } + }, + "bin-build": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/bin-build/-/bin-build-2.2.0.tgz", + "integrity": "sha1-EfjdYfcP/Por3KpbRvXo/t1CIcw=", + "dev": true, + "optional": true, + "requires": { + "archive-type": "^3.0.1", + "decompress": "^3.0.0", + "download": "^4.1.2", + "exec-series": "^1.0.0", + "rimraf": "^2.2.6", + "tempfile": "^1.0.0", + "url-regex": "^3.0.0" + }, + "dependencies": { + "tempfile": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tempfile/-/tempfile-1.1.1.tgz", + "integrity": "sha1-W8xOrsxKsscH2LwR2ZzMmiyyh/I=", + "dev": true, + "optional": true, + "requires": { + "os-tmpdir": "^1.0.0", + "uuid": "^2.0.1" + } + }, + "uuid": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", + "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=", + "dev": true, + "optional": true + } + } + }, + "bin-check": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/bin-check/-/bin-check-2.0.0.tgz", + "integrity": "sha1-hvjm9CU4k99g3DFpV/WvAqywWTA=", + "dev": true, + "optional": true, + "requires": { + "executable": "^1.0.0" + } + }, + "bin-version": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/bin-version/-/bin-version-1.0.4.tgz", + "integrity": "sha1-nrSY7m/Xb3q5p8FgQ2+JV5Q1144=", + "dev": true, + "optional": true, + "requires": { + "find-versions": "^1.0.0" + } + }, + "bin-version-check": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bin-version-check/-/bin-version-check-2.1.0.tgz", + "integrity": "sha1-5OXfKQuQaffRETJAMe/BP90RpbA=", + "dev": true, + "optional": true, + "requires": { + "bin-version": "^1.0.0", + "minimist": "^1.1.0", + "semver": "^4.0.3", + "semver-truncate": "^1.0.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true, + "optional": true + } + } + }, + "bin-wrapper": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/bin-wrapper/-/bin-wrapper-3.0.2.tgz", + "integrity": "sha1-Z9MwYmLksaXy+I7iNGT2plVneus=", + "dev": true, + "optional": true, + "requires": { + "bin-check": "^2.0.0", + "bin-version-check": "^2.1.0", + "download": "^4.0.0", + "each-async": "^1.1.1", + "lazy-req": "^1.0.0", + "os-filter-obj": "^1.0.0" + } + }, + "binary-extensions": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.12.0.tgz", + "integrity": "sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg==", + "dev": true + }, + "bitsyntax": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/bitsyntax/-/bitsyntax-0.0.4.tgz", + "integrity": "sha1-6xDMb4K4xJDj6FaY8H6D1G4MuoI=", + "dev": true, + "optional": true, + "requires": { + "buffer-more-ints": "0.0.2" + } + }, + "bl": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", + "integrity": "sha1-oWCRFxcQPAdBDO9j71Gzl8Alr5w=", + "dev": true, + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "blob": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz", + "integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE=", + "dev": true + }, + "bluebird": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.2.tgz", + "integrity": "sha512-dhHTWMI7kMx5whMQntl7Vr9C6BvV10lFXDAasnqnrMYhXVCzzk6IO9Fo2L75jXHT07WrOngL1WDXOp+yYS91Yg==", + "dev": true + }, + "body-parser": { + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.13.3.tgz", + "integrity": "sha1-wIzzMMM1jhUQFqBXRvE/ApyX+pc=", + "dev": true, + "requires": { + "bytes": "2.1.0", + "content-type": "~1.0.1", + "debug": "~2.2.0", + "depd": "~1.0.1", + "http-errors": "~1.3.1", + "iconv-lite": "0.4.11", + "on-finished": "~2.3.0", + "qs": "4.0.0", + "raw-body": "~2.1.2", + "type-is": "~1.6.6" + }, + "dependencies": { + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + } + } + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true + }, + "boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "dev": true, + "requires": { + "hoek": "2.x.x" + } + }, + "bootstrap": { + "version": "3.3.7", + "resolved": "http://registry.npmjs.org/bootstrap/-/bootstrap-3.3.7.tgz", + "integrity": "sha1-WjiTlFSfIzMIdaOxUGVldPip63E=" + }, + "bootstrap-social": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/bootstrap-social/-/bootstrap-social-4.8.0.tgz", + "integrity": "sha1-ZtRj3JZtbbQH37mTNR1YxTSqLHo=", + "requires": { + "bootstrap": "~3", + "font-awesome": "~4.3" + }, + "dependencies": { + "font-awesome": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.3.0.tgz", + "integrity": "sha1-RO63kM35hmQnhvM/znhHZPGEHEA=" + } + } + }, + "bower": { + "version": "1.8.4", + "resolved": "https://registry.npmjs.org/bower/-/bower-1.8.4.tgz", + "integrity": "sha1-54dqB23rgTf30GUl3F6MZtuC8oo=", + "dev": true + }, + "bower-installer": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/bower-installer/-/bower-installer-1.3.6.tgz", + "integrity": "sha1-z3g5tlQh0rJwqyLHT8hYpV46E3A=", + "dev": true, + "requires": { + "async": "^2.1.4", + "bower": "^1.8.0", + "colors": "^1.1.2", + "glob": "^7.1.1", + "lodash": "^4.17.2", + "mkdirp": "^0.5.1", + "node-fs": "~0.1.7", + "nopt": "^3.0.6" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha1-WXn9PxTNUxVl5fot8av/8d+u5yk=", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "browserslist": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", + "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", + "dev": true, + "requires": { + "caniuse-db": "^1.0.30000639", + "electron-to-chromium": "^1.2.7" + } + }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha1-iQ3ZDZI6hz4I4Q5f1RpX5bfM4Ow=", + "dev": true, + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha1-vX3CauKXLQ7aJTvgYdupkjScGfA=", + "dev": true + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "dev": true + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", + "dev": true + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "buffer-more-ints": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-0.0.2.tgz", + "integrity": "sha1-JrOIXRD6E9t/wBquOquHAZngEkw=", + "dev": true + }, + "buffer-to-vinyl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-to-vinyl/-/buffer-to-vinyl-1.1.0.tgz", + "integrity": "sha1-APFfruOreh3aLN5tkSG//dB7ImI=", + "dev": true, + "requires": { + "file-type": "^3.1.0", + "readable-stream": "^2.0.2", + "uuid": "^2.0.1", + "vinyl": "^1.0.0" + }, + "dependencies": { + "file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha1-sRwn2IuP8fvgcGQ8+UsMea4bCq8=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "uuid": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", + "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=", + "dev": true + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + } + } + } + }, + "bufferstreams": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bufferstreams/-/bufferstreams-1.0.1.tgz", + "integrity": "sha1-z7GtlWjTujz+k1upq92VLeiKqyo=", + "dev": true, + "requires": { + "readable-stream": "^1.0.33" + } + }, + "buildmail": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/buildmail/-/buildmail-4.0.1.tgz", + "integrity": "sha1-h393OLeHKYccmhBeO4N9K+EaenI=", + "dev": true, + "optional": true, + "requires": { + "addressparser": "1.0.1", + "libbase64": "0.1.0", + "libmime": "3.0.0", + "libqp": "1.1.0", + "nodemailer-fetch": "1.6.0", + "nodemailer-shared": "1.1.0", + "punycode": "1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true, + "optional": true + } + } + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "bytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz", + "integrity": "sha1-rJPEEOL/ycx89LRks4KJBn9eR7Q=", + "dev": true + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha1-Cn9GQWgxyLZi7jb+TnxZ129marI=", + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "dev": true, + "requires": { + "callsites": "^0.2.0" + } + }, + "callsite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", + "dev": true + }, + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true + }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "dev": true, + "requires": { + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" + } + }, + "caniuse-api": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.6.1.tgz", + "integrity": "sha1-tTTnxzTE+B7F++isoq0kNUuWLGw=", + "dev": true, + "requires": { + "browserslist": "^1.3.6", + "caniuse-db": "^1.0.30000529", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "caniuse-db": { + "version": "1.0.30000889", + "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000889.tgz", + "integrity": "sha512-Rf9Sbm2KS7s6Rk8iNeI5zJdquqctXBXAfy/bb1tCCYRds5RAaHNdyt2D4z8TSRToDkYsAwiSBV/bFHR+4IgTiw==", + "dev": true + }, + "caniuse-lite": { + "version": "1.0.30000889", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000889.tgz", + "integrity": "sha512-MFxcQ6x/LEEoaIhO7Zdb7Eg8YyNONN+WBnS5ERJ0li2yRw51+i4xXUNxnLaveTb/4ZoJqsWKEmlomhG2pYzlQA==", + "dev": true + }, + "canonical-path": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/canonical-path/-/canonical-path-0.0.2.tgz", + "integrity": "sha1-4x65N6jJPuKgHfGDl5RyGQKHRXQ=", + "dev": true + }, + "capture-stack-trace": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz", + "integrity": "sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw==", + "dev": true + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "caw": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/caw/-/caw-1.2.0.tgz", + "integrity": "sha1-/7Im/n78VHKI3GLuPpcHPCEtEDQ=", + "dev": true, + "requires": { + "get-proxy": "^1.0.1", + "is-obj": "^1.0.0", + "object-assign": "^3.0.0", + "tunnel-agent": "^0.4.0" + }, + "dependencies": { + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "dev": true + } + } + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "dev": true, + "requires": { + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "dev": true, + "requires": { + "anymatch": "^1.3.0", + "async-each": "^1.0.0", + "fsevents": "^1.0.0", + "glob-parent": "^2.0.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^2.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0" + }, + "dependencies": { + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "^2.0.0" + } + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + } + } + }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", + "dev": true + }, + "clap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/clap/-/clap-1.2.3.tgz", + "integrity": "sha1-TzZ0WzIAhJJVf0ZBLWbVDLmbzlE=", + "dev": true, + "requires": { + "chalk": "^1.1.3" + } + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha1-+TNprouafOAv1B+q0MqDAzGQxGM=", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "clean-css": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz", + "integrity": "sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==", + "dev": true, + "requires": { + "source-map": "~0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "dev": true + }, + "clipboard": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.0.tgz", + "integrity": "sha512-gXzHBlzEVqCk2b8Wpkil89S0WSMAX7eZho2zANX+EEEa9LMutGe9ICU+wHRzsH7cCHaCbUzj900P+AXOM0FE3A==", + "requires": { + "good-listener": "^1.2.2", + "select": "^1.1.2", + "tiny-emitter": "^2.0.0" + } + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true, + "requires": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true + } + } + }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true + }, + "clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", + "dev": true + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "dev": true + }, + "cloneable-readable": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.2.tgz", + "integrity": "sha1-1ZHe5Kj4vBXaQ86X3O66E9Q+KmU=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha1-sRwn2IuP8fvgcGQ8+UsMea4bCq8=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "co": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/co/-/co-3.1.0.tgz", + "integrity": "sha1-TqVOpaCJOBUxheFSEMaNkJK8G3g=", + "dev": true + }, + "coa": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/coa/-/coa-1.0.4.tgz", + "integrity": "sha1-qe8VNmDWqGqL3sAomlxoTSF0Mv0=", + "dev": true, + "requires": { + "q": "^1.1.2" + } + }, + "codemirror": { + "version": "5.3.0", + "resolved": "http://registry.npmjs.org/codemirror/-/codemirror-5.3.0.tgz", + "integrity": "sha1-JDyyaN1hynjdsn6C8uws74j7lGE=" + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/color/-/color-0.11.4.tgz", + "integrity": "sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q=", + "dev": true, + "requires": { + "clone": "^1.0.2", + "color-convert": "^1.3.0", + "color-string": "^0.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "color-string": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-0.3.0.tgz", + "integrity": "sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE=", + "dev": true, + "requires": { + "color-name": "^1.0.0" + } + }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha1-k4NDeaHMmgxh+C9S8NBDIiUb1aI=", + "dev": true + }, + "colormin": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colormin/-/colormin-1.1.2.tgz", + "integrity": "sha1-6i90IKcrlogaOKrlnsEkpvcpgTM=", + "dev": true, + "requires": { + "color": "^0.11.0", + "css-color-names": "0.0.4", + "has": "^1.0.1" + } + }, + "colors": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.2.tgz", + "integrity": "sha512-rhP0JSBGYvpcNQj4s5AdShMeE5ahMop96cTeDl/v9qQQm2fYClE2QXZRi8wLzc+GmXSxdIqqbOIAhyObEXDbfQ==", + "dev": true + }, + "combine-lists": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/combine-lists/-/combine-lists-1.0.1.tgz", + "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=", + "dev": true, + "requires": { + "lodash": "^4.5.0" + } + }, + "combined-stream": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", + "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", + "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", + "dev": true, + "requires": { + "graceful-readlink": ">= 1.0.0" + } + }, + "component-bind": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", + "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=", + "dev": true + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, + "component-inherit": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", + "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=", + "dev": true + }, + "compressible": { + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.15.tgz", + "integrity": "sha512-4aE67DL33dSW9gw4CI2H/yTxqHLNcxp0yS6jB+4h+wr3e43+1z7vm0HU9qXOH8j+qjKuL8+UtkOxYQSMq60Ylw==", + "dev": true, + "requires": { + "mime-db": ">= 1.36.0 < 2" + } + }, + "compression": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.5.2.tgz", + "integrity": "sha1-sDuNhub4rSloPLqN+R3cb/x3s5U=", + "dev": true, + "requires": { + "accepts": "~1.2.12", + "bytes": "2.1.0", + "compressible": "~2.0.5", + "debug": "~2.2.0", + "on-headers": "~1.0.0", + "vary": "~1.0.1" + }, + "dependencies": { + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + } + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "concat-with-sourcemaps": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz", + "integrity": "sha1-1OqT8FriV5CVG5nns7CeOQikCC4=", + "dev": true, + "requires": { + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true + } + } + }, + "connect": { + "version": "2.30.2", + "resolved": "https://registry.npmjs.org/connect/-/connect-2.30.2.tgz", + "integrity": "sha1-jam8vooFTT0xjXTf7JA7XDmhtgk=", + "dev": true, + "requires": { + "basic-auth-connect": "1.0.0", + "body-parser": "~1.13.3", + "bytes": "2.1.0", + "compression": "~1.5.2", + "connect-timeout": "~1.6.2", + "content-type": "~1.0.1", + "cookie": "0.1.3", + "cookie-parser": "~1.3.5", + "cookie-signature": "1.0.6", + "csurf": "~1.8.3", + "debug": "~2.2.0", + "depd": "~1.0.1", + "errorhandler": "~1.4.2", + "express-session": "~1.11.3", + "finalhandler": "0.4.0", + "fresh": "0.3.0", + "http-errors": "~1.3.1", + "method-override": "~2.3.5", + "morgan": "~1.6.1", + "multiparty": "3.3.2", + "on-headers": "~1.0.0", + "parseurl": "~1.3.0", + "pause": "0.1.0", + "qs": "4.0.0", + "response-time": "~2.3.1", + "serve-favicon": "~2.3.0", + "serve-index": "~1.7.2", + "serve-static": "~1.10.0", + "type-is": "~1.6.6", + "utils-merge": "1.0.0", + "vhost": "~3.0.1" + }, + "dependencies": { + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + } + } + }, + "connect-livereload": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/connect-livereload/-/connect-livereload-0.5.4.tgz", + "integrity": "sha1-gBV9E3HJ83zBQDmrGJWXDRGdw7w=", + "dev": true + }, + "connect-timeout": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/connect-timeout/-/connect-timeout-1.6.2.tgz", + "integrity": "sha1-3ppexh4zoStu2qt7XwYumMWZuI4=", + "dev": true, + "requires": { + "debug": "~2.2.0", + "http-errors": "~1.3.1", + "ms": "0.7.1", + "on-headers": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + } + } + }, + "console-stream": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/console-stream/-/console-stream-0.1.1.tgz", + "integrity": "sha1-oJX+B7IEZZVfL6/Si11yvM2UnUQ=", + "dev": true, + "optional": true + }, + "consolidate": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.14.5.tgz", + "integrity": "sha1-WiUEe8dvcwcmZ8jLUsmJiI9JTGM=", + "dev": true, + "requires": { + "bluebird": "^3.1.1" + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js=", + "dev": true + }, + "convert-source-map": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", + "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "cookie": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.3.tgz", + "integrity": "sha1-5zSlwUF/zkctWu+Cw4HKu2TRpDU=", + "dev": true + }, + "cookie-parser": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.3.5.tgz", + "integrity": "sha1-nXVVcPtdF4kHcSJ6AjFNm+fPg1Y=", + "dev": true, + "requires": { + "cookie": "0.1.3", + "cookie-signature": "1.0.6" + } + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "core-js": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", + "integrity": "sha1-+XJgj/DOrWi4QaFqky0LGDeRgU4=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cosmiconfig": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-2.2.2.tgz", + "integrity": "sha1-YXPOvVb6wELB9DkO33r2wHx8uJI=", + "dev": true, + "requires": { + "is-directory": "^0.3.1", + "js-yaml": "^3.4.3", + "minimist": "^1.2.0", + "object-assign": "^4.1.0", + "os-homedir": "^1.0.1", + "parse-json": "^2.2.0", + "require-from-string": "^1.1.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "crc": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.3.0.tgz", + "integrity": "sha1-+mIuG8OIvyVzCQgta2UgDOZwkLo=", + "dev": true + }, + "create-error-class": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", + "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", + "dev": true, + "requires": { + "capture-stack-trace": "^1.0.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "dependencies": { + "semver": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", + "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==", + "dev": true + } + } + }, + "cryptiles": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "dev": true, + "requires": { + "boom": "2.x.x" + } + }, + "csrf": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/csrf/-/csrf-3.0.6.tgz", + "integrity": "sha1-thEg3c7q/JHnbtUxO7XAsmZ7cQo=", + "dev": true, + "requires": { + "rndm": "1.2.0", + "tsscmp": "1.0.5", + "uid-safe": "2.1.4" + } + }, + "css-color-names": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", + "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=", + "dev": true + }, + "css-select": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.0.0.tgz", + "integrity": "sha512-MGhoq1S9EyPgZIGnts8Yz5WwUOyHmPMdlqeifsYs/xFX7AAm3hY0RJe1dqVlXtYPI66Nsk39R/sa5/ree6L2qg==", + "dev": true, + "optional": true, + "requires": { + "boolbase": "^1.0.0", + "css-what": "2.1", + "domutils": "^1.7.0", + "nth-check": "^1.0.1" + } + }, + "css-select-base-adapter": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.0.tgz", + "integrity": "sha1-AQKz0UYw34bD65+p9UVicBBs+ZA=", + "dev": true, + "optional": true + }, + "css-tree": { + "version": "1.0.0-alpha.28", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.28.tgz", + "integrity": "sha512-joNNW1gCp3qFFzj4St6zk+Wh/NBv0vM5YbEreZk0SD4S23S+1xBKb6cLDg2uj4P4k/GUMlIm6cKIDqIG+vdt0w==", + "dev": true, + "optional": true, + "requires": { + "mdn-data": "~1.1.0", + "source-map": "^0.5.3" + } + }, + "css-url-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/css-url-regex/-/css-url-regex-1.1.0.tgz", + "integrity": "sha1-g4NCMMyfdMRX3lnuvRVD/uuDt+w=", + "dev": true, + "optional": true + }, + "css-what": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.0.tgz", + "integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0=", + "dev": true, + "optional": true + }, + "cssnano": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-3.10.0.tgz", + "integrity": "sha1-Tzj2zqK5sX+gFJDyPx3GjqZcHDg=", + "dev": true, + "requires": { + "autoprefixer": "^6.3.1", + "decamelize": "^1.1.2", + "defined": "^1.0.0", + "has": "^1.0.1", + "object-assign": "^4.0.1", + "postcss": "^5.0.14", + "postcss-calc": "^5.2.0", + "postcss-colormin": "^2.1.8", + "postcss-convert-values": "^2.3.4", + "postcss-discard-comments": "^2.0.4", + "postcss-discard-duplicates": "^2.0.1", + "postcss-discard-empty": "^2.0.1", + "postcss-discard-overridden": "^0.1.1", + "postcss-discard-unused": "^2.2.1", + "postcss-filter-plugins": "^2.0.0", + "postcss-merge-idents": "^2.1.5", + "postcss-merge-longhand": "^2.0.1", + "postcss-merge-rules": "^2.0.3", + "postcss-minify-font-values": "^1.0.2", + "postcss-minify-gradients": "^1.0.1", + "postcss-minify-params": "^1.0.4", + "postcss-minify-selectors": "^2.0.4", + "postcss-normalize-charset": "^1.1.0", + "postcss-normalize-url": "^3.0.7", + "postcss-ordered-values": "^2.1.0", + "postcss-reduce-idents": "^2.2.2", + "postcss-reduce-initial": "^1.0.0", + "postcss-reduce-transforms": "^1.0.3", + "postcss-svgo": "^2.1.1", + "postcss-unique-selectors": "^2.0.2", + "postcss-value-parser": "^3.2.3", + "postcss-zindex": "^2.0.1" + } + }, + "csso": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/csso/-/csso-2.3.2.tgz", + "integrity": "sha1-3dUsWHAz9J6Utx/FVWnyUuj/X4U=", + "dev": true, + "requires": { + "clap": "^1.0.9", + "source-map": "^0.5.3" + } + }, + "csurf": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/csurf/-/csurf-1.8.3.tgz", + "integrity": "sha1-I/KhO/HY/OHQyZZYg5RELLqGpWo=", + "dev": true, + "requires": { + "cookie": "0.1.3", + "cookie-signature": "1.0.6", + "csrf": "~3.0.0", + "http-errors": "~1.3.1" + } + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "dev": true, + "requires": { + "array-find-index": "^1.0.1" + } + }, + "custom-event": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", + "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", + "dev": true + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "data-uri-to-buffer": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz", + "integrity": "sha1-dxY+qcINhkG0cH6PGKvfmnjzSDU=", + "dev": true, + "optional": true + }, + "date-format": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz", + "integrity": "sha1-YV6CjiM90aubua4JUODOzPpuytg=", + "dev": true + }, + "dateformat": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", + "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "decompress": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/decompress/-/decompress-3.0.0.tgz", + "integrity": "sha1-rx3VDQbjv8QyRh033hGzjA2ZG+0=", + "dev": true, + "requires": { + "buffer-to-vinyl": "^1.0.0", + "concat-stream": "^1.4.6", + "decompress-tar": "^3.0.0", + "decompress-tarbz2": "^3.0.0", + "decompress-targz": "^3.0.0", + "decompress-unzip": "^3.0.0", + "stream-combiner2": "^1.1.1", + "vinyl-assign": "^1.0.1", + "vinyl-fs": "^2.2.0" + }, + "dependencies": { + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1" + } + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" + } + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "^0.1.0" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-stream": { + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz", + "integrity": "sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=", + "dev": true, + "requires": { + "extend": "^3.0.0", + "glob": "^5.0.3", + "glob-parent": "^3.0.0", + "micromatch": "^2.3.7", + "ordered-read-streams": "^0.3.0", + "through2": "^0.6.0", + "to-absolute-glob": "^0.1.1", + "unique-stream": "^2.0.2" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + } + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" + } + }, + "ordered-read-streams": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", + "integrity": "sha1-cTfmmzKYuzQiR6G77jiByA4v14s=", + "dev": true, + "requires": { + "is-stream": "^1.0.1", + "readable-stream": "^2.0.1" + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + }, + "unique-stream": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", + "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", + "dev": true, + "requires": { + "json-stable-stringify": "^1.0.0", + "through2-filter": "^2.0.0" + } + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + } + }, + "vinyl-fs": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz", + "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=", + "dev": true, + "requires": { + "duplexify": "^3.2.0", + "glob-stream": "^5.3.2", + "graceful-fs": "^4.0.0", + "gulp-sourcemaps": "1.6.0", + "is-valid-glob": "^0.3.0", + "lazystream": "^1.0.0", + "lodash.isequal": "^4.0.0", + "merge-stream": "^1.0.0", + "mkdirp": "^0.5.0", + "object-assign": "^4.0.0", + "readable-stream": "^2.0.4", + "strip-bom": "^2.0.0", + "strip-bom-stream": "^1.0.0", + "through2": "^2.0.0", + "through2-filter": "^2.0.0", + "vali-date": "^1.0.0", + "vinyl": "^1.0.0" + } + } + } + }, + "decompress-tar": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-3.1.0.tgz", + "integrity": "sha1-IXx4n5uURQ76rcXF5TeXj8MzxGY=", + "dev": true, + "requires": { + "is-tar": "^1.0.0", + "object-assign": "^2.0.0", + "strip-dirs": "^1.0.0", + "tar-stream": "^1.1.1", + "through2": "^0.6.1", + "vinyl": "^0.4.3" + }, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "object-assign": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz", + "integrity": "sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "^0.2.0", + "clone-stats": "^0.0.1" + } + } + } + }, + "decompress-tarbz2": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-3.1.0.tgz", + "integrity": "sha1-iyOTVoE1X58YnYclag+L3ZbZZm0=", + "dev": true, + "requires": { + "is-bzip2": "^1.0.0", + "object-assign": "^2.0.0", + "seek-bzip": "^1.0.3", + "strip-dirs": "^1.0.0", + "tar-stream": "^1.1.1", + "through2": "^0.6.1", + "vinyl": "^0.4.3" + }, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "object-assign": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz", + "integrity": "sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "^0.2.0", + "clone-stats": "^0.0.1" + } + } + } + }, + "decompress-targz": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-3.1.0.tgz", + "integrity": "sha1-ssE9+YFmJomRtxXWRH9kLpaW9aA=", + "dev": true, + "requires": { + "is-gzip": "^1.0.0", + "object-assign": "^2.0.0", + "strip-dirs": "^1.0.0", + "tar-stream": "^1.1.1", + "through2": "^0.6.1", + "vinyl": "^0.4.3" + }, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "object-assign": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz", + "integrity": "sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "^0.2.0", + "clone-stats": "^0.0.1" + } + } + } + }, + "decompress-unzip": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-3.4.0.tgz", + "integrity": "sha1-YUdbQVIGa74/7hL51inRX+ZHjus=", + "dev": true, + "requires": { + "is-zip": "^1.0.0", + "read-all-stream": "^3.0.0", + "stat-mode": "^0.2.0", + "strip-dirs": "^1.0.0", + "through2": "^2.0.0", + "vinyl": "^1.0.0", + "yauzl": "^2.2.1" + }, + "dependencies": { + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + } + } + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha1-xPp8lUBKF6nD6Mp+FTcxK3NjMKw=", + "dev": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dev": true, + "requires": { + "clone": "^1.0.2" + } + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha1-1Flono1lS6d+AqgX+HENcCyxbp0=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "degenerator": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-1.0.4.tgz", + "integrity": "sha1-/PSQo37OJmRk2cxDGrmMWBnO0JU=", + "dev": true, + "optional": true, + "requires": { + "ast-types": "0.x.x", + "escodegen": "1.x.x", + "esprima": "3.x.x" + }, + "dependencies": { + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "dev": true, + "optional": true + } + } + }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true, + "requires": { + "globby": "^5.0.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "rimraf": "^2.2.8" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "delegate": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", + "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==" + }, + "depd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.0.1.tgz", + "integrity": "sha1-gK7GTJ1tl+ZcwqnKqTwKpqv3Oqo=", + "dev": true + }, + "deprecated": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", + "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=", + "dev": true + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "dev": true + }, + "di": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", + "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", + "dev": true + }, + "diff": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.4.0.tgz", + "integrity": "sha512-QpVuMTEoJMF7cKzi6bvWhRulU1fZqZnvyVQgNhPaxxuTYwyjn/j1v9falseQ/uXWwPnO56RBfwtg4h/EQXmucA==" + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha1-XNAfwQFiG0LEzX9dGmYkNxbT850=", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "dom-serialize": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", + "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", + "dev": true, + "requires": { + "custom-event": "~1.0.0", + "ent": "~2.2.0", + "extend": "^3.0.0", + "void-elements": "^2.0.0" + } + }, + "dom-serializer": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", + "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", + "dev": true, + "optional": true, + "requires": { + "domelementtype": "~1.1.1", + "entities": "~1.1.1" + }, + "dependencies": { + "domelementtype": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", + "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", + "dev": true, + "optional": true + } + } + }, + "domelementtype": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", + "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=", + "dev": true, + "optional": true + }, + "domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "dev": true, + "optional": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "double-ended-queue": { + "version": "2.1.0-0", + "resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz", + "integrity": "sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw=", + "dev": true, + "optional": true + }, + "download": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/download/-/download-4.4.3.tgz", + "integrity": "sha1-qlX9rTktldS2jowr4D4MKqIbqaw=", + "dev": true, + "requires": { + "caw": "^1.0.1", + "concat-stream": "^1.4.7", + "each-async": "^1.0.0", + "filenamify": "^1.0.1", + "got": "^5.0.0", + "gulp-decompress": "^1.2.0", + "gulp-rename": "^1.2.0", + "is-url": "^1.2.0", + "object-assign": "^4.0.1", + "read-all-stream": "^3.0.0", + "readable-stream": "^2.0.2", + "stream-combiner2": "^1.1.1", + "vinyl": "^1.0.0", + "vinyl-fs": "^2.2.0", + "ware": "^1.2.0" + }, + "dependencies": { + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1" + } + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" + } + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "^0.1.0" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-stream": { + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz", + "integrity": "sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=", + "dev": true, + "requires": { + "extend": "^3.0.0", + "glob": "^5.0.3", + "glob-parent": "^3.0.0", + "micromatch": "^2.3.7", + "ordered-read-streams": "^0.3.0", + "through2": "^0.6.0", + "to-absolute-glob": "^0.1.1", + "unique-stream": "^2.0.2" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + } + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" + } + }, + "ordered-read-streams": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", + "integrity": "sha1-cTfmmzKYuzQiR6G77jiByA4v14s=", + "dev": true, + "requires": { + "is-stream": "^1.0.1", + "readable-stream": "^2.0.1" + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + }, + "unique-stream": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", + "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", + "dev": true, + "requires": { + "json-stable-stringify": "^1.0.0", + "through2-filter": "^2.0.0" + } + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + } + }, + "vinyl-fs": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz", + "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=", + "dev": true, + "requires": { + "duplexify": "^3.2.0", + "glob-stream": "^5.3.2", + "graceful-fs": "^4.0.0", + "gulp-sourcemaps": "1.6.0", + "is-valid-glob": "^0.3.0", + "lazystream": "^1.0.0", + "lodash.isequal": "^4.0.0", + "merge-stream": "^1.0.0", + "mkdirp": "^0.5.0", + "object-assign": "^4.0.0", + "readable-stream": "^2.0.4", + "strip-bom": "^2.0.0", + "strip-bom-stream": "^1.0.0", + "through2": "^2.0.0", + "through2-filter": "^2.0.0", + "vali-date": "^1.0.0", + "vinyl": "^1.0.0" + } + } + } + }, + "duplexer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", + "dev": true + }, + "duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "dev": true, + "requires": { + "readable-stream": "~1.1.9" + } + }, + "duplexify": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.0.tgz", + "integrity": "sha1-WSkD9dgLONA3IgVBJk1poZj7NBA=", + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha1-7SljTRm6ukY7bOa4CjchPqtx7EM=", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "each-async": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/each-async/-/each-async-1.1.1.tgz", + "integrity": "sha1-3uUim98KtrogEqOV4bhpq/iBNHM=", + "dev": true, + "requires": { + "onetime": "^1.0.0", + "set-immediate-shim": "^1.0.0" + }, + "dependencies": { + "onetime": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "dev": true + } + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, + "optional": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "electron-to-chromium": { + "version": "1.3.73", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.73.tgz", + "integrity": "sha512-6PIg7v9zRoVGh6EheRF8h6Plti+3Yo/qtHobS4/Htyt53DNHmKKGFqSae1AIk0k1S4gCQvt7I2WgpbuZNcDY+g==", + "dev": true + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true + }, + "end-of-stream": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", + "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", + "dev": true, + "requires": { + "once": "~1.3.0" + }, + "dependencies": { + "once": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", + "dev": true, + "requires": { + "wrappy": "1" + } + } + } + }, + "engine.io": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.1.5.tgz", + "integrity": "sha1-Dn751pDrCzVZfx1K0Comyi26OEU=", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "base64id": "1.0.0", + "cookie": "0.3.1", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.0", + "uws": "~9.14.0", + "ws": "~3.3.1" + }, + "dependencies": { + "accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "dev": true, + "requires": { + "mime-types": "~2.1.18", + "negotiator": "0.6.1" + } + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", + "dev": true + } + } + }, + "engine.io-client": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.1.6.tgz", + "integrity": "sha1-W96xMPi5SlCsXL63JYPnpKBj3f0=", + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "component-inherit": "0.0.3", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.1", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "ws": "~3.3.1", + "xmlhttprequest-ssl": "~1.5.4", + "yeast": "0.1.2" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "engine.io-parser": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.2.tgz", + "integrity": "sha1-TA9M/3mq7su9z96maoI8YIVAkZY=", + "dev": true, + "requires": { + "after": "0.8.2", + "arraybuffer.slice": "~0.0.7", + "base64-arraybuffer": "0.1.5", + "blob": "0.0.4", + "has-binary2": "~1.0.2" + } + }, + "ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", + "dev": true + }, + "entities": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", + "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=", + "dev": true, + "optional": true + }, + "errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha1-RoTXF3mtOa8Xfj8AeZb3xnyFJhg=", + "dev": true, + "optional": true, + "requires": { + "prr": "~1.0.1" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "errorhandler": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.4.3.tgz", + "integrity": "sha1-t7cO2PNZ6duICS8tIMD4MUIK2D8=", + "dev": true, + "requires": { + "accepts": "~1.3.0", + "escape-html": "~1.0.3" + }, + "dependencies": { + "accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "dev": true, + "requires": { + "mime-types": "~2.1.18", + "negotiator": "0.6.1" + } + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", + "dev": true + } + } + }, + "es-abstract": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz", + "integrity": "sha1-nbvdJ8aFbwABQhyhh4LXhr+KYWU=", + "dev": true, + "requires": { + "es-to-primitive": "^1.1.1", + "function-bind": "^1.1.1", + "has": "^1.0.1", + "is-callable": "^1.1.3", + "is-regex": "^1.0.4" + } + }, + "es-to-primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "es6-promise": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", + "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=", + "dev": true + }, + "es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "dev": true, + "requires": { + "es6-promise": "^4.0.3" + }, + "dependencies": { + "es6-promise": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.5.tgz", + "integrity": "sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg==", + "dev": true + } + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "escodegen": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.0.tgz", + "integrity": "sha512-IeMV45ReixHS53K/OmfKAIztN/igDHzTJUhZM3k1jMhIZWjk45SMwAtBsEXiJp3vSPmTcu6CXn7mDvFHRN66fw==", + "dev": true, + "requires": { + "esprima": "^3.1.3", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + }, + "dependencies": { + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true, + "optional": true + } + } + }, + "eslint": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.6.1.tgz", + "integrity": "sha512-hgrDtGWz368b7Wqf+v1Z69O3ZebNR0+GA7PtDdbmuz4rInFVUV9uw7whjZEiWyLzCjVb5Rs5WRN1TAS6eo7AYA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.5.3", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^2.1.0", + "eslint-scope": "^4.0.0", + "eslint-utils": "^1.3.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^4.0.0", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^2.0.0", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^11.7.0", + "ignore": "^4.0.6", + "imurmurhash": "^0.1.4", + "inquirer": "^6.1.0", + "is-resolvable": "^1.1.0", + "js-yaml": "^3.12.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.5", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.2", + "pluralize": "^7.0.0", + "progress": "^2.0.0", + "regexpp": "^2.0.0", + "require-uncached": "^1.0.3", + "semver": "^5.5.1", + "strip-ansi": "^4.0.0", + "strip-json-comments": "^2.0.1", + "table": "^4.0.3", + "text-table": "^0.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "debug": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.0.1.tgz", + "integrity": "sha512-K23FHJ/Mt404FSlp6gSZCevIbTMLX0j3fmHhUEhQ3Wq0FMODW3+cUSoLdy1Gx4polAf4t/lphhmHH35BB8cLYw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "js-yaml": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "semver": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", + "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "eslint-scope": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", + "integrity": "sha1-UL8wcekzi83EMzF5Sgy1M/ATYXI=", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.3.1.tgz", + "integrity": "sha1-moUbqJ7nxGA0b5fPiTnHKYgn5RI=", + "dev": true + }, + "eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha1-PzGA+y4pEBdxastMnW1bXDSmqB0=", + "dev": true + }, + "espree": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-4.0.0.tgz", + "integrity": "sha1-JTmY8goPgttdhmOFeZ2RKoOjZjQ=", + "dev": true, + "requires": { + "acorn": "^5.6.0", + "acorn-jsx": "^4.1.1" + } + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, + "esquery": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", + "integrity": "sha1-QGxRZYsfWZGl+bYrHcJbAOPlxwg=", + "dev": true, + "requires": { + "estraverse": "^4.0.0" + } + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha1-AHo7n9vCs7uH5IeeoZyS/b05Qs8=", + "dev": true, + "requires": { + "estraverse": "^4.1.0" + } + }, + "estemplate": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/estemplate/-/estemplate-0.5.1.tgz", + "integrity": "sha1-FxSp1GGQc4rJWLyv1J4CnNpWo54=", + "dev": true, + "requires": { + "esprima": "^2.7.2", + "estraverse": "^4.1.1" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "etag": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz", + "integrity": "sha1-A9MLX2fdbmMtKUXTDWZScxo01dg=", + "dev": true + }, + "event-stream": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.6.tgz", + "integrity": "sha512-dGXNg4F/FgVzlApjzItL+7naHutA3fDqbV/zAZqDDlXTjiMnQmZKu+prImWKszeBM5UQeGvAl3u1wBiKeDh61g==", + "dev": true, + "requires": { + "duplexer": "^0.1.1", + "flatmap-stream": "^0.1.0", + "from": "^0.1.7", + "map-stream": "0.0.7", + "pause-stream": "^0.0.11", + "split": "^1.0.1", + "stream-combiner": "^0.2.2", + "through": "^2.3.8" + } + }, + "eventemitter3": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz", + "integrity": "sha1-CQtNbNvWRe0Qv3UNS1QHlC17oWM=", + "dev": true + }, + "exec-buffer": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/exec-buffer/-/exec-buffer-3.2.0.tgz", + "integrity": "sha1-sWhtvZBMfPmC5lLB9aebHlVzCCs=", + "dev": true, + "optional": true, + "requires": { + "execa": "^0.7.0", + "p-finally": "^1.0.0", + "pify": "^3.0.0", + "rimraf": "^2.5.4", + "tempfile": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true, + "optional": true + } + } + }, + "exec-series": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/exec-series/-/exec-series-1.0.3.tgz", + "integrity": "sha1-bSV6m+rEgqhyx3g7yGFYOfx3FDo=", + "dev": true, + "optional": true, + "requires": { + "async-each-series": "^1.1.0", + "object-assign": "^4.1.0" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "optional": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "optional": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "lru-cache": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", + "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", + "dev": true, + "optional": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + } + } + }, + "executable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/executable/-/executable-1.1.0.tgz", + "integrity": "sha1-h3mA6REvM5EGbaNyZd562ENKtNk=", + "dev": true, + "optional": true, + "requires": { + "meow": "^3.1.0" + } + }, + "expand-braces": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz", + "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=", + "dev": true, + "requires": { + "array-slice": "^0.2.3", + "array-unique": "^0.2.1", + "braces": "^0.1.2" + }, + "dependencies": { + "array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "braces": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz", + "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=", + "dev": true, + "requires": { + "expand-range": "^0.1.0" + } + }, + "expand-range": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz", + "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=", + "dev": true, + "requires": { + "is-number": "^0.1.1", + "repeat-string": "^0.2.2" + } + }, + "is-number": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz", + "integrity": "sha1-aaevEWlj1HIG7JvZtIoUIW8eOAY=", + "dev": true + }, + "repeat-string": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-0.2.2.tgz", + "integrity": "sha1-x6jTI2BoNiBZp+RlH8aITosftK4=", + "dev": true + } + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "requires": { + "fill-range": "^2.1.0" + }, + "dependencies": { + "fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha1-6x53OrsFbc2N8r/favWbizqTZWU=", + "dev": true, + "requires": { + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^3.0.0", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "express-session": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.11.3.tgz", + "integrity": "sha1-XMmPP1/4Ttg1+Ry/CqvQxxB0AK8=", + "dev": true, + "requires": { + "cookie": "0.1.3", + "cookie-signature": "1.0.6", + "crc": "3.3.0", + "debug": "~2.2.0", + "depd": "~1.0.1", + "on-headers": "~1.0.0", + "parseurl": "~1.3.0", + "uid-safe": "~2.0.0", + "utils-merge": "1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + }, + "uid-safe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.0.0.tgz", + "integrity": "sha1-p/PGymSh9qXQTsDvPkw9U2cxcTc=", + "dev": true, + "requires": { + "base64-url": "1.2.1" + } + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "external-editor": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz", + "integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha1-rQD+TcYSqSMuhxhxHcXLWrAoVUM=", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "extract-zip": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.7.tgz", + "integrity": "sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k=", + "dev": true, + "requires": { + "concat-stream": "1.6.2", + "debug": "2.6.9", + "mkdirp": "0.5.1", + "yauzl": "2.4.1" + }, + "dependencies": { + "fd-slicer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", + "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", + "dev": true, + "requires": { + "pend": "~1.2.0" + } + }, + "yauzl": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", + "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", + "dev": true, + "requires": { + "fd-slicer": "~1.0.1" + } + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "fancy-log": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", + "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", + "dev": true, + "requires": { + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "time-stamp": "^1.0.0" + } + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "faye-websocket": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", + "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", + "dev": true, + "requires": { + "websocket-driver": ">=0.5.1" + } + }, + "fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "dev": true, + "requires": { + "pend": "~1.2.0" + } + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "dev": true, + "requires": { + "flat-cache": "^1.2.1", + "object-assign": "^4.0.1" + } + }, + "file-type": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-4.4.0.tgz", + "integrity": "sha1-G2AOX8ofvcboDApwxxyNul95BsU=", + "dev": true + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha1-VTp7hEb/b2hDWcRF8eN6BdrMM90=", + "dev": true, + "optional": true + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, + "filename-reserved-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-1.0.0.tgz", + "integrity": "sha1-5hz4BfDeHJhFZ9A4bcXfUO5a9+Q=", + "dev": true + }, + "filenamify": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-1.2.1.tgz", + "integrity": "sha1-qfL/0RxQO+0wABUCknI3jx8TZaU=", + "dev": true, + "requires": { + "filename-reserved-regex": "^1.0.0", + "strip-outer": "^1.0.0", + "trim-repeated": "^1.0.0" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "finalhandler": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.4.0.tgz", + "integrity": "sha1-llpS2ejQXSuFdUhUH7ibU6JJfZs=", + "dev": true, + "requires": { + "debug": "~2.2.0", + "escape-html": "1.0.2", + "on-finished": "~2.3.0", + "unpipe": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "escape-html": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.2.tgz", + "integrity": "sha1-130y+pjjjC9BroXpJ44ODmuhAiw=", + "dev": true + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + } + } + }, + "find-index": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", + "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=", + "dev": true + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "find-versions": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-1.2.1.tgz", + "integrity": "sha1-y96fEuOFdaCvG+G5osXV/Y8Ya2I=", + "dev": true, + "optional": true, + "requires": { + "array-uniq": "^1.0.0", + "get-stdin": "^4.0.1", + "meow": "^3.5.0", + "semver-regex": "^1.0.0" + } + }, + "findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } + }, + "fined": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", + "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" + } + }, + "first-chunk-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", + "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", + "dev": true + }, + "flagged-respawn": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz", + "integrity": "sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c=", + "dev": true + }, + "flat-cache": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", + "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", + "dev": true, + "requires": { + "circular-json": "^0.3.1", + "del": "^2.0.2", + "graceful-fs": "^4.1.2", + "write": "^0.2.1" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + } + } + }, + "flatmap-stream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/flatmap-stream/-/flatmap-stream-0.1.0.tgz", + "integrity": "sha512-Nlic4ZRYxikqnK5rj3YoxDVKGGtUjcNDUtvQ7XsdGLZmMwdUYnXf10o1zcXtzEZTBgc6GxeRpQxV/Wu3WPIIHA==", + "dev": true + }, + "flatpickr": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-4.5.2.tgz", + "integrity": "sha512-jDy4QYGpmiy7+Qk8QvKJ4spjDdxcx9cxMydmq1x427HkKWBw0qizLYeYM2F6tMcvvqGjU5VpJS55j4LnsaBblA==" + }, + "flatten": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz", + "integrity": "sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=", + "dev": true + }, + "follow-redirects": { + "version": "1.5.8", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.8.tgz", + "integrity": "sha512-sy1mXPmv7kLAMKW/8XofG7o9T+6gAjzdZK4AJF6ryqQYUa/hnzgiypoeUecZ53x7XiqKNEpNqLtS97MshW2nxg==", + "dev": true, + "requires": { + "debug": "=3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "font-awesome": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz", + "integrity": "sha1-j6jPBBGhoxr9B7BtKQK7n8gVoTM=" + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.5", + "mime-types": "^2.1.12" + } + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "fresh": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz", + "integrity": "sha1-ZR+DjiJCTnVm3hYdg1jKoZn4PU8=", + "dev": true + }, + "from": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", + "dev": true + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha1-a+Dem+mYzhavivwkSXue6bfM2a0=", + "dev": true + }, + "fs-extra": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz", + "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0", + "klaw": "^1.0.0" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + } + } + }, + "fs-readfile-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fs-readfile-promise/-/fs-readfile-promise-2.0.1.tgz", + "integrity": "sha1-gAI4I5gfn//+AWCei+Zo9prknnA=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + } + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", + "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", + "dev": true, + "optional": true, + "requires": { + "nan": "^2.9.2", + "node-pre-gyp": "^0.10.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "2.6.9", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.21", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": "^2.1.0" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "minipass": { + "version": "2.2.4", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "^5.1.1", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.2.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "^2.1.2", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.10.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.0", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.1.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.1.10", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "^0.5.1", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "^7.0.5" + } + }, + "safe-buffer": { + "version": "5.1.1", + "bundled": true, + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.5.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "^1.0.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.2.4", + "minizlib": "^1.1.0", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.1", + "yallist": "^3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "^1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "yallist": { + "version": "3.0.2", + "bundled": true, + "dev": true + } + } + }, + "ftp": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", + "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", + "dev": true, + "optional": true, + "requires": { + "readable-stream": "1.1.x", + "xregexp": "2.0.0" + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=", + "dev": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "gaze": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", + "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", + "dev": true, + "requires": { + "globule": "~0.1.0" + } + }, + "generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "dev": true, + "optional": true, + "requires": { + "is-property": "^1.0.2" + } + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "dev": true, + "optional": true, + "requires": { + "is-property": "^1.0.0" + } + }, + "get-proxy": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-1.1.0.tgz", + "integrity": "sha1-iUhUSRvFkbDxR9euVw9cZ4tyVus=", + "dev": true, + "requires": { + "rc": "^1.1.2" + } + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true, + "optional": true + }, + "get-uri": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.2.tgz", + "integrity": "sha1-XHlecTJvbKEoby/IJXXNK6sq9Xg=", + "dev": true, + "optional": true, + "requires": { + "data-uri-to-buffer": "1", + "debug": "2", + "extend": "3", + "file-uri-to-path": "1", + "ftp": "~0.3.10", + "readable-stream": "2" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true, + "optional": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha1-sRwn2IuP8fvgcGQ8+UsMea4bCq8=", + "dev": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "gifsicle": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/gifsicle/-/gifsicle-3.0.4.tgz", + "integrity": "sha1-9Fy17RAWW2ZdySng6TKLbIId+js=", + "dev": true, + "optional": true, + "requires": { + "bin-build": "^2.0.0", + "bin-wrapper": "^3.0.0", + "logalot": "^2.0.0" + } + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "requires": { + "glob-parent": "^2.0.0", + "is-glob": "^2.0.0" + }, + "dependencies": { + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "^2.0.0" + } + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "glob-stream": { + "version": "3.1.18", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", + "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", + "dev": true, + "requires": { + "glob": "^4.3.1", + "glob2base": "^0.0.12", + "minimatch": "^2.0.1", + "ordered-read-streams": "^0.1.0", + "through2": "^0.6.1", + "unique-stream": "^1.0.0" + }, + "dependencies": { + "glob": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", + "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", + "dev": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^2.0.1", + "once": "^1.3.0" + } + }, + "minimatch": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "dev": true, + "requires": { + "brace-expansion": "^1.0.0" + } + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + } + } + }, + "glob-watcher": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", + "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", + "dev": true, + "requires": { + "gaze": "^0.5.1" + } + }, + "glob2base": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", + "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", + "dev": true, + "requires": { + "find-index": "^0.1.1" + } + }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha1-bXcPDrUjrHgWTXK15xqIdyZcw+o=", + "dev": true, + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + } + }, + "globals": { + "version": "11.8.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.8.0.tgz", + "integrity": "sha512-io6LkyPVuzCHBSQV9fmOwxZkUk6nIaGmxheLDgmuFv89j0fm2aqDbIXKAGfzCMHqz3HLF2Zf8WSG6VqMh2qFmA==", + "dev": true + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "globule": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", + "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", + "dev": true, + "requires": { + "glob": "~3.1.21", + "lodash": "~1.0.1", + "minimatch": "~0.2.11" + }, + "dependencies": { + "glob": { + "version": "3.1.21", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", + "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", + "dev": true, + "requires": { + "graceful-fs": "~1.2.0", + "inherits": "1", + "minimatch": "~0.2.11" + } + }, + "graceful-fs": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", + "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", + "dev": true + }, + "inherits": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", + "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", + "dev": true + }, + "lodash": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", + "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", + "dev": true + }, + "minimatch": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "dev": true, + "requires": { + "lru-cache": "2", + "sigmund": "~1.0.0" + } + } + } + }, + "glogg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.1.tgz", + "integrity": "sha1-3PdY5EeJzD89MsHzVio2duajSBA=", + "dev": true, + "requires": { + "sparkles": "^1.0.0" + } + }, + "good-listener": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", + "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=", + "requires": { + "delegate": "^3.1.2" + } + }, + "got": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/got/-/got-5.7.1.tgz", + "integrity": "sha1-X4FjWmHkplifGAVp6k44FoClHzU=", + "dev": true, + "requires": { + "create-error-class": "^3.0.1", + "duplexer2": "^0.1.4", + "is-redirect": "^1.0.0", + "is-retry-allowed": "^1.0.0", + "is-stream": "^1.0.0", + "lowercase-keys": "^1.0.0", + "node-status-codes": "^1.0.0", + "object-assign": "^4.0.1", + "parse-json": "^2.1.0", + "pinkie-promise": "^2.0.0", + "read-all-stream": "^3.0.0", + "readable-stream": "^2.0.5", + "timed-out": "^3.0.0", + "unzip-response": "^1.0.2", + "url-parse-lax": "^1.0.0" + }, + "dependencies": { + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "dev": true, + "requires": { + "readable-stream": "^2.0.2" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "graceful-fs": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", + "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", + "dev": true, + "requires": { + "natives": "^1.1.0" + } + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", + "dev": true + }, + "gulp": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", + "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", + "dev": true, + "requires": { + "archy": "^1.0.0", + "chalk": "^1.0.0", + "deprecated": "^0.0.1", + "gulp-util": "^3.0.0", + "interpret": "^1.0.0", + "liftoff": "^2.1.0", + "minimist": "^1.1.0", + "orchestrator": "^0.3.0", + "pretty-hrtime": "^1.0.0", + "semver": "^4.1.0", + "tildify": "^1.0.0", + "v8flags": "^2.0.2", + "vinyl-fs": "^0.3.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "gulp-babel": { + "version": "8.0.0-beta.2", + "resolved": "http://registry.npmjs.org/gulp-babel/-/gulp-babel-8.0.0-beta.2.tgz", + "integrity": "sha512-GTC2PxAXWkp6u1fP+C5+kn5biQ0dKGhkOSSXvKAf3ykF0+R3tevmLm/zSIkc1+S7U1JwH3XTvuMwRL6LD+sEiw==", + "dev": true, + "requires": { + "plugin-error": "^1.0.1", + "replace-ext": "^1.0.0", + "through2": "^2.0.0", + "vinyl-sourcemaps-apply": "^0.2.0" + }, + "dependencies": { + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true + } + } + }, + "gulp-clean-css": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/gulp-clean-css/-/gulp-clean-css-3.10.0.tgz", + "integrity": "sha512-7Isf9Y690o/Q5MVjEylH1H7L8WeZ89woW7DnhD5unTintOdZb67KdOayRgp9trUFo+f9UyJtuatV42e/+kghPg==", + "dev": true, + "requires": { + "clean-css": "4.2.1", + "plugin-error": "1.0.1", + "through2": "2.0.3", + "vinyl-sourcemaps-apply": "0.2.1" + } + }, + "gulp-concat": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz", + "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", + "dev": true, + "requires": { + "concat-with-sourcemaps": "^1.0.0", + "through2": "^2.0.0", + "vinyl": "^2.0.0" + }, + "dependencies": { + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true + }, + "vinyl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", + "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", + "dev": true, + "requires": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + } + } + } + }, + "gulp-connect": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/gulp-connect/-/gulp-connect-5.0.0.tgz", + "integrity": "sha1-8v3zBq6RFGg2jCKF8teC8T7dr04=", + "dev": true, + "requires": { + "connect": "^2.30.0", + "connect-livereload": "^0.5.4", + "event-stream": "^3.3.2", + "gulp-util": "^3.0.6", + "tiny-lr": "^0.2.1" + } + }, + "gulp-decompress": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gulp-decompress/-/gulp-decompress-1.2.0.tgz", + "integrity": "sha1-jutlpeAV+O2FMsr+KEVJYGJvDcc=", + "dev": true, + "requires": { + "archive-type": "^3.0.0", + "decompress": "^3.0.0", + "gulp-util": "^3.0.1", + "readable-stream": "^2.0.2" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "gulp-eslint": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/gulp-eslint/-/gulp-eslint-5.0.0.tgz", + "integrity": "sha1-KiaECV93Syz3kxAmIHjFbMehK1I=", + "dev": true, + "requires": { + "eslint": "^5.0.1", + "fancy-log": "^1.3.2", + "plugin-error": "^1.0.1" + } + }, + "gulp-imagemin": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/gulp-imagemin/-/gulp-imagemin-4.1.0.tgz", + "integrity": "sha1-XONH8dFwb+08yPF3fKkJSlg7ULc=", + "dev": true, + "requires": { + "chalk": "^2.1.0", + "fancy-log": "^1.3.2", + "imagemin": "^5.3.1", + "imagemin-gifsicle": "^5.2.0", + "imagemin-jpegtran": "^5.0.2", + "imagemin-optipng": "^5.2.1", + "imagemin-svgo": "^6.0.0", + "plugin-error": "^0.1.2", + "plur": "^2.1.2", + "pretty-bytes": "^4.0.2", + "through2-concurrent": "^1.1.1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0=", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "arr-diff": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz", + "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1", + "array-slice": "^0.2.3" + } + }, + "arr-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz", + "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=", + "dev": true + }, + "array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", + "dev": true + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha1-GMSasWoDe26wFSzIPjRxM4IVtm4=", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "extend-shallow": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz", + "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", + "dev": true, + "requires": { + "kind-of": "^1.1.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "kind-of": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", + "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=", + "dev": true + }, + "plugin-error": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", + "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", + "dev": true, + "requires": { + "ansi-cyan": "^0.1.1", + "ansi-red": "^0.1.1", + "arr-diff": "^1.0.1", + "arr-union": "^2.0.1", + "extend-shallow": "^1.1.2" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "gulp-less": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/gulp-less/-/gulp-less-3.5.0.tgz", + "integrity": "sha1-gBT0ad38ZUTX3aUAmN7wNxu7T3g=", + "dev": true, + "requires": { + "accord": "^0.28.0", + "less": "2.6.x || ^2.7.1", + "object-assign": "^4.0.1", + "plugin-error": "^0.1.2", + "replace-ext": "^1.0.0", + "through2": "^2.0.0", + "vinyl-sourcemaps-apply": "^0.2.0" + }, + "dependencies": { + "arr-diff": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz", + "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1", + "array-slice": "^0.2.3" + } + }, + "arr-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz", + "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=", + "dev": true + }, + "array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", + "dev": true + }, + "extend-shallow": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz", + "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", + "dev": true, + "requires": { + "kind-of": "^1.1.0" + } + }, + "kind-of": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", + "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=", + "dev": true + }, + "plugin-error": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", + "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", + "dev": true, + "requires": { + "ansi-cyan": "^0.1.1", + "ansi-red": "^0.1.1", + "arr-diff": "^1.0.1", + "arr-union": "^2.0.1", + "extend-shallow": "^1.1.2" + } + }, + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true + } + } + }, + "gulp-ngdocs": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/gulp-ngdocs/-/gulp-ngdocs-0.3.0.tgz", + "integrity": "sha1-J7Z6Ql6zh1ImNFq4lgTXN/Y1fCE=", + "dev": true, + "requires": { + "angular": "~1.3.1", + "angular-animate": "~1.3.1", + "canonical-path": "0.0.2", + "extend": "1.3.0", + "gulp-util": "3.0.0", + "lodash": "2.4.1", + "marked": "0.3.2", + "merge-stream": "0.1.5", + "path": "0.4.9", + "string_decoder": "0.10.31", + "through2": "0.6.1", + "vinyl-fs": "0.3.7" + }, + "dependencies": { + "angular": { + "version": "1.3.20", + "resolved": "http://registry.npmjs.org/angular/-/angular-1.3.20.tgz", + "integrity": "sha1-sjo9fF5/mffZW5tNSbmsNVJpuu4=", + "dev": true + }, + "angular-animate": { + "version": "1.3.20", + "resolved": "http://registry.npmjs.org/angular-animate/-/angular-animate-1.3.20.tgz", + "integrity": "sha1-0XB8cn+K0N8hxKLewgzX/ElFtSo=", + "dev": true + }, + "ansi-regex": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", + "integrity": "sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk=", + "dev": true + }, + "ansi-styles": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", + "integrity": "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94=", + "dev": true + }, + "chalk": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", + "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=", + "dev": true, + "requires": { + "ansi-styles": "^1.1.0", + "escape-string-regexp": "^1.0.0", + "has-ansi": "^0.1.0", + "strip-ansi": "^0.3.0", + "supports-color": "^0.2.0" + } + }, + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "dateformat": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", + "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", + "dev": true, + "requires": { + "get-stdin": "^4.0.1", + "meow": "^3.3.0" + } + }, + "extend": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extend/-/extend-1.3.0.tgz", + "integrity": "sha1-0VFvsP9WJNLr+RI+odrFoZlABPg=", + "dev": true + }, + "gulp-util": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.0.tgz", + "integrity": "sha1-b+7cR9aXKCO6zplH/F9GvYo0Zuc=", + "dev": true, + "requires": { + "chalk": "^0.5.0", + "dateformat": "^1.0.7-1.2.3", + "lodash": "^2.4.1", + "lodash._reinterpolate": "^2.4.1", + "lodash.template": "^2.4.1", + "minimist": "^0.2.0", + "multipipe": "^0.1.0", + "through2": "^0.5.0", + "vinyl": "^0.2.1" + }, + "dependencies": { + "through2": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", + "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", + "dev": true, + "requires": { + "readable-stream": "~1.0.17", + "xtend": "~3.0.0" + } + } + } + }, + "has-ansi": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", + "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=", + "dev": true, + "requires": { + "ansi-regex": "^0.2.0" + } + }, + "lodash": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.1.tgz", + "integrity": "sha1-W3cjA03aTSYuWkb7LFjXzCL3FCA=", + "dev": true + }, + "lodash._reinterpolate": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz", + "integrity": "sha1-TxInqlqHEfxjL1sHofRgequLMiI=", + "dev": true + }, + "lodash.defaults": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz", + "integrity": "sha1-p+iIXwXmiFEUS24SqPNngCa8TFQ=", + "dev": true, + "requires": { + "lodash._objecttypes": "~2.4.1", + "lodash.keys": "~2.4.1" + } + }, + "lodash.escape": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz", + "integrity": "sha1-LOEsXghNsKV92l5dHu659dF1o7Q=", + "dev": true, + "requires": { + "lodash._escapehtmlchar": "~2.4.1", + "lodash._reunescapedhtml": "~2.4.1", + "lodash.keys": "~2.4.1" + } + }, + "lodash.keys": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", + "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", + "dev": true, + "requires": { + "lodash._isnative": "~2.4.1", + "lodash._shimkeys": "~2.4.1", + "lodash.isobject": "~2.4.1" + } + }, + "lodash.template": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-2.4.1.tgz", + "integrity": "sha1-nmEQB+32KRKal0qzxIuBez4c8g0=", + "dev": true, + "requires": { + "lodash._escapestringchar": "~2.4.1", + "lodash._reinterpolate": "~2.4.1", + "lodash.defaults": "~2.4.1", + "lodash.escape": "~2.4.1", + "lodash.keys": "~2.4.1", + "lodash.templatesettings": "~2.4.1", + "lodash.values": "~2.4.1" + } + }, + "lodash.templatesettings": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-2.4.1.tgz", + "integrity": "sha1-6nbHXRHrhtTb6JqDiTu4YZKaxpk=", + "dev": true, + "requires": { + "lodash._reinterpolate": "~2.4.1", + "lodash.escape": "~2.4.1" + } + }, + "merge-stream": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-0.1.5.tgz", + "integrity": "sha1-5oIPet267gA/SMpKWMfFolPV4Fw=", + "dev": true, + "requires": { + "through2": "^0.5.1" + }, + "dependencies": { + "through2": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", + "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", + "dev": true, + "requires": { + "readable-stream": "~1.0.17", + "xtend": "~3.0.0" + } + } + } + }, + "minimist": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.2.0.tgz", + "integrity": "sha1-Tf/lJdriuGTGbC4jxicdev3s784=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "strip-ansi": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", + "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", + "dev": true, + "requires": { + "ansi-regex": "^0.2.1" + } + }, + "supports-color": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", + "integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=", + "dev": true + }, + "through2": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.1.tgz", + "integrity": "sha1-90KzKJPovSYUbnieT9LMssB6cX4=", + "dev": true, + "requires": { + "readable-stream": ">=1.0.27-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + }, + "dependencies": { + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + } + } + }, + "vinyl": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.2.3.tgz", + "integrity": "sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI=", + "dev": true, + "requires": { + "clone-stats": "~0.0.1" + } + }, + "vinyl-fs": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.7.tgz", + "integrity": "sha1-LiXP5t9cgIGPl/9Be/XCGkHkpJs=", + "dev": true, + "requires": { + "glob-stream": "^3.1.5", + "glob-watcher": "^0.0.6", + "graceful-fs": "^3.0.0", + "lodash": "^2.4.1", + "mkdirp": "^0.5.0", + "strip-bom": "^1.0.0", + "through2": "^0.6.1", + "vinyl": "^0.4.0" + }, + "dependencies": { + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "^0.2.0", + "clone-stats": "^0.0.1" + } + } + } + }, + "xtend": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", + "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=", + "dev": true + } + } + }, + "gulp-open": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/gulp-open/-/gulp-open-2.1.0.tgz", + "integrity": "sha1-rAHu6JjXenrAgS+tTz1T0IaH1Bw=", + "dev": true, + "requires": { + "colors": "^1.1.2", + "open": "0.0.5", + "plugin-log": "^0.1.0", + "through2": "^2.0.1" + } + }, + "gulp-postcss": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/gulp-postcss/-/gulp-postcss-6.4.0.tgz", + "integrity": "sha1-eKMuPIeqbNzsWuHJBeGW1HjoxdU=", + "dev": true, + "requires": { + "gulp-util": "^3.0.8", + "postcss": "^5.2.12", + "postcss-load-config": "^1.2.0", + "vinyl-sourcemaps-apply": "^0.2.1" + } + }, + "gulp-rename": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.4.0.tgz", + "integrity": "sha512-swzbIGb/arEoFK89tPY58vg3Ok1bw+d35PfUNwWqdo7KM4jkmuGA78JiDNqR+JeZFaeeHnRg9N7aihX3YPmsyg==", + "dev": true + }, + "gulp-sort": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/gulp-sort/-/gulp-sort-2.0.0.tgz", + "integrity": "sha1-xnYqLx8N4KP8WVohWZ0/rI26Gso=", + "dev": true, + "requires": { + "through2": "^2.0.1" + } + }, + "gulp-sourcemaps": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz", + "integrity": "sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw=", + "dev": true, + "requires": { + "convert-source-map": "^1.1.1", + "graceful-fs": "^4.1.2", + "strip-bom": "^2.0.0", + "through2": "^2.0.0", + "vinyl": "^1.0.0" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + } + } + } + }, + "gulp-util": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", + "dev": true, + "requires": { + "array-differ": "^1.0.0", + "array-uniq": "^1.0.2", + "beeper": "^1.0.0", + "chalk": "^1.0.0", + "dateformat": "^2.0.0", + "fancy-log": "^1.1.0", + "gulplog": "^1.0.0", + "has-gulplog": "^0.1.0", + "lodash._reescape": "^3.0.0", + "lodash._reevaluate": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.template": "^3.0.0", + "minimist": "^1.1.0", + "multipipe": "^0.1.2", + "object-assign": "^3.0.0", + "replace-ext": "0.0.1", + "through2": "^2.0.0", + "vinyl": "^0.5.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "dev": true + } + } + }, + "gulp-watch": { + "version": "4.3.11", + "resolved": "https://registry.npmjs.org/gulp-watch/-/gulp-watch-4.3.11.tgz", + "integrity": "sha1-Fi/FY96fx3DpH5p845VVE6mhGMA=", + "dev": true, + "requires": { + "anymatch": "^1.3.0", + "chokidar": "^1.6.1", + "glob-parent": "^3.0.1", + "gulp-util": "^3.0.7", + "object-assign": "^4.1.0", + "path-is-absolute": "^1.0.1", + "readable-stream": "^2.2.2", + "slash": "^1.0.0", + "vinyl": "^1.2.0", + "vinyl-file": "^2.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha1-sRwn2IuP8fvgcGQ8+UsMea4bCq8=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + } + } + } + }, + "gulp-wrap": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/gulp-wrap/-/gulp-wrap-0.13.0.tgz", + "integrity": "sha1-kPsLSieiZkM4Mv98YSLbXB7olMY=", + "dev": true, + "requires": { + "consolidate": "^0.14.1", + "es6-promise": "^3.1.2", + "fs-readfile-promise": "^2.0.1", + "gulp-util": "^3.0.3", + "js-yaml": "^3.2.6", + "lodash": "^4.11.1", + "node.extend": "^1.1.2", + "through2": "^2.0.1", + "tryit": "^1.0.1", + "vinyl-bufferstream": "^1.0.1" + } + }, + "gulp-wrap-js": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/gulp-wrap-js/-/gulp-wrap-js-0.4.1.tgz", + "integrity": "sha1-3uYqpISqupVHqT0f9c0MPQvtwDE=", + "dev": true, + "requires": { + "escodegen": "^1.6.1", + "esprima": "^2.3.0", + "estemplate": "*", + "gulp-util": "~3.0.5", + "through2": "*", + "vinyl-sourcemaps-apply": "^0.1.4" + }, + "dependencies": { + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "dev": true, + "requires": { + "amdefine": ">=0.0.4" + } + }, + "vinyl-sourcemaps-apply": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.1.4.tgz", + "integrity": "sha1-xfy9Q+LyOEI8LcmL3db3m3K8NFs=", + "dev": true, + "requires": { + "source-map": "^0.1.39" + } + } + } + }, + "gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "dev": true, + "requires": { + "glogg": "^1.0.0" + } + }, + "har-schema": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", + "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", + "dev": true + }, + "har-validator": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", + "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", + "dev": true, + "requires": { + "ajv": "^4.9.1", + "har-schema": "^1.0.5" + }, + "dependencies": { + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "dev": true, + "requires": { + "co": "^4.6.0", + "json-stable-stringify": "^1.0.1" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + } + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-binary2": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", + "integrity": "sha1-d3asYn8+p3JQz8My2rfd9eT10R0=", + "dev": true, + "requires": { + "isarray": "2.0.1" + }, + "dependencies": { + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true + } + } + }, + "has-cors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", + "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=", + "dev": true + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "has-gulplog": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", + "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", + "dev": true, + "requires": { + "sparkles": "^1.0.0" + } + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "hasha": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-2.2.0.tgz", + "integrity": "sha1-eNfL/B5tZjA/55g3NlmEUXsvbuE=", + "dev": true, + "requires": { + "is-stream": "^1.0.1", + "pinkie-promise": "^2.0.0" + } + }, + "hawk": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "dev": true, + "requires": { + "boom": "2.x.x", + "cryptiles": "2.x.x", + "hoek": "2.x.x", + "sntp": "1.x.x" + } + }, + "hipchat-notifier": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hipchat-notifier/-/hipchat-notifier-1.1.0.tgz", + "integrity": "sha1-ttJJdVQ3wZEII2d5nTupoPI7Ix4=", + "dev": true, + "optional": true, + "requires": { + "lodash": "^4.0.0", + "request": "^2.0.0" + } + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", + "dev": true + }, + "homedir-polyfill": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", + "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", + "dev": true, + "requires": { + "parse-passwd": "^1.0.0" + } + }, + "hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", + "dev": true + }, + "html-comment-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.1.tgz", + "integrity": "sha1-ZouTd26q5V696POtRkswekljYl4=", + "dev": true + }, + "http-errors": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", + "integrity": "sha1-GX4izevUGYWF6GlO9nhhl7ke2UI=", + "dev": true, + "requires": { + "inherits": "~2.0.1", + "statuses": "1" + } + }, + "http-parser-js": { + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.13.tgz", + "integrity": "sha1-O9bW/ebjFyyTNMOzO2wZPYD+ETc=", + "dev": true + }, + "http-proxy": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", + "integrity": "sha1-etOElGWPhGBeL220Q230EPTlvpo=", + "dev": true, + "requires": { + "eventemitter3": "^3.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, + "http-proxy-agent": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", + "integrity": "sha1-5IIb7vWyFCogJr1zkm/lN2McVAU=", + "dev": true, + "requires": { + "agent-base": "4", + "debug": "3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "http-signature": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "dev": true, + "requires": { + "assert-plus": "^0.2.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "httpntlm": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.6.1.tgz", + "integrity": "sha1-rQFScUOi6Hc8+uapb1hla7UqNLI=", + "dev": true, + "requires": { + "httpreq": ">=0.4.22", + "underscore": "~1.7.0" + }, + "dependencies": { + "underscore": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", + "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=", + "dev": true + } + } + }, + "httpreq": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/httpreq/-/httpreq-0.4.24.tgz", + "integrity": "sha1-QzX/2CzZaWaKOUZckprGHWOTYn8=", + "dev": true + }, + "https-proxy-agent": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", + "integrity": "sha1-UVUpcPoE1yPgTFbQQXjD+SWSu8A=", + "dev": true, + "requires": { + "agent-base": "^4.1.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.5.tgz", + "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "iconv-lite": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.11.tgz", + "integrity": "sha1-LstC/SlHRJIiCaLnxATayHk9it4=", + "dev": true + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "image-size": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", + "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=", + "dev": true, + "optional": true + }, + "imagemin": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/imagemin/-/imagemin-5.3.1.tgz", + "integrity": "sha1-8Zwu7h5xumxlWMUV+fyWaAGJptQ=", + "dev": true, + "requires": { + "file-type": "^4.1.0", + "globby": "^6.1.0", + "make-dir": "^1.0.0", + "p-pipe": "^1.1.0", + "pify": "^2.3.0", + "replace-ext": "^1.0.0" + }, + "dependencies": { + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true + } + } + }, + "imagemin-gifsicle": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/imagemin-gifsicle/-/imagemin-gifsicle-5.2.0.tgz", + "integrity": "sha1-N4FSTEV2Eu8EkWrzQkGitCv8tAo=", + "dev": true, + "optional": true, + "requires": { + "exec-buffer": "^3.0.0", + "gifsicle": "^3.0.0", + "is-gif": "^1.0.0" + } + }, + "imagemin-jpegtran": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/imagemin-jpegtran/-/imagemin-jpegtran-5.0.2.tgz", + "integrity": "sha1-5ogiY7j3kW/duABkDPddLpcNKtY=", + "dev": true, + "optional": true, + "requires": { + "exec-buffer": "^3.0.0", + "is-jpg": "^1.0.0", + "jpegtran-bin": "^3.0.0" + } + }, + "imagemin-optipng": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/imagemin-optipng/-/imagemin-optipng-5.2.1.tgz", + "integrity": "sha1-0i2kEsCfX/AKQzmWC5ioix2+hpU=", + "dev": true, + "optional": true, + "requires": { + "exec-buffer": "^3.0.0", + "is-png": "^1.0.0", + "optipng-bin": "^3.0.0" + } + }, + "imagemin-svgo": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/imagemin-svgo/-/imagemin-svgo-6.0.0.tgz", + "integrity": "sha1-LdjIKUa+Qqjiy8rjxb8Ae8K4ueg=", + "dev": true, + "optional": true, + "requires": { + "buffer-from": "^0.1.1", + "is-svg": "^2.0.0", + "svgo": "^1.0.0" + }, + "dependencies": { + "buffer-from": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-0.1.2.tgz", + "integrity": "sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg==", + "dev": true, + "optional": true + }, + "coa": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.1.tgz", + "integrity": "sha1-8/iwsVBz411wJj+xBCyywCPbOK8=", + "dev": true, + "optional": true, + "requires": { + "q": "^1.1.2" + } + }, + "colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", + "dev": true, + "optional": true + }, + "csso": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/csso/-/csso-3.5.1.tgz", + "integrity": "sha1-e564vmFiiXPBsmHhadLwJACOdYs=", + "dev": true, + "optional": true, + "requires": { + "css-tree": "1.0.0-alpha.29" + }, + "dependencies": { + "css-tree": { + "version": "1.0.0-alpha.29", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.29.tgz", + "integrity": "sha1-P6nU7zFCy9HDAedmTB81K9gvWjk=", + "dev": true, + "optional": true, + "requires": { + "mdn-data": "~1.1.0", + "source-map": "^0.5.3" + } + } + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha1-E7BM2z5sXRnfkatph6hpVhmwqnE=", + "dev": true, + "optional": true + }, + "js-yaml": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "dev": true, + "optional": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "svgo": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.1.1.tgz", + "integrity": "sha512-GBkJbnTuFpM4jFbiERHDWhZc/S/kpHToqmZag3aEBjPYK44JAN2QBjvrGIxLOoCyMZjuFQIfTO2eJd8uwLY/9g==", + "dev": true, + "optional": true, + "requires": { + "coa": "~2.0.1", + "colors": "~1.1.2", + "css-select": "^2.0.0", + "css-select-base-adapter": "~0.1.0", + "css-tree": "1.0.0-alpha.28", + "css-url-regex": "^1.1.0", + "csso": "^3.5.0", + "js-yaml": "^3.12.0", + "mkdirp": "~0.5.1", + "object.values": "^1.0.4", + "sax": "~1.2.4", + "stable": "~0.1.6", + "unquote": "~1.1.1", + "util.promisify": "~1.0.0" + } + } + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "dev": true, + "requires": { + "repeating": "^2.0.0" + } + }, + "indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", + "dev": true + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "indx": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/indx/-/indx-0.2.3.tgz", + "integrity": "sha1-Fdz1bunPZcAjTFE8J/vVgOcPvFA=", + "dev": true + }, + "inflection": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", + "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=", + "dev": true, + "optional": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha1-7uJfVtscnsYIXgwid4CD9Zar+Sc=", + "dev": true + }, + "inquirer": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.0.tgz", + "integrity": "sha512-QIEQG4YyQ2UYZGDC4srMZ7BjHOmNk1lR2JQj5UknBapklm6WHA+VVH7N+sUdX3A7NeCfGF8o4X1S3Ao7nAcIeg==", + "dev": true, + "requires": { + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.0", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.0", + "figures": "^2.0.0", + "lodash": "^4.17.10", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.1.0", + "string-width": "^2.1.0", + "strip-ansi": "^4.0.0", + "through": "^2.3.6" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "interpret": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", + "dev": true + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "requires": { + "loose-envify": "^1.0.0" + } + }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "dev": true + }, + "ip-regex": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-1.0.3.tgz", + "integrity": "sha1-3FiQdvZZ9BnCIgOaMzFvHHOH7/0=", + "dev": true, + "optional": true + }, + "irregular-plurals": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-1.4.0.tgz", + "integrity": "sha1-LKmwM2UREYVUEvFr5dd8YqRYp2Y=", + "dev": true + }, + "is": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/is/-/is-3.2.1.tgz", + "integrity": "sha1-0Kwq1V63sL7JJqUmb2xmKqqD3KU=", + "dev": true + }, + "is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha1-OV4a6EsR8mrReV5zwXN45IowFXY=", + "dev": true, + "requires": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + } + }, + "is-absolute-url": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", + "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=", + "dev": true + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=", + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "^1.0.0" + } + }, + "is-bzip2": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-bzip2/-/is-bzip2-1.0.0.tgz", + "integrity": "sha1-XuWOqlounIDiFAe+3yOuWsCRs/w=", + "dev": true + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha1-HhrfIZ4e62hNaR+dagX/DTCiTXU=", + "dev": true + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=", + "dev": true + } + } + }, + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", + "dev": true + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "requires": { + "is-primitive": "^2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-gif": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-gif/-/is-gif-1.0.0.tgz", + "integrity": "sha1-ptKumIkwB7/6l6HYwB1jIFgyCX4=", + "dev": true, + "optional": true + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + }, + "is-gzip": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-gzip/-/is-gzip-1.0.0.tgz", + "integrity": "sha1-bKiwe5nHeZgCWQDlVc7Y7YCHmoM=", + "dev": true + }, + "is-jpg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-jpg/-/is-jpg-1.0.1.tgz", + "integrity": "sha1-KW1X/dmc4BBDSnKD40armhA16XU=", + "dev": true, + "optional": true + }, + "is-my-ip-valid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", + "integrity": "sha1-ezUbjo7dTTmV1NBmaA5mTZRpaCQ=", + "dev": true, + "optional": true + }, + "is-my-json-valid": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.19.0.tgz", + "integrity": "sha512-mG0f/unGX1HZ5ep4uhRaPOS8EkAY8/j6mDRMJrutq4CqhoJWYp7qAlonIPy3TV7p3ju4TK9fo/PbnoksWmsp5Q==", + "dev": true, + "optional": true, + "requires": { + "generate-function": "^2.0.0", + "generate-object-property": "^1.1.0", + "is-my-ip-valid": "^1.0.0", + "jsonpointer": "^4.0.0", + "xtend": "^4.0.0" + } + }, + "is-natural-number": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-2.1.1.tgz", + "integrity": "sha1-fUxXKDd+84bD4ZSpkRv1fG3DNec=", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "dev": true + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha1-WsSLNF72dTOb1sekipEhELJBz1I=", + "dev": true, + "requires": { + "is-path-inside": "^1.0.0" + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "requires": { + "path-is-inside": "^1.0.1" + } + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "is-png": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-png/-/is-png-1.1.0.tgz", + "integrity": "sha1-1XSxK/J1wDUEVVcLDltXqwYgd84=", + "dev": true, + "optional": true + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "dev": true + }, + "is-redirect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", + "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", + "dev": true + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "^1.0.1" + } + }, + "is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha1-obtpNc6MXboei5dUubLcwCDiJg0=", + "dev": true, + "requires": { + "is-unc-path": "^1.0.0" + } + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha1-+xj4fOH+uSUWnJpAfBkxijIG7Yg=", + "dev": true + }, + "is-retry-allowed": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", + "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=", + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-svg": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-2.1.0.tgz", + "integrity": "sha1-z2EJDaDZ77yrhyLeum8DIgjbsOk=", + "dev": true, + "requires": { + "html-comment-regex": "^1.1.0" + } + }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.0" + } + }, + "is-tar": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-tar/-/is-tar-1.0.0.tgz", + "integrity": "sha1-L2suF5LB9bs2UZrKqdZcDSb+hT0=", + "dev": true + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha1-1zHoiY7QkKEsNSrS6u1Qla0yLJ0=", + "dev": true, + "requires": { + "unc-path-regex": "^0.1.2" + } + }, + "is-url": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha1-BKTfRtKMTP89c9Af8Gq+sxihqlI=", + "dev": true + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-valid-glob": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-0.3.0.tgz", + "integrity": "sha1-1LVcafUYhvm2XHDWwmItN+KfSP4=", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha1-0YUOuXkezRjmGCzhKjDzlmNLsZ0=", + "dev": true + }, + "is-zip": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-zip/-/is-zip-1.0.0.tgz", + "integrity": "sha1-R7Co/004p2QxzP2ZqOFaTIa6IyU=", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "isbinaryfile": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", + "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", + "dev": true, + "requires": { + "buffer-alloc": "^1.2.0" + } + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "jasmine-core": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.1.0.tgz", + "integrity": "sha1-pHheE11d9lAk38kiSVPfWFvSdmw=", + "dev": true + }, + "jpegtran-bin": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jpegtran-bin/-/jpegtran-bin-3.2.0.tgz", + "integrity": "sha1-9g7PSumZwL2tLp+83ytvCYHnops=", + "dev": true, + "optional": true, + "requires": { + "bin-build": "^2.0.0", + "bin-wrapper": "^3.0.0", + "logalot": "^2.0.0" + } + }, + "jquery": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-2.2.4.tgz", + "integrity": "sha1-LInWiJterFIqfuoywUUhVZxsvwI=" + }, + "jquery-migrate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jquery-migrate/-/jquery-migrate-1.4.0.tgz", + "integrity": "sha1-4AKOSDHMFH2PIvOCBRbr+5dReaU=" + }, + "jquery-ui-dist": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/jquery-ui-dist/-/jquery-ui-dist-1.12.1.tgz", + "integrity": "sha1-XAgV08xvkP9fqvWyaKbiO0ypBPo=" + }, + "jquery-validation": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/jquery-validation/-/jquery-validation-1.17.0.tgz", + "integrity": "sha512-XddiAwhGdWhcIJ+W3ri3KG8uTPMua4TPYuUIC8/E7lOyqdScG5xHuy9YishlKc0c/lIQai77EX7hxMdTSYCEjA==", + "requires": { + "jquery": "^1.7 || ^2.0 || ^3.1" + } + }, + "jquery-validation-unobtrusive": { + "version": "3.2.10", + "resolved": "https://registry.npmjs.org/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-3.2.10.tgz", + "integrity": "sha512-z9ZBP/HslaGNKzFSpfLNJoFm2iqPJfE6CKM0H5e9LmKnYTFxErvCFQZomOLiTmLmZi8Wi/otW38cEXExVDha0w==", + "requires": { + "jquery": ">=1.8", + "jquery-validation": ">=1.16" + } + }, + "js-base64": { + "version": "2.4.9", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.9.tgz", + "integrity": "sha512-xcinL3AuDJk7VSzsHgb9DvvIXayBbadtMZ4HFPx8rUszbW1MuNMlwYVC4zzCZ6e1sqZpnNS5ZFYOhXqA39T7LQ==", + "dev": true + }, + "js-levenshtein": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.4.tgz", + "integrity": "sha512-PxfGzSs0ztShKrUYPIn5r0MtyAhYcCwmndozzpz8YObbPnD1jFxzlBGbRnX2mIu6Z13xN6+PTu05TQFnZFlzow==", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.7.0.tgz", + "integrity": "sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A=", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^2.6.0" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true, + "optional": true + }, + "jsesc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.1.tgz", + "integrity": "sha1-5CGiqOINawgZ3yiQj3glJrlt0f4=", + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha1-afaofZUTq4u4/mO9sJecRI5oRmA=", + "dev": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true, + "requires": { + "jsonify": "~0.0.0" + } + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "json5": { + "version": "0.5.1", + "resolved": "http://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true, + "optional": true + } + } + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "jsonpointer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", + "dev": true, + "optional": true + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "karma": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/karma/-/karma-2.0.5.tgz", + "integrity": "sha1-NxDHoucbHEOTE/KDhG2I4E5PkYw=", + "dev": true, + "requires": { + "bluebird": "^3.3.0", + "body-parser": "^1.16.1", + "chokidar": "^2.0.3", + "colors": "^1.1.0", + "combine-lists": "^1.0.0", + "connect": "^3.6.0", + "core-js": "^2.2.0", + "di": "^0.0.1", + "dom-serialize": "^2.2.0", + "expand-braces": "^0.1.1", + "glob": "^7.1.1", + "graceful-fs": "^4.1.2", + "http-proxy": "^1.13.0", + "isbinaryfile": "^3.0.0", + "lodash": "^4.17.4", + "log4js": "^2.5.3", + "mime": "^1.3.4", + "minimatch": "^3.0.2", + "optimist": "^0.6.1", + "qjobs": "^1.1.4", + "range-parser": "^1.2.0", + "rimraf": "^2.6.0", + "safe-buffer": "^5.0.1", + "socket.io": "2.0.4", + "source-map": "^0.6.1", + "tmp": "0.0.33", + "useragent": "2.2.1" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha1-vLJLTzeTTZqnrBe0ra+J58du8us=", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "body-parser": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", + "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", + "dev": true, + "requires": { + "bytes": "3.0.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "~1.6.3", + "iconv-lite": "0.4.23", + "on-finished": "~2.3.0", + "qs": "6.5.2", + "raw-body": "2.3.3", + "type-is": "~1.6.16" + } + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "dev": true + }, + "chokidar": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", + "integrity": "sha1-NW/04rDo5D4yLRijckYLvPOszSY=", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.0", + "braces": "^2.3.0", + "fsevents": "^1.2.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "lodash.debounce": "^4.0.8", + "normalize-path": "^2.1.1", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0", + "upath": "^1.0.5" + } + }, + "connect": { + "version": "3.6.6", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz", + "integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=", + "dev": true, + "requires": { + "debug": "2.6.9", + "finalhandler": "1.1.0", + "parseurl": "~1.3.2", + "utils-merge": "1.0.1" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "finalhandler": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", + "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.1", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.3.1", + "unpipe": "~1.0.0" + }, + "dependencies": { + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", + "dev": true + } + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha1-KXhx9jvlB63Pv8pxXQzQ7thOmmM=", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha1-yzroBuh0BERYTvFUzo7pjUA/PjY=", + "dev": true + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", + "dev": true + }, + "raw-body": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha1-GzJOzmtXBuFThVvBFIxlu39uoMM=", + "dev": true, + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true + } + } + }, + "karma-jasmine": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-1.1.2.tgz", + "integrity": "sha1-OU8rJf+0pkS5rabyLUQ+L9CIhsM=", + "dev": true + }, + "karma-phantomjs-launcher": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/karma-phantomjs-launcher/-/karma-phantomjs-launcher-1.0.4.tgz", + "integrity": "sha1-0jyjSAG9qYY60xjju0vUBisTrNI=", + "dev": true, + "requires": { + "lodash": "^4.0.1", + "phantomjs-prebuilt": "^2.1.7" + } + }, + "kew": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/kew/-/kew-0.7.0.tgz", + "integrity": "sha1-edk9LTM2PW/dKXCzNdkUGtWR15s=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha1-ARRrNqYhjmTljzqNZt5df8b20FE=", + "dev": true + }, + "klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.9" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true, + "optional": true + } + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true + }, + "lazy-req": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/lazy-req/-/lazy-req-1.1.0.tgz", + "integrity": "sha1-va6+rTD42CQDnODOFJ1Nqge6H6w=", + "dev": true, + "optional": true + }, + "lazyload-js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazyload-js/-/lazyload-js-1.0.0.tgz", + "integrity": "sha1-jBA5sbaRec1J/cMkICOvSM4IOSU=" + }, + "lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "dev": true, + "requires": { + "readable-stream": "^2.0.5" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "less": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/less/-/less-2.7.3.tgz", + "integrity": "sha1-zBJg9RyQCp7A2R+2mYE54CUHtjs=", + "dev": true, + "requires": { + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "mime": "^1.2.11", + "mkdirp": "^0.5.0", + "promise": "^7.1.1", + "request": "2.81.0", + "source-map": "^0.5.3" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true, + "optional": true + } + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "libbase64": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-0.1.0.tgz", + "integrity": "sha1-YjUag5VjrF/1vSbxL2Dpgwu3UeY=", + "dev": true + }, + "libmime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/libmime/-/libmime-3.0.0.tgz", + "integrity": "sha1-UaGp50SOy9Ms2lRCFnW7IbwJPaY=", + "dev": true, + "requires": { + "iconv-lite": "0.4.15", + "libbase64": "0.1.0", + "libqp": "1.1.0" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", + "integrity": "sha1-/iZaIYrGpXz+hUkn6dBMGYJe3es=", + "dev": true + } + } + }, + "libqp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/libqp/-/libqp-1.1.0.tgz", + "integrity": "sha1-9ebgatdLeU+1tbZpiL9yjvHe2+g=", + "dev": true + }, + "liftoff": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", + "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", + "dev": true, + "requires": { + "extend": "^3.0.0", + "findup-sync": "^2.0.0", + "fined": "^1.0.1", + "flagged-respawn": "^1.0.0", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.0", + "rechoir": "^0.6.2", + "resolve": "^1.1.7" + } + }, + "livereload-js": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.3.0.tgz", + "integrity": "sha1-w6si6Kr1vzUF2A0JjLrWdyZUjJo=", + "dev": true + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + } + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", + "dev": true + }, + "lodash._basetostring": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", + "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", + "dev": true + }, + "lodash._basevalues": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", + "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", + "dev": true + }, + "lodash._escapehtmlchar": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._escapehtmlchar/-/lodash._escapehtmlchar-2.4.1.tgz", + "integrity": "sha1-32fDu2t+jh6DGrSL+geVuSr+iZ0=", + "dev": true, + "requires": { + "lodash._htmlescapes": "~2.4.1" + } + }, + "lodash._escapestringchar": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._escapestringchar/-/lodash._escapestringchar-2.4.1.tgz", + "integrity": "sha1-7P4iYYoq3lC/7qQ5N+Ud9m8O23I=", + "dev": true + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", + "dev": true + }, + "lodash._htmlescapes": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz", + "integrity": "sha1-MtFL8IRLbeb4tioFG09nwii2JMs=", + "dev": true + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", + "dev": true + }, + "lodash._isnative": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", + "integrity": "sha1-PqZAS3hKe+g2x7V1gOHN95sUgyw=", + "dev": true + }, + "lodash._objecttypes": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz", + "integrity": "sha1-fAt/admKH3ZSn4kLDNsbTf7BHBE=", + "dev": true + }, + "lodash._reescape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", + "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", + "dev": true + }, + "lodash._reevaluate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", + "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", + "dev": true + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true + }, + "lodash._reunescapedhtml": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz", + "integrity": "sha1-dHxPxAED6zu4oJduVx96JlnpO6c=", + "dev": true, + "requires": { + "lodash._htmlescapes": "~2.4.1", + "lodash.keys": "~2.4.1" + }, + "dependencies": { + "lodash.keys": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", + "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", + "dev": true, + "requires": { + "lodash._isnative": "~2.4.1", + "lodash._shimkeys": "~2.4.1", + "lodash.isobject": "~2.4.1" + } + } + } + }, + "lodash._root": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", + "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", + "dev": true + }, + "lodash._shimkeys": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", + "integrity": "sha1-bpzJZm/wgfC1psl4uD4kLmlJ0gM=", + "dev": true, + "requires": { + "lodash._objecttypes": "~2.4.1" + } + }, + "lodash.clone": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", + "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=", + "dev": true + }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", + "dev": true + }, + "lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=", + "dev": true + }, + "lodash.escape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", + "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", + "dev": true, + "requires": { + "lodash._root": "^3.0.0" + } + }, + "lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", + "dev": true + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", + "dev": true + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", + "dev": true + }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", + "dev": true + }, + "lodash.isobject": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", + "integrity": "sha1-Wi5H/mmVPx7mMafrof5k0tBlWPU=", + "dev": true, + "requires": { + "lodash._objecttypes": "~2.4.1" + } + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "dev": true, + "requires": { + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" + } + }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", + "dev": true + }, + "lodash.merge": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.1.tgz", + "integrity": "sha1-rcJdnLmbk5HFliTzefu6YNcRHVQ=", + "dev": true + }, + "lodash.partialright": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/lodash.partialright/-/lodash.partialright-4.2.1.tgz", + "integrity": "sha1-ATDYDoM2MmTUAHTzKbij56ihzEs=", + "dev": true + }, + "lodash.pick": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", + "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=", + "dev": true + }, + "lodash.restparam": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", + "dev": true + }, + "lodash.template": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", + "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", + "dev": true, + "requires": { + "lodash._basecopy": "^3.0.0", + "lodash._basetostring": "^3.0.0", + "lodash._basevalues": "^3.0.0", + "lodash._isiterateecall": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0", + "lodash.keys": "^3.0.0", + "lodash.restparam": "^3.0.0", + "lodash.templatesettings": "^3.0.0" + } + }, + "lodash.templatesettings": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", + "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", + "dev": true, + "requires": { + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0" + } + }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", + "dev": true + }, + "lodash.values": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.values/-/lodash.values-2.4.1.tgz", + "integrity": "sha1-q/UUQ2s8twUAFieXjLzzCxKA7qQ=", + "dev": true, + "requires": { + "lodash.keys": "~2.4.1" + }, + "dependencies": { + "lodash.keys": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", + "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", + "dev": true, + "requires": { + "lodash._isnative": "~2.4.1", + "lodash._shimkeys": "~2.4.1", + "lodash.isobject": "~2.4.1" + } + } + } + }, + "log4js": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-2.11.0.tgz", + "integrity": "sha1-vzkC7/ZcaSPZzpz70ttUFg40AFo=", + "dev": true, + "requires": { + "amqplib": "^0.5.2", + "axios": "^0.15.3", + "circular-json": "^0.5.4", + "date-format": "^1.2.0", + "debug": "^3.1.0", + "hipchat-notifier": "^1.1.0", + "loggly": "^1.1.0", + "mailgun-js": "^0.18.0", + "nodemailer": "^2.5.0", + "redis": "^2.7.1", + "semver": "^5.5.0", + "slack-node": "~0.2.0", + "streamroller": "0.7.0" + }, + "dependencies": { + "circular-json": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.7.tgz", + "integrity": "sha512-/pXoV1JA847qRKPrHbBK6YIBGFF8GOP4wzSgUOA7q0ew0vAv0iJswP+2/nZQ9uzA3Azi7eTrg9L2yzXc/7ZMIA==", + "dev": true + }, + "debug": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.5.tgz", + "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "semver": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", + "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==", + "dev": true + } + } + }, + "logalot": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/logalot/-/logalot-2.1.0.tgz", + "integrity": "sha1-X46MkNME7fElMJUaVVSruMXj9VI=", + "dev": true, + "optional": true, + "requires": { + "figures": "^1.3.5", + "squeak": "^1.0.0" + }, + "dependencies": { + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "optional": true, + "requires": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + } + } + } + }, + "loggly": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/loggly/-/loggly-1.1.1.tgz", + "integrity": "sha1-Cg/B0/o6XsRP3HuJe+uipGlc6+4=", + "dev": true, + "optional": true, + "requires": { + "json-stringify-safe": "5.0.x", + "request": "2.75.x", + "timespan": "2.3.x" + }, + "dependencies": { + "bl": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.1.2.tgz", + "integrity": "sha1-/cqHGplxOqANGeO7ukHER4emU5g=", + "dev": true, + "optional": true, + "requires": { + "readable-stream": "~2.0.5" + } + }, + "caseless": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", + "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", + "dev": true, + "optional": true + }, + "commander": { + "version": "2.18.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.18.0.tgz", + "integrity": "sha512-6CYPa+JP2ftfRU2qkDK+UTVeQYosOg/2GbcjIcKPHfinyOLPVGXu/ovN86RP49Re5ndJK1N0kuiidFFuepc4ZQ==", + "dev": true, + "optional": true + }, + "form-data": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.0.0.tgz", + "integrity": "sha1-bwrrrcxdoWwT4ezBETfYX5uIOyU=", + "dev": true, + "optional": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.5", + "mime-types": "^2.1.11" + } + }, + "har-validator": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", + "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", + "dev": true, + "optional": true, + "requires": { + "chalk": "^1.1.1", + "commander": "^2.9.0", + "is-my-json-valid": "^2.12.4", + "pinkie-promise": "^2.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true, + "optional": true + }, + "node-uuid": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", + "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=", + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true, + "optional": true + }, + "qs": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.3.tgz", + "integrity": "sha1-HPyyXBCpsrSDBT/zn138kjOQjP4=", + "dev": true, + "optional": true + }, + "readable-stream": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "dev": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~0.10.x", + "util-deprecate": "~1.0.1" + } + }, + "request": { + "version": "2.75.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.75.0.tgz", + "integrity": "sha1-0rgmiihtoT6qXQGt9dGMyQ9lfZM=", + "dev": true, + "optional": true, + "requires": { + "aws-sign2": "~0.6.0", + "aws4": "^1.2.1", + "bl": "~1.1.2", + "caseless": "~0.11.0", + "combined-stream": "~1.0.5", + "extend": "~3.0.0", + "forever-agent": "~0.6.1", + "form-data": "~2.0.0", + "har-validator": "~2.0.6", + "hawk": "~3.1.3", + "http-signature": "~1.1.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.7", + "node-uuid": "~1.4.7", + "oauth-sign": "~0.8.1", + "qs": "~6.2.0", + "stringstream": "~0.0.4", + "tough-cookie": "~2.3.0", + "tunnel-agent": "~0.4.1" + } + } + } + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "dev": true + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "dev": true, + "requires": { + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" + } + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha1-b54wtHCE2XGnyCD/FabFFnt0wm8=", + "dev": true + }, + "lpad-align": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/lpad-align/-/lpad-align-1.1.2.tgz", + "integrity": "sha1-IfYArBwwlcPG5JfuZyce4ISB/p4=", + "dev": true, + "optional": true, + "requires": { + "get-stdin": "^4.0.1", + "indent-string": "^2.1.0", + "longest": "^1.0.0", + "meow": "^3.3.0" + } + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "mailcomposer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/mailcomposer/-/mailcomposer-4.0.1.tgz", + "integrity": "sha1-DhxEsqB890DuF9wUm6AJ8Zyt/rQ=", + "dev": true, + "optional": true, + "requires": { + "buildmail": "4.0.1", + "libmime": "3.0.0" + } + }, + "mailgun-js": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/mailgun-js/-/mailgun-js-0.18.1.tgz", + "integrity": "sha1-7jmqGNe7WYpc6e3oSvtoHe/IprA=", + "dev": true, + "optional": true, + "requires": { + "async": "~2.6.0", + "debug": "~3.1.0", + "form-data": "~2.3.0", + "inflection": "~1.12.0", + "is-stream": "^1.1.0", + "path-proxy": "~1.0.0", + "promisify-call": "^2.0.2", + "proxy-agent": "~3.0.0", + "tsscmp": "~1.0.0" + }, + "dependencies": { + "combined-stream": { + "version": "1.0.6", + "resolved": "http://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "dev": true, + "optional": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "form-data": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "dev": true, + "optional": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "1.0.6", + "mime-types": "^2.1.12" + } + } + } + }, + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha1-ecEDO4BRW9bSTsmTPoYMp17ifww=", + "dev": true, + "requires": { + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "make-iterator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha1-KbM/MSqo9UfEpeSQ9Wr87JkTOtY=", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + }, + "map-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", + "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, + "marked": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.2.tgz", + "integrity": "sha1-AV2xWIZEOPJKZL3WGgQotBhwbQk=", + "dev": true + }, + "math-expression-evaluator": { + "version": "1.2.17", + "resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz", + "integrity": "sha1-3oGf282E3M2PrlnGrreWFbnSZqw=", + "dev": true + }, + "math-random": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz", + "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=", + "dev": true + }, + "mdn-data": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-1.1.4.tgz", + "integrity": "sha1-ULXU/8RXUnZXPE7tuHgIEqhBnwE=", + "dev": true + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true + }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "dev": true, + "requires": { + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "merge-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", + "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", + "dev": true, + "requires": { + "readable-stream": "^2.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha1-sRwn2IuP8fvgcGQ8+UsMea4bCq8=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "method-override": { + "version": "2.3.10", + "resolved": "https://registry.npmjs.org/method-override/-/method-override-2.3.10.tgz", + "integrity": "sha1-49r41d7hDdLc59SuiNYrvud0drQ=", + "dev": true, + "requires": { + "debug": "2.6.9", + "methods": "~1.1.2", + "parseurl": "~1.3.2", + "vary": "~1.1.2" + }, + "dependencies": { + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true + } + } + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha1-cIWbyVyYQJUvNZoGij/En57PrCM=", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "mime": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", + "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=", + "dev": true + }, + "mime-db": { + "version": "1.36.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz", + "integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw==", + "dev": true + }, + "mime-types": { + "version": "2.1.20", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz", + "integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==", + "dev": true, + "requires": { + "mime-db": "~1.36.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha1-ggyGo5M0ZA6ZUWkovQP8qIBX0CI=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mixin-deep": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha1-pJ5yaNzhoNlpjkUybFYm3zVD0P4=", + "dev": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "moment": { + "version": "2.10.6", + "resolved": "http://registry.npmjs.org/moment/-/moment-2.10.6.tgz", + "integrity": "sha1-bLIZZ8ecunsMpeZmRPFzZis++nc=" + }, + "morgan": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.6.1.tgz", + "integrity": "sha1-X9gYOYxoGcuiinzWZk8pL+HAu/I=", + "dev": true, + "requires": { + "basic-auth": "~1.0.3", + "debug": "~2.2.0", + "depd": "~1.0.1", + "on-finished": "~2.3.0", + "on-headers": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "multiparty": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/multiparty/-/multiparty-3.3.2.tgz", + "integrity": "sha1-Nd5oBNwZZD5SSfPT473GyM4wHT8=", + "dev": true, + "requires": { + "readable-stream": "~1.1.9", + "stream-counter": "~0.2.0" + } + }, + "multipipe": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", + "dev": true, + "requires": { + "duplexer2": "0.0.2" + } + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "nan": { + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.11.1.tgz", + "integrity": "sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA==", + "dev": true, + "optional": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, + "natives": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.5.tgz", + "integrity": "sha512-1pJ+02gl2KJgCPFtpZGtuD4lGSJnIZvvFHCQTOeDRMSXjfu2GmYWuhI8NFMA4W2I5NNFRbfy/YCiVt4CgNpP8A==", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "negotiator": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.5.3.tgz", + "integrity": "sha1-Jp1cR2gQ7JLtvntsLygxY4T5p+g=", + "dev": true + }, + "netmask": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz", + "integrity": "sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU=", + "dev": true, + "optional": true + }, + "ng-file-upload": { + "version": "12.2.13", + "resolved": "https://registry.npmjs.org/ng-file-upload/-/ng-file-upload-12.2.13.tgz", + "integrity": "sha1-AYAPOHLlJvlTEPhHfpnk8S0NjRQ=" + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node-fs": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/node-fs/-/node-fs-0.1.7.tgz", + "integrity": "sha1-MjI8zLRsn78PwRgS1FAhzDHTJbs=", + "dev": true + }, + "node-releases": { + "version": "1.0.0-alpha.12", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.0.0-alpha.12.tgz", + "integrity": "sha512-VPB4rTPqpVyWKBHbSa4YPFme3+8WHsOSpvbp0Mfj0bWsC8TEjt4HQrLl1hsBDELlp1nB4lflSgSuGTYiuyaP7Q==", + "dev": true, + "requires": { + "semver": "^5.3.0" + }, + "dependencies": { + "semver": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", + "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==", + "dev": true + } + } + }, + "node-status-codes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-status-codes/-/node-status-codes-1.0.0.tgz", + "integrity": "sha1-WuVUHQJGRdMqWPzdyc7s6nrjrC8=", + "dev": true + }, + "node.extend": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/node.extend/-/node.extend-1.1.6.tgz", + "integrity": "sha1-p7iCyC1sk6SGOlUEvV3o7IYli5Y=", + "dev": true, + "requires": { + "is": "^3.1.0" + } + }, + "nodemailer": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-2.7.2.tgz", + "integrity": "sha1-8kLmSa7q45tsftdA73sGHEBNMPk=", + "dev": true, + "optional": true, + "requires": { + "libmime": "3.0.0", + "mailcomposer": "4.0.1", + "nodemailer-direct-transport": "3.3.2", + "nodemailer-shared": "1.1.0", + "nodemailer-smtp-pool": "2.8.2", + "nodemailer-smtp-transport": "2.7.2", + "socks": "1.1.9" + }, + "dependencies": { + "smart-buffer": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-1.1.15.tgz", + "integrity": "sha1-fxFLW2X6s+KjWqd1uxLw0cZJvxY=", + "dev": true, + "optional": true + }, + "socks": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/socks/-/socks-1.1.9.tgz", + "integrity": "sha1-Yo1+TQSRJDVEWsC25Fk3bLPm1pE=", + "dev": true, + "optional": true, + "requires": { + "ip": "^1.1.2", + "smart-buffer": "^1.0.4" + } + } + } + }, + "nodemailer-direct-transport": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/nodemailer-direct-transport/-/nodemailer-direct-transport-3.3.2.tgz", + "integrity": "sha1-6W+vuQNYVglH5WkBfZfmBzilCoY=", + "dev": true, + "optional": true, + "requires": { + "nodemailer-shared": "1.1.0", + "smtp-connection": "2.12.0" + } + }, + "nodemailer-fetch": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/nodemailer-fetch/-/nodemailer-fetch-1.6.0.tgz", + "integrity": "sha1-ecSQihwPXzdbc/6IjamCj23JY6Q=", + "dev": true + }, + "nodemailer-shared": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", + "integrity": "sha1-z1mU4v0mjQD1zw+nZ6CBae2wfsA=", + "dev": true, + "requires": { + "nodemailer-fetch": "1.6.0" + } + }, + "nodemailer-smtp-pool": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/nodemailer-smtp-pool/-/nodemailer-smtp-pool-2.8.2.tgz", + "integrity": "sha1-LrlNbPhXgLG0clzoU7nL1ejajHI=", + "dev": true, + "optional": true, + "requires": { + "nodemailer-shared": "1.1.0", + "nodemailer-wellknown": "0.1.10", + "smtp-connection": "2.12.0" + } + }, + "nodemailer-smtp-transport": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/nodemailer-smtp-transport/-/nodemailer-smtp-transport-2.7.2.tgz", + "integrity": "sha1-A9ccdjFPFKx9vHvwM6am0W1n+3c=", + "dev": true, + "optional": true, + "requires": { + "nodemailer-shared": "1.1.0", + "nodemailer-wellknown": "0.1.10", + "smtp-connection": "2.12.0" + } + }, + "nodemailer-wellknown": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/nodemailer-wellknown/-/nodemailer-wellknown-0.1.10.tgz", + "integrity": "sha1-WG24EB2zDLRDjrVGc3pBqtDPE9U=", + "dev": true + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "requires": { + "abbrev": "1" + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha1-EvlaMH1YNSB1oEkHuErIvpisAS8=", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", + "dev": true + }, + "normalize-url": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", + "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", + "dev": true, + "requires": { + "object-assign": "^4.0.1", + "prepend-http": "^1.0.0", + "query-string": "^4.1.0", + "sort-keys": "^1.0.0" + } + }, + "npm": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/npm/-/npm-6.4.1.tgz", + "integrity": "sha512-mXJL1NTVU136PtuopXCUQaNWuHlXCTp4McwlSW8S9/Aj8OEPAlSBgo8og7kJ01MjCDrkmqFQTvN5tTEhBMhXQg==", + "requires": { + "JSONStream": "^1.3.4", + "abbrev": "~1.1.1", + "ansicolors": "~0.3.2", + "ansistyles": "~0.1.3", + "aproba": "~1.2.0", + "archy": "~1.0.0", + "bin-links": "^1.1.2", + "bluebird": "~3.5.1", + "byte-size": "^4.0.3", + "cacache": "^11.2.0", + "call-limit": "~1.1.0", + "chownr": "~1.0.1", + "ci-info": "^1.4.0", + "cli-columns": "^3.1.2", + "cli-table3": "^0.5.0", + "cmd-shim": "~2.0.2", + "columnify": "~1.5.4", + "config-chain": "~1.1.11", + "debuglog": "*", + "detect-indent": "~5.0.0", + "detect-newline": "^2.1.0", + "dezalgo": "~1.0.3", + "editor": "~1.0.0", + "figgy-pudding": "^3.4.1", + "find-npm-prefix": "^1.0.2", + "fs-vacuum": "~1.2.10", + "fs-write-stream-atomic": "~1.0.10", + "gentle-fs": "^2.0.1", + "glob": "~7.1.2", + "graceful-fs": "~4.1.11", + "has-unicode": "~2.0.1", + "hosted-git-info": "^2.7.1", + "iferr": "^1.0.2", + "imurmurhash": "*", + "inflight": "~1.0.6", + "inherits": "~2.0.3", + "ini": "^1.3.5", + "init-package-json": "^1.10.3", + "is-cidr": "^2.0.6", + "json-parse-better-errors": "^1.0.2", + "lazy-property": "~1.0.0", + "libcipm": "^2.0.2", + "libnpmhook": "^4.0.1", + "libnpx": "^10.2.0", + "lock-verify": "^2.0.2", + "lockfile": "^1.0.4", + "lodash._baseindexof": "*", + "lodash._baseuniq": "~4.6.0", + "lodash._bindcallback": "*", + "lodash._cacheindexof": "*", + "lodash._createcache": "*", + "lodash._getnative": "*", + "lodash.clonedeep": "~4.5.0", + "lodash.restparam": "*", + "lodash.union": "~4.6.0", + "lodash.uniq": "~4.5.0", + "lodash.without": "~4.4.0", + "lru-cache": "^4.1.3", + "meant": "~1.0.1", + "mississippi": "^3.0.0", + "mkdirp": "~0.5.1", + "move-concurrently": "^1.0.1", + "node-gyp": "^3.8.0", + "nopt": "~4.0.1", + "normalize-package-data": "~2.4.0", + "npm-audit-report": "^1.3.1", + "npm-cache-filename": "~1.0.2", + "npm-install-checks": "~3.0.0", + "npm-lifecycle": "^2.1.0", + "npm-package-arg": "^6.1.0", + "npm-packlist": "^1.1.11", + "npm-pick-manifest": "^2.1.0", + "npm-profile": "^3.0.2", + "npm-registry-client": "^8.6.0", + "npm-registry-fetch": "^1.1.0", + "npm-user-validate": "~1.0.0", + "npmlog": "~4.1.2", + "once": "~1.4.0", + "opener": "^1.5.0", + "osenv": "^0.1.5", + "pacote": "^8.1.6", + "path-is-inside": "~1.0.2", + "promise-inflight": "~1.0.1", + "qrcode-terminal": "^0.12.0", + "query-string": "^6.1.0", + "qw": "~1.0.1", + "read": "~1.0.7", + "read-cmd-shim": "~1.0.1", + "read-installed": "~4.0.3", + "read-package-json": "^2.0.13", + "read-package-tree": "^5.2.1", + "readable-stream": "^2.3.6", + "readdir-scoped-modules": "*", + "request": "^2.88.0", + "retry": "^0.12.0", + "rimraf": "~2.6.2", + "safe-buffer": "^5.1.2", + "semver": "^5.5.0", + "sha": "~2.0.1", + "slide": "~1.1.6", + "sorted-object": "~2.0.1", + "sorted-union-stream": "~2.1.3", + "ssri": "^6.0.0", + "stringify-package": "^1.0.0", + "tar": "^4.4.6", + "text-table": "~0.2.0", + "tiny-relative-date": "^1.3.0", + "uid-number": "0.0.6", + "umask": "~1.1.0", + "unique-filename": "~1.1.0", + "unpipe": "~1.0.0", + "update-notifier": "^2.5.0", + "uuid": "^3.3.2", + "validate-npm-package-license": "^3.0.4", + "validate-npm-package-name": "~3.0.0", + "which": "^1.3.1", + "worker-farm": "^1.6.0", + "write-file-atomic": "^2.3.0" + }, + "dependencies": { + "JSONStream": { + "version": "1.3.4", + "resolved": false, + "integrity": "sha512-Y7vfi3I5oMOYIr+WxV8NZxDSwcbNgzdKYsTNInmycOq9bUYwGg9ryu57Wg5NLmCjqdFPNUmpMBo3kSJN9tCbXg==", + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + } + }, + "abbrev": { + "version": "1.1.1", + "resolved": false, + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "agent-base": { + "version": "4.2.0", + "resolved": false, + "integrity": "sha512-c+R/U5X+2zz2+UCrCFv6odQzJdoqI+YecuhnAJLa1zYaMc13zPfwMwZrr91Pd1DYNo/yPRbiM4WVf9whgwFsIg==", + "requires": { + "es6-promisify": "^5.0.0" + } + }, + "agentkeepalive": { + "version": "3.4.1", + "resolved": false, + "integrity": "sha512-MPIwsZU9PP9kOrZpyu2042kYA8Fdt/AedQYkYXucHgF9QoD9dXVp0ypuGnHXSR0hTstBxdt85Xkh4JolYfK5wg==", + "requires": { + "humanize-ms": "^1.2.1" + } + }, + "ajv": { + "version": "5.5.2", + "resolved": false, + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "requires": { + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" + } + }, + "ansi-align": { + "version": "2.0.0", + "resolved": false, + "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", + "requires": { + "string-width": "^2.0.0" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": false, + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": false, + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "ansicolors": { + "version": "0.3.2", + "resolved": false, + "integrity": "sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=" + }, + "ansistyles": { + "version": "0.1.3", + "resolved": false, + "integrity": "sha1-XeYEFb2gcbs3EnhUyGT0GyMlRTk=" + }, + "aproba": { + "version": "1.2.0", + "resolved": false, + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "archy": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=" + }, + "are-we-there-yet": { + "version": "1.1.4", + "resolved": false, + "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "asap": { + "version": "2.0.6", + "resolved": false, + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + }, + "asn1": { + "version": "0.2.4", + "resolved": false, + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "asynckit": { + "version": "0.4.0", + "resolved": false, + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": false, + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.8.0", + "resolved": false, + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "optional": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "bin-links": { + "version": "1.1.2", + "resolved": false, + "integrity": "sha512-8eEHVgYP03nILphilltWjeIjMbKyJo3wvp9K816pHbhP301ismzw15mxAAEVQ/USUwcP++1uNrbERbp8lOA6Fg==", + "requires": { + "bluebird": "^3.5.0", + "cmd-shim": "^2.0.2", + "gentle-fs": "^2.0.0", + "graceful-fs": "^4.1.11", + "write-file-atomic": "^2.3.0" + } + }, + "block-stream": { + "version": "0.0.9", + "resolved": false, + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "requires": { + "inherits": "~2.0.0" + } + }, + "bluebird": { + "version": "3.5.1", + "resolved": false, + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" + }, + "boxen": { + "version": "1.3.0", + "resolved": false, + "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==", + "requires": { + "ansi-align": "^2.0.0", + "camelcase": "^4.0.0", + "chalk": "^2.0.1", + "cli-boxes": "^1.0.0", + "string-width": "^2.0.0", + "term-size": "^1.2.0", + "widest-line": "^2.0.0" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": false, + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer-from": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha512-83apNb8KK0Se60UE1+4Ukbe3HbfELJ6UlI4ldtOGs7So4KD26orJM8hIY9lxdzP+UpItH1Yh/Y8GUvNFWFFRxA==" + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": false, + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" + }, + "builtins": { + "version": "1.0.3", + "resolved": false, + "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=" + }, + "byline": { + "version": "5.0.0", + "resolved": false, + "integrity": "sha1-dBxSFkaOrcRXsDQQEYrXfejB3bE=" + }, + "byte-size": { + "version": "4.0.3", + "resolved": false, + "integrity": "sha512-JGC3EV2bCzJH/ENSh3afyJrH4vwxbHTuO5ljLoI5+2iJOcEpMgP8T782jH9b5qGxf2mSUIp1lfGnfKNrRHpvVg==" + }, + "cacache": { + "version": "11.2.0", + "resolved": false, + "integrity": "sha512-IFWl6lfK6wSeYCHUXh+N1lY72UDrpyrYQJNIVQf48paDuWbv5RbAtJYf/4gUQFObTCHZwdZ5sI8Iw7nqwP6nlQ==", + "requires": { + "bluebird": "^3.5.1", + "chownr": "^1.0.1", + "figgy-pudding": "^3.1.0", + "glob": "^7.1.2", + "graceful-fs": "^4.1.11", + "lru-cache": "^4.1.3", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.2", + "ssri": "^6.0.0", + "unique-filename": "^1.1.0", + "y18n": "^4.0.0" + } + }, + "call-limit": { + "version": "1.1.0", + "resolved": false, + "integrity": "sha1-b9YbA/PaQqLNDsK2DwK9DnGZH+o=" + }, + "camelcase": { + "version": "4.1.0", + "resolved": false, + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + }, + "capture-stack-trace": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=" + }, + "caseless": { + "version": "0.12.0", + "resolved": false, + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "chalk": { + "version": "2.4.1", + "resolved": false, + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chownr": { + "version": "1.0.1", + "resolved": false, + "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=" + }, + "ci-info": { + "version": "1.4.0", + "resolved": false, + "integrity": "sha512-Oqmw2pVfCl8sCL+1QgMywPfdxPJPkC51y4usw0iiE2S9qnEOAqXy8bwl1CpMpnoU39g4iKJTz6QZj+28FvOnjQ==" + }, + "cidr-regex": { + "version": "2.0.9", + "resolved": false, + "integrity": "sha512-F7/fBRUU45FnvSPjXdpIrc++WRSBdCiSTlyq4ZNhLKOlHFNWgtzZ0Fd+zrqI/J1j0wmlx/f5ZQDmD2GcbrNcmw==", + "requires": { + "ip-regex": "^2.1.0" + } + }, + "cli-boxes": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=" + }, + "cli-columns": { + "version": "3.1.2", + "resolved": false, + "integrity": "sha1-ZzLZcpee/CrkRKHwjgj6E5yWoY4=", + "requires": { + "string-width": "^2.0.0", + "strip-ansi": "^3.0.1" + } + }, + "cli-table3": { + "version": "0.5.0", + "resolved": false, + "integrity": "sha512-c7YHpUyO1SaKaO7kYtxd5NZ8FjAmSK3LpKkuzdwn+2CwpFxBpdoQLm+OAnnCfoEl7onKhN9PKQi1lsHuAIUqGQ==", + "requires": { + "colors": "^1.1.2", + "object-assign": "^4.1.0", + "string-width": "^2.1.1" + } + }, + "cliui": { + "version": "4.1.0", + "resolved": false, + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": false, + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": false, + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "clone": { + "version": "1.0.4", + "resolved": false, + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" + }, + "cmd-shim": { + "version": "2.0.2", + "resolved": false, + "integrity": "sha1-b8vamUg6j9FdfTChlspp1oii79s=", + "requires": { + "graceful-fs": "^4.1.2", + "mkdirp": "~0.5.0" + } + }, + "co": { + "version": "4.6.0", + "resolved": false, + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": false, + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "color-convert": { + "version": "1.9.1", + "resolved": false, + "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", + "requires": { + "color-name": "^1.1.1" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": false, + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "colors": { + "version": "1.1.2", + "resolved": false, + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", + "optional": true + }, + "columnify": { + "version": "1.5.4", + "resolved": false, + "integrity": "sha1-Rzfd8ce2mop8NAVweC6UfuyOeLs=", + "requires": { + "strip-ansi": "^3.0.0", + "wcwidth": "^1.0.0" + } + }, + "combined-stream": { + "version": "1.0.6", + "resolved": false, + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": false, + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "1.6.2", + "resolved": false, + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "config-chain": { + "version": "1.1.11", + "resolved": false, + "integrity": "sha1-q6CXR9++TD5w52am5BWG4YWfxvI=", + "requires": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "configstore": { + "version": "3.1.2", + "resolved": false, + "integrity": "sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==", + "requires": { + "dot-prop": "^4.1.0", + "graceful-fs": "^4.1.2", + "make-dir": "^1.0.0", + "unique-string": "^1.0.0", + "write-file-atomic": "^2.0.0", + "xdg-basedir": "^3.0.0" + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": false, + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": false, + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + }, + "dependencies": { + "iferr": { + "version": "0.1.5", + "resolved": false, + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=" + } + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "create-error-class": { + "version": "3.0.2", + "resolved": false, + "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", + "requires": { + "capture-stack-trace": "^1.0.0" + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": false, + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "crypto-random-string": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=" + }, + "cyclist": { + "version": "0.2.2", + "resolved": false, + "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=" + }, + "dashdash": { + "version": "1.14.1", + "resolved": false, + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "debug": { + "version": "3.1.0", + "resolved": false, + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": false, + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "debuglog": { + "version": "1.0.1", + "resolved": false, + "integrity": "sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=" + }, + "decamelize": { + "version": "1.2.0", + "resolved": false, + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": false, + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + }, + "deep-extend": { + "version": "0.5.1", + "resolved": false, + "integrity": "sha512-N8vBdOa+DF7zkRrDCsaOXoCs/E2fJfx9B9MrKnnSiHNh4ws7eSys6YQE4KvT1cecKmOASYQBhbKjeuDD9lT81w==" + }, + "defaults": { + "version": "1.0.3", + "resolved": false, + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "requires": { + "clone": "^1.0.2" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "delegates": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "detect-indent": { + "version": "5.0.0", + "resolved": false, + "integrity": "sha1-OHHMCmoALow+Wzz38zYmRnXwa50=" + }, + "detect-newline": { + "version": "2.1.0", + "resolved": false, + "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=" + }, + "dezalgo": { + "version": "1.0.3", + "resolved": false, + "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=", + "requires": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, + "dot-prop": { + "version": "4.2.0", + "resolved": false, + "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", + "requires": { + "is-obj": "^1.0.0" + } + }, + "dotenv": { + "version": "5.0.1", + "resolved": false, + "integrity": "sha512-4As8uPrjfwb7VXC+WnLCbXK7y+Ueb2B3zgNCePYfhxS1PYeaO1YTeplffTEcbfLhvFNGLAz90VvJs9yomG7bow==" + }, + "duplexer3": { + "version": "0.1.4", + "resolved": false, + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + }, + "duplexify": { + "version": "3.6.0", + "resolved": false, + "integrity": "sha512-fO3Di4tBKJpYTFHAxTU00BcfWMY9w24r/x21a6rZRbsD/ToUgGxsMbiGRmB7uVAXeGKXD9MwiLZa5E97EVgIRQ==", + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": false, + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "optional": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "editor": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-YMf4e9YrzGqJT6jM1q+3gjok90I=" + }, + "encoding": { + "version": "0.1.12", + "resolved": false, + "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "requires": { + "iconv-lite": "~0.4.13" + } + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": false, + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "requires": { + "once": "^1.4.0" + } + }, + "err-code": { + "version": "1.1.2", + "resolved": false, + "integrity": "sha1-BuARbTAo9q70gGhJ6w6mp0iuaWA=" + }, + "errno": { + "version": "0.1.7", + "resolved": false, + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "requires": { + "prr": "~1.0.1" + } + }, + "es6-promise": { + "version": "4.2.4", + "resolved": false, + "integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==" + }, + "es6-promisify": { + "version": "5.0.0", + "resolved": false, + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "requires": { + "es6-promise": "^4.0.3" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": false, + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "execa": { + "version": "0.7.0", + "resolved": false, + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "extend": { + "version": "3.0.2", + "resolved": false, + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extsprintf": { + "version": "1.3.0", + "resolved": false, + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": false, + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": false, + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "figgy-pudding": { + "version": "3.4.1", + "resolved": false, + "integrity": "sha512-j1SAT641cerGuOvoSBoaE9LbSzh1N/E5ufk9oMpOKuyK8MyW3sGg4rh+4qhLmVTEAzipO5XTHYT4gjb6JYLE8g==" + }, + "find-npm-prefix": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha512-KEftzJ+H90x6pcKtdXZEPsQse8/y/UnvzRKrOSQFprnrGaFuJ62fVkP34Iu2IYuMvyauCyoLTNkJZgrrGA2wkA==" + }, + "find-up": { + "version": "2.1.0", + "resolved": false, + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "requires": { + "locate-path": "^2.0.0" + } + }, + "flush-write-stream": { + "version": "1.0.3", + "resolved": false, + "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==", + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.4" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": false, + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.2", + "resolved": false, + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "1.0.6", + "mime-types": "^2.1.12" + } + }, + "from2": { + "version": "2.3.0", + "resolved": false, + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "fs-minipass": { + "version": "1.2.5", + "resolved": false, + "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", + "requires": { + "minipass": "^2.2.1" + } + }, + "fs-vacuum": { + "version": "1.2.10", + "resolved": false, + "integrity": "sha1-t2Kb7AekAxolSP35n17PHMizHjY=", + "requires": { + "graceful-fs": "^4.1.2", + "path-is-inside": "^1.0.1", + "rimraf": "^2.5.2" + } + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": false, + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + }, + "dependencies": { + "iferr": { + "version": "0.1.5", + "resolved": false, + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=" + } + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fstream": { + "version": "1.0.11", + "resolved": false, + "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", + "requires": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + } + }, + "gauge": { + "version": "2.7.4", + "resolved": false, + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "genfun": { + "version": "4.0.1", + "resolved": false, + "integrity": "sha1-7RAEHy5KfxsKOEZtF6XD4n3x38E=" + }, + "gentle-fs": { + "version": "2.0.1", + "resolved": false, + "integrity": "sha512-cEng5+3fuARewXktTEGbwsktcldA+YsnUEaXZwcK/3pjSE1X9ObnTs+/8rYf8s+RnIcQm2D5x3rwpN7Zom8Bew==", + "requires": { + "aproba": "^1.1.2", + "fs-vacuum": "^1.2.10", + "graceful-fs": "^4.1.11", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "path-is-inside": "^1.0.2", + "read-cmd-shim": "^1.0.1", + "slide": "^1.1.6" + }, + "dependencies": { + "iferr": { + "version": "0.1.5", + "resolved": false, + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=" + } + } + }, + "get-caller-file": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=" + }, + "get-stream": { + "version": "3.0.0", + "resolved": false, + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" + }, + "getpass": { + "version": "0.1.7", + "resolved": false, + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.2", + "resolved": false, + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "global-dirs": { + "version": "0.1.1", + "resolved": false, + "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", + "requires": { + "ini": "^1.3.4" + } + }, + "got": { + "version": "6.7.1", + "resolved": false, + "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", + "requires": { + "create-error-class": "^3.0.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "is-redirect": "^1.0.0", + "is-retry-allowed": "^1.0.0", + "is-stream": "^1.0.0", + "lowercase-keys": "^1.0.0", + "safe-buffer": "^5.0.1", + "timed-out": "^4.0.0", + "unzip-response": "^2.0.1", + "url-parse-lax": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": false, + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "har-schema": { + "version": "2.0.0", + "resolved": false, + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.1.0", + "resolved": false, + "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==", + "requires": { + "ajv": "^5.3.0", + "har-schema": "^2.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": false, + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": false, + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "hosted-git-info": { + "version": "2.7.1", + "resolved": false, + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==" + }, + "http-cache-semantics": { + "version": "3.8.1", + "resolved": false, + "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==" + }, + "http-proxy-agent": { + "version": "2.1.0", + "resolved": false, + "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", + "requires": { + "agent-base": "4", + "debug": "3.1.0" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": false, + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "https-proxy-agent": { + "version": "2.2.1", + "resolved": false, + "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", + "requires": { + "agent-base": "^4.1.0", + "debug": "^3.1.0" + } + }, + "humanize-ms": { + "version": "1.2.1", + "resolved": false, + "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", + "requires": { + "ms": "^2.0.0" + } + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": false, + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "iferr": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha512-9AfeLfji44r5TKInjhz3W9DyZI1zR1JAf2hVBMGhddAKPqBsupb89jGfbCTHIGZd6fGZl9WlHdn4AObygyMKwg==" + }, + "ignore-walk": { + "version": "3.0.1", + "resolved": false, + "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", + "requires": { + "minimatch": "^3.0.4" + } + }, + "import-lazy": { + "version": "2.1.0", + "resolved": false, + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=" + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": false, + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + }, + "inflight": { + "version": "1.0.6", + "resolved": false, + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": false, + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "1.3.5", + "resolved": false, + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" + }, + "init-package-json": { + "version": "1.10.3", + "resolved": false, + "integrity": "sha512-zKSiXKhQveNteyhcj1CoOP8tqp1QuxPIPBl8Bid99DGLFqA1p87M6lNgfjJHSBoWJJlidGOv5rWjyYKEB3g2Jw==", + "requires": { + "glob": "^7.1.1", + "npm-package-arg": "^4.0.0 || ^5.0.0 || ^6.0.0", + "promzard": "^0.3.0", + "read": "~1.0.1", + "read-package-json": "1 || 2", + "semver": "2.x || 3.x || 4 || 5", + "validate-npm-package-license": "^3.0.1", + "validate-npm-package-name": "^3.0.0" + } + }, + "invert-kv": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" + }, + "ip": { + "version": "1.1.5", + "resolved": false, + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" + }, + "ip-regex": { + "version": "2.1.0", + "resolved": false, + "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=" + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "requires": { + "builtin-modules": "^1.0.0" + } + }, + "is-ci": { + "version": "1.1.0", + "resolved": false, + "integrity": "sha512-c7TnwxLePuqIlxHgr7xtxzycJPegNHFuIrBkwbf8hc58//+Op1CqFkyS+xnIMkwn9UsJIwc174BIjkyBmSpjKg==", + "requires": { + "ci-info": "^1.0.0" + } + }, + "is-cidr": { + "version": "2.0.6", + "resolved": false, + "integrity": "sha512-A578p1dV22TgPXn6NCaDAPj6vJvYsBgAzUrAd28a4oldeXJjWqEUuSZOLIW3im51mazOKsoyVp8NU/OItlWacw==", + "requires": { + "cidr-regex": "^2.0.8" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-installed-globally": { + "version": "0.1.0", + "resolved": false, + "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=", + "requires": { + "global-dirs": "^0.1.0", + "is-path-inside": "^1.0.0" + } + }, + "is-npm": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=" + }, + "is-obj": { + "version": "1.0.1", + "resolved": false, + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=" + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": false, + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "requires": { + "path-is-inside": "^1.0.1" + } + }, + "is-redirect": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=" + }, + "is-retry-allowed": { + "version": "1.1.0", + "resolved": false, + "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=" + }, + "is-stream": { + "version": "1.1.0", + "resolved": false, + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "isarray": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isexe": { + "version": "2.0.0", + "resolved": false, + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "isstream": { + "version": "0.1.2", + "resolved": false, + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "jsbn": { + "version": "0.1.1", + "resolved": false, + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "optional": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" + }, + "json-schema": { + "version": "0.2.3", + "resolved": false, + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": false, + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": false, + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsonparse": { + "version": "1.3.1", + "resolved": false, + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=" + }, + "jsprim": { + "version": "1.4.1", + "resolved": false, + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "latest-version": { + "version": "3.1.0", + "resolved": false, + "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=", + "requires": { + "package-json": "^4.0.0" + } + }, + "lazy-property": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-hN3Es3Bnm6i9TNz6TAa0PVcREUc=" + }, + "lcid": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "requires": { + "invert-kv": "^1.0.0" + } + }, + "libcipm": { + "version": "2.0.2", + "resolved": false, + "integrity": "sha512-9uZ6/LAflVEijksTRq/RX0e+pGA4mr8tND9Cmk2JMg7j2fFUBrs8PpFX2DOAJR/XoxPzz+5h8bkWmtIYLunKAg==", + "requires": { + "bin-links": "^1.1.2", + "bluebird": "^3.5.1", + "find-npm-prefix": "^1.0.2", + "graceful-fs": "^4.1.11", + "lock-verify": "^2.0.2", + "mkdirp": "^0.5.1", + "npm-lifecycle": "^2.0.3", + "npm-logical-tree": "^1.2.1", + "npm-package-arg": "^6.1.0", + "pacote": "^8.1.6", + "protoduck": "^5.0.0", + "read-package-json": "^2.0.13", + "rimraf": "^2.6.2", + "worker-farm": "^1.6.0" + } + }, + "libnpmhook": { + "version": "4.0.1", + "resolved": false, + "integrity": "sha512-3qqpfqvBD1712WA6iGe0stkG40WwAeoWcujA6BlC0Be1JArQbqwabnEnZ0CRcD05Tf1fPYJYdCbSfcfedEJCOg==", + "requires": { + "figgy-pudding": "^3.1.0", + "npm-registry-fetch": "^3.0.0" + }, + "dependencies": { + "npm-registry-fetch": { + "version": "3.1.1", + "resolved": false, + "integrity": "sha512-xBobENeenvjIG8PgQ1dy77AXTI25IbYhmA3DusMIfw/4EL5BaQ5e1V9trkPrqHvyjR3/T0cnH6o0Wt/IzcI5Ag==", + "requires": { + "bluebird": "^3.5.1", + "figgy-pudding": "^3.1.0", + "lru-cache": "^4.1.2", + "make-fetch-happen": "^4.0.0", + "npm-package-arg": "^6.0.0" + } + } + } + }, + "libnpx": { + "version": "10.2.0", + "resolved": false, + "integrity": "sha512-X28coei8/XRCt15cYStbLBph+KGhFra4VQhRBPuH/HHMkC5dxM8v24RVgUsvODKCrUZ0eTgiTqJp6zbl0sskQQ==", + "requires": { + "dotenv": "^5.0.1", + "npm-package-arg": "^6.0.0", + "rimraf": "^2.6.2", + "safe-buffer": "^5.1.0", + "update-notifier": "^2.3.0", + "which": "^1.3.0", + "y18n": "^4.0.0", + "yargs": "^11.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": false, + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lock-verify": { + "version": "2.0.2", + "resolved": false, + "integrity": "sha512-QNVwK0EGZBS4R3YQ7F1Ox8p41Po9VGl2QG/2GsuvTbkJZYSsPeWHKMbbH6iZMCHWSMww5nrJroZYnGzI4cePuw==", + "requires": { + "npm-package-arg": "^5.1.2 || 6", + "semver": "^5.4.1" + } + }, + "lockfile": { + "version": "1.0.4", + "resolved": false, + "integrity": "sha512-cvbTwETRfsFh4nHsL1eGWapU1XFi5Ot9E85sWAwia7Y7EgB7vfqcZhTKZ+l7hCGxSPoushMv5GKhT5PdLv03WA==", + "requires": { + "signal-exit": "^3.0.2" + } + }, + "lodash._baseindexof": { + "version": "3.1.0", + "resolved": false, + "integrity": "sha1-/lK1OhxnYeQmGNZU5KJXie1hgiw=" + }, + "lodash._baseuniq": { + "version": "4.6.0", + "resolved": false, + "integrity": "sha1-DrtE5FaBSveQXGIS+iybLVG4Qeg=", + "requires": { + "lodash._createset": "~4.0.0", + "lodash._root": "~3.0.0" + } + }, + "lodash._bindcallback": { + "version": "3.0.1", + "resolved": false, + "integrity": "sha1-5THCdkTPi1epnhftlbNcdIeJOS4=" + }, + "lodash._cacheindexof": { + "version": "3.0.2", + "resolved": false, + "integrity": "sha1-PcaayCSY0u5ePOVgkbr9Ktx73pI=" + }, + "lodash._createcache": { + "version": "3.1.2", + "resolved": false, + "integrity": "sha1-VtagZAF2JeeevKa4AY4XRAvc8JM=", + "requires": { + "lodash._getnative": "^3.0.0" + } + }, + "lodash._createset": { + "version": "4.0.3", + "resolved": false, + "integrity": "sha1-D0ZZ+7CddRlPqeK4imZE02PJ/iY=" + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": false, + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=" + }, + "lodash._root": { + "version": "3.0.1", + "resolved": false, + "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=" + }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": false, + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" + }, + "lodash.restparam": { + "version": "3.6.1", + "resolved": false, + "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=" + }, + "lodash.union": { + "version": "4.6.0", + "resolved": false, + "integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=" + }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": false, + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=" + }, + "lodash.without": { + "version": "4.4.0", + "resolved": false, + "integrity": "sha1-PNRXSgC2e643OpS3SHcmQFB7eqw=" + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": false, + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" + }, + "lru-cache": { + "version": "4.1.3", + "resolved": false, + "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "make-dir": { + "version": "1.3.0", + "resolved": false, + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "requires": { + "pify": "^3.0.0" + } + }, + "make-fetch-happen": { + "version": "4.0.1", + "resolved": false, + "integrity": "sha512-7R5ivfy9ilRJ1EMKIOziwrns9fGeAD4bAha8EB7BIiBBLHm2KeTUGCrICFt2rbHfzheTLynv50GnNTK1zDTrcQ==", + "requires": { + "agentkeepalive": "^3.4.1", + "cacache": "^11.0.1", + "http-cache-semantics": "^3.8.1", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^2.2.1", + "lru-cache": "^4.1.2", + "mississippi": "^3.0.0", + "node-fetch-npm": "^2.0.2", + "promise-retry": "^1.1.1", + "socks-proxy-agent": "^4.0.0", + "ssri": "^6.0.0" + } + }, + "meant": { + "version": "1.0.1", + "resolved": false, + "integrity": "sha512-UakVLFjKkbbUwNWJ2frVLnnAtbb7D7DsloxRd3s/gDpI8rdv8W5Hp3NaDb+POBI1fQdeussER6NB8vpcRURvlg==" + }, + "mem": { + "version": "1.1.0", + "resolved": false, + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "mime-db": { + "version": "1.35.0", + "resolved": false, + "integrity": "sha512-JWT/IcCTsB0Io3AhWUMjRqucrHSPsSf2xKLaRldJVULioggvkJvggZ3VXNNSRkCddE6D+BUI4HEIZIA2OjwIvg==" + }, + "mime-types": { + "version": "2.1.19", + "resolved": false, + "integrity": "sha512-P1tKYHVSZ6uFo26mtnve4HQFE3koh1UWVkp8YUC+ESBHe945xWSoXuHHiGarDqcEZ+whpCDnlNw5LON0kLo+sw==", + "requires": { + "mime-db": "~1.35.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": false, + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" + }, + "minimatch": { + "version": "3.0.4", + "resolved": false, + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": false, + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "minipass": { + "version": "2.3.3", + "resolved": false, + "integrity": "sha512-/jAn9/tEX4gnpyRATxgHEOV6xbcyxgT7iUnxo9Y3+OB0zX00TgKIv/2FZCf5brBbICcwbLqVv2ImjvWWrQMSYw==", + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + }, + "dependencies": { + "yallist": { + "version": "3.0.2", + "resolved": false, + "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=" + } + } + }, + "minizlib": { + "version": "1.1.0", + "resolved": false, + "integrity": "sha512-4T6Ur/GctZ27nHfpt9THOdRZNgyJ9FZchYO1ceg5S8Q3DNLCKYy44nCZzgCJgcvx2UM8czmqak5BCxJMrq37lA==", + "requires": { + "minipass": "^2.2.1" + } + }, + "mississippi": { + "version": "3.0.0", + "resolved": false, + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": false, + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + }, + "move-concurrently": { + "version": "1.0.1", + "resolved": false, + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "requires": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + } + }, + "ms": { + "version": "2.1.1", + "resolved": false, + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + }, + "mute-stream": { + "version": "0.0.7", + "resolved": false, + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" + }, + "node-fetch-npm": { + "version": "2.0.2", + "resolved": false, + "integrity": "sha512-nJIxm1QmAj4v3nfCvEeCrYSoVwXyxLnaPBK5W1W5DGEJwjlKuC2VEUycGw5oxk+4zZahRrB84PUJJgEmhFTDFw==", + "requires": { + "encoding": "^0.1.11", + "json-parse-better-errors": "^1.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node-gyp": { + "version": "3.8.0", + "resolved": false, + "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==", + "requires": { + "fstream": "^1.0.0", + "glob": "^7.0.3", + "graceful-fs": "^4.1.2", + "mkdirp": "^0.5.0", + "nopt": "2 || 3", + "npmlog": "0 || 1 || 2 || 3 || 4", + "osenv": "0", + "request": "^2.87.0", + "rimraf": "2", + "semver": "~5.3.0", + "tar": "^2.0.0", + "which": "1" + }, + "dependencies": { + "nopt": { + "version": "3.0.6", + "resolved": false, + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "requires": { + "abbrev": "1" + } + }, + "semver": { + "version": "5.3.0", + "resolved": false, + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" + }, + "tar": { + "version": "2.2.1", + "resolved": false, + "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", + "requires": { + "block-stream": "*", + "fstream": "^1.0.2", + "inherits": "2" + } + } + } + }, + "nopt": { + "version": "4.0.1", + "resolved": false, + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": false, + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "npm-audit-report": { + "version": "1.3.1", + "resolved": false, + "integrity": "sha512-SjTF8ZP4rOu3JiFrTMi4M1CmVo2tni2sP4TzhyCMHwnMGf6XkdGLZKt9cdZ12esKf0mbQqFyU9LtY0SoeahL7g==", + "requires": { + "cli-table3": "^0.5.0", + "console-control-strings": "^1.1.0" + } + }, + "npm-bundled": { + "version": "1.0.5", + "resolved": false, + "integrity": "sha512-m/e6jgWu8/v5niCUKQi9qQl8QdeEduFA96xHDDzFGqly0OOjI7c+60KM/2sppfnUU9JJagf+zs+yGhqSOFj71g==" + }, + "npm-cache-filename": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-3tMGxbC/yHCp6fr4I7xfKD4FrhE=" + }, + "npm-install-checks": { + "version": "3.0.0", + "resolved": false, + "integrity": "sha1-1K7N/VGlPjcjt7L5Oy7ijjB7wNc=", + "requires": { + "semver": "^2.3.0 || 3.x || 4 || 5" + } + }, + "npm-lifecycle": { + "version": "2.1.0", + "resolved": false, + "integrity": "sha512-QbBfLlGBKsktwBZLj6AviHC6Q9Y3R/AY4a2PYSIRhSKSS0/CxRyD/PfxEX6tPeOCXQgMSNdwGeECacstgptc+g==", + "requires": { + "byline": "^5.0.0", + "graceful-fs": "^4.1.11", + "node-gyp": "^3.8.0", + "resolve-from": "^4.0.0", + "slide": "^1.1.6", + "uid-number": "0.0.6", + "umask": "^1.1.0", + "which": "^1.3.1" + } + }, + "npm-logical-tree": { + "version": "1.2.1", + "resolved": false, + "integrity": "sha512-AJI/qxDB2PWI4LG1CYN579AY1vCiNyWfkiquCsJWqntRu/WwimVrC8yXeILBFHDwxfOejxewlmnvW9XXjMlYIg==" + }, + "npm-package-arg": { + "version": "6.1.0", + "resolved": false, + "integrity": "sha512-zYbhP2k9DbJhA0Z3HKUePUgdB1x7MfIfKssC+WLPFMKTBZKpZh5m13PgexJjCq6KW7j17r0jHWcCpxEqnnncSA==", + "requires": { + "hosted-git-info": "^2.6.0", + "osenv": "^0.1.5", + "semver": "^5.5.0", + "validate-npm-package-name": "^3.0.0" + } + }, + "npm-packlist": { + "version": "1.1.11", + "resolved": false, + "integrity": "sha512-CxKlZ24urLkJk+9kCm48RTQ7L4hsmgSVzEk0TLGPzzyuFxD7VNgy5Sl24tOLMzQv773a/NeJ1ce1DKeacqffEA==", + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npm-pick-manifest": { + "version": "2.1.0", + "resolved": false, + "integrity": "sha512-q9zLP8cTr8xKPmMZN3naxp1k/NxVFsjxN6uWuO1tiw9gxg7wZWQ/b5UTfzD0ANw2q1lQxdLKTeCCksq+bPSgbQ==", + "requires": { + "npm-package-arg": "^6.0.0", + "semver": "^5.4.1" + } + }, + "npm-profile": { + "version": "3.0.2", + "resolved": false, + "integrity": "sha512-rEJOFR6PbwOvvhGa2YTNOJQKNuc6RovJ6T50xPU7pS9h/zKPNCJ+VHZY2OFXyZvEi+UQYtHRTp8O/YM3tUD20A==", + "requires": { + "aproba": "^1.1.2 || 2", + "make-fetch-happen": "^2.5.0 || 3 || 4" + } + }, + "npm-registry-client": { + "version": "8.6.0", + "resolved": false, + "integrity": "sha512-Qs6P6nnopig+Y8gbzpeN/dkt+n7IyVd8f45NTMotGk6Qo7GfBmzwYx6jRLoOOgKiMnaQfYxsuyQlD8Mc3guBhg==", + "requires": { + "concat-stream": "^1.5.2", + "graceful-fs": "^4.1.6", + "normalize-package-data": "~1.0.1 || ^2.0.0", + "npm-package-arg": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0", + "npmlog": "2 || ^3.1.0 || ^4.0.0", + "once": "^1.3.3", + "request": "^2.74.0", + "retry": "^0.10.0", + "safe-buffer": "^5.1.1", + "semver": "2 >=2.2.1 || 3.x || 4 || 5", + "slide": "^1.1.3", + "ssri": "^5.2.4" + }, + "dependencies": { + "retry": { + "version": "0.10.1", + "resolved": false, + "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=" + }, + "ssri": { + "version": "5.3.0", + "resolved": false, + "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==", + "requires": { + "safe-buffer": "^5.1.1" + } + } + } + }, + "npm-registry-fetch": { + "version": "1.1.0", + "resolved": false, + "integrity": "sha512-XJPIBfMtgaooRtZmuA42xCeLf3tkxdIX0xqRsGWwNrcVvJ9UYFccD7Ho7QWCzvkM3i/QrkUC37Hu0a+vDBmt5g==", + "requires": { + "bluebird": "^3.5.1", + "figgy-pudding": "^2.0.1", + "lru-cache": "^4.1.2", + "make-fetch-happen": "^3.0.0", + "npm-package-arg": "^6.0.0", + "safe-buffer": "^5.1.1" + }, + "dependencies": { + "cacache": { + "version": "10.0.4", + "resolved": false, + "integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==", + "requires": { + "bluebird": "^3.5.1", + "chownr": "^1.0.1", + "glob": "^7.1.2", + "graceful-fs": "^4.1.11", + "lru-cache": "^4.1.1", + "mississippi": "^2.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.2", + "ssri": "^5.2.4", + "unique-filename": "^1.1.0", + "y18n": "^4.0.0" + }, + "dependencies": { + "mississippi": { + "version": "2.0.0", + "resolved": false, + "integrity": "sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw==", + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^2.0.1", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + } + } + }, + "figgy-pudding": { + "version": "2.0.1", + "resolved": false, + "integrity": "sha512-yIJPhIBi/oFdU/P+GSXjmk/rmGjuZkm7A5LTXZxNrEprXJXRK012FiI1BR1Pga+0d/d6taWWD+B5d2ozqaxHig==" + }, + "make-fetch-happen": { + "version": "3.0.0", + "resolved": false, + "integrity": "sha512-FmWY7gC0mL6Z4N86vE14+m719JKE4H0A+pyiOH18B025gF/C113pyfb4gHDDYP5cqnRMHOz06JGdmffC/SES+w==", + "requires": { + "agentkeepalive": "^3.4.1", + "cacache": "^10.0.4", + "http-cache-semantics": "^3.8.1", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^2.2.0", + "lru-cache": "^4.1.2", + "mississippi": "^3.0.0", + "node-fetch-npm": "^2.0.2", + "promise-retry": "^1.1.1", + "socks-proxy-agent": "^3.0.1", + "ssri": "^5.2.4" + } + }, + "pump": { + "version": "2.0.1", + "resolved": false, + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "smart-buffer": { + "version": "1.1.15", + "resolved": false, + "integrity": "sha1-fxFLW2X6s+KjWqd1uxLw0cZJvxY=" + }, + "socks": { + "version": "1.1.10", + "resolved": false, + "integrity": "sha1-W4t/x8jzQcU+0FbpKbe/Tei6e1o=", + "requires": { + "ip": "^1.1.4", + "smart-buffer": "^1.0.13" + } + }, + "socks-proxy-agent": { + "version": "3.0.1", + "resolved": false, + "integrity": "sha512-ZwEDymm204mTzvdqyUqOdovVr2YRd2NYskrYrF2LXyZ9qDiMAoFESGK8CRphiO7rtbo2Y757k2Nia3x2hGtalA==", + "requires": { + "agent-base": "^4.1.0", + "socks": "^1.1.10" + } + }, + "ssri": { + "version": "5.3.0", + "resolved": false, + "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==", + "requires": { + "safe-buffer": "^5.1.1" + } + } + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": false, + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "requires": { + "path-key": "^2.0.0" + } + }, + "npm-user-validate": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-jOyg9c6gTU6TUZ73LQVXp1Ei6VE=" + }, + "npmlog": { + "version": "4.1.2", + "resolved": false, + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": false, + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": false, + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": false, + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "once": { + "version": "1.4.0", + "resolved": false, + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "opener": { + "version": "1.5.0", + "resolved": false, + "integrity": "sha512-MD4s/o61y2slS27zm2s4229V2gAUHX0/e3/XOmY/jsXwhysjjCIHN8lx7gqZCrZk19ym+HjCUWHeMKD7YJtKCQ==" + }, + "os-homedir": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, + "os-locale": { + "version": "2.1.0", + "resolved": false, + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "osenv": { + "version": "0.1.5", + "resolved": false, + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" + }, + "p-limit": { + "version": "1.2.0", + "resolved": false, + "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": false, + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" + }, + "package-json": { + "version": "4.0.1", + "resolved": false, + "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=", + "requires": { + "got": "^6.7.1", + "registry-auth-token": "^3.0.1", + "registry-url": "^3.0.3", + "semver": "^5.1.0" + } + }, + "pacote": { + "version": "8.1.6", + "resolved": false, + "integrity": "sha512-wTOOfpaAQNEQNtPEx92x9Y9kRWVu45v583XT8x2oEV2xRB74+xdqMZIeGW4uFvAyZdmSBtye+wKdyyLaT8pcmw==", + "requires": { + "bluebird": "^3.5.1", + "cacache": "^11.0.2", + "get-stream": "^3.0.0", + "glob": "^7.1.2", + "lru-cache": "^4.1.3", + "make-fetch-happen": "^4.0.1", + "minimatch": "^3.0.4", + "minipass": "^2.3.3", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "normalize-package-data": "^2.4.0", + "npm-package-arg": "^6.1.0", + "npm-packlist": "^1.1.10", + "npm-pick-manifest": "^2.1.0", + "osenv": "^0.1.5", + "promise-inflight": "^1.0.1", + "promise-retry": "^1.1.1", + "protoduck": "^5.0.0", + "rimraf": "^2.6.2", + "safe-buffer": "^5.1.2", + "semver": "^5.5.0", + "ssri": "^6.0.0", + "tar": "^4.4.3", + "unique-filename": "^1.1.0", + "which": "^1.3.0" + } + }, + "parallel-transform": { + "version": "1.1.0", + "resolved": false, + "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", + "requires": { + "cyclist": "~0.2.2", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": false, + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": false, + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" + }, + "path-key": { + "version": "2.0.1", + "resolved": false, + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + }, + "performance-now": { + "version": "2.1.0", + "resolved": false, + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "pify": { + "version": "3.0.0", + "resolved": false, + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + }, + "prepend-http": { + "version": "1.0.4", + "resolved": false, + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": false, + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + }, + "promise-inflight": { + "version": "1.0.1", + "resolved": false, + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=" + }, + "promise-retry": { + "version": "1.1.1", + "resolved": false, + "integrity": "sha1-ZznpaOMFHaIM5kl/srUPaRHfPW0=", + "requires": { + "err-code": "^1.0.0", + "retry": "^0.10.0" + }, + "dependencies": { + "retry": { + "version": "0.10.1", + "resolved": false, + "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=" + } + } + }, + "promzard": { + "version": "0.3.0", + "resolved": false, + "integrity": "sha1-JqXW7ox97kyxIggwWs+5O6OCqe4=", + "requires": { + "read": "1" + } + }, + "proto-list": { + "version": "1.2.4", + "resolved": false, + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=" + }, + "protoduck": { + "version": "5.0.0", + "resolved": false, + "integrity": "sha512-agsGWD8/RZrS4ga6v82Fxb0RHIS2RZnbsSue6A9/MBRhB/jcqOANAMNrqM9900b8duj+Gx+T/JMy5IowDoO/hQ==", + "requires": { + "genfun": "^4.0.1" + } + }, + "prr": { + "version": "1.0.1", + "resolved": false, + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" + }, + "pseudomap": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, + "psl": { + "version": "1.1.29", + "resolved": false, + "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==" + }, + "pump": { + "version": "3.0.0", + "resolved": false, + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": false, + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "resolved": false, + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "punycode": { + "version": "1.4.1", + "resolved": false, + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "qrcode-terminal": { + "version": "0.12.0", + "resolved": false, + "integrity": "sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ==" + }, + "qs": { + "version": "6.5.2", + "resolved": false, + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "query-string": { + "version": "6.1.0", + "resolved": false, + "integrity": "sha512-pNB/Gr8SA8ff8KpUFM36o/WFAlthgaThka5bV19AD9PNTH20Pwq5Zxodif2YyHwrctp6SkL4GqlOot0qR/wGaw==", + "requires": { + "decode-uri-component": "^0.2.0", + "strict-uri-encode": "^2.0.0" + } + }, + "qw": { + "version": "1.0.1", + "resolved": false, + "integrity": "sha1-77/cdA+a0FQwRCassYNBLMi5ltQ=" + }, + "rc": { + "version": "1.2.7", + "resolved": false, + "integrity": "sha512-LdLD8xD4zzLsAT5xyushXDNscEjB7+2ulnl8+r1pnESlYtlJtVSoCMBGr30eDRJ3+2Gq89jK9P9e4tCEH1+ywA==", + "requires": { + "deep-extend": "^0.5.1", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": false, + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + } + } + }, + "read": { + "version": "1.0.7", + "resolved": false, + "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", + "requires": { + "mute-stream": "~0.0.4" + } + }, + "read-cmd-shim": { + "version": "1.0.1", + "resolved": false, + "integrity": "sha1-LV0Vd4ajfAVdIgd8MsU/gynpHHs=", + "requires": { + "graceful-fs": "^4.1.2" + } + }, + "read-installed": { + "version": "4.0.3", + "resolved": false, + "integrity": "sha1-/5uLZ/GH0eTCm5/rMfayI6zRkGc=", + "requires": { + "debuglog": "^1.0.1", + "graceful-fs": "^4.1.2", + "read-package-json": "^2.0.0", + "readdir-scoped-modules": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "slide": "~1.1.3", + "util-extend": "^1.0.1" + } + }, + "read-package-json": { + "version": "2.0.13", + "resolved": false, + "integrity": "sha512-/1dZ7TRZvGrYqE0UAfN6qQb5GYBsNcqS1C0tNK601CFOJmtHI7NIGXwetEPU/OtoFHZL3hDxm4rolFFVE9Bnmg==", + "requires": { + "glob": "^7.1.1", + "graceful-fs": "^4.1.2", + "json-parse-better-errors": "^1.0.1", + "normalize-package-data": "^2.0.0", + "slash": "^1.0.0" + } + }, + "read-package-tree": { + "version": "5.2.1", + "resolved": false, + "integrity": "sha512-2CNoRoh95LxY47LvqrehIAfUVda2JbuFE/HaGYs42bNrGG+ojbw1h3zOcPcQ+1GQ3+rkzNndZn85u1XyZ3UsIA==", + "requires": { + "debuglog": "^1.0.1", + "dezalgo": "^1.0.0", + "once": "^1.3.0", + "read-package-json": "^2.0.0", + "readdir-scoped-modules": "^1.0.0" + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": false, + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "readdir-scoped-modules": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-n6+jfShr5dksuuve4DDcm19AZ0c=", + "requires": { + "debuglog": "^1.0.1", + "dezalgo": "^1.0.0", + "graceful-fs": "^4.1.2", + "once": "^1.3.0" + } + }, + "registry-auth-token": { + "version": "3.3.2", + "resolved": false, + "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==", + "requires": { + "rc": "^1.1.6", + "safe-buffer": "^5.0.1" + } + }, + "registry-url": { + "version": "3.1.0", + "resolved": false, + "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", + "requires": { + "rc": "^1.0.1" + } + }, + "request": { + "version": "2.88.0", + "resolved": false, + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": false, + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": false, + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" + }, + "resolve-from": { + "version": "4.0.0", + "resolved": false, + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" + }, + "retry": { + "version": "0.12.0", + "resolved": false, + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=" + }, + "rimraf": { + "version": "2.6.2", + "resolved": false, + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "requires": { + "glob": "^7.0.5" + } + }, + "run-queue": { + "version": "1.0.3", + "resolved": false, + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "requires": { + "aproba": "^1.1.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": false, + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": false, + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "semver": { + "version": "5.5.0", + "resolved": false, + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" + }, + "semver-diff": { + "version": "2.1.0", + "resolved": false, + "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", + "requires": { + "semver": "^5.0.3" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": false, + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "sha": { + "version": "2.0.1", + "resolved": false, + "integrity": "sha1-YDCCL70smCOUn49y7WQR7lzyWq4=", + "requires": { + "graceful-fs": "^4.1.2", + "readable-stream": "^2.0.2" + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": false, + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + }, + "signal-exit": { + "version": "3.0.2", + "resolved": false, + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "slash": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" + }, + "slide": { + "version": "1.1.6", + "resolved": false, + "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=" + }, + "smart-buffer": { + "version": "4.0.1", + "resolved": false, + "integrity": "sha512-RFqinRVJVcCAL9Uh1oVqE6FZkqsyLiVOYEZ20TqIOjuX7iFVJ+zsbs4RIghnw/pTs7mZvt8ZHhvm1ZUrR4fykg==" + }, + "socks": { + "version": "2.2.0", + "resolved": false, + "integrity": "sha512-uRKV9uXQ9ytMbGm2+DilS1jB7N3AC0mmusmW5TVWjNuBZjxS8+lX38fasKVY9I4opv/bY/iqTbcpFFaTwpfwRg==", + "requires": { + "ip": "^1.1.5", + "smart-buffer": "^4.0.1" + } + }, + "socks-proxy-agent": { + "version": "4.0.1", + "resolved": false, + "integrity": "sha512-Kezx6/VBguXOsEe5oU3lXYyKMi4+gva72TwJ7pQY5JfqUx2nMk7NXA6z/mpNqIlfQjWYVfeuNvQjexiTaTn6Nw==", + "requires": { + "agent-base": "~4.2.0", + "socks": "~2.2.0" + } + }, + "sorted-object": { + "version": "2.0.1", + "resolved": false, + "integrity": "sha1-fWMfS9OnmKJK8d/8+/6DM3pd9fw=" + }, + "sorted-union-stream": { + "version": "2.1.3", + "resolved": false, + "integrity": "sha1-x3lMfgd4gAUv9xqNSi27Sppjisc=", + "requires": { + "from2": "^1.3.0", + "stream-iterate": "^1.1.0" + }, + "dependencies": { + "from2": { + "version": "1.3.0", + "resolved": false, + "integrity": "sha1-iEE7qqX5pZfP3pIh2GmGzTwGHf0=", + "requires": { + "inherits": "~2.0.1", + "readable-stream": "~1.1.10" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": false, + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": false, + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": false, + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, + "spdx-correct": { + "version": "3.0.0", + "resolved": false, + "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.1.0", + "resolved": false, + "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==" + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": false, + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.0", + "resolved": false, + "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==" + }, + "sshpk": { + "version": "1.14.2", + "resolved": false, + "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "ssri": { + "version": "6.0.0", + "resolved": false, + "integrity": "sha512-zYOGfVHPhxyzwi8MdtdNyxv3IynWCIM4jYReR48lqu0VngxgH1c+C6CmipRdJ55eVByTJV/gboFEEI7TEQI8DA==" + }, + "stream-each": { + "version": "1.2.2", + "resolved": false, + "integrity": "sha512-mc1dbFhGBxvTM3bIWmAAINbqiuAk9TATcfIQC8P+/+HJefgaiTlMn2dHvkX8qlI12KeYKSQ1Ua9RrIqrn1VPoA==", + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "stream-iterate": { + "version": "1.2.0", + "resolved": false, + "integrity": "sha1-K9fHcpbBcCpGSIuK1B95hl7s1OE=", + "requires": { + "readable-stream": "^2.1.5", + "stream-shift": "^1.0.0" + } + }, + "stream-shift": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=" + }, + "strict-uri-encode": { + "version": "2.0.0", + "resolved": false, + "integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY=" + }, + "string-width": { + "version": "2.1.1", + "resolved": false, + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": false, + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": false, + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": false, + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": false, + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "stringify-package": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha512-JIQqiWmLiEozOC0b0BtxZ/AOUtdUZHCBPgqIZ2kSJJqGwgb9neo44XdTHUC4HZSGqi03hOeB7W/E8rAlKnGe9g==" + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": false, + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": false, + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "supports-color": { + "version": "5.4.0", + "resolved": false, + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "tar": { + "version": "4.4.6", + "resolved": false, + "integrity": "sha512-tMkTnh9EdzxyfW+6GK6fCahagXsnYk6kE6S9Gr9pjVdys769+laCTbodXDhPAjzVtEBazRgP0gYqOjnk9dQzLg==", + "requires": { + "chownr": "^1.0.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.3", + "minizlib": "^1.1.0", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + }, + "dependencies": { + "yallist": { + "version": "3.0.2", + "resolved": false, + "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=" + } + } + }, + "term-size": { + "version": "1.2.0", + "resolved": false, + "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", + "requires": { + "execa": "^0.7.0" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": false, + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" + }, + "through": { + "version": "2.3.8", + "resolved": false, + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "through2": { + "version": "2.0.3", + "resolved": false, + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "requires": { + "readable-stream": "^2.1.5", + "xtend": "~4.0.1" + } + }, + "timed-out": { + "version": "4.0.1", + "resolved": false, + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" + }, + "tiny-relative-date": { + "version": "1.3.0", + "resolved": false, + "integrity": "sha512-MOQHpzllWxDCHHaDno30hhLfbouoYlOI8YlMNtvKe1zXbjEVhbcEovQxvZrPvtiYW630GQDoMMarCnjfyfHA+A==" + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": false, + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": false, + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": false, + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "optional": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": false, + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "uid-number": { + "version": "0.0.6", + "resolved": false, + "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=" + }, + "umask": { + "version": "1.1.0", + "resolved": false, + "integrity": "sha1-8pzr8B31F5ErtY/5xOUP3o4zMg0=" + }, + "unique-filename": { + "version": "1.1.0", + "resolved": false, + "integrity": "sha1-0F8v5AMlYIcfMOk8vnNe6iAVFPM=", + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.0", + "resolved": false, + "integrity": "sha1-22Z258fMBimHj/GWCXx4hVrp9Ks=", + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "unique-string": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", + "requires": { + "crypto-random-string": "^1.0.0" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "unzip-response": { + "version": "2.0.1", + "resolved": false, + "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=" + }, + "update-notifier": { + "version": "2.5.0", + "resolved": false, + "integrity": "sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==", + "requires": { + "boxen": "^1.2.1", + "chalk": "^2.0.1", + "configstore": "^3.0.0", + "import-lazy": "^2.1.0", + "is-ci": "^1.0.10", + "is-installed-globally": "^0.1.0", + "is-npm": "^1.0.0", + "latest-version": "^3.0.0", + "semver-diff": "^2.0.0", + "xdg-basedir": "^3.0.0" + } + }, + "url-parse-lax": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "requires": { + "prepend-http": "^1.0.1" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "util-extend": { + "version": "1.0.3", + "resolved": false, + "integrity": "sha1-p8IW0mdUUWljeztu3GypEZ4v+T8=" + }, + "uuid": { + "version": "3.3.2", + "resolved": false, + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": false, + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "validate-npm-package-name": { + "version": "3.0.0", + "resolved": false, + "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=", + "requires": { + "builtins": "^1.0.3" + } + }, + "verror": { + "version": "1.10.0", + "resolved": false, + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "wcwidth": { + "version": "1.0.1", + "resolved": false, + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "requires": { + "defaults": "^1.0.3" + } + }, + "which": { + "version": "1.3.1", + "resolved": false, + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": false, + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "wide-align": { + "version": "1.1.2", + "resolved": false, + "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", + "requires": { + "string-width": "^1.0.2" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "widest-line": { + "version": "2.0.0", + "resolved": false, + "integrity": "sha1-AUKk6KJD+IgsAjOqDgKBqnYVInM=", + "requires": { + "string-width": "^2.1.1" + } + }, + "worker-farm": { + "version": "1.6.0", + "resolved": false, + "integrity": "sha512-6w+3tHbM87WnSWnENBUvA2pxJPLhQUg5LKwUQHq3r+XPhIM+Gh2R5ycbwPCyuGbNg+lPgdcnQUhuC02kJCvffQ==", + "requires": { + "errno": "~0.1.7" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": false, + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write-file-atomic": { + "version": "2.3.0", + "resolved": false, + "integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==", + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "xdg-basedir": { + "version": "3.0.0", + "resolved": false, + "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=" + }, + "xtend": { + "version": "4.0.1", + "resolved": false, + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + }, + "y18n": { + "version": "4.0.0", + "resolved": false, + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" + }, + "yallist": { + "version": "2.1.2", + "resolved": false, + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + }, + "yargs": { + "version": "11.0.0", + "resolved": false, + "integrity": "sha512-Rjp+lMYQOWtgqojx1dEWorjCofi1YN7AoFvYV7b1gx/7dAAeuI4kN5SZiEvr0ZmsZTOpDRcCqrpI10L31tFkBw==", + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.1.1", + "find-up": "^2.1.0", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^9.0.2" + }, + "dependencies": { + "y18n": { + "version": "3.2.1", + "resolved": false, + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + } + } + }, + "yargs-parser": { + "version": "9.0.2", + "resolved": false, + "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", + "requires": { + "camelcase": "^4.1.0" + } + } + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "optional": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "nth-check": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz", + "integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=", + "dev": true, + "optional": true, + "requires": { + "boolbase": "~1.0.0" + } + }, + "num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", + "dev": true + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-component": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", + "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-keys": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", + "integrity": "sha1-CcU4VTd1dTEMymL1W7M0q/97PtI=", + "dev": true + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "^3.0.0" + } + }, + "object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "dev": true, + "requires": { + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "object.getownpropertydescriptors": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", + "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", + "dev": true, + "optional": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.5.1" + } + }, + "object.map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", + "dev": true, + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "requires": { + "for-own": "^0.1.4", + "is-extendable": "^0.1.1" + }, + "dependencies": { + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + } + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "object.values": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.0.4.tgz", + "integrity": "sha1-5STaCbT2b/Bd9FdUbscqyZ8TBpo=", + "dev": true, + "optional": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.6.1", + "function-bind": "^1.1.0", + "has": "^1.0.1" + } + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", + "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "open": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/open/-/open-0.0.5.tgz", + "integrity": "sha1-QsPhjslUZra/DcQvOilFw/DK2Pw=", + "dev": true + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + } + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + } + }, + "optipng-bin": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/optipng-bin/-/optipng-bin-3.1.4.tgz", + "integrity": "sha1-ldNPLEiHBPb9cGBr/qDGWfHZXYQ=", + "dev": true, + "optional": true, + "requires": { + "bin-build": "^2.0.0", + "bin-wrapper": "^3.0.0", + "logalot": "^2.0.0" + } + }, + "orchestrator": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", + "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", + "dev": true, + "requires": { + "end-of-stream": "~0.1.5", + "sequencify": "~0.0.7", + "stream-consume": "~0.1.0" + } + }, + "ordered-read-streams": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", + "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=", + "dev": true + }, + "os-filter-obj": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/os-filter-obj/-/os-filter-obj-1.0.3.tgz", + "integrity": "sha1-WRUzDZDs7VV9LZOKMcbdIU2cY60=", + "dev": true, + "optional": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-pipe": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-pipe/-/p-pipe-1.2.0.tgz", + "integrity": "sha1-SxoROZoRUgpneQ7loMHViB1r7+k=", + "dev": true + }, + "pac-proxy-agent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-3.0.0.tgz", + "integrity": "sha512-AOUX9jES/EkQX2zRz0AW7lSx9jD//hQS8wFXBvcnd/J2Py9KaMJMqV/LPqJssj1tgGufotb2mmopGPR15ODv1Q==", + "dev": true, + "optional": true, + "requires": { + "agent-base": "^4.2.0", + "debug": "^3.1.0", + "get-uri": "^2.0.0", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^2.2.1", + "pac-resolver": "^3.0.0", + "raw-body": "^2.2.0", + "socks-proxy-agent": "^4.0.1" + }, + "dependencies": { + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "dev": true, + "optional": true + }, + "debug": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.5.tgz", + "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", + "dev": true, + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true, + "optional": true + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dev": true, + "optional": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha1-KXhx9jvlB63Pv8pxXQzQ7thOmmM=", + "dev": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true, + "optional": true + }, + "raw-body": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha1-GzJOzmtXBuFThVvBFIxlu39uoMM=", + "dev": true, + "optional": true, + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + } + } + } + }, + "pac-resolver": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-3.0.0.tgz", + "integrity": "sha1-auoweH2wqJFwTet4AKcip2FabyY=", + "dev": true, + "optional": true, + "requires": { + "co": "^4.6.0", + "degenerator": "^1.0.4", + "ip": "^1.1.5", + "netmask": "^1.0.6", + "thunkify": "^2.1.2" + }, + "dependencies": { + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true, + "optional": true + } + } + }, + "parse-filepath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", + "dev": true, + "requires": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "requires": { + "glob-base": "^0.3.0", + "is-dotfile": "^1.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.0" + }, + "dependencies": { + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + } + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, + "parseqs": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", + "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", + "dev": true, + "requires": { + "better-assert": "~1.0.0" + } + }, + "parseuri": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", + "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", + "dev": true, + "requires": { + "better-assert": "~1.0.0" + } + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path": { + "version": "0.4.9", + "resolved": "https://registry.npmjs.org/path/-/path-0.4.9.tgz", + "integrity": "sha1-OAxo0BJz5D+TaNetUP7l4+jUd/A=", + "dev": true + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-proxy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-proxy/-/path-proxy-1.0.0.tgz", + "integrity": "sha1-GOijaFn8nS8aU7SN7hOFQ8Ag3l4=", + "dev": true, + "optional": true, + "requires": { + "inflection": "~1.3.0" + }, + "dependencies": { + "inflection": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.3.8.tgz", + "integrity": "sha1-y9Fg2p91sUw8xjV41POWeEvzAU4=", + "dev": true, + "optional": true + } + } + }, + "path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "dev": true, + "requires": { + "path-root-regex": "^0.1.0" + } + }, + "path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", + "dev": true + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + } + } + }, + "pause": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.1.0.tgz", + "integrity": "sha1-68ikqGGf8LioGsFRPDQ0/0af23Q=", + "dev": true + }, + "pause-stream": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", + "dev": true, + "requires": { + "through": "~2.3" + } + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "dev": true + }, + "performance-now": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", + "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", + "dev": true + }, + "phantomjs-prebuilt": { + "version": "2.1.16", + "resolved": "https://registry.npmjs.org/phantomjs-prebuilt/-/phantomjs-prebuilt-2.1.16.tgz", + "integrity": "sha1-79ISpKOWbTZHaE6ouniFSb4q7+8=", + "dev": true, + "requires": { + "es6-promise": "^4.0.3", + "extract-zip": "^1.6.5", + "fs-extra": "^1.0.0", + "hasha": "^2.2.0", + "kew": "^0.7.0", + "progress": "^1.1.8", + "request": "^2.81.0", + "request-progress": "^2.0.1", + "which": "^1.2.10" + }, + "dependencies": { + "es6-promise": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.5.tgz", + "integrity": "sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg==", + "dev": true + }, + "progress": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", + "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", + "dev": true + } + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "plugin-error": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", + "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", + "dev": true, + "requires": { + "ansi-colors": "^1.0.1", + "arr-diff": "^4.0.0", + "arr-union": "^3.1.0", + "extend-shallow": "^3.0.2" + } + }, + "plugin-log": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/plugin-log/-/plugin-log-0.1.0.tgz", + "integrity": "sha1-hgSc9qsQgzOYqTHzaJy67nteEzM=", + "dev": true, + "requires": { + "chalk": "^1.1.1", + "dateformat": "^1.0.11" + }, + "dependencies": { + "dateformat": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", + "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", + "dev": true, + "requires": { + "get-stdin": "^4.0.1", + "meow": "^3.3.0" + } + } + } + }, + "plur": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/plur/-/plur-2.1.2.tgz", + "integrity": "sha1-dIJFLBoPUI4+NE6uwxLJHCncZVo=", + "dev": true, + "requires": { + "irregular-plurals": "^1.0.0" + } + }, + "pluralize": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", + "integrity": "sha1-KYuJ34uTsCIdv0Ia0rGx6iP8Z3c=", + "dev": true + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha1-ut+hSX1GJE9jkPWLMZgw2RB4U8U=", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" + } + }, + "postcss-calc": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-5.3.1.tgz", + "integrity": "sha1-d7rnypKK2FcW4v2kLyYb98HWW14=", + "dev": true, + "requires": { + "postcss": "^5.0.2", + "postcss-message-helpers": "^2.0.0", + "reduce-css-calc": "^1.2.6" + } + }, + "postcss-colormin": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-2.2.2.tgz", + "integrity": "sha1-ZjFBfV8OkJo9fsJrJMio0eT5bks=", + "dev": true, + "requires": { + "colormin": "^1.0.5", + "postcss": "^5.0.13", + "postcss-value-parser": "^3.2.3" + } + }, + "postcss-convert-values": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-2.6.1.tgz", + "integrity": "sha1-u9hZPFwf0uPRwyK7kl3K6Nrk1i0=", + "dev": true, + "requires": { + "postcss": "^5.0.11", + "postcss-value-parser": "^3.1.2" + } + }, + "postcss-discard-comments": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz", + "integrity": "sha1-vv6J+v1bPazlzM5Rt2uBUUvgDj0=", + "dev": true, + "requires": { + "postcss": "^5.0.14" + } + }, + "postcss-discard-duplicates": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-2.1.0.tgz", + "integrity": "sha1-uavye4isGIFYpesSq8riAmO5GTI=", + "dev": true, + "requires": { + "postcss": "^5.0.4" + } + }, + "postcss-discard-empty": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz", + "integrity": "sha1-0rS9nVztXr2Nyt52QMfXzX9PkrU=", + "dev": true, + "requires": { + "postcss": "^5.0.14" + } + }, + "postcss-discard-overridden": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz", + "integrity": "sha1-ix6vVU9ob7KIzYdMVWZ7CqNmjVg=", + "dev": true, + "requires": { + "postcss": "^5.0.16" + } + }, + "postcss-discard-unused": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz", + "integrity": "sha1-vOMLLMWR/8Y0Mitfs0ZLbZNPRDM=", + "dev": true, + "requires": { + "postcss": "^5.0.14", + "uniqs": "^2.0.0" + } + }, + "postcss-filter-plugins": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/postcss-filter-plugins/-/postcss-filter-plugins-2.0.3.tgz", + "integrity": "sha512-T53GVFsdinJhgwm7rg1BzbeBRomOg9y5MBVhGcsV0CxurUdVj1UlPdKtn7aqYA/c/QVkzKMjq2bSV5dKG5+AwQ==", + "dev": true, + "requires": { + "postcss": "^5.0.4" + } + }, + "postcss-load-config": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-1.2.0.tgz", + "integrity": "sha1-U56a/J3chiASHr+djDZz4M5Q0oo=", + "dev": true, + "requires": { + "cosmiconfig": "^2.1.0", + "object-assign": "^4.1.0", + "postcss-load-options": "^1.2.0", + "postcss-load-plugins": "^2.3.0" + } + }, + "postcss-load-options": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postcss-load-options/-/postcss-load-options-1.2.0.tgz", + "integrity": "sha1-sJixVZ3awt8EvAuzdfmaXP4rbYw=", + "dev": true, + "requires": { + "cosmiconfig": "^2.1.0", + "object-assign": "^4.1.0" + } + }, + "postcss-load-plugins": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/postcss-load-plugins/-/postcss-load-plugins-2.3.0.tgz", + "integrity": "sha1-dFdoEWWZrKLwCfrUJrABdQSdjZI=", + "dev": true, + "requires": { + "cosmiconfig": "^2.1.1", + "object-assign": "^4.1.0" + } + }, + "postcss-merge-idents": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz", + "integrity": "sha1-TFUwMTwI4dWzu/PSu8dH4njuonA=", + "dev": true, + "requires": { + "has": "^1.0.1", + "postcss": "^5.0.10", + "postcss-value-parser": "^3.1.1" + } + }, + "postcss-merge-longhand": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-2.0.2.tgz", + "integrity": "sha1-I9kM0Sewp3mUkVMyc5A0oaTz1lg=", + "dev": true, + "requires": { + "postcss": "^5.0.4" + } + }, + "postcss-merge-rules": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-2.1.2.tgz", + "integrity": "sha1-0d9d+qexrMO+VT8OnhDofGG19yE=", + "dev": true, + "requires": { + "browserslist": "^1.5.2", + "caniuse-api": "^1.5.2", + "postcss": "^5.0.4", + "postcss-selector-parser": "^2.2.2", + "vendors": "^1.0.0" + } + }, + "postcss-message-helpers": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz", + "integrity": "sha1-pPL0+rbk/gAvCu0ABHjN9S+bpg4=", + "dev": true + }, + "postcss-minify-font-values": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz", + "integrity": "sha1-S1jttWZB66fIR0qzUmyv17vey2k=", + "dev": true, + "requires": { + "object-assign": "^4.0.1", + "postcss": "^5.0.4", + "postcss-value-parser": "^3.0.2" + } + }, + "postcss-minify-gradients": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz", + "integrity": "sha1-Xb2hE3NwP4PPtKPqOIHY11/15uE=", + "dev": true, + "requires": { + "postcss": "^5.0.12", + "postcss-value-parser": "^3.3.0" + } + }, + "postcss-minify-params": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz", + "integrity": "sha1-rSzgcTc7lDs9kwo/pZo1jCjW8fM=", + "dev": true, + "requires": { + "alphanum-sort": "^1.0.1", + "postcss": "^5.0.2", + "postcss-value-parser": "^3.0.2", + "uniqs": "^2.0.0" + } + }, + "postcss-minify-selectors": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz", + "integrity": "sha1-ssapjAByz5G5MtGkllCBFDEXNb8=", + "dev": true, + "requires": { + "alphanum-sort": "^1.0.2", + "has": "^1.0.1", + "postcss": "^5.0.14", + "postcss-selector-parser": "^2.0.0" + } + }, + "postcss-normalize-charset": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz", + "integrity": "sha1-757nEhLX/nWceO0WL2HtYrXLk/E=", + "dev": true, + "requires": { + "postcss": "^5.0.5" + } + }, + "postcss-normalize-url": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-3.0.8.tgz", + "integrity": "sha1-EI90s/L82viRov+j6kWSJ5/HgiI=", + "dev": true, + "requires": { + "is-absolute-url": "^2.0.0", + "normalize-url": "^1.4.0", + "postcss": "^5.0.14", + "postcss-value-parser": "^3.2.3" + } + }, + "postcss-ordered-values": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-2.2.3.tgz", + "integrity": "sha1-7sbCpntsQSqNsgQud/6NpD+VwR0=", + "dev": true, + "requires": { + "postcss": "^5.0.4", + "postcss-value-parser": "^3.0.1" + } + }, + "postcss-reduce-idents": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz", + "integrity": "sha1-wsbSDMlYKE9qv75j92Cb9AkFmtM=", + "dev": true, + "requires": { + "postcss": "^5.0.4", + "postcss-value-parser": "^3.0.2" + } + }, + "postcss-reduce-initial": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz", + "integrity": "sha1-aPgGlfBF0IJjqHmtJA343WT2ROo=", + "dev": true, + "requires": { + "postcss": "^5.0.4" + } + }, + "postcss-reduce-transforms": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz", + "integrity": "sha1-/3b02CEkN7McKYpC0uFEQCV3GuE=", + "dev": true, + "requires": { + "has": "^1.0.1", + "postcss": "^5.0.8", + "postcss-value-parser": "^3.0.1" + } + }, + "postcss-selector-parser": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz", + "integrity": "sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A=", + "dev": true, + "requires": { + "flatten": "^1.0.2", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "postcss-svgo": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-2.1.6.tgz", + "integrity": "sha1-tt8YqmE7Zm4TPwittSGcJoSsEI0=", + "dev": true, + "requires": { + "is-svg": "^2.0.0", + "postcss": "^5.0.14", + "postcss-value-parser": "^3.2.3", + "svgo": "^0.7.0" + } + }, + "postcss-unique-selectors": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz", + "integrity": "sha1-mB1X0p3csz57Hf4f1DuGSfkzyh0=", + "dev": true, + "requires": { + "alphanum-sort": "^1.0.1", + "postcss": "^5.0.4", + "uniqs": "^2.0.0" + } + }, + "postcss-value-parser": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz", + "integrity": "sha1-h/OPnxj3dKSrTIojL1xc6IcqnRU=", + "dev": true + }, + "postcss-zindex": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-2.2.0.tgz", + "integrity": "sha1-0hCd3AVbka9n/EyzsCWUZjnSryI=", + "dev": true, + "requires": { + "has": "^1.0.1", + "postcss": "^5.0.4", + "uniqs": "^2.0.0" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", + "dev": true + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "pretty-bytes": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-4.0.2.tgz", + "integrity": "sha1-sr+C5zUNZcbDOqlaqlpPYyf2HNk=", + "dev": true + }, + "pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", + "dev": true + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha1-o31zL0JxtKsa0HDTVQjoKQeI/6o=", + "dev": true + }, + "progress": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", + "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", + "dev": true + }, + "promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha1-BktyYCsY+Q8pGSuLG8QY/9Hr078=", + "dev": true, + "optional": true, + "requires": { + "asap": "~2.0.3" + } + }, + "promisify-call": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/promisify-call/-/promisify-call-2.0.4.tgz", + "integrity": "sha1-1IwtRWUszM1SgB3ey9UzptS9X7o=", + "dev": true, + "optional": true, + "requires": { + "with-callback": "^1.0.2" + } + }, + "proxy-agent": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-3.0.3.tgz", + "integrity": "sha512-PXVVVuH9tiQuxQltFJVSnXWuDtNr+8aNBP6XVDDCDiUuDN8eRCm+ii4/mFWmXWEA0w8jjJSlePa4LXlM4jIzNA==", + "dev": true, + "optional": true, + "requires": { + "agent-base": "^4.2.0", + "debug": "^3.1.0", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^2.2.1", + "lru-cache": "^4.1.2", + "pac-proxy-agent": "^3.0.0", + "proxy-from-env": "^1.0.0", + "socks-proxy-agent": "^4.0.1" + }, + "dependencies": { + "debug": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.5.tgz", + "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", + "dev": true, + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "lru-cache": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", + "integrity": "sha1-oRdc80lt/IQ2wVbDNLSVWZK85pw=", + "dev": true, + "optional": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true, + "optional": true + } + } + }, + "proxy-from-env": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", + "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=", + "dev": true, + "optional": true + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true, + "optional": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true, + "optional": true + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true + }, + "qjobs": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", + "integrity": "sha1-xF6cYYAL0IfviNfiVkI73Unl0HE=", + "dev": true + }, + "qs": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-4.0.0.tgz", + "integrity": "sha1-wx2bdOwn33XlQ6hseHKO2NRiNgc=", + "dev": true + }, + "query-string": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", + "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", + "dev": true, + "requires": { + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + } + }, + "random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=", + "dev": true + }, + "randomatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.0.tgz", + "integrity": "sha512-KnGPVE0lo2WoXxIZ7cPR8YBpiol4gsSuOwDSg410oHh80ZMp5EiypNqL2K4Z77vJn6lB5rap7IkAmcUlalcnBQ==", + "dev": true, + "requires": { + "is-number": "^4.0.0", + "kind-of": "^6.0.0", + "math-random": "^1.0.1" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, + "range-parser": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.3.tgz", + "integrity": "sha1-aHKCNTXGkuLCoBA4Jq/YLC4P8XU=", + "dev": true + }, + "raw-body": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz", + "integrity": "sha1-rf6s4uT7MJgFgBTQjActzFl1h3Q=", + "dev": true, + "requires": { + "bytes": "2.4.0", + "iconv-lite": "0.4.13", + "unpipe": "1.0.0" + }, + "dependencies": { + "bytes": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", + "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=", + "dev": true + }, + "iconv-lite": { + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", + "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=", + "dev": true + } + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha1-zZJL9SAKB1uDwYjNa54hG3/A0+0=", + "dev": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "read-all-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/read-all-stream/-/read-all-stream-3.1.0.tgz", + "integrity": "sha1-NcPhd/IHjveJ7kv6+kNzB06u9Po=", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0", + "readable-stream": "^2.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "^1.1.6" + } + }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "dev": true, + "requires": { + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" + } + }, + "redis": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/redis/-/redis-2.8.0.tgz", + "integrity": "sha1-ICKI4/WMSfYHnZevehDhMDrhSwI=", + "dev": true, + "optional": true, + "requires": { + "double-ended-queue": "^2.1.0-0", + "redis-commands": "^1.2.0", + "redis-parser": "^2.6.0" + } + }, + "redis-commands": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.3.5.tgz", + "integrity": "sha1-RJWIlBTx6IYmEYCxRC5ylWAtg6I=", + "dev": true, + "optional": true + }, + "redis-parser": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-2.6.0.tgz", + "integrity": "sha1-Uu0J2srBCPGmMcB+m2mUHnoZUEs=", + "dev": true, + "optional": true + }, + "reduce-css-calc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz", + "integrity": "sha1-dHyRTgSWFKTJz7umKYca0dKSdxY=", + "dev": true, + "requires": { + "balanced-match": "^0.4.2", + "math-expression-evaluator": "^1.2.14", + "reduce-function-call": "^1.0.1" + }, + "dependencies": { + "balanced-match": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", + "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", + "dev": true + } + } + }, + "reduce-function-call": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/reduce-function-call/-/reduce-function-call-1.0.2.tgz", + "integrity": "sha1-WiAL+S4ON3UXUv5FsKszD9S2vpk=", + "dev": true, + "requires": { + "balanced-match": "^0.4.2" + }, + "dependencies": { + "balanced-match": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", + "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", + "dev": true + } + } + }, + "regenerate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", + "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", + "dev": true + }, + "regenerate-unicode-properties": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-7.0.0.tgz", + "integrity": "sha512-s5NGghCE4itSlUS+0WUj88G6cfMVMmH8boTPNvABf8od+2dhT9WDlWu8n01raQAJZMOK8Ch6jSexaRO7swd6aw==", + "dev": true, + "requires": { + "regenerate": "^1.4.0" + } + }, + "regenerator-transform": { + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.13.3.tgz", + "integrity": "sha512-5ipTrZFSq5vU2YoGoww4uaRVAK4wyYC4TSICibbfEPOruUu8FFP7ErV0BjmbIOEpn3O/k9na9UEdYR/3m7N6uA==", + "dev": true, + "requires": { + "private": "^0.1.6" + } + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha1-db3FiioUls7EihKDW8VMjVYjNt0=", + "dev": true, + "requires": { + "is-equal-shallow": "^0.1.3" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha1-H07OJ+ALC2XgJHpoEOaoXYOldSw=", + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "regexpp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.0.tgz", + "integrity": "sha1-sqdTSoXKGwM7z1zp/45W1OB1U2U=", + "dev": true + }, + "regexpu-core": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.2.0.tgz", + "integrity": "sha512-Z835VSnJJ46CNBttalHD/dB+Sj2ezmY6Xp38npwU87peK6mqOzOpV8eYktdkLTEkzzD+JsTcxd84ozd8I14+rw==", + "dev": true, + "requires": { + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^7.0.0", + "regjsgen": "^0.4.0", + "regjsparser": "^0.3.0", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.0.2" + } + }, + "regjsgen": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.4.0.tgz", + "integrity": "sha512-X51Lte1gCYUdlwhF28+2YMO0U6WeN0GLpgpA7LK7mbdDnkQYiwvEpmpe0F/cv5L14EbxgrdayAG3JETBv0dbXA==", + "dev": true + }, + "regjsparser": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.3.0.tgz", + "integrity": "sha512-zza72oZBBHzt64G7DxdqrOo/30bhHkwMUoT0WqfGu98XLd7N+1tsy5MJ96Bk4MD0y74n629RhmrGW6XlnLLwCA==", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + } + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "^1.0.0" + } + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "request": { + "version": "2.81.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", + "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", + "dev": true, + "requires": { + "aws-sign2": "~0.6.0", + "aws4": "^1.2.1", + "caseless": "~0.12.0", + "combined-stream": "~1.0.5", + "extend": "~3.0.0", + "forever-agent": "~0.6.1", + "form-data": "~2.1.1", + "har-validator": "~4.2.1", + "hawk": "~3.1.3", + "http-signature": "~1.1.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.7", + "oauth-sign": "~0.8.1", + "performance-now": "^0.2.0", + "qs": "~6.4.0", + "safe-buffer": "^5.0.1", + "stringstream": "~0.0.4", + "tough-cookie": "~2.3.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.0.0" + }, + "dependencies": { + "qs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", + "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + } + } + }, + "request-progress": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-2.0.1.tgz", + "integrity": "sha1-XTa7V5YcZzqlt4jbyBQf3yO0Tgg=", + "dev": true, + "requires": { + "throttleit": "^1.0.0" + } + }, + "requestretry": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/requestretry/-/requestretry-1.13.0.tgz", + "integrity": "sha1-IT7BAG7rdQ6LjOVBdig9FajVXZQ=", + "dev": true, + "optional": true, + "requires": { + "extend": "^3.0.0", + "lodash": "^4.15.0", + "request": "^2.74.0", + "when": "^3.7.7" + } + }, + "require-from-string": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz", + "integrity": "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg=", + "dev": true + }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "dev": true, + "requires": { + "caller-path": "^0.1.0", + "resolve-from": "^1.0.0" + } + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, + "resolve": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", + "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", + "dev": true, + "requires": { + "path-parse": "^1.0.5" + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + } + }, + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "dev": true + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "response-time": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/response-time/-/response-time-2.3.2.tgz", + "integrity": "sha1-/6cbq5UtYvfB1Jt0NDVfvGjf/Fo=", + "dev": true, + "requires": { + "depd": "~1.1.0", + "on-headers": "~1.0.1" + }, + "dependencies": { + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + } + } + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha1-uKSCXVvbH8P29Twrwz+BOIaBx7w=", + "dev": true + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "dev": true, + "requires": { + "align-text": "^0.1.1" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=", + "dev": true, + "requires": { + "glob": "^7.0.5" + } + }, + "rndm": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz", + "integrity": "sha1-8z/pz7Urv9UgqhgyO8ZdsRCht2w=", + "dev": true + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "dev": true, + "requires": { + "is-promise": "^2.1.0" + } + }, + "run-sequence": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/run-sequence/-/run-sequence-2.2.1.tgz", + "integrity": "sha1-HOZD2jb9jH6n4akynaM/wriJhJU=", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "fancy-log": "^1.3.2", + "plugin-error": "^0.1.2" + }, + "dependencies": { + "arr-diff": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz", + "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1", + "array-slice": "^0.2.3" + } + }, + "arr-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz", + "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=", + "dev": true + }, + "array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", + "dev": true + }, + "extend-shallow": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz", + "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", + "dev": true, + "requires": { + "kind-of": "^1.1.0" + } + }, + "kind-of": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", + "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=", + "dev": true + }, + "plugin-error": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", + "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", + "dev": true, + "requires": { + "ansi-cyan": "^0.1.1", + "ansi-red": "^0.1.1", + "arr-diff": "^1.0.1", + "arr-union": "^2.0.1", + "extend-shallow": "^1.1.2" + } + } + } + }, + "rxjs": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz", + "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0=", + "dev": true + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo=", + "dev": true + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha1-KBYjTiN4vdxOU1T6tcqold9xANk=", + "dev": true + }, + "seek-bzip": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz", + "integrity": "sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=", + "dev": true, + "requires": { + "commander": "~2.8.1" + } + }, + "select": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", + "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=" + }, + "semver": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", + "dev": true + }, + "semver-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-1.0.0.tgz", + "integrity": "sha1-kqSWkGX5xwxpR1PVUkj8aPj2Usk=", + "dev": true, + "optional": true + }, + "semver-truncate": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/semver-truncate/-/semver-truncate-1.1.2.tgz", + "integrity": "sha1-V/Qd5pcHpicJp+AQS6IRcQnqR+g=", + "dev": true, + "optional": true, + "requires": { + "semver": "^5.3.0" + }, + "dependencies": { + "semver": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", + "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==", + "dev": true, + "optional": true + } + } + }, + "send": { + "version": "0.13.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.13.2.tgz", + "integrity": "sha1-dl52B8gFVFK7pvCwUllTUJhgNt4=", + "dev": true, + "requires": { + "debug": "~2.2.0", + "depd": "~1.1.0", + "destroy": "~1.0.4", + "escape-html": "~1.0.3", + "etag": "~1.7.0", + "fresh": "0.3.0", + "http-errors": "~1.3.1", + "mime": "1.3.4", + "ms": "0.7.1", + "on-finished": "~2.3.0", + "range-parser": "~1.0.3", + "statuses": "~1.2.1" + }, + "dependencies": { + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + }, + "statuses": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz", + "integrity": "sha1-3e1FzBglbVHtQK7BQkidXGECbSg=", + "dev": true + } + } + }, + "sequencify": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", + "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", + "dev": true + }, + "serve-favicon": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.3.2.tgz", + "integrity": "sha1-3UGeJo3gEqtysxnTN/IQUBP5OB8=", + "dev": true, + "requires": { + "etag": "~1.7.0", + "fresh": "0.3.0", + "ms": "0.7.2", + "parseurl": "~1.3.1" + }, + "dependencies": { + "ms": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", + "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", + "dev": true + } + } + }, + "serve-index": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.7.3.tgz", + "integrity": "sha1-egV/xu4o3GP2RWbl+lexEahq7NI=", + "dev": true, + "requires": { + "accepts": "~1.2.13", + "batch": "0.5.3", + "debug": "~2.2.0", + "escape-html": "~1.0.3", + "http-errors": "~1.3.1", + "mime-types": "~2.1.9", + "parseurl": "~1.3.1" + }, + "dependencies": { + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + } + } + }, + "serve-static": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.10.3.tgz", + "integrity": "sha1-zlpuzTEB/tXsCYJ9rCKpwpv7BTU=", + "dev": true, + "requires": { + "escape-html": "~1.0.3", + "parseurl": "~1.3.1", + "send": "0.13.2" + } + }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true + }, + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha1-ca5KiPD+77v1LR6mBPP7MV67YnQ=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha1-0L2FU2iHtv58DYGMuWLZ2RxU5lY=", + "dev": true + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "signalr": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/signalr/-/signalr-2.3.0.tgz", + "integrity": "sha512-NrvIGftLz3QVujdjCvaNso56ltTr1FowSR0DCIaSOJ3J4t5pTebTfnh2VT0HHIM3PJ/v15lukIL4y+8MMknqzg==", + "requires": { + "jquery": ">=1.6.4" + } + }, + "slack-node": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/slack-node/-/slack-node-0.2.0.tgz", + "integrity": "sha1-3kuN3aqLeT9h29KTgQT9q/N9+jA=", + "dev": true, + "optional": true, + "requires": { + "requestretry": "^1.2.2" + } + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "slice-ansi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha1-BE8aSdiEL/MHqta1Be0Xi9lQE00=", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0" + } + }, + "smart-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.0.1.tgz", + "integrity": "sha512-RFqinRVJVcCAL9Uh1oVqE6FZkqsyLiVOYEZ20TqIOjuX7iFVJ+zsbs4RIghnw/pTs7mZvt8ZHhvm1ZUrR4fykg==", + "dev": true + }, + "smtp-connection": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.12.0.tgz", + "integrity": "sha1-1275EnyyPCJZ7bHoNJwujV4tdME=", + "dev": true, + "requires": { + "httpntlm": "1.6.1", + "nodemailer-shared": "1.1.0" + } + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha1-ZJIufFZbDhQgS6GqfWlkJ40lGC0=", + "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha1-bBdfhv8UvbByRWPo88GwIaKGhTs=", + "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI=", + "dev": true, + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "sntp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "dev": true, + "requires": { + "hoek": "2.x.x" + } + }, + "socket.io": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.0.4.tgz", + "integrity": "sha1-waRZDO/4fs8TxyZS8Eb3FrKeYBQ=", + "dev": true, + "requires": { + "debug": "~2.6.6", + "engine.io": "~3.1.0", + "socket.io-adapter": "~1.1.0", + "socket.io-client": "2.0.4", + "socket.io-parser": "~3.1.1" + } + }, + "socket.io-adapter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", + "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=", + "dev": true + }, + "socket.io-client": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.0.4.tgz", + "integrity": "sha1-CRilUkBtxeVAs4Dc2Xr8SmQzL44=", + "dev": true, + "requires": { + "backo2": "1.0.2", + "base64-arraybuffer": "0.1.5", + "component-bind": "1.0.0", + "component-emitter": "1.2.1", + "debug": "~2.6.4", + "engine.io-client": "~3.1.0", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "object-component": "0.0.3", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "socket.io-parser": "~3.1.1", + "to-array": "0.1.4" + } + }, + "socket.io-parser": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.1.3.tgz", + "integrity": "sha1-7S2l7nnxCVUDbj2kE7/X8eTYbI4=", + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "has-binary2": "~1.0.2", + "isarray": "2.0.1" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true + } + } + }, + "socks": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.2.1.tgz", + "integrity": "sha512-0GabKw7n9mI46vcNrVfs0o6XzWzjVa3h6GaSo2UPxtWAROXUWavfJWh1M4PR5tnE0dcnQXZIDFP4yrAysLze/w==", + "dev": true, + "requires": { + "ip": "^1.1.5", + "smart-buffer": "^4.0.1" + } + }, + "socks-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.1.tgz", + "integrity": "sha1-WTa/i3B6mTB5xvN9sgkYIb/6ZHM=", + "dev": true, + "requires": { + "agent-base": "~4.2.0", + "socks": "~2.2.0" + } + }, + "sort-keys": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", + "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", + "dev": true, + "requires": { + "is-plain-obj": "^1.0.0" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "dev": true, + "requires": { + "atob": "^2.1.1", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "sparkles": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", + "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", + "dev": true + }, + "spdx-correct": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.1.tgz", + "integrity": "sha512-hxSPZbRZvSDuOvADntOElzJpenIR7wXJkuoUcUtS0erbgt2fgeaoPIYretfKpslMhfFDY4k0MZ2F5CUzhBsSvQ==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha1-meEZt6XaAOBUkcn6M4t5BII7QdA=", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.1.tgz", + "integrity": "sha512-TfOfPcYGBB5sDuPn3deByxPhmfegAhpDYKSOXZQN81Oyrrif8ZCodOLzK3AesELnCx03kikhyDwh0pfvvQvF8w==", + "dev": true + }, + "split": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "dev": true, + "requires": { + "through": "2" + } + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha1-fLCd2jqGWFcFxks5pkZgOGguj+I=", + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "squeak": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/squeak/-/squeak-1.3.0.tgz", + "integrity": "sha1-MwRQN7ZDiLVnZ0uEMiplIQc5FsM=", + "dev": true, + "optional": true, + "requires": { + "chalk": "^1.0.0", + "console-stream": "^0.1.1", + "lpad-align": "^1.0.1" + } + }, + "sshpk": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz", + "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", + "dev": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha1-g26zyDgv4pNv6vVEYxAXzn1Ho88=", + "dev": true, + "optional": true + }, + "stat-mode": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-0.2.2.tgz", + "integrity": "sha1-5sgLYjEj19gM8TLOU480YokHJQI=", + "dev": true + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true + }, + "stream-combiner": { + "version": "0.2.2", + "resolved": "http://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", + "integrity": "sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=", + "dev": true, + "requires": { + "duplexer": "~0.1.1", + "through": "~2.3.4" + } + }, + "stream-combiner2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", + "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", + "dev": true, + "requires": { + "duplexer2": "~0.1.0", + "readable-stream": "^2.0.2" + }, + "dependencies": { + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "dev": true, + "requires": { + "readable-stream": "^2.0.2" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "stream-consume": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.1.tgz", + "integrity": "sha1-0721mMK9CugrjKx6xQsRB6eZbEg=", + "dev": true + }, + "stream-counter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/stream-counter/-/stream-counter-0.2.0.tgz", + "integrity": "sha1-3tJmVWMZyLDiIoErnPOyb6fZR94=", + "dev": true, + "requires": { + "readable-stream": "~1.1.8" + } + }, + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", + "dev": true + }, + "streamroller": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", + "integrity": "sha1-odG3z4PTmvsNYwSaWsv5NJO99ks=", + "dev": true, + "requires": { + "date-format": "^1.2.0", + "debug": "^3.1.0", + "mkdirp": "^0.5.1", + "readable-stream": "^2.3.0" + }, + "dependencies": { + "debug": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.5.tgz", + "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha1-sRwn2IuP8fvgcGQ8+UsMea4bCq8=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "stringstream": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz", + "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", + "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", + "dev": true, + "requires": { + "first-chunk-stream": "^1.0.0", + "is-utf8": "^0.2.0" + } + }, + "strip-bom-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz", + "integrity": "sha1-5xRDmFd9Uaa+0PoZlPoF9D/ZiO4=", + "dev": true, + "requires": { + "first-chunk-stream": "^1.0.0", + "strip-bom": "^2.0.0" + }, + "dependencies": { + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + } + } + }, + "strip-dirs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-1.1.1.tgz", + "integrity": "sha1-lgu9EoeETzl1pFWKoQOoJV4kVqA=", + "dev": true, + "requires": { + "chalk": "^1.0.0", + "get-stdin": "^4.0.1", + "is-absolute": "^0.1.5", + "is-natural-number": "^2.0.0", + "minimist": "^1.1.0", + "sum-up": "^1.0.1" + }, + "dependencies": { + "is-absolute": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-0.1.7.tgz", + "integrity": "sha1-hHSREZ/MtftDYhfMc39/qtUPYD8=", + "dev": true, + "requires": { + "is-relative": "^0.1.0" + } + }, + "is-relative": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.1.3.tgz", + "integrity": "sha1-kF/uiuhvRbPsYUvDwVyGnfCHboI=", + "dev": true + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true, + "optional": true + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "dev": true, + "requires": { + "get-stdin": "^4.0.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "strip-outer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha1-sv0qv2YEudHmATBXGV34Nrip1jE=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.2" + } + }, + "sum-up": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sum-up/-/sum-up-1.0.3.tgz", + "integrity": "sha1-HGYfZnBX9jvLeHWqFDi8FiUlFW4=", + "dev": true, + "requires": { + "chalk": "^1.0.0" + } + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "^1.0.0" + } + }, + "svgo": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-0.7.2.tgz", + "integrity": "sha1-n1dyQTlSE1xv779Ar+ak+qiLS7U=", + "dev": true, + "requires": { + "coa": "~1.0.1", + "colors": "~1.1.2", + "csso": "~2.3.1", + "js-yaml": "~3.7.0", + "mkdirp": "~0.5.1", + "sax": "~1.2.1", + "whet.extend": "~0.9.9" + }, + "dependencies": { + "colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", + "dev": true + } + } + }, + "table": { + "version": "4.0.3", + "resolved": "http://registry.npmjs.org/table/-/table-4.0.3.tgz", + "integrity": "sha512-S7rnFITmBH1EnyKcvxBh1LjYeQMmnZtCXSEbHcH6S0NoKit24ZuFO/T1vDcLdYsLQkM188PVVhQmzKIuThNkKg==", + "dev": true, + "requires": { + "ajv": "^6.0.1", + "ajv-keywords": "^3.0.0", + "chalk": "^2.1.0", + "lodash": "^4.17.4", + "slice-ansi": "1.0.0", + "string-width": "^2.1.1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "tar-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "dev": true, + "requires": { + "bl": "^1.0.0", + "buffer-alloc": "^1.2.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.1", + "xtend": "^4.0.0" + }, + "dependencies": { + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha1-7SljTRm6ukY7bOa4CjchPqtx7EM=", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "temp-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz", + "integrity": "sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0=", + "dev": true, + "optional": true + }, + "tempfile": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tempfile/-/tempfile-2.0.0.tgz", + "integrity": "sha1-awRGhWqbERTRhW/8vlCczLCXcmU=", + "dev": true, + "optional": true, + "requires": { + "temp-dir": "^1.0.0", + "uuid": "^3.0.1" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "throttleit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", + "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "^2.1.5", + "xtend": "~4.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha1-sRwn2IuP8fvgcGQ8+UsMea4bCq8=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "through2-concurrent": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/through2-concurrent/-/through2-concurrent-1.1.1.tgz", + "integrity": "sha1-EctOpMnjG8puTB5tukjRxyjDUks=", + "dev": true, + "requires": { + "through2": "^2.0.0" + } + }, + "through2-filter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz", + "integrity": "sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=", + "dev": true, + "requires": { + "through2": "~2.0.0", + "xtend": "~4.0.0" + } + }, + "thunkify": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/thunkify/-/thunkify-2.1.2.tgz", + "integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0=", + "dev": true, + "optional": true + }, + "tildify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", + "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", + "dev": true, + "requires": { + "os-homedir": "^1.0.0" + } + }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true + }, + "timed-out": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-3.1.3.tgz", + "integrity": "sha1-lYYL/MXHbCd/j4Mm/Q9bLiDrohc=", + "dev": true + }, + "timespan": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/timespan/-/timespan-2.3.0.tgz", + "integrity": "sha1-SQLOBAvRPYRcj1myfp1ZutbzmSk=", + "dev": true, + "optional": true + }, + "tiny-emitter": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.0.2.tgz", + "integrity": "sha512-2NM0auVBGft5tee/OxP4PI3d8WItkDM+fPnaRAVo6xTDI2knbz9eC5ArWGqtGlYqiH3RU5yMpdyTTO7MguC4ow==" + }, + "tiny-lr": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-0.2.1.tgz", + "integrity": "sha1-s/26gC5dVqM8L28QeUsy5Hescp0=", + "dev": true, + "requires": { + "body-parser": "~1.14.0", + "debug": "~2.2.0", + "faye-websocket": "~0.10.0", + "livereload-js": "^2.2.0", + "parseurl": "~1.3.0", + "qs": "~5.1.0" + }, + "dependencies": { + "body-parser": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.14.2.tgz", + "integrity": "sha1-EBXLH+LEQ4WCWVgdtTMy+NDPUPk=", + "dev": true, + "requires": { + "bytes": "2.2.0", + "content-type": "~1.0.1", + "debug": "~2.2.0", + "depd": "~1.1.0", + "http-errors": "~1.3.1", + "iconv-lite": "0.4.13", + "on-finished": "~2.3.0", + "qs": "5.2.0", + "raw-body": "~2.1.5", + "type-is": "~1.6.10" + }, + "dependencies": { + "qs": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-5.2.0.tgz", + "integrity": "sha1-qfMRQq9GjLcrJbMBNrokVoNJFr4=", + "dev": true + } + } + }, + "bytes": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.2.0.tgz", + "integrity": "sha1-/TVGSkA/b5EXwt42Cez/nK4ABYg=", + "dev": true + }, + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "iconv-lite": { + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", + "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=", + "dev": true + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + }, + "qs": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-5.1.0.tgz", + "integrity": "sha1-TZMuXH6kEcynajEtOaYGIA/VDNk=", + "dev": true + } + } + }, + "tinymce": { + "version": "4.7.13", + "resolved": "https://registry.npmjs.org/tinymce/-/tinymce-4.7.13.tgz", + "integrity": "sha512-6QbNYGV4VExH+p7+o/5km6jOnVSD5mO7aw0s+eKByKnpyG8gZfajxXPhwBM57r7SIravrCI6LFj8DARNe31qPw==" + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha1-bTQzWIl2jSGyvNoKonfO07G/rfk=", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "to-absolute-glob": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz", + "integrity": "sha1-HN+kcqnvUMI57maZm2YsoOs5k38=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "to-array": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", + "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", + "dev": true + }, + "to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha1-STvUj2LXxD/N7TE6A9ytsuEhOoA=", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha1-E8/dmzNlUvMLUfM6iuG0Knp1mc4=", + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "tough-cookie": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha1-7GDO44rGdQY//JelwYlwV47oNlU=", + "dev": true, + "requires": { + "punycode": "^1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + } + } + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + }, + "trim-repeated": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.2" + } + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, + "tryit": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz", + "integrity": "sha1-OTvnMKlEb9Hq1tpZoBQwjzbCics=", + "dev": true + }, + "tslib": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", + "dev": true + }, + "tsscmp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.5.tgz", + "integrity": "sha1-fcSjOvcVgatDN9qR2FylQn69mpc=", + "dev": true + }, + "tunnel-agent": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", + "dev": true + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true, + "optional": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "type-is": { + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha1-+JzjQVQcZysl7nrjxz3uOyvlAZQ=", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.18" + } + }, + "typeahead.js": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/typeahead.js/-/typeahead.js-0.10.5.tgz", + "integrity": "sha1-HZlxsPRNOF/q2/IsnzadtWKRLeE=" + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "dev": true, + "requires": { + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "dev": true, + "optional": true + }, + "uid-safe": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.4.tgz", + "integrity": "sha1-Otbzg2jG1MjHXsF2I/t5qh0HHYE=", + "dev": true, + "requires": { + "random-bytes": "~1.0.0" + } + }, + "ultron": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha1-n+FTahCmZKZSZqHjzPhf02MCvJw=", + "dev": true + }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", + "dev": true + }, + "underscore": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", + "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==" + }, + "unicode-canonical-property-names-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", + "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", + "dev": true + }, + "unicode-match-property-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", + "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", + "dev": true, + "requires": { + "unicode-canonical-property-names-ecmascript": "^1.0.4", + "unicode-property-aliases-ecmascript": "^1.0.4" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.0.2.tgz", + "integrity": "sha512-Rx7yODZC1L/T8XKo/2kNzVAQaRE88AaMvI1EF/Xnj3GW2wzN6fop9DDWuFAKUVFH7vozkz26DzP0qyWLKLIVPQ==", + "dev": true + }, + "unicode-property-aliases-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.4.tgz", + "integrity": "sha512-2WSLa6OdYd2ng8oqiGIWnJqyFArvhn+5vgx5GTxMbUYjCYKUcuKS62YLFF0R/BDGlB1yzXjQOLtPAfHsgirEpg==", + "dev": true + }, + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^0.4.3" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.1", + "to-object-path": "^0.3.0" + } + } + } + }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", + "dev": true + }, + "uniqs": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", + "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=", + "dev": true + }, + "unique-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", + "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=", + "dev": true + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true + }, + "unquote": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", + "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=", + "dev": true, + "optional": true + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + } + } + }, + "unzip-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-1.0.2.tgz", + "integrity": "sha1-uYTwh3/AqJwsdzzB73tbIytbBv4=", + "dev": true + }, + "upath": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", + "integrity": "sha1-NSVll+RqWB20eT0M5H+prr/J+r0=", + "dev": true + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha1-lMVA4f93KVbiKZUHwBCupsiDjrA=", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "dev": true, + "requires": { + "prepend-http": "^1.0.1" + } + }, + "url-regex": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/url-regex/-/url-regex-3.2.0.tgz", + "integrity": "sha1-260eDJ4p4QXdCx8J9oYvf9tIJyQ=", + "dev": true, + "optional": true, + "requires": { + "ip-regex": "^1.0.1" + } + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", + "dev": true + }, + "useragent": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.2.1.tgz", + "integrity": "sha1-z1k+9PLRdYdei7ZY6pLhik/QbY4=", + "dev": true, + "requires": { + "lru-cache": "2.2.x", + "tmp": "0.0.x" + }, + "dependencies": { + "lru-cache": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.2.4.tgz", + "integrity": "sha1-bGWGGb7PFAMdDQtZSxYELOTcBj0=", + "dev": true + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "util.promisify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", + "integrity": "sha1-RA9xZaRZyaFtwUXrjnLzVocJcDA=", + "dev": true, + "optional": true, + "requires": { + "define-properties": "^1.1.2", + "object.getownpropertydescriptors": "^2.0.3" + } + }, + "utils-merge": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", + "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=", + "dev": true + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "dev": true + }, + "uws": { + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/uws/-/uws-9.14.0.tgz", + "integrity": "sha1-+sg4a+/DOno3BcvVjcR7Qwyk3ZU=", + "dev": true, + "optional": true + }, + "v8flags": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", + "dev": true, + "requires": { + "user-home": "^1.1.1" + } + }, + "vali-date": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz", + "integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "vary": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.0.1.tgz", + "integrity": "sha1-meSYFWaihhGN+yuBc1ffeZM3bRA=", + "dev": true + }, + "vendors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.2.tgz", + "integrity": "sha1-f8te759WI7FWvOqJ7DfWNnbyGAE=", + "dev": true + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "vhost": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/vhost/-/vhost-3.0.2.tgz", + "integrity": "sha1-L7HezUxGaqiLD5NBrzPcGv8keNU=", + "dev": true + }, + "vinyl": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", + "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", + "dev": true, + "requires": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + } + }, + "vinyl-assign": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/vinyl-assign/-/vinyl-assign-1.2.1.tgz", + "integrity": "sha1-TRmIkbVRWRHXcajNnFSApGoHSkU=", + "dev": true, + "requires": { + "object-assign": "^4.0.1", + "readable-stream": "^2.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "vinyl-bufferstream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vinyl-bufferstream/-/vinyl-bufferstream-1.0.1.tgz", + "integrity": "sha1-BTeGn1gO/6TKRay0dXnkuf5jCBo=", + "dev": true, + "requires": { + "bufferstreams": "1.0.1" + } + }, + "vinyl-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/vinyl-file/-/vinyl-file-2.0.0.tgz", + "integrity": "sha1-p+v1/779obfRjRQPyweyI++2dRo=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.3.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0", + "strip-bom-stream": "^2.0.0", + "vinyl": "^1.1.0" + }, + "dependencies": { + "first-chunk-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-2.0.0.tgz", + "integrity": "sha1-G97NuOCDwGZLkZRVgVd6Q6nzHXA=", + "dev": true, + "requires": { + "readable-stream": "^2.0.2" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + }, + "strip-bom-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-2.0.0.tgz", + "integrity": "sha1-+H217yYT9paKpUWr/h7HKLaoKco=", + "dev": true, + "requires": { + "first-chunk-stream": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + } + } + } + }, + "vinyl-fs": { + "version": "0.3.14", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", + "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", + "dev": true, + "requires": { + "defaults": "^1.0.0", + "glob-stream": "^3.1.5", + "glob-watcher": "^0.0.6", + "graceful-fs": "^3.0.0", + "mkdirp": "^0.5.0", + "strip-bom": "^1.0.0", + "through2": "^0.6.1", + "vinyl": "^0.4.0" + }, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "^0.2.0", + "clone-stats": "^0.0.1" + } + } + } + }, + "vinyl-sourcemaps-apply": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", + "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", + "dev": true, + "requires": { + "source-map": "^0.5.1" + } + }, + "void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", + "dev": true + }, + "ware": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ware/-/ware-1.3.0.tgz", + "integrity": "sha1-0bFPOdLiy0q4xAmPdW/ksWTkc9Q=", + "dev": true, + "requires": { + "wrap-fn": "^0.1.0" + } + }, + "websocket-driver": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", + "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", + "dev": true, + "requires": { + "http-parser-js": ">=0.4.0", + "websocket-extensions": ">=0.1.1" + } + }, + "websocket-extensions": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", + "integrity": "sha1-XS/yKXcAPsaHpLhwc9+7rBRszyk=", + "dev": true + }, + "when": { + "version": "3.7.8", + "resolved": "https://registry.npmjs.org/when/-/when-3.7.8.tgz", + "integrity": "sha1-xxMLan6gRpPoQs3J56Hyqjmjn4I=", + "dev": true + }, + "whet.extend": { + "version": "0.9.9", + "resolved": "https://registry.npmjs.org/whet.extend/-/whet.extend-0.9.9.tgz", + "integrity": "sha1-+HfVv2SMl+WqVC+twW1qJZucEaE=", + "dev": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true + }, + "with-callback": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/with-callback/-/with-callback-1.0.2.tgz", + "integrity": "sha1-oJYpuakgAo1yFAT7Q1vc/1yRvCE=", + "dev": true, + "optional": true + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "wrap-fn": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/wrap-fn/-/wrap-fn-0.1.5.tgz", + "integrity": "sha1-8htuQQFv9KfjFyDbxjoJAWvfmEU=", + "dev": true, + "requires": { + "co": "3.1.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + }, + "ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha1-8c+E/i1ekB686U767OeF8YeiKPI=", + "dev": true, + "requires": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" + } + }, + "xmlhttprequest-ssl": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", + "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", + "dev": true + }, + "xregexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", + "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=", + "dev": true, + "optional": true + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true, + "optional": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, + "requires": { + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "0.1.0" + }, + "dependencies": { + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true + } + } + }, + "yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "dev": true, + "requires": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "yeast": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", + "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=", + "dev": true + } + } +} From d1e377bc38fb383f7bbdb9eee59581e3c94ed4a6 Mon Sep 17 00:00:00 2001 From: Stephan Date: Thu, 25 Oct 2018 15:07:04 +0200 Subject: [PATCH 068/469] Cleanup BootFailedException --- .../Exceptions/BootFailedException.cs | 29 ++++++++++++++++++- src/Umbraco.Web/Composing/ModuleInjector.cs | 21 +++++++++++--- src/Umbraco.Web/UmbracoInjectedModule.cs | 15 ++-------- 3 files changed, 47 insertions(+), 18 deletions(-) diff --git a/src/Umbraco.Core/Exceptions/BootFailedException.cs b/src/Umbraco.Core/Exceptions/BootFailedException.cs index ec07389d37..10a648fd76 100644 --- a/src/Umbraco.Core/Exceptions/BootFailedException.cs +++ b/src/Umbraco.Core/Exceptions/BootFailedException.cs @@ -1,9 +1,10 @@ using System; +using System.Text; namespace Umbraco.Core.Exceptions { /// - /// An exception that is thrown if the Umbraco application cannnot boot. + /// An exception that is thrown if the Umbraco application cannot boot. /// public class BootFailedException : Exception { @@ -29,5 +30,31 @@ namespace Umbraco.Core.Exceptions public BootFailedException(string message, Exception inner) : base(message, inner) { } + + /// + /// Rethrows a captured . + /// + /// The exception can be null, in which case a default message is used. + public static void Rethrow(BootFailedException bootFailedException) + { + if (bootFailedException == null) + throw new BootFailedException(DefaultMessage); + + // see https://stackoverflow.com/questions/57383 + // would that be the correct way to do it? + //ExceptionDispatchInfo.Capture(bootFailedException).Throw(); + + Exception e = bootFailedException; + var m = new StringBuilder(); + m.Append(DefaultMessage); + while (e != null) + { + m.Append($"\n\n-> {e.GetType().FullName}: {e.Message}"); + if (string.IsNullOrWhiteSpace(e.StackTrace) == false) + m.Append($"\n{e.StackTrace}"); + e = e.InnerException; + } + throw new BootFailedException(m.ToString()); + } } } diff --git a/src/Umbraco.Web/Composing/ModuleInjector.cs b/src/Umbraco.Web/Composing/ModuleInjector.cs index 8ff8f407e1..c415d5ca6e 100644 --- a/src/Umbraco.Web/Composing/ModuleInjector.cs +++ b/src/Umbraco.Web/Composing/ModuleInjector.cs @@ -2,6 +2,7 @@ using System.Web; using Umbraco.Core; using Umbraco.Core.Composing; +using Umbraco.Core.Exceptions; namespace Umbraco.Web.Composing { @@ -21,16 +22,28 @@ namespace Umbraco.Web.Composing { // using the service locator here - no other way, really Module = Current.Container.GetInstance(); - Module.Init(context); } catch { - var runtimeState = Current.Container.GetInstance(); - if (runtimeState.BootFailedException != null) + // if GetInstance fails, it may be because of a boot error, in + // which case that is the error we actually want to report + IRuntimeState runtimeState = null; + + try { - throw new Exception("Failed to boot", runtimeState.BootFailedException); + runtimeState = Current.Container.GetInstance(); } + catch { /* don't make it worse */ } + + if (runtimeState?.BootFailedException != null) + BootFailedException.Rethrow(runtimeState.BootFailedException); + + // else... throw what we have + throw; } + + // initialize + Module.Init(context); } /// diff --git a/src/Umbraco.Web/UmbracoInjectedModule.cs b/src/Umbraco.Web/UmbracoInjectedModule.cs index 11670df51b..23d3e2fb5a 100644 --- a/src/Umbraco.Web/UmbracoInjectedModule.cs +++ b/src/Umbraco.Web/UmbracoInjectedModule.cs @@ -13,6 +13,7 @@ using Umbraco.Web.Routing; using Umbraco.Web.Security; using Umbraco.Core.Exceptions; using Umbraco.Core.Models.PublishedContent; +using Umbraco.Core.Persistence.FaultHandling; using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Web.Composing; @@ -458,19 +459,7 @@ namespace Umbraco.Web // also, if something goes wrong with our DI setup, the logging subsystem may // not even kick in, so here we try to give as much detail as possible - Exception e = Core.Composing.Current.RuntimeState.BootFailedException; - if (e == null) - throw new BootFailedException(BootFailedException.DefaultMessage); - var m = new StringBuilder(); - m.Append(BootFailedException.DefaultMessage); - while (e != null) - { - m.Append($"\n\n-> {e.GetType().FullName}: {e.Message}"); - if (string.IsNullOrWhiteSpace(e.StackTrace) == false) - m.Append($"\n{e.StackTrace}"); - e = e.InnerException; - } - throw new BootFailedException(m.ToString()); + BootFailedException.Rethrow(Core.Composing.Current.RuntimeState.BootFailedException); }; return; } From d7adf63a62d45034cea4bfff5a1fec4d5414add8 Mon Sep 17 00:00:00 2001 From: Stephan Date: Thu, 25 Oct 2018 15:07:55 +0200 Subject: [PATCH 069/469] Cleanup UmbracoContext registration --- src/Umbraco.Web/Runtime/WebRuntimeComponent.cs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs index 280fcce352..1e90c47c4a 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs @@ -89,10 +89,6 @@ namespace Umbraco.Web.Runtime // let's use an hybrid accessor that can fall back to a ThreadStatic context. composition.Container.RegisterSingleton(); - // review - Let's just keep the one, eh? (Line 104) - //// register the 'current' umbraco context - transient - for eg controllers - //composition.Container.Register(factory => factory.GetInstance().UmbracoContext, "TransientUmbracoContext"); - // register a per-request HttpContextBase object // is per-request so only one wrapper is created per request composition.Container.Register(factory => new HttpContextWrapper(factory.GetInstance().HttpContext), Lifetime.Request); @@ -100,11 +96,11 @@ namespace Umbraco.Web.Runtime // register the published snapshot accessor - the "current" published snapshot is in the umbraco context composition.Container.RegisterSingleton(); - // review - making the umbraco context and actual per request thing. See 9a4eecab0177a67b8e7670edadb4547f5c3271b9 - // register a per-request UmbracoContext object - // no real need to be per request but assuming it is faster - // fixme - this second registration really bugs me. re-purposing a (nameless) service? can't we force everything to use the accessor now? - composition.Container.Register(factory => factory.GetInstance().UmbracoContext, Lifetime.Request); + // we should stop injecting UmbracoContext and always inject IUmbracoContextAccessor, however at the moment + // there are tons of places (controllers...) which require UmbracoContext in their ctor - so let's register + // a way to inject the UmbracoContext - and register it per-request to be more efficient + //TODO: stop doing this + composition.Container.Register(factory => factory.GetInstance().UmbracoContext, Lifetime.Request); // register the umbraco helper composition.Container.RegisterSingleton(); From 2b1ba4580178d72cc7d44799858882c03b650493 Mon Sep 17 00:00:00 2001 From: Stephan Date: Thu, 25 Oct 2018 15:14:47 +0200 Subject: [PATCH 070/469] Cleanup, refactor components --- src/Umbraco.Core/Components/BootLoader.cs | 25 +----------- .../Components/IUmbracoComponent.cs | 14 +------ .../Components/IUmbracoUserComponent.cs | 2 +- .../Components/RequireComponentAttribute.cs | 8 ++-- .../Components/RequiredComponentAttribute.cs | 9 ++--- .../Components/UmbracoComponentBase.cs | 6 +-- .../Components/UmbracoCoreComponent.cs | 9 ----- .../Components/UmbracoCoreComponentBase.cs | 8 ++++ .../Components/UmbracoUserComponentBase.cs | 8 ++++ .../Runtime/CoreRuntimeComponent.cs | 38 +++++++----------- src/Umbraco.Core/Umbraco.Core.csproj | 3 +- .../Components/ComponentTests.cs | 39 ++----------------- 12 files changed, 47 insertions(+), 122 deletions(-) delete mode 100644 src/Umbraco.Core/Components/UmbracoCoreComponent.cs create mode 100644 src/Umbraco.Core/Components/UmbracoCoreComponentBase.cs create mode 100644 src/Umbraco.Core/Components/UmbracoUserComponentBase.cs diff --git a/src/Umbraco.Core/Components/BootLoader.cs b/src/Umbraco.Core/Components/BootLoader.cs index c0b9915fbd..e2ab754956 100644 --- a/src/Umbraco.Core/Components/BootLoader.cs +++ b/src/Umbraco.Core/Components/BootLoader.cs @@ -48,7 +48,6 @@ namespace Umbraco.Core.Components InstantiateComponents(orderedComponentTypes); ComposeComponents(level); - RegisterInitializers(); using (var scope = _container.GetInstance().CreateScope()) { @@ -82,10 +81,6 @@ namespace Umbraco.Core.Components }) .ToList(); - // cannot remove that one - ever - if (componentTypeList.Contains(typeof(UmbracoCoreComponent)) == false) - componentTypeList.Add(typeof(UmbracoCoreComponent)); - // enable or disable components EnableDisableComponents(componentTypeList); @@ -113,7 +108,7 @@ namespace Umbraco.Core.Components { // in case of an error, force-dump everything to log _logger.Info("Component Report:\r\n{ComponentReport}", GetComponentsReport(requirements)); - _logger.Error(e, "Failed to sort compontents."); + _logger.Error(e, "Failed to sort components."); throw; } @@ -189,7 +184,6 @@ namespace Umbraco.Core.Components foreach (var attr in componentType.GetCustomAttributes()) { var type = attr.DisabledType ?? componentType; - if (type == typeof(UmbracoCoreComponent)) throw new InvalidOperationException("Cannot disable UmbracoCoreComponent."); if (enabled.TryGetValue(type, out var enableInfo) == false) enableInfo = enabled[type] = new EnableInfo(); var weight = type == componentType ? 1 : 2; if (enableInfo.Weight > weight) continue; @@ -303,17 +297,6 @@ namespace Umbraco.Core.Components } } - private void RegisterInitializers() - { - foreach (var component in _components) - { - if (component.InitializerType != null) - { - _container.Register(component.InitializerType); - } - } - } - private void InitializeComponents() { // use a container scope to ensure that PerScope instances are disposed @@ -335,12 +318,6 @@ namespace Umbraco.Core.Components .ToArray(); initializer.Invoke(component, parameters); } - - if (component.InitializerType != null) - { - var initializer = (IComponentInitializer) _container.GetInstance(component.InitializerType); - initializer.Initialize(); - } } } } diff --git a/src/Umbraco.Core/Components/IUmbracoComponent.cs b/src/Umbraco.Core/Components/IUmbracoComponent.cs index 6d51ebe30d..d25b97c270 100644 --- a/src/Umbraco.Core/Components/IUmbracoComponent.cs +++ b/src/Umbraco.Core/Components/IUmbracoComponent.cs @@ -1,5 +1,4 @@ -using System; -using Umbraco.Core.Composing; +using Umbraco.Core.Composing; namespace Umbraco.Core.Components { @@ -14,20 +13,9 @@ namespace Umbraco.Core.Components /// The composition. void Compose(Composition composition); - /// - /// An optional that will be executed after composition is done. - /// The initializer will be registered with the DI container and can have constructor dependencies. - /// - Type InitializerType { get; } - /// /// Terminates the component. /// void Terminate(); } - - public interface IComponentInitializer - { - void Initialize(); - } } diff --git a/src/Umbraco.Core/Components/IUmbracoUserComponent.cs b/src/Umbraco.Core/Components/IUmbracoUserComponent.cs index 61a07cfd48..377528ff26 100644 --- a/src/Umbraco.Core/Components/IUmbracoUserComponent.cs +++ b/src/Umbraco.Core/Components/IUmbracoUserComponent.cs @@ -1,6 +1,6 @@ namespace Umbraco.Core.Components { - [RequireComponent(typeof(UmbracoCoreComponent))] + [RequireComponent(typeof(IUmbracoCoreComponent))] public interface IUmbracoUserComponent : IUmbracoComponent { } } diff --git a/src/Umbraco.Core/Components/RequireComponentAttribute.cs b/src/Umbraco.Core/Components/RequireComponentAttribute.cs index 2d53413f99..cbf86e48a1 100644 --- a/src/Umbraco.Core/Components/RequireComponentAttribute.cs +++ b/src/Umbraco.Core/Components/RequireComponentAttribute.cs @@ -10,11 +10,11 @@ namespace Umbraco.Core.Components /// another component class does *not* inherit its requirements. However, the bootloader checks /// the *interfaces* of every component for their requirements, so requirements declared on /// interfaces are inherited by every component class implementing the interface. - /// When targetting a class, indicates a dependency on the component which must be enabled, - /// unless the requirement has explicitely been declared as weak (and then, only if the component + /// When targeting a class, indicates a dependency on the component which must be enabled, + /// unless the requirement has explicitly been declared as weak (and then, only if the component /// is enabled). - /// When targetting an interface, indicates a dependency on enabled components implementing - /// the interface. It could be no component at all, unless the requirement has explicitely been + /// When targeting an interface, indicates a dependency on enabled components implementing + /// the interface. It could be no component at all, unless the requirement has explicitly been /// declared as strong (and at least one component must be enabled). /// [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = true, Inherited = false)] diff --git a/src/Umbraco.Core/Components/RequiredComponentAttribute.cs b/src/Umbraco.Core/Components/RequiredComponentAttribute.cs index 7895445179..0a542b9fd6 100644 --- a/src/Umbraco.Core/Components/RequiredComponentAttribute.cs +++ b/src/Umbraco.Core/Components/RequiredComponentAttribute.cs @@ -6,16 +6,15 @@ namespace Umbraco.Core.Components /// Indicates that a component is required by another component. /// /// - /// fixme /// This attribute is *not* inherited. This means that a component class inheriting from /// another component class does *not* inherit its requirements. However, the bootloader checks /// the *interfaces* of every component for their requirements, so requirements declared on /// interfaces are inherited by every component class implementing the interface. - /// When targetting a class, indicates a dependency on the component which must be enabled, - /// unless the requirement has explicitely been declared as weak (and then, only if the component + /// When targeting a class, indicates a dependency on the component which must be enabled, + /// unless the requirement has explicitly been declared as weak (and then, only if the component /// is enabled). - /// When targetting an interface, indicates a dependency on enabled components implementing - /// the interface. It could be no component at all, unless the requirement has explicitely been + /// When targeting an interface, indicates a dependency on enabled components implementing + /// the interface. It could be no component at all, unless the requirement has explicitly been /// declared as strong (and at least one component must be enabled). /// diff --git a/src/Umbraco.Core/Components/UmbracoComponentBase.cs b/src/Umbraco.Core/Components/UmbracoComponentBase.cs index f96e2aed12..476c4c6d59 100644 --- a/src/Umbraco.Core/Components/UmbracoComponentBase.cs +++ b/src/Umbraco.Core/Components/UmbracoComponentBase.cs @@ -1,6 +1,4 @@ -using System; - -namespace Umbraco.Core.Components +namespace Umbraco.Core.Components { /// /// Provides a base class for implementations. @@ -11,8 +9,6 @@ namespace Umbraco.Core.Components public virtual void Compose(Composition composition) { } - public virtual Type InitializerType => null; - /// public virtual void Terminate() { } diff --git a/src/Umbraco.Core/Components/UmbracoCoreComponent.cs b/src/Umbraco.Core/Components/UmbracoCoreComponent.cs deleted file mode 100644 index 9f6709c494..0000000000 --- a/src/Umbraco.Core/Components/UmbracoCoreComponent.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Umbraco.Core.Components -{ - // the UmbracoCoreComponent requires all IUmbracoCoreComponent - // all user-level components should require the UmbracoCoreComponent - - [RequireComponent(typeof(IUmbracoCoreComponent))] - public class UmbracoCoreComponent : UmbracoComponentBase - { } -} diff --git a/src/Umbraco.Core/Components/UmbracoCoreComponentBase.cs b/src/Umbraco.Core/Components/UmbracoCoreComponentBase.cs new file mode 100644 index 0000000000..519ef42f85 --- /dev/null +++ b/src/Umbraco.Core/Components/UmbracoCoreComponentBase.cs @@ -0,0 +1,8 @@ +namespace Umbraco.Core.Components +{ + /// + /// Provides a base class for implementations. + /// + public abstract class UmbracoCoreComponentBase : UmbracoComponentBase, IUmbracoCoreComponent + { } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Components/UmbracoUserComponentBase.cs b/src/Umbraco.Core/Components/UmbracoUserComponentBase.cs new file mode 100644 index 0000000000..34223a3b0a --- /dev/null +++ b/src/Umbraco.Core/Components/UmbracoUserComponentBase.cs @@ -0,0 +1,8 @@ +namespace Umbraco.Core.Components +{ + /// + /// Provides a base class for implementations. + /// + public abstract class UmbracoUserComponentBase : UmbracoComponentBase, IUmbracoUserComponent + { } +} diff --git a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs index 9d7c3e5a6a..efd9bde0b5 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs @@ -111,34 +111,22 @@ namespace Umbraco.Core.Runtime composition.Container.RegisterSingleton(); } - public override Type InitializerType => typeof(Initializer); - - internal class Initializer : IComponentInitializer + internal void Initialize(IEnumerable mapperProfiles) { - private readonly IEnumerable mapperProfiles; - - public Initializer(IEnumerable mapperProfiles) + // mapper profiles have been registered & are created by the container + Mapper.Initialize(configuration => { - this.mapperProfiles = mapperProfiles; - } + foreach (var profile in mapperProfiles) + configuration.AddProfile(profile); + }); - public void Initialize() - { - // mapper profiles have been registered & are created by the container - Mapper.Initialize(configuration => - { - foreach (var profile in mapperProfiles) - configuration.AddProfile(profile); - }); - - // ensure we have some essential directories - // every other component can then initialize safely - IOHelper.EnsurePathExists("~/App_Data"); - IOHelper.EnsurePathExists(SystemDirectories.Media); - IOHelper.EnsurePathExists(SystemDirectories.MvcViews); - IOHelper.EnsurePathExists(SystemDirectories.MvcViews + "/Partials"); - IOHelper.EnsurePathExists(SystemDirectories.MvcViews + "/MacroPartials"); - } + // ensure we have some essential directories + // every other component can then initialize safely + IOHelper.EnsurePathExists("~/App_Data"); + IOHelper.EnsurePathExists(SystemDirectories.Media); + IOHelper.EnsurePathExists(SystemDirectories.MvcViews); + IOHelper.EnsurePathExists(SystemDirectories.MvcViews + "/Partials"); + IOHelper.EnsurePathExists(SystemDirectories.MvcViews + "/MacroPartials"); } } } diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 4fc16badd0..59f353e1e9 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -169,7 +169,8 @@ - + + diff --git a/src/Umbraco.Tests/Components/ComponentTests.cs b/src/Umbraco.Tests/Components/ComponentTests.cs index 9483b94c82..a78f9f3249 100644 --- a/src/Umbraco.Tests/Components/ComponentTests.cs +++ b/src/Umbraco.Tests/Components/ComponentTests.cs @@ -25,21 +25,20 @@ namespace Umbraco.Tests.Components { // fixme use IUmbracoDatabaseFactory vs UmbracoDatabaseFactory, clean it all up! + var mock = new Mock(); + var testObjects = new TestObjects(null); var logger = Mock.Of(); var s = testObjects.GetDefaultSqlSyntaxProviders(logger); var f = new UmbracoDatabaseFactory(s, logger, new MapperCollection(Enumerable.Empty())); - var fs = new FileSystems(logger); + var fs = new FileSystems(mock.Object, logger); var p = new ScopeProvider(f, fs, logger); - var mock = new Mock(); mock.Setup(x => x.GetInstance(typeof (ILogger))).Returns(logger); mock.Setup(x => x.GetInstance(typeof (ProfilingLogger))).Returns(new ProfilingLogger(Mock.Of(), Mock.Of())); mock.Setup(x => x.GetInstance(typeof (IUmbracoDatabaseFactory))).Returns(f); mock.Setup(x => x.GetInstance(typeof (IScopeProvider))).Returns(p); - - setup?.Invoke(mock); return mock.Object; } @@ -146,6 +145,7 @@ namespace Umbraco.Tests.Components var thing = new BootLoader(container); Composed.Clear(); + Initialized.Clear(); thing.Boot(new[] { typeof(Component1), typeof(Component5) }, RuntimeLevel.Unknown); Assert.AreEqual(2, Composed.Count); Assert.AreEqual(typeof(Component1), Composed[0]); @@ -234,24 +234,6 @@ namespace Umbraco.Tests.Components Assert.AreEqual(typeof(Component8), Composed[1]); } - [Test] - public void Runs_Initializers_When_Defined() - { - var container = MockContainer(); - Mock.Get(container).Setup(x => x.GetInstance(typeof(TestComponentWithInitializer.Initializer))) - .Returns(new TestComponentWithInitializer.Initializer()); - - var thing = new BootLoader(container); - Composed.Clear(); - Initialized.Clear(); - thing.Boot(new[] { typeof(TestComponentWithInitializer) }, RuntimeLevel.Unknown); // 8 disables 7 which is not in the list - - Mock.Get(container).Verify(x => x.Register(typeof(TestComponentWithInitializer.Initializer), Lifetime.Transient)); - - Assert.AreEqual(1, Initialized.Count); - Assert.AreEqual("Initializer", Initialized[0]); - } - #region Components public class TestComponentBase : UmbracoComponentBase @@ -263,19 +245,6 @@ namespace Umbraco.Tests.Components } } - public class TestComponentWithInitializer : TestComponentBase - { - public override Type InitializerType => typeof(Initializer); - - public class Initializer : IComponentInitializer - { - public void Initialize() - { - Initialized.Add(GetType().Name); - } - } - } - public class Component1 : TestComponentBase { } From 246b9e5af89ca28ca9ddf29a6b0e9a8aa052310e Mon Sep 17 00:00:00 2001 From: Stephan Date: Thu, 25 Oct 2018 15:16:25 +0200 Subject: [PATCH 071/469] Cleanup --- src/Umbraco.Core/UmbracoApplicationBase.cs | 5 ++--- src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs | 5 ----- src/Umbraco.Web/UmbracoContext.cs | 1 - 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/src/Umbraco.Core/UmbracoApplicationBase.cs b/src/Umbraco.Core/UmbracoApplicationBase.cs index 18884eb459..dc39fb295e 100644 --- a/src/Umbraco.Core/UmbracoApplicationBase.cs +++ b/src/Umbraco.Core/UmbracoApplicationBase.cs @@ -34,8 +34,6 @@ namespace Umbraco.Core /// protected virtual IContainer GetContainer() { - // note: the actual, web UmbracoApplication is overriding this - // with a web-supporting container return ContainerFactory.Create(); } @@ -70,7 +68,6 @@ namespace Umbraco.Core // create the container for the application, and configure. // the boot manager is responsible for registrations var container = GetContainer(); - container.RegisterInstance(container); Current.Container = container; // register the essential stuff, @@ -107,6 +104,8 @@ namespace Umbraco.Core protected virtual void ConfigureAssemblyResolve(ILogger logger) { + // TODO - do we still need this? + // When an assembly can't be resolved. In here we can do magic with the assembly name and try loading another. // This is used for loading a signed assembly of AutoMapper (v. 3.1+) without having to recompile old code. AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => diff --git a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs index d9769cfb35..4314af38b5 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs @@ -34,8 +34,6 @@ namespace Umbraco.Tests.TestHelpers var container = Current.Container = ContainerFactory.Create(); - PreSetUp(); - container.RegisterSingleton(factory => Mock.Of()); container.RegisterSingleton(factory => Mock.Of()); @@ -57,9 +55,6 @@ namespace Umbraco.Tests.TestHelpers SetUp(); } - public virtual void PreSetUp() - {} - public virtual void SetUp() {} diff --git a/src/Umbraco.Web/UmbracoContext.cs b/src/Umbraco.Web/UmbracoContext.cs index 831e3c5cdc..b20316fc4a 100644 --- a/src/Umbraco.Web/UmbracoContext.cs +++ b/src/Umbraco.Web/UmbracoContext.cs @@ -5,7 +5,6 @@ using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Models.PublishedContent; -using Umbraco.Core.Services; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; using Umbraco.Web.Runtime; From a12778fd94add3e5cf0b9e49da7de166bbde06e0 Mon Sep 17 00:00:00 2001 From: Stephan Date: Thu, 25 Oct 2018 15:29:29 +0200 Subject: [PATCH 072/469] Cleanup IContainer --- .../Composing/ContainerExtensions.cs | 58 ++++++++++++----- .../Composing/ContainerFactory.cs | 4 ++ src/Umbraco.Core/Composing/IContainer.cs | 63 ++++++++++++------- .../LightInject/LightInjectContainer.cs | 13 ++-- .../Clr/ReflectionUtilitiesTests.cs | 17 +++++ 5 files changed, 110 insertions(+), 45 deletions(-) diff --git a/src/Umbraco.Core/Composing/ContainerExtensions.cs b/src/Umbraco.Core/Composing/ContainerExtensions.cs index 33925e010b..86e18db35b 100644 --- a/src/Umbraco.Core/Composing/ContainerExtensions.cs +++ b/src/Umbraco.Core/Composing/ContainerExtensions.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; @@ -9,10 +10,13 @@ namespace Umbraco.Core.Composing /// public static class ContainerExtensions { + private static readonly ConcurrentDictionary>> ArgumentPropertyGetters + = new ConcurrentDictionary>>(); + /// - /// Gets an instance. + /// Gets an instance of a service. /// - /// The type of the instance. + /// The type of the service. /// The container. /// An instance of the specified type. /// Throws an exception if the container failed to get an instance of the specified type. @@ -20,20 +24,20 @@ namespace Umbraco.Core.Composing => (T) container.GetInstance(typeof(T)); /// - /// Gets a named instance. + /// Gets an instance of a named service. /// - /// The type of the instance. + /// The type of the service. /// The container. - /// The name of the instance. + /// The name of the service. /// An instance of the specified type and name. /// Throws an exception if the container failed to get an instance of the specified type. public static T GetInstance(this IContainer container, string name) => (T) container.GetInstance(typeof(T), name); /// - /// Tries to get an instance. + /// Tries to get an instance of a service. /// - /// The type of the instance. + /// The type of the service. /// An instance of the specified type, or null. /// Returns null if the container does not know how to get an instance /// of the specified type. Throws an exception if the container does know how @@ -42,7 +46,7 @@ namespace Umbraco.Core.Composing => (T) container.TryGetInstance(typeof(T)); /// - /// Gets registration for a service. + /// Gets registrations for a service. /// /// The type of the service. /// The registrations for the service. @@ -63,6 +67,32 @@ namespace Umbraco.Core.Composing public static T CreateInstance(this IContainer container, IDictionary args) => (T) container.CreateInstance(typeof(T), args); + /// + /// Creates an instance with arguments. + /// + /// The type of the instance. + /// The container. + /// Arguments. + /// An instance of the specified type. + /// + /// Throws an exception if the container failed to get an instance of the specified type. + /// The arguments are used as dependencies by the container. + /// + public static T CreateInstance(this IContainer container, object args) + { + var typeOfArgs = args.GetType(); + var getters = ArgumentPropertyGetters.GetOrAdd(typeOfArgs, type => + args.GetType() + .GetProperties() + .ToDictionary(x => x.Name, x => ReflectionUtilities.EmitMethodUnsafe>(x.GetMethod))); + + var argsDictionary = new Dictionary(); + foreach (var (name, getter) in getters) + argsDictionary[name] = getter(args); + + return (T) container.CreateInstance(typeof(T), argsDictionary); + } + /// /// Registers a service with an implementation type. /// @@ -70,15 +100,15 @@ namespace Umbraco.Core.Composing => container.Register(typeof(TService), typeof(TImplementing), lifetime); /// - /// Registers a service with a named implementation type. + /// Registers a named service with an implementation type. /// public static void Register(this IContainer container, string name, Lifetime lifetime = Lifetime.Transient) => container.Register(typeof(TService), typeof(TImplementing), name, lifetime); /// - /// Registers a service with a named implementation type and factory. + /// Registers a named service with an implementation factory. /// - public static void Register(this IContainer container, string name, Func factory, Lifetime lifetime = Lifetime.Transient) + public static void Register(this IContainer container, string name, Func factory, Lifetime lifetime = Lifetime.Transient) => container.Register(factory, name, lifetime); /// @@ -107,7 +137,6 @@ namespace Umbraco.Core.Composing /// /// Registers a named singleton service with an implementation factory. - /// Note to implementors: The last registered component must be the default. /// public static void RegisterSingleton(this IContainer container, string name, Func factory) => container.Register(factory, name, Lifetime.Singleton); @@ -125,7 +154,7 @@ namespace Umbraco.Core.Composing => container.RegisterAuto(typeof(TServiceBase)); /// - /// Registers and instanciates a collection builder. + /// Registers and instantiates a collection builder. /// /// The type of the collection builder. /// A collection builder of the specified type. @@ -137,7 +166,8 @@ namespace Umbraco.Core.Composing throw new InvalidOperationException("Collection builders should be registered only once."); // register the builder - container.RegisterSingleton(); + // use a factory so we don't have to self-register the container + container.RegisterSingleton(factory => factory.CreateInstance(new Dictionary {{ "container", container }} )); // initialize and return the builder return container.GetInstance(); diff --git a/src/Umbraco.Core/Composing/ContainerFactory.cs b/src/Umbraco.Core/Composing/ContainerFactory.cs index fb2c5f6eb7..bf808d56ae 100644 --- a/src/Umbraco.Core/Composing/ContainerFactory.cs +++ b/src/Umbraco.Core/Composing/ContainerFactory.cs @@ -50,6 +50,10 @@ namespace Umbraco.Core.Composing if (container == null) throw new Exception($"Container factory '{configuredTypeName}' did not return an IContainer implementation."); + // self-register the container - this is where it should happen + // but - we do NOT want to do it! + //container.RegisterInstance(container); + return container; } } diff --git a/src/Umbraco.Core/Composing/IContainer.cs b/src/Umbraco.Core/Composing/IContainer.cs index 97a9d47437..78137eb990 100644 --- a/src/Umbraco.Core/Composing/IContainer.cs +++ b/src/Umbraco.Core/Composing/IContainer.cs @@ -3,6 +3,22 @@ using System.Collections.Generic; namespace Umbraco.Core.Composing { + // Implementing IContainer: + // + // The factory + // - always picks the constructor with the most parameters + // - supports Lazy parameters (and prefers them over non-Lazy) in constructors + // - what happens with 'releasing' is unclear + // + // The registry + // - supports registering a service, even after some instances of other services have been created + // - supports re-registering a service, as long as no instance of that service has been created + // - throws when re-registering a service, and an instance of that service has been created + // + // - registers only one implementation of a nameless service, re-registering replaces the previous + // registration - names are required to register multiple implementations - and getting an + // IEnumerable of the service, nameless, returns them all + /// /// Defines a container for Umbraco. /// @@ -15,32 +31,27 @@ namespace Umbraco.Core.Composing #region Factory - // notes - // when implementing IContainer, the following rules apply - // - always pick the constructor with the most parameters - // - always prefer Lazy parameters over non-Lazy in constructors - /// - /// Gets an instance. + /// Gets an instance of a service. /// - /// The type of the instance. + /// The type of the service. /// An instance of the specified type. /// Throws an exception if the container failed to get an instance of the specified type. object GetInstance(Type type); /// - /// Gets a named instance. + /// Gets an instance of a named service. /// - /// The type of the instance. - /// The name of the instance. + /// The type of the service. + /// The name of the service. /// An instance of the specified type. /// Throws an exception if the container failed to get an instance of the specified type. object GetInstance(Type type, string name); /// - /// Tries to get an instance. + /// Tries to get an instance of a service. /// - /// The type of the instance. + /// The type of the service. /// An instance of the specified type, or null. /// Returns null if the container does not know how to get an instance /// of the specified type. Throws an exception if the container does know how @@ -60,14 +71,14 @@ namespace Umbraco.Core.Composing IEnumerable GetAllInstances(); /// - /// Gets registration for a service. + /// Gets registrations for a service. /// /// The type of the service. /// The registrations for the service. IEnumerable GetRegistered(Type serviceType); /// - /// Creates an instance with arguments. + /// Creates an instance of a service, with arguments. /// /// The type of the instance. /// Named arguments. @@ -79,16 +90,21 @@ namespace Umbraco.Core.Composing /// object CreateInstance(Type type, IDictionary args); + /// + /// Releases an instance. + /// + /// The instance. + /// + /// See https://stackoverflow.com/questions/14072208 and http://kozmic.net/2010/08/27/must-i-release-everything-when-using-windsor/, + /// you only need to release instances you specifically resolved, and even then, if done right, that might never be needed. For + /// instance, LightInject does not require this and does not support it - should work with scopes. + /// + void Release(object instance); + #endregion #region Registry - // notes - // when implementing IContainer, the following rules apply - // - it is possible to register a service, even after some instances of other services have been created - // - it is possible to re-register a service, as long as an instance of that service has not been created - // - once an instance of a service has been created, it is not possible to change its registration - /// /// Registers a service as its own implementation. /// @@ -100,7 +116,7 @@ namespace Umbraco.Core.Composing void Register(Type serviceType, Type implementingType, Lifetime lifetime = Lifetime.Transient); /// - /// Registers a service with a named implementation type. + /// Registers a named service with a implementation type. /// void Register(Type serviceType, Type implementingType, string name, Lifetime lifetime = Lifetime.Transient); @@ -120,7 +136,7 @@ namespace Umbraco.Core.Composing void RegisterInstance(Type serviceType, object instance); /// - /// Registers a service with a named implementing instance. + /// Registers a named service with an implementing instance. /// void RegisterInstance(Type serviceType, object instance, string name); @@ -139,6 +155,7 @@ namespace Umbraco.Core.Composing /// /// Registers a service with an ordered set of implementation types. /// + // fixme: once we merge the installer refactoring, kill that one void RegisterOrdered(Type serviceType, Type[] implementingTypes, Lifetime lifetime = Lifetime.Transient); #endregion @@ -174,7 +191,5 @@ namespace Umbraco.Core.Composing IContainer EnablePerWebRequestScope(); #endregion - - void Release(object instance); } } diff --git a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs index 1302676514..dca07938cc 100644 --- a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs +++ b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs @@ -20,8 +20,6 @@ namespace Umbraco.Core.Composing.LightInject protected LightInjectContainer(ServiceContainer container) { Container = container; - - container.RegisterSingleton(_ => this); } /// @@ -154,6 +152,12 @@ namespace Umbraco.Core.Composing.LightInject return ctor.Invoke(ctorArgs); } + /// + public void Release(object instance) + { + // nothing to release with LightInject + } + // notes: // we may want to look into MS code, eg: // TypeActivatorCache in MVC at https://github.com/aspnet/Mvc/blob/dev/src/Microsoft.AspNetCore.Mvc.Core/Internal/TypeActivatorCache.cs @@ -318,11 +322,6 @@ namespace Umbraco.Core.Composing.LightInject #endregion - public void Release(object instance) - { - // fixme - no idea how to do this with LI - } - #region Control /// diff --git a/src/Umbraco.Tests/Clr/ReflectionUtilitiesTests.cs b/src/Umbraco.Tests/Clr/ReflectionUtilitiesTests.cs index 46dae8bcfd..b87ac70ea5 100644 --- a/src/Umbraco.Tests/Clr/ReflectionUtilitiesTests.cs +++ b/src/Umbraco.Tests/Clr/ReflectionUtilitiesTests.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Reflection; using NUnit.Framework; using Umbraco.Core; @@ -553,6 +554,22 @@ namespace Umbraco.Tests.Clr // fixme - missing tests specifying 'returned' on method, property + [Test] + public void DeconstructAnonymousType() + { + var o = new { a = 1, b = "hello" }; + + var getters = new Dictionary>(); + foreach (var prop in o.GetType().GetProperties()) + getters[prop.Name] = ReflectionUtilities.EmitMethodUnsafe>(prop.GetMethod); + + Assert.AreEqual(2, getters.Count); + Assert.IsTrue(getters.ContainsKey("a")); + Assert.IsTrue(getters.ContainsKey("b")); + Assert.AreEqual(1, getters["a"](o)); + Assert.AreEqual("hello", getters["b"](o)); + } + #region IL Code // these functions can be examined in eg DotPeek to understand IL works From 1644434ea7b2e168c229efbb0e960756d1a3444b Mon Sep 17 00:00:00 2001 From: Stephan Date: Thu, 25 Oct 2018 17:26:23 +0200 Subject: [PATCH 073/469] Cleanup controller factories --- .../Mvc/ContainerControllerFactory.cs | 9 ++++----- .../Mvc/ControllerFactoryExtensions.cs | 13 +++---------- src/Umbraco.Web/Mvc/MasterControllerFactory.cs | 15 +++++++-------- src/Umbraco.Web/Mvc/RenderControllerFactory.cs | 18 +++++++----------- .../Mvc/UmbracoControllerFactory.cs | 12 ++++-------- 5 files changed, 25 insertions(+), 42 deletions(-) diff --git a/src/Umbraco.Web/Mvc/ContainerControllerFactory.cs b/src/Umbraco.Web/Mvc/ContainerControllerFactory.cs index d37054fda1..74ac491df6 100644 --- a/src/Umbraco.Web/Mvc/ContainerControllerFactory.cs +++ b/src/Umbraco.Web/Mvc/ContainerControllerFactory.cs @@ -1,28 +1,27 @@ using System; using System.Web.Mvc; using System.Web.Routing; -using System.Web.SessionState; using Umbraco.Core.Composing; namespace Umbraco.Web.Mvc { public class ContainerControllerFactory : DefaultControllerFactory { - private readonly IContainer container; + private readonly IContainer _container; public ContainerControllerFactory(IContainer container) { - this.container = container; + _container = container; } protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) { - return (IController)container.GetInstance(controllerType); + return (IController) _container.GetInstance(controllerType); } public override void ReleaseController(IController controller) { - container.Release(controller); + _container.Release(controller); } } } diff --git a/src/Umbraco.Web/Mvc/ControllerFactoryExtensions.cs b/src/Umbraco.Web/Mvc/ControllerFactoryExtensions.cs index 87f7227b82..07a3f2a5e3 100644 --- a/src/Umbraco.Web/Mvc/ControllerFactoryExtensions.cs +++ b/src/Umbraco.Web/Mvc/ControllerFactoryExtensions.cs @@ -14,25 +14,18 @@ namespace Umbraco.Web.Mvc /// /// /// - /// This is related to issue: http://issues.umbraco.org/issue/U4-1726. We already have a method called GetControllerTypeInternal on our MasterControlelrFactory, + /// This is related to issue: http://issues.umbraco.org/issue/U4-1726. We already have a method called GetControllerTypeInternal on our MasterControllerFactory, /// however, we cannot always guarantee that the usage of this will be a MasterControllerFactory like during unit tests. So we needed to create /// this extension method to do the checks instead. /// internal static Type GetControllerTypeInternal(this IControllerFactory factory, RequestContext requestContext, string controllerName) { - var controllerFactory = factory as MasterControllerFactory; - if (controllerFactory != null) - { + if (factory is MasterControllerFactory controllerFactory) return controllerFactory.GetControllerTypeInternal(requestContext, controllerName); - } //we have no choice but to instantiate the controller var instance = factory.CreateController(requestContext, controllerName); - if (instance != null) - { - return instance.GetType(); - } - return null; + return instance?.GetType(); } } } diff --git a/src/Umbraco.Web/Mvc/MasterControllerFactory.cs b/src/Umbraco.Web/Mvc/MasterControllerFactory.cs index 3d1e450c93..30838e606a 100644 --- a/src/Umbraco.Web/Mvc/MasterControllerFactory.cs +++ b/src/Umbraco.Web/Mvc/MasterControllerFactory.cs @@ -54,8 +54,8 @@ namespace Umbraco.Web.Mvc { var factory = FactoryForRequest(requestContext); return factory != null - ? factory.CreateController(requestContext, controllerName) - : base.CreateController(requestContext, controllerName); + ? factory.CreateController(requestContext, controllerName) + : base.CreateController(requestContext, controllerName); } /// @@ -76,11 +76,9 @@ namespace Umbraco.Web.Mvc // an instance of the controller to figure out what it is. This is a work around for not having a breaking change for: // http://issues.umbraco.org/issue/U4-1726 - var umbFactory = factory as UmbracoControllerFactory; - if (umbFactory != null) - { + if (factory is UmbracoControllerFactory umbFactory) return umbFactory.GetControllerType(requestContext, controllerName); - } + //we have no choice but to instantiate the controller var instance = factory.CreateController(requestContext, controllerName); return instance?.GetType(); @@ -97,8 +95,8 @@ namespace Umbraco.Web.Mvc public override void ReleaseController(IController icontroller) { var released = false; - var controller = icontroller as Controller; - if (controller != null) + + if (icontroller is Controller controller) { var requestContext = controller.ControllerContext.RequestContext; var factory = FactoryForRequest(requestContext); @@ -108,6 +106,7 @@ namespace Umbraco.Web.Mvc released = true; } } + if (released == false) base.ReleaseController(icontroller); } diff --git a/src/Umbraco.Web/Mvc/RenderControllerFactory.cs b/src/Umbraco.Web/Mvc/RenderControllerFactory.cs index 8158cc8d22..c9734e24b0 100644 --- a/src/Umbraco.Web/Mvc/RenderControllerFactory.cs +++ b/src/Umbraco.Web/Mvc/RenderControllerFactory.cs @@ -10,7 +10,6 @@ namespace Umbraco.Web.Mvc /// public class RenderControllerFactory : UmbracoControllerFactory { - /// /// Determines whether this instance can handle the specified request. /// @@ -34,16 +33,13 @@ namespace Umbraco.Web.Mvc /// public override IController CreateController(RequestContext requestContext, string controllerName) { - var instance = base.CreateController(requestContext, controllerName); - var controllerInstance = instance as Controller; - if (controllerInstance != null) - { - //set the action invoker! - controllerInstance.ActionInvoker = new RenderActionInvoker(); - } - - return instance; + var instance = base.CreateController(requestContext, controllerName); + if (instance is Controller controllerInstance) + { + //set the action invoker! + controllerInstance.ActionInvoker = new RenderActionInvoker(); + } + return instance; } - } } diff --git a/src/Umbraco.Web/Mvc/UmbracoControllerFactory.cs b/src/Umbraco.Web/Mvc/UmbracoControllerFactory.cs index 330031976d..45ca1480c7 100644 --- a/src/Umbraco.Web/Mvc/UmbracoControllerFactory.cs +++ b/src/Umbraco.Web/Mvc/UmbracoControllerFactory.cs @@ -66,12 +66,10 @@ namespace Umbraco.Web.Mvc /// /// internal class OverridenDefaultControllerFactory : ContainerControllerFactory - // DefaultControllerFactory { public OverridenDefaultControllerFactory() : base(Current.Container) - { - } + { } public new IController GetControllerInstance(RequestContext requestContext, Type controllerType) { @@ -80,11 +78,9 @@ namespace Umbraco.Web.Mvc public new Type GetControllerType(RequestContext requestContext, string controllerName) { - if (controllerName.IsNullOrWhiteSpace()) - { - return null; - } - return base.GetControllerType(requestContext, controllerName); + return controllerName.IsNullOrWhiteSpace() + ? null + : base.GetControllerType(requestContext, controllerName); } } } From eee7222e0b0b162f6a412f7f34e6bb02a24acee4 Mon Sep 17 00:00:00 2001 From: Stephan Date: Fri, 26 Oct 2018 15:06:53 +0200 Subject: [PATCH 074/469] Refactor filesystems --- .../Composers/FileSystemsComposer.cs | 99 ++++++++- src/Umbraco.Core/ContentExtensions.cs | 4 +- .../Events/QueuingEventDispatcher.cs | 4 +- src/Umbraco.Core/IO/FileSystemAttribute.cs | 25 +++ .../IO/FileSystemProviderAttribute.cs | 19 -- src/Umbraco.Core/IO/FileSystemWrapper.cs | 44 ++-- src/Umbraco.Core/IO/FileSystems.cs | 191 +++--------------- src/Umbraco.Core/IO/IFileSystem.cs | 2 +- src/Umbraco.Core/IO/IFileSystems.cs | 43 ++++ src/Umbraco.Core/IO/IMediaFileSystem.cs | 66 ++++++ src/Umbraco.Core/IO/MediaFileSystem.cs | 113 ++--------- src/Umbraco.Core/IO/ShadowFileSystems.cs | 95 +-------- .../Services/Implement/ContentService.cs | 8 +- .../Services/Implement/MediaService.cs | 7 +- .../Services/Implement/MemberService.cs | 9 +- src/Umbraco.Core/Umbraco.Core.csproj | 4 +- src/Umbraco.Tests/IO/FileSystemsTests.cs | 84 ++++---- .../Scoping/ScopeEventDispatcherTests.cs | 3 +- src/Umbraco.Tests/TestHelpers/TestObjects.cs | 2 +- src/Umbraco.Web/Editors/ImagesController.cs | 4 +- .../Media/UploadAutoFillProperties.cs | 4 +- .../FileUploadPropertyEditor.cs | 4 +- .../FileUploadPropertyValueEditor.cs | 4 +- .../ImageCropperPropertyEditor.cs | 4 +- .../ImageCropperPropertyValueEditor.cs | 4 +- 25 files changed, 380 insertions(+), 466 deletions(-) create mode 100644 src/Umbraco.Core/IO/FileSystemAttribute.cs delete mode 100644 src/Umbraco.Core/IO/FileSystemProviderAttribute.cs create mode 100644 src/Umbraco.Core/IO/IFileSystems.cs create mode 100644 src/Umbraco.Core/IO/IMediaFileSystem.cs diff --git a/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs b/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs index 15c4bd0eea..56a0ba316c 100644 --- a/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs @@ -1,28 +1,105 @@ -using Umbraco.Core.IO; +using System; +using System.Configuration; +using Umbraco.Core.Configuration; +using Umbraco.Core.IO; namespace Umbraco.Core.Composing.Composers { public static class FileSystemsComposer { + /* + * HOW TO REPLACE THE MEDIA UNDERLYING FILESYSTEM + * ---------------------------------------------- + * + * Create a component and use it to modify the composition by adding something like: + * + * composition.Container.RegisterSingleton("media", factory => ...); + * + * where the ... part returns the new underlying filesystem, as an IFileSystem. + * + * + * HOW TO IMPLEMENT MY OWN FILESYSTEM + * ---------------------------------- + * + * Declare your filesystem interface: + * + * public interface IMyFileSystem : IFileSystem + * { } + * + * Create your filesystem class: + * + * [FileSystem("my")] + * public class MyFileSystem : FileSystemWrapper, IFormsFileSystem + * { + * public FormsFileSystem(IFileSystem innerFileSystem) + * : base(innerFileSystem) + * { } + * } + * + * Register both the underlying filesystem, and your filesystem, in a component: + * + * composition.Container.RegisterSingleton("my", factory => ...); + * composition.Container.RegisterSingleton(factory => + * factory.GetInstance().GetFileSystem(); + * + * And that's it, you can inject IMyFileSystem wherever it's needed. + * + * + * WHAT IS SHADOWING + * ----------------- + * + * Shadowing is the technology used for Deploy to implement some sort of + * transaction-management on top of filesystems. The plumbing explained above, + * compared to creating your own physical filesystem, ensures that your filesystem + * would participate into such transactions. + * + * Also note that in order for things to work correctly, all filesystems should + * be instantiated before shadowing - so if registering a new filesystem in a + * component, it's a good idea to initialize it. This would be enough (in the + * component): + * + * public void Initialize(IMyFileSystem fs) + * { } + * + * + */ + public static IContainer ComposeFileSystems(this IContainer container) { // register FileSystems, which manages all filesystems - container.RegisterSingleton(); + // it needs to be registered (not only the interface) because it provides additional + // functionality eg for scoping, and is injected in the scope provider - whereas the + // interface is really for end-users to get access to filesystems. + //container.RegisterSingleton(); + container.RegisterSingleton(factory => factory.CreateInstance(new { container} )); // register IFileSystems, which gives access too all filesystems container.RegisterSingleton(factory => factory.GetInstance()); - - // fixme - review registering mediafilesystem. it seems to create cyclic dependencies for castle. - // let's try naming it so the default is overwritten... - - // register MediaFileSystem, which can be injected directly - // note: the actual MediaFileSystem implementation is created by FileSystems directly, - // without being registered in the container - this just gives access to it - container.Register(f => f.GetInstance().MediaFileSystem); - + // register IMediaFileSystem + var virtualRoot = GetMediaFileSystemVirtualRoot(); + container.RegisterSingleton("media", factory => new PhysicalFileSystem(virtualRoot)); + container.RegisterSingleton(factory => factory.GetInstance().GetFileSystem()); return container; } + + private static string GetMediaFileSystemVirtualRoot() + { + // for the time being, we still use the FileSystemProvider config file + // but, detect if ppl are trying to use it to change the "provider" + + var virtualRoot = "~/media"; + + var config = (FileSystemProvidersSection)ConfigurationManager.GetSection("umbracoConfiguration/FileSystemProviders"); + var p = config?.Providers["media"]; + if (p == null) return virtualRoot; + + if (!string.IsNullOrWhiteSpace(p.Type) && p.Type != "Umbraco.Core.IO.PhysicalFileSystem, Umbraco.Core") + throw new InvalidOperationException("Setting a provider type in FileSystemProviders.config is not supported anymore, see FileSystemsComposer for help."); + + virtualRoot = p?.Parameters["virtualRoot"]?.Value ?? "~/media"; + return virtualRoot; + } } } diff --git a/src/Umbraco.Core/ContentExtensions.cs b/src/Umbraco.Core/ContentExtensions.cs index 4f88c2b803..ee6602e9aa 100644 --- a/src/Umbraco.Core/ContentExtensions.cs +++ b/src/Umbraco.Core/ContentExtensions.cs @@ -18,8 +18,8 @@ namespace Umbraco.Core public static class ContentExtensions { // this ain't pretty - private static MediaFileSystem _mediaFileSystem; - private static MediaFileSystem MediaFileSystem => _mediaFileSystem ?? (_mediaFileSystem = Current.FileSystems.MediaFileSystem); + private static IMediaFileSystem _mediaFileSystem; + private static IMediaFileSystem MediaFileSystem => _mediaFileSystem ?? (_mediaFileSystem = Current.FileSystems.MediaFileSystem); #region IContent diff --git a/src/Umbraco.Core/Events/QueuingEventDispatcher.cs b/src/Umbraco.Core/Events/QueuingEventDispatcher.cs index e0d3847c17..54ed8580a0 100644 --- a/src/Umbraco.Core/Events/QueuingEventDispatcher.cs +++ b/src/Umbraco.Core/Events/QueuingEventDispatcher.cs @@ -32,9 +32,9 @@ namespace Umbraco.Core.Events } } - private MediaFileSystem _mediaFileSystem; + private IMediaFileSystem _mediaFileSystem; // fixme inject - private MediaFileSystem MediaFileSystem => _mediaFileSystem ?? (_mediaFileSystem = Current.FileSystems.MediaFileSystem); + private IMediaFileSystem MediaFileSystem => _mediaFileSystem ?? (_mediaFileSystem = Current.FileSystems.MediaFileSystem); } } diff --git a/src/Umbraco.Core/IO/FileSystemAttribute.cs b/src/Umbraco.Core/IO/FileSystemAttribute.cs new file mode 100644 index 0000000000..cf59d4e145 --- /dev/null +++ b/src/Umbraco.Core/IO/FileSystemAttribute.cs @@ -0,0 +1,25 @@ +using System; + +namespace Umbraco.Core.IO +{ + /// + /// Decorates a filesystem. + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] + public class FileSystemAttribute : Attribute + { + /// + /// Initializes a new instance of the class. + /// + /// + public FileSystemAttribute(string alias) + { + Alias = alias; + } + + /// + /// Gets the alias of the filesystem. + /// + public string Alias { get; } + } +} diff --git a/src/Umbraco.Core/IO/FileSystemProviderAttribute.cs b/src/Umbraco.Core/IO/FileSystemProviderAttribute.cs deleted file mode 100644 index b3b6cb6b79..0000000000 --- a/src/Umbraco.Core/IO/FileSystemProviderAttribute.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Umbraco.Core.CodeAnnotations; - -namespace Umbraco.Core.IO -{ - [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] - public class FileSystemProviderAttribute : Attribute - { - public string Alias { get; private set; } - - public FileSystemProviderAttribute(string alias) - { - Alias = alias; - } - } -} diff --git a/src/Umbraco.Core/IO/FileSystemWrapper.cs b/src/Umbraco.Core/IO/FileSystemWrapper.cs index 2c4377b89b..14d028c16d 100644 --- a/src/Umbraco.Core/IO/FileSystemWrapper.cs +++ b/src/Umbraco.Core/IO/FileSystemWrapper.cs @@ -16,103 +16,103 @@ namespace Umbraco.Core.IO /// public abstract class FileSystemWrapper : IFileSystem { - protected FileSystemWrapper(IFileSystem wrapped) + protected FileSystemWrapper(IFileSystem innerFileSystem) { - Wrapped = wrapped; + InnerFileSystem = innerFileSystem; } - internal IFileSystem Wrapped { get; set; } + internal IFileSystem InnerFileSystem { get; set; } public IEnumerable GetDirectories(string path) { - return Wrapped.GetDirectories(path); + return InnerFileSystem.GetDirectories(path); } public void DeleteDirectory(string path) { - Wrapped.DeleteDirectory(path); + InnerFileSystem.DeleteDirectory(path); } public void DeleteDirectory(string path, bool recursive) { - Wrapped.DeleteDirectory(path, recursive); + InnerFileSystem.DeleteDirectory(path, recursive); } public bool DirectoryExists(string path) { - return Wrapped.DirectoryExists(path); + return InnerFileSystem.DirectoryExists(path); } public void AddFile(string path, Stream stream) { - Wrapped.AddFile(path, stream); + InnerFileSystem.AddFile(path, stream); } public void AddFile(string path, Stream stream, bool overrideExisting) { - Wrapped.AddFile(path, stream, overrideExisting); + InnerFileSystem.AddFile(path, stream, overrideExisting); } public IEnumerable GetFiles(string path) { - return Wrapped.GetFiles(path); + return InnerFileSystem.GetFiles(path); } public IEnumerable GetFiles(string path, string filter) { - return Wrapped.GetFiles(path, filter); + return InnerFileSystem.GetFiles(path, filter); } public Stream OpenFile(string path) { - return Wrapped.OpenFile(path); + return InnerFileSystem.OpenFile(path); } public void DeleteFile(string path) { - Wrapped.DeleteFile(path); + InnerFileSystem.DeleteFile(path); } public bool FileExists(string path) { - return Wrapped.FileExists(path); + return InnerFileSystem.FileExists(path); } public string GetRelativePath(string fullPathOrUrl) { - return Wrapped.GetRelativePath(fullPathOrUrl); + return InnerFileSystem.GetRelativePath(fullPathOrUrl); } public string GetFullPath(string path) { - return Wrapped.GetFullPath(path); + return InnerFileSystem.GetFullPath(path); } public string GetUrl(string path) { - return Wrapped.GetUrl(path); + return InnerFileSystem.GetUrl(path); } public DateTimeOffset GetLastModified(string path) { - return Wrapped.GetLastModified(path); + return InnerFileSystem.GetLastModified(path); } public DateTimeOffset GetCreated(string path) { - return Wrapped.GetCreated(path); + return InnerFileSystem.GetCreated(path); } public long GetSize(string path) { - return Wrapped.GetSize(path); + return InnerFileSystem.GetSize(path); } - public bool CanAddPhysical => Wrapped.CanAddPhysical; + public bool CanAddPhysical => InnerFileSystem.CanAddPhysical; public void AddFile(string path, string physicalPath, bool overrideIfExists = true, bool copy = false) { - Wrapped.AddFile(path, physicalPath, overrideIfExists, copy); + InnerFileSystem.AddFile(path, physicalPath, overrideIfExists, copy); } } } diff --git a/src/Umbraco.Core/IO/FileSystems.cs b/src/Umbraco.Core/IO/FileSystems.cs index cc52487018..24e7a73172 100644 --- a/src/Umbraco.Core/IO/FileSystems.cs +++ b/src/Umbraco.Core/IO/FileSystems.cs @@ -1,36 +1,20 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; -using System.Configuration; -using System.IO; using System.Linq; -using System.Reflection; using System.Threading; -using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Composing; namespace Umbraco.Core.IO { - public interface IFileSystems // fixme move! - { - IFileSystem MacroPartialsFileSystem { get; } - IFileSystem PartialViewsFileSystem { get; } - IFileSystem StylesheetsFileSystem { get; } - IFileSystem ScriptsFileSystem { get; } - IFileSystem MasterPagesFileSystem { get; } - IFileSystem MvcViewsFileSystem { get; } - MediaFileSystem MediaFileSystem { get; } - } - public class FileSystems : IFileSystems { - private readonly IFileSystemProvidersSection _config; private readonly ConcurrentSet _wrappers = new ConcurrentSet(); + private readonly IContainer _container; private readonly ILogger _logger; - private readonly ConcurrentDictionary _providerLookup = new ConcurrentDictionary(); - private readonly ConcurrentDictionary _filesystems = new ConcurrentDictionary(); + private readonly ConcurrentDictionary> _filesystems = new ConcurrentDictionary>(); // wrappers for shadow support private ShadowWrapper _macroPartialFileSystem; @@ -50,11 +34,9 @@ namespace Umbraco.Core.IO #region Constructor // DI wants a public ctor - // but IScopeProviderInternal is not public - public FileSystems(ILogger logger) + public FileSystems(IContainer container, ILogger logger) { - // fixme inject config section => can be used by tests - _config = (FileSystemProvidersSection) ConfigurationManager.GetSection("umbracoConfiguration/FileSystemProviders"); + _container = container; _logger = logger; } @@ -62,7 +44,6 @@ namespace Umbraco.Core.IO internal void Reset() { _wrappers.Clear(); - _providerLookup.Clear(); _filesystems.Clear(); Volatile.Write(ref _wkfsInitialized, false); } @@ -73,6 +54,7 @@ namespace Umbraco.Core.IO #region Well-Known FileSystems + /// public IFileSystem MacroPartialsFileSystem { get @@ -82,6 +64,7 @@ namespace Umbraco.Core.IO } } + /// public IFileSystem PartialViewsFileSystem { get @@ -91,6 +74,7 @@ namespace Umbraco.Core.IO } } + /// public IFileSystem StylesheetsFileSystem { get @@ -100,6 +84,7 @@ namespace Umbraco.Core.IO } } + /// public IFileSystem ScriptsFileSystem { get @@ -108,16 +93,18 @@ namespace Umbraco.Core.IO return _scriptsFileSystem; } } - + + /// public IFileSystem MasterPagesFileSystem { get { if (Volatile.Read(ref _wkfsInitialized) == false) EnsureWellKnownFileSystems(); - return _masterPagesFileSystem;// fixme - see 7.6?! + return _masterPagesFileSystem; } } + /// public IFileSystem MvcViewsFileSystem { get @@ -127,7 +114,8 @@ namespace Umbraco.Core.IO } } - public MediaFileSystem MediaFileSystem + /// + public IMediaFileSystem MediaFileSystem { get { @@ -160,7 +148,7 @@ namespace Umbraco.Core.IO _mvcViewsFileSystem = new ShadowWrapper(mvcViewsFileSystem, "Views", () => IsScoped()); // filesystems obtained from GetFileSystemProvider are already wrapped and do not need to be wrapped again - _mediaFileSystem = GetFileSystemProvider(); + _mediaFileSystem = GetFileSystem(); return null; } @@ -169,155 +157,42 @@ namespace Umbraco.Core.IO #region Providers - /// - /// used to cache the lookup of how to construct this object so we don't have to reflect each time. - /// - private class ProviderConstructionInfo - { - public object[] Parameters { get; set; } - public ConstructorInfo Constructor { get; set; } - //public string ProviderAlias { get; set; } - } - - /// - /// Gets an underlying (non-typed) filesystem supporting a strongly-typed filesystem. - /// - /// The alias of the strongly-typed filesystem. - /// The non-typed filesystem supporting the strongly-typed filesystem with the specified alias. - /// This method should not be used directly, used instead. - internal IFileSystem GetUnderlyingFileSystemProvider(string alias) - { - return GetUnderlyingFileSystemProvider(alias, null); - } - - /// - /// Gets an underlying (non-typed) filesystem supporting a strongly-typed filesystem. - /// - /// The alias of the strongly-typed filesystem. - /// A fallback creator for the filesystem. - /// The non-typed filesystem supporting the strongly-typed filesystem with the specified alias. - /// This method should not be used directly, used instead. - internal IFileSystem GetUnderlyingFileSystemProvider(string alias, Func fallback) - { - // either get the constructor info from cache or create it and add to cache - var ctorInfo = _providerLookup.GetOrAdd(alias, _ => GetUnderlyingFileSystemCtor(alias, fallback)); - return ctorInfo == null ? fallback() : (IFileSystem) ctorInfo.Constructor.Invoke(ctorInfo.Parameters); - } - - private IFileSystem GetUnderlyingFileSystemNoCache(string alias, Func fallback) - { - var ctorInfo = GetUnderlyingFileSystemCtor(alias, fallback); - return ctorInfo == null ? fallback() : (IFileSystem) ctorInfo.Constructor.Invoke(ctorInfo.Parameters); - } - - private ProviderConstructionInfo GetUnderlyingFileSystemCtor(string alias, Func fallback) - { - // get config - if (_config.Providers.TryGetValue(alias, out var providerConfig) == false) - { - if (fallback != null) return null; - throw new ArgumentException($"No provider found with alias {alias}."); - } - - // get the filesystem type - var providerType = Type.GetType(providerConfig.Type); - if (providerType == null) - throw new InvalidOperationException($"Could not find type {providerConfig.Type}."); - - // ensure it implements IFileSystem - if (providerType.IsAssignableFrom(typeof (IFileSystem))) - throw new InvalidOperationException($"Type {providerType.FullName} does not implement IFileSystem."); - - // find a ctor matching the config parameters - var paramCount = providerConfig.Parameters?.Count ?? 0; - var constructor = providerType.GetConstructors().SingleOrDefault(x - => x.GetParameters().Length == paramCount && x.GetParameters().All(y => providerConfig.Parameters.Keys.Contains(y.Name))); - if (constructor == null) - throw new InvalidOperationException($"Type {providerType.FullName} has no ctor matching the {paramCount} configuration parameter(s)."); - - var parameters = new object[paramCount]; - if (providerConfig.Parameters != null) // keeps ReSharper happy - { - var allKeys = providerConfig.Parameters.Keys.ToArray(); - for (var i = 0; i < paramCount; i++) - parameters[i] = providerConfig.Parameters[allKeys[i]]; - } - - return new ProviderConstructionInfo - { - Constructor = constructor, - Parameters = parameters, - //ProviderAlias = s - }; - } - /// /// Gets a strongly-typed filesystem. /// /// The type of the filesystem. /// A strongly-typed filesystem of the specified type. /// - /// Ideally, this should cache the instances, but that would break backward compatibility, so we - /// only do it for our own MediaFileSystem - for everything else, it's the responsibility of the caller - /// to ensure that they maintain singletons. This is important for singletons, as each filesystem maintains - /// its own shadow and having multiple instances would lead to inconsistencies. /// Note that any filesystem created by this method *after* shadowing begins, will *not* be /// shadowing (and an exception will be thrown by the ShadowWrapper). /// - // fixme - should it change for v8? - public TFileSystem GetFileSystemProvider() - where TFileSystem : FileSystemWrapper - { - return GetFileSystemProvider(null); - } - - /// - /// Gets a strongly-typed filesystem. - /// - /// The type of the filesystem. - /// A fallback creator for the inner filesystem. - /// A strongly-typed filesystem of the specified type. - /// - /// The fallback creator is used only if nothing is configured. - /// Ideally, this should cache the instances, but that would break backward compatibility, so we - /// only do it for our own MediaFileSystem - for everything else, it's the responsibility of the caller - /// to ensure that they maintain singletons. This is important for singletons, as each filesystem maintains - /// its own shadow and having multiple instances would lead to inconsistencies. - /// Note that any filesystem created by this method *after* shadowing begins, will *not* be - /// shadowing (and an exception will be thrown by the ShadowWrapper). - /// - public TFileSystem GetFileSystemProvider(Func fallback) + public TFileSystem GetFileSystem() where TFileSystem : FileSystemWrapper { var alias = GetFileSystemAlias(); - return (TFileSystem)_filesystems.GetOrAdd(alias, _ => - { - // gets the inner fs, create the strongly-typed fs wrapping the inner fs, register & return - // so we are double-wrapping here - // could be optimized by having FileSystemWrapper inherit from ShadowWrapper, maybe - var innerFs = GetUnderlyingFileSystemNoCache(alias, fallback); - var shadowWrapper = new ShadowWrapper(innerFs, "typed/" + alias, () => IsScoped()); - var fs = (IFileSystem)Activator.CreateInstance(typeof(TFileSystem), shadowWrapper); - _wrappers.Add(shadowWrapper); // keeping a reference to the wrapper - return fs; - }); + // note: GetOrAdd can run multiple times - and here, since we have side effects + // (adding to _wrappers) we want to be sure the factory runs only once, hence the + // additional Lazy. + return (TFileSystem) _filesystems.GetOrAdd(alias, _ => new Lazy(() => + { + var supportingFileSystem = _container.GetInstance(alias); + var shadowWrapper = new ShadowWrapper(supportingFileSystem, "typed/" + alias, () => IsScoped()); + + _wrappers.Add(shadowWrapper); // _wrappers is a concurrent set - this is safe + + return _container.CreateInstance(new { innerFileSystem = shadowWrapper}); + })).Value; } private string GetFileSystemAlias() { - var fsType = typeof(TFileSystem); - - // validate the ctor - var constructor = fsType.GetConstructors().SingleOrDefault(x - => x.GetParameters().Length >= 1 && TypeHelper.IsTypeAssignableFrom(x.GetParameters().First().ParameterType)); - if (constructor == null) - throw new InvalidOperationException("Type " + fsType.FullName + " must inherit from FileSystemWrapper and have a constructor that accepts one parameter of type " + typeof(IFileSystem).FullName + "."); + var fileSystemType = typeof(TFileSystem); // find the attribute and get the alias - var attr = (FileSystemProviderAttribute)fsType.GetCustomAttributes(typeof(FileSystemProviderAttribute), false).SingleOrDefault(); + var attr = (FileSystemAttribute) fileSystemType.GetCustomAttributes(typeof(FileSystemAttribute), false).SingleOrDefault(); if (attr == null) - throw new InvalidOperationException("Type " + fsType.FullName + "is missing the required FileSystemProviderAttribute."); + throw new InvalidOperationException("Type " + fileSystemType.FullName + "is missing the required FileSystemProviderAttribute."); return attr.Alias; } @@ -334,9 +209,9 @@ namespace Umbraco.Core.IO // be created directly (via ctor) or via GetFileSystem is *not* shadowed. // shadow must be enabled in an app event handler before anything else ie before any filesystem - // is actually created and used - after, it is too late - enabling shadow has a neglictible perfs + // is actually created and used - after, it is too late - enabling shadow has a negligible perfs // impact. - // NO! by the time an app event handler is instanciated it is already too late, see note in ctor. + // NO! by the time an app event handler is instantiated it is already too late, see note in ctor. //internal void EnableShadow() //{ // if (_mvcViewsFileSystem != null) // test one of the fs... diff --git a/src/Umbraco.Core/IO/IFileSystem.cs b/src/Umbraco.Core/IO/IFileSystem.cs index 115cb8a5c1..14b015a468 100644 --- a/src/Umbraco.Core/IO/IFileSystem.cs +++ b/src/Umbraco.Core/IO/IFileSystem.cs @@ -5,7 +5,7 @@ using System.IO; namespace Umbraco.Core.IO { /// - /// Provides methods allowing the manipulation of files within an Umbraco application. + /// Provides methods allowing the manipulation of files. /// public interface IFileSystem { diff --git a/src/Umbraco.Core/IO/IFileSystems.cs b/src/Umbraco.Core/IO/IFileSystems.cs new file mode 100644 index 0000000000..1af5377c43 --- /dev/null +++ b/src/Umbraco.Core/IO/IFileSystems.cs @@ -0,0 +1,43 @@ +namespace Umbraco.Core.IO +{ + /// + /// Provides the system filesystems. + /// + public interface IFileSystems + { + /// + /// Gets the macro partials filesystem. + /// + IFileSystem MacroPartialsFileSystem { get; } + + /// + /// Gets the partial views filesystem. + /// + IFileSystem PartialViewsFileSystem { get; } + + /// + /// Gets the stylesheets filesystem. + /// + IFileSystem StylesheetsFileSystem { get; } + + /// + /// Gets the scripts filesystem. + /// + IFileSystem ScriptsFileSystem { get; } + + /// + /// Gets the masterpages filesystem. + /// + IFileSystem MasterPagesFileSystem { get; } + + /// + /// Gets the MVC views filesystem. + /// + IFileSystem MvcViewsFileSystem { get; } + + /// + /// Gets the media filesystem. + /// + IMediaFileSystem MediaFileSystem { get; } + } +} diff --git a/src/Umbraco.Core/IO/IMediaFileSystem.cs b/src/Umbraco.Core/IO/IMediaFileSystem.cs new file mode 100644 index 0000000000..e1957857bf --- /dev/null +++ b/src/Umbraco.Core/IO/IMediaFileSystem.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.IO; +using Umbraco.Core.Models; + +namespace Umbraco.Core.IO +{ + /// + /// Provides methods allowing the manipulation of media files. + /// + public interface IMediaFileSystem : IFileSystem + { + /// + /// Delete media files. + /// + /// Files to delete (filesystem-relative paths). + void DeleteMediaFiles(IEnumerable files); + + /// + /// Gets the file path of a media file. + /// + /// The file name. + /// The unique identifier of the content/media owning the file. + /// The unique identifier of the property type owning the file. + /// The filesystem-relative path to the media file. + /// With the old media path scheme, this CREATES a new media path each time it is invoked. + string GetMediaPath(string filename, Guid cuid, Guid puid); + + /// + /// Gets the file path of a media file. + /// + /// The file name. + /// A previous file path. + /// The unique identifier of the content/media owning the file. + /// The unique identifier of the property type owning the file. + /// The filesystem-relative path to the media file. + /// In the old, legacy, number-based scheme, we try to re-use the media folder + /// specified by . Else, we CREATE a new one. Each time we are invoked. + string GetMediaPath(string filename, string prevpath, Guid cuid, Guid puid); + + /// + /// Stores a media file associated to a property of a content item. + /// + /// The content item owning the media file. + /// The property type owning the media file. + /// The media file name. + /// A stream containing the media bytes. + /// An optional filesystem-relative filepath to the previous media file. + /// The filesystem-relative filepath to the media file. + /// + /// The file is considered "owned" by the content/propertyType. + /// If an is provided then that file (and associated thumbnails if any) is deleted + /// before the new file is saved, and depending on the media path scheme, the folder may be reused for the new file. + /// + string StoreFile(IContentBase content, PropertyType propertyType, string filename, Stream filestream, string oldpath); + + /// + /// Copies a media file as a new media file, associated to a property of a content item. + /// + /// The content item owning the copy of the media file. + /// The property type owning the copy of the media file. + /// The filesystem-relative path to the source media file. + /// The filesystem-relative path to the copy of the media file. + string CopyFile(IContentBase content, PropertyType propertyType, string sourcepath); + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/IO/MediaFileSystem.cs b/src/Umbraco.Core/IO/MediaFileSystem.cs index 1b0c8079f0..c36a086bf8 100644 --- a/src/Umbraco.Core/IO/MediaFileSystem.cs +++ b/src/Umbraco.Core/IO/MediaFileSystem.cs @@ -15,11 +15,14 @@ namespace Umbraco.Core.IO /// /// A custom file system provider for media /// - [FileSystemProvider("media")] - public class MediaFileSystem : FileSystemWrapper + [FileSystem("media")] + public class MediaFileSystem : FileSystemWrapper, IMediaFileSystem { - public MediaFileSystem(IFileSystem wrapped) - : base(wrapped) + /// + /// Initializes a new instance of the class. + /// + public MediaFileSystem(IFileSystem innerFileSystem) + : base(innerFileSystem) { ContentConfig = Current.Container.GetInstance(); Logger = Current.Container.GetInstance(); @@ -32,58 +35,16 @@ namespace Umbraco.Core.IO private IContentSection ContentConfig { get; } private ILogger Logger { get; } - - /// - /// Deletes all files passed in. - /// - /// - /// - /// - internal bool DeleteFiles(IEnumerable files, Action onError = null) - { - //ensure duplicates are removed - files = files.Distinct(); - - var allsuccess = true; - var rootRelativePath = GetRelativePath("/"); - - Parallel.ForEach(files, file => - { - try - { - if (file.IsNullOrWhiteSpace()) return; - - var relativeFilePath = GetRelativePath(file); - if (FileExists(relativeFilePath) == false) return; - - var parentDirectory = Path.GetDirectoryName(relativeFilePath); - - // don't want to delete the media folder if not using directories. - if (ContentConfig.UploadAllowDirectories && parentDirectory != rootRelativePath) - { - //issue U4-771: if there is a parent directory the recursive parameter should be true - DeleteDirectory(parentDirectory, string.IsNullOrEmpty(parentDirectory) == false); - } - else - { - DeleteFile(file); - } - } - catch (Exception e) - { - onError?.Invoke(file, e); - allsuccess = false; - } - }); - - return allsuccess; - } + /// public void DeleteMediaFiles(IEnumerable files) { files = files.Distinct(); - Parallel.ForEach(files, file => + // kinda try to keep things under control + var options = new ParallelOptions { MaxDegreeOfParallelism = 20 }; + + Parallel.ForEach(files, options, file => { try { @@ -97,21 +58,14 @@ namespace Umbraco.Core.IO } catch (Exception e) { - Logger.Error(e, "Failed to delete attached file '{File}'", file); + Logger.Error(e, "Failed to delete media file '{File}'.", file); } }); } #region Media Path - /// - /// Gets the file path of a media file. - /// - /// The file name. - /// The unique identifier of the content/media owning the file. - /// The unique identifier of the property type owning the file. - /// The filesystem-relative path to the media file. - /// With the old media path scheme, this CREATES a new media path each time it is invoked. + /// public string GetMediaPath(string filename, Guid cuid, Guid puid) { filename = Path.GetFileName(filename); @@ -121,16 +75,7 @@ namespace Umbraco.Core.IO return MediaPathScheme.GetFilePath(cuid, puid, filename); } - /// - /// Gets the file path of a media file. - /// - /// The file name. - /// A previous file path. - /// The unique identifier of the content/media owning the file. - /// The unique identifier of the property type owning the file. - /// The filesystem-relative path to the media file. - /// In the old, legacy, number-based scheme, we try to re-use the media folder - /// specified by . Else, we CREATE a new one. Each time we are invoked. + /// public string GetMediaPath(string filename, string prevpath, Guid cuid, Guid puid) { filename = Path.GetFileName(filename); @@ -144,20 +89,7 @@ namespace Umbraco.Core.IO #region Associated Media Files - /// - /// Stores a media file associated to a property of a content item. - /// - /// The content item owning the media file. - /// The property type owning the media file. - /// The media file name. - /// A stream containing the media bytes. - /// An optional filesystem-relative filepath to the previous media file. - /// The filesystem-relative filepath to the media file. - /// - /// The file is considered "owned" by the content/propertyType. - /// If an is provided then that file (and associated thumbnails if any) is deleted - /// before the new file is saved, and depending on the media path scheme, the folder may be reused for the new file. - /// + /// public string StoreFile(IContentBase content, PropertyType propertyType, string filename, Stream filestream, string oldpath) { if (content == null) throw new ArgumentNullException(nameof(content)); @@ -176,13 +108,7 @@ namespace Umbraco.Core.IO return filepath; } - /// - /// Copies a media file as a new media file, associated to a property of a content item. - /// - /// The content item owning the copy of the media file. - /// The property type owning the copy of the media file. - /// The filesystem-relative path to the source media file. - /// The filesystem-relative path to the copy of the media file. + /// public string CopyFile(IContentBase content, PropertyType propertyType, string sourcepath) { if (content == null) throw new ArgumentNullException(nameof(content)); @@ -199,9 +125,6 @@ namespace Umbraco.Core.IO return filepath; } - - - #endregion - + #endregion } } diff --git a/src/Umbraco.Core/IO/ShadowFileSystems.cs b/src/Umbraco.Core/IO/ShadowFileSystems.cs index 289667b0db..80aa1791fd 100644 --- a/src/Umbraco.Core/IO/ShadowFileSystems.cs +++ b/src/Umbraco.Core/IO/ShadowFileSystems.cs @@ -6,19 +6,6 @@ namespace Umbraco.Core.IO { internal class ShadowFileSystems : ICompletable { - // note: taking a reference to the _manager instead of using manager.Current - // to avoid using Current everywhere but really, we support only 1 scope at - // a time, not multiple scopes in case of multiple managers (not supported) - - // fixme - why are we managing logical call context here? should be bound - // to the current scope, always => REFACTOR! but there should be something in - // place (static?) to ensure we only have one concurrent shadow FS? - // - // => yes, that's _currentId - need to cleanup this entirely - // and, we probably need a way to stop shadowing entirely without cycling the app - - private const string ItemKey = "Umbraco.Core.IO.ShadowFileSystems"; - private static readonly object Locker = new object(); private static Guid _currentId = Guid.Empty; @@ -28,26 +15,13 @@ namespace Umbraco.Core.IO private bool _completed; - //static ShadowFileSystems() - //{ - // SafeCallContext.Register( - // () => - // { - // var scope = CallContext.LogicalGetData(ItemKey); - // CallContext.FreeNamedDataSlot(ItemKey); - // return scope; - // }, - // o => - // { - // if (CallContext.LogicalGetData(ItemKey) != null) throw new InvalidOperationException(); - // if (o != null) CallContext.LogicalSetData(ItemKey, o); - // }); - //} - + // invoked by the filesystems when shadowing + // can only be 1 shadow at a time (static) public ShadowFileSystems(Guid id, ShadowWrapper[] wrappers, ILogger logger) { lock (Locker) { + // if we throw here, it means that something very wrong happened. if (_currentId != Guid.Empty) throw new InvalidOperationException("Already shadowing."); _currentId = id; @@ -62,56 +36,23 @@ namespace Umbraco.Core.IO wrapper.Shadow(id); } - // fixme - remove - //// internal for tests + FileSystems - //// do NOT use otherwise - //internal static ShadowFileSystems CreateScope(Guid id, ShadowWrapper[] wrappers, ILogger logger) - //{ - // lock (Locker) - // { - // if (CallContext.LogicalGetData(ItemKey) != null) throw new InvalidOperationException("Already shadowing."); - // CallContext.LogicalSetData(ItemKey, ItemKey); // value does not matter - // } - // return new ShadowFileSystems(id, wrappers, logger); - //} - - //internal static bool InScope => NoScope == false; - - //internal static bool NoScope => CallContext.LogicalGetData(ItemKey) == null; - + // invoked by the scope when exiting, if completed public void Complete() { _completed = true; - //lock (Locker) - //{ - // _logger.Debug("UnShadow " + _id + " (complete)."); - - // var exceptions = new List(); - // foreach (var wrapper in _wrappers) - // { - // try - // { - // // this may throw an AggregateException if some of the changes could not be applied - // wrapper.UnShadow(true); - // } - // catch (AggregateException ae) - // { - // exceptions.Add(ae); - // } - // } - - // if (exceptions.Count > 0) - // throw new AggregateException("Failed to apply all changes (see exceptions).", exceptions); - - // // last, & *only* if successful (otherwise we'll unshadow & cleanup as best as we can) - // CallContext.FreeNamedDataSlot(ItemKey); - //} } + // invoked by the scope when exiting public void Dispose() { lock (Locker) { + // if we throw here, it means that something very wrong happened. + if (_currentId == Guid.Empty) + throw new InvalidOperationException("Not shadowing."); + if (_id != _currentId) + throw new InvalidOperationException("Not the current shadow."); + _logger.Debug("UnShadow '{ShadowId}' {Status}", _id, _completed ? "complete" : "abort"); var exceptions = new List(); @@ -132,20 +73,6 @@ namespace Umbraco.Core.IO if (exceptions.Count > 0) throw new AggregateException(_completed ? "Failed to apply all changes (see exceptions)." : "Failed to abort (see exceptions).", exceptions); - - //if (CallContext.LogicalGetData(ItemKey) == null) return; - - //try - //{ - // _logger.Debug("UnShadow " + _id + " (abort)"); - // foreach (var wrapper in _wrappers) - // wrapper.UnShadow(false); // should not throw - //} - //finally - //{ - // // last, & always - // CallContext.FreeNamedDataSlot(ItemKey); - //} } } diff --git a/src/Umbraco.Core/Services/Implement/ContentService.cs b/src/Umbraco.Core/Services/Implement/ContentService.cs index f14747cda3..999bd56646 100644 --- a/src/Umbraco.Core/Services/Implement/ContentService.cs +++ b/src/Umbraco.Core/Services/Implement/ContentService.cs @@ -28,13 +28,13 @@ namespace Umbraco.Core.Services.Implement private readonly IContentTypeRepository _contentTypeRepository; private readonly IDocumentBlueprintRepository _documentBlueprintRepository; private readonly ILanguageRepository _languageRepository; - private readonly MediaFileSystem _mediaFileSystem; + private readonly IMediaFileSystem _mediaFileSystem; private IQuery _queryNotTrashed; #region Constructors public ContentService(IScopeProvider provider, ILogger logger, - IEventMessagesFactory eventMessagesFactory, MediaFileSystem mediaFileSystem, + IEventMessagesFactory eventMessagesFactory, IMediaFileSystem mediaFileSystem, IDocumentRepository documentRepository, IEntityRepository entityRepository, IAuditRepository auditRepository, IContentTypeRepository contentTypeRepository, IDocumentBlueprintRepository documentBlueprintRepository, ILanguageRepository languageRepository) : base(provider, logger, eventMessagesFactory) @@ -1471,9 +1471,7 @@ namespace Umbraco.Core.Services.Implement var args = new DeleteEventArgs(c, false); // raise event & get flagged files scope.Events.Dispatch(Deleted, this, args, nameof(Deleted)); - // fixme not going to work, do it differently - _mediaFileSystem.DeleteFiles(args.MediaFilesToDelete, // remove flagged files - (file, e) => Logger.Error(e, "An error occurred while deleting file attached to nodes: {File}", file)); + // media files deleted by QueuingEventDispatcher } } diff --git a/src/Umbraco.Core/Services/Implement/MediaService.cs b/src/Umbraco.Core/Services/Implement/MediaService.cs index da04f41e18..8363935adb 100644 --- a/src/Umbraco.Core/Services/Implement/MediaService.cs +++ b/src/Umbraco.Core/Services/Implement/MediaService.cs @@ -26,11 +26,11 @@ namespace Umbraco.Core.Services.Implement private readonly IAuditRepository _auditRepository; private readonly IEntityRepository _entityRepository; - private readonly MediaFileSystem _mediaFileSystem; + private readonly IMediaFileSystem _mediaFileSystem; #region Constructors - public MediaService(IScopeProvider provider, MediaFileSystem mediaFileSystem, ILogger logger, IEventMessagesFactory eventMessagesFactory, + public MediaService(IScopeProvider provider, IMediaFileSystem mediaFileSystem, ILogger logger, IEventMessagesFactory eventMessagesFactory, IMediaRepository mediaRepository, IAuditRepository auditRepository, IMediaTypeRepository mediaTypeRepository, IEntityRepository entityRepository) : base(provider, logger, eventMessagesFactory) @@ -888,8 +888,7 @@ namespace Umbraco.Core.Services.Implement var args = new DeleteEventArgs(c, false); // raise event & get flagged files scope.Events.Dispatch(Deleted, this, args); - _mediaFileSystem.DeleteFiles(args.MediaFilesToDelete, // remove flagged files - (file, e) => Logger.Error(e, "An error occurred while deleting file attached to nodes: {File}", file)); + // media files deleted by QueuingEventDispatcher } } diff --git a/src/Umbraco.Core/Services/Implement/MemberService.cs b/src/Umbraco.Core/Services/Implement/MemberService.cs index 3fd714f974..82be6d3dc6 100644 --- a/src/Umbraco.Core/Services/Implement/MemberService.cs +++ b/src/Umbraco.Core/Services/Implement/MemberService.cs @@ -28,14 +28,14 @@ namespace Umbraco.Core.Services.Implement private readonly IAuditRepository _auditRepository; private readonly IMemberGroupService _memberGroupService; - private readonly MediaFileSystem _mediaFileSystem; + private readonly IMediaFileSystem _mediaFileSystem; //only for unit tests! internal MembershipProviderBase MembershipProvider { get; set; } #region Constructor - public MemberService(IScopeProvider provider, ILogger logger, IEventMessagesFactory eventMessagesFactory, IMemberGroupService memberGroupService, MediaFileSystem mediaFileSystem, + public MemberService(IScopeProvider provider, ILogger logger, IEventMessagesFactory eventMessagesFactory, IMemberGroupService memberGroupService, IMediaFileSystem mediaFileSystem, IMemberRepository memberRepository, IMemberTypeRepository memberTypeRepository, IMemberGroupRepository memberGroupRepository, IAuditRepository auditRepository) : base(provider, logger, eventMessagesFactory) { @@ -927,10 +927,7 @@ namespace Umbraco.Core.Services.Implement args.CanCancel = false; scope.Events.Dispatch(Deleted, this, args); - // fixme - this is MOOT because the event will not trigger immediately - // it's been refactored already (think it's the dispatcher that deals with it?) - _mediaFileSystem.DeleteFiles(args.MediaFilesToDelete, // remove flagged files - (file, e) => Logger.Error(e, "An error occurred while deleting file attached to nodes: {File}", file)); + // media files deleted by QueuingEventDispatcher } #endregion diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 59f353e1e9..e7d85472fb 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -329,6 +329,8 @@ + + @@ -574,7 +576,7 @@ - + diff --git a/src/Umbraco.Tests/IO/FileSystemsTests.cs b/src/Umbraco.Tests/IO/FileSystemsTests.cs index f97bdc4189..fe27229c72 100644 --- a/src/Umbraco.Tests/IO/FileSystemsTests.cs +++ b/src/Umbraco.Tests/IO/FileSystemsTests.cs @@ -6,6 +6,7 @@ using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Composing; +using Umbraco.Core.Composing.Composers; using Umbraco.Core.IO; using Umbraco.Core.IO.MediaPathSchemes; using Umbraco.Core.Logging; @@ -29,11 +30,12 @@ namespace Umbraco.Tests.IO _container = Current.Container = ContainerFactory.Create(); _container.Register(_ => Mock.Of()); - _container.Register(); _container.Register(_ => Mock.Of()); _container.Register(_ => Mock.Of()); _container.RegisterSingleton(); + _container.ComposeFileSystems(); + // make sure we start clean // because some tests will create corrupt or weird filesystems FileSystems.Reset(); @@ -52,25 +54,39 @@ namespace Umbraco.Tests.IO private FileSystems FileSystems => _container.GetInstance(); [Test] - public void Can_Get_Base_File_System() + public void Can_Get_MediaFileSystem() { - var fileSystem = FileSystems.GetUnderlyingFileSystemProvider("media"); - + var fileSystem = FileSystems.GetFileSystem(); Assert.NotNull(fileSystem); } [Test] - public void Can_Get_Typed_File_System() + public void Can_Get_IMediaFileSystem() { - var fileSystem = FileSystems.GetFileSystemProvider(); - + var fileSystem = _container.GetInstance(); Assert.NotNull(fileSystem); } [Test] - public void Media_Fs_Safe_Delete() + public void MediaFileSystem_Is_Singleton() { - var fs = FileSystems.GetFileSystemProvider(); + var fileSystem1 = FileSystems.GetFileSystem(); + var fileSystem2 = FileSystems.GetFileSystem(); + Assert.AreSame(fileSystem1, fileSystem2); + } + + [Test] + public void IMediaFileSystem_Is_Singleton() + { + var fileSystem1 = _container.GetInstance(); + var fileSystem2 = _container.GetInstance(); + Assert.AreSame(fileSystem1, fileSystem2); + } + + [Test] + public void Can_Delete_MediaFiles() + { + var fs = FileSystems.GetFileSystem(); var ms = new MemoryStream(Encoding.UTF8.GetBytes("test")); var virtPath = fs.GetMediaPath("file.txt", Guid.NewGuid(), Guid.NewGuid()); fs.AddFile(virtPath, ms); @@ -92,51 +108,37 @@ namespace Umbraco.Tests.IO Assert.IsTrue(Directory.Exists(physPath)); } - public void Singleton_Typed_File_System() + [Test] + public void Cannot_Get_InvalidFileSystem() { - var fs1 = FileSystems.GetFileSystemProvider(); - var fs2 = FileSystems.GetFileSystemProvider(); - - Assert.AreSame(fs1, fs2); + // throws because InvalidTypedFileSystem does not have the proper attribute with an alias + Assert.Throws(() => FileSystems.GetFileSystem()); } [Test] - public void Exception_Thrown_On_Invalid_Typed_File_System() - { - Assert.Throws(() => FileSystems.GetFileSystemProvider()); - } - - [Test] - public void Exception_Thrown_On_NonConfigured_Typed_File_System() + public void Cannot_Get_NonConfiguredFileSystem() { // note: we need to reset the manager between tests else the Accept_Fallback test would corrupt that one - Assert.Throws(() => FileSystems.GetFileSystemProvider()); + // throws because NonConfiguredFileSystem has the proper attribute with an alias, + // but then the container cannot find an IFileSystem implementation for that alias + Assert.Throws(() => FileSystems.GetFileSystem()); + + // all we'd need to pass is to register something like: + //_container.Register("noconfig", factory => new PhysicalFileSystem("~/foo")); } - [Test] - public void Accept_Fallback_On_NonConfigured_Typed_File_System() + internal class InvalidFileSystem : FileSystemWrapper { - var fs = FileSystems.GetFileSystemProvider(() => new PhysicalFileSystem("~/App_Data/foo")); - - Assert.NotNull(fs); - } - - /// - /// Used in unit tests, for a typed file system we need to inherit from FileSystemWrapper and they MUST have a ctor - /// that only accepts a base IFileSystem object - /// - internal class InvalidTypedFileSystem : FileSystemWrapper - { - public InvalidTypedFileSystem(IFileSystem wrapped, string invalidParam) - : base(wrapped) + public InvalidFileSystem(IFileSystem innerFileSystem) + : base(innerFileSystem) { } } - [FileSystemProvider("noconfig")] - internal class NonConfiguredTypeFileSystem : FileSystemWrapper + [FileSystem("noconfig")] + internal class NonConfiguredFileSystem : FileSystemWrapper { - public NonConfiguredTypeFileSystem(IFileSystem wrapped) - : base(wrapped) + public NonConfiguredFileSystem(IFileSystem innerFileSystem) + : base(innerFileSystem) { } } } diff --git a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs index f652205147..56987416a4 100644 --- a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs @@ -33,8 +33,7 @@ namespace Umbraco.Tests.Scoping _testObjects = new TestObjects(container); - Current.Container.RegisterSingleton(f => Current.Container); - Current.Container.RegisterSingleton(factory => new FileSystems(factory.TryGetInstance())); + Current.Container.RegisterSingleton(factory => new FileSystems(container, factory.TryGetInstance())); Current.Container.RegisterCollectionBuilder(); SettingsForTests.Reset(); // ensure we have configuration diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects.cs b/src/Umbraco.Tests/TestHelpers/TestObjects.cs index fb4eed6180..b2ac7b4431 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects.cs @@ -240,7 +240,7 @@ namespace Umbraco.Tests.TestHelpers databaseFactory = new UmbracoDatabaseFactory(Constants.System.UmbracoConnectionName, GetDefaultSqlSyntaxProviders(logger), logger, mappers); } - fileSystems = fileSystems ?? new FileSystems(logger); + fileSystems = fileSystems ?? new FileSystems(Current.Container, logger); var scopeProvider = new ScopeProvider(databaseFactory, fileSystems, logger); return scopeProvider; } diff --git a/src/Umbraco.Web/Editors/ImagesController.cs b/src/Umbraco.Web/Editors/ImagesController.cs index e9b89a0ab4..0eb0f54882 100644 --- a/src/Umbraco.Web/Editors/ImagesController.cs +++ b/src/Umbraco.Web/Editors/ImagesController.cs @@ -17,10 +17,10 @@ namespace Umbraco.Web.Editors [PluginController("UmbracoApi")] public class ImagesController : UmbracoAuthorizedApiController { - private readonly MediaFileSystem _mediaFileSystem; + private readonly IMediaFileSystem _mediaFileSystem; private readonly IContentSection _contentSection; - public ImagesController(MediaFileSystem mediaFileSystem, IContentSection contentSection) + public ImagesController(IMediaFileSystem mediaFileSystem, IContentSection contentSection) { _mediaFileSystem = mediaFileSystem; _contentSection = contentSection; diff --git a/src/Umbraco.Web/Media/UploadAutoFillProperties.cs b/src/Umbraco.Web/Media/UploadAutoFillProperties.cs index 6a56dec918..01ced179d6 100644 --- a/src/Umbraco.Web/Media/UploadAutoFillProperties.cs +++ b/src/Umbraco.Web/Media/UploadAutoFillProperties.cs @@ -15,11 +15,11 @@ namespace Umbraco.Web.Media /// internal class UploadAutoFillProperties { - private readonly MediaFileSystem _mediaFileSystem; + private readonly IMediaFileSystem _mediaFileSystem; private readonly ILogger _logger; private readonly IContentSection _contentSection; - public UploadAutoFillProperties(MediaFileSystem mediaFileSystem, ILogger logger, IContentSection contentSection) + public UploadAutoFillProperties(IMediaFileSystem mediaFileSystem, ILogger logger, IContentSection contentSection) { _mediaFileSystem = mediaFileSystem ?? throw new ArgumentNullException(nameof(mediaFileSystem)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); diff --git a/src/Umbraco.Web/PropertyEditors/FileUploadPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/FileUploadPropertyEditor.cs index 412b8c9766..2b32e9d774 100644 --- a/src/Umbraco.Web/PropertyEditors/FileUploadPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/FileUploadPropertyEditor.cs @@ -15,11 +15,11 @@ namespace Umbraco.Web.PropertyEditors [DataEditor(Constants.PropertyEditors.Aliases.UploadField, "File upload", "fileupload", Icon = "icon-download-alt", Group = "media")] public class FileUploadPropertyEditor : DataEditor { - private readonly MediaFileSystem _mediaFileSystem; + private readonly IMediaFileSystem _mediaFileSystem; private readonly IContentSection _contentSection; private readonly UploadAutoFillProperties _uploadAutoFillProperties; - public FileUploadPropertyEditor(ILogger logger, MediaFileSystem mediaFileSystem, IContentSection contentSection) + public FileUploadPropertyEditor(ILogger logger, IMediaFileSystem mediaFileSystem, IContentSection contentSection) : base(logger) { _mediaFileSystem = mediaFileSystem ?? throw new ArgumentNullException(nameof(mediaFileSystem)); diff --git a/src/Umbraco.Web/PropertyEditors/FileUploadPropertyValueEditor.cs b/src/Umbraco.Web/PropertyEditors/FileUploadPropertyValueEditor.cs index 47711507b2..f36dd6bfa8 100644 --- a/src/Umbraco.Web/PropertyEditors/FileUploadPropertyValueEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/FileUploadPropertyValueEditor.cs @@ -15,9 +15,9 @@ namespace Umbraco.Web.PropertyEditors /// internal class FileUploadPropertyValueEditor : DataValueEditor { - private readonly MediaFileSystem _mediaFileSystem; + private readonly IMediaFileSystem _mediaFileSystem; - public FileUploadPropertyValueEditor(DataEditorAttribute attribute, MediaFileSystem mediaFileSystem) + public FileUploadPropertyValueEditor(DataEditorAttribute attribute, IMediaFileSystem mediaFileSystem) : base(attribute) { _mediaFileSystem = mediaFileSystem ?? throw new ArgumentNullException(nameof(mediaFileSystem)); diff --git a/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyEditor.cs index c8a7bfc80c..70b705f397 100644 --- a/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyEditor.cs @@ -22,7 +22,7 @@ namespace Umbraco.Web.PropertyEditors [DataEditor(Constants.PropertyEditors.Aliases.ImageCropper, "Image Cropper", "imagecropper", ValueType = ValueTypes.Json, HideLabel = false, Group="media", Icon="icon-crop")] public class ImageCropperPropertyEditor : DataEditor { - private readonly MediaFileSystem _mediaFileSystem; + private readonly IMediaFileSystem _mediaFileSystem; private readonly IContentSection _contentSettings; private readonly IDataTypeService _dataTypeService; private readonly UploadAutoFillProperties _autoFillProperties; @@ -30,7 +30,7 @@ namespace Umbraco.Web.PropertyEditors /// /// Initializes a new instance of the class. /// - public ImageCropperPropertyEditor(ILogger logger, MediaFileSystem mediaFileSystem, IContentSection contentSettings, IDataTypeService dataTypeService) + public ImageCropperPropertyEditor(ILogger logger, IMediaFileSystem mediaFileSystem, IContentSection contentSettings, IDataTypeService dataTypeService) : base(logger) { _mediaFileSystem = mediaFileSystem ?? throw new ArgumentNullException(nameof(mediaFileSystem)); diff --git a/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyValueEditor.cs b/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyValueEditor.cs index 4f44352d34..88da8982c7 100644 --- a/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyValueEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyValueEditor.cs @@ -19,9 +19,9 @@ namespace Umbraco.Web.PropertyEditors internal class ImageCropperPropertyValueEditor : DataValueEditor // fixme core vs web? { private readonly ILogger _logger; - private readonly MediaFileSystem _mediaFileSystem; + private readonly IMediaFileSystem _mediaFileSystem; - public ImageCropperPropertyValueEditor(DataEditorAttribute attribute, ILogger logger, MediaFileSystem mediaFileSystem) + public ImageCropperPropertyValueEditor(DataEditorAttribute attribute, ILogger logger, IMediaFileSystem mediaFileSystem) : base(attribute) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); From c967d6a0fcd25a87ca91df85b0a0385e4dd4b2bb Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Fri, 26 Oct 2018 21:14:19 +0200 Subject: [PATCH 075/469] Makes Container.CreateInstance into an extension --- .../Composing/ContainerExtensions.cs | 39 +++++++++++++++++++ src/Umbraco.Core/Composing/IContainer.cs | 14 +------ .../LightInject/LightInjectContainer.cs | 27 ------------- 3 files changed, 40 insertions(+), 40 deletions(-) diff --git a/src/Umbraco.Core/Composing/ContainerExtensions.cs b/src/Umbraco.Core/Composing/ContainerExtensions.cs index 86e18db35b..36af613e55 100644 --- a/src/Umbraco.Core/Composing/ContainerExtensions.cs +++ b/src/Umbraco.Core/Composing/ContainerExtensions.cs @@ -2,6 +2,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; +using System.Reflection; namespace Umbraco.Core.Composing { @@ -172,5 +173,43 @@ namespace Umbraco.Core.Composing // initialize and return the builder return container.GetInstance(); } + + /// + /// Creates an instance of a service, with arguments. + /// + /// + /// The type of the instance. + /// Named arguments. + /// An instance of the specified type. + /// + /// The instance type does not need to be registered into the container. + /// The arguments are used as dependencies by the container. Other dependencies + /// are retrieved from the container. + /// + public static object CreateInstance(this IContainer container, Type type, IDictionary args) + { + // LightInject has this, but then it requires RegisterConstructorDependency etc and has various oddities + // including the most annoying one, which is that it does not work on singletons (hard to fix) + //return Container.GetInstance(type, args); + + // this method is essentially used to build singleton instances, so it is assumed that it would be + // more expensive to build and cache a dynamic method ctor than to simply invoke the ctor, as we do + // here - this can be discussed + + var ctor = type.GetConstructors(BindingFlags.Instance | BindingFlags.Public).OrderByDescending(x => x.GetParameters().Length).FirstOrDefault(); + if (ctor == null) throw new InvalidOperationException($"Could not find a public constructor for type {type.FullName}."); + + var ctorParameters = ctor.GetParameters(); + var ctorArgs = new object[ctorParameters.Length]; + var i = 0; + foreach (var parameter in ctorParameters) + { + // no! IsInstanceOfType is not ok here + // ReSharper disable once UseMethodIsInstanceOfType + var arg = args?.Values.FirstOrDefault(a => parameter.ParameterType.IsAssignableFrom(a.GetType())); + ctorArgs[i++] = arg ?? container.GetInstance(parameter.ParameterType); + } + return ctor.Invoke(ctorArgs); + } } } diff --git a/src/Umbraco.Core/Composing/IContainer.cs b/src/Umbraco.Core/Composing/IContainer.cs index 78137eb990..1780516c76 100644 --- a/src/Umbraco.Core/Composing/IContainer.cs +++ b/src/Umbraco.Core/Composing/IContainer.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using Umbraco.Core.Composing.LightInject; namespace Umbraco.Core.Composing { @@ -77,19 +78,6 @@ namespace Umbraco.Core.Composing /// The registrations for the service. IEnumerable GetRegistered(Type serviceType); - /// - /// Creates an instance of a service, with arguments. - /// - /// The type of the instance. - /// Named arguments. - /// An instance of the specified type. - /// - /// The instance type does not need to be registered into the container. - /// The arguments are used as dependencies by the container. Other dependencies - /// are retrieved from the container. - /// - object CreateInstance(Type type, IDictionary args); - /// /// Releases an instance. /// diff --git a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs index dca07938cc..34bd2f1499 100644 --- a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs +++ b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs @@ -125,33 +125,6 @@ namespace Umbraco.Core.Composing.LightInject public IEnumerable GetRegistered(Type type) => Container.AvailableServices.Where(x => x.ServiceType == type).Select(x => new Registration(x.ServiceType, x.ServiceName)); - /// - public object CreateInstance(Type type, IDictionary args) - { - // LightInject has this, but then it requires RegisterConstructorDependency etc and has various oddities - // including the most annoying one, which is that it does not work on singletons (hard to fix) - //return Container.GetInstance(type, args); - - // this method is essentially used to build singleton instances, so it is assumed that it would be - // more expensive to build and cache a dynamic method ctor than to simply invoke the ctor, as we do - // here - this can be discussed - - var ctor = type.GetConstructors(BindingFlags.Instance | BindingFlags.Public).OrderByDescending(x => x.GetParameters().Length).FirstOrDefault(); - if (ctor == null) throw new InvalidOperationException($"Could not find a public constructor for type {type.FullName}."); - - var ctorParameters = ctor.GetParameters(); - var ctorArgs = new object[ctorParameters.Length]; - var i = 0; - foreach (var parameter in ctorParameters) - { - // no! IsInstanceOfType is not ok here - // ReSharper disable once UseMethodIsInstanceOfType - var arg = args?.Values.FirstOrDefault(a => parameter.ParameterType.IsAssignableFrom(a.GetType())); - ctorArgs[i++] = arg ?? GetInstance(parameter.ParameterType); - } - return ctor.Invoke(ctorArgs); - } - /// public void Release(object instance) { From 993972fa62bcca6fa482c6af0f3608bf01db2b0e Mon Sep 17 00:00:00 2001 From: Stefano Chiodino Date: Thu, 8 Nov 2018 13:24:34 +0000 Subject: [PATCH 076/469] #3544: change template reference for its ID (WIP: it builds) --- src/Umbraco.Core/Models/Content.cs | 16 +- src/Umbraco.Core/Models/IContent.cs | 8 +- .../Factories/ContentBaseFactory.cs | 2 +- .../Implement/DocumentRepository.cs | 16 +- .../Services/EntityXmlSerializer.cs | 2 +- src/Umbraco.Examine/UmbracoContentIndexer.cs | 2 +- src/Umbraco.Tests/Models/ContentTests.cs | 29 +- src/Umbraco.Tests/Models/ContentXmlTest.cs | 2 +- .../Repositories/DocumentRepositoryTest.cs | 8 +- .../Repositories/TemplateRepositoryTest.cs | 2 +- src/Umbraco.Web.UI.Client/package-lock.json | 6246 ++++++++--------- .../Umbraco/dialogs/ChangeDocType.aspx.cs | 2 +- src/Umbraco.Web/Editors/ContentController.cs | 9 +- .../Models/Mapping/DefaultTemplateResolver.cs | 28 +- src/Umbraco.Web/umbraco.presentation/page.cs | 5 +- 15 files changed, 3182 insertions(+), 3195 deletions(-) diff --git a/src/Umbraco.Core/Models/Content.cs b/src/Umbraco.Core/Models/Content.cs index b048998691..dc86b5e3ce 100644 --- a/src/Umbraco.Core/Models/Content.cs +++ b/src/Umbraco.Core/Models/Content.cs @@ -16,7 +16,7 @@ namespace Umbraco.Core.Models public class Content : ContentBase, IContent { private IContentType _contentType; - private ITemplate _template; + private int _templateId; private bool _published; private PublishedState _publishedState; private DateTime? _releaseDate; @@ -84,7 +84,7 @@ namespace Umbraco.Core.Models // ReSharper disable once ClassNeverInstantiated.Local private class PropertySelectors { - public readonly PropertyInfo TemplateSelector = ExpressionHelper.GetPropertyInfo(x => x.Template); + public readonly PropertyInfo TemplateSelector = ExpressionHelper.GetPropertyInfo(x => x.TemplateId); public readonly PropertyInfo PublishedSelector = ExpressionHelper.GetPropertyInfo(x => x.Published); public readonly PropertyInfo ReleaseDateSelector = ExpressionHelper.GetPropertyInfo(x => x.ReleaseDate); public readonly PropertyInfo ExpireDateSelector = ExpressionHelper.GetPropertyInfo(x => x.ExpireDate); @@ -100,10 +100,10 @@ namespace Umbraco.Core.Models /// the Default template from the ContentType will be returned. /// [DataMember] - public virtual ITemplate Template + public virtual int TemplateId { - get => _template ?? _contentType.DefaultTemplate; - set => SetPropertyValueAndDetectChanges(value, ref _template, Ps.Value.TemplateSelector); + get => _templateId; + set => SetPropertyValueAndDetectChanges(value, ref _templateId, Ps.Value.TemplateSelector); } /// @@ -205,7 +205,7 @@ namespace Umbraco.Core.Models /// [IgnoreDataMember] - public ITemplate PublishTemplate { get; internal set; } // set by persistence + public int PublishTemplateId { get; internal set; } // set by persistence /// [IgnoreDataMember] @@ -466,9 +466,7 @@ namespace Umbraco.Core.Models public override void ResetDirtyProperties(bool rememberDirty) { base.ResetDirtyProperties(rememberDirty); - - if (Template != null) - Template.ResetDirtyProperties(rememberDirty); + if (ContentType != null) ContentType.ResetDirtyProperties(rememberDirty); diff --git a/src/Umbraco.Core/Models/IContent.cs b/src/Umbraco.Core/Models/IContent.cs index 0c0d9449e0..3bb2e7d396 100644 --- a/src/Umbraco.Core/Models/IContent.cs +++ b/src/Umbraco.Core/Models/IContent.cs @@ -12,9 +12,9 @@ namespace Umbraco.Core.Models public interface IContent : IContentBase { /// - /// Gets or sets the template used to render the content. + /// Gets or sets the template id used to render the content. /// - ITemplate Template { get; set; } + int TemplateId { get; set; } /// /// Gets a value indicating whether the content is published. @@ -39,10 +39,10 @@ namespace Umbraco.Core.Models bool Blueprint { get; } /// - /// Gets the template used to render the published version of the content. + /// Gets the template id used to render the published version of the content. /// /// When editing the content, the template can change, but this will not until the content is published. - ITemplate PublishTemplate { get; } + int PublishTemplateId { get; } /// /// Gets the name of the published version of the content. diff --git a/src/Umbraco.Core/Persistence/Factories/ContentBaseFactory.cs b/src/Umbraco.Core/Persistence/Factories/ContentBaseFactory.cs index ec364c7c6a..21203b5572 100644 --- a/src/Umbraco.Core/Persistence/Factories/ContentBaseFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/ContentBaseFactory.cs @@ -271,7 +271,7 @@ namespace Umbraco.Core.Persistence.Factories var dto = new DocumentVersionDto { Id = entity.VersionId, - TemplateId = entity.Template?.Id, + TemplateId = entity.TemplateId, Published = false, // always building the current, unpublished one ContentVersionDto = BuildContentVersionDto(entity, contentDto) diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs index b3a7c31e54..78ad16c890 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs @@ -266,8 +266,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement var publishing = content.PublishedState == PublishedState.Publishing; // ensure that the default template is assigned - if (entity.Template == null) - entity.Template = entity.ContentType.DefaultTemplate; + if (entity.TemplateId == 0) + entity.TemplateId = entity.ContentType.DefaultTemplate.Id; // sanitize names SanitizeNames(content, publishing); @@ -395,7 +395,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement if (content.PublishedState == PublishedState.Publishing) { content.Published = true; - content.PublishTemplate = content.Template; + content.PublishTemplateId = content.TemplateId; content.PublisherId = content.WriterId; content.PublishName = content.Name; content.PublishDate = content.UpdateDate; @@ -405,7 +405,6 @@ namespace Umbraco.Core.Persistence.Repositories.Implement else if (content.PublishedState == PublishedState.Unpublishing) { content.Published = false; - content.PublishTemplate = null; content.PublisherId = null; content.PublishName = null; content.PublishDate = null; @@ -595,7 +594,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement if (content.PublishedState == PublishedState.Publishing) { content.Published = true; - content.PublishTemplate = content.Template; + content.PublishTemplateId = content.TemplateId; content.PublisherId = content.WriterId; content.PublishName = content.Name; content.PublishDate = content.UpdateDate; @@ -605,7 +604,6 @@ namespace Umbraco.Core.Persistence.Repositories.Implement else if (content.PublishedState == PublishedState.Unpublishing) { content.Published = false; - content.PublishTemplate = null; content.PublisherId = null; content.PublishName = null; content.PublishDate = null; @@ -993,9 +991,9 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { // complete the item if (temp.Template1Id.HasValue && templates.TryGetValue(temp.Template1Id.Value, out var template)) - temp.Content.Template = template; + temp.Content.TemplateId = temp.Template1Id.Value; if (temp.Template2Id.HasValue && templates.TryGetValue(temp.Template2Id.Value, out template)) - temp.Content.PublishTemplate = template; + temp.Content.PublishTemplateId = temp.Template2Id.Value; if (properties.ContainsKey(temp.VersionId)) temp.Content.Properties = properties[temp.VersionId]; @@ -1028,7 +1026,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement // get template if (dto.DocumentVersionDto.TemplateId.HasValue && dto.DocumentVersionDto.TemplateId.Value > 0) - content.Template = _templateRepository.Get(dto.DocumentVersionDto.TemplateId.Value); + content.TemplateId = dto.DocumentVersionDto.TemplateId.Value; // get properties - indexed by version id var versionId = dto.DocumentVersionDto.Id; diff --git a/src/Umbraco.Core/Services/EntityXmlSerializer.cs b/src/Umbraco.Core/Services/EntityXmlSerializer.cs index 5b64584dc6..8db4a238f5 100644 --- a/src/Umbraco.Core/Services/EntityXmlSerializer.cs +++ b/src/Umbraco.Core/Services/EntityXmlSerializer.cs @@ -52,7 +52,7 @@ namespace Umbraco.Core.Services xml.Add(new XAttribute("writerName", content.GetWriterProfile(userService)?.Name ?? "??")); xml.Add(new XAttribute("writerID", content.WriterId)); - xml.Add(new XAttribute("template", content.Template?.Id.ToString(CultureInfo.InvariantCulture) ?? "0")); + xml.Add(new XAttribute("template", content.TemplateId.ToString(CultureInfo.InvariantCulture) ?? "0")); xml.Add(new XAttribute("isPublished", content.Published)); diff --git a/src/Umbraco.Examine/UmbracoContentIndexer.cs b/src/Umbraco.Examine/UmbracoContentIndexer.cs index fab9f226a4..a9fd8483c4 100644 --- a/src/Umbraco.Examine/UmbracoContentIndexer.cs +++ b/src/Umbraco.Examine/UmbracoContentIndexer.cs @@ -341,7 +341,7 @@ namespace Umbraco.Examine {"creatorName", new object[] {c.GetCreatorProfile(userService)?.Name ?? "??"}}, {"writerName", new object[] {c.GetWriterProfile(userService)?.Name ?? "??"}}, {"writerID", new object[] {c.WriterId}}, - {"template", new object[] {c.Template?.Id ?? 0}} + {"template", new object[] {c.TemplateId}} }; foreach (var property in c.Properties) diff --git a/src/Umbraco.Tests/Models/ContentTests.cs b/src/Umbraco.Tests/Models/ContentTests.cs index 31110d7196..8cba508fa9 100644 --- a/src/Umbraco.Tests/Models/ContentTests.cs +++ b/src/Umbraco.Tests/Models/ContentTests.cs @@ -235,10 +235,7 @@ namespace Umbraco.Tests.Models content.ReleaseDate = DateTime.Now; //content.ChangePublishedState(PublishedState.Published); content.SortOrder = 5; - content.Template = new Template((string) "Test Template", (string) "testTemplate") - { - Id = 88 - }; + content.TemplateId = 88; content.Trashed = false; content.UpdateDate = DateTime.Now; content.WriterId = 23; @@ -298,10 +295,7 @@ namespace Umbraco.Tests.Models content.Path = "-1,4,10"; content.ReleaseDate = DateTime.Now; content.SortOrder = 5; - content.Template = new Template((string) "Test Template", (string) "testTemplate") - { - Id = 88 - }; + content.TemplateId = 88; content.Trashed = false; content.UpdateDate = DateTime.Now; content.WriterId = 23; @@ -342,8 +336,8 @@ namespace Umbraco.Tests.Models Assert.AreEqual(clone.PublishedState, content.PublishedState); Assert.AreEqual(clone.SortOrder, content.SortOrder); Assert.AreEqual(clone.PublishedState, content.PublishedState); - Assert.AreNotSame(clone.Template, content.Template); - Assert.AreEqual(clone.Template, content.Template); + Assert.AreNotSame(clone.TemplateId, content.TemplateId); + Assert.AreEqual(clone.TemplateId, content.TemplateId); Assert.AreEqual(clone.Trashed, content.Trashed); Assert.AreEqual(clone.UpdateDate, content.UpdateDate); Assert.AreEqual(clone.VersionId, content.VersionId); @@ -419,16 +413,12 @@ namespace Umbraco.Tests.Models content.Path = "-1,4,10"; content.ReleaseDate = DateTime.Now; content.SortOrder = 5; - content.Template = new Template((string)"Test Template", (string)"testTemplate") - { - Id = 88 - }; + content.TemplateId = 88; content.Trashed = true; content.UpdateDate = DateTime.Now; content.WriterId = 23; - - content.Template.UpdateDate = DateTime.Now; //update a child object + content.ContentType.UpdateDate = DateTime.Now; //update a child object // Act @@ -469,7 +459,7 @@ namespace Umbraco.Tests.Models Assert.IsTrue(culture.Value.WasPropertyDirty("Date")); } //verify child objects were reset too - Assert.IsTrue(content.Template.WasPropertyDirty("UpdateDate")); + Assert.Zero(content.TemplateId); Assert.IsTrue(content.ContentType.WasPropertyDirty("UpdateDate")); } @@ -497,10 +487,7 @@ namespace Umbraco.Tests.Models content.ReleaseDate = DateTime.Now; //content.ChangePublishedState(PublishedState.Publishing); content.SortOrder = 5; - content.Template = new Template((string) "Test Template", (string) "testTemplate") - { - Id = 88 - }; + content.TemplateId = 88; content.Trashed = false; content.UpdateDate = DateTime.Now; content.WriterId = 23; diff --git a/src/Umbraco.Tests/Models/ContentXmlTest.cs b/src/Umbraco.Tests/Models/ContentXmlTest.cs index 9cc41ffa6f..38cce9d88a 100644 --- a/src/Umbraco.Tests/Models/ContentXmlTest.cs +++ b/src/Umbraco.Tests/Models/ContentXmlTest.cs @@ -49,7 +49,7 @@ namespace Umbraco.Tests.Models Assert.AreEqual(content.GetCreatorProfile(ServiceContext.UserService).Name, (string)element.Attribute("creatorName")); Assert.AreEqual(content.GetWriterProfile(ServiceContext.UserService).Name, (string)element.Attribute("writerName")); Assert.AreEqual(content.WriterId.ToString(), (string)element.Attribute("writerID")); - Assert.AreEqual(content.Template == null ? "0" : content.Template.Id.ToString(), (string)element.Attribute("template")); + Assert.AreEqual(content.TemplateId.ToString(), (string)element.Attribute("template")); Assert.AreEqual(content.Properties["title"].GetValue().ToString(), element.Elements("title").Single().Value); Assert.AreEqual(content.Properties["bodyText"].GetValue().ToString(), element.Elements("bodyText").Single().Value); diff --git a/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs index 9f84d9faf5..37dd1b6919 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs @@ -432,8 +432,8 @@ namespace Umbraco.Tests.Persistence.Repositories var fetched = repository.Get(textpage.Id); - Assert.NotNull(textpage.Template); - Assert.AreEqual(textpage.Template, contentType.DefaultTemplate); + Assert.Zero(textpage.TemplateId); + Assert.AreEqual(textpage.TemplateId, contentType.DefaultTemplate.Id); scope.Complete(); @@ -557,12 +557,12 @@ namespace Umbraco.Tests.Persistence.Repositories var repository = CreateRepository((IScopeAccessor)provider, out _); var content = repository.Get(NodeDto.NodeIdSeed + 2); - content.Template = null; + content.TemplateId = 0; repository.Save(content); var updatedContent = repository.Get(NodeDto.NodeIdSeed + 2); - Assert.IsNull(updatedContent.Template); + Assert.Zero(updatedContent.TemplateId); } } diff --git a/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs index 3ef769adbc..c27bd55334 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs @@ -424,7 +424,7 @@ namespace Umbraco.Tests.Persistence.Repositories templateRepository.Save(template); - textpage.Template = template; + textpage.TemplateId = template.Id; contentRepo.Save(textpage); diff --git a/src/Umbraco.Web.UI.Client/package-lock.json b/src/Umbraco.Web.UI.Client/package-lock.json index 9233b24d53..cb1733b8e1 100644 --- a/src/Umbraco.Web.UI.Client/package-lock.json +++ b/src/Umbraco.Web.UI.Client/package-lock.json @@ -8,7 +8,7 @@ "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", "dev": true, "requires": { - "@babel/highlight": "^7.0.0" + "@babel/highlight": "7.0.0" } }, "@babel/core": { @@ -17,20 +17,20 @@ "integrity": "sha512-IFeSSnjXdhDaoysIlev//UzHZbdEmm7D0EIH2qtse9xK7mXEZQpYjs2P00XlP1qYsYvid79p+Zgg6tz1mp6iVw==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.1.2", - "@babel/helpers": "^7.1.2", - "@babel/parser": "^7.1.2", - "@babel/template": "^7.1.2", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.1.2", - "convert-source-map": "^1.1.0", - "debug": "^3.1.0", - "json5": "^0.5.0", - "lodash": "^4.17.10", - "resolve": "^1.3.2", - "semver": "^5.4.1", - "source-map": "^0.5.0" + "@babel/code-frame": "7.0.0", + "@babel/generator": "7.1.2", + "@babel/helpers": "7.1.2", + "@babel/parser": "7.1.2", + "@babel/template": "7.1.2", + "@babel/traverse": "7.1.0", + "@babel/types": "7.1.2", + "convert-source-map": "1.6.0", + "debug": "3.2.5", + "json5": "0.5.1", + "lodash": "4.17.11", + "resolve": "1.8.1", + "semver": "5.5.1", + "source-map": "0.5.7" }, "dependencies": { "debug": { @@ -39,7 +39,7 @@ "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.1" } }, "ms": { @@ -62,11 +62,11 @@ "integrity": "sha512-70A9HWLS/1RHk3Ck8tNHKxOoKQuSKocYgwDN85Pyl/RBduss6AKxUR7RIZ/lzduQMSYfWEM4DDBu6A+XGbkFig==", "dev": true, "requires": { - "@babel/types": "^7.1.2", - "jsesc": "^2.5.1", - "lodash": "^4.17.10", - "source-map": "^0.5.0", - "trim-right": "^1.0.1" + "@babel/types": "7.1.2", + "jsesc": "2.5.1", + "lodash": "4.17.11", + "source-map": "0.5.7", + "trim-right": "1.0.1" } }, "@babel/helper-annotate-as-pure": { @@ -75,7 +75,7 @@ "integrity": "sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q==", "dev": true, "requires": { - "@babel/types": "^7.0.0" + "@babel/types": "7.1.2" } }, "@babel/helper-builder-binary-assignment-operator-visitor": { @@ -84,8 +84,8 @@ "integrity": "sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w==", "dev": true, "requires": { - "@babel/helper-explode-assignable-expression": "^7.1.0", - "@babel/types": "^7.0.0" + "@babel/helper-explode-assignable-expression": "7.1.0", + "@babel/types": "7.1.2" } }, "@babel/helper-call-delegate": { @@ -94,9 +94,9 @@ "integrity": "sha512-YEtYZrw3GUK6emQHKthltKNZwszBcHK58Ygcis+gVUrF4/FmTVr5CCqQNSfmvg2y+YDEANyYoaLz/SHsnusCwQ==", "dev": true, "requires": { - "@babel/helper-hoist-variables": "^7.0.0", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" + "@babel/helper-hoist-variables": "7.0.0", + "@babel/traverse": "7.1.0", + "@babel/types": "7.1.2" } }, "@babel/helper-define-map": { @@ -105,9 +105,9 @@ "integrity": "sha512-yPPcW8dc3gZLN+U1mhYV91QU3n5uTbx7DUdf8NnPbjS0RMwBuHi9Xt2MUgppmNz7CJxTBWsGczTiEp1CSOTPRg==", "dev": true, "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/types": "^7.0.0", - "lodash": "^4.17.10" + "@babel/helper-function-name": "7.1.0", + "@babel/types": "7.1.2", + "lodash": "4.17.11" } }, "@babel/helper-explode-assignable-expression": { @@ -116,8 +116,8 @@ "integrity": "sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA==", "dev": true, "requires": { - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" + "@babel/traverse": "7.1.0", + "@babel/types": "7.1.2" } }, "@babel/helper-function-name": { @@ -126,9 +126,9 @@ "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", "dev": true, "requires": { - "@babel/helper-get-function-arity": "^7.0.0", - "@babel/template": "^7.1.0", - "@babel/types": "^7.0.0" + "@babel/helper-get-function-arity": "7.0.0", + "@babel/template": "7.1.2", + "@babel/types": "7.1.2" } }, "@babel/helper-get-function-arity": { @@ -137,7 +137,7 @@ "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", "dev": true, "requires": { - "@babel/types": "^7.0.0" + "@babel/types": "7.1.2" } }, "@babel/helper-hoist-variables": { @@ -146,7 +146,7 @@ "integrity": "sha512-Ggv5sldXUeSKsuzLkddtyhyHe2YantsxWKNi7A+7LeD12ExRDWTRk29JCXpaHPAbMaIPZSil7n+lq78WY2VY7w==", "dev": true, "requires": { - "@babel/types": "^7.0.0" + "@babel/types": "7.1.2" } }, "@babel/helper-member-expression-to-functions": { @@ -155,7 +155,7 @@ "integrity": "sha512-avo+lm/QmZlv27Zsi0xEor2fKcqWG56D5ae9dzklpIaY7cQMK5N8VSpaNVPPagiqmy7LrEjK1IWdGMOqPu5csg==", "dev": true, "requires": { - "@babel/types": "^7.0.0" + "@babel/types": "7.1.2" } }, "@babel/helper-module-imports": { @@ -164,7 +164,7 @@ "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==", "dev": true, "requires": { - "@babel/types": "^7.0.0" + "@babel/types": "7.1.2" } }, "@babel/helper-module-transforms": { @@ -173,12 +173,12 @@ "integrity": "sha512-0JZRd2yhawo79Rcm4w0LwSMILFmFXjugG3yqf+P/UsKsRS1mJCmMwwlHDlMg7Avr9LrvSpp4ZSULO9r8jpCzcw==", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-simple-access": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.0.0", - "@babel/template": "^7.1.0", - "@babel/types": "^7.0.0", - "lodash": "^4.17.10" + "@babel/helper-module-imports": "7.0.0", + "@babel/helper-simple-access": "7.1.0", + "@babel/helper-split-export-declaration": "7.0.0", + "@babel/template": "7.1.2", + "@babel/types": "7.1.2", + "lodash": "4.17.11" } }, "@babel/helper-optimise-call-expression": { @@ -187,7 +187,7 @@ "integrity": "sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g==", "dev": true, "requires": { - "@babel/types": "^7.0.0" + "@babel/types": "7.1.2" } }, "@babel/helper-plugin-utils": { @@ -202,7 +202,7 @@ "integrity": "sha512-TR0/N0NDCcUIUEbqV6dCO+LptmmSQFQ7q70lfcEB4URsjD0E1HzicrwUH+ap6BAQ2jhCX9Q4UqZy4wilujWlkg==", "dev": true, "requires": { - "lodash": "^4.17.10" + "lodash": "4.17.11" } }, "@babel/helper-remap-async-to-generator": { @@ -211,11 +211,11 @@ "integrity": "sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-wrap-function": "^7.1.0", - "@babel/template": "^7.1.0", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" + "@babel/helper-annotate-as-pure": "7.0.0", + "@babel/helper-wrap-function": "7.1.0", + "@babel/template": "7.1.2", + "@babel/traverse": "7.1.0", + "@babel/types": "7.1.2" } }, "@babel/helper-replace-supers": { @@ -224,10 +224,10 @@ "integrity": "sha512-BvcDWYZRWVuDeXTYZWxekQNO5D4kO55aArwZOTFXw6rlLQA8ZaDicJR1sO47h+HrnCiDFiww0fSPV0d713KBGQ==", "dev": true, "requires": { - "@babel/helper-member-expression-to-functions": "^7.0.0", - "@babel/helper-optimise-call-expression": "^7.0.0", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" + "@babel/helper-member-expression-to-functions": "7.0.0", + "@babel/helper-optimise-call-expression": "7.0.0", + "@babel/traverse": "7.1.0", + "@babel/types": "7.1.2" } }, "@babel/helper-simple-access": { @@ -236,8 +236,8 @@ "integrity": "sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w==", "dev": true, "requires": { - "@babel/template": "^7.1.0", - "@babel/types": "^7.0.0" + "@babel/template": "7.1.2", + "@babel/types": "7.1.2" } }, "@babel/helper-split-export-declaration": { @@ -246,7 +246,7 @@ "integrity": "sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag==", "dev": true, "requires": { - "@babel/types": "^7.0.0" + "@babel/types": "7.1.2" } }, "@babel/helper-wrap-function": { @@ -255,10 +255,10 @@ "integrity": "sha512-R6HU3dete+rwsdAfrOzTlE9Mcpk4RjU3aX3gi9grtmugQY0u79X7eogUvfXA5sI81Mfq1cn6AgxihfN33STjJA==", "dev": true, "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/template": "^7.1.0", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" + "@babel/helper-function-name": "7.1.0", + "@babel/template": "7.1.2", + "@babel/traverse": "7.1.0", + "@babel/types": "7.1.2" } }, "@babel/helpers": { @@ -267,9 +267,9 @@ "integrity": "sha512-Myc3pUE8eswD73aWcartxB16K6CGmHDv9KxOmD2CeOs/FaEAQodr3VYGmlvOmog60vNQ2w8QbatuahepZwrHiA==", "dev": true, "requires": { - "@babel/template": "^7.1.2", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.1.2" + "@babel/template": "7.1.2", + "@babel/traverse": "7.1.0", + "@babel/types": "7.1.2" } }, "@babel/highlight": { @@ -278,9 +278,9 @@ "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", "dev": true, "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^4.0.0" + "chalk": "2.4.1", + "esutils": "2.0.2", + "js-tokens": "4.0.0" }, "dependencies": { "ansi-styles": { @@ -289,7 +289,7 @@ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { - "color-convert": "^1.9.0" + "color-convert": "1.9.3" } }, "chalk": { @@ -298,9 +298,9 @@ "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.5.0" } }, "has-flag": { @@ -315,7 +315,7 @@ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "3.0.0" } } } @@ -332,9 +332,9 @@ "integrity": "sha512-Fq803F3Jcxo20MXUSDdmZZXrPe6BWyGcWBPPNB/M7WaUYESKDeKMOGIxEzQOjGSmW/NWb6UaPZrtTB2ekhB/ew==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-remap-async-to-generator": "^7.1.0", - "@babel/plugin-syntax-async-generators": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0", + "@babel/helper-remap-async-to-generator": "7.1.0", + "@babel/plugin-syntax-async-generators": "7.0.0" } }, "@babel/plugin-proposal-json-strings": { @@ -343,8 +343,8 @@ "integrity": "sha512-kfVdUkIAGJIVmHmtS/40i/fg/AGnw/rsZBCaapY5yjeO5RA9m165Xbw9KMOu2nqXP5dTFjEjHdfNdoVcHv133Q==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-json-strings": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0", + "@babel/plugin-syntax-json-strings": "7.0.0" } }, "@babel/plugin-proposal-object-rest-spread": { @@ -353,8 +353,8 @@ "integrity": "sha512-14fhfoPcNu7itSen7Py1iGN0gEm87hX/B+8nZPqkdmANyyYWYMY2pjA3r8WXbWVKMzfnSNS0xY8GVS0IjXi/iw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-object-rest-spread": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0", + "@babel/plugin-syntax-object-rest-spread": "7.0.0" } }, "@babel/plugin-proposal-optional-catch-binding": { @@ -363,8 +363,8 @@ "integrity": "sha512-JPqAvLG1s13B/AuoBjdBYvn38RqW6n1TzrQO839/sIpqLpbnXKacsAgpZHzLD83Sm8SDXMkkrAvEnJ25+0yIpw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0", + "@babel/plugin-syntax-optional-catch-binding": "7.0.0" } }, "@babel/plugin-proposal-unicode-property-regex": { @@ -373,9 +373,9 @@ "integrity": "sha512-tM3icA6GhC3ch2SkmSxv7J/hCWKISzwycub6eGsDrFDgukD4dZ/I+x81XgW0YslS6mzNuQ1Cbzh5osjIMgepPQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.0.0", - "regexpu-core": "^4.2.0" + "@babel/helper-plugin-utils": "7.0.0", + "@babel/helper-regex": "7.0.0", + "regexpu-core": "4.2.0" } }, "@babel/plugin-syntax-async-generators": { @@ -384,7 +384,7 @@ "integrity": "sha512-im7ged00ddGKAjcZgewXmp1vxSZQQywuQXe2B1A7kajjZmDeY/ekMPmWr9zJgveSaQH0k7BcGrojQhcK06l0zA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-syntax-json-strings": { @@ -393,7 +393,7 @@ "integrity": "sha512-UlSfNydC+XLj4bw7ijpldc1uZ/HB84vw+U6BTuqMdIEmz/LDe63w/GHtpQMdXWdqQZFeAI9PjnHe/vDhwirhKA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-syntax-object-rest-spread": { @@ -402,7 +402,7 @@ "integrity": "sha512-5A0n4p6bIiVe5OvQPxBnesezsgFJdHhSs3uFSvaPdMqtsovajLZ+G2vZyvNe10EzJBWWo3AcHGKhAFUxqwp2dw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-syntax-optional-catch-binding": { @@ -411,7 +411,7 @@ "integrity": "sha512-Wc+HVvwjcq5qBg1w5RG9o9RVzmCaAg/Vp0erHCKpAYV8La6I94o4GQAmFYNmkzoMO6gzoOSulpKeSSz6mPEoZw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-transform-arrow-functions": { @@ -420,7 +420,7 @@ "integrity": "sha512-2EZDBl1WIO/q4DIkIp4s86sdp4ZifL51MoIviLY/gG/mLSuOIEg7J8o6mhbxOTvUJkaN50n+8u41FVsr5KLy/w==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-transform-async-to-generator": { @@ -429,9 +429,9 @@ "integrity": "sha512-rNmcmoQ78IrvNCIt/R9U+cixUHeYAzgusTFgIAv+wQb9HJU4szhpDD6e5GCACmj/JP5KxuCwM96bX3L9v4ZN/g==", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-remap-async-to-generator": "^7.1.0" + "@babel/helper-module-imports": "7.0.0", + "@babel/helper-plugin-utils": "7.0.0", + "@babel/helper-remap-async-to-generator": "7.1.0" } }, "@babel/plugin-transform-block-scoped-functions": { @@ -440,7 +440,7 @@ "integrity": "sha512-AOBiyUp7vYTqz2Jibe1UaAWL0Hl9JUXEgjFvvvcSc9MVDItv46ViXFw2F7SVt1B5k+KWjl44eeXOAk3UDEaJjQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-transform-block-scoping": { @@ -449,8 +449,8 @@ "integrity": "sha512-GWEMCrmHQcYWISilUrk9GDqH4enf3UmhOEbNbNrlNAX1ssH3MsS1xLOS6rdjRVPgA7XXVPn87tRkdTEoA/dxEg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "lodash": "^4.17.10" + "@babel/helper-plugin-utils": "7.0.0", + "lodash": "4.17.11" } }, "@babel/plugin-transform-classes": { @@ -459,14 +459,14 @@ "integrity": "sha512-rNaqoD+4OCBZjM7VaskladgqnZ1LO6o2UxuWSDzljzW21pN1KXkB7BstAVweZdxQkHAujps5QMNOTWesBciKFg==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-define-map": "^7.1.0", - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-optimise-call-expression": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.0.0", - "globals": "^11.1.0" + "@babel/helper-annotate-as-pure": "7.0.0", + "@babel/helper-define-map": "7.1.0", + "@babel/helper-function-name": "7.1.0", + "@babel/helper-optimise-call-expression": "7.0.0", + "@babel/helper-plugin-utils": "7.0.0", + "@babel/helper-replace-supers": "7.1.0", + "@babel/helper-split-export-declaration": "7.0.0", + "globals": "11.8.0" } }, "@babel/plugin-transform-computed-properties": { @@ -475,7 +475,7 @@ "integrity": "sha512-ubouZdChNAv4AAWAgU7QKbB93NU5sHwInEWfp+/OzJKA02E6Woh9RVoX4sZrbRwtybky/d7baTUqwFx+HgbvMA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-transform-destructuring": { @@ -484,7 +484,7 @@ "integrity": "sha512-cvToXvp/OsYxtEn57XJu9BvsGSEYjAh9UeUuXpoi7x6QHB7YdWyQ4lRU/q0Fu1IJNT0o0u4FQ1DMQBzJ8/8vZg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-transform-dotall-regex": { @@ -493,9 +493,9 @@ "integrity": "sha512-00THs8eJxOJUFVx1w8i1MBF4XH4PsAjKjQ1eqN/uCH3YKwP21GCKfrn6YZFZswbOk9+0cw1zGQPHVc1KBlSxig==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.0.0", - "regexpu-core": "^4.1.3" + "@babel/helper-plugin-utils": "7.0.0", + "@babel/helper-regex": "7.0.0", + "regexpu-core": "4.2.0" } }, "@babel/plugin-transform-duplicate-keys": { @@ -504,7 +504,7 @@ "integrity": "sha512-w2vfPkMqRkdxx+C71ATLJG30PpwtTpW7DDdLqYt2acXU7YjztzeWW2Jk1T6hKqCLYCcEA5UQM/+xTAm+QCSnuQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-transform-exponentiation-operator": { @@ -513,8 +513,8 @@ "integrity": "sha512-uZt9kD1Pp/JubkukOGQml9tqAeI8NkE98oZnHZ2qHRElmeKCodbTZgOEUtujSCSLhHSBWbzNiFSDIMC4/RBTLQ==", "dev": true, "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-builder-binary-assignment-operator-visitor": "7.1.0", + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-transform-for-of": { @@ -523,7 +523,7 @@ "integrity": "sha512-TlxKecN20X2tt2UEr2LNE6aqA0oPeMT1Y3cgz8k4Dn1j5ObT8M3nl9aA37LLklx0PBZKETC9ZAf9n/6SujTuXA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-transform-function-name": { @@ -532,8 +532,8 @@ "integrity": "sha512-VxOa1TMlFMtqPW2IDYZQaHsFrq/dDoIjgN098NowhexhZcz3UGlvPgZXuE1jEvNygyWyxRacqDpCZt+par1FNg==", "dev": true, "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-function-name": "7.1.0", + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-transform-literals": { @@ -542,7 +542,7 @@ "integrity": "sha512-1NTDBWkeNXgpUcyoVFxbr9hS57EpZYXpje92zv0SUzjdu3enaRwF/l3cmyRnXLtIdyJASyiS6PtybK+CgKf7jA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-transform-modules-amd": { @@ -551,8 +551,8 @@ "integrity": "sha512-wt8P+xQ85rrnGNr2x1iV3DW32W8zrB6ctuBkYBbf5/ZzJY99Ob4MFgsZDFgczNU76iy9PWsy4EuxOliDjdKw6A==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-module-transforms": "7.1.0", + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-transform-modules-commonjs": { @@ -561,9 +561,9 @@ "integrity": "sha512-wtNwtMjn1XGwM0AXPspQgvmE6msSJP15CX2RVfpTSTNPLhKhaOjaIfBaVfj4iUZ/VrFSodcFedwtPg/NxwQlPA==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-simple-access": "^7.1.0" + "@babel/helper-module-transforms": "7.1.0", + "@babel/helper-plugin-utils": "7.0.0", + "@babel/helper-simple-access": "7.1.0" } }, "@babel/plugin-transform-modules-systemjs": { @@ -572,8 +572,8 @@ "integrity": "sha512-8EDKMAsitLkiF/D4Zhe9CHEE2XLh4bfLbb9/Zf3FgXYQOZyZYyg7EAel/aT2A7bHv62jwHf09q2KU/oEexr83g==", "dev": true, "requires": { - "@babel/helper-hoist-variables": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-hoist-variables": "7.0.0", + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-transform-modules-umd": { @@ -582,8 +582,8 @@ "integrity": "sha512-enrRtn5TfRhMmbRwm7F8qOj0qEYByqUvTttPEGimcBH4CJHphjyK1Vg7sdU7JjeEmgSpM890IT/efS2nMHwYig==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-module-transforms": "7.1.0", + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-transform-new-target": { @@ -592,7 +592,7 @@ "integrity": "sha512-yin069FYjah+LbqfGeTfzIBODex/e++Yfa0rH0fpfam9uTbuEeEOx5GLGr210ggOV77mVRNoeqSYqeuaqSzVSw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-transform-object-super": { @@ -601,8 +601,8 @@ "integrity": "sha512-/O02Je1CRTSk2SSJaq0xjwQ8hG4zhZGNjE8psTsSNPXyLRCODv7/PBozqT5AmQMzp7MI3ndvMhGdqp9c96tTEw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.1.0" + "@babel/helper-plugin-utils": "7.0.0", + "@babel/helper-replace-supers": "7.1.0" } }, "@babel/plugin-transform-parameters": { @@ -611,9 +611,9 @@ "integrity": "sha512-vHV7oxkEJ8IHxTfRr3hNGzV446GAb+0hgbA7o/0Jd76s+YzccdWuTU296FOCOl/xweU4t/Ya4g41yWz80RFCRw==", "dev": true, "requires": { - "@babel/helper-call-delegate": "^7.1.0", - "@babel/helper-get-function-arity": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-call-delegate": "7.1.0", + "@babel/helper-get-function-arity": "7.0.0", + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-transform-regenerator": { @@ -622,7 +622,7 @@ "integrity": "sha512-sj2qzsEx8KDVv1QuJc/dEfilkg3RRPvPYx/VnKLtItVQRWt1Wqf5eVCOLZm29CiGFfYYsA3VPjfizTCV0S0Dlw==", "dev": true, "requires": { - "regenerator-transform": "^0.13.3" + "regenerator-transform": "0.13.3" } }, "@babel/plugin-transform-shorthand-properties": { @@ -631,7 +631,7 @@ "integrity": "sha512-g/99LI4vm5iOf5r1Gdxq5Xmu91zvjhEG5+yZDJW268AZELAu4J1EiFLnkSG3yuUsZyOipVOVUKoGPYwfsTymhw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-transform-spread": { @@ -640,7 +640,7 @@ "integrity": "sha512-L702YFy2EvirrR4shTj0g2xQp7aNwZoWNCkNu2mcoU0uyzMl0XRwDSwzB/xp6DSUFiBmEXuyAyEN16LsgVqGGQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-transform-sticky-regex": { @@ -649,8 +649,8 @@ "integrity": "sha512-LFUToxiyS/WD+XEWpkx/XJBrUXKewSZpzX68s+yEOtIbdnsRjpryDw9U06gYc6klYEij/+KQVRnD3nz3AoKmjw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0", + "@babel/helper-regex": "7.0.0" } }, "@babel/plugin-transform-template-literals": { @@ -659,8 +659,8 @@ "integrity": "sha512-vA6rkTCabRZu7Nbl9DfLZE1imj4tzdWcg5vtdQGvj+OH9itNNB6hxuRMHuIY8SGnEt1T9g5foqs9LnrHzsqEFg==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-annotate-as-pure": "7.0.0", + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-transform-typeof-symbol": { @@ -669,7 +669,7 @@ "integrity": "sha512-1r1X5DO78WnaAIvs5uC48t41LLckxsYklJrZjNKcevyz83sF2l4RHbw29qrCPr/6ksFsdfRpT/ZgxNWHXRnffg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/plugin-transform-unicode-regex": { @@ -678,9 +678,9 @@ "integrity": "sha512-uJBrJhBOEa3D033P95nPHu3nbFwFE9ZgXsfEitzoIXIwqAZWk7uXcg06yFKXz9FSxBH5ucgU/cYdX0IV8ldHKw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.0.0", - "regexpu-core": "^4.1.3" + "@babel/helper-plugin-utils": "7.0.0", + "@babel/helper-regex": "7.0.0", + "regexpu-core": "4.2.0" } }, "@babel/preset-env": { @@ -689,47 +689,47 @@ "integrity": "sha512-ZLVSynfAoDHB/34A17/JCZbyrzbQj59QC1Anyueb4Bwjh373nVPq5/HMph0z+tCmcDjXDe+DlKQq9ywQuvWrQg==", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-async-generator-functions": "^7.1.0", - "@babel/plugin-proposal-json-strings": "^7.0.0", - "@babel/plugin-proposal-object-rest-spread": "^7.0.0", - "@babel/plugin-proposal-optional-catch-binding": "^7.0.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.0.0", - "@babel/plugin-syntax-async-generators": "^7.0.0", - "@babel/plugin-syntax-object-rest-spread": "^7.0.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.0.0", - "@babel/plugin-transform-arrow-functions": "^7.0.0", - "@babel/plugin-transform-async-to-generator": "^7.1.0", - "@babel/plugin-transform-block-scoped-functions": "^7.0.0", - "@babel/plugin-transform-block-scoping": "^7.0.0", - "@babel/plugin-transform-classes": "^7.1.0", - "@babel/plugin-transform-computed-properties": "^7.0.0", - "@babel/plugin-transform-destructuring": "^7.0.0", - "@babel/plugin-transform-dotall-regex": "^7.0.0", - "@babel/plugin-transform-duplicate-keys": "^7.0.0", - "@babel/plugin-transform-exponentiation-operator": "^7.1.0", - "@babel/plugin-transform-for-of": "^7.0.0", - "@babel/plugin-transform-function-name": "^7.1.0", - "@babel/plugin-transform-literals": "^7.0.0", - "@babel/plugin-transform-modules-amd": "^7.1.0", - "@babel/plugin-transform-modules-commonjs": "^7.1.0", - "@babel/plugin-transform-modules-systemjs": "^7.0.0", - "@babel/plugin-transform-modules-umd": "^7.1.0", - "@babel/plugin-transform-new-target": "^7.0.0", - "@babel/plugin-transform-object-super": "^7.1.0", - "@babel/plugin-transform-parameters": "^7.1.0", - "@babel/plugin-transform-regenerator": "^7.0.0", - "@babel/plugin-transform-shorthand-properties": "^7.0.0", - "@babel/plugin-transform-spread": "^7.0.0", - "@babel/plugin-transform-sticky-regex": "^7.0.0", - "@babel/plugin-transform-template-literals": "^7.0.0", - "@babel/plugin-transform-typeof-symbol": "^7.0.0", - "@babel/plugin-transform-unicode-regex": "^7.0.0", - "browserslist": "^4.1.0", - "invariant": "^2.2.2", - "js-levenshtein": "^1.1.3", - "semver": "^5.3.0" + "@babel/helper-module-imports": "7.0.0", + "@babel/helper-plugin-utils": "7.0.0", + "@babel/plugin-proposal-async-generator-functions": "7.1.0", + "@babel/plugin-proposal-json-strings": "7.0.0", + "@babel/plugin-proposal-object-rest-spread": "7.0.0", + "@babel/plugin-proposal-optional-catch-binding": "7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "7.0.0", + "@babel/plugin-syntax-async-generators": "7.0.0", + "@babel/plugin-syntax-object-rest-spread": "7.0.0", + "@babel/plugin-syntax-optional-catch-binding": "7.0.0", + "@babel/plugin-transform-arrow-functions": "7.0.0", + "@babel/plugin-transform-async-to-generator": "7.1.0", + "@babel/plugin-transform-block-scoped-functions": "7.0.0", + "@babel/plugin-transform-block-scoping": "7.0.0", + "@babel/plugin-transform-classes": "7.1.0", + "@babel/plugin-transform-computed-properties": "7.0.0", + "@babel/plugin-transform-destructuring": "7.1.2", + "@babel/plugin-transform-dotall-regex": "7.0.0", + "@babel/plugin-transform-duplicate-keys": "7.0.0", + "@babel/plugin-transform-exponentiation-operator": "7.1.0", + "@babel/plugin-transform-for-of": "7.0.0", + "@babel/plugin-transform-function-name": "7.1.0", + "@babel/plugin-transform-literals": "7.0.0", + "@babel/plugin-transform-modules-amd": "7.1.0", + "@babel/plugin-transform-modules-commonjs": "7.1.0", + "@babel/plugin-transform-modules-systemjs": "7.0.0", + "@babel/plugin-transform-modules-umd": "7.1.0", + "@babel/plugin-transform-new-target": "7.0.0", + "@babel/plugin-transform-object-super": "7.1.0", + "@babel/plugin-transform-parameters": "7.1.0", + "@babel/plugin-transform-regenerator": "7.0.0", + "@babel/plugin-transform-shorthand-properties": "7.0.0", + "@babel/plugin-transform-spread": "7.0.0", + "@babel/plugin-transform-sticky-regex": "7.0.0", + "@babel/plugin-transform-template-literals": "7.0.0", + "@babel/plugin-transform-typeof-symbol": "7.0.0", + "@babel/plugin-transform-unicode-regex": "7.0.0", + "browserslist": "4.2.0", + "invariant": "2.2.4", + "js-levenshtein": "1.1.4", + "semver": "5.5.1" }, "dependencies": { "browserslist": { @@ -738,9 +738,9 @@ "integrity": "sha512-Berls1CHL7qfQz8Lct6QxYA5d2Tvt4doDWHcjvAISybpd+EKZVppNtXgXhaN6SdrPKo7YLTSZuYBs5cYrSWN8w==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30000889", - "electron-to-chromium": "^1.3.73", - "node-releases": "^1.0.0-alpha.12" + "caniuse-lite": "1.0.30000889", + "electron-to-chromium": "1.3.73", + "node-releases": "1.0.0-alpha.12" } }, "semver": { @@ -757,9 +757,9 @@ "integrity": "sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.1.2", - "@babel/types": "^7.1.2" + "@babel/code-frame": "7.0.0", + "@babel/parser": "7.1.2", + "@babel/types": "7.1.2" } }, "@babel/traverse": { @@ -768,15 +768,15 @@ "integrity": "sha512-bwgln0FsMoxm3pLOgrrnGaXk18sSM9JNf1/nHC/FksmNGFbYnPWY4GYCfLxyP1KRmfsxqkRpfoa6xr6VuuSxdw==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.0.0", - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.0.0", - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0", - "debug": "^3.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.10" + "@babel/code-frame": "7.0.0", + "@babel/generator": "7.1.2", + "@babel/helper-function-name": "7.1.0", + "@babel/helper-split-export-declaration": "7.0.0", + "@babel/parser": "7.1.2", + "@babel/types": "7.1.2", + "debug": "3.2.5", + "globals": "11.8.0", + "lodash": "4.17.11" }, "dependencies": { "debug": { @@ -785,7 +785,7 @@ "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.1" } }, "ms": { @@ -802,9 +802,9 @@ "integrity": "sha512-pb1I05sZEKiSlMUV9UReaqsCPUpgbHHHu2n1piRm7JkuBkm6QxcaIzKu6FMnMtCbih/cEYTR+RGYYC96Yk9HAg==", "dev": true, "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.10", - "to-fast-properties": "^2.0.0" + "esutils": "2.0.2", + "lodash": "4.17.11", + "to-fast-properties": "2.0.0" } }, "@types/angular": { @@ -824,7 +824,7 @@ "integrity": "sha1-5fHzkoxtlf2WVYw27D2dDeSm7Oo=", "dev": true, "requires": { - "mime-types": "~2.1.6", + "mime-types": "2.1.20", "negotiator": "0.5.3" } }, @@ -834,20 +834,20 @@ "integrity": "sha1-vsUWovci59UPX59C+Bt387lUSLo=", "dev": true, "requires": { - "convert-source-map": "^1.5.0", - "glob": "^7.0.5", - "indx": "^0.2.3", - "lodash.clone": "^4.3.2", - "lodash.defaults": "^4.0.1", - "lodash.flatten": "^4.2.0", - "lodash.merge": "^4.4.0", - "lodash.partialright": "^4.1.4", - "lodash.pick": "^4.2.1", - "lodash.uniq": "^4.3.0", - "resolve": "^1.5.0", - "semver": "^5.3.0", - "uglify-js": "^2.8.22", - "when": "^3.7.8" + "convert-source-map": "1.6.0", + "glob": "7.1.3", + "indx": "0.2.3", + "lodash.clone": "4.5.0", + "lodash.defaults": "4.2.0", + "lodash.flatten": "4.4.0", + "lodash.merge": "4.6.1", + "lodash.partialright": "4.2.1", + "lodash.pick": "4.4.0", + "lodash.uniq": "4.5.0", + "resolve": "1.8.1", + "semver": "5.5.1", + "uglify-js": "2.8.29", + "when": "3.7.8" }, "dependencies": { "semver": { @@ -875,7 +875,7 @@ "integrity": "sha512-JY+iV6r+cO21KtntVvFkD+iqjtdpRUpGqKWgfkCdZq1R+kbreEl8EcdcJR4SmiIgsIQT33s6QzheQ9a275Q8xw==", "dev": true, "requires": { - "acorn": "^5.0.3" + "acorn": "5.7.3" } }, "addressparser": { @@ -897,7 +897,7 @@ "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", "dev": true, "requires": { - "es6-promisify": "^5.0.0" + "es6-promisify": "5.0.0" } }, "ajv": { @@ -906,10 +906,10 @@ "integrity": "sha512-4Wyjt8+t6YszqaXnLDfMmG/8AlO5Zbcsy3ATHncCzjW/NoPzAId8AK6749Ybjmdt+kUY1gP60fCu46oDxPv/mg==", "dev": true, "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "fast-deep-equal": "2.0.1", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.4.1", + "uri-js": "4.2.2" } }, "ajv-keywords": { @@ -924,9 +924,9 @@ "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", "dev": true, "requires": { - "kind-of": "^3.0.2", - "longest": "^1.0.1", - "repeat-string": "^1.5.2" + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" }, "dependencies": { "kind-of": { @@ -935,7 +935,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -959,11 +959,11 @@ "dev": true, "optional": true, "requires": { - "bitsyntax": "~0.0.4", - "bluebird": "^3.4.6", + "bitsyntax": "0.0.4", + "bluebird": "3.5.2", "buffer-more-ints": "0.0.2", - "readable-stream": "1.x >=1.1.9", - "safe-buffer": "^5.0.1" + "readable-stream": "1.1.14", + "safe-buffer": "5.1.2" } }, "angular": { @@ -986,7 +986,7 @@ "resolved": "https://registry.npmjs.org/angular-dynamic-locale/-/angular-dynamic-locale-0.1.37.tgz", "integrity": "sha512-m5Kyk8W8/mOZSqRxuByOwHBjv8labLBAgvl0Z3iQx2xT/tWCqb94imKUPwumudszdPDjxeopwyucQvm8Sw7ogw==", "requires": { - "@types/angular": "^1.6.25" + "@types/angular": "1.6.51" } }, "angular-i18n": { @@ -1040,7 +1040,7 @@ "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", "dev": true, "requires": { - "ansi-wrap": "^0.1.0" + "ansi-wrap": "0.1.0" } }, "ansi-cyan": { @@ -1100,8 +1100,8 @@ "integrity": "sha1-VT3Lj5HjyImEXf26NMd3IbkLnXo=", "dev": true, "requires": { - "micromatch": "^2.1.5", - "normalize-path": "^2.0.0" + "micromatch": "2.3.11", + "normalize-path": "2.1.1" }, "dependencies": { "arr-diff": { @@ -1110,7 +1110,7 @@ "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", "dev": true, "requires": { - "arr-flatten": "^1.0.1" + "arr-flatten": "1.1.0" } }, "array-unique": { @@ -1125,9 +1125,9 @@ "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", "dev": true, "requires": { - "expand-range": "^1.8.1", - "preserve": "^0.2.0", - "repeat-element": "^1.1.2" + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.3" } }, "expand-brackets": { @@ -1136,7 +1136,7 @@ "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", "dev": true, "requires": { - "is-posix-bracket": "^0.1.0" + "is-posix-bracket": "0.1.1" } }, "extglob": { @@ -1145,7 +1145,7 @@ "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", "dev": true, "requires": { - "is-extglob": "^1.0.0" + "is-extglob": "1.0.0" } }, "is-extglob": { @@ -1160,7 +1160,7 @@ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "^1.0.0" + "is-extglob": "1.0.0" } }, "kind-of": { @@ -1169,7 +1169,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } }, "micromatch": { @@ -1178,19 +1178,19 @@ "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", "dev": true, "requires": { - "arr-diff": "^2.0.0", - "array-unique": "^0.2.1", - "braces": "^1.8.2", - "expand-brackets": "^0.1.4", - "extglob": "^0.3.1", - "filename-regex": "^2.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.1", - "kind-of": "^3.0.2", - "normalize-path": "^2.0.1", - "object.omit": "^2.0.0", - "parse-glob": "^3.0.4", - "regex-cache": "^0.4.2" + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" } } } @@ -1201,7 +1201,7 @@ "integrity": "sha1-nNnABpV+vpX62tW9YJiUKoE3N/Y=", "dev": true, "requires": { - "file-type": "^3.1.0" + "file-type": "3.9.0" }, "dependencies": { "file-type": { @@ -1224,7 +1224,7 @@ "integrity": "sha1-vNZ5HqWuCXJeF+WtmIE0zUCz2RE=", "dev": true, "requires": { - "sprintf-js": "~1.0.2" + "sprintf-js": "1.0.3" } }, "arr-diff": { @@ -1275,7 +1275,7 @@ "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", "dev": true, "requires": { - "array-uniq": "^1.0.1" + "array-uniq": "1.0.3" } }, "array-uniq": { @@ -1315,7 +1315,7 @@ "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", "dev": true, "requires": { - "safer-buffer": "~2.1.0" + "safer-buffer": "2.1.2" } }, "assert-plus": { @@ -1343,7 +1343,7 @@ "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", "dev": true, "requires": { - "lodash": "^4.17.10" + "lodash": "4.17.11" } }, "async-each": { @@ -1383,12 +1383,12 @@ "integrity": "sha1-Hb0cg1ZY41zj+ZhAmdsAWFx4IBQ=", "dev": true, "requires": { - "browserslist": "^1.7.6", - "caniuse-db": "^1.0.30000634", - "normalize-range": "^0.1.2", - "num2fraction": "^1.2.2", - "postcss": "^5.2.16", - "postcss-value-parser": "^3.2.3" + "browserslist": "1.7.7", + "caniuse-db": "1.0.30000889", + "normalize-range": "0.1.2", + "num2fraction": "1.2.2", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" } }, "aws-sign2": { @@ -1420,7 +1420,7 @@ "dev": true, "optional": true, "requires": { - "debug": "^2.2.0" + "debug": "2.6.9" } } } @@ -1443,13 +1443,13 @@ "integrity": "sha1-e95c7RRbbVUakNuH+DxVi060io8=", "dev": true, "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" + "cache-base": "1.0.1", + "class-utils": "0.3.6", + "component-emitter": "1.2.1", + "define-property": "1.0.0", + "isobject": "3.0.1", + "mixin-deep": "1.3.1", + "pascalcase": "0.1.1" }, "dependencies": { "define-property": { @@ -1458,7 +1458,7 @@ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "^1.0.0" + "is-descriptor": "1.0.2" } }, "is-accessor-descriptor": { @@ -1467,7 +1467,7 @@ "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", "dev": true, "requires": { - "kind-of": "^6.0.0" + "kind-of": "6.0.2" } }, "is-data-descriptor": { @@ -1476,7 +1476,7 @@ "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", "dev": true, "requires": { - "kind-of": "^6.0.0" + "kind-of": "6.0.2" } }, "is-descriptor": { @@ -1485,9 +1485,9 @@ "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", "dev": true, "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" } } } @@ -1535,7 +1535,7 @@ "dev": true, "optional": true, "requires": { - "tweetnacl": "^0.14.3" + "tweetnacl": "0.14.5" } }, "beeper": { @@ -1560,13 +1560,13 @@ "dev": true, "optional": true, "requires": { - "archive-type": "^3.0.1", - "decompress": "^3.0.0", - "download": "^4.1.2", - "exec-series": "^1.0.0", - "rimraf": "^2.2.6", - "tempfile": "^1.0.0", - "url-regex": "^3.0.0" + "archive-type": "3.2.0", + "decompress": "3.0.0", + "download": "4.4.3", + "exec-series": "1.0.3", + "rimraf": "2.6.2", + "tempfile": "1.1.1", + "url-regex": "3.2.0" }, "dependencies": { "tempfile": { @@ -1576,8 +1576,8 @@ "dev": true, "optional": true, "requires": { - "os-tmpdir": "^1.0.0", - "uuid": "^2.0.1" + "os-tmpdir": "1.0.2", + "uuid": "2.0.3" } }, "uuid": { @@ -1596,7 +1596,7 @@ "dev": true, "optional": true, "requires": { - "executable": "^1.0.0" + "executable": "1.1.0" } }, "bin-version": { @@ -1606,7 +1606,7 @@ "dev": true, "optional": true, "requires": { - "find-versions": "^1.0.0" + "find-versions": "1.2.1" } }, "bin-version-check": { @@ -1616,10 +1616,10 @@ "dev": true, "optional": true, "requires": { - "bin-version": "^1.0.0", - "minimist": "^1.1.0", - "semver": "^4.0.3", - "semver-truncate": "^1.0.0" + "bin-version": "1.0.4", + "minimist": "1.2.0", + "semver": "4.3.6", + "semver-truncate": "1.1.2" }, "dependencies": { "minimist": { @@ -1638,12 +1638,12 @@ "dev": true, "optional": true, "requires": { - "bin-check": "^2.0.0", - "bin-version-check": "^2.1.0", - "download": "^4.0.0", - "each-async": "^1.1.1", - "lazy-req": "^1.0.0", - "os-filter-obj": "^1.0.0" + "bin-check": "2.0.0", + "bin-version-check": "2.1.0", + "download": "4.4.3", + "each-async": "1.1.1", + "lazy-req": "1.1.0", + "os-filter-obj": "1.0.3" } }, "binary-extensions": { @@ -1668,8 +1668,8 @@ "integrity": "sha1-oWCRFxcQPAdBDO9j71Gzl8Alr5w=", "dev": true, "requires": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" + "readable-stream": "2.3.6", + "safe-buffer": "5.1.2" }, "dependencies": { "isarray": { @@ -1684,13 +1684,13 @@ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -1699,7 +1699,7 @@ "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } } } @@ -1723,15 +1723,15 @@ "dev": true, "requires": { "bytes": "2.1.0", - "content-type": "~1.0.1", - "debug": "~2.2.0", - "depd": "~1.0.1", - "http-errors": "~1.3.1", + "content-type": "1.0.4", + "debug": "2.2.0", + "depd": "1.0.1", + "http-errors": "1.3.1", "iconv-lite": "0.4.11", - "on-finished": "~2.3.0", + "on-finished": "2.3.0", "qs": "4.0.0", - "raw-body": "~2.1.2", - "type-is": "~1.6.6" + "raw-body": "2.1.7", + "type-is": "1.6.16" }, "dependencies": { "debug": { @@ -1763,7 +1763,7 @@ "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", "dev": true, "requires": { - "hoek": "2.x.x" + "hoek": "2.16.3" } }, "bootstrap": { @@ -1776,8 +1776,8 @@ "resolved": "https://registry.npmjs.org/bootstrap-social/-/bootstrap-social-4.8.0.tgz", "integrity": "sha1-ZtRj3JZtbbQH37mTNR1YxTSqLHo=", "requires": { - "bootstrap": "~3", - "font-awesome": "~4.3" + "bootstrap": "3.3.7", + "font-awesome": "4.3.0" }, "dependencies": { "font-awesome": { @@ -1799,14 +1799,14 @@ "integrity": "sha1-z3g5tlQh0rJwqyLHT8hYpV46E3A=", "dev": true, "requires": { - "async": "^2.1.4", - "bower": "^1.8.0", - "colors": "^1.1.2", - "glob": "^7.1.1", - "lodash": "^4.17.2", - "mkdirp": "^0.5.1", - "node-fs": "~0.1.7", - "nopt": "^3.0.6" + "async": "2.6.1", + "bower": "1.8.4", + "colors": "1.3.2", + "glob": "7.1.3", + "lodash": "4.17.11", + "mkdirp": "0.5.1", + "node-fs": "0.1.7", + "nopt": "3.0.6" } }, "brace-expansion": { @@ -1815,7 +1815,7 @@ "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=", "dev": true, "requires": { - "balanced-match": "^1.0.0", + "balanced-match": "1.0.0", "concat-map": "0.0.1" } }, @@ -1825,16 +1825,16 @@ "integrity": "sha1-WXn9PxTNUxVl5fot8av/8d+u5yk=", "dev": true, "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.3", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" }, "dependencies": { "extend-shallow": { @@ -1843,7 +1843,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } } } @@ -1854,8 +1854,8 @@ "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", "dev": true, "requires": { - "caniuse-db": "^1.0.30000639", - "electron-to-chromium": "^1.2.7" + "caniuse-db": "1.0.30000889", + "electron-to-chromium": "1.3.73" } }, "buffer-alloc": { @@ -1864,8 +1864,8 @@ "integrity": "sha1-iQ3ZDZI6hz4I4Q5f1RpX5bfM4Ow=", "dev": true, "requires": { - "buffer-alloc-unsafe": "^1.1.0", - "buffer-fill": "^1.0.0" + "buffer-alloc-unsafe": "1.1.0", + "buffer-fill": "1.0.0" } }, "buffer-alloc-unsafe": { @@ -1904,10 +1904,10 @@ "integrity": "sha1-APFfruOreh3aLN5tkSG//dB7ImI=", "dev": true, "requires": { - "file-type": "^3.1.0", - "readable-stream": "^2.0.2", - "uuid": "^2.0.1", - "vinyl": "^1.0.0" + "file-type": "3.9.0", + "readable-stream": "2.3.6", + "uuid": "2.0.3", + "vinyl": "1.2.0" }, "dependencies": { "file-type": { @@ -1928,13 +1928,13 @@ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -1943,7 +1943,7 @@ "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } }, "uuid": { @@ -1958,8 +1958,8 @@ "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", "dev": true, "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", + "clone": "1.0.4", + "clone-stats": "0.0.1", "replace-ext": "0.0.1" } } @@ -1971,7 +1971,7 @@ "integrity": "sha1-z7GtlWjTujz+k1upq92VLeiKqyo=", "dev": true, "requires": { - "readable-stream": "^1.0.33" + "readable-stream": "1.1.14" } }, "buildmail": { @@ -2017,15 +2017,15 @@ "integrity": "sha1-Cn9GQWgxyLZi7jb+TnxZ129marI=", "dev": true, "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" + "collection-visit": "1.0.0", + "component-emitter": "1.2.1", + "get-value": "2.0.6", + "has-value": "1.0.0", + "isobject": "3.0.1", + "set-value": "2.0.0", + "to-object-path": "0.3.0", + "union-value": "1.0.0", + "unset-value": "1.0.0" } }, "caller-path": { @@ -2034,7 +2034,7 @@ "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", "dev": true, "requires": { - "callsites": "^0.2.0" + "callsites": "0.2.0" } }, "callsite": { @@ -2061,8 +2061,8 @@ "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", "dev": true, "requires": { - "camelcase": "^2.0.0", - "map-obj": "^1.0.0" + "camelcase": "2.1.1", + "map-obj": "1.0.1" } }, "caniuse-api": { @@ -2071,10 +2071,10 @@ "integrity": "sha1-tTTnxzTE+B7F++isoq0kNUuWLGw=", "dev": true, "requires": { - "browserslist": "^1.3.6", - "caniuse-db": "^1.0.30000529", - "lodash.memoize": "^4.1.2", - "lodash.uniq": "^4.5.0" + "browserslist": "1.7.7", + "caniuse-db": "1.0.30000889", + "lodash.memoize": "4.1.2", + "lodash.uniq": "4.5.0" } }, "caniuse-db": { @@ -2113,10 +2113,10 @@ "integrity": "sha1-/7Im/n78VHKI3GLuPpcHPCEtEDQ=", "dev": true, "requires": { - "get-proxy": "^1.0.1", - "is-obj": "^1.0.0", - "object-assign": "^3.0.0", - "tunnel-agent": "^0.4.0" + "get-proxy": "1.1.0", + "is-obj": "1.0.1", + "object-assign": "3.0.0", + "tunnel-agent": "0.4.3" }, "dependencies": { "object-assign": { @@ -2133,8 +2133,8 @@ "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", "dev": true, "requires": { - "align-text": "^0.1.3", - "lazy-cache": "^1.0.3" + "align-text": "0.1.4", + "lazy-cache": "1.0.4" } }, "chalk": { @@ -2143,11 +2143,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" }, "dependencies": { "supports-color": { @@ -2170,15 +2170,15 @@ "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", "dev": true, "requires": { - "anymatch": "^1.3.0", - "async-each": "^1.0.0", - "fsevents": "^1.0.0", - "glob-parent": "^2.0.0", - "inherits": "^2.0.1", - "is-binary-path": "^1.0.0", - "is-glob": "^2.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0" + "anymatch": "1.3.2", + "async-each": "1.0.1", + "fsevents": "1.2.4", + "glob-parent": "2.0.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "2.0.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.2.1" }, "dependencies": { "glob-parent": { @@ -2187,7 +2187,7 @@ "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", "dev": true, "requires": { - "is-glob": "^2.0.0" + "is-glob": "2.0.1" } }, "is-extglob": { @@ -2202,7 +2202,7 @@ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "^1.0.0" + "is-extglob": "1.0.0" } } } @@ -2219,7 +2219,7 @@ "integrity": "sha1-TzZ0WzIAhJJVf0ZBLWbVDLmbzlE=", "dev": true, "requires": { - "chalk": "^1.1.3" + "chalk": "1.1.3" } }, "class-utils": { @@ -2228,10 +2228,10 @@ "integrity": "sha1-+TNprouafOAv1B+q0MqDAzGQxGM=", "dev": true, "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" + "arr-union": "3.1.0", + "define-property": "0.2.5", + "isobject": "3.0.1", + "static-extend": "0.1.2" }, "dependencies": { "define-property": { @@ -2240,7 +2240,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "is-descriptor": "0.1.6" } } } @@ -2251,7 +2251,7 @@ "integrity": "sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==", "dev": true, "requires": { - "source-map": "~0.6.0" + "source-map": "0.6.1" }, "dependencies": { "source-map": { @@ -2268,7 +2268,7 @@ "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", "dev": true, "requires": { - "restore-cursor": "^2.0.0" + "restore-cursor": "2.0.0" } }, "cli-width": { @@ -2282,9 +2282,9 @@ "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.0.tgz", "integrity": "sha512-gXzHBlzEVqCk2b8Wpkil89S0WSMAX7eZho2zANX+EEEa9LMutGe9ICU+wHRzsH7cCHaCbUzj900P+AXOM0FE3A==", "requires": { - "good-listener": "^1.2.2", - "select": "^1.1.2", - "tiny-emitter": "^2.0.0" + "good-listener": "1.2.2", + "select": "1.1.2", + "tiny-emitter": "2.0.2" } }, "cliui": { @@ -2293,8 +2293,8 @@ "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", "dev": true, "requires": { - "center-align": "^0.1.1", - "right-align": "^0.1.1", + "center-align": "0.1.3", + "right-align": "0.1.3", "wordwrap": "0.0.2" }, "dependencies": { @@ -2330,9 +2330,9 @@ "integrity": "sha1-1ZHe5Kj4vBXaQ86X3O66E9Q+KmU=", "dev": true, "requires": { - "inherits": "^2.0.1", - "process-nextick-args": "^2.0.0", - "readable-stream": "^2.3.5" + "inherits": "2.0.3", + "process-nextick-args": "2.0.0", + "readable-stream": "2.3.6" }, "dependencies": { "isarray": { @@ -2347,13 +2347,13 @@ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -2362,7 +2362,7 @@ "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } } } @@ -2379,7 +2379,7 @@ "integrity": "sha1-qe8VNmDWqGqL3sAomlxoTSF0Mv0=", "dev": true, "requires": { - "q": "^1.1.2" + "q": "1.5.1" } }, "codemirror": { @@ -2393,8 +2393,8 @@ "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", "dev": true, "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" + "map-visit": "1.0.0", + "object-visit": "1.0.1" } }, "color": { @@ -2403,9 +2403,9 @@ "integrity": "sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q=", "dev": true, "requires": { - "clone": "^1.0.2", - "color-convert": "^1.3.0", - "color-string": "^0.3.0" + "clone": "1.0.4", + "color-convert": "1.9.3", + "color-string": "0.3.0" } }, "color-convert": { @@ -2429,7 +2429,7 @@ "integrity": "sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE=", "dev": true, "requires": { - "color-name": "^1.0.0" + "color-name": "1.1.3" } }, "color-support": { @@ -2444,9 +2444,9 @@ "integrity": "sha1-6i90IKcrlogaOKrlnsEkpvcpgTM=", "dev": true, "requires": { - "color": "^0.11.0", + "color": "0.11.4", "css-color-names": "0.0.4", - "has": "^1.0.1" + "has": "1.0.3" } }, "colors": { @@ -2461,7 +2461,7 @@ "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=", "dev": true, "requires": { - "lodash": "^4.5.0" + "lodash": "4.17.11" } }, "combined-stream": { @@ -2470,7 +2470,7 @@ "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", "dev": true, "requires": { - "delayed-stream": "~1.0.0" + "delayed-stream": "1.0.0" } }, "commander": { @@ -2479,7 +2479,7 @@ "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", "dev": true, "requires": { - "graceful-readlink": ">= 1.0.0" + "graceful-readlink": "1.0.1" } }, "component-bind": { @@ -2506,7 +2506,7 @@ "integrity": "sha512-4aE67DL33dSW9gw4CI2H/yTxqHLNcxp0yS6jB+4h+wr3e43+1z7vm0HU9qXOH8j+qjKuL8+UtkOxYQSMq60Ylw==", "dev": true, "requires": { - "mime-db": ">= 1.36.0 < 2" + "mime-db": "1.36.0" } }, "compression": { @@ -2515,12 +2515,12 @@ "integrity": "sha1-sDuNhub4rSloPLqN+R3cb/x3s5U=", "dev": true, "requires": { - "accepts": "~1.2.12", + "accepts": "1.2.13", "bytes": "2.1.0", - "compressible": "~2.0.5", - "debug": "~2.2.0", - "on-headers": "~1.0.0", - "vary": "~1.0.1" + "compressible": "2.0.15", + "debug": "2.2.0", + "on-headers": "1.0.1", + "vary": "1.0.1" }, "dependencies": { "debug": { @@ -2552,10 +2552,10 @@ "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", "dev": true, "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" + "buffer-from": "1.1.1", + "inherits": "2.0.3", + "readable-stream": "2.3.6", + "typedarray": "0.0.6" }, "dependencies": { "isarray": { @@ -2570,13 +2570,13 @@ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -2585,7 +2585,7 @@ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } } } @@ -2596,7 +2596,7 @@ "integrity": "sha1-1OqT8FriV5CVG5nns7CeOQikCC4=", "dev": true, "requires": { - "source-map": "^0.6.1" + "source-map": "0.6.1" }, "dependencies": { "source-map": { @@ -2614,36 +2614,36 @@ "dev": true, "requires": { "basic-auth-connect": "1.0.0", - "body-parser": "~1.13.3", + "body-parser": "1.13.3", "bytes": "2.1.0", - "compression": "~1.5.2", - "connect-timeout": "~1.6.2", - "content-type": "~1.0.1", + "compression": "1.5.2", + "connect-timeout": "1.6.2", + "content-type": "1.0.4", "cookie": "0.1.3", - "cookie-parser": "~1.3.5", + "cookie-parser": "1.3.5", "cookie-signature": "1.0.6", - "csurf": "~1.8.3", - "debug": "~2.2.0", - "depd": "~1.0.1", - "errorhandler": "~1.4.2", - "express-session": "~1.11.3", + "csurf": "1.8.3", + "debug": "2.2.0", + "depd": "1.0.1", + "errorhandler": "1.4.3", + "express-session": "1.11.3", "finalhandler": "0.4.0", "fresh": "0.3.0", - "http-errors": "~1.3.1", - "method-override": "~2.3.5", - "morgan": "~1.6.1", + "http-errors": "1.3.1", + "method-override": "2.3.10", + "morgan": "1.6.1", "multiparty": "3.3.2", - "on-headers": "~1.0.0", - "parseurl": "~1.3.0", + "on-headers": "1.0.1", + "parseurl": "1.3.2", "pause": "0.1.0", "qs": "4.0.0", - "response-time": "~2.3.1", - "serve-favicon": "~2.3.0", - "serve-index": "~1.7.2", - "serve-static": "~1.10.0", - "type-is": "~1.6.6", + "response-time": "2.3.2", + "serve-favicon": "2.3.2", + "serve-index": "1.7.3", + "serve-static": "1.10.3", + "type-is": "1.6.16", "utils-merge": "1.0.0", - "vhost": "~3.0.1" + "vhost": "3.0.2" }, "dependencies": { "debug": { @@ -2675,10 +2675,10 @@ "integrity": "sha1-3ppexh4zoStu2qt7XwYumMWZuI4=", "dev": true, "requires": { - "debug": "~2.2.0", - "http-errors": "~1.3.1", + "debug": "2.2.0", + "http-errors": "1.3.1", "ms": "0.7.1", - "on-headers": "~1.0.0" + "on-headers": "1.0.1" }, "dependencies": { "debug": { @@ -2711,7 +2711,7 @@ "integrity": "sha1-WiUEe8dvcwcmZ8jLUsmJiI9JTGM=", "dev": true, "requires": { - "bluebird": "^3.1.1" + "bluebird": "3.5.2" } }, "content-type": { @@ -2726,7 +2726,7 @@ "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", "dev": true, "requires": { - "safe-buffer": "~5.1.1" + "safe-buffer": "5.1.2" } }, "cookie": { @@ -2775,13 +2775,13 @@ "integrity": "sha1-YXPOvVb6wELB9DkO33r2wHx8uJI=", "dev": true, "requires": { - "is-directory": "^0.3.1", - "js-yaml": "^3.4.3", - "minimist": "^1.2.0", - "object-assign": "^4.1.0", - "os-homedir": "^1.0.1", - "parse-json": "^2.2.0", - "require-from-string": "^1.1.0" + "is-directory": "0.3.1", + "js-yaml": "3.7.0", + "minimist": "1.2.0", + "object-assign": "4.1.1", + "os-homedir": "1.0.2", + "parse-json": "2.2.0", + "require-from-string": "1.2.1" }, "dependencies": { "minimist": { @@ -2804,7 +2804,7 @@ "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", "dev": true, "requires": { - "capture-stack-trace": "^1.0.0" + "capture-stack-trace": "1.0.1" } }, "cross-spawn": { @@ -2813,11 +2813,11 @@ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "dev": true, "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "nice-try": "1.0.5", + "path-key": "2.0.1", + "semver": "5.5.1", + "shebang-command": "1.2.0", + "which": "1.3.1" }, "dependencies": { "semver": { @@ -2834,7 +2834,7 @@ "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", "dev": true, "requires": { - "boom": "2.x.x" + "boom": "2.10.1" } }, "csrf": { @@ -2861,10 +2861,10 @@ "dev": true, "optional": true, "requires": { - "boolbase": "^1.0.0", - "css-what": "2.1", - "domutils": "^1.7.0", - "nth-check": "^1.0.1" + "boolbase": "1.0.0", + "css-what": "2.1.0", + "domutils": "1.7.0", + "nth-check": "1.0.1" } }, "css-select-base-adapter": { @@ -2881,8 +2881,8 @@ "dev": true, "optional": true, "requires": { - "mdn-data": "~1.1.0", - "source-map": "^0.5.3" + "mdn-data": "1.1.4", + "source-map": "0.5.7" } }, "css-url-regex": { @@ -2905,38 +2905,38 @@ "integrity": "sha1-Tzj2zqK5sX+gFJDyPx3GjqZcHDg=", "dev": true, "requires": { - "autoprefixer": "^6.3.1", - "decamelize": "^1.1.2", - "defined": "^1.0.0", - "has": "^1.0.1", - "object-assign": "^4.0.1", - "postcss": "^5.0.14", - "postcss-calc": "^5.2.0", - "postcss-colormin": "^2.1.8", - "postcss-convert-values": "^2.3.4", - "postcss-discard-comments": "^2.0.4", - "postcss-discard-duplicates": "^2.0.1", - "postcss-discard-empty": "^2.0.1", - "postcss-discard-overridden": "^0.1.1", - "postcss-discard-unused": "^2.2.1", - "postcss-filter-plugins": "^2.0.0", - "postcss-merge-idents": "^2.1.5", - "postcss-merge-longhand": "^2.0.1", - "postcss-merge-rules": "^2.0.3", - "postcss-minify-font-values": "^1.0.2", - "postcss-minify-gradients": "^1.0.1", - "postcss-minify-params": "^1.0.4", - "postcss-minify-selectors": "^2.0.4", - "postcss-normalize-charset": "^1.1.0", - "postcss-normalize-url": "^3.0.7", - "postcss-ordered-values": "^2.1.0", - "postcss-reduce-idents": "^2.2.2", - "postcss-reduce-initial": "^1.0.0", - "postcss-reduce-transforms": "^1.0.3", - "postcss-svgo": "^2.1.1", - "postcss-unique-selectors": "^2.0.2", - "postcss-value-parser": "^3.2.3", - "postcss-zindex": "^2.0.1" + "autoprefixer": "6.7.7", + "decamelize": "1.2.0", + "defined": "1.0.0", + "has": "1.0.3", + "object-assign": "4.1.1", + "postcss": "5.2.18", + "postcss-calc": "5.3.1", + "postcss-colormin": "2.2.2", + "postcss-convert-values": "2.6.1", + "postcss-discard-comments": "2.0.4", + "postcss-discard-duplicates": "2.1.0", + "postcss-discard-empty": "2.1.0", + "postcss-discard-overridden": "0.1.1", + "postcss-discard-unused": "2.2.3", + "postcss-filter-plugins": "2.0.3", + "postcss-merge-idents": "2.1.7", + "postcss-merge-longhand": "2.0.2", + "postcss-merge-rules": "2.1.2", + "postcss-minify-font-values": "1.0.5", + "postcss-minify-gradients": "1.0.5", + "postcss-minify-params": "1.2.2", + "postcss-minify-selectors": "2.1.1", + "postcss-normalize-charset": "1.1.1", + "postcss-normalize-url": "3.0.8", + "postcss-ordered-values": "2.2.3", + "postcss-reduce-idents": "2.4.0", + "postcss-reduce-initial": "1.0.1", + "postcss-reduce-transforms": "1.0.4", + "postcss-svgo": "2.1.6", + "postcss-unique-selectors": "2.0.2", + "postcss-value-parser": "3.3.0", + "postcss-zindex": "2.2.0" } }, "csso": { @@ -2945,8 +2945,8 @@ "integrity": "sha1-3dUsWHAz9J6Utx/FVWnyUuj/X4U=", "dev": true, "requires": { - "clap": "^1.0.9", - "source-map": "^0.5.3" + "clap": "1.2.3", + "source-map": "0.5.7" } }, "csurf": { @@ -2957,8 +2957,8 @@ "requires": { "cookie": "0.1.3", "cookie-signature": "1.0.6", - "csrf": "~3.0.0", - "http-errors": "~1.3.1" + "csrf": "3.0.6", + "http-errors": "1.3.1" } }, "currently-unhandled": { @@ -2967,7 +2967,7 @@ "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", "dev": true, "requires": { - "array-find-index": "^1.0.1" + "array-find-index": "1.0.2" } }, "custom-event": { @@ -2982,7 +2982,7 @@ "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", "dev": true, "requires": { - "assert-plus": "^1.0.0" + "assert-plus": "1.0.0" }, "dependencies": { "assert-plus": { @@ -3039,15 +3039,15 @@ "integrity": "sha1-rx3VDQbjv8QyRh033hGzjA2ZG+0=", "dev": true, "requires": { - "buffer-to-vinyl": "^1.0.0", - "concat-stream": "^1.4.6", - "decompress-tar": "^3.0.0", - "decompress-tarbz2": "^3.0.0", - "decompress-targz": "^3.0.0", - "decompress-unzip": "^3.0.0", - "stream-combiner2": "^1.1.1", - "vinyl-assign": "^1.0.1", - "vinyl-fs": "^2.2.0" + "buffer-to-vinyl": "1.1.0", + "concat-stream": "1.6.2", + "decompress-tar": "3.1.0", + "decompress-tarbz2": "3.1.0", + "decompress-targz": "3.1.0", + "decompress-unzip": "3.4.0", + "stream-combiner2": "1.1.1", + "vinyl-assign": "1.2.1", + "vinyl-fs": "2.4.4" }, "dependencies": { "arr-diff": { @@ -3056,7 +3056,7 @@ "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", "dev": true, "requires": { - "arr-flatten": "^1.0.1" + "arr-flatten": "1.1.0" } }, "array-unique": { @@ -3071,9 +3071,9 @@ "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", "dev": true, "requires": { - "expand-range": "^1.8.1", - "preserve": "^0.2.0", - "repeat-element": "^1.1.2" + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.3" } }, "expand-brackets": { @@ -3082,7 +3082,7 @@ "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", "dev": true, "requires": { - "is-posix-bracket": "^0.1.0" + "is-posix-bracket": "0.1.1" } }, "extglob": { @@ -3091,7 +3091,7 @@ "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", "dev": true, "requires": { - "is-extglob": "^1.0.0" + "is-extglob": "1.0.0" } }, "glob": { @@ -3100,11 +3100,11 @@ "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", "dev": true, "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" } }, "glob-stream": { @@ -3113,14 +3113,14 @@ "integrity": "sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=", "dev": true, "requires": { - "extend": "^3.0.0", - "glob": "^5.0.3", - "glob-parent": "^3.0.0", - "micromatch": "^2.3.7", - "ordered-read-streams": "^0.3.0", - "through2": "^0.6.0", - "to-absolute-glob": "^0.1.1", - "unique-stream": "^2.0.2" + "extend": "3.0.2", + "glob": "5.0.15", + "glob-parent": "3.1.0", + "micromatch": "2.3.11", + "ordered-read-streams": "0.3.0", + "through2": "0.6.5", + "to-absolute-glob": "0.1.1", + "unique-stream": "2.2.1" }, "dependencies": { "isarray": { @@ -3135,10 +3135,10 @@ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", + "core-util-is": "1.0.2", + "inherits": "2.0.3", "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "string_decoder": "0.10.31" } }, "string_decoder": { @@ -3153,8 +3153,8 @@ "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", "dev": true, "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" + "readable-stream": "1.0.34", + "xtend": "4.0.1" } } } @@ -3177,7 +3177,7 @@ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "^1.0.0" + "is-extglob": "1.0.0" } }, "isarray": { @@ -3192,7 +3192,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } }, "micromatch": { @@ -3201,19 +3201,19 @@ "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", "dev": true, "requires": { - "arr-diff": "^2.0.0", - "array-unique": "^0.2.1", - "braces": "^1.8.2", - "expand-brackets": "^0.1.4", - "extglob": "^0.3.1", - "filename-regex": "^2.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.1", - "kind-of": "^3.0.2", - "normalize-path": "^2.0.1", - "object.omit": "^2.0.0", - "parse-glob": "^3.0.4", - "regex-cache": "^0.4.2" + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" } }, "ordered-read-streams": { @@ -3222,8 +3222,8 @@ "integrity": "sha1-cTfmmzKYuzQiR6G77jiByA4v14s=", "dev": true, "requires": { - "is-stream": "^1.0.1", - "readable-stream": "^2.0.1" + "is-stream": "1.1.0", + "readable-stream": "2.3.6" } }, "readable-stream": { @@ -3232,13 +3232,13 @@ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -3247,7 +3247,7 @@ "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } }, "strip-bom": { @@ -3256,7 +3256,7 @@ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "dev": true, "requires": { - "is-utf8": "^0.2.0" + "is-utf8": "0.2.1" } }, "unique-stream": { @@ -3265,8 +3265,8 @@ "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", "dev": true, "requires": { - "json-stable-stringify": "^1.0.0", - "through2-filter": "^2.0.0" + "json-stable-stringify": "1.0.1", + "through2-filter": "2.0.0" } }, "vinyl": { @@ -3275,8 +3275,8 @@ "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", "dev": true, "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", + "clone": "1.0.4", + "clone-stats": "0.0.1", "replace-ext": "0.0.1" } }, @@ -3286,23 +3286,23 @@ "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=", "dev": true, "requires": { - "duplexify": "^3.2.0", - "glob-stream": "^5.3.2", - "graceful-fs": "^4.0.0", + "duplexify": "3.6.0", + "glob-stream": "5.3.5", + "graceful-fs": "4.1.11", "gulp-sourcemaps": "1.6.0", - "is-valid-glob": "^0.3.0", - "lazystream": "^1.0.0", - "lodash.isequal": "^4.0.0", - "merge-stream": "^1.0.0", - "mkdirp": "^0.5.0", - "object-assign": "^4.0.0", - "readable-stream": "^2.0.4", - "strip-bom": "^2.0.0", - "strip-bom-stream": "^1.0.0", - "through2": "^2.0.0", - "through2-filter": "^2.0.0", - "vali-date": "^1.0.0", - "vinyl": "^1.0.0" + "is-valid-glob": "0.3.0", + "lazystream": "1.0.0", + "lodash.isequal": "4.5.0", + "merge-stream": "1.0.1", + "mkdirp": "0.5.1", + "object-assign": "4.1.1", + "readable-stream": "2.3.6", + "strip-bom": "2.0.0", + "strip-bom-stream": "1.0.0", + "through2": "2.0.3", + "through2-filter": "2.0.0", + "vali-date": "1.0.0", + "vinyl": "1.2.0" } } } @@ -3313,12 +3313,12 @@ "integrity": "sha1-IXx4n5uURQ76rcXF5TeXj8MzxGY=", "dev": true, "requires": { - "is-tar": "^1.0.0", - "object-assign": "^2.0.0", - "strip-dirs": "^1.0.0", - "tar-stream": "^1.1.1", - "through2": "^0.6.1", - "vinyl": "^0.4.3" + "is-tar": "1.0.0", + "object-assign": "2.1.1", + "strip-dirs": "1.1.1", + "tar-stream": "1.6.2", + "through2": "0.6.5", + "vinyl": "0.4.6" }, "dependencies": { "clone": { @@ -3339,10 +3339,10 @@ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", + "core-util-is": "1.0.2", + "inherits": "2.0.3", "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "string_decoder": "0.10.31" } }, "through2": { @@ -3351,8 +3351,8 @@ "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", "dev": true, "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" + "readable-stream": "1.0.34", + "xtend": "4.0.1" } }, "vinyl": { @@ -3361,8 +3361,8 @@ "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", "dev": true, "requires": { - "clone": "^0.2.0", - "clone-stats": "^0.0.1" + "clone": "0.2.0", + "clone-stats": "0.0.1" } } } @@ -3373,13 +3373,13 @@ "integrity": "sha1-iyOTVoE1X58YnYclag+L3ZbZZm0=", "dev": true, "requires": { - "is-bzip2": "^1.0.0", - "object-assign": "^2.0.0", - "seek-bzip": "^1.0.3", - "strip-dirs": "^1.0.0", - "tar-stream": "^1.1.1", - "through2": "^0.6.1", - "vinyl": "^0.4.3" + "is-bzip2": "1.0.0", + "object-assign": "2.1.1", + "seek-bzip": "1.0.5", + "strip-dirs": "1.1.1", + "tar-stream": "1.6.2", + "through2": "0.6.5", + "vinyl": "0.4.6" }, "dependencies": { "clone": { @@ -3400,10 +3400,10 @@ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", + "core-util-is": "1.0.2", + "inherits": "2.0.3", "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "string_decoder": "0.10.31" } }, "through2": { @@ -3412,8 +3412,8 @@ "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", "dev": true, "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" + "readable-stream": "1.0.34", + "xtend": "4.0.1" } }, "vinyl": { @@ -3422,8 +3422,8 @@ "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", "dev": true, "requires": { - "clone": "^0.2.0", - "clone-stats": "^0.0.1" + "clone": "0.2.0", + "clone-stats": "0.0.1" } } } @@ -3434,12 +3434,12 @@ "integrity": "sha1-ssE9+YFmJomRtxXWRH9kLpaW9aA=", "dev": true, "requires": { - "is-gzip": "^1.0.0", - "object-assign": "^2.0.0", - "strip-dirs": "^1.0.0", - "tar-stream": "^1.1.1", - "through2": "^0.6.1", - "vinyl": "^0.4.3" + "is-gzip": "1.0.0", + "object-assign": "2.1.1", + "strip-dirs": "1.1.1", + "tar-stream": "1.6.2", + "through2": "0.6.5", + "vinyl": "0.4.6" }, "dependencies": { "clone": { @@ -3460,10 +3460,10 @@ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", + "core-util-is": "1.0.2", + "inherits": "2.0.3", "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "string_decoder": "0.10.31" } }, "through2": { @@ -3472,8 +3472,8 @@ "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", "dev": true, "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" + "readable-stream": "1.0.34", + "xtend": "4.0.1" } }, "vinyl": { @@ -3482,8 +3482,8 @@ "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", "dev": true, "requires": { - "clone": "^0.2.0", - "clone-stats": "^0.0.1" + "clone": "0.2.0", + "clone-stats": "0.0.1" } } } @@ -3494,13 +3494,13 @@ "integrity": "sha1-YUdbQVIGa74/7hL51inRX+ZHjus=", "dev": true, "requires": { - "is-zip": "^1.0.0", - "read-all-stream": "^3.0.0", - "stat-mode": "^0.2.0", - "strip-dirs": "^1.0.0", - "through2": "^2.0.0", - "vinyl": "^1.0.0", - "yauzl": "^2.2.1" + "is-zip": "1.0.0", + "read-all-stream": "3.1.0", + "stat-mode": "0.2.2", + "strip-dirs": "1.1.1", + "through2": "2.0.3", + "vinyl": "1.2.0", + "yauzl": "2.10.0" }, "dependencies": { "vinyl": { @@ -3509,8 +3509,8 @@ "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", "dev": true, "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", + "clone": "1.0.4", + "clone-stats": "0.0.1", "replace-ext": "0.0.1" } } @@ -3534,7 +3534,7 @@ "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", "dev": true, "requires": { - "clone": "^1.0.2" + "clone": "1.0.4" } }, "define-properties": { @@ -3543,7 +3543,7 @@ "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", "dev": true, "requires": { - "object-keys": "^1.0.12" + "object-keys": "1.0.12" } }, "define-property": { @@ -3552,8 +3552,8 @@ "integrity": "sha1-1Flono1lS6d+AqgX+HENcCyxbp0=", "dev": true, "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" + "is-descriptor": "1.0.2", + "isobject": "3.0.1" }, "dependencies": { "is-accessor-descriptor": { @@ -3562,7 +3562,7 @@ "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", "dev": true, "requires": { - "kind-of": "^6.0.0" + "kind-of": "6.0.2" } }, "is-data-descriptor": { @@ -3571,7 +3571,7 @@ "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", "dev": true, "requires": { - "kind-of": "^6.0.0" + "kind-of": "6.0.2" } }, "is-descriptor": { @@ -3580,9 +3580,9 @@ "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", "dev": true, "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" } } } @@ -3600,9 +3600,9 @@ "dev": true, "optional": true, "requires": { - "ast-types": "0.x.x", - "escodegen": "1.x.x", - "esprima": "3.x.x" + "ast-types": "0.11.5", + "escodegen": "1.11.0", + "esprima": "3.1.3" }, "dependencies": { "esprima": { @@ -3620,13 +3620,13 @@ "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", "dev": true, "requires": { - "globby": "^5.0.0", - "is-path-cwd": "^1.0.0", - "is-path-in-cwd": "^1.0.0", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "rimraf": "^2.2.8" + "globby": "5.0.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.1", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "rimraf": "2.6.2" } }, "delayed-stream": { @@ -3681,7 +3681,7 @@ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, "requires": { - "esutils": "^2.0.2" + "esutils": "2.0.2" } }, "dom-serialize": { @@ -3690,10 +3690,10 @@ "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", "dev": true, "requires": { - "custom-event": "~1.0.0", - "ent": "~2.2.0", - "extend": "^3.0.0", - "void-elements": "^2.0.0" + "custom-event": "1.0.1", + "ent": "2.2.0", + "extend": "3.0.2", + "void-elements": "2.0.1" } }, "dom-serializer": { @@ -3703,8 +3703,8 @@ "dev": true, "optional": true, "requires": { - "domelementtype": "~1.1.1", - "entities": "~1.1.1" + "domelementtype": "1.1.3", + "entities": "1.1.1" }, "dependencies": { "domelementtype": { @@ -3730,8 +3730,8 @@ "dev": true, "optional": true, "requires": { - "dom-serializer": "0", - "domelementtype": "1" + "dom-serializer": "0.1.0", + "domelementtype": "1.3.0" } }, "double-ended-queue": { @@ -3747,21 +3747,21 @@ "integrity": "sha1-qlX9rTktldS2jowr4D4MKqIbqaw=", "dev": true, "requires": { - "caw": "^1.0.1", - "concat-stream": "^1.4.7", - "each-async": "^1.0.0", - "filenamify": "^1.0.1", - "got": "^5.0.0", - "gulp-decompress": "^1.2.0", - "gulp-rename": "^1.2.0", - "is-url": "^1.2.0", - "object-assign": "^4.0.1", - "read-all-stream": "^3.0.0", - "readable-stream": "^2.0.2", - "stream-combiner2": "^1.1.1", - "vinyl": "^1.0.0", - "vinyl-fs": "^2.2.0", - "ware": "^1.2.0" + "caw": "1.2.0", + "concat-stream": "1.6.2", + "each-async": "1.1.1", + "filenamify": "1.2.1", + "got": "5.7.1", + "gulp-decompress": "1.2.0", + "gulp-rename": "1.4.0", + "is-url": "1.2.4", + "object-assign": "4.1.1", + "read-all-stream": "3.1.0", + "readable-stream": "2.3.6", + "stream-combiner2": "1.1.1", + "vinyl": "1.2.0", + "vinyl-fs": "2.4.4", + "ware": "1.3.0" }, "dependencies": { "arr-diff": { @@ -3770,7 +3770,7 @@ "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", "dev": true, "requires": { - "arr-flatten": "^1.0.1" + "arr-flatten": "1.1.0" } }, "array-unique": { @@ -3785,9 +3785,9 @@ "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", "dev": true, "requires": { - "expand-range": "^1.8.1", - "preserve": "^0.2.0", - "repeat-element": "^1.1.2" + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.3" } }, "expand-brackets": { @@ -3796,7 +3796,7 @@ "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", "dev": true, "requires": { - "is-posix-bracket": "^0.1.0" + "is-posix-bracket": "0.1.1" } }, "extglob": { @@ -3805,7 +3805,7 @@ "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", "dev": true, "requires": { - "is-extglob": "^1.0.0" + "is-extglob": "1.0.0" } }, "glob": { @@ -3814,11 +3814,11 @@ "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", "dev": true, "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" } }, "glob-stream": { @@ -3827,14 +3827,14 @@ "integrity": "sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=", "dev": true, "requires": { - "extend": "^3.0.0", - "glob": "^5.0.3", - "glob-parent": "^3.0.0", - "micromatch": "^2.3.7", - "ordered-read-streams": "^0.3.0", - "through2": "^0.6.0", - "to-absolute-glob": "^0.1.1", - "unique-stream": "^2.0.2" + "extend": "3.0.2", + "glob": "5.0.15", + "glob-parent": "3.1.0", + "micromatch": "2.3.11", + "ordered-read-streams": "0.3.0", + "through2": "0.6.5", + "to-absolute-glob": "0.1.1", + "unique-stream": "2.2.1" }, "dependencies": { "isarray": { @@ -3849,10 +3849,10 @@ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", + "core-util-is": "1.0.2", + "inherits": "2.0.3", "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "string_decoder": "0.10.31" } }, "string_decoder": { @@ -3867,8 +3867,8 @@ "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", "dev": true, "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" + "readable-stream": "1.0.34", + "xtend": "4.0.1" } } } @@ -3891,7 +3891,7 @@ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "^1.0.0" + "is-extglob": "1.0.0" } }, "isarray": { @@ -3906,7 +3906,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } }, "micromatch": { @@ -3915,19 +3915,19 @@ "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", "dev": true, "requires": { - "arr-diff": "^2.0.0", - "array-unique": "^0.2.1", - "braces": "^1.8.2", - "expand-brackets": "^0.1.4", - "extglob": "^0.3.1", - "filename-regex": "^2.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.1", - "kind-of": "^3.0.2", - "normalize-path": "^2.0.1", - "object.omit": "^2.0.0", - "parse-glob": "^3.0.4", - "regex-cache": "^0.4.2" + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" } }, "ordered-read-streams": { @@ -3936,8 +3936,8 @@ "integrity": "sha1-cTfmmzKYuzQiR6G77jiByA4v14s=", "dev": true, "requires": { - "is-stream": "^1.0.1", - "readable-stream": "^2.0.1" + "is-stream": "1.1.0", + "readable-stream": "2.3.6" } }, "readable-stream": { @@ -3946,13 +3946,13 @@ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -3961,7 +3961,7 @@ "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } }, "strip-bom": { @@ -3970,7 +3970,7 @@ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "dev": true, "requires": { - "is-utf8": "^0.2.0" + "is-utf8": "0.2.1" } }, "unique-stream": { @@ -3979,8 +3979,8 @@ "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", "dev": true, "requires": { - "json-stable-stringify": "^1.0.0", - "through2-filter": "^2.0.0" + "json-stable-stringify": "1.0.1", + "through2-filter": "2.0.0" } }, "vinyl": { @@ -3989,8 +3989,8 @@ "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", "dev": true, "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", + "clone": "1.0.4", + "clone-stats": "0.0.1", "replace-ext": "0.0.1" } }, @@ -4000,23 +4000,23 @@ "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=", "dev": true, "requires": { - "duplexify": "^3.2.0", - "glob-stream": "^5.3.2", - "graceful-fs": "^4.0.0", + "duplexify": "3.6.0", + "glob-stream": "5.3.5", + "graceful-fs": "4.1.11", "gulp-sourcemaps": "1.6.0", - "is-valid-glob": "^0.3.0", - "lazystream": "^1.0.0", - "lodash.isequal": "^4.0.0", - "merge-stream": "^1.0.0", - "mkdirp": "^0.5.0", - "object-assign": "^4.0.0", - "readable-stream": "^2.0.4", - "strip-bom": "^2.0.0", - "strip-bom-stream": "^1.0.0", - "through2": "^2.0.0", - "through2-filter": "^2.0.0", - "vali-date": "^1.0.0", - "vinyl": "^1.0.0" + "is-valid-glob": "0.3.0", + "lazystream": "1.0.0", + "lodash.isequal": "4.5.0", + "merge-stream": "1.0.1", + "mkdirp": "0.5.1", + "object-assign": "4.1.1", + "readable-stream": "2.3.6", + "strip-bom": "2.0.0", + "strip-bom-stream": "1.0.0", + "through2": "2.0.3", + "through2-filter": "2.0.0", + "vali-date": "1.0.0", + "vinyl": "1.2.0" } } } @@ -4033,7 +4033,7 @@ "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", "dev": true, "requires": { - "readable-stream": "~1.1.9" + "readable-stream": "1.1.14" } }, "duplexify": { @@ -4042,10 +4042,10 @@ "integrity": "sha1-WSkD9dgLONA3IgVBJk1poZj7NBA=", "dev": true, "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" + "end-of-stream": "1.4.1", + "inherits": "2.0.3", + "readable-stream": "2.3.6", + "stream-shift": "1.0.0" }, "dependencies": { "end-of-stream": { @@ -4054,7 +4054,7 @@ "integrity": "sha1-7SljTRm6ukY7bOa4CjchPqtx7EM=", "dev": true, "requires": { - "once": "^1.4.0" + "once": "1.4.0" } }, "isarray": { @@ -4069,13 +4069,13 @@ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -4084,7 +4084,7 @@ "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } } } @@ -4095,8 +4095,8 @@ "integrity": "sha1-3uUim98KtrogEqOV4bhpq/iBNHM=", "dev": true, "requires": { - "onetime": "^1.0.0", - "set-immediate-shim": "^1.0.0" + "onetime": "1.1.0", + "set-immediate-shim": "1.0.1" }, "dependencies": { "onetime": { @@ -4114,8 +4114,8 @@ "dev": true, "optional": true, "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" + "jsbn": "0.1.1", + "safer-buffer": "2.1.2" } }, "ee-first": { @@ -4142,7 +4142,7 @@ "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", "dev": true, "requires": { - "once": "~1.3.0" + "once": "1.3.3" }, "dependencies": { "once": { @@ -4151,7 +4151,7 @@ "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", "dev": true, "requires": { - "wrappy": "1" + "wrappy": "1.0.2" } } } @@ -4162,13 +4162,13 @@ "integrity": "sha512-D06ivJkYxyRrcEe0bTpNnBQNgP9d3xog+qZlLbui8EsMr/DouQpf5o9FzJnWYHEYE0YsFHllUv2R1dkgYZXHcA==", "dev": true, "requires": { - "accepts": "~1.3.4", + "accepts": "1.3.5", "base64id": "1.0.0", "cookie": "0.3.1", - "debug": "~3.1.0", - "engine.io-parser": "~2.1.0", - "uws": "~9.14.0", - "ws": "~3.3.1" + "debug": "3.1.0", + "engine.io-parser": "2.1.2", + "uws": "9.14.0", + "ws": "3.3.3" }, "dependencies": { "accepts": { @@ -4177,7 +4177,7 @@ "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", "dev": true, "requires": { - "mime-types": "~2.1.18", + "mime-types": "2.1.20", "negotiator": "0.6.1" } }, @@ -4212,14 +4212,14 @@ "requires": { "component-emitter": "1.2.1", "component-inherit": "0.0.3", - "debug": "~3.1.0", - "engine.io-parser": "~2.1.1", + "debug": "3.1.0", + "engine.io-parser": "2.1.2", "has-cors": "1.1.0", "indexof": "0.0.1", "parseqs": "0.0.5", "parseuri": "0.0.5", - "ws": "~3.3.1", - "xmlhttprequest-ssl": "~1.5.4", + "ws": "3.3.3", + "xmlhttprequest-ssl": "1.5.5", "yeast": "0.1.2" }, "dependencies": { @@ -4241,10 +4241,10 @@ "dev": true, "requires": { "after": "0.8.2", - "arraybuffer.slice": "~0.0.7", + "arraybuffer.slice": "0.0.7", "base64-arraybuffer": "0.1.5", "blob": "0.0.4", - "has-binary2": "~1.0.2" + "has-binary2": "1.0.3" } }, "ent": { @@ -4267,7 +4267,7 @@ "dev": true, "optional": true, "requires": { - "prr": "~1.0.1" + "prr": "1.0.1" } }, "error-ex": { @@ -4276,7 +4276,7 @@ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, "requires": { - "is-arrayish": "^0.2.1" + "is-arrayish": "0.2.1" } }, "errorhandler": { @@ -4285,8 +4285,8 @@ "integrity": "sha1-t7cO2PNZ6duICS8tIMD4MUIK2D8=", "dev": true, "requires": { - "accepts": "~1.3.0", - "escape-html": "~1.0.3" + "accepts": "1.3.5", + "escape-html": "1.0.3" }, "dependencies": { "accepts": { @@ -4295,7 +4295,7 @@ "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", "dev": true, "requires": { - "mime-types": "~2.1.18", + "mime-types": "2.1.20", "negotiator": "0.6.1" } }, @@ -4313,11 +4313,11 @@ "integrity": "sha1-nbvdJ8aFbwABQhyhh4LXhr+KYWU=", "dev": true, "requires": { - "es-to-primitive": "^1.1.1", - "function-bind": "^1.1.1", - "has": "^1.0.1", - "is-callable": "^1.1.3", - "is-regex": "^1.0.4" + "es-to-primitive": "1.2.0", + "function-bind": "1.1.1", + "has": "1.0.3", + "is-callable": "1.1.4", + "is-regex": "1.0.4" } }, "es-to-primitive": { @@ -4326,9 +4326,9 @@ "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", "dev": true, "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" + "is-callable": "1.1.4", + "is-date-object": "1.0.1", + "is-symbol": "1.0.2" } }, "es6-promise": { @@ -4343,7 +4343,7 @@ "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", "dev": true, "requires": { - "es6-promise": "^4.0.3" + "es6-promise": "4.2.5" }, "dependencies": { "es6-promise": { @@ -4372,11 +4372,11 @@ "integrity": "sha512-IeMV45ReixHS53K/OmfKAIztN/igDHzTJUhZM3k1jMhIZWjk45SMwAtBsEXiJp3vSPmTcu6CXn7mDvFHRN66fw==", "dev": true, "requires": { - "esprima": "^3.1.3", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" + "esprima": "3.1.3", + "estraverse": "4.2.0", + "esutils": "2.0.2", + "optionator": "0.8.2", + "source-map": "0.6.1" }, "dependencies": { "esprima": { @@ -4400,44 +4400,44 @@ "integrity": "sha512-hgrDtGWz368b7Wqf+v1Z69O3ZebNR0+GA7PtDdbmuz4rInFVUV9uw7whjZEiWyLzCjVb5Rs5WRN1TAS6eo7AYA==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "ajv": "^6.5.3", - "chalk": "^2.1.0", - "cross-spawn": "^6.0.5", - "debug": "^4.0.1", - "doctrine": "^2.1.0", - "eslint-scope": "^4.0.0", - "eslint-utils": "^1.3.1", - "eslint-visitor-keys": "^1.0.0", - "espree": "^4.0.0", - "esquery": "^1.0.1", - "esutils": "^2.0.2", - "file-entry-cache": "^2.0.0", - "functional-red-black-tree": "^1.0.1", - "glob": "^7.1.2", - "globals": "^11.7.0", - "ignore": "^4.0.6", - "imurmurhash": "^0.1.4", - "inquirer": "^6.1.0", - "is-resolvable": "^1.1.0", - "js-yaml": "^3.12.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.3.0", - "lodash": "^4.17.5", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", - "natural-compare": "^1.4.0", - "optionator": "^0.8.2", - "path-is-inside": "^1.0.2", - "pluralize": "^7.0.0", - "progress": "^2.0.0", - "regexpp": "^2.0.0", - "require-uncached": "^1.0.3", - "semver": "^5.5.1", - "strip-ansi": "^4.0.0", - "strip-json-comments": "^2.0.1", - "table": "^4.0.3", - "text-table": "^0.2.0" + "@babel/code-frame": "7.0.0", + "ajv": "6.5.4", + "chalk": "2.4.1", + "cross-spawn": "6.0.5", + "debug": "4.0.1", + "doctrine": "2.1.0", + "eslint-scope": "4.0.0", + "eslint-utils": "1.3.1", + "eslint-visitor-keys": "1.0.0", + "espree": "4.0.0", + "esquery": "1.0.1", + "esutils": "2.0.2", + "file-entry-cache": "2.0.0", + "functional-red-black-tree": "1.0.1", + "glob": "7.1.3", + "globals": "11.8.0", + "ignore": "4.0.6", + "imurmurhash": "0.1.4", + "inquirer": "6.2.0", + "is-resolvable": "1.1.0", + "js-yaml": "3.12.0", + "json-stable-stringify-without-jsonify": "1.0.1", + "levn": "0.3.0", + "lodash": "4.17.11", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "natural-compare": "1.4.0", + "optionator": "0.8.2", + "path-is-inside": "1.0.2", + "pluralize": "7.0.0", + "progress": "2.0.0", + "regexpp": "2.0.0", + "require-uncached": "1.0.3", + "semver": "5.5.1", + "strip-ansi": "4.0.0", + "strip-json-comments": "2.0.1", + "table": "4.0.3", + "text-table": "0.2.0" }, "dependencies": { "ansi-regex": { @@ -4452,7 +4452,7 @@ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { - "color-convert": "^1.9.0" + "color-convert": "1.9.3" } }, "chalk": { @@ -4461,9 +4461,9 @@ "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.5.0" } }, "debug": { @@ -4472,7 +4472,7 @@ "integrity": "sha512-K23FHJ/Mt404FSlp6gSZCevIbTMLX0j3fmHhUEhQ3Wq0FMODW3+cUSoLdy1Gx4polAf4t/lphhmHH35BB8cLYw==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.1" } }, "esprima": { @@ -4493,8 +4493,8 @@ "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", "dev": true, "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "argparse": "1.0.10", + "esprima": "4.0.1" } }, "ms": { @@ -4515,7 +4515,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "3.0.0" } }, "supports-color": { @@ -4524,7 +4524,7 @@ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "3.0.0" } } } @@ -4535,8 +4535,8 @@ "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==", "dev": true, "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" + "esrecurse": "4.2.1", + "estraverse": "4.2.0" } }, "eslint-utils": { @@ -4557,8 +4557,8 @@ "integrity": "sha512-kapdTCt1bjmspxStVKX6huolXVV5ZfyZguY1lcfhVVZstce3bqxH9mcLzNn3/mlgW6wQ732+0fuG9v7h0ZQoKg==", "dev": true, "requires": { - "acorn": "^5.6.0", - "acorn-jsx": "^4.1.1" + "acorn": "5.7.3", + "acorn-jsx": "4.1.1" } }, "esprima": { @@ -4573,7 +4573,7 @@ "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", "dev": true, "requires": { - "estraverse": "^4.0.0" + "estraverse": "4.2.0" } }, "esrecurse": { @@ -4582,7 +4582,7 @@ "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", "dev": true, "requires": { - "estraverse": "^4.1.0" + "estraverse": "4.2.0" } }, "estemplate": { @@ -4591,8 +4591,8 @@ "integrity": "sha1-FxSp1GGQc4rJWLyv1J4CnNpWo54=", "dev": true, "requires": { - "esprima": "^2.7.2", - "estraverse": "^4.1.1" + "esprima": "2.7.3", + "estraverse": "4.2.0" } }, "estraverse": { @@ -4619,14 +4619,14 @@ "integrity": "sha512-dGXNg4F/FgVzlApjzItL+7naHutA3fDqbV/zAZqDDlXTjiMnQmZKu+prImWKszeBM5UQeGvAl3u1wBiKeDh61g==", "dev": true, "requires": { - "duplexer": "^0.1.1", - "flatmap-stream": "^0.1.0", - "from": "^0.1.7", + "duplexer": "0.1.1", + "flatmap-stream": "0.1.0", + "from": "0.1.7", "map-stream": "0.0.7", - "pause-stream": "^0.0.11", - "split": "^1.0.1", - "stream-combiner": "^0.2.2", - "through": "^2.3.8" + "pause-stream": "0.0.11", + "split": "1.0.1", + "stream-combiner": "0.2.2", + "through": "2.3.8" } }, "eventemitter3": { @@ -4642,11 +4642,11 @@ "dev": true, "optional": true, "requires": { - "execa": "^0.7.0", - "p-finally": "^1.0.0", - "pify": "^3.0.0", - "rimraf": "^2.5.4", - "tempfile": "^2.0.0" + "execa": "0.7.0", + "p-finally": "1.0.0", + "pify": "3.0.0", + "rimraf": "2.6.2", + "tempfile": "2.0.0" }, "dependencies": { "pify": { @@ -4665,8 +4665,8 @@ "dev": true, "optional": true, "requires": { - "async-each-series": "^1.1.0", - "object-assign": "^4.1.0" + "async-each-series": "1.1.0", + "object-assign": "4.1.1" } }, "execa": { @@ -4676,13 +4676,13 @@ "dev": true, "optional": true, "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" }, "dependencies": { "cross-spawn": { @@ -4692,9 +4692,9 @@ "dev": true, "optional": true, "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "lru-cache": "4.1.3", + "shebang-command": "1.2.0", + "which": "1.3.1" } }, "lru-cache": { @@ -4704,8 +4704,8 @@ "dev": true, "optional": true, "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" + "pseudomap": "1.0.2", + "yallist": "2.1.2" } } } @@ -4717,7 +4717,7 @@ "dev": true, "optional": true, "requires": { - "meow": "^3.1.0" + "meow": "3.7.0" } }, "expand-braces": { @@ -4726,9 +4726,9 @@ "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=", "dev": true, "requires": { - "array-slice": "^0.2.3", - "array-unique": "^0.2.1", - "braces": "^0.1.2" + "array-slice": "0.2.3", + "array-unique": "0.2.1", + "braces": "0.1.5" }, "dependencies": { "array-slice": { @@ -4749,7 +4749,7 @@ "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=", "dev": true, "requires": { - "expand-range": "^0.1.0" + "expand-range": "0.1.1" } }, "expand-range": { @@ -4758,8 +4758,8 @@ "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=", "dev": true, "requires": { - "is-number": "^0.1.1", - "repeat-string": "^0.2.2" + "is-number": "0.1.1", + "repeat-string": "0.2.2" } }, "is-number": { @@ -4782,13 +4782,13 @@ "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", "dev": true, "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" }, "dependencies": { "define-property": { @@ -4797,7 +4797,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "is-descriptor": "0.1.6" } }, "extend-shallow": { @@ -4806,7 +4806,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } } } @@ -4817,7 +4817,7 @@ "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", "dev": true, "requires": { - "fill-range": "^2.1.0" + "fill-range": "2.2.4" }, "dependencies": { "fill-range": { @@ -4826,11 +4826,11 @@ "integrity": "sha1-6x53OrsFbc2N8r/favWbizqTZWU=", "dev": true, "requires": { - "is-number": "^2.1.0", - "isobject": "^2.0.0", - "randomatic": "^3.0.0", - "repeat-element": "^1.1.2", - "repeat-string": "^1.5.2" + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "3.1.0", + "repeat-element": "1.1.3", + "repeat-string": "1.6.1" } }, "is-number": { @@ -4839,7 +4839,7 @@ "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", "dev": true, "requires": { - "kind-of": "^3.0.2" + "kind-of": "3.2.2" } }, "isarray": { @@ -4863,7 +4863,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -4874,7 +4874,7 @@ "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", "dev": true, "requires": { - "homedir-polyfill": "^1.0.1" + "homedir-polyfill": "1.0.1" } }, "express-session": { @@ -4886,11 +4886,11 @@ "cookie": "0.1.3", "cookie-signature": "1.0.6", "crc": "3.3.0", - "debug": "~2.2.0", - "depd": "~1.0.1", - "on-headers": "~1.0.0", - "parseurl": "~1.3.0", - "uid-safe": "~2.0.0", + "debug": "2.2.0", + "depd": "1.0.1", + "on-headers": "1.0.1", + "parseurl": "1.3.2", + "uid-safe": "2.0.0", "utils-merge": "1.0.0" }, "dependencies": { @@ -4932,8 +4932,8 @@ "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", "dev": true, "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" }, "dependencies": { "is-extendable": { @@ -4942,7 +4942,7 @@ "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", "dev": true, "requires": { - "is-plain-object": "^2.0.4" + "is-plain-object": "2.0.4" } } } @@ -4953,9 +4953,9 @@ "integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==", "dev": true, "requires": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" + "chardet": "0.7.0", + "iconv-lite": "0.4.24", + "tmp": "0.0.33" }, "dependencies": { "iconv-lite": { @@ -4964,7 +4964,7 @@ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, "requires": { - "safer-buffer": ">= 2.1.2 < 3" + "safer-buffer": "2.1.2" } } } @@ -4975,14 +4975,14 @@ "integrity": "sha1-rQD+TcYSqSMuhxhxHcXLWrAoVUM=", "dev": true, "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" }, "dependencies": { "define-property": { @@ -4991,7 +4991,7 @@ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "^1.0.0" + "is-descriptor": "1.0.2" } }, "extend-shallow": { @@ -5000,7 +5000,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } }, "is-accessor-descriptor": { @@ -5009,7 +5009,7 @@ "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", "dev": true, "requires": { - "kind-of": "^6.0.0" + "kind-of": "6.0.2" } }, "is-data-descriptor": { @@ -5018,7 +5018,7 @@ "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", "dev": true, "requires": { - "kind-of": "^6.0.0" + "kind-of": "6.0.2" } }, "is-descriptor": { @@ -5027,9 +5027,9 @@ "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", "dev": true, "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" } } } @@ -5052,7 +5052,7 @@ "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", "dev": true, "requires": { - "pend": "~1.2.0" + "pend": "1.2.0" } }, "yauzl": { @@ -5061,7 +5061,7 @@ "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", "dev": true, "requires": { - "fd-slicer": "~1.0.1" + "fd-slicer": "1.0.1" } } } @@ -5078,9 +5078,9 @@ "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", "dev": true, "requires": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "time-stamp": "^1.0.0" + "ansi-gray": "0.1.1", + "color-support": "1.1.3", + "time-stamp": "1.1.0" } }, "fast-deep-equal": { @@ -5107,7 +5107,7 @@ "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", "dev": true, "requires": { - "websocket-driver": ">=0.5.1" + "websocket-driver": "0.7.0" } }, "fd-slicer": { @@ -5116,7 +5116,7 @@ "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", "dev": true, "requires": { - "pend": "~1.2.0" + "pend": "1.2.0" } }, "figures": { @@ -5125,7 +5125,7 @@ "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", "dev": true, "requires": { - "escape-string-regexp": "^1.0.5" + "escape-string-regexp": "1.0.5" } }, "file-entry-cache": { @@ -5134,8 +5134,8 @@ "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", "dev": true, "requires": { - "flat-cache": "^1.2.1", - "object-assign": "^4.0.1" + "flat-cache": "1.3.0", + "object-assign": "4.1.1" } }, "file-type": { @@ -5169,9 +5169,9 @@ "integrity": "sha1-qfL/0RxQO+0wABUCknI3jx8TZaU=", "dev": true, "requires": { - "filename-reserved-regex": "^1.0.0", - "strip-outer": "^1.0.0", - "trim-repeated": "^1.0.0" + "filename-reserved-regex": "1.0.0", + "strip-outer": "1.0.1", + "trim-repeated": "1.0.0" } }, "fill-range": { @@ -5180,10 +5180,10 @@ "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", "dev": true, "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" }, "dependencies": { "extend-shallow": { @@ -5192,7 +5192,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } } } @@ -5203,10 +5203,10 @@ "integrity": "sha1-llpS2ejQXSuFdUhUH7ibU6JJfZs=", "dev": true, "requires": { - "debug": "~2.2.0", + "debug": "2.2.0", "escape-html": "1.0.2", - "on-finished": "~2.3.0", - "unpipe": "~1.0.0" + "on-finished": "2.3.0", + "unpipe": "1.0.0" }, "dependencies": { "debug": { @@ -5244,8 +5244,8 @@ "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", "dev": true, "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" } }, "find-versions": { @@ -5255,10 +5255,10 @@ "dev": true, "optional": true, "requires": { - "array-uniq": "^1.0.0", - "get-stdin": "^4.0.1", - "meow": "^3.5.0", - "semver-regex": "^1.0.0" + "array-uniq": "1.0.3", + "get-stdin": "4.0.1", + "meow": "3.7.0", + "semver-regex": "1.0.0" } }, "findup-sync": { @@ -5267,10 +5267,10 @@ "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", "dev": true, "requires": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" + "detect-file": "1.0.0", + "is-glob": "3.1.0", + "micromatch": "3.1.10", + "resolve-dir": "1.0.1" } }, "fined": { @@ -5279,11 +5279,11 @@ "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", "dev": true, "requires": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^2.0.3", - "object.defaults": "^1.1.0", - "object.pick": "^1.2.0", - "parse-filepath": "^1.0.1" + "expand-tilde": "2.0.2", + "is-plain-object": "2.0.4", + "object.defaults": "1.1.0", + "object.pick": "1.3.0", + "parse-filepath": "1.0.2" } }, "first-chunk-stream": { @@ -5304,10 +5304,10 @@ "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", "dev": true, "requires": { - "circular-json": "^0.3.1", - "del": "^2.0.2", - "graceful-fs": "^4.1.2", - "write": "^0.2.1" + "circular-json": "0.3.3", + "del": "2.2.2", + "graceful-fs": "4.1.11", + "write": "0.2.1" }, "dependencies": { "graceful-fs": { @@ -5341,7 +5341,7 @@ "integrity": "sha512-sy1mXPmv7kLAMKW/8XofG7o9T+6gAjzdZK4AJF6ryqQYUa/hnzgiypoeUecZ53x7XiqKNEpNqLtS97MshW2nxg==", "dev": true, "requires": { - "debug": "=3.1.0" + "debug": "3.1.0" }, "dependencies": { "debug": { @@ -5372,7 +5372,7 @@ "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", "dev": true, "requires": { - "for-in": "^1.0.1" + "for-in": "1.0.2" } }, "forever-agent": { @@ -5387,9 +5387,9 @@ "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", "dev": true, "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.5", - "mime-types": "^2.1.12" + "asynckit": "0.4.0", + "combined-stream": "1.0.7", + "mime-types": "2.1.20" } }, "fragment-cache": { @@ -5398,7 +5398,7 @@ "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", "dev": true, "requires": { - "map-cache": "^0.2.2" + "map-cache": "0.2.2" } }, "fresh": { @@ -5425,9 +5425,9 @@ "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "klaw": "^1.0.0" + "graceful-fs": "4.1.11", + "jsonfile": "2.4.0", + "klaw": "1.3.1" }, "dependencies": { "graceful-fs": { @@ -5444,7 +5444,7 @@ "integrity": "sha1-gAI4I5gfn//+AWCei+Zo9prknnA=", "dev": true, "requires": { - "graceful-fs": "^4.1.2" + "graceful-fs": "4.1.11" }, "dependencies": { "graceful-fs": { @@ -5468,8 +5468,8 @@ "dev": true, "optional": true, "requires": { - "nan": "^2.9.2", - "node-pre-gyp": "^0.10.0" + "nan": "2.11.1", + "node-pre-gyp": "0.10.0" }, "dependencies": { "abbrev": { @@ -5495,8 +5495,8 @@ "dev": true, "optional": true, "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" + "delegates": "1.0.0", + "readable-stream": "2.3.6" } }, "balanced-match": { @@ -5509,7 +5509,7 @@ "bundled": true, "dev": true, "requires": { - "balanced-match": "^1.0.0", + "balanced-match": "1.0.0", "concat-map": "0.0.1" } }, @@ -5573,7 +5573,7 @@ "dev": true, "optional": true, "requires": { - "minipass": "^2.2.1" + "minipass": "2.2.4" } }, "fs.realpath": { @@ -5588,14 +5588,14 @@ "dev": true, "optional": true, "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" } }, "glob": { @@ -5604,12 +5604,12 @@ "dev": true, "optional": true, "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" } }, "has-unicode": { @@ -5624,7 +5624,7 @@ "dev": true, "optional": true, "requires": { - "safer-buffer": "^2.1.0" + "safer-buffer": "2.1.2" } }, "ignore-walk": { @@ -5633,7 +5633,7 @@ "dev": true, "optional": true, "requires": { - "minimatch": "^3.0.4" + "minimatch": "3.0.4" } }, "inflight": { @@ -5642,8 +5642,8 @@ "dev": true, "optional": true, "requires": { - "once": "^1.3.0", - "wrappy": "1" + "once": "1.4.0", + "wrappy": "1.0.2" } }, "inherits": { @@ -5662,7 +5662,7 @@ "bundled": true, "dev": true, "requires": { - "number-is-nan": "^1.0.0" + "number-is-nan": "1.0.1" } }, "isarray": { @@ -5676,7 +5676,7 @@ "bundled": true, "dev": true, "requires": { - "brace-expansion": "^1.1.7" + "brace-expansion": "1.1.11" } }, "minimist": { @@ -5689,8 +5689,8 @@ "bundled": true, "dev": true, "requires": { - "safe-buffer": "^5.1.1", - "yallist": "^3.0.0" + "safe-buffer": "5.1.1", + "yallist": "3.0.2" } }, "minizlib": { @@ -5699,7 +5699,7 @@ "dev": true, "optional": true, "requires": { - "minipass": "^2.2.1" + "minipass": "2.2.4" } }, "mkdirp": { @@ -5722,9 +5722,9 @@ "dev": true, "optional": true, "requires": { - "debug": "^2.1.2", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" + "debug": "2.6.9", + "iconv-lite": "0.4.21", + "sax": "1.2.4" } }, "node-pre-gyp": { @@ -5733,16 +5733,16 @@ "dev": true, "optional": true, "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.0", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.1.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" + "detect-libc": "1.0.3", + "mkdirp": "0.5.1", + "needle": "2.2.0", + "nopt": "4.0.1", + "npm-packlist": "1.1.10", + "npmlog": "4.1.2", + "rc": "1.2.7", + "rimraf": "2.6.2", + "semver": "5.5.0", + "tar": "4.4.1" } }, "nopt": { @@ -5751,8 +5751,8 @@ "dev": true, "optional": true, "requires": { - "abbrev": "1", - "osenv": "^0.1.4" + "abbrev": "1.1.1", + "osenv": "0.1.5" } }, "npm-bundled": { @@ -5767,8 +5767,8 @@ "dev": true, "optional": true, "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" + "ignore-walk": "3.0.1", + "npm-bundled": "1.0.3" } }, "npmlog": { @@ -5777,10 +5777,10 @@ "dev": true, "optional": true, "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" } }, "number-is-nan": { @@ -5799,7 +5799,7 @@ "bundled": true, "dev": true, "requires": { - "wrappy": "1" + "wrappy": "1.0.2" } }, "os-homedir": { @@ -5820,8 +5820,8 @@ "dev": true, "optional": true, "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" } }, "path-is-absolute": { @@ -5842,10 +5842,10 @@ "dev": true, "optional": true, "requires": { - "deep-extend": "^0.5.1", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" + "deep-extend": "0.5.1", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" }, "dependencies": { "minimist": { @@ -5862,13 +5862,13 @@ "dev": true, "optional": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "rimraf": { @@ -5877,7 +5877,7 @@ "dev": true, "optional": true, "requires": { - "glob": "^7.0.5" + "glob": "7.1.2" } }, "safe-buffer": { @@ -5920,9 +5920,9 @@ "bundled": true, "dev": true, "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" } }, "string_decoder": { @@ -5931,7 +5931,7 @@ "dev": true, "optional": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.1" } }, "strip-ansi": { @@ -5939,7 +5939,7 @@ "bundled": true, "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "2.1.1" } }, "strip-json-comments": { @@ -5954,13 +5954,13 @@ "dev": true, "optional": true, "requires": { - "chownr": "^1.0.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.2.4", - "minizlib": "^1.1.0", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.1", - "yallist": "^3.0.2" + "chownr": "1.0.1", + "fs-minipass": "1.2.5", + "minipass": "2.2.4", + "minizlib": "1.1.0", + "mkdirp": "0.5.1", + "safe-buffer": "5.1.1", + "yallist": "3.0.2" } }, "util-deprecate": { @@ -5975,7 +5975,7 @@ "dev": true, "optional": true, "requires": { - "string-width": "^1.0.2" + "string-width": "1.0.2" } }, "wrappy": { @@ -5997,7 +5997,7 @@ "dev": true, "optional": true, "requires": { - "readable-stream": "1.1.x", + "readable-stream": "1.1.14", "xregexp": "2.0.0" } }, @@ -6019,7 +6019,7 @@ "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", "dev": true, "requires": { - "globule": "~0.1.0" + "globule": "0.1.0" } }, "generate-function": { @@ -6029,7 +6029,7 @@ "dev": true, "optional": true, "requires": { - "is-property": "^1.0.2" + "is-property": "1.0.2" } }, "generate-object-property": { @@ -6039,7 +6039,7 @@ "dev": true, "optional": true, "requires": { - "is-property": "^1.0.0" + "is-property": "1.0.2" } }, "get-proxy": { @@ -6048,7 +6048,7 @@ "integrity": "sha1-iUhUSRvFkbDxR9euVw9cZ4tyVus=", "dev": true, "requires": { - "rc": "^1.1.2" + "rc": "1.2.8" } }, "get-stdin": { @@ -6071,12 +6071,12 @@ "dev": true, "optional": true, "requires": { - "data-uri-to-buffer": "1", - "debug": "2", - "extend": "3", - "file-uri-to-path": "1", - "ftp": "~0.3.10", - "readable-stream": "2" + "data-uri-to-buffer": "1.2.0", + "debug": "2.6.9", + "extend": "3.0.2", + "file-uri-to-path": "1.0.0", + "ftp": "0.3.10", + "readable-stream": "2.3.6" }, "dependencies": { "isarray": { @@ -6093,13 +6093,13 @@ "dev": true, "optional": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -6109,7 +6109,7 @@ "dev": true, "optional": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } } } @@ -6126,7 +6126,7 @@ "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", "dev": true, "requires": { - "assert-plus": "^1.0.0" + "assert-plus": "1.0.0" }, "dependencies": { "assert-plus": { @@ -6144,9 +6144,9 @@ "dev": true, "optional": true, "requires": { - "bin-build": "^2.0.0", - "bin-wrapper": "^3.0.0", - "logalot": "^2.0.0" + "bin-build": "2.2.0", + "bin-wrapper": "3.0.2", + "logalot": "2.1.0" } }, "glob": { @@ -6155,12 +6155,12 @@ "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "dev": true, "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" } }, "glob-base": { @@ -6169,8 +6169,8 @@ "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", "dev": true, "requires": { - "glob-parent": "^2.0.0", - "is-glob": "^2.0.0" + "glob-parent": "2.0.0", + "is-glob": "2.0.1" }, "dependencies": { "glob-parent": { @@ -6179,7 +6179,7 @@ "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", "dev": true, "requires": { - "is-glob": "^2.0.0" + "is-glob": "2.0.1" } }, "is-extglob": { @@ -6194,7 +6194,7 @@ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "^1.0.0" + "is-extglob": "1.0.0" } } } @@ -6205,8 +6205,8 @@ "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", "dev": true, "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" + "is-glob": "3.1.0", + "path-dirname": "1.0.2" } }, "glob-stream": { @@ -6215,12 +6215,12 @@ "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", "dev": true, "requires": { - "glob": "^4.3.1", - "glob2base": "^0.0.12", - "minimatch": "^2.0.1", - "ordered-read-streams": "^0.1.0", - "through2": "^0.6.1", - "unique-stream": "^1.0.0" + "glob": "4.5.3", + "glob2base": "0.0.12", + "minimatch": "2.0.10", + "ordered-read-streams": "0.1.0", + "through2": "0.6.5", + "unique-stream": "1.0.0" }, "dependencies": { "glob": { @@ -6229,10 +6229,10 @@ "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", "dev": true, "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^2.0.1", - "once": "^1.3.0" + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "2.0.10", + "once": "1.4.0" } }, "minimatch": { @@ -6241,7 +6241,7 @@ "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", "dev": true, "requires": { - "brace-expansion": "^1.0.0" + "brace-expansion": "1.1.11" } }, "readable-stream": { @@ -6250,10 +6250,10 @@ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", + "core-util-is": "1.0.2", + "inherits": "2.0.3", "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "string_decoder": "0.10.31" } }, "through2": { @@ -6262,8 +6262,8 @@ "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", "dev": true, "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" + "readable-stream": "1.0.34", + "xtend": "4.0.1" } } } @@ -6274,7 +6274,7 @@ "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", "dev": true, "requires": { - "gaze": "^0.5.1" + "gaze": "0.5.2" } }, "glob2base": { @@ -6283,7 +6283,7 @@ "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", "dev": true, "requires": { - "find-index": "^0.1.1" + "find-index": "0.1.1" } }, "global-modules": { @@ -6292,9 +6292,9 @@ "integrity": "sha1-bXcPDrUjrHgWTXK15xqIdyZcw+o=", "dev": true, "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" + "global-prefix": "1.0.2", + "is-windows": "1.0.2", + "resolve-dir": "1.0.1" } }, "global-prefix": { @@ -6303,11 +6303,11 @@ "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", "dev": true, "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" + "expand-tilde": "2.0.2", + "homedir-polyfill": "1.0.1", + "ini": "1.3.5", + "is-windows": "1.0.2", + "which": "1.3.1" } }, "globals": { @@ -6322,12 +6322,12 @@ "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", "dev": true, "requires": { - "array-union": "^1.0.1", - "arrify": "^1.0.0", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" + "array-union": "1.0.2", + "arrify": "1.0.1", + "glob": "7.1.3", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" } }, "globule": { @@ -6336,9 +6336,9 @@ "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", "dev": true, "requires": { - "glob": "~3.1.21", - "lodash": "~1.0.1", - "minimatch": "~0.2.11" + "glob": "3.1.21", + "lodash": "1.0.2", + "minimatch": "0.2.14" }, "dependencies": { "glob": { @@ -6347,9 +6347,9 @@ "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", "dev": true, "requires": { - "graceful-fs": "~1.2.0", - "inherits": "1", - "minimatch": "~0.2.11" + "graceful-fs": "1.2.3", + "inherits": "1.0.2", + "minimatch": "0.2.14" } }, "graceful-fs": { @@ -6376,8 +6376,8 @@ "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", "dev": true, "requires": { - "lru-cache": "2", - "sigmund": "~1.0.0" + "lru-cache": "2.7.3", + "sigmund": "1.0.1" } } } @@ -6388,7 +6388,7 @@ "integrity": "sha1-3PdY5EeJzD89MsHzVio2duajSBA=", "dev": true, "requires": { - "sparkles": "^1.0.0" + "sparkles": "1.0.1" } }, "good-listener": { @@ -6396,7 +6396,7 @@ "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=", "requires": { - "delegate": "^3.1.2" + "delegate": "3.2.0" } }, "got": { @@ -6405,21 +6405,21 @@ "integrity": "sha1-X4FjWmHkplifGAVp6k44FoClHzU=", "dev": true, "requires": { - "create-error-class": "^3.0.1", - "duplexer2": "^0.1.4", - "is-redirect": "^1.0.0", - "is-retry-allowed": "^1.0.0", - "is-stream": "^1.0.0", - "lowercase-keys": "^1.0.0", - "node-status-codes": "^1.0.0", - "object-assign": "^4.0.1", - "parse-json": "^2.1.0", - "pinkie-promise": "^2.0.0", - "read-all-stream": "^3.0.0", - "readable-stream": "^2.0.5", - "timed-out": "^3.0.0", - "unzip-response": "^1.0.2", - "url-parse-lax": "^1.0.0" + "create-error-class": "3.0.2", + "duplexer2": "0.1.4", + "is-redirect": "1.0.0", + "is-retry-allowed": "1.1.0", + "is-stream": "1.1.0", + "lowercase-keys": "1.0.1", + "node-status-codes": "1.0.0", + "object-assign": "4.1.1", + "parse-json": "2.2.0", + "pinkie-promise": "2.0.1", + "read-all-stream": "3.1.0", + "readable-stream": "2.3.6", + "timed-out": "3.1.3", + "unzip-response": "1.0.2", + "url-parse-lax": "1.0.0" }, "dependencies": { "duplexer2": { @@ -6428,7 +6428,7 @@ "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", "dev": true, "requires": { - "readable-stream": "^2.0.2" + "readable-stream": "2.3.6" } }, "isarray": { @@ -6443,13 +6443,13 @@ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -6458,7 +6458,7 @@ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } } } @@ -6469,7 +6469,7 @@ "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", "dev": true, "requires": { - "natives": "^1.1.0" + "natives": "1.1.5" } }, "graceful-readlink": { @@ -6484,19 +6484,19 @@ "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", "dev": true, "requires": { - "archy": "^1.0.0", - "chalk": "^1.0.0", - "deprecated": "^0.0.1", - "gulp-util": "^3.0.0", - "interpret": "^1.0.0", - "liftoff": "^2.1.0", - "minimist": "^1.1.0", - "orchestrator": "^0.3.0", - "pretty-hrtime": "^1.0.0", - "semver": "^4.1.0", - "tildify": "^1.0.0", - "v8flags": "^2.0.2", - "vinyl-fs": "^0.3.0" + "archy": "1.0.0", + "chalk": "1.1.3", + "deprecated": "0.0.1", + "gulp-util": "3.0.8", + "interpret": "1.1.0", + "liftoff": "2.5.0", + "minimist": "1.2.0", + "orchestrator": "0.3.8", + "pretty-hrtime": "1.0.3", + "semver": "4.3.6", + "tildify": "1.2.0", + "v8flags": "2.1.1", + "vinyl-fs": "0.3.14" }, "dependencies": { "minimist": { @@ -6513,10 +6513,10 @@ "integrity": "sha512-GTC2PxAXWkp6u1fP+C5+kn5biQ0dKGhkOSSXvKAf3ykF0+R3tevmLm/zSIkc1+S7U1JwH3XTvuMwRL6LD+sEiw==", "dev": true, "requires": { - "plugin-error": "^1.0.1", - "replace-ext": "^1.0.0", - "through2": "^2.0.0", - "vinyl-sourcemaps-apply": "^0.2.0" + "plugin-error": "1.0.1", + "replace-ext": "1.0.0", + "through2": "2.0.3", + "vinyl-sourcemaps-apply": "0.2.1" }, "dependencies": { "replace-ext": { @@ -6545,9 +6545,9 @@ "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", "dev": true, "requires": { - "concat-with-sourcemaps": "^1.0.0", - "through2": "^2.0.0", - "vinyl": "^2.0.0" + "concat-with-sourcemaps": "1.1.0", + "through2": "2.0.3", + "vinyl": "2.2.0" }, "dependencies": { "clone": { @@ -6574,12 +6574,12 @@ "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", "dev": true, "requires": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" + "clone": "2.1.2", + "clone-buffer": "1.0.0", + "clone-stats": "1.0.0", + "cloneable-readable": "1.1.2", + "remove-trailing-separator": "1.1.0", + "replace-ext": "1.0.0" } } } @@ -6590,11 +6590,11 @@ "integrity": "sha1-8v3zBq6RFGg2jCKF8teC8T7dr04=", "dev": true, "requires": { - "connect": "^2.30.0", - "connect-livereload": "^0.5.4", - "event-stream": "^3.3.2", - "gulp-util": "^3.0.6", - "tiny-lr": "^0.2.1" + "connect": "2.30.2", + "connect-livereload": "0.5.4", + "event-stream": "3.3.6", + "gulp-util": "3.0.8", + "tiny-lr": "0.2.1" } }, "gulp-decompress": { @@ -6603,10 +6603,10 @@ "integrity": "sha1-jutlpeAV+O2FMsr+KEVJYGJvDcc=", "dev": true, "requires": { - "archive-type": "^3.0.0", - "decompress": "^3.0.0", - "gulp-util": "^3.0.1", - "readable-stream": "^2.0.2" + "archive-type": "3.2.0", + "decompress": "3.0.0", + "gulp-util": "3.0.8", + "readable-stream": "2.3.6" }, "dependencies": { "isarray": { @@ -6621,13 +6621,13 @@ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -6636,7 +6636,7 @@ "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } } } @@ -6647,9 +6647,9 @@ "integrity": "sha512-9GUqCqh85C7rP9120cpxXuZz2ayq3BZc85pCTuPJS03VQYxne0aWPIXWx6LSvsGPa3uRqtSO537vaugOh+5cXg==", "dev": true, "requires": { - "eslint": "^5.0.1", - "fancy-log": "^1.3.2", - "plugin-error": "^1.0.1" + "eslint": "5.6.1", + "fancy-log": "1.3.2", + "plugin-error": "1.0.1" } }, "gulp-imagemin": { @@ -6658,17 +6658,17 @@ "integrity": "sha1-XONH8dFwb+08yPF3fKkJSlg7ULc=", "dev": true, "requires": { - "chalk": "^2.1.0", - "fancy-log": "^1.3.2", - "imagemin": "^5.3.1", - "imagemin-gifsicle": "^5.2.0", - "imagemin-jpegtran": "^5.0.2", - "imagemin-optipng": "^5.2.1", - "imagemin-svgo": "^6.0.0", - "plugin-error": "^0.1.2", - "plur": "^2.1.2", - "pretty-bytes": "^4.0.2", - "through2-concurrent": "^1.1.1" + "chalk": "2.4.1", + "fancy-log": "1.3.2", + "imagemin": "5.3.1", + "imagemin-gifsicle": "5.2.0", + "imagemin-jpegtran": "5.0.2", + "imagemin-optipng": "5.2.1", + "imagemin-svgo": "6.0.0", + "plugin-error": "0.1.2", + "plur": "2.1.2", + "pretty-bytes": "4.0.2", + "through2-concurrent": "1.1.1" }, "dependencies": { "ansi-styles": { @@ -6677,7 +6677,7 @@ "integrity": "sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0=", "dev": true, "requires": { - "color-convert": "^1.9.0" + "color-convert": "1.9.3" } }, "arr-diff": { @@ -6686,8 +6686,8 @@ "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", "dev": true, "requires": { - "arr-flatten": "^1.0.1", - "array-slice": "^0.2.3" + "arr-flatten": "1.1.0", + "array-slice": "0.2.3" } }, "arr-union": { @@ -6708,9 +6708,9 @@ "integrity": "sha1-GMSasWoDe26wFSzIPjRxM4IVtm4=", "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.5.0" } }, "extend-shallow": { @@ -6719,7 +6719,7 @@ "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", "dev": true, "requires": { - "kind-of": "^1.1.0" + "kind-of": "1.1.0" } }, "has-flag": { @@ -6740,11 +6740,11 @@ "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", "dev": true, "requires": { - "ansi-cyan": "^0.1.1", - "ansi-red": "^0.1.1", - "arr-diff": "^1.0.1", - "arr-union": "^2.0.1", - "extend-shallow": "^1.1.2" + "ansi-cyan": "0.1.1", + "ansi-red": "0.1.1", + "arr-diff": "1.1.0", + "arr-union": "2.1.0", + "extend-shallow": "1.1.4" } }, "supports-color": { @@ -6753,7 +6753,7 @@ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "3.0.0" } } } @@ -6764,13 +6764,13 @@ "integrity": "sha1-gBT0ad38ZUTX3aUAmN7wNxu7T3g=", "dev": true, "requires": { - "accord": "^0.28.0", - "less": "2.6.x || ^2.7.1", - "object-assign": "^4.0.1", - "plugin-error": "^0.1.2", - "replace-ext": "^1.0.0", - "through2": "^2.0.0", - "vinyl-sourcemaps-apply": "^0.2.0" + "accord": "0.28.0", + "less": "2.7.3", + "object-assign": "4.1.1", + "plugin-error": "0.1.2", + "replace-ext": "1.0.0", + "through2": "2.0.3", + "vinyl-sourcemaps-apply": "0.2.1" }, "dependencies": { "arr-diff": { @@ -6779,8 +6779,8 @@ "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", "dev": true, "requires": { - "arr-flatten": "^1.0.1", - "array-slice": "^0.2.3" + "arr-flatten": "1.1.0", + "array-slice": "0.2.3" } }, "arr-union": { @@ -6801,7 +6801,7 @@ "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", "dev": true, "requires": { - "kind-of": "^1.1.0" + "kind-of": "1.1.0" } }, "kind-of": { @@ -6816,11 +6816,11 @@ "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", "dev": true, "requires": { - "ansi-cyan": "^0.1.1", - "ansi-red": "^0.1.1", - "arr-diff": "^1.0.1", - "arr-union": "^2.0.1", - "extend-shallow": "^1.1.2" + "ansi-cyan": "0.1.1", + "ansi-red": "0.1.1", + "arr-diff": "1.1.0", + "arr-union": "2.1.0", + "extend-shallow": "1.1.4" } }, "replace-ext": { @@ -6837,8 +6837,8 @@ "integrity": "sha1-J7Z6Ql6zh1ImNFq4lgTXN/Y1fCE=", "dev": true, "requires": { - "angular": "~1.3.1", - "angular-animate": "~1.3.1", + "angular": "1.3.20", + "angular-animate": "1.3.20", "canonical-path": "0.0.2", "extend": "1.3.0", "gulp-util": "3.0.0", @@ -6881,11 +6881,11 @@ "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=", "dev": true, "requires": { - "ansi-styles": "^1.1.0", - "escape-string-regexp": "^1.0.0", - "has-ansi": "^0.1.0", - "strip-ansi": "^0.3.0", - "supports-color": "^0.2.0" + "ansi-styles": "1.1.0", + "escape-string-regexp": "1.0.5", + "has-ansi": "0.1.0", + "strip-ansi": "0.3.0", + "supports-color": "0.2.0" } }, "clone": { @@ -6900,8 +6900,8 @@ "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", "dev": true, "requires": { - "get-stdin": "^4.0.1", - "meow": "^3.3.0" + "get-stdin": "4.0.1", + "meow": "3.7.0" } }, "extend": { @@ -6916,15 +6916,15 @@ "integrity": "sha1-b+7cR9aXKCO6zplH/F9GvYo0Zuc=", "dev": true, "requires": { - "chalk": "^0.5.0", - "dateformat": "^1.0.7-1.2.3", - "lodash": "^2.4.1", - "lodash._reinterpolate": "^2.4.1", - "lodash.template": "^2.4.1", - "minimist": "^0.2.0", - "multipipe": "^0.1.0", - "through2": "^0.5.0", - "vinyl": "^0.2.1" + "chalk": "0.5.1", + "dateformat": "1.0.12", + "lodash": "2.4.1", + "lodash._reinterpolate": "2.4.1", + "lodash.template": "2.4.1", + "minimist": "0.2.0", + "multipipe": "0.1.2", + "through2": "0.5.1", + "vinyl": "0.2.3" }, "dependencies": { "through2": { @@ -6933,8 +6933,8 @@ "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", "dev": true, "requires": { - "readable-stream": "~1.0.17", - "xtend": "~3.0.0" + "readable-stream": "1.0.34", + "xtend": "3.0.0" } } } @@ -6945,7 +6945,7 @@ "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=", "dev": true, "requires": { - "ansi-regex": "^0.2.0" + "ansi-regex": "0.2.1" } }, "lodash": { @@ -6966,8 +6966,8 @@ "integrity": "sha1-p+iIXwXmiFEUS24SqPNngCa8TFQ=", "dev": true, "requires": { - "lodash._objecttypes": "~2.4.1", - "lodash.keys": "~2.4.1" + "lodash._objecttypes": "2.4.1", + "lodash.keys": "2.4.1" } }, "lodash.escape": { @@ -6976,9 +6976,9 @@ "integrity": "sha1-LOEsXghNsKV92l5dHu659dF1o7Q=", "dev": true, "requires": { - "lodash._escapehtmlchar": "~2.4.1", - "lodash._reunescapedhtml": "~2.4.1", - "lodash.keys": "~2.4.1" + "lodash._escapehtmlchar": "2.4.1", + "lodash._reunescapedhtml": "2.4.1", + "lodash.keys": "2.4.1" } }, "lodash.keys": { @@ -6987,9 +6987,9 @@ "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", "dev": true, "requires": { - "lodash._isnative": "~2.4.1", - "lodash._shimkeys": "~2.4.1", - "lodash.isobject": "~2.4.1" + "lodash._isnative": "2.4.1", + "lodash._shimkeys": "2.4.1", + "lodash.isobject": "2.4.1" } }, "lodash.template": { @@ -6998,13 +6998,13 @@ "integrity": "sha1-nmEQB+32KRKal0qzxIuBez4c8g0=", "dev": true, "requires": { - "lodash._escapestringchar": "~2.4.1", - "lodash._reinterpolate": "~2.4.1", - "lodash.defaults": "~2.4.1", - "lodash.escape": "~2.4.1", - "lodash.keys": "~2.4.1", - "lodash.templatesettings": "~2.4.1", - "lodash.values": "~2.4.1" + "lodash._escapestringchar": "2.4.1", + "lodash._reinterpolate": "2.4.1", + "lodash.defaults": "2.4.1", + "lodash.escape": "2.4.1", + "lodash.keys": "2.4.1", + "lodash.templatesettings": "2.4.1", + "lodash.values": "2.4.1" } }, "lodash.templatesettings": { @@ -7013,8 +7013,8 @@ "integrity": "sha1-6nbHXRHrhtTb6JqDiTu4YZKaxpk=", "dev": true, "requires": { - "lodash._reinterpolate": "~2.4.1", - "lodash.escape": "~2.4.1" + "lodash._reinterpolate": "2.4.1", + "lodash.escape": "2.4.1" } }, "merge-stream": { @@ -7023,7 +7023,7 @@ "integrity": "sha1-5oIPet267gA/SMpKWMfFolPV4Fw=", "dev": true, "requires": { - "through2": "^0.5.1" + "through2": "0.5.1" }, "dependencies": { "through2": { @@ -7032,8 +7032,8 @@ "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", "dev": true, "requires": { - "readable-stream": "~1.0.17", - "xtend": "~3.0.0" + "readable-stream": "1.0.34", + "xtend": "3.0.0" } } } @@ -7050,10 +7050,10 @@ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", + "core-util-is": "1.0.2", + "inherits": "2.0.3", "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "string_decoder": "0.10.31" } }, "strip-ansi": { @@ -7062,7 +7062,7 @@ "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", "dev": true, "requires": { - "ansi-regex": "^0.2.1" + "ansi-regex": "0.2.1" } }, "supports-color": { @@ -7077,8 +7077,8 @@ "integrity": "sha1-90KzKJPovSYUbnieT9LMssB6cX4=", "dev": true, "requires": { - "readable-stream": ">=1.0.27-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" + "readable-stream": "1.0.34", + "xtend": "4.0.1" }, "dependencies": { "xtend": { @@ -7095,7 +7095,7 @@ "integrity": "sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI=", "dev": true, "requires": { - "clone-stats": "~0.0.1" + "clone-stats": "0.0.1" } }, "vinyl-fs": { @@ -7104,14 +7104,14 @@ "integrity": "sha1-LiXP5t9cgIGPl/9Be/XCGkHkpJs=", "dev": true, "requires": { - "glob-stream": "^3.1.5", - "glob-watcher": "^0.0.6", - "graceful-fs": "^3.0.0", - "lodash": "^2.4.1", - "mkdirp": "^0.5.0", - "strip-bom": "^1.0.0", - "through2": "^0.6.1", - "vinyl": "^0.4.0" + "glob-stream": "3.1.18", + "glob-watcher": "0.0.6", + "graceful-fs": "3.0.11", + "lodash": "2.4.1", + "mkdirp": "0.5.1", + "strip-bom": "1.0.0", + "through2": "0.6.1", + "vinyl": "0.4.6" }, "dependencies": { "vinyl": { @@ -7120,8 +7120,8 @@ "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", "dev": true, "requires": { - "clone": "^0.2.0", - "clone-stats": "^0.0.1" + "clone": "0.2.0", + "clone-stats": "0.0.1" } } } @@ -7140,10 +7140,10 @@ "integrity": "sha1-rAHu6JjXenrAgS+tTz1T0IaH1Bw=", "dev": true, "requires": { - "colors": "^1.1.2", + "colors": "1.3.2", "open": "0.0.5", - "plugin-log": "^0.1.0", - "through2": "^2.0.1" + "plugin-log": "0.1.0", + "through2": "2.0.3" } }, "gulp-postcss": { @@ -7152,10 +7152,10 @@ "integrity": "sha1-eKMuPIeqbNzsWuHJBeGW1HjoxdU=", "dev": true, "requires": { - "gulp-util": "^3.0.8", - "postcss": "^5.2.12", - "postcss-load-config": "^1.2.0", - "vinyl-sourcemaps-apply": "^0.2.1" + "gulp-util": "3.0.8", + "postcss": "5.2.18", + "postcss-load-config": "1.2.0", + "vinyl-sourcemaps-apply": "0.2.1" } }, "gulp-rename": { @@ -7170,7 +7170,7 @@ "integrity": "sha1-xnYqLx8N4KP8WVohWZ0/rI26Gso=", "dev": true, "requires": { - "through2": "^2.0.1" + "through2": "2.0.3" } }, "gulp-sourcemaps": { @@ -7179,11 +7179,11 @@ "integrity": "sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw=", "dev": true, "requires": { - "convert-source-map": "^1.1.1", - "graceful-fs": "^4.1.2", - "strip-bom": "^2.0.0", - "through2": "^2.0.0", - "vinyl": "^1.0.0" + "convert-source-map": "1.6.0", + "graceful-fs": "4.1.11", + "strip-bom": "2.0.0", + "through2": "2.0.3", + "vinyl": "1.2.0" }, "dependencies": { "graceful-fs": { @@ -7198,7 +7198,7 @@ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "dev": true, "requires": { - "is-utf8": "^0.2.0" + "is-utf8": "0.2.1" } }, "vinyl": { @@ -7207,8 +7207,8 @@ "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", "dev": true, "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", + "clone": "1.0.4", + "clone-stats": "0.0.1", "replace-ext": "0.0.1" } } @@ -7220,24 +7220,24 @@ "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", "dev": true, "requires": { - "array-differ": "^1.0.0", - "array-uniq": "^1.0.2", - "beeper": "^1.0.0", - "chalk": "^1.0.0", - "dateformat": "^2.0.0", - "fancy-log": "^1.1.0", - "gulplog": "^1.0.0", - "has-gulplog": "^0.1.0", - "lodash._reescape": "^3.0.0", - "lodash._reevaluate": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.template": "^3.0.0", - "minimist": "^1.1.0", - "multipipe": "^0.1.2", - "object-assign": "^3.0.0", + "array-differ": "1.0.0", + "array-uniq": "1.0.3", + "beeper": "1.1.1", + "chalk": "1.1.3", + "dateformat": "2.2.0", + "fancy-log": "1.3.2", + "gulplog": "1.0.0", + "has-gulplog": "0.1.0", + "lodash._reescape": "3.0.0", + "lodash._reevaluate": "3.0.0", + "lodash._reinterpolate": "3.0.0", + "lodash.template": "3.6.2", + "minimist": "1.2.0", + "multipipe": "0.1.2", + "object-assign": "3.0.0", "replace-ext": "0.0.1", - "through2": "^2.0.0", - "vinyl": "^0.5.0" + "through2": "2.0.3", + "vinyl": "0.5.3" }, "dependencies": { "minimist": { @@ -7260,16 +7260,16 @@ "integrity": "sha1-Fi/FY96fx3DpH5p845VVE6mhGMA=", "dev": true, "requires": { - "anymatch": "^1.3.0", - "chokidar": "^1.6.1", - "glob-parent": "^3.0.1", - "gulp-util": "^3.0.7", - "object-assign": "^4.1.0", - "path-is-absolute": "^1.0.1", - "readable-stream": "^2.2.2", - "slash": "^1.0.0", - "vinyl": "^1.2.0", - "vinyl-file": "^2.0.0" + "anymatch": "1.3.2", + "chokidar": "1.7.0", + "glob-parent": "3.1.0", + "gulp-util": "3.0.8", + "object-assign": "4.1.1", + "path-is-absolute": "1.0.1", + "readable-stream": "2.3.6", + "slash": "1.0.0", + "vinyl": "1.2.0", + "vinyl-file": "2.0.0" }, "dependencies": { "isarray": { @@ -7284,13 +7284,13 @@ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -7299,7 +7299,7 @@ "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } }, "vinyl": { @@ -7308,8 +7308,8 @@ "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", "dev": true, "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", + "clone": "1.0.4", + "clone-stats": "0.0.1", "replace-ext": "0.0.1" } } @@ -7321,16 +7321,16 @@ "integrity": "sha1-kPsLSieiZkM4Mv98YSLbXB7olMY=", "dev": true, "requires": { - "consolidate": "^0.14.1", - "es6-promise": "^3.1.2", - "fs-readfile-promise": "^2.0.1", - "gulp-util": "^3.0.3", - "js-yaml": "^3.2.6", - "lodash": "^4.11.1", - "node.extend": "^1.1.2", - "through2": "^2.0.1", - "tryit": "^1.0.1", - "vinyl-bufferstream": "^1.0.1" + "consolidate": "0.14.5", + "es6-promise": "3.3.1", + "fs-readfile-promise": "2.0.1", + "gulp-util": "3.0.8", + "js-yaml": "3.7.0", + "lodash": "4.17.11", + "node.extend": "1.1.6", + "through2": "2.0.3", + "tryit": "1.0.3", + "vinyl-bufferstream": "1.0.1" } }, "gulp-wrap-js": { @@ -7339,12 +7339,12 @@ "integrity": "sha1-3uYqpISqupVHqT0f9c0MPQvtwDE=", "dev": true, "requires": { - "escodegen": "^1.6.1", - "esprima": "^2.3.0", - "estemplate": "*", - "gulp-util": "~3.0.5", - "through2": "*", - "vinyl-sourcemaps-apply": "^0.1.4" + "escodegen": "1.11.0", + "esprima": "2.7.3", + "estemplate": "0.5.1", + "gulp-util": "3.0.8", + "through2": "2.0.3", + "vinyl-sourcemaps-apply": "0.1.4" }, "dependencies": { "source-map": { @@ -7353,7 +7353,7 @@ "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", "dev": true, "requires": { - "amdefine": ">=0.0.4" + "amdefine": "1.0.1" } }, "vinyl-sourcemaps-apply": { @@ -7362,7 +7362,7 @@ "integrity": "sha1-xfy9Q+LyOEI8LcmL3db3m3K8NFs=", "dev": true, "requires": { - "source-map": "^0.1.39" + "source-map": "0.1.43" } } } @@ -7373,7 +7373,7 @@ "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", "dev": true, "requires": { - "glogg": "^1.0.0" + "glogg": "1.0.1" } }, "har-schema": { @@ -7388,8 +7388,8 @@ "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", "dev": true, "requires": { - "ajv": "^4.9.1", - "har-schema": "^1.0.5" + "ajv": "4.11.8", + "har-schema": "1.0.5" }, "dependencies": { "ajv": { @@ -7398,8 +7398,8 @@ "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", "dev": true, "requires": { - "co": "^4.6.0", - "json-stable-stringify": "^1.0.1" + "co": "4.6.0", + "json-stable-stringify": "1.0.1" } }, "co": { @@ -7416,7 +7416,7 @@ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, "requires": { - "function-bind": "^1.1.1" + "function-bind": "1.1.1" } }, "has-ansi": { @@ -7425,7 +7425,7 @@ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "2.1.1" } }, "has-binary2": { @@ -7463,7 +7463,7 @@ "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", "dev": true, "requires": { - "sparkles": "^1.0.0" + "sparkles": "1.0.1" } }, "has-symbols": { @@ -7478,9 +7478,9 @@ "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", "dev": true, "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" + "get-value": "2.0.6", + "has-values": "1.0.0", + "isobject": "3.0.1" } }, "has-values": { @@ -7489,8 +7489,8 @@ "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", "dev": true, "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" + "is-number": "3.0.0", + "kind-of": "4.0.0" }, "dependencies": { "kind-of": { @@ -7499,7 +7499,7 @@ "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -7510,8 +7510,8 @@ "integrity": "sha1-eNfL/B5tZjA/55g3NlmEUXsvbuE=", "dev": true, "requires": { - "is-stream": "^1.0.1", - "pinkie-promise": "^2.0.0" + "is-stream": "1.1.0", + "pinkie-promise": "2.0.1" } }, "hawk": { @@ -7520,10 +7520,10 @@ "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", "dev": true, "requires": { - "boom": "2.x.x", - "cryptiles": "2.x.x", - "hoek": "2.x.x", - "sntp": "1.x.x" + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" } }, "hipchat-notifier": { @@ -7533,8 +7533,8 @@ "dev": true, "optional": true, "requires": { - "lodash": "^4.0.0", - "request": "^2.0.0" + "lodash": "4.17.11", + "request": "2.81.0" } }, "hoek": { @@ -7549,7 +7549,7 @@ "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", "dev": true, "requires": { - "parse-passwd": "^1.0.0" + "parse-passwd": "1.0.0" } }, "hosted-git-info": { @@ -7570,8 +7570,8 @@ "integrity": "sha1-GX4izevUGYWF6GlO9nhhl7ke2UI=", "dev": true, "requires": { - "inherits": "~2.0.1", - "statuses": "1" + "inherits": "2.0.3", + "statuses": "1.5.0" } }, "http-parser-js": { @@ -7586,9 +7586,9 @@ "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", "dev": true, "requires": { - "eventemitter3": "^3.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" + "eventemitter3": "3.1.0", + "follow-redirects": "1.5.8", + "requires-port": "1.0.0" } }, "http-proxy-agent": { @@ -7597,7 +7597,7 @@ "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", "dev": true, "requires": { - "agent-base": "4", + "agent-base": "4.2.1", "debug": "3.1.0" }, "dependencies": { @@ -7618,9 +7618,9 @@ "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", "dev": true, "requires": { - "assert-plus": "^0.2.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" + "assert-plus": "0.2.0", + "jsprim": "1.4.1", + "sshpk": "1.14.2" } }, "httpntlm": { @@ -7629,8 +7629,8 @@ "integrity": "sha1-rQFScUOi6Hc8+uapb1hla7UqNLI=", "dev": true, "requires": { - "httpreq": ">=0.4.22", - "underscore": "~1.7.0" + "httpreq": "0.4.24", + "underscore": "1.7.0" }, "dependencies": { "underscore": { @@ -7653,8 +7653,8 @@ "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", "dev": true, "requires": { - "agent-base": "^4.1.0", - "debug": "^3.1.0" + "agent-base": "4.2.1", + "debug": "3.2.5" }, "dependencies": { "debug": { @@ -7663,7 +7663,7 @@ "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.1" } }, "ms": { @@ -7699,12 +7699,12 @@ "integrity": "sha1-8Zwu7h5xumxlWMUV+fyWaAGJptQ=", "dev": true, "requires": { - "file-type": "^4.1.0", - "globby": "^6.1.0", - "make-dir": "^1.0.0", - "p-pipe": "^1.1.0", - "pify": "^2.3.0", - "replace-ext": "^1.0.0" + "file-type": "4.4.0", + "globby": "6.1.0", + "make-dir": "1.3.0", + "p-pipe": "1.2.0", + "pify": "2.3.0", + "replace-ext": "1.0.0" }, "dependencies": { "globby": { @@ -7713,11 +7713,11 @@ "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", "dev": true, "requires": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" + "array-union": "1.0.2", + "glob": "7.1.3", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" } }, "replace-ext": { @@ -7735,9 +7735,9 @@ "dev": true, "optional": true, "requires": { - "exec-buffer": "^3.0.0", - "gifsicle": "^3.0.0", - "is-gif": "^1.0.0" + "exec-buffer": "3.2.0", + "gifsicle": "3.0.4", + "is-gif": "1.0.0" } }, "imagemin-jpegtran": { @@ -7747,9 +7747,9 @@ "dev": true, "optional": true, "requires": { - "exec-buffer": "^3.0.0", - "is-jpg": "^1.0.0", - "jpegtran-bin": "^3.0.0" + "exec-buffer": "3.2.0", + "is-jpg": "1.0.1", + "jpegtran-bin": "3.2.0" } }, "imagemin-optipng": { @@ -7759,9 +7759,9 @@ "dev": true, "optional": true, "requires": { - "exec-buffer": "^3.0.0", - "is-png": "^1.0.0", - "optipng-bin": "^3.0.0" + "exec-buffer": "3.2.0", + "is-png": "1.1.0", + "optipng-bin": "3.1.4" } }, "imagemin-svgo": { @@ -7771,9 +7771,9 @@ "dev": true, "optional": true, "requires": { - "buffer-from": "^0.1.1", - "is-svg": "^2.0.0", - "svgo": "^1.0.0" + "buffer-from": "0.1.2", + "is-svg": "2.1.0", + "svgo": "1.1.1" }, "dependencies": { "buffer-from": { @@ -7790,7 +7790,7 @@ "dev": true, "optional": true, "requires": { - "q": "^1.1.2" + "q": "1.5.1" } }, "colors": { @@ -7817,8 +7817,8 @@ "dev": true, "optional": true, "requires": { - "mdn-data": "~1.1.0", - "source-map": "^0.5.3" + "mdn-data": "1.1.4", + "source-map": "0.5.7" } } } @@ -7837,8 +7837,8 @@ "dev": true, "optional": true, "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "argparse": "1.0.10", + "esprima": "4.0.1" } }, "svgo": { @@ -7848,20 +7848,20 @@ "dev": true, "optional": true, "requires": { - "coa": "~2.0.1", - "colors": "~1.1.2", - "css-select": "^2.0.0", - "css-select-base-adapter": "~0.1.0", + "coa": "2.0.1", + "colors": "1.1.2", + "css-select": "2.0.0", + "css-select-base-adapter": "0.1.0", "css-tree": "1.0.0-alpha.28", - "css-url-regex": "^1.1.0", - "csso": "^3.5.0", - "js-yaml": "^3.12.0", - "mkdirp": "~0.5.1", - "object.values": "^1.0.4", - "sax": "~1.2.4", - "stable": "~0.1.6", - "unquote": "~1.1.1", - "util.promisify": "~1.0.0" + "css-url-regex": "1.1.0", + "csso": "3.5.1", + "js-yaml": "3.12.0", + "mkdirp": "0.5.1", + "object.values": "1.0.4", + "sax": "1.2.4", + "stable": "0.1.8", + "unquote": "1.1.1", + "util.promisify": "1.0.0" } } } @@ -7878,7 +7878,7 @@ "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", "dev": true, "requires": { - "repeating": "^2.0.0" + "repeating": "2.0.1" } }, "indexes-of": { @@ -7912,8 +7912,8 @@ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "requires": { - "once": "^1.3.0", - "wrappy": "1" + "once": "1.4.0", + "wrappy": "1.0.2" } }, "inherits": { @@ -7934,19 +7934,19 @@ "integrity": "sha512-QIEQG4YyQ2UYZGDC4srMZ7BjHOmNk1lR2JQj5UknBapklm6WHA+VVH7N+sUdX3A7NeCfGF8o4X1S3Ao7nAcIeg==", "dev": true, "requires": { - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.0", - "cli-cursor": "^2.1.0", - "cli-width": "^2.0.0", - "external-editor": "^3.0.0", - "figures": "^2.0.0", - "lodash": "^4.17.10", + "ansi-escapes": "3.1.0", + "chalk": "2.4.1", + "cli-cursor": "2.1.0", + "cli-width": "2.2.0", + "external-editor": "3.0.3", + "figures": "2.0.0", + "lodash": "4.17.11", "mute-stream": "0.0.7", - "run-async": "^2.2.0", - "rxjs": "^6.1.0", - "string-width": "^2.1.0", - "strip-ansi": "^4.0.0", - "through": "^2.3.6" + "run-async": "2.3.0", + "rxjs": "6.3.3", + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "through": "2.3.8" }, "dependencies": { "ansi-regex": { @@ -7961,7 +7961,7 @@ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { - "color-convert": "^1.9.0" + "color-convert": "1.9.3" } }, "chalk": { @@ -7970,9 +7970,9 @@ "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.5.0" } }, "has-flag": { @@ -7987,7 +7987,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "3.0.0" } }, "supports-color": { @@ -7996,7 +7996,7 @@ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "3.0.0" } } } @@ -8013,7 +8013,7 @@ "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", "dev": true, "requires": { - "loose-envify": "^1.0.0" + "loose-envify": "1.4.0" } }, "ip": { @@ -8047,8 +8047,8 @@ "integrity": "sha1-OV4a6EsR8mrReV5zwXN45IowFXY=", "dev": true, "requires": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" + "is-relative": "1.0.0", + "is-windows": "1.0.2" } }, "is-absolute-url": { @@ -8063,7 +8063,7 @@ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, "requires": { - "kind-of": "^3.0.2" + "kind-of": "3.2.2" }, "dependencies": { "kind-of": { @@ -8072,7 +8072,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -8089,7 +8089,7 @@ "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", "dev": true, "requires": { - "binary-extensions": "^1.0.0" + "binary-extensions": "1.12.0" } }, "is-buffer": { @@ -8104,7 +8104,7 @@ "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", "dev": true, "requires": { - "builtin-modules": "^1.0.0" + "builtin-modules": "1.1.1" } }, "is-bzip2": { @@ -8125,7 +8125,7 @@ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dev": true, "requires": { - "kind-of": "^3.0.2" + "kind-of": "3.2.2" }, "dependencies": { "kind-of": { @@ -8134,7 +8134,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -8151,9 +8151,9 @@ "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", "dev": true, "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" }, "dependencies": { "kind-of": { @@ -8182,7 +8182,7 @@ "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", "dev": true, "requires": { - "is-primitive": "^2.0.0" + "is-primitive": "2.0.0" } }, "is-extendable": { @@ -8203,7 +8203,7 @@ "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", "dev": true, "requires": { - "number-is-nan": "^1.0.0" + "number-is-nan": "1.0.1" } }, "is-fullwidth-code-point": { @@ -8225,7 +8225,7 @@ "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", "dev": true, "requires": { - "is-extglob": "^2.1.0" + "is-extglob": "2.1.1" } }, "is-gzip": { @@ -8255,11 +8255,11 @@ "dev": true, "optional": true, "requires": { - "generate-function": "^2.0.0", - "generate-object-property": "^1.1.0", - "is-my-ip-valid": "^1.0.0", - "jsonpointer": "^4.0.0", - "xtend": "^4.0.0" + "generate-function": "2.3.1", + "generate-object-property": "1.2.0", + "is-my-ip-valid": "1.0.0", + "jsonpointer": "4.0.1", + "xtend": "4.0.1" } }, "is-natural-number": { @@ -8274,7 +8274,7 @@ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, "requires": { - "kind-of": "^3.0.2" + "kind-of": "3.2.2" }, "dependencies": { "kind-of": { @@ -8283,7 +8283,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -8306,7 +8306,7 @@ "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", "dev": true, "requires": { - "is-path-inside": "^1.0.0" + "is-path-inside": "1.0.1" } }, "is-path-inside": { @@ -8315,7 +8315,7 @@ "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", "dev": true, "requires": { - "path-is-inside": "^1.0.1" + "path-is-inside": "1.0.2" } }, "is-plain-obj": { @@ -8330,7 +8330,7 @@ "integrity": "sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=", "dev": true, "requires": { - "isobject": "^3.0.1" + "isobject": "3.0.1" } }, "is-png": { @@ -8376,7 +8376,7 @@ "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", "dev": true, "requires": { - "has": "^1.0.1" + "has": "1.0.3" } }, "is-relative": { @@ -8385,7 +8385,7 @@ "integrity": "sha1-obtpNc6MXboei5dUubLcwCDiJg0=", "dev": true, "requires": { - "is-unc-path": "^1.0.0" + "is-unc-path": "1.0.0" } }, "is-resolvable": { @@ -8412,7 +8412,7 @@ "integrity": "sha1-z2EJDaDZ77yrhyLeum8DIgjbsOk=", "dev": true, "requires": { - "html-comment-regex": "^1.1.0" + "html-comment-regex": "1.1.1" } }, "is-symbol": { @@ -8421,7 +8421,7 @@ "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", "dev": true, "requires": { - "has-symbols": "^1.0.0" + "has-symbols": "1.0.0" } }, "is-tar": { @@ -8442,7 +8442,7 @@ "integrity": "sha1-1zHoiY7QkKEsNSrS6u1Qla0yLJ0=", "dev": true, "requires": { - "unc-path-regex": "^0.1.2" + "unc-path-regex": "0.1.2" } }, "is-url": { @@ -8487,7 +8487,7 @@ "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", "dev": true, "requires": { - "buffer-alloc": "^1.2.0" + "buffer-alloc": "1.2.0" } }, "isexe": { @@ -8521,9 +8521,9 @@ "dev": true, "optional": true, "requires": { - "bin-build": "^2.0.0", - "bin-wrapper": "^3.0.0", - "logalot": "^2.0.0" + "bin-build": "2.2.0", + "bin-wrapper": "3.0.2", + "logalot": "2.1.0" } }, "jquery": { @@ -8546,7 +8546,7 @@ "resolved": "https://registry.npmjs.org/jquery-validation/-/jquery-validation-1.17.0.tgz", "integrity": "sha512-XddiAwhGdWhcIJ+W3ri3KG8uTPMua4TPYuUIC8/E7lOyqdScG5xHuy9YishlKc0c/lIQai77EX7hxMdTSYCEjA==", "requires": { - "jquery": "^1.7 || ^2.0 || ^3.1" + "jquery": "2.2.4" } }, "jquery-validation-unobtrusive": { @@ -8554,8 +8554,8 @@ "resolved": "https://registry.npmjs.org/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-3.2.10.tgz", "integrity": "sha512-z9ZBP/HslaGNKzFSpfLNJoFm2iqPJfE6CKM0H5e9LmKnYTFxErvCFQZomOLiTmLmZi8Wi/otW38cEXExVDha0w==", "requires": { - "jquery": ">=1.8", - "jquery-validation": ">=1.16" + "jquery": "2.2.4", + "jquery-validation": "1.17.0" } }, "js-base64": { @@ -8582,8 +8582,8 @@ "integrity": "sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A=", "dev": true, "requires": { - "argparse": "^1.0.7", - "esprima": "^2.6.0" + "argparse": "1.0.10", + "esprima": "2.7.3" } }, "jsbn": { @@ -8617,7 +8617,7 @@ "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", "dev": true, "requires": { - "jsonify": "~0.0.0" + "jsonify": "0.0.0" } }, "json-stable-stringify-without-jsonify": { @@ -8644,7 +8644,7 @@ "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", "dev": true, "requires": { - "graceful-fs": "^4.1.6" + "graceful-fs": "4.1.11" }, "dependencies": { "graceful-fs": { @@ -8695,31 +8695,31 @@ "integrity": "sha512-rECezBeY7mjzGUWhFlB7CvPHgkHJLXyUmWg+6vHCEsdWNUTnmiS6jRrIMcJEWgU2DUGZzGWG0bTRVky8fsDTOA==", "dev": true, "requires": { - "bluebird": "^3.3.0", - "body-parser": "^1.16.1", - "chokidar": "^2.0.3", - "colors": "^1.1.0", - "combine-lists": "^1.0.0", - "connect": "^3.6.0", - "core-js": "^2.2.0", - "di": "^0.0.1", - "dom-serialize": "^2.2.0", - "expand-braces": "^0.1.1", - "glob": "^7.1.1", - "graceful-fs": "^4.1.2", - "http-proxy": "^1.13.0", - "isbinaryfile": "^3.0.0", - "lodash": "^4.17.4", - "log4js": "^2.5.3", - "mime": "^1.3.4", - "minimatch": "^3.0.2", - "optimist": "^0.6.1", - "qjobs": "^1.1.4", - "range-parser": "^1.2.0", - "rimraf": "^2.6.0", - "safe-buffer": "^5.0.1", + "bluebird": "3.5.2", + "body-parser": "1.18.3", + "chokidar": "2.0.4", + "colors": "1.3.2", + "combine-lists": "1.0.1", + "connect": "3.6.6", + "core-js": "2.5.7", + "di": "0.0.1", + "dom-serialize": "2.2.1", + "expand-braces": "0.1.2", + "glob": "7.1.3", + "graceful-fs": "4.1.11", + "http-proxy": "1.17.0", + "isbinaryfile": "3.0.3", + "lodash": "4.17.11", + "log4js": "2.11.0", + "mime": "1.3.4", + "minimatch": "3.0.4", + "optimist": "0.6.1", + "qjobs": "1.2.0", + "range-parser": "1.2.0", + "rimraf": "2.6.2", + "safe-buffer": "5.1.2", "socket.io": "2.0.4", - "source-map": "^0.6.1", + "source-map": "0.6.1", "tmp": "0.0.33", "useragent": "2.2.1" }, @@ -8730,8 +8730,8 @@ "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", "dev": true, "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" + "micromatch": "3.1.10", + "normalize-path": "2.1.1" } }, "body-parser": { @@ -8741,15 +8741,15 @@ "dev": true, "requires": { "bytes": "3.0.0", - "content-type": "~1.0.4", + "content-type": "1.0.4", "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "~1.6.3", + "depd": "1.1.2", + "http-errors": "1.6.3", "iconv-lite": "0.4.23", - "on-finished": "~2.3.0", + "on-finished": "2.3.0", "qs": "6.5.2", "raw-body": "2.3.3", - "type-is": "~1.6.16" + "type-is": "1.6.16" } }, "bytes": { @@ -8764,19 +8764,19 @@ "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", "dev": true, "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.0", - "braces": "^2.3.0", - "fsevents": "^1.2.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.1", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "lodash.debounce": "^4.0.8", - "normalize-path": "^2.1.1", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0", - "upath": "^1.0.5" + "anymatch": "2.0.0", + "async-each": "1.0.1", + "braces": "2.3.2", + "fsevents": "1.2.4", + "glob-parent": "3.1.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "4.0.0", + "lodash.debounce": "4.0.8", + "normalize-path": "2.1.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.2.1", + "upath": "1.1.0" } }, "connect": { @@ -8787,7 +8787,7 @@ "requires": { "debug": "2.6.9", "finalhandler": "1.1.0", - "parseurl": "~1.3.2", + "parseurl": "1.3.2", "utils-merge": "1.0.1" } }, @@ -8804,12 +8804,12 @@ "dev": true, "requires": { "debug": "2.6.9", - "encodeurl": "~1.0.1", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.2", - "statuses": "~1.3.1", - "unpipe": "~1.0.0" + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "on-finished": "2.3.0", + "parseurl": "1.3.2", + "statuses": "1.3.1", + "unpipe": "1.0.0" }, "dependencies": { "statuses": { @@ -8832,10 +8832,10 @@ "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "dev": true, "requires": { - "depd": "~1.1.2", + "depd": "1.1.2", "inherits": "2.0.3", "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" + "statuses": "1.5.0" } }, "iconv-lite": { @@ -8844,7 +8844,7 @@ "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", "dev": true, "requires": { - "safer-buffer": ">= 2.1.2 < 3" + "safer-buffer": "2.1.2" } }, "is-glob": { @@ -8853,7 +8853,7 @@ "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", "dev": true, "requires": { - "is-extglob": "^2.1.1" + "is-extglob": "2.1.1" } }, "qs": { @@ -8906,8 +8906,8 @@ "integrity": "sha1-0jyjSAG9qYY60xjju0vUBisTrNI=", "dev": true, "requires": { - "lodash": "^4.0.1", - "phantomjs-prebuilt": "^2.1.7" + "lodash": "4.17.11", + "phantomjs-prebuilt": "2.1.16" } }, "kew": { @@ -8928,7 +8928,7 @@ "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", "dev": true, "requires": { - "graceful-fs": "^4.1.9" + "graceful-fs": "4.1.11" }, "dependencies": { "graceful-fs": { @@ -8964,7 +8964,7 @@ "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", "dev": true, "requires": { - "readable-stream": "^2.0.5" + "readable-stream": "2.3.6" }, "dependencies": { "isarray": { @@ -8979,13 +8979,13 @@ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -8994,7 +8994,7 @@ "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } } } @@ -9005,14 +9005,14 @@ "integrity": "sha1-zBJg9RyQCp7A2R+2mYE54CUHtjs=", "dev": true, "requires": { - "errno": "^0.1.1", - "graceful-fs": "^4.1.2", - "image-size": "~0.5.0", - "mime": "^1.2.11", - "mkdirp": "^0.5.0", - "promise": "^7.1.1", + "errno": "0.1.7", + "graceful-fs": "4.1.11", + "image-size": "0.5.5", + "mime": "1.3.4", + "mkdirp": "0.5.1", + "promise": "7.3.1", "request": "2.81.0", - "source-map": "^0.5.3" + "source-map": "0.5.7" }, "dependencies": { "graceful-fs": { @@ -9030,8 +9030,8 @@ "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", "dev": true, "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" + "prelude-ls": "1.1.2", + "type-check": "0.3.2" } }, "libbase64": { @@ -9071,14 +9071,14 @@ "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", "dev": true, "requires": { - "extend": "^3.0.0", - "findup-sync": "^2.0.0", - "fined": "^1.0.1", - "flagged-respawn": "^1.0.0", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.0", - "rechoir": "^0.6.2", - "resolve": "^1.1.7" + "extend": "3.0.2", + "findup-sync": "2.0.0", + "fined": "1.1.0", + "flagged-respawn": "1.0.0", + "is-plain-object": "2.0.4", + "object.map": "1.0.1", + "rechoir": "0.6.2", + "resolve": "1.8.1" } }, "livereload-js": { @@ -9093,11 +9093,11 @@ "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" }, "dependencies": { "graceful-fs": { @@ -9112,7 +9112,7 @@ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "dev": true, "requires": { - "is-utf8": "^0.2.0" + "is-utf8": "0.2.1" } } } @@ -9147,7 +9147,7 @@ "integrity": "sha1-32fDu2t+jh6DGrSL+geVuSr+iZ0=", "dev": true, "requires": { - "lodash._htmlescapes": "~2.4.1" + "lodash._htmlescapes": "2.4.1" } }, "lodash._escapestringchar": { @@ -9210,8 +9210,8 @@ "integrity": "sha1-dHxPxAED6zu4oJduVx96JlnpO6c=", "dev": true, "requires": { - "lodash._htmlescapes": "~2.4.1", - "lodash.keys": "~2.4.1" + "lodash._htmlescapes": "2.4.1", + "lodash.keys": "2.4.1" }, "dependencies": { "lodash.keys": { @@ -9220,9 +9220,9 @@ "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", "dev": true, "requires": { - "lodash._isnative": "~2.4.1", - "lodash._shimkeys": "~2.4.1", - "lodash.isobject": "~2.4.1" + "lodash._isnative": "2.4.1", + "lodash._shimkeys": "2.4.1", + "lodash.isobject": "2.4.1" } } } @@ -9239,7 +9239,7 @@ "integrity": "sha1-bpzJZm/wgfC1psl4uD4kLmlJ0gM=", "dev": true, "requires": { - "lodash._objecttypes": "~2.4.1" + "lodash._objecttypes": "2.4.1" } }, "lodash.clone": { @@ -9266,7 +9266,7 @@ "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", "dev": true, "requires": { - "lodash._root": "^3.0.0" + "lodash._root": "3.0.1" } }, "lodash.flatten": { @@ -9299,7 +9299,7 @@ "integrity": "sha1-Wi5H/mmVPx7mMafrof5k0tBlWPU=", "dev": true, "requires": { - "lodash._objecttypes": "~2.4.1" + "lodash._objecttypes": "2.4.1" } }, "lodash.keys": { @@ -9308,9 +9308,9 @@ "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", "dev": true, "requires": { - "lodash._getnative": "^3.0.0", - "lodash.isarguments": "^3.0.0", - "lodash.isarray": "^3.0.0" + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" } }, "lodash.memoize": { @@ -9349,15 +9349,15 @@ "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", "dev": true, "requires": { - "lodash._basecopy": "^3.0.0", - "lodash._basetostring": "^3.0.0", - "lodash._basevalues": "^3.0.0", - "lodash._isiterateecall": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.escape": "^3.0.0", - "lodash.keys": "^3.0.0", - "lodash.restparam": "^3.0.0", - "lodash.templatesettings": "^3.0.0" + "lodash._basecopy": "3.0.1", + "lodash._basetostring": "3.0.1", + "lodash._basevalues": "3.0.0", + "lodash._isiterateecall": "3.0.9", + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0", + "lodash.keys": "3.1.2", + "lodash.restparam": "3.6.1", + "lodash.templatesettings": "3.1.1" } }, "lodash.templatesettings": { @@ -9366,8 +9366,8 @@ "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", "dev": true, "requires": { - "lodash._reinterpolate": "^3.0.0", - "lodash.escape": "^3.0.0" + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0" } }, "lodash.uniq": { @@ -9382,7 +9382,7 @@ "integrity": "sha1-q/UUQ2s8twUAFieXjLzzCxKA7qQ=", "dev": true, "requires": { - "lodash.keys": "~2.4.1" + "lodash.keys": "2.4.1" }, "dependencies": { "lodash.keys": { @@ -9391,9 +9391,9 @@ "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", "dev": true, "requires": { - "lodash._isnative": "~2.4.1", - "lodash._shimkeys": "~2.4.1", - "lodash.isobject": "~2.4.1" + "lodash._isnative": "2.4.1", + "lodash._shimkeys": "2.4.1", + "lodash.isobject": "2.4.1" } } } @@ -9404,18 +9404,18 @@ "integrity": "sha512-z1XdwyGFg8/WGkOyF6DPJjivCWNLKrklGdViywdYnSKOvgtEBo2UyEMZS5sD2mZrQlU3TvO8wDWLc8mzE1ncBQ==", "dev": true, "requires": { - "amqplib": "^0.5.2", - "axios": "^0.15.3", - "circular-json": "^0.5.4", - "date-format": "^1.2.0", - "debug": "^3.1.0", - "hipchat-notifier": "^1.1.0", - "loggly": "^1.1.0", - "mailgun-js": "^0.18.0", - "nodemailer": "^2.5.0", - "redis": "^2.7.1", - "semver": "^5.5.0", - "slack-node": "~0.2.0", + "amqplib": "0.5.2", + "axios": "0.15.3", + "circular-json": "0.5.7", + "date-format": "1.2.0", + "debug": "3.2.5", + "hipchat-notifier": "1.1.0", + "loggly": "1.1.1", + "mailgun-js": "0.18.1", + "nodemailer": "2.7.2", + "redis": "2.8.0", + "semver": "5.5.1", + "slack-node": "0.2.0", "streamroller": "0.7.0" }, "dependencies": { @@ -9431,7 +9431,7 @@ "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.1" } }, "ms": { @@ -9455,8 +9455,8 @@ "dev": true, "optional": true, "requires": { - "figures": "^1.3.5", - "squeak": "^1.0.0" + "figures": "1.7.0", + "squeak": "1.3.0" }, "dependencies": { "figures": { @@ -9466,8 +9466,8 @@ "dev": true, "optional": true, "requires": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" } } } @@ -9479,9 +9479,9 @@ "dev": true, "optional": true, "requires": { - "json-stringify-safe": "5.0.x", - "request": "2.75.x", - "timespan": "2.3.x" + "json-stringify-safe": "5.0.1", + "request": "2.75.0", + "timespan": "2.3.0" }, "dependencies": { "bl": { @@ -9491,7 +9491,7 @@ "dev": true, "optional": true, "requires": { - "readable-stream": "~2.0.5" + "readable-stream": "2.0.6" } }, "caseless": { @@ -9515,9 +9515,9 @@ "dev": true, "optional": true, "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.5", - "mime-types": "^2.1.11" + "asynckit": "0.4.0", + "combined-stream": "1.0.7", + "mime-types": "2.1.20" } }, "har-validator": { @@ -9527,10 +9527,10 @@ "dev": true, "optional": true, "requires": { - "chalk": "^1.1.1", - "commander": "^2.9.0", - "is-my-json-valid": "^2.12.4", - "pinkie-promise": "^2.0.0" + "chalk": "1.1.3", + "commander": "2.18.0", + "is-my-json-valid": "2.19.0", + "pinkie-promise": "2.0.1" } }, "isarray": { @@ -9568,12 +9568,12 @@ "dev": true, "optional": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "~1.0.0", - "process-nextick-args": "~1.0.6", - "string_decoder": "~0.10.x", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "0.10.31", + "util-deprecate": "1.0.2" } }, "request": { @@ -9583,27 +9583,27 @@ "dev": true, "optional": true, "requires": { - "aws-sign2": "~0.6.0", - "aws4": "^1.2.1", - "bl": "~1.1.2", - "caseless": "~0.11.0", - "combined-stream": "~1.0.5", - "extend": "~3.0.0", - "forever-agent": "~0.6.1", - "form-data": "~2.0.0", - "har-validator": "~2.0.6", - "hawk": "~3.1.3", - "http-signature": "~1.1.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.7", - "node-uuid": "~1.4.7", - "oauth-sign": "~0.8.1", - "qs": "~6.2.0", - "stringstream": "~0.0.4", - "tough-cookie": "~2.3.0", - "tunnel-agent": "~0.4.1" + "aws-sign2": "0.6.0", + "aws4": "1.8.0", + "bl": "1.1.2", + "caseless": "0.11.0", + "combined-stream": "1.0.7", + "extend": "3.0.2", + "forever-agent": "0.6.1", + "form-data": "2.0.0", + "har-validator": "2.0.6", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.20", + "node-uuid": "1.4.8", + "oauth-sign": "0.8.2", + "qs": "6.2.3", + "stringstream": "0.0.6", + "tough-cookie": "2.3.4", + "tunnel-agent": "0.4.3" } } } @@ -9620,7 +9620,7 @@ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", "dev": true, "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" + "js-tokens": "4.0.0" } }, "loud-rejection": { @@ -9629,8 +9629,8 @@ "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", "dev": true, "requires": { - "currently-unhandled": "^0.4.1", - "signal-exit": "^3.0.0" + "currently-unhandled": "0.4.1", + "signal-exit": "3.0.2" } }, "lowercase-keys": { @@ -9646,10 +9646,10 @@ "dev": true, "optional": true, "requires": { - "get-stdin": "^4.0.1", - "indent-string": "^2.1.0", - "longest": "^1.0.0", - "meow": "^3.3.0" + "get-stdin": "4.0.1", + "indent-string": "2.1.0", + "longest": "1.0.1", + "meow": "3.7.0" } }, "lru-cache": { @@ -9676,15 +9676,15 @@ "dev": true, "optional": true, "requires": { - "async": "~2.6.0", - "debug": "~3.1.0", - "form-data": "~2.3.0", - "inflection": "~1.12.0", - "is-stream": "^1.1.0", - "path-proxy": "~1.0.0", - "promisify-call": "^2.0.2", - "proxy-agent": "~3.0.0", - "tsscmp": "~1.0.0" + "async": "2.6.1", + "debug": "3.1.0", + "form-data": "2.3.2", + "inflection": "1.12.0", + "is-stream": "1.1.0", + "path-proxy": "1.0.0", + "promisify-call": "2.0.4", + "proxy-agent": "3.0.3", + "tsscmp": "1.0.5" }, "dependencies": { "combined-stream": { @@ -9694,7 +9694,7 @@ "dev": true, "optional": true, "requires": { - "delayed-stream": "~1.0.0" + "delayed-stream": "1.0.0" } }, "debug": { @@ -9714,9 +9714,9 @@ "dev": true, "optional": true, "requires": { - "asynckit": "^0.4.0", + "asynckit": "0.4.0", "combined-stream": "1.0.6", - "mime-types": "^2.1.12" + "mime-types": "2.1.20" } } } @@ -9727,7 +9727,7 @@ "integrity": "sha1-ecEDO4BRW9bSTsmTPoYMp17ifww=", "dev": true, "requires": { - "pify": "^3.0.0" + "pify": "3.0.0" }, "dependencies": { "pify": { @@ -9744,7 +9744,7 @@ "integrity": "sha1-KbM/MSqo9UfEpeSQ9Wr87JkTOtY=", "dev": true, "requires": { - "kind-of": "^6.0.2" + "kind-of": "6.0.2" } }, "map-cache": { @@ -9771,7 +9771,7 @@ "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", "dev": true, "requires": { - "object-visit": "^1.0.0" + "object-visit": "1.0.1" } }, "marked": { @@ -9810,16 +9810,16 @@ "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", "dev": true, "requires": { - "camelcase-keys": "^2.0.0", - "decamelize": "^1.1.2", - "loud-rejection": "^1.0.0", - "map-obj": "^1.0.1", - "minimist": "^1.1.3", - "normalize-package-data": "^2.3.4", - "object-assign": "^4.0.1", - "read-pkg-up": "^1.0.1", - "redent": "^1.0.0", - "trim-newlines": "^1.0.0" + "camelcase-keys": "2.1.0", + "decamelize": "1.2.0", + "loud-rejection": "1.6.0", + "map-obj": "1.0.1", + "minimist": "1.2.0", + "normalize-package-data": "2.4.0", + "object-assign": "4.1.1", + "read-pkg-up": "1.0.1", + "redent": "1.0.0", + "trim-newlines": "1.0.0" }, "dependencies": { "minimist": { @@ -9836,7 +9836,7 @@ "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", "dev": true, "requires": { - "readable-stream": "^2.0.1" + "readable-stream": "2.3.6" }, "dependencies": { "isarray": { @@ -9851,13 +9851,13 @@ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -9866,7 +9866,7 @@ "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } } } @@ -9878,9 +9878,9 @@ "dev": true, "requires": { "debug": "2.6.9", - "methods": "~1.1.2", - "parseurl": "~1.3.2", - "vary": "~1.1.2" + "methods": "1.1.2", + "parseurl": "1.3.2", + "vary": "1.1.2" }, "dependencies": { "vary": { @@ -9903,19 +9903,19 @@ "integrity": "sha1-cIWbyVyYQJUvNZoGij/En57PrCM=", "dev": true, "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.13", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" } }, "mime": { @@ -9936,7 +9936,7 @@ "integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==", "dev": true, "requires": { - "mime-db": "~1.36.0" + "mime-db": "1.36.0" } }, "mimic-fn": { @@ -9951,7 +9951,7 @@ "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", "dev": true, "requires": { - "brace-expansion": "^1.1.7" + "brace-expansion": "1.1.11" } }, "minimist": { @@ -9966,8 +9966,8 @@ "integrity": "sha1-pJ5yaNzhoNlpjkUybFYm3zVD0P4=", "dev": true, "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" + "for-in": "1.0.2", + "is-extendable": "1.0.1" }, "dependencies": { "is-extendable": { @@ -9976,7 +9976,7 @@ "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", "dev": true, "requires": { - "is-plain-object": "^2.0.4" + "is-plain-object": "2.0.4" } } } @@ -10001,11 +10001,11 @@ "integrity": "sha1-X9gYOYxoGcuiinzWZk8pL+HAu/I=", "dev": true, "requires": { - "basic-auth": "~1.0.3", - "debug": "~2.2.0", - "depd": "~1.0.1", - "on-finished": "~2.3.0", - "on-headers": "~1.0.0" + "basic-auth": "1.0.4", + "debug": "2.2.0", + "depd": "1.0.1", + "on-finished": "2.3.0", + "on-headers": "1.0.1" }, "dependencies": { "debug": { @@ -10037,8 +10037,8 @@ "integrity": "sha1-Nd5oBNwZZD5SSfPT473GyM4wHT8=", "dev": true, "requires": { - "readable-stream": "~1.1.9", - "stream-counter": "~0.2.0" + "readable-stream": "1.1.14", + "stream-counter": "0.2.0" } }, "multipipe": { @@ -10069,17 +10069,17 @@ "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", "dev": true, "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "fragment-cache": "0.2.1", + "is-windows": "1.0.2", + "kind-of": "6.0.2", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" } }, "natives": { @@ -10130,7 +10130,7 @@ "integrity": "sha512-VPB4rTPqpVyWKBHbSa4YPFme3+8WHsOSpvbp0Mfj0bWsC8TEjt4HQrLl1hsBDELlp1nB4lflSgSuGTYiuyaP7Q==", "dev": true, "requires": { - "semver": "^5.3.0" + "semver": "5.5.1" }, "dependencies": { "semver": { @@ -10153,7 +10153,7 @@ "integrity": "sha1-p7iCyC1sk6SGOlUEvV3o7IYli5Y=", "dev": true, "requires": { - "is": "^3.1.0" + "is": "3.2.1" } }, "nodemailer": { @@ -10186,8 +10186,8 @@ "dev": true, "optional": true, "requires": { - "ip": "^1.1.2", - "smart-buffer": "^1.0.4" + "ip": "1.1.5", + "smart-buffer": "1.1.15" } } } @@ -10254,7 +10254,7 @@ "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", "dev": true, "requires": { - "abbrev": "1" + "abbrev": "1.1.1" } }, "normalize-package-data": { @@ -10263,10 +10263,10 @@ "integrity": "sha1-EvlaMH1YNSB1oEkHuErIvpisAS8=", "dev": true, "requires": { - "hosted-git-info": "^2.1.4", - "is-builtin-module": "^1.0.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" + "hosted-git-info": "2.7.1", + "is-builtin-module": "1.0.0", + "semver": "4.3.6", + "validate-npm-package-license": "3.0.4" } }, "normalize-path": { @@ -10275,7 +10275,7 @@ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", "dev": true, "requires": { - "remove-trailing-separator": "^1.0.1" + "remove-trailing-separator": "1.1.0" } }, "normalize-range": { @@ -10290,10 +10290,10 @@ "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", "dev": true, "requires": { - "object-assign": "^4.0.1", - "prepend-http": "^1.0.0", - "query-string": "^4.1.0", - "sort-keys": "^1.0.0" + "object-assign": "4.1.1", + "prepend-http": "1.0.4", + "query-string": "4.3.4", + "sort-keys": "1.1.2" } }, "npm": { @@ -10301,132 +10301,132 @@ "resolved": "https://registry.npmjs.org/npm/-/npm-6.4.1.tgz", "integrity": "sha512-mXJL1NTVU136PtuopXCUQaNWuHlXCTp4McwlSW8S9/Aj8OEPAlSBgo8og7kJ01MjCDrkmqFQTvN5tTEhBMhXQg==", "requires": { - "JSONStream": "^1.3.4", - "abbrev": "~1.1.1", - "ansicolors": "~0.3.2", - "ansistyles": "~0.1.3", - "aproba": "~1.2.0", - "archy": "~1.0.0", - "bin-links": "^1.1.2", - "bluebird": "~3.5.1", - "byte-size": "^4.0.3", - "cacache": "^11.2.0", - "call-limit": "~1.1.0", - "chownr": "~1.0.1", - "ci-info": "^1.4.0", - "cli-columns": "^3.1.2", - "cli-table3": "^0.5.0", - "cmd-shim": "~2.0.2", - "columnify": "~1.5.4", - "config-chain": "~1.1.11", - "debuglog": "*", - "detect-indent": "~5.0.0", - "detect-newline": "^2.1.0", - "dezalgo": "~1.0.3", - "editor": "~1.0.0", - "figgy-pudding": "^3.4.1", - "find-npm-prefix": "^1.0.2", - "fs-vacuum": "~1.2.10", - "fs-write-stream-atomic": "~1.0.10", - "gentle-fs": "^2.0.1", - "glob": "~7.1.2", - "graceful-fs": "~4.1.11", - "has-unicode": "~2.0.1", - "hosted-git-info": "^2.7.1", - "iferr": "^1.0.2", - "imurmurhash": "*", - "inflight": "~1.0.6", - "inherits": "~2.0.3", - "ini": "^1.3.5", - "init-package-json": "^1.10.3", - "is-cidr": "^2.0.6", - "json-parse-better-errors": "^1.0.2", - "lazy-property": "~1.0.0", - "libcipm": "^2.0.2", - "libnpmhook": "^4.0.1", - "libnpx": "^10.2.0", - "lock-verify": "^2.0.2", - "lockfile": "^1.0.4", - "lodash._baseindexof": "*", - "lodash._baseuniq": "~4.6.0", - "lodash._bindcallback": "*", - "lodash._cacheindexof": "*", - "lodash._createcache": "*", - "lodash._getnative": "*", - "lodash.clonedeep": "~4.5.0", - "lodash.restparam": "*", - "lodash.union": "~4.6.0", - "lodash.uniq": "~4.5.0", - "lodash.without": "~4.4.0", - "lru-cache": "^4.1.3", - "meant": "~1.0.1", - "mississippi": "^3.0.0", - "mkdirp": "~0.5.1", - "move-concurrently": "^1.0.1", - "node-gyp": "^3.8.0", - "nopt": "~4.0.1", - "normalize-package-data": "~2.4.0", - "npm-audit-report": "^1.3.1", - "npm-cache-filename": "~1.0.2", - "npm-install-checks": "~3.0.0", - "npm-lifecycle": "^2.1.0", - "npm-package-arg": "^6.1.0", - "npm-packlist": "^1.1.11", - "npm-pick-manifest": "^2.1.0", - "npm-profile": "^3.0.2", - "npm-registry-client": "^8.6.0", - "npm-registry-fetch": "^1.1.0", - "npm-user-validate": "~1.0.0", - "npmlog": "~4.1.2", - "once": "~1.4.0", - "opener": "^1.5.0", - "osenv": "^0.1.5", - "pacote": "^8.1.6", - "path-is-inside": "~1.0.2", - "promise-inflight": "~1.0.1", - "qrcode-terminal": "^0.12.0", - "query-string": "^6.1.0", - "qw": "~1.0.1", - "read": "~1.0.7", - "read-cmd-shim": "~1.0.1", - "read-installed": "~4.0.3", - "read-package-json": "^2.0.13", - "read-package-tree": "^5.2.1", - "readable-stream": "^2.3.6", - "readdir-scoped-modules": "*", - "request": "^2.88.0", - "retry": "^0.12.0", - "rimraf": "~2.6.2", - "safe-buffer": "^5.1.2", - "semver": "^5.5.0", - "sha": "~2.0.1", - "slide": "~1.1.6", - "sorted-object": "~2.0.1", - "sorted-union-stream": "~2.1.3", - "ssri": "^6.0.0", - "stringify-package": "^1.0.0", - "tar": "^4.4.6", - "text-table": "~0.2.0", - "tiny-relative-date": "^1.3.0", + "JSONStream": "1.3.4", + "abbrev": "1.1.1", + "ansicolors": "0.3.2", + "ansistyles": "0.1.3", + "aproba": "1.2.0", + "archy": "1.0.0", + "bin-links": "1.1.2", + "bluebird": "3.5.1", + "byte-size": "4.0.3", + "cacache": "11.2.0", + "call-limit": "1.1.0", + "chownr": "1.0.1", + "ci-info": "1.4.0", + "cli-columns": "3.1.2", + "cli-table3": "0.5.0", + "cmd-shim": "2.0.2", + "columnify": "1.5.4", + "config-chain": "1.1.11", + "debuglog": "1.0.1", + "detect-indent": "5.0.0", + "detect-newline": "2.1.0", + "dezalgo": "1.0.3", + "editor": "1.0.0", + "figgy-pudding": "3.4.1", + "find-npm-prefix": "1.0.2", + "fs-vacuum": "1.2.10", + "fs-write-stream-atomic": "1.0.10", + "gentle-fs": "2.0.1", + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "has-unicode": "2.0.1", + "hosted-git-info": "2.7.1", + "iferr": "1.0.2", + "imurmurhash": "0.1.4", + "inflight": "1.0.6", + "inherits": "2.0.3", + "ini": "1.3.5", + "init-package-json": "1.10.3", + "is-cidr": "2.0.6", + "json-parse-better-errors": "1.0.2", + "lazy-property": "1.0.0", + "libcipm": "2.0.2", + "libnpmhook": "4.0.1", + "libnpx": "10.2.0", + "lock-verify": "2.0.2", + "lockfile": "1.0.4", + "lodash._baseindexof": "3.1.0", + "lodash._baseuniq": "4.6.0", + "lodash._bindcallback": "3.0.1", + "lodash._cacheindexof": "3.0.2", + "lodash._createcache": "3.1.2", + "lodash._getnative": "3.9.1", + "lodash.clonedeep": "4.5.0", + "lodash.restparam": "3.6.1", + "lodash.union": "4.6.0", + "lodash.uniq": "4.5.0", + "lodash.without": "4.4.0", + "lru-cache": "4.1.3", + "meant": "1.0.1", + "mississippi": "3.0.0", + "mkdirp": "0.5.1", + "move-concurrently": "1.0.1", + "node-gyp": "3.8.0", + "nopt": "4.0.1", + "normalize-package-data": "2.4.0", + "npm-audit-report": "1.3.1", + "npm-cache-filename": "1.0.2", + "npm-install-checks": "3.0.0", + "npm-lifecycle": "2.1.0", + "npm-package-arg": "6.1.0", + "npm-packlist": "1.1.11", + "npm-pick-manifest": "2.1.0", + "npm-profile": "3.0.2", + "npm-registry-client": "8.6.0", + "npm-registry-fetch": "1.1.0", + "npm-user-validate": "1.0.0", + "npmlog": "4.1.2", + "once": "1.4.0", + "opener": "1.5.0", + "osenv": "0.1.5", + "pacote": "8.1.6", + "path-is-inside": "1.0.2", + "promise-inflight": "1.0.1", + "qrcode-terminal": "0.12.0", + "query-string": "6.1.0", + "qw": "1.0.1", + "read": "1.0.7", + "read-cmd-shim": "1.0.1", + "read-installed": "4.0.3", + "read-package-json": "2.0.13", + "read-package-tree": "5.2.1", + "readable-stream": "2.3.6", + "readdir-scoped-modules": "1.0.2", + "request": "2.88.0", + "retry": "0.12.0", + "rimraf": "2.6.2", + "safe-buffer": "5.1.2", + "semver": "5.5.0", + "sha": "2.0.1", + "slide": "1.1.6", + "sorted-object": "2.0.1", + "sorted-union-stream": "2.1.3", + "ssri": "6.0.0", + "stringify-package": "1.0.0", + "tar": "4.4.6", + "text-table": "0.2.0", + "tiny-relative-date": "1.3.0", "uid-number": "0.0.6", - "umask": "~1.1.0", - "unique-filename": "~1.1.0", - "unpipe": "~1.0.0", - "update-notifier": "^2.5.0", - "uuid": "^3.3.2", - "validate-npm-package-license": "^3.0.4", - "validate-npm-package-name": "~3.0.0", - "which": "^1.3.1", - "worker-farm": "^1.6.0", - "write-file-atomic": "^2.3.0" + "umask": "1.1.0", + "unique-filename": "1.1.0", + "unpipe": "1.0.0", + "update-notifier": "2.5.0", + "uuid": "3.3.2", + "validate-npm-package-license": "3.0.4", + "validate-npm-package-name": "3.0.0", + "which": "1.3.1", + "worker-farm": "1.6.0", + "write-file-atomic": "2.3.0" }, "dependencies": { "JSONStream": { "version": "1.3.4", "bundled": true, "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" + "jsonparse": "1.3.1", + "through": "2.3.8" } }, "abbrev": { @@ -10437,31 +10437,31 @@ "version": "4.2.0", "bundled": true, "requires": { - "es6-promisify": "^5.0.0" + "es6-promisify": "5.0.0" } }, "agentkeepalive": { "version": "3.4.1", "bundled": true, "requires": { - "humanize-ms": "^1.2.1" + "humanize-ms": "1.2.1" } }, "ajv": { "version": "5.5.2", "bundled": true, "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" } }, "ansi-align": { "version": "2.0.0", "bundled": true, "requires": { - "string-width": "^2.0.0" + "string-width": "2.1.1" } }, "ansi-regex": { @@ -10472,7 +10472,7 @@ "version": "3.2.1", "bundled": true, "requires": { - "color-convert": "^1.9.0" + "color-convert": "1.9.1" } }, "ansicolors": { @@ -10495,8 +10495,8 @@ "version": "1.1.4", "bundled": true, "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" + "delegates": "1.0.0", + "readable-stream": "2.3.6" } }, "asap": { @@ -10507,7 +10507,7 @@ "version": "0.2.4", "bundled": true, "requires": { - "safer-buffer": "~2.1.0" + "safer-buffer": "2.1.2" } }, "assert-plus": { @@ -10535,25 +10535,25 @@ "bundled": true, "optional": true, "requires": { - "tweetnacl": "^0.14.3" + "tweetnacl": "0.14.5" } }, "bin-links": { "version": "1.1.2", "bundled": true, "requires": { - "bluebird": "^3.5.0", - "cmd-shim": "^2.0.2", - "gentle-fs": "^2.0.0", - "graceful-fs": "^4.1.11", - "write-file-atomic": "^2.3.0" + "bluebird": "3.5.1", + "cmd-shim": "2.0.2", + "gentle-fs": "2.0.1", + "graceful-fs": "4.1.11", + "write-file-atomic": "2.3.0" } }, "block-stream": { "version": "0.0.9", "bundled": true, "requires": { - "inherits": "~2.0.0" + "inherits": "2.0.3" } }, "bluebird": { @@ -10564,20 +10564,20 @@ "version": "1.3.0", "bundled": true, "requires": { - "ansi-align": "^2.0.0", - "camelcase": "^4.0.0", - "chalk": "^2.0.1", - "cli-boxes": "^1.0.0", - "string-width": "^2.0.0", - "term-size": "^1.2.0", - "widest-line": "^2.0.0" + "ansi-align": "2.0.0", + "camelcase": "4.1.0", + "chalk": "2.4.1", + "cli-boxes": "1.0.0", + "string-width": "2.1.1", + "term-size": "1.2.0", + "widest-line": "2.0.0" } }, "brace-expansion": { "version": "1.1.11", "bundled": true, "requires": { - "balanced-match": "^1.0.0", + "balanced-match": "1.0.0", "concat-map": "0.0.1" } }, @@ -10605,20 +10605,20 @@ "version": "11.2.0", "bundled": true, "requires": { - "bluebird": "^3.5.1", - "chownr": "^1.0.1", - "figgy-pudding": "^3.1.0", - "glob": "^7.1.2", - "graceful-fs": "^4.1.11", - "lru-cache": "^4.1.3", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "promise-inflight": "^1.0.1", - "rimraf": "^2.6.2", - "ssri": "^6.0.0", - "unique-filename": "^1.1.0", - "y18n": "^4.0.0" + "bluebird": "3.5.1", + "chownr": "1.0.1", + "figgy-pudding": "3.4.1", + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "lru-cache": "4.1.3", + "mississippi": "3.0.0", + "mkdirp": "0.5.1", + "move-concurrently": "1.0.1", + "promise-inflight": "1.0.1", + "rimraf": "2.6.2", + "ssri": "6.0.0", + "unique-filename": "1.1.0", + "y18n": "4.0.0" } }, "call-limit": { @@ -10641,9 +10641,9 @@ "version": "2.4.1", "bundled": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" } }, "chownr": { @@ -10658,7 +10658,7 @@ "version": "2.0.9", "bundled": true, "requires": { - "ip-regex": "^2.1.0" + "ip-regex": "2.1.0" } }, "cli-boxes": { @@ -10669,26 +10669,26 @@ "version": "3.1.2", "bundled": true, "requires": { - "string-width": "^2.0.0", - "strip-ansi": "^3.0.1" + "string-width": "2.1.1", + "strip-ansi": "3.0.1" } }, "cli-table3": { "version": "0.5.0", "bundled": true, "requires": { - "colors": "^1.1.2", - "object-assign": "^4.1.0", - "string-width": "^2.1.1" + "colors": "1.1.2", + "object-assign": "4.1.1", + "string-width": "2.1.1" } }, "cliui": { "version": "4.1.0", "bundled": true, "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "wrap-ansi": "2.1.0" }, "dependencies": { "ansi-regex": { @@ -10699,7 +10699,7 @@ "version": "4.0.0", "bundled": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "3.0.0" } } } @@ -10712,8 +10712,8 @@ "version": "2.0.2", "bundled": true, "requires": { - "graceful-fs": "^4.1.2", - "mkdirp": "~0.5.0" + "graceful-fs": "4.1.11", + "mkdirp": "0.5.1" } }, "co": { @@ -10728,7 +10728,7 @@ "version": "1.9.1", "bundled": true, "requires": { - "color-name": "^1.1.1" + "color-name": "1.1.3" } }, "color-name": { @@ -10744,15 +10744,15 @@ "version": "1.5.4", "bundled": true, "requires": { - "strip-ansi": "^3.0.0", - "wcwidth": "^1.0.0" + "strip-ansi": "3.0.1", + "wcwidth": "1.0.1" } }, "combined-stream": { "version": "1.0.6", "bundled": true, "requires": { - "delayed-stream": "~1.0.0" + "delayed-stream": "1.0.0" } }, "concat-map": { @@ -10763,30 +10763,30 @@ "version": "1.6.2", "bundled": true, "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" + "buffer-from": "1.0.0", + "inherits": "2.0.3", + "readable-stream": "2.3.6", + "typedarray": "0.0.6" } }, "config-chain": { "version": "1.1.11", "bundled": true, "requires": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" + "ini": "1.3.5", + "proto-list": "1.2.4" } }, "configstore": { "version": "3.1.2", "bundled": true, "requires": { - "dot-prop": "^4.1.0", - "graceful-fs": "^4.1.2", - "make-dir": "^1.0.0", - "unique-string": "^1.0.0", - "write-file-atomic": "^2.0.0", - "xdg-basedir": "^3.0.0" + "dot-prop": "4.2.0", + "graceful-fs": "4.1.11", + "make-dir": "1.3.0", + "unique-string": "1.0.0", + "write-file-atomic": "2.3.0", + "xdg-basedir": "3.0.0" } }, "console-control-strings": { @@ -10797,12 +10797,12 @@ "version": "1.0.5", "bundled": true, "requires": { - "aproba": "^1.1.1", - "fs-write-stream-atomic": "^1.0.8", - "iferr": "^0.1.5", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.0" + "aproba": "1.2.0", + "fs-write-stream-atomic": "1.0.10", + "iferr": "0.1.5", + "mkdirp": "0.5.1", + "rimraf": "2.6.2", + "run-queue": "1.0.3" }, "dependencies": { "iferr": { @@ -10819,16 +10819,16 @@ "version": "3.0.2", "bundled": true, "requires": { - "capture-stack-trace": "^1.0.0" + "capture-stack-trace": "1.0.0" } }, "cross-spawn": { "version": "5.1.0", "bundled": true, "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "lru-cache": "4.1.3", + "shebang-command": "1.2.0", + "which": "1.3.1" } }, "crypto-random-string": { @@ -10843,7 +10843,7 @@ "version": "1.14.1", "bundled": true, "requires": { - "assert-plus": "^1.0.0" + "assert-plus": "1.0.0" } }, "debug": { @@ -10879,7 +10879,7 @@ "version": "1.0.3", "bundled": true, "requires": { - "clone": "^1.0.2" + "clone": "1.0.4" } }, "delayed-stream": { @@ -10902,15 +10902,15 @@ "version": "1.0.3", "bundled": true, "requires": { - "asap": "^2.0.0", - "wrappy": "1" + "asap": "2.0.6", + "wrappy": "1.0.2" } }, "dot-prop": { "version": "4.2.0", "bundled": true, "requires": { - "is-obj": "^1.0.0" + "is-obj": "1.0.1" } }, "dotenv": { @@ -10925,10 +10925,10 @@ "version": "3.6.0", "bundled": true, "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" + "end-of-stream": "1.4.1", + "inherits": "2.0.3", + "readable-stream": "2.3.6", + "stream-shift": "1.0.0" } }, "ecc-jsbn": { @@ -10936,8 +10936,8 @@ "bundled": true, "optional": true, "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" + "jsbn": "0.1.1", + "safer-buffer": "2.1.2" } }, "editor": { @@ -10948,14 +10948,14 @@ "version": "0.1.12", "bundled": true, "requires": { - "iconv-lite": "~0.4.13" + "iconv-lite": "0.4.23" } }, "end-of-stream": { "version": "1.4.1", "bundled": true, "requires": { - "once": "^1.4.0" + "once": "1.4.0" } }, "err-code": { @@ -10966,7 +10966,7 @@ "version": "0.1.7", "bundled": true, "requires": { - "prr": "~1.0.1" + "prr": "1.0.1" } }, "es6-promise": { @@ -10977,7 +10977,7 @@ "version": "5.0.0", "bundled": true, "requires": { - "es6-promise": "^4.0.3" + "es6-promise": "4.2.4" } }, "escape-string-regexp": { @@ -10988,13 +10988,13 @@ "version": "0.7.0", "bundled": true, "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" } }, "extend": { @@ -11025,15 +11025,15 @@ "version": "2.1.0", "bundled": true, "requires": { - "locate-path": "^2.0.0" + "locate-path": "2.0.0" } }, "flush-write-stream": { "version": "1.0.3", "bundled": true, "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.4" + "inherits": "2.0.3", + "readable-stream": "2.3.6" } }, "forever-agent": { @@ -11044,43 +11044,43 @@ "version": "2.3.2", "bundled": true, "requires": { - "asynckit": "^0.4.0", + "asynckit": "0.4.0", "combined-stream": "1.0.6", - "mime-types": "^2.1.12" + "mime-types": "2.1.19" } }, "from2": { "version": "2.3.0", "bundled": true, "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" + "inherits": "2.0.3", + "readable-stream": "2.3.6" } }, "fs-minipass": { "version": "1.2.5", "bundled": true, "requires": { - "minipass": "^2.2.1" + "minipass": "2.3.3" } }, "fs-vacuum": { "version": "1.2.10", "bundled": true, "requires": { - "graceful-fs": "^4.1.2", - "path-is-inside": "^1.0.1", - "rimraf": "^2.5.2" + "graceful-fs": "4.1.11", + "path-is-inside": "1.0.2", + "rimraf": "2.6.2" } }, "fs-write-stream-atomic": { "version": "1.0.10", "bundled": true, "requires": { - "graceful-fs": "^4.1.2", - "iferr": "^0.1.5", - "imurmurhash": "^0.1.4", - "readable-stream": "1 || 2" + "graceful-fs": "4.1.11", + "iferr": "0.1.5", + "imurmurhash": "0.1.4", + "readable-stream": "2.3.6" }, "dependencies": { "iferr": { @@ -11097,33 +11097,33 @@ "version": "1.0.11", "bundled": true, "requires": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.2" } }, "gauge": { "version": "2.7.4", "bundled": true, "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" }, "dependencies": { "string-width": { "version": "1.0.2", "bundled": true, "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" } } } @@ -11136,14 +11136,14 @@ "version": "2.0.1", "bundled": true, "requires": { - "aproba": "^1.1.2", - "fs-vacuum": "^1.2.10", - "graceful-fs": "^4.1.11", - "iferr": "^0.1.5", - "mkdirp": "^0.5.1", - "path-is-inside": "^1.0.2", - "read-cmd-shim": "^1.0.1", - "slide": "^1.1.6" + "aproba": "1.2.0", + "fs-vacuum": "1.2.10", + "graceful-fs": "4.1.11", + "iferr": "0.1.5", + "mkdirp": "0.5.1", + "path-is-inside": "1.0.2", + "read-cmd-shim": "1.0.1", + "slide": "1.1.6" }, "dependencies": { "iferr": { @@ -11164,43 +11164,43 @@ "version": "0.1.7", "bundled": true, "requires": { - "assert-plus": "^1.0.0" + "assert-plus": "1.0.0" } }, "glob": { "version": "7.1.2", "bundled": true, "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" } }, "global-dirs": { "version": "0.1.1", "bundled": true, "requires": { - "ini": "^1.3.4" + "ini": "1.3.5" } }, "got": { "version": "6.7.1", "bundled": true, "requires": { - "create-error-class": "^3.0.0", - "duplexer3": "^0.1.4", - "get-stream": "^3.0.0", - "is-redirect": "^1.0.0", - "is-retry-allowed": "^1.0.0", - "is-stream": "^1.0.0", - "lowercase-keys": "^1.0.0", - "safe-buffer": "^5.0.1", - "timed-out": "^4.0.0", - "unzip-response": "^2.0.1", - "url-parse-lax": "^1.0.0" + "create-error-class": "3.0.2", + "duplexer3": "0.1.4", + "get-stream": "3.0.0", + "is-redirect": "1.0.0", + "is-retry-allowed": "1.1.0", + "is-stream": "1.1.0", + "lowercase-keys": "1.0.1", + "safe-buffer": "5.1.2", + "timed-out": "4.0.1", + "unzip-response": "2.0.1", + "url-parse-lax": "1.0.0" } }, "graceful-fs": { @@ -11215,8 +11215,8 @@ "version": "5.1.0", "bundled": true, "requires": { - "ajv": "^5.3.0", - "har-schema": "^2.0.0" + "ajv": "5.5.2", + "har-schema": "2.0.0" } }, "has-flag": { @@ -11239,7 +11239,7 @@ "version": "2.1.0", "bundled": true, "requires": { - "agent-base": "4", + "agent-base": "4.2.0", "debug": "3.1.0" } }, @@ -11247,31 +11247,31 @@ "version": "1.2.0", "bundled": true, "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.14.2" } }, "https-proxy-agent": { "version": "2.2.1", "bundled": true, "requires": { - "agent-base": "^4.1.0", - "debug": "^3.1.0" + "agent-base": "4.2.0", + "debug": "3.1.0" } }, "humanize-ms": { "version": "1.2.1", "bundled": true, "requires": { - "ms": "^2.0.0" + "ms": "2.1.1" } }, "iconv-lite": { "version": "0.4.23", "bundled": true, "requires": { - "safer-buffer": ">= 2.1.2 < 3" + "safer-buffer": "2.1.2" } }, "iferr": { @@ -11282,7 +11282,7 @@ "version": "3.0.1", "bundled": true, "requires": { - "minimatch": "^3.0.4" + "minimatch": "3.0.4" } }, "import-lazy": { @@ -11297,8 +11297,8 @@ "version": "1.0.6", "bundled": true, "requires": { - "once": "^1.3.0", - "wrappy": "1" + "once": "1.4.0", + "wrappy": "1.0.2" } }, "inherits": { @@ -11313,14 +11313,14 @@ "version": "1.10.3", "bundled": true, "requires": { - "glob": "^7.1.1", - "npm-package-arg": "^4.0.0 || ^5.0.0 || ^6.0.0", - "promzard": "^0.3.0", - "read": "~1.0.1", - "read-package-json": "1 || 2", - "semver": "2.x || 3.x || 4 || 5", - "validate-npm-package-license": "^3.0.1", - "validate-npm-package-name": "^3.0.0" + "glob": "7.1.2", + "npm-package-arg": "6.1.0", + "promzard": "0.3.0", + "read": "1.0.7", + "read-package-json": "2.0.13", + "semver": "5.5.0", + "validate-npm-package-license": "3.0.4", + "validate-npm-package-name": "3.0.0" } }, "invert-kv": { @@ -11339,36 +11339,36 @@ "version": "1.0.0", "bundled": true, "requires": { - "builtin-modules": "^1.0.0" + "builtin-modules": "1.1.1" } }, "is-ci": { "version": "1.1.0", "bundled": true, "requires": { - "ci-info": "^1.0.0" + "ci-info": "1.4.0" } }, "is-cidr": { "version": "2.0.6", "bundled": true, "requires": { - "cidr-regex": "^2.0.8" + "cidr-regex": "2.0.9" } }, "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, "requires": { - "number-is-nan": "^1.0.0" + "number-is-nan": "1.0.1" } }, "is-installed-globally": { "version": "0.1.0", "bundled": true, "requires": { - "global-dirs": "^0.1.0", - "is-path-inside": "^1.0.0" + "global-dirs": "0.1.1", + "is-path-inside": "1.0.1" } }, "is-npm": { @@ -11383,7 +11383,7 @@ "version": "1.0.1", "bundled": true, "requires": { - "path-is-inside": "^1.0.1" + "path-is-inside": "1.0.2" } }, "is-redirect": { @@ -11453,7 +11453,7 @@ "version": "3.1.0", "bundled": true, "requires": { - "package-json": "^4.0.0" + "package-json": "4.0.1" } }, "lazy-property": { @@ -11464,46 +11464,46 @@ "version": "1.0.0", "bundled": true, "requires": { - "invert-kv": "^1.0.0" + "invert-kv": "1.0.0" } }, "libcipm": { "version": "2.0.2", "bundled": true, "requires": { - "bin-links": "^1.1.2", - "bluebird": "^3.5.1", - "find-npm-prefix": "^1.0.2", - "graceful-fs": "^4.1.11", - "lock-verify": "^2.0.2", - "mkdirp": "^0.5.1", - "npm-lifecycle": "^2.0.3", - "npm-logical-tree": "^1.2.1", - "npm-package-arg": "^6.1.0", - "pacote": "^8.1.6", - "protoduck": "^5.0.0", - "read-package-json": "^2.0.13", - "rimraf": "^2.6.2", - "worker-farm": "^1.6.0" + "bin-links": "1.1.2", + "bluebird": "3.5.1", + "find-npm-prefix": "1.0.2", + "graceful-fs": "4.1.11", + "lock-verify": "2.0.2", + "mkdirp": "0.5.1", + "npm-lifecycle": "2.1.0", + "npm-logical-tree": "1.2.1", + "npm-package-arg": "6.1.0", + "pacote": "8.1.6", + "protoduck": "5.0.0", + "read-package-json": "2.0.13", + "rimraf": "2.6.2", + "worker-farm": "1.6.0" } }, "libnpmhook": { "version": "4.0.1", "bundled": true, "requires": { - "figgy-pudding": "^3.1.0", - "npm-registry-fetch": "^3.0.0" + "figgy-pudding": "3.4.1", + "npm-registry-fetch": "3.1.1" }, "dependencies": { "npm-registry-fetch": { "version": "3.1.1", "bundled": true, "requires": { - "bluebird": "^3.5.1", - "figgy-pudding": "^3.1.0", - "lru-cache": "^4.1.2", - "make-fetch-happen": "^4.0.0", - "npm-package-arg": "^6.0.0" + "bluebird": "3.5.1", + "figgy-pudding": "3.4.1", + "lru-cache": "4.1.3", + "make-fetch-happen": "4.0.1", + "npm-package-arg": "6.1.0" } } } @@ -11512,37 +11512,37 @@ "version": "10.2.0", "bundled": true, "requires": { - "dotenv": "^5.0.1", - "npm-package-arg": "^6.0.0", - "rimraf": "^2.6.2", - "safe-buffer": "^5.1.0", - "update-notifier": "^2.3.0", - "which": "^1.3.0", - "y18n": "^4.0.0", - "yargs": "^11.0.0" + "dotenv": "5.0.1", + "npm-package-arg": "6.1.0", + "rimraf": "2.6.2", + "safe-buffer": "5.1.2", + "update-notifier": "2.5.0", + "which": "1.3.1", + "y18n": "4.0.0", + "yargs": "11.0.0" } }, "locate-path": { "version": "2.0.0", "bundled": true, "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" + "p-locate": "2.0.0", + "path-exists": "3.0.0" } }, "lock-verify": { "version": "2.0.2", "bundled": true, "requires": { - "npm-package-arg": "^5.1.2 || 6", - "semver": "^5.4.1" + "npm-package-arg": "6.1.0", + "semver": "5.5.0" } }, "lockfile": { "version": "1.0.4", "bundled": true, "requires": { - "signal-exit": "^3.0.2" + "signal-exit": "3.0.2" } }, "lodash._baseindexof": { @@ -11553,8 +11553,8 @@ "version": "4.6.0", "bundled": true, "requires": { - "lodash._createset": "~4.0.0", - "lodash._root": "~3.0.0" + "lodash._createset": "4.0.3", + "lodash._root": "3.0.1" } }, "lodash._bindcallback": { @@ -11569,7 +11569,7 @@ "version": "3.1.2", "bundled": true, "requires": { - "lodash._getnative": "^3.0.0" + "lodash._getnative": "3.9.1" } }, "lodash._createset": { @@ -11612,32 +11612,32 @@ "version": "4.1.3", "bundled": true, "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" + "pseudomap": "1.0.2", + "yallist": "2.1.2" } }, "make-dir": { "version": "1.3.0", "bundled": true, "requires": { - "pify": "^3.0.0" + "pify": "3.0.0" } }, "make-fetch-happen": { "version": "4.0.1", "bundled": true, "requires": { - "agentkeepalive": "^3.4.1", - "cacache": "^11.0.1", - "http-cache-semantics": "^3.8.1", - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.1", - "lru-cache": "^4.1.2", - "mississippi": "^3.0.0", - "node-fetch-npm": "^2.0.2", - "promise-retry": "^1.1.1", - "socks-proxy-agent": "^4.0.0", - "ssri": "^6.0.0" + "agentkeepalive": "3.4.1", + "cacache": "11.2.0", + "http-cache-semantics": "3.8.1", + "http-proxy-agent": "2.1.0", + "https-proxy-agent": "2.2.1", + "lru-cache": "4.1.3", + "mississippi": "3.0.0", + "node-fetch-npm": "2.0.2", + "promise-retry": "1.1.1", + "socks-proxy-agent": "4.0.1", + "ssri": "6.0.0" } }, "meant": { @@ -11648,7 +11648,7 @@ "version": "1.1.0", "bundled": true, "requires": { - "mimic-fn": "^1.0.0" + "mimic-fn": "1.2.0" } }, "mime-db": { @@ -11659,7 +11659,7 @@ "version": "2.1.19", "bundled": true, "requires": { - "mime-db": "~1.35.0" + "mime-db": "1.35.0" } }, "mimic-fn": { @@ -11670,7 +11670,7 @@ "version": "3.0.4", "bundled": true, "requires": { - "brace-expansion": "^1.1.7" + "brace-expansion": "1.1.11" } }, "minimist": { @@ -11681,8 +11681,8 @@ "version": "2.3.3", "bundled": true, "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" + "safe-buffer": "5.1.2", + "yallist": "3.0.2" }, "dependencies": { "yallist": { @@ -11695,23 +11695,23 @@ "version": "1.1.0", "bundled": true, "requires": { - "minipass": "^2.2.1" + "minipass": "2.3.3" } }, "mississippi": { "version": "3.0.0", "bundled": true, "requires": { - "concat-stream": "^1.5.0", - "duplexify": "^3.4.2", - "end-of-stream": "^1.1.0", - "flush-write-stream": "^1.0.0", - "from2": "^2.1.0", - "parallel-transform": "^1.1.0", - "pump": "^3.0.0", - "pumpify": "^1.3.3", - "stream-each": "^1.1.0", - "through2": "^2.0.0" + "concat-stream": "1.6.2", + "duplexify": "3.6.0", + "end-of-stream": "1.4.1", + "flush-write-stream": "1.0.3", + "from2": "2.3.0", + "parallel-transform": "1.1.0", + "pump": "3.0.0", + "pumpify": "1.5.1", + "stream-each": "1.2.2", + "through2": "2.0.3" } }, "mkdirp": { @@ -11725,12 +11725,12 @@ "version": "1.0.1", "bundled": true, "requires": { - "aproba": "^1.1.1", - "copy-concurrently": "^1.0.0", - "fs-write-stream-atomic": "^1.0.8", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.3" + "aproba": "1.2.0", + "copy-concurrently": "1.0.5", + "fs-write-stream-atomic": "1.0.10", + "mkdirp": "0.5.1", + "rimraf": "2.6.2", + "run-queue": "1.0.3" } }, "ms": { @@ -11745,34 +11745,34 @@ "version": "2.0.2", "bundled": true, "requires": { - "encoding": "^0.1.11", - "json-parse-better-errors": "^1.0.0", - "safe-buffer": "^5.1.1" + "encoding": "0.1.12", + "json-parse-better-errors": "1.0.2", + "safe-buffer": "5.1.2" } }, "node-gyp": { "version": "3.8.0", "bundled": true, "requires": { - "fstream": "^1.0.0", - "glob": "^7.0.3", - "graceful-fs": "^4.1.2", - "mkdirp": "^0.5.0", - "nopt": "2 || 3", - "npmlog": "0 || 1 || 2 || 3 || 4", - "osenv": "0", - "request": "^2.87.0", - "rimraf": "2", - "semver": "~5.3.0", - "tar": "^2.0.0", - "which": "1" + "fstream": "1.0.11", + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "mkdirp": "0.5.1", + "nopt": "3.0.6", + "npmlog": "4.1.2", + "osenv": "0.1.5", + "request": "2.88.0", + "rimraf": "2.6.2", + "semver": "5.3.0", + "tar": "2.2.1", + "which": "1.3.1" }, "dependencies": { "nopt": { "version": "3.0.6", "bundled": true, "requires": { - "abbrev": "1" + "abbrev": "1.1.1" } }, "semver": { @@ -11783,9 +11783,9 @@ "version": "2.2.1", "bundled": true, "requires": { - "block-stream": "*", - "fstream": "^1.0.2", - "inherits": "2" + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" } } } @@ -11794,26 +11794,26 @@ "version": "4.0.1", "bundled": true, "requires": { - "abbrev": "1", - "osenv": "^0.1.4" + "abbrev": "1.1.1", + "osenv": "0.1.5" } }, "normalize-package-data": { "version": "2.4.0", "bundled": true, "requires": { - "hosted-git-info": "^2.1.4", - "is-builtin-module": "^1.0.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" + "hosted-git-info": "2.7.1", + "is-builtin-module": "1.0.0", + "semver": "5.5.0", + "validate-npm-package-license": "3.0.4" } }, "npm-audit-report": { "version": "1.3.1", "bundled": true, "requires": { - "cli-table3": "^0.5.0", - "console-control-strings": "^1.1.0" + "cli-table3": "0.5.0", + "console-control-strings": "1.1.0" } }, "npm-bundled": { @@ -11828,21 +11828,21 @@ "version": "3.0.0", "bundled": true, "requires": { - "semver": "^2.3.0 || 3.x || 4 || 5" + "semver": "5.5.0" } }, "npm-lifecycle": { "version": "2.1.0", "bundled": true, "requires": { - "byline": "^5.0.0", - "graceful-fs": "^4.1.11", - "node-gyp": "^3.8.0", - "resolve-from": "^4.0.0", - "slide": "^1.1.6", + "byline": "5.0.0", + "graceful-fs": "4.1.11", + "node-gyp": "3.8.0", + "resolve-from": "4.0.0", + "slide": "1.1.6", "uid-number": "0.0.6", - "umask": "^1.1.0", - "which": "^1.3.1" + "umask": "1.1.0", + "which": "1.3.1" } }, "npm-logical-tree": { @@ -11853,52 +11853,52 @@ "version": "6.1.0", "bundled": true, "requires": { - "hosted-git-info": "^2.6.0", - "osenv": "^0.1.5", - "semver": "^5.5.0", - "validate-npm-package-name": "^3.0.0" + "hosted-git-info": "2.7.1", + "osenv": "0.1.5", + "semver": "5.5.0", + "validate-npm-package-name": "3.0.0" } }, "npm-packlist": { "version": "1.1.11", "bundled": true, "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" + "ignore-walk": "3.0.1", + "npm-bundled": "1.0.5" } }, "npm-pick-manifest": { "version": "2.1.0", "bundled": true, "requires": { - "npm-package-arg": "^6.0.0", - "semver": "^5.4.1" + "npm-package-arg": "6.1.0", + "semver": "5.5.0" } }, "npm-profile": { "version": "3.0.2", "bundled": true, "requires": { - "aproba": "^1.1.2 || 2", - "make-fetch-happen": "^2.5.0 || 3 || 4" + "aproba": "1.2.0", + "make-fetch-happen": "4.0.1" } }, "npm-registry-client": { "version": "8.6.0", "bundled": true, "requires": { - "concat-stream": "^1.5.2", - "graceful-fs": "^4.1.6", - "normalize-package-data": "~1.0.1 || ^2.0.0", - "npm-package-arg": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0", - "npmlog": "2 || ^3.1.0 || ^4.0.0", - "once": "^1.3.3", - "request": "^2.74.0", - "retry": "^0.10.0", - "safe-buffer": "^5.1.1", - "semver": "2 >=2.2.1 || 3.x || 4 || 5", - "slide": "^1.1.3", - "ssri": "^5.2.4" + "concat-stream": "1.6.2", + "graceful-fs": "4.1.11", + "normalize-package-data": "2.4.0", + "npm-package-arg": "6.1.0", + "npmlog": "4.1.2", + "once": "1.4.0", + "request": "2.88.0", + "retry": "0.10.1", + "safe-buffer": "5.1.2", + "semver": "5.5.0", + "slide": "1.1.6", + "ssri": "5.3.0" }, "dependencies": { "retry": { @@ -11909,7 +11909,7 @@ "version": "5.3.0", "bundled": true, "requires": { - "safe-buffer": "^5.1.1" + "safe-buffer": "5.1.2" } } } @@ -11918,47 +11918,47 @@ "version": "1.1.0", "bundled": true, "requires": { - "bluebird": "^3.5.1", - "figgy-pudding": "^2.0.1", - "lru-cache": "^4.1.2", - "make-fetch-happen": "^3.0.0", - "npm-package-arg": "^6.0.0", - "safe-buffer": "^5.1.1" + "bluebird": "3.5.1", + "figgy-pudding": "2.0.1", + "lru-cache": "4.1.3", + "make-fetch-happen": "3.0.0", + "npm-package-arg": "6.1.0", + "safe-buffer": "5.1.2" }, "dependencies": { "cacache": { "version": "10.0.4", "bundled": true, "requires": { - "bluebird": "^3.5.1", - "chownr": "^1.0.1", - "glob": "^7.1.2", - "graceful-fs": "^4.1.11", - "lru-cache": "^4.1.1", - "mississippi": "^2.0.0", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "promise-inflight": "^1.0.1", - "rimraf": "^2.6.2", - "ssri": "^5.2.4", - "unique-filename": "^1.1.0", - "y18n": "^4.0.0" + "bluebird": "3.5.1", + "chownr": "1.0.1", + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "lru-cache": "4.1.3", + "mississippi": "2.0.0", + "mkdirp": "0.5.1", + "move-concurrently": "1.0.1", + "promise-inflight": "1.0.1", + "rimraf": "2.6.2", + "ssri": "5.3.0", + "unique-filename": "1.1.0", + "y18n": "4.0.0" }, "dependencies": { "mississippi": { "version": "2.0.0", "bundled": true, "requires": { - "concat-stream": "^1.5.0", - "duplexify": "^3.4.2", - "end-of-stream": "^1.1.0", - "flush-write-stream": "^1.0.0", - "from2": "^2.1.0", - "parallel-transform": "^1.1.0", - "pump": "^2.0.1", - "pumpify": "^1.3.3", - "stream-each": "^1.1.0", - "through2": "^2.0.0" + "concat-stream": "1.6.2", + "duplexify": "3.6.0", + "end-of-stream": "1.4.1", + "flush-write-stream": "1.0.3", + "from2": "2.3.0", + "parallel-transform": "1.1.0", + "pump": "2.0.1", + "pumpify": "1.5.1", + "stream-each": "1.2.2", + "through2": "2.0.3" } } } @@ -11971,25 +11971,25 @@ "version": "3.0.0", "bundled": true, "requires": { - "agentkeepalive": "^3.4.1", - "cacache": "^10.0.4", - "http-cache-semantics": "^3.8.1", - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.0", - "lru-cache": "^4.1.2", - "mississippi": "^3.0.0", - "node-fetch-npm": "^2.0.2", - "promise-retry": "^1.1.1", - "socks-proxy-agent": "^3.0.1", - "ssri": "^5.2.4" + "agentkeepalive": "3.4.1", + "cacache": "10.0.4", + "http-cache-semantics": "3.8.1", + "http-proxy-agent": "2.1.0", + "https-proxy-agent": "2.2.1", + "lru-cache": "4.1.3", + "mississippi": "3.0.0", + "node-fetch-npm": "2.0.2", + "promise-retry": "1.1.1", + "socks-proxy-agent": "3.0.1", + "ssri": "5.3.0" } }, "pump": { "version": "2.0.1", "bundled": true, "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" + "end-of-stream": "1.4.1", + "once": "1.4.0" } }, "smart-buffer": { @@ -12000,23 +12000,23 @@ "version": "1.1.10", "bundled": true, "requires": { - "ip": "^1.1.4", - "smart-buffer": "^1.0.13" + "ip": "1.1.5", + "smart-buffer": "1.1.15" } }, "socks-proxy-agent": { "version": "3.0.1", "bundled": true, "requires": { - "agent-base": "^4.1.0", - "socks": "^1.1.10" + "agent-base": "4.2.0", + "socks": "1.1.10" } }, "ssri": { "version": "5.3.0", "bundled": true, "requires": { - "safe-buffer": "^5.1.1" + "safe-buffer": "5.1.2" } } } @@ -12025,7 +12025,7 @@ "version": "2.0.2", "bundled": true, "requires": { - "path-key": "^2.0.0" + "path-key": "2.0.1" } }, "npm-user-validate": { @@ -12036,10 +12036,10 @@ "version": "4.1.2", "bundled": true, "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" } }, "number-is-nan": { @@ -12058,7 +12058,7 @@ "version": "1.4.0", "bundled": true, "requires": { - "wrappy": "1" + "wrappy": "1.0.2" } }, "opener": { @@ -12073,9 +12073,9 @@ "version": "2.1.0", "bundled": true, "requires": { - "execa": "^0.7.0", - "lcid": "^1.0.0", - "mem": "^1.1.0" + "execa": "0.7.0", + "lcid": "1.0.0", + "mem": "1.1.0" } }, "os-tmpdir": { @@ -12086,8 +12086,8 @@ "version": "0.1.5", "bundled": true, "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" } }, "p-finally": { @@ -12098,14 +12098,14 @@ "version": "1.2.0", "bundled": true, "requires": { - "p-try": "^1.0.0" + "p-try": "1.0.0" } }, "p-locate": { "version": "2.0.0", "bundled": true, "requires": { - "p-limit": "^1.1.0" + "p-limit": "1.2.0" } }, "p-try": { @@ -12116,50 +12116,50 @@ "version": "4.0.1", "bundled": true, "requires": { - "got": "^6.7.1", - "registry-auth-token": "^3.0.1", - "registry-url": "^3.0.3", - "semver": "^5.1.0" + "got": "6.7.1", + "registry-auth-token": "3.3.2", + "registry-url": "3.1.0", + "semver": "5.5.0" } }, "pacote": { "version": "8.1.6", "bundled": true, "requires": { - "bluebird": "^3.5.1", - "cacache": "^11.0.2", - "get-stream": "^3.0.0", - "glob": "^7.1.2", - "lru-cache": "^4.1.3", - "make-fetch-happen": "^4.0.1", - "minimatch": "^3.0.4", - "minipass": "^2.3.3", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", - "normalize-package-data": "^2.4.0", - "npm-package-arg": "^6.1.0", - "npm-packlist": "^1.1.10", - "npm-pick-manifest": "^2.1.0", - "osenv": "^0.1.5", - "promise-inflight": "^1.0.1", - "promise-retry": "^1.1.1", - "protoduck": "^5.0.0", - "rimraf": "^2.6.2", - "safe-buffer": "^5.1.2", - "semver": "^5.5.0", - "ssri": "^6.0.0", - "tar": "^4.4.3", - "unique-filename": "^1.1.0", - "which": "^1.3.0" + "bluebird": "3.5.1", + "cacache": "11.2.0", + "get-stream": "3.0.0", + "glob": "7.1.2", + "lru-cache": "4.1.3", + "make-fetch-happen": "4.0.1", + "minimatch": "3.0.4", + "minipass": "2.3.3", + "mississippi": "3.0.0", + "mkdirp": "0.5.1", + "normalize-package-data": "2.4.0", + "npm-package-arg": "6.1.0", + "npm-packlist": "1.1.11", + "npm-pick-manifest": "2.1.0", + "osenv": "0.1.5", + "promise-inflight": "1.0.1", + "promise-retry": "1.1.1", + "protoduck": "5.0.0", + "rimraf": "2.6.2", + "safe-buffer": "5.1.2", + "semver": "5.5.0", + "ssri": "6.0.0", + "tar": "4.4.6", + "unique-filename": "1.1.0", + "which": "1.3.1" } }, "parallel-transform": { "version": "1.1.0", "bundled": true, "requires": { - "cyclist": "~0.2.2", - "inherits": "^2.0.3", - "readable-stream": "^2.1.5" + "cyclist": "0.2.2", + "inherits": "2.0.3", + "readable-stream": "2.3.6" } }, "path-exists": { @@ -12202,8 +12202,8 @@ "version": "1.1.1", "bundled": true, "requires": { - "err-code": "^1.0.0", - "retry": "^0.10.0" + "err-code": "1.1.2", + "retry": "0.10.1" }, "dependencies": { "retry": { @@ -12216,7 +12216,7 @@ "version": "0.3.0", "bundled": true, "requires": { - "read": "1" + "read": "1.0.7" } }, "proto-list": { @@ -12227,7 +12227,7 @@ "version": "5.0.0", "bundled": true, "requires": { - "genfun": "^4.0.1" + "genfun": "4.0.1" } }, "prr": { @@ -12246,25 +12246,25 @@ "version": "3.0.0", "bundled": true, "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" + "end-of-stream": "1.4.1", + "once": "1.4.0" } }, "pumpify": { "version": "1.5.1", "bundled": true, "requires": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" + "duplexify": "3.6.0", + "inherits": "2.0.3", + "pump": "2.0.1" }, "dependencies": { "pump": { "version": "2.0.1", "bundled": true, "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" + "end-of-stream": "1.4.1", + "once": "1.4.0" } } } @@ -12285,8 +12285,8 @@ "version": "6.1.0", "bundled": true, "requires": { - "decode-uri-component": "^0.2.0", - "strict-uri-encode": "^2.0.0" + "decode-uri-component": "0.2.0", + "strict-uri-encode": "2.0.0" } }, "qw": { @@ -12297,10 +12297,10 @@ "version": "1.2.7", "bundled": true, "requires": { - "deep-extend": "^0.5.1", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" + "deep-extend": "0.5.1", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" }, "dependencies": { "minimist": { @@ -12313,113 +12313,113 @@ "version": "1.0.7", "bundled": true, "requires": { - "mute-stream": "~0.0.4" + "mute-stream": "0.0.7" } }, "read-cmd-shim": { "version": "1.0.1", "bundled": true, "requires": { - "graceful-fs": "^4.1.2" + "graceful-fs": "4.1.11" } }, "read-installed": { "version": "4.0.3", "bundled": true, "requires": { - "debuglog": "^1.0.1", - "graceful-fs": "^4.1.2", - "read-package-json": "^2.0.0", - "readdir-scoped-modules": "^1.0.0", - "semver": "2 || 3 || 4 || 5", - "slide": "~1.1.3", - "util-extend": "^1.0.1" + "debuglog": "1.0.1", + "graceful-fs": "4.1.11", + "read-package-json": "2.0.13", + "readdir-scoped-modules": "1.0.2", + "semver": "5.5.0", + "slide": "1.1.6", + "util-extend": "1.0.3" } }, "read-package-json": { "version": "2.0.13", "bundled": true, "requires": { - "glob": "^7.1.1", - "graceful-fs": "^4.1.2", - "json-parse-better-errors": "^1.0.1", - "normalize-package-data": "^2.0.0", - "slash": "^1.0.0" + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "json-parse-better-errors": "1.0.2", + "normalize-package-data": "2.4.0", + "slash": "1.0.0" } }, "read-package-tree": { "version": "5.2.1", "bundled": true, "requires": { - "debuglog": "^1.0.1", - "dezalgo": "^1.0.0", - "once": "^1.3.0", - "read-package-json": "^2.0.0", - "readdir-scoped-modules": "^1.0.0" + "debuglog": "1.0.1", + "dezalgo": "1.0.3", + "once": "1.4.0", + "read-package-json": "2.0.13", + "readdir-scoped-modules": "1.0.2" } }, "readable-stream": { "version": "2.3.6", "bundled": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "readdir-scoped-modules": { "version": "1.0.2", "bundled": true, "requires": { - "debuglog": "^1.0.1", - "dezalgo": "^1.0.0", - "graceful-fs": "^4.1.2", - "once": "^1.3.0" + "debuglog": "1.0.1", + "dezalgo": "1.0.3", + "graceful-fs": "4.1.11", + "once": "1.4.0" } }, "registry-auth-token": { "version": "3.3.2", "bundled": true, "requires": { - "rc": "^1.1.6", - "safe-buffer": "^5.0.1" + "rc": "1.2.7", + "safe-buffer": "5.1.2" } }, "registry-url": { "version": "3.1.0", "bundled": true, "requires": { - "rc": "^1.0.1" + "rc": "1.2.7" } }, "request": { "version": "2.88.0", "bundled": true, "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.0", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" + "aws-sign2": "0.7.0", + "aws4": "1.8.0", + "caseless": "0.12.0", + "combined-stream": "1.0.6", + "extend": "3.0.2", + "forever-agent": "0.6.1", + "form-data": "2.3.2", + "har-validator": "5.1.0", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.19", + "oauth-sign": "0.9.0", + "performance-now": "2.1.0", + "qs": "6.5.2", + "safe-buffer": "5.1.2", + "tough-cookie": "2.4.3", + "tunnel-agent": "0.6.0", + "uuid": "3.3.2" } }, "require-directory": { @@ -12442,14 +12442,14 @@ "version": "2.6.2", "bundled": true, "requires": { - "glob": "^7.0.5" + "glob": "7.1.2" } }, "run-queue": { "version": "1.0.3", "bundled": true, "requires": { - "aproba": "^1.1.1" + "aproba": "1.2.0" } }, "safe-buffer": { @@ -12468,7 +12468,7 @@ "version": "2.1.0", "bundled": true, "requires": { - "semver": "^5.0.3" + "semver": "5.5.0" } }, "set-blocking": { @@ -12479,15 +12479,15 @@ "version": "2.0.1", "bundled": true, "requires": { - "graceful-fs": "^4.1.2", - "readable-stream": "^2.0.2" + "graceful-fs": "4.1.11", + "readable-stream": "2.3.6" } }, "shebang-command": { "version": "1.2.0", "bundled": true, "requires": { - "shebang-regex": "^1.0.0" + "shebang-regex": "1.0.0" } }, "shebang-regex": { @@ -12514,16 +12514,16 @@ "version": "2.2.0", "bundled": true, "requires": { - "ip": "^1.1.5", - "smart-buffer": "^4.0.1" + "ip": "1.1.5", + "smart-buffer": "4.0.1" } }, "socks-proxy-agent": { "version": "4.0.1", "bundled": true, "requires": { - "agent-base": "~4.2.0", - "socks": "~2.2.0" + "agent-base": "4.2.0", + "socks": "2.2.0" } }, "sorted-object": { @@ -12534,16 +12534,16 @@ "version": "2.1.3", "bundled": true, "requires": { - "from2": "^1.3.0", - "stream-iterate": "^1.1.0" + "from2": "1.3.0", + "stream-iterate": "1.2.0" }, "dependencies": { "from2": { "version": "1.3.0", "bundled": true, "requires": { - "inherits": "~2.0.1", - "readable-stream": "~1.1.10" + "inherits": "2.0.3", + "readable-stream": "1.1.14" } }, "isarray": { @@ -12554,10 +12554,10 @@ "version": "1.1.14", "bundled": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", + "core-util-is": "1.0.2", + "inherits": "2.0.3", "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "string_decoder": "0.10.31" } }, "string_decoder": { @@ -12570,8 +12570,8 @@ "version": "3.0.0", "bundled": true, "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" + "spdx-expression-parse": "3.0.0", + "spdx-license-ids": "3.0.0" } }, "spdx-exceptions": { @@ -12582,8 +12582,8 @@ "version": "3.0.0", "bundled": true, "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "spdx-exceptions": "2.1.0", + "spdx-license-ids": "3.0.0" } }, "spdx-license-ids": { @@ -12594,15 +12594,15 @@ "version": "1.14.2", "bundled": true, "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" + "asn1": "0.2.4", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.2", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.2", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "safer-buffer": "2.1.2", + "tweetnacl": "0.14.5" } }, "ssri": { @@ -12613,16 +12613,16 @@ "version": "1.2.2", "bundled": true, "requires": { - "end-of-stream": "^1.1.0", - "stream-shift": "^1.0.0" + "end-of-stream": "1.4.1", + "stream-shift": "1.0.0" } }, "stream-iterate": { "version": "1.2.0", "bundled": true, "requires": { - "readable-stream": "^2.1.5", - "stream-shift": "^1.0.0" + "readable-stream": "2.3.6", + "stream-shift": "1.0.0" } }, "stream-shift": { @@ -12637,8 +12637,8 @@ "version": "2.1.1", "bundled": true, "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" }, "dependencies": { "ansi-regex": { @@ -12653,7 +12653,7 @@ "version": "4.0.0", "bundled": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "3.0.0" } } } @@ -12662,7 +12662,7 @@ "version": "1.1.1", "bundled": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } }, "stringify-package": { @@ -12673,7 +12673,7 @@ "version": "3.0.1", "bundled": true, "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "2.1.1" } }, "strip-eof": { @@ -12688,20 +12688,20 @@ "version": "5.4.0", "bundled": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "3.0.0" } }, "tar": { "version": "4.4.6", "bundled": true, "requires": { - "chownr": "^1.0.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.3.3", - "minizlib": "^1.1.0", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.2" + "chownr": "1.0.1", + "fs-minipass": "1.2.5", + "minipass": "2.3.3", + "minizlib": "1.1.0", + "mkdirp": "0.5.1", + "safe-buffer": "5.1.2", + "yallist": "3.0.2" }, "dependencies": { "yallist": { @@ -12714,7 +12714,7 @@ "version": "1.2.0", "bundled": true, "requires": { - "execa": "^0.7.0" + "execa": "0.7.0" } }, "text-table": { @@ -12729,8 +12729,8 @@ "version": "2.0.3", "bundled": true, "requires": { - "readable-stream": "^2.1.5", - "xtend": "~4.0.1" + "readable-stream": "2.3.6", + "xtend": "4.0.1" } }, "timed-out": { @@ -12745,15 +12745,15 @@ "version": "2.4.3", "bundled": true, "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" + "psl": "1.1.29", + "punycode": "1.4.1" } }, "tunnel-agent": { "version": "0.6.0", "bundled": true, "requires": { - "safe-buffer": "^5.0.1" + "safe-buffer": "5.1.2" } }, "tweetnacl": { @@ -12777,21 +12777,21 @@ "version": "1.1.0", "bundled": true, "requires": { - "unique-slug": "^2.0.0" + "unique-slug": "2.0.0" } }, "unique-slug": { "version": "2.0.0", "bundled": true, "requires": { - "imurmurhash": "^0.1.4" + "imurmurhash": "0.1.4" } }, "unique-string": { "version": "1.0.0", "bundled": true, "requires": { - "crypto-random-string": "^1.0.0" + "crypto-random-string": "1.0.0" } }, "unpipe": { @@ -12806,23 +12806,23 @@ "version": "2.5.0", "bundled": true, "requires": { - "boxen": "^1.2.1", - "chalk": "^2.0.1", - "configstore": "^3.0.0", - "import-lazy": "^2.1.0", - "is-ci": "^1.0.10", - "is-installed-globally": "^0.1.0", - "is-npm": "^1.0.0", - "latest-version": "^3.0.0", - "semver-diff": "^2.0.0", - "xdg-basedir": "^3.0.0" + "boxen": "1.3.0", + "chalk": "2.4.1", + "configstore": "3.1.2", + "import-lazy": "2.1.0", + "is-ci": "1.1.0", + "is-installed-globally": "0.1.0", + "is-npm": "1.0.0", + "latest-version": "3.1.0", + "semver-diff": "2.1.0", + "xdg-basedir": "3.0.0" } }, "url-parse-lax": { "version": "1.0.0", "bundled": true, "requires": { - "prepend-http": "^1.0.1" + "prepend-http": "1.0.4" } }, "util-deprecate": { @@ -12841,38 +12841,38 @@ "version": "3.0.4", "bundled": true, "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" + "spdx-correct": "3.0.0", + "spdx-expression-parse": "3.0.0" } }, "validate-npm-package-name": { "version": "3.0.0", "bundled": true, "requires": { - "builtins": "^1.0.3" + "builtins": "1.0.3" } }, "verror": { "version": "1.10.0", "bundled": true, "requires": { - "assert-plus": "^1.0.0", + "assert-plus": "1.0.0", "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" + "extsprintf": "1.3.0" } }, "wcwidth": { "version": "1.0.1", "bundled": true, "requires": { - "defaults": "^1.0.3" + "defaults": "1.0.3" } }, "which": { "version": "1.3.1", "bundled": true, "requires": { - "isexe": "^2.0.0" + "isexe": "2.0.0" } }, "which-module": { @@ -12883,16 +12883,16 @@ "version": "1.1.2", "bundled": true, "requires": { - "string-width": "^1.0.2" + "string-width": "1.0.2" }, "dependencies": { "string-width": { "version": "1.0.2", "bundled": true, "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" } } } @@ -12901,31 +12901,31 @@ "version": "2.0.0", "bundled": true, "requires": { - "string-width": "^2.1.1" + "string-width": "2.1.1" } }, "worker-farm": { "version": "1.6.0", "bundled": true, "requires": { - "errno": "~0.1.7" + "errno": "0.1.7" } }, "wrap-ansi": { "version": "2.1.0", "bundled": true, "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" + "string-width": "1.0.2", + "strip-ansi": "3.0.1" }, "dependencies": { "string-width": { "version": "1.0.2", "bundled": true, "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" } } } @@ -12938,9 +12938,9 @@ "version": "2.3.0", "bundled": true, "requires": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" + "graceful-fs": "4.1.11", + "imurmurhash": "0.1.4", + "signal-exit": "3.0.2" } }, "xdg-basedir": { @@ -12963,18 +12963,18 @@ "version": "11.0.0", "bundled": true, "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.1.1", - "find-up": "^2.1.0", - "get-caller-file": "^1.0.1", - "os-locale": "^2.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^9.0.2" + "cliui": "4.1.0", + "decamelize": "1.2.0", + "find-up": "2.1.0", + "get-caller-file": "1.0.2", + "os-locale": "2.1.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "3.2.1", + "yargs-parser": "9.0.2" }, "dependencies": { "y18n": { @@ -12987,7 +12987,7 @@ "version": "9.0.2", "bundled": true, "requires": { - "camelcase": "^4.1.0" + "camelcase": "4.1.0" } } } @@ -12999,7 +12999,7 @@ "dev": true, "optional": true, "requires": { - "path-key": "^2.0.0" + "path-key": "2.0.1" } }, "nth-check": { @@ -13009,7 +13009,7 @@ "dev": true, "optional": true, "requires": { - "boolbase": "~1.0.0" + "boolbase": "1.0.0" } }, "num2fraction": { @@ -13048,9 +13048,9 @@ "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", "dev": true, "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" + "copy-descriptor": "0.1.1", + "define-property": "0.2.5", + "kind-of": "3.2.2" }, "dependencies": { "define-property": { @@ -13059,7 +13059,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "is-descriptor": "0.1.6" } }, "kind-of": { @@ -13068,7 +13068,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -13085,7 +13085,7 @@ "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", "dev": true, "requires": { - "isobject": "^3.0.0" + "isobject": "3.0.1" } }, "object.defaults": { @@ -13094,10 +13094,10 @@ "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", "dev": true, "requires": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" + "array-each": "1.0.1", + "array-slice": "1.1.0", + "for-own": "1.0.0", + "isobject": "3.0.1" } }, "object.getownpropertydescriptors": { @@ -13107,8 +13107,8 @@ "dev": true, "optional": true, "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.5.1" + "define-properties": "1.1.3", + "es-abstract": "1.12.0" } }, "object.map": { @@ -13117,8 +13117,8 @@ "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", "dev": true, "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" + "for-own": "1.0.0", + "make-iterator": "1.0.1" } }, "object.omit": { @@ -13127,8 +13127,8 @@ "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", "dev": true, "requires": { - "for-own": "^0.1.4", - "is-extendable": "^0.1.1" + "for-own": "0.1.5", + "is-extendable": "0.1.1" }, "dependencies": { "for-own": { @@ -13137,7 +13137,7 @@ "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", "dev": true, "requires": { - "for-in": "^1.0.1" + "for-in": "1.0.2" } } } @@ -13148,7 +13148,7 @@ "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", "dev": true, "requires": { - "isobject": "^3.0.1" + "isobject": "3.0.1" } }, "object.values": { @@ -13158,10 +13158,10 @@ "dev": true, "optional": true, "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.6.1", - "function-bind": "^1.1.0", - "has": "^1.0.1" + "define-properties": "1.1.3", + "es-abstract": "1.12.0", + "function-bind": "1.1.1", + "has": "1.0.3" } }, "on-finished": { @@ -13185,7 +13185,7 @@ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { - "wrappy": "1" + "wrappy": "1.0.2" } }, "onetime": { @@ -13194,7 +13194,7 @@ "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", "dev": true, "requires": { - "mimic-fn": "^1.0.0" + "mimic-fn": "1.2.0" } }, "open": { @@ -13209,8 +13209,8 @@ "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", "dev": true, "requires": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" + "minimist": "0.0.8", + "wordwrap": "0.0.3" }, "dependencies": { "wordwrap": { @@ -13227,12 +13227,12 @@ "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", "dev": true, "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.4", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "wordwrap": "~1.0.0" + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "1.0.0" } }, "optipng-bin": { @@ -13242,9 +13242,9 @@ "dev": true, "optional": true, "requires": { - "bin-build": "^2.0.0", - "bin-wrapper": "^3.0.0", - "logalot": "^2.0.0" + "bin-build": "2.2.0", + "bin-wrapper": "3.0.2", + "logalot": "2.1.0" } }, "orchestrator": { @@ -13253,9 +13253,9 @@ "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", "dev": true, "requires": { - "end-of-stream": "~0.1.5", - "sequencify": "~0.0.7", - "stream-consume": "~0.1.0" + "end-of-stream": "0.1.5", + "sequencify": "0.0.7", + "stream-consume": "0.1.1" } }, "ordered-read-streams": { @@ -13302,14 +13302,14 @@ "dev": true, "optional": true, "requires": { - "agent-base": "^4.2.0", - "debug": "^3.1.0", - "get-uri": "^2.0.0", - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.1", - "pac-resolver": "^3.0.0", - "raw-body": "^2.2.0", - "socks-proxy-agent": "^4.0.1" + "agent-base": "4.2.1", + "debug": "3.2.5", + "get-uri": "2.0.2", + "http-proxy-agent": "2.1.0", + "https-proxy-agent": "2.2.1", + "pac-resolver": "3.0.0", + "raw-body": "2.3.3", + "socks-proxy-agent": "4.0.1" }, "dependencies": { "bytes": { @@ -13326,7 +13326,7 @@ "dev": true, "optional": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.1" } }, "depd": { @@ -13343,10 +13343,10 @@ "dev": true, "optional": true, "requires": { - "depd": "~1.1.2", + "depd": "1.1.2", "inherits": "2.0.3", "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" + "statuses": "1.5.0" } }, "iconv-lite": { @@ -13356,7 +13356,7 @@ "dev": true, "optional": true, "requires": { - "safer-buffer": ">= 2.1.2 < 3" + "safer-buffer": "2.1.2" } }, "ms": { @@ -13388,11 +13388,11 @@ "dev": true, "optional": true, "requires": { - "co": "^4.6.0", - "degenerator": "^1.0.4", - "ip": "^1.1.5", - "netmask": "^1.0.6", - "thunkify": "^2.1.2" + "co": "4.6.0", + "degenerator": "1.0.4", + "ip": "1.1.5", + "netmask": "1.0.6", + "thunkify": "2.1.2" }, "dependencies": { "co": { @@ -13410,9 +13410,9 @@ "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", "dev": true, "requires": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" + "is-absolute": "1.0.0", + "map-cache": "0.2.2", + "path-root": "0.1.1" } }, "parse-glob": { @@ -13421,10 +13421,10 @@ "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", "dev": true, "requires": { - "glob-base": "^0.3.0", - "is-dotfile": "^1.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.0" + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" }, "dependencies": { "is-extglob": { @@ -13439,7 +13439,7 @@ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "^1.0.0" + "is-extglob": "1.0.0" } } } @@ -13450,7 +13450,7 @@ "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", "dev": true, "requires": { - "error-ex": "^1.2.0" + "error-ex": "1.3.2" } }, "parse-passwd": { @@ -13465,7 +13465,7 @@ "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", "dev": true, "requires": { - "better-assert": "~1.0.0" + "better-assert": "1.0.2" } }, "parseuri": { @@ -13474,7 +13474,7 @@ "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", "dev": true, "requires": { - "better-assert": "~1.0.0" + "better-assert": "1.0.2" } }, "parseurl": { @@ -13507,7 +13507,7 @@ "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", "dev": true, "requires": { - "pinkie-promise": "^2.0.0" + "pinkie-promise": "2.0.1" } }, "path-is-absolute": { @@ -13541,7 +13541,7 @@ "dev": true, "optional": true, "requires": { - "inflection": "~1.3.0" + "inflection": "1.3.8" }, "dependencies": { "inflection": { @@ -13559,7 +13559,7 @@ "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", "dev": true, "requires": { - "path-root-regex": "^0.1.0" + "path-root-regex": "0.1.2" } }, "path-root-regex": { @@ -13574,9 +13574,9 @@ "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" }, "dependencies": { "graceful-fs": { @@ -13599,7 +13599,7 @@ "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", "dev": true, "requires": { - "through": "~2.3" + "through": "2.3.8" } }, "pend": { @@ -13620,15 +13620,15 @@ "integrity": "sha1-79ISpKOWbTZHaE6ouniFSb4q7+8=", "dev": true, "requires": { - "es6-promise": "^4.0.3", - "extract-zip": "^1.6.5", - "fs-extra": "^1.0.0", - "hasha": "^2.2.0", - "kew": "^0.7.0", - "progress": "^1.1.8", - "request": "^2.81.0", - "request-progress": "^2.0.1", - "which": "^1.2.10" + "es6-promise": "4.2.5", + "extract-zip": "1.6.7", + "fs-extra": "1.0.0", + "hasha": "2.2.0", + "kew": "0.7.0", + "progress": "1.1.8", + "request": "2.81.0", + "request-progress": "2.0.1", + "which": "1.3.1" }, "dependencies": { "es6-promise": { @@ -13663,7 +13663,7 @@ "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", "dev": true, "requires": { - "pinkie": "^2.0.0" + "pinkie": "2.0.4" } }, "plugin-error": { @@ -13672,10 +13672,10 @@ "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", "dev": true, "requires": { - "ansi-colors": "^1.0.1", - "arr-diff": "^4.0.0", - "arr-union": "^3.1.0", - "extend-shallow": "^3.0.2" + "ansi-colors": "1.1.0", + "arr-diff": "4.0.0", + "arr-union": "3.1.0", + "extend-shallow": "3.0.2" } }, "plugin-log": { @@ -13684,8 +13684,8 @@ "integrity": "sha1-hgSc9qsQgzOYqTHzaJy67nteEzM=", "dev": true, "requires": { - "chalk": "^1.1.1", - "dateformat": "^1.0.11" + "chalk": "1.1.3", + "dateformat": "1.0.12" }, "dependencies": { "dateformat": { @@ -13694,8 +13694,8 @@ "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", "dev": true, "requires": { - "get-stdin": "^4.0.1", - "meow": "^3.3.0" + "get-stdin": "4.0.1", + "meow": "3.7.0" } } } @@ -13706,7 +13706,7 @@ "integrity": "sha1-dIJFLBoPUI4+NE6uwxLJHCncZVo=", "dev": true, "requires": { - "irregular-plurals": "^1.0.0" + "irregular-plurals": "1.4.0" } }, "pluralize": { @@ -13727,10 +13727,10 @@ "integrity": "sha1-ut+hSX1GJE9jkPWLMZgw2RB4U8U=", "dev": true, "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" + "chalk": "1.1.3", + "js-base64": "2.4.9", + "source-map": "0.5.7", + "supports-color": "3.2.3" } }, "postcss-calc": { @@ -13739,9 +13739,9 @@ "integrity": "sha1-d7rnypKK2FcW4v2kLyYb98HWW14=", "dev": true, "requires": { - "postcss": "^5.0.2", - "postcss-message-helpers": "^2.0.0", - "reduce-css-calc": "^1.2.6" + "postcss": "5.2.18", + "postcss-message-helpers": "2.0.0", + "reduce-css-calc": "1.3.0" } }, "postcss-colormin": { @@ -13750,9 +13750,9 @@ "integrity": "sha1-ZjFBfV8OkJo9fsJrJMio0eT5bks=", "dev": true, "requires": { - "colormin": "^1.0.5", - "postcss": "^5.0.13", - "postcss-value-parser": "^3.2.3" + "colormin": "1.1.2", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" } }, "postcss-convert-values": { @@ -13761,8 +13761,8 @@ "integrity": "sha1-u9hZPFwf0uPRwyK7kl3K6Nrk1i0=", "dev": true, "requires": { - "postcss": "^5.0.11", - "postcss-value-parser": "^3.1.2" + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" } }, "postcss-discard-comments": { @@ -13771,7 +13771,7 @@ "integrity": "sha1-vv6J+v1bPazlzM5Rt2uBUUvgDj0=", "dev": true, "requires": { - "postcss": "^5.0.14" + "postcss": "5.2.18" } }, "postcss-discard-duplicates": { @@ -13780,7 +13780,7 @@ "integrity": "sha1-uavye4isGIFYpesSq8riAmO5GTI=", "dev": true, "requires": { - "postcss": "^5.0.4" + "postcss": "5.2.18" } }, "postcss-discard-empty": { @@ -13789,7 +13789,7 @@ "integrity": "sha1-0rS9nVztXr2Nyt52QMfXzX9PkrU=", "dev": true, "requires": { - "postcss": "^5.0.14" + "postcss": "5.2.18" } }, "postcss-discard-overridden": { @@ -13798,7 +13798,7 @@ "integrity": "sha1-ix6vVU9ob7KIzYdMVWZ7CqNmjVg=", "dev": true, "requires": { - "postcss": "^5.0.16" + "postcss": "5.2.18" } }, "postcss-discard-unused": { @@ -13807,8 +13807,8 @@ "integrity": "sha1-vOMLLMWR/8Y0Mitfs0ZLbZNPRDM=", "dev": true, "requires": { - "postcss": "^5.0.14", - "uniqs": "^2.0.0" + "postcss": "5.2.18", + "uniqs": "2.0.0" } }, "postcss-filter-plugins": { @@ -13817,7 +13817,7 @@ "integrity": "sha512-T53GVFsdinJhgwm7rg1BzbeBRomOg9y5MBVhGcsV0CxurUdVj1UlPdKtn7aqYA/c/QVkzKMjq2bSV5dKG5+AwQ==", "dev": true, "requires": { - "postcss": "^5.0.4" + "postcss": "5.2.18" } }, "postcss-load-config": { @@ -13826,10 +13826,10 @@ "integrity": "sha1-U56a/J3chiASHr+djDZz4M5Q0oo=", "dev": true, "requires": { - "cosmiconfig": "^2.1.0", - "object-assign": "^4.1.0", - "postcss-load-options": "^1.2.0", - "postcss-load-plugins": "^2.3.0" + "cosmiconfig": "2.2.2", + "object-assign": "4.1.1", + "postcss-load-options": "1.2.0", + "postcss-load-plugins": "2.3.0" } }, "postcss-load-options": { @@ -13838,8 +13838,8 @@ "integrity": "sha1-sJixVZ3awt8EvAuzdfmaXP4rbYw=", "dev": true, "requires": { - "cosmiconfig": "^2.1.0", - "object-assign": "^4.1.0" + "cosmiconfig": "2.2.2", + "object-assign": "4.1.1" } }, "postcss-load-plugins": { @@ -13848,8 +13848,8 @@ "integrity": "sha1-dFdoEWWZrKLwCfrUJrABdQSdjZI=", "dev": true, "requires": { - "cosmiconfig": "^2.1.1", - "object-assign": "^4.1.0" + "cosmiconfig": "2.2.2", + "object-assign": "4.1.1" } }, "postcss-merge-idents": { @@ -13858,9 +13858,9 @@ "integrity": "sha1-TFUwMTwI4dWzu/PSu8dH4njuonA=", "dev": true, "requires": { - "has": "^1.0.1", - "postcss": "^5.0.10", - "postcss-value-parser": "^3.1.1" + "has": "1.0.3", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" } }, "postcss-merge-longhand": { @@ -13869,7 +13869,7 @@ "integrity": "sha1-I9kM0Sewp3mUkVMyc5A0oaTz1lg=", "dev": true, "requires": { - "postcss": "^5.0.4" + "postcss": "5.2.18" } }, "postcss-merge-rules": { @@ -13878,11 +13878,11 @@ "integrity": "sha1-0d9d+qexrMO+VT8OnhDofGG19yE=", "dev": true, "requires": { - "browserslist": "^1.5.2", - "caniuse-api": "^1.5.2", - "postcss": "^5.0.4", - "postcss-selector-parser": "^2.2.2", - "vendors": "^1.0.0" + "browserslist": "1.7.7", + "caniuse-api": "1.6.1", + "postcss": "5.2.18", + "postcss-selector-parser": "2.2.3", + "vendors": "1.0.2" } }, "postcss-message-helpers": { @@ -13897,9 +13897,9 @@ "integrity": "sha1-S1jttWZB66fIR0qzUmyv17vey2k=", "dev": true, "requires": { - "object-assign": "^4.0.1", - "postcss": "^5.0.4", - "postcss-value-parser": "^3.0.2" + "object-assign": "4.1.1", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" } }, "postcss-minify-gradients": { @@ -13908,8 +13908,8 @@ "integrity": "sha1-Xb2hE3NwP4PPtKPqOIHY11/15uE=", "dev": true, "requires": { - "postcss": "^5.0.12", - "postcss-value-parser": "^3.3.0" + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" } }, "postcss-minify-params": { @@ -13918,10 +13918,10 @@ "integrity": "sha1-rSzgcTc7lDs9kwo/pZo1jCjW8fM=", "dev": true, "requires": { - "alphanum-sort": "^1.0.1", - "postcss": "^5.0.2", - "postcss-value-parser": "^3.0.2", - "uniqs": "^2.0.0" + "alphanum-sort": "1.0.2", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0", + "uniqs": "2.0.0" } }, "postcss-minify-selectors": { @@ -13930,10 +13930,10 @@ "integrity": "sha1-ssapjAByz5G5MtGkllCBFDEXNb8=", "dev": true, "requires": { - "alphanum-sort": "^1.0.2", - "has": "^1.0.1", - "postcss": "^5.0.14", - "postcss-selector-parser": "^2.0.0" + "alphanum-sort": "1.0.2", + "has": "1.0.3", + "postcss": "5.2.18", + "postcss-selector-parser": "2.2.3" } }, "postcss-normalize-charset": { @@ -13942,7 +13942,7 @@ "integrity": "sha1-757nEhLX/nWceO0WL2HtYrXLk/E=", "dev": true, "requires": { - "postcss": "^5.0.5" + "postcss": "5.2.18" } }, "postcss-normalize-url": { @@ -13951,10 +13951,10 @@ "integrity": "sha1-EI90s/L82viRov+j6kWSJ5/HgiI=", "dev": true, "requires": { - "is-absolute-url": "^2.0.0", - "normalize-url": "^1.4.0", - "postcss": "^5.0.14", - "postcss-value-parser": "^3.2.3" + "is-absolute-url": "2.1.0", + "normalize-url": "1.9.1", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" } }, "postcss-ordered-values": { @@ -13963,8 +13963,8 @@ "integrity": "sha1-7sbCpntsQSqNsgQud/6NpD+VwR0=", "dev": true, "requires": { - "postcss": "^5.0.4", - "postcss-value-parser": "^3.0.1" + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" } }, "postcss-reduce-idents": { @@ -13973,8 +13973,8 @@ "integrity": "sha1-wsbSDMlYKE9qv75j92Cb9AkFmtM=", "dev": true, "requires": { - "postcss": "^5.0.4", - "postcss-value-parser": "^3.0.2" + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" } }, "postcss-reduce-initial": { @@ -13983,7 +13983,7 @@ "integrity": "sha1-aPgGlfBF0IJjqHmtJA343WT2ROo=", "dev": true, "requires": { - "postcss": "^5.0.4" + "postcss": "5.2.18" } }, "postcss-reduce-transforms": { @@ -13992,9 +13992,9 @@ "integrity": "sha1-/3b02CEkN7McKYpC0uFEQCV3GuE=", "dev": true, "requires": { - "has": "^1.0.1", - "postcss": "^5.0.8", - "postcss-value-parser": "^3.0.1" + "has": "1.0.3", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" } }, "postcss-selector-parser": { @@ -14003,9 +14003,9 @@ "integrity": "sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A=", "dev": true, "requires": { - "flatten": "^1.0.2", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" + "flatten": "1.0.2", + "indexes-of": "1.0.1", + "uniq": "1.0.1" } }, "postcss-svgo": { @@ -14014,10 +14014,10 @@ "integrity": "sha1-tt8YqmE7Zm4TPwittSGcJoSsEI0=", "dev": true, "requires": { - "is-svg": "^2.0.0", - "postcss": "^5.0.14", - "postcss-value-parser": "^3.2.3", - "svgo": "^0.7.0" + "is-svg": "2.1.0", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0", + "svgo": "0.7.2" } }, "postcss-unique-selectors": { @@ -14026,9 +14026,9 @@ "integrity": "sha1-mB1X0p3csz57Hf4f1DuGSfkzyh0=", "dev": true, "requires": { - "alphanum-sort": "^1.0.1", - "postcss": "^5.0.4", - "uniqs": "^2.0.0" + "alphanum-sort": "1.0.2", + "postcss": "5.2.18", + "uniqs": "2.0.0" } }, "postcss-value-parser": { @@ -14043,9 +14043,9 @@ "integrity": "sha1-0hCd3AVbka9n/EyzsCWUZjnSryI=", "dev": true, "requires": { - "has": "^1.0.1", - "postcss": "^5.0.4", - "uniqs": "^2.0.0" + "has": "1.0.3", + "postcss": "5.2.18", + "uniqs": "2.0.0" } }, "prelude-ls": { @@ -14103,7 +14103,7 @@ "dev": true, "optional": true, "requires": { - "asap": "~2.0.3" + "asap": "2.0.6" } }, "promisify-call": { @@ -14113,7 +14113,7 @@ "dev": true, "optional": true, "requires": { - "with-callback": "^1.0.2" + "with-callback": "1.0.2" } }, "proxy-agent": { @@ -14123,14 +14123,14 @@ "dev": true, "optional": true, "requires": { - "agent-base": "^4.2.0", - "debug": "^3.1.0", - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.1", - "lru-cache": "^4.1.2", - "pac-proxy-agent": "^3.0.0", - "proxy-from-env": "^1.0.0", - "socks-proxy-agent": "^4.0.1" + "agent-base": "4.2.1", + "debug": "3.2.5", + "http-proxy-agent": "2.1.0", + "https-proxy-agent": "2.2.1", + "lru-cache": "4.1.3", + "pac-proxy-agent": "3.0.0", + "proxy-from-env": "1.0.0", + "socks-proxy-agent": "4.0.1" }, "dependencies": { "debug": { @@ -14140,7 +14140,7 @@ "dev": true, "optional": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.1" } }, "lru-cache": { @@ -14150,8 +14150,8 @@ "dev": true, "optional": true, "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" + "pseudomap": "1.0.2", + "yallist": "2.1.2" } }, "ms": { @@ -14214,8 +14214,8 @@ "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", "dev": true, "requires": { - "object-assign": "^4.1.0", - "strict-uri-encode": "^1.0.0" + "object-assign": "4.1.1", + "strict-uri-encode": "1.1.0" } }, "random-bytes": { @@ -14230,9 +14230,9 @@ "integrity": "sha512-KnGPVE0lo2WoXxIZ7cPR8YBpiol4gsSuOwDSg410oHh80ZMp5EiypNqL2K4Z77vJn6lB5rap7IkAmcUlalcnBQ==", "dev": true, "requires": { - "is-number": "^4.0.0", - "kind-of": "^6.0.0", - "math-random": "^1.0.1" + "is-number": "4.0.0", + "kind-of": "6.0.2", + "math-random": "1.0.1" }, "dependencies": { "is-number": { @@ -14280,10 +14280,10 @@ "integrity": "sha1-zZJL9SAKB1uDwYjNa54hG3/A0+0=", "dev": true, "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" + "deep-extend": "0.6.0", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" }, "dependencies": { "minimist": { @@ -14300,8 +14300,8 @@ "integrity": "sha1-NcPhd/IHjveJ7kv6+kNzB06u9Po=", "dev": true, "requires": { - "pinkie-promise": "^2.0.0", - "readable-stream": "^2.0.0" + "pinkie-promise": "2.0.1", + "readable-stream": "2.3.6" }, "dependencies": { "isarray": { @@ -14316,13 +14316,13 @@ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -14331,7 +14331,7 @@ "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } } } @@ -14342,9 +14342,9 @@ "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", "dev": true, "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" + "load-json-file": "1.1.0", + "normalize-package-data": "2.4.0", + "path-type": "1.1.0" } }, "read-pkg-up": { @@ -14353,8 +14353,8 @@ "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", "dev": true, "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" + "find-up": "1.1.2", + "read-pkg": "1.1.0" } }, "readable-stream": { @@ -14363,10 +14363,10 @@ "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", + "core-util-is": "1.0.2", + "inherits": "2.0.3", "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "string_decoder": "0.10.31" } }, "readdirp": { @@ -14375,9 +14375,9 @@ "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", "dev": true, "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" + "graceful-fs": "4.1.11", + "micromatch": "3.1.10", + "readable-stream": "2.3.6" }, "dependencies": { "graceful-fs": { @@ -14398,13 +14398,13 @@ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -14413,7 +14413,7 @@ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } } } @@ -14424,7 +14424,7 @@ "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", "dev": true, "requires": { - "resolve": "^1.1.6" + "resolve": "1.8.1" } }, "redent": { @@ -14433,8 +14433,8 @@ "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", "dev": true, "requires": { - "indent-string": "^2.1.0", - "strip-indent": "^1.0.1" + "indent-string": "2.1.0", + "strip-indent": "1.0.1" } }, "redis": { @@ -14444,9 +14444,9 @@ "dev": true, "optional": true, "requires": { - "double-ended-queue": "^2.1.0-0", - "redis-commands": "^1.2.0", - "redis-parser": "^2.6.0" + "double-ended-queue": "2.1.0-0", + "redis-commands": "1.3.5", + "redis-parser": "2.6.0" } }, "redis-commands": { @@ -14469,9 +14469,9 @@ "integrity": "sha1-dHyRTgSWFKTJz7umKYca0dKSdxY=", "dev": true, "requires": { - "balanced-match": "^0.4.2", - "math-expression-evaluator": "^1.2.14", - "reduce-function-call": "^1.0.1" + "balanced-match": "0.4.2", + "math-expression-evaluator": "1.2.17", + "reduce-function-call": "1.0.2" }, "dependencies": { "balanced-match": { @@ -14488,7 +14488,7 @@ "integrity": "sha1-WiAL+S4ON3UXUv5FsKszD9S2vpk=", "dev": true, "requires": { - "balanced-match": "^0.4.2" + "balanced-match": "0.4.2" }, "dependencies": { "balanced-match": { @@ -14511,7 +14511,7 @@ "integrity": "sha512-s5NGghCE4itSlUS+0WUj88G6cfMVMmH8boTPNvABf8od+2dhT9WDlWu8n01raQAJZMOK8Ch6jSexaRO7swd6aw==", "dev": true, "requires": { - "regenerate": "^1.4.0" + "regenerate": "1.4.0" } }, "regenerator-transform": { @@ -14520,7 +14520,7 @@ "integrity": "sha512-5ipTrZFSq5vU2YoGoww4uaRVAK4wyYC4TSICibbfEPOruUu8FFP7ErV0BjmbIOEpn3O/k9na9UEdYR/3m7N6uA==", "dev": true, "requires": { - "private": "^0.1.6" + "private": "0.1.8" } }, "regex-cache": { @@ -14529,7 +14529,7 @@ "integrity": "sha1-db3FiioUls7EihKDW8VMjVYjNt0=", "dev": true, "requires": { - "is-equal-shallow": "^0.1.3" + "is-equal-shallow": "0.1.3" } }, "regex-not": { @@ -14538,8 +14538,8 @@ "integrity": "sha1-H07OJ+ALC2XgJHpoEOaoXYOldSw=", "dev": true, "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" + "extend-shallow": "3.0.2", + "safe-regex": "1.1.0" } }, "regexpp": { @@ -14554,12 +14554,12 @@ "integrity": "sha512-Z835VSnJJ46CNBttalHD/dB+Sj2ezmY6Xp38npwU87peK6mqOzOpV8eYktdkLTEkzzD+JsTcxd84ozd8I14+rw==", "dev": true, "requires": { - "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^7.0.0", - "regjsgen": "^0.4.0", - "regjsparser": "^0.3.0", - "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.0.2" + "regenerate": "1.4.0", + "regenerate-unicode-properties": "7.0.0", + "regjsgen": "0.4.0", + "regjsparser": "0.3.0", + "unicode-match-property-ecmascript": "1.0.4", + "unicode-match-property-value-ecmascript": "1.0.2" } }, "regjsgen": { @@ -14574,7 +14574,7 @@ "integrity": "sha512-zza72oZBBHzt64G7DxdqrOo/30bhHkwMUoT0WqfGu98XLd7N+1tsy5MJ96Bk4MD0y74n629RhmrGW6XlnLLwCA==", "dev": true, "requires": { - "jsesc": "~0.5.0" + "jsesc": "0.5.0" }, "dependencies": { "jsesc": { @@ -14609,7 +14609,7 @@ "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", "dev": true, "requires": { - "is-finite": "^1.0.0" + "is-finite": "1.0.2" } }, "replace-ext": { @@ -14624,28 +14624,28 @@ "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", "dev": true, "requires": { - "aws-sign2": "~0.6.0", - "aws4": "^1.2.1", - "caseless": "~0.12.0", - "combined-stream": "~1.0.5", - "extend": "~3.0.0", - "forever-agent": "~0.6.1", - "form-data": "~2.1.1", - "har-validator": "~4.2.1", - "hawk": "~3.1.3", - "http-signature": "~1.1.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.7", - "oauth-sign": "~0.8.1", - "performance-now": "^0.2.0", - "qs": "~6.4.0", - "safe-buffer": "^5.0.1", - "stringstream": "~0.0.4", - "tough-cookie": "~2.3.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.0.0" + "aws-sign2": "0.6.0", + "aws4": "1.8.0", + "caseless": "0.12.0", + "combined-stream": "1.0.7", + "extend": "3.0.2", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.20", + "oauth-sign": "0.8.2", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.1.2", + "stringstream": "0.0.6", + "tough-cookie": "2.3.4", + "tunnel-agent": "0.6.0", + "uuid": "3.3.2" }, "dependencies": { "qs": { @@ -14660,7 +14660,7 @@ "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "dev": true, "requires": { - "safe-buffer": "^5.0.1" + "safe-buffer": "5.1.2" } } } @@ -14671,7 +14671,7 @@ "integrity": "sha1-XTa7V5YcZzqlt4jbyBQf3yO0Tgg=", "dev": true, "requires": { - "throttleit": "^1.0.0" + "throttleit": "1.0.0" } }, "requestretry": { @@ -14681,10 +14681,10 @@ "dev": true, "optional": true, "requires": { - "extend": "^3.0.0", - "lodash": "^4.15.0", - "request": "^2.74.0", - "when": "^3.7.7" + "extend": "3.0.2", + "lodash": "4.17.11", + "request": "2.81.0", + "when": "3.7.8" } }, "require-from-string": { @@ -14699,8 +14699,8 @@ "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", "dev": true, "requires": { - "caller-path": "^0.1.0", - "resolve-from": "^1.0.0" + "caller-path": "0.1.0", + "resolve-from": "1.0.1" } }, "requires-port": { @@ -14715,7 +14715,7 @@ "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", "dev": true, "requires": { - "path-parse": "^1.0.5" + "path-parse": "1.0.6" } }, "resolve-dir": { @@ -14724,8 +14724,8 @@ "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", "dev": true, "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" + "expand-tilde": "2.0.2", + "global-modules": "1.0.0" } }, "resolve-from": { @@ -14746,8 +14746,8 @@ "integrity": "sha1-/6cbq5UtYvfB1Jt0NDVfvGjf/Fo=", "dev": true, "requires": { - "depd": "~1.1.0", - "on-headers": "~1.0.1" + "depd": "1.1.2", + "on-headers": "1.0.1" }, "dependencies": { "depd": { @@ -14764,8 +14764,8 @@ "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", "dev": true, "requires": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" + "onetime": "2.0.1", + "signal-exit": "3.0.2" } }, "ret": { @@ -14780,7 +14780,7 @@ "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", "dev": true, "requires": { - "align-text": "^0.1.1" + "align-text": "0.1.4" } }, "rimraf": { @@ -14789,7 +14789,7 @@ "integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=", "dev": true, "requires": { - "glob": "^7.0.5" + "glob": "7.1.3" } }, "rndm": { @@ -14804,7 +14804,7 @@ "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", "dev": true, "requires": { - "is-promise": "^2.1.0" + "is-promise": "2.1.0" } }, "run-sequence": { @@ -14813,9 +14813,9 @@ "integrity": "sha1-HOZD2jb9jH6n4akynaM/wriJhJU=", "dev": true, "requires": { - "chalk": "^1.1.3", - "fancy-log": "^1.3.2", - "plugin-error": "^0.1.2" + "chalk": "1.1.3", + "fancy-log": "1.3.2", + "plugin-error": "0.1.2" }, "dependencies": { "arr-diff": { @@ -14824,8 +14824,8 @@ "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", "dev": true, "requires": { - "arr-flatten": "^1.0.1", - "array-slice": "^0.2.3" + "arr-flatten": "1.1.0", + "array-slice": "0.2.3" } }, "arr-union": { @@ -14846,7 +14846,7 @@ "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", "dev": true, "requires": { - "kind-of": "^1.1.0" + "kind-of": "1.1.0" } }, "kind-of": { @@ -14861,11 +14861,11 @@ "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", "dev": true, "requires": { - "ansi-cyan": "^0.1.1", - "ansi-red": "^0.1.1", - "arr-diff": "^1.0.1", - "arr-union": "^2.0.1", - "extend-shallow": "^1.1.2" + "ansi-cyan": "0.1.1", + "ansi-red": "0.1.1", + "arr-diff": "1.1.0", + "arr-union": "2.1.0", + "extend-shallow": "1.1.4" } } } @@ -14876,7 +14876,7 @@ "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==", "dev": true, "requires": { - "tslib": "^1.9.0" + "tslib": "1.9.3" } }, "safe-buffer": { @@ -14891,7 +14891,7 @@ "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "dev": true, "requires": { - "ret": "~0.1.10" + "ret": "0.1.15" } }, "safer-buffer": { @@ -14912,7 +14912,7 @@ "integrity": "sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=", "dev": true, "requires": { - "commander": "~2.8.1" + "commander": "2.8.1" } }, "select": { @@ -14940,7 +14940,7 @@ "dev": true, "optional": true, "requires": { - "semver": "^5.3.0" + "semver": "5.5.1" }, "dependencies": { "semver": { @@ -14958,18 +14958,18 @@ "integrity": "sha1-dl52B8gFVFK7pvCwUllTUJhgNt4=", "dev": true, "requires": { - "debug": "~2.2.0", - "depd": "~1.1.0", - "destroy": "~1.0.4", - "escape-html": "~1.0.3", - "etag": "~1.7.0", + "debug": "2.2.0", + "depd": "1.1.2", + "destroy": "1.0.4", + "escape-html": "1.0.3", + "etag": "1.7.0", "fresh": "0.3.0", - "http-errors": "~1.3.1", + "http-errors": "1.3.1", "mime": "1.3.4", "ms": "0.7.1", - "on-finished": "~2.3.0", - "range-parser": "~1.0.3", - "statuses": "~1.2.1" + "on-finished": "2.3.0", + "range-parser": "1.0.3", + "statuses": "1.2.1" }, "dependencies": { "debug": { @@ -15013,10 +15013,10 @@ "integrity": "sha1-3UGeJo3gEqtysxnTN/IQUBP5OB8=", "dev": true, "requires": { - "etag": "~1.7.0", + "etag": "1.7.0", "fresh": "0.3.0", "ms": "0.7.2", - "parseurl": "~1.3.1" + "parseurl": "1.3.2" }, "dependencies": { "ms": { @@ -15033,13 +15033,13 @@ "integrity": "sha1-egV/xu4o3GP2RWbl+lexEahq7NI=", "dev": true, "requires": { - "accepts": "~1.2.13", + "accepts": "1.2.13", "batch": "0.5.3", - "debug": "~2.2.0", - "escape-html": "~1.0.3", - "http-errors": "~1.3.1", - "mime-types": "~2.1.9", - "parseurl": "~1.3.1" + "debug": "2.2.0", + "escape-html": "1.0.3", + "http-errors": "1.3.1", + "mime-types": "2.1.20", + "parseurl": "1.3.2" }, "dependencies": { "debug": { @@ -15065,8 +15065,8 @@ "integrity": "sha1-zlpuzTEB/tXsCYJ9rCKpwpv7BTU=", "dev": true, "requires": { - "escape-html": "~1.0.3", - "parseurl": "~1.3.1", + "escape-html": "1.0.3", + "parseurl": "1.3.2", "send": "0.13.2" } }, @@ -15082,10 +15082,10 @@ "integrity": "sha1-ca5KiPD+77v1LR6mBPP7MV67YnQ=", "dev": true, "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "split-string": "3.1.0" }, "dependencies": { "extend-shallow": { @@ -15094,7 +15094,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } } } @@ -15111,7 +15111,7 @@ "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", "dev": true, "requires": { - "shebang-regex": "^1.0.0" + "shebang-regex": "1.0.0" } }, "shebang-regex": { @@ -15137,7 +15137,7 @@ "resolved": "https://registry.npmjs.org/signalr/-/signalr-2.3.0.tgz", "integrity": "sha512-NrvIGftLz3QVujdjCvaNso56ltTr1FowSR0DCIaSOJ3J4t5pTebTfnh2VT0HHIM3PJ/v15lukIL4y+8MMknqzg==", "requires": { - "jquery": ">=1.6.4" + "jquery": "2.2.4" } }, "slack-node": { @@ -15147,7 +15147,7 @@ "dev": true, "optional": true, "requires": { - "requestretry": "^1.2.2" + "requestretry": "1.13.0" } }, "slash": { @@ -15162,7 +15162,7 @@ "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", "dev": true, "requires": { - "is-fullwidth-code-point": "^2.0.0" + "is-fullwidth-code-point": "2.0.0" } }, "smart-buffer": { @@ -15187,14 +15187,14 @@ "integrity": "sha1-ZJIufFZbDhQgS6GqfWlkJ40lGC0=", "dev": true, "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" + "base": "0.11.2", + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "map-cache": "0.2.2", + "source-map": "0.5.7", + "source-map-resolve": "0.5.2", + "use": "3.1.1" }, "dependencies": { "define-property": { @@ -15203,7 +15203,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "is-descriptor": "0.1.6" } }, "extend-shallow": { @@ -15212,7 +15212,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } } } @@ -15223,9 +15223,9 @@ "integrity": "sha1-bBdfhv8UvbByRWPo88GwIaKGhTs=", "dev": true, "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" + "define-property": "1.0.0", + "isobject": "3.0.1", + "snapdragon-util": "3.0.1" }, "dependencies": { "define-property": { @@ -15234,7 +15234,7 @@ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "^1.0.0" + "is-descriptor": "1.0.2" } }, "is-accessor-descriptor": { @@ -15243,7 +15243,7 @@ "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", "dev": true, "requires": { - "kind-of": "^6.0.0" + "kind-of": "6.0.2" } }, "is-data-descriptor": { @@ -15252,7 +15252,7 @@ "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", "dev": true, "requires": { - "kind-of": "^6.0.0" + "kind-of": "6.0.2" } }, "is-descriptor": { @@ -15261,9 +15261,9 @@ "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", "dev": true, "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" } } } @@ -15274,7 +15274,7 @@ "integrity": "sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI=", "dev": true, "requires": { - "kind-of": "^3.2.0" + "kind-of": "3.2.2" }, "dependencies": { "kind-of": { @@ -15283,7 +15283,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -15294,7 +15294,7 @@ "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", "dev": true, "requires": { - "hoek": "2.x.x" + "hoek": "2.16.3" } }, "socket.io": { @@ -15303,11 +15303,11 @@ "integrity": "sha1-waRZDO/4fs8TxyZS8Eb3FrKeYBQ=", "dev": true, "requires": { - "debug": "~2.6.6", - "engine.io": "~3.1.0", - "socket.io-adapter": "~1.1.0", + "debug": "2.6.9", + "engine.io": "3.1.5", + "socket.io-adapter": "1.1.1", "socket.io-client": "2.0.4", - "socket.io-parser": "~3.1.1" + "socket.io-parser": "3.1.3" } }, "socket.io-adapter": { @@ -15326,14 +15326,14 @@ "base64-arraybuffer": "0.1.5", "component-bind": "1.0.0", "component-emitter": "1.2.1", - "debug": "~2.6.4", - "engine.io-client": "~3.1.0", + "debug": "2.6.9", + "engine.io-client": "3.1.6", "has-cors": "1.1.0", "indexof": "0.0.1", "object-component": "0.0.3", "parseqs": "0.0.5", "parseuri": "0.0.5", - "socket.io-parser": "~3.1.1", + "socket.io-parser": "3.1.3", "to-array": "0.1.4" } }, @@ -15344,8 +15344,8 @@ "dev": true, "requires": { "component-emitter": "1.2.1", - "debug": "~3.1.0", - "has-binary2": "~1.0.2", + "debug": "3.1.0", + "has-binary2": "1.0.3", "isarray": "2.0.1" }, "dependencies": { @@ -15372,8 +15372,8 @@ "integrity": "sha512-0GabKw7n9mI46vcNrVfs0o6XzWzjVa3h6GaSo2UPxtWAROXUWavfJWh1M4PR5tnE0dcnQXZIDFP4yrAysLze/w==", "dev": true, "requires": { - "ip": "^1.1.5", - "smart-buffer": "^4.0.1" + "ip": "1.1.5", + "smart-buffer": "4.0.1" } }, "socks-proxy-agent": { @@ -15382,8 +15382,8 @@ "integrity": "sha512-Kezx6/VBguXOsEe5oU3lXYyKMi4+gva72TwJ7pQY5JfqUx2nMk7NXA6z/mpNqIlfQjWYVfeuNvQjexiTaTn6Nw==", "dev": true, "requires": { - "agent-base": "~4.2.0", - "socks": "~2.2.0" + "agent-base": "4.2.1", + "socks": "2.2.1" } }, "sort-keys": { @@ -15392,7 +15392,7 @@ "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", "dev": true, "requires": { - "is-plain-obj": "^1.0.0" + "is-plain-obj": "1.1.0" } }, "source-map": { @@ -15407,11 +15407,11 @@ "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", "dev": true, "requires": { - "atob": "^2.1.1", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" + "atob": "2.1.2", + "decode-uri-component": "0.2.0", + "resolve-url": "0.2.1", + "source-map-url": "0.4.0", + "urix": "0.1.0" } }, "source-map-url": { @@ -15432,8 +15432,8 @@ "integrity": "sha512-hxSPZbRZvSDuOvADntOElzJpenIR7wXJkuoUcUtS0erbgt2fgeaoPIYretfKpslMhfFDY4k0MZ2F5CUzhBsSvQ==", "dev": true, "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" + "spdx-expression-parse": "3.0.0", + "spdx-license-ids": "3.0.1" } }, "spdx-exceptions": { @@ -15448,8 +15448,8 @@ "integrity": "sha1-meEZt6XaAOBUkcn6M4t5BII7QdA=", "dev": true, "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "spdx-exceptions": "2.2.0", + "spdx-license-ids": "3.0.1" } }, "spdx-license-ids": { @@ -15464,7 +15464,7 @@ "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", "dev": true, "requires": { - "through": "2" + "through": "2.3.8" } }, "split-string": { @@ -15473,7 +15473,7 @@ "integrity": "sha1-fLCd2jqGWFcFxks5pkZgOGguj+I=", "dev": true, "requires": { - "extend-shallow": "^3.0.0" + "extend-shallow": "3.0.2" } }, "sprintf-js": { @@ -15489,9 +15489,9 @@ "dev": true, "optional": true, "requires": { - "chalk": "^1.0.0", - "console-stream": "^0.1.1", - "lpad-align": "^1.0.1" + "chalk": "1.1.3", + "console-stream": "0.1.1", + "lpad-align": "1.1.2" } }, "sshpk": { @@ -15500,15 +15500,15 @@ "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", "dev": true, "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" + "asn1": "0.2.4", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.2", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.2", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "safer-buffer": "2.1.2", + "tweetnacl": "0.14.5" }, "dependencies": { "assert-plus": { @@ -15538,8 +15538,8 @@ "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", "dev": true, "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" + "define-property": "0.2.5", + "object-copy": "0.1.0" }, "dependencies": { "define-property": { @@ -15548,7 +15548,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "is-descriptor": "0.1.6" } } } @@ -15565,8 +15565,8 @@ "integrity": "sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=", "dev": true, "requires": { - "duplexer": "~0.1.1", - "through": "~2.3.4" + "duplexer": "0.1.1", + "through": "2.3.8" } }, "stream-combiner2": { @@ -15575,8 +15575,8 @@ "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", "dev": true, "requires": { - "duplexer2": "~0.1.0", - "readable-stream": "^2.0.2" + "duplexer2": "0.1.4", + "readable-stream": "2.3.6" }, "dependencies": { "duplexer2": { @@ -15585,7 +15585,7 @@ "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", "dev": true, "requires": { - "readable-stream": "^2.0.2" + "readable-stream": "2.3.6" } }, "isarray": { @@ -15600,13 +15600,13 @@ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -15615,7 +15615,7 @@ "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } } } @@ -15632,7 +15632,7 @@ "integrity": "sha1-3tJmVWMZyLDiIoErnPOyb6fZR94=", "dev": true, "requires": { - "readable-stream": "~1.1.8" + "readable-stream": "1.1.14" } }, "stream-shift": { @@ -15647,10 +15647,10 @@ "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", "dev": true, "requires": { - "date-format": "^1.2.0", - "debug": "^3.1.0", - "mkdirp": "^0.5.1", - "readable-stream": "^2.3.0" + "date-format": "1.2.0", + "debug": "3.2.5", + "mkdirp": "0.5.1", + "readable-stream": "2.3.6" }, "dependencies": { "debug": { @@ -15659,7 +15659,7 @@ "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.1" } }, "isarray": { @@ -15680,13 +15680,13 @@ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -15695,7 +15695,7 @@ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } } } @@ -15712,8 +15712,8 @@ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" }, "dependencies": { "ansi-regex": { @@ -15728,7 +15728,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "3.0.0" } } } @@ -15751,7 +15751,7 @@ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "2.1.1" } }, "strip-bom": { @@ -15760,8 +15760,8 @@ "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", "dev": true, "requires": { - "first-chunk-stream": "^1.0.0", - "is-utf8": "^0.2.0" + "first-chunk-stream": "1.0.0", + "is-utf8": "0.2.1" } }, "strip-bom-stream": { @@ -15770,8 +15770,8 @@ "integrity": "sha1-5xRDmFd9Uaa+0PoZlPoF9D/ZiO4=", "dev": true, "requires": { - "first-chunk-stream": "^1.0.0", - "strip-bom": "^2.0.0" + "first-chunk-stream": "1.0.0", + "strip-bom": "2.0.0" }, "dependencies": { "strip-bom": { @@ -15780,7 +15780,7 @@ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "dev": true, "requires": { - "is-utf8": "^0.2.0" + "is-utf8": "0.2.1" } } } @@ -15791,12 +15791,12 @@ "integrity": "sha1-lgu9EoeETzl1pFWKoQOoJV4kVqA=", "dev": true, "requires": { - "chalk": "^1.0.0", - "get-stdin": "^4.0.1", - "is-absolute": "^0.1.5", - "is-natural-number": "^2.0.0", - "minimist": "^1.1.0", - "sum-up": "^1.0.1" + "chalk": "1.1.3", + "get-stdin": "4.0.1", + "is-absolute": "0.1.7", + "is-natural-number": "2.1.1", + "minimist": "1.2.0", + "sum-up": "1.0.3" }, "dependencies": { "is-absolute": { @@ -15805,7 +15805,7 @@ "integrity": "sha1-hHSREZ/MtftDYhfMc39/qtUPYD8=", "dev": true, "requires": { - "is-relative": "^0.1.0" + "is-relative": "0.1.3" } }, "is-relative": { @@ -15835,7 +15835,7 @@ "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", "dev": true, "requires": { - "get-stdin": "^4.0.1" + "get-stdin": "4.0.1" } }, "strip-json-comments": { @@ -15850,7 +15850,7 @@ "integrity": "sha1-sv0qv2YEudHmATBXGV34Nrip1jE=", "dev": true, "requires": { - "escape-string-regexp": "^1.0.2" + "escape-string-regexp": "1.0.5" } }, "sum-up": { @@ -15859,7 +15859,7 @@ "integrity": "sha1-HGYfZnBX9jvLeHWqFDi8FiUlFW4=", "dev": true, "requires": { - "chalk": "^1.0.0" + "chalk": "1.1.3" } }, "supports-color": { @@ -15868,7 +15868,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "^1.0.0" + "has-flag": "1.0.0" } }, "svgo": { @@ -15877,13 +15877,13 @@ "integrity": "sha1-n1dyQTlSE1xv779Ar+ak+qiLS7U=", "dev": true, "requires": { - "coa": "~1.0.1", - "colors": "~1.1.2", - "csso": "~2.3.1", - "js-yaml": "~3.7.0", - "mkdirp": "~0.5.1", - "sax": "~1.2.1", - "whet.extend": "~0.9.9" + "coa": "1.0.4", + "colors": "1.1.2", + "csso": "2.3.2", + "js-yaml": "3.7.0", + "mkdirp": "0.5.1", + "sax": "1.2.4", + "whet.extend": "0.9.9" }, "dependencies": { "colors": { @@ -15900,12 +15900,12 @@ "integrity": "sha512-S7rnFITmBH1EnyKcvxBh1LjYeQMmnZtCXSEbHcH6S0NoKit24ZuFO/T1vDcLdYsLQkM188PVVhQmzKIuThNkKg==", "dev": true, "requires": { - "ajv": "^6.0.1", - "ajv-keywords": "^3.0.0", - "chalk": "^2.1.0", - "lodash": "^4.17.4", + "ajv": "6.5.4", + "ajv-keywords": "3.2.0", + "chalk": "2.4.1", + "lodash": "4.17.11", "slice-ansi": "1.0.0", - "string-width": "^2.1.1" + "string-width": "2.1.1" }, "dependencies": { "ansi-styles": { @@ -15914,7 +15914,7 @@ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { - "color-convert": "^1.9.0" + "color-convert": "1.9.3" } }, "chalk": { @@ -15923,9 +15923,9 @@ "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.5.0" } }, "has-flag": { @@ -15940,7 +15940,7 @@ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "3.0.0" } } } @@ -15951,13 +15951,13 @@ "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", "dev": true, "requires": { - "bl": "^1.0.0", - "buffer-alloc": "^1.2.0", - "end-of-stream": "^1.0.0", - "fs-constants": "^1.0.0", - "readable-stream": "^2.3.0", - "to-buffer": "^1.1.1", - "xtend": "^4.0.0" + "bl": "1.2.2", + "buffer-alloc": "1.2.0", + "end-of-stream": "1.4.1", + "fs-constants": "1.0.0", + "readable-stream": "2.3.6", + "to-buffer": "1.1.1", + "xtend": "4.0.1" }, "dependencies": { "end-of-stream": { @@ -15966,7 +15966,7 @@ "integrity": "sha1-7SljTRm6ukY7bOa4CjchPqtx7EM=", "dev": true, "requires": { - "once": "^1.4.0" + "once": "1.4.0" } }, "isarray": { @@ -15981,13 +15981,13 @@ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -15996,7 +15996,7 @@ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } } } @@ -16015,8 +16015,8 @@ "dev": true, "optional": true, "requires": { - "temp-dir": "^1.0.0", - "uuid": "^3.0.1" + "temp-dir": "1.0.0", + "uuid": "3.3.2" } }, "text-table": { @@ -16043,8 +16043,8 @@ "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", "dev": true, "requires": { - "readable-stream": "^2.1.5", - "xtend": "~4.0.1" + "readable-stream": "2.3.6", + "xtend": "4.0.1" }, "dependencies": { "isarray": { @@ -16059,13 +16059,13 @@ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -16074,7 +16074,7 @@ "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } } } @@ -16085,7 +16085,7 @@ "integrity": "sha1-EctOpMnjG8puTB5tukjRxyjDUks=", "dev": true, "requires": { - "through2": "^2.0.0" + "through2": "2.0.3" } }, "through2-filter": { @@ -16094,8 +16094,8 @@ "integrity": "sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=", "dev": true, "requires": { - "through2": "~2.0.0", - "xtend": "~4.0.0" + "through2": "2.0.3", + "xtend": "4.0.1" } }, "thunkify": { @@ -16111,7 +16111,7 @@ "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", "dev": true, "requires": { - "os-homedir": "^1.0.0" + "os-homedir": "1.0.2" } }, "time-stamp": { @@ -16144,12 +16144,12 @@ "integrity": "sha1-s/26gC5dVqM8L28QeUsy5Hescp0=", "dev": true, "requires": { - "body-parser": "~1.14.0", - "debug": "~2.2.0", - "faye-websocket": "~0.10.0", - "livereload-js": "^2.2.0", - "parseurl": "~1.3.0", - "qs": "~5.1.0" + "body-parser": "1.14.2", + "debug": "2.2.0", + "faye-websocket": "0.10.0", + "livereload-js": "2.3.0", + "parseurl": "1.3.2", + "qs": "5.1.0" }, "dependencies": { "body-parser": { @@ -16159,15 +16159,15 @@ "dev": true, "requires": { "bytes": "2.2.0", - "content-type": "~1.0.1", - "debug": "~2.2.0", - "depd": "~1.1.0", - "http-errors": "~1.3.1", + "content-type": "1.0.4", + "debug": "2.2.0", + "depd": "1.1.2", + "http-errors": "1.3.1", "iconv-lite": "0.4.13", - "on-finished": "~2.3.0", + "on-finished": "2.3.0", "qs": "5.2.0", - "raw-body": "~2.1.5", - "type-is": "~1.6.10" + "raw-body": "2.1.7", + "type-is": "1.6.16" }, "dependencies": { "qs": { @@ -16230,7 +16230,7 @@ "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dev": true, "requires": { - "os-tmpdir": "~1.0.2" + "os-tmpdir": "1.0.2" } }, "to-absolute-glob": { @@ -16239,7 +16239,7 @@ "integrity": "sha1-HN+kcqnvUMI57maZm2YsoOs5k38=", "dev": true, "requires": { - "extend-shallow": "^2.0.1" + "extend-shallow": "2.0.1" }, "dependencies": { "extend-shallow": { @@ -16248,7 +16248,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } } } @@ -16277,7 +16277,7 @@ "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", "dev": true, "requires": { - "kind-of": "^3.0.2" + "kind-of": "3.2.2" }, "dependencies": { "kind-of": { @@ -16286,7 +16286,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -16297,10 +16297,10 @@ "integrity": "sha1-E8/dmzNlUvMLUfM6iuG0Knp1mc4=", "dev": true, "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "regex-not": "1.0.2", + "safe-regex": "1.1.0" } }, "to-regex-range": { @@ -16309,8 +16309,8 @@ "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", "dev": true, "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" + "is-number": "3.0.0", + "repeat-string": "1.6.1" } }, "tough-cookie": { @@ -16319,7 +16319,7 @@ "integrity": "sha1-7GDO44rGdQY//JelwYlwV47oNlU=", "dev": true, "requires": { - "punycode": "^1.4.1" + "punycode": "1.4.1" }, "dependencies": { "punycode": { @@ -16342,7 +16342,7 @@ "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=", "dev": true, "requires": { - "escape-string-regexp": "^1.0.2" + "escape-string-regexp": "1.0.5" } }, "trim-right": { @@ -16388,7 +16388,7 @@ "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", "dev": true, "requires": { - "prelude-ls": "~1.1.2" + "prelude-ls": "1.1.2" } }, "type-is": { @@ -16398,7 +16398,7 @@ "dev": true, "requires": { "media-typer": "0.3.0", - "mime-types": "~2.1.18" + "mime-types": "2.1.20" } }, "typeahead.js": { @@ -16418,9 +16418,9 @@ "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", "dev": true, "requires": { - "source-map": "~0.5.1", - "uglify-to-browserify": "~1.0.0", - "yargs": "~3.10.0" + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" } }, "uglify-to-browserify": { @@ -16436,7 +16436,7 @@ "integrity": "sha1-Otbzg2jG1MjHXsF2I/t5qh0HHYE=", "dev": true, "requires": { - "random-bytes": "~1.0.0" + "random-bytes": "1.0.0" } }, "ultron": { @@ -16468,8 +16468,8 @@ "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", "dev": true, "requires": { - "unicode-canonical-property-names-ecmascript": "^1.0.4", - "unicode-property-aliases-ecmascript": "^1.0.4" + "unicode-canonical-property-names-ecmascript": "1.0.4", + "unicode-property-aliases-ecmascript": "1.0.4" } }, "unicode-match-property-value-ecmascript": { @@ -16490,10 +16490,10 @@ "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", "dev": true, "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^0.4.3" + "arr-union": "3.1.0", + "get-value": "2.0.6", + "is-extendable": "0.1.1", + "set-value": "0.4.3" }, "dependencies": { "extend-shallow": { @@ -16502,7 +16502,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } }, "set-value": { @@ -16511,10 +16511,10 @@ "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", "dev": true, "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.1", - "to-object-path": "^0.3.0" + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "to-object-path": "0.3.0" } } } @@ -16556,8 +16556,8 @@ "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", "dev": true, "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" + "has-value": "0.3.1", + "isobject": "3.0.1" }, "dependencies": { "has-value": { @@ -16566,9 +16566,9 @@ "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", "dev": true, "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" + "get-value": "2.0.6", + "has-values": "0.1.4", + "isobject": "2.1.0" }, "dependencies": { "isobject": { @@ -16614,7 +16614,7 @@ "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", "dev": true, "requires": { - "punycode": "^2.1.0" + "punycode": "2.1.1" } }, "urix": { @@ -16629,7 +16629,7 @@ "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", "dev": true, "requires": { - "prepend-http": "^1.0.1" + "prepend-http": "1.0.4" } }, "url-regex": { @@ -16639,7 +16639,7 @@ "dev": true, "optional": true, "requires": { - "ip-regex": "^1.0.1" + "ip-regex": "1.0.3" } }, "use": { @@ -16660,8 +16660,8 @@ "integrity": "sha1-z1k+9PLRdYdei7ZY6pLhik/QbY4=", "dev": true, "requires": { - "lru-cache": "2.2.x", - "tmp": "0.0.x" + "lru-cache": "2.2.4", + "tmp": "0.0.33" }, "dependencies": { "lru-cache": { @@ -16685,8 +16685,8 @@ "dev": true, "optional": true, "requires": { - "define-properties": "^1.1.2", - "object.getownpropertydescriptors": "^2.0.3" + "define-properties": "1.1.3", + "object.getownpropertydescriptors": "2.0.3" } }, "utils-merge": { @@ -16714,7 +16714,7 @@ "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", "dev": true, "requires": { - "user-home": "^1.1.1" + "user-home": "1.1.1" } }, "vali-date": { @@ -16729,8 +16729,8 @@ "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" + "spdx-correct": "3.0.1", + "spdx-expression-parse": "3.0.0" } }, "vary": { @@ -16751,9 +16751,9 @@ "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", "dev": true, "requires": { - "assert-plus": "^1.0.0", + "assert-plus": "1.0.0", "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" + "extsprintf": "1.3.0" }, "dependencies": { "assert-plus": { @@ -16776,8 +16776,8 @@ "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", "dev": true, "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", + "clone": "1.0.4", + "clone-stats": "0.0.1", "replace-ext": "0.0.1" } }, @@ -16787,8 +16787,8 @@ "integrity": "sha1-TRmIkbVRWRHXcajNnFSApGoHSkU=", "dev": true, "requires": { - "object-assign": "^4.0.1", - "readable-stream": "^2.0.0" + "object-assign": "4.1.1", + "readable-stream": "2.3.6" }, "dependencies": { "isarray": { @@ -16803,13 +16803,13 @@ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -16818,7 +16818,7 @@ "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } } } @@ -16838,12 +16838,12 @@ "integrity": "sha1-p+v1/779obfRjRQPyweyI++2dRo=", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.3.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0", - "strip-bom-stream": "^2.0.0", - "vinyl": "^1.1.0" + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0", + "strip-bom-stream": "2.0.0", + "vinyl": "1.2.0" }, "dependencies": { "first-chunk-stream": { @@ -16852,7 +16852,7 @@ "integrity": "sha1-G97NuOCDwGZLkZRVgVd6Q6nzHXA=", "dev": true, "requires": { - "readable-stream": "^2.0.2" + "readable-stream": "2.3.6" } }, "graceful-fs": { @@ -16873,13 +16873,13 @@ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -16888,7 +16888,7 @@ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } }, "strip-bom": { @@ -16897,7 +16897,7 @@ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "dev": true, "requires": { - "is-utf8": "^0.2.0" + "is-utf8": "0.2.1" } }, "strip-bom-stream": { @@ -16906,8 +16906,8 @@ "integrity": "sha1-+H217yYT9paKpUWr/h7HKLaoKco=", "dev": true, "requires": { - "first-chunk-stream": "^2.0.0", - "strip-bom": "^2.0.0" + "first-chunk-stream": "2.0.0", + "strip-bom": "2.0.0" } }, "vinyl": { @@ -16916,8 +16916,8 @@ "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", "dev": true, "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", + "clone": "1.0.4", + "clone-stats": "0.0.1", "replace-ext": "0.0.1" } } @@ -16929,14 +16929,14 @@ "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", "dev": true, "requires": { - "defaults": "^1.0.0", - "glob-stream": "^3.1.5", - "glob-watcher": "^0.0.6", - "graceful-fs": "^3.0.0", - "mkdirp": "^0.5.0", - "strip-bom": "^1.0.0", - "through2": "^0.6.1", - "vinyl": "^0.4.0" + "defaults": "1.0.3", + "glob-stream": "3.1.18", + "glob-watcher": "0.0.6", + "graceful-fs": "3.0.11", + "mkdirp": "0.5.1", + "strip-bom": "1.0.0", + "through2": "0.6.5", + "vinyl": "0.4.6" }, "dependencies": { "clone": { @@ -16951,10 +16951,10 @@ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", + "core-util-is": "1.0.2", + "inherits": "2.0.3", "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "string_decoder": "0.10.31" } }, "through2": { @@ -16963,8 +16963,8 @@ "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", "dev": true, "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" + "readable-stream": "1.0.34", + "xtend": "4.0.1" } }, "vinyl": { @@ -16973,8 +16973,8 @@ "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", "dev": true, "requires": { - "clone": "^0.2.0", - "clone-stats": "^0.0.1" + "clone": "0.2.0", + "clone-stats": "0.0.1" } } } @@ -16985,7 +16985,7 @@ "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", "dev": true, "requires": { - "source-map": "^0.5.1" + "source-map": "0.5.7" } }, "void-elements": { @@ -17000,7 +17000,7 @@ "integrity": "sha1-0bFPOdLiy0q4xAmPdW/ksWTkc9Q=", "dev": true, "requires": { - "wrap-fn": "^0.1.0" + "wrap-fn": "0.1.5" } }, "websocket-driver": { @@ -17009,8 +17009,8 @@ "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", "dev": true, "requires": { - "http-parser-js": ">=0.4.0", - "websocket-extensions": ">=0.1.1" + "http-parser-js": "0.4.13", + "websocket-extensions": "0.1.3" } }, "websocket-extensions": { @@ -17037,7 +17037,7 @@ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "requires": { - "isexe": "^2.0.0" + "isexe": "2.0.0" } }, "window-size": { @@ -17080,7 +17080,7 @@ "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", "dev": true, "requires": { - "mkdirp": "^0.5.1" + "mkdirp": "0.5.1" } }, "ws": { @@ -17089,9 +17089,9 @@ "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", "dev": true, "requires": { - "async-limiter": "~1.0.0", - "safe-buffer": "~5.1.0", - "ultron": "~1.1.0" + "async-limiter": "1.0.0", + "safe-buffer": "5.1.2", + "ultron": "1.1.1" } }, "xmlhttprequest-ssl": { @@ -17126,9 +17126,9 @@ "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", "dev": true, "requires": { - "camelcase": "^1.0.2", - "cliui": "^2.1.0", - "decamelize": "^1.0.0", + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", "window-size": "0.1.0" }, "dependencies": { @@ -17146,8 +17146,8 @@ "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", "dev": true, "requires": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" + "buffer-crc32": "0.2.13", + "fd-slicer": "1.1.0" } }, "yeast": { diff --git a/src/Umbraco.Web.UI/Umbraco/dialogs/ChangeDocType.aspx.cs b/src/Umbraco.Web.UI/Umbraco/dialogs/ChangeDocType.aspx.cs index 8111410edd..54464c88e3 100644 --- a/src/Umbraco.Web.UI/Umbraco/dialogs/ChangeDocType.aspx.cs +++ b/src/Umbraco.Web.UI/Umbraco/dialogs/ChangeDocType.aspx.cs @@ -231,7 +231,7 @@ namespace Umbraco.Web.UI.Umbraco.Dialogs if (NewTemplateList.SelectedItem != null) { var templateId = int.Parse(NewTemplateList.SelectedItem.Value); - _content.Template = templateId > 0 ? Services.FileService.GetTemplate(templateId) : null; + _content.TemplateId = templateId; } // Set the property values diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs index 5fddac0c14..54fd749f1b 100644 --- a/src/Umbraco.Web/Editors/ContentController.cs +++ b/src/Umbraco.Web/Editors/ContentController.cs @@ -1427,12 +1427,9 @@ namespace Umbraco.Web.Editors contentSave.PersistedContent.ReleaseDate = contentSave.ReleaseDate; //only set the template if it didn't change - var templateChanged = (contentSave.PersistedContent.Template == null && contentSave.TemplateAlias.IsNullOrWhiteSpace() == false) - || (contentSave.PersistedContent.Template != null && contentSave.PersistedContent.Template.Alias != contentSave.TemplateAlias) - || (contentSave.PersistedContent.Template != null && contentSave.TemplateAlias.IsNullOrWhiteSpace()); - if (templateChanged) + var template = Services.FileService.GetTemplate(contentSave.TemplateAlias); + if (contentSave.PersistedContent.TemplateId != template.Id) { - var template = Services.FileService.GetTemplate(contentSave.TemplateAlias); if (template == null && contentSave.TemplateAlias.IsNullOrWhiteSpace() == false) { //ModelState.AddModelError("Template", "No template exists with the specified alias: " + contentItem.TemplateAlias); @@ -1441,7 +1438,7 @@ namespace Umbraco.Web.Editors else { //NOTE: this could be null if there was a template and the posted template is null, this should remove the assigned template - contentSave.PersistedContent.Template = template; + contentSave.PersistedContent.TemplateId = template.Id; } } } diff --git a/src/Umbraco.Web/Models/Mapping/DefaultTemplateResolver.cs b/src/Umbraco.Web/Models/Mapping/DefaultTemplateResolver.cs index ae32e7a691..07965382f0 100644 --- a/src/Umbraco.Web/Models/Mapping/DefaultTemplateResolver.cs +++ b/src/Umbraco.Web/Models/Mapping/DefaultTemplateResolver.cs @@ -1,24 +1,34 @@ using AutoMapper; +using LightInject; using Umbraco.Core.Models; +using Umbraco.Core.Services; using Umbraco.Web.Models.ContentEditing; namespace Umbraco.Web.Models.Mapping { internal class DefaultTemplateResolver : IValueResolver { + /// + /// Gets or sets the services context. + /// + [Inject] + public ServiceContext Services { get; set; } + public string Resolve(IContent source, ContentItemDisplay destination, string destMember, ResolutionContext context) { - if (source == null || source.Template == null) return null; + if (source == null) + return null; - var alias = source.Template.Alias; + // If no template id was set return default template. + if (source.TemplateId == 0 && !string.IsNullOrWhiteSpace(source.ContentType.DefaultTemplate?.Alias)) + { + var defaultTemplate = Services.FileService.GetTemplate(source.ContentType.DefaultTemplate.Alias); + return defaultTemplate.Alias; + } - //set default template if template isn't set - if (string.IsNullOrEmpty(alias)) - alias = source.ContentType.DefaultTemplate == null - ? string.Empty - : source.ContentType.DefaultTemplate.Alias; + var template = Services.FileService.GetTemplate(source.TemplateId); - return alias; + return template.Alias; } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Web/umbraco.presentation/page.cs b/src/Umbraco.Web/umbraco.presentation/page.cs index e8d395881c..b6fe51552b 100644 --- a/src/Umbraco.Web/umbraco.presentation/page.cs +++ b/src/Umbraco.Web/umbraco.presentation/page.cs @@ -357,10 +357,7 @@ namespace umbraco get { return _key; } } - public int TemplateId - { - get { return _inner.Template == null ? 0 : _inner.Template.Id; } - } + public int TemplateId => _inner.TemplateId; public int SortOrder { From 04d6704766a024ea95792b41cbb639b0c53bd2ec Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Thu, 8 Nov 2018 14:56:43 +0100 Subject: [PATCH 077/469] Change badge color from boolean (alert=true/false) to string (type=warning/error) --- .../src/less/components/umb-editor-navigation.less | 5 ++++- .../src/views/components/editor/umb-editor-navigation.html | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation.less index 1a8a773c91..61cab3b477 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation.less @@ -61,9 +61,12 @@ padding: 2px; line-height: 16px; - &.-alert { + &.-type-alert { background-color: @red-l1; } + &.-type-warning { + background-color: @yellow-d2; + } } .umb-sub-views-nav-item-text { diff --git a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-navigation.html b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-navigation.html index c7dfa26b3c..1f973ea2f6 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-navigation.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-navigation.html @@ -12,7 +12,7 @@ ng-class="{'is-active': item.active, '-has-error': item.hasError}"> {{ item.name }} -
{{item.badge.count}}
+
{{item.badge.count}}
From 2e3cf979d36bb847f97dc09dd613ab43b20c1e89 Mon Sep 17 00:00:00 2001 From: Stefano Chiodino Date: Thu, 8 Nov 2018 13:57:59 +0000 Subject: [PATCH 078/469] #3544: Fix IFileService resolution (now it runs and seem functional) --- src/Umbraco.Web/Editors/ContentController.cs | 26 +++++++++++-------- .../Models/Mapping/DefaultTemplateResolver.cs | 12 +++------ 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs index 54fd749f1b..24be0b942c 100644 --- a/src/Umbraco.Web/Editors/ContentController.cs +++ b/src/Umbraco.Web/Editors/ContentController.cs @@ -1426,19 +1426,23 @@ namespace Umbraco.Web.Editors contentSave.PersistedContent.ExpireDate = contentSave.ExpireDate; contentSave.PersistedContent.ReleaseDate = contentSave.ReleaseDate; - //only set the template if it didn't change - var template = Services.FileService.GetTemplate(contentSave.TemplateAlias); - if (contentSave.PersistedContent.TemplateId != template.Id) + // If the template was set. + if (contentSave.TemplateAlias != null) { - if (template == null && contentSave.TemplateAlias.IsNullOrWhiteSpace() == false) + //only set the template if it didn't change + var template = Services.FileService.GetTemplate(contentSave.TemplateAlias); + if (contentSave.PersistedContent.TemplateId != template.Id) { - //ModelState.AddModelError("Template", "No template exists with the specified alias: " + contentItem.TemplateAlias); - Logger.Warn("No template exists with the specified alias: {TemplateAlias}", contentSave.TemplateAlias); - } - else - { - //NOTE: this could be null if there was a template and the posted template is null, this should remove the assigned template - contentSave.PersistedContent.TemplateId = template.Id; + if (template == null && contentSave.TemplateAlias.IsNullOrWhiteSpace() == false) + { + //ModelState.AddModelError("Template", "No template exists with the specified alias: " + contentItem.TemplateAlias); + Logger.Warn("No template exists with the specified alias: {TemplateAlias}", contentSave.TemplateAlias); + } + else + { + //NOTE: this could be null if there was a template and the posted template is null, this should remove the assigned template + contentSave.PersistedContent.TemplateId = template.Id; + } } } } diff --git a/src/Umbraco.Web/Models/Mapping/DefaultTemplateResolver.cs b/src/Umbraco.Web/Models/Mapping/DefaultTemplateResolver.cs index 07965382f0..a84de9257b 100644 --- a/src/Umbraco.Web/Models/Mapping/DefaultTemplateResolver.cs +++ b/src/Umbraco.Web/Models/Mapping/DefaultTemplateResolver.cs @@ -1,5 +1,6 @@ using AutoMapper; using LightInject; +using System.Web.Mvc; using Umbraco.Core.Models; using Umbraco.Core.Services; using Umbraco.Web.Models.ContentEditing; @@ -8,25 +9,20 @@ namespace Umbraco.Web.Models.Mapping { internal class DefaultTemplateResolver : IValueResolver { - /// - /// Gets or sets the services context. - /// - [Inject] - public ServiceContext Services { get; set; } - public string Resolve(IContent source, ContentItemDisplay destination, string destMember, ResolutionContext context) { + var fileService = DependencyResolver.Current.GetService(); if (source == null) return null; // If no template id was set return default template. if (source.TemplateId == 0 && !string.IsNullOrWhiteSpace(source.ContentType.DefaultTemplate?.Alias)) { - var defaultTemplate = Services.FileService.GetTemplate(source.ContentType.DefaultTemplate.Alias); + var defaultTemplate = fileService.GetTemplate(source.ContentType.DefaultTemplate.Alias); return defaultTemplate.Alias; } - var template = Services.FileService.GetTemplate(source.TemplateId); + var template = fileService.GetTemplate(source.TemplateId); return template.Alias; } From ccd6711a8adda3355c4fe83435cb043216dfa368 Mon Sep 17 00:00:00 2001 From: Stefano Chiodino Date: Thu, 8 Nov 2018 14:30:01 +0000 Subject: [PATCH 079/469] cleanup --- .../Implement/DocumentRepository.cs | 8 +++++--- .../Services/EntityXmlSerializer.cs | 2 +- .../Repositories/DocumentRepositoryTest.cs | 2 +- .../Models/Mapping/DefaultTemplateResolver.cs | 17 ++++++++++------- 4 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs index 78ad16c890..22d4877869 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs @@ -267,7 +267,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement // ensure that the default template is assigned if (entity.TemplateId == 0) - entity.TemplateId = entity.ContentType.DefaultTemplate.Id; + entity.TemplateId = entity.ContentType.DefaultTemplate?.Id ?? 0; // sanitize names SanitizeNames(content, publishing); @@ -405,6 +405,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement else if (content.PublishedState == PublishedState.Unpublishing) { content.Published = false; + content.PublishTemplateId = 0; content.PublisherId = null; content.PublishName = null; content.PublishDate = null; @@ -604,6 +605,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement else if (content.PublishedState == PublishedState.Unpublishing) { content.Published = false; + content.PublishTemplateId = 0; content.PublisherId = null; content.PublishName = null; content.PublishDate = null; @@ -990,9 +992,9 @@ namespace Umbraco.Core.Persistence.Repositories.Implement foreach (var temp in temps) { // complete the item - if (temp.Template1Id.HasValue && templates.TryGetValue(temp.Template1Id.Value, out var template)) + if (temp.Template1Id.HasValue && templates.ContainsKey(temp.Template1Id.Value)) temp.Content.TemplateId = temp.Template1Id.Value; - if (temp.Template2Id.HasValue && templates.TryGetValue(temp.Template2Id.Value, out template)) + if (temp.Template2Id.HasValue && templates.ContainsKey(temp.Template2Id.Value)) temp.Content.PublishTemplateId = temp.Template2Id.Value; if (properties.ContainsKey(temp.VersionId)) diff --git a/src/Umbraco.Core/Services/EntityXmlSerializer.cs b/src/Umbraco.Core/Services/EntityXmlSerializer.cs index 8db4a238f5..a652776c95 100644 --- a/src/Umbraco.Core/Services/EntityXmlSerializer.cs +++ b/src/Umbraco.Core/Services/EntityXmlSerializer.cs @@ -52,7 +52,7 @@ namespace Umbraco.Core.Services xml.Add(new XAttribute("writerName", content.GetWriterProfile(userService)?.Name ?? "??")); xml.Add(new XAttribute("writerID", content.WriterId)); - xml.Add(new XAttribute("template", content.TemplateId.ToString(CultureInfo.InvariantCulture) ?? "0")); + xml.Add(new XAttribute("template", content.TemplateId.ToString(CultureInfo.InvariantCulture))); xml.Add(new XAttribute("isPublished", content.Published)); diff --git a/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs index 37dd1b6919..f48445fae0 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs @@ -432,7 +432,7 @@ namespace Umbraco.Tests.Persistence.Repositories var fetched = repository.Get(textpage.Id); - Assert.Zero(textpage.TemplateId); + Assert.NotZero(textpage.TemplateId); Assert.AreEqual(textpage.TemplateId, contentType.DefaultTemplate.Id); scope.Complete(); diff --git a/src/Umbraco.Web/Models/Mapping/DefaultTemplateResolver.cs b/src/Umbraco.Web/Models/Mapping/DefaultTemplateResolver.cs index a84de9257b..32fc0c7ea0 100644 --- a/src/Umbraco.Web/Models/Mapping/DefaultTemplateResolver.cs +++ b/src/Umbraco.Web/Models/Mapping/DefaultTemplateResolver.cs @@ -1,5 +1,4 @@ using AutoMapper; -using LightInject; using System.Web.Mvc; using Umbraco.Core.Models; using Umbraco.Core.Services; @@ -11,17 +10,21 @@ namespace Umbraco.Web.Models.Mapping { public string Resolve(IContent source, ContentItemDisplay destination, string destMember, ResolutionContext context) { - var fileService = DependencyResolver.Current.GetService(); if (source == null) return null; - // If no template id was set return default template. - if (source.TemplateId == 0 && !string.IsNullOrWhiteSpace(source.ContentType.DefaultTemplate?.Alias)) + // If no template id was set... + if (source.TemplateId == 0) { - var defaultTemplate = fileService.GetTemplate(source.ContentType.DefaultTemplate.Alias); - return defaultTemplate.Alias; - } + // ... and no default template is set, return null... + if (string.IsNullOrWhiteSpace(source.ContentType.DefaultTemplate?.Alias)) + return null; + // ... otherwise return the content type default template alias. + return source.ContentType.DefaultTemplate?.Alias; + } + + var fileService = DependencyResolver.Current.GetService(); var template = fileService.GetTemplate(source.TemplateId); return template.Alias; From 4a4a897ab1d262529c21496cdbc87ecaa1e1578a Mon Sep 17 00:00:00 2001 From: Stefano Chiodino Date: Thu, 8 Nov 2018 16:46:12 +0000 Subject: [PATCH 080/469] Find that DB schema isn't happy with TemplateId being zero, using nullable instead --- src/Umbraco.Core/Models/Content.cs | 8 +++--- src/Umbraco.Core/Models/IContent.cs | 4 +-- .../Services/EntityXmlSerializer.cs | 2 +- src/Umbraco.Tests/Models/ContentTests.cs | 27 +++++++++---------- .../Repositories/DocumentRepositoryTest.cs | 5 ++-- .../Models/Mapping/DefaultTemplateResolver.cs | 4 +-- src/Umbraco.Web/umbraco.presentation/page.cs | 2 +- 7 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/Umbraco.Core/Models/Content.cs b/src/Umbraco.Core/Models/Content.cs index dc86b5e3ce..d408cf9c2e 100644 --- a/src/Umbraco.Core/Models/Content.cs +++ b/src/Umbraco.Core/Models/Content.cs @@ -16,7 +16,7 @@ namespace Umbraco.Core.Models public class Content : ContentBase, IContent { private IContentType _contentType; - private int _templateId; + private int? _templateId; private bool _published; private PublishedState _publishedState; private DateTime? _releaseDate; @@ -84,7 +84,7 @@ namespace Umbraco.Core.Models // ReSharper disable once ClassNeverInstantiated.Local private class PropertySelectors { - public readonly PropertyInfo TemplateSelector = ExpressionHelper.GetPropertyInfo(x => x.TemplateId); + public readonly PropertyInfo TemplateSelector = ExpressionHelper.GetPropertyInfo(x => x.TemplateId); public readonly PropertyInfo PublishedSelector = ExpressionHelper.GetPropertyInfo(x => x.Published); public readonly PropertyInfo ReleaseDateSelector = ExpressionHelper.GetPropertyInfo(x => x.ReleaseDate); public readonly PropertyInfo ExpireDateSelector = ExpressionHelper.GetPropertyInfo(x => x.ExpireDate); @@ -100,7 +100,7 @@ namespace Umbraco.Core.Models /// the Default template from the ContentType will be returned. /// [DataMember] - public virtual int TemplateId + public virtual int? TemplateId { get => _templateId; set => SetPropertyValueAndDetectChanges(value, ref _templateId, Ps.Value.TemplateSelector); @@ -205,7 +205,7 @@ namespace Umbraco.Core.Models /// [IgnoreDataMember] - public int PublishTemplateId { get; internal set; } // set by persistence + public int? PublishTemplateId { get; internal set; } // set by persistence /// [IgnoreDataMember] diff --git a/src/Umbraco.Core/Models/IContent.cs b/src/Umbraco.Core/Models/IContent.cs index 3bb2e7d396..da0aa4a404 100644 --- a/src/Umbraco.Core/Models/IContent.cs +++ b/src/Umbraco.Core/Models/IContent.cs @@ -14,7 +14,7 @@ namespace Umbraco.Core.Models /// /// Gets or sets the template id used to render the content. /// - int TemplateId { get; set; } + int? TemplateId { get; set; } /// /// Gets a value indicating whether the content is published. @@ -42,7 +42,7 @@ namespace Umbraco.Core.Models /// Gets the template id used to render the published version of the content. /// /// When editing the content, the template can change, but this will not until the content is published. - int PublishTemplateId { get; } + int? PublishTemplateId { get; } /// /// Gets the name of the published version of the content. diff --git a/src/Umbraco.Core/Services/EntityXmlSerializer.cs b/src/Umbraco.Core/Services/EntityXmlSerializer.cs index a652776c95..3ba4b60b53 100644 --- a/src/Umbraco.Core/Services/EntityXmlSerializer.cs +++ b/src/Umbraco.Core/Services/EntityXmlSerializer.cs @@ -52,7 +52,7 @@ namespace Umbraco.Core.Services xml.Add(new XAttribute("writerName", content.GetWriterProfile(userService)?.Name ?? "??")); xml.Add(new XAttribute("writerID", content.WriterId)); - xml.Add(new XAttribute("template", content.TemplateId.ToString(CultureInfo.InvariantCulture))); + xml.Add(new XAttribute("template", content.TemplateId?.ToString(CultureInfo.InvariantCulture))); xml.Add(new XAttribute("isPublished", content.Published)); diff --git a/src/Umbraco.Tests/Models/ContentTests.cs b/src/Umbraco.Tests/Models/ContentTests.cs index 8cba508fa9..3f1ca0346b 100644 --- a/src/Umbraco.Tests/Models/ContentTests.cs +++ b/src/Umbraco.Tests/Models/ContentTests.cs @@ -426,19 +426,19 @@ namespace Umbraco.Tests.Models // Assert Assert.IsTrue(content.WasDirty()); - Assert.IsTrue(content.WasPropertyDirty("Id")); - Assert.IsTrue(content.WasPropertyDirty("CreateDate")); - Assert.IsTrue(content.WasPropertyDirty("CreatorId")); - Assert.IsTrue(content.WasPropertyDirty("ExpireDate")); - Assert.IsTrue(content.WasPropertyDirty("Key")); - Assert.IsTrue(content.WasPropertyDirty("Level")); - Assert.IsTrue(content.WasPropertyDirty("Path")); - Assert.IsTrue(content.WasPropertyDirty("ReleaseDate")); - Assert.IsTrue(content.WasPropertyDirty("SortOrder")); - Assert.IsTrue(content.WasPropertyDirty("Template")); - Assert.IsTrue(content.WasPropertyDirty("Trashed")); - Assert.IsTrue(content.WasPropertyDirty("UpdateDate")); - Assert.IsTrue(content.WasPropertyDirty("WriterId")); + Assert.IsTrue(content.WasPropertyDirty(nameof(Content.Id))); + Assert.IsTrue(content.WasPropertyDirty(nameof(Content.CreateDate))); + Assert.IsTrue(content.WasPropertyDirty(nameof(Content.CreatorId))); + Assert.IsTrue(content.WasPropertyDirty(nameof(Content.ExpireDate))); + Assert.IsTrue(content.WasPropertyDirty(nameof(Content.Key))); + Assert.IsTrue(content.WasPropertyDirty(nameof(Content.Level))); + Assert.IsTrue(content.WasPropertyDirty(nameof(Content.Path))); + Assert.IsTrue(content.WasPropertyDirty(nameof(Content.ReleaseDate))); + Assert.IsTrue(content.WasPropertyDirty(nameof(Content.SortOrder))); + Assert.IsTrue(content.WasPropertyDirty(nameof(Content.TemplateId))); + Assert.IsTrue(content.WasPropertyDirty(nameof(Content.Trashed))); + Assert.IsTrue(content.WasPropertyDirty(nameof(Content.UpdateDate))); + Assert.IsTrue(content.WasPropertyDirty(nameof(Content.WriterId))); foreach (var prop in content.Properties) { Assert.IsTrue(prop.WasDirty()); @@ -459,7 +459,6 @@ namespace Umbraco.Tests.Models Assert.IsTrue(culture.Value.WasPropertyDirty("Date")); } //verify child objects were reset too - Assert.Zero(content.TemplateId); Assert.IsTrue(content.ContentType.WasPropertyDirty("UpdateDate")); } diff --git a/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs index f48445fae0..7c5e10dc89 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs @@ -432,7 +432,8 @@ namespace Umbraco.Tests.Persistence.Repositories var fetched = repository.Get(textpage.Id); - Assert.NotZero(textpage.TemplateId); + Assert.True(textpage.TemplateId.HasValue); + Assert.NotZero(textpage.TemplateId.Value); Assert.AreEqual(textpage.TemplateId, contentType.DefaultTemplate.Id); scope.Complete(); @@ -562,7 +563,7 @@ namespace Umbraco.Tests.Persistence.Repositories var updatedContent = repository.Get(NodeDto.NodeIdSeed + 2); - Assert.Zero(updatedContent.TemplateId); + Assert.False(updatedContent.TemplateId.HasValue); } } diff --git a/src/Umbraco.Web/Models/Mapping/DefaultTemplateResolver.cs b/src/Umbraco.Web/Models/Mapping/DefaultTemplateResolver.cs index 32fc0c7ea0..12caf93681 100644 --- a/src/Umbraco.Web/Models/Mapping/DefaultTemplateResolver.cs +++ b/src/Umbraco.Web/Models/Mapping/DefaultTemplateResolver.cs @@ -14,7 +14,7 @@ namespace Umbraco.Web.Models.Mapping return null; // If no template id was set... - if (source.TemplateId == 0) + if (!source.TemplateId.HasValue) { // ... and no default template is set, return null... if (string.IsNullOrWhiteSpace(source.ContentType.DefaultTemplate?.Alias)) @@ -25,7 +25,7 @@ namespace Umbraco.Web.Models.Mapping } var fileService = DependencyResolver.Current.GetService(); - var template = fileService.GetTemplate(source.TemplateId); + var template = fileService.GetTemplate(source.TemplateId.Value); return template.Alias; } diff --git a/src/Umbraco.Web/umbraco.presentation/page.cs b/src/Umbraco.Web/umbraco.presentation/page.cs index b6fe51552b..b74d8c5602 100644 --- a/src/Umbraco.Web/umbraco.presentation/page.cs +++ b/src/Umbraco.Web/umbraco.presentation/page.cs @@ -357,7 +357,7 @@ namespace umbraco get { return _key; } } - public int TemplateId => _inner.TemplateId; + public int TemplateId => _inner.TemplateId ?? 0; public int SortOrder { From 7c971b8366a5a4b72ff1a9ee0c862693e02deafe Mon Sep 17 00:00:00 2001 From: Stefano Chiodino Date: Tue, 13 Nov 2018 16:17:45 +0000 Subject: [PATCH 081/469] Update DocumentRepository.cs --- .../Persistence/Repositories/Implement/DocumentRepository.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs index 22d4877869..02392002a2 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs @@ -405,7 +405,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement else if (content.PublishedState == PublishedState.Unpublishing) { content.Published = false; - content.PublishTemplateId = 0; + content.PublishTemplateId = null; content.PublisherId = null; content.PublishName = null; content.PublishDate = null; From 8183f32399f6960d52bbb77c74ee5559a6afda52 Mon Sep 17 00:00:00 2001 From: Stefano Chiodino Date: Tue, 13 Nov 2018 16:18:40 +0000 Subject: [PATCH 082/469] Update DocumentRepository.cs --- .../Persistence/Repositories/Implement/DocumentRepository.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs index 02392002a2..00c50adb4f 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs @@ -605,7 +605,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement else if (content.PublishedState == PublishedState.Unpublishing) { content.Published = false; - content.PublishTemplateId = 0; + content.PublishTemplateId = null; content.PublisherId = null; content.PublishName = null; content.PublishDate = null; From 6dd260a825e17aec760e04a783c126b61846d706 Mon Sep 17 00:00:00 2001 From: Stefano Chiodino Date: Tue, 13 Nov 2018 16:20:11 +0000 Subject: [PATCH 083/469] Update DocumentRepositoryTest.cs --- .../Persistence/Repositories/DocumentRepositoryTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs index 7c5e10dc89..fd6776225b 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs @@ -558,7 +558,7 @@ namespace Umbraco.Tests.Persistence.Repositories var repository = CreateRepository((IScopeAccessor)provider, out _); var content = repository.Get(NodeDto.NodeIdSeed + 2); - content.TemplateId = 0; + content.TemplateId = null; repository.Save(content); var updatedContent = repository.Get(NodeDto.NodeIdSeed + 2); From 8275050deec61aa19e2eb488752260513de5499f Mon Sep 17 00:00:00 2001 From: Stefano Chiodino Date: Thu, 15 Nov 2018 06:48:03 +0000 Subject: [PATCH 084/469] Comes to terms that we are now using nullables...spread the word to all other types that use a template ID one way or another. --- .../Models/PublishedContent/IPublishedContent.cs | 2 +- .../Models/PublishedContent/PublishedContentWrapped.cs | 2 +- .../Repositories/Implement/DocumentRepository.cs | 10 +++++----- src/Umbraco.Web/umbraco.presentation/page.cs | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Umbraco.Core/Models/PublishedContent/IPublishedContent.cs b/src/Umbraco.Core/Models/PublishedContent/IPublishedContent.cs index 5b604eff3f..75c9e08600 100644 --- a/src/Umbraco.Core/Models/PublishedContent/IPublishedContent.cs +++ b/src/Umbraco.Core/Models/PublishedContent/IPublishedContent.cs @@ -62,7 +62,7 @@ namespace Umbraco.Core.Models.PublishedContent /// /// Gets the identifier of the template to use to render the content item. /// - int TemplateId { get; } + int? TemplateId { get; } /// /// Gets the identifier of the user who created the content item. diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedContentWrapped.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedContentWrapped.cs index 5bdeb3685d..363442486d 100644 --- a/src/Umbraco.Core/Models/PublishedContent/PublishedContentWrapped.cs +++ b/src/Umbraco.Core/Models/PublishedContent/PublishedContentWrapped.cs @@ -73,7 +73,7 @@ namespace Umbraco.Core.Models.PublishedContent public virtual string Path => _content.Path; /// - public virtual int TemplateId => _content.TemplateId; + public virtual int? TemplateId => _content.TemplateId; /// public virtual int CreatorId => _content.CreatorId; diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs index 00c50adb4f..e4dbd03f6d 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs @@ -266,8 +266,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement var publishing = content.PublishedState == PublishedState.Publishing; // ensure that the default template is assigned - if (entity.TemplateId == 0) - entity.TemplateId = entity.ContentType.DefaultTemplate?.Id ?? 0; + if (entity.TemplateId.HasValue == false) + entity.TemplateId = entity.ContentType.DefaultTemplate?.Id; // sanitize names SanitizeNames(content, publishing); @@ -993,9 +993,9 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { // complete the item if (temp.Template1Id.HasValue && templates.ContainsKey(temp.Template1Id.Value)) - temp.Content.TemplateId = temp.Template1Id.Value; + temp.Content.TemplateId = temp.Template1Id; if (temp.Template2Id.HasValue && templates.ContainsKey(temp.Template2Id.Value)) - temp.Content.PublishTemplateId = temp.Template2Id.Value; + temp.Content.PublishTemplateId = temp.Template2Id; if (properties.ContainsKey(temp.VersionId)) temp.Content.Properties = properties[temp.VersionId]; @@ -1028,7 +1028,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement // get template if (dto.DocumentVersionDto.TemplateId.HasValue && dto.DocumentVersionDto.TemplateId.Value > 0) - content.TemplateId = dto.DocumentVersionDto.TemplateId.Value; + content.TemplateId = dto.DocumentVersionDto.TemplateId; // get properties - indexed by version id var versionId = dto.DocumentVersionDto.Id; diff --git a/src/Umbraco.Web/umbraco.presentation/page.cs b/src/Umbraco.Web/umbraco.presentation/page.cs index b74d8c5602..ab82de7294 100644 --- a/src/Umbraco.Web/umbraco.presentation/page.cs +++ b/src/Umbraco.Web/umbraco.presentation/page.cs @@ -88,10 +88,10 @@ namespace umbraco doc.WriterName, doc.CreatorName, doc.CreateDate, doc.UpdateDate, doc.Path, doc.Parent == null ? -1 : doc.Parent.Id); - if (doc.TemplateId > 0) + if (doc.TemplateId.HasValue) { //set the template to whatever is assigned to the doc - _template = doc.TemplateId; + _template = doc.TemplateId.Value; _elements["template"] = _template.ToString(); } @@ -357,7 +357,7 @@ namespace umbraco get { return _key; } } - public int TemplateId => _inner.TemplateId ?? 0; + public int? TemplateId => _inner.TemplateId; public int SortOrder { From cc8cb96140218a289850071120f956ce4420a529 Mon Sep 17 00:00:00 2001 From: Stefano Chiodino Date: Thu, 15 Nov 2018 07:23:09 +0000 Subject: [PATCH 085/469] The change to nullable expands to even more neighbors... --- .../Published/NestedContentTests.cs | 2 +- .../PublishedContentDataTableTests.cs | 2 +- .../PublishedContent/SolidPublishedSnapshot.cs | 2 +- .../TestHelpers/Stubs/TestPublishedContent.cs | 2 +- src/Umbraco.Web/Models/PublishedContentBase.cs | 2 +- .../DataSource/BTree.ContentDataSerializer.cs | 7 +++++-- .../NuCache/DataSource/ContentData.cs | 2 +- .../PublishedCache/NuCache/PublishedContent.cs | 2 +- .../PublishedCache/PublishedMember.cs | 2 +- .../DictionaryPublishedContent.cs | 2 +- .../XmlPublishedCache/XmlPublishedContent.cs | 2 +- src/Umbraco.Web/PublishedContentExtensions.cs | 9 +++++++-- src/Umbraco.Web/Routing/PublishedRouter.cs | 9 ++++++--- src/Umbraco.Web/Templates/TemplateRenderer.cs | 16 +++++++++------- 14 files changed, 37 insertions(+), 24 deletions(-) diff --git a/src/Umbraco.Tests/Published/NestedContentTests.cs b/src/Umbraco.Tests/Published/NestedContentTests.cs index 920fa2acd5..702187dd9e 100644 --- a/src/Umbraco.Tests/Published/NestedContentTests.cs +++ b/src/Umbraco.Tests/Published/NestedContentTests.cs @@ -270,7 +270,7 @@ namespace Umbraco.Tests.Published // ReSharper disable UnassignedGetOnlyAutoProperty public override int Id { get; } - public override int TemplateId { get; } + public override int? TemplateId { get; } public override int SortOrder { get; } public override string Name { get; } public override PublishedCultureInfo GetCulture(string culture = ".") => throw new NotSupportedException(); diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentDataTableTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentDataTableTests.cs index a640423515..9d47d77e6e 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentDataTableTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentDataTableTests.cs @@ -201,7 +201,7 @@ namespace Umbraco.Tests.PublishedContent public IPublishedContent Parent { get; set; } public int Id { get; set; } public Guid Key { get; set; } - public int TemplateId { get; set; } + public int? TemplateId { get; set; } public int SortOrder { get; set; } public string Name { get; set; } public PublishedCultureInfo GetCulture(string culture = null) => throw new NotSupportedException(); diff --git a/src/Umbraco.Tests/PublishedContent/SolidPublishedSnapshot.cs b/src/Umbraco.Tests/PublishedContent/SolidPublishedSnapshot.cs index efd1c6ae8b..d62a98ab15 100644 --- a/src/Umbraco.Tests/PublishedContent/SolidPublishedSnapshot.cs +++ b/src/Umbraco.Tests/PublishedContent/SolidPublishedSnapshot.cs @@ -173,7 +173,7 @@ namespace Umbraco.Tests.PublishedContent public int Id { get; set; } public Guid Key { get; set; } - public int TemplateId { get; set; } + public int? TemplateId { get; set; } public int SortOrder { get; set; } public string Name { get; set; } public PublishedCultureInfo GetCulture(string culture = null) => throw new NotSupportedException(); diff --git a/src/Umbraco.Tests/TestHelpers/Stubs/TestPublishedContent.cs b/src/Umbraco.Tests/TestHelpers/Stubs/TestPublishedContent.cs index 0faf1537b3..0fb1aba576 100644 --- a/src/Umbraco.Tests/TestHelpers/Stubs/TestPublishedContent.cs +++ b/src/Umbraco.Tests/TestHelpers/Stubs/TestPublishedContent.cs @@ -15,7 +15,7 @@ namespace Umbraco.Tests.TestHelpers.Stubs } public int Id { get; } - public int TemplateId { get; set; } + public int? TemplateId { get; set; } public int SortOrder { get; set; } public string Name { get; set; } public IVariationContextAccessor VariationContextAccessor { get; set; } diff --git a/src/Umbraco.Web/Models/PublishedContentBase.cs b/src/Umbraco.Web/Models/PublishedContentBase.cs index 1b8128b4c0..b85ec0a0d1 100644 --- a/src/Umbraco.Web/Models/PublishedContentBase.cs +++ b/src/Umbraco.Web/Models/PublishedContentBase.cs @@ -51,7 +51,7 @@ namespace Umbraco.Web.Models public abstract string Path { get; } /// - public abstract int TemplateId { get; } + public abstract int? TemplateId { get; } /// public abstract int CreatorId { get; } diff --git a/src/Umbraco.Web/PublishedCache/NuCache/DataSource/BTree.ContentDataSerializer.cs b/src/Umbraco.Web/PublishedCache/NuCache/DataSource/BTree.ContentDataSerializer.cs index 7c793b69bd..80633efe2e 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/DataSource/BTree.ContentDataSerializer.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/DataSource/BTree.ContentDataSerializer.cs @@ -30,9 +30,12 @@ namespace Umbraco.Web.PublishedCache.NuCache.DataSource PrimitiveSerializer.Int32.WriteTo(value.VersionId, stream); PrimitiveSerializer.DateTime.WriteTo(value.VersionDate, stream); PrimitiveSerializer.Int32.WriteTo(value.WriterId, stream); - PrimitiveSerializer.Int32.WriteTo(value.TemplateId, stream); + if (value.TemplateId.HasValue) + { + PrimitiveSerializer.Int32.WriteTo(value.TemplateId.Value, stream); + } PropertiesSerializer.WriteTo(value.Properties, stream); CultureVariationsSerializer.WriteTo(value.CultureInfos, stream); } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Web/PublishedCache/NuCache/DataSource/ContentData.cs b/src/Umbraco.Web/PublishedCache/NuCache/DataSource/ContentData.cs index 4721a1f4ca..520cc99011 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/DataSource/ContentData.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/DataSource/ContentData.cs @@ -10,7 +10,7 @@ namespace Umbraco.Web.PublishedCache.NuCache.DataSource public int VersionId { get; set; } public DateTime VersionDate { get; set; } public int WriterId { get; set; } - public int TemplateId { get; set; } + public int? TemplateId { get; set; } public bool Published { get; set; } public IDictionary Properties { get; set; } diff --git a/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs b/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs index a4610e82db..5d4e007212 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs @@ -215,7 +215,7 @@ namespace Umbraco.Web.PublishedCache.NuCache public override string Path => _contentNode.Path; /// - public override int TemplateId => _contentData.TemplateId; + public override int? TemplateId => _contentData.TemplateId; /// public override int CreatorId => _contentNode.CreatorId; diff --git a/src/Umbraco.Web/PublishedCache/PublishedMember.cs b/src/Umbraco.Web/PublishedCache/PublishedMember.cs index 44ce2328b7..de9831ffeb 100644 --- a/src/Umbraco.Web/PublishedCache/PublishedMember.cs +++ b/src/Umbraco.Web/PublishedCache/PublishedMember.cs @@ -129,7 +129,7 @@ namespace Umbraco.Web.PublishedCache public override Guid Key => _member.Key; - public override int TemplateId => throw new NotSupportedException(); + public override int? TemplateId => throw new NotSupportedException(); public override int SortOrder => 0; diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/DictionaryPublishedContent.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/DictionaryPublishedContent.cs index 49e0d1e9d2..201607593c 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/DictionaryPublishedContent.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/DictionaryPublishedContent.cs @@ -148,7 +148,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache public override Guid Key => _key; - public override int TemplateId => 0; + public override int? TemplateId => null; public override int SortOrder => _sortOrder; diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlPublishedContent.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlPublishedContent.cs index 3c143a6066..1643e6219d 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlPublishedContent.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlPublishedContent.cs @@ -109,7 +109,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache } } - public override int TemplateId + public override int? TemplateId { get { diff --git a/src/Umbraco.Web/PublishedContentExtensions.cs b/src/Umbraco.Web/PublishedContentExtensions.cs index f0ddf62074..79c7e27d98 100644 --- a/src/Umbraco.Web/PublishedContentExtensions.cs +++ b/src/Umbraco.Web/PublishedContentExtensions.cs @@ -132,10 +132,15 @@ namespace Umbraco.Web /// Returns the current template Alias /// /// - /// + /// Empty string if none is set. public static string GetTemplateAlias(this IPublishedContent content) { - var template = Current.Services.FileService.GetTemplate(content.TemplateId); + if(content.TemplateId.HasValue == false) + { + return string.Empty; + } + + var template = Current.Services.FileService.GetTemplate(content.TemplateId.Value); return template == null ? string.Empty : template.Alias; } diff --git a/src/Umbraco.Web/Routing/PublishedRouter.cs b/src/Umbraco.Web/Routing/PublishedRouter.cs index 06c23406ab..9b1a614bb5 100644 --- a/src/Umbraco.Web/Routing/PublishedRouter.cs +++ b/src/Umbraco.Web/Routing/PublishedRouter.cs @@ -755,9 +755,9 @@ namespace Umbraco.Web.Routing } } - private ITemplate GetTemplateModel(int templateId) + private ITemplate GetTemplateModel(int? templateId) { - if (templateId <= 0) + if (templateId.HasValue == false) { _logger.Debug("GetTemplateModel: No template."); return null; @@ -765,7 +765,10 @@ namespace Umbraco.Web.Routing _logger.Debug("GetTemplateModel: Get template id={TemplateId}", templateId); - var template = _services.FileService.GetTemplate(templateId); + if (templateId == null) + throw new InvalidOperationException("The template is not set, the page cannot render."); + + var template = _services.FileService.GetTemplate(templateId.Value); if (template == null) throw new InvalidOperationException("The template with Id " + templateId + " does not exist, the page cannot render."); _logger.Debug("GetTemplateModel: Got template id={TemplateId} alias={TemplateAlias}", template.Id, template.Alias); diff --git a/src/Umbraco.Web/Templates/TemplateRenderer.cs b/src/Umbraco.Web/Templates/TemplateRenderer.cs index e0b5c8c301..a94a489c5b 100644 --- a/src/Umbraco.Web/Templates/TemplateRenderer.cs +++ b/src/Umbraco.Web/Templates/TemplateRenderer.cs @@ -36,7 +36,7 @@ namespace Umbraco.Web.Templates { if (umbracoContext == null) throw new ArgumentNullException(nameof(umbracoContext)); PageId = pageId; - AltTemplate = altTemplateId; + AltTemplateId = altTemplateId; _umbracoContext = umbracoContext; } @@ -52,7 +52,7 @@ namespace Umbraco.Web.Templates /// /// Gets/sets the alt template to render if there is one /// - public int? AltTemplate { get; } + public int? AltTemplateId { get; } public void Render(StringWriter writer) { @@ -90,20 +90,22 @@ namespace Umbraco.Web.Templates //set the doc that was found by id contentRequest.PublishedContent = doc; //set the template, either based on the AltTemplate found or the standard template of the doc - contentRequest.TemplateModel = UmbracoConfig.For.UmbracoSettings().WebRouting.DisableAlternativeTemplates || AltTemplate.HasValue == false - ? _fileService.GetTemplate(doc.TemplateId) - : _fileService.GetTemplate(AltTemplate.Value); + var templateId = UmbracoConfig.For.UmbracoSettings().WebRouting.DisableAlternativeTemplates || AltTemplateId.HasValue == false + ? doc.TemplateId + : AltTemplateId.Value; + if (templateId.HasValue) + contentRequest.TemplateModel = _fileService.GetTemplate(templateId.Value); //if there is not template then exit if (contentRequest.HasTemplate == false) { - if (AltTemplate.HasValue == false) + if (AltTemplateId.HasValue == false) { writer.Write("", doc.TemplateId); } else { - writer.Write("", AltTemplate); + writer.Write("", AltTemplateId); } return; } From 470585b50d437c46802753b9bd3797ecd1921284 Mon Sep 17 00:00:00 2001 From: Stefano Chiodino Date: Thu, 15 Nov 2018 08:01:54 +0000 Subject: [PATCH 086/469] Fix some more tests that were counting on defaulting to 0 --- src/Umbraco.Core/Services/EntityXmlSerializer.cs | 2 +- .../Cache/PublishedCache/PublishedMediaCacheTests.cs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Core/Services/EntityXmlSerializer.cs b/src/Umbraco.Core/Services/EntityXmlSerializer.cs index 3ba4b60b53..f47690c2eb 100644 --- a/src/Umbraco.Core/Services/EntityXmlSerializer.cs +++ b/src/Umbraco.Core/Services/EntityXmlSerializer.cs @@ -52,7 +52,7 @@ namespace Umbraco.Core.Services xml.Add(new XAttribute("writerName", content.GetWriterProfile(userService)?.Name ?? "??")); xml.Add(new XAttribute("writerID", content.WriterId)); - xml.Add(new XAttribute("template", content.TemplateId?.ToString(CultureInfo.InvariantCulture))); + xml.Add(new XAttribute("template", content.TemplateId?.ToString(CultureInfo.InvariantCulture) ?? "0")); xml.Add(new XAttribute("isPublished", content.Published)); diff --git a/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs b/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs index 64194ebb47..0e7b3fff0f 100644 --- a/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs +++ b/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs @@ -209,7 +209,7 @@ namespace Umbraco.Tests.Cache.PublishedCache var store = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), ServiceContext.MediaService, ServiceContext.UserService, new StaticCacheProvider(), ContentTypesCache); var doc = store.CreateFromCacheValues(store.ConvertFromSearchResult(result)); - DoAssert(doc, 1234, key, 0, 0, "/media/test.jpg", "Image", 23, "Shannon", "Shannon", 0, 0, "-1,1234", DateTime.Parse("2012-07-17T10:34:09"), DateTime.Parse("2012-07-16T10:34:09"), 2); + DoAssert(doc, 1234, key, templateIdVal: null, 0, "/media/test.jpg", "Image", 23, "Shannon", "Shannon", 0, 0, "-1,1234", DateTime.Parse("2012-07-17T10:34:09"), DateTime.Parse("2012-07-16T10:34:09"), 2); Assert.AreEqual(null, doc.Parent); } @@ -225,7 +225,7 @@ namespace Umbraco.Tests.Cache.PublishedCache var cache = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), ServiceContext.MediaService, ServiceContext.UserService, new StaticCacheProvider(), ContentTypesCache); var doc = cache.CreateFromCacheValues(cache.ConvertFromXPathNavigator(navigator, true)); - DoAssert(doc, 2000, key, 0, 2, "image1", "Image", 23, "Shannon", "Shannon", 33, 33, "-1,2000", DateTime.Parse("2012-06-12T14:13:17"), DateTime.Parse("2012-07-20T18:50:43"), 1); + DoAssert(doc, 2000, key, templateIdVal: null, 2, "image1", "Image", 23, "Shannon", "Shannon", 33, 33, "-1,2000", DateTime.Parse("2012-06-12T14:13:17"), DateTime.Parse("2012-07-20T18:50:43"), 1); Assert.AreEqual(null, doc.Parent); Assert.AreEqual(2, doc.Children.Count()); Assert.AreEqual(2001, doc.Children.ElementAt(0).Id); @@ -339,7 +339,7 @@ namespace Umbraco.Tests.Cache.PublishedCache DictionaryPublishedContent dicDoc, int idVal = 1234, Guid keyVal = default(Guid), - int templateIdVal = 0, + int? templateIdVal = null, int sortOrderVal = 44, string urlNameVal = "testing", string nodeTypeAliasVal = "myType", @@ -370,7 +370,7 @@ namespace Umbraco.Tests.Cache.PublishedCache IPublishedContent doc, int idVal = 1234, Guid keyVal = default(Guid), - int templateIdVal = 0, + int? templateIdVal = null, int sortOrderVal = 44, string urlNameVal = "testing", string nodeTypeAliasVal = "myType", From e2455b14d99580232f1a115e264cf4ef63d1441e Mon Sep 17 00:00:00 2001 From: Stefano Chiodino Date: Sat, 17 Nov 2018 10:59:26 +0000 Subject: [PATCH 087/469] Don't serialise null template id to 0. Use empty string instead as null doesn't work in this case. --- src/Umbraco.Core/Services/EntityXmlSerializer.cs | 2 +- .../Cache/PublishedCache/PublishedMediaCacheTests.cs | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Umbraco.Core/Services/EntityXmlSerializer.cs b/src/Umbraco.Core/Services/EntityXmlSerializer.cs index f47690c2eb..d938e032a8 100644 --- a/src/Umbraco.Core/Services/EntityXmlSerializer.cs +++ b/src/Umbraco.Core/Services/EntityXmlSerializer.cs @@ -52,7 +52,7 @@ namespace Umbraco.Core.Services xml.Add(new XAttribute("writerName", content.GetWriterProfile(userService)?.Name ?? "??")); xml.Add(new XAttribute("writerID", content.WriterId)); - xml.Add(new XAttribute("template", content.TemplateId?.ToString(CultureInfo.InvariantCulture) ?? "0")); + xml.Add(new XAttribute("template", content.TemplateId?.ToString(CultureInfo.InvariantCulture) ?? "")); xml.Add(new XAttribute("isPublished", content.Published)); diff --git a/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs b/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs index 0e7b3fff0f..e2b87cb17d 100644 --- a/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs +++ b/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs @@ -404,9 +404,6 @@ namespace Umbraco.Tests.Cache.PublishedCache Assert.AreEqual(createDateVal.Value, doc.CreateDate); Assert.AreEqual(updateDateVal.Value, doc.UpdateDate); Assert.AreEqual(levelVal, doc.Level); - } - - } } From 5b39e5e5c7c2a0cb55367d46206609b7ef3dc20e Mon Sep 17 00:00:00 2001 From: Stephan Date: Sun, 18 Nov 2018 11:05:14 +0100 Subject: [PATCH 088/469] Fix typo in ReflectionUtilities --- .../PublishedContent/PublishedModelFactory.cs | 2 +- src/Umbraco.Core/ReflectionUtilities.cs | 2 +- .../CtorInvokeBenchmarks.cs | 4 ++-- src/Umbraco.Tests/Clr/ReflectionUtilitiesTests.cs | 14 +++++++------- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedModelFactory.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedModelFactory.cs index 67758c1c69..ee3fd62985 100644 --- a/src/Umbraco.Core/Models/PublishedContent/PublishedModelFactory.cs +++ b/src/Umbraco.Core/Models/PublishedContent/PublishedModelFactory.cs @@ -112,7 +112,7 @@ namespace Umbraco.Core.Models.PublishedContent if (ctor != null) return ctor(); var listType = typeof(List<>).MakeGenericType(modelInfo.ModelType); - ctor = modelInfo.ListCtor = ReflectionUtilities.EmitConstuctor>(declaring: listType); + ctor = modelInfo.ListCtor = ReflectionUtilities.EmitConstructor>(declaring: listType); return ctor(); } diff --git a/src/Umbraco.Core/ReflectionUtilities.cs b/src/Umbraco.Core/ReflectionUtilities.cs index 870cb9ec13..622d81f5f2 100644 --- a/src/Umbraco.Core/ReflectionUtilities.cs +++ b/src/Umbraco.Core/ReflectionUtilities.cs @@ -295,7 +295,7 @@ namespace Umbraco.Core /// Occurs when the constructor does not exist and is true. /// Occurs when is not a Func or when /// is specified and does not match the function's returned type. - public static TLambda EmitConstuctor(bool mustExist = true, Type declaring = null) + public static TLambda EmitConstructor(bool mustExist = true, Type declaring = null) { var (_, lambdaParameters, lambdaReturned) = AnalyzeLambda(true, true); diff --git a/src/Umbraco.Tests.Benchmarks/CtorInvokeBenchmarks.cs b/src/Umbraco.Tests.Benchmarks/CtorInvokeBenchmarks.cs index 1d5876187b..f024bd937b 100644 --- a/src/Umbraco.Tests.Benchmarks/CtorInvokeBenchmarks.cs +++ b/src/Umbraco.Tests.Benchmarks/CtorInvokeBenchmarks.cs @@ -25,7 +25,7 @@ namespace Umbraco.Tests.Benchmarks // see benchmarkdotnet FAQ Add(Job.Default .WithLaunchCount(1) // benchmark process will be launched only once - .WithIterationTime(TimeInterval.FromMilliseconds(400)) + .WithIterationTime(TimeInterval.FromMilliseconds(400)) .WithWarmupCount(3) .WithTargetCount(6)); } @@ -144,7 +144,7 @@ namespace Umbraco.Tests.Benchmarks // however, unfortunately, the generated "compiled to delegate" code cannot access private stuff :( - _emittedCtor = ReflectionUtilities.EmitConstuctor>(); + _emittedCtor = ReflectionUtilities.EmitConstructor>(); } public IFoo IlCtor(IFoo foo) diff --git a/src/Umbraco.Tests/Clr/ReflectionUtilitiesTests.cs b/src/Umbraco.Tests/Clr/ReflectionUtilitiesTests.cs index b87ac70ea5..f40ca3f500 100644 --- a/src/Umbraco.Tests/Clr/ReflectionUtilitiesTests.cs +++ b/src/Umbraco.Tests/Clr/ReflectionUtilitiesTests.cs @@ -14,16 +14,16 @@ namespace Umbraco.Tests.Clr [Test] public void EmitCtorEmits() { - var ctor1 = ReflectionUtilities.EmitConstuctor>(); + var ctor1 = ReflectionUtilities.EmitConstructor>(); Assert.IsInstanceOf(ctor1()); - var ctor2 = ReflectionUtilities.EmitConstuctor>(declaring: typeof(Class1)); + var ctor2 = ReflectionUtilities.EmitConstructor>(declaring: typeof(Class1)); Assert.IsInstanceOf(ctor2()); - var ctor3 = ReflectionUtilities.EmitConstuctor>(); + var ctor3 = ReflectionUtilities.EmitConstructor>(); Assert.IsInstanceOf(ctor3(42)); - var ctor4 = ReflectionUtilities.EmitConstuctor>(declaring: typeof(Class3)); + var ctor4 = ReflectionUtilities.EmitConstructor>(declaring: typeof(Class3)); Assert.IsInstanceOf(ctor4(42)); } @@ -44,14 +44,14 @@ namespace Umbraco.Tests.Clr [Test] public void EmitCtorEmitsPrivateCtor() { - var ctor = ReflectionUtilities.EmitConstuctor>(); + var ctor = ReflectionUtilities.EmitConstructor>(); Assert.IsInstanceOf(ctor("foo")); } [Test] public void EmitCtorThrowsIfNotFound() { - Assert.Throws(() => ReflectionUtilities.EmitConstuctor>()); + Assert.Throws(() => ReflectionUtilities.EmitConstructor>()); } [Test] @@ -64,7 +64,7 @@ namespace Umbraco.Tests.Clr [Test] public void EmitCtorReturnsNull() { - Assert.IsNull(ReflectionUtilities.EmitConstuctor>(false)); + Assert.IsNull(ReflectionUtilities.EmitConstructor>(false)); } [Test] From 3960791bf257383b892a672402d685f904e04007 Mon Sep 17 00:00:00 2001 From: Stephan Date: Sun, 18 Nov 2018 11:05:39 +0100 Subject: [PATCH 089/469] Simplify CollectionBuilderBase, no more named services --- .../Composing/CollectionBuilderBase.cs | 47 +++++-------------- 1 file changed, 13 insertions(+), 34 deletions(-) diff --git a/src/Umbraco.Core/Composing/CollectionBuilderBase.cs b/src/Umbraco.Core/Composing/CollectionBuilderBase.cs index efdef82114..36c6879a32 100644 --- a/src/Umbraco.Core/Composing/CollectionBuilderBase.cs +++ b/src/Umbraco.Core/Composing/CollectionBuilderBase.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Linq.Expressions; namespace Umbraco.Core.Composing { @@ -18,7 +17,7 @@ namespace Umbraco.Core.Composing private readonly List _types = new List(); private readonly object _locker = new object(); private Func, TCollection> _collectionCtor; - private Registration[] _registrations; + private Type[] _registeredTypes; /// /// Initializes a new instance of the @@ -50,17 +49,8 @@ namespace Umbraco.Core.Composing protected virtual void Initialize() { // compile the auto-collection constructor - var argType = typeof(IEnumerable); - var ctorArgTypes = new[] { argType }; - var constructor = typeof(TCollection).GetConstructor(ctorArgTypes); - if (constructor != null) - { - var exprArg = Expression.Parameter(argType, "items"); - var exprNew = Expression.New(constructor, exprArg); - var expr = Expression.Lambda, TCollection>>(exprNew, exprArg); - _collectionCtor = expr.Compile(); - } - // else _collectionCtor remains null, assuming CreateCollection has been overriden + // can be null, if no ctor found, and then assume CreateCollection has been overriden + _collectionCtor = ReflectionUtilities.EmitConstructor, TCollection>>(mustExist: false); // we just don't want to support re-registering collections here if (Container.GetRegistered().Any()) @@ -84,7 +74,7 @@ namespace Umbraco.Core.Composing { lock (_locker) { - if (_registrations != null) + if (_registeredTypes != null) throw new InvalidOperationException("Cannot configure a collection builder after its types have been resolved."); action(_types); } @@ -105,43 +95,32 @@ namespace Umbraco.Core.Composing { lock (_locker) { - if (_registrations != null) return; + if (_registeredTypes != null) return; var types = GetRegisteringTypes(_types).ToArray(); + + // ensure they are safe foreach (var type in types) EnsureType(type, "register"); - var prefix = GetType().FullName + "_"; - var i = 0; + // register them foreach (var type in types) - { - var name = $"{prefix}{i++:00000}"; - Container.Register(typeof(TItem), type, name); - } + Container.Register(type); - // note: we do this, because we don't want to get "all", - // because other types implementing TItem may be registered, - // and we only want those for *this* builder - - _registrations = Container.GetRegistered(typeof(TItem)) - .Where(x => x.ServiceName.StartsWith(prefix)) - .OrderBy(x => x.ServiceName) - .ToArray(); + _registeredTypes = types; } } /// /// Creates the collection items. /// - /// The arguments. /// The collection items. - protected virtual IEnumerable CreateItems(/*params object[] args*/) + protected virtual IEnumerable CreateItems() { RegisterTypes(); // will do it only once - var type = typeof (TItem); - return _registrations - .Select(x => (TItem) Container.GetInstance(type, x.ServiceName/*, args*/)) + return _registeredTypes // respect order + .Select(x => (TItem) Container.GetInstance(x)) .ToArray(); // safe } From 87a64b740669ecebd2f52db56a61acdf6da14501 Mon Sep 17 00:00:00 2001 From: Stephan Date: Mon, 19 Nov 2018 14:40:59 +0100 Subject: [PATCH 090/469] Refactor filesystems (again) --- .../Composers/FileSystemsComposer.cs | 12 +- src/Umbraco.Core/Composing/Current.cs | 3 + src/Umbraco.Core/ContentExtensions.cs | 2 +- .../Events/QueuingEventDispatcher.cs | 2 +- src/Umbraco.Core/IO/FileSystemAttribute.cs | 25 --- src/Umbraco.Core/IO/FileSystems.cs | 186 +++++++++--------- src/Umbraco.Core/IO/IFileSystems.cs | 5 - src/Umbraco.Core/IO/IMediaFileSystem.cs | 2 +- src/Umbraco.Core/IO/MediaFileSystem.cs | 1 - src/Umbraco.Core/IO/ShadowFileSystems.cs | 71 ++----- src/Umbraco.Core/Models/UserExtensions.cs | 2 +- src/Umbraco.Core/Umbraco.Core.csproj | 1 - src/Umbraco.Tests/IO/FileSystemsTests.cs | 18 +- src/Umbraco.Tests/IO/ShadowFileSystemTests.cs | 100 ++++++---- src/Umbraco.Tests/Models/ContentTests.cs | 6 +- .../Scoping/ScopeFileSystemsTests.cs | 10 +- .../TestHelpers/TestObjects-Mocks.cs | 3 - src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 2 +- src/Umbraco.Web/Editors/UsersController.cs | 6 +- 19 files changed, 203 insertions(+), 254 deletions(-) delete mode 100644 src/Umbraco.Core/IO/FileSystemAttribute.cs diff --git a/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs b/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs index 56a0ba316c..22e0d33456 100644 --- a/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs @@ -76,15 +76,13 @@ namespace Umbraco.Core.Composing.Composers // register IFileSystems, which gives access too all filesystems container.RegisterSingleton(factory => factory.GetInstance()); - // register IMediaFileSystem - var virtualRoot = GetMediaFileSystemVirtualRoot(); - container.RegisterSingleton("media", factory => new PhysicalFileSystem(virtualRoot)); - container.RegisterSingleton(factory => factory.GetInstance().GetFileSystem()); + // register IMediaFileSystem with its actual, underlying filesystem factory + container.RegisterSingleton(factory => factory.GetInstance().GetFileSystem(MediaInnerFileSystemFactory)); return container; } - private static string GetMediaFileSystemVirtualRoot() + private static IFileSystem MediaInnerFileSystemFactory() { // for the time being, we still use the FileSystemProvider config file // but, detect if ppl are trying to use it to change the "provider" @@ -93,13 +91,13 @@ namespace Umbraco.Core.Composing.Composers var config = (FileSystemProvidersSection)ConfigurationManager.GetSection("umbracoConfiguration/FileSystemProviders"); var p = config?.Providers["media"]; - if (p == null) return virtualRoot; + if (p == null) return new PhysicalFileSystem(virtualRoot); if (!string.IsNullOrWhiteSpace(p.Type) && p.Type != "Umbraco.Core.IO.PhysicalFileSystem, Umbraco.Core") throw new InvalidOperationException("Setting a provider type in FileSystemProviders.config is not supported anymore, see FileSystemsComposer for help."); virtualRoot = p?.Parameters["virtualRoot"]?.Value ?? "~/media"; - return virtualRoot; + return new PhysicalFileSystem(virtualRoot); } } } diff --git a/src/Umbraco.Core/Composing/Current.cs b/src/Umbraco.Core/Composing/Current.cs index cfadb37d6d..7792b31dc1 100644 --- a/src/Umbraco.Core/Composing/Current.cs +++ b/src/Umbraco.Core/Composing/Current.cs @@ -104,6 +104,9 @@ namespace Umbraco.Core.Composing public static IFileSystems FileSystems => Container.GetInstance(); + public static IMediaFileSystem MediaFileSystem + => Container.GetInstance(); + public static UrlSegmentProviderCollection UrlSegmentProviders => Container.GetInstance(); diff --git a/src/Umbraco.Core/ContentExtensions.cs b/src/Umbraco.Core/ContentExtensions.cs index ee6602e9aa..d26f04d454 100644 --- a/src/Umbraco.Core/ContentExtensions.cs +++ b/src/Umbraco.Core/ContentExtensions.cs @@ -19,7 +19,7 @@ namespace Umbraco.Core { // this ain't pretty private static IMediaFileSystem _mediaFileSystem; - private static IMediaFileSystem MediaFileSystem => _mediaFileSystem ?? (_mediaFileSystem = Current.FileSystems.MediaFileSystem); + private static IMediaFileSystem MediaFileSystem => _mediaFileSystem ?? (_mediaFileSystem = Current.MediaFileSystem); #region IContent diff --git a/src/Umbraco.Core/Events/QueuingEventDispatcher.cs b/src/Umbraco.Core/Events/QueuingEventDispatcher.cs index 54ed8580a0..b31b64e435 100644 --- a/src/Umbraco.Core/Events/QueuingEventDispatcher.cs +++ b/src/Umbraco.Core/Events/QueuingEventDispatcher.cs @@ -35,6 +35,6 @@ namespace Umbraco.Core.Events private IMediaFileSystem _mediaFileSystem; // fixme inject - private IMediaFileSystem MediaFileSystem => _mediaFileSystem ?? (_mediaFileSystem = Current.FileSystems.MediaFileSystem); + private IMediaFileSystem MediaFileSystem => _mediaFileSystem ?? (_mediaFileSystem = Current.MediaFileSystem); } } diff --git a/src/Umbraco.Core/IO/FileSystemAttribute.cs b/src/Umbraco.Core/IO/FileSystemAttribute.cs deleted file mode 100644 index cf59d4e145..0000000000 --- a/src/Umbraco.Core/IO/FileSystemAttribute.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; - -namespace Umbraco.Core.IO -{ - /// - /// Decorates a filesystem. - /// - [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] - public class FileSystemAttribute : Attribute - { - /// - /// Initializes a new instance of the class. - /// - /// - public FileSystemAttribute(string alias) - { - Alias = alias; - } - - /// - /// Gets the alias of the filesystem. - /// - public string Alias { get; } - } -} diff --git a/src/Umbraco.Core/IO/FileSystems.cs b/src/Umbraco.Core/IO/FileSystems.cs index 24e7a73172..29ea2c44b1 100644 --- a/src/Umbraco.Core/IO/FileSystems.cs +++ b/src/Umbraco.Core/IO/FileSystems.cs @@ -10,7 +10,6 @@ namespace Umbraco.Core.IO { public class FileSystems : IFileSystems { - private readonly ConcurrentSet _wrappers = new ConcurrentSet(); private readonly IContainer _container; private readonly ILogger _logger; @@ -23,13 +22,16 @@ namespace Umbraco.Core.IO private ShadowWrapper _scriptsFileSystem; private ShadowWrapper _masterPagesFileSystem; private ShadowWrapper _mvcViewsFileSystem; - + // well-known file systems lazy initialization private object _wkfsLock = new object(); private bool _wkfsInitialized; - private object _wkfsObject; + private object _wkfsObject; // unused - private MediaFileSystem _mediaFileSystem; + // shadow support + private readonly List _shadowWrappers = new List(); + private readonly object _shadowLocker = new object(); + private static Guid _shadowCurrentId = Guid.Empty; // static - unique!! #region Constructor @@ -43,11 +45,19 @@ namespace Umbraco.Core.IO // for tests only, totally unsafe internal void Reset() { - _wrappers.Clear(); + _shadowWrappers.Clear(); _filesystems.Clear(); Volatile.Write(ref _wkfsInitialized, false); + _shadowCurrentId = Guid.Empty; } + // for tests only, totally unsafe + internal static void ResetShadowId() + { + _shadowCurrentId = Guid.Empty; + } + + // set by the scope provider when taking control of filesystems internal Func IsScoped { get; set; } = () => false; #endregion @@ -114,16 +124,6 @@ namespace Umbraco.Core.IO } } - /// - public IMediaFileSystem MediaFileSystem - { - get - { - if (Volatile.Read(ref _wkfsInitialized) == false) EnsureWellKnownFileSystems(); - return _mediaFileSystem; - } - } - private void EnsureWellKnownFileSystems() { LazyInitializer.EnsureInitialized(ref _wkfsObject, ref _wkfsInitialized, ref _wkfsLock, CreateWellKnownFileSystems); @@ -140,15 +140,20 @@ namespace Umbraco.Core.IO var masterPagesFileSystem = new PhysicalFileSystem(SystemDirectories.Masterpages); var mvcViewsFileSystem = new PhysicalFileSystem(SystemDirectories.MvcViews); - _macroPartialFileSystem = new ShadowWrapper(macroPartialFileSystem, "Views/MacroPartials", () => IsScoped()); - _partialViewsFileSystem = new ShadowWrapper(partialViewsFileSystem, "Views/Partials", () => IsScoped()); - _stylesheetsFileSystem = new ShadowWrapper(stylesheetsFileSystem, "css", () => IsScoped()); - _scriptsFileSystem = new ShadowWrapper(scriptsFileSystem, "scripts", () => IsScoped()); - _masterPagesFileSystem = new ShadowWrapper(masterPagesFileSystem, "masterpages", () => IsScoped()); - _mvcViewsFileSystem = new ShadowWrapper(mvcViewsFileSystem, "Views", () => IsScoped()); + _macroPartialFileSystem = new ShadowWrapper(macroPartialFileSystem, "Views/MacroPartials", IsScoped); + _partialViewsFileSystem = new ShadowWrapper(partialViewsFileSystem, "Views/Partials", IsScoped); + _stylesheetsFileSystem = new ShadowWrapper(stylesheetsFileSystem, "css", IsScoped); + _scriptsFileSystem = new ShadowWrapper(scriptsFileSystem, "scripts", IsScoped); + _masterPagesFileSystem = new ShadowWrapper(masterPagesFileSystem, "masterpages", IsScoped); + _mvcViewsFileSystem = new ShadowWrapper(mvcViewsFileSystem, "Views", IsScoped); - // filesystems obtained from GetFileSystemProvider are already wrapped and do not need to be wrapped again - _mediaFileSystem = GetFileSystem(); + // fixme locking? + _shadowWrappers.Add(_macroPartialFileSystem); + _shadowWrappers.Add(_partialViewsFileSystem); + _shadowWrappers.Add(_stylesheetsFileSystem); + _shadowWrappers.Add(_scriptsFileSystem); + _shadowWrappers.Add(_masterPagesFileSystem); + _shadowWrappers.Add(_mvcViewsFileSystem); return null; } @@ -166,37 +171,22 @@ namespace Umbraco.Core.IO /// Note that any filesystem created by this method *after* shadowing begins, will *not* be /// shadowing (and an exception will be thrown by the ShadowWrapper). /// - public TFileSystem GetFileSystem() + public TFileSystem GetFileSystem(Func innerFileSystemFactory) where TFileSystem : FileSystemWrapper { - var alias = GetFileSystemAlias(); + if (Volatile.Read(ref _wkfsInitialized) == false) EnsureWellKnownFileSystems(); - // note: GetOrAdd can run multiple times - and here, since we have side effects - // (adding to _wrappers) we want to be sure the factory runs only once, hence the - // additional Lazy. - return (TFileSystem) _filesystems.GetOrAdd(alias, _ => new Lazy(() => + var name = typeof(TFileSystem).FullName; + if (name == null) throw new Exception("panic!"); + + return (TFileSystem) _filesystems.GetOrAdd(name, _ => new Lazy(() => { - var supportingFileSystem = _container.GetInstance(alias); - var shadowWrapper = new ShadowWrapper(supportingFileSystem, "typed/" + alias, () => IsScoped()); - - _wrappers.Add(shadowWrapper); // _wrappers is a concurrent set - this is safe - - return _container.CreateInstance(new { innerFileSystem = shadowWrapper}); + var innerFileSystem = innerFileSystemFactory(); + var shadowWrapper = CreateShadowWrapper(innerFileSystem, "typed/" + name); + return _container.CreateInstance(new { innerFileSystem = shadowWrapper }); })).Value; } - private string GetFileSystemAlias() - { - var fileSystemType = typeof(TFileSystem); - - // find the attribute and get the alias - var attr = (FileSystemAttribute) fileSystemType.GetCustomAttributes(typeof(FileSystemAttribute), false).SingleOrDefault(); - if (attr == null) - throw new InvalidOperationException("Type " + fileSystemType.FullName + "is missing the required FileSystemProviderAttribute."); - - return attr.Alias; - } - #endregion #region Shadow @@ -223,50 +213,70 @@ namespace Umbraco.Core.IO { if (Volatile.Read(ref _wkfsInitialized) == false) EnsureWellKnownFileSystems(); - var typed = _wrappers.ToArray(); - var wrappers = new ShadowWrapper[typed.Length + 6]; - var i = 0; - while (i < typed.Length) wrappers[i] = typed[i++]; - wrappers[i++] = _macroPartialFileSystem; - wrappers[i++] = _partialViewsFileSystem; - wrappers[i++] = _stylesheetsFileSystem; - wrappers[i++] = _scriptsFileSystem; - wrappers[i++] = _masterPagesFileSystem; - wrappers[i] = _mvcViewsFileSystem; + return new ShadowFileSystems(this, id); // will invoke BeginShadow and EndShadow + } - return new ShadowFileSystems(id, wrappers, _logger); + internal void BeginShadow(Guid id) + { + lock (_shadowLocker) + { + // if we throw here, it means that something very wrong happened. + if (_shadowCurrentId != Guid.Empty) + throw new InvalidOperationException("Already shadowing."); + _shadowCurrentId = id; + + _logger.Debug("Shadow '{ShadowId}'", id); + + foreach (var wrapper in _shadowWrappers) + wrapper.Shadow(id); + } + } + + internal void EndShadow(Guid id, bool completed) + { + lock (_shadowLocker) + { + // if we throw here, it means that something very wrong happened. + if (_shadowCurrentId == Guid.Empty) + throw new InvalidOperationException("Not shadowing."); + if (id != _shadowCurrentId) + throw new InvalidOperationException("Not the current shadow."); + + _logger.Debug("UnShadow '{ShadowId}' {Status}", id, completed ? "complete" : "abort"); + + var exceptions = new List(); + foreach (var wrapper in _shadowWrappers) + { + try + { + // this may throw an AggregateException if some of the changes could not be applied + wrapper.UnShadow(completed); + } + catch (AggregateException ae) + { + exceptions.Add(ae); + } + } + + _shadowCurrentId = Guid.Empty; + + if (exceptions.Count > 0) + throw new AggregateException(completed ? "Failed to apply all changes (see exceptions)." : "Failed to abort (see exceptions).", exceptions); + } + } + + private ShadowWrapper CreateShadowWrapper(IFileSystem filesystem, string shadowPath) + { + lock (_shadowLocker) + { + var wrapper = new ShadowWrapper(filesystem, shadowPath, IsScoped); + if (_shadowCurrentId != Guid.Empty) + wrapper.Shadow(_shadowCurrentId); + _shadowWrappers.Add(wrapper); + return wrapper; + } } #endregion - - private class ConcurrentSet - where T : class - { - private readonly HashSet _set = new HashSet(); - - public void Add(T item) - { - lock (_set) - { - _set.Add(item); - } - } - - public void Clear() - { - lock (_set) - { - _set.Clear(); - } - } - - public T[] ToArray() - { - lock (_set) - { - return _set.ToArray(); - } - } - } } } diff --git a/src/Umbraco.Core/IO/IFileSystems.cs b/src/Umbraco.Core/IO/IFileSystems.cs index 1af5377c43..d74ad48145 100644 --- a/src/Umbraco.Core/IO/IFileSystems.cs +++ b/src/Umbraco.Core/IO/IFileSystems.cs @@ -34,10 +34,5 @@ /// Gets the MVC views filesystem. /// IFileSystem MvcViewsFileSystem { get; } - - /// - /// Gets the media filesystem. - /// - IMediaFileSystem MediaFileSystem { get; } } } diff --git a/src/Umbraco.Core/IO/IMediaFileSystem.cs b/src/Umbraco.Core/IO/IMediaFileSystem.cs index e1957857bf..ed88516135 100644 --- a/src/Umbraco.Core/IO/IMediaFileSystem.cs +++ b/src/Umbraco.Core/IO/IMediaFileSystem.cs @@ -63,4 +63,4 @@ namespace Umbraco.Core.IO /// The filesystem-relative path to the copy of the media file. string CopyFile(IContentBase content, PropertyType propertyType, string sourcepath); } -} \ No newline at end of file +} diff --git a/src/Umbraco.Core/IO/MediaFileSystem.cs b/src/Umbraco.Core/IO/MediaFileSystem.cs index c36a086bf8..867fe94c03 100644 --- a/src/Umbraco.Core/IO/MediaFileSystem.cs +++ b/src/Umbraco.Core/IO/MediaFileSystem.cs @@ -15,7 +15,6 @@ namespace Umbraco.Core.IO /// /// A custom file system provider for media /// - [FileSystem("media")] public class MediaFileSystem : FileSystemWrapper, IMediaFileSystem { /// diff --git a/src/Umbraco.Core/IO/ShadowFileSystems.cs b/src/Umbraco.Core/IO/ShadowFileSystems.cs index 80aa1791fd..bce0cc6df7 100644 --- a/src/Umbraco.Core/IO/ShadowFileSystems.cs +++ b/src/Umbraco.Core/IO/ShadowFileSystems.cs @@ -1,41 +1,26 @@ using System; -using System.Collections.Generic; -using Umbraco.Core.Logging; namespace Umbraco.Core.IO { + // shadow filesystems is definitively ... too convoluted + internal class ShadowFileSystems : ICompletable { - private static readonly object Locker = new object(); - private static Guid _currentId = Guid.Empty; - - private readonly Guid _id; - private readonly ShadowWrapper[] _wrappers; - private readonly ILogger _logger; - + private readonly FileSystems _fileSystems; private bool _completed; // invoked by the filesystems when shadowing - // can only be 1 shadow at a time (static) - public ShadowFileSystems(Guid id, ShadowWrapper[] wrappers, ILogger logger) + public ShadowFileSystems(FileSystems fileSystems, Guid id) { - lock (Locker) - { - // if we throw here, it means that something very wrong happened. - if (_currentId != Guid.Empty) - throw new InvalidOperationException("Already shadowing."); - _currentId = id; - } + _fileSystems = fileSystems; + Id = id; - _logger = logger; - _logger.Debug("Shadow '{ShadowId}'", id); - _id = id; - - _wrappers = wrappers; - foreach (var wrapper in _wrappers) - wrapper.Shadow(id); + _fileSystems.BeginShadow(id); } + // for tests + public Guid Id { get; } + // invoked by the scope when exiting, if completed public void Complete() { @@ -45,41 +30,7 @@ namespace Umbraco.Core.IO // invoked by the scope when exiting public void Dispose() { - lock (Locker) - { - // if we throw here, it means that something very wrong happened. - if (_currentId == Guid.Empty) - throw new InvalidOperationException("Not shadowing."); - if (_id != _currentId) - throw new InvalidOperationException("Not the current shadow."); - - _logger.Debug("UnShadow '{ShadowId}' {Status}", _id, _completed ? "complete" : "abort"); - - var exceptions = new List(); - foreach (var wrapper in _wrappers) - { - try - { - // this may throw an AggregateException if some of the changes could not be applied - wrapper.UnShadow(_completed); - } - catch (AggregateException ae) - { - exceptions.Add(ae); - } - } - - _currentId = Guid.Empty; - - if (exceptions.Count > 0) - throw new AggregateException(_completed ? "Failed to apply all changes (see exceptions)." : "Failed to abort (see exceptions).", exceptions); - } - } - - // for tests - internal static void ResetId() - { - _currentId = Guid.Empty; + _fileSystems.EndShadow(Id, _completed); } } } diff --git a/src/Umbraco.Core/Models/UserExtensions.cs b/src/Umbraco.Core/Models/UserExtensions.cs index 82e4935616..ad515f4197 100644 --- a/src/Umbraco.Core/Models/UserExtensions.cs +++ b/src/Umbraco.Core/Models/UserExtensions.cs @@ -100,7 +100,7 @@ namespace Umbraco.Core.Models } //use the custom avatar - var avatarUrl = Current.FileSystems.MediaFileSystem.GetUrl(user.Avatar); + var avatarUrl = Current.MediaFileSystem.GetUrl(user.Avatar); return new[] { avatarUrl + "?width=30&height=30&mode=crop", diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index e7d85472fb..352300333d 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -576,7 +576,6 @@ - diff --git a/src/Umbraco.Tests/IO/FileSystemsTests.cs b/src/Umbraco.Tests/IO/FileSystemsTests.cs index fe27229c72..4842b3feec 100644 --- a/src/Umbraco.Tests/IO/FileSystemsTests.cs +++ b/src/Umbraco.Tests/IO/FileSystemsTests.cs @@ -56,7 +56,7 @@ namespace Umbraco.Tests.IO [Test] public void Can_Get_MediaFileSystem() { - var fileSystem = FileSystems.GetFileSystem(); + var fileSystem = _container.GetInstance(); Assert.NotNull(fileSystem); } @@ -67,14 +67,6 @@ namespace Umbraco.Tests.IO Assert.NotNull(fileSystem); } - [Test] - public void MediaFileSystem_Is_Singleton() - { - var fileSystem1 = FileSystems.GetFileSystem(); - var fileSystem2 = FileSystems.GetFileSystem(); - Assert.AreSame(fileSystem1, fileSystem2); - } - [Test] public void IMediaFileSystem_Is_Singleton() { @@ -86,7 +78,7 @@ namespace Umbraco.Tests.IO [Test] public void Can_Delete_MediaFiles() { - var fs = FileSystems.GetFileSystem(); + var fs = _container.GetInstance(); var ms = new MemoryStream(Encoding.UTF8.GetBytes("test")); var virtPath = fs.GetMediaPath("file.txt", Guid.NewGuid(), Guid.NewGuid()); fs.AddFile(virtPath, ms); @@ -108,6 +100,9 @@ namespace Umbraco.Tests.IO Assert.IsTrue(Directory.Exists(physPath)); } + + // fixme - don't make sense anymore + /* [Test] public void Cannot_Get_InvalidFileSystem() { @@ -134,12 +129,13 @@ namespace Umbraco.Tests.IO { } } - [FileSystem("noconfig")] + [InnerFileSystem("noconfig")] internal class NonConfiguredFileSystem : FileSystemWrapper { public NonConfiguredFileSystem(IFileSystem innerFileSystem) : base(innerFileSystem) { } } + */ } } diff --git a/src/Umbraco.Tests/IO/ShadowFileSystemTests.cs b/src/Umbraco.Tests/IO/ShadowFileSystemTests.cs index 90fdf3810d..304f7b1efb 100644 --- a/src/Umbraco.Tests/IO/ShadowFileSystemTests.cs +++ b/src/Umbraco.Tests/IO/ShadowFileSystemTests.cs @@ -1,10 +1,12 @@ using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Composing; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Scoping; @@ -25,7 +27,7 @@ namespace Umbraco.Tests.IO { SafeCallContext.Clear(); ClearFiles(); - ShadowFileSystems.ResetId(); + FileSystems.ResetShadowId(); } [TearDown] @@ -33,7 +35,7 @@ namespace Umbraco.Tests.IO { SafeCallContext.Clear(); ClearFiles(); - ShadowFileSystems.ResetId(); + FileSystems.ResetShadowId(); } private static void ClearFiles() @@ -373,6 +375,13 @@ namespace Umbraco.Tests.IO Assert.IsFalse(File.Exists(path + "/ShadowTests/sub/sub/f2.txt")); } + class FS : FileSystemWrapper + { + public FS(IFileSystem innerFileSystem) + : base(innerFileSystem) + { } + } + [Test] public void ShadowScopeComplete() { @@ -385,13 +394,16 @@ namespace Umbraco.Tests.IO var scopedFileSystems = false; - var fs = new PhysicalFileSystem(path, "ignore"); - var sw = new ShadowWrapper(fs, "shadow", () => scopedFileSystems); - var swa = new[] { sw }; + var phy = new PhysicalFileSystem(path, "ignore"); + + var container = Mock.Of(); + var fileSystems = new FileSystems(container, logger) { IsScoped = () => scopedFileSystems }; + var fs = fileSystems.GetFileSystem(() => phy); + var sw = (ShadowWrapper) fs.InnerFileSystem; using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo"))) sw.AddFile("sub/f1.txt", ms); - Assert.IsTrue(fs.FileExists("sub/f1.txt")); + Assert.IsTrue(phy.FileExists("sub/f1.txt")); Guid id; @@ -400,47 +412,55 @@ namespace Umbraco.Tests.IO Assert.IsTrue(Directory.Exists(appdata + "/TEMP/ShadowFs/" + id)); using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo"))) sw.AddFile("sub/f2.txt", ms); - Assert.IsTrue(fs.FileExists("sub/f2.txt")); + Assert.IsTrue(phy.FileExists("sub/f2.txt")); sw.UnShadow(true); - Assert.IsTrue(fs.FileExists("sub/f2.txt")); + Assert.IsTrue(phy.FileExists("sub/f2.txt")); Assert.IsFalse(Directory.Exists(appdata + "/TEMP/ShadowFs/" + id)); // shadow with scope but no complete does not complete scopedFileSystems = true; // pretend we have a scope - var scope = new ShadowFileSystems(id = Guid.NewGuid(), swa, logger); + var scope = new ShadowFileSystems(fileSystems, id = Guid.NewGuid()); Assert.IsTrue(Directory.Exists(appdata + "/TEMP/ShadowFs/" + id)); using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo"))) sw.AddFile("sub/f3.txt", ms); - Assert.IsFalse(fs.FileExists("sub/f3.txt")); - Assert.AreEqual(1, Directory.GetDirectories(appdata + "/TEMP/ShadowFs").Length); + Assert.IsFalse(phy.FileExists("sub/f3.txt")); + var dirs = Directory.GetDirectories(appdata + "/TEMP/ShadowFs"); + Assert.AreEqual(1, dirs.Length); + Assert.AreEqual((appdata + "/TEMP/ShadowFs/" + id).Replace('\\', '/'), dirs[0].Replace('\\', '/')); + dirs = Directory.GetDirectories(dirs[0]); + var typedDir = dirs.FirstOrDefault(x => x.Replace('\\', '/').EndsWith("/typed")); + Assert.IsNotNull(typedDir); + dirs = Directory.GetDirectories(typedDir); + var scopedDir = dirs.FirstOrDefault(x => x.Replace('\\', '/').EndsWith("/Umbraco.Tests.IO.ShadowFileSystemTests+FS")); // this is where files go + Assert.IsNotNull(scopedDir); scope.Dispose(); scopedFileSystems = false; - Assert.IsFalse(fs.FileExists("sub/f3.txt")); + Assert.IsFalse(phy.FileExists("sub/f3.txt")); TestHelper.TryAssert(() => Assert.IsFalse(Directory.Exists(appdata + "/TEMP/ShadowFs/" + id))); // shadow with scope and complete does complete scopedFileSystems = true; // pretend we have a scope - scope = new ShadowFileSystems(id = Guid.NewGuid(), swa, logger); + scope = new ShadowFileSystems(fileSystems, id = Guid.NewGuid()); Assert.IsTrue(Directory.Exists(appdata + "/TEMP/ShadowFs/" + id)); using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo"))) sw.AddFile("sub/f4.txt", ms); - Assert.IsFalse(fs.FileExists("sub/f4.txt")); + Assert.IsFalse(phy.FileExists("sub/f4.txt")); Assert.AreEqual(1, Directory.GetDirectories(appdata + "/TEMP/ShadowFs").Length); scope.Complete(); scope.Dispose(); scopedFileSystems = false; TestHelper.TryAssert(() => Assert.AreEqual(0, Directory.GetDirectories(appdata + "/TEMP/ShadowFs").Length)); - Assert.IsTrue(fs.FileExists("sub/f4.txt")); + Assert.IsTrue(phy.FileExists("sub/f4.txt")); Assert.IsFalse(Directory.Exists(appdata + "/TEMP/ShadowFs/" + id)); // test scope for "another thread" scopedFileSystems = true; // pretend we have a scope - scope = new ShadowFileSystems(id = Guid.NewGuid(), swa, logger); + scope = new ShadowFileSystems(fileSystems, id = Guid.NewGuid()); Assert.IsTrue(Directory.Exists(appdata + "/TEMP/ShadowFs/" + id)); using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo"))) sw.AddFile("sub/f5.txt", ms); - Assert.IsFalse(fs.FileExists("sub/f5.txt")); + Assert.IsFalse(phy.FileExists("sub/f5.txt")); // pretend we're another thread w/out scope scopedFileSystems = false; @@ -448,11 +468,11 @@ namespace Umbraco.Tests.IO sw.AddFile("sub/f6.txt", ms); scopedFileSystems = true; // pretend we have a scope - Assert.IsTrue(fs.FileExists("sub/f6.txt")); // other thread has written out to fs + Assert.IsTrue(phy.FileExists("sub/f6.txt")); // other thread has written out to fs scope.Complete(); scope.Dispose(); scopedFileSystems = false; - Assert.IsTrue(fs.FileExists("sub/f5.txt")); + Assert.IsTrue(phy.FileExists("sub/f5.txt")); Assert.IsFalse(Directory.Exists(appdata + "/TEMP/ShadowFs/" + id)); } @@ -467,22 +487,25 @@ namespace Umbraco.Tests.IO var scopedFileSystems = false; - var fs = new PhysicalFileSystem(path, "ignore"); - var sw = new ShadowWrapper(fs, "shadow", () => scopedFileSystems); - var swa = new[] { sw }; + var phy = new PhysicalFileSystem(path, "ignore"); + + var container = Mock.Of(); + var fileSystems = new FileSystems(container, logger) { IsScoped = () => scopedFileSystems }; + var fs = fileSystems.GetFileSystem(() => phy); + var sw = (ShadowWrapper) fs.InnerFileSystem; using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo"))) sw.AddFile("sub/f1.txt", ms); - Assert.IsTrue(fs.FileExists("sub/f1.txt")); + Assert.IsTrue(phy.FileExists("sub/f1.txt")); Guid id; scopedFileSystems = true; // pretend we have a scope - var scope = new ShadowFileSystems(id = Guid.NewGuid(), swa, logger); + var scope = new ShadowFileSystems(fileSystems, id = Guid.NewGuid()); Assert.IsTrue(Directory.Exists(appdata + "/TEMP/ShadowFs/" + id)); using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo"))) sw.AddFile("sub/f2.txt", ms); - Assert.IsFalse(fs.FileExists("sub/f2.txt")); + Assert.IsFalse(phy.FileExists("sub/f2.txt")); // pretend we're another thread w/out scope scopedFileSystems = false; @@ -490,15 +513,15 @@ namespace Umbraco.Tests.IO sw.AddFile("sub/f2.txt", ms); scopedFileSystems = true; // pretend we have a scope - Assert.IsTrue(fs.FileExists("sub/f2.txt")); // other thread has written out to fs + Assert.IsTrue(phy.FileExists("sub/f2.txt")); // other thread has written out to fs scope.Complete(); scope.Dispose(); scopedFileSystems = false; - Assert.IsTrue(fs.FileExists("sub/f2.txt")); + Assert.IsTrue(phy.FileExists("sub/f2.txt")); TestHelper.TryAssert(() => Assert.IsFalse(Directory.Exists(appdata + "/TEMP/ShadowFs/" + id))); string text; - using (var s = fs.OpenFile("sub/f2.txt")) + using (var s = phy.OpenFile("sub/f2.txt")) using (var r = new StreamReader(s)) text = r.ReadToEnd(); @@ -517,22 +540,25 @@ namespace Umbraco.Tests.IO var scopedFileSystems = false; - var fs = new PhysicalFileSystem(path, "ignore"); - var sw = new ShadowWrapper(fs, "shadow", () => scopedFileSystems); - var swa = new[] { sw }; + var phy = new PhysicalFileSystem(path, "ignore"); + + var container = Mock.Of(); + var fileSystems = new FileSystems(container, logger) { IsScoped = () => scopedFileSystems }; + var fs = fileSystems.GetFileSystem(() => phy); + var sw = (ShadowWrapper)fs.InnerFileSystem; using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo"))) sw.AddFile("sub/f1.txt", ms); - Assert.IsTrue(fs.FileExists("sub/f1.txt")); + Assert.IsTrue(phy.FileExists("sub/f1.txt")); Guid id; scopedFileSystems = true; // pretend we have a scope - var scope = new ShadowFileSystems(id = Guid.NewGuid(), swa, logger); + var scope = new ShadowFileSystems(fileSystems, id = Guid.NewGuid()); Assert.IsTrue(Directory.Exists(appdata + "/TEMP/ShadowFs/" + id)); using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo"))) sw.AddFile("sub/f2.txt", ms); - Assert.IsFalse(fs.FileExists("sub/f2.txt")); + Assert.IsFalse(phy.FileExists("sub/f2.txt")); // pretend we're another thread w/out scope scopedFileSystems = false; @@ -540,11 +566,11 @@ namespace Umbraco.Tests.IO sw.AddFile("sub/f2.txt/f2.txt", ms); scopedFileSystems = true; // pretend we have a scope - Assert.IsTrue(fs.FileExists("sub/f2.txt/f2.txt")); // other thread has written out to fs + Assert.IsTrue(phy.FileExists("sub/f2.txt/f2.txt")); // other thread has written out to fs using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo"))) sw.AddFile("sub/f3.txt", ms); - Assert.IsFalse(fs.FileExists("sub/f3.txt")); + Assert.IsFalse(phy.FileExists("sub/f3.txt")); scope.Complete(); @@ -570,7 +596,7 @@ namespace Umbraco.Tests.IO } // still, the rest of the changes has been applied ok - Assert.IsTrue(fs.FileExists("sub/f3.txt")); + Assert.IsTrue(phy.FileExists("sub/f3.txt")); } [Test] diff --git a/src/Umbraco.Tests/Models/ContentTests.cs b/src/Umbraco.Tests/Models/ContentTests.cs index f32e7c3046..bb9f176e0c 100644 --- a/src/Umbraco.Tests/Models/ContentTests.cs +++ b/src/Umbraco.Tests/Models/ContentTests.cs @@ -10,6 +10,7 @@ using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; +using Umbraco.Core.Composing.Composers; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; using Umbraco.Core.Logging; @@ -40,9 +41,8 @@ namespace Umbraco.Tests.Models base.Compose(); Container.Register(_ => Mock.Of()); - Container.Register(); - Container.Register(factory => factory.GetInstance()); - Container.Register(factory => factory.GetInstance().MediaFileSystem); + Container.ComposeFileSystems(); + Container.Register(_ => Mock.Of()); Container.Register(_ => Mock.Of()); } diff --git a/src/Umbraco.Tests/Scoping/ScopeFileSystemsTests.cs b/src/Umbraco.Tests/Scoping/ScopeFileSystemsTests.cs index f095e30553..680eddf953 100644 --- a/src/Umbraco.Tests/Scoping/ScopeFileSystemsTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopeFileSystemsTests.cs @@ -37,7 +37,7 @@ namespace Umbraco.Tests.Scoping { base.TearDown(); SafeCallContext.Clear(); - ShadowFileSystems.ResetId(); + FileSystems.ResetShadowId(); ClearFiles(); } @@ -53,7 +53,7 @@ namespace Umbraco.Tests.Scoping public void CreateMediaTest(bool complete) { var physMediaFileSystem = new PhysicalFileSystem(IOHelper.MapPath("media"), "ignore"); - var mediaFileSystem = Current.FileSystems.MediaFileSystem; + var mediaFileSystem = Current.MediaFileSystem; Assert.IsFalse(physMediaFileSystem.FileExists("f1.txt")); @@ -72,12 +72,12 @@ namespace Umbraco.Tests.Scoping if (complete) { - Assert.IsTrue(Current.FileSystems.MediaFileSystem.FileExists("f1.txt")); + Assert.IsTrue(Current.MediaFileSystem.FileExists("f1.txt")); Assert.IsTrue(physMediaFileSystem.FileExists("f1.txt")); } else { - Assert.IsFalse(Current.FileSystems.MediaFileSystem.FileExists("f1.txt")); + Assert.IsFalse(Current.MediaFileSystem.FileExists("f1.txt")); Assert.IsFalse(physMediaFileSystem.FileExists("f1.txt")); } } @@ -86,7 +86,7 @@ namespace Umbraco.Tests.Scoping public void MultiThread() { var physMediaFileSystem = new PhysicalFileSystem(IOHelper.MapPath("media"), "ignore"); - var mediaFileSystem = Current.FileSystems.MediaFileSystem; + var mediaFileSystem = Current.MediaFileSystem; var scopeProvider = ScopeProvider; using (var scope = scopeProvider.CreateScope(scopeFileSystems: true)) diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs b/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs index 0a0d381570..06654a3519 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs @@ -150,9 +150,6 @@ namespace Umbraco.Tests.TestHelpers MockFs(fileSystems, x => x.ScriptsFileSystem); MockFs(fileSystems, x => x.StylesheetsFileSystem); - var mediaFs = new MediaFileSystem(Mock.Of()); - Mock.Get(fileSystems).Setup(x => x.MediaFileSystem).Returns(mediaFs); - return fileSystems; } diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index 26c4c1e785..6104f365cf 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -297,7 +297,7 @@ namespace Umbraco.Tests.Testing // register filesystems Container.RegisterSingleton(factory => TestObjects.GetFileSystemsMock()); - Container.RegisterSingleton(factory => factory.GetInstance().MediaFileSystem); + Container.RegisterSingleton(factory => new MediaFileSystem(Mock.Of())); // no factory (noop) Container.RegisterSingleton(); diff --git a/src/Umbraco.Web/Editors/UsersController.cs b/src/Umbraco.Web/Editors/UsersController.cs index f7edd3de8f..dc5d45799f 100644 --- a/src/Umbraco.Web/Editors/UsersController.cs +++ b/src/Umbraco.Web/Editors/UsersController.cs @@ -105,7 +105,7 @@ namespace Umbraco.Web.Editors using (var fs = System.IO.File.OpenRead(file.LocalFileName)) { - Current.FileSystems.MediaFileSystem.AddFile(user.Avatar, fs, true); + Current.MediaFileSystem.AddFile(user.Avatar, fs, true); } userService.Save(user); @@ -146,8 +146,8 @@ namespace Umbraco.Web.Editors if (filePath.IsNullOrWhiteSpace() == false) { - if (Current.FileSystems.MediaFileSystem.FileExists(filePath)) - Current.FileSystems.MediaFileSystem.DeleteFile(filePath); + if (Current.MediaFileSystem.FileExists(filePath)) + Current.MediaFileSystem.DeleteFile(filePath); } return Request.CreateResponse(HttpStatusCode.OK, found.GetUserAvatarUrls(ApplicationCache.StaticCache)); From 199e09c789b4b1f40429c30867c6630108702660 Mon Sep 17 00:00:00 2001 From: Stephan Date: Mon, 19 Nov 2018 14:52:55 +0100 Subject: [PATCH 091/469] Remove named services support requirement from IContainer --- .../Composing/ContainerExtensions.cs | 29 ----------- src/Umbraco.Core/Composing/IContainer.cs | 24 ---------- .../LightInject/LightInjectContainer.cs | 48 ------------------- src/Umbraco.Core/Runtime/CoreRuntime.cs | 8 ++-- 4 files changed, 4 insertions(+), 105 deletions(-) diff --git a/src/Umbraco.Core/Composing/ContainerExtensions.cs b/src/Umbraco.Core/Composing/ContainerExtensions.cs index 36af613e55..ac1df5dadb 100644 --- a/src/Umbraco.Core/Composing/ContainerExtensions.cs +++ b/src/Umbraco.Core/Composing/ContainerExtensions.cs @@ -24,17 +24,6 @@ namespace Umbraco.Core.Composing public static T GetInstance(this IContainer container) => (T) container.GetInstance(typeof(T)); - /// - /// Gets an instance of a named service. - /// - /// The type of the service. - /// The container. - /// The name of the service. - /// An instance of the specified type and name. - /// Throws an exception if the container failed to get an instance of the specified type. - public static T GetInstance(this IContainer container, string name) - => (T) container.GetInstance(typeof(T), name); - /// /// Tries to get an instance of a service. /// @@ -100,18 +89,6 @@ namespace Umbraco.Core.Composing public static void Register(this IContainer container, Lifetime lifetime = Lifetime.Transient) => container.Register(typeof(TService), typeof(TImplementing), lifetime); - /// - /// Registers a named service with an implementation type. - /// - public static void Register(this IContainer container, string name, Lifetime lifetime = Lifetime.Transient) - => container.Register(typeof(TService), typeof(TImplementing), name, lifetime); - - /// - /// Registers a named service with an implementation factory. - /// - public static void Register(this IContainer container, string name, Func factory, Lifetime lifetime = Lifetime.Transient) - => container.Register(factory, name, lifetime); - /// /// Registers a service as its own implementation. /// @@ -136,12 +113,6 @@ namespace Umbraco.Core.Composing public static void RegisterSingleton(this IContainer container, Func factory) => container.Register(factory, Lifetime.Singleton); - /// - /// Registers a named singleton service with an implementation factory. - /// - public static void RegisterSingleton(this IContainer container, string name, Func factory) - => container.Register(factory, name, Lifetime.Singleton); - /// /// Registers a service with an implementing instance. /// diff --git a/src/Umbraco.Core/Composing/IContainer.cs b/src/Umbraco.Core/Composing/IContainer.cs index 1780516c76..f25314806f 100644 --- a/src/Umbraco.Core/Composing/IContainer.cs +++ b/src/Umbraco.Core/Composing/IContainer.cs @@ -40,15 +40,6 @@ namespace Umbraco.Core.Composing /// Throws an exception if the container failed to get an instance of the specified type. object GetInstance(Type type); - /// - /// Gets an instance of a named service. - /// - /// The type of the service. - /// The name of the service. - /// An instance of the specified type. - /// Throws an exception if the container failed to get an instance of the specified type. - object GetInstance(Type type, string name); - /// /// Tries to get an instance of a service. /// @@ -103,16 +94,6 @@ namespace Umbraco.Core.Composing /// void Register(Type serviceType, Type implementingType, Lifetime lifetime = Lifetime.Transient); - /// - /// Registers a named service with a implementation type. - /// - void Register(Type serviceType, Type implementingType, string name, Lifetime lifetime = Lifetime.Transient); - - /// - /// Registers a named service with an implementation factory. - /// - void Register(Func factory, string name, Lifetime lifetime = Lifetime.Transient); - /// /// Registers a service with an implementation factory. /// @@ -123,11 +104,6 @@ namespace Umbraco.Core.Composing /// void RegisterInstance(Type serviceType, object instance); - /// - /// Registers a named service with an implementing instance. - /// - void RegisterInstance(Type serviceType, object instance, string name); - /// /// Registers a base type for auto-registration. /// diff --git a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs index 34bd2f1499..dfa404a07a 100644 --- a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs +++ b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs @@ -105,10 +105,6 @@ namespace Umbraco.Core.Composing.LightInject public object GetInstance(Type type) => Container.GetInstance(type); - /// - public object GetInstance(Type type, string name) - => Container.GetInstance(type, name); - /// public object TryGetInstance(Type type) => Container.TryGetInstance(type); @@ -181,26 +177,6 @@ namespace Umbraco.Core.Composing.LightInject } } - /// - public void Register(Type serviceType, Type implementingType, string name, Lifetime lifetime = Lifetime.Transient) - { - switch (lifetime) - { - case Lifetime.Transient: - Container.Register(serviceType, implementingType, name); - break; - case Lifetime.Request: - case Lifetime.Scope: - Container.Register(serviceType, implementingType, name, GetLifetime(lifetime)); - break; - case Lifetime.Singleton: - Container.RegisterSingleton(serviceType, implementingType, name); - break; - default: - throw new NotSupportedException($"Lifetime {lifetime} is not supported."); - } - } - /// public void Register(Func factory, Lifetime lifetime = Lifetime.Transient) { @@ -221,26 +197,6 @@ namespace Umbraco.Core.Composing.LightInject } } - /// - public void Register(Func factory, string name, Lifetime lifetime = Lifetime.Transient) - { - switch (lifetime) - { - case Lifetime.Transient: - Container.Register(f => factory(this), name); - break; - case Lifetime.Request: - case Lifetime.Scope: - Container.Register(f => factory(this), name, GetLifetime(lifetime)); - break; - case Lifetime.Singleton: - Container.RegisterSingleton(f => factory(this), name); - break; - default: - throw new NotSupportedException($"Lifetime {lifetime} is not supported."); - } - } - private ILifetime GetLifetime(Lifetime lifetime) { switch (lifetime) @@ -262,10 +218,6 @@ namespace Umbraco.Core.Composing.LightInject public void RegisterInstance(Type serviceType, object instance) => Container.RegisterInstance(serviceType, instance); - /// - public void RegisterInstance(Type serviceType, object instance, string name) - => Container.RegisterInstance(serviceType, instance, name); - /// public void RegisterAuto(Type serviceBaseType) { diff --git a/src/Umbraco.Core/Runtime/CoreRuntime.cs b/src/Umbraco.Core/Runtime/CoreRuntime.cs index 5464961f16..3440582084 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntime.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntime.cs @@ -210,10 +210,10 @@ namespace Umbraco.Core.Runtime // register the plugin manager container.RegisterSingleton(f => new TypeLoader(f.GetInstance(), f.GetInstance(), f.GetInstance())); - // register syntax providers - required by database factory - container.Register("MySqlSyntaxProvider"); - container.Register("SqlCeSyntaxProvider"); - container.Register("SqlServerSyntaxProvider"); + // register syntax providers - required by database factory - GetAllInstances or an IEnumerable can get them + container.Register(); + container.Register(); + container.Register(); // register persistence mappers - required by database factory so needs to be done here // means the only place the collection can be modified is in a runtime - afterwards it From b69cbf0c53e1c4b5d68b89f22dc6d04cb5071b9a Mon Sep 17 00:00:00 2001 From: Stephan Date: Mon, 19 Nov 2018 15:10:35 +0100 Subject: [PATCH 092/469] Remove RegisterOrdered requirement from IContainer --- src/Umbraco.Core/Composing/IContainer.cs | 6 ---- .../LightInject/LightInjectContainer.cs | 4 --- .../Composing/Composers/InstallerComposer.cs | 35 ++++++++----------- .../Install/InstallStepCollection.cs | 24 +++++++++++-- 4 files changed, 37 insertions(+), 32 deletions(-) diff --git a/src/Umbraco.Core/Composing/IContainer.cs b/src/Umbraco.Core/Composing/IContainer.cs index f25314806f..0d4fcb0d98 100644 --- a/src/Umbraco.Core/Composing/IContainer.cs +++ b/src/Umbraco.Core/Composing/IContainer.cs @@ -116,12 +116,6 @@ namespace Umbraco.Core.Composing /// void RegisterAuto(Type serviceBaseType); - /// - /// Registers a service with an ordered set of implementation types. - /// - // fixme: once we merge the installer refactoring, kill that one - void RegisterOrdered(Type serviceType, Type[] implementingTypes, Lifetime lifetime = Lifetime.Transient); - #endregion #region Control diff --git a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs index dfa404a07a..90c2903bc7 100644 --- a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs +++ b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs @@ -230,10 +230,6 @@ namespace Umbraco.Core.Composing.LightInject }, null); } - /// - public void RegisterOrdered(Type serviceType, Type[] implementingTypes, Lifetime lifetime = Lifetime.Transient) - => Container.RegisterOrdered(serviceType, implementingTypes, _ => GetLifetime(lifetime)); - // was the Light-Inject specific way of dealing with args, but we've replaced it with our own // beware! does NOT work on singletons, see https://github.com/seesharper/LightInject/issues/294 // diff --git a/src/Umbraco.Web/Composing/Composers/InstallerComposer.cs b/src/Umbraco.Web/Composing/Composers/InstallerComposer.cs index 9c701495fd..b9acc636c5 100644 --- a/src/Umbraco.Web/Composing/Composers/InstallerComposer.cs +++ b/src/Umbraco.Web/Composing/Composers/InstallerComposer.cs @@ -1,8 +1,6 @@ -using Umbraco.Core; -using Umbraco.Core.Composing; +using Umbraco.Core.Composing; using Umbraco.Web.Install; using Umbraco.Web.Install.InstallSteps; -using Umbraco.Web.Install.Models; namespace Umbraco.Web.Composing.Composers { @@ -10,25 +8,22 @@ namespace Umbraco.Web.Composing.Composers { public static IContainer ComposeInstaller(this IContainer container) { - //register the installer steps in order - container.RegisterOrdered(typeof(InstallSetupStep), - new[] - { - typeof(NewInstallStep), - typeof(UpgradeStep), - typeof(FilePermissionsStep), - typeof(ConfigureMachineKey), - typeof(DatabaseConfigureStep), - typeof(DatabaseInstallStep), - typeof(DatabaseUpgradeStep), + // register the installer steps - //TODO: Add these back once we have a compatible starter kit - //typeof(StarterKitDownloadStep), - //typeof(StarterKitInstallStep), - //typeof(StarterKitCleanupStep), + container.Register(Lifetime.Scope); + container.Register(Lifetime.Scope); + container.Register(Lifetime.Scope); + container.Register(Lifetime.Scope); + container.Register(Lifetime.Scope); + container.Register(Lifetime.Scope); + container.Register(Lifetime.Scope); - typeof(SetUmbracoVersionStep) - }, Lifetime.Scope); + //TODO: Add these back once we have a compatible starter kit + //container.Register(Lifetime.Scope); + //container.Register(Lifetime.Scope); + //container.Register(Lifetime.Scope); + + container.Register(Lifetime.Scope); container.Register(); container.Register(); diff --git a/src/Umbraco.Web/Install/InstallStepCollection.cs b/src/Umbraco.Web/Install/InstallStepCollection.cs index 22e084ede3..ffbd3f10cb 100644 --- a/src/Umbraco.Web/Install/InstallStepCollection.cs +++ b/src/Umbraco.Web/Install/InstallStepCollection.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Linq; +using Umbraco.Web.Install.InstallSteps; using Umbraco.Web.Install.Models; namespace Umbraco.Web.Install @@ -9,10 +10,29 @@ namespace Umbraco.Web.Install private readonly InstallHelper _installHelper; private readonly IEnumerable _orderedInstallerSteps; - public InstallStepCollection(InstallHelper installHelper, IEnumerable orderedInstallerSteps) + public InstallStepCollection(InstallHelper installHelper, IEnumerable installerSteps) { _installHelper = installHelper; - _orderedInstallerSteps = orderedInstallerSteps; + + // fixme this is ugly but I have a branch where it's nicely refactored - for now we just want to manage ordering + var a = installerSteps.ToArray(); + _orderedInstallerSteps = new InstallSetupStep[] + { + a.OfType().First(), + a.OfType().First(), + a.OfType().First(), + a.OfType().First(), + a.OfType().First(), + a.OfType().First(), + a.OfType().First(), + + //TODO: Add these back once we have a compatible starter kit + //orderedInstallerSteps.OfType().First(), + //orderedInstallerSteps.OfType().First(), + //orderedInstallerSteps.OfType().First(), + + a.OfType().First(), + }; } From e41790b8869fc6958df5533ef0349a15a5c7026c Mon Sep 17 00:00:00 2001 From: Stephan Date: Mon, 19 Nov 2018 15:16:55 +0100 Subject: [PATCH 093/469] Add IContainer tests --- src/Umbraco.Tests/Composing/ContainerTests.cs | 43 +++++++++++++++++++ src/Umbraco.Tests/Umbraco.Tests.csproj | 1 + 2 files changed, 44 insertions(+) create mode 100644 src/Umbraco.Tests/Composing/ContainerTests.cs diff --git a/src/Umbraco.Tests/Composing/ContainerTests.cs b/src/Umbraco.Tests/Composing/ContainerTests.cs new file mode 100644 index 0000000000..6f4a21ca5f --- /dev/null +++ b/src/Umbraco.Tests/Composing/ContainerTests.cs @@ -0,0 +1,43 @@ +using System.Collections.Generic; +using System.Linq; +using NUnit.Framework; +using Umbraco.Core.Composing; +using Umbraco.Core.Composing.LightInject; + +namespace Umbraco.Tests.Composing +{ + [TestFixture] + public class ContainerTests + { + // tests that a container conforms + + private IContainer GetContainer() => LightInjectContainer.Create(); + + [Test] + public void CanGetEnumerable() + { + var container = GetContainer(); + + container.Register(); + container.Register(); + container.Register(); + + var needThings = container.GetInstance(); + Assert.AreEqual(2, needThings.Things.Count()); + } + + public abstract class ThingBase { } + public class Thing1 : ThingBase { } + public class Thing2 : ThingBase { } + + public class NeedThings + { + public NeedThings(IEnumerable things) + { + Things = things; + } + + public IEnumerable Things { get; } + } + } +} diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index d21d1e89c7..8095bcfb2c 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -117,6 +117,7 @@ + From ce47eae85b4348d067ae7cfb5c4c5044a277df31 Mon Sep 17 00:00:00 2001 From: Stephan Date: Fri, 23 Nov 2018 16:19:03 +0100 Subject: [PATCH 094/469] Various fixes --- src/Umbraco.Core/Components/BootLoader.cs | 16 ++-- ...ute.cs => RequiredByComponentAttribute.cs} | 6 +- .../Composing/ContainerFactory.cs | 4 - src/Umbraco.Core/Composing/IContainer.cs | 1 - src/Umbraco.Core/Runtime/CoreRuntime.cs | 17 +--- src/Umbraco.Core/Umbraco.Core.csproj | 2 +- .../Components/ComponentTests.cs | 6 +- .../Repositories/StylesheetRepositoryTest.cs | 27 +++---- src/Umbraco.Web/Actions/ActionCollection.cs | 78 +++---------------- .../Actions/ActionCollectionBuilder.cs | 21 +++-- .../Cache/CacheRefresherComponent.cs | 2 +- src/Umbraco.Web/UmbracoApplicationBase.cs | 5 +- src/Umbraco.Web/UmbracoContext.cs | 2 +- 13 files changed, 54 insertions(+), 133 deletions(-) rename src/Umbraco.Core/Components/{RequiredComponentAttribute.cs => RequiredByComponentAttribute.cs} (92%) diff --git a/src/Umbraco.Core/Components/BootLoader.cs b/src/Umbraco.Core/Components/BootLoader.cs index e2ab754956..ff0b7ab05b 100644 --- a/src/Umbraco.Core/Components/BootLoader.cs +++ b/src/Umbraco.Core/Components/BootLoader.cs @@ -135,7 +135,7 @@ namespace Umbraco.Core.Components text.AppendLine(" -> " + attribute.RequiredType + (attribute.Weak.HasValue ? (attribute.Weak.Value ? " (weak)" : (" (strong" + (requirements.ContainsKey(attribute.RequiredType) ? ", missing" : "") + ")")) : "")); - foreach (var attribute in type.GetCustomAttributes()) + foreach (var attribute in type.GetCustomAttributes()) text.AppendLine(" -< " + attribute.RequiringType); foreach (var i in type.GetInterfaces()) { @@ -144,7 +144,7 @@ namespace Umbraco.Core.Components text.AppendLine(" -> " + attribute.RequiredType + (attribute.Weak.HasValue ? (attribute.Weak.Value ? " (weak)" : (" (strong" + (requirements.ContainsKey(attribute.RequiredType) ? ", missing" : "") + ")")) : "")); - foreach (var attribute in i.GetCustomAttributes()) + foreach (var attribute in i.GetCustomAttributes()) text.AppendLine(" -< " + attribute.RequiringType); } if (kvp.Value != null) @@ -221,7 +221,7 @@ namespace Umbraco.Core.Components if (requirements[type] == null) requirements[type] = new List(); requirements[type].AddRange(implems); } - else if (attr.Weak == false) // if explicitely set to !weak, is strong, else is weak + else if (attr.Weak == false) // if explicitly set to !weak, is strong, else is weak throw new Exception($"Broken component dependency: {type.FullName} -> {attr.RequiredType.FullName}."); } // requiring a class = require that the component is enabled @@ -233,7 +233,7 @@ namespace Umbraco.Core.Components if (requirements[type] == null) requirements[type] = new List(); requirements[type].Add(attr.RequiredType); } - else if (attr.Weak != true) // if not explicitely set to weak, is strong + else if (attr.Weak != true) // if not explicitly set to weak, is strong throw new Exception($"Broken component dependency: {type.FullName} -> {attr.RequiredType.FullName}."); } } @@ -244,8 +244,8 @@ namespace Umbraco.Core.Components // get 'required' attributes // these attributes are *not* inherited because we want to "custom-inherit" for interfaces only var requiredAttributes = type - .GetInterfaces().SelectMany(x => x.GetCustomAttributes()) // those marking interfaces - .Concat(type.GetCustomAttributes()); // those marking the component + .GetInterfaces().SelectMany(x => x.GetCustomAttributes()) // those marking interfaces + .Concat(type.GetCustomAttributes()); // those marking the component foreach (var attr in requiredAttributes) { @@ -275,7 +275,7 @@ namespace Umbraco.Core.Components private void InstantiateComponents(IEnumerable types) { - using (_proflog.DebugDuration("Instanciating components.", "Instanciated components.")) + using (_proflog.DebugDuration("Instantiating components.", "Instantiated components.")) { _components = types.Select(x => (IUmbracoComponent) Activator.CreateInstance(x)).ToArray(); } @@ -309,7 +309,7 @@ namespace Umbraco.Core.Components var componentType = component.GetType(); var initializers = componentType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) .Where(x => x.Name == "Initialize" && x.IsGenericMethod == false && x.IsStatic == false); - using (_proflog.DebugDuration($"Initializing {componentType.FullName}.", $"Initialised {componentType.FullName}.", thresholdMilliseconds: LogThresholdMilliseconds)) + using (_proflog.DebugDuration($"Initializing {componentType.FullName}.", $"Initialized {componentType.FullName}.", thresholdMilliseconds: LogThresholdMilliseconds)) { foreach (var initializer in initializers) { diff --git a/src/Umbraco.Core/Components/RequiredComponentAttribute.cs b/src/Umbraco.Core/Components/RequiredByComponentAttribute.cs similarity index 92% rename from src/Umbraco.Core/Components/RequiredComponentAttribute.cs rename to src/Umbraco.Core/Components/RequiredByComponentAttribute.cs index 0a542b9fd6..9d206b564b 100644 --- a/src/Umbraco.Core/Components/RequiredComponentAttribute.cs +++ b/src/Umbraco.Core/Components/RequiredByComponentAttribute.cs @@ -19,13 +19,13 @@ namespace Umbraco.Core.Components /// [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = true, Inherited = false)] - public class RequiredComponentAttribute : Attribute + public class RequiredByComponentAttribute : Attribute { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The type of the required component. - public RequiredComponentAttribute(Type requiringType) + public RequiredByComponentAttribute(Type requiringType) { if (typeof(IUmbracoComponent).IsAssignableFrom(requiringType) == false) throw new ArgumentException($"Type {requiringType.FullName} is invalid here because it does not implement {typeof(IUmbracoComponent).FullName}."); diff --git a/src/Umbraco.Core/Composing/ContainerFactory.cs b/src/Umbraco.Core/Composing/ContainerFactory.cs index bf808d56ae..fb2c5f6eb7 100644 --- a/src/Umbraco.Core/Composing/ContainerFactory.cs +++ b/src/Umbraco.Core/Composing/ContainerFactory.cs @@ -50,10 +50,6 @@ namespace Umbraco.Core.Composing if (container == null) throw new Exception($"Container factory '{configuredTypeName}' did not return an IContainer implementation."); - // self-register the container - this is where it should happen - // but - we do NOT want to do it! - //container.RegisterInstance(container); - return container; } } diff --git a/src/Umbraco.Core/Composing/IContainer.cs b/src/Umbraco.Core/Composing/IContainer.cs index 0d4fcb0d98..d068339eb1 100644 --- a/src/Umbraco.Core/Composing/IContainer.cs +++ b/src/Umbraco.Core/Composing/IContainer.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using Umbraco.Core.Composing.LightInject; namespace Umbraco.Core.Composing { diff --git a/src/Umbraco.Core/Runtime/CoreRuntime.cs b/src/Umbraco.Core/Runtime/CoreRuntime.cs index 5d64f75adb..3004c7566a 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntime.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntime.cs @@ -14,7 +14,6 @@ using Umbraco.Core.Logging; using Umbraco.Core.Logging.Serilog; using Umbraco.Core.Migrations.Upgrade; using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.Dtos; using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Scoping; @@ -32,16 +31,11 @@ namespace Umbraco.Core.Runtime private BootLoader _bootLoader; private RuntimeState _state; - /// - /// Initializes a new instance of the class. - /// - public CoreRuntime() - { } - /// public virtual void Boot(IContainer container) { - container.ConfigureUmbracoCore(); // also sets Current.Container + // assign current container + Current.Container = container; // register the essential stuff, // ie the global application logger @@ -109,13 +103,6 @@ namespace Umbraco.Core.Runtime // throw a BootFailedException for every requests. } } - - //fixme - // after Umbraco has started there is a scope in "context" and that context is - // going to stay there and never get destroyed nor reused, so we have to ensure that - // everything is cleared - //var sa = container.GetInstance(); - //sa.Scope?.Dispose(); } /// diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 077487c8be..1b517ae1f9 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -165,7 +165,7 @@ - + diff --git a/src/Umbraco.Tests/Components/ComponentTests.cs b/src/Umbraco.Tests/Components/ComponentTests.cs index a78f9f3249..a537aac4ae 100644 --- a/src/Umbraco.Tests/Components/ComponentTests.cs +++ b/src/Umbraco.Tests/Components/ComponentTests.cs @@ -296,7 +296,7 @@ namespace Umbraco.Tests.Components public class Component12 : TestComponentBase, IUmbracoCoreComponent { } - [RequiredComponent(typeof(Component1))] + [RequiredByComponent(typeof(Component1))] public class Component13 : TestComponentBase { } @@ -307,7 +307,7 @@ namespace Umbraco.Tests.Components public class Component20 : TestComponentBase { } - [RequiredComponent(typeof(Component20))] + [RequiredByComponent(typeof(Component20))] public class Component21 : TestComponentBase { } @@ -322,7 +322,7 @@ namespace Umbraco.Tests.Components { } // should insert itself between 22 and anything i23 - [RequiredComponent(typeof(IComponent23))] + [RequiredByComponent(typeof(IComponent23))] //[RequireComponent(typeof(Component22))] - not needed, implement i23 public class Component25 : TestComponentBase, IComponent23 { } diff --git a/src/Umbraco.Tests/Persistence/Repositories/StylesheetRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/StylesheetRepositoryTest.cs index a1acbca1e9..6fae1d4749 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/StylesheetRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/StylesheetRepositoryTest.cs @@ -2,6 +2,7 @@ using System.IO; using System.Linq; using System.Text; +using Moq; using NUnit.Framework; using Umbraco.Core.IO; using Umbraco.Core.Models; @@ -55,7 +56,7 @@ namespace Umbraco.Tests.Persistence.Repositories // Act var stylesheet = new Stylesheet("test-add.css") { Content = "body { color:#000; } .bold {font-weight:bold;}" }; repository.Save(stylesheet); - + //Assert Assert.That(_fileSystem.FileExists("test-add.css"), Is.True); @@ -73,12 +74,12 @@ namespace Umbraco.Tests.Persistence.Repositories // Act var stylesheet = new Stylesheet("test-update.css") { Content = "body { color:#000; } .bold {font-weight:bold;}" }; repository.Save(stylesheet); - + var stylesheetUpdate = repository.Get("test-update.css"); stylesheetUpdate.Content = "body { color:#000; }"; repository.Save(stylesheetUpdate); - + var stylesheetUpdated = repository.Get("test-update.css"); @@ -100,12 +101,12 @@ namespace Umbraco.Tests.Persistence.Repositories // Act var stylesheet = new Stylesheet("test-update.css") { Content = "body { color:#000; } .bold {font-weight:bold;}" }; repository.Save(stylesheet); - + stylesheet.AddProperty(new StylesheetProperty("Test", "p", "font-size:2em;")); repository.Save(stylesheet); - + //re-get stylesheet = repository.Get(stylesheet.Name); @@ -127,7 +128,7 @@ namespace Umbraco.Tests.Persistence.Repositories // Act var stylesheet = new Stylesheet("test-update.css") { Content = "body { color:#000; } .bold {font-weight:bold;}" }; repository.Save(stylesheet); - + stylesheet.AddProperty(new StylesheetProperty("Test", "p", "font-size:2em;")); @@ -146,10 +147,10 @@ namespace Umbraco.Tests.Persistence.Repositories // Act var stylesheet = new Stylesheet("test-delete.css") { Content = "body { color:#000; } .bold {font-weight:bold;}" }; repository.Save(stylesheet); - + repository.Delete(stylesheet); - + //Assert Assert.That(_fileSystem.FileExists("test-delete.css"), Is.False); @@ -185,7 +186,7 @@ namespace Umbraco.Tests.Persistence.Repositories var stylesheet = new Stylesheet("styles-v2.css") { Content = "body { color:#000; } .bold {font-weight:bold;}" }; repository.Save(stylesheet); - + // Act var stylesheets = repository.GetMany(); @@ -208,7 +209,7 @@ namespace Umbraco.Tests.Persistence.Repositories var stylesheet = new Stylesheet("styles-v2.css") { Content = "body { color:#000; } .bold {font-weight:bold;}" }; repository.Save(stylesheet); - + // Act var stylesheets = repository.GetMany("styles-v2.css", "styles.css"); @@ -248,14 +249,14 @@ namespace Umbraco.Tests.Persistence.Repositories var stylesheet = new Stylesheet("test-path-1.css") { Content = "body { color:#000; } .bold {font-weight:bold;}" }; repository.Save(stylesheet); - + Assert.IsTrue(_fileSystem.FileExists("test-path-1.css")); Assert.AreEqual("test-path-1.css", stylesheet.Path); Assert.AreEqual("/css/test-path-1.css", stylesheet.VirtualPath); stylesheet = new Stylesheet("path-2/test-path-2.css") { Content = "body { color:#000; } .bold {font-weight:bold;}" }; repository.Save(stylesheet); - + Assert.IsTrue(_fileSystem.FileExists("path-2/test-path-2.css")); Assert.AreEqual("path-2\\test-path-2.css", stylesheet.Path); // fixed in 7.3 - 7.2.8 does not update the path Assert.AreEqual("/css/path-2/test-path-2.css", stylesheet.VirtualPath); @@ -267,7 +268,7 @@ namespace Umbraco.Tests.Persistence.Repositories stylesheet = new Stylesheet("path-2\\test-path-3.css") { Content = "body { color:#000; } .bold {font-weight:bold;}" }; repository.Save(stylesheet); - + Assert.IsTrue(_fileSystem.FileExists("path-2/test-path-3.css")); Assert.AreEqual("path-2\\test-path-3.css", stylesheet.Path); Assert.AreEqual("/css/path-2/test-path-3.css", stylesheet.VirtualPath); diff --git a/src/Umbraco.Web/Actions/ActionCollection.cs b/src/Umbraco.Web/Actions/ActionCollection.cs index 23b33d5f67..0e33f03103 100644 --- a/src/Umbraco.Web/Actions/ActionCollection.cs +++ b/src/Umbraco.Web/Actions/ActionCollection.cs @@ -1,9 +1,5 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Globalization; +using System.Collections.Generic; using System.Linq; -using System.Reflection; using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Core.Models.Membership; @@ -11,16 +7,11 @@ using Umbraco.Core.Models.Membership; namespace Umbraco.Web.Actions { - public class ActionCollection : IBuilderCollection + public class ActionCollection : BuilderCollectionBase { - private Func> _producer; - private readonly object _locker = new object(); - private IAction[] _items; - - internal ActionCollection(Func> producer) - { - _producer = producer; - } + public ActionCollection(IEnumerable items) + : base(items) + { } internal T GetAction() where T : IAction @@ -30,66 +21,19 @@ namespace Umbraco.Web.Actions internal IEnumerable GetByLetters(IEnumerable letters) { - var all = this.ToArray(); - return letters.Select(x => all.FirstOrDefault(y => y.Letter.ToString(CultureInfo.InvariantCulture) == x)) + return letters + .Where(x => x.Length == 1) + .Select(x => this.FirstOrDefault(y => y.Letter == x[0])) .WhereNotNull() - .ToArray(); + .ToList(); } - private IAction[] Items - { - get - { - lock (_locker) - { - if (_items != null) return _items; - // fixme - // why is this not a builder collection base anymore? - // - var actions = new List(); - foreach (var type in _producer()) - { - var getter = type.GetProperty("Instance", BindingFlags.Public | BindingFlags.Static); - var instance = getter == null - ? Activator.CreateInstance(type) as IAction - : getter.GetValue(null, null) as IAction; - if (instance == null) continue; - actions.Add(instance); - } - - return _items = actions.ToArray(); - } - } - } - - internal void Reset(Func> producer) - { - lock (_locker) - { - _items = null; - _producer = producer; - } - } - - public int Count => Items.Length; - - public IEnumerator GetEnumerator() - { - return ((IEnumerable) Items).GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - internal IReadOnlyList FromEntityPermission(EntityPermission entityPermission) { return entityPermission.AssignedPermissions .Where(x => x.Length == 1) - .Select(x => x.ToCharArray()[0]) - .SelectMany(c => this.Where(x => x.Letter == c)) - .Where(action => action != null) + .SelectMany(x => this.Where(y => y.Letter == x[0])) + .WhereNotNull() .ToList(); } } diff --git a/src/Umbraco.Web/Actions/ActionCollectionBuilder.cs b/src/Umbraco.Web/Actions/ActionCollectionBuilder.cs index 6002c8d2b0..027a3fcd9b 100644 --- a/src/Umbraco.Web/Actions/ActionCollectionBuilder.cs +++ b/src/Umbraco.Web/Actions/ActionCollectionBuilder.cs @@ -1,31 +1,28 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Reflection; -using LightInject; using Umbraco.Core.Composing; - namespace Umbraco.Web.Actions { internal class ActionCollectionBuilder : LazyCollectionBuilderBase { - public ActionCollectionBuilder(IServiceContainer container) + public ActionCollectionBuilder(IContainer container) : base(container) { } protected override ActionCollectionBuilder This => this; - protected override IEnumerable CreateItems(params object[] args) + protected override IEnumerable CreateItems() { - var items = base.CreateItems(args).ToList(); + var items = base.CreateItems().ToList(); + //validate the items, no actions should exist that do not either expose notifications or permissions - var invalid = items.Where(x => !x.CanBePermissionAssigned && !x.ShowInNotifier).ToList(); - if (invalid.Count > 0) - { - throw new InvalidOperationException($"Invalid actions '{string.Join(", ", invalid.Select(x => x.Alias))}'. All {typeof(IAction)} implementations must be true for either {nameof(IAction.CanBePermissionAssigned)} or {nameof(IAction.ShowInNotifier)}"); - } - return items; + var invalidItems = items.Where(x => !x.CanBePermissionAssigned && !x.ShowInNotifier).ToList(); + if (invalidItems.Count == 0) return items; + + var invalidActions = string.Join(", ", invalidItems.Select(x => "'" + x.Alias + "'")); + throw new InvalidOperationException($"Invalid actions {invalidActions}'. All {typeof(IAction)} implementations must be true for either {nameof(IAction.CanBePermissionAssigned)} or {nameof(IAction.ShowInNotifier)}."); } } } diff --git a/src/Umbraco.Web/Cache/CacheRefresherComponent.cs b/src/Umbraco.Web/Cache/CacheRefresherComponent.cs index 7f6de38418..3a5f716552 100644 --- a/src/Umbraco.Web/Cache/CacheRefresherComponent.cs +++ b/src/Umbraco.Web/Cache/CacheRefresherComponent.cs @@ -29,7 +29,7 @@ namespace Umbraco.Web.Cache /// Installs listeners on service events in order to refresh our caches. /// [RuntimeLevel(MinLevel = RuntimeLevel.Run)] - [RequiredComponent(typeof(IUmbracoCoreComponent))] // runs before every other IUmbracoCoreComponent! + [RequiredByComponent(typeof(IUmbracoCoreComponent))] // runs before every other IUmbracoCoreComponent! public class CacheRefresherComponent : UmbracoComponentBase, IUmbracoCoreComponent { private static readonly ConcurrentDictionary FoundHandlers = new ConcurrentDictionary(); diff --git a/src/Umbraco.Web/UmbracoApplicationBase.cs b/src/Umbraco.Web/UmbracoApplicationBase.cs index b680f340c5..b778a04967 100644 --- a/src/Umbraco.Web/UmbracoApplicationBase.cs +++ b/src/Umbraco.Web/UmbracoApplicationBase.cs @@ -58,12 +58,9 @@ namespace Umbraco.Web { // ******** THIS IS WHERE EVERYTHING BEGINS ******** - // create the container for the application, and configure. + // create the container for the application, and boot // the boot manager is responsible for registrations var container = GetContainer(); - Current.Container = container; // fixme NOT HERE OR WHAT? - - // get runtime & boot _runtime = GetRuntime(); _runtime.Boot(container); } diff --git a/src/Umbraco.Web/UmbracoContext.cs b/src/Umbraco.Web/UmbracoContext.cs index 19a79a7492..8ee5910bae 100644 --- a/src/Umbraco.Web/UmbracoContext.cs +++ b/src/Umbraco.Web/UmbracoContext.cs @@ -5,13 +5,13 @@ using System.Web; using System.Web.Hosting; using Umbraco.Core; using Umbraco.Core.Configuration; +using Umbraco.Core.Composing; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Models.PublishedContent; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; using Umbraco.Web.Runtime; using Umbraco.Web.Security; -using LightInject; namespace Umbraco.Web { From 392c9ed83bbae4521077901d065831ea5b7eb101 Mon Sep 17 00:00:00 2001 From: Stephan Date: Sat, 24 Nov 2018 15:38:00 +0100 Subject: [PATCH 095/469] More filesystem DI fixes --- .../Composers/FileSystemsComposer.cs | 75 ++++++++----------- .../Composing/ContainerExtensions.cs | 43 +++++++++++ src/Umbraco.Core/IO/FileSystems.cs | 29 ++----- src/Umbraco.Core/IO/IMediaPathScheme.cs | 16 +--- src/Umbraco.Core/IO/MediaFileSystem.cs | 31 ++++---- .../CombinedGuidsMediaPathScheme.cs | 8 +- .../OriginalMediaPathScheme.cs | 23 ++---- .../TwoGuidsMediaPathScheme.cs | 8 +- .../Runtime/CoreRuntimeComponent.cs | 2 - src/Umbraco.Tests/IO/ShadowFileSystemTests.cs | 6 +- src/Umbraco.Tests/Models/MediaXmlTest.cs | 7 +- .../PropertyEditors/ImageCropperTest.cs | 9 ++- src/Umbraco.Tests/TestHelpers/TestObjects.cs | 5 +- src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 8 +- 14 files changed, 138 insertions(+), 132 deletions(-) diff --git a/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs b/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs index 22e0d33456..a240f1c0ce 100644 --- a/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs @@ -2,6 +2,7 @@ using System.Configuration; using Umbraco.Core.Configuration; using Umbraco.Core.IO; +using Umbraco.Core.IO.MediaPathSchemes; namespace Umbraco.Core.Composing.Composers { @@ -13,34 +14,45 @@ namespace Umbraco.Core.Composing.Composers * * Create a component and use it to modify the composition by adding something like: * - * composition.Container.RegisterSingleton("media", factory => ...); + * composition.Container.RegisterFileSystem( + * factory => new PhysicalFileSystem("~/somewhere")); * - * where the ... part returns the new underlying filesystem, as an IFileSystem. + * return whatever supporting filesystem you like. * * * HOW TO IMPLEMENT MY OWN FILESYSTEM * ---------------------------------- * - * Declare your filesystem interface: - * - * public interface IMyFileSystem : IFileSystem - * { } - * * Create your filesystem class: * - * [FileSystem("my")] - * public class MyFileSystem : FileSystemWrapper, IFormsFileSystem + * public class MyFileSystem : FileSystemWrapper * { - * public FormsFileSystem(IFileSystem innerFileSystem) + * public MyFileSystem(IFileSystem innerFileSystem) * : base(innerFileSystem) * { } * } * - * Register both the underlying filesystem, and your filesystem, in a component: + * Note that the ctor parameter MUST be named innerFileSystem. fixme oh yea? + * The ctor can have more parameters that will be resolved by the container. * - * composition.Container.RegisterSingleton("my", factory => ...); - * composition.Container.RegisterSingleton(factory => - * factory.GetInstance().GetFileSystem(); + * Register your filesystem, in a component: + * + * composition.Container.RegisterFileSystem( + * factory => new PhysicalFileSystem("~/my")); + * + * And that's it, you can inject MyFileSystem wherever it's needed. + * + * + * You can also declare a filesystem interface: + * + * public interface IMyFileSystem : IFileSystem + * { } + * + * Make the class implement the interface, then + * register your filesystem, in a component: + * + * composition.Container.RegisterFileSystem( + * factory => new PhysicalFileSystem("~/my")); * * And that's it, you can inject IMyFileSystem wherever it's needed. * @@ -53,14 +65,6 @@ namespace Umbraco.Core.Composing.Composers * compared to creating your own physical filesystem, ensures that your filesystem * would participate into such transactions. * - * Also note that in order for things to work correctly, all filesystems should - * be instantiated before shadowing - so if registering a new filesystem in a - * component, it's a good idea to initialize it. This would be enough (in the - * component): - * - * public void Initialize(IMyFileSystem fs) - * { } - * * */ @@ -70,34 +74,19 @@ namespace Umbraco.Core.Composing.Composers // it needs to be registered (not only the interface) because it provides additional // functionality eg for scoping, and is injected in the scope provider - whereas the // interface is really for end-users to get access to filesystems. - //container.RegisterSingleton(); container.RegisterSingleton(factory => factory.CreateInstance(new { container} )); // register IFileSystems, which gives access too all filesystems container.RegisterSingleton(factory => factory.GetInstance()); - // register IMediaFileSystem with its actual, underlying filesystem factory - container.RegisterSingleton(factory => factory.GetInstance().GetFileSystem(MediaInnerFileSystemFactory)); + // register the scheme for media paths + container.RegisterSingleton(); + + // register the IMediaFileSystem implementation with a supporting filesystem + container.RegisterFileSystem( + factory => new PhysicalFileSystem("~/media")); return container; } - - private static IFileSystem MediaInnerFileSystemFactory() - { - // for the time being, we still use the FileSystemProvider config file - // but, detect if ppl are trying to use it to change the "provider" - - var virtualRoot = "~/media"; - - var config = (FileSystemProvidersSection)ConfigurationManager.GetSection("umbracoConfiguration/FileSystemProviders"); - var p = config?.Providers["media"]; - if (p == null) return new PhysicalFileSystem(virtualRoot); - - if (!string.IsNullOrWhiteSpace(p.Type) && p.Type != "Umbraco.Core.IO.PhysicalFileSystem, Umbraco.Core") - throw new InvalidOperationException("Setting a provider type in FileSystemProviders.config is not supported anymore, see FileSystemsComposer for help."); - - virtualRoot = p?.Parameters["virtualRoot"]?.Value ?? "~/media"; - return new PhysicalFileSystem(virtualRoot); - } } } diff --git a/src/Umbraco.Core/Composing/ContainerExtensions.cs b/src/Umbraco.Core/Composing/ContainerExtensions.cs index ac1df5dadb..c9b3200b34 100644 --- a/src/Umbraco.Core/Composing/ContainerExtensions.cs +++ b/src/Umbraco.Core/Composing/ContainerExtensions.cs @@ -3,6 +3,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Reflection; +using Umbraco.Core.IO; namespace Umbraco.Core.Composing { @@ -167,6 +168,8 @@ namespace Umbraco.Core.Composing // more expensive to build and cache a dynamic method ctor than to simply invoke the ctor, as we do // here - this can be discussed + // TODO: we currently try the ctor with most parameters, but we could want to fall back to others + var ctor = type.GetConstructors(BindingFlags.Instance | BindingFlags.Public).OrderByDescending(x => x.GetParameters().Length).FirstOrDefault(); if (ctor == null) throw new InvalidOperationException($"Could not find a public constructor for type {type.FullName}."); @@ -177,10 +180,50 @@ namespace Umbraco.Core.Composing { // no! IsInstanceOfType is not ok here // ReSharper disable once UseMethodIsInstanceOfType + // fixme so we just ignore the names? var arg = args?.Values.FirstOrDefault(a => parameter.ParameterType.IsAssignableFrom(a.GetType())); ctorArgs[i++] = arg ?? container.GetInstance(parameter.ParameterType); } return ctor.Invoke(ctorArgs); } + + /// + /// Registers a filesystem. + /// + /// The type of the filesystem. + /// The implementing type. + /// The container. + /// A factory method creating the supporting filesystem. + /// The container. + public static IContainer RegisterFileSystem(this IContainer container, Func supportingFileSystemFactory) + where TImplementing : FileSystemWrapper, TFileSystem + { + container.RegisterSingleton(factory => + { + var fileSystems = factory.GetInstance(); + return fileSystems.GetFileSystem(supportingFileSystemFactory(factory)); + }); + + return container; + } + + /// + /// Registers a filesystem. + /// + /// The type of the filesystem. + /// The container. + /// A factory method creating the supporting filesystem. + /// The container. + public static IContainer RegisterFileSystem(this IContainer container, Func supportingFileSystemFactory) + where TFileSystem : FileSystemWrapper + { + container.RegisterSingleton(factory => + { + var fileSystems = factory.GetInstance(); + return fileSystems.GetFileSystem(supportingFileSystemFactory(factory)); + }); + + return container; + } } } diff --git a/src/Umbraco.Core/IO/FileSystems.cs b/src/Umbraco.Core/IO/FileSystems.cs index 3a4eea91d6..4962d88a4e 100644 --- a/src/Umbraco.Core/IO/FileSystems.cs +++ b/src/Umbraco.Core/IO/FileSystems.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; -using System.Linq; using System.Threading; using Umbraco.Core.Logging; using Umbraco.Core.Composing; @@ -13,7 +12,7 @@ namespace Umbraco.Core.IO private readonly IContainer _container; private readonly ILogger _logger; - private readonly ConcurrentDictionary> _filesystems = new ConcurrentDictionary>(); + private readonly ConcurrentDictionary> _filesystems = new ConcurrentDictionary>(); // wrappers for shadow support private ShadowWrapper _macroPartialFileSystem; @@ -170,18 +169,17 @@ namespace Umbraco.Core.IO /// Note that any filesystem created by this method *after* shadowing begins, will *not* be /// shadowing (and an exception will be thrown by the ShadowWrapper). /// - public TFileSystem GetFileSystem(Func innerFileSystemFactory) + public TFileSystem GetFileSystem(IFileSystem supporting) where TFileSystem : FileSystemWrapper { if (Volatile.Read(ref _wkfsInitialized) == false) EnsureWellKnownFileSystems(); - var name = typeof(TFileSystem).FullName; - if (name == null) throw new Exception("panic!"); - - return (TFileSystem) _filesystems.GetOrAdd(name, _ => new Lazy(() => + return (TFileSystem) _filesystems.GetOrAdd(typeof(TFileSystem), _ => new Lazy(() => { - var innerFileSystem = innerFileSystemFactory(); - var shadowWrapper = CreateShadowWrapper(innerFileSystem, "typed/" + name); + var name = typeof(TFileSystem).FullName; + if (name == null) throw new Exception("panic!"); + + var shadowWrapper = CreateShadowWrapper(supporting, "typed/" + name); return _container.CreateInstance(new { innerFileSystem = shadowWrapper }); })).Value; } @@ -194,19 +192,6 @@ namespace Umbraco.Core.IO // shadowing is thread-safe, but entering and exiting shadow mode is not, and there is only one // global shadow for the entire application, so great care should be taken to ensure that the // application is *not* doing anything else when using a shadow. - // shadow applies to well-known filesystems *only* - at the moment, any other filesystem that would - // be created directly (via ctor) or via GetFileSystem is *not* shadowed. - - // shadow must be enabled in an app event handler before anything else ie before any filesystem - // is actually created and used - after, it is too late - enabling shadow has a negligible perfs - // impact. - // NO! by the time an app event handler is instantiated it is already too late, see note in ctor. - //internal void EnableShadow() - //{ - // if (_mvcViewsFileSystem != null) // test one of the fs... - // throw new InvalidOperationException("Cannot enable shadow once filesystems have been created."); - // _shadowEnabled = true; - //} internal ICompletable Shadow(Guid id) { diff --git a/src/Umbraco.Core/IO/IMediaPathScheme.cs b/src/Umbraco.Core/IO/IMediaPathScheme.cs index 5cfb43ed77..9a38cdc74f 100644 --- a/src/Umbraco.Core/IO/IMediaPathScheme.cs +++ b/src/Umbraco.Core/IO/IMediaPathScheme.cs @@ -7,35 +7,27 @@ namespace Umbraco.Core.IO ///
public interface IMediaPathScheme { - // fixme - // to anyone finding this code: YES the Initialize() method is CompletelyBroken™ (temporal whatever) - // but at the moment, the media filesystem wants a scheme which wants a filesystem, and it's all - // convoluted due to how filesystems are managed in FileSystems - clear that part first! - - /// - /// Initialize. - /// - void Initialize(IFileSystem filesystem); - /// /// Gets a media file path. /// + /// The media filesystem. /// The (content, media) item unique identifier. /// The property type unique identifier. /// The file name. /// A previous filename. /// The filesystem-relative complete file path. - string GetFilePath(Guid itemGuid, Guid propertyGuid, string filename, string previous = null); + string GetFilePath(IMediaFileSystem fileSystem, Guid itemGuid, Guid propertyGuid, string filename, string previous = null); /// /// Gets the directory that can be deleted when the file is deleted. /// + /// The media filesystem. /// The filesystem-relative path of the file. /// The filesystem-relative path of the directory. /// /// The directory, and anything below it, will be deleted. /// Can return null (or empty) when no directory should be deleted. /// - string GetDeleteDirectory(string filepath); + string GetDeleteDirectory(IMediaFileSystem fileSystem, string filepath); } } diff --git a/src/Umbraco.Core/IO/MediaFileSystem.cs b/src/Umbraco.Core/IO/MediaFileSystem.cs index 867fe94c03..2ce1230bcc 100644 --- a/src/Umbraco.Core/IO/MediaFileSystem.cs +++ b/src/Umbraco.Core/IO/MediaFileSystem.cs @@ -1,9 +1,11 @@ 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; @@ -17,24 +19,21 @@ namespace Umbraco.Core.IO ///
public class MediaFileSystem : FileSystemWrapper, IMediaFileSystem { + private readonly IMediaPathScheme _mediaPathScheme; + private readonly IContentSection _contentConfig; + private readonly ILogger _logger; + /// /// Initializes a new instance of the class. /// - public MediaFileSystem(IFileSystem innerFileSystem) + public MediaFileSystem(IFileSystem innerFileSystem, IContentSection contentConfig, IMediaPathScheme mediaPathScheme, ILogger logger) : base(innerFileSystem) { - ContentConfig = Current.Container.GetInstance(); - Logger = Current.Container.GetInstance(); - MediaPathScheme = Current.Container.GetInstance(); - MediaPathScheme.Initialize(this); + _contentConfig = contentConfig; + _mediaPathScheme = mediaPathScheme; + _logger = logger; } - private IMediaPathScheme MediaPathScheme { get; } - - private IContentSection ContentConfig { get; } - - private ILogger Logger { get; } - /// public void DeleteMediaFiles(IEnumerable files) { @@ -51,13 +50,13 @@ namespace Umbraco.Core.IO if (FileExists(file) == false) return; DeleteFile(file); - var directory = MediaPathScheme.GetDeleteDirectory(file); + var directory = _mediaPathScheme.GetDeleteDirectory(this, file); if (!directory.IsNullOrWhiteSpace()) DeleteDirectory(directory, true); } catch (Exception e) { - Logger.Error(e, "Failed to delete media file '{File}'.", file); + _logger.Error(e, "Failed to delete media file '{File}'.", file); } }); } @@ -71,7 +70,7 @@ namespace Umbraco.Core.IO if (filename == null) throw new ArgumentException("Cannot become a safe filename.", nameof(filename)); filename = IOHelper.SafeFileName(filename.ToLowerInvariant()); - return MediaPathScheme.GetFilePath(cuid, puid, filename); + return _mediaPathScheme.GetFilePath(this, cuid, puid, filename); } /// @@ -81,7 +80,7 @@ namespace Umbraco.Core.IO if (filename == null) throw new ArgumentException("Cannot become a safe filename.", nameof(filename)); filename = IOHelper.SafeFileName(filename.ToLowerInvariant()); - return MediaPathScheme.GetFilePath(cuid, puid, filename, prevpath); + return _mediaPathScheme.GetFilePath(this, cuid, puid, filename, prevpath); } #endregion @@ -124,6 +123,6 @@ namespace Umbraco.Core.IO return filepath; } - #endregion + #endregion } } diff --git a/src/Umbraco.Core/IO/MediaPathSchemes/CombinedGuidsMediaPathScheme.cs b/src/Umbraco.Core/IO/MediaPathSchemes/CombinedGuidsMediaPathScheme.cs index ef71aff3bc..2d9d964b90 100644 --- a/src/Umbraco.Core/IO/MediaPathSchemes/CombinedGuidsMediaPathScheme.cs +++ b/src/Umbraco.Core/IO/MediaPathSchemes/CombinedGuidsMediaPathScheme.cs @@ -12,11 +12,7 @@ namespace Umbraco.Core.IO.MediaPathSchemes public class CombinedGuidsMediaPathScheme : IMediaPathScheme { /// - public void Initialize(IFileSystem filesystem) - { } - - /// - public string GetFilePath(Guid itemGuid, Guid propertyGuid, string filename, string previous = null) + public string GetFilePath(IMediaFileSystem fileSystem, Guid itemGuid, Guid propertyGuid, string filename, string previous = null) { // assumes that cuid and puid keys can be trusted - and that a single property type // for a single content cannot store two different files with the same name @@ -25,7 +21,7 @@ namespace Umbraco.Core.IO.MediaPathSchemes } /// - public string GetDeleteDirectory(string filepath) + public string GetDeleteDirectory(IMediaFileSystem fileSystem, string filepath) { return Path.GetDirectoryName(filepath); } diff --git a/src/Umbraco.Core/IO/MediaPathSchemes/OriginalMediaPathScheme.cs b/src/Umbraco.Core/IO/MediaPathSchemes/OriginalMediaPathScheme.cs index 1ed2ea59ce..8e53e34ee8 100644 --- a/src/Umbraco.Core/IO/MediaPathSchemes/OriginalMediaPathScheme.cs +++ b/src/Umbraco.Core/IO/MediaPathSchemes/OriginalMediaPathScheme.cs @@ -17,18 +17,11 @@ namespace Umbraco.Core.IO.MediaPathSchemes public class OriginalMediaPathScheme : IMediaPathScheme { private readonly object _folderCounterLock = new object(); - private IFileSystem _filesystem; private long _folderCounter; private bool _folderCounterInitialized; /// - public void Initialize(IFileSystem filesystem) - { - _filesystem = filesystem; - } - - /// - public string GetFilePath(Guid itemGuid, Guid propertyGuid, string filename, string previous = null) + public string GetFilePath(IMediaFileSystem fileSystem, Guid itemGuid, Guid propertyGuid, string filename, string previous = null) { string directory; if (previous != null) @@ -41,11 +34,11 @@ namespace Umbraco.Core.IO.MediaPathSchemes var pos = previous.IndexOf(sep, StringComparison.Ordinal); var s = pos > 0 ? previous.Substring(0, pos) : null; - directory = pos > 0 && int.TryParse(s, out _) ? s : GetNextDirectory(); + directory = pos > 0 && int.TryParse(s, out _) ? s : GetNextDirectory(fileSystem); } else { - directory = GetNextDirectory(); + directory = GetNextDirectory(fileSystem); } if (directory == null) @@ -57,25 +50,25 @@ namespace Umbraco.Core.IO.MediaPathSchemes } /// - public string GetDeleteDirectory(string filepath) + public string GetDeleteDirectory(IMediaFileSystem fileSystem, string filepath) { return Path.GetDirectoryName(filepath); } - private string GetNextDirectory() + private string GetNextDirectory(IFileSystem fileSystem) { - EnsureFolderCounterIsInitialized(); + EnsureFolderCounterIsInitialized(fileSystem); return Interlocked.Increment(ref _folderCounter).ToString(CultureInfo.InvariantCulture); } - private void EnsureFolderCounterIsInitialized() + private void EnsureFolderCounterIsInitialized(IFileSystem fileSystem) { lock (_folderCounterLock) { if (_folderCounterInitialized) return; _folderCounter = 1000; // seed - var directories = _filesystem.GetDirectories(""); + var directories = fileSystem.GetDirectories(""); foreach (var directory in directories) { if (long.TryParse(directory, out var folderNumber) && folderNumber > _folderCounter) diff --git a/src/Umbraco.Core/IO/MediaPathSchemes/TwoGuidsMediaPathScheme.cs b/src/Umbraco.Core/IO/MediaPathSchemes/TwoGuidsMediaPathScheme.cs index 4a6fdfcdbe..3c06e295e6 100644 --- a/src/Umbraco.Core/IO/MediaPathSchemes/TwoGuidsMediaPathScheme.cs +++ b/src/Umbraco.Core/IO/MediaPathSchemes/TwoGuidsMediaPathScheme.cs @@ -12,17 +12,13 @@ namespace Umbraco.Core.IO.MediaPathSchemes public class TwoGuidsMediaPathScheme : IMediaPathScheme { /// - public void Initialize(IFileSystem filesystem) - { } - - /// - public string GetFilePath(Guid itemGuid, Guid propertyGuid, string filename, string previous = null) + public string GetFilePath(IMediaFileSystem fileSystem, Guid itemGuid, Guid propertyGuid, string filename, string previous = null) { return Path.Combine(itemGuid.ToString("N"), propertyGuid.ToString("N"), filename).Replace('\\', '/'); } /// - public string GetDeleteDirectory(string filepath) + public string GetDeleteDirectory(IMediaFileSystem fileSystem, string filepath) { return Path.GetDirectoryName(filepath); } diff --git a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs index efd9bde0b5..34fd04d181 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs @@ -107,8 +107,6 @@ namespace Umbraco.Core.Runtime // by default, register a noop factory composition.Container.RegisterSingleton(); - - composition.Container.RegisterSingleton(); } internal void Initialize(IEnumerable mapperProfiles) diff --git a/src/Umbraco.Tests/IO/ShadowFileSystemTests.cs b/src/Umbraco.Tests/IO/ShadowFileSystemTests.cs index 304f7b1efb..50ce85f356 100644 --- a/src/Umbraco.Tests/IO/ShadowFileSystemTests.cs +++ b/src/Umbraco.Tests/IO/ShadowFileSystemTests.cs @@ -398,7 +398,7 @@ namespace Umbraco.Tests.IO var container = Mock.Of(); var fileSystems = new FileSystems(container, logger) { IsScoped = () => scopedFileSystems }; - var fs = fileSystems.GetFileSystem(() => phy); + var fs = fileSystems.GetFileSystem(phy); var sw = (ShadowWrapper) fs.InnerFileSystem; using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo"))) @@ -491,7 +491,7 @@ namespace Umbraco.Tests.IO var container = Mock.Of(); var fileSystems = new FileSystems(container, logger) { IsScoped = () => scopedFileSystems }; - var fs = fileSystems.GetFileSystem(() => phy); + var fs = fileSystems.GetFileSystem( phy); var sw = (ShadowWrapper) fs.InnerFileSystem; using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo"))) @@ -544,7 +544,7 @@ namespace Umbraco.Tests.IO var container = Mock.Of(); var fileSystems = new FileSystems(container, logger) { IsScoped = () => scopedFileSystems }; - var fs = fileSystems.GetFileSystem(() => phy); + var fs = fileSystems.GetFileSystem( phy); var sw = (ShadowWrapper)fs.InnerFileSystem; using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo"))) diff --git a/src/Umbraco.Tests/Models/MediaXmlTest.cs b/src/Umbraco.Tests/Models/MediaXmlTest.cs index 492803ce17..1a56fac4eb 100644 --- a/src/Umbraco.Tests/Models/MediaXmlTest.cs +++ b/src/Umbraco.Tests/Models/MediaXmlTest.cs @@ -29,7 +29,12 @@ namespace Umbraco.Tests.Models // reference, so static ctor runs, so event handlers register // and then, this will reset the width, height... because the file does not exist, of course ;-( - var ignored = new FileUploadPropertyEditor(Mock.Of(), new MediaFileSystem(Mock.Of()), Mock.Of()); + var logger = Mock.Of(); + var scheme = Mock.Of(); + var config = Mock.Of(); + + var mediaFileSystem = new MediaFileSystem(Mock.Of(), config, scheme, logger); + var ignored = new FileUploadPropertyEditor(Mock.Of(), mediaFileSystem, config); var media = MockedMedia.CreateMediaImage(mediaType, -1); media.WriterId = -1; // else it's zero and that's not a user and it breaks the tests diff --git a/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs b/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs index cdc3918fc3..7e56ad61a8 100644 --- a/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs +++ b/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs @@ -70,10 +70,11 @@ namespace Umbraco.Tests.PropertyEditors container.RegisterCollectionBuilder(); - Current.Container.RegisterSingleton(f => Mock.Of()); - Current.Container.RegisterSingleton(f => Mock.Of()); - Current.Container.RegisterSingleton(f => Mock.Of()); - var mediaFileSystem = new MediaFileSystem(Mock.Of()); + var logger = Mock.Of(); + var scheme = Mock.Of(); + var config = Mock.Of(); + + var mediaFileSystem = new MediaFileSystem(Mock.Of(), config, scheme, logger); var dataTypeService = new TestObjects.TestDataTypeService( new DataType(new ImageCropperPropertyEditor(Mock.Of(), mediaFileSystem, Mock.Of(), Mock.Of())) { Id = 1 }); diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects.cs b/src/Umbraco.Tests/TestHelpers/TestObjects.cs index efa77d26dc..9f16141c2f 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects.cs @@ -117,7 +117,10 @@ namespace Umbraco.Tests.TestHelpers if (logger == null) throw new ArgumentNullException(nameof(logger)); if (eventMessagesFactory == null) throw new ArgumentNullException(nameof(eventMessagesFactory)); - var mediaFileSystem = new MediaFileSystem(Mock.Of()); + var scheme = Mock.Of(); + var config = Mock.Of(); + + var mediaFileSystem = new MediaFileSystem(Mock.Of(), config, scheme, logger); var externalLoginService = GetLazyService(container, c => new ExternalLoginService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); var publicAccessService = GetLazyService(container, c => new PublicAccessService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index 4084c2ac69..45a4bc5917 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -295,7 +295,13 @@ namespace Umbraco.Tests.Testing // register filesystems Container.RegisterSingleton(factory => TestObjects.GetFileSystemsMock()); - Container.RegisterSingleton(factory => new MediaFileSystem(Mock.Of())); + + var logger = Mock.Of(); + var scheme = Mock.Of(); + var config = Mock.Of(); + + var mediaFileSystem = new MediaFileSystem(Mock.Of(), config, scheme, logger); + Container.RegisterSingleton(factory => mediaFileSystem); // no factory (noop) Container.RegisterSingleton(); From 8b74453c136635bd97bca8e2e75c2b591645acc4 Mon Sep 17 00:00:00 2001 From: Stephan Date: Sat, 24 Nov 2018 16:41:27 +0100 Subject: [PATCH 096/469] Simplify IContainer.CreateInstance --- .../Composers/FileSystemsComposer.cs | 3 +- .../Composing/ContainerExtensions.cs | 38 ++----------------- src/Umbraco.Core/IO/FileSystems.cs | 2 +- .../Composing/ContainerImplementationTests.cs | 2 +- 4 files changed, 7 insertions(+), 38 deletions(-) diff --git a/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs b/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs index a240f1c0ce..313e4ce97c 100644 --- a/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs @@ -32,7 +32,6 @@ namespace Umbraco.Core.Composing.Composers * { } * } * - * Note that the ctor parameter MUST be named innerFileSystem. fixme oh yea? * The ctor can have more parameters that will be resolved by the container. * * Register your filesystem, in a component: @@ -74,7 +73,7 @@ namespace Umbraco.Core.Composing.Composers // it needs to be registered (not only the interface) because it provides additional // functionality eg for scoping, and is injected in the scope provider - whereas the // interface is really for end-users to get access to filesystems. - container.RegisterSingleton(factory => factory.CreateInstance(new { container} )); + container.RegisterSingleton(factory => factory.CreateInstance(container)); // register IFileSystems, which gives access too all filesystems container.RegisterSingleton(factory => factory.GetInstance()); diff --git a/src/Umbraco.Core/Composing/ContainerExtensions.cs b/src/Umbraco.Core/Composing/ContainerExtensions.cs index c9b3200b34..a2eb3af7cf 100644 --- a/src/Umbraco.Core/Composing/ContainerExtensions.cs +++ b/src/Umbraco.Core/Composing/ContainerExtensions.cs @@ -12,9 +12,6 @@ namespace Umbraco.Core.Composing ///
public static class ContainerExtensions { - private static readonly ConcurrentDictionary>> ArgumentPropertyGetters - = new ConcurrentDictionary>>(); - /// /// Gets an instance of a service. /// @@ -55,35 +52,9 @@ namespace Umbraco.Core.Composing /// Throws an exception if the container failed to get an instance of the specified type. /// The arguments are used as dependencies by the container. /// - public static T CreateInstance(this IContainer container, IDictionary args) + public static T CreateInstance(this IContainer container, params object[] args) => (T) container.CreateInstance(typeof(T), args); - /// - /// Creates an instance with arguments. - /// - /// The type of the instance. - /// The container. - /// Arguments. - /// An instance of the specified type. - /// - /// Throws an exception if the container failed to get an instance of the specified type. - /// The arguments are used as dependencies by the container. - /// - public static T CreateInstance(this IContainer container, object args) - { - var typeOfArgs = args.GetType(); - var getters = ArgumentPropertyGetters.GetOrAdd(typeOfArgs, type => - args.GetType() - .GetProperties() - .ToDictionary(x => x.Name, x => ReflectionUtilities.EmitMethodUnsafe>(x.GetMethod))); - - var argsDictionary = new Dictionary(); - foreach (var (name, getter) in getters) - argsDictionary[name] = getter(args); - - return (T) container.CreateInstance(typeof(T), argsDictionary); - } - /// /// Registers a service with an implementation type. /// @@ -140,7 +111,7 @@ namespace Umbraco.Core.Composing // register the builder // use a factory so we don't have to self-register the container - container.RegisterSingleton(factory => factory.CreateInstance(new Dictionary {{ "container", container }} )); + container.RegisterSingleton(factory => factory.CreateInstance(container)); // initialize and return the builder return container.GetInstance(); @@ -158,7 +129,7 @@ namespace Umbraco.Core.Composing /// The arguments are used as dependencies by the container. Other dependencies /// are retrieved from the container. /// - public static object CreateInstance(this IContainer container, Type type, IDictionary args) + public static object CreateInstance(this IContainer container, Type type, params object[] args) { // LightInject has this, but then it requires RegisterConstructorDependency etc and has various oddities // including the most annoying one, which is that it does not work on singletons (hard to fix) @@ -180,8 +151,7 @@ namespace Umbraco.Core.Composing { // no! IsInstanceOfType is not ok here // ReSharper disable once UseMethodIsInstanceOfType - // fixme so we just ignore the names? - var arg = args?.Values.FirstOrDefault(a => parameter.ParameterType.IsAssignableFrom(a.GetType())); + var arg = args?.FirstOrDefault(a => parameter.ParameterType.IsAssignableFrom(a.GetType())); ctorArgs[i++] = arg ?? container.GetInstance(parameter.ParameterType); } return ctor.Invoke(ctorArgs); diff --git a/src/Umbraco.Core/IO/FileSystems.cs b/src/Umbraco.Core/IO/FileSystems.cs index 4962d88a4e..47e2b02bb7 100644 --- a/src/Umbraco.Core/IO/FileSystems.cs +++ b/src/Umbraco.Core/IO/FileSystems.cs @@ -180,7 +180,7 @@ namespace Umbraco.Core.IO if (name == null) throw new Exception("panic!"); var shadowWrapper = CreateShadowWrapper(supporting, "typed/" + name); - return _container.CreateInstance(new { innerFileSystem = shadowWrapper }); + return _container.CreateInstance(shadowWrapper); })).Value; } diff --git a/src/Umbraco.Tests/Composing/ContainerImplementationTests.cs b/src/Umbraco.Tests/Composing/ContainerImplementationTests.cs index f16c6534fc..5b72bc17b4 100644 --- a/src/Umbraco.Tests/Composing/ContainerImplementationTests.cs +++ b/src/Umbraco.Tests/Composing/ContainerImplementationTests.cs @@ -47,7 +47,7 @@ namespace Umbraco.Tests.Composing public void CanRegisterSingletonWithCreate() { var container = CreateContainer(); - container.RegisterSingleton(c => c.CreateInstance(new Dictionary{{"c", new TestClass1()}})); + container.RegisterSingleton(c => c.CreateInstance(new TestClass1())); var s1 = container.GetInstance(); var s2 = container.GetInstance(); Assert.AreSame(s1, s2); From b8608f1b2e97393debf7966ca2b10037bbbe57fc Mon Sep 17 00:00:00 2001 From: Stephan Date: Mon, 26 Nov 2018 16:54:32 +0100 Subject: [PATCH 097/469] Refactor runtimes, injection and composition --- .../Cache/CacheRefresherCollectionBuilder.cs | 4 - .../{BootLoader.cs => Components.cs} | 87 +++--- src/Umbraco.Core/Components/Composition.cs | 27 +- .../Composing/CollectionBuilderBase.cs | 32 +- .../Composing/ContainerExtensions.cs | 20 -- .../Composing/ICollectionBuilder.cs | 13 +- .../Composing/LazyCollectionBuilderBase.cs | 9 +- .../Composing/OrderedCollectionBuilderBase.cs | 10 +- src/Umbraco.Core/Composing/TypeLoader.cs | 26 +- .../Composing/TypeLoaderExtensions.cs | 8 - .../WeightedCollectionBuilderBase.cs | 10 +- src/Umbraco.Core/Logging/IProfilingLogger.cs | 40 +++ src/Umbraco.Core/Logging/ProfilingLogger.cs | 80 ++++- .../Migrations/Install/DatabaseBuilder.cs | 46 --- .../PostMigrationCollectionBuilder.cs | 4 - .../Mappers/MapperCollectionBuilder.cs | 10 +- .../SqlSyntax/MySqlSyntaxProvider.cs | 3 +- .../SqlSyntax/SqlCeSyntaxProvider.cs | 2 - .../SqlSyntax/SqlServerSyntaxProvider.cs | 98 +++--- .../SqlSyntax/SqlSyntaxProviderAttribute.cs | 21 -- .../Persistence/UmbracoDatabaseFactory.cs | 57 ++-- .../DataEditorCollectionBuilder.cs | 4 - ...ManifestValueValidatorCollectionBuilder.cs | 4 - ...PropertyValueConverterCollectionBuilder.cs | 4 - src/Umbraco.Core/Runtime/CoreRuntime.cs | 291 ++++++++++-------- .../Runtime/CoreRuntimeComponent.cs | 14 +- src/Umbraco.Core/RuntimeState.cs | 67 ++-- .../UrlSegmentProviderCollectionBuilder.cs | 4 - src/Umbraco.Core/Umbraco.Core.csproj | 4 +- .../PackageActionCollectionBuilder.cs | 4 - .../BulkInsertBenchmarks.cs | 13 +- .../DistributedCache/DistributedCacheTests.cs | 4 +- .../PublishedMediaCacheTests.cs | 2 +- .../Components/ComponentTests.cs | 93 ++++-- .../Composing/CollectionBuildersTests.cs | 67 ++-- .../Composing/LazyCollectionBuilderTests.cs | 20 +- .../Composing/PackageActionCollectionTests.cs | 5 +- .../Integration/ContentEventsTests.cs | 2 +- .../Misc/ApplicationUrlHelperTests.cs | 11 +- .../Models/Mapping/AutoMapperTests.cs | 2 +- .../Persistence/DatabaseContextTests.cs | 4 +- .../FaultHandling/ConnectionRetryTest.cs | 6 +- .../Repositories/DocumentRepositoryTest.cs | 2 +- .../SqlCeSyntaxProviderTests.cs | 12 +- .../PropertyEditors/ImageCropperTest.cs | 4 +- .../Published/ConvertersTests.cs | 5 +- .../PublishedContentTestBase.cs | 6 +- .../PublishedContent/PublishedMediaTests.cs | 2 +- .../Routing/UmbracoModuleTests.cs | 3 +- .../Runtimes/CoreRuntimeTests.cs | 10 +- .../Scoping/ScopeEventDispatcherTests.cs | 4 +- .../Scoping/ScopedNuCacheTests.cs | 2 +- .../Scoping/ScopedRepositoryTests.cs | 2 +- src/Umbraco.Tests/Scoping/ScopedXmlTests.cs | 2 +- .../Services/ContentServiceTests.cs | 3 +- .../ContentTypeServiceVariantsTests.cs | 4 +- .../Services/Importing/PackageImportTests.cs | 2 +- .../TestHelpers/BaseUsingSqlCeSyntax.cs | 4 +- src/Umbraco.Tests/TestHelpers/TestObjects.cs | 20 +- .../TestHelpers/TestWithDatabaseBase.cs | 5 +- src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 27 +- .../Actions/ActionCollectionBuilder.cs | 4 - .../ContentAppDefinitionCollectionBuilder.cs | 4 - .../EditorValidatorCollectionBuilder.cs | 4 - ...heckNotificationMethodCollectionBuilder.cs | 4 - .../HeathCheckCollectionBuilder.cs | 4 - ...teredControllerFactoryCollectionBuilder.cs | 4 - .../Routing/ContentFinderCollectionBuilder.cs | 4 - .../Routing/UrlProviderCollectionBuilder.cs | 4 - src/Umbraco.Web/Runtime/WebRuntime.cs | 38 +-- .../Runtime/WebRuntimeComponent.cs | 98 +++--- .../Search/SearchableTreeCollectionBuilder.cs | 14 - .../Tour/TourFilterCollectionBuilder.cs | 7 - 73 files changed, 711 insertions(+), 829 deletions(-) rename src/Umbraco.Core/Components/{BootLoader.cs => Components.cs} (80%) create mode 100644 src/Umbraco.Core/Logging/IProfilingLogger.cs delete mode 100644 src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxProviderAttribute.cs diff --git a/src/Umbraco.Core/Cache/CacheRefresherCollectionBuilder.cs b/src/Umbraco.Core/Cache/CacheRefresherCollectionBuilder.cs index bb4a14c147..8bae755149 100644 --- a/src/Umbraco.Core/Cache/CacheRefresherCollectionBuilder.cs +++ b/src/Umbraco.Core/Cache/CacheRefresherCollectionBuilder.cs @@ -4,10 +4,6 @@ namespace Umbraco.Core.Cache { public class CacheRefresherCollectionBuilder : LazyCollectionBuilderBase { - public CacheRefresherCollectionBuilder(IContainer container) - : base(container) - { } - protected override CacheRefresherCollectionBuilder This => this; } } diff --git a/src/Umbraco.Core/Components/BootLoader.cs b/src/Umbraco.Core/Components/Components.cs similarity index 80% rename from src/Umbraco.Core/Components/BootLoader.cs rename to src/Umbraco.Core/Components/Components.cs index ff0b7ab05b..155674782e 100644 --- a/src/Umbraco.Core/Components/BootLoader.cs +++ b/src/Umbraco.Core/Components/Components.cs @@ -13,25 +13,26 @@ namespace Umbraco.Core.Components { // note: this class is NOT thread-safe in any ways - internal class BootLoader + internal class Components { - private readonly IContainer _container; - private readonly ProfilingLogger _proflog; - private readonly ILogger _logger; + private readonly Composition _composition; + private readonly IProfilingLogger _logger; + private readonly IEnumerable _componentTypes; private IUmbracoComponent[] _components; - private bool _booted; private const int LogThresholdMilliseconds = 100; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// The application container. - public BootLoader(IContainer container) + /// The composition. + /// The component types. + /// A profiling logger. + public Components(Composition composition, IEnumerable componentTypes, IProfilingLogger logger) { - _container = container ?? throw new ArgumentNullException(nameof(container)); - _proflog = container.GetInstance(); - _logger = container.GetInstance(); + _composition = composition ?? throw new ArgumentNullException(nameof(composition)); + _componentTypes = componentTypes ?? throw new ArgumentNullException(nameof(componentTypes)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); } private class EnableInfo @@ -40,44 +41,42 @@ namespace Umbraco.Core.Components public int Weight = -1; } - public void Boot(IEnumerable componentTypes, RuntimeLevel level) + public void Compose() { - if (_booted) throw new InvalidOperationException("Can not boot, has already booted."); - - var orderedComponentTypes = PrepareComponentTypes(componentTypes, level); + var orderedComponentTypes = PrepareComponentTypes(); InstantiateComponents(orderedComponentTypes); - ComposeComponents(level); + ComposeComponents(); + } - using (var scope = _container.GetInstance().CreateScope()) + public void Initialize() + { + using (var scope = _composition.Container.GetInstance().CreateScope()) { InitializeComponents(); scope.Complete(); } - - // rejoice! - _booted = true; } - private IEnumerable PrepareComponentTypes(IEnumerable componentTypes, RuntimeLevel level) + private IEnumerable PrepareComponentTypes() { - using (_proflog.DebugDuration("Preparing component types.", "Prepared component types.")) + using (_logger.DebugDuration("Preparing component types.", "Prepared component types.")) { - return PrepareComponentTypes2(componentTypes, level); + return PrepareComponentTypes2(); } } - private IEnumerable PrepareComponentTypes2(IEnumerable componentTypes, RuntimeLevel level) + private IEnumerable PrepareComponentTypes2() { // create a list, remove those that cannot be enabled due to runtime level - var componentTypeList = componentTypes + var componentTypeList = _componentTypes .Where(x => { // use the min level specified by the attribute if any // otherwise, user components have Run min level, anything else is Unknown (always run) var attr = x.GetCustomAttribute(); var minLevel = attr?.MinLevel ?? (x.Implements() ? RuntimeLevel.Run : RuntimeLevel.Unknown); - return level >= minLevel; + return _composition.RuntimeLevel >= minLevel; }) .ToList(); @@ -107,15 +106,15 @@ namespace Umbraco.Core.Components catch (Exception e) { // in case of an error, force-dump everything to log - _logger.Info("Component Report:\r\n{ComponentReport}", GetComponentsReport(requirements)); - _logger.Error(e, "Failed to sort components."); + _logger.Info("Component Report:\r\n{ComponentReport}", GetComponentsReport(requirements)); + _logger.Error(e, "Failed to sort components."); throw; } // bit verbose but should help for troubleshooting var text = "Ordered Components: " + Environment.NewLine + string.Join(Environment.NewLine, sortedComponentTypes) + Environment.NewLine; Console.WriteLine(text); - _logger.Debug("Ordered Components: {SortedComponentTypes}", sortedComponentTypes); + _logger.Debug("Ordered Components: {SortedComponentTypes}", sortedComponentTypes); return sortedComponentTypes; } @@ -275,23 +274,23 @@ namespace Umbraco.Core.Components private void InstantiateComponents(IEnumerable types) { - using (_proflog.DebugDuration("Instantiating components.", "Instantiated components.")) + using (_logger.DebugDuration("Instantiating components.", "Instantiated components.")) { + // fixme is there a faster way? _components = types.Select(x => (IUmbracoComponent) Activator.CreateInstance(x)).ToArray(); } } - private void ComposeComponents(RuntimeLevel level) + private void ComposeComponents() { - using (_proflog.DebugDuration($"Composing components. (log when >{LogThresholdMilliseconds}ms)", "Composed components.")) + using (_logger.DebugDuration($"Composing components. (log when >{LogThresholdMilliseconds}ms)", "Composed components.")) { - var composition = new Composition(_container, level); foreach (var component in _components) { var componentType = component.GetType(); - using (_proflog.DebugDuration($"Composing {componentType.FullName}.", $"Composed {componentType.FullName}.", thresholdMilliseconds: LogThresholdMilliseconds)) + using (_logger.DebugDuration($"Composing {componentType.FullName}.", $"Composed {componentType.FullName}.", thresholdMilliseconds: LogThresholdMilliseconds)) { - component.Compose(composition); + component.Compose(_composition); } } } @@ -301,15 +300,15 @@ namespace Umbraco.Core.Components { // use a container scope to ensure that PerScope instances are disposed // components that require instances that should not survive should register them with PerScope lifetime - using (_proflog.DebugDuration($"Initializing components. (log when >{LogThresholdMilliseconds}ms)", "Initialized components.")) - using (_container.BeginScope()) + using (_logger.DebugDuration($"Initializing components. (log when >{LogThresholdMilliseconds}ms)", "Initialized components.")) + using (_composition.Container.BeginScope()) { foreach (var component in _components) { var componentType = component.GetType(); var initializers = componentType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) .Where(x => x.Name == "Initialize" && x.IsGenericMethod == false && x.IsStatic == false); - using (_proflog.DebugDuration($"Initializing {componentType.FullName}.", $"Initialized {componentType.FullName}.", thresholdMilliseconds: LogThresholdMilliseconds)) + using (_logger.DebugDuration($"Initializing {componentType.FullName}.", $"Initialized {componentType.FullName}.", thresholdMilliseconds: LogThresholdMilliseconds)) { foreach (var initializer in initializers) { @@ -329,7 +328,7 @@ namespace Umbraco.Core.Components try { - param = _container.TryGetInstance(parameterType); + param = _composition.Container.TryGetInstance(parameterType); } catch (Exception e) { @@ -342,19 +341,13 @@ namespace Umbraco.Core.Components public void Terminate() { - if (_booted == false) - { - _proflog.Logger.Warn("Cannot terminate, has not booted."); - return; - } - - using (_proflog.DebugDuration($"Terminating. (log components when >{LogThresholdMilliseconds}ms)", "Terminated.")) + using (_logger.DebugDuration($"Terminating. (log components when >{LogThresholdMilliseconds}ms)", "Terminated.")) { for (var i = _components.Length - 1; i >= 0; i--) // terminate components in reverse order { var component = _components[i]; var componentType = component.GetType(); - using (_proflog.DebugDuration($"Terminating {componentType.FullName}.", $"Terminated {componentType.FullName}.", thresholdMilliseconds: LogThresholdMilliseconds)) + using (_logger.DebugDuration($"Terminating {componentType.FullName}.", $"Terminated {componentType.FullName}.", thresholdMilliseconds: LogThresholdMilliseconds)) { component.Terminate(); } diff --git a/src/Umbraco.Core/Components/Composition.cs b/src/Umbraco.Core/Components/Composition.cs index 91fa519694..bf3ff40c79 100644 --- a/src/Umbraco.Core/Components/Composition.cs +++ b/src/Umbraco.Core/Components/Composition.cs @@ -1,4 +1,6 @@ -using Umbraco.Core.Composing; +using System; +using System.Collections.Generic; +using Umbraco.Core.Composing; namespace Umbraco.Core.Components { @@ -12,6 +14,8 @@ namespace Umbraco.Core.Components /// may cause issues. public class Composition { + private readonly Dictionary _builders = new Dictionary(); + /// /// Initializes a new instance of the class. /// @@ -33,5 +37,26 @@ namespace Umbraco.Core.Components /// Gets the runtime level. ///
public RuntimeLevel RuntimeLevel { get; } + + /// + /// Gets a collection builder (and registers the collection). + /// + /// The type of the collection builder. + /// The collection builder. + public TBuilder GetCollectionBuilder() + where TBuilder: ICollectionBuilder, new() + { + var typeOfBuilder = typeof(TBuilder); + + if (_builders.TryGetValue(typeOfBuilder, out var o)) + return (TBuilder) o; + + var builder = new TBuilder(); + builder.Initialize(Container); + + _builders[typeOfBuilder] = builder; + + return builder; + } } } diff --git a/src/Umbraco.Core/Composing/CollectionBuilderBase.cs b/src/Umbraco.Core/Composing/CollectionBuilderBase.cs index 36c6879a32..b1d43d101c 100644 --- a/src/Umbraco.Core/Composing/CollectionBuilderBase.cs +++ b/src/Umbraco.Core/Composing/CollectionBuilderBase.cs @@ -16,25 +16,12 @@ namespace Umbraco.Core.Composing { private readonly List _types = new List(); private readonly object _locker = new object(); - private Func, TCollection> _collectionCtor; private Type[] _registeredTypes; - /// - /// Initializes a new instance of the - /// class with a service container. - /// - /// A container. - protected CollectionBuilderBase(IContainer container) - { - Container = container; - // ReSharper disable once DoNotCallOverridableMethodsInConstructor - Initialize(); - } - /// /// Gets the container. /// - protected IContainer Container { get; } + protected IContainer Container { get; private set; } /// /// Gets the internal list of types as an IEnumerable (immutable). @@ -44,17 +31,13 @@ namespace Umbraco.Core.Composing /// /// Initializes a new instance of the builder. /// - /// This is called by the constructor and, by default, registers the - /// collection automatically. - protected virtual void Initialize() + /// By default, this registers the collection automatically. + public virtual void Initialize(IContainer container) { - // compile the auto-collection constructor - // can be null, if no ctor found, and then assume CreateCollection has been overriden - _collectionCtor = ReflectionUtilities.EmitConstructor, TCollection>>(mustExist: false); + if (Container != null) + throw new InvalidOperationException("This builder has already been initialized."); - // we just don't want to support re-registering collections here - if (Container.GetRegistered().Any()) - throw new InvalidOperationException("Collection builders cannot be registered once the collection itself has been registered."); + Container = container; // register the collection Container.Register(_ => CreateCollection(), CollectionLifetime); @@ -131,8 +114,7 @@ namespace Umbraco.Core.Composing /// Creates a new collection each time it is invoked. public virtual TCollection CreateCollection() { - if (_collectionCtor == null) throw new InvalidOperationException("Collection auto-creation is not possible."); - return _collectionCtor(CreateItems()); + return Container.CreateInstance(CreateItems()); } protected Type EnsureType(Type type, string action) diff --git a/src/Umbraco.Core/Composing/ContainerExtensions.cs b/src/Umbraco.Core/Composing/ContainerExtensions.cs index a2eb3af7cf..789cdf6366 100644 --- a/src/Umbraco.Core/Composing/ContainerExtensions.cs +++ b/src/Umbraco.Core/Composing/ContainerExtensions.cs @@ -97,26 +97,6 @@ namespace Umbraco.Core.Composing public static void RegisterAuto(this IContainer container) => container.RegisterAuto(typeof(TServiceBase)); - /// - /// Registers and instantiates a collection builder. - /// - /// The type of the collection builder. - /// A collection builder of the specified type. - public static TBuilder RegisterCollectionBuilder(this IContainer container) - { - // make sure it's not already registered - // we just don't want to support re-registering collection builders - if (container.GetRegistered().Any()) - throw new InvalidOperationException("Collection builders should be registered only once."); - - // register the builder - // use a factory so we don't have to self-register the container - container.RegisterSingleton(factory => factory.CreateInstance(container)); - - // initialize and return the builder - return container.GetInstance(); - } - /// /// Creates an instance of a service, with arguments. /// diff --git a/src/Umbraco.Core/Composing/ICollectionBuilder.cs b/src/Umbraco.Core/Composing/ICollectionBuilder.cs index 5efc03c9ac..a493d90a0a 100644 --- a/src/Umbraco.Core/Composing/ICollectionBuilder.cs +++ b/src/Umbraco.Core/Composing/ICollectionBuilder.cs @@ -1,11 +1,22 @@ namespace Umbraco.Core.Composing { + /// + /// Represents a collection builder. + /// + public interface ICollectionBuilder + { + /// + /// Initializes a new instance of the builder, and registers the collection. + /// + void Initialize(IContainer container); + } + /// /// Represents a collection builder. /// /// The type of the collection. /// The type of the items. - public interface ICollectionBuilder + public interface ICollectionBuilder : ICollectionBuilder where TCollection : IBuilderCollection { /// diff --git a/src/Umbraco.Core/Composing/LazyCollectionBuilderBase.cs b/src/Umbraco.Core/Composing/LazyCollectionBuilderBase.cs index 04110b2070..79e5ffd4b1 100644 --- a/src/Umbraco.Core/Composing/LazyCollectionBuilderBase.cs +++ b/src/Umbraco.Core/Composing/LazyCollectionBuilderBase.cs @@ -18,19 +18,12 @@ namespace Umbraco.Core.Composing private readonly List>> _producers2 = new List>>(); private readonly List _excluded = new List(); - /// - /// Initializes a new instance of the class. - /// - protected LazyCollectionBuilderBase(IContainer container) - : base(container) - { } - protected abstract TBuilder This { get; } /// /// Clears all types in the collection. /// - /// The buidler. + /// The builder. public TBuilder Clear() { Configure(types => diff --git a/src/Umbraco.Core/Composing/OrderedCollectionBuilderBase.cs b/src/Umbraco.Core/Composing/OrderedCollectionBuilderBase.cs index 6dd6945ee1..5acf716ec0 100644 --- a/src/Umbraco.Core/Composing/OrderedCollectionBuilderBase.cs +++ b/src/Umbraco.Core/Composing/OrderedCollectionBuilderBase.cs @@ -13,20 +13,12 @@ namespace Umbraco.Core.Composing where TBuilder : OrderedCollectionBuilderBase where TCollection : IBuilderCollection { - /// - /// Initializes a new instance of the class. - /// - /// - protected OrderedCollectionBuilderBase(IContainer container) - : base (container) - { } - protected abstract TBuilder This { get; } /// /// Clears all types in the collection. /// - /// The buidler. + /// The builder. public TBuilder Clear() { Configure(types => types.Clear()); diff --git a/src/Umbraco.Core/Composing/TypeLoader.cs b/src/Umbraco.Core/Composing/TypeLoader.cs index 304638e017..4240f96a5b 100644 --- a/src/Umbraco.Core/Composing/TypeLoader.cs +++ b/src/Umbraco.Core/Composing/TypeLoader.cs @@ -16,7 +16,7 @@ using File = System.IO.File; namespace Umbraco.Core.Composing { /// - /// Provides methods to find and instanciate types. + /// Provides methods to find and instantiate types. /// /// /// This class should be used to get all types, the class should never be used directly. @@ -30,7 +30,7 @@ namespace Umbraco.Core.Composing private readonly IRuntimeCacheProvider _runtimeCache; private readonly IGlobalSettings _globalSettings; - private readonly ProfilingLogger _logger; + private readonly IProfilingLogger _logger; private readonly object _typesLock = new object(); private readonly Dictionary _types = new Dictionary(); @@ -49,7 +49,7 @@ namespace Umbraco.Core.Composing /// /// A profiling logger. /// Whether to detect changes using hashes. - internal TypeLoader(IRuntimeCacheProvider runtimeCache, IGlobalSettings globalSettings, ProfilingLogger logger, bool detectChanges = true) + internal TypeLoader(IRuntimeCacheProvider runtimeCache, IGlobalSettings globalSettings, IProfilingLogger logger, bool detectChanges = true) { _runtimeCache = runtimeCache ?? throw new ArgumentNullException(nameof(runtimeCache)); _globalSettings = globalSettings ?? throw new ArgumentNullException(nameof(globalSettings)); @@ -192,7 +192,7 @@ namespace Umbraco.Core.Composing /// The hash. /// Each file is a tuple containing the FileInfo object and a boolean which indicates whether to hash the /// file properties (false) or the file contents (true). - private static string GetFileHash(IEnumerable> filesAndFolders, ProfilingLogger logger) + private static string GetFileHash(IEnumerable> filesAndFolders, IProfilingLogger logger) { using (logger.TraceDuration("Determining hash of code files on disk", "Hash determined")) { @@ -494,7 +494,7 @@ namespace Umbraco.Core.Composing if (--attempts == 0) throw; - _logger.Logger.Debug("Attempted to get filestream for file {Path} failed, {NumberOfAttempts} attempts left, pausing for {PauseMilliseconds} milliseconds", path, attempts, pauseMilliseconds); + _logger.Debug("Attempted to get filestream for file {Path} failed, {NumberOfAttempts} attempts left, pausing for {PauseMilliseconds} milliseconds", path, attempts, pauseMilliseconds); Thread.Sleep(pauseMilliseconds); } } @@ -645,7 +645,7 @@ namespace Umbraco.Core.Composing if (typeList != null) { // need to put some logging here to try to figure out why this is happening: http://issues.umbraco.org/issue/U4-3505 - _logger.Logger.Debug("Getting {TypeName}: found a cached type list.", GetName(baseType, attributeType)); + _logger.Debug("Getting {TypeName}: found a cached type list.", GetName(baseType, attributeType)); return typeList.Types; } @@ -661,7 +661,7 @@ namespace Umbraco.Core.Composing // report (only once) and scan and update the cache file if (_reportedChange == false) { - _logger.Logger.Debug("Assemblies changes detected, need to rescan everything."); + _logger.Debug("Assemblies changes detected, need to rescan everything."); _reportedChange = true; } } @@ -676,7 +676,7 @@ namespace Umbraco.Core.Composing // so in this instance there will never be a result. if (cacheResult.Exception is CachedTypeNotFoundInFileException || cacheResult.Success == false) { - _logger.Logger.Debug("Getting {TypeName}: failed to load from cache file, must scan assemblies.", GetName(baseType, attributeType)); + _logger.Debug("Getting {TypeName}: failed to load from cache file, must scan assemblies.", GetName(baseType, attributeType)); scan = true; } else @@ -695,7 +695,7 @@ namespace Umbraco.Core.Composing catch (Exception ex) { // in case of any exception, we have to exit, and revert to scanning - _logger.Logger.Error(ex, "Getting {TypeName}: failed to load cache file type {CacheType}, reverting to scanning assemblies.", GetName(baseType, attributeType), type); + _logger.Error(ex, "Getting {TypeName}: failed to load cache file type {CacheType}, reverting to scanning assemblies.", GetName(baseType, attributeType), type); scan = true; break; } @@ -703,7 +703,7 @@ namespace Umbraco.Core.Composing if (scan == false) { - _logger.Logger.Debug("Getting {TypeName}: loaded types from cache file.", GetName(baseType, attributeType)); + _logger.Debug("Getting {TypeName}: loaded types from cache file.", GetName(baseType, attributeType)); } } } @@ -711,7 +711,7 @@ namespace Umbraco.Core.Composing if (scan) { // either we had to scan, or we could not get the types from the cache file - scan now - _logger.Logger.Debug("Getting {TypeName}: scanning assemblies.", GetName(baseType, attributeType)); + _logger.Debug("Getting {TypeName}: scanning assemblies.", GetName(baseType, attributeType)); foreach (var t in finder()) typeList.Add(t); @@ -729,11 +729,11 @@ namespace Umbraco.Core.Composing UpdateCache(); } - _logger.Logger.Debug("Got {TypeName}, caching ({CacheType}).", GetName(baseType, attributeType), added.ToString().ToLowerInvariant()); + _logger.Debug("Got {TypeName}, caching ({CacheType}).", GetName(baseType, attributeType), added.ToString().ToLowerInvariant()); } else { - _logger.Logger.Debug("Got {TypeName}.", GetName(baseType, attributeType)); + _logger.Debug("Got {TypeName}.", GetName(baseType, attributeType)); } return typeList.Types; diff --git a/src/Umbraco.Core/Composing/TypeLoaderExtensions.cs b/src/Umbraco.Core/Composing/TypeLoaderExtensions.cs index 6177151a00..ba57243071 100644 --- a/src/Umbraco.Core/Composing/TypeLoaderExtensions.cs +++ b/src/Umbraco.Core/Composing/TypeLoaderExtensions.cs @@ -42,13 +42,5 @@ namespace Umbraco.Core.Composing { return mgr.GetTypesWithAttribute(); } - - /// - /// Gets all classes implementing ISqlSyntaxProvider and marked with the SqlSyntaxProviderAttribute. - /// - public static IEnumerable GetSqlSyntaxProviders(this TypeLoader mgr) - { - return mgr.GetTypesWithAttribute(); - } } } diff --git a/src/Umbraco.Core/Composing/WeightedCollectionBuilderBase.cs b/src/Umbraco.Core/Composing/WeightedCollectionBuilderBase.cs index 499984a931..da47c53bf8 100644 --- a/src/Umbraco.Core/Composing/WeightedCollectionBuilderBase.cs +++ b/src/Umbraco.Core/Composing/WeightedCollectionBuilderBase.cs @@ -14,20 +14,12 @@ namespace Umbraco.Core.Composing where TBuilder : WeightedCollectionBuilderBase where TCollection : IBuilderCollection { - /// - /// Initializes a new instance of the class. - /// - /// - protected WeightedCollectionBuilderBase(IContainer container) - : base(container) - { } - protected abstract TBuilder This { get; } /// /// Clears all types in the collection. /// - /// The buidler. + /// The builder. public TBuilder Clear() { Configure(types => types.Clear()); diff --git a/src/Umbraco.Core/Logging/IProfilingLogger.cs b/src/Umbraco.Core/Logging/IProfilingLogger.cs new file mode 100644 index 0000000000..1d7c231e95 --- /dev/null +++ b/src/Umbraco.Core/Logging/IProfilingLogger.cs @@ -0,0 +1,40 @@ +using System; + +namespace Umbraco.Core.Logging +{ + /// + /// Defines the profiling logging service. + /// + public interface IProfilingLogger : ILogger + { + /// + /// Profiles an action and log as information messages. + /// + DisposableTimer TraceDuration(string startMessage); + + /// + /// Profiles an action and log as information messages. + /// + DisposableTimer TraceDuration(string startMessage, string completeMessage, string failMessage = null); + + /// + /// Profiles an action and log as information messages. + /// + DisposableTimer TraceDuration(Type loggerType, string startMessage, string completeMessage, string failMessage = null); + + /// + /// Profiles an action and log as debug messages. + /// + DisposableTimer DebugDuration(string startMessage); + + /// + /// Profiles an action and log as debug messages. + /// + DisposableTimer DebugDuration(string startMessage, string completeMessage, string failMessage = null, int thresholdMilliseconds = 0); + + /// + /// Profiles an action and log as debug messages. + /// + DisposableTimer DebugDuration(Type loggerType, string startMessage, string completeMessage, string failMessage = null, int thresholdMilliseconds = 0); + } +} diff --git a/src/Umbraco.Core/Logging/ProfilingLogger.cs b/src/Umbraco.Core/Logging/ProfilingLogger.cs index 80560e923a..d642926147 100644 --- a/src/Umbraco.Core/Logging/ProfilingLogger.cs +++ b/src/Umbraco.Core/Logging/ProfilingLogger.cs @@ -3,14 +3,23 @@ namespace Umbraco.Core.Logging { /// - /// Provides debug or trace logging with duration management. + /// Provides logging and profiling services. /// - public sealed class ProfilingLogger + public sealed class ProfilingLogger : IProfilingLogger { + /// + /// Gets the underlying implementation. + /// public ILogger Logger { get; } + /// + /// Gets the underlying implementation. + /// public IProfiler Profiler { get; } + /// + /// Initializes a new instance of the class. + /// public ProfilingLogger(ILogger logger, IProfiler profiler) { Logger = logger ?? throw new ArgumentNullException(nameof(logger)); @@ -52,5 +61,72 @@ namespace Umbraco.Core.Logging ? new DisposableTimer(Logger, LogLevel.Debug, Profiler, loggerType, startMessage, completeMessage, failMessage, thresholdMilliseconds) : null; } + + #region ILogger + + public bool IsEnabled(Type reporting, LogLevel level) + => Logger.IsEnabled(reporting, level); + + public void Fatal(Type reporting, Exception exception, string message) + => Logger.Fatal(reporting, exception, message); + + public void Fatal(Type reporting, Exception exception) + => Logger.Fatal(reporting, exception); + + public void Fatal(Type reporting, string message) + => Logger.Fatal(reporting, message); + + public void Fatal(Type reporting, Exception exception, string messageTemplate, params object[] propertyValues) + => Logger.Fatal(reporting, exception, messageTemplate, propertyValues); + + public void Fatal(Type reporting, string messageTemplate, params object[] propertyValues) + => Logger.Fatal(reporting, messageTemplate, propertyValues); + + public void Error(Type reporting, Exception exception, string message) + => Logger.Error(reporting, exception, message); + + public void Error(Type reporting, Exception exception) + => Logger.Error(reporting, exception); + + public void Error(Type reporting, string message) + => Logger.Error(reporting, message); + + public void Error(Type reporting, Exception exception, string messageTemplate, params object[] propertyValues) + => Logger.Error(reporting, exception, messageTemplate, propertyValues); + + public void Error(Type reporting, string messageTemplate, params object[] propertyValues) + => Logger.Error(reporting, messageTemplate, propertyValues); + + public void Warn(Type reporting, string message) + => Logger.Warn(reporting, message); + + public void Warn(Type reporting, string messageTemplate, params object[] propertyValues) + => Logger.Warn(reporting, messageTemplate, propertyValues); + + public void Warn(Type reporting, Exception exception, string message) + => Logger.Warn(reporting, exception, message); + + public void Warn(Type reporting, Exception exception, string messageTemplate, params object[] propertyValues) + => Logger.Warn(reporting, exception, messageTemplate, propertyValues); + + public void Info(Type reporting, string message) + => Logger.Info(reporting, message); + + public void Info(Type reporting, string messageTemplate, params object[] propertyValues) + => Logger.Info(reporting, messageTemplate, propertyValues); + + public void Debug(Type reporting, string message) + => Logger.Debug(reporting, message); + + public void Debug(Type reporting, string messageTemplate, params object[] propertyValues) + => Logger.Debug(reporting, messageTemplate, propertyValues); + + public void Verbose(Type reporting, string message) + => Logger.Verbose(reporting, message); + + public void Verbose(Type reporting, string messageTemplate, params object[] propertyValues) + => Logger.Verbose(reporting, messageTemplate, propertyValues); + + #endregion } } diff --git a/src/Umbraco.Core/Migrations/Install/DatabaseBuilder.cs b/src/Umbraco.Core/Migrations/Install/DatabaseBuilder.cs index 4986eeab02..f5e3892f5d 100644 --- a/src/Umbraco.Core/Migrations/Install/DatabaseBuilder.cs +++ b/src/Umbraco.Core/Migrations/Install/DatabaseBuilder.cs @@ -369,52 +369,6 @@ namespace Umbraco.Core.Migrations.Install #endregion - #region Utils - - internal static void GiveLegacyAChance(IUmbracoDatabaseFactory factory, ILogger logger) - { - // look for the legacy appSettings key - var legacyConnString = ConfigurationManager.AppSettings[Constants.System.UmbracoConnectionName]; - if (string.IsNullOrWhiteSpace(legacyConnString)) return; - - var test = legacyConnString.ToLowerInvariant(); - if (test.Contains("sqlce4umbraco")) - { - // sql ce - ConfigureEmbeddedDatabaseConnection(factory, logger); - } - else if (test.Contains("tcp:")) - { - // sql azure - SaveConnectionString(legacyConnString, Constants.DbProviderNames.SqlServer, logger); - factory.Configure(legacyConnString, Constants.DbProviderNames.SqlServer); - } - else if (test.Contains("datalayer=mysql")) - { - // mysql - - // strip the datalayer part off - var connectionStringWithoutDatalayer = string.Empty; - // ReSharper disable once LoopCanBeConvertedToQuery - foreach (var variable in legacyConnString.Split(';').Where(x => x.ToLowerInvariant().StartsWith("datalayer") == false)) - connectionStringWithoutDatalayer = $"{connectionStringWithoutDatalayer}{variable};"; - - SaveConnectionString(connectionStringWithoutDatalayer, Constants.DbProviderNames.MySql, logger); - factory.Configure(connectionStringWithoutDatalayer, Constants.DbProviderNames.MySql); - } - else - { - // sql server - SaveConnectionString(legacyConnString, Constants.DbProviderNames.SqlServer, logger); - factory.Configure(legacyConnString, Constants.DbProviderNames.SqlServer); - } - - // remove the legacy connection string, so we don't end up in a loop if something goes wrong - GlobalSettings.RemoveSetting(Constants.System.UmbracoConnectionName); - } - - #endregion - #region Database Schema internal DatabaseSchemaResult ValidateDatabaseSchema() diff --git a/src/Umbraco.Core/Migrations/PostMigrationCollectionBuilder.cs b/src/Umbraco.Core/Migrations/PostMigrationCollectionBuilder.cs index ba3eb96ce9..b23d4f1c9c 100644 --- a/src/Umbraco.Core/Migrations/PostMigrationCollectionBuilder.cs +++ b/src/Umbraco.Core/Migrations/PostMigrationCollectionBuilder.cs @@ -4,10 +4,6 @@ namespace Umbraco.Core.Migrations { public class PostMigrationCollectionBuilder : LazyCollectionBuilderBase { - public PostMigrationCollectionBuilder(IContainer container) - : base(container) - { } - protected override PostMigrationCollectionBuilder This => this; protected override Lifetime CollectionLifetime => Lifetime.Transient; diff --git a/src/Umbraco.Core/Persistence/Mappers/MapperCollectionBuilder.cs b/src/Umbraco.Core/Persistence/Mappers/MapperCollectionBuilder.cs index 65bfbcdbaf..28e19088bf 100644 --- a/src/Umbraco.Core/Persistence/Mappers/MapperCollectionBuilder.cs +++ b/src/Umbraco.Core/Persistence/Mappers/MapperCollectionBuilder.cs @@ -4,15 +4,11 @@ namespace Umbraco.Core.Persistence.Mappers { public class MapperCollectionBuilder : LazyCollectionBuilderBase { - public MapperCollectionBuilder(IContainer container) - : base(container) - { } - protected override MapperCollectionBuilder This => this; - protected override void Initialize() + public override void Initialize(IContainer container) { - base.Initialize(); + base.Initialize(container); // default initializer registers // - service MapperCollectionBuilder, returns MapperCollectionBuilder @@ -23,7 +19,7 @@ namespace Umbraco.Core.Persistence.Mappers Container.Register(factory => factory.GetInstance()); } - public MapperCollectionBuilder AddCore() + public MapperCollectionBuilder AddCoreMappers() { Add(); Add(); diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/MySqlSyntaxProvider.cs b/src/Umbraco.Core/Persistence/SqlSyntax/MySqlSyntaxProvider.cs index d69786fbfc..5cf9fa3af8 100644 --- a/src/Umbraco.Core/Persistence/SqlSyntax/MySqlSyntaxProvider.cs +++ b/src/Umbraco.Core/Persistence/SqlSyntax/MySqlSyntaxProvider.cs @@ -11,7 +11,6 @@ namespace Umbraco.Core.Persistence.SqlSyntax /// /// Represents an SqlSyntaxProvider for MySql /// - [SqlSyntaxProvider(Constants.DbProviderNames.MySql)] public class MySqlSyntaxProvider : SqlSyntaxProviderBase { private readonly ILogger _logger; @@ -334,7 +333,7 @@ ORDER BY TABLE_NAME, INDEX_NAME", switch (systemMethod) { case SystemMethods.NewGuid: - return null; // NOT SUPPORTED! + return null; // NOT SUPPORTED! case SystemMethods.CurrentDateTime: return "CURRENT_TIMESTAMP"; } diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/SqlCeSyntaxProvider.cs b/src/Umbraco.Core/Persistence/SqlSyntax/SqlCeSyntaxProvider.cs index 75fc9c0b69..8f39e36fb9 100644 --- a/src/Umbraco.Core/Persistence/SqlSyntax/SqlCeSyntaxProvider.cs +++ b/src/Umbraco.Core/Persistence/SqlSyntax/SqlCeSyntaxProvider.cs @@ -4,14 +4,12 @@ using System.Linq; using NPoco; using Umbraco.Core.Persistence.DatabaseAnnotations; using Umbraco.Core.Persistence.DatabaseModelDefinitions; -using Umbraco.Core.Persistence.Querying; namespace Umbraco.Core.Persistence.SqlSyntax { /// /// Represents an SqlSyntaxProvider for Sql Ce /// - [SqlSyntaxProvider(Constants.DbProviderNames.SqlCe)] public class SqlCeSyntaxProvider : MicrosoftSqlSyntaxProviderBase { public override Sql SelectTop(Sql sql, int top) diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs b/src/Umbraco.Core/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs index 90a2215e3d..d9bfe85098 100644 --- a/src/Umbraco.Core/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs +++ b/src/Umbraco.Core/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs @@ -11,29 +11,9 @@ namespace Umbraco.Core.Persistence.SqlSyntax /// /// Represents an SqlSyntaxProvider for Sql Server. /// - [SqlSyntaxProvider(Constants.DbProviderNames.SqlServer)] public class SqlServerSyntaxProvider : MicrosoftSqlSyntaxProviderBase { - // IUmbracoDatabaseFactory to be lazily injected - public SqlServerSyntaxProvider(Lazy lazyScopeProvider) - { - _serverVersion = new Lazy(() => - { - var scopeProvider = lazyScopeProvider.Value; - if (scopeProvider == null) - throw new InvalidOperationException("Failed to determine Sql Server version (no scope provider)."); - using (var scope = scopeProvider.CreateScope()) - { - var version = DetermineVersion(scope.Database); - scope.Complete(); - return version; - } - }); - } - - private readonly Lazy _serverVersion; - - internal ServerVersionInfo ServerVersion => _serverVersion.Value; + internal ServerVersionInfo ServerVersion { get; private set; } internal enum VersionName { @@ -62,19 +42,31 @@ namespace Umbraco.Core.Persistence.SqlSyntax internal class ServerVersionInfo { - public string Edition { get; set; } - public string InstanceName { get; set; } - public string ProductVersion { get; set; } - public VersionName ProductVersionName { get; private set; } - public EngineEdition EngineEdition { get; set; } - public bool IsAzure => EngineEdition == EngineEdition.Azure; - public string MachineName { get; set; } - public string ProductLevel { get; set; } - - public void Initialize() + public ServerVersionInfo() { - ProductVersionName = MapProductVersion(ProductVersion); + ProductVersionName = VersionName.Unknown; + EngineEdition = EngineEdition.Unknown; } + + public ServerVersionInfo(string edition, string instanceName, string productVersion, EngineEdition engineEdition, string machineName, string productLevel) + { + Edition = edition; + InstanceName = instanceName; + ProductVersion = productVersion; + ProductVersionName = MapProductVersion(ProductVersion); + EngineEdition = engineEdition; + MachineName = machineName; + ProductLevel = productLevel; + } + + public string Edition { get; } + public string InstanceName { get; } + public string ProductVersion { get; } + public VersionName ProductVersionName { get; } + public EngineEdition EngineEdition { get; } + public bool IsAzure => EngineEdition == EngineEdition.Azure; + public string MachineName { get; } + public string ProductLevel { get; } } private static VersionName MapProductVersion(string productVersion) @@ -105,8 +97,14 @@ namespace Umbraco.Core.Persistence.SqlSyntax } } - private static ServerVersionInfo DetermineVersion(IUmbracoDatabase database) + internal ServerVersionInfo GetSetVersion(string connectionString, string providerName) { + var factory = DbProviderFactories.GetFactory(providerName); + var connection = factory.CreateConnection(); + + if (connection == null) + throw new InvalidOperationException($"Could not create a connection for provider \"{providerName}\"."); + // Edition: "Express Edition", "Windows Azure SQL Database..." // EngineEdition: 1/Desktop 2/Standard 3/Enterprise 4/Express 5/Azure // ProductLevel: RTM, SPx, CTP... @@ -123,44 +121,28 @@ namespace Umbraco.Core.Persistence.SqlSyntax SERVERPROPERTY('ResourceLastUpdateDateTime') ResourceLastUpdateDateTime, SERVERPROPERTY('ProductLevel') ProductLevel;"; - try - { - var version = database.Fetch(sql).First(); - version.Initialize(); - return version; - } - catch (Exception e) - { - // can't ignore, really - throw new Exception("Failed to determine Sql Server version (see inner exception).", e); - } - } - - internal static VersionName GetVersionName(string connectionString, string providerName) - { - var factory = DbProviderFactories.GetFactory(providerName); - var connection = factory.CreateConnection(); - - if (connection == null) - throw new InvalidOperationException($"Could not create a connection for provider \"{providerName}\"."); - connection.ConnectionString = connectionString; + ServerVersionInfo version; using (connection) { try { connection.Open(); var command = connection.CreateCommand(); - command.CommandText = "SELECT SERVERPROPERTY('ProductVersion');"; - var productVersion = command.ExecuteScalar().ToString(); + command.CommandText = sql; + using (var reader = command.ExecuteReader()) + { + version = new ServerVersionInfo(reader.GetString(0), reader.GetString(2), reader.GetString(3), (EngineEdition) reader.GetInt32(5), reader.GetString(7), reader.GetString(9)); + } connection.Close(); - return MapProductVersion(productVersion); } catch { - return VersionName.Unknown; + version = new ServerVersionInfo(); // all unknown } } + + return ServerVersion = version; } /// diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxProviderAttribute.cs b/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxProviderAttribute.cs deleted file mode 100644 index 191ee86bac..0000000000 --- a/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxProviderAttribute.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; - -namespace Umbraco.Core.Persistence.SqlSyntax -{ - /// - /// Attribute for implementations of an ISqlSyntaxProvider - /// - [AttributeUsage(AttributeTargets.Class)] - public class SqlSyntaxProviderAttribute : Attribute - { - public SqlSyntaxProviderAttribute(string providerName) - { - ProviderName = providerName; - } - - /// - /// Gets or sets the ProviderName that corresponds to the sql syntax in a provider. - /// - public string ProviderName { get; set; } - } -} diff --git a/src/Umbraco.Core/Persistence/UmbracoDatabaseFactory.cs b/src/Umbraco.Core/Persistence/UmbracoDatabaseFactory.cs index ea597007b7..e55f462a7b 100644 --- a/src/Umbraco.Core/Persistence/UmbracoDatabaseFactory.cs +++ b/src/Umbraco.Core/Persistence/UmbracoDatabaseFactory.cs @@ -1,14 +1,11 @@ using System; -using System.Collections.Generic; using System.Configuration; using System.Data.Common; -using System.Linq; using System.Threading; using NPoco; using NPoco.FluentMappings; using Umbraco.Core.Exceptions; using Umbraco.Core.Logging; -using Umbraco.Core.Migrations.Install; using Umbraco.Core.Persistence.FaultHandling; using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Persistence.SqlSyntax; @@ -27,12 +24,11 @@ namespace Umbraco.Core.Persistence /// internal class UmbracoDatabaseFactory : DisposableObject, IUmbracoDatabaseFactory { - private readonly ISqlSyntaxProvider[] _sqlSyntaxProviders; - private readonly IMapperCollection _mappers; + private readonly Lazy _mappers; private readonly ILogger _logger; - private readonly SqlContext _sqlContext = new SqlContext(); private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(); + private SqlContext _sqlContext; private DatabaseFactory _npocoDatabaseFactory; private IPocoDataFactory _pocoDataFactory; private string _connectionString; @@ -51,24 +47,20 @@ namespace Umbraco.Core.Persistence /// /// Initializes a new instance of the . /// - /// Used by injection. - public UmbracoDatabaseFactory(IEnumerable sqlSyntaxProviders, ILogger logger, IMapperCollection mappers) - : this(Constants.System.UmbracoConnectionName, sqlSyntaxProviders, logger, mappers) - { - if (Configured == false) - DatabaseBuilder.GiveLegacyAChance(this, logger); - } + /// Used by core runtime. + public UmbracoDatabaseFactory(ILogger logger, Lazy mappers) + : this(Constants.System.UmbracoConnectionName, logger, mappers) + { } /// /// Initializes a new instance of the . /// /// Used by the other ctor and in tests. - public UmbracoDatabaseFactory(string connectionStringName, IEnumerable sqlSyntaxProviders, ILogger logger, IMapperCollection mappers) + public UmbracoDatabaseFactory(string connectionStringName, ILogger logger, Lazy mappers) { if (string.IsNullOrWhiteSpace(connectionStringName)) throw new ArgumentNullOrEmptyException(nameof(connectionStringName)); _mappers = mappers ?? throw new ArgumentNullException(nameof(mappers)); - _sqlSyntaxProviders = sqlSyntaxProviders?.ToArray() ?? throw new ArgumentNullException(nameof(sqlSyntaxProviders)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); var settings = ConfigurationManager.ConnectionStrings[connectionStringName]; @@ -92,10 +84,9 @@ namespace Umbraco.Core.Persistence /// Initializes a new instance of the . /// /// Used in tests. - public UmbracoDatabaseFactory(string connectionString, string providerName, IEnumerable sqlSyntaxProviders, ILogger logger, IMapperCollection mappers) + public UmbracoDatabaseFactory(string connectionString, string providerName, ILogger logger, Lazy mappers) { _mappers = mappers ?? throw new ArgumentNullException(nameof(mappers)); - _sqlSyntaxProviders = sqlSyntaxProviders?.ToArray() ?? throw new ArgumentNullException(nameof(sqlSyntaxProviders)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); if (string.IsNullOrWhiteSpace(connectionString) || string.IsNullOrWhiteSpace(providerName)) @@ -139,7 +130,7 @@ namespace Umbraco.Core.Persistence if (setting.IsNullOrWhiteSpace() || !setting.StartsWith("SqlServer.") || !Enum.TryParse(setting.Substring("SqlServer.".Length), out var versionName, true)) { - versionName = SqlServerSyntaxProvider.GetVersionName(_connectionString, _providerName); + versionName = ((SqlServerSyntaxProvider) _sqlSyntax).GetSetVersion(_connectionString, _providerName).ProductVersionName; } else { @@ -165,7 +156,7 @@ namespace Umbraco.Core.Persistence } /// - public ISqlContext SqlContext => _sqlContext; + public ISqlContext SqlContext => _sqlContext ?? (_sqlContext = new SqlContext(_sqlSyntax, _databaseType, _pocoDataFactory, _mappers.Value)); /// public void ConfigureForUpgrade() @@ -218,10 +209,6 @@ namespace Umbraco.Core.Persistence if (_npocoDatabaseFactory == null) throw new NullReferenceException("The call to UmbracoDatabaseFactory.Config yielded a null UmbracoDatabaseFactory instance."); - // can initialize now because it is the UmbracoDatabaseFactory that determines - // the sql syntax, poco data factory, and database type - _sqlContext.Initialize(_sqlSyntax, _databaseType, _pocoDataFactory, _mappers); - _logger.Debug("Configured."); Configured = true; } @@ -245,17 +232,17 @@ namespace Umbraco.Core.Persistence // gets the sql syntax provider that corresponds, from attribute private ISqlSyntaxProvider GetSqlSyntaxProvider(string providerName) { - var name = providerName.ToLowerInvariant(); - var provider = _sqlSyntaxProviders.FirstOrDefault(x => - x.GetType() - .FirstAttribute() - .ProviderName.ToLowerInvariant() - .Equals(name)); - if (provider != null) return provider; - throw new InvalidOperationException($"Unknown provider name \"{providerName}\""); - - // previously we'd try to return SqlServerSyntaxProvider by default but this is bad - //provider = _syntaxProviders.FirstOrDefault(x => x.GetType() == typeof(SqlServerSyntaxProvider)); + switch (providerName) + { + case Constants.DbProviderNames.MySql: + return new MySqlSyntaxProvider(_logger); + case Constants.DbProviderNames.SqlCe: + return new SqlCeSyntaxProvider(); + case Constants.DbProviderNames.SqlServer: + return new SqlServerSyntaxProvider(); + default: + throw new InvalidOperationException($"Unknown provider name \"{providerName}\""); + } } // ensures that the database is configured, else throws @@ -277,7 +264,7 @@ namespace Umbraco.Core.Persistence // method used by NPoco's UmbracoDatabaseFactory to actually create the database instance private UmbracoDatabase CreateDatabaseInstance() { - return new UmbracoDatabase(_connectionString, _sqlContext, _dbProviderFactory, _logger, _connectionRetryPolicy, _commandRetryPolicy); + return new UmbracoDatabase(_connectionString, SqlContext, _dbProviderFactory, _logger, _connectionRetryPolicy, _commandRetryPolicy); } protected override void DisposeResources() diff --git a/src/Umbraco.Core/PropertyEditors/DataEditorCollectionBuilder.cs b/src/Umbraco.Core/PropertyEditors/DataEditorCollectionBuilder.cs index c23972c684..c0c0a3651e 100644 --- a/src/Umbraco.Core/PropertyEditors/DataEditorCollectionBuilder.cs +++ b/src/Umbraco.Core/PropertyEditors/DataEditorCollectionBuilder.cs @@ -4,10 +4,6 @@ namespace Umbraco.Core.PropertyEditors { public class DataEditorCollectionBuilder : LazyCollectionBuilderBase { - public DataEditorCollectionBuilder(IContainer container) - : base(container) - { } - protected override DataEditorCollectionBuilder This => this; } } diff --git a/src/Umbraco.Core/PropertyEditors/ManifestValueValidatorCollectionBuilder.cs b/src/Umbraco.Core/PropertyEditors/ManifestValueValidatorCollectionBuilder.cs index 3ba6f4e402..8f7c68c813 100644 --- a/src/Umbraco.Core/PropertyEditors/ManifestValueValidatorCollectionBuilder.cs +++ b/src/Umbraco.Core/PropertyEditors/ManifestValueValidatorCollectionBuilder.cs @@ -4,10 +4,6 @@ namespace Umbraco.Core.PropertyEditors { internal class ManifestValueValidatorCollectionBuilder : LazyCollectionBuilderBase { - public ManifestValueValidatorCollectionBuilder(IContainer container) - : base(container) - { } - protected override ManifestValueValidatorCollectionBuilder This => this; } } diff --git a/src/Umbraco.Core/PropertyEditors/PropertyValueConverterCollectionBuilder.cs b/src/Umbraco.Core/PropertyEditors/PropertyValueConverterCollectionBuilder.cs index e95159ed0b..a64fe8c43a 100644 --- a/src/Umbraco.Core/PropertyEditors/PropertyValueConverterCollectionBuilder.cs +++ b/src/Umbraco.Core/PropertyEditors/PropertyValueConverterCollectionBuilder.cs @@ -4,10 +4,6 @@ namespace Umbraco.Core.PropertyEditors { public class PropertyValueConverterCollectionBuilder : OrderedCollectionBuilderBase { - public PropertyValueConverterCollectionBuilder(IContainer container) - : base(container) - { } - protected override PropertyValueConverterCollectionBuilder This => this; } } diff --git a/src/Umbraco.Core/Runtime/CoreRuntime.cs b/src/Umbraco.Core/Runtime/CoreRuntime.cs index 3004c7566a..2ae7c66136 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntime.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntime.cs @@ -15,9 +15,9 @@ using Umbraco.Core.Logging.Serilog; using Umbraco.Core.Migrations.Upgrade; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Mappers; -using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Scoping; using Umbraco.Core.Services.Implement; +using Umbraco.Core.Sync; namespace Umbraco.Core.Runtime { @@ -28,39 +28,71 @@ namespace Umbraco.Core.Runtime /// should be possible to use this runtime in console apps. public class CoreRuntime : IRuntime { - private BootLoader _bootLoader; + private Components.Components _components; private RuntimeState _state; + /// + /// Gets the logger. + /// + protected ILogger Logger { get; private set; } + + /// + /// Gets the profiling logger. + /// + protected IProfilingLogger ProfilingLogger { get; private set; } + /// public virtual void Boot(IContainer container) { // assign current container Current.Container = container; - // register the essential stuff, - // ie the global application logger - // (profiler etc depend on boot manager) + // create and register the essential services + // ie the bare minimum required to boot + + var composition = new Composition(container, RuntimeLevel.Boot); + + // loggers var logger = GetLogger(); container.RegisterInstance(logger); - // now it is ok to use Current.Logger + Logger = logger; + var profiler = GetProfiler(); + container.RegisterInstance(profiler); + var profilingLogger = new ProfilingLogger(logger, profiler); + container.RegisterInstance(profilingLogger); + ProfilingLogger = profilingLogger; - ConfigureUnhandledException(logger); - ConfigureAssemblyResolve(logger); + // application environment + ConfigureUnhandledException(); + ConfigureAssemblyResolve(); + ConfigureApplicationRootPath(); - Compose(container); + // application caches + var appCaches = GetAppCaches(); + container.RegisterInstance(appCaches); + var runtimeCache = appCaches.RuntimeCache; + container.RegisterInstance(runtimeCache); - // prepare essential stuff + // database factory + var databaseFactory = new UmbracoDatabaseFactory(logger, new Lazy(container.GetInstance)); + container.RegisterSingleton(factory => factory.GetInstance().SqlContext); - var path = GetApplicationRootPath(); - if (string.IsNullOrWhiteSpace(path) == false) - IOHelper.SetRootDirectory(path); + // type loader + var globalSettings = UmbracoConfig.For.GlobalSettings(); + var typeLoader = new TypeLoader(runtimeCache, globalSettings, profilingLogger); + container.RegisterInstance(typeLoader); - _state = (RuntimeState) container.GetInstance(); - _state.Level = RuntimeLevel.Boot; + // runtime state + _state = new RuntimeState(logger, + UmbracoConfig.For.UmbracoSettings(), UmbracoConfig.For.GlobalSettings(), + new Lazy(container.GetInstance), + new Lazy(container.GetInstance)) + { + Level = RuntimeLevel.Boot + }; + container.RegisterInstance(_state); - Logger = container.GetInstance(); - Profiler = container.GetInstance(); - ProfilingLogger = container.GetInstance(); + Compose(composition); // the boot loader boots using a container scope, so anything that is PerScope will // be disposed after the boot loader has booted, and anything else will remain. @@ -76,18 +108,33 @@ namespace Umbraco.Core.Runtime "Booted.", "Boot failed.")) { - // throws if not full-trust - new AspNetHostingPermission(AspNetHostingPermissionLevel.Unrestricted).Demand(); - try { - Logger.Debug("Runtime: {Runtime}", GetType().FullName); + // throws if not full-trust + new AspNetHostingPermission(AspNetHostingPermissionLevel.Unrestricted).Demand(); - AquireMainDom(container); - DetermineRuntimeLevel(container); - var componentTypes = ResolveComponentTypes(); - _bootLoader = new BootLoader(container); - _bootLoader.Boot(componentTypes, _state.Level); + logger.Debug("Runtime: {Runtime}", GetType().FullName); + + var mainDom = AquireMainDom(); + container.RegisterInstance(mainDom); + + DetermineRuntimeLevel(databaseFactory); + + var componentTypes = ResolveComponentTypes(typeLoader); + _components = new Components.Components(composition, componentTypes, profilingLogger); + + _components.Compose(); + + // no Current.Container only Current.Factory? + //factory = register.Compile(); + + // fixme at that point we can start actually getting things from the container + // but, ideally, not before = need to detect everything we use!! + + // at that point, getting things from the container is ok + // fixme split IRegistry vs IFactory + + _components.Initialize(); } catch (Exception e) { @@ -105,15 +152,7 @@ namespace Umbraco.Core.Runtime } } - /// - /// Gets a logger. - /// - protected virtual ILogger GetLogger() - { - return SerilogLogger.CreateWithDefaultConfiguration(); - } - - protected virtual void ConfigureUnhandledException(ILogger logger) + protected virtual void ConfigureUnhandledException() { //take care of unhandled exceptions - there is nothing we can do to // prevent the launch process to go down but at least we can try @@ -126,33 +165,40 @@ namespace Umbraco.Core.Runtime var msg = "Unhandled exception in AppDomain"; if (isTerminating) msg += " (terminating)"; msg += "."; - logger.Error(exception, msg); + Logger.Error(exception, msg); }; } - protected virtual void ConfigureAssemblyResolve(ILogger logger) + protected virtual void ConfigureAssemblyResolve() { // When an assembly can't be resolved. In here we can do magic with the assembly name and try loading another. // This is used for loading a signed assembly of AutoMapper (v. 3.1+) without having to recompile old code. AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => { // ensure the assembly is indeed AutoMapper and that the PublicKeyToken is null before trying to Load again - // do NOT just replace this with 'return Assembly', as it will cause an infinite loop -> stackoverflow + // do NOT just replace this with 'return Assembly', as it will cause an infinite loop -> stack overflow if (args.Name.StartsWith("AutoMapper") && args.Name.EndsWith("PublicKeyToken=null")) return Assembly.Load(args.Name.Replace(", PublicKeyToken=null", ", PublicKeyToken=be96cd2c38ef1005")); return null; }; } - - private void AquireMainDom(IContainer container) + protected virtual void ConfigureApplicationRootPath() { - using (var timer = ProfilingLogger.DebugDuration("Acquiring MainDom.", "Aquired.")) + var path = GetApplicationRootPath(); + if (string.IsNullOrWhiteSpace(path) == false) + IOHelper.SetRootDirectory(path); + } + + private MainDom AquireMainDom() + { + using (var timer = ProfilingLogger.DebugDuration("Acquiring MainDom.", "Acquired.")) { try { - var mainDom = container.GetInstance(); + var mainDom = new MainDom(Logger); mainDom.Acquire(); + return mainDom; } catch { @@ -163,38 +209,38 @@ namespace Umbraco.Core.Runtime } // internal for tests - internal void DetermineRuntimeLevel(IContainer container) + internal void DetermineRuntimeLevel(IUmbracoDatabaseFactory databaseFactory) { using (var timer = ProfilingLogger.DebugDuration("Determining runtime level.", "Determined.")) { try { - var dbfactory = container.GetInstance(); - SetRuntimeStateLevel(dbfactory, Logger); + _state.Level = DetermineRuntimeLevel2(databaseFactory); - Logger.Debug("Runtime level: {RuntimeLevel}", _state.Level); + ProfilingLogger.Debug("Runtime level: {RuntimeLevel}", _state.Level); if (_state.Level == RuntimeLevel.Upgrade) { - Logger.Debug("Configure database factory for upgrades."); - dbfactory.ConfigureForUpgrade(); + ProfilingLogger.Debug("Configure database factory for upgrades."); + databaseFactory.ConfigureForUpgrade(); } } catch { + _state.Level = RuntimeLevel.BootFailed; timer.Fail(); throw; } } } - private IEnumerable ResolveComponentTypes() + private IEnumerable ResolveComponentTypes(TypeLoader typeLoader) { using (var timer = ProfilingLogger.TraceDuration("Resolving component types.", "Resolved.")) { try { - return GetComponentTypes(); + return GetComponentTypes(typeLoader); } catch { @@ -209,97 +255,56 @@ namespace Umbraco.Core.Runtime { using (ProfilingLogger.DebugDuration("Terminating Umbraco.", "Terminated.")) { - _bootLoader?.Terminate(); + _components?.Terminate(); } } /// /// Composes the runtime. /// - public virtual void Compose(IContainer container) + public virtual void Compose(Composition composition) { + var container = composition.Container; + // compose the very essential things that are needed to bootstrap, before anything else, // and only these things - the rest should be composed in runtime components - - // register basic things - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); + // FIXME should be essentially empty! move all to component! container.ComposeConfiguration(); - // register caches - // need the deep clone runtime cache profiver to ensure entities are cached properly, ie - // are cloned in and cloned out - no request-based cache here since no web-based context, - // will be overriden later or - container.RegisterSingleton(_ => new CacheHelper( - new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()), - new StaticCacheProvider(), - NullCacheProvider.Instance, - new IsolatedRuntimeCache(type => new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider())))); - container.RegisterSingleton(f => f.GetInstance().RuntimeCache); - - // register the plugin manager - container.RegisterSingleton(f => new TypeLoader(f.GetInstance(), f.GetInstance(), f.GetInstance())); - - // register syntax providers - required by database factory - GetAllInstances or an IEnumerable can get them - container.Register(); - container.Register(); - container.Register(); - // register persistence mappers - required by database factory so needs to be done here // means the only place the collection can be modified is in a runtime - afterwards it // has been frozen and it is too late - var mapperCollectionBuilder = container.RegisterCollectionBuilder(); - ComposeMapperCollection(mapperCollectionBuilder); - - // register database factory - required to check for migrations - // will be initialized with syntax providers and a logger, and will try to configure - // from the default connection string name, if possible, else will remain non-configured - // until properly configured (eg when installing) - container.RegisterSingleton(); - container.RegisterSingleton(f => f.GetInstance().SqlContext); + composition.GetCollectionBuilder().AddCoreMappers(); // register the scope provider container.RegisterSingleton(); // implements both IScopeProvider and IScopeAccessor container.RegisterSingleton(f => f.GetInstance()); container.RegisterSingleton(f => f.GetInstance()); - - // register MainDom - container.RegisterSingleton(); } - protected virtual void ComposeMapperCollection(MapperCollectionBuilder builder) - { - builder.AddCore(); - } - - private void SetRuntimeStateLevel(IUmbracoDatabaseFactory databaseFactory, ILogger logger) + private RuntimeLevel DetermineRuntimeLevel2(IUmbracoDatabaseFactory databaseFactory) { var localVersion = UmbracoVersion.LocalVersion; // the local, files, version var codeVersion = _state.SemanticVersion; // the executing code version var connect = false; - // we don't know yet - _state.Level = RuntimeLevel.Unknown; - if (localVersion == null) { // there is no local version, we are not installed - logger.Debug("No local version, need to install Umbraco."); - _state.Level = RuntimeLevel.Install; + Logger.Debug("No local version, need to install Umbraco."); + return RuntimeLevel.Install; } - else if (localVersion < codeVersion) + + if (localVersion < codeVersion) { // there *is* a local version, but it does not match the code version // need to upgrade - logger.Debug("Local version '{LocalVersion}' < code version '{CodeVersion}', need to upgrade Umbraco.", localVersion, codeVersion); - _state.Level = RuntimeLevel.Upgrade; + Logger.Debug("Local version '{LocalVersion}' < code version '{CodeVersion}', need to upgrade Umbraco.", localVersion, codeVersion); } else if (localVersion > codeVersion) { - logger.Warn("Local version '{LocalVersion}' > code version '{CodeVersion}', downgrading is not supported.", localVersion, codeVersion); - _state.Level = RuntimeLevel.BootFailed; + Logger.Warn("Local version '{LocalVersion}' > code version '{CodeVersion}', downgrading is not supported.", localVersion, codeVersion); // in fact, this is bad enough that we want to throw throw new BootFailedException($"Local version \"{localVersion}\" > code version \"{codeVersion}\", downgrading is not supported."); @@ -308,14 +313,10 @@ namespace Umbraco.Core.Runtime { // local version *does* match code version, but the database is not configured // install (again? this is a weird situation...) - logger.Debug("Database is not configured, need to install Umbraco."); - _state.Level = RuntimeLevel.Install; + Logger.Debug("Database is not configured, need to install Umbraco."); + return RuntimeLevel.Install; } - // install? not going to test anything else - if (_state.Level == RuntimeLevel.Install) - return; - // 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) @@ -323,15 +324,14 @@ namespace Umbraco.Core.Runtime { connect = databaseFactory.CanConnect; if (connect) break; - logger.Debug("Could not immediately connect to database, trying again."); + Logger.Debug("Could not immediately connect to database, trying again."); Thread.Sleep(1000); } if (connect == false) { // cannot connect to configured database, this is bad, fail - logger.Debug("Could not connect to database."); - _state.Level = RuntimeLevel.BootFailed; + Logger.Debug("Could not connect to database."); // in fact, this is bad enough that we want to throw throw new BootFailedException("A connection string is configured but Umbraco could not connect to the database."); @@ -347,20 +347,19 @@ namespace Umbraco.Core.Runtime bool noUpgrade; try { - noUpgrade = EnsureUmbracoUpgradeState(databaseFactory, logger); + noUpgrade = EnsureUmbracoUpgradeState(databaseFactory); } catch (Exception e) { // can connect to the database but cannot check the upgrade state... oops - logger.Warn(e, "Could not check the upgrade state."); + Logger.Warn(e, "Could not check the upgrade state."); throw new BootFailedException("Could not check the upgrade state.", e); } if (noUpgrade) { // the database version matches the code & files version, all clear, can run - _state.Level = RuntimeLevel.Run; - return; + return RuntimeLevel.Run; } // the db version does not match... but we do have a migration table @@ -368,11 +367,11 @@ namespace Umbraco.Core.Runtime // although the files version matches the code version, the database version does not // which means the local files have been upgraded but not the database - need to upgrade - logger.Debug("Has not reached the final upgrade step, need to upgrade Umbraco."); - _state.Level = RuntimeLevel.Upgrade; + Logger.Debug("Has not reached the final upgrade step, need to upgrade Umbraco."); + return RuntimeLevel.Upgrade; } - protected virtual bool EnsureUmbracoUpgradeState(IUmbracoDatabaseFactory databaseFactory, ILogger logger) + protected virtual bool EnsureUmbracoUpgradeState(IUmbracoDatabaseFactory databaseFactory) { var umbracoPlan = new UmbracoPlan(); var stateValueKey = Upgrader.GetStateValueKey(umbracoPlan); @@ -384,31 +383,53 @@ namespace Umbraco.Core.Runtime _state.FinalMigrationState = umbracoPlan.FinalState; } - logger.Debug("Final upgrade state is {FinalMigrationState}, database contains {DatabaseState}", _state.FinalMigrationState, _state.CurrentMigrationState ?? ""); + Logger.Debug("Final upgrade state is {FinalMigrationState}, database contains {DatabaseState}", _state.FinalMigrationState, _state.CurrentMigrationState ?? ""); return _state.CurrentMigrationState == _state.FinalMigrationState; } - #region Locals - - protected ILogger Logger { get; private set; } - - protected IProfiler Profiler { get; private set; } - - protected ProfilingLogger ProfilingLogger { get; private set; } - - #endregion - #region Getters // getters can be implemented by runtimes inheriting from CoreRuntime - // fixme - inject! no Current! - protected virtual IEnumerable GetComponentTypes() => Current.TypeLoader.GetTypes(); + /// + /// Gets all component types. + /// + protected virtual IEnumerable GetComponentTypes(TypeLoader typeLoader) + => typeLoader.GetTypes(); + + /// + /// Gets a logger. + /// + protected virtual ILogger GetLogger() + => SerilogLogger.CreateWithDefaultConfiguration(); + + /// + /// Gets a profiler. + /// + protected virtual IProfiler GetProfiler() + => new LogProfiler(ProfilingLogger); + + /// + /// Gets the application caches. + /// + protected virtual CacheHelper GetAppCaches() + { + // need the deep clone runtime cache provider to ensure entities are cached properly, ie + // are cloned in and cloned out - no request-based cache here since no web-based context, + // is overriden by the web runtime + + return new CacheHelper( + new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()), + new StaticCacheProvider(), + NullCacheProvider.Instance, + new IsolatedRuntimeCache(type => new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()))); + } // by default, returns null, meaning that Umbraco should auto-detect the application root path. // override and return the absolute path to the Umbraco site/solution, if needed - protected virtual string GetApplicationRootPath() => null; + protected virtual string GetApplicationRootPath() + => null; #endregion } diff --git a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs index 34fd04d181..058c2ed593 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs @@ -47,7 +47,7 @@ namespace Umbraco.Core.Runtime composition.Container.RegisterSingleton(); // register our predefined validators - composition.Container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Add() .Add() .Add() @@ -56,7 +56,7 @@ namespace Umbraco.Core.Runtime .Add(); // properties and parameters derive from data editors - composition.Container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Add(factory => factory.GetInstance().GetDataEditors()); composition.Container.RegisterSingleton(); composition.Container.RegisterSingleton(); @@ -83,13 +83,13 @@ namespace Umbraco.Core.Runtime factory.GetInstance(), true, new DatabaseServerMessengerOptions())); - composition.Container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Add(factory => factory.GetInstance().GetCacheRefreshers()); - composition.Container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Add(f => f.GetInstance().GetPackageActions()); - composition.Container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Append(factory => factory.GetInstance().GetTypes()); composition.Container.RegisterSingleton(); @@ -97,10 +97,10 @@ namespace Umbraco.Core.Runtime composition.Container.RegisterSingleton(factory => new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(factory.GetInstance()))); - composition.Container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Append(); - composition.Container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Add(factory => factory.GetInstance().GetTypes()); composition.Container.RegisterSingleton(factory => new MigrationBuilder(composition.Container)); diff --git a/src/Umbraco.Core/RuntimeState.cs b/src/Umbraco.Core/RuntimeState.cs index 4f6f56531b..4ba75ed89f 100644 --- a/src/Umbraco.Core/RuntimeState.cs +++ b/src/Umbraco.Core/RuntimeState.cs @@ -17,76 +17,67 @@ namespace Umbraco.Core internal class RuntimeState : IRuntimeState { private readonly ILogger _logger; - private readonly Lazy _serverRegistrar; - private readonly Lazy _mainDom; private readonly IUmbracoSettingsSection _settings; private readonly IGlobalSettings _globalSettings; private readonly HashSet _applicationUrls = new HashSet(); private RuntimeLevel _level; + private Lazy _mainDom; + private Lazy _serverRegistrar; /// /// Initializes a new instance of the class. /// /// A logger. - /// A (lazy) server registrar. - /// A (lazy) MainDom. - public RuntimeState(ILogger logger, Lazy serverRegistrar, Lazy mainDom, IUmbracoSettingsSection settings, IGlobalSettings globalSettings) + /// Umbraco settings. + /// Global settings. + public RuntimeState(ILogger logger, IUmbracoSettingsSection settings, IGlobalSettings globalSettings, + Lazy mainDom, Lazy serverRegistrar) { _logger = logger; - _serverRegistrar = serverRegistrar; - _mainDom = mainDom; _settings = settings; _globalSettings = globalSettings; + _mainDom = mainDom; + _serverRegistrar = serverRegistrar; } + /// + /// Gets the server registrar. + /// + /// + /// This is NOT exposed in the interface. + /// private IServerRegistrar ServerRegistrar => _serverRegistrar.Value; /// /// Gets the application MainDom. /// - /// This is NOT exposed in the interface as MainDom is internal. + /// + /// This is NOT exposed in the interface as MainDom is internal. + /// public MainDom MainDom => _mainDom.Value; - /// - /// Gets the version of the executing code. - /// + /// public Version Version => UmbracoVersion.Current; - /// - /// Gets the version comment of the executing code. - /// + /// public string VersionComment => UmbracoVersion.Comment; - /// - /// Gets the semantic version of the executing code. - /// + /// public SemVersion SemanticVersion => UmbracoVersion.SemanticVersion; - /// - /// Gets a value indicating whether the application is running in debug mode. - /// + /// public bool Debug { get; } = GlobalSettings.DebugMode; - /// - /// Gets a value indicating whether the runtime is the current main domain. - /// + /// public bool IsMainDom => MainDom.IsMainDom; - /// - /// Get the server's current role. - /// + /// public ServerRole ServerRole => ServerRegistrar.GetCurrentServerRole(); - /// - /// Gets the Umbraco application url. - /// - /// This is eg "http://www.example.com". + /// public Uri ApplicationUrl { get; private set; } - /// - /// Gets the Umbraco application virtual path. - /// - /// This is either "/" or eg "/virtual". + /// public string ApplicationVirtualPath { get; } = HttpRuntime.AppDomainAppVirtualPath; /// @@ -95,9 +86,7 @@ namespace Umbraco.Core /// public string FinalMigrationState { get; internal set; } - /// - /// Gets the runtime level of execution. - /// + /// public RuntimeLevel Level { get => _level; @@ -137,9 +126,7 @@ namespace Umbraco.Core return _runLevel.WaitHandle.WaitOne(timeout); } - /// - /// Gets the exception that caused the boot to fail. - /// + /// public BootFailedException BootFailedException { get; internal set; } } } diff --git a/src/Umbraco.Core/Strings/UrlSegmentProviderCollectionBuilder.cs b/src/Umbraco.Core/Strings/UrlSegmentProviderCollectionBuilder.cs index 7c45bf0884..5183c28e15 100644 --- a/src/Umbraco.Core/Strings/UrlSegmentProviderCollectionBuilder.cs +++ b/src/Umbraco.Core/Strings/UrlSegmentProviderCollectionBuilder.cs @@ -4,10 +4,6 @@ namespace Umbraco.Core.Strings { public class UrlSegmentProviderCollectionBuilder : OrderedCollectionBuilderBase { - public UrlSegmentProviderCollectionBuilder(IContainer container) - : base(container) - { } - protected override UrlSegmentProviderCollectionBuilder This => this; } } diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 1b517ae1f9..57f7208d03 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -155,7 +155,7 @@ - + @@ -335,6 +335,7 @@ + @@ -1222,7 +1223,6 @@ - diff --git a/src/Umbraco.Core/_Legacy/PackageActions/PackageActionCollectionBuilder.cs b/src/Umbraco.Core/_Legacy/PackageActions/PackageActionCollectionBuilder.cs index a92d340b48..2f73a2b489 100644 --- a/src/Umbraco.Core/_Legacy/PackageActions/PackageActionCollectionBuilder.cs +++ b/src/Umbraco.Core/_Legacy/PackageActions/PackageActionCollectionBuilder.cs @@ -4,10 +4,6 @@ namespace Umbraco.Core._Legacy.PackageActions { internal class PackageActionCollectionBuilder : LazyCollectionBuilderBase { - public PackageActionCollectionBuilder(IContainer container) - : base(container) - { } - protected override PackageActionCollectionBuilder This => this; } } diff --git a/src/Umbraco.Tests.Benchmarks/BulkInsertBenchmarks.cs b/src/Umbraco.Tests.Benchmarks/BulkInsertBenchmarks.cs index 0505974304..ee2e75cfad 100644 --- a/src/Umbraco.Tests.Benchmarks/BulkInsertBenchmarks.cs +++ b/src/Umbraco.Tests.Benchmarks/BulkInsertBenchmarks.cs @@ -4,18 +4,12 @@ using System.Data.SqlServerCe; using System.IO; using System.Linq; using BenchmarkDotNet.Attributes; -using BenchmarkDotNet.Configs; -using BenchmarkDotNet.Diagnosers; -using BenchmarkDotNet.Horology; -using BenchmarkDotNet.Jobs; using Umbraco.Core; using Umbraco.Core.Logging; using Umbraco.Core.Migrations.Install; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Dtos; using Umbraco.Core.Persistence.Mappers; -using Umbraco.Core.Persistence.Querying; -using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Scoping; using Umbraco.Tests.Benchmarks.Config; using Umbraco.Tests.TestHelpers; @@ -34,13 +28,11 @@ namespace Umbraco.Tests.Benchmarks { IScopeProvider f = null; var l = new Lazy(() => f); - var p = new SqlServerSyntaxProvider(l); var factory = new UmbracoDatabaseFactory( "server=.\\SQLExpress;database=YOURDB;user id=YOURUSER;password=YOURPASS", Constants.DatabaseProviders.SqlServer, - new [] { p }, logger, - new MapperCollection(Enumerable.Empty())); + new Lazy(() => new MapperCollection(Enumerable.Empty()))); return factory.CreateDatabase(); } @@ -49,9 +41,8 @@ namespace Umbraco.Tests.Benchmarks var f = new UmbracoDatabaseFactory( cstr, Constants.DatabaseProviders.SqlCe, - new[] { new SqlCeSyntaxProvider() }, logger, - new MapperCollection(Enumerable.Empty())); + new Lazy(() => new MapperCollection(Enumerable.Empty()))); return f.CreateDatabase(); } diff --git a/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs b/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs index 554194fd91..d3b0b6cda8 100644 --- a/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs +++ b/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs @@ -4,6 +4,7 @@ using System.Linq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; +using Umbraco.Core.Components; using Umbraco.Core.Composing; using Umbraco.Core.Sync; @@ -21,11 +22,12 @@ namespace Umbraco.Tests.Cache.DistributedCache public void Setup() { var container = Current.Container = ContainerFactory.Create(); + var composition = new Composition(container, RuntimeLevel.Run); container.Register(_ => new TestServerRegistrar()); container.RegisterSingleton(_ => new TestServerMessenger()); - container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Add(); _distributedCache = new Umbraco.Web.Cache.DistributedCache(); diff --git a/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs b/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs index e4a15a2ac2..a0ab75f0f9 100644 --- a/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs +++ b/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs @@ -29,7 +29,7 @@ namespace Umbraco.Tests.Cache.PublishedCache { base.Compose(); - Container.GetInstance() + Composition.GetCollectionBuilder() .Clear() .Append(); } diff --git a/src/Umbraco.Tests/Components/ComponentTests.cs b/src/Umbraco.Tests/Components/ComponentTests.cs index a537aac4ae..111a1370ee 100644 --- a/src/Umbraco.Tests/Components/ComponentTests.cs +++ b/src/Umbraco.Tests/Components/ComponentTests.cs @@ -27,10 +27,8 @@ namespace Umbraco.Tests.Components var mock = new Mock(); - var testObjects = new TestObjects(null); var logger = Mock.Of(); - var s = testObjects.GetDefaultSqlSyntaxProviders(logger); - var f = new UmbracoDatabaseFactory(s, logger, new MapperCollection(Enumerable.Empty())); + var f = new UmbracoDatabaseFactory(logger, new Lazy(() => new MapperCollection(Enumerable.Empty()))); var fs = new FileSystems(mock.Object, logger); var p = new ScopeProvider(f, fs, logger); @@ -47,13 +45,15 @@ namespace Umbraco.Tests.Components public void Boot1A() { var container = MockContainer(); + var composition = new Composition(container, RuntimeLevel.Unknown); - var loader = new BootLoader(container); + var types = TypeArray(); + var components = new Core.Components.Components(composition, types, Mock.Of()); Composed.Clear(); // 2 is Core and requires 4 // 3 is User - goes away with RuntimeLevel.Unknown // => reorder components accordingly - loader.Boot(TypeArray(), RuntimeLevel.Unknown); + components.Compose(); AssertTypeArray(TypeArray(), Composed); } @@ -61,13 +61,15 @@ namespace Umbraco.Tests.Components public void Boot1B() { var container = MockContainer(); + var composition = new Composition(container, RuntimeLevel.Run); - var loader = new BootLoader(container); + var types = TypeArray(); + var components = new Core.Components.Components(composition, types, Mock.Of()); Composed.Clear(); // 2 is Core and requires 4 // 3 is User - stays with RuntimeLevel.Run // => reorder components accordingly - loader.Boot(TypeArray(), RuntimeLevel.Run); + components.Compose(); AssertTypeArray(TypeArray(), Composed); } @@ -75,12 +77,14 @@ namespace Umbraco.Tests.Components public void Boot2() { var container = MockContainer(); + var composition = new Composition(container, RuntimeLevel.Unknown); - var loader = new BootLoader(container); + var types = TypeArray(); + var components = new Core.Components.Components(composition, types, Mock.Of()); Composed.Clear(); // 21 is required by 20 // => reorder components accordingly - loader.Boot(TypeArray(), RuntimeLevel.Unknown); + components.Compose(); AssertTypeArray(TypeArray(), Composed); } @@ -88,14 +92,16 @@ namespace Umbraco.Tests.Components public void Boot3() { var container = MockContainer(); + var composition = new Composition(container, RuntimeLevel.Unknown); - var loader = new BootLoader(container); + var types = TypeArray(); + var components = new Core.Components.Components(composition, types, Mock.Of()); Composed.Clear(); // i23 requires 22 // 24, 25 implement i23 // 25 required by i23 // => reorder components accordingly - loader.Boot(TypeArray(), RuntimeLevel.Unknown); + components.Compose(); AssertTypeArray(TypeArray(), Composed); } @@ -103,15 +109,17 @@ namespace Umbraco.Tests.Components public void BrokenRequire() { var container = MockContainer(); + var composition = new Composition(container, RuntimeLevel.Unknown); - var thing = new BootLoader(container); + var types = TypeArray(); + var components = new Core.Components.Components(composition, types, Mock.Of()); Composed.Clear(); try { // 2 is Core and requires 4 // 4 is missing // => throw - thing.Boot(TypeArray < Component1, Component2, Component3>(), RuntimeLevel.Unknown); + components.Compose(); Assert.Fail("Expected exception."); } catch (Exception e) @@ -124,14 +132,16 @@ namespace Umbraco.Tests.Components public void BrokenRequired() { var container = MockContainer(); + var composition = new Composition(container, RuntimeLevel.Unknown); - var thing = new BootLoader(container); + var types = TypeArray(); + var components = new Core.Components.Components(composition, types, Mock.Of()); Composed.Clear(); // 2 is Core and requires 4 // 13 is required by 1 // 1 is missing // => reorder components accordingly - thing.Boot(TypeArray(), RuntimeLevel.Unknown); + components.Compose(); AssertTypeArray(TypeArray(), Composed); } @@ -142,11 +152,14 @@ namespace Umbraco.Tests.Components { m.Setup(x => x.TryGetInstance(It.Is(t => t == typeof (ISomeResource)))).Returns(() => new SomeResource()); }); + var composition = new Composition(container, RuntimeLevel.Unknown); - var thing = new BootLoader(container); + var types = new[] { typeof(Component1), typeof(Component5) }; + var components = new Core.Components.Components(composition, types, Mock.Of()); Composed.Clear(); Initialized.Clear(); - thing.Boot(new[] { typeof(Component1), typeof(Component5) }, RuntimeLevel.Unknown); + components.Compose(); + components.Initialize(); Assert.AreEqual(2, Composed.Count); Assert.AreEqual(typeof(Component1), Composed[0]); Assert.AreEqual(typeof(Component5), Composed[1]); @@ -158,10 +171,12 @@ namespace Umbraco.Tests.Components public void Requires1() { var container = MockContainer(); + var composition = new Composition(container, RuntimeLevel.Unknown); - var thing = new BootLoader(container); + var types = new[] { typeof(Component6), typeof(Component7), typeof(Component8) }; + var components = new Core.Components.Components(composition, types, Mock.Of()); Composed.Clear(); - thing.Boot(new[] { typeof(Component6), typeof(Component7), typeof(Component8) }, RuntimeLevel.Unknown); + components.Compose(); Assert.AreEqual(2, Composed.Count); Assert.AreEqual(typeof(Component6), Composed[0]); Assert.AreEqual(typeof(Component8), Composed[1]); @@ -171,10 +186,12 @@ namespace Umbraco.Tests.Components public void Requires2A() { var container = MockContainer(); + var composition = new Composition(container, RuntimeLevel.Unknown); - var thing = new BootLoader(container); + var types = new[] { typeof(Component9), typeof(Component2), typeof(Component4) }; + var components = new Core.Components.Components(composition, types, Mock.Of()); Composed.Clear(); - thing.Boot(new[] { typeof(Component9), typeof(Component2), typeof(Component4) }, RuntimeLevel.Unknown); + components.Compose(); Assert.AreEqual(2, Composed.Count); Assert.AreEqual(typeof(Component4), Composed[0]); Assert.AreEqual(typeof(Component2), Composed[1]); @@ -185,10 +202,13 @@ namespace Umbraco.Tests.Components public void Requires2B() { var container = MockContainer(); + var composition = new Composition(container, RuntimeLevel.Run); - var thing = new BootLoader(container); + var types = new[] { typeof(Component9), typeof(Component2), typeof(Component4) }; + var components = new Core.Components.Components(composition, types, Mock.Of()); Composed.Clear(); - thing.Boot(new[] { typeof(Component9), typeof(Component2), typeof(Component4) }, RuntimeLevel.Run); + components.Compose(); + components.Initialize(); Assert.AreEqual(3, Composed.Count); Assert.AreEqual(typeof(Component4), Composed[0]); Assert.AreEqual(typeof(Component2), Composed[1]); @@ -199,24 +219,29 @@ namespace Umbraco.Tests.Components public void WeakDependencies() { var container = MockContainer(); + var composition = new Composition(container, RuntimeLevel.Unknown); - var thing = new BootLoader(container); + var types = new[] { typeof(Component10) }; + var components = new Core.Components.Components(composition, types, Mock.Of()); Composed.Clear(); - thing.Boot(new[] { typeof(Component10) }, RuntimeLevel.Unknown); + components.Compose(); Assert.AreEqual(1, Composed.Count); Assert.AreEqual(typeof(Component10), Composed[0]); - thing = new BootLoader(container); + types = new[] { typeof(Component11) }; + components = new Core.Components.Components(composition, types, Mock.Of()); Composed.Clear(); - Assert.Throws(() => thing.Boot(new[] { typeof(Component11) }, RuntimeLevel.Unknown)); + Assert.Throws(() => components.Compose()); - thing = new BootLoader(container); + types = new[] { typeof(Component2) }; + components = new Core.Components.Components(composition, types, Mock.Of()); Composed.Clear(); - Assert.Throws(() => thing.Boot(new[] { typeof(Component2) }, RuntimeLevel.Unknown)); + Assert.Throws(() => components.Compose()); - thing = new BootLoader(container); + types = new[] { typeof(Component12) }; + components = new Core.Components.Components(composition, types, Mock.Of()); Composed.Clear(); - thing.Boot(new[] { typeof(Component12) }, RuntimeLevel.Unknown); + components.Compose(); Assert.AreEqual(1, Composed.Count); Assert.AreEqual(typeof(Component12), Composed[0]); } @@ -225,10 +250,12 @@ namespace Umbraco.Tests.Components public void DisableMissing() { var container = MockContainer(); + var composition = new Composition(container, RuntimeLevel.Unknown); - var thing = new BootLoader(container); + var types = new[] { typeof(Component6), typeof(Component8) }; // 8 disables 7 which is not in the list + var components = new Core.Components.Components(composition, types, Mock.Of()); Composed.Clear(); - thing.Boot(new[] { typeof(Component6), typeof(Component8) }, RuntimeLevel.Unknown); // 8 disables 7 which is not in the list + components.Compose(); Assert.AreEqual(2, Composed.Count); Assert.AreEqual(typeof(Component6), Composed[0]); Assert.AreEqual(typeof(Component8), Composed[1]); diff --git a/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs b/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs index 1bddbdfbb2..23914ef2bf 100644 --- a/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs +++ b/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs @@ -4,6 +4,7 @@ using System.Linq; using NUnit.Framework; using Umbraco.Core.Composing; using Umbraco.Core; +using Umbraco.Core.Components; namespace Umbraco.Tests.Composing { @@ -11,6 +12,7 @@ namespace Umbraco.Tests.Composing public class CollectionBuildersTests { private IContainer _container; + private Composition _composition; [SetUp] public void Setup() @@ -18,6 +20,7 @@ namespace Umbraco.Tests.Composing Current.Reset(); _container = Current.Container = ContainerFactory.Create(); + _composition = new Composition(_container, RuntimeLevel.Run); } [TearDown] @@ -32,7 +35,7 @@ namespace Umbraco.Tests.Composing [Test] public void ContainsTypes() { - var builder = _container.RegisterCollectionBuilder() + var builder = _composition.GetCollectionBuilder() .Append() .Append(); @@ -48,7 +51,7 @@ namespace Umbraco.Tests.Composing [Test] public void CanClearBuilderBeforeCollectionIsCreated() { - var builder = _container.RegisterCollectionBuilder() + var builder = _composition.GetCollectionBuilder() .Append() .Append(); @@ -63,7 +66,7 @@ namespace Umbraco.Tests.Composing [Test] public void CannotClearBuilderOnceCollectionIsCreated() { - var builder = _container.RegisterCollectionBuilder() + var builder = _composition.GetCollectionBuilder() .Append() .Append(); @@ -75,7 +78,7 @@ namespace Umbraco.Tests.Composing [Test] public void CanAppendToBuilder() { - var builder = _container.RegisterCollectionBuilder(); + var builder = _composition.GetCollectionBuilder(); builder.Append(); builder.Append(); @@ -90,7 +93,7 @@ namespace Umbraco.Tests.Composing [Test] public void CannotAppendToBuilderOnceCollectionIsCreated() { - var builder = _container.RegisterCollectionBuilder(); + var builder = _composition.GetCollectionBuilder(); var col = builder.CreateCollection(); @@ -102,7 +105,7 @@ namespace Umbraco.Tests.Composing [Test] public void CanAppendDuplicateToBuilderAndDeDuplicate() { - var builder = _container.RegisterCollectionBuilder(); + var builder = _composition.GetCollectionBuilder(); builder.Append(); builder.Append(); @@ -113,7 +116,7 @@ namespace Umbraco.Tests.Composing [Test] public void CannotAppendInvalidTypeToBUilder() { - var builder = _container.RegisterCollectionBuilder(); + var builder = _composition.GetCollectionBuilder(); //builder.Append(); // does not compile Assert.Throws(() => builder.Append(new[] { typeof (Resolved4) }) // throws @@ -123,7 +126,7 @@ namespace Umbraco.Tests.Composing [Test] public void CanRemoveFromBuilder() { - var builder = _container.RegisterCollectionBuilder() + var builder = _composition.GetCollectionBuilder() .Append() .Append() .Remove(); @@ -139,7 +142,7 @@ namespace Umbraco.Tests.Composing [Test] public void CanRemoveMissingFromBuilder() { - var builder = _container.RegisterCollectionBuilder() + var builder = _composition.GetCollectionBuilder() .Append() .Append() .Remove(); @@ -151,7 +154,7 @@ namespace Umbraco.Tests.Composing [Test] public void CannotRemoveFromBuilderOnceCollectionIsCreated() { - var builder = _container.RegisterCollectionBuilder() + var builder = _composition.GetCollectionBuilder() .Append() .Append(); @@ -164,7 +167,7 @@ namespace Umbraco.Tests.Composing [Test] public void CanInsertIntoBuilder() { - var builder = _container.RegisterCollectionBuilder() + var builder = _composition.GetCollectionBuilder() .Append() .Append() .Insert(); @@ -180,7 +183,7 @@ namespace Umbraco.Tests.Composing [Test] public void CannotInsertIntoBuilderOnceCollectionIsCreated() { - var builder = _container.RegisterCollectionBuilder() + var builder = _composition.GetCollectionBuilder() .Append() .Append(); @@ -193,7 +196,7 @@ namespace Umbraco.Tests.Composing [Test] public void CanInsertDuplicateIntoBuilderAndDeDuplicate() { - var builder = _container.RegisterCollectionBuilder() + var builder = _composition.GetCollectionBuilder() .Append() .Append() .Insert(); @@ -205,7 +208,7 @@ namespace Umbraco.Tests.Composing [Test] public void CanInsertIntoEmptyBuilder() { - var builder = _container.RegisterCollectionBuilder(); + var builder = _composition.GetCollectionBuilder(); builder.Insert(); var col = builder.CreateCollection(); @@ -215,7 +218,7 @@ namespace Umbraco.Tests.Composing [Test] public void CannotInsertIntoBuilderAtWrongIndex() { - var builder = _container.RegisterCollectionBuilder() + var builder = _composition.GetCollectionBuilder() .Append() .Append(); @@ -231,7 +234,7 @@ namespace Umbraco.Tests.Composing [Test] public void CanInsertIntoBuilderBefore() { - var builder = _container.RegisterCollectionBuilder() + var builder = _composition.GetCollectionBuilder() .Append() .Append() .InsertBefore(); @@ -247,7 +250,7 @@ namespace Umbraco.Tests.Composing [Test] public void CannotInsertIntoBuilderBeforeOnceCollectionIsCreated() { - var builder = _container.RegisterCollectionBuilder() + var builder = _composition.GetCollectionBuilder() .Append() .Append(); @@ -260,7 +263,7 @@ namespace Umbraco.Tests.Composing [Test] public void CanInsertDuplicateIntoBuilderBeforeAndDeDuplicate() { - var builder = _container.RegisterCollectionBuilder() + var builder = _composition.GetCollectionBuilder() .Append() .Append() .InsertBefore(); @@ -272,7 +275,7 @@ namespace Umbraco.Tests.Composing [Test] public void CannotInsertIntoBuilderBeforeMissing() { - var builder = _container.RegisterCollectionBuilder() + var builder = _composition.GetCollectionBuilder() .Append(); Assert.Throws(() => @@ -283,7 +286,7 @@ namespace Umbraco.Tests.Composing [Test] public void ScopeBuilderCreatesScopedCollection() { - _container.RegisterCollectionBuilder() + _composition.GetCollectionBuilder() .Append() .Append(); @@ -303,7 +306,7 @@ namespace Umbraco.Tests.Composing [Test] public void TransientBuilderCreatesTransientCollection() { - _container.RegisterCollectionBuilder() + _composition.GetCollectionBuilder() .Append() .Append(); @@ -323,7 +326,7 @@ namespace Umbraco.Tests.Composing [Test] public void BuilderRespectsTypesOrder() { - var builder = _container.RegisterCollectionBuilder() + var builder = _composition.GetCollectionBuilder() .Append() .Insert() .InsertBefore(); @@ -335,7 +338,7 @@ namespace Umbraco.Tests.Composing [Test] public void ScopeBuilderRespectsContainerScope() { - _container.RegisterCollectionBuilder() + _composition.GetCollectionBuilder() .Append() .Append(); @@ -369,7 +372,7 @@ namespace Umbraco.Tests.Composing [Test] public void WeightedBuilderCreatesWeightedCollection() { - var builder = _container.RegisterCollectionBuilder() + var builder = _composition.GetCollectionBuilder() .Add() .Add(); @@ -434,20 +437,12 @@ namespace Umbraco.Tests.Composing // ReSharper disable once ClassNeverInstantiated.Local private class TestCollectionBuilder : OrderedCollectionBuilderBase { - public TestCollectionBuilder(IContainer container) - : base(container) - { } - protected override TestCollectionBuilder This => this; } // ReSharper disable once ClassNeverInstantiated.Local private class TestCollectionBuilderTransient : OrderedCollectionBuilderBase { - public TestCollectionBuilderTransient(IContainer container) - : base(container) - { } - protected override TestCollectionBuilderTransient This => this; protected override Lifetime CollectionLifetime => Lifetime.Transient; // transient @@ -456,10 +451,6 @@ namespace Umbraco.Tests.Composing // ReSharper disable once ClassNeverInstantiated.Local private class TestCollectionBuilderScope : OrderedCollectionBuilderBase { - public TestCollectionBuilderScope(IContainer container) - : base(container) - { } - protected override TestCollectionBuilderScope This => this; protected override Lifetime CollectionLifetime => Lifetime.Scope; @@ -468,10 +459,6 @@ namespace Umbraco.Tests.Composing // ReSharper disable once ClassNeverInstantiated.Local private class TestCollectionBuilderWeighted : WeightedCollectionBuilderBase { - public TestCollectionBuilderWeighted(IContainer container) - : base(container) - { } - protected override TestCollectionBuilderWeighted This => this; } diff --git a/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs b/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs index e0dde277f9..3d0a9602a2 100644 --- a/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs +++ b/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Components; using Umbraco.Core.Composing; namespace Umbraco.Tests.Composing @@ -33,8 +34,9 @@ namespace Umbraco.Tests.Composing public void LazyCollectionBuilderHandlesTypes() { var container = CreateContainer(); + var composition = new Composition(container, RuntimeLevel.Run); - container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Add() .Add() .Add() @@ -56,8 +58,9 @@ namespace Umbraco.Tests.Composing public void LazyCollectionBuilderHandlesProducers() { var container = CreateContainer(); + var composition = new Composition(container, RuntimeLevel.Run); - container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Add(() => new[] { typeof(TransientObject3), typeof(TransientObject2) }) .Add(() => new[] { typeof(TransientObject3), typeof(TransientObject2) }) .Add(() => new[] { typeof(TransientObject1) }); @@ -78,8 +81,9 @@ namespace Umbraco.Tests.Composing public void LazyCollectionBuilderHandlesTypesAndProducers() { var container = CreateContainer(); + var composition = new Composition(container, RuntimeLevel.Run); - container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Add() .Add() .Add() @@ -101,8 +105,9 @@ namespace Umbraco.Tests.Composing public void LazyCollectionBuilderThrowsOnIllegalTypes() { var container = CreateContainer(); + var composition = new Composition(container, RuntimeLevel.Run); - container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Add() // illegal, does not implement the interface! @@ -122,8 +127,9 @@ namespace Umbraco.Tests.Composing public void LazyCollectionBuilderCanExcludeTypes() { var container = CreateContainer(); + var composition = new Composition(container, RuntimeLevel.Run); - container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Add() .Add(() => new[] { typeof(TransientObject3), typeof(TransientObject2), typeof(TransientObject1) }) .Exclude(); @@ -162,10 +168,6 @@ namespace Umbraco.Tests.Composing // ReSharper disable once ClassNeverInstantiated.Local private class TestCollectionBuilder : LazyCollectionBuilderBase { - public TestCollectionBuilder(IContainer container) - : base(container) - { } - protected override TestCollectionBuilder This => this; protected override Lifetime CollectionLifetime => Lifetime.Transient; // transient diff --git a/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs b/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs index 236d92b94e..8893b61fde 100644 --- a/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs +++ b/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs @@ -2,6 +2,8 @@ using System.Linq; using System.Xml; using NUnit.Framework; +using Umbraco.Core; +using Umbraco.Core.Components; using Umbraco.Core.Composing; using Umbraco.Core._Legacy.PackageActions; @@ -14,8 +16,9 @@ namespace Umbraco.Tests.Composing public void PackageActionCollectionBuilderWorks() { var container = Current.Container = ContainerFactory.Create(); + var composition = new Composition(container, RuntimeLevel.Run); - container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Add(() => TypeLoader.GetPackageActions()); var actions = Current.PackageActions; diff --git a/src/Umbraco.Tests/Integration/ContentEventsTests.cs b/src/Umbraco.Tests/Integration/ContentEventsTests.cs index fd48834cfe..30dfabbbdc 100644 --- a/src/Umbraco.Tests/Integration/ContentEventsTests.cs +++ b/src/Umbraco.Tests/Integration/ContentEventsTests.cs @@ -52,7 +52,7 @@ namespace Umbraco.Tests.Integration Container.Register(_ => new TestServerRegistrar()); // localhost-only Container.RegisterSingleton(); - Container.RegisterCollectionBuilder() + Composition.GetCollectionBuilder() .Add() .Add() .Add(); diff --git a/src/Umbraco.Tests/Misc/ApplicationUrlHelperTests.cs b/src/Umbraco.Tests/Misc/ApplicationUrlHelperTests.cs index ae72d996a8..f4a33f735d 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(), new Lazy(Mock.Of), new Lazy(Mock.Of), Mock.Of(), Mock.Of()); + var state = new RuntimeState(Mock.Of(), Mock.Of(), Mock.Of(), new Lazy(), new Lazy()); Assert.IsNull(state.ApplicationUrl); } @@ -46,10 +46,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(), - new Lazy(() => registrar.Object), - new Lazy(Mock.Of), settings, globalConfig.Object); + var state = new RuntimeState(Mock.Of(), settings, globalConfig.Object, new Lazy(), new Lazy(() => registrar.Object)); state.EnsureApplicationUrl(); @@ -72,7 +69,7 @@ namespace Umbraco.Tests.Misc - var state = new RuntimeState(Mock.Of(), new Lazy(Mock.Of), new Lazy(Mock.Of), settings, globalConfig.Object); + var state = new RuntimeState(Mock.Of(), settings, globalConfig.Object, new Lazy(), new Lazy(() => Mock.Of())); state.EnsureApplicationUrl(); @@ -147,7 +144,5 @@ namespace Umbraco.Tests.Misc Assert.AreEqual("httpx://whatever.com/umbraco", url); } - - } } diff --git a/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs b/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs index 2bf8aeead3..87698db400 100644 --- a/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs +++ b/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs @@ -31,7 +31,7 @@ namespace Umbraco.Tests.Models.Mapping Container.Register(_ => manifestBuilder); Func> typeListProducerList = Enumerable.Empty; - Container.GetInstance() + Composition.GetCollectionBuilder() .Clear() .Add(typeListProducerList); } diff --git a/src/Umbraco.Tests/Persistence/DatabaseContextTests.cs b/src/Umbraco.Tests/Persistence/DatabaseContextTests.cs index 788ee597dd..d45016ba11 100644 --- a/src/Umbraco.Tests/Persistence/DatabaseContextTests.cs +++ b/src/Umbraco.Tests/Persistence/DatabaseContextTests.cs @@ -33,7 +33,7 @@ namespace Umbraco.Tests.Persistence _sqlCeSyntaxProvider = new SqlCeSyntaxProvider(); _sqlSyntaxProviders = new[] { (ISqlSyntaxProvider) _sqlCeSyntaxProvider }; _logger = Mock.Of(); - _databaseFactory = new UmbracoDatabaseFactory(_sqlSyntaxProviders, _logger, Mock.Of()); + _databaseFactory = new UmbracoDatabaseFactory(_logger, new Lazy(() => Mock.Of())); } [TearDown] @@ -76,7 +76,7 @@ namespace Umbraco.Tests.Persistence } // re-create the database factory and database context with proper connection string - _databaseFactory = new UmbracoDatabaseFactory(connString, Constants.DbProviderNames.SqlCe, _sqlSyntaxProviders, _logger, Mock.Of()); + _databaseFactory = new UmbracoDatabaseFactory(connString, Constants.DbProviderNames.SqlCe, _logger, new Lazy(() => Mock.Of())); // create application context //var appCtx = new ApplicationContext( diff --git a/src/Umbraco.Tests/Persistence/FaultHandling/ConnectionRetryTest.cs b/src/Umbraco.Tests/Persistence/FaultHandling/ConnectionRetryTest.cs index bff43d5ea8..6aba8187f2 100644 --- a/src/Umbraco.Tests/Persistence/FaultHandling/ConnectionRetryTest.cs +++ b/src/Umbraco.Tests/Persistence/FaultHandling/ConnectionRetryTest.cs @@ -19,8 +19,7 @@ namespace Umbraco.Tests.Persistence.FaultHandling { const string connectionString = @"server=.\SQLEXPRESS;database=EmptyForTest;user id=x;password=umbraco"; const string providerName = Constants.DbProviderNames.SqlServer; - var sqlSyntax = new[] { new SqlServerSyntaxProvider(new Lazy(() => null)) }; - var factory = new UmbracoDatabaseFactory(connectionString, providerName, sqlSyntax, Mock.Of(), Mock.Of()); + var factory = new UmbracoDatabaseFactory(connectionString, providerName, Mock.Of(), new Lazy(() => Mock.Of())); using (var database = factory.CreateDatabase()) { @@ -34,8 +33,7 @@ namespace Umbraco.Tests.Persistence.FaultHandling { const string connectionString = @"server=.\SQLEXPRESS;database=EmptyForTest;user id=umbraco;password=umbraco"; const string providerName = Constants.DbProviderNames.SqlServer; - var sqlSyntax = new[] { new SqlServerSyntaxProvider(new Lazy(() => null)) }; - var factory = new UmbracoDatabaseFactory(connectionString, providerName, sqlSyntax, Mock.Of(), Mock.Of()); + var factory = new UmbracoDatabaseFactory(connectionString, providerName, Mock.Of(), new Lazy(() => Mock.Of())); using (var database = factory.CreateDatabase()) { diff --git a/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs index 0e8f1e9e16..1f0036d874 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs @@ -670,7 +670,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void AliasRegexTest() { - var regex = new SqlServerSyntaxProvider(new Lazy(() => null)).AliasRegex; + var regex = new SqlServerSyntaxProvider().AliasRegex; Assert.AreEqual(@"(\[\w+]\.\[\w+])\s+AS\s+(\[\w+])", regex.ToString()); const string sql = "SELECT [table].[column1] AS [alias1], [table].[column2] AS [alias2] FROM [table];"; var matches = regex.Matches(sql); diff --git a/src/Umbraco.Tests/Persistence/SyntaxProvider/SqlCeSyntaxProviderTests.cs b/src/Umbraco.Tests/Persistence/SyntaxProvider/SqlCeSyntaxProviderTests.cs index df842dc43c..557de9eb11 100644 --- a/src/Umbraco.Tests/Persistence/SyntaxProvider/SqlCeSyntaxProviderTests.cs +++ b/src/Umbraco.Tests/Persistence/SyntaxProvider/SqlCeSyntaxProviderTests.cs @@ -74,7 +74,7 @@ WHERE (([umbracoNode].[nodeObjectType] = @0))) x)".Replace(Environment.NewLine, [Test] public void Format_SqlServer_NonClusteredIndexDefinition_AddsNonClusteredDirective() { - var sqlSyntax = new SqlServerSyntaxProvider(new Lazy(() => null)); + var sqlSyntax = new SqlServerSyntaxProvider(); var indexDefinition = CreateIndexDefinition(); indexDefinition.IndexType = IndexTypes.NonClustered; @@ -86,7 +86,7 @@ WHERE (([umbracoNode].[nodeObjectType] = @0))) x)".Replace(Environment.NewLine, [Test] public void Format_SqlServer_NonClusteredIndexDefinition_UsingIsClusteredFalse_AddsClusteredDirective() { - var sqlSyntax = new SqlServerSyntaxProvider(new Lazy(() => null)); + var sqlSyntax = new SqlServerSyntaxProvider(); var indexDefinition = CreateIndexDefinition(); indexDefinition.IndexType = IndexTypes.Clustered; @@ -99,7 +99,7 @@ WHERE (([umbracoNode].[nodeObjectType] = @0))) x)".Replace(Environment.NewLine, public void CreateIndexBuilder_SqlServer_NonClustered_CreatesNonClusteredIndex() { var logger = Mock.Of(); - var sqlSyntax = new SqlServerSyntaxProvider(new Lazy(() => null)); + var sqlSyntax = new SqlServerSyntaxProvider(); var db = new TestDatabase(DatabaseType.SqlServer2005, sqlSyntax); var context = new MigrationContext(db, logger); @@ -120,7 +120,7 @@ WHERE (([umbracoNode].[nodeObjectType] = @0))) x)".Replace(Environment.NewLine, public void CreateIndexBuilder_SqlServer_Unique_CreatesUniqueNonClusteredIndex() { var logger = Mock.Of(); - var sqlSyntax = new SqlServerSyntaxProvider(new Lazy(() => null)); + var sqlSyntax = new SqlServerSyntaxProvider(); var db = new TestDatabase(DatabaseType.SqlServer2005, sqlSyntax); var context = new MigrationContext(db, logger); @@ -141,7 +141,7 @@ WHERE (([umbracoNode].[nodeObjectType] = @0))) x)".Replace(Environment.NewLine, public void CreateIndexBuilder_SqlServer_Unique_CreatesUniqueNonClusteredIndex_Multi_Columnn() { var logger = Mock.Of(); - var sqlSyntax = new SqlServerSyntaxProvider(new Lazy(() => null)); + var sqlSyntax = new SqlServerSyntaxProvider(); var db = new TestDatabase(DatabaseType.SqlServer2005, sqlSyntax); var context = new MigrationContext(db, logger); @@ -162,7 +162,7 @@ WHERE (([umbracoNode].[nodeObjectType] = @0))) x)".Replace(Environment.NewLine, public void CreateIndexBuilder_SqlServer_Clustered_CreatesClusteredIndex() { var logger = Mock.Of(); - var sqlSyntax = new SqlServerSyntaxProvider(new Lazy(() => null)); + var sqlSyntax = new SqlServerSyntaxProvider(); var db = new TestDatabase(DatabaseType.SqlServer2005, sqlSyntax); var context = new MigrationContext(db, logger); diff --git a/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs b/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs index 7e56ad61a8..de27c30b1d 100644 --- a/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs +++ b/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs @@ -5,6 +5,7 @@ using Newtonsoft.Json; using NUnit.Framework; using Newtonsoft.Json.Linq; using Umbraco.Core; +using Umbraco.Core.Components; using Umbraco.Core.Composing; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; @@ -67,8 +68,9 @@ namespace Umbraco.Tests.PropertyEditors try { var container = Current.Container = ContainerFactory.Create(); + var composition = new Composition(container, RuntimeLevel.Run); - container.RegisterCollectionBuilder(); + composition.GetCollectionBuilder(); var logger = Mock.Of(); var scheme = Mock.Of(); diff --git a/src/Umbraco.Tests/Published/ConvertersTests.cs b/src/Umbraco.Tests/Published/ConvertersTests.cs index c0ae68d7d5..0e65f5723f 100644 --- a/src/Umbraco.Tests/Published/ConvertersTests.cs +++ b/src/Umbraco.Tests/Published/ConvertersTests.cs @@ -4,6 +4,7 @@ using System.Linq; using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Components; using Umbraco.Core.Composing; using Umbraco.Core.Logging; using Umbraco.Core.Models; @@ -172,9 +173,9 @@ namespace Umbraco.Tests.Published { Current.Reset(); var container = Current.Container = ContainerFactory.Create(); + var composition = new Composition(container, RuntimeLevel.Run); - - Current.Container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Append() .Append(); diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs index a1df9e3720..80fb02ec0f 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs @@ -23,10 +23,8 @@ namespace Umbraco.Tests.PublishedContent // fixme - what about the if (PropertyValueConvertersResolver.HasCurrent == false) ?? // can we risk double - registering and then, what happens? - var builder = Container.TryGetInstance() - ?? Container.RegisterCollectionBuilder(); - - builder.Clear() + Composition.GetCollectionBuilder() + .Clear() .Append() .Append() .Append(); diff --git a/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs index e9d133c901..9d603a9569 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs @@ -39,7 +39,7 @@ namespace Umbraco.Tests.PublishedContent { base.Compose(); - Container.GetInstance() + Composition.GetCollectionBuilder() .Clear() .Append(); } diff --git a/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs b/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs index e26db55ace..7fef0147e7 100644 --- a/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs +++ b/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs @@ -32,7 +32,8 @@ namespace Umbraco.Tests.Routing //create the module var logger = Mock.Of(); var globalSettings = TestObjects.GetGlobalSettings(); - var runtime = new RuntimeState(logger, new Lazy(), new Lazy(), Mock.Of(), globalSettings); + var runtime = new RuntimeState(logger, Mock.Of(), globalSettings, + new Lazy(), new Lazy()); _module = new UmbracoInjectedModule ( diff --git a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs index 68746350f6..907de9ccde 100644 --- a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs +++ b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs @@ -74,9 +74,11 @@ namespace Umbraco.Tests.Runtimes return new DebugDiagnosticsLogger(); } - public override void Compose(IContainer container) + public override void Compose(Composition composition) { - base.Compose(container); + base.Compose(composition); + + var container = composition.Container; // the application's profiler and profiling logger are // registered by CoreRuntime.Compose() but can be @@ -100,7 +102,7 @@ namespace Umbraco.Tests.Runtimes // pretend we have the proper migration // else BootFailedException because our mock IUmbracoDatabaseFactory does not provide databases - protected override bool EnsureUmbracoUpgradeState(IUmbracoDatabaseFactory databaseFactory, ILogger logger) + protected override bool EnsureUmbracoUpgradeState(IUmbracoDatabaseFactory databaseFactory) { return true; } @@ -122,7 +124,7 @@ namespace Umbraco.Tests.Runtimes // runs with only one single component // UmbracoCoreComponent will be force-added too // and that's it - protected override IEnumerable GetComponentTypes() + protected override IEnumerable GetComponentTypes(TypeLoader typeLoader) { return new[] { typeof(TestComponent) }; } diff --git a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs index 56987416a4..486cf55769 100644 --- a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs @@ -3,6 +3,7 @@ using System.Linq; using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Components; using Umbraco.Core.Events; using Umbraco.Core.Models; using Umbraco.Core.IO; @@ -30,11 +31,12 @@ namespace Umbraco.Tests.Scoping DoThing3 = null; var container = Current.Container = ContainerFactory.Create(); + var composition = new Composition(container, RuntimeLevel.Run); _testObjects = new TestObjects(container); Current.Container.RegisterSingleton(factory => new FileSystems(container, factory.TryGetInstance())); - Current.Container.RegisterCollectionBuilder(); + composition.GetCollectionBuilder(); SettingsForTests.Reset(); // ensure we have configuration } diff --git a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs index 9308e9bbaf..b25b7eed42 100644 --- a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs @@ -46,7 +46,7 @@ namespace Umbraco.Tests.Scoping // so doing all this mess Container.RegisterSingleton(); Container.RegisterSingleton(f => Mock.Of()); - Container.RegisterCollectionBuilder() + Composition.GetCollectionBuilder() .Add(f => f.TryGetInstance().GetCacheRefreshers()); } diff --git a/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs b/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs index 4f6fafbbbf..3d281575fb 100644 --- a/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs @@ -32,7 +32,7 @@ namespace Umbraco.Tests.Scoping // so doing all this mess Container.RegisterSingleton(); Container.RegisterSingleton(f => Mock.Of()); - Container.RegisterCollectionBuilder() + Composition.GetCollectionBuilder() .Add(f => f.TryGetInstance().GetCacheRefreshers()); } diff --git a/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs b/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs index 65bc5762c7..2cfadb9408 100644 --- a/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs @@ -34,7 +34,7 @@ namespace Umbraco.Tests.Scoping // so doing all this mess Container.RegisterSingleton(); Container.RegisterSingleton(f => Mock.Of()); - Container.RegisterCollectionBuilder() + Composition.GetCollectionBuilder() .Add(f => f.TryGetInstance().GetCacheRefreshers()); } diff --git a/src/Umbraco.Tests/Services/ContentServiceTests.cs b/src/Umbraco.Tests/Services/ContentServiceTests.cs index 489be00a14..31f0f0308b 100644 --- a/src/Umbraco.Tests/Services/ContentServiceTests.cs +++ b/src/Umbraco.Tests/Services/ContentServiceTests.cs @@ -57,8 +57,7 @@ namespace Umbraco.Tests.Services { base.Compose(); - // fixme - do it differently - Container.Register(factory => factory.GetInstance().TextService); + Container.RegisterSingleton(factory => Mock.Of()); } /// diff --git a/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs b/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs index c28d4f7955..b934686c87 100644 --- a/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs +++ b/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs @@ -37,7 +37,7 @@ namespace Umbraco.Tests.Services // pfew - see note in ScopedNuCacheTests? Container.RegisterSingleton(); Container.RegisterSingleton(f => Mock.Of()); - Container.RegisterCollectionBuilder() + Composition.GetCollectionBuilder() .Add(f => f.TryGetInstance().GetCacheRefreshers()); } @@ -770,4 +770,4 @@ namespace Umbraco.Tests.Services "{'properties':{'value11':[{'culture':'','seg':'','val':'v11'}],'value12':[{'culture':'','seg':'','val':'v12'}],'value31':[{'culture':'','seg':'','val':'v31'}],'value32':[{'culture':'','seg':'','val':'v32'}]},'cultureData':"); } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs b/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs index b9b410206e..05793e85dd 100644 --- a/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs +++ b/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs @@ -49,7 +49,7 @@ namespace Umbraco.Tests.Services.Importing // pollute everything, they are ignored by the type finder and explicitely // added to the editors collection - Container.GetInstance() + Composition.GetCollectionBuilder() .Add() .Add(); } diff --git a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs index 4314af38b5..c8a2219c3f 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs @@ -3,6 +3,7 @@ using NPoco; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; +using Umbraco.Core.Components; using Umbraco.Core.Logging; using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Persistence.SqlSyntax; @@ -33,6 +34,7 @@ namespace Umbraco.Tests.TestHelpers var sqlSyntax = new SqlCeSyntaxProvider(); var container = Current.Container = ContainerFactory.Create(); + var composition = new Composition(container, RuntimeLevel.Run); container.RegisterSingleton(factory => Mock.Of()); container.RegisterSingleton(factory => Mock.Of()); @@ -44,7 +46,7 @@ namespace Umbraco.Tests.TestHelpers false); container.RegisterInstance(pluginManager); - container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Add(() => Current.TypeLoader.GetAssignedMapperTypes()); Mappers = container.GetInstance(); diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects.cs b/src/Umbraco.Tests/TestHelpers/TestObjects.cs index 9f16141c2f..c965a71a70 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects.cs @@ -37,22 +37,6 @@ namespace Umbraco.Tests.TestHelpers _container = container; } - /// - /// Gets the default ISqlSyntaxProvider objects. - /// - /// A logger. - /// A (lazy) scope provider. - /// The default ISqlSyntaxProvider objects. - public IEnumerable GetDefaultSqlSyntaxProviders(ILogger logger, Lazy lazyScopeProvider = null) - { - return new ISqlSyntaxProvider[] - { - new MySqlSyntaxProvider(logger), - new SqlCeSyntaxProvider(), - new SqlServerSyntaxProvider(lazyScopeProvider ?? new Lazy(() => null)) - }; - } - /// /// Gets an UmbracoDatabase. /// @@ -77,7 +61,7 @@ namespace Umbraco.Tests.TestHelpers /// that can begin a transaction. public UmbracoDatabase GetUmbracoSqlServerDatabase(ILogger logger) { - var syntax = new SqlServerSyntaxProvider(new Lazy(() => null)); // do NOT try to get the server's version! + var syntax = new SqlServerSyntaxProvider(); // do NOT try to get the server's version! var connection = GetDbConnection(); var sqlContext = new SqlContext(syntax, DatabaseType.SqlServer2008, Mock.Of()); return new UmbracoDatabase(connection, sqlContext, logger); @@ -241,7 +225,7 @@ namespace Umbraco.Tests.TestHelpers //mappersBuilder.AddCore(); //var mappers = mappersBuilder.CreateCollection(); var mappers = Current.Container.GetInstance(); - databaseFactory = new UmbracoDatabaseFactory(Constants.System.UmbracoConnectionName, GetDefaultSqlSyntaxProviders(logger), logger, mappers); + databaseFactory = new UmbracoDatabaseFactory(Constants.System.UmbracoConnectionName, logger, new Lazy(() => mappers)); } fileSystems = fileSystems ?? new FileSystems(Current.Container, logger); diff --git a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs index d0dfcc8c2e..fa61381eed 100644 --- a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs +++ b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs @@ -76,7 +76,7 @@ namespace Umbraco.Tests.TestHelpers Container.Register(factory => PublishedSnapshotService); Container.Register(factory => DefaultCultureAccessor); - Container.GetInstance() + Composition.GetCollectionBuilder() .Clear() .Add(f => f.GetInstance().GetDataEditors()); @@ -85,10 +85,9 @@ namespace Umbraco.Tests.TestHelpers if (Options.Database == UmbracoTestOptions.Database.None) return TestObjects.GetDatabaseFactoryMock(); - var sqlSyntaxProviders = new[] { new SqlCeSyntaxProvider() }; var logger = f.GetInstance(); var mappers = f.GetInstance(); - var factory = new UmbracoDatabaseFactory(GetDbConnectionString(), GetDbProviderName(), sqlSyntaxProviders, logger, mappers); + var factory = new UmbracoDatabaseFactory(GetDbConnectionString(), GetDbProviderName(), logger, new Lazy(() => mappers)); factory.ResetForTests(); return factory; }); diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index 45a4bc5917..ee5768d499 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -76,6 +76,8 @@ namespace Umbraco.Tests.Testing // test feature, and no test "base" class should be. only actual test feature classes // should be marked with that attribute. + protected Composition Composition { get; private set; } + protected IContainer Container { get; private set; } protected UmbracoTestAttribute Options { get; private set; } @@ -116,6 +118,7 @@ namespace Umbraco.Tests.Testing Reset(); Container = Current.Container = ContainerFactory.Create(); + Composition = new Composition(Container, RuntimeLevel.Run); TestObjects = new TestObjects(Container); @@ -189,7 +192,7 @@ namespace Umbraco.Tests.Testing // web Container.Register(_ => Umbraco.Web.Composing.Current.UmbracoContextAccessor); Container.RegisterSingleton(); - Container.RegisterCollectionBuilder(); + Composition.GetCollectionBuilder(); Container.Register(); Container.Register(); } @@ -202,14 +205,14 @@ namespace Umbraco.Tests.Testing Container.RegisterSingleton(f => runtimeStateMock.Object); // ah... - Container.RegisterCollectionBuilder(); - Container.RegisterCollectionBuilder(); + Composition.GetCollectionBuilder(); + Composition.GetCollectionBuilder(); Container.RegisterSingleton(); Container.RegisterSingleton(); // register empty content apps collection - Container.RegisterCollectionBuilder(); + Composition.GetCollectionBuilder(); } protected virtual void ComposeCacheHelper() @@ -307,20 +310,17 @@ namespace Umbraco.Tests.Testing Container.RegisterSingleton(); // register application stuff (database factory & context, services...) - Container.RegisterCollectionBuilder() - .AddCore(); + Composition.GetCollectionBuilder() + .AddCoreMappers(); Container.RegisterSingleton(_ => new TransientEventMessagesFactory()); - var sqlSyntaxProviders = TestObjects.GetDefaultSqlSyntaxProviders(Logger); - Container.RegisterSingleton(_ => sqlSyntaxProviders.OfType().First()); Container.RegisterSingleton(f => new UmbracoDatabaseFactory( Constants.System.UmbracoConnectionName, - sqlSyntaxProviders, Logger, - Mock.Of())); + new Lazy(() => Mock.Of()))); Container.RegisterSingleton(f => f.TryGetInstance().SqlContext); - Container.RegisterCollectionBuilder(); // empty + Composition.GetCollectionBuilder(); // empty Container.RegisterSingleton(factory => TestObjects.GetScopeProvider(factory.TryGetInstance(), factory.TryGetInstance(), factory.TryGetInstance())); @@ -333,12 +333,11 @@ namespace Umbraco.Tests.Testing Container.RegisterSingleton(); // somehow property editor ends up wanting this - Container.RegisterCollectionBuilder(); + Composition.GetCollectionBuilder(); Container.RegisterSingleton(); // note - don't register collections, use builders - Container.RegisterCollectionBuilder(); - var temp = Container.GetInstance(); + Composition.GetCollectionBuilder(); Container.RegisterSingleton(); Container.RegisterSingleton(); } diff --git a/src/Umbraco.Web/Actions/ActionCollectionBuilder.cs b/src/Umbraco.Web/Actions/ActionCollectionBuilder.cs index 027a3fcd9b..8400e02271 100644 --- a/src/Umbraco.Web/Actions/ActionCollectionBuilder.cs +++ b/src/Umbraco.Web/Actions/ActionCollectionBuilder.cs @@ -7,10 +7,6 @@ namespace Umbraco.Web.Actions { internal class ActionCollectionBuilder : LazyCollectionBuilderBase { - public ActionCollectionBuilder(IContainer container) - : base(container) - { } - protected override ActionCollectionBuilder This => this; protected override IEnumerable CreateItems() diff --git a/src/Umbraco.Web/ContentApps/ContentAppDefinitionCollectionBuilder.cs b/src/Umbraco.Web/ContentApps/ContentAppDefinitionCollectionBuilder.cs index 6fcaea87a3..8c47e0f640 100644 --- a/src/Umbraco.Web/ContentApps/ContentAppDefinitionCollectionBuilder.cs +++ b/src/Umbraco.Web/ContentApps/ContentAppDefinitionCollectionBuilder.cs @@ -9,10 +9,6 @@ namespace Umbraco.Web.ContentApps { public class ContentAppDefinitionCollectionBuilder : OrderedCollectionBuilderBase { - public ContentAppDefinitionCollectionBuilder(IContainer container) - : base(container) - { } - protected override ContentAppDefinitionCollectionBuilder This => this; // need to inject dependencies in the collection, so override creation diff --git a/src/Umbraco.Web/Editors/EditorValidatorCollectionBuilder.cs b/src/Umbraco.Web/Editors/EditorValidatorCollectionBuilder.cs index 3189f2e71f..b3b7bab1a5 100644 --- a/src/Umbraco.Web/Editors/EditorValidatorCollectionBuilder.cs +++ b/src/Umbraco.Web/Editors/EditorValidatorCollectionBuilder.cs @@ -4,10 +4,6 @@ namespace Umbraco.Web.Editors { internal class EditorValidatorCollectionBuilder : LazyCollectionBuilderBase { - public EditorValidatorCollectionBuilder(IContainer container) - : base(container) - { } - protected override EditorValidatorCollectionBuilder This => this; } } diff --git a/src/Umbraco.Web/HealthCheck/HealthCheckNotificationMethodCollectionBuilder.cs b/src/Umbraco.Web/HealthCheck/HealthCheckNotificationMethodCollectionBuilder.cs index 76a93fe217..b78c188660 100644 --- a/src/Umbraco.Web/HealthCheck/HealthCheckNotificationMethodCollectionBuilder.cs +++ b/src/Umbraco.Web/HealthCheck/HealthCheckNotificationMethodCollectionBuilder.cs @@ -5,10 +5,6 @@ namespace Umbraco.Web.HealthCheck { internal class HealthCheckNotificationMethodCollectionBuilder : LazyCollectionBuilderBase { - public HealthCheckNotificationMethodCollectionBuilder(IContainer container) - : base(container) - { } - protected override HealthCheckNotificationMethodCollectionBuilder This => this; } } diff --git a/src/Umbraco.Web/HealthCheck/HeathCheckCollectionBuilder.cs b/src/Umbraco.Web/HealthCheck/HeathCheckCollectionBuilder.cs index 7e600d9238..e616ba49ae 100644 --- a/src/Umbraco.Web/HealthCheck/HeathCheckCollectionBuilder.cs +++ b/src/Umbraco.Web/HealthCheck/HeathCheckCollectionBuilder.cs @@ -4,10 +4,6 @@ namespace Umbraco.Web.HealthCheck { public class HealthCheckCollectionBuilder : LazyCollectionBuilderBase { - public HealthCheckCollectionBuilder(IContainer container) - : base(container) - { } - protected override HealthCheckCollectionBuilder This => this; // note: in v7 they were per-request, not sure why? diff --git a/src/Umbraco.Web/Mvc/FilteredControllerFactoryCollectionBuilder.cs b/src/Umbraco.Web/Mvc/FilteredControllerFactoryCollectionBuilder.cs index 4ec48bac3f..2c4182beac 100644 --- a/src/Umbraco.Web/Mvc/FilteredControllerFactoryCollectionBuilder.cs +++ b/src/Umbraco.Web/Mvc/FilteredControllerFactoryCollectionBuilder.cs @@ -4,10 +4,6 @@ namespace Umbraco.Web.Mvc { public class FilteredControllerFactoryCollectionBuilder : OrderedCollectionBuilderBase { - public FilteredControllerFactoryCollectionBuilder(IContainer container) - : base(container) - { } - protected override FilteredControllerFactoryCollectionBuilder This => this; } } diff --git a/src/Umbraco.Web/Routing/ContentFinderCollectionBuilder.cs b/src/Umbraco.Web/Routing/ContentFinderCollectionBuilder.cs index 47186dbb74..401a7daf43 100644 --- a/src/Umbraco.Web/Routing/ContentFinderCollectionBuilder.cs +++ b/src/Umbraco.Web/Routing/ContentFinderCollectionBuilder.cs @@ -4,10 +4,6 @@ namespace Umbraco.Web.Routing { public class ContentFinderCollectionBuilder : OrderedCollectionBuilderBase { - public ContentFinderCollectionBuilder(IContainer container) - : base(container) - { } - protected override ContentFinderCollectionBuilder This => this; } } diff --git a/src/Umbraco.Web/Routing/UrlProviderCollectionBuilder.cs b/src/Umbraco.Web/Routing/UrlProviderCollectionBuilder.cs index d66a7554b8..06f2728f4c 100644 --- a/src/Umbraco.Web/Routing/UrlProviderCollectionBuilder.cs +++ b/src/Umbraco.Web/Routing/UrlProviderCollectionBuilder.cs @@ -4,10 +4,6 @@ namespace Umbraco.Web.Routing { public class UrlProviderCollectionBuilder : OrderedCollectionBuilderBase { - public UrlProviderCollectionBuilder(IContainer container) - : base(container) - { } - protected override UrlProviderCollectionBuilder This => this; } } diff --git a/src/Umbraco.Web/Runtime/WebRuntime.cs b/src/Umbraco.Web/Runtime/WebRuntime.cs index 342e4aede4..52bf980853 100644 --- a/src/Umbraco.Web/Runtime/WebRuntime.cs +++ b/src/Umbraco.Web/Runtime/WebRuntime.cs @@ -1,5 +1,6 @@ using System.Web; using Umbraco.Core.Cache; +using Umbraco.Core.Components; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; @@ -51,21 +52,23 @@ namespace Umbraco.Web.Runtime } /// - public override void Compose(IContainer container) + public override void Compose(Composition composition) { + base.Compose(composition); + + var container = composition.Container; + // some components may want to initialize with the UmbracoApplicationBase // well, they should not - we should not do this // TODO remove this eventually. container.RegisterInstance(_umbracoApplication); - base.Compose(container); + } - container.Register(); + #region Getters - // replace CoreRuntime's IProfiler registration - container.RegisterSingleton(_ => _webProfiler); + protected override IProfiler GetProfiler() => new WebProfiler(); - // replace CoreRuntime's CacheHelper registration - container.RegisterSingleton(_ => new CacheHelper( + protected override CacheHelper GetAppCaches() => new CacheHelper( // we need to have the dep clone runtime cache provider to ensure // all entities are cached properly (cloned in and cloned out) new DeepCloneRuntimeCacheProvider(new HttpRuntimeCacheProvider(HttpRuntime.Cache)), @@ -75,26 +78,7 @@ namespace Umbraco.Web.Runtime new IsolatedRuntimeCache(type => // we need to have the dep clone runtime cache provider to ensure // all entities are cached properly (cloned in and cloned out) - new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider())))); - - container.RegisterSingleton(); // required for hybrid accessors - } - - #region Getters - - //protected override IProfiler GetProfiler() => new WebProfiler(); - - //protected override CacheHelper GetApplicationCache() => new CacheHelper( - // // we need to have the dep clone runtime cache provider to ensure - // // all entities are cached properly (cloned in and cloned out) - // new DeepCloneRuntimeCacheProvider(new HttpRuntimeCacheProvider(HttpRuntime.Cache)), - // new StaticCacheProvider(), - // // we need request based cache when running in web-based context - // new HttpRequestCacheProvider(), - // new IsolatedRuntimeCache(type => - // // we need to have the dep clone runtime cache provider to ensure - // // all entities are cached properly (cloned in and cloned out) - // new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()))); + new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()))); #endregion } diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs index 24a84905e3..3705eea086 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs @@ -64,109 +64,115 @@ namespace Umbraco.Web.Runtime { base.Compose(composition); - composition.Container.ComposeWebMappingProfiles(); + var container = composition.Container; + + container.Register(); + + container.RegisterSingleton(); // required for hybrid accessors + + container.ComposeWebMappingProfiles(); //register the install components //NOTE: i tried to not have these registered if we weren't installing or upgrading but post install when the site restarts //it still needs to use the install controller so we can't do that - composition.Container.ComposeInstaller(); + container.ComposeInstaller(); // register membership stuff - composition.Container.Register(factory => Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider()); - composition.Container.Register(factory => Roles.Enabled ? Roles.Provider : new MembersRoleProvider(factory.GetInstance())); - composition.Container.Register(); + container.Register(factory => Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider()); + container.Register(factory => Roles.Enabled ? Roles.Provider : new MembersRoleProvider(factory.GetInstance())); + container.Register(); // register accessors for cultures - composition.Container.RegisterSingleton(); - composition.Container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); - var typeLoader = composition.Container.GetInstance(); - var logger = composition.Container.GetInstance(); - var proflog = composition.Container.GetInstance(); + var typeLoader = container.GetInstance(); + var logger = container.GetInstance(); + var proflog = container.GetInstance(); // register the http context and umbraco context accessors // we *should* use the HttpContextUmbracoContextAccessor, however there are cases when // we have no http context, eg when booting Umbraco or in background threads, so instead // let's use an hybrid accessor that can fall back to a ThreadStatic context. - composition.Container.RegisterSingleton(); + container.RegisterSingleton(); // register a per-request HttpContextBase object // is per-request so only one wrapper is created per request - composition.Container.Register(factory => new HttpContextWrapper(factory.GetInstance().HttpContext), Lifetime.Request); + container.Register(factory => new HttpContextWrapper(factory.GetInstance().HttpContext), Lifetime.Request); // register the published snapshot accessor - the "current" published snapshot is in the umbraco context - composition.Container.RegisterSingleton(); + container.RegisterSingleton(); // we should stop injecting UmbracoContext and always inject IUmbracoContextAccessor, however at the moment // there are tons of places (controllers...) which require UmbracoContext in their ctor - so let's register // a way to inject the UmbracoContext - and register it per-request to be more efficient //TODO: stop doing this - composition.Container.Register(factory => factory.GetInstance().UmbracoContext, Lifetime.Request); + container.Register(factory => factory.GetInstance().UmbracoContext, Lifetime.Request); // register the umbraco helper - composition.Container.RegisterSingleton(); + container.RegisterSingleton(); // register distributed cache - composition.Container.RegisterSingleton(f => new DistributedCache()); + container.RegisterSingleton(f => new DistributedCache()); // replace some services - composition.Container.RegisterSingleton(); - composition.Container.RegisterSingleton(); - composition.Container.RegisterSingleton(); - composition.Container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); - composition.Container.RegisterSingleton(factory => ExamineManager.Instance); + container.RegisterSingleton(factory => ExamineManager.Instance); // configure the container for web - composition.Container.ConfigureForWeb(); - composition.Container.ComposeMvcControllers(typeLoader, GetType().Assembly); - composition.Container.ComposeApiControllers(typeLoader, GetType().Assembly); + container.ConfigureForWeb(); + container.ComposeMvcControllers(typeLoader, GetType().Assembly); + container.ComposeApiControllers(typeLoader, GetType().Assembly); - composition.Container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Add(() => typeLoader.GetTypes()); // fixme which searchable trees?! - composition.Container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Add(() => typeLoader.GetTypes()); - composition.Container.RegisterCollectionBuilder(); + composition.GetCollectionBuilder(); - composition.Container.RegisterSingleton(); + container.RegisterSingleton(); // set the default RenderMvcController Current.DefaultRenderMvcControllerType = typeof(RenderMvcController); // fixme WRONG! - composition.Container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Add(() => typeLoader.GetTypes()); var surfaceControllerTypes = new SurfaceControllerTypeCollection(typeLoader.GetSurfaceControllers()); - composition.Container.RegisterInstance(surfaceControllerTypes); + container.RegisterInstance(surfaceControllerTypes); var umbracoApiControllerTypes = new UmbracoApiControllerTypeCollection(typeLoader.GetUmbracoApiControllers()); - composition.Container.RegisterInstance(umbracoApiControllerTypes); + container.RegisterInstance(umbracoApiControllerTypes); // both TinyMceValueConverter (in Core) and RteMacroRenderingValueConverter (in Web) will be // discovered when CoreBootManager configures the converters. We HAVE to remove one of them // here because there cannot be two converters for one property editor - and we want the full // RteMacroRenderingValueConverter that converts macros, etc. So remove TinyMceValueConverter. // (the limited one, defined in Core, is there for tests) - same for others - composition.Container.GetInstance() + container.GetInstance() .Remove() .Remove() .Remove(); // add all known factories, devs can then modify this list on application // startup either by binding to events or in their own global.asax - composition.Container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Append(); - composition.Container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Append() .Append() .Append(); - composition.Container.RegisterSingleton(); + container.RegisterSingleton(); - composition.Container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() // all built-in finders in the correct order, // devs can then modify this list on application startup .Append() @@ -176,32 +182,32 @@ namespace Umbraco.Web.Runtime .Append() .Append(); - composition.Container.RegisterSingleton(); + container.RegisterSingleton(); - composition.Container.RegisterSingleton(); + container.RegisterSingleton(); // register *all* checks, except those marked [HideFromTypeFinder] of course - composition.Container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Add(() => typeLoader.GetTypes()); - composition.Container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Add(() => typeLoader.GetTypes()); // auto-register views - composition.Container.RegisterAuto(typeof(UmbracoViewPage<>)); + container.RegisterAuto(typeof(UmbracoViewPage<>)); // register published router - composition.Container.RegisterSingleton(); - composition.Container.Register(_ => UmbracoConfig.For.UmbracoSettings().WebRouting); + container.RegisterSingleton(); + container.Register(_ => UmbracoConfig.For.UmbracoSettings().WebRouting); // register preview SignalR hub - composition.Container.RegisterSingleton(_ => GlobalHost.ConnectionManager.GetHubContext()); + container.RegisterSingleton(_ => GlobalHost.ConnectionManager.GetHubContext()); // register properties fallback - composition.Container.RegisterSingleton(); + container.RegisterSingleton(); // register known content apps - composition.Container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Append() .Append() .Append(); diff --git a/src/Umbraco.Web/Search/SearchableTreeCollectionBuilder.cs b/src/Umbraco.Web/Search/SearchableTreeCollectionBuilder.cs index e64738329b..51f4b13f0a 100644 --- a/src/Umbraco.Web/Search/SearchableTreeCollectionBuilder.cs +++ b/src/Umbraco.Web/Search/SearchableTreeCollectionBuilder.cs @@ -1,24 +1,10 @@ using Umbraco.Core.Composing; -using Umbraco.Core.Services; using Umbraco.Web.Trees; namespace Umbraco.Web.Search { internal class SearchableTreeCollectionBuilder : LazyCollectionBuilderBase { - private readonly IApplicationTreeService _treeService; - - public SearchableTreeCollectionBuilder(IContainer container, IApplicationTreeService treeService) - : base(container) - { - _treeService = treeService; - } - protected override SearchableTreeCollectionBuilder This => this; - - public override SearchableTreeCollection CreateCollection() - { - return new SearchableTreeCollection(CreateItems(), _treeService); - } } } diff --git a/src/Umbraco.Web/Tour/TourFilterCollectionBuilder.cs b/src/Umbraco.Web/Tour/TourFilterCollectionBuilder.cs index f521b91f26..c5d7f7eadd 100644 --- a/src/Umbraco.Web/Tour/TourFilterCollectionBuilder.cs +++ b/src/Umbraco.Web/Tour/TourFilterCollectionBuilder.cs @@ -14,13 +14,6 @@ namespace Umbraco.Web.Tour { private readonly HashSet _instances = new HashSet(); - /// - /// Initializes a new instance of the class. - /// - public TourFilterCollectionBuilder(IContainer container) - : base(container) - { } - /// protected override IEnumerable CreateItems(/*params object[] args*/) { From 5b111f96291e3d8b6046a82daf8febe99b6d225d Mon Sep 17 00:00:00 2001 From: Stephan Date: Tue, 27 Nov 2018 10:37:33 +0100 Subject: [PATCH 098/469] More composition simplification --- .../Composers/ConfigurationComposer.cs | 9 +- .../Composers/CoreMappingProfilesComposer.cs | 6 +- .../Composers/FileSystemsComposer.cs | 10 +-- .../Composers/RepositoriesComposer.cs | 9 +- .../Composing/Composers/ServicesComposer.cs | 7 +- src/Umbraco.Core/Composing/Current.cs | 6 +- src/Umbraco.Core/IRuntime.cs | 5 ++ .../ValueConverters/GridValueConverter.cs | 2 +- src/Umbraco.Core/Runtime/CoreRuntime.cs | 51 +++++------ .../Runtime/CoreRuntimeComponent.cs | 25 ++++-- .../Sync/DatabaseServerMessenger.cs | 6 +- src/Umbraco.Examine/UmbracoContentIndexer.cs | 4 +- src/Umbraco.Examine/UmbracoExamineIndexer.cs | 14 +-- src/Umbraco.Examine/UmbracoMemberIndexer.cs | 2 +- src/Umbraco.Tests/IO/FileSystemsTests.cs | 4 +- src/Umbraco.Tests/Models/ContentTests.cs | 2 +- .../Runtimes/CoreRuntimeTests.cs | 85 ++++++++++++------- .../Scoping/ScopeFileSystemsTests.cs | 2 +- .../Services/Importing/PackageImportTests.cs | 2 +- src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 9 +- .../Composers/ControllersComposer.cs | 13 ++- .../Composing/Composers/InstallerComposer.cs | 9 +- .../Composers/WebMappingProfilesComposer.cs | 7 +- src/Umbraco.Web/Composing/Current.cs | 4 +- src/Umbraco.Web/Macros/MacroRenderer.cs | 10 +-- src/Umbraco.Web/Runtime/WebRuntime.cs | 1 - .../Runtime/WebRuntimeComponent.cs | 9 +- src/Umbraco.Web/Suspendable.cs | 12 +-- src/Umbraco.Web/UI/Controls/UmbracoControl.cs | 3 +- .../UI/Controls/UmbracoUserControl.cs | 6 +- src/Umbraco.Web/UI/Pages/BasePage.cs | 5 +- src/Umbraco.Web/UmbracoHttpHandler.cs | 5 +- src/Umbraco.Web/UmbracoWebService.cs | 2 +- 33 files changed, 199 insertions(+), 147 deletions(-) diff --git a/src/Umbraco.Core/Composing/Composers/ConfigurationComposer.cs b/src/Umbraco.Core/Composing/Composers/ConfigurationComposer.cs index 4e8f2ec65c..08b88dfc04 100644 --- a/src/Umbraco.Core/Composing/Composers/ConfigurationComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/ConfigurationComposer.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Configuration; +using Umbraco.Core.Components; +using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; namespace Umbraco.Core.Composing.Composers @@ -8,8 +9,10 @@ namespace Umbraco.Core.Composing.Composers /// public static class ConfigurationComposer { - public static IContainer ComposeConfiguration(this IContainer container) + public static Composition ComposeConfiguration(this Composition composition) { + var container = composition.Container; + container.Register(factory => UmbracoConfig.For.UmbracoSettings()); container.Register(factory => factory.GetInstance().Content); container.Register(factory => factory.GetInstance().Templates); @@ -18,7 +21,7 @@ namespace Umbraco.Core.Composing.Composers // fixme - other sections we need to add? - return container; + return composition; } } } diff --git a/src/Umbraco.Core/Composing/Composers/CoreMappingProfilesComposer.cs b/src/Umbraco.Core/Composing/Composers/CoreMappingProfilesComposer.cs index fbb653b3e9..38b15b6084 100644 --- a/src/Umbraco.Core/Composing/Composers/CoreMappingProfilesComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/CoreMappingProfilesComposer.cs @@ -1,4 +1,5 @@ using AutoMapper; +using Umbraco.Core.Components; using Umbraco.Core.Models.Identity; namespace Umbraco.Core.Composing.Composers @@ -6,10 +7,11 @@ namespace Umbraco.Core.Composing.Composers { public static class CoreMappingProfilesComposer { - public static IContainer ComposeCoreMappingProfiles(this IContainer container) + public static Composition ComposeCoreMappingProfiles(this Composition composition) { + var container = composition.Container; container.Register(); - return container; + return composition; } } } diff --git a/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs b/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs index 313e4ce97c..a1895df4e6 100644 --- a/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs @@ -1,6 +1,4 @@ -using System; -using System.Configuration; -using Umbraco.Core.Configuration; +using Umbraco.Core.Components; using Umbraco.Core.IO; using Umbraco.Core.IO.MediaPathSchemes; @@ -67,8 +65,10 @@ namespace Umbraco.Core.Composing.Composers * */ - public static IContainer ComposeFileSystems(this IContainer container) + public static Composition ComposeFileSystems(this Composition composition) { + var container = composition.Container; + // register FileSystems, which manages all filesystems // it needs to be registered (not only the interface) because it provides additional // functionality eg for scoping, and is injected in the scope provider - whereas the @@ -85,7 +85,7 @@ namespace Umbraco.Core.Composing.Composers container.RegisterFileSystem( factory => new PhysicalFileSystem("~/media")); - return container; + return composition; } } } diff --git a/src/Umbraco.Core/Composing/Composers/RepositoriesComposer.cs b/src/Umbraco.Core/Composing/Composers/RepositoriesComposer.cs index f44afe394f..d0fdf63fb9 100644 --- a/src/Umbraco.Core/Composing/Composers/RepositoriesComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/RepositoriesComposer.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Persistence.Repositories; +using Umbraco.Core.Components; +using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; namespace Umbraco.Core.Composing.Composers @@ -8,8 +9,10 @@ namespace Umbraco.Core.Composing.Composers /// public static class RepositoriesComposer { - public static IContainer ComposeRepositories(this IContainer container) + public static Composition ComposeRepositories(this Composition composition) { + var container = composition.Container; + // repositories container.RegisterSingleton(); container.RegisterSingleton(); @@ -47,7 +50,7 @@ namespace Umbraco.Core.Composing.Composers container.RegisterSingleton(); container.RegisterSingleton(); - return container; + return composition; } } } diff --git a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs index 16b824e481..2db718f0ce 100644 --- a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs @@ -2,6 +2,7 @@ using System.IO; using System.Linq; using Umbraco.Core.Cache; +using Umbraco.Core.Components; using Umbraco.Core.Events; using Umbraco.Core.IO; using Umbraco.Core.Logging; @@ -12,8 +13,10 @@ namespace Umbraco.Core.Composing.Composers { public static class ServicesComposer { - public static IContainer ComposeServices(this IContainer container) + public static Composition ComposeServices(this Composition composition) { + var container = composition.Container; + // register a transient messages factory, which will be replaced by the web // boot manager when running in a web context container.RegisterSingleton(); @@ -60,7 +63,7 @@ namespace Umbraco.Core.Composing.Composers container.RegisterSingleton(); container.RegisterSingleton(); - return container; + return composition; } private static LocalizedTextServiceFileSources SourcesFactory(IContainer container) diff --git a/src/Umbraco.Core/Composing/Current.cs b/src/Umbraco.Core/Composing/Current.cs index 7792b31dc1..17c8fcd48b 100644 --- a/src/Umbraco.Core/Composing/Current.cs +++ b/src/Umbraco.Core/Composing/Current.cs @@ -31,7 +31,7 @@ namespace Umbraco.Core.Composing private static IShortStringHelper _shortStringHelper; private static ILogger _logger; private static IProfiler _profiler; - private static ProfilingLogger _profilingLogger; + private static IProfilingLogger _profilingLogger; private static IPublishedValueFallback _publishedValueFallback; /// @@ -91,8 +91,8 @@ namespace Umbraco.Core.Composing => _profiler ?? (_profiler = _container?.TryGetInstance() ?? new LogProfiler(Logger)); - public static ProfilingLogger ProfilingLogger - => _profilingLogger ?? (_profilingLogger = _container?.TryGetInstance()) + public static IProfilingLogger ProfilingLogger + => _profilingLogger ?? (_profilingLogger = _container?.TryGetInstance()) ?? new ProfilingLogger(Logger, Profiler); public static IRuntimeState RuntimeState diff --git a/src/Umbraco.Core/IRuntime.cs b/src/Umbraco.Core/IRuntime.cs index f11bafbf2f..12a189b781 100644 --- a/src/Umbraco.Core/IRuntime.cs +++ b/src/Umbraco.Core/IRuntime.cs @@ -13,6 +13,11 @@ namespace Umbraco.Core /// The application container. void Boot(IContainer container); + /// + /// Gets the runtime state. + /// + IRuntimeState State { get; } + /// /// Terminates the runtime. /// diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/GridValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/GridValueConverter.cs index 2131764ad6..d64a89dd07 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/GridValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/GridValueConverter.cs @@ -49,7 +49,7 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters //TODO: Change all singleton access to use ctor injection in v8!!! //TODO: That would mean that property value converters would need to be request lifespan, hrm.... var gridConfig = UmbracoConfig.For.GridConfig( - Current.ProfilingLogger.Logger, + Current.ProfilingLogger, Current.ApplicationCache.RuntimeCache, new DirectoryInfo(IOHelper.MapPath(SystemDirectories.AppPlugins)), new DirectoryInfo(IOHelper.MapPath(SystemDirectories.Config)), diff --git a/src/Umbraco.Core/Runtime/CoreRuntime.cs b/src/Umbraco.Core/Runtime/CoreRuntime.cs index 2ae7c66136..d4c7d80c3d 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntime.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntime.cs @@ -6,7 +6,6 @@ using System.Web; using Umbraco.Core.Cache; using Umbraco.Core.Components; using Umbraco.Core.Composing; -using Umbraco.Core.Composing.Composers; using Umbraco.Core.Configuration; using Umbraco.Core.Exceptions; using Umbraco.Core.IO; @@ -15,7 +14,6 @@ using Umbraco.Core.Logging.Serilog; using Umbraco.Core.Migrations.Upgrade; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Mappers; -using Umbraco.Core.Scoping; using Umbraco.Core.Services.Implement; using Umbraco.Core.Sync; @@ -30,6 +28,7 @@ namespace Umbraco.Core.Runtime { private Components.Components _components; private RuntimeState _state; + private IContainer _container; /// /// Gets the logger. @@ -41,11 +40,14 @@ namespace Umbraco.Core.Runtime /// protected IProfilingLogger ProfilingLogger { get; private set; } + /// + public IRuntimeState State => _state; + /// public virtual void Boot(IContainer container) { // assign current container - Current.Container = container; + Current.Container = _container = container; // create and register the essential services // ie the bare minimum required to boot @@ -74,8 +76,9 @@ namespace Umbraco.Core.Runtime container.RegisterInstance(runtimeCache); // database factory - var databaseFactory = new UmbracoDatabaseFactory(logger, new Lazy(container.GetInstance)); - container.RegisterSingleton(factory => factory.GetInstance().SqlContext); + var databaseFactory = GetDatabaseFactory(); + container.RegisterInstance(databaseFactory); + container.RegisterSingleton(factory => databaseFactory.SqlContext); // type loader var globalSettings = UmbracoConfig.For.GlobalSettings(); @@ -92,6 +95,7 @@ namespace Umbraco.Core.Runtime }; container.RegisterInstance(_state); + // register runtime-level services Compose(composition); // the boot loader boots using a container scope, so anything that is PerScope will @@ -125,14 +129,10 @@ namespace Umbraco.Core.Runtime _components.Compose(); - // no Current.Container only Current.Factory? - //factory = register.Compile(); - - // fixme at that point we can start actually getting things from the container - // but, ideally, not before = need to detect everything we use!! - - // at that point, getting things from the container is ok - // fixme split IRegistry vs IFactory + // fixme split Container into Register and Factory + // we should have a Current.Factory not a Current.Container + // we should compile the register into a factory *now* + // using the factory before this point should just throw _components.Initialize(); } @@ -264,23 +264,7 @@ namespace Umbraco.Core.Runtime /// public virtual void Compose(Composition composition) { - var container = composition.Container; - - // compose the very essential things that are needed to bootstrap, before anything else, - // and only these things - the rest should be composed in runtime components - // FIXME should be essentially empty! move all to component! - - container.ComposeConfiguration(); - - // register persistence mappers - required by database factory so needs to be done here - // means the only place the collection can be modified is in a runtime - afterwards it - // has been frozen and it is too late - composition.GetCollectionBuilder().AddCoreMappers(); - - // register the scope provider - container.RegisterSingleton(); // implements both IScopeProvider and IScopeAccessor - container.RegisterSingleton(f => f.GetInstance()); - container.RegisterSingleton(f => f.GetInstance()); + // nothing } private RuntimeLevel DetermineRuntimeLevel2(IUmbracoDatabaseFactory databaseFactory) @@ -431,6 +415,13 @@ namespace Umbraco.Core.Runtime protected virtual string GetApplicationRootPath() => null; + /// + /// Gets the database factory. + /// + /// This is strictly internal, for tests only. + protected internal virtual IUmbracoDatabaseFactory GetDatabaseFactory() + => new UmbracoDatabaseFactory(Logger, new Lazy(_container.GetInstance)); + #endregion } } diff --git a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs index 058c2ed593..7fbdd46f36 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs @@ -16,6 +16,7 @@ using Umbraco.Core.Migrations; using Umbraco.Core.Migrations.Install; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Persistence; +using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.PropertyEditors; using Umbraco.Core.PropertyEditors.Validators; using Umbraco.Core.Scoping; @@ -33,11 +34,25 @@ namespace Umbraco.Core.Runtime { base.Compose(composition); + var container = composition.Container; + // composers - composition.Container.ComposeRepositories(); - composition.Container.ComposeServices(); - composition.Container.ComposeCoreMappingProfiles(); - composition.Container.ComposeFileSystems(); + composition + .ComposeConfiguration() + .ComposeRepositories() + .ComposeServices() + .ComposeCoreMappingProfiles() + .ComposeFileSystems(); + + // register persistence mappers - required by database factory so needs to be done here + // means the only place the collection can be modified is in a runtime - afterwards it + // has been frozen and it is too late + composition.GetCollectionBuilder().AddCoreMappers(); + + // register the scope provider + container.RegisterSingleton(); // implements both IScopeProvider and IScopeAccessor + container.RegisterSingleton(f => f.GetInstance()); + container.RegisterSingleton(f => f.GetInstance()); // register database builder // *not* a singleton, don't want to keep it around @@ -79,7 +94,7 @@ namespace Umbraco.Core.Runtime factory.GetInstance(), factory.GetInstance(), factory.GetInstance(), - factory.GetInstance(), + factory.GetInstance(), factory.GetInstance(), true, new DatabaseServerMessengerOptions())); diff --git a/src/Umbraco.Core/Sync/DatabaseServerMessenger.cs b/src/Umbraco.Core/Sync/DatabaseServerMessenger.cs index 20f9276ba1..5cfcb501e5 100644 --- a/src/Umbraco.Core/Sync/DatabaseServerMessenger.cs +++ b/src/Umbraco.Core/Sync/DatabaseServerMessenger.cs @@ -33,7 +33,7 @@ namespace Umbraco.Core.Sync private readonly IRuntimeState _runtime; private readonly ManualResetEvent _syncIdle; private readonly object _locko = new object(); - private readonly ProfilingLogger _profilingLogger; + private readonly IProfilingLogger _profilingLogger; private readonly ISqlContext _sqlContext; private readonly Lazy _distCacheFilePath; private int _lastId = -1; @@ -46,7 +46,7 @@ namespace Umbraco.Core.Sync public DatabaseServerMessengerOptions Options { get; } public DatabaseServerMessenger( - IRuntimeState runtime, IScopeProvider scopeProvider, ISqlContext sqlContext, ProfilingLogger proflog, IGlobalSettings globalSettings, + IRuntimeState runtime, IScopeProvider scopeProvider, ISqlContext sqlContext, IProfilingLogger proflog, IGlobalSettings globalSettings, bool distributedEnabled, DatabaseServerMessengerOptions options) : base(distributedEnabled) { @@ -54,7 +54,7 @@ namespace Umbraco.Core.Sync _sqlContext = sqlContext; _runtime = runtime; _profilingLogger = proflog ?? throw new ArgumentNullException(nameof(proflog)); - Logger = proflog.Logger; + Logger = proflog; Options = options ?? throw new ArgumentNullException(nameof(options)); _lastPruned = _lastSync = DateTime.UtcNow; _syncIdle = new ManualResetEvent(true); diff --git a/src/Umbraco.Examine/UmbracoContentIndexer.cs b/src/Umbraco.Examine/UmbracoContentIndexer.cs index fab9f226a4..33590d12db 100644 --- a/src/Umbraco.Examine/UmbracoContentIndexer.cs +++ b/src/Umbraco.Examine/UmbracoContentIndexer.cs @@ -75,7 +75,7 @@ namespace Umbraco.Examine IEnumerable fieldDefinitions, Directory luceneDirectory, Analyzer defaultAnalyzer, - ProfilingLogger profilingLogger, + IProfilingLogger profilingLogger, IContentService contentService, IMediaService mediaService, IUserService userService, @@ -212,7 +212,7 @@ namespace Umbraco.Examine var filtered = c.RawQuery(rawQuery); var results = searcher.Search(filtered); - ProfilingLogger.Logger.Debug(GetType(), "DeleteFromIndex with query: {Query} (found {TotalItems} results)", rawQuery, results.TotalItemCount); + ProfilingLogger.Debug(GetType(), "DeleteFromIndex with query: {Query} (found {TotalItems} results)", rawQuery, results.TotalItemCount); //need to queue a delete item for each one found foreach (var r in results) diff --git a/src/Umbraco.Examine/UmbracoExamineIndexer.cs b/src/Umbraco.Examine/UmbracoExamineIndexer.cs index a4c1fb4336..3f30a02f28 100644 --- a/src/Umbraco.Examine/UmbracoExamineIndexer.cs +++ b/src/Umbraco.Examine/UmbracoExamineIndexer.cs @@ -76,7 +76,7 @@ namespace Umbraco.Examine IEnumerable fieldDefinitions, Directory luceneDirectory, Analyzer defaultAnalyzer, - ProfilingLogger profilingLogger, + IProfilingLogger profilingLogger, IValueSetValidator validator = null, IReadOnlyDictionary> indexValueTypes = null) : base(name, fieldDefinitions, luceneDirectory, defaultAnalyzer, validator, indexValueTypes) @@ -114,7 +114,7 @@ namespace Umbraco.Examine new FieldDefinition(IconFieldName, FieldDefinitionTypes.Raw) }; - protected ProfilingLogger ProfilingLogger { get; } + protected IProfilingLogger ProfilingLogger { get; } /// /// Overridden to ensure that the umbraco system field definitions are in place @@ -162,7 +162,7 @@ namespace Umbraco.Examine /// public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config) { - ProfilingLogger.Logger.Debug(GetType(), "{IndexerName} indexer initializing", name); + ProfilingLogger.Debug(GetType(), "{IndexerName} indexer initializing", name); if (config["enableDefaultEventHandler"] != null && bool.TryParse(config["enableDefaultEventHandler"], out var enabled)) { @@ -253,7 +253,7 @@ namespace Umbraco.Examine { if (CanInitialize()) { - ProfilingLogger.Logger.Debug(GetType(), "Rebuilding index"); + ProfilingLogger.Debug(GetType(), "Rebuilding index"); using (new SafeCallContext()) { base.RebuildIndex(); @@ -334,7 +334,7 @@ namespace Umbraco.Examine /// protected override void OnIndexingError(IndexingErrorEventArgs ex) { - ProfilingLogger.Logger.Error(GetType(), ex.InnerException, ex.Message); + ProfilingLogger.Error(GetType(), ex.InnerException, ex.Message); base.OnIndexingError(ex); } @@ -359,7 +359,7 @@ namespace Umbraco.Examine } } - ProfilingLogger.Logger.Debug(GetType(), + ProfilingLogger.Debug(GetType(), "Write lucene doc id:{DocumentId}, category:{DocumentCategory}, type:{DocumentItemType}", docArgs.ValueSet.Id, docArgs.ValueSet.Category, @@ -374,7 +374,7 @@ namespace Umbraco.Examine /// protected override void AddDocument(Document doc, IndexItem item, IndexWriter writer) { - ProfilingLogger.Logger.Debug(GetType(), + ProfilingLogger.Debug(GetType(), "AddDocument {DocumentId} with type {DocumentItemType}", item.ValueSet.Id, item.ValueSet.ItemType); diff --git a/src/Umbraco.Examine/UmbracoMemberIndexer.cs b/src/Umbraco.Examine/UmbracoMemberIndexer.cs index 82bf3b9cf6..ea060693d5 100644 --- a/src/Umbraco.Examine/UmbracoMemberIndexer.cs +++ b/src/Umbraco.Examine/UmbracoMemberIndexer.cs @@ -49,7 +49,7 @@ namespace Umbraco.Examine IEnumerable fieldDefinitions, Directory luceneDirectory, Analyzer analyzer, - ProfilingLogger profilingLogger, + IProfilingLogger profilingLogger, IValueSetValidator validator, IMemberService memberService) : base(name, fieldDefinitions, luceneDirectory, analyzer, profilingLogger, validator) diff --git a/src/Umbraco.Tests/IO/FileSystemsTests.cs b/src/Umbraco.Tests/IO/FileSystemsTests.cs index 4842b3feec..c72f7949f5 100644 --- a/src/Umbraco.Tests/IO/FileSystemsTests.cs +++ b/src/Umbraco.Tests/IO/FileSystemsTests.cs @@ -4,6 +4,7 @@ using System.Text; using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Components; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Composing; using Umbraco.Core.Composing.Composers; @@ -28,13 +29,14 @@ namespace Umbraco.Tests.IO SettingsForTests.ConfigureSettings(config); _container = Current.Container = ContainerFactory.Create(); + var composition = new Composition(_container, RuntimeLevel.Run); _container.Register(_ => Mock.Of()); _container.Register(_ => Mock.Of()); _container.Register(_ => Mock.Of()); _container.RegisterSingleton(); - _container.ComposeFileSystems(); + composition.ComposeFileSystems(); // make sure we start clean // because some tests will create corrupt or weird filesystems diff --git a/src/Umbraco.Tests/Models/ContentTests.cs b/src/Umbraco.Tests/Models/ContentTests.cs index 6353224b2a..aed31ca1be 100644 --- a/src/Umbraco.Tests/Models/ContentTests.cs +++ b/src/Umbraco.Tests/Models/ContentTests.cs @@ -42,7 +42,7 @@ namespace Umbraco.Tests.Models base.Compose(); Container.Register(_ => Mock.Of()); - Container.ComposeFileSystems(); + Composition.ComposeFileSystems(); Container.Register(_ => Mock.Of()); Container.Register(_ => Mock.Of()); diff --git a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs index 907de9ccde..f92b4264ec 100644 --- a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs +++ b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Data; using System.Web.Hosting; using Examine; using Moq; @@ -7,9 +8,12 @@ using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Components; using Umbraco.Core.Composing; +using Umbraco.Core.Events; +using Umbraco.Core.Exceptions; using Umbraco.Core.Logging; using Umbraco.Core.Persistence; using Umbraco.Core.Runtime; +using Umbraco.Core.Scoping; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Stubs; using Umbraco.Web; @@ -17,13 +21,18 @@ using Umbraco.Web; namespace Umbraco.Tests.Runtimes { [TestFixture] - [Ignore("cannot work until we refactor IUmbracoDatabaseFactory vs UmbracoDatabaseFactory")] public class CoreRuntimeTests { [SetUp] public void SetUp() { TestComponent.Reset(); + + // cannot boot runtime without some configuration + var umbracoSettings = SettingsForTests.GenerateMockUmbracoSettings(); + var globalSettings = SettingsForTests.GenerateMockGlobalSettings(); + SettingsForTests.ConfigureSettings(umbracoSettings); + SettingsForTests.ConfigureSettings(globalSettings); } public void TearDown() @@ -38,12 +47,29 @@ namespace Umbraco.Tests.Runtimes { app.HandleApplicationStart(app, new EventArgs()); + var e = app.Runtime.State.BootFailedException; + var m = ""; + switch (e) + { + case null: + m = ""; + break; + case BootFailedException bfe when bfe.InnerException != null: + m = "BootFailed: " + bfe.InnerException.GetType() + " " + bfe.InnerException.Message + " " + bfe.InnerException.StackTrace; + break; + default: + m = e.GetType() + " " + e.Message + " " + e.StackTrace; + break; + } + + Assert.AreNotEqual(RuntimeLevel.BootFailed, app.Runtime.State.Level, m); Assert.IsTrue(TestComponent.Ctored); Assert.IsTrue(TestComponent.Composed); Assert.IsTrue(TestComponent.Initialized1); Assert.IsTrue(TestComponent.Initialized2); Assert.IsNotNull(TestComponent.ProfilingLogger); - Assert.IsInstanceOf(TestComponent.ProfilingLogger.Logger); + Assert.IsInstanceOf(TestComponent.ProfilingLogger); + Assert.IsInstanceOf(((ProfilingLogger) TestComponent.ProfilingLogger).Logger); // note: components are NOT disposed after boot @@ -57,42 +83,23 @@ namespace Umbraco.Tests.Runtimes // test application public class TestUmbracoApplication : UmbracoApplicationBase { + public IRuntime Runtime { get; private set; } + protected override IRuntime GetRuntime() { - return new TestRuntime(); + return Runtime = new TestRuntime(); } } // test runtime public class TestRuntime : CoreRuntime { - // the application's logger is created by the application - // through GetLogger, that custom application can override - protected override ILogger GetLogger() - { - //return Mock.Of(); - return new DebugDiagnosticsLogger(); - } - - public override void Compose(Composition composition) - { - base.Compose(composition); - - var container = composition.Container; - - // the application's profiler and profiling logger are - // registered by CoreRuntime.Compose() but can be - // overriden afterwards - they haven't been resolved yet - container.RegisterSingleton(_ => new TestProfiler()); - container.RegisterSingleton(factory => new ProfilingLogger(factory.GetInstance(), factory.GetInstance())); - - // must override the database factory - container.RegisterSingleton(_ => GetDatabaseFactory()); - } + protected override ILogger GetLogger() => new DebugDiagnosticsLogger(); + protected override IProfiler GetProfiler() => new TestProfiler(); // must override the database factory // else BootFailedException because U cannot connect to the configured db - private static IUmbracoDatabaseFactory GetDatabaseFactory() + protected internal override IUmbracoDatabaseFactory GetDatabaseFactory() { var mock = new Mock(); mock.Setup(x => x.Configured).Returns(true); @@ -107,6 +114,26 @@ namespace Umbraco.Tests.Runtimes return true; } + // because we don't even have the core runtime component, + // there are a few required stuff that we need to compose + public override void Compose(Composition composition) + { + base.Compose(composition); + + var scopeProvider = Mock.Of(); + Mock.Get(scopeProvider) + .Setup(x => x.CreateScope( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())) + .Returns(Mock.Of()); + + composition.Container.RegisterInstance(scopeProvider); + } + private MainDom _mainDom; public override void Boot(IContainer container) @@ -139,7 +166,7 @@ namespace Umbraco.Tests.Runtimes public static bool Initialized1; public static bool Initialized2; public static bool Terminated; - public static ProfilingLogger ProfilingLogger; + public static IProfilingLogger ProfilingLogger; public static void Reset() { @@ -172,7 +199,7 @@ namespace Umbraco.Tests.Runtimes Initialized2 = true; } - public void Initialize(ProfilingLogger proflog) + public void Initialize(IProfilingLogger proflog) { ProfilingLogger = proflog; } diff --git a/src/Umbraco.Tests/Scoping/ScopeFileSystemsTests.cs b/src/Umbraco.Tests/Scoping/ScopeFileSystemsTests.cs index 680eddf953..aa41bdd613 100644 --- a/src/Umbraco.Tests/Scoping/ScopeFileSystemsTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopeFileSystemsTests.cs @@ -30,7 +30,7 @@ namespace Umbraco.Tests.Scoping if (!withApplication) return; // re-register with actual media fs - Container.ComposeFileSystems(); + Composition.ComposeFileSystems(); } public override void TearDown() diff --git a/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs b/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs index 05793e85dd..49b52f4276 100644 --- a/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs +++ b/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs @@ -61,7 +61,7 @@ namespace Umbraco.Tests.Services.Importing if (!withApplication) return; // re-register with actual media fs - Container.ComposeFileSystems(); + Composition.ComposeFileSystems(); } [Test] diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index ee5768d499..969bfff4fe 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -225,8 +225,9 @@ namespace Umbraco.Tests.Testing { if (configure == false) return; - Container.ComposeCoreMappingProfiles(); - Container.ComposeWebMappingProfiles(); + Composition + .ComposeCoreMappingProfiles() + .ComposeWebMappingProfiles(); } protected virtual void ComposePluginManager(UmbracoTestOptions.PluginManager pluginManager) @@ -285,7 +286,7 @@ namespace Umbraco.Tests.Testing SettingsForTests.ConfigureSettings(globalSettings); // default Datalayer/Repositories/SQL/Database/etc... - Container.ComposeRepositories(); + Composition.ComposeRepositories(); // register basic stuff that might need to be there for some container resolvers to work Container.RegisterSingleton(factory => umbracoSettings); @@ -326,7 +327,7 @@ namespace Umbraco.Tests.Testing => TestObjects.GetScopeProvider(factory.TryGetInstance(), factory.TryGetInstance(), factory.TryGetInstance())); Container.RegisterSingleton(factory => (IScopeAccessor) factory.GetInstance()); - Container.ComposeServices(); + Composition.ComposeServices(); // composition root is doing weird things, fix Container.RegisterSingleton(); diff --git a/src/Umbraco.Web/Composing/Composers/ControllersComposer.cs b/src/Umbraco.Web/Composing/Composers/ControllersComposer.cs index 889ef195a5..2225c369df 100644 --- a/src/Umbraco.Web/Composing/Composers/ControllersComposer.cs +++ b/src/Umbraco.Web/Composing/Composers/ControllersComposer.cs @@ -1,6 +1,7 @@ using System.Reflection; using System.Web.Http.Controllers; using System.Web.Mvc; +using Umbraco.Core.Components; using Umbraco.Core.Composing; namespace Umbraco.Web.Composing.Composers @@ -10,27 +11,31 @@ namespace Umbraco.Web.Composing.Composers /// /// Registers all IControllers using the TypeLoader for scanning and caching found instances for the calling assembly /// - public static IContainer ComposeMvcControllers(this IContainer container, TypeLoader typeLoader, Assembly assembly) + public static Composition ComposeMvcControllers(this Composition composition, TypeLoader typeLoader, Assembly assembly) { + var container = composition.Container; + //TODO: We've already scanned for UmbracoApiControllers and SurfaceControllers - should we scan again // for all controllers? Seems like we should just do this once and then filter. That said here we are // only scanning our own single assembly. Hrm. container.RegisterControllers(typeLoader, assembly); - return container; + return composition; } /// /// Registers all IHttpController using the TypeLoader for scanning and caching found instances for the calling assembly /// - public static IContainer ComposeApiControllers(this IContainer container, TypeLoader typeLoader, Assembly assembly) + public static Composition ComposeApiControllers(this Composition composition, TypeLoader typeLoader, Assembly assembly) { + var container = composition.Container; + //TODO: We've already scanned for UmbracoApiControllers and SurfaceControllers - should we scan again // for all controllers? Seems like we should just do this once and then filter. That said here we are // only scanning our own single assembly. Hrm. container.RegisterControllers(typeLoader, assembly); - return container; + return composition; } private static void RegisterControllers(this IContainer container, TypeLoader typeLoader, Assembly assembly) diff --git a/src/Umbraco.Web/Composing/Composers/InstallerComposer.cs b/src/Umbraco.Web/Composing/Composers/InstallerComposer.cs index b9acc636c5..3d1a5b5c43 100644 --- a/src/Umbraco.Web/Composing/Composers/InstallerComposer.cs +++ b/src/Umbraco.Web/Composing/Composers/InstallerComposer.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Composing; +using Umbraco.Core.Components; +using Umbraco.Core.Composing; using Umbraco.Web.Install; using Umbraco.Web.Install.InstallSteps; @@ -6,8 +7,10 @@ namespace Umbraco.Web.Composing.Composers { public static class InstallerComposer { - public static IContainer ComposeInstaller(this IContainer container) + public static Composition ComposeInstaller(this Composition composition) { + var container = composition.Container; + // register the installer steps container.Register(Lifetime.Scope); @@ -28,7 +31,7 @@ namespace Umbraco.Web.Composing.Composers container.Register(); container.Register(); - return container; + return composition; } } } diff --git a/src/Umbraco.Web/Composing/Composers/WebMappingProfilesComposer.cs b/src/Umbraco.Web/Composing/Composers/WebMappingProfilesComposer.cs index c5629b983e..4779ba129b 100644 --- a/src/Umbraco.Web/Composing/Composers/WebMappingProfilesComposer.cs +++ b/src/Umbraco.Web/Composing/Composers/WebMappingProfilesComposer.cs @@ -1,5 +1,6 @@ using AutoMapper; using Umbraco.Core; +using Umbraco.Core.Components; using Umbraco.Core.Composing; using Umbraco.Core.Models; using Umbraco.Web.Models.ContentEditing; @@ -10,8 +11,10 @@ namespace Umbraco.Web.Composing.Composers { public static class WebMappingProfilesComposer { - public static IContainer ComposeWebMappingProfiles(this IContainer container) + public static Composition ComposeWebMappingProfiles(this Composition composition) { + var container = composition.Container; + //register the profiles container.Register(); container.Register(); @@ -44,7 +47,7 @@ namespace Umbraco.Web.Composing.Composers container.Register(); container.Register(); - return container; + return composition; } } } diff --git a/src/Umbraco.Web/Composing/Current.cs b/src/Umbraco.Web/Composing/Current.cs index 9fc7a8a941..d0d6aeb2fa 100644 --- a/src/Umbraco.Web/Composing/Current.cs +++ b/src/Umbraco.Web/Composing/Current.cs @@ -120,7 +120,7 @@ namespace Umbraco.Web.Composing internal static EditorValidatorCollection EditorValidators => Container.GetInstance(); - + internal static UmbracoApiControllerTypeCollection UmbracoApiControllerTypes => Container.GetInstance(); @@ -230,7 +230,7 @@ namespace Umbraco.Web.Composing public static IProfiler Profiler => CoreCurrent.Profiler; - public static ProfilingLogger ProfilingLogger => CoreCurrent.ProfilingLogger; + public static IProfilingLogger ProfilingLogger => CoreCurrent.ProfilingLogger; public static CacheHelper ApplicationCache => CoreCurrent.ApplicationCache; diff --git a/src/Umbraco.Web/Macros/MacroRenderer.cs b/src/Umbraco.Web/Macros/MacroRenderer.cs index a8c89f179a..5ba9de6577 100755 --- a/src/Umbraco.Web/Macros/MacroRenderer.cs +++ b/src/Umbraco.Web/Macros/MacroRenderer.cs @@ -27,11 +27,11 @@ namespace Umbraco.Web.Macros { public class MacroRenderer { - private readonly ProfilingLogger _plogger; + private readonly IProfilingLogger _plogger; // todo: there are many more things that would need to be injected in here - public MacroRenderer(ProfilingLogger plogger) + public MacroRenderer(IProfilingLogger plogger) { _plogger = plogger; } @@ -143,7 +143,7 @@ namespace Umbraco.Web.Macros var key = member?.ProviderUserKey; if (key == null) return; } - + // this is legacy and I'm not sure what exactly it is supposed to do if (macroContent.Control != null) macroContent.ControlId = macroContent.Control.ID; @@ -304,7 +304,7 @@ namespace Umbraco.Web.Macros { Exceptions.Add(e); - _plogger.Logger.Warn(e, "Failed {MsgIn}", msgIn); + _plogger.Warn(e, "Failed {MsgIn}", msgIn); var macroErrorEventArgs = new MacroErrorEventArgs { @@ -362,7 +362,7 @@ namespace Umbraco.Web.Macros "Executed PartialView.", () => ExecutePartialView(model), () => textService.Localize("errors/macroErrorLoadingPartialView", new[] { model.MacroSource })); - + case MacroTypes.UserControl: return ExecuteMacroWithErrorWrapper(model, $"Loading UserControl: MacroSource=\"{model.MacroSource}\".", diff --git a/src/Umbraco.Web/Runtime/WebRuntime.cs b/src/Umbraco.Web/Runtime/WebRuntime.cs index 52bf980853..3e4d2c1c1f 100644 --- a/src/Umbraco.Web/Runtime/WebRuntime.cs +++ b/src/Umbraco.Web/Runtime/WebRuntime.cs @@ -23,7 +23,6 @@ namespace Umbraco.Web.Runtime /// /// public WebRuntime(UmbracoApplicationBase umbracoApplication) - : base() { _umbracoApplication = umbracoApplication; } diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs index 3705eea086..c3c74f0c0b 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs @@ -70,12 +70,12 @@ namespace Umbraco.Web.Runtime container.RegisterSingleton(); // required for hybrid accessors - container.ComposeWebMappingProfiles(); + composition.ComposeWebMappingProfiles(); //register the install components //NOTE: i tried to not have these registered if we weren't installing or upgrading but post install when the site restarts //it still needs to use the install controller so we can't do that - container.ComposeInstaller(); + composition.ComposeInstaller(); // register membership stuff container.Register(factory => Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider()); @@ -125,8 +125,9 @@ namespace Umbraco.Web.Runtime // configure the container for web container.ConfigureForWeb(); - container.ComposeMvcControllers(typeLoader, GetType().Assembly); - container.ComposeApiControllers(typeLoader, GetType().Assembly); + composition + .ComposeMvcControllers(typeLoader, GetType().Assembly) + .ComposeApiControllers(typeLoader, GetType().Assembly); composition.GetCollectionBuilder() .Add(() => typeLoader.GetTypes()); // fixme which searchable trees?! diff --git a/src/Umbraco.Web/Suspendable.cs b/src/Umbraco.Web/Suspendable.cs index beb0029f4f..e7c0c34d80 100644 --- a/src/Umbraco.Web/Suspendable.cs +++ b/src/Umbraco.Web/Suspendable.cs @@ -31,7 +31,7 @@ namespace Umbraco.Web public static void SuspendDocumentCache() { - Current.ProfilingLogger.Logger.Info(typeof (PageCacheRefresher), "Suspend document cache."); + Current.Logger.Info(typeof (PageCacheRefresher), "Suspend document cache."); _suspended = true; } @@ -39,7 +39,7 @@ namespace Umbraco.Web { _suspended = false; - Current.ProfilingLogger.Logger.Info(typeof (PageCacheRefresher), "Resume document cache (reload:{Tried}).", _tried); + Current.Logger.Info(typeof (PageCacheRefresher), "Resume document cache (reload:{Tried}).", _tried); if (_tried == false) return; _tried = false; @@ -65,7 +65,7 @@ namespace Umbraco.Web public static void SuspendIndexers() { - Current.ProfilingLogger.Logger.Info(typeof (ExamineEvents), "Suspend indexers."); + Current.Logger.Info(typeof (ExamineEvents), "Suspend indexers."); _suspended = true; } @@ -73,7 +73,7 @@ namespace Umbraco.Web { _suspended = false; - Current.ProfilingLogger.Logger.Info(typeof (ExamineEvents), "Resume indexers (rebuild:{Tried}).", _tried); + Current.Logger.Info(typeof (ExamineEvents), "Resume indexers (rebuild:{Tried}).", _tried); if (_tried == false) return; _tried = false; @@ -93,13 +93,13 @@ namespace Umbraco.Web public static void Suspend() { - Current.ProfilingLogger.Logger.Info(typeof (ScheduledPublishing), "Suspend scheduled publishing."); + Current.Logger.Info(typeof (ScheduledPublishing), "Suspend scheduled publishing."); _suspended = true; } public static void Resume() { - Current.ProfilingLogger.Logger.Info(typeof (ScheduledPublishing), "Resume scheduled publishing."); + Current.Logger.Info(typeof (ScheduledPublishing), "Resume scheduled publishing."); _suspended = false; } } diff --git a/src/Umbraco.Web/UI/Controls/UmbracoControl.cs b/src/Umbraco.Web/UI/Controls/UmbracoControl.cs index 744b77ac50..d9dae18b14 100644 --- a/src/Umbraco.Web/UI/Controls/UmbracoControl.cs +++ b/src/Umbraco.Web/UI/Controls/UmbracoControl.cs @@ -3,7 +3,6 @@ using System.Web.Mvc; using System.Web.UI; using Umbraco.Core.Cache; using Umbraco.Core.Logging; -using Umbraco.Core.Persistence; using Umbraco.Core.Services; using Umbraco.Web.Composing; @@ -47,7 +46,7 @@ namespace Umbraco.Web.UI.Controls /// /// Gets the profiling logger. /// - public ProfilingLogger ProfilingLogger { get; } + public IProfilingLogger ProfilingLogger { get; } /// /// Gets the Umbraco context. diff --git a/src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs b/src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs index 62e94ddded..e1c81d9a35 100644 --- a/src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs +++ b/src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs @@ -1,12 +1,8 @@ using System; -using System.Web; using System.Web.Mvc; -using System.Web.Routing; using System.Web.UI; -using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Logging; -using Umbraco.Core.Persistence; using Umbraco.Core.Services; using Umbraco.Web.Composing; using Umbraco.Web.Security; @@ -75,7 +71,7 @@ namespace Umbraco.Web.UI.Controls /// /// Gets the ProfilingLogger. /// - public ProfilingLogger ProfilingLogger { get; } + public IProfilingLogger ProfilingLogger { get; } /// /// Gets the Umbraco context. diff --git a/src/Umbraco.Web/UI/Pages/BasePage.cs b/src/Umbraco.Web/UI/Pages/BasePage.cs index def4288c6d..5974dfcbe8 100644 --- a/src/Umbraco.Web/UI/Pages/BasePage.cs +++ b/src/Umbraco.Web/UI/Pages/BasePage.cs @@ -1,14 +1,11 @@ using System; using System.Web; using System.Web.Mvc; -using System.Web.Routing; -using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Services; using Umbraco.Web.Security; using System.Web.UI; -using Umbraco.Core.Persistence; using Umbraco.Web.Composing; namespace Umbraco.Web.UI.Pages @@ -33,7 +30,7 @@ namespace Umbraco.Web.UI.Pages /// /// Gets the profiling helper. /// - public ProfilingLogger ProfilingLogger => Current.ProfilingLogger; + public IProfilingLogger ProfilingLogger => Current.ProfilingLogger; /// /// Gets the Url helper. diff --git a/src/Umbraco.Web/UmbracoHttpHandler.cs b/src/Umbraco.Web/UmbracoHttpHandler.cs index e64c4c5fe1..c1cf460c81 100644 --- a/src/Umbraco.Web/UmbracoHttpHandler.cs +++ b/src/Umbraco.Web/UmbracoHttpHandler.cs @@ -1,11 +1,8 @@ using System; using System.Web; using System.Web.Mvc; -using System.Web.Routing; -using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Logging; -using Umbraco.Core.Persistence; using Umbraco.Core.Services; using Umbraco.Web.Composing; using Umbraco.Web.Security; @@ -44,7 +41,7 @@ namespace Umbraco.Web /// /// Gets the ProfilingLogger. /// - public ProfilingLogger ProfilingLogger { get; } + public IProfilingLogger ProfilingLogger { get; } /// /// Gets the Umbraco context. diff --git a/src/Umbraco.Web/UmbracoWebService.cs b/src/Umbraco.Web/UmbracoWebService.cs index 20db7208b5..fbe4eb9f04 100644 --- a/src/Umbraco.Web/UmbracoWebService.cs +++ b/src/Umbraco.Web/UmbracoWebService.cs @@ -40,7 +40,7 @@ namespace Umbraco.Web /// /// Gets the ProfilingLogger. /// - public ProfilingLogger ProfilingLogger { get; } + public IProfilingLogger ProfilingLogger { get; } /// /// Gets the Umbraco context. From c23c7749b4bdd83cc91cf26cd94ee183289d507c Mon Sep 17 00:00:00 2001 From: Stephan Date: Tue, 27 Nov 2018 13:46:43 +0100 Subject: [PATCH 099/469] Composition fixes --- src/Umbraco.Core/Components/Composition.cs | 14 ++++++++ src/Umbraco.Core/Composing/TypeLoader.cs | 2 +- .../Migrations/MigrationBuilder.cs | 3 +- src/Umbraco.Core/Persistence/SqlContext.cs | 36 +++++++++---------- .../SqlSyntax/SqlServerSyntaxProvider.cs | 7 ++-- .../Persistence/UmbracoDatabaseFactory.cs | 7 ++-- src/Umbraco.Core/Runtime/CoreRuntime.cs | 7 ++-- .../Components/ComponentTests.cs | 2 +- .../Composing/ComposingTestBase.cs | 2 +- .../Composing/TypeFinderTests.cs | 2 +- src/Umbraco.Tests/Models/ContentTests.cs | 14 ++++---- src/Umbraco.Tests/Models/ContentTypeTests.cs | 2 +- .../Routing/RenderRouteHandlerTests.cs | 4 +-- .../Services/ContentServicePerformanceTest.cs | 2 +- .../Services/PerformanceTests.cs | 2 +- src/Umbraco.Tests/TestHelpers/BaseWebTest.cs | 2 +- .../TestHelpers/TestWithDatabaseBase.cs | 2 +- src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 6 ++-- .../UmbracoExamine/EventsTest.cs | 2 +- .../UmbracoExamine/ExamineBaseTest.cs | 4 +-- .../UmbracoExamine/IndexInitializer.cs | 2 +- .../Web/TemplateUtilitiesTests.cs | 2 +- .../BatchedDatabaseServerMessenger.cs | 2 +- ...aseServerRegistrarAndMessengerComponent.cs | 2 +- .../Composers/ControllersComposer.cs | 17 ++++----- .../Controllers/UmbLoginController.cs | 2 +- .../Controllers/UmbLoginStatusController.cs | 2 +- .../Controllers/UmbProfileController.cs | 2 +- .../Controllers/UmbRegisterController.cs | 2 +- .../Editors/AuthenticationController.cs | 4 +-- .../Editors/BackOfficeController.cs | 14 ++++---- .../Editors/DashboardController.cs | 4 +-- .../Controllers/InstallApiController.cs | 7 ++-- src/Umbraco.Web/Macros/MacroRenderer.cs | 2 +- src/Umbraco.Web/Mvc/PluginController.cs | 6 ++-- src/Umbraco.Web/Mvc/RenderMvcController.cs | 2 +- src/Umbraco.Web/Mvc/SurfaceController.cs | 2 +- .../Mvc/UmbracoAuthorizedController.cs | 2 +- src/Umbraco.Web/Mvc/UmbracoController.cs | 6 ++-- src/Umbraco.Web/Mvc/UmbracoPageResult.cs | 4 +-- .../NestedContentManyValueConverter.cs | 4 +-- .../NestedContentSingleValueConverter.cs | 4 +-- src/Umbraco.Web/Routing/PublishedRouter.cs | 6 ++-- .../Runtime/WebRuntimeComponent.cs | 24 ++++++------- .../Scheduling/HealthCheckNotifier.cs | 4 +-- src/Umbraco.Web/Scheduling/KeepAlive.cs | 4 +-- src/Umbraco.Web/Scheduling/LogScrubber.cs | 4 +-- src/Umbraco.Web/Scheduling/ScheduledTasks.cs | 6 ++-- .../Scheduling/SchedulerComponent.cs | 6 ++-- src/Umbraco.Web/Search/ExamineComponent.cs | 26 +++++++------- src/Umbraco.Web/TagsController.cs | 2 +- .../WebApi/UmbracoApiController.cs | 2 +- .../WebApi/UmbracoApiControllerBase.cs | 6 ++-- .../WebApi/UmbracoAuthorizedApiController.cs | 2 +- 54 files changed, 158 insertions(+), 150 deletions(-) diff --git a/src/Umbraco.Core/Components/Composition.cs b/src/Umbraco.Core/Components/Composition.cs index bf3ff40c79..412008c175 100644 --- a/src/Umbraco.Core/Components/Composition.cs +++ b/src/Umbraco.Core/Components/Composition.cs @@ -20,7 +20,16 @@ namespace Umbraco.Core.Components /// Initializes a new instance of the class. /// /// A container. + /// The type loader. /// The runtime level. + public Composition(IContainer container, TypeLoader typeLoader, RuntimeLevel level) + { + Container = container; + TypeLoader = typeLoader; + RuntimeLevel = level; + } + + // fixme / tests public Composition(IContainer container, RuntimeLevel level) { Container = container; @@ -33,6 +42,11 @@ namespace Umbraco.Core.Components /// Use with care! public IContainer Container { get; } + /// + /// Gets the type loader. + /// + public TypeLoader TypeLoader { get; } + /// /// Gets the runtime level. /// diff --git a/src/Umbraco.Core/Composing/TypeLoader.cs b/src/Umbraco.Core/Composing/TypeLoader.cs index 4240f96a5b..714c5c0ec5 100644 --- a/src/Umbraco.Core/Composing/TypeLoader.cs +++ b/src/Umbraco.Core/Composing/TypeLoader.cs @@ -250,7 +250,7 @@ namespace Umbraco.Core.Composing /// A profiling logger. /// The hash. // internal for tests - internal static string GetFileHash(IEnumerable filesAndFolders, ProfilingLogger logger) + internal static string GetFileHash(IEnumerable filesAndFolders, IProfilingLogger logger) { using (logger.TraceDuration("Determining hash of code files on disk", "Hash determined")) { diff --git a/src/Umbraco.Core/Migrations/MigrationBuilder.cs b/src/Umbraco.Core/Migrations/MigrationBuilder.cs index 65e40f6e75..aebd8bd1ee 100644 --- a/src/Umbraco.Core/Migrations/MigrationBuilder.cs +++ b/src/Umbraco.Core/Migrations/MigrationBuilder.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using Umbraco.Core.Composing; namespace Umbraco.Core.Migrations @@ -15,7 +14,7 @@ namespace Umbraco.Core.Migrations public IMigration Build(Type migrationType, IMigrationContext context) { - return (IMigration) _container.CreateInstance(migrationType, new Dictionary{{"context", context}}); + return (IMigration) _container.CreateInstance(migrationType, context); } } } diff --git a/src/Umbraco.Core/Persistence/SqlContext.cs b/src/Umbraco.Core/Persistence/SqlContext.cs index feb92e0849..6f9f91114c 100644 --- a/src/Umbraco.Core/Persistence/SqlContext.cs +++ b/src/Umbraco.Core/Persistence/SqlContext.cs @@ -12,6 +12,8 @@ namespace Umbraco.Core.Persistence /// public class SqlContext : ISqlContext { + private readonly Lazy _mappers; + /// /// Initializes a new instance of the class. /// @@ -20,24 +22,20 @@ namespace Umbraco.Core.Persistence /// The database type. /// The mappers. public SqlContext(ISqlSyntaxProvider sqlSyntax, DatabaseType databaseType, IPocoDataFactory pocoDataFactory, IMapperCollection mappers = null) - { - // for tests - Mappers = mappers ?? new Mappers.MapperCollection(Enumerable.Empty()); - - SqlSyntax = sqlSyntax ?? throw new ArgumentNullException(nameof(sqlSyntax)); - PocoDataFactory = pocoDataFactory ?? throw new ArgumentNullException(nameof(pocoDataFactory)); - DatabaseType = databaseType ?? throw new ArgumentNullException(nameof(databaseType)); - Templates = new SqlTemplates(this); - } - - // fixme - internal SqlContext() + : this(sqlSyntax, databaseType, pocoDataFactory, new Lazy(() => mappers ?? new Mappers.MapperCollection(Enumerable.Empty()))) { } - internal void Initialize(ISqlSyntaxProvider sqlSyntax, DatabaseType databaseType, IPocoDataFactory pocoDataFactory, IMapperCollection mappers = null) + /// + /// Initializes a new instance of the class. + /// + /// The sql syntax provider. + /// The Poco data factory. + /// The database type. + /// The mappers. + public SqlContext(ISqlSyntaxProvider sqlSyntax, DatabaseType databaseType, IPocoDataFactory pocoDataFactory, Lazy mappers) { // for tests - Mappers = mappers ?? new Mappers.MapperCollection(Enumerable.Empty()); + _mappers = mappers; SqlSyntax = sqlSyntax ?? throw new ArgumentNullException(nameof(sqlSyntax)); PocoDataFactory = pocoDataFactory ?? throw new ArgumentNullException(nameof(pocoDataFactory)); @@ -46,10 +44,10 @@ namespace Umbraco.Core.Persistence } /// - public ISqlSyntaxProvider SqlSyntax { get; private set; } + public ISqlSyntaxProvider SqlSyntax { get; } /// - public DatabaseType DatabaseType { get; private set; } + public DatabaseType DatabaseType { get; } /// public Sql Sql() => NPoco.Sql.BuilderFor((ISqlContext) this); @@ -61,12 +59,12 @@ namespace Umbraco.Core.Persistence public IQuery Query() => new Query(this); /// - public SqlTemplates Templates { get; private set; } + public SqlTemplates Templates { get; } /// - public IPocoDataFactory PocoDataFactory { get; private set; } + public IPocoDataFactory PocoDataFactory { get; } /// - public IMapperCollection Mappers { get; private set; } + public IMapperCollection Mappers => _mappers.Value; } } diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs b/src/Umbraco.Core/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs index d9bfe85098..8b8550b694 100644 --- a/src/Umbraco.Core/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs +++ b/src/Umbraco.Core/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Data.Common; using System.Linq; using NPoco; +using Umbraco.Core.Logging; using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Scoping; @@ -97,7 +98,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax } } - internal ServerVersionInfo GetSetVersion(string connectionString, string providerName) + internal ServerVersionInfo GetSetVersion(string connectionString, string providerName, ILogger logger) { var factory = DbProviderFactories.GetFactory(providerName); var connection = factory.CreateConnection(); @@ -132,12 +133,14 @@ namespace Umbraco.Core.Persistence.SqlSyntax command.CommandText = sql; using (var reader = command.ExecuteReader()) { + reader.Read(); version = new ServerVersionInfo(reader.GetString(0), reader.GetString(2), reader.GetString(3), (EngineEdition) reader.GetInt32(5), reader.GetString(7), reader.GetString(9)); } connection.Close(); } - catch + catch (Exception e) { + logger.Error(e, "Failed to detected SqlServer version."); version = new ServerVersionInfo(); // all unknown } } diff --git a/src/Umbraco.Core/Persistence/UmbracoDatabaseFactory.cs b/src/Umbraco.Core/Persistence/UmbracoDatabaseFactory.cs index e55f462a7b..c9a509fe94 100644 --- a/src/Umbraco.Core/Persistence/UmbracoDatabaseFactory.cs +++ b/src/Umbraco.Core/Persistence/UmbracoDatabaseFactory.cs @@ -28,7 +28,6 @@ namespace Umbraco.Core.Persistence private readonly ILogger _logger; private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(); - private SqlContext _sqlContext; private DatabaseFactory _npocoDatabaseFactory; private IPocoDataFactory _pocoDataFactory; private string _connectionString; @@ -130,7 +129,7 @@ namespace Umbraco.Core.Persistence if (setting.IsNullOrWhiteSpace() || !setting.StartsWith("SqlServer.") || !Enum.TryParse(setting.Substring("SqlServer.".Length), out var versionName, true)) { - versionName = ((SqlServerSyntaxProvider) _sqlSyntax).GetSetVersion(_connectionString, _providerName).ProductVersionName; + versionName = ((SqlServerSyntaxProvider) _sqlSyntax).GetSetVersion(_connectionString, _providerName, _logger).ProductVersionName; } else { @@ -156,7 +155,7 @@ namespace Umbraco.Core.Persistence } /// - public ISqlContext SqlContext => _sqlContext ?? (_sqlContext = new SqlContext(_sqlSyntax, _databaseType, _pocoDataFactory, _mappers.Value)); + public ISqlContext SqlContext { get; private set; } /// public void ConfigureForUpgrade() @@ -209,6 +208,8 @@ namespace Umbraco.Core.Persistence if (_npocoDatabaseFactory == null) throw new NullReferenceException("The call to UmbracoDatabaseFactory.Config yielded a null UmbracoDatabaseFactory instance."); + SqlContext = new SqlContext(_sqlSyntax, _databaseType, _pocoDataFactory, _mappers); + _logger.Debug("Configured."); Configured = true; } diff --git a/src/Umbraco.Core/Runtime/CoreRuntime.cs b/src/Umbraco.Core/Runtime/CoreRuntime.cs index d4c7d80c3d..21ce073719 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntime.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntime.cs @@ -52,8 +52,6 @@ namespace Umbraco.Core.Runtime // create and register the essential services // ie the bare minimum required to boot - var composition = new Composition(container, RuntimeLevel.Boot); - // loggers var logger = GetLogger(); container.RegisterInstance(logger); @@ -93,7 +91,10 @@ namespace Umbraco.Core.Runtime { Level = RuntimeLevel.Boot }; - container.RegisterInstance(_state); + container.RegisterInstance(_state); + + // create the composition + var composition = new Composition(container, typeLoader, RuntimeLevel.Boot); // register runtime-level services Compose(composition); diff --git a/src/Umbraco.Tests/Components/ComponentTests.cs b/src/Umbraco.Tests/Components/ComponentTests.cs index 111a1370ee..9c38731cb8 100644 --- a/src/Umbraco.Tests/Components/ComponentTests.cs +++ b/src/Umbraco.Tests/Components/ComponentTests.cs @@ -33,7 +33,7 @@ namespace Umbraco.Tests.Components var p = new ScopeProvider(f, fs, logger); mock.Setup(x => x.GetInstance(typeof (ILogger))).Returns(logger); - mock.Setup(x => x.GetInstance(typeof (ProfilingLogger))).Returns(new ProfilingLogger(Mock.Of(), Mock.Of())); + mock.Setup(x => x.GetInstance(typeof (IProfilingLogger))).Returns(new ProfilingLogger(Mock.Of(), Mock.Of())); mock.Setup(x => x.GetInstance(typeof (IUmbracoDatabaseFactory))).Returns(f); mock.Setup(x => x.GetInstance(typeof (IScopeProvider))).Returns(p); diff --git a/src/Umbraco.Tests/Composing/ComposingTestBase.cs b/src/Umbraco.Tests/Composing/ComposingTestBase.cs index be595885e7..7380a5968a 100644 --- a/src/Umbraco.Tests/Composing/ComposingTestBase.cs +++ b/src/Umbraco.Tests/Composing/ComposingTestBase.cs @@ -13,7 +13,7 @@ namespace Umbraco.Tests.Composing { protected TypeLoader TypeLoader { get; private set; } - protected ProfilingLogger ProfilingLogger { get; private set; } + protected IProfilingLogger ProfilingLogger { get; private set; } [SetUp] public void Initialize() diff --git a/src/Umbraco.Tests/Composing/TypeFinderTests.cs b/src/Umbraco.Tests/Composing/TypeFinderTests.cs index 955f6f94c8..075fab4778 100644 --- a/src/Umbraco.Tests/Composing/TypeFinderTests.cs +++ b/src/Umbraco.Tests/Composing/TypeFinderTests.cs @@ -93,7 +93,7 @@ namespace Umbraco.Tests.Composing Assert.AreEqual(21, typesFound.Count()); // + classes in Umbraco.Web are marked with [Tree] } - private static ProfilingLogger GetTestProfilingLogger() + private static IProfilingLogger GetTestProfilingLogger() { var logger = new DebugDiagnosticsLogger(); var profiler = new TestProfiler(); diff --git a/src/Umbraco.Tests/Models/ContentTests.cs b/src/Umbraco.Tests/Models/ContentTests.cs index aed31ca1be..37f2d4e62d 100644 --- a/src/Umbraco.Tests/Models/ContentTests.cs +++ b/src/Umbraco.Tests/Models/ContentTests.cs @@ -55,7 +55,7 @@ namespace Umbraco.Tests.Models var content = new Content("content", -1, contentType) { Id = 1, VersionId = 1 }; const string langFr = "fr-FR"; - + contentType.Variations = ContentVariation.Culture; Assert.IsFalse(content.IsPropertyDirty("CultureInfos")); //hasn't been changed @@ -73,7 +73,7 @@ namespace Umbraco.Tests.Models Thread.Sleep(500); //The "Date" wont be dirty if the test runs too fast since it will be the same date content.SetCultureName("name-fr", langFr); - Assert.IsTrue(frCultureName.IsPropertyDirty("Date")); + Assert.IsTrue(frCultureName.IsPropertyDirty("Date")); Assert.IsTrue(content.IsPropertyDirty("CultureInfos")); //it's true now since we've updated a name } @@ -104,7 +104,7 @@ namespace Umbraco.Tests.Models Thread.Sleep(500); //The "Date" wont be dirty if the test runs too fast since it will be the same date content.SetCultureName("name-fr", langFr); content.PublishCulture(langFr); //we've set the name, now we're publishing it - Assert.IsTrue(frCultureName.IsPropertyDirty("Date")); + Assert.IsTrue(frCultureName.IsPropertyDirty("Date")); Assert.IsTrue(content.IsPropertyDirty("PublishCultureInfos")); //it's true now since we've updated a name } @@ -210,7 +210,7 @@ namespace Umbraco.Tests.Models Assert.AreNotSame(content.Properties, clone.Properties); } - private static ProfilingLogger GetTestProfilingLogger() + private static IProfilingLogger GetTestProfilingLogger() { var logger = new DebugDiagnosticsLogger(); var profiler = new TestProfiler(); @@ -309,7 +309,7 @@ namespace Umbraco.Tests.Models content.UpdateDate = DateTime.Now; content.WriterId = 23; - + // Act var clone = (Content)content.DeepClone(); @@ -406,7 +406,7 @@ namespace Umbraco.Tests.Models content.SetCultureName("Hello", "en-US"); content.SetCultureName("World", "es-ES"); content.PublishCulture("en-US"); - + var i = 200; foreach (var property in content.Properties) { @@ -424,7 +424,7 @@ namespace Umbraco.Tests.Models { Id = 88 }; - + content.Trashed = true; content.UpdateDate = DateTime.Now; content.WriterId = 23; diff --git a/src/Umbraco.Tests/Models/ContentTypeTests.cs b/src/Umbraco.Tests/Models/ContentTypeTests.cs index a0e9a370da..d505c38ae0 100644 --- a/src/Umbraco.Tests/Models/ContentTypeTests.cs +++ b/src/Umbraco.Tests/Models/ContentTypeTests.cs @@ -93,7 +93,7 @@ namespace Umbraco.Tests.Models } } - private static ProfilingLogger GetTestProfilingLogger() + private static IProfilingLogger GetTestProfilingLogger() { var logger = new DebugDiagnosticsLogger(); var profiler = new TestProfiler(); diff --git a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs index d27d6fa34c..0bb12ebda5 100644 --- a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs +++ b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs @@ -55,7 +55,7 @@ namespace Umbraco.Tests.Routing container.RegisterInstance(logger); var profiler = Mock.Of(); container.RegisterInstance(profiler); - container.RegisterInstance(new ProfilingLogger(logger, profiler)); + container.RegisterInstance(new ProfilingLogger(logger, profiler)); base.Boot(container); } @@ -182,7 +182,7 @@ namespace Umbraco.Tests.Routing /// public class CustomDocumentController : RenderMvcController { - public CustomDocumentController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger) + public CustomDocumentController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, IProfilingLogger profilingLogger) : base(globalSettings, umbracoContext, services, applicationCache, logger, profilingLogger) { } diff --git a/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs b/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs index 8c6a2f4f58..ce673bcd47 100644 --- a/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs +++ b/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs @@ -45,7 +45,7 @@ namespace Umbraco.Tests.Services Assert.IsInstanceOf(Current.Profiler); } - private static ProfilingLogger GetTestProfilingLogger() + private static IProfilingLogger GetTestProfilingLogger() { var logger = new DebugDiagnosticsLogger(); var profiler = new TestProfiler(); diff --git a/src/Umbraco.Tests/Services/PerformanceTests.cs b/src/Umbraco.Tests/Services/PerformanceTests.cs index 900a466a1d..09743b350f 100644 --- a/src/Umbraco.Tests/Services/PerformanceTests.cs +++ b/src/Umbraco.Tests/Services/PerformanceTests.cs @@ -57,7 +57,7 @@ namespace Umbraco.Tests.Services base.TearDown(); } - private static ProfilingLogger GetTestProfilingLogger() + private static IProfilingLogger GetTestProfilingLogger() { var logger = new DebugDiagnosticsLogger(); var profiler = new TestProfiler(); diff --git a/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs b/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs index 421870c969..cabbf40fe9 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs @@ -28,7 +28,7 @@ namespace Umbraco.Tests.TestHelpers base.Compose(); Container.RegisterSingleton(); - Container.RegisterSingleton(); + Container.RegisterSingleton(); } protected override void Initialize() diff --git a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs index fa61381eed..02df0b4271 100644 --- a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs +++ b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs @@ -101,7 +101,7 @@ namespace Umbraco.Tests.TestHelpers public override void TearDown() { - var profilingLogger = Container.TryGetInstance(); + var profilingLogger = Container.TryGetInstance(); var timer = profilingLogger?.TraceDuration("teardown"); // fixme move that one up try { diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index 969bfff4fe..6459342e7a 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -98,7 +98,7 @@ namespace Umbraco.Tests.Testing protected IProfiler Profiler => Container.GetInstance(); - protected virtual ProfilingLogger ProfilingLogger => Container.GetInstance(); + protected virtual IProfilingLogger ProfilingLogger => Container.GetInstance(); protected CacheHelper CacheHelper => Container.GetInstance(); @@ -178,7 +178,7 @@ namespace Umbraco.Tests.Testing Container.RegisterSingleton(f => new LogProfiler(f.GetInstance())); } - Container.RegisterSingleton(f => new ProfilingLogger(f.GetInstance(), f.GetInstance())); + Container.RegisterSingleton(f => new ProfilingLogger(f.GetInstance(), f.GetInstance())); } protected virtual void ComposeWeb() @@ -255,7 +255,7 @@ namespace Umbraco.Tests.Testing private static TypeLoader CreateCommonPluginManager(IContainer f) { - return new TypeLoader(f.GetInstance().RuntimeCache, f.GetInstance(), f.GetInstance(), false) + return new TypeLoader(f.GetInstance().RuntimeCache, f.GetInstance(), f.GetInstance(), false) { AssembliesToScan = new[] { diff --git a/src/Umbraco.Tests/UmbracoExamine/EventsTest.cs b/src/Umbraco.Tests/UmbracoExamine/EventsTest.cs index e2279ee833..b3fcc3c3cd 100644 --- a/src/Umbraco.Tests/UmbracoExamine/EventsTest.cs +++ b/src/Umbraco.Tests/UmbracoExamine/EventsTest.cs @@ -22,7 +22,7 @@ namespace Umbraco.Tests.UmbracoExamine using (indexer.ProcessNonAsync()) { var searcher = indexer.GetSearcher(); - + var contentService = new ExamineDemoDataContentService(); //get a node from the data repo var node = contentService.GetPublishedContentByXPath("//*[string-length(@id)>0 and number(@id)>0]") diff --git a/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs b/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs index 5ca195849b..e496d90dd1 100644 --- a/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs +++ b/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs @@ -18,8 +18,8 @@ namespace Umbraco.Tests.UmbracoExamine _profilingLogger = new ProfilingLogger(logger, new LogProfiler(logger)); } - private ProfilingLogger _profilingLogger; - protected override ProfilingLogger ProfilingLogger => _profilingLogger; + private IProfilingLogger _profilingLogger; + protected override IProfilingLogger ProfilingLogger => _profilingLogger; /// /// sets up resolvers before resolution is frozen diff --git a/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs b/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs index 8b57e10849..b15342aa57 100644 --- a/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs +++ b/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs @@ -29,7 +29,7 @@ namespace Umbraco.Tests.UmbracoExamine internal static class IndexInitializer { public static UmbracoContentIndexer GetUmbracoIndexer( - ProfilingLogger profilingLogger, + IProfilingLogger profilingLogger, Directory luceneDir, ISqlContext sqlContext, Analyzer analyzer = null, diff --git a/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs b/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs index 336ee3eff4..fd8ace1904 100644 --- a/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs +++ b/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs @@ -81,7 +81,7 @@ namespace Umbraco.Tests.Web .Returns((UmbracoContext umbCtx, IPublishedContent content, UrlProviderMode mode, string culture, Uri url) => "/my-test-url"); var globalSettings = SettingsForTests.GenerateMockGlobalSettings(); - + var contentType = new PublishedContentType(666, "alias", PublishedItemType.Content, Enumerable.Empty(), Enumerable.Empty(), ContentVariation.Nothing); var publishedContent = Mock.Of(); Mock.Get(publishedContent).Setup(x => x.Id).Returns(1234); diff --git a/src/Umbraco.Web/BatchedDatabaseServerMessenger.cs b/src/Umbraco.Web/BatchedDatabaseServerMessenger.cs index 8929c6edd9..ce0be7fbe6 100644 --- a/src/Umbraco.Web/BatchedDatabaseServerMessenger.cs +++ b/src/Umbraco.Web/BatchedDatabaseServerMessenger.cs @@ -26,7 +26,7 @@ namespace Umbraco.Web private readonly IUmbracoDatabaseFactory _databaseFactory; public BatchedDatabaseServerMessenger( - IRuntimeState runtime, IUmbracoDatabaseFactory databaseFactory, IScopeProvider scopeProvider, ISqlContext sqlContext, ProfilingLogger proflog, IGlobalSettings globalSettings, + IRuntimeState runtime, IUmbracoDatabaseFactory databaseFactory, IScopeProvider scopeProvider, ISqlContext sqlContext, IProfilingLogger proflog, IGlobalSettings globalSettings, bool enableDistCalls, DatabaseServerMessengerOptions options) : base(runtime, scopeProvider, sqlContext, proflog, globalSettings, enableDistCalls, options) { diff --git a/src/Umbraco.Web/Components/DatabaseServerRegistrarAndMessengerComponent.cs b/src/Umbraco.Web/Components/DatabaseServerRegistrarAndMessengerComponent.cs index 6af55dbdac..1c44098943 100644 --- a/src/Umbraco.Web/Components/DatabaseServerRegistrarAndMessengerComponent.cs +++ b/src/Umbraco.Web/Components/DatabaseServerRegistrarAndMessengerComponent.cs @@ -57,7 +57,7 @@ namespace Umbraco.Web.Components var runtime = ContainerExtensions.GetInstance(factory); var databaseFactory = ContainerExtensions.GetInstance(factory); var globalSettings = ContainerExtensions.GetInstance(factory); - var proflog = ContainerExtensions.GetInstance(factory); + var proflog = ContainerExtensions.GetInstance(factory); var scopeProvider = ContainerExtensions.GetInstance(factory); var sqlContext = ContainerExtensions.GetInstance(factory); diff --git a/src/Umbraco.Web/Composing/Composers/ControllersComposer.cs b/src/Umbraco.Web/Composing/Composers/ControllersComposer.cs index 2225c369df..5491c0cc97 100644 --- a/src/Umbraco.Web/Composing/Composers/ControllersComposer.cs +++ b/src/Umbraco.Web/Composing/Composers/ControllersComposer.cs @@ -11,36 +11,33 @@ namespace Umbraco.Web.Composing.Composers /// /// Registers all IControllers using the TypeLoader for scanning and caching found instances for the calling assembly /// - public static Composition ComposeMvcControllers(this Composition composition, TypeLoader typeLoader, Assembly assembly) + public static Composition ComposeMvcControllers(this Composition composition, Assembly assembly) { - var container = composition.Container; - //TODO: We've already scanned for UmbracoApiControllers and SurfaceControllers - should we scan again // for all controllers? Seems like we should just do this once and then filter. That said here we are // only scanning our own single assembly. Hrm. - container.RegisterControllers(typeLoader, assembly); + composition.RegisterControllers(assembly); return composition; } /// /// Registers all IHttpController using the TypeLoader for scanning and caching found instances for the calling assembly /// - public static Composition ComposeApiControllers(this Composition composition, TypeLoader typeLoader, Assembly assembly) + public static Composition ComposeApiControllers(this Composition composition, Assembly assembly) { - var container = composition.Container; - //TODO: We've already scanned for UmbracoApiControllers and SurfaceControllers - should we scan again // for all controllers? Seems like we should just do this once and then filter. That said here we are // only scanning our own single assembly. Hrm. - container.RegisterControllers(typeLoader, assembly); + composition.RegisterControllers(assembly); return composition; } - private static void RegisterControllers(this IContainer container, TypeLoader typeLoader, Assembly assembly) + private static void RegisterControllers(this Composition composition, Assembly assembly) { - var types = typeLoader.GetTypes(specificAssemblies: new[] { assembly }); + var container = composition.Container; + var types = composition.TypeLoader.GetTypes(specificAssemblies: new[] { assembly }); foreach (var type in types) container.Register(type, Lifetime.Request); } diff --git a/src/Umbraco.Web/Controllers/UmbLoginController.cs b/src/Umbraco.Web/Controllers/UmbLoginController.cs index 2774cdebc6..60b7f3ee21 100644 --- a/src/Umbraco.Web/Controllers/UmbLoginController.cs +++ b/src/Umbraco.Web/Controllers/UmbLoginController.cs @@ -16,7 +16,7 @@ namespace Umbraco.Web.Controllers { } - public UmbLoginController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger) + public UmbLoginController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, CacheHelper applicationCache, ILogger logger, IProfilingLogger profilingLogger) : base(umbracoContext, databaseFactory, services, applicationCache, logger, profilingLogger) { } diff --git a/src/Umbraco.Web/Controllers/UmbLoginStatusController.cs b/src/Umbraco.Web/Controllers/UmbLoginStatusController.cs index 1c52c0e537..46c46a9b72 100644 --- a/src/Umbraco.Web/Controllers/UmbLoginStatusController.cs +++ b/src/Umbraco.Web/Controllers/UmbLoginStatusController.cs @@ -18,7 +18,7 @@ namespace Umbraco.Web.Controllers { } - public UmbLoginStatusController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger) : base(umbracoContext, databaseFactory, services, applicationCache, logger, profilingLogger) + public UmbLoginStatusController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, CacheHelper applicationCache, ILogger logger, IProfilingLogger profilingLogger) : base(umbracoContext, databaseFactory, services, applicationCache, logger, profilingLogger) { } diff --git a/src/Umbraco.Web/Controllers/UmbProfileController.cs b/src/Umbraco.Web/Controllers/UmbProfileController.cs index 6e24853f34..95ad26c8b1 100644 --- a/src/Umbraco.Web/Controllers/UmbProfileController.cs +++ b/src/Umbraco.Web/Controllers/UmbProfileController.cs @@ -19,7 +19,7 @@ namespace Umbraco.Web.Controllers { } - public UmbProfileController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger) : base(umbracoContext, databaseFactory, services, applicationCache, logger, profilingLogger) + public UmbProfileController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, CacheHelper applicationCache, ILogger logger, IProfilingLogger profilingLogger) : base(umbracoContext, databaseFactory, services, applicationCache, logger, profilingLogger) { } diff --git a/src/Umbraco.Web/Controllers/UmbRegisterController.cs b/src/Umbraco.Web/Controllers/UmbRegisterController.cs index b0e1f65b23..8ad8ff0c58 100644 --- a/src/Umbraco.Web/Controllers/UmbRegisterController.cs +++ b/src/Umbraco.Web/Controllers/UmbRegisterController.cs @@ -18,7 +18,7 @@ namespace Umbraco.Web.Controllers { } - public UmbRegisterController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger) : base(umbracoContext, databaseFactory, services, applicationCache, logger, profilingLogger) + public UmbRegisterController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, CacheHelper applicationCache, ILogger logger, IProfilingLogger profilingLogger) : base(umbracoContext, databaseFactory, services, applicationCache, logger, profilingLogger) { } diff --git a/src/Umbraco.Web/Editors/AuthenticationController.cs b/src/Umbraco.Web/Editors/AuthenticationController.cs index 203e4ca04f..3893afd62f 100644 --- a/src/Umbraco.Web/Editors/AuthenticationController.cs +++ b/src/Umbraco.Web/Editors/AuthenticationController.cs @@ -57,7 +57,7 @@ namespace Umbraco.Web.Editors { } - public AuthenticationController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger, IRuntimeState runtimeState) + public AuthenticationController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, IProfilingLogger profilingLogger, IRuntimeState runtimeState) : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, profilingLogger, runtimeState) { } @@ -447,7 +447,7 @@ namespace Umbraco.Web.Editors if (LastLoginDate == default && IsApproved == false && InvitedDate != null) return UserState.Invited; */ - if (identityUser != null && !identityUser.IsApproved) + if (identityUser != null && !identityUser.IsApproved) { var user = Services.UserService.GetByUsername(identityUser.UserName); //also check InvitedDate and never logged in, otherwise this would allow a disabled user to reactivate their account with a forgot password diff --git a/src/Umbraco.Web/Editors/BackOfficeController.cs b/src/Umbraco.Web/Editors/BackOfficeController.cs index f015fba25f..668b35c2d9 100644 --- a/src/Umbraco.Web/Editors/BackOfficeController.cs +++ b/src/Umbraco.Web/Editors/BackOfficeController.cs @@ -49,7 +49,7 @@ namespace Umbraco.Web.Editors private const string TokenPasswordResetCode = "PasswordResetCode"; private static readonly string[] TempDataTokenNames = { TokenExternalSignInError, TokenPasswordResetCode }; - public BackOfficeController(ManifestParser manifestParser, UmbracoFeatures features, IGlobalSettings globalSettings, UmbracoContext umbracoContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger, IRuntimeState runtimeState) + public BackOfficeController(ManifestParser manifestParser, UmbracoFeatures features, IGlobalSettings globalSettings, UmbracoContext umbracoContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, IProfilingLogger profilingLogger, IRuntimeState runtimeState) : base(globalSettings, umbracoContext, services, applicationCache, logger, profilingLogger) { _manifestParser = manifestParser; @@ -86,7 +86,7 @@ namespace Umbraco.Web.Editors Core.Constants.Security.BackOfficeAuthenticationType, Core.Constants.Security.BackOfficeExternalAuthenticationType); } - + if (invite == null) { Logger.Warn("VerifyUser endpoint reached with invalid token: NULL"); @@ -192,7 +192,7 @@ namespace Umbraco.Web.Editors { var initJs = new JsInitialization(_manifestParser); var initCss = new CssInitialization(_manifestParser); - + var files = initJs.OptimizeBackOfficeScriptFiles(HttpContext, JsInitialization.GetDefaultInitialization()); var result = JsInitialization.GetJavascriptInitialization(HttpContext, files, "umbraco"); result += initCss.GetStylesheetInitialization(HttpContext); @@ -379,9 +379,9 @@ namespace Umbraco.Web.Editors ExternalSignInAutoLinkOptions autoLinkOptions = null; //Here we can check if the provider associated with the request has been configured to allow - // new users (auto-linked external accounts). This would never be used with public providers such as + // new users (auto-linked external accounts). This would never be used with public providers such as // Google, unless you for some reason wanted anybody to be able to access the backend if they have a Google account - // .... not likely! + // .... not likely! var authType = OwinContext.Authentication.GetExternalAuthenticationTypes().FirstOrDefault(x => x.AuthenticationType == loginInfo.Login.LoginProvider); if (authType == null) { @@ -472,7 +472,7 @@ namespace Umbraco.Web.Editors { autoLinkUser.AddRole(userGroup.Alias); } - + //call the callback if one is assigned if (autoLinkOptions.OnAutoLinking != null) { @@ -511,7 +511,7 @@ namespace Umbraco.Web.Editors } return true; } - + private ActionResult RedirectToLocal(string returnUrl) { if (Url.IsLocalUrl(returnUrl)) diff --git a/src/Umbraco.Web/Editors/DashboardController.cs b/src/Umbraco.Web/Editors/DashboardController.cs index 6f42b17af6..8a8db06d8d 100644 --- a/src/Umbraco.Web/Editors/DashboardController.cs +++ b/src/Umbraco.Web/Editors/DashboardController.cs @@ -30,13 +30,13 @@ namespace Umbraco.Web.Editors public DashboardController() { } - public DashboardController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger, IRuntimeState runtimeState) + public DashboardController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, IProfilingLogger profilingLogger, IRuntimeState runtimeState) : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, profilingLogger, runtimeState) { } //we have just one instance of HttpClient shared for the entire application private static readonly HttpClient HttpClient = new HttpClient(); - + //we have baseurl as a param to make previewing easier, so we can test with a dev domain from client side [ValidateAngularAntiForgeryToken] public async Task GetRemoteDashboardContent(string section, string baseUrl = "https://dashboard.umbraco.org/") diff --git a/src/Umbraco.Web/Install/Controllers/InstallApiController.cs b/src/Umbraco.Web/Install/Controllers/InstallApiController.cs index 387360163a..0762dfc12f 100644 --- a/src/Umbraco.Web/Install/Controllers/InstallApiController.cs +++ b/src/Umbraco.Web/Install/Controllers/InstallApiController.cs @@ -5,7 +5,6 @@ using System.Reflection; using System.Web.Http; using Newtonsoft.Json.Linq; using Umbraco.Core; -using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Migrations.Install; using Umbraco.Web.Install.Models; @@ -18,18 +17,18 @@ namespace Umbraco.Web.Install.Controllers public class InstallApiController : ApiController { private readonly DatabaseBuilder _databaseBuilder; - private readonly ProfilingLogger _proflog; + private readonly IProfilingLogger _proflog; private readonly InstallStepCollection _installSteps; private readonly ILogger _logger; - public InstallApiController(UmbracoContext umbracoContext, DatabaseBuilder databaseBuilder, ProfilingLogger proflog, InstallHelper installHelper, InstallStepCollection installSteps) + public InstallApiController(UmbracoContext umbracoContext, DatabaseBuilder databaseBuilder, IProfilingLogger proflog, InstallHelper installHelper, InstallStepCollection installSteps) { UmbracoContext = umbracoContext ?? throw new ArgumentNullException(nameof(umbracoContext)); _databaseBuilder = databaseBuilder ?? throw new ArgumentNullException(nameof(databaseBuilder)); _proflog = proflog ?? throw new ArgumentNullException(nameof(proflog)); _installSteps = installSteps; InstallHelper = installHelper; - _logger = _proflog.Logger; + _logger = _proflog; } /// diff --git a/src/Umbraco.Web/Macros/MacroRenderer.cs b/src/Umbraco.Web/Macros/MacroRenderer.cs index 5ba9de6577..3cc890c67a 100755 --- a/src/Umbraco.Web/Macros/MacroRenderer.cs +++ b/src/Umbraco.Web/Macros/MacroRenderer.cs @@ -567,7 +567,7 @@ namespace Umbraco.Web.Macros private static readonly Regex HrefRegex = new Regex("href=\"([^\"]*)\"", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); - public static string GetRenderedMacro(int macroId, Hashtable elements, Hashtable attributes, int pageId, IMacroService macroService, ProfilingLogger plogger) + public static string GetRenderedMacro(int macroId, Hashtable elements, Hashtable attributes, int pageId, IMacroService macroService, IProfilingLogger plogger) { var m = macroService.GetById(macroId); if (m == null) return string.Empty; diff --git a/src/Umbraco.Web/Mvc/PluginController.cs b/src/Umbraco.Web/Mvc/PluginController.cs index 6590206223..e82d7437e2 100644 --- a/src/Umbraco.Web/Mvc/PluginController.cs +++ b/src/Umbraco.Web/Mvc/PluginController.cs @@ -60,7 +60,7 @@ namespace Umbraco.Web.Mvc /// /// Gets or sets the profiling logger. /// - public ProfilingLogger ProfilingLogger { get; } + public IProfilingLogger ProfilingLogger { get; } /// /// Gets the membership helper. @@ -95,12 +95,12 @@ namespace Umbraco.Web.Mvc Current.Container.GetInstance(), Current.Container.GetInstance(), Current.Container.GetInstance(), - Current.Container.GetInstance() + Current.Container.GetInstance() ) { } - protected PluginController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger) + protected PluginController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, CacheHelper applicationCache, ILogger logger, IProfilingLogger profilingLogger) { UmbracoContext = umbracoContext; DatabaseFactory = databaseFactory; diff --git a/src/Umbraco.Web/Mvc/RenderMvcController.cs b/src/Umbraco.Web/Mvc/RenderMvcController.cs index 7262541610..eb824c0980 100644 --- a/src/Umbraco.Web/Mvc/RenderMvcController.cs +++ b/src/Umbraco.Web/Mvc/RenderMvcController.cs @@ -26,7 +26,7 @@ namespace Umbraco.Web.Mvc ActionInvoker = new RenderActionInvoker(); } - public RenderMvcController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger) + public RenderMvcController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, IProfilingLogger profilingLogger) : base(globalSettings, umbracoContext, services, applicationCache, logger, profilingLogger) { ActionInvoker = new RenderActionInvoker(); diff --git a/src/Umbraco.Web/Mvc/SurfaceController.cs b/src/Umbraco.Web/Mvc/SurfaceController.cs index c01196a4e0..b3e67e4b2b 100644 --- a/src/Umbraco.Web/Mvc/SurfaceController.cs +++ b/src/Umbraco.Web/Mvc/SurfaceController.cs @@ -21,7 +21,7 @@ namespace Umbraco.Web.Mvc { } - protected SurfaceController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger) + protected SurfaceController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, CacheHelper applicationCache, ILogger logger, IProfilingLogger profilingLogger) : base(umbracoContext, databaseFactory, services, applicationCache, logger, profilingLogger) { } diff --git a/src/Umbraco.Web/Mvc/UmbracoAuthorizedController.cs b/src/Umbraco.Web/Mvc/UmbracoAuthorizedController.cs index aba498530a..2f8f7a6e76 100644 --- a/src/Umbraco.Web/Mvc/UmbracoAuthorizedController.cs +++ b/src/Umbraco.Web/Mvc/UmbracoAuthorizedController.cs @@ -20,7 +20,7 @@ namespace Umbraco.Web.Mvc protected UmbracoAuthorizedController() { } - protected UmbracoAuthorizedController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger) + protected UmbracoAuthorizedController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, IProfilingLogger profilingLogger) : base(globalSettings, umbracoContext, services, applicationCache, logger, profilingLogger) { } } diff --git a/src/Umbraco.Web/Mvc/UmbracoController.cs b/src/Umbraco.Web/Mvc/UmbracoController.cs index b3c62abec0..a7dd23b1ea 100644 --- a/src/Umbraco.Web/Mvc/UmbracoController.cs +++ b/src/Umbraco.Web/Mvc/UmbracoController.cs @@ -58,7 +58,7 @@ namespace Umbraco.Web.Mvc /// /// Gets or sets the profiling logger. /// - public ProfilingLogger ProfilingLogger { get; set; } + public IProfilingLogger ProfilingLogger { get; set; } protected IOwinContext OwinContext => Request.GetOwinContext(); @@ -85,12 +85,12 @@ namespace Umbraco.Web.Mvc Current.Container.GetInstance(), Current.Container.GetInstance(), Current.Container.GetInstance(), - Current.Container.GetInstance() + Current.Container.GetInstance() ) { } - protected UmbracoController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger) + protected UmbracoController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, IProfilingLogger profilingLogger) { GlobalSettings = globalSettings; UmbracoContext = umbracoContext; diff --git a/src/Umbraco.Web/Mvc/UmbracoPageResult.cs b/src/Umbraco.Web/Mvc/UmbracoPageResult.cs index f23407ab4c..9769945f37 100644 --- a/src/Umbraco.Web/Mvc/UmbracoPageResult.cs +++ b/src/Umbraco.Web/Mvc/UmbracoPageResult.cs @@ -15,9 +15,9 @@ namespace Umbraco.Web.Mvc /// public class UmbracoPageResult : ActionResult { - private readonly ProfilingLogger _profilingLogger; + private readonly IProfilingLogger _profilingLogger; - public UmbracoPageResult(ProfilingLogger profilingLogger) + public UmbracoPageResult(IProfilingLogger profilingLogger) { _profilingLogger = profilingLogger; } diff --git a/src/Umbraco.Web/PropertyEditors/ValueConverters/NestedContentManyValueConverter.cs b/src/Umbraco.Web/PropertyEditors/ValueConverters/NestedContentManyValueConverter.cs index fee6ee8f8a..93e4afc7e5 100644 --- a/src/Umbraco.Web/PropertyEditors/ValueConverters/NestedContentManyValueConverter.cs +++ b/src/Umbraco.Web/PropertyEditors/ValueConverters/NestedContentManyValueConverter.cs @@ -16,12 +16,12 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters /// public class NestedContentManyValueConverter : NestedContentValueConverterBase { - private readonly ProfilingLogger _proflog; + private readonly IProfilingLogger _proflog; /// /// Initializes a new instance of the class. /// - public NestedContentManyValueConverter(IPublishedSnapshotAccessor publishedSnapshotAccessor, IPublishedModelFactory publishedModelFactory, ProfilingLogger proflog) + public NestedContentManyValueConverter(IPublishedSnapshotAccessor publishedSnapshotAccessor, IPublishedModelFactory publishedModelFactory, IProfilingLogger proflog) : base(publishedSnapshotAccessor, publishedModelFactory) { _proflog = proflog; diff --git a/src/Umbraco.Web/PropertyEditors/ValueConverters/NestedContentSingleValueConverter.cs b/src/Umbraco.Web/PropertyEditors/ValueConverters/NestedContentSingleValueConverter.cs index 52d6c7d53a..e084b3a343 100644 --- a/src/Umbraco.Web/PropertyEditors/ValueConverters/NestedContentSingleValueConverter.cs +++ b/src/Umbraco.Web/PropertyEditors/ValueConverters/NestedContentSingleValueConverter.cs @@ -15,12 +15,12 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters /// public class NestedContentSingleValueConverter : NestedContentValueConverterBase { - private readonly ProfilingLogger _proflog; + private readonly IProfilingLogger _proflog; /// /// Initializes a new instance of the class. /// - public NestedContentSingleValueConverter(IPublishedSnapshotAccessor publishedSnapshotAccessor, IPublishedModelFactory publishedModelFactory, ProfilingLogger proflog) + public NestedContentSingleValueConverter(IPublishedSnapshotAccessor publishedSnapshotAccessor, IPublishedModelFactory publishedModelFactory, IProfilingLogger proflog) : base(publishedSnapshotAccessor, publishedModelFactory) { _proflog = proflog; diff --git a/src/Umbraco.Web/Routing/PublishedRouter.cs b/src/Umbraco.Web/Routing/PublishedRouter.cs index 80986e2943..387ec8b579 100644 --- a/src/Umbraco.Web/Routing/PublishedRouter.cs +++ b/src/Umbraco.Web/Routing/PublishedRouter.cs @@ -27,7 +27,7 @@ namespace Umbraco.Web.Routing private readonly ContentFinderCollection _contentFinders; private readonly IContentLastChanceFinder _contentLastChanceFinder; private readonly ServiceContext _services; - private readonly ProfilingLogger _profilingLogger; + private readonly IProfilingLogger _profilingLogger; private readonly IVariationContextAccessor _variationContextAccessor; private readonly ILogger _logger; @@ -40,7 +40,7 @@ namespace Umbraco.Web.Routing IContentLastChanceFinder contentLastChanceFinder, IVariationContextAccessor variationContextAccessor, ServiceContext services, - ProfilingLogger proflog, + IProfilingLogger proflog, Func> getRolesForLogin = null) { _webRoutingSection = webRoutingSection ?? throw new ArgumentNullException(nameof(webRoutingSection)); @@ -49,7 +49,7 @@ namespace Umbraco.Web.Routing _services = services ?? throw new ArgumentNullException(nameof(services)); _profilingLogger = proflog ?? throw new ArgumentNullException(nameof(proflog)); _variationContextAccessor = variationContextAccessor ?? throw new ArgumentNullException(nameof(variationContextAccessor)); - _logger = proflog.Logger; + _logger = proflog; GetRolesForLogin = getRolesForLogin ?? (s => Roles.Provider.GetRolesForUser(s)); } diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs index c3c74f0c0b..25b14ecadf 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs @@ -86,10 +86,6 @@ namespace Umbraco.Web.Runtime container.RegisterSingleton(); container.RegisterSingleton(); - var typeLoader = container.GetInstance(); - var logger = container.GetInstance(); - var proflog = container.GetInstance(); - // register the http context and umbraco context accessors // we *should* use the HttpContextUmbracoContextAccessor, however there are cases when // we have no http context, eg when booting Umbraco or in background threads, so instead @@ -126,14 +122,14 @@ namespace Umbraco.Web.Runtime // configure the container for web container.ConfigureForWeb(); composition - .ComposeMvcControllers(typeLoader, GetType().Assembly) - .ComposeApiControllers(typeLoader, GetType().Assembly); + .ComposeMvcControllers(GetType().Assembly) + .ComposeApiControllers(GetType().Assembly); composition.GetCollectionBuilder() - .Add(() => typeLoader.GetTypes()); // fixme which searchable trees?! + .Add(() => composition.TypeLoader.GetTypes()); // fixme which searchable trees?! composition.GetCollectionBuilder() - .Add(() => typeLoader.GetTypes()); + .Add(() => composition.TypeLoader.GetTypes()); composition.GetCollectionBuilder(); @@ -143,12 +139,12 @@ namespace Umbraco.Web.Runtime Current.DefaultRenderMvcControllerType = typeof(RenderMvcController); // fixme WRONG! composition.GetCollectionBuilder() - .Add(() => typeLoader.GetTypes()); + .Add(() => composition.TypeLoader.GetTypes()); - var surfaceControllerTypes = new SurfaceControllerTypeCollection(typeLoader.GetSurfaceControllers()); + var surfaceControllerTypes = new SurfaceControllerTypeCollection(composition.TypeLoader.GetSurfaceControllers()); container.RegisterInstance(surfaceControllerTypes); - var umbracoApiControllerTypes = new UmbracoApiControllerTypeCollection(typeLoader.GetUmbracoApiControllers()); + var umbracoApiControllerTypes = new UmbracoApiControllerTypeCollection(composition.TypeLoader.GetUmbracoApiControllers()); container.RegisterInstance(umbracoApiControllerTypes); // both TinyMceValueConverter (in Core) and RteMacroRenderingValueConverter (in Web) will be @@ -156,7 +152,7 @@ namespace Umbraco.Web.Runtime // here because there cannot be two converters for one property editor - and we want the full // RteMacroRenderingValueConverter that converts macros, etc. So remove TinyMceValueConverter. // (the limited one, defined in Core, is there for tests) - same for others - container.GetInstance() + composition.GetCollectionBuilder() .Remove() .Remove() .Remove(); @@ -189,10 +185,10 @@ namespace Umbraco.Web.Runtime // register *all* checks, except those marked [HideFromTypeFinder] of course composition.GetCollectionBuilder() - .Add(() => typeLoader.GetTypes()); + .Add(() => composition.TypeLoader.GetTypes()); composition.GetCollectionBuilder() - .Add(() => typeLoader.GetTypes()); + .Add(() => composition.TypeLoader.GetTypes()); // auto-register views container.RegisterAuto(typeof(UmbracoViewPage<>)); diff --git a/src/Umbraco.Web/Scheduling/HealthCheckNotifier.cs b/src/Umbraco.Web/Scheduling/HealthCheckNotifier.cs index 89fba7717d..163549d6c7 100644 --- a/src/Umbraco.Web/Scheduling/HealthCheckNotifier.cs +++ b/src/Umbraco.Web/Scheduling/HealthCheckNotifier.cs @@ -15,12 +15,12 @@ namespace Umbraco.Web.Scheduling private readonly HealthCheckCollection _healthChecks; private readonly HealthCheckNotificationMethodCollection _notifications; private readonly ILogger _logger; - private readonly ProfilingLogger _proflog; + private readonly IProfilingLogger _proflog; public HealthCheckNotifier(IBackgroundTaskRunner runner, int delayMilliseconds, int periodMilliseconds, HealthCheckCollection healthChecks, HealthCheckNotificationMethodCollection notifications, IRuntimeState runtimeState, - ILogger logger, ProfilingLogger proflog) + ILogger logger, IProfilingLogger proflog) : base(runner, delayMilliseconds, periodMilliseconds) { _healthChecks = healthChecks; diff --git a/src/Umbraco.Web/Scheduling/KeepAlive.cs b/src/Umbraco.Web/Scheduling/KeepAlive.cs index 24f6775166..7ef1ec6453 100644 --- a/src/Umbraco.Web/Scheduling/KeepAlive.cs +++ b/src/Umbraco.Web/Scheduling/KeepAlive.cs @@ -13,10 +13,10 @@ namespace Umbraco.Web.Scheduling private readonly IRuntimeState _runtime; private readonly ILogger _logger; private static HttpClient _httpClient; - private readonly ProfilingLogger _proflog; + private readonly IProfilingLogger _proflog; public KeepAlive(IBackgroundTaskRunner runner, int delayMilliseconds, int periodMilliseconds, - IRuntimeState runtime, ILogger logger, ProfilingLogger proflog) + IRuntimeState runtime, ILogger logger, IProfilingLogger proflog) : base(runner, delayMilliseconds, periodMilliseconds) { _runtime = runtime; diff --git a/src/Umbraco.Web/Scheduling/LogScrubber.cs b/src/Umbraco.Web/Scheduling/LogScrubber.cs index ae73da04c8..d5cd114977 100644 --- a/src/Umbraco.Web/Scheduling/LogScrubber.cs +++ b/src/Umbraco.Web/Scheduling/LogScrubber.cs @@ -17,11 +17,11 @@ namespace Umbraco.Web.Scheduling private readonly IAuditService _auditService; private readonly IUmbracoSettingsSection _settings; private readonly ILogger _logger; - private readonly ProfilingLogger _proflog; + private readonly IProfilingLogger _proflog; private readonly IScopeProvider _scopeProvider; public LogScrubber(IBackgroundTaskRunner runner, int delayMilliseconds, int periodMilliseconds, - IRuntimeState runtime, IAuditService auditService, IUmbracoSettingsSection settings, IScopeProvider scopeProvider, ILogger logger, ProfilingLogger proflog) + IRuntimeState runtime, IAuditService auditService, IUmbracoSettingsSection settings, IScopeProvider scopeProvider, ILogger logger, IProfilingLogger proflog) : base(runner, delayMilliseconds, periodMilliseconds) { _runtime = runtime; diff --git a/src/Umbraco.Web/Scheduling/ScheduledTasks.cs b/src/Umbraco.Web/Scheduling/ScheduledTasks.cs index 49fa1e469b..1d0ebb5364 100644 --- a/src/Umbraco.Web/Scheduling/ScheduledTasks.cs +++ b/src/Umbraco.Web/Scheduling/ScheduledTasks.cs @@ -21,11 +21,11 @@ namespace Umbraco.Web.Scheduling private readonly IRuntimeState _runtime; private readonly IUmbracoSettingsSection _settings; private readonly ILogger _logger; - private readonly ProfilingLogger _proflog; + private readonly IProfilingLogger _proflog; private static readonly Hashtable ScheduledTaskTimes = new Hashtable(); public ScheduledTasks(IBackgroundTaskRunner runner, int delayMilliseconds, int periodMilliseconds, - IRuntimeState runtime, IUmbracoSettingsSection settings, ILogger logger, ProfilingLogger proflog) + IRuntimeState runtime, IUmbracoSettingsSection settings, ILogger logger, IProfilingLogger proflog) : base(runner, delayMilliseconds, periodMilliseconds) { _runtime = runtime; @@ -71,7 +71,7 @@ namespace Umbraco.Web.Scheduling { BaseAddress = _runtime.ApplicationUrl }; - + var request = new HttpRequestMessage(HttpMethod.Get, url); //TODO: pass custom the authorization header, currently these aren't really secured! diff --git a/src/Umbraco.Web/Scheduling/SchedulerComponent.cs b/src/Umbraco.Web/Scheduling/SchedulerComponent.cs index d14a7bb34f..a9e8016485 100644 --- a/src/Umbraco.Web/Scheduling/SchedulerComponent.cs +++ b/src/Umbraco.Web/Scheduling/SchedulerComponent.cs @@ -28,7 +28,7 @@ namespace Umbraco.Web.Scheduling private IContentService _contentService; private IAuditService _auditService; private ILogger _logger; - private ProfilingLogger _proflog; + private IProfilingLogger _proflog; private IScopeProvider _scopeProvider; private HealthCheckCollection _healthChecks; private HealthCheckNotificationMethodCollection _notifications; @@ -46,7 +46,7 @@ namespace Umbraco.Web.Scheduling public void Initialize(IRuntimeState runtime, IContentService contentService, IAuditService auditService, HealthCheckCollection healthChecks, HealthCheckNotificationMethodCollection notifications, - IScopeProvider scopeProvider, ILogger logger, ProfilingLogger proflog) + IScopeProvider scopeProvider, ILogger logger, IProfilingLogger proflog) { _runtime = runtime; _contentService = contentService; @@ -130,7 +130,7 @@ namespace Umbraco.Web.Scheduling private IBackgroundTask RegisterHealthCheckNotifier(IHealthChecks healthCheckConfig, HealthCheckCollection healthChecks, HealthCheckNotificationMethodCollection notifications, - ILogger logger, ProfilingLogger proflog) + ILogger logger, IProfilingLogger proflog) { // If first run time not set, start with just small delay after application start int delayInMilliseconds; diff --git a/src/Umbraco.Web/Search/ExamineComponent.cs b/src/Umbraco.Web/Search/ExamineComponent.cs index 7a036ef712..a4f4a38695 100644 --- a/src/Umbraco.Web/Search/ExamineComponent.cs +++ b/src/Umbraco.Web/Search/ExamineComponent.cs @@ -49,7 +49,7 @@ namespace Umbraco.Web.Search // but greater that SafeXmlReaderWriter priority which is 60 private const int EnlistPriority = 80; - internal void Initialize(IRuntimeState runtime, MainDom mainDom, PropertyEditorCollection propertyEditors, IExamineManager examineManager, ProfilingLogger profilingLogger, IScopeProvider scopeProvider, UrlSegmentProviderCollection urlSegmentProviderCollection, ServiceContext services) + internal void Initialize(IRuntimeState runtime, MainDom mainDom, PropertyEditorCollection propertyEditors, IExamineManager examineManager, IProfilingLogger profilingLogger, IScopeProvider scopeProvider, UrlSegmentProviderCollection urlSegmentProviderCollection, ServiceContext services) { _services = services; _urlSegmentProviders = urlSegmentProviderCollection; @@ -68,7 +68,7 @@ namespace Umbraco.Web.Search var simpleFsLockFactory = new NoPrefixSimpleFsLockFactory(d); return simpleFsLockFactory; }; - + //let's deal with shutting down Examine with MainDom var examineShutdownRegistered = mainDom.Register(() => { @@ -80,7 +80,7 @@ namespace Umbraco.Web.Search if (!examineShutdownRegistered) { - profilingLogger.Logger.Debug("Examine shutdown not registered, this appdomain is not the MainDom, Examine will be disabled"); + profilingLogger.Debug("Examine shutdown not registered, this appdomain is not the MainDom, Examine will be disabled"); //if we could not register the shutdown examine ourselves, it means we are not maindom! in this case all of examine should be disabled! Suspendable.ExamineEvents.SuspendIndexers(); @@ -88,17 +88,17 @@ namespace Umbraco.Web.Search return; //exit, do not continue } - profilingLogger.Logger.Debug("Examine shutdown registered with MainDom"); + profilingLogger.Debug("Examine shutdown registered with MainDom"); var registeredIndexers = examineManager.IndexProviders.Values.OfType().Count(x => x.EnableDefaultEventHandler); - profilingLogger.Logger.Info("Adding examine event handlers for {RegisteredIndexers} index providers.", registeredIndexers); + profilingLogger.Info("Adding examine event handlers for {RegisteredIndexers} index providers.", registeredIndexers); // don't bind event handlers if we're not suppose to listen if (registeredIndexers == 0) return; - BindGridToExamine(profilingLogger.Logger, examineManager, propertyEditors); + BindGridToExamine(profilingLogger, examineManager, propertyEditors); // bind to distributed cache events - this ensures that this logic occurs on ALL servers // that are taking part in a load balanced environment. @@ -107,9 +107,9 @@ namespace Umbraco.Web.Search MediaCacheRefresher.CacheUpdated += MediaCacheRefresherUpdated; MemberCacheRefresher.CacheUpdated += MemberCacheRefresherUpdated; - EnsureUnlocked(profilingLogger.Logger, examineManager); + EnsureUnlocked(profilingLogger, examineManager); - RebuildIndexesOnStartup(profilingLogger.Logger); + RebuildIndexesOnStartup(profilingLogger); } /// @@ -333,9 +333,9 @@ namespace Umbraco.Web.Search if (args.MessageType != MessageType.RefreshByPayload) throw new NotSupportedException(); - + var changedIds = new Dictionary removedIds, List refreshedIds, List otherIds)>(); - + foreach (var payload in (ContentTypeCacheRefresher.JsonPayload[])args.MessageObject) { if (!changedIds.TryGetValue(payload.ItemType, out var idLists)) @@ -545,7 +545,7 @@ namespace Umbraco.Web.Search var total = long.MaxValue; while(page * pageSize < total) { - var descendants = contentService.GetPagedDescendants(content.Id, page++, pageSize, out total, + var descendants = contentService.GetPagedDescendants(content.Id, page++, pageSize, out total, //order by shallowest to deepest, this allows us to check it's published state without checking every item ordering: Ordering.By("Path", Direction.Ascending)); @@ -642,7 +642,7 @@ namespace Umbraco.Web.Search if (actions != null) actions.Add(new DeferedDeleteIndex(this, entityId, keepIfUnpublished)); else - DeferedDeleteIndex.Execute(this, entityId, keepIfUnpublished); + DeferedDeleteIndex.Execute(this, entityId, keepIfUnpublished); } private class DeferedActions @@ -686,7 +686,7 @@ namespace Umbraco.Web.Search private readonly bool? _supportUnpublished; public DeferedReIndexForContent(ExamineComponent examineComponent, IContent content, bool? supportUnpublished) - { + { _examineComponent = examineComponent; _content = content; _supportUnpublished = supportUnpublished; diff --git a/src/Umbraco.Web/TagsController.cs b/src/Umbraco.Web/TagsController.cs index fe448690d5..a85b37c545 100644 --- a/src/Umbraco.Web/TagsController.cs +++ b/src/Umbraco.Web/TagsController.cs @@ -24,7 +24,7 @@ namespace Umbraco.Web.WebServices { } - public TagsController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger, IRuntimeState runtimeState) + public TagsController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, IProfilingLogger profilingLogger, IRuntimeState runtimeState) : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, profilingLogger, runtimeState) { } diff --git a/src/Umbraco.Web/WebApi/UmbracoApiController.cs b/src/Umbraco.Web/WebApi/UmbracoApiController.cs index 4730b7f46f..b35516b59d 100644 --- a/src/Umbraco.Web/WebApi/UmbracoApiController.cs +++ b/src/Umbraco.Web/WebApi/UmbracoApiController.cs @@ -17,7 +17,7 @@ namespace Umbraco.Web.WebApi { } - protected UmbracoApiController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger, IRuntimeState runtimeState) + protected UmbracoApiController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, IProfilingLogger profilingLogger, IRuntimeState runtimeState) : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, profilingLogger, runtimeState) { } diff --git a/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs b/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs index c1ec6332ee..2e5e4b81c3 100644 --- a/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs +++ b/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs @@ -67,7 +67,7 @@ namespace Umbraco.Web.WebApi /// /// Gets or sets the profiling logger. /// - public ProfilingLogger ProfilingLogger { get; } + public IProfilingLogger ProfilingLogger { get; } /// /// Gets or sets the runtime state. @@ -103,14 +103,14 @@ namespace Umbraco.Web.WebApi Current.Container.GetInstance(), Current.Container.GetInstance(), Current.Container.GetInstance(), - Current.Container.GetInstance(), + Current.Container.GetInstance(), Current.Container.GetInstance() ) { } // fixme - Inject fewer things? (Aggregate more) - protected UmbracoApiControllerBase(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger, IRuntimeState runtimeState) + protected UmbracoApiControllerBase(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, IProfilingLogger profilingLogger, IRuntimeState runtimeState) { GlobalSettings = globalSettings; UmbracoContext = umbracoContext; diff --git a/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs b/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs index 6211736a4a..82c172af79 100644 --- a/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs +++ b/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs @@ -36,7 +36,7 @@ namespace Umbraco.Web.WebApi protected UmbracoAuthorizedApiController() { } - protected UmbracoAuthorizedApiController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, ProfilingLogger profilingLogger, IRuntimeState runtimeState) + protected UmbracoAuthorizedApiController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, IProfilingLogger profilingLogger, IRuntimeState runtimeState) : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, profilingLogger, runtimeState) { } } From 5d167b49a4f451b778a419b28fb4f2a8df70b094 Mon Sep 17 00:00:00 2001 From: Stephan Date: Tue, 27 Nov 2018 15:09:08 +0100 Subject: [PATCH 100/469] More composition fixes --- src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs | 1 + .../Migrations/Upgrade/V_8_0_0/DropTaskTables.cs | 6 +++--- .../Migrations/Upgrade/V_8_0_0/RefactorVariantsModel.cs | 3 ++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs b/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs index ec49544976..53a86f3524 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs @@ -144,6 +144,7 @@ namespace Umbraco.Core.Migrations.Upgrade Chain("{EE429F1B-9B26-43CA-89F8-A86017C809A3}"); Chain("{08919C4B-B431-449C-90EC-2B8445B5C6B1}"); Chain("{7EB0254C-CB8B-4C75-B15B-D48C55B449EB}"); + Chain("{648A2D5F-7467-48F8-B309-E99CEEE00E2A}"); // fixed version //FINAL diff --git a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropTaskTables.cs b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropTaskTables.cs index e8fd4f409e..008b3e4b5f 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropTaskTables.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropTaskTables.cs @@ -9,10 +9,10 @@ public override void Migrate() { - if (TableExists("cmsTaskType")) - Delete.Table("cmsTaskType"); if (TableExists("cmsTask")) - Delete.Table("cmsTask"); + Delete.Table("cmsTask").Do(); + if (TableExists("cmsTaskType")) + Delete.Table("cmsTaskType").Do(); } } } diff --git a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/RefactorVariantsModel.cs b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/RefactorVariantsModel.cs index aa498583ff..6ddd49841d 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/RefactorVariantsModel.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/RefactorVariantsModel.cs @@ -11,7 +11,8 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0 public override void Migrate() { - Delete.Column("edited").FromTable(Constants.DatabaseSchema.Tables.ContentVersionCultureVariation).Do(); + if (ColumnExists(Constants.DatabaseSchema.Tables.ContentVersionCultureVariation, "edited")) + Delete.Column("edited").FromTable(Constants.DatabaseSchema.Tables.ContentVersionCultureVariation).Do(); // add available column From b365539368e380c1a5e9eb4acf145b24db46c5ad Mon Sep 17 00:00:00 2001 From: Stephan Date: Tue, 27 Nov 2018 15:15:44 +0100 Subject: [PATCH 101/469] Optimize --- src/Umbraco.Core/Components/Components.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Core/Components/Components.cs b/src/Umbraco.Core/Components/Components.cs index 155674782e..cb73e9cc5c 100644 --- a/src/Umbraco.Core/Components/Components.cs +++ b/src/Umbraco.Core/Components/Components.cs @@ -274,10 +274,17 @@ namespace Umbraco.Core.Components private void InstantiateComponents(IEnumerable types) { + IUmbracoComponent InstantiateComponent(Type type) + { + var ctor = type.GetConstructor(Array.Empty()); + if (ctor == null) + throw new InvalidOperationException($"Component {type.FullName} does not have a parameter-less."); + return (IUmbracoComponent) ctor.Invoke(Array.Empty()); + } + using (_logger.DebugDuration("Instantiating components.", "Instantiated components.")) { - // fixme is there a faster way? - _components = types.Select(x => (IUmbracoComponent) Activator.CreateInstance(x)).ToArray(); + _components = types.Select(InstantiateComponent).ToArray(); } } From de8dbe004157ce5cb93a1a96dd2f54f710c693d2 Mon Sep 17 00:00:00 2001 From: Stephan Date: Tue, 27 Nov 2018 15:17:26 +0100 Subject: [PATCH 102/469] Cleanup --- src/Umbraco.Core/Components/Composition.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Core/Components/Composition.cs b/src/Umbraco.Core/Components/Composition.cs index 412008c175..4a6c312968 100644 --- a/src/Umbraco.Core/Components/Composition.cs +++ b/src/Umbraco.Core/Components/Composition.cs @@ -29,8 +29,8 @@ namespace Umbraco.Core.Components RuntimeLevel = level; } - // fixme / tests - public Composition(IContainer container, RuntimeLevel level) + // used for tests + internal Composition(IContainer container, RuntimeLevel level) { Container = container; RuntimeLevel = level; From 80f3fc68649b0543e431e9ea3cf3d1f0aa0ccec8 Mon Sep 17 00:00:00 2001 From: Stephan Date: Tue, 27 Nov 2018 15:20:26 +0100 Subject: [PATCH 103/469] Get rid of IContainer.GetRegistered --- .../Composing/ContainerExtensions.cs | 8 ----- src/Umbraco.Core/Composing/IContainer.cs | 9 +----- .../LightInject/LightInjectContainer.cs | 4 --- src/Umbraco.Core/Composing/Registration.cs | 31 ------------------- src/Umbraco.Core/Umbraco.Core.csproj | 1 - 5 files changed, 1 insertion(+), 52 deletions(-) delete mode 100644 src/Umbraco.Core/Composing/Registration.cs diff --git a/src/Umbraco.Core/Composing/ContainerExtensions.cs b/src/Umbraco.Core/Composing/ContainerExtensions.cs index 789cdf6366..047bcd2ae5 100644 --- a/src/Umbraco.Core/Composing/ContainerExtensions.cs +++ b/src/Umbraco.Core/Composing/ContainerExtensions.cs @@ -33,14 +33,6 @@ namespace Umbraco.Core.Composing public static T TryGetInstance(this IContainer container) => (T) container.TryGetInstance(typeof(T)); - /// - /// Gets registrations for a service. - /// - /// The type of the service. - /// The registrations for the service. - public static IEnumerable GetRegistered(this IContainer container) - => container.GetRegistered(typeof(TService)); - /// /// Creates an instance with arguments. /// diff --git a/src/Umbraco.Core/Composing/IContainer.cs b/src/Umbraco.Core/Composing/IContainer.cs index d068339eb1..4975f5d08d 100644 --- a/src/Umbraco.Core/Composing/IContainer.cs +++ b/src/Umbraco.Core/Composing/IContainer.cs @@ -61,13 +61,6 @@ namespace Umbraco.Core.Composing /// The type of the service. IEnumerable GetAllInstances(); - /// - /// Gets registrations for a service. - /// - /// The type of the service. - /// The registrations for the service. - IEnumerable GetRegistered(Type serviceType); - /// /// Releases an instance. /// @@ -76,7 +69,7 @@ namespace Umbraco.Core.Composing /// See https://stackoverflow.com/questions/14072208 and http://kozmic.net/2010/08/27/must-i-release-everything-when-using-windsor/, /// you only need to release instances you specifically resolved, and even then, if done right, that might never be needed. For /// instance, LightInject does not require this and does not support it - should work with scopes. - /// + /// void Release(object instance); #endregion diff --git a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs index 90c2903bc7..e3b93f5aea 100644 --- a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs +++ b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs @@ -117,10 +117,6 @@ namespace Umbraco.Core.Composing.LightInject public IEnumerable GetAllInstances(Type type) => Container.GetAllInstances(type); - /// - public IEnumerable GetRegistered(Type type) - => Container.AvailableServices.Where(x => x.ServiceType == type).Select(x => new Registration(x.ServiceType, x.ServiceName)); - /// public void Release(object instance) { diff --git a/src/Umbraco.Core/Composing/Registration.cs b/src/Umbraco.Core/Composing/Registration.cs deleted file mode 100644 index a3cb62522b..0000000000 --- a/src/Umbraco.Core/Composing/Registration.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; - -namespace Umbraco.Core.Composing -{ - /// - /// Represents a service registration in the container. - /// - public class Registration - { - /// - /// Initializes a new instance of the class. - /// - /// - /// - public Registration(Type serviceType, string serviceName) - { - ServiceType = serviceType; - ServiceName = serviceName; - } - - /// - /// Gets the service type. - /// - public Type ServiceType { get; } - - /// - /// Gets the service name. - /// - public string ServiceName { get; } - } -} diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 57f7208d03..2e235dcd23 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -190,7 +190,6 @@ - From f290065bb6aa62d6f4a08270dfc26805b639f792 Mon Sep 17 00:00:00 2001 From: Stephan Date: Tue, 27 Nov 2018 16:27:16 +0100 Subject: [PATCH 104/469] More container tests --- src/Umbraco.Tests/Composing/ContainerTests.cs | 168 +++++++++++++++++- 1 file changed, 165 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Tests/Composing/ContainerTests.cs b/src/Umbraco.Tests/Composing/ContainerTests.cs index 6f4a21ca5f..62080ef626 100644 --- a/src/Umbraco.Tests/Composing/ContainerTests.cs +++ b/src/Umbraco.Tests/Composing/ContainerTests.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using NUnit.Framework; using Umbraco.Core.Composing; @@ -14,7 +15,154 @@ namespace Umbraco.Tests.Composing private IContainer GetContainer() => LightInjectContainer.Create(); [Test] - public void CanGetEnumerable() + public void CanRegisterAndGet() + { + var container = GetContainer(); + + container.Register(); + + var thing = container.GetInstance(); + Assert.IsNotNull(thing); + Assert.IsInstanceOf(thing); + } + + [Test] + public void CanRegisterAndGetLazy() + { + var container = GetContainer(); + + container.Register(); + + var lazyThing = container.GetInstance>(); + Assert.IsNotNull(lazyThing); + Assert.IsInstanceOf>(lazyThing); + var thing = lazyThing.Value; + Assert.IsNotNull(thing); + Assert.IsInstanceOf(thing); + } + + [Test] + public void CannotRegistedAndGetBase() + { + var container = GetContainer(); + + container.Register(); + + Assert.IsNull(container.TryGetInstance()); + } + + [Test] + public void CannotRegisterAndGetInterface() + { + var container = GetContainer(); + + container.Register(); + + Assert.IsNull(container.TryGetInstance()); + } + + [Test] + public void CanRegisterAndGetAllBase() + { + var container = GetContainer(); + + container.Register(); + + var things = container.GetAllInstances(); + Assert.AreEqual(1, things.Count()); + + // lightInject: would be zero with option EnableVariance set to false + } + + [Test] + public void CanRegisterAndGetAllInterface() + { + var container = GetContainer(); + + container.Register(); + + var things = container.GetAllInstances(); + Assert.AreEqual(1, things.Count()); + + // lightInject: would be zero with option EnableVariance set to false + } + + [Test] + public void CanRegisterBaseAndGet() + { + var container = GetContainer(); + + container.Register(); + + var thing = container.GetInstance(); + Assert.IsNotNull(thing); + Assert.IsInstanceOf(thing); + } + + [Test] + public void CanRegisterInterfaceAndGet() + { + var container = GetContainer(); + + container.Register(); + + var thing = container.GetInstance(); + Assert.IsNotNull(thing); + Assert.IsInstanceOf(thing); + } + + [Test] + public void NonSingletonServiceIsNotUnique() + { + var container = GetContainer(); + + container.Register(); + container.Register(); + + var things = container.GetInstance>(); + Assert.AreEqual(2, things.Count()); + + Assert.IsNull(container.TryGetInstance()); + } + + [Test] + public void SingletonServiceIsUnique() + { + var container = GetContainer(); + + // for Core services that ppl may want to redefine in components, + // it is important to be able to have a unique, singleton implementation, + // and to redefine it - how it's done at container's level depends + // on each container + + // redefine the service + container.Register(Lifetime.Singleton); + container.Register(Lifetime.Singleton); + + var things = container.GetInstance>(); + Assert.AreEqual(1, things.Count()); + + var thing = container.GetInstance(); + Assert.IsInstanceOf(thing); + } + + [Test] + public void SingletonImplementationIsNotUnique() + { + var container = GetContainer(); + + // define two implementations + container.Register(Lifetime.Singleton); + container.Register(Lifetime.Singleton); + + var things = container.GetInstance>(); + Assert.AreEqual(2, things.Count()); + + Assert.IsNull(container.TryGetInstance()); + } + + [Test] + public void CanInjectEnumerableOfBase() { var container = GetContainer(); @@ -26,7 +174,21 @@ namespace Umbraco.Tests.Composing Assert.AreEqual(2, needThings.Things.Count()); } - public abstract class ThingBase { } + [Test] + public void CanGetEnumerableOfBase() + { + var container = GetContainer(); + + container.Register(); + container.Register(); + + var things = container.GetInstance>(); + Assert.AreEqual(2, things. Count()); + } + + public interface IThing { } + + public abstract class ThingBase : IThing { } public class Thing1 : ThingBase { } public class Thing2 : ThingBase { } From 49a0b68b285de09934c82c2899d38bd757d15755 Mon Sep 17 00:00:00 2001 From: Stephan Date: Wed, 28 Nov 2018 11:05:41 +0100 Subject: [PATCH 105/469] IContainer is IRegister+IFactory --- src/Umbraco.Core/Components/Components.cs | 17 +- src/Umbraco.Core/Components/Composition.cs | 69 +- .../Components/CompositionExtensions.cs | 56 +- .../Composing/CollectionBuilderBase.cs | 14 +- .../Composers/ConfigurationComposer.cs | 12 +- .../Composers/CoreMappingProfilesComposer.cs | 3 +- .../Composers/FileSystemsComposer.cs | 10 +- .../Composers/RepositoriesComposer.cs | 72 +- .../Composing/Composers/ServicesComposer.cs | 68 +- src/Umbraco.Core/Composing/Current.cs | 74 +- .../Composing/ICollectionBuilder.cs | 4 +- src/Umbraco.Core/Composing/IContainer.cs | 132 +- .../Composing/LazyCollectionBuilderBase.cs | 27 +- .../LightInject/LightInjectContainer.cs | 2 +- .../Composing/OrderedCollectionBuilderBase.cs | 20 - ...nerExtensions.cs => RegisterExtensions.cs} | 28 +- src/Umbraco.Core/Composing/TypeLoader.cs | 16 + src/Umbraco.Core/IO/FileSystems.cs | 4 +- .../Migrations/MigrationBuilder.cs | 4 +- src/Umbraco.Core/Models/Language.cs | 2 +- .../Mappers/MapperCollectionBuilder.cs | 2 +- src/Umbraco.Core/Runtime/CoreRuntime.cs | 7 +- .../Runtime/CoreRuntimeComponent.cs | 38 +- src/Umbraco.Core/Umbraco.Core.csproj | 2 +- .../DistributedCache/DistributedCacheTests.cs | 8 +- .../Components/ComponentTests.cs | 72 +- .../Composing/CollectionBuildersTests.cs | 47 +- .../Composing/ContainerImplementationTests.cs | 2 +- .../Composing/LazyCollectionBuilderTests.cs | 20 +- .../Composing/PackageActionCollectionTests.cs | 7 +- src/Umbraco.Tests/CoreThings/UdiTests.cs | 4 +- .../FrontEnd/UmbracoHelperTests.cs | 4 +- src/Umbraco.Tests/IO/FileSystemsTests.cs | 7 +- src/Umbraco.Tests/IO/ShadowFileSystemTests.cs | 6 +- .../Manifest/ManifestParserTests.cs | 2 +- src/Umbraco.Tests/Models/VariationTests.cs | 2 +- .../PropertyEditors/ImageCropperTest.cs | 7 +- .../PropertyEditorValueEditorTests.cs | 3 +- .../Published/ConvertersTests.cs | 13 +- .../PublishedContentLanguageVariantTests.cs | 2 +- .../PublishedContentMoreTests.cs | 2 +- .../PublishedContentSnapshotTestBase.cs | 6 +- .../PublishedContent/PublishedContentTests.cs | 8 +- .../Runtimes/CoreRuntimeTests.cs | 6 +- .../Scoping/ScopeEventDispatcherTests.cs | 9 +- .../Scoping/ScopedNuCacheTests.cs | 2 +- .../Scoping/ScopedRepositoryTests.cs | 8 +- src/Umbraco.Tests/Scoping/ScopedXmlTests.cs | 4 +- .../ContentTypeServiceVariantsTests.cs | 2 +- .../TestHelpers/BaseUsingSqlCeSyntax.cs | 6 +- src/Umbraco.Tests/TestHelpers/BaseWebTest.cs | 4 +- .../TestControllerActivatorBase.cs | 3 - .../Stubs/TestControllerFactory.cs | 2 +- .../TestHelpers/TestObjects-Mocks.cs | 51 +- src/Umbraco.Tests/TestHelpers/TestObjects.cs | 8 +- .../TestHelpers/TestWithDatabaseBase.cs | 2 +- .../Testing/UmbracoTestAttribute.cs | 6 +- src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 110 +- .../Testing/UmbracoTestOptions.cs | 8 +- ...RenderIndexActionSelectorAttributeTests.cs | 2 +- .../Web/TemplateUtilitiesTests.cs | 4 +- src/Umbraco.Web.UI.Client/package-lock.json | 3093 +---------------- .../Actions/ActionCollectionBuilder.cs | 4 +- .../Cache/CacheRefresherComponent.cs | 1 - ...aseServerRegistrarAndMessengerComponent.cs | 16 +- .../Components/NotificationsComponent.cs | 8 +- .../Composers/ControllersComposer.cs | 3 +- .../Composing/Composers/InstallerComposer.cs | 22 +- .../Composers/WebMappingProfilesComposer.cs | 58 +- src/Umbraco.Web/Composing/Current.cs | 36 +- src/Umbraco.Web/Composing/ModuleInjector.cs | 4 +- src/Umbraco.Web/CompositionExtensions.cs | 41 +- .../ContentAppDefinitionCollectionBuilder.cs | 12 +- .../Editors/DataTypeValidateAttribute.cs | 2 +- src/Umbraco.Web/Editors/TourController.cs | 2 +- src/Umbraco.Web/HtmlHelperRenderExtensions.cs | 6 +- src/Umbraco.Web/Models/LoginStatusModel.cs | 6 +- src/Umbraco.Web/Models/ProfileModel.cs | 6 +- src/Umbraco.Web/Models/RegisterModel.cs | 6 +- .../Mvc/ContainerControllerFactory.cs | 4 +- .../EnsurePublishedContentRequestAttribute.cs | 6 +- .../Mvc/MasterControllerFactory.cs | 2 +- src/Umbraco.Web/Mvc/PluginController.cs | 12 +- src/Umbraco.Web/Mvc/RenderRouteHandler.cs | 4 +- src/Umbraco.Web/Mvc/UmbracoController.cs | 12 +- .../Mvc/UmbracoControllerFactory.cs | 2 +- .../Mvc/UmbracoViewPageOfTModel.cs | 8 +- .../Mvc/UmbracoVirtualNodeRouteHandler.cs | 2 +- .../NuCache/NuCacheComponent.cs | 5 +- src/Umbraco.Web/Routing/PublishedRouter.cs | 2 +- src/Umbraco.Web/Runtime/WebRuntime.cs | 4 +- .../Runtime/WebRuntimeComponent.cs | 62 +- .../Scheduling/BackgroundTaskRunner.cs | 2 +- src/Umbraco.Web/Security/WebSecurity.cs | 2 +- .../SignalR/PreviewHubComponent.cs | 2 +- src/Umbraco.Web/Templates/TemplateRenderer.cs | 6 +- .../Tour/TourFilterCollectionBuilder.cs | 4 +- .../UI/Controls/UmbracoUserControl.cs | 6 +- src/Umbraco.Web/UmbracoContext.cs | 2 +- src/Umbraco.Web/UmbracoHelper.cs | 6 +- .../Filters/FeatureAuthorizeAttribute.cs | 2 +- .../WebApi/UmbracoApiController.cs | 6 +- .../WebApi/UmbracoApiControllerBase.cs | 26 +- 103 files changed, 814 insertions(+), 3843 deletions(-) rename src/Umbraco.Core/Composing/{ContainerExtensions.cs => RegisterExtensions.cs} (84%) diff --git a/src/Umbraco.Core/Components/Components.cs b/src/Umbraco.Core/Components/Components.cs index cb73e9cc5c..dffa471be6 100644 --- a/src/Umbraco.Core/Components/Components.cs +++ b/src/Umbraco.Core/Components/Components.cs @@ -41,6 +41,7 @@ namespace Umbraco.Core.Components public int Weight = -1; } + public void Compose() { var orderedComponentTypes = PrepareComponentTypes(); @@ -49,11 +50,11 @@ namespace Umbraco.Core.Components ComposeComponents(); } - public void Initialize() + public void Initialize(IFactory factory) { - using (var scope = _composition.Container.GetInstance().CreateScope()) + using (var scope = factory.GetInstance().CreateScope()) { - InitializeComponents(); + InitializeComponents(factory); scope.Complete(); } } @@ -303,12 +304,12 @@ namespace Umbraco.Core.Components } } - private void InitializeComponents() + private void InitializeComponents(IFactory factory) { // use a container scope to ensure that PerScope instances are disposed // components that require instances that should not survive should register them with PerScope lifetime using (_logger.DebugDuration($"Initializing components. (log when >{LogThresholdMilliseconds}ms)", "Initialized components.")) - using (_composition.Container.BeginScope()) + using (factory.BeginScope()) { foreach (var component in _components) { @@ -320,7 +321,7 @@ namespace Umbraco.Core.Components foreach (var initializer in initializers) { var parameters = initializer.GetParameters() - .Select(x => GetParameter(componentType, x.ParameterType)) + .Select(x => GetParameter(factory, componentType, x.ParameterType)) .ToArray(); initializer.Invoke(component, parameters); } @@ -329,13 +330,13 @@ namespace Umbraco.Core.Components } } - private object GetParameter(Type componentType, Type parameterType) + private object GetParameter(IFactory factory, Type componentType, Type parameterType) { object param; try { - param = _composition.Container.TryGetInstance(parameterType); + param = factory.TryGetInstance(parameterType); } catch (Exception e) { diff --git a/src/Umbraco.Core/Components/Composition.cs b/src/Umbraco.Core/Components/Composition.cs index 4a6c312968..6032dd303d 100644 --- a/src/Umbraco.Core/Components/Composition.cs +++ b/src/Umbraco.Core/Components/Composition.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using Umbraco.Core.Composing; +using Umbraco.Core.Logging; namespace Umbraco.Core.Components { @@ -12,35 +13,32 @@ namespace Umbraco.Core.Components /// avoid accessing the container. This is because everything needs to be properly registered and with /// the proper lifecycle. These methods will take care of it. Directly registering into the container /// may cause issues. - public class Composition + public class Composition : IRegister { private readonly Dictionary _builders = new Dictionary(); + private readonly IRegister _register; /// /// Initializes a new instance of the class. /// - /// A container. - /// The type loader. + /// A register. + /// A type loader. + /// A logger. /// The runtime level. - public Composition(IContainer container, TypeLoader typeLoader, RuntimeLevel level) + public Composition(IRegister register, TypeLoader typeLoader, IProfilingLogger logger, RuntimeLevel level) { - Container = container; + _register = register; TypeLoader = typeLoader; + Logger = logger; RuntimeLevel = level; } - // used for tests - internal Composition(IContainer container, RuntimeLevel level) - { - Container = container; - RuntimeLevel = level; - } + #region Services /// - /// Gets the container. + /// Gets the logger. /// - /// Use with care! - public IContainer Container { get; } + public IProfilingLogger Logger { get; } /// /// Gets the type loader. @@ -52,6 +50,45 @@ namespace Umbraco.Core.Components /// public RuntimeLevel RuntimeLevel { get; } + #endregion + + #region IRegister + + /// + public object ConcreteContainer => _register.ConcreteContainer; + + /// + public void Register(Type serviceType, Lifetime lifetime = Lifetime.Transient) + => _register.Register(serviceType, lifetime); + + /// + public void Register(Type serviceType, Type implementingType, Lifetime lifetime = Lifetime.Transient) + => _register.Register(serviceType, implementingType, lifetime); + + /// + public void Register(Func factory, Lifetime lifetime = Lifetime.Transient) + => _register.Register(factory, lifetime); + + /// + public void RegisterInstance(Type serviceType, object instance) + => _register.RegisterInstance(serviceType, instance); + + /// + public void RegisterAuto(Type serviceBaseType) + => _register.RegisterAuto(serviceBaseType); + + /// + public IContainer ConfigureForWeb() + => _register.ConfigureForWeb(); + + /// + public IContainer EnablePerWebRequestScope() + => _register.EnablePerWebRequestScope(); + + #endregion + + #region Collection Builders + /// /// Gets a collection builder (and registers the collection). /// @@ -66,11 +103,13 @@ namespace Umbraco.Core.Components return (TBuilder) o; var builder = new TBuilder(); - builder.Initialize(Container); + builder.Initialize(_register); _builders[typeOfBuilder] = builder; return builder; } + + #endregion } } diff --git a/src/Umbraco.Core/Components/CompositionExtensions.cs b/src/Umbraco.Core/Components/CompositionExtensions.cs index abc0fa3862..8ac8c66bc1 100644 --- a/src/Umbraco.Core/Components/CompositionExtensions.cs +++ b/src/Umbraco.Core/Components/CompositionExtensions.cs @@ -24,56 +24,56 @@ namespace Umbraco.Core.Components /// /// The composition. public static CacheRefresherCollectionBuilder CacheRefreshers(this Composition composition) - => composition.Container.GetInstance(); + => composition.GetCollectionBuilder(); /// /// Gets the mappers collection builder. /// /// The composition. public static MapperCollectionBuilder Mappers(this Composition composition) - => composition.Container.GetInstance(); + => composition.GetCollectionBuilder(); /// /// Gets the package actions collection builder. /// /// The composition. internal static PackageActionCollectionBuilder PackageActions(this Composition composition) - => composition.Container.GetInstance(); + => composition.GetCollectionBuilder(); /// /// Gets the data editor collection builder. /// /// The composition. public static DataEditorCollectionBuilder DataEditors(this Composition composition) - => composition.Container.GetInstance(); + => composition.GetCollectionBuilder(); /// /// Gets the property value converters collection builder. /// /// The composition. public static PropertyValueConverterCollectionBuilder PropertyValueConverters(this Composition composition) - => composition.Container.GetInstance(); + => composition.GetCollectionBuilder(); /// /// Gets the url segment providers collection builder. /// /// The composition. public static UrlSegmentProviderCollectionBuilder UrlSegmentProviders(this Composition composition) - => composition.Container.GetInstance(); + => composition.GetCollectionBuilder(); /// /// Gets the validators collection builder. /// /// The composition. internal static ManifestValueValidatorCollectionBuilder Validators(this Composition composition) - => composition.Container.GetInstance(); + => composition.GetCollectionBuilder(); /// /// Gets the post-migrations collection builder. /// /// The composition. internal static PostMigrationCollectionBuilder PostMigrations(this Composition composition) - => composition.Container.GetInstance(); + => composition.GetCollectionBuilder(); #endregion @@ -87,7 +87,7 @@ namespace Umbraco.Core.Components public static void SetCultureDictionaryFactory(this Composition composition) where T : ICultureDictionaryFactory { - composition.Container.RegisterSingleton(); + composition.RegisterSingleton(); } /// @@ -95,9 +95,9 @@ namespace Umbraco.Core.Components /// /// The composition. /// A function creating a culture dictionary factory. - public static void SetCultureDictionaryFactory(this Composition composition, Func factory) + public static void SetCultureDictionaryFactory(this Composition composition, Func factory) { - composition.Container.RegisterSingleton(factory); + composition.RegisterSingleton(factory); } /// @@ -107,7 +107,7 @@ namespace Umbraco.Core.Components /// A factory. public static void SetCultureDictionaryFactory(this Composition composition, ICultureDictionaryFactory factory) { - composition.Container.RegisterSingleton(_ => factory); + composition.RegisterSingleton(_ => factory); } /// @@ -118,7 +118,7 @@ namespace Umbraco.Core.Components public static void SetPublishedContentModelFactory(this Composition composition) where T : IPublishedModelFactory { - composition.Container.RegisterSingleton(); + composition.RegisterSingleton(); } /// @@ -126,9 +126,9 @@ namespace Umbraco.Core.Components /// /// The composition. /// A function creating a published content model factory. - public static void SetPublishedContentModelFactory(this Composition composition, Func factory) + public static void SetPublishedContentModelFactory(this Composition composition, Func factory) { - composition.Container.RegisterSingleton(factory); + composition.RegisterSingleton(factory); } /// @@ -138,7 +138,7 @@ namespace Umbraco.Core.Components /// A published content model factory. public static void SetPublishedContentModelFactory(this Composition composition, IPublishedModelFactory factory) { - composition.Container.RegisterSingleton(_ => factory); + composition.RegisterSingleton(_ => factory); } /// @@ -149,7 +149,7 @@ namespace Umbraco.Core.Components public static void SetServerRegistrar(this Composition composition) where T : IServerRegistrar { - composition.Container.RegisterSingleton(); + composition.RegisterSingleton(); } /// @@ -157,9 +157,9 @@ namespace Umbraco.Core.Components /// /// The composition. /// A function creating a server registar. - public static void SetServerRegistrar(this Composition composition, Func factory) + public static void SetServerRegistrar(this Composition composition, Func factory) { - composition.Container.RegisterSingleton(factory); + composition.RegisterSingleton(factory); } /// @@ -169,7 +169,7 @@ namespace Umbraco.Core.Components /// A server registrar. public static void SetServerRegistrar(this Composition composition, IServerRegistrar registrar) { - composition.Container.RegisterSingleton(_ => registrar); + composition.RegisterSingleton(_ => registrar); } /// @@ -180,7 +180,7 @@ namespace Umbraco.Core.Components public static void SetServerMessenger(this Composition composition) where T : IServerMessenger { - composition.Container.Register(Lifetime.Singleton); + composition.Register(Lifetime.Singleton); } /// @@ -188,9 +188,9 @@ namespace Umbraco.Core.Components /// /// The composition. /// A function creating a server messenger. - public static void SetServerMessenger(this Composition composition, Func factory) + public static void SetServerMessenger(this Composition composition, Func factory) { - composition.Container.RegisterSingleton(factory); + composition.RegisterSingleton(factory); } /// @@ -200,7 +200,7 @@ namespace Umbraco.Core.Components /// A server messenger. public static void SetServerMessenger(this Composition composition, IServerMessenger registrar) { - composition.Container.RegisterSingleton(_ => registrar); + composition.RegisterSingleton(_ => registrar); } /// @@ -211,7 +211,7 @@ namespace Umbraco.Core.Components public static void SetShortStringHelper(this Composition composition) where T : IShortStringHelper { - composition.Container.RegisterSingleton(); + composition.RegisterSingleton(); } /// @@ -219,9 +219,9 @@ namespace Umbraco.Core.Components /// /// The composition. /// A function creating a short string helper. - public static void SetShortStringHelper(this Composition composition, Func factory) + public static void SetShortStringHelper(this Composition composition, Func factory) { - composition.Container.RegisterSingleton(factory); + composition.RegisterSingleton(factory); } /// @@ -231,7 +231,7 @@ namespace Umbraco.Core.Components /// A short string helper. public static void SetShortStringHelper(this Composition composition, IShortStringHelper helper) { - composition.Container.RegisterSingleton(_ => helper); + composition.RegisterSingleton(_ => helper); } #endregion diff --git a/src/Umbraco.Core/Composing/CollectionBuilderBase.cs b/src/Umbraco.Core/Composing/CollectionBuilderBase.cs index b1d43d101c..b9ba687316 100644 --- a/src/Umbraco.Core/Composing/CollectionBuilderBase.cs +++ b/src/Umbraco.Core/Composing/CollectionBuilderBase.cs @@ -21,7 +21,7 @@ namespace Umbraco.Core.Composing /// /// Gets the container. /// - protected IContainer Container { get; private set; } + protected IRegister Container { get; private set; } /// /// Gets the internal list of types as an IEnumerable (immutable). @@ -32,7 +32,7 @@ namespace Umbraco.Core.Composing /// Initializes a new instance of the builder. /// /// By default, this registers the collection automatically. - public virtual void Initialize(IContainer container) + public virtual void Initialize(IRegister container) { if (Container != null) throw new InvalidOperationException("This builder has already been initialized."); @@ -40,7 +40,7 @@ namespace Umbraco.Core.Composing Container = container; // register the collection - Container.Register(_ => CreateCollection(), CollectionLifetime); + Container.Register(factory => CreateCollection(factory), CollectionLifetime); } /// @@ -98,12 +98,12 @@ namespace Umbraco.Core.Composing /// Creates the collection items. /// /// The collection items. - protected virtual IEnumerable CreateItems() + protected virtual IEnumerable CreateItems(IFactory factory) { RegisterTypes(); // will do it only once return _registeredTypes // respect order - .Select(x => (TItem) Container.GetInstance(x)) + .Select(x => (TItem) factory.GetInstance(x)) .ToArray(); // safe } @@ -112,9 +112,9 @@ namespace Umbraco.Core.Composing /// /// A collection. /// Creates a new collection each time it is invoked. - public virtual TCollection CreateCollection() + public virtual TCollection CreateCollection(IFactory factory) { - return Container.CreateInstance(CreateItems()); + return factory.CreateInstance(CreateItems(factory)); } protected Type EnsureType(Type type, string action) diff --git a/src/Umbraco.Core/Composing/Composers/ConfigurationComposer.cs b/src/Umbraco.Core/Composing/Composers/ConfigurationComposer.cs index 08b88dfc04..8e81256e3b 100644 --- a/src/Umbraco.Core/Composing/Composers/ConfigurationComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/ConfigurationComposer.cs @@ -11,13 +11,11 @@ namespace Umbraco.Core.Composing.Composers { public static Composition ComposeConfiguration(this Composition composition) { - var container = composition.Container; - - container.Register(factory => UmbracoConfig.For.UmbracoSettings()); - container.Register(factory => factory.GetInstance().Content); - container.Register(factory => factory.GetInstance().Templates); - container.Register(factory => factory.GetInstance().RequestHandler); - container.Register(factory => UmbracoConfig.For.GlobalSettings()); + composition.Register(factory => UmbracoConfig.For.UmbracoSettings()); + composition.Register(factory => factory.GetInstance().Content); + composition.Register(factory => factory.GetInstance().Templates); + composition.Register(factory => factory.GetInstance().RequestHandler); + composition.Register(factory => UmbracoConfig.For.GlobalSettings()); // fixme - other sections we need to add? diff --git a/src/Umbraco.Core/Composing/Composers/CoreMappingProfilesComposer.cs b/src/Umbraco.Core/Composing/Composers/CoreMappingProfilesComposer.cs index 38b15b6084..0274b8f1a9 100644 --- a/src/Umbraco.Core/Composing/Composers/CoreMappingProfilesComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/CoreMappingProfilesComposer.cs @@ -9,8 +9,7 @@ namespace Umbraco.Core.Composing.Composers { public static Composition ComposeCoreMappingProfiles(this Composition composition) { - var container = composition.Container; - container.Register(); + composition.Register(); return composition; } } diff --git a/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs b/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs index a1895df4e6..1970fc7f4c 100644 --- a/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs @@ -67,22 +67,20 @@ namespace Umbraco.Core.Composing.Composers public static Composition ComposeFileSystems(this Composition composition) { - var container = composition.Container; - // register FileSystems, which manages all filesystems // it needs to be registered (not only the interface) because it provides additional // functionality eg for scoping, and is injected in the scope provider - whereas the // interface is really for end-users to get access to filesystems. - container.RegisterSingleton(factory => factory.CreateInstance(container)); + composition.RegisterSingleton(factory => factory.CreateInstance(factory)); // register IFileSystems, which gives access too all filesystems - container.RegisterSingleton(factory => factory.GetInstance()); + composition.RegisterSingleton(factory => factory.GetInstance()); // register the scheme for media paths - container.RegisterSingleton(); + composition.RegisterSingleton(); // register the IMediaFileSystem implementation with a supporting filesystem - container.RegisterFileSystem( + composition.RegisterFileSystem( factory => new PhysicalFileSystem("~/media")); return composition; diff --git a/src/Umbraco.Core/Composing/Composers/RepositoriesComposer.cs b/src/Umbraco.Core/Composing/Composers/RepositoriesComposer.cs index d0fdf63fb9..54f9ff3e53 100644 --- a/src/Umbraco.Core/Composing/Composers/RepositoriesComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/RepositoriesComposer.cs @@ -11,44 +11,42 @@ namespace Umbraco.Core.Composing.Composers { public static Composition ComposeRepositories(this Composition composition) { - var container = composition.Container; - // repositories - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); return composition; } diff --git a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs index 2db718f0ce..ec53f7efdc 100644 --- a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs @@ -15,58 +15,56 @@ namespace Umbraco.Core.Composing.Composers { public static Composition ComposeServices(this Composition composition) { - var container = composition.Container; - // register a transient messages factory, which will be replaced by the web // boot manager when running in a web context - container.RegisterSingleton(); + composition.RegisterSingleton(); // register the service context - container.RegisterSingleton(); + composition.RegisterSingleton(); // register the special idk map - container.RegisterSingleton(); + composition.RegisterSingleton(); // register the services - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.Register(SourcesFactory); - container.RegisterSingleton(factory => new LocalizedTextService( + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.Register(SourcesFactory); + composition.RegisterSingleton(factory => new LocalizedTextService( factory.GetInstance>(), factory.GetInstance())); //TODO: These are replaced in the web project - we need to declare them so that // something is wired up, just not sure this is very nice but will work for now. - container.RegisterSingleton(); - container.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); return composition; } - private static LocalizedTextServiceFileSources SourcesFactory(IContainer container) + private static LocalizedTextServiceFileSources SourcesFactory(IFactory container) { var mainLangFolder = new DirectoryInfo(IOHelper.MapPath(SystemDirectories.Umbraco + "/config/lang/")); var appPlugins = new DirectoryInfo(IOHelper.MapPath(SystemDirectories.AppPlugins)); diff --git a/src/Umbraco.Core/Composing/Current.cs b/src/Umbraco.Core/Composing/Current.cs index 17c8fcd48b..312d9251a3 100644 --- a/src/Umbraco.Core/Composing/Current.cs +++ b/src/Umbraco.Core/Composing/Current.cs @@ -26,7 +26,7 @@ namespace Umbraco.Core.Composing /// public static class Current { - private static IContainer _container; + private static IFactory _factory; private static IShortStringHelper _shortStringHelper; private static ILogger _logger; @@ -35,30 +35,30 @@ namespace Umbraco.Core.Composing private static IPublishedValueFallback _publishedValueFallback; /// - /// Gets or sets the DI container. + /// Gets or sets the factory. /// - public static IContainer Container + public static IFactory Factory { get { - if (_container == null) throw new Exception("No container has been set."); - return _container; + if (_factory == null) throw new Exception("No factory has been set."); + return _factory; } set { - if (_container != null) throw new Exception("A container has already been set."); - _container = value; + if (_factory != null) throw new Exception("A factory has already been set."); + _factory = value; } } - internal static bool HasContainer => _container != null; + internal static bool HasContainer => _factory != null; // for UNIT TESTS exclusively! // resets *everything* that is 'current' internal static void Reset() { - _container?.Dispose(); - _container = null; + _factory.DisposeIfDisposable(); + _factory = null; _shortStringHelper = null; _logger = null; @@ -80,89 +80,89 @@ namespace Umbraco.Core.Composing // not happen. Will do when we get rid of IShortStringHelper. public static IShortStringHelper ShortStringHelper - => _shortStringHelper ?? (_shortStringHelper = _container?.TryGetInstance() + => _shortStringHelper ?? (_shortStringHelper = _factory?.TryGetInstance() ?? new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(UmbracoConfig.For.UmbracoSettings()))); public static ILogger Logger - => _logger ?? (_logger = _container?.TryGetInstance() + => _logger ?? (_logger = _factory?.TryGetInstance() ?? new DebugDiagnosticsLogger()); public static IProfiler Profiler - => _profiler ?? (_profiler = _container?.TryGetInstance() + => _profiler ?? (_profiler = _factory?.TryGetInstance() ?? new LogProfiler(Logger)); public static IProfilingLogger ProfilingLogger - => _profilingLogger ?? (_profilingLogger = _container?.TryGetInstance()) + => _profilingLogger ?? (_profilingLogger = _factory?.TryGetInstance()) ?? new ProfilingLogger(Logger, Profiler); public static IRuntimeState RuntimeState - => Container.GetInstance(); + => Factory.GetInstance(); public static TypeLoader TypeLoader - => Container.GetInstance(); + => Factory.GetInstance(); public static IFileSystems FileSystems - => Container.GetInstance(); + => Factory.GetInstance(); public static IMediaFileSystem MediaFileSystem - => Container.GetInstance(); + => Factory.GetInstance(); public static UrlSegmentProviderCollection UrlSegmentProviders - => Container.GetInstance(); + => Factory.GetInstance(); public static CacheRefresherCollection CacheRefreshers - => Container.GetInstance(); + => Factory.GetInstance(); public static DataEditorCollection DataEditors - => Container.GetInstance(); + => Factory.GetInstance(); public static PropertyEditorCollection PropertyEditors - => Container.GetInstance(); + => Factory.GetInstance(); public static ParameterEditorCollection ParameterEditors - => Container.GetInstance(); + => Factory.GetInstance(); internal static ManifestValueValidatorCollection ManifestValidators - => Container.GetInstance(); + => Factory.GetInstance(); internal static PackageActionCollection PackageActions - => Container.GetInstance(); + => Factory.GetInstance(); internal static PropertyValueConverterCollection PropertyValueConverters - => Container.GetInstance(); + => Factory.GetInstance(); internal static IPublishedModelFactory PublishedModelFactory - => Container.GetInstance(); + => Factory.GetInstance(); public static IServerMessenger ServerMessenger - => Container.GetInstance(); + => Factory.GetInstance(); public static IServerRegistrar ServerRegistrar - => Container.GetInstance(); + => Factory.GetInstance(); public static ICultureDictionaryFactory CultureDictionaryFactory - => Container.GetInstance(); + => Factory.GetInstance(); public static CacheHelper ApplicationCache - => Container.GetInstance(); + => Factory.GetInstance(); public static ServiceContext Services - => Container.GetInstance(); + => Factory.GetInstance(); public static IScopeProvider ScopeProvider - => Container.GetInstance(); + => Factory.GetInstance(); public static ISqlContext SqlContext - => Container.GetInstance(); + => Factory.GetInstance(); public static IPublishedContentTypeFactory PublishedContentTypeFactory - => Container.GetInstance(); + => Factory.GetInstance(); public static IPublishedValueFallback PublishedValueFallback - => _publishedValueFallback ?? Container.GetInstance() ?? new NoopPublishedValueFallback(); + => _publishedValueFallback ?? Factory.GetInstance() ?? new NoopPublishedValueFallback(); public static IVariationContextAccessor VariationContextAccessor - => Container.GetInstance(); + => Factory.GetInstance(); #endregion } diff --git a/src/Umbraco.Core/Composing/ICollectionBuilder.cs b/src/Umbraco.Core/Composing/ICollectionBuilder.cs index a493d90a0a..e17a362e6d 100644 --- a/src/Umbraco.Core/Composing/ICollectionBuilder.cs +++ b/src/Umbraco.Core/Composing/ICollectionBuilder.cs @@ -8,7 +8,7 @@ /// /// Initializes a new instance of the builder, and registers the collection. /// - void Initialize(IContainer container); + void Initialize(IRegister container); } /// @@ -24,6 +24,6 @@ /// /// A collection. /// Creates a new collection each time it is invoked. - TCollection CreateCollection(); + TCollection CreateCollection(IFactory factory); } } diff --git a/src/Umbraco.Core/Composing/IContainer.cs b/src/Umbraco.Core/Composing/IContainer.cs index 4975f5d08d..22b6ac3eae 100644 --- a/src/Umbraco.Core/Composing/IContainer.cs +++ b/src/Umbraco.Core/Composing/IContainer.cs @@ -20,17 +20,76 @@ namespace Umbraco.Core.Composing // IEnumerable of the service, nameless, returns them all /// - /// Defines a container for Umbraco. + /// Defines a service register for Umbraco. /// - public interface IContainer : IDisposable + public interface IRegister { /// /// Gets the concrete container. /// object ConcreteContainer { get; } - #region Factory + /// + /// Registers a service as its own implementation. + /// + void Register(Type serviceType, Lifetime lifetime = Lifetime.Transient); + /// + /// Registers a service with an implementation type. + /// + void Register(Type serviceType, Type implementingType, Lifetime lifetime = Lifetime.Transient); + + /// + /// Registers a service with an implementation factory. + /// + void Register(Func factory, Lifetime lifetime = Lifetime.Transient); + + /// + /// Registers a service with an implementing instance. + /// + void RegisterInstance(Type serviceType, object instance); + + /// + /// Registers a base type for auto-registration. + /// + /// + /// Auto-registration means that anytime the container is asked to create an instance + /// of a type deriving from , it will first register that + /// type automatically. + /// This can be used for instance for views or controllers. Then, one just needs to + /// register a common base class or interface, and the container knows how to create instances. + /// + void RegisterAuto(Type serviceBaseType); + + #region Control + + /// + /// Configures the container for web support. + /// + /// The container. + /// + /// Enables support for MVC, WebAPI, but *not* per-request scope. This is used early in the boot + /// process, where anything "scoped" should not be linked to a web request. + /// + IContainer ConfigureForWeb(); + + /// + /// Enables per-request scope. + /// + /// The container. + /// + /// Ties scopes to web requests. + /// + IContainer EnablePerWebRequestScope(); + + #endregion + } + + /// + /// Defines a service factory for Umbraco. + /// + public interface IFactory + { /// /// Gets an instance of a service. /// @@ -72,46 +131,6 @@ namespace Umbraco.Core.Composing /// void Release(object instance); - #endregion - - #region Registry - - /// - /// Registers a service as its own implementation. - /// - void Register(Type serviceType, Lifetime lifetime = Lifetime.Transient); - - /// - /// Registers a service with an implementation type. - /// - void Register(Type serviceType, Type implementingType, Lifetime lifetime = Lifetime.Transient); - - /// - /// Registers a service with an implementation factory. - /// - void Register(Func factory, Lifetime lifetime = Lifetime.Transient); - - /// - /// Registers a service with an implementing instance. - /// - void RegisterInstance(Type serviceType, object instance); - - /// - /// Registers a base type for auto-registration. - /// - /// - /// Auto-registration means that anytime the container is asked to create an instance - /// of a type deriving from , it will first register that - /// type automatically. - /// This can be used for instance for views or controllers. Then, one just needs to - /// register a common base class or interface, and the container knows how to create instances. - /// - void RegisterAuto(Type serviceBaseType); - - #endregion - - #region Control - /// /// Begins a scope. /// @@ -120,26 +139,11 @@ namespace Umbraco.Core.Composing /// Scopes can be nested. Each instance is disposed individually. /// IDisposable BeginScope(); - - /// - /// Configures the container for web support. - /// - /// The container. - /// - /// Enables support for MVC, WebAPI, but *not* per-request scope. This is used early in the boot - /// process, where anything "scoped" should not be linked to a web request. - /// - IContainer ConfigureForWeb(); - - /// - /// Enables per-request scope. - /// - /// The container. - /// - /// Ties scopes to web requests. - /// - IContainer EnablePerWebRequestScope(); - - #endregion } + + /// + /// Defines a container for Umbraco. + /// + public interface IContainer : IRegister, IFactory, IDisposable // fixme kill? + { } } diff --git a/src/Umbraco.Core/Composing/LazyCollectionBuilderBase.cs b/src/Umbraco.Core/Composing/LazyCollectionBuilderBase.cs index 79e5ffd4b1..50d76b47a2 100644 --- a/src/Umbraco.Core/Composing/LazyCollectionBuilderBase.cs +++ b/src/Umbraco.Core/Composing/LazyCollectionBuilderBase.cs @@ -14,8 +14,7 @@ namespace Umbraco.Core.Composing where TBuilder : LazyCollectionBuilderBase where TCollection : IBuilderCollection { - private readonly List>> _producers1 = new List>>(); - private readonly List>> _producers2 = new List>>(); + private readonly List>> _producers = new List>>(); private readonly List _excluded = new List(); protected abstract TBuilder This { get; } @@ -29,9 +28,8 @@ namespace Umbraco.Core.Composing Configure(types => { types.Clear(); - _producers1.Clear(); - _producers2.Clear(); - _excluded.Clear(); + _producers.Clear(); + _excluded.Clear(); }); return This; } @@ -107,21 +105,7 @@ namespace Umbraco.Core.Composing { Configure(types => { - _producers1.Add(producer); - }); - return This; - } - - /// - /// Adds a types producer to the collection. - /// - /// The types producer. - /// The builder. - public TBuilder Add(Func> producer) - { - Configure(types => - { - _producers2.Add(producer); + _producers.Add(producer); }); return This; } @@ -160,8 +144,7 @@ namespace Umbraco.Core.Composing protected override IEnumerable GetRegisteringTypes(IEnumerable types) { return types - .Union(_producers1.SelectMany(x => x())) - .Union(_producers2.SelectMany(x => x(Container))) + .Union(_producers.SelectMany(x => x())) .Distinct() .Select(x => EnsureType(x, "register")) .Except(_excluded); diff --git a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs index e3b93f5aea..a15bfdfb16 100644 --- a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs +++ b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs @@ -174,7 +174,7 @@ namespace Umbraco.Core.Composing.LightInject } /// - public void Register(Func factory, Lifetime lifetime = Lifetime.Transient) + public void Register(Func factory, Lifetime lifetime = Lifetime.Transient) { switch (lifetime) { diff --git a/src/Umbraco.Core/Composing/OrderedCollectionBuilderBase.cs b/src/Umbraco.Core/Composing/OrderedCollectionBuilderBase.cs index 5acf716ec0..bde1bf96c5 100644 --- a/src/Umbraco.Core/Composing/OrderedCollectionBuilderBase.cs +++ b/src/Umbraco.Core/Composing/OrderedCollectionBuilderBase.cs @@ -78,26 +78,6 @@ namespace Umbraco.Core.Composing return This; } - /// - /// Appends types to the collections. - /// - /// The types to append. - /// The builder. - public TBuilder Append(Func> types) - { - Configure(list => - { - foreach (var type in types(Container)) - { - // would be detected by CollectionBuilderBase when registering, anyways, but let's fail fast - EnsureType(type, "register"); - if (list.Contains(type)) list.Remove(type); - list.Add(type); - } - }); - return This; - } - /// /// Appends a type after another type. /// diff --git a/src/Umbraco.Core/Composing/ContainerExtensions.cs b/src/Umbraco.Core/Composing/RegisterExtensions.cs similarity index 84% rename from src/Umbraco.Core/Composing/ContainerExtensions.cs rename to src/Umbraco.Core/Composing/RegisterExtensions.cs index 047bcd2ae5..fc6aa78f0b 100644 --- a/src/Umbraco.Core/Composing/ContainerExtensions.cs +++ b/src/Umbraco.Core/Composing/RegisterExtensions.cs @@ -10,7 +10,7 @@ namespace Umbraco.Core.Composing /// /// Provides extension methods to the class. /// - public static class ContainerExtensions + public static class RegisterExtensions { /// /// Gets an instance of a service. @@ -19,7 +19,7 @@ namespace Umbraco.Core.Composing /// The container. /// An instance of the specified type. /// Throws an exception if the container failed to get an instance of the specified type. - public static T GetInstance(this IContainer container) + public static T GetInstance(this IFactory container) => (T) container.GetInstance(typeof(T)); /// @@ -30,7 +30,7 @@ namespace Umbraco.Core.Composing /// Returns null if the container does not know how to get an instance /// of the specified type. Throws an exception if the container does know how /// to get an instance of the specified type, but failed to do so. - public static T TryGetInstance(this IContainer container) + public static T TryGetInstance(this IFactory container) => (T) container.TryGetInstance(typeof(T)); /// @@ -44,49 +44,49 @@ namespace Umbraco.Core.Composing /// Throws an exception if the container failed to get an instance of the specified type. /// The arguments are used as dependencies by the container. /// - public static T CreateInstance(this IContainer container, params object[] args) + public static T CreateInstance(this IFactory container, params object[] args) => (T) container.CreateInstance(typeof(T), args); /// /// Registers a service with an implementation type. /// - public static void Register(this IContainer container, Lifetime lifetime = Lifetime.Transient) + public static void Register(this IRegister container, Lifetime lifetime = Lifetime.Transient) => container.Register(typeof(TService), typeof(TImplementing), lifetime); /// /// Registers a service as its own implementation. /// - public static void Register(this IContainer container, Lifetime lifetime = Lifetime.Transient) + public static void Register(this IRegister container, Lifetime lifetime = Lifetime.Transient) => container.Register(typeof(TService), lifetime); /// /// Registers a singleton service as its own implementation. /// - public static void RegisterSingleton(this IContainer container) + public static void RegisterSingleton(this IRegister container) => container.Register(typeof(TService), Lifetime.Singleton); /// /// Registers a singleton service with an implementation type. /// - public static void RegisterSingleton(this IContainer container) + public static void RegisterSingleton(this IRegister container) => container.Register(typeof(TService), typeof(TImplementing), Lifetime.Singleton); /// /// Registers a singleton service with an implementation factory. /// - public static void RegisterSingleton(this IContainer container, Func factory) + public static void RegisterSingleton(this IRegister container, Func factory) => container.Register(factory, Lifetime.Singleton); /// /// Registers a service with an implementing instance. /// - public static void RegisterInstance(this IContainer container, TService instance) + public static void RegisterInstance(this IRegister container, TService instance) => container.RegisterInstance(typeof(TService), instance); /// /// Registers a base type for auto-registration. /// - public static void RegisterAuto(this IContainer container) + public static void RegisterAuto(this IRegister container) => container.RegisterAuto(typeof(TServiceBase)); /// @@ -101,7 +101,7 @@ namespace Umbraco.Core.Composing /// The arguments are used as dependencies by the container. Other dependencies /// are retrieved from the container. /// - public static object CreateInstance(this IContainer container, Type type, params object[] args) + public static object CreateInstance(this IFactory container, Type type, params object[] args) { // LightInject has this, but then it requires RegisterConstructorDependency etc and has various oddities // including the most annoying one, which is that it does not work on singletons (hard to fix) @@ -137,7 +137,7 @@ namespace Umbraco.Core.Composing /// The container. /// A factory method creating the supporting filesystem. /// The container. - public static IContainer RegisterFileSystem(this IContainer container, Func supportingFileSystemFactory) + public static IRegister RegisterFileSystem(this IRegister container, Func supportingFileSystemFactory) where TImplementing : FileSystemWrapper, TFileSystem { container.RegisterSingleton(factory => @@ -156,7 +156,7 @@ namespace Umbraco.Core.Composing /// The container. /// A factory method creating the supporting filesystem. /// The container. - public static IContainer RegisterFileSystem(this IContainer container, Func supportingFileSystemFactory) + public static IRegister RegisterFileSystem(this IRegister container, Func supportingFileSystemFactory) where TFileSystem : FileSystemWrapper { container.RegisterSingleton(factory => diff --git a/src/Umbraco.Core/Composing/TypeLoader.cs b/src/Umbraco.Core/Composing/TypeLoader.cs index 714c5c0ec5..3e7baf66b8 100644 --- a/src/Umbraco.Core/Composing/TypeLoader.cs +++ b/src/Umbraco.Core/Composing/TypeLoader.cs @@ -87,6 +87,13 @@ namespace Umbraco.Core.Composing } } + /// + /// Initializes a new, test/blank, instance of the class. + /// + /// The initialized instance cannot get types. + internal TypeLoader() + { } + /// /// Gets or sets the set of assemblies to scan. /// @@ -514,6 +521,9 @@ namespace Umbraco.Core.Composing /// Caching is disabled when using specific assemblies. public IEnumerable GetTypes(bool cache = true, IEnumerable specificAssemblies = null) { + if (_logger == null) + throw new InvalidOperationException("Cannot get types from a test/blank type loader."); + // do not cache anything from specific assemblies cache &= specificAssemblies == null; @@ -553,6 +563,9 @@ namespace Umbraco.Core.Composing public IEnumerable GetTypesWithAttribute(bool cache = true, IEnumerable specificAssemblies = null) where TAttribute : Attribute { + if (_logger == null) + throw new InvalidOperationException("Cannot get types from a test/blank type loader."); + // do not cache anything from specific assemblies cache &= specificAssemblies == null; @@ -592,6 +605,9 @@ namespace Umbraco.Core.Composing public IEnumerable GetAttributedTypes(bool cache = true, IEnumerable specificAssemblies = null) where TAttribute : Attribute { + if (_logger == null) + throw new InvalidOperationException("Cannot get types from a test/blank type loader."); + // do not cache anything from specific assemblies cache &= specificAssemblies == null; diff --git a/src/Umbraco.Core/IO/FileSystems.cs b/src/Umbraco.Core/IO/FileSystems.cs index 47e2b02bb7..7fc846319b 100644 --- a/src/Umbraco.Core/IO/FileSystems.cs +++ b/src/Umbraco.Core/IO/FileSystems.cs @@ -9,7 +9,7 @@ namespace Umbraco.Core.IO { public class FileSystems : IFileSystems { - private readonly IContainer _container; + private readonly IFactory _container; private readonly ILogger _logger; private readonly ConcurrentDictionary> _filesystems = new ConcurrentDictionary>(); @@ -34,7 +34,7 @@ namespace Umbraco.Core.IO #region Constructor // DI wants a public ctor - public FileSystems(IContainer container, ILogger logger) + public FileSystems(IFactory container, ILogger logger) { _container = container; _logger = logger; diff --git a/src/Umbraco.Core/Migrations/MigrationBuilder.cs b/src/Umbraco.Core/Migrations/MigrationBuilder.cs index aebd8bd1ee..d2d2b7d32a 100644 --- a/src/Umbraco.Core/Migrations/MigrationBuilder.cs +++ b/src/Umbraco.Core/Migrations/MigrationBuilder.cs @@ -5,9 +5,9 @@ namespace Umbraco.Core.Migrations { public class MigrationBuilder : IMigrationBuilder { - private readonly IContainer _container; + private readonly IFactory _container; - public MigrationBuilder(IContainer container) + public MigrationBuilder(IFactory container) { _container = container; } diff --git a/src/Umbraco.Core/Models/Language.cs b/src/Umbraco.Core/Models/Language.cs index e190c8ad3b..03f8f87cd3 100644 --- a/src/Umbraco.Core/Models/Language.cs +++ b/src/Umbraco.Core/Models/Language.cs @@ -88,7 +88,7 @@ namespace Umbraco.Core.Models try { - var globalSettings = (IGlobalSettings) Composing.Current.Container.GetInstance(typeof(IGlobalSettings)); + var globalSettings = (IGlobalSettings) Composing.Current.Factory.GetInstance(typeof(IGlobalSettings)); var defaultUiCulture = CultureInfo.GetCultureInfo(globalSettings.DefaultUILanguage); Thread.CurrentThread.CurrentUICulture = defaultUiCulture; diff --git a/src/Umbraco.Core/Persistence/Mappers/MapperCollectionBuilder.cs b/src/Umbraco.Core/Persistence/Mappers/MapperCollectionBuilder.cs index 28e19088bf..40bc76928b 100644 --- a/src/Umbraco.Core/Persistence/Mappers/MapperCollectionBuilder.cs +++ b/src/Umbraco.Core/Persistence/Mappers/MapperCollectionBuilder.cs @@ -6,7 +6,7 @@ namespace Umbraco.Core.Persistence.Mappers { protected override MapperCollectionBuilder This => this; - public override void Initialize(IContainer container) + public override void Initialize(IRegister container) { base.Initialize(container); diff --git a/src/Umbraco.Core/Runtime/CoreRuntime.cs b/src/Umbraco.Core/Runtime/CoreRuntime.cs index 21ce073719..4793b1994b 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntime.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntime.cs @@ -47,7 +47,7 @@ namespace Umbraco.Core.Runtime public virtual void Boot(IContainer container) { // assign current container - Current.Container = _container = container; + Current.Factory = _container = container; // create and register the essential services // ie the bare minimum required to boot @@ -94,7 +94,7 @@ namespace Umbraco.Core.Runtime container.RegisterInstance(_state); // create the composition - var composition = new Composition(container, typeLoader, RuntimeLevel.Boot); + var composition = new Composition(container, typeLoader, profilingLogger, RuntimeLevel.Boot); // register runtime-level services Compose(composition); @@ -134,8 +134,9 @@ namespace Umbraco.Core.Runtime // we should have a Current.Factory not a Current.Container // we should compile the register into a factory *now* // using the factory before this point should just throw + IFactory factory = container; - _components.Initialize(); + _components.Initialize(factory); } catch (Exception e) { diff --git a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs index 7fbdd46f36..c4167af2b0 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs @@ -34,8 +34,6 @@ namespace Umbraco.Core.Runtime { base.Compose(composition); - var container = composition.Container; - // composers composition .ComposeConfiguration() @@ -50,16 +48,16 @@ namespace Umbraco.Core.Runtime composition.GetCollectionBuilder().AddCoreMappers(); // register the scope provider - container.RegisterSingleton(); // implements both IScopeProvider and IScopeAccessor - container.RegisterSingleton(f => f.GetInstance()); - container.RegisterSingleton(f => f.GetInstance()); + composition.RegisterSingleton(); // implements both IScopeProvider and IScopeAccessor + composition.RegisterSingleton(f => f.GetInstance()); + composition.RegisterSingleton(f => f.GetInstance()); // register database builder // *not* a singleton, don't want to keep it around - composition.Container.Register(); + composition.Register(); // register manifest parser, will be injected in collection builders where needed - composition.Container.RegisterSingleton(); + composition.RegisterSingleton(); // register our predefined validators composition.GetCollectionBuilder() @@ -72,12 +70,12 @@ namespace Umbraco.Core.Runtime // properties and parameters derive from data editors composition.GetCollectionBuilder() - .Add(factory => factory.GetInstance().GetDataEditors()); - composition.Container.RegisterSingleton(); - composition.Container.RegisterSingleton(); + .Add(() => composition.TypeLoader.GetDataEditors()); + composition.RegisterSingleton(); + composition.RegisterSingleton(); // register a server registrar, by default it's the db registrar - composition.Container.RegisterSingleton(f => + composition.RegisterSingleton(f => { if ("true".InvariantEquals(ConfigurationManager.AppSettings["umbracoDisableElectionForSingleServer"])) return new SingleServerRegistrar(f.GetInstance()); @@ -89,7 +87,7 @@ namespace Umbraco.Core.Runtime // by default we'll use the database server messenger with default options (no callbacks), // this will be overridden by either the legacy thing or the db thing in the corresponding // components in the web project - fixme - should obsolete the legacy thing - composition.Container.RegisterSingleton(factory + composition.RegisterSingleton(factory => new DatabaseServerMessenger( factory.GetInstance(), factory.GetInstance(), @@ -99,29 +97,29 @@ namespace Umbraco.Core.Runtime true, new DatabaseServerMessengerOptions())); composition.GetCollectionBuilder() - .Add(factory => factory.GetInstance().GetCacheRefreshers()); + .Add(() => composition.TypeLoader.GetCacheRefreshers()); composition.GetCollectionBuilder() - .Add(f => f.GetInstance().GetPackageActions()); + .Add(() => composition.TypeLoader.GetPackageActions()); composition.GetCollectionBuilder() - .Append(factory => factory.GetInstance().GetTypes()); + .Append(composition.TypeLoader.GetTypes()); - composition.Container.RegisterSingleton(); + composition.RegisterSingleton(); - composition.Container.RegisterSingleton(factory + composition.RegisterSingleton(factory => new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(factory.GetInstance()))); composition.GetCollectionBuilder() .Append(); composition.GetCollectionBuilder() - .Add(factory => factory.GetInstance().GetTypes()); + .Add(() => composition.TypeLoader.GetTypes()); - composition.Container.RegisterSingleton(factory => new MigrationBuilder(composition.Container)); + composition.RegisterSingleton(factory => new MigrationBuilder(factory)); // by default, register a noop factory - composition.Container.RegisterSingleton(); + composition.RegisterSingleton(); } internal void Initialize(IEnumerable mapperProfiles) diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 2e235dcd23..3dfde3b175 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -321,7 +321,7 @@ - + diff --git a/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs b/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs index d3b0b6cda8..2c68b1608a 100644 --- a/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs +++ b/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs @@ -1,11 +1,14 @@ using System; using System.Collections.Generic; using System.Linq; +using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Components; using Umbraco.Core.Composing; +using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; using Umbraco.Core.Sync; namespace Umbraco.Tests.Cache.DistributedCache @@ -21,8 +24,9 @@ namespace Umbraco.Tests.Cache.DistributedCache [SetUp] public void Setup() { - var container = Current.Container = ContainerFactory.Create(); - var composition = new Composition(container, RuntimeLevel.Run); + var container = ContainerFactory.Create(); + Current.Factory = container; + var composition = new Composition(container, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); container.Register(_ => new TestServerRegistrar()); container.RegisterSingleton(_ => new TestServerMessenger()); diff --git a/src/Umbraco.Tests/Components/ComponentTests.cs b/src/Umbraco.Tests/Components/ComponentTests.cs index 9c38731cb8..e455f9e6e7 100644 --- a/src/Umbraco.Tests/Components/ComponentTests.cs +++ b/src/Umbraco.Tests/Components/ComponentTests.cs @@ -4,8 +4,10 @@ using System.Linq; using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Components; using Umbraco.Core.Composing; +using Umbraco.Core.Configuration; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Persistence; @@ -21,11 +23,11 @@ namespace Umbraco.Tests.Components private static readonly List Composed = new List(); private static readonly List Initialized = new List(); - private static IContainer MockContainer(Action> setup = null) + private static IFactory GetMockFactory(Action> setup = null) { // fixme use IUmbracoDatabaseFactory vs UmbracoDatabaseFactory, clean it all up! - var mock = new Mock(); + var mock = new Mock(); var logger = Mock.Of(); var f = new UmbracoDatabaseFactory(logger, new Lazy(() => new MapperCollection(Enumerable.Empty()))); @@ -41,11 +43,23 @@ namespace Umbraco.Tests.Components return mock.Object; } + private static IRegister GetMockRegister() + { + return Mock.Of(); + } + + private static TypeLoader GetMockTypeLoader() + { + return new TypeLoader(); + } + + // fixme should we have Composition.Logger, which would be a profiling logger too? + [Test] public void Boot1A() { - var container = MockContainer(); - var composition = new Composition(container, RuntimeLevel.Unknown); + var register = GetMockRegister(); + var composition = new Composition(register, GetMockTypeLoader(), Mock.Of(), RuntimeLevel.Unknown); var types = TypeArray(); var components = new Core.Components.Components(composition, types, Mock.Of()); @@ -60,8 +74,8 @@ namespace Umbraco.Tests.Components [Test] public void Boot1B() { - var container = MockContainer(); - var composition = new Composition(container, RuntimeLevel.Run); + var register = GetMockRegister(); + var composition = new Composition(register, GetMockTypeLoader(), Mock.Of(), RuntimeLevel.Run); var types = TypeArray(); var components = new Core.Components.Components(composition, types, Mock.Of()); @@ -76,8 +90,8 @@ namespace Umbraco.Tests.Components [Test] public void Boot2() { - var container = MockContainer(); - var composition = new Composition(container, RuntimeLevel.Unknown); + var register = GetMockRegister(); + var composition = new Composition(register, GetMockTypeLoader(), Mock.Of(), RuntimeLevel.Unknown); var types = TypeArray(); var components = new Core.Components.Components(composition, types, Mock.Of()); @@ -91,8 +105,8 @@ namespace Umbraco.Tests.Components [Test] public void Boot3() { - var container = MockContainer(); - var composition = new Composition(container, RuntimeLevel.Unknown); + var register = GetMockRegister(); + var composition = new Composition(register, GetMockTypeLoader(), Mock.Of(), RuntimeLevel.Unknown); var types = TypeArray(); var components = new Core.Components.Components(composition, types, Mock.Of()); @@ -108,8 +122,8 @@ namespace Umbraco.Tests.Components [Test] public void BrokenRequire() { - var container = MockContainer(); - var composition = new Composition(container, RuntimeLevel.Unknown); + var register = GetMockRegister(); + var composition = new Composition(register, GetMockTypeLoader(), Mock.Of(), RuntimeLevel.Unknown); var types = TypeArray(); var components = new Core.Components.Components(composition, types, Mock.Of()); @@ -131,8 +145,8 @@ namespace Umbraco.Tests.Components [Test] public void BrokenRequired() { - var container = MockContainer(); - var composition = new Composition(container, RuntimeLevel.Unknown); + var register = GetMockRegister(); + var composition = new Composition(register, GetMockTypeLoader(), Mock.Of(), RuntimeLevel.Unknown); var types = TypeArray(); var components = new Core.Components.Components(composition, types, Mock.Of()); @@ -148,18 +162,19 @@ namespace Umbraco.Tests.Components [Test] public void Initialize() { - var container = MockContainer(m => + var register = GetMockRegister(); + var factory = GetMockFactory(m => { m.Setup(x => x.TryGetInstance(It.Is(t => t == typeof (ISomeResource)))).Returns(() => new SomeResource()); }); - var composition = new Composition(container, RuntimeLevel.Unknown); + var composition = new Composition(register, GetMockTypeLoader(), Mock.Of(), RuntimeLevel.Unknown); var types = new[] { typeof(Component1), typeof(Component5) }; var components = new Core.Components.Components(composition, types, Mock.Of()); Composed.Clear(); Initialized.Clear(); components.Compose(); - components.Initialize(); + components.Initialize(factory); Assert.AreEqual(2, Composed.Count); Assert.AreEqual(typeof(Component1), Composed[0]); Assert.AreEqual(typeof(Component5), Composed[1]); @@ -170,8 +185,8 @@ namespace Umbraco.Tests.Components [Test] public void Requires1() { - var container = MockContainer(); - var composition = new Composition(container, RuntimeLevel.Unknown); + var register = GetMockRegister(); + var composition = new Composition(register, GetMockTypeLoader(), Mock.Of(), RuntimeLevel.Unknown); var types = new[] { typeof(Component6), typeof(Component7), typeof(Component8) }; var components = new Core.Components.Components(composition, types, Mock.Of()); @@ -185,8 +200,8 @@ namespace Umbraco.Tests.Components [Test] public void Requires2A() { - var container = MockContainer(); - var composition = new Composition(container, RuntimeLevel.Unknown); + var register = GetMockRegister(); + var composition = new Composition(register, GetMockTypeLoader(), Mock.Of(), RuntimeLevel.Unknown); var types = new[] { typeof(Component9), typeof(Component2), typeof(Component4) }; var components = new Core.Components.Components(composition, types, Mock.Of()); @@ -201,14 +216,15 @@ namespace Umbraco.Tests.Components [Test] public void Requires2B() { - var container = MockContainer(); - var composition = new Composition(container, RuntimeLevel.Run); + var register = GetMockRegister(); + var factory = GetMockFactory(); + var composition = new Composition(register, GetMockTypeLoader(), Mock.Of(), RuntimeLevel.Run); var types = new[] { typeof(Component9), typeof(Component2), typeof(Component4) }; var components = new Core.Components.Components(composition, types, Mock.Of()); Composed.Clear(); components.Compose(); - components.Initialize(); + components.Initialize(factory); Assert.AreEqual(3, Composed.Count); Assert.AreEqual(typeof(Component4), Composed[0]); Assert.AreEqual(typeof(Component2), Composed[1]); @@ -218,8 +234,8 @@ namespace Umbraco.Tests.Components [Test] public void WeakDependencies() { - var container = MockContainer(); - var composition = new Composition(container, RuntimeLevel.Unknown); + var register = GetMockRegister(); + var composition = new Composition(register, GetMockTypeLoader(), Mock.Of(), RuntimeLevel.Unknown); var types = new[] { typeof(Component10) }; var components = new Core.Components.Components(composition, types, Mock.Of()); @@ -249,8 +265,8 @@ namespace Umbraco.Tests.Components [Test] public void DisableMissing() { - var container = MockContainer(); - var composition = new Composition(container, RuntimeLevel.Unknown); + var register = GetMockRegister(); + var composition = new Composition(register, GetMockTypeLoader(), Mock.Of(), RuntimeLevel.Unknown); var types = new[] { typeof(Component6), typeof(Component8) }; // 8 disables 7 which is not in the list var components = new Core.Components.Components(composition, types, Mock.Of()); diff --git a/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs b/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs index 23914ef2bf..6047b5bb9a 100644 --- a/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs +++ b/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs @@ -1,10 +1,14 @@ using System; using System.Collections.Generic; using System.Linq; +using Moq; using NUnit.Framework; using Umbraco.Core.Composing; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Components; +using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; namespace Umbraco.Tests.Composing { @@ -12,6 +16,7 @@ namespace Umbraco.Tests.Composing public class CollectionBuildersTests { private IContainer _container; + private IFactory _factory; private Composition _composition; [SetUp] @@ -19,8 +24,10 @@ namespace Umbraco.Tests.Composing { Current.Reset(); - _container = Current.Container = ContainerFactory.Create(); - _composition = new Composition(_container, RuntimeLevel.Run); + _container = ContainerFactory.Create(); + _factory = _container; + Current.Factory = _container; + _composition = new Composition(_container, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); } [TearDown] @@ -44,7 +51,7 @@ namespace Umbraco.Tests.Composing Assert.IsFalse(builder.Has()); //Assert.IsFalse(col.ContainsType()); // does not compile - var col = builder.CreateCollection(); + var col = builder.CreateCollection(_factory); AssertCollection(col, typeof(Resolved1), typeof(Resolved2)); } @@ -59,7 +66,7 @@ namespace Umbraco.Tests.Composing Assert.IsFalse(builder.Has()); Assert.IsFalse(builder.Has()); - var col = builder.CreateCollection(); + var col = builder.CreateCollection(_factory); AssertCollection(col); } @@ -70,7 +77,7 @@ namespace Umbraco.Tests.Composing .Append() .Append(); - var col = builder.CreateCollection(); + var col = builder.CreateCollection(_factory); Assert.Throws(() => builder.Clear()); } @@ -86,7 +93,7 @@ namespace Umbraco.Tests.Composing Assert.IsTrue(builder.Has()); Assert.IsFalse(builder.Has()); - var col = builder.CreateCollection(); + var col = builder.CreateCollection(_factory); AssertCollection(col, typeof(Resolved1), typeof(Resolved2)); } @@ -95,7 +102,7 @@ namespace Umbraco.Tests.Composing { var builder = _composition.GetCollectionBuilder(); - var col = builder.CreateCollection(); + var col = builder.CreateCollection(_factory); Assert.Throws(() => builder.Append() @@ -109,7 +116,7 @@ namespace Umbraco.Tests.Composing builder.Append(); builder.Append(); - var col = builder.CreateCollection(); + var col = builder.CreateCollection(_factory); AssertCollection(col, typeof(Resolved1)); } @@ -135,7 +142,7 @@ namespace Umbraco.Tests.Composing Assert.IsFalse(builder.Has()); Assert.IsFalse(builder.Has()); - var col = builder.CreateCollection(); + var col = builder.CreateCollection(_factory); AssertCollection(col, typeof(Resolved1)); } @@ -147,7 +154,7 @@ namespace Umbraco.Tests.Composing .Append() .Remove(); - var col = builder.CreateCollection(); + var col = builder.CreateCollection(_factory); AssertCollection(col, typeof(Resolved1), typeof(Resolved2)); } @@ -158,7 +165,7 @@ namespace Umbraco.Tests.Composing .Append() .Append(); - var col = builder.CreateCollection(); + var col = builder.CreateCollection(_factory); Assert.Throws(() => builder.Remove() // throws ); @@ -176,7 +183,7 @@ namespace Umbraco.Tests.Composing Assert.IsTrue(builder.Has()); Assert.IsTrue(builder.Has()); - var col = builder.CreateCollection(); + var col = builder.CreateCollection(_factory); AssertCollection(col, typeof(Resolved3), typeof(Resolved1), typeof(Resolved2)); } @@ -187,7 +194,7 @@ namespace Umbraco.Tests.Composing .Append() .Append(); - var col = builder.CreateCollection(); + var col = builder.CreateCollection(_factory); Assert.Throws(() => builder.Insert() // throws ); @@ -201,7 +208,7 @@ namespace Umbraco.Tests.Composing .Append() .Insert(); - var col = builder.CreateCollection(); + var col = builder.CreateCollection(_factory); AssertCollection(col, typeof(Resolved2), typeof(Resolved1)); } @@ -211,7 +218,7 @@ namespace Umbraco.Tests.Composing var builder = _composition.GetCollectionBuilder(); builder.Insert(); - var col = builder.CreateCollection(); + var col = builder.CreateCollection(_factory); AssertCollection(col, typeof(Resolved2)); } @@ -243,7 +250,7 @@ namespace Umbraco.Tests.Composing Assert.IsTrue(builder.Has()); Assert.IsTrue(builder.Has()); - var col = builder.CreateCollection(); + var col = builder.CreateCollection(_factory); AssertCollection(col, typeof(Resolved1), typeof(Resolved3), typeof(Resolved2)); } @@ -254,7 +261,7 @@ namespace Umbraco.Tests.Composing .Append() .Append(); - var col = builder.CreateCollection(); + var col = builder.CreateCollection(_factory); Assert.Throws(() => builder.InsertBefore() ); @@ -268,7 +275,7 @@ namespace Umbraco.Tests.Composing .Append() .InsertBefore(); - var col = builder.CreateCollection(); + var col = builder.CreateCollection(_factory); AssertCollection(col, typeof(Resolved2), typeof(Resolved1)); } @@ -331,7 +338,7 @@ namespace Umbraco.Tests.Composing .Insert() .InsertBefore(); - var col1 = builder.CreateCollection(); + var col1 = builder.CreateCollection(_factory); AssertCollection(col1, typeof(Resolved1), typeof(Resolved2), typeof(Resolved3)); } @@ -376,7 +383,7 @@ namespace Umbraco.Tests.Composing .Add() .Add(); - var col = builder.CreateCollection(); + var col = builder.CreateCollection(_factory); AssertCollection(col, typeof(Resolved2), typeof(Resolved1)); } diff --git a/src/Umbraco.Tests/Composing/ContainerImplementationTests.cs b/src/Umbraco.Tests/Composing/ContainerImplementationTests.cs index 5b72bc17b4..7b0ac4acf9 100644 --- a/src/Umbraco.Tests/Composing/ContainerImplementationTests.cs +++ b/src/Umbraco.Tests/Composing/ContainerImplementationTests.cs @@ -9,7 +9,7 @@ namespace Umbraco.Tests.Composing // complies with Umbraco's requirements. [TestFixture] - public class ContainerImplementationTests + public class ContainerImplementationTests // FIXME merge into ContainerTests or ContainerConformingTests { private IContainer CreateContainer() => ContainerFactory.Create(); diff --git a/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs b/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs index 3d0a9602a2..c39b7d6943 100644 --- a/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs +++ b/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs @@ -1,10 +1,14 @@ using System; using System.Collections.Generic; using System.Linq; +using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Components; using Umbraco.Core.Composing; +using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; namespace Umbraco.Tests.Composing { @@ -24,7 +28,11 @@ namespace Umbraco.Tests.Composing } private IContainer CreateContainer() - => Current.Container = ContainerFactory.Create(); + { + var container = ContainerFactory.Create(); + Current.Factory = container; + return container; + } // note // lazy collection builder does not throw on duplicate, just uses distinct types @@ -34,7 +42,7 @@ namespace Umbraco.Tests.Composing public void LazyCollectionBuilderHandlesTypes() { var container = CreateContainer(); - var composition = new Composition(container, RuntimeLevel.Run); + var composition = new Composition(container, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); composition.GetCollectionBuilder() .Add() @@ -58,7 +66,7 @@ namespace Umbraco.Tests.Composing public void LazyCollectionBuilderHandlesProducers() { var container = CreateContainer(); - var composition = new Composition(container, RuntimeLevel.Run); + var composition = new Composition(container, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); composition.GetCollectionBuilder() .Add(() => new[] { typeof(TransientObject3), typeof(TransientObject2) }) @@ -81,7 +89,7 @@ namespace Umbraco.Tests.Composing public void LazyCollectionBuilderHandlesTypesAndProducers() { var container = CreateContainer(); - var composition = new Composition(container, RuntimeLevel.Run); + var composition = new Composition(container, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); composition.GetCollectionBuilder() .Add() @@ -105,7 +113,7 @@ namespace Umbraco.Tests.Composing public void LazyCollectionBuilderThrowsOnIllegalTypes() { var container = CreateContainer(); - var composition = new Composition(container, RuntimeLevel.Run); + var composition = new Composition(container, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); composition.GetCollectionBuilder() .Add() @@ -127,7 +135,7 @@ namespace Umbraco.Tests.Composing public void LazyCollectionBuilderCanExcludeTypes() { var container = CreateContainer(); - var composition = new Composition(container, RuntimeLevel.Run); + var composition = new Composition(container, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); composition.GetCollectionBuilder() .Add() diff --git a/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs b/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs index 8893b61fde..c130165d69 100644 --- a/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs +++ b/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs @@ -1,10 +1,12 @@ using System; using System.Linq; using System.Xml; +using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Components; using Umbraco.Core.Composing; +using Umbraco.Core.Logging; using Umbraco.Core._Legacy.PackageActions; namespace Umbraco.Tests.Composing @@ -15,8 +17,9 @@ namespace Umbraco.Tests.Composing [Test] public void PackageActionCollectionBuilderWorks() { - var container = Current.Container = ContainerFactory.Create(); - var composition = new Composition(container, RuntimeLevel.Run); + var container = ContainerFactory.Create(); + Current.Factory = container; + var composition = new Composition(container, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); composition.GetCollectionBuilder() .Add(() => TypeLoader.GetPackageActions()); diff --git a/src/Umbraco.Tests/CoreThings/UdiTests.cs b/src/Umbraco.Tests/CoreThings/UdiTests.cs index 77f3b10a2f..3ee7f33b6e 100644 --- a/src/Umbraco.Tests/CoreThings/UdiTests.cs +++ b/src/Umbraco.Tests/CoreThings/UdiTests.cs @@ -22,11 +22,11 @@ namespace Umbraco.Tests.CoreThings public void SetUp() { // fixme - bad in a unit test - but Udi has a static ctor that wants it?! - var container = new Mock(); + var container = new Mock(); var globalSettings = SettingsForTests.GenerateMockGlobalSettings(); container.Setup(x => x.GetInstance(typeof(TypeLoader))).Returns( new TypeLoader(NullCacheProvider.Instance, globalSettings, new ProfilingLogger(Mock.Of(), Mock.Of()))); - Current.Container = container.Object; + Current.Factory = container.Object; Udi.ResetUdiTypes(); } diff --git a/src/Umbraco.Tests/FrontEnd/UmbracoHelperTests.cs b/src/Umbraco.Tests/FrontEnd/UmbracoHelperTests.cs index 3d33604870..7571388d1b 100644 --- a/src/Umbraco.Tests/FrontEnd/UmbracoHelperTests.cs +++ b/src/Umbraco.Tests/FrontEnd/UmbracoHelperTests.cs @@ -406,7 +406,7 @@ namespace Umbraco.Tests.FrontEnd private void SetUpDependencyContainer() { // fixme - bad in a unit test - but Udi has a static ctor that wants it?! - var container = new Mock(); + var container = new Mock(); var globalSettings = SettingsForTests.GenerateMockGlobalSettings(); container @@ -418,7 +418,7 @@ namespace Umbraco.Tests.FrontEnd ) ); - Current.Container = container.Object; + Current.Factory = container.Object; } } } diff --git a/src/Umbraco.Tests/IO/FileSystemsTests.cs b/src/Umbraco.Tests/IO/FileSystemsTests.cs index c72f7949f5..cd2d60395f 100644 --- a/src/Umbraco.Tests/IO/FileSystemsTests.cs +++ b/src/Umbraco.Tests/IO/FileSystemsTests.cs @@ -4,10 +4,12 @@ using System.Text; using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Components; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Composing; using Umbraco.Core.Composing.Composers; +using Umbraco.Core.Configuration; using Umbraco.Core.IO; using Umbraco.Core.IO.MediaPathSchemes; using Umbraco.Core.Logging; @@ -28,8 +30,9 @@ namespace Umbraco.Tests.IO var config = SettingsForTests.GetDefaultUmbracoSettings(); SettingsForTests.ConfigureSettings(config); - _container = Current.Container = ContainerFactory.Create(); - var composition = new Composition(_container, RuntimeLevel.Run); + _container = ContainerFactory.Create(); + Current.Factory = _container; + var composition = new Composition(_container, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); _container.Register(_ => Mock.Of()); _container.Register(_ => Mock.Of()); diff --git a/src/Umbraco.Tests/IO/ShadowFileSystemTests.cs b/src/Umbraco.Tests/IO/ShadowFileSystemTests.cs index 50ce85f356..36f4c56173 100644 --- a/src/Umbraco.Tests/IO/ShadowFileSystemTests.cs +++ b/src/Umbraco.Tests/IO/ShadowFileSystemTests.cs @@ -396,7 +396,7 @@ namespace Umbraco.Tests.IO var phy = new PhysicalFileSystem(path, "ignore"); - var container = Mock.Of(); + var container = Mock.Of(); var fileSystems = new FileSystems(container, logger) { IsScoped = () => scopedFileSystems }; var fs = fileSystems.GetFileSystem(phy); var sw = (ShadowWrapper) fs.InnerFileSystem; @@ -489,7 +489,7 @@ namespace Umbraco.Tests.IO var phy = new PhysicalFileSystem(path, "ignore"); - var container = Mock.Of(); + var container = Mock.Of(); var fileSystems = new FileSystems(container, logger) { IsScoped = () => scopedFileSystems }; var fs = fileSystems.GetFileSystem( phy); var sw = (ShadowWrapper) fs.InnerFileSystem; @@ -542,7 +542,7 @@ namespace Umbraco.Tests.IO var phy = new PhysicalFileSystem(path, "ignore"); - var container = Mock.Of(); + var container = Mock.Of(); var fileSystems = new FileSystems(container, logger) { IsScoped = () => scopedFileSystems }; var fs = fileSystems.GetFileSystem( phy); var sw = (ShadowWrapper)fs.InnerFileSystem; diff --git a/src/Umbraco.Tests/Manifest/ManifestParserTests.cs b/src/Umbraco.Tests/Manifest/ManifestParserTests.cs index 98ebeb9315..948171b0cb 100644 --- a/src/Umbraco.Tests/Manifest/ManifestParserTests.cs +++ b/src/Umbraco.Tests/Manifest/ManifestParserTests.cs @@ -26,7 +26,7 @@ namespace Umbraco.Tests.Manifest { Current.Reset(); var container = Mock.Of(); - Current.Container = container; + Current.Factory = container; var serviceContext = new ServiceContext( localizedTextService: Mock.Of()); diff --git a/src/Umbraco.Tests/Models/VariationTests.cs b/src/Umbraco.Tests/Models/VariationTests.cs index 6eb7e35aa8..c7bc269e61 100644 --- a/src/Umbraco.Tests/Models/VariationTests.cs +++ b/src/Umbraco.Tests/Models/VariationTests.cs @@ -27,7 +27,7 @@ namespace Umbraco.Tests.Models Current.Reset(); var container = Mock.Of(); - Current.Container = container; + Current.Factory = container; var dataEditors = new DataEditorCollection(new IDataEditor[] { diff --git a/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs b/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs index de27c30b1d..24aa1aaa55 100644 --- a/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs +++ b/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs @@ -5,8 +5,10 @@ using Newtonsoft.Json; using NUnit.Framework; using Newtonsoft.Json.Linq; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Components; using Umbraco.Core.Composing; +using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; using Umbraco.Core.Logging; @@ -67,8 +69,9 @@ namespace Umbraco.Tests.PropertyEditors { try { - var container = Current.Container = ContainerFactory.Create(); - var composition = new Composition(container, RuntimeLevel.Run); + var container = ContainerFactory.Create(); + Current.Factory = container; + var composition = new Composition(container, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); composition.GetCollectionBuilder(); diff --git a/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs b/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs index 00ca646360..17ca52ca61 100644 --- a/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs +++ b/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs @@ -21,7 +21,8 @@ namespace Umbraco.Tests.PropertyEditors //normalize culture Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture; - var container = Current.Container = ContainerFactory.Create(); + var container = ContainerFactory.Create(); + Current.Factory = container; container.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 0e65f5723f..2a0aea1e8e 100644 --- a/src/Umbraco.Tests/Published/ConvertersTests.cs +++ b/src/Umbraco.Tests/Published/ConvertersTests.cs @@ -4,8 +4,10 @@ using System.Linq; using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Components; using Umbraco.Core.Composing; +using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; @@ -172,8 +174,9 @@ namespace Umbraco.Tests.Published public void SimpleConverter3Test() { Current.Reset(); - var container = Current.Container = ContainerFactory.Create(); - var composition = new Composition(container, RuntimeLevel.Run); + var container = ContainerFactory.Create(); + Current.Factory = container; + var composition = new Composition(container, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); composition.GetCollectionBuilder() .Append() @@ -184,7 +187,7 @@ namespace Umbraco.Tests.Published typeof (PublishedSnapshotTestObjects.TestElementModel1), typeof (PublishedSnapshotTestObjects.TestElementModel2), typeof (PublishedSnapshotTestObjects.TestContentModel1), typeof (PublishedSnapshotTestObjects.TestContentModel2), }); - Current.Container.Register(f => factory); + container.Register(f => factory); var cacheMock = new Mock(); var cacheContent = new Dictionary(); @@ -193,9 +196,9 @@ namespace Umbraco.Tests.Published publishedSnapshotMock.Setup(x => x.Content).Returns(cacheMock.Object); var publishedSnapshotAccessorMock = new Mock(); publishedSnapshotAccessorMock.Setup(x => x.PublishedSnapshot).Returns(publishedSnapshotMock.Object); - Current.Container.Register(f => publishedSnapshotAccessorMock.Object); + container.Register(f => publishedSnapshotAccessorMock.Object); - var converters = Current.Container.GetInstance(); + var converters = Current.Factory.GetInstance(); var dataTypeService = new TestObjects.TestDataTypeService( new DataType(new VoidEditor(Mock.Of())) { Id = 1 }, diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentLanguageVariantTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentLanguageVariantTests.cs index 2288ff80c2..4b431d18e6 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentLanguageVariantTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentLanguageVariantTests.cs @@ -16,7 +16,7 @@ using Umbraco.Web; namespace Umbraco.Tests.PublishedContent { [TestFixture] - [UmbracoTest(PluginManager = UmbracoTestOptions.PluginManager.PerFixture)] + [UmbracoTest(TypeLoader = UmbracoTestOptions.TypeLoader.PerFixture)] public class PublishedContentLanguageVariantTests : PublishedContentSnapshotTestBase { protected override void Compose() diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentMoreTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentMoreTests.cs index 9751a7ae6a..c5b8e21870 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentMoreTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentMoreTests.cs @@ -9,7 +9,7 @@ using Umbraco.Tests.Testing; namespace Umbraco.Tests.PublishedContent { [TestFixture] - [UmbracoTest(PluginManager = UmbracoTestOptions.PluginManager.PerFixture)] + [UmbracoTest(TypeLoader = UmbracoTestOptions.TypeLoader.PerFixture)] public class PublishedContentMoreTests : PublishedContentSnapshotTestBase { internal override void PopulateCache(PublishedContentTypeFactory factory, SolidPublishedContentCache cache) diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs index dc88f8bea1..c4f4d5304f 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs @@ -11,6 +11,8 @@ using Umbraco.Web.Security; using Umbraco.Core.Composing; using Current = Umbraco.Core.Composing.Current; using LightInject; +using Umbraco.Core.Cache; +using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; @@ -40,9 +42,9 @@ namespace Umbraco.Tests.PublishedContent Container.RegisterSingleton(f => new PublishedModelFactory(f.GetInstance().GetTypes())); } - protected override TypeLoader CreatePluginManager(IContainer f) + protected override TypeLoader CreateTypeLoader(IRuntimeCacheProvider runtimeCache, IGlobalSettings globalSettings, IProfilingLogger logger) { - var pluginManager = base.CreatePluginManager(f); + var pluginManager = base.CreateTypeLoader(runtimeCache, globalSettings, logger); // this is so the model factory looks into the test assembly pluginManager.AssembliesToScan = pluginManager.AssembliesToScan diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs index 6eef72bcd9..9b3ceb21d1 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs @@ -10,6 +10,8 @@ using Umbraco.Web; using Umbraco.Web.PublishedCache; using Umbraco.Core.Composing; using Moq; +using Umbraco.Core.Cache; +using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Services; @@ -24,7 +26,7 @@ namespace Umbraco.Tests.PublishedContent /// Tests the methods on IPublishedContent using the DefaultPublishedContentStore /// [TestFixture] - [UmbracoTest(PluginManager = UmbracoTestOptions.PluginManager.PerFixture)] + [UmbracoTest(TypeLoader = UmbracoTestOptions.TypeLoader.PerFixture)] public class PublishedContentTests : PublishedContentTestBase { protected override void Compose() @@ -71,9 +73,9 @@ namespace Umbraco.Tests.PublishedContent ContentTypesCache.GetPublishedContentTypeByAlias = alias => type; } - protected override TypeLoader CreatePluginManager(IContainer f) + protected override TypeLoader CreateTypeLoader(IRuntimeCacheProvider runtimeCache, IGlobalSettings globalSettings, IProfilingLogger logger) { - var pluginManager = base.CreatePluginManager(f); + var pluginManager = base.CreateTypeLoader(runtimeCache, globalSettings, logger); // this is so the model factory looks into the test assembly pluginManager.AssembliesToScan = pluginManager.AssembliesToScan diff --git a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs index f92b4264ec..ceac7127f2 100644 --- a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs +++ b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs @@ -131,7 +131,7 @@ namespace Umbraco.Tests.Runtimes It.IsAny())) .Returns(Mock.Of()); - composition.Container.RegisterInstance(scopeProvider); + composition.RegisterInstance(scopeProvider); } private MainDom _mainDom; @@ -183,8 +183,8 @@ namespace Umbraco.Tests.Runtimes { base.Compose(composition); - composition.Container.Register(factory => SettingsForTests.GetDefaultUmbracoSettings()); - composition.Container.RegisterSingleton(); + composition.Register(factory => SettingsForTests.GetDefaultUmbracoSettings()); + composition.RegisterSingleton(); Composed = true; } diff --git a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs index 486cf55769..fa1d0482cf 100644 --- a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs @@ -3,6 +3,7 @@ using System.Linq; using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Components; using Umbraco.Core.Events; using Umbraco.Core.Models; @@ -12,6 +13,7 @@ using Umbraco.Core.Scoping; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Entities; using Umbraco.Core.Composing; +using Umbraco.Core.Configuration; using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Services; @@ -30,12 +32,13 @@ namespace Umbraco.Tests.Scoping DoThing2 = null; DoThing3 = null; - var container = Current.Container = ContainerFactory.Create(); - var composition = new Composition(container, RuntimeLevel.Run); + var container = ContainerFactory.Create(); + Current.Factory = container; + var composition = new Composition(container, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); _testObjects = new TestObjects(container); - Current.Container.RegisterSingleton(factory => new FileSystems(container, factory.TryGetInstance())); + container.RegisterSingleton(factory => new FileSystems(container, factory.TryGetInstance())); composition.GetCollectionBuilder(); SettingsForTests.Reset(); // ensure we have configuration diff --git a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs index b25b7eed42..ada58942c3 100644 --- a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs @@ -47,7 +47,7 @@ namespace Umbraco.Tests.Scoping Container.RegisterSingleton(); Container.RegisterSingleton(f => Mock.Of()); Composition.GetCollectionBuilder() - .Add(f => f.TryGetInstance().GetCacheRefreshers()); + .Add(() => Composition.TypeLoader.GetCacheRefreshers()); } public override void TearDown() diff --git a/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs b/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs index 3d281575fb..a4040ca019 100644 --- a/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs @@ -33,19 +33,17 @@ namespace Umbraco.Tests.Scoping Container.RegisterSingleton(); Container.RegisterSingleton(f => Mock.Of()); Composition.GetCollectionBuilder() - .Add(f => f.TryGetInstance().GetCacheRefreshers()); + .Add(() => Composition.TypeLoader.GetCacheRefreshers()); } - protected override void ComposeCacheHelper() + protected override CacheHelper GetCacheHelper() { // this is what's created core web runtime - var cacheHelper = new CacheHelper( + return new CacheHelper( new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()), new StaticCacheProvider(), NullCacheProvider.Instance, new IsolatedRuntimeCache(type => new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()))); - Container.RegisterSingleton(f => cacheHelper); - Container.RegisterSingleton(f => f.GetInstance().RuntimeCache); } [TearDown] diff --git a/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs b/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs index 2cfadb9408..9c98dcd538 100644 --- a/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs @@ -35,7 +35,7 @@ namespace Umbraco.Tests.Scoping Container.RegisterSingleton(); Container.RegisterSingleton(f => Mock.Of()); Composition.GetCollectionBuilder() - .Add(f => f.TryGetInstance().GetCacheRefreshers()); + .Add(() => Composition.TypeLoader.GetCacheRefreshers()); } [TearDown] @@ -63,7 +63,7 @@ namespace Umbraco.Tests.Scoping // xmlStore.Xml - the actual main xml document // publishedContentCache.GetXml() - the captured xml - private static XmlStore XmlStore => (Current.Container.GetInstance() as PublishedSnapshotService).XmlStore; + private static XmlStore XmlStore => (Current.Factory.GetInstance() as PublishedSnapshotService).XmlStore; private static XmlDocument XmlMaster => XmlStore.Xml; private static XmlDocument XmlInContext => ((PublishedContentCache) Umbraco.Web.Composing.Current.UmbracoContext.ContentCache).GetXml(false); diff --git a/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs b/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs index b934686c87..5b3d2f2583 100644 --- a/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs +++ b/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs @@ -38,7 +38,7 @@ namespace Umbraco.Tests.Services Container.RegisterSingleton(); Container.RegisterSingleton(f => Mock.Of()); Composition.GetCollectionBuilder() - .Add(f => f.TryGetInstance().GetCacheRefreshers()); + .Add(() => Composition.TypeLoader.GetCacheRefreshers()); } protected override IPublishedSnapshotService CreatePublishedSnapshotService() diff --git a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs index c8a2219c3f..09ce5fb916 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs @@ -8,6 +8,7 @@ using Umbraco.Core.Logging; using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Composing; +using Umbraco.Core.Configuration; using Umbraco.Core.Persistence; namespace Umbraco.Tests.TestHelpers @@ -33,8 +34,9 @@ namespace Umbraco.Tests.TestHelpers var sqlSyntax = new SqlCeSyntaxProvider(); - var container = Current.Container = ContainerFactory.Create(); - var composition = new Composition(container, RuntimeLevel.Run); + var container = ContainerFactory.Create(); + Current.Factory = container; + var composition = new Composition(container, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); container.RegisterSingleton(factory => Mock.Of()); container.RegisterSingleton(factory => Mock.Of()); diff --git a/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs b/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs index cabbf40fe9..b1e9257918 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs @@ -85,12 +85,12 @@ namespace Umbraco.Tests.TestHelpers "; } - internal PublishedRouter CreatePublishedRouter(IContainer container = null, ContentFinderCollection contentFinders = null) + internal PublishedRouter CreatePublishedRouter(IFactory container = null, ContentFinderCollection contentFinders = null) { return CreatePublishedRouter(TestObjects.GetUmbracoSettings().WebRouting, container, contentFinders); } - internal static PublishedRouter CreatePublishedRouter(IWebRoutingSection webRoutingSection, IContainer container = null, ContentFinderCollection contentFinders = null) + internal static PublishedRouter CreatePublishedRouter(IWebRoutingSection webRoutingSection, IFactory container = null, ContentFinderCollection contentFinders = null) { return new PublishedRouter( webRoutingSection, diff --git a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs index 7b1e47798a..0fb6e42999 100644 --- a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs +++ b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs @@ -134,10 +134,7 @@ namespace Umbraco.Tests.TestHelpers.ControllerTesting var publishedSnapshotService = new Mock(); publishedSnapshotService.Setup(x => x.CreatePublishedSnapshot(It.IsAny())).Returns(publishedSnapshot.Object); - //var umbracoContextAccessor = new TestUmbracoContextAccessor(); - //Umbraco.Web.Composing.Current.UmbracoContextAccessor = umbracoContextAccessor; var umbracoContextAccessor = Umbraco.Web.Composing.Current.UmbracoContextAccessor; - Current.Container.Register(factory => umbracoContextAccessor.UmbracoContext); // but really, should we inject this?! var umbCtx = UmbracoContext.EnsureContext( umbracoContextAccessor, diff --git a/src/Umbraco.Tests/TestHelpers/Stubs/TestControllerFactory.cs b/src/Umbraco.Tests/TestHelpers/Stubs/TestControllerFactory.cs index e9d4bb5e1a..36c5961b9f 100644 --- a/src/Umbraco.Tests/TestHelpers/Stubs/TestControllerFactory.cs +++ b/src/Umbraco.Tests/TestHelpers/Stubs/TestControllerFactory.cs @@ -48,7 +48,7 @@ namespace Umbraco.Tests.TestHelpers.Stubs foreach (var parameter in allParams) { var found = possibleParams.SingleOrDefault(x => x.GetType() == parameter.ParameterType) - ?? Current.Container.GetInstance(parameter.ParameterType); + ?? Current.Factory.GetInstance(parameter.ParameterType); if (found != null) args.Add(found); } if (args.Count == allParams.Length) diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs b/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs index 06654a3519..eeddfa6043 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs @@ -53,34 +53,37 @@ namespace Umbraco.Tests.TestHelpers /// Gets a mocked service context built with mocked services. /// /// A ServiceContext. - public ServiceContext GetServiceContextMock(IContainer container = null) + public ServiceContext GetServiceContextMock(IFactory container = null) { + // fixme - else tests break - something's wrong + container = null; + return new ServiceContext( - MockService(), - MockService(), - MockService(), - MockService(), - MockService(), - MockService(), - MockService(), - MockService(), - MockService(), - MockService(), - MockService(), - MockService(), - MockService(), - MockService(), - MockService(), - MockService(), - MockService(), - MockService(), - MockService(), - MockService(), - MockService(), - MockService()); + MockService(container), + MockService(container), + MockService(container), + MockService(container), + MockService(container), + MockService(container), + MockService(container), + MockService(container), + MockService(container), + MockService(container), + MockService(container), + MockService(container), + MockService(container), + MockService(container), + MockService(container), + MockService(container), + MockService(container), + MockService(container), + MockService(container), + MockService(container), + MockService(container), + MockService(container)); } - private T MockService(IContainer container = null) + private T MockService(IFactory container = null) where T : class { return container?.TryGetInstance() ?? new Mock().Object; diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects.cs b/src/Umbraco.Tests/TestHelpers/TestObjects.cs index c965a71a70..02e77ae1a5 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects.cs @@ -205,13 +205,13 @@ namespace Umbraco.Tests.TestHelpers consentService); } - private Lazy GetLazyService(IContainer container, Func ctor) + private Lazy GetLazyService(IFactory container, Func ctor) where T : class { return new Lazy(() => container?.TryGetInstance() ?? ctor(container)); } - private T GetRepo(IContainer container) + private T GetRepo(IFactory container) where T : class, IRepository { return container?.TryGetInstance() ?? Mock.Of(); @@ -224,11 +224,11 @@ namespace Umbraco.Tests.TestHelpers //var mappersBuilder = new MapperCollectionBuilder(Current.Container); // fixme //mappersBuilder.AddCore(); //var mappers = mappersBuilder.CreateCollection(); - var mappers = Current.Container.GetInstance(); + var mappers = Current.Factory.GetInstance(); databaseFactory = new UmbracoDatabaseFactory(Constants.System.UmbracoConnectionName, logger, new Lazy(() => mappers)); } - fileSystems = fileSystems ?? new FileSystems(Current.Container, logger); + fileSystems = fileSystems ?? new FileSystems(Current.Factory, logger); var scopeProvider = new ScopeProvider(databaseFactory, fileSystems, logger); return scopeProvider; } diff --git a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs index 02df0b4271..8128666898 100644 --- a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs +++ b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs @@ -78,7 +78,7 @@ namespace Umbraco.Tests.TestHelpers Composition.GetCollectionBuilder() .Clear() - .Add(f => f.GetInstance().GetDataEditors()); + .Add(() => Composition.TypeLoader.GetDataEditors()); Container.RegisterSingleton(f => { diff --git a/src/Umbraco.Tests/Testing/UmbracoTestAttribute.cs b/src/Umbraco.Tests/Testing/UmbracoTestAttribute.cs index 723ce43c6c..2bf4ba2716 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestAttribute.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestAttribute.cs @@ -48,8 +48,8 @@ namespace Umbraco.Tests.Testing /// Gets or sets a value indicating the required plugin manager support. /// /// Default is to use the global tests plugin manager. - public UmbracoTestOptions.PluginManager PluginManager { get => _pluginManager.ValueOrDefault(UmbracoTestOptions.PluginManager.Default); set => _pluginManager.Set(value); } - private readonly Settable _pluginManager = new Settable(); + public UmbracoTestOptions.TypeLoader TypeLoader { get => _typeLoader.ValueOrDefault(UmbracoTestOptions.TypeLoader.Default); set => _typeLoader.Set(value); } + private readonly Settable _typeLoader = new Settable(); protected override TestOptionAttributeBase Merge(TestOptionAttributeBase other) { @@ -62,7 +62,7 @@ namespace Umbraco.Tests.Testing _publishedRepositoryEvents.Set(attr._publishedRepositoryEvents); _logger.Set(attr._logger); _database.Set(attr._database); - _pluginManager.Set(attr._pluginManager); + _typeLoader.Set(attr._typeLoader); return this; } diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index 6459342e7a..d81d71511c 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -117,24 +117,35 @@ namespace Umbraco.Tests.Testing // but hey, never know, better avoid garbage-in Reset(); - Container = Current.Container = ContainerFactory.Create(); - Composition = new Composition(Container, RuntimeLevel.Run); - - TestObjects = new TestObjects(Container); - // get/merge the attributes marking the method and/or the classes Options = TestOptionAttributeBase.GetTestOptions(); + // fixme see CoreRuntime and align! + var (logger, profiler) = GetLoggers(Options.Logger); + var proflogger = new ProfilingLogger(logger, profiler); + var cacheHelper = GetCacheHelper(); + var globalSettings = SettingsForTests.GetDefaultGlobalSettings(); + var typeLoader = GetTypeLoader(cacheHelper.RuntimeCache, globalSettings, proflogger, Options.TypeLoader); + + Container = ContainerFactory.Create(); + Current.Factory = Container; + + Container.RegisterInstance(typeLoader); + Container.RegisterInstance(logger); + Container.RegisterInstance(profiler); + Container.RegisterInstance(proflogger); + Container.RegisterInstance(cacheHelper); + Container.RegisterInstance(cacheHelper.RuntimeCache); + + Composition = new Composition(Container, typeLoader, proflogger, RuntimeLevel.Run); + TestObjects = new TestObjects(Container); Compose(); Initialize(); } protected virtual void Compose() { - ComposeLogging(Options.Logger); - ComposeCacheHelper(); ComposeAutoMapper(Options.AutoMapper); - ComposePluginManager(Options.PluginManager); ComposeDatabase(Options.Database); ComposeApplication(Options.WithApplication); @@ -143,8 +154,7 @@ namespace Umbraco.Tests.Testing ComposeWtf(); // not sure really - var composition = new Composition(Container, RuntimeLevel.Run); - Compose(composition); + Compose(Composition); } protected virtual void Compose(Composition composition) @@ -160,25 +170,35 @@ namespace Umbraco.Tests.Testing #region Compose - protected virtual void ComposeLogging(UmbracoTestOptions.Logger option) + protected virtual (ILogger, IProfiler) GetLoggers(UmbracoTestOptions.Logger option) { - if (option == UmbracoTestOptions.Logger.Mock) + ILogger logger; + IProfiler profiler; + + switch (option) { - Container.RegisterSingleton(f => Mock.Of()); - Container.RegisterSingleton(f => Mock.Of()); - } - else if (option == UmbracoTestOptions.Logger.Serilog) - { - Container.RegisterSingleton(f => new SerilogLogger(new FileInfo(TestHelper.MapPathForTest("~/unit-test.config")))); - Container.RegisterSingleton(f => new LogProfiler(f.GetInstance())); - } - else if (option == UmbracoTestOptions.Logger.Console) - { - Container.RegisterSingleton(f => new ConsoleLogger()); - Container.RegisterSingleton(f => new LogProfiler(f.GetInstance())); + case UmbracoTestOptions.Logger.Mock: + logger = Mock.Of(); + profiler = Mock.Of(); + break; + case UmbracoTestOptions.Logger.Serilog: + logger = new SerilogLogger(new FileInfo(TestHelper.MapPathForTest("~/unit-test.config"))); + profiler = new LogProfiler(logger); + break; + case UmbracoTestOptions.Logger.Console: + logger = new ConsoleLogger(); + profiler = new LogProfiler(logger); + break; + default: + throw new NotSupportedException($"Logger option {option} is not supported."); } - Container.RegisterSingleton(f => new ProfilingLogger(f.GetInstance(), f.GetInstance())); + return (logger, profiler); + } + + protected virtual CacheHelper GetCacheHelper() + { + return CacheHelper.Disabled; } protected virtual void ComposeWeb() @@ -215,12 +235,6 @@ namespace Umbraco.Tests.Testing Composition.GetCollectionBuilder(); } - protected virtual void ComposeCacheHelper() - { - Container.RegisterSingleton(f => CacheHelper.Disabled); - Container.RegisterSingleton(f => f.GetInstance().RuntimeCache); - } - protected virtual void ComposeAutoMapper(bool configure) { if (configure == false) return; @@ -230,32 +244,30 @@ namespace Umbraco.Tests.Testing .ComposeWebMappingProfiles(); } - protected virtual void ComposePluginManager(UmbracoTestOptions.PluginManager pluginManager) + protected virtual TypeLoader GetTypeLoader(IRuntimeCacheProvider runtimeCache, IGlobalSettings globalSettings, IProfilingLogger logger, UmbracoTestOptions.TypeLoader option) { - Container.RegisterSingleton(f => + switch (option) { - switch (pluginManager) - { - case UmbracoTestOptions.PluginManager.Default: - return _commonTypeLoader ?? (_commonTypeLoader = CreateCommonPluginManager(f)); - case UmbracoTestOptions.PluginManager.PerFixture: - return _featureTypeLoader ?? (_featureTypeLoader = CreatePluginManager(f)); - case UmbracoTestOptions.PluginManager.PerTest: - return CreatePluginManager(f); - default: - throw new ArgumentOutOfRangeException(nameof(pluginManager)); - } - }); + case UmbracoTestOptions.TypeLoader.Default: + return _commonTypeLoader ?? (_commonTypeLoader = CreateCommonTypeLoader(runtimeCache, globalSettings, logger)); + case UmbracoTestOptions.TypeLoader.PerFixture: + return _featureTypeLoader ?? (_featureTypeLoader = CreateTypeLoader(runtimeCache, globalSettings, logger)); + case UmbracoTestOptions.TypeLoader.PerTest: + return CreateTypeLoader(runtimeCache, globalSettings, logger); + default: + throw new ArgumentOutOfRangeException(nameof(option)); + } } - protected virtual TypeLoader CreatePluginManager(IContainer f) + protected virtual TypeLoader CreateTypeLoader(IRuntimeCacheProvider runtimeCache, IGlobalSettings globalSettings, IProfilingLogger logger) { - return CreateCommonPluginManager(f); + return CreateCommonTypeLoader(runtimeCache, globalSettings, logger); } - private static TypeLoader CreateCommonPluginManager(IContainer f) + // common to all tests = cannot be overriden + private static TypeLoader CreateCommonTypeLoader(IRuntimeCacheProvider runtimeCache, IGlobalSettings globalSettings, IProfilingLogger logger) { - return new TypeLoader(f.GetInstance().RuntimeCache, f.GetInstance(), f.GetInstance(), false) + return new TypeLoader(runtimeCache, globalSettings, logger, false) { AssembliesToScan = new[] { diff --git a/src/Umbraco.Tests/Testing/UmbracoTestOptions.cs b/src/Umbraco.Tests/Testing/UmbracoTestOptions.cs index 5248026788..da3ffccc55 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestOptions.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestOptions.cs @@ -26,13 +26,13 @@ NewSchemaPerTest } - public enum PluginManager + public enum TypeLoader { - // the default, global plugin manager for tests + // the default, global type loader for tests Default, - // create one plugin manager for the feature + // create one type loader for the feature PerFixture, - // create one plugin manager for each test + // create one type loader for each test PerTest } } diff --git a/src/Umbraco.Tests/Web/Mvc/RenderIndexActionSelectorAttributeTests.cs b/src/Umbraco.Tests/Web/Mvc/RenderIndexActionSelectorAttributeTests.cs index bf29f7e35e..c6609f38c9 100644 --- a/src/Umbraco.Tests/Web/Mvc/RenderIndexActionSelectorAttributeTests.cs +++ b/src/Umbraco.Tests/Web/Mvc/RenderIndexActionSelectorAttributeTests.cs @@ -34,7 +34,7 @@ namespace Umbraco.Tests.Web.Mvc public void SetUp() { Current.UmbracoContextAccessor = new TestUmbracoContextAccessor(); - Core.Composing.Current.Container = Mock.Of(); + Core.Composing.Current.Factory = Mock.Of(); } [TearDown] diff --git a/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs b/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs index fd8ace1904..613ae4f1c2 100644 --- a/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs +++ b/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs @@ -37,11 +37,11 @@ namespace Umbraco.Tests.Web var serviceContext = new ServiceContext(entityService: entityService.Object); // fixme - bad in a unit test - but Udi has a static ctor that wants it?! - var container = new Mock(); + var container = new Mock(); container.Setup(x => x.GetInstance(typeof(TypeLoader))).Returns( new TypeLoader(NullCacheProvider.Instance, SettingsForTests.GenerateMockGlobalSettings(), new ProfilingLogger(Mock.Of(), Mock.Of()))); container.Setup(x => x.GetInstance(typeof (ServiceContext))).Returns(serviceContext); - Current.Container = container.Object; + Current.Factory = container.Object; Umbraco.Web.Composing.Current.UmbracoContextAccessor = new TestUmbracoContextAccessor(); diff --git a/src/Umbraco.Web.UI.Client/package-lock.json b/src/Umbraco.Web.UI.Client/package-lock.json index 3ae35a0de8..1066ee75ad 100644 --- a/src/Umbraco.Web.UI.Client/package-lock.json +++ b/src/Umbraco.Web.UI.Client/package-lock.json @@ -2382,11 +2382,6 @@ "q": "^1.1.2" } }, - "codemirror": { - "version": "5.3.0", - "resolved": "http://registry.npmjs.org/codemirror/-/codemirror-5.3.0.tgz", - "integrity": "sha1-JDyyaN1hynjdsn6C8uws74j7lGE=" - }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", @@ -10296,3088 +10291,6 @@ "sort-keys": "^1.0.0" } }, - "npm": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/npm/-/npm-6.4.1.tgz", - "integrity": "sha512-mXJL1NTVU136PtuopXCUQaNWuHlXCTp4McwlSW8S9/Aj8OEPAlSBgo8og7kJ01MjCDrkmqFQTvN5tTEhBMhXQg==", - "requires": { - "JSONStream": "^1.3.4", - "abbrev": "~1.1.1", - "ansicolors": "~0.3.2", - "ansistyles": "~0.1.3", - "aproba": "~1.2.0", - "archy": "~1.0.0", - "bin-links": "^1.1.2", - "bluebird": "~3.5.1", - "byte-size": "^4.0.3", - "cacache": "^11.2.0", - "call-limit": "~1.1.0", - "chownr": "~1.0.1", - "ci-info": "^1.4.0", - "cli-columns": "^3.1.2", - "cli-table3": "^0.5.0", - "cmd-shim": "~2.0.2", - "columnify": "~1.5.4", - "config-chain": "~1.1.11", - "debuglog": "*", - "detect-indent": "~5.0.0", - "detect-newline": "^2.1.0", - "dezalgo": "~1.0.3", - "editor": "~1.0.0", - "figgy-pudding": "^3.4.1", - "find-npm-prefix": "^1.0.2", - "fs-vacuum": "~1.2.10", - "fs-write-stream-atomic": "~1.0.10", - "gentle-fs": "^2.0.1", - "glob": "~7.1.2", - "graceful-fs": "~4.1.11", - "has-unicode": "~2.0.1", - "hosted-git-info": "^2.7.1", - "iferr": "^1.0.2", - "imurmurhash": "*", - "inflight": "~1.0.6", - "inherits": "~2.0.3", - "ini": "^1.3.5", - "init-package-json": "^1.10.3", - "is-cidr": "^2.0.6", - "json-parse-better-errors": "^1.0.2", - "lazy-property": "~1.0.0", - "libcipm": "^2.0.2", - "libnpmhook": "^4.0.1", - "libnpx": "^10.2.0", - "lock-verify": "^2.0.2", - "lockfile": "^1.0.4", - "lodash._baseindexof": "*", - "lodash._baseuniq": "~4.6.0", - "lodash._bindcallback": "*", - "lodash._cacheindexof": "*", - "lodash._createcache": "*", - "lodash._getnative": "*", - "lodash.clonedeep": "~4.5.0", - "lodash.restparam": "*", - "lodash.union": "~4.6.0", - "lodash.uniq": "~4.5.0", - "lodash.without": "~4.4.0", - "lru-cache": "^4.1.3", - "meant": "~1.0.1", - "mississippi": "^3.0.0", - "mkdirp": "~0.5.1", - "move-concurrently": "^1.0.1", - "node-gyp": "^3.8.0", - "nopt": "~4.0.1", - "normalize-package-data": "~2.4.0", - "npm-audit-report": "^1.3.1", - "npm-cache-filename": "~1.0.2", - "npm-install-checks": "~3.0.0", - "npm-lifecycle": "^2.1.0", - "npm-package-arg": "^6.1.0", - "npm-packlist": "^1.1.11", - "npm-pick-manifest": "^2.1.0", - "npm-profile": "^3.0.2", - "npm-registry-client": "^8.6.0", - "npm-registry-fetch": "^1.1.0", - "npm-user-validate": "~1.0.0", - "npmlog": "~4.1.2", - "once": "~1.4.0", - "opener": "^1.5.0", - "osenv": "^0.1.5", - "pacote": "^8.1.6", - "path-is-inside": "~1.0.2", - "promise-inflight": "~1.0.1", - "qrcode-terminal": "^0.12.0", - "query-string": "^6.1.0", - "qw": "~1.0.1", - "read": "~1.0.7", - "read-cmd-shim": "~1.0.1", - "read-installed": "~4.0.3", - "read-package-json": "^2.0.13", - "read-package-tree": "^5.2.1", - "readable-stream": "^2.3.6", - "readdir-scoped-modules": "*", - "request": "^2.88.0", - "retry": "^0.12.0", - "rimraf": "~2.6.2", - "safe-buffer": "^5.1.2", - "semver": "^5.5.0", - "sha": "~2.0.1", - "slide": "~1.1.6", - "sorted-object": "~2.0.1", - "sorted-union-stream": "~2.1.3", - "ssri": "^6.0.0", - "stringify-package": "^1.0.0", - "tar": "^4.4.6", - "text-table": "~0.2.0", - "tiny-relative-date": "^1.3.0", - "uid-number": "0.0.6", - "umask": "~1.1.0", - "unique-filename": "~1.1.0", - "unpipe": "~1.0.0", - "update-notifier": "^2.5.0", - "uuid": "^3.3.2", - "validate-npm-package-license": "^3.0.4", - "validate-npm-package-name": "~3.0.0", - "which": "^1.3.1", - "worker-farm": "^1.6.0", - "write-file-atomic": "^2.3.0" - }, - "dependencies": { - "JSONStream": { - "version": "1.3.4", - "resolved": false, - "integrity": "sha512-Y7vfi3I5oMOYIr+WxV8NZxDSwcbNgzdKYsTNInmycOq9bUYwGg9ryu57Wg5NLmCjqdFPNUmpMBo3kSJN9tCbXg==", - "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - } - }, - "abbrev": { - "version": "1.1.1", - "resolved": false, - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" - }, - "agent-base": { - "version": "4.2.0", - "resolved": false, - "integrity": "sha512-c+R/U5X+2zz2+UCrCFv6odQzJdoqI+YecuhnAJLa1zYaMc13zPfwMwZrr91Pd1DYNo/yPRbiM4WVf9whgwFsIg==", - "requires": { - "es6-promisify": "^5.0.0" - } - }, - "agentkeepalive": { - "version": "3.4.1", - "resolved": false, - "integrity": "sha512-MPIwsZU9PP9kOrZpyu2042kYA8Fdt/AedQYkYXucHgF9QoD9dXVp0ypuGnHXSR0hTstBxdt85Xkh4JolYfK5wg==", - "requires": { - "humanize-ms": "^1.2.1" - } - }, - "ajv": { - "version": "5.5.2", - "resolved": false, - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" - } - }, - "ansi-align": { - "version": "2.0.0", - "resolved": false, - "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", - "requires": { - "string-width": "^2.0.0" - } - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": false, - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": false, - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "ansicolors": { - "version": "0.3.2", - "resolved": false, - "integrity": "sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=" - }, - "ansistyles": { - "version": "0.1.3", - "resolved": false, - "integrity": "sha1-XeYEFb2gcbs3EnhUyGT0GyMlRTk=" - }, - "aproba": { - "version": "1.2.0", - "resolved": false, - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" - }, - "archy": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=" - }, - "are-we-there-yet": { - "version": "1.1.4", - "resolved": false, - "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "asap": { - "version": "2.0.6", - "resolved": false, - "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" - }, - "asn1": { - "version": "0.2.4", - "resolved": false, - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - }, - "asynckit": { - "version": "0.4.0", - "resolved": false, - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": false, - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" - }, - "aws4": { - "version": "1.8.0", - "resolved": false, - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" - }, - "balanced-match": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" - }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": false, - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "optional": true, - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "bin-links": { - "version": "1.1.2", - "resolved": false, - "integrity": "sha512-8eEHVgYP03nILphilltWjeIjMbKyJo3wvp9K816pHbhP301ismzw15mxAAEVQ/USUwcP++1uNrbERbp8lOA6Fg==", - "requires": { - "bluebird": "^3.5.0", - "cmd-shim": "^2.0.2", - "gentle-fs": "^2.0.0", - "graceful-fs": "^4.1.11", - "write-file-atomic": "^2.3.0" - } - }, - "block-stream": { - "version": "0.0.9", - "resolved": false, - "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", - "requires": { - "inherits": "~2.0.0" - } - }, - "bluebird": { - "version": "3.5.1", - "resolved": false, - "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" - }, - "boxen": { - "version": "1.3.0", - "resolved": false, - "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==", - "requires": { - "ansi-align": "^2.0.0", - "camelcase": "^4.0.0", - "chalk": "^2.0.1", - "cli-boxes": "^1.0.0", - "string-width": "^2.0.0", - "term-size": "^1.2.0", - "widest-line": "^2.0.0" - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": false, - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "buffer-from": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha512-83apNb8KK0Se60UE1+4Ukbe3HbfELJ6UlI4ldtOGs7So4KD26orJM8hIY9lxdzP+UpItH1Yh/Y8GUvNFWFFRxA==" - }, - "builtin-modules": { - "version": "1.1.1", - "resolved": false, - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" - }, - "builtins": { - "version": "1.0.3", - "resolved": false, - "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=" - }, - "byline": { - "version": "5.0.0", - "resolved": false, - "integrity": "sha1-dBxSFkaOrcRXsDQQEYrXfejB3bE=" - }, - "byte-size": { - "version": "4.0.3", - "resolved": false, - "integrity": "sha512-JGC3EV2bCzJH/ENSh3afyJrH4vwxbHTuO5ljLoI5+2iJOcEpMgP8T782jH9b5qGxf2mSUIp1lfGnfKNrRHpvVg==" - }, - "cacache": { - "version": "11.2.0", - "resolved": false, - "integrity": "sha512-IFWl6lfK6wSeYCHUXh+N1lY72UDrpyrYQJNIVQf48paDuWbv5RbAtJYf/4gUQFObTCHZwdZ5sI8Iw7nqwP6nlQ==", - "requires": { - "bluebird": "^3.5.1", - "chownr": "^1.0.1", - "figgy-pudding": "^3.1.0", - "glob": "^7.1.2", - "graceful-fs": "^4.1.11", - "lru-cache": "^4.1.3", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "promise-inflight": "^1.0.1", - "rimraf": "^2.6.2", - "ssri": "^6.0.0", - "unique-filename": "^1.1.0", - "y18n": "^4.0.0" - } - }, - "call-limit": { - "version": "1.1.0", - "resolved": false, - "integrity": "sha1-b9YbA/PaQqLNDsK2DwK9DnGZH+o=" - }, - "camelcase": { - "version": "4.1.0", - "resolved": false, - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" - }, - "capture-stack-trace": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=" - }, - "caseless": { - "version": "0.12.0", - "resolved": false, - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, - "chalk": { - "version": "2.4.1", - "resolved": false, - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "chownr": { - "version": "1.0.1", - "resolved": false, - "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=" - }, - "ci-info": { - "version": "1.4.0", - "resolved": false, - "integrity": "sha512-Oqmw2pVfCl8sCL+1QgMywPfdxPJPkC51y4usw0iiE2S9qnEOAqXy8bwl1CpMpnoU39g4iKJTz6QZj+28FvOnjQ==" - }, - "cidr-regex": { - "version": "2.0.9", - "resolved": false, - "integrity": "sha512-F7/fBRUU45FnvSPjXdpIrc++WRSBdCiSTlyq4ZNhLKOlHFNWgtzZ0Fd+zrqI/J1j0wmlx/f5ZQDmD2GcbrNcmw==", - "requires": { - "ip-regex": "^2.1.0" - } - }, - "cli-boxes": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=" - }, - "cli-columns": { - "version": "3.1.2", - "resolved": false, - "integrity": "sha1-ZzLZcpee/CrkRKHwjgj6E5yWoY4=", - "requires": { - "string-width": "^2.0.0", - "strip-ansi": "^3.0.1" - } - }, - "cli-table3": { - "version": "0.5.0", - "resolved": false, - "integrity": "sha512-c7YHpUyO1SaKaO7kYtxd5NZ8FjAmSK3LpKkuzdwn+2CwpFxBpdoQLm+OAnnCfoEl7onKhN9PKQi1lsHuAIUqGQ==", - "requires": { - "colors": "^1.1.2", - "object-assign": "^4.1.0", - "string-width": "^2.1.1" - } - }, - "cliui": { - "version": "4.1.0", - "resolved": false, - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": false, - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": false, - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "clone": { - "version": "1.0.4", - "resolved": false, - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" - }, - "cmd-shim": { - "version": "2.0.2", - "resolved": false, - "integrity": "sha1-b8vamUg6j9FdfTChlspp1oii79s=", - "requires": { - "graceful-fs": "^4.1.2", - "mkdirp": "~0.5.0" - } - }, - "co": { - "version": "4.6.0", - "resolved": false, - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" - }, - "code-point-at": { - "version": "1.1.0", - "resolved": false, - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" - }, - "color-convert": { - "version": "1.9.1", - "resolved": false, - "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", - "requires": { - "color-name": "^1.1.1" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": false, - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "colors": { - "version": "1.1.2", - "resolved": false, - "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", - "optional": true - }, - "columnify": { - "version": "1.5.4", - "resolved": false, - "integrity": "sha1-Rzfd8ce2mop8NAVweC6UfuyOeLs=", - "requires": { - "strip-ansi": "^3.0.0", - "wcwidth": "^1.0.0" - } - }, - "combined-stream": { - "version": "1.0.6", - "resolved": false, - "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": false, - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "concat-stream": { - "version": "1.6.2", - "resolved": false, - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "config-chain": { - "version": "1.1.11", - "resolved": false, - "integrity": "sha1-q6CXR9++TD5w52am5BWG4YWfxvI=", - "requires": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, - "configstore": { - "version": "3.1.2", - "resolved": false, - "integrity": "sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==", - "requires": { - "dot-prop": "^4.1.0", - "graceful-fs": "^4.1.2", - "make-dir": "^1.0.0", - "unique-string": "^1.0.0", - "write-file-atomic": "^2.0.0", - "xdg-basedir": "^3.0.0" - } - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": false, - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" - }, - "copy-concurrently": { - "version": "1.0.5", - "resolved": false, - "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", - "requires": { - "aproba": "^1.1.1", - "fs-write-stream-atomic": "^1.0.8", - "iferr": "^0.1.5", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.0" - }, - "dependencies": { - "iferr": { - "version": "0.1.5", - "resolved": false, - "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=" - } - } - }, - "core-util-is": { - "version": "1.0.2", - "resolved": false, - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "create-error-class": { - "version": "3.0.2", - "resolved": false, - "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", - "requires": { - "capture-stack-trace": "^1.0.0" - } - }, - "cross-spawn": { - "version": "5.1.0", - "resolved": false, - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "crypto-random-string": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=" - }, - "cyclist": { - "version": "0.2.2", - "resolved": false, - "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=" - }, - "dashdash": { - "version": "1.14.1", - "resolved": false, - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "requires": { - "assert-plus": "^1.0.0" - } - }, - "debug": { - "version": "3.1.0", - "resolved": false, - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "resolved": false, - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } - } - }, - "debuglog": { - "version": "1.0.1", - "resolved": false, - "integrity": "sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=" - }, - "decamelize": { - "version": "1.2.0", - "resolved": false, - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" - }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": false, - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" - }, - "deep-extend": { - "version": "0.5.1", - "resolved": false, - "integrity": "sha512-N8vBdOa+DF7zkRrDCsaOXoCs/E2fJfx9B9MrKnnSiHNh4ws7eSys6YQE4KvT1cecKmOASYQBhbKjeuDD9lT81w==" - }, - "defaults": { - "version": "1.0.3", - "resolved": false, - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "requires": { - "clone": "^1.0.2" - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" - }, - "delegates": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" - }, - "detect-indent": { - "version": "5.0.0", - "resolved": false, - "integrity": "sha1-OHHMCmoALow+Wzz38zYmRnXwa50=" - }, - "detect-newline": { - "version": "2.1.0", - "resolved": false, - "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=" - }, - "dezalgo": { - "version": "1.0.3", - "resolved": false, - "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=", - "requires": { - "asap": "^2.0.0", - "wrappy": "1" - } - }, - "dot-prop": { - "version": "4.2.0", - "resolved": false, - "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", - "requires": { - "is-obj": "^1.0.0" - } - }, - "dotenv": { - "version": "5.0.1", - "resolved": false, - "integrity": "sha512-4As8uPrjfwb7VXC+WnLCbXK7y+Ueb2B3zgNCePYfhxS1PYeaO1YTeplffTEcbfLhvFNGLAz90VvJs9yomG7bow==" - }, - "duplexer3": { - "version": "0.1.4", - "resolved": false, - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" - }, - "duplexify": { - "version": "3.6.0", - "resolved": false, - "integrity": "sha512-fO3Di4tBKJpYTFHAxTU00BcfWMY9w24r/x21a6rZRbsD/ToUgGxsMbiGRmB7uVAXeGKXD9MwiLZa5E97EVgIRQ==", - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": false, - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "optional": true, - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "editor": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-YMf4e9YrzGqJT6jM1q+3gjok90I=" - }, - "encoding": { - "version": "0.1.12", - "resolved": false, - "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", - "requires": { - "iconv-lite": "~0.4.13" - } - }, - "end-of-stream": { - "version": "1.4.1", - "resolved": false, - "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", - "requires": { - "once": "^1.4.0" - } - }, - "err-code": { - "version": "1.1.2", - "resolved": false, - "integrity": "sha1-BuARbTAo9q70gGhJ6w6mp0iuaWA=" - }, - "errno": { - "version": "0.1.7", - "resolved": false, - "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "requires": { - "prr": "~1.0.1" - } - }, - "es6-promise": { - "version": "4.2.4", - "resolved": false, - "integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==" - }, - "es6-promisify": { - "version": "5.0.0", - "resolved": false, - "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", - "requires": { - "es6-promise": "^4.0.3" - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": false, - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" - }, - "execa": { - "version": "0.7.0", - "resolved": false, - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "extend": { - "version": "3.0.2", - "resolved": false, - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "extsprintf": { - "version": "1.3.0", - "resolved": false, - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" - }, - "fast-deep-equal": { - "version": "1.1.0", - "resolved": false, - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" - }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": false, - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" - }, - "figgy-pudding": { - "version": "3.4.1", - "resolved": false, - "integrity": "sha512-j1SAT641cerGuOvoSBoaE9LbSzh1N/E5ufk9oMpOKuyK8MyW3sGg4rh+4qhLmVTEAzipO5XTHYT4gjb6JYLE8g==" - }, - "find-npm-prefix": { - "version": "1.0.2", - "resolved": false, - "integrity": "sha512-KEftzJ+H90x6pcKtdXZEPsQse8/y/UnvzRKrOSQFprnrGaFuJ62fVkP34Iu2IYuMvyauCyoLTNkJZgrrGA2wkA==" - }, - "find-up": { - "version": "2.1.0", - "resolved": false, - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "requires": { - "locate-path": "^2.0.0" - } - }, - "flush-write-stream": { - "version": "1.0.3", - "resolved": false, - "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==", - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.4" - } - }, - "forever-agent": { - "version": "0.6.1", - "resolved": false, - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" - }, - "form-data": { - "version": "2.3.2", - "resolved": false, - "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "1.0.6", - "mime-types": "^2.1.12" - } - }, - "from2": { - "version": "2.3.0", - "resolved": false, - "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" - } - }, - "fs-minipass": { - "version": "1.2.5", - "resolved": false, - "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", - "requires": { - "minipass": "^2.2.1" - } - }, - "fs-vacuum": { - "version": "1.2.10", - "resolved": false, - "integrity": "sha1-t2Kb7AekAxolSP35n17PHMizHjY=", - "requires": { - "graceful-fs": "^4.1.2", - "path-is-inside": "^1.0.1", - "rimraf": "^2.5.2" - } - }, - "fs-write-stream-atomic": { - "version": "1.0.10", - "resolved": false, - "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", - "requires": { - "graceful-fs": "^4.1.2", - "iferr": "^0.1.5", - "imurmurhash": "^0.1.4", - "readable-stream": "1 || 2" - }, - "dependencies": { - "iferr": { - "version": "0.1.5", - "resolved": false, - "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=" - } - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "fstream": { - "version": "1.0.11", - "resolved": false, - "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", - "requires": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - } - }, - "gauge": { - "version": "2.7.4", - "resolved": false, - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - }, - "dependencies": { - "string-width": { - "version": "1.0.2", - "resolved": false, - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - } - } - }, - "genfun": { - "version": "4.0.1", - "resolved": false, - "integrity": "sha1-7RAEHy5KfxsKOEZtF6XD4n3x38E=" - }, - "gentle-fs": { - "version": "2.0.1", - "resolved": false, - "integrity": "sha512-cEng5+3fuARewXktTEGbwsktcldA+YsnUEaXZwcK/3pjSE1X9ObnTs+/8rYf8s+RnIcQm2D5x3rwpN7Zom8Bew==", - "requires": { - "aproba": "^1.1.2", - "fs-vacuum": "^1.2.10", - "graceful-fs": "^4.1.11", - "iferr": "^0.1.5", - "mkdirp": "^0.5.1", - "path-is-inside": "^1.0.2", - "read-cmd-shim": "^1.0.1", - "slide": "^1.1.6" - }, - "dependencies": { - "iferr": { - "version": "0.1.5", - "resolved": false, - "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=" - } - } - }, - "get-caller-file": { - "version": "1.0.2", - "resolved": false, - "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=" - }, - "get-stream": { - "version": "3.0.0", - "resolved": false, - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" - }, - "getpass": { - "version": "0.1.7", - "resolved": false, - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "requires": { - "assert-plus": "^1.0.0" - } - }, - "glob": { - "version": "7.1.2", - "resolved": false, - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "global-dirs": { - "version": "0.1.1", - "resolved": false, - "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", - "requires": { - "ini": "^1.3.4" - } - }, - "got": { - "version": "6.7.1", - "resolved": false, - "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", - "requires": { - "create-error-class": "^3.0.0", - "duplexer3": "^0.1.4", - "get-stream": "^3.0.0", - "is-redirect": "^1.0.0", - "is-retry-allowed": "^1.0.0", - "is-stream": "^1.0.0", - "lowercase-keys": "^1.0.0", - "safe-buffer": "^5.0.1", - "timed-out": "^4.0.0", - "unzip-response": "^2.0.1", - "url-parse-lax": "^1.0.0" - } - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": false, - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" - }, - "har-schema": { - "version": "2.0.0", - "resolved": false, - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" - }, - "har-validator": { - "version": "5.1.0", - "resolved": false, - "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==", - "requires": { - "ajv": "^5.3.0", - "har-schema": "^2.0.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": false, - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "has-unicode": { - "version": "2.0.1", - "resolved": false, - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" - }, - "hosted-git-info": { - "version": "2.7.1", - "resolved": false, - "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==" - }, - "http-cache-semantics": { - "version": "3.8.1", - "resolved": false, - "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==" - }, - "http-proxy-agent": { - "version": "2.1.0", - "resolved": false, - "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", - "requires": { - "agent-base": "4", - "debug": "3.1.0" - } - }, - "http-signature": { - "version": "1.2.0", - "resolved": false, - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "https-proxy-agent": { - "version": "2.2.1", - "resolved": false, - "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", - "requires": { - "agent-base": "^4.1.0", - "debug": "^3.1.0" - } - }, - "humanize-ms": { - "version": "1.2.1", - "resolved": false, - "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", - "requires": { - "ms": "^2.0.0" - } - }, - "iconv-lite": { - "version": "0.4.23", - "resolved": false, - "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "iferr": { - "version": "1.0.2", - "resolved": false, - "integrity": "sha512-9AfeLfji44r5TKInjhz3W9DyZI1zR1JAf2hVBMGhddAKPqBsupb89jGfbCTHIGZd6fGZl9WlHdn4AObygyMKwg==" - }, - "ignore-walk": { - "version": "3.0.1", - "resolved": false, - "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", - "requires": { - "minimatch": "^3.0.4" - } - }, - "import-lazy": { - "version": "2.1.0", - "resolved": false, - "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=" - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": false, - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" - }, - "inflight": { - "version": "1.0.6", - "resolved": false, - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": false, - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "ini": { - "version": "1.3.5", - "resolved": false, - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" - }, - "init-package-json": { - "version": "1.10.3", - "resolved": false, - "integrity": "sha512-zKSiXKhQveNteyhcj1CoOP8tqp1QuxPIPBl8Bid99DGLFqA1p87M6lNgfjJHSBoWJJlidGOv5rWjyYKEB3g2Jw==", - "requires": { - "glob": "^7.1.1", - "npm-package-arg": "^4.0.0 || ^5.0.0 || ^6.0.0", - "promzard": "^0.3.0", - "read": "~1.0.1", - "read-package-json": "1 || 2", - "semver": "2.x || 3.x || 4 || 5", - "validate-npm-package-license": "^3.0.1", - "validate-npm-package-name": "^3.0.0" - } - }, - "invert-kv": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" - }, - "ip": { - "version": "1.1.5", - "resolved": false, - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" - }, - "ip-regex": { - "version": "2.1.0", - "resolved": false, - "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=" - }, - "is-builtin-module": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", - "requires": { - "builtin-modules": "^1.0.0" - } - }, - "is-ci": { - "version": "1.1.0", - "resolved": false, - "integrity": "sha512-c7TnwxLePuqIlxHgr7xtxzycJPegNHFuIrBkwbf8hc58//+Op1CqFkyS+xnIMkwn9UsJIwc174BIjkyBmSpjKg==", - "requires": { - "ci-info": "^1.0.0" - } - }, - "is-cidr": { - "version": "2.0.6", - "resolved": false, - "integrity": "sha512-A578p1dV22TgPXn6NCaDAPj6vJvYsBgAzUrAd28a4oldeXJjWqEUuSZOLIW3im51mazOKsoyVp8NU/OItlWacw==", - "requires": { - "cidr-regex": "^2.0.8" - } - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "is-installed-globally": { - "version": "0.1.0", - "resolved": false, - "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=", - "requires": { - "global-dirs": "^0.1.0", - "is-path-inside": "^1.0.0" - } - }, - "is-npm": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=" - }, - "is-obj": { - "version": "1.0.1", - "resolved": false, - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=" - }, - "is-path-inside": { - "version": "1.0.1", - "resolved": false, - "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", - "requires": { - "path-is-inside": "^1.0.1" - } - }, - "is-redirect": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=" - }, - "is-retry-allowed": { - "version": "1.1.0", - "resolved": false, - "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=" - }, - "is-stream": { - "version": "1.1.0", - "resolved": false, - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, - "isarray": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "isexe": { - "version": "2.0.0", - "resolved": false, - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" - }, - "isstream": { - "version": "0.1.2", - "resolved": false, - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, - "jsbn": { - "version": "0.1.1", - "resolved": false, - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "optional": true - }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": false, - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" - }, - "json-schema": { - "version": "0.2.3", - "resolved": false, - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" - }, - "json-schema-traverse": { - "version": "0.3.1", - "resolved": false, - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": false, - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, - "jsonparse": { - "version": "1.3.1", - "resolved": false, - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=" - }, - "jsprim": { - "version": "1.4.1", - "resolved": false, - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "latest-version": { - "version": "3.1.0", - "resolved": false, - "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=", - "requires": { - "package-json": "^4.0.0" - } - }, - "lazy-property": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-hN3Es3Bnm6i9TNz6TAa0PVcREUc=" - }, - "lcid": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "requires": { - "invert-kv": "^1.0.0" - } - }, - "libcipm": { - "version": "2.0.2", - "resolved": false, - "integrity": "sha512-9uZ6/LAflVEijksTRq/RX0e+pGA4mr8tND9Cmk2JMg7j2fFUBrs8PpFX2DOAJR/XoxPzz+5h8bkWmtIYLunKAg==", - "requires": { - "bin-links": "^1.1.2", - "bluebird": "^3.5.1", - "find-npm-prefix": "^1.0.2", - "graceful-fs": "^4.1.11", - "lock-verify": "^2.0.2", - "mkdirp": "^0.5.1", - "npm-lifecycle": "^2.0.3", - "npm-logical-tree": "^1.2.1", - "npm-package-arg": "^6.1.0", - "pacote": "^8.1.6", - "protoduck": "^5.0.0", - "read-package-json": "^2.0.13", - "rimraf": "^2.6.2", - "worker-farm": "^1.6.0" - } - }, - "libnpmhook": { - "version": "4.0.1", - "resolved": false, - "integrity": "sha512-3qqpfqvBD1712WA6iGe0stkG40WwAeoWcujA6BlC0Be1JArQbqwabnEnZ0CRcD05Tf1fPYJYdCbSfcfedEJCOg==", - "requires": { - "figgy-pudding": "^3.1.0", - "npm-registry-fetch": "^3.0.0" - }, - "dependencies": { - "npm-registry-fetch": { - "version": "3.1.1", - "resolved": false, - "integrity": "sha512-xBobENeenvjIG8PgQ1dy77AXTI25IbYhmA3DusMIfw/4EL5BaQ5e1V9trkPrqHvyjR3/T0cnH6o0Wt/IzcI5Ag==", - "requires": { - "bluebird": "^3.5.1", - "figgy-pudding": "^3.1.0", - "lru-cache": "^4.1.2", - "make-fetch-happen": "^4.0.0", - "npm-package-arg": "^6.0.0" - } - } - } - }, - "libnpx": { - "version": "10.2.0", - "resolved": false, - "integrity": "sha512-X28coei8/XRCt15cYStbLBph+KGhFra4VQhRBPuH/HHMkC5dxM8v24RVgUsvODKCrUZ0eTgiTqJp6zbl0sskQQ==", - "requires": { - "dotenv": "^5.0.1", - "npm-package-arg": "^6.0.0", - "rimraf": "^2.6.2", - "safe-buffer": "^5.1.0", - "update-notifier": "^2.3.0", - "which": "^1.3.0", - "y18n": "^4.0.0", - "yargs": "^11.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": false, - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "lock-verify": { - "version": "2.0.2", - "resolved": false, - "integrity": "sha512-QNVwK0EGZBS4R3YQ7F1Ox8p41Po9VGl2QG/2GsuvTbkJZYSsPeWHKMbbH6iZMCHWSMww5nrJroZYnGzI4cePuw==", - "requires": { - "npm-package-arg": "^5.1.2 || 6", - "semver": "^5.4.1" - } - }, - "lockfile": { - "version": "1.0.4", - "resolved": false, - "integrity": "sha512-cvbTwETRfsFh4nHsL1eGWapU1XFi5Ot9E85sWAwia7Y7EgB7vfqcZhTKZ+l7hCGxSPoushMv5GKhT5PdLv03WA==", - "requires": { - "signal-exit": "^3.0.2" - } - }, - "lodash._baseindexof": { - "version": "3.1.0", - "resolved": false, - "integrity": "sha1-/lK1OhxnYeQmGNZU5KJXie1hgiw=" - }, - "lodash._baseuniq": { - "version": "4.6.0", - "resolved": false, - "integrity": "sha1-DrtE5FaBSveQXGIS+iybLVG4Qeg=", - "requires": { - "lodash._createset": "~4.0.0", - "lodash._root": "~3.0.0" - } - }, - "lodash._bindcallback": { - "version": "3.0.1", - "resolved": false, - "integrity": "sha1-5THCdkTPi1epnhftlbNcdIeJOS4=" - }, - "lodash._cacheindexof": { - "version": "3.0.2", - "resolved": false, - "integrity": "sha1-PcaayCSY0u5ePOVgkbr9Ktx73pI=" - }, - "lodash._createcache": { - "version": "3.1.2", - "resolved": false, - "integrity": "sha1-VtagZAF2JeeevKa4AY4XRAvc8JM=", - "requires": { - "lodash._getnative": "^3.0.0" - } - }, - "lodash._createset": { - "version": "4.0.3", - "resolved": false, - "integrity": "sha1-D0ZZ+7CddRlPqeK4imZE02PJ/iY=" - }, - "lodash._getnative": { - "version": "3.9.1", - "resolved": false, - "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=" - }, - "lodash._root": { - "version": "3.0.1", - "resolved": false, - "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=" - }, - "lodash.clonedeep": { - "version": "4.5.0", - "resolved": false, - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" - }, - "lodash.restparam": { - "version": "3.6.1", - "resolved": false, - "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=" - }, - "lodash.union": { - "version": "4.6.0", - "resolved": false, - "integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=" - }, - "lodash.uniq": { - "version": "4.5.0", - "resolved": false, - "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=" - }, - "lodash.without": { - "version": "4.4.0", - "resolved": false, - "integrity": "sha1-PNRXSgC2e643OpS3SHcmQFB7eqw=" - }, - "lowercase-keys": { - "version": "1.0.1", - "resolved": false, - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" - }, - "lru-cache": { - "version": "4.1.3", - "resolved": false, - "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "make-dir": { - "version": "1.3.0", - "resolved": false, - "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", - "requires": { - "pify": "^3.0.0" - } - }, - "make-fetch-happen": { - "version": "4.0.1", - "resolved": false, - "integrity": "sha512-7R5ivfy9ilRJ1EMKIOziwrns9fGeAD4bAha8EB7BIiBBLHm2KeTUGCrICFt2rbHfzheTLynv50GnNTK1zDTrcQ==", - "requires": { - "agentkeepalive": "^3.4.1", - "cacache": "^11.0.1", - "http-cache-semantics": "^3.8.1", - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.1", - "lru-cache": "^4.1.2", - "mississippi": "^3.0.0", - "node-fetch-npm": "^2.0.2", - "promise-retry": "^1.1.1", - "socks-proxy-agent": "^4.0.0", - "ssri": "^6.0.0" - } - }, - "meant": { - "version": "1.0.1", - "resolved": false, - "integrity": "sha512-UakVLFjKkbbUwNWJ2frVLnnAtbb7D7DsloxRd3s/gDpI8rdv8W5Hp3NaDb+POBI1fQdeussER6NB8vpcRURvlg==" - }, - "mem": { - "version": "1.1.0", - "resolved": false, - "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", - "requires": { - "mimic-fn": "^1.0.0" - } - }, - "mime-db": { - "version": "1.35.0", - "resolved": false, - "integrity": "sha512-JWT/IcCTsB0Io3AhWUMjRqucrHSPsSf2xKLaRldJVULioggvkJvggZ3VXNNSRkCddE6D+BUI4HEIZIA2OjwIvg==" - }, - "mime-types": { - "version": "2.1.19", - "resolved": false, - "integrity": "sha512-P1tKYHVSZ6uFo26mtnve4HQFE3koh1UWVkp8YUC+ESBHe945xWSoXuHHiGarDqcEZ+whpCDnlNw5LON0kLo+sw==", - "requires": { - "mime-db": "~1.35.0" - } - }, - "mimic-fn": { - "version": "1.2.0", - "resolved": false, - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" - }, - "minimatch": { - "version": "3.0.4", - "resolved": false, - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "resolved": false, - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" - }, - "minipass": { - "version": "2.3.3", - "resolved": false, - "integrity": "sha512-/jAn9/tEX4gnpyRATxgHEOV6xbcyxgT7iUnxo9Y3+OB0zX00TgKIv/2FZCf5brBbICcwbLqVv2ImjvWWrQMSYw==", - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - }, - "dependencies": { - "yallist": { - "version": "3.0.2", - "resolved": false, - "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=" - } - } - }, - "minizlib": { - "version": "1.1.0", - "resolved": false, - "integrity": "sha512-4T6Ur/GctZ27nHfpt9THOdRZNgyJ9FZchYO1ceg5S8Q3DNLCKYy44nCZzgCJgcvx2UM8czmqak5BCxJMrq37lA==", - "requires": { - "minipass": "^2.2.1" - } - }, - "mississippi": { - "version": "3.0.0", - "resolved": false, - "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", - "requires": { - "concat-stream": "^1.5.0", - "duplexify": "^3.4.2", - "end-of-stream": "^1.1.0", - "flush-write-stream": "^1.0.0", - "from2": "^2.1.0", - "parallel-transform": "^1.1.0", - "pump": "^3.0.0", - "pumpify": "^1.3.3", - "stream-each": "^1.1.0", - "through2": "^2.0.0" - } - }, - "mkdirp": { - "version": "0.5.1", - "resolved": false, - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "requires": { - "minimist": "0.0.8" - } - }, - "move-concurrently": { - "version": "1.0.1", - "resolved": false, - "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", - "requires": { - "aproba": "^1.1.1", - "copy-concurrently": "^1.0.0", - "fs-write-stream-atomic": "^1.0.8", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.3" - } - }, - "ms": { - "version": "2.1.1", - "resolved": false, - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" - }, - "mute-stream": { - "version": "0.0.7", - "resolved": false, - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" - }, - "node-fetch-npm": { - "version": "2.0.2", - "resolved": false, - "integrity": "sha512-nJIxm1QmAj4v3nfCvEeCrYSoVwXyxLnaPBK5W1W5DGEJwjlKuC2VEUycGw5oxk+4zZahRrB84PUJJgEmhFTDFw==", - "requires": { - "encoding": "^0.1.11", - "json-parse-better-errors": "^1.0.0", - "safe-buffer": "^5.1.1" - } - }, - "node-gyp": { - "version": "3.8.0", - "resolved": false, - "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==", - "requires": { - "fstream": "^1.0.0", - "glob": "^7.0.3", - "graceful-fs": "^4.1.2", - "mkdirp": "^0.5.0", - "nopt": "2 || 3", - "npmlog": "0 || 1 || 2 || 3 || 4", - "osenv": "0", - "request": "^2.87.0", - "rimraf": "2", - "semver": "~5.3.0", - "tar": "^2.0.0", - "which": "1" - }, - "dependencies": { - "nopt": { - "version": "3.0.6", - "resolved": false, - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "requires": { - "abbrev": "1" - } - }, - "semver": { - "version": "5.3.0", - "resolved": false, - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" - }, - "tar": { - "version": "2.2.1", - "resolved": false, - "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", - "requires": { - "block-stream": "*", - "fstream": "^1.0.2", - "inherits": "2" - } - } - } - }, - "nopt": { - "version": "4.0.1", - "resolved": false, - "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "normalize-package-data": { - "version": "2.4.0", - "resolved": false, - "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", - "requires": { - "hosted-git-info": "^2.1.4", - "is-builtin-module": "^1.0.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "npm-audit-report": { - "version": "1.3.1", - "resolved": false, - "integrity": "sha512-SjTF8ZP4rOu3JiFrTMi4M1CmVo2tni2sP4TzhyCMHwnMGf6XkdGLZKt9cdZ12esKf0mbQqFyU9LtY0SoeahL7g==", - "requires": { - "cli-table3": "^0.5.0", - "console-control-strings": "^1.1.0" - } - }, - "npm-bundled": { - "version": "1.0.5", - "resolved": false, - "integrity": "sha512-m/e6jgWu8/v5niCUKQi9qQl8QdeEduFA96xHDDzFGqly0OOjI7c+60KM/2sppfnUU9JJagf+zs+yGhqSOFj71g==" - }, - "npm-cache-filename": { - "version": "1.0.2", - "resolved": false, - "integrity": "sha1-3tMGxbC/yHCp6fr4I7xfKD4FrhE=" - }, - "npm-install-checks": { - "version": "3.0.0", - "resolved": false, - "integrity": "sha1-1K7N/VGlPjcjt7L5Oy7ijjB7wNc=", - "requires": { - "semver": "^2.3.0 || 3.x || 4 || 5" - } - }, - "npm-lifecycle": { - "version": "2.1.0", - "resolved": false, - "integrity": "sha512-QbBfLlGBKsktwBZLj6AviHC6Q9Y3R/AY4a2PYSIRhSKSS0/CxRyD/PfxEX6tPeOCXQgMSNdwGeECacstgptc+g==", - "requires": { - "byline": "^5.0.0", - "graceful-fs": "^4.1.11", - "node-gyp": "^3.8.0", - "resolve-from": "^4.0.0", - "slide": "^1.1.6", - "uid-number": "0.0.6", - "umask": "^1.1.0", - "which": "^1.3.1" - } - }, - "npm-logical-tree": { - "version": "1.2.1", - "resolved": false, - "integrity": "sha512-AJI/qxDB2PWI4LG1CYN579AY1vCiNyWfkiquCsJWqntRu/WwimVrC8yXeILBFHDwxfOejxewlmnvW9XXjMlYIg==" - }, - "npm-package-arg": { - "version": "6.1.0", - "resolved": false, - "integrity": "sha512-zYbhP2k9DbJhA0Z3HKUePUgdB1x7MfIfKssC+WLPFMKTBZKpZh5m13PgexJjCq6KW7j17r0jHWcCpxEqnnncSA==", - "requires": { - "hosted-git-info": "^2.6.0", - "osenv": "^0.1.5", - "semver": "^5.5.0", - "validate-npm-package-name": "^3.0.0" - } - }, - "npm-packlist": { - "version": "1.1.11", - "resolved": false, - "integrity": "sha512-CxKlZ24urLkJk+9kCm48RTQ7L4hsmgSVzEk0TLGPzzyuFxD7VNgy5Sl24tOLMzQv773a/NeJ1ce1DKeacqffEA==", - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } - }, - "npm-pick-manifest": { - "version": "2.1.0", - "resolved": false, - "integrity": "sha512-q9zLP8cTr8xKPmMZN3naxp1k/NxVFsjxN6uWuO1tiw9gxg7wZWQ/b5UTfzD0ANw2q1lQxdLKTeCCksq+bPSgbQ==", - "requires": { - "npm-package-arg": "^6.0.0", - "semver": "^5.4.1" - } - }, - "npm-profile": { - "version": "3.0.2", - "resolved": false, - "integrity": "sha512-rEJOFR6PbwOvvhGa2YTNOJQKNuc6RovJ6T50xPU7pS9h/zKPNCJ+VHZY2OFXyZvEi+UQYtHRTp8O/YM3tUD20A==", - "requires": { - "aproba": "^1.1.2 || 2", - "make-fetch-happen": "^2.5.0 || 3 || 4" - } - }, - "npm-registry-client": { - "version": "8.6.0", - "resolved": false, - "integrity": "sha512-Qs6P6nnopig+Y8gbzpeN/dkt+n7IyVd8f45NTMotGk6Qo7GfBmzwYx6jRLoOOgKiMnaQfYxsuyQlD8Mc3guBhg==", - "requires": { - "concat-stream": "^1.5.2", - "graceful-fs": "^4.1.6", - "normalize-package-data": "~1.0.1 || ^2.0.0", - "npm-package-arg": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0", - "npmlog": "2 || ^3.1.0 || ^4.0.0", - "once": "^1.3.3", - "request": "^2.74.0", - "retry": "^0.10.0", - "safe-buffer": "^5.1.1", - "semver": "2 >=2.2.1 || 3.x || 4 || 5", - "slide": "^1.1.3", - "ssri": "^5.2.4" - }, - "dependencies": { - "retry": { - "version": "0.10.1", - "resolved": false, - "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=" - }, - "ssri": { - "version": "5.3.0", - "resolved": false, - "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==", - "requires": { - "safe-buffer": "^5.1.1" - } - } - } - }, - "npm-registry-fetch": { - "version": "1.1.0", - "resolved": false, - "integrity": "sha512-XJPIBfMtgaooRtZmuA42xCeLf3tkxdIX0xqRsGWwNrcVvJ9UYFccD7Ho7QWCzvkM3i/QrkUC37Hu0a+vDBmt5g==", - "requires": { - "bluebird": "^3.5.1", - "figgy-pudding": "^2.0.1", - "lru-cache": "^4.1.2", - "make-fetch-happen": "^3.0.0", - "npm-package-arg": "^6.0.0", - "safe-buffer": "^5.1.1" - }, - "dependencies": { - "cacache": { - "version": "10.0.4", - "resolved": false, - "integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==", - "requires": { - "bluebird": "^3.5.1", - "chownr": "^1.0.1", - "glob": "^7.1.2", - "graceful-fs": "^4.1.11", - "lru-cache": "^4.1.1", - "mississippi": "^2.0.0", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "promise-inflight": "^1.0.1", - "rimraf": "^2.6.2", - "ssri": "^5.2.4", - "unique-filename": "^1.1.0", - "y18n": "^4.0.0" - }, - "dependencies": { - "mississippi": { - "version": "2.0.0", - "resolved": false, - "integrity": "sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw==", - "requires": { - "concat-stream": "^1.5.0", - "duplexify": "^3.4.2", - "end-of-stream": "^1.1.0", - "flush-write-stream": "^1.0.0", - "from2": "^2.1.0", - "parallel-transform": "^1.1.0", - "pump": "^2.0.1", - "pumpify": "^1.3.3", - "stream-each": "^1.1.0", - "through2": "^2.0.0" - } - } - } - }, - "figgy-pudding": { - "version": "2.0.1", - "resolved": false, - "integrity": "sha512-yIJPhIBi/oFdU/P+GSXjmk/rmGjuZkm7A5LTXZxNrEprXJXRK012FiI1BR1Pga+0d/d6taWWD+B5d2ozqaxHig==" - }, - "make-fetch-happen": { - "version": "3.0.0", - "resolved": false, - "integrity": "sha512-FmWY7gC0mL6Z4N86vE14+m719JKE4H0A+pyiOH18B025gF/C113pyfb4gHDDYP5cqnRMHOz06JGdmffC/SES+w==", - "requires": { - "agentkeepalive": "^3.4.1", - "cacache": "^10.0.4", - "http-cache-semantics": "^3.8.1", - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.0", - "lru-cache": "^4.1.2", - "mississippi": "^3.0.0", - "node-fetch-npm": "^2.0.2", - "promise-retry": "^1.1.1", - "socks-proxy-agent": "^3.0.1", - "ssri": "^5.2.4" - } - }, - "pump": { - "version": "2.0.1", - "resolved": false, - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "smart-buffer": { - "version": "1.1.15", - "resolved": false, - "integrity": "sha1-fxFLW2X6s+KjWqd1uxLw0cZJvxY=" - }, - "socks": { - "version": "1.1.10", - "resolved": false, - "integrity": "sha1-W4t/x8jzQcU+0FbpKbe/Tei6e1o=", - "requires": { - "ip": "^1.1.4", - "smart-buffer": "^1.0.13" - } - }, - "socks-proxy-agent": { - "version": "3.0.1", - "resolved": false, - "integrity": "sha512-ZwEDymm204mTzvdqyUqOdovVr2YRd2NYskrYrF2LXyZ9qDiMAoFESGK8CRphiO7rtbo2Y757k2Nia3x2hGtalA==", - "requires": { - "agent-base": "^4.1.0", - "socks": "^1.1.10" - } - }, - "ssri": { - "version": "5.3.0", - "resolved": false, - "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==", - "requires": { - "safe-buffer": "^5.1.1" - } - } - } - }, - "npm-run-path": { - "version": "2.0.2", - "resolved": false, - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "requires": { - "path-key": "^2.0.0" - } - }, - "npm-user-validate": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-jOyg9c6gTU6TUZ73LQVXp1Ei6VE=" - }, - "npmlog": { - "version": "4.1.2", - "resolved": false, - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": false, - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" - }, - "oauth-sign": { - "version": "0.9.0", - "resolved": false, - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" - }, - "object-assign": { - "version": "4.1.1", - "resolved": false, - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "once": { - "version": "1.4.0", - "resolved": false, - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1" - } - }, - "opener": { - "version": "1.5.0", - "resolved": false, - "integrity": "sha512-MD4s/o61y2slS27zm2s4229V2gAUHX0/e3/XOmY/jsXwhysjjCIHN8lx7gqZCrZk19ym+HjCUWHeMKD7YJtKCQ==" - }, - "os-homedir": { - "version": "1.0.2", - "resolved": false, - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" - }, - "os-locale": { - "version": "2.1.0", - "resolved": false, - "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", - "requires": { - "execa": "^0.7.0", - "lcid": "^1.0.0", - "mem": "^1.1.0" - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": false, - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" - }, - "osenv": { - "version": "0.1.5", - "resolved": false, - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "p-finally": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" - }, - "p-limit": { - "version": "1.2.0", - "resolved": false, - "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": false, - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" - }, - "package-json": { - "version": "4.0.1", - "resolved": false, - "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=", - "requires": { - "got": "^6.7.1", - "registry-auth-token": "^3.0.1", - "registry-url": "^3.0.3", - "semver": "^5.1.0" - } - }, - "pacote": { - "version": "8.1.6", - "resolved": false, - "integrity": "sha512-wTOOfpaAQNEQNtPEx92x9Y9kRWVu45v583XT8x2oEV2xRB74+xdqMZIeGW4uFvAyZdmSBtye+wKdyyLaT8pcmw==", - "requires": { - "bluebird": "^3.5.1", - "cacache": "^11.0.2", - "get-stream": "^3.0.0", - "glob": "^7.1.2", - "lru-cache": "^4.1.3", - "make-fetch-happen": "^4.0.1", - "minimatch": "^3.0.4", - "minipass": "^2.3.3", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", - "normalize-package-data": "^2.4.0", - "npm-package-arg": "^6.1.0", - "npm-packlist": "^1.1.10", - "npm-pick-manifest": "^2.1.0", - "osenv": "^0.1.5", - "promise-inflight": "^1.0.1", - "promise-retry": "^1.1.1", - "protoduck": "^5.0.0", - "rimraf": "^2.6.2", - "safe-buffer": "^5.1.2", - "semver": "^5.5.0", - "ssri": "^6.0.0", - "tar": "^4.4.3", - "unique-filename": "^1.1.0", - "which": "^1.3.0" - } - }, - "parallel-transform": { - "version": "1.1.0", - "resolved": false, - "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", - "requires": { - "cyclist": "~0.2.2", - "inherits": "^2.0.3", - "readable-stream": "^2.1.5" - } - }, - "path-exists": { - "version": "3.0.0", - "resolved": false, - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": false, - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": false, - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" - }, - "path-key": { - "version": "2.0.1", - "resolved": false, - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" - }, - "performance-now": { - "version": "2.1.0", - "resolved": false, - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, - "pify": { - "version": "3.0.0", - "resolved": false, - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" - }, - "prepend-http": { - "version": "1.0.4", - "resolved": false, - "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" - }, - "process-nextick-args": { - "version": "2.0.0", - "resolved": false, - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" - }, - "promise-inflight": { - "version": "1.0.1", - "resolved": false, - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=" - }, - "promise-retry": { - "version": "1.1.1", - "resolved": false, - "integrity": "sha1-ZznpaOMFHaIM5kl/srUPaRHfPW0=", - "requires": { - "err-code": "^1.0.0", - "retry": "^0.10.0" - }, - "dependencies": { - "retry": { - "version": "0.10.1", - "resolved": false, - "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=" - } - } - }, - "promzard": { - "version": "0.3.0", - "resolved": false, - "integrity": "sha1-JqXW7ox97kyxIggwWs+5O6OCqe4=", - "requires": { - "read": "1" - } - }, - "proto-list": { - "version": "1.2.4", - "resolved": false, - "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=" - }, - "protoduck": { - "version": "5.0.0", - "resolved": false, - "integrity": "sha512-agsGWD8/RZrS4ga6v82Fxb0RHIS2RZnbsSue6A9/MBRhB/jcqOANAMNrqM9900b8duj+Gx+T/JMy5IowDoO/hQ==", - "requires": { - "genfun": "^4.0.1" - } - }, - "prr": { - "version": "1.0.1", - "resolved": false, - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" - }, - "pseudomap": { - "version": "1.0.2", - "resolved": false, - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" - }, - "psl": { - "version": "1.1.29", - "resolved": false, - "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==" - }, - "pump": { - "version": "3.0.0", - "resolved": false, - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "pumpify": { - "version": "1.5.1", - "resolved": false, - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "requires": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - }, - "dependencies": { - "pump": { - "version": "2.0.1", - "resolved": false, - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - } - } - }, - "punycode": { - "version": "1.4.1", - "resolved": false, - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" - }, - "qrcode-terminal": { - "version": "0.12.0", - "resolved": false, - "integrity": "sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ==" - }, - "qs": { - "version": "6.5.2", - "resolved": false, - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" - }, - "query-string": { - "version": "6.1.0", - "resolved": false, - "integrity": "sha512-pNB/Gr8SA8ff8KpUFM36o/WFAlthgaThka5bV19AD9PNTH20Pwq5Zxodif2YyHwrctp6SkL4GqlOot0qR/wGaw==", - "requires": { - "decode-uri-component": "^0.2.0", - "strict-uri-encode": "^2.0.0" - } - }, - "qw": { - "version": "1.0.1", - "resolved": false, - "integrity": "sha1-77/cdA+a0FQwRCassYNBLMi5ltQ=" - }, - "rc": { - "version": "1.2.7", - "resolved": false, - "integrity": "sha512-LdLD8xD4zzLsAT5xyushXDNscEjB7+2ulnl8+r1pnESlYtlJtVSoCMBGr30eDRJ3+2Gq89jK9P9e4tCEH1+ywA==", - "requires": { - "deep-extend": "^0.5.1", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": false, - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" - } - } - }, - "read": { - "version": "1.0.7", - "resolved": false, - "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", - "requires": { - "mute-stream": "~0.0.4" - } - }, - "read-cmd-shim": { - "version": "1.0.1", - "resolved": false, - "integrity": "sha1-LV0Vd4ajfAVdIgd8MsU/gynpHHs=", - "requires": { - "graceful-fs": "^4.1.2" - } - }, - "read-installed": { - "version": "4.0.3", - "resolved": false, - "integrity": "sha1-/5uLZ/GH0eTCm5/rMfayI6zRkGc=", - "requires": { - "debuglog": "^1.0.1", - "graceful-fs": "^4.1.2", - "read-package-json": "^2.0.0", - "readdir-scoped-modules": "^1.0.0", - "semver": "2 || 3 || 4 || 5", - "slide": "~1.1.3", - "util-extend": "^1.0.1" - } - }, - "read-package-json": { - "version": "2.0.13", - "resolved": false, - "integrity": "sha512-/1dZ7TRZvGrYqE0UAfN6qQb5GYBsNcqS1C0tNK601CFOJmtHI7NIGXwetEPU/OtoFHZL3hDxm4rolFFVE9Bnmg==", - "requires": { - "glob": "^7.1.1", - "graceful-fs": "^4.1.2", - "json-parse-better-errors": "^1.0.1", - "normalize-package-data": "^2.0.0", - "slash": "^1.0.0" - } - }, - "read-package-tree": { - "version": "5.2.1", - "resolved": false, - "integrity": "sha512-2CNoRoh95LxY47LvqrehIAfUVda2JbuFE/HaGYs42bNrGG+ojbw1h3zOcPcQ+1GQ3+rkzNndZn85u1XyZ3UsIA==", - "requires": { - "debuglog": "^1.0.1", - "dezalgo": "^1.0.0", - "once": "^1.3.0", - "read-package-json": "^2.0.0", - "readdir-scoped-modules": "^1.0.0" - } - }, - "readable-stream": { - "version": "2.3.6", - "resolved": false, - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "readdir-scoped-modules": { - "version": "1.0.2", - "resolved": false, - "integrity": "sha1-n6+jfShr5dksuuve4DDcm19AZ0c=", - "requires": { - "debuglog": "^1.0.1", - "dezalgo": "^1.0.0", - "graceful-fs": "^4.1.2", - "once": "^1.3.0" - } - }, - "registry-auth-token": { - "version": "3.3.2", - "resolved": false, - "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==", - "requires": { - "rc": "^1.1.6", - "safe-buffer": "^5.0.1" - } - }, - "registry-url": { - "version": "3.1.0", - "resolved": false, - "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", - "requires": { - "rc": "^1.0.1" - } - }, - "request": { - "version": "2.88.0", - "resolved": false, - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.0", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": false, - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": false, - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" - }, - "resolve-from": { - "version": "4.0.0", - "resolved": false, - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" - }, - "retry": { - "version": "0.12.0", - "resolved": false, - "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=" - }, - "rimraf": { - "version": "2.6.2", - "resolved": false, - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "requires": { - "glob": "^7.0.5" - } - }, - "run-queue": { - "version": "1.0.3", - "resolved": false, - "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", - "requires": { - "aproba": "^1.1.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": false, - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": false, - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "semver": { - "version": "5.5.0", - "resolved": false, - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" - }, - "semver-diff": { - "version": "2.1.0", - "resolved": false, - "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", - "requires": { - "semver": "^5.0.3" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": false, - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" - }, - "sha": { - "version": "2.0.1", - "resolved": false, - "integrity": "sha1-YDCCL70smCOUn49y7WQR7lzyWq4=", - "requires": { - "graceful-fs": "^4.1.2", - "readable-stream": "^2.0.2" - } - }, - "shebang-command": { - "version": "1.2.0", - "resolved": false, - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" - }, - "signal-exit": { - "version": "3.0.2", - "resolved": false, - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" - }, - "slash": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" - }, - "slide": { - "version": "1.1.6", - "resolved": false, - "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=" - }, - "smart-buffer": { - "version": "4.0.1", - "resolved": false, - "integrity": "sha512-RFqinRVJVcCAL9Uh1oVqE6FZkqsyLiVOYEZ20TqIOjuX7iFVJ+zsbs4RIghnw/pTs7mZvt8ZHhvm1ZUrR4fykg==" - }, - "socks": { - "version": "2.2.0", - "resolved": false, - "integrity": "sha512-uRKV9uXQ9ytMbGm2+DilS1jB7N3AC0mmusmW5TVWjNuBZjxS8+lX38fasKVY9I4opv/bY/iqTbcpFFaTwpfwRg==", - "requires": { - "ip": "^1.1.5", - "smart-buffer": "^4.0.1" - } - }, - "socks-proxy-agent": { - "version": "4.0.1", - "resolved": false, - "integrity": "sha512-Kezx6/VBguXOsEe5oU3lXYyKMi4+gva72TwJ7pQY5JfqUx2nMk7NXA6z/mpNqIlfQjWYVfeuNvQjexiTaTn6Nw==", - "requires": { - "agent-base": "~4.2.0", - "socks": "~2.2.0" - } - }, - "sorted-object": { - "version": "2.0.1", - "resolved": false, - "integrity": "sha1-fWMfS9OnmKJK8d/8+/6DM3pd9fw=" - }, - "sorted-union-stream": { - "version": "2.1.3", - "resolved": false, - "integrity": "sha1-x3lMfgd4gAUv9xqNSi27Sppjisc=", - "requires": { - "from2": "^1.3.0", - "stream-iterate": "^1.1.0" - }, - "dependencies": { - "from2": { - "version": "1.3.0", - "resolved": false, - "integrity": "sha1-iEE7qqX5pZfP3pIh2GmGzTwGHf0=", - "requires": { - "inherits": "~2.0.1", - "readable-stream": "~1.1.10" - } - }, - "isarray": { - "version": "0.0.1", - "resolved": false, - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "readable-stream": { - "version": "1.1.14", - "resolved": false, - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": false, - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - } - } - }, - "spdx-correct": { - "version": "3.0.0", - "resolved": false, - "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.1.0", - "resolved": false, - "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==" - }, - "spdx-expression-parse": { - "version": "3.0.0", - "resolved": false, - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.0", - "resolved": false, - "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==" - }, - "sshpk": { - "version": "1.14.2", - "resolved": false, - "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, - "ssri": { - "version": "6.0.0", - "resolved": false, - "integrity": "sha512-zYOGfVHPhxyzwi8MdtdNyxv3IynWCIM4jYReR48lqu0VngxgH1c+C6CmipRdJ55eVByTJV/gboFEEI7TEQI8DA==" - }, - "stream-each": { - "version": "1.2.2", - "resolved": false, - "integrity": "sha512-mc1dbFhGBxvTM3bIWmAAINbqiuAk9TATcfIQC8P+/+HJefgaiTlMn2dHvkX8qlI12KeYKSQ1Ua9RrIqrn1VPoA==", - "requires": { - "end-of-stream": "^1.1.0", - "stream-shift": "^1.0.0" - } - }, - "stream-iterate": { - "version": "1.2.0", - "resolved": false, - "integrity": "sha1-K9fHcpbBcCpGSIuK1B95hl7s1OE=", - "requires": { - "readable-stream": "^2.1.5", - "stream-shift": "^1.0.0" - } - }, - "stream-shift": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=" - }, - "strict-uri-encode": { - "version": "2.0.0", - "resolved": false, - "integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY=" - }, - "string-width": { - "version": "2.1.1", - "resolved": false, - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": false, - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": false, - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": false, - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": false, - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "stringify-package": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha512-JIQqiWmLiEozOC0b0BtxZ/AOUtdUZHCBPgqIZ2kSJJqGwgb9neo44XdTHUC4HZSGqi03hOeB7W/E8rAlKnGe9g==" - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": false, - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-eof": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": false, - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" - }, - "supports-color": { - "version": "5.4.0", - "resolved": false, - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "requires": { - "has-flag": "^3.0.0" - } - }, - "tar": { - "version": "4.4.6", - "resolved": false, - "integrity": "sha512-tMkTnh9EdzxyfW+6GK6fCahagXsnYk6kE6S9Gr9pjVdys769+laCTbodXDhPAjzVtEBazRgP0gYqOjnk9dQzLg==", - "requires": { - "chownr": "^1.0.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.3.3", - "minizlib": "^1.1.0", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.2" - }, - "dependencies": { - "yallist": { - "version": "3.0.2", - "resolved": false, - "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=" - } - } - }, - "term-size": { - "version": "1.2.0", - "resolved": false, - "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", - "requires": { - "execa": "^0.7.0" - } - }, - "text-table": { - "version": "0.2.0", - "resolved": false, - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" - }, - "through": { - "version": "2.3.8", - "resolved": false, - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" - }, - "through2": { - "version": "2.0.3", - "resolved": false, - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "requires": { - "readable-stream": "^2.1.5", - "xtend": "~4.0.1" - } - }, - "timed-out": { - "version": "4.0.1", - "resolved": false, - "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" - }, - "tiny-relative-date": { - "version": "1.3.0", - "resolved": false, - "integrity": "sha512-MOQHpzllWxDCHHaDno30hhLfbouoYlOI8YlMNtvKe1zXbjEVhbcEovQxvZrPvtiYW630GQDoMMarCnjfyfHA+A==" - }, - "tough-cookie": { - "version": "2.4.3", - "resolved": false, - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", - "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - } - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": false, - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": false, - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "optional": true - }, - "typedarray": { - "version": "0.0.6", - "resolved": false, - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" - }, - "uid-number": { - "version": "0.0.6", - "resolved": false, - "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=" - }, - "umask": { - "version": "1.1.0", - "resolved": false, - "integrity": "sha1-8pzr8B31F5ErtY/5xOUP3o4zMg0=" - }, - "unique-filename": { - "version": "1.1.0", - "resolved": false, - "integrity": "sha1-0F8v5AMlYIcfMOk8vnNe6iAVFPM=", - "requires": { - "unique-slug": "^2.0.0" - } - }, - "unique-slug": { - "version": "2.0.0", - "resolved": false, - "integrity": "sha1-22Z258fMBimHj/GWCXx4hVrp9Ks=", - "requires": { - "imurmurhash": "^0.1.4" - } - }, - "unique-string": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", - "requires": { - "crypto-random-string": "^1.0.0" - } - }, - "unpipe": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" - }, - "unzip-response": { - "version": "2.0.1", - "resolved": false, - "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=" - }, - "update-notifier": { - "version": "2.5.0", - "resolved": false, - "integrity": "sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==", - "requires": { - "boxen": "^1.2.1", - "chalk": "^2.0.1", - "configstore": "^3.0.0", - "import-lazy": "^2.1.0", - "is-ci": "^1.0.10", - "is-installed-globally": "^0.1.0", - "is-npm": "^1.0.0", - "latest-version": "^3.0.0", - "semver-diff": "^2.0.0", - "xdg-basedir": "^3.0.0" - } - }, - "url-parse-lax": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", - "requires": { - "prepend-http": "^1.0.1" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": false, - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "util-extend": { - "version": "1.0.3", - "resolved": false, - "integrity": "sha1-p8IW0mdUUWljeztu3GypEZ4v+T8=" - }, - "uuid": { - "version": "3.3.2", - "resolved": false, - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": false, - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "validate-npm-package-name": { - "version": "3.0.0", - "resolved": false, - "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=", - "requires": { - "builtins": "^1.0.3" - } - }, - "verror": { - "version": "1.10.0", - "resolved": false, - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "wcwidth": { - "version": "1.0.1", - "resolved": false, - "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", - "requires": { - "defaults": "^1.0.3" - } - }, - "which": { - "version": "1.3.1", - "resolved": false, - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "requires": { - "isexe": "^2.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": false, - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" - }, - "wide-align": { - "version": "1.1.2", - "resolved": false, - "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", - "requires": { - "string-width": "^1.0.2" - }, - "dependencies": { - "string-width": { - "version": "1.0.2", - "resolved": false, - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - } - } - }, - "widest-line": { - "version": "2.0.0", - "resolved": false, - "integrity": "sha1-AUKk6KJD+IgsAjOqDgKBqnYVInM=", - "requires": { - "string-width": "^2.1.1" - } - }, - "worker-farm": { - "version": "1.6.0", - "resolved": false, - "integrity": "sha512-6w+3tHbM87WnSWnENBUvA2pxJPLhQUg5LKwUQHq3r+XPhIM+Gh2R5ycbwPCyuGbNg+lPgdcnQUhuC02kJCvffQ==", - "requires": { - "errno": "~0.1.7" - } - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": false, - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - }, - "dependencies": { - "string-width": { - "version": "1.0.2", - "resolved": false, - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - } - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": false, - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "write-file-atomic": { - "version": "2.3.0", - "resolved": false, - "integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==", - "requires": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" - } - }, - "xdg-basedir": { - "version": "3.0.0", - "resolved": false, - "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=" - }, - "xtend": { - "version": "4.0.1", - "resolved": false, - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" - }, - "y18n": { - "version": "4.0.0", - "resolved": false, - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" - }, - "yallist": { - "version": "2.1.2", - "resolved": false, - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" - }, - "yargs": { - "version": "11.0.0", - "resolved": false, - "integrity": "sha512-Rjp+lMYQOWtgqojx1dEWorjCofi1YN7AoFvYV7b1gx/7dAAeuI4kN5SZiEvr0ZmsZTOpDRcCqrpI10L31tFkBw==", - "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.1.1", - "find-up": "^2.1.0", - "get-caller-file": "^1.0.1", - "os-locale": "^2.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^9.0.2" - }, - "dependencies": { - "y18n": { - "version": "3.2.1", - "resolved": false, - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" - } - } - }, - "yargs-parser": { - "version": "9.0.2", - "resolved": false, - "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", - "requires": { - "camelcase": "^4.1.0" - } - } - } - }, "npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", @@ -16606,9 +13519,9 @@ } }, "tinymce": { - "version": "4.7.13", - "resolved": "https://registry.npmjs.org/tinymce/-/tinymce-4.7.13.tgz", - "integrity": "sha512-6QbNYGV4VExH+p7+o/5km6jOnVSD5mO7aw0s+eKByKnpyG8gZfajxXPhwBM57r7SIravrCI6LFj8DARNe31qPw==" + "version": "4.8.3", + "resolved": "https://registry.npmjs.org/tinymce/-/tinymce-4.8.3.tgz", + "integrity": "sha512-kNEsKTqUYZRG+GTZ7tcVAktUlDeApz6d3IqnNaZXNX0CP0BsK8NPC02FCJ0EVYxdNnq6fvvknWkItmbreXD9aA==" }, "tmp": { "version": "0.0.33", diff --git a/src/Umbraco.Web/Actions/ActionCollectionBuilder.cs b/src/Umbraco.Web/Actions/ActionCollectionBuilder.cs index 8400e02271..55fa1c2099 100644 --- a/src/Umbraco.Web/Actions/ActionCollectionBuilder.cs +++ b/src/Umbraco.Web/Actions/ActionCollectionBuilder.cs @@ -9,9 +9,9 @@ namespace Umbraco.Web.Actions { protected override ActionCollectionBuilder This => this; - protected override IEnumerable CreateItems() + protected override IEnumerable CreateItems(IFactory factory) { - var items = base.CreateItems().ToList(); + var items = base.CreateItems(factory).ToList(); //validate the items, no actions should exist that do not either expose notifications or permissions var invalidItems = items.Where(x => !x.CanBePermissionAssigned && !x.ShowInNotifier).ToList(); diff --git a/src/Umbraco.Web/Cache/CacheRefresherComponent.cs b/src/Umbraco.Web/Cache/CacheRefresherComponent.cs index 3a5f716552..95b037c468 100644 --- a/src/Umbraco.Web/Cache/CacheRefresherComponent.cs +++ b/src/Umbraco.Web/Cache/CacheRefresherComponent.cs @@ -21,7 +21,6 @@ using Umbraco.Web.Composing; using Umbraco.Web.Security; using Umbraco.Web.Services; using ApplicationTree = Umbraco.Core.Models.ApplicationTree; -using ContainerExtensions = Umbraco.Core.Composing.ContainerExtensions; namespace Umbraco.Web.Cache { diff --git a/src/Umbraco.Web/Components/DatabaseServerRegistrarAndMessengerComponent.cs b/src/Umbraco.Web/Components/DatabaseServerRegistrarAndMessengerComponent.cs index 1c44098943..8e01b61302 100644 --- a/src/Umbraco.Web/Components/DatabaseServerRegistrarAndMessengerComponent.cs +++ b/src/Umbraco.Web/Components/DatabaseServerRegistrarAndMessengerComponent.cs @@ -3,6 +3,7 @@ using System.Threading; using Examine; using Umbraco.Core; using Umbraco.Core.Components; +using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Persistence; @@ -11,11 +12,10 @@ using Umbraco.Core.Services; using Umbraco.Core.Services.Changes; using Umbraco.Core.Sync; using Umbraco.Web.Cache; -using Umbraco.Web.Composing; using Umbraco.Web.Routing; using Umbraco.Web.Scheduling; using Umbraco.Web.Search; -using ContainerExtensions = Umbraco.Core.Composing.ContainerExtensions; +using Current = Umbraco.Web.Composing.Current; namespace Umbraco.Web.Components { @@ -54,12 +54,12 @@ namespace Umbraco.Web.Components { composition.SetServerMessenger(factory => { - var runtime = ContainerExtensions.GetInstance(factory); - var databaseFactory = ContainerExtensions.GetInstance(factory); - var globalSettings = ContainerExtensions.GetInstance(factory); - var proflog = ContainerExtensions.GetInstance(factory); - var scopeProvider = ContainerExtensions.GetInstance(factory); - var sqlContext = ContainerExtensions.GetInstance(factory); + var runtime = RegisterExtensions.GetInstance(factory); + var databaseFactory = RegisterExtensions.GetInstance(factory); + var globalSettings = RegisterExtensions.GetInstance(factory); + var proflog = RegisterExtensions.GetInstance(factory); + var scopeProvider = RegisterExtensions.GetInstance(factory); + var sqlContext = RegisterExtensions.GetInstance(factory); return new BatchedDatabaseServerMessenger( runtime, databaseFactory, scopeProvider, sqlContext, proflog, globalSettings, diff --git a/src/Umbraco.Web/Components/NotificationsComponent.cs b/src/Umbraco.Web/Components/NotificationsComponent.cs index 38ec283cfe..b54dce4e3e 100644 --- a/src/Umbraco.Web/Components/NotificationsComponent.cs +++ b/src/Umbraco.Web/Components/NotificationsComponent.cs @@ -23,7 +23,7 @@ namespace Umbraco.Web.Components public override void Compose(Composition composition) { base.Compose(composition); - composition.Container.RegisterSingleton(); + composition.RegisterSingleton(); } public void Initialize(INotificationService notificationService, Notifier notifier, ActionCollection actions) @@ -42,7 +42,7 @@ namespace Umbraco.Web.Components //Send notifications for the delete action ContentService.Deleted += (sender, args) => notifier.Notify(actions.GetAction(), args.DeletedEntities.ToArray()); - + //Send notifications for the unpublish action ContentService.Unpublished += (sender, args) => notifier.Notify(actions.GetAction(), args.PublishedEntities.ToArray()); } @@ -54,7 +54,7 @@ namespace Umbraco.Web.Components // in this case there's nothing to report since if the root is sorted we can't report on a fake entity. // this is how it was in v7, we can't report on root changes because you can't subscribe to root changes. - if (parentId[0] <= 0) return; + if (parentId[0] <= 0) return; var parent = sender.GetById(parentId[0]); if (parent == null) return; // this shouldn't happen @@ -191,5 +191,5 @@ namespace Umbraco.Web.Components } } - + } diff --git a/src/Umbraco.Web/Composing/Composers/ControllersComposer.cs b/src/Umbraco.Web/Composing/Composers/ControllersComposer.cs index 5491c0cc97..83a52456a1 100644 --- a/src/Umbraco.Web/Composing/Composers/ControllersComposer.cs +++ b/src/Umbraco.Web/Composing/Composers/ControllersComposer.cs @@ -36,10 +36,9 @@ namespace Umbraco.Web.Composing.Composers private static void RegisterControllers(this Composition composition, Assembly assembly) { - var container = composition.Container; var types = composition.TypeLoader.GetTypes(specificAssemblies: new[] { assembly }); foreach (var type in types) - container.Register(type, Lifetime.Request); + composition.Register(type, Lifetime.Request); } } } diff --git a/src/Umbraco.Web/Composing/Composers/InstallerComposer.cs b/src/Umbraco.Web/Composing/Composers/InstallerComposer.cs index 3d1a5b5c43..760e966435 100644 --- a/src/Umbraco.Web/Composing/Composers/InstallerComposer.cs +++ b/src/Umbraco.Web/Composing/Composers/InstallerComposer.cs @@ -9,27 +9,25 @@ namespace Umbraco.Web.Composing.Composers { public static Composition ComposeInstaller(this Composition composition) { - var container = composition.Container; - // register the installer steps - container.Register(Lifetime.Scope); - container.Register(Lifetime.Scope); - container.Register(Lifetime.Scope); - container.Register(Lifetime.Scope); - container.Register(Lifetime.Scope); - container.Register(Lifetime.Scope); - container.Register(Lifetime.Scope); + composition.Register(Lifetime.Scope); + composition.Register(Lifetime.Scope); + composition.Register(Lifetime.Scope); + composition.Register(Lifetime.Scope); + composition.Register(Lifetime.Scope); + composition.Register(Lifetime.Scope); + composition.Register(Lifetime.Scope); //TODO: Add these back once we have a compatible starter kit //container.Register(Lifetime.Scope); //container.Register(Lifetime.Scope); //container.Register(Lifetime.Scope); - container.Register(Lifetime.Scope); + composition.Register(Lifetime.Scope); - container.Register(); - container.Register(); + composition.Register(); + composition.Register(); return composition; } diff --git a/src/Umbraco.Web/Composing/Composers/WebMappingProfilesComposer.cs b/src/Umbraco.Web/Composing/Composers/WebMappingProfilesComposer.cs index 4779ba129b..202849a975 100644 --- a/src/Umbraco.Web/Composing/Composers/WebMappingProfilesComposer.cs +++ b/src/Umbraco.Web/Composing/Composers/WebMappingProfilesComposer.cs @@ -13,39 +13,37 @@ namespace Umbraco.Web.Composing.Composers { public static Composition ComposeWebMappingProfiles(this Composition composition) { - var container = composition.Container; - //register the profiles - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); + composition.Register(); + composition.Register(); + composition.Register(); + composition.Register(); + composition.Register(); + composition.Register(); + composition.Register(); + composition.Register(); + composition.Register(); + composition.Register(); + composition.Register(); + composition.Register(); + composition.Register(); + composition.Register(); + composition.Register(); + composition.Register(); + composition.Register(); + composition.Register(); //register any resolvers, etc.. that the profiles use - container.Register(); - container.Register>(); - container.Register>(); - container.Register>(); - container.Register>(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); - container.Register(); + composition.Register(); + composition.Register>(); + composition.Register>(); + composition.Register>(); + composition.Register>(); + composition.Register(); + composition.Register(); + composition.Register(); + composition.Register(); + composition.Register(); return composition; } diff --git a/src/Umbraco.Web/Composing/Current.cs b/src/Umbraco.Web/Composing/Current.cs index d0d6aeb2fa..6fce8c1318 100644 --- a/src/Umbraco.Web/Composing/Current.cs +++ b/src/Umbraco.Web/Composing/Current.cs @@ -53,10 +53,10 @@ namespace Umbraco.Web.Composing } /// - /// Gets the DI container. + /// Gets the factory. /// - public static IContainer Container - => CoreCurrent.Container; + public static IFactory Factory + => CoreCurrent.Factory; #region Temp & Special @@ -67,7 +67,7 @@ namespace Umbraco.Web.Composing get { if (_umbracoContextAccessor != null) return _umbracoContextAccessor; - return _umbracoContextAccessor = Container.GetInstance(); + return _umbracoContextAccessor = Factory.GetInstance(); } set => _umbracoContextAccessor = value; // for tests } @@ -92,46 +92,46 @@ namespace Umbraco.Web.Composing => UmbracoContextAccessor.UmbracoContext; public static DistributedCache DistributedCache - => Container.GetInstance(); + => Factory.GetInstance(); public static IPublishedSnapshot PublishedSnapshot - => Container.GetInstance().PublishedSnapshot; + => Factory.GetInstance().PublishedSnapshot; public static EventMessages EventMessages - => Container.GetInstance().GetOrDefault(); + => Factory.GetInstance().GetOrDefault(); public static UrlProviderCollection UrlProviders - => Container.GetInstance(); + => Factory.GetInstance(); public static HealthCheckCollectionBuilder HealthCheckCollectionBuilder - => Container.GetInstance(); + => Factory.GetInstance(); internal static ActionCollectionBuilder ActionCollectionBuilder - => Container.GetInstance(); + => Factory.GetInstance(); public static ActionCollection Actions - => Container.GetInstance(); + => Factory.GetInstance(); public static ContentFinderCollection ContentFinders - => Container.GetInstance(); + => Factory.GetInstance(); public static IContentLastChanceFinder LastChanceContentFinder - => Container.GetInstance(); + => Factory.GetInstance(); internal static EditorValidatorCollection EditorValidators - => Container.GetInstance(); + => Factory.GetInstance(); internal static UmbracoApiControllerTypeCollection UmbracoApiControllerTypes - => Container.GetInstance(); + => Factory.GetInstance(); internal static SurfaceControllerTypeCollection SurfaceControllerTypes - => Container.GetInstance(); + => Factory.GetInstance(); public static FilteredControllerFactoryCollection FilteredControllerFactories - => Container.GetInstance(); + => Factory.GetInstance(); internal static IPublishedSnapshotService PublishedSnapshotService - => Container.GetInstance(); + => Factory.GetInstance(); #endregion diff --git a/src/Umbraco.Web/Composing/ModuleInjector.cs b/src/Umbraco.Web/Composing/ModuleInjector.cs index c415d5ca6e..01930d55fd 100644 --- a/src/Umbraco.Web/Composing/ModuleInjector.cs +++ b/src/Umbraco.Web/Composing/ModuleInjector.cs @@ -21,7 +21,7 @@ namespace Umbraco.Web.Composing try { // using the service locator here - no other way, really - Module = Current.Container.GetInstance(); + Module = Current.Factory.GetInstance(); } catch { @@ -31,7 +31,7 @@ namespace Umbraco.Web.Composing try { - runtimeState = Current.Container.GetInstance(); + runtimeState = Current.Factory.GetInstance(); } catch { /* don't make it worse */ } diff --git a/src/Umbraco.Web/CompositionExtensions.cs b/src/Umbraco.Web/CompositionExtensions.cs index 2dfb504662..ee57ca98cb 100644 --- a/src/Umbraco.Web/CompositionExtensions.cs +++ b/src/Umbraco.Web/CompositionExtensions.cs @@ -30,7 +30,7 @@ namespace Umbraco.Core.Components /// The composition. /// internal static ActionCollectionBuilder Actions(this Composition composition) - => composition.Container.GetInstance(); + => composition.GetCollectionBuilder(); /// /// Gets the content apps collection builder. @@ -38,7 +38,7 @@ namespace Umbraco.Core.Components /// The composition. /// public static ContentAppDefinitionCollectionBuilder ContentApps(this Composition composition) - => composition.Container.GetInstance(); + => composition.GetCollectionBuilder(); /// /// Gets the content finders collection builder. @@ -46,7 +46,7 @@ namespace Umbraco.Core.Components /// The composition. /// public static ContentFinderCollectionBuilder ContentFinders(this Composition composition) - => composition.Container.GetInstance(); + => composition.GetCollectionBuilder(); /// /// Gets the editor validators collection builder. @@ -54,10 +54,7 @@ namespace Umbraco.Core.Components /// The composition. /// internal static EditorValidatorCollectionBuilder EditorValidators(this Composition composition) - => composition.Container.GetInstance(); - - public static UmbracoFeatures Features(this Composition composition) - => composition.Container.GetInstance(); + => composition.GetCollectionBuilder(); /// /// Gets the filtered controller factories collection builder. @@ -65,21 +62,21 @@ namespace Umbraco.Core.Components /// The composition. /// public static FilteredControllerFactoryCollectionBuilder FilderedControllerFactory(this Composition composition) - => composition.Container.GetInstance(); + => composition.GetCollectionBuilder(); /// /// Gets the health checks collection builder. /// /// The composition. public static HealthCheckCollectionBuilder HealthChecks(this Composition composition) - => composition.Container.GetInstance(); + => composition.GetCollectionBuilder(); /// /// Gets the url providers collection builder. /// /// The composition. internal static UrlProviderCollectionBuilder UrlProviders(this Composition composition) - => composition.Container.GetInstance(); + => composition.GetCollectionBuilder(); #endregion @@ -93,7 +90,7 @@ namespace Umbraco.Core.Components public static void SetContentLastChanceFinder(this Composition composition) where T : IContentLastChanceFinder { - composition.Container.RegisterSingleton(); + composition.RegisterSingleton(); } /// @@ -101,9 +98,9 @@ namespace Umbraco.Core.Components /// /// The composition. /// A function creating a last chance finder. - public static void SetContentLastChanceFinder(this Composition composition, Func factory) + public static void SetContentLastChanceFinder(this Composition composition, Func factory) { - composition.Container.RegisterSingleton(factory); + composition.RegisterSingleton(factory); } /// @@ -113,7 +110,7 @@ namespace Umbraco.Core.Components /// A last chance finder. public static void SetContentLastChanceFinder(this Composition composition, IContentLastChanceFinder finder) { - composition.Container.RegisterSingleton(_ => finder); + composition.RegisterSingleton(_ => finder); } /// @@ -134,7 +131,7 @@ namespace Umbraco.Core.Components public static void SetPublishedSnapshotService(this Composition composition) where T : IPublishedSnapshotService { - composition.Container.RegisterSingleton(); + composition.RegisterSingleton(); } /// @@ -142,9 +139,9 @@ namespace Umbraco.Core.Components /// /// The composition. /// A function creating a published snapshot service. - public static void SetPublishedSnapshotService(this Composition composition, Func factory) + public static void SetPublishedSnapshotService(this Composition composition, Func factory) { - composition.Container.RegisterSingleton(factory); + composition.RegisterSingleton(factory); } /// @@ -154,7 +151,7 @@ namespace Umbraco.Core.Components /// A published snapshot service. public static void SetPublishedSnapshotService(this Composition composition, IPublishedSnapshotService service) { - composition.Container.RegisterSingleton(_ => service); + composition.RegisterSingleton(_ => service); } /// @@ -165,7 +162,7 @@ namespace Umbraco.Core.Components public static void SetSiteDomainHelper(this Composition composition) where T : ISiteDomainHelper { - composition.Container.RegisterSingleton(); + composition.RegisterSingleton(); } /// @@ -173,9 +170,9 @@ namespace Umbraco.Core.Components /// /// The composition. /// A function creating a helper. - public static void SetSiteDomainHelper(this Composition composition, Func factory) + public static void SetSiteDomainHelper(this Composition composition, Func factory) { - composition.Container.RegisterSingleton(factory); + composition.RegisterSingleton(factory); } /// @@ -185,7 +182,7 @@ namespace Umbraco.Core.Components /// A helper. public static void SetSiteDomainHelper(this Composition composition, ISiteDomainHelper helper) { - composition.Container.RegisterSingleton(_ => helper); + composition.RegisterSingleton(_ => helper); } #endregion diff --git a/src/Umbraco.Web/ContentApps/ContentAppDefinitionCollectionBuilder.cs b/src/Umbraco.Web/ContentApps/ContentAppDefinitionCollectionBuilder.cs index 8c47e0f640..5299fe7152 100644 --- a/src/Umbraco.Web/ContentApps/ContentAppDefinitionCollectionBuilder.cs +++ b/src/Umbraco.Web/ContentApps/ContentAppDefinitionCollectionBuilder.cs @@ -12,22 +12,22 @@ namespace Umbraco.Web.ContentApps protected override ContentAppDefinitionCollectionBuilder This => this; // need to inject dependencies in the collection, so override creation - public override ContentAppDefinitionCollection CreateCollection() + public override ContentAppDefinitionCollection CreateCollection(IFactory factory) { // get the logger just-in-time - see note below for manifest parser - var logger = Container.GetInstance(); + var logger = factory.GetInstance(); - return new ContentAppDefinitionCollection(CreateItems(), logger); + return new ContentAppDefinitionCollection(CreateItems(factory), logger); } - protected override IEnumerable CreateItems() + protected override IEnumerable CreateItems(IFactory factory) { // 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 = Container.GetInstance(); + var manifestParser = factory.GetInstance(); - return base.CreateItems().Concat(manifestParser.Manifest.ContentApps); + return base.CreateItems(factory).Concat(manifestParser.Manifest.ContentApps); } } } diff --git a/src/Umbraco.Web/Editors/DataTypeValidateAttribute.cs b/src/Umbraco.Web/Editors/DataTypeValidateAttribute.cs index 48bae14400..bbb9e22082 100644 --- a/src/Umbraco.Web/Editors/DataTypeValidateAttribute.cs +++ b/src/Umbraco.Web/Editors/DataTypeValidateAttribute.cs @@ -25,7 +25,7 @@ namespace Umbraco.Web.Editors public PropertyEditorCollection PropertyEditors { get; } public DataTypeValidateAttribute() - : this(Current.Container.GetInstance(), Current.Container.GetInstance()) + : this(Current.Factory.GetInstance(), Current.Factory.GetInstance()) { } diff --git a/src/Umbraco.Web/Editors/TourController.cs b/src/Umbraco.Web/Editors/TourController.cs index 5b3c3ab283..021daff423 100644 --- a/src/Umbraco.Web/Editors/TourController.cs +++ b/src/Umbraco.Web/Editors/TourController.cs @@ -23,7 +23,7 @@ namespace Umbraco.Web.Editors if (UmbracoConfig.For.UmbracoSettings().BackOffice.Tours.EnableTours == false) return result; - var filters = Current.Container.GetInstance().ToList(); // fixme inject + var filters = Current.Factory.GetInstance().ToList(); // fixme inject //get all filters that will be applied to all tour aliases var aliasOnlyFilters = filters.Where(x => x.PluginName == null && x.TourFileName == null).ToList(); diff --git a/src/Umbraco.Web/HtmlHelperRenderExtensions.cs b/src/Umbraco.Web/HtmlHelperRenderExtensions.cs index 11ef966a33..5183cd0c3c 100644 --- a/src/Umbraco.Web/HtmlHelperRenderExtensions.cs +++ b/src/Umbraco.Web/HtmlHelperRenderExtensions.cs @@ -7,13 +7,13 @@ using System.Web.Mvc; using System.Web.Mvc.Html; using System.Web.Routing; using Umbraco.Core; +using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Exceptions; using Umbraco.Core.IO; -using Umbraco.Web.Composing; using Umbraco.Web.Mvc; using Umbraco.Web.Security; -using ContainerExtensions = Umbraco.Core.Composing.ContainerExtensions; +using Current = Umbraco.Web.Composing.Current; namespace Umbraco.Web { @@ -94,7 +94,7 @@ namespace Umbraco.Web } if (cacheByMember) { - var helper = ContainerExtensions.GetInstance(Current.Container); + var helper = RegisterExtensions.GetInstance(Current.Factory); var currentMember = helper.GetCurrentMember(); cacheKey.AppendFormat("m{0}-", currentMember == null ? 0 : currentMember.Id); } diff --git a/src/Umbraco.Web/Models/LoginStatusModel.cs b/src/Umbraco.Web/Models/LoginStatusModel.cs index 3d9a1090f9..5f9391dc7c 100644 --- a/src/Umbraco.Web/Models/LoginStatusModel.cs +++ b/src/Umbraco.Web/Models/LoginStatusModel.cs @@ -1,8 +1,8 @@ using System.ComponentModel.DataAnnotations; using Umbraco.Core; -using Umbraco.Web.Composing; +using Umbraco.Core.Composing; using Umbraco.Web.Security; -using ContainerExtensions = Umbraco.Core.Composing.ContainerExtensions; +using Current = Umbraco.Web.Composing.Current; namespace Umbraco.Web.Models { @@ -24,7 +24,7 @@ namespace Umbraco.Web.Models { if (doLookup && Current.UmbracoContext != null) { - var helper = ContainerExtensions.GetInstance(Current.Container); + var helper = RegisterExtensions.GetInstance(Current.Factory); var model = helper.GetCurrentLoginStatus(); if (model != null) { diff --git a/src/Umbraco.Web/Models/ProfileModel.cs b/src/Umbraco.Web/Models/ProfileModel.cs index 17ca54687e..a3c26812a3 100644 --- a/src/Umbraco.Web/Models/ProfileModel.cs +++ b/src/Umbraco.Web/Models/ProfileModel.cs @@ -3,10 +3,10 @@ using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Web.Mvc; -using Umbraco.Web.Composing; using Umbraco.Web.Security; using Umbraco.Core; -using ContainerExtensions = Umbraco.Core.Composing.ContainerExtensions; +using Umbraco.Core.Composing; +using Current = Umbraco.Web.Composing.Current; namespace Umbraco.Web.Models { @@ -28,7 +28,7 @@ namespace Umbraco.Web.Models MemberProperties = new List(); if (doLookup && Current.UmbracoContext != null) { - var helper = ContainerExtensions.GetInstance(Current.Container); + var helper = RegisterExtensions.GetInstance(Current.Factory); var model = helper.GetCurrentMemberProfileModel(); MemberProperties = model.MemberProperties; } diff --git a/src/Umbraco.Web/Models/RegisterModel.cs b/src/Umbraco.Web/Models/RegisterModel.cs index 76d02244b7..26c3d2428c 100644 --- a/src/Umbraco.Web/Models/RegisterModel.cs +++ b/src/Umbraco.Web/Models/RegisterModel.cs @@ -5,9 +5,9 @@ using System.ComponentModel.DataAnnotations; using System.Web; using System.Web.Mvc; using Umbraco.Core; -using Umbraco.Web.Composing; +using Umbraco.Core.Composing; using Umbraco.Web.Security; -using ContainerExtensions = Umbraco.Core.Composing.ContainerExtensions; +using Current = Umbraco.Web.Composing.Current; namespace Umbraco.Web.Models { @@ -32,7 +32,7 @@ namespace Umbraco.Web.Models CreatePersistentLoginCookie = true; if (doLookup && Current.UmbracoContext != null) { - var helper = ContainerExtensions.GetInstance(Current.Container); + var helper = RegisterExtensions.GetInstance(Current.Factory); var model = helper.CreateRegistrationModel(MemberTypeAlias); MemberProperties = model.MemberProperties; } diff --git a/src/Umbraco.Web/Mvc/ContainerControllerFactory.cs b/src/Umbraco.Web/Mvc/ContainerControllerFactory.cs index 74ac491df6..9262903355 100644 --- a/src/Umbraco.Web/Mvc/ContainerControllerFactory.cs +++ b/src/Umbraco.Web/Mvc/ContainerControllerFactory.cs @@ -7,9 +7,9 @@ namespace Umbraco.Web.Mvc { public class ContainerControllerFactory : DefaultControllerFactory { - private readonly IContainer _container; + private readonly IFactory _container; - public ContainerControllerFactory(IContainer container) + public ContainerControllerFactory(IFactory container) { _container = container; } diff --git a/src/Umbraco.Web/Mvc/EnsurePublishedContentRequestAttribute.cs b/src/Umbraco.Web/Mvc/EnsurePublishedContentRequestAttribute.cs index 8477fe9322..4c1c71a223 100644 --- a/src/Umbraco.Web/Mvc/EnsurePublishedContentRequestAttribute.cs +++ b/src/Umbraco.Web/Mvc/EnsurePublishedContentRequestAttribute.cs @@ -2,9 +2,9 @@ using System.Web.Mvc; using Umbraco.Web.Routing; using Umbraco.Core; +using Umbraco.Core.Composing; using Umbraco.Core.Models.PublishedContent; -using Umbraco.Web.Composing; -using ContainerExtensions = Umbraco.Core.Composing.ContainerExtensions; +using Current = Umbraco.Web.Composing.Current; namespace Umbraco.Web.Mvc { @@ -74,7 +74,7 @@ namespace Umbraco.Web.Mvc protected UmbracoContext UmbracoContext => _umbracoContext ?? (_umbracoContext = UmbracoContext.Current); // todo - try lazy property injection? - private PublishedRouter PublishedRouter => ContainerExtensions.GetInstance(Core.Composing.Current.Container); + private PublishedRouter PublishedRouter => RegisterExtensions.GetInstance(Core.Composing.Current.Factory); /// /// Exposes an UmbracoHelper diff --git a/src/Umbraco.Web/Mvc/MasterControllerFactory.cs b/src/Umbraco.Web/Mvc/MasterControllerFactory.cs index 30838e606a..6bc799baa5 100644 --- a/src/Umbraco.Web/Mvc/MasterControllerFactory.cs +++ b/src/Umbraco.Web/Mvc/MasterControllerFactory.cs @@ -22,7 +22,7 @@ namespace Umbraco.Web.Mvc /// /// The factories accessor. public MasterControllerFactory(Func factoriesAccessor) - : base(Current.Container) + : base(Current.Factory) { // note // because the MasterControllerFactory needs to be ctored to be assigned to diff --git a/src/Umbraco.Web/Mvc/PluginController.cs b/src/Umbraco.Web/Mvc/PluginController.cs index e82d7437e2..b8e1612b36 100644 --- a/src/Umbraco.Web/Mvc/PluginController.cs +++ b/src/Umbraco.Web/Mvc/PluginController.cs @@ -90,12 +90,12 @@ namespace Umbraco.Web.Mvc protected PluginController() : this( - Current.Container.GetInstance(), - Current.Container.GetInstance(), - Current.Container.GetInstance(), - Current.Container.GetInstance(), - Current.Container.GetInstance(), - Current.Container.GetInstance() + Current.Factory.GetInstance(), + Current.Factory.GetInstance(), + Current.Factory.GetInstance(), + Current.Factory.GetInstance(), + Current.Factory.GetInstance(), + Current.Factory.GetInstance() ) { } diff --git a/src/Umbraco.Web/Mvc/RenderRouteHandler.cs b/src/Umbraco.Web/Mvc/RenderRouteHandler.cs index fa52b102d4..5ab597c5ca 100644 --- a/src/Umbraco.Web/Mvc/RenderRouteHandler.cs +++ b/src/Umbraco.Web/Mvc/RenderRouteHandler.cs @@ -49,7 +49,7 @@ namespace Umbraco.Web.Mvc private UmbracoContext UmbracoContext => _umbracoContext ?? _umbracoContextAccessor.UmbracoContext; - private UmbracoFeatures Features => Current.Container.GetInstance(); // fixme inject + private UmbracoFeatures Features => Current.Factory.GetInstance(); // fixme inject #region IRouteHandler Members @@ -397,7 +397,7 @@ namespace Umbraco.Web.Mvc && routeDef.HasHijackedRoute == false) { // fixme - better find a way to inject that engine? or at least Current.Engine of some sort! - var engine = Core.Composing.Current.Container.GetInstance(); + var engine = Core.Composing.Current.Factory.GetInstance(); request.UpdateOnMissingTemplate(); // request will go 404 // HandleHttpResponseStatus returns a value indicating that the request should diff --git a/src/Umbraco.Web/Mvc/UmbracoController.cs b/src/Umbraco.Web/Mvc/UmbracoController.cs index a7dd23b1ea..5be543bd23 100644 --- a/src/Umbraco.Web/Mvc/UmbracoController.cs +++ b/src/Umbraco.Web/Mvc/UmbracoController.cs @@ -80,12 +80,12 @@ namespace Umbraco.Web.Mvc protected UmbracoController() : this( - Current.Container.GetInstance(), - Current.Container.GetInstance(), - Current.Container.GetInstance(), - Current.Container.GetInstance(), - Current.Container.GetInstance(), - Current.Container.GetInstance() + Current.Factory.GetInstance(), + Current.Factory.GetInstance(), + Current.Factory.GetInstance(), + Current.Factory.GetInstance(), + Current.Factory.GetInstance(), + Current.Factory.GetInstance() ) { } diff --git a/src/Umbraco.Web/Mvc/UmbracoControllerFactory.cs b/src/Umbraco.Web/Mvc/UmbracoControllerFactory.cs index 45ca1480c7..1c041d417c 100644 --- a/src/Umbraco.Web/Mvc/UmbracoControllerFactory.cs +++ b/src/Umbraco.Web/Mvc/UmbracoControllerFactory.cs @@ -68,7 +68,7 @@ namespace Umbraco.Web.Mvc internal class OverridenDefaultControllerFactory : ContainerControllerFactory { public OverridenDefaultControllerFactory() - : base(Current.Container) + : base(Current.Factory) { } public new IController GetControllerInstance(RequestContext requestContext, Type controllerType) diff --git a/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs b/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs index 7f9c07365a..b3449c245d 100644 --- a/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs +++ b/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs @@ -5,15 +5,15 @@ using System.Web.Mvc; using System.Web.WebPages; using Umbraco.Core; using Umbraco.Core.Cache; +using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.IO; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Services; -using Umbraco.Web.Composing; using Umbraco.Web.Models; using Umbraco.Web.Routing; using Umbraco.Web.Security; -using ContainerExtensions = Umbraco.Core.Composing.ContainerExtensions; +using Current = Umbraco.Web.Composing.Current; namespace Umbraco.Web.Mvc { @@ -109,8 +109,8 @@ namespace Umbraco.Web.Mvc protected UmbracoViewPage() : this( - ContainerExtensions.GetInstance(Current.Container), - ContainerExtensions.GetInstance(Current.Container) + RegisterExtensions.GetInstance(Current.Factory), + RegisterExtensions.GetInstance(Current.Factory) ) { } diff --git a/src/Umbraco.Web/Mvc/UmbracoVirtualNodeRouteHandler.cs b/src/Umbraco.Web/Mvc/UmbracoVirtualNodeRouteHandler.cs index c4f5acde19..164fb7acf7 100644 --- a/src/Umbraco.Web/Mvc/UmbracoVirtualNodeRouteHandler.cs +++ b/src/Umbraco.Web/Mvc/UmbracoVirtualNodeRouteHandler.cs @@ -12,7 +12,7 @@ namespace Umbraco.Web.Mvc public abstract class UmbracoVirtualNodeRouteHandler : IRouteHandler { // todo - try lazy property injection? - private PublishedRouter PublishedRouter => Core.Composing.Current.Container.GetInstance(); + private PublishedRouter PublishedRouter => Core.Composing.Current.Factory.GetInstance(); /// /// Returns the UmbracoContext for this route handler diff --git a/src/Umbraco.Web/PublishedCache/NuCache/NuCacheComponent.cs b/src/Umbraco.Web/PublishedCache/NuCache/NuCacheComponent.cs index 0b0effcce9..0651ea1aed 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/NuCacheComponent.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/NuCacheComponent.cs @@ -1,5 +1,4 @@ using Umbraco.Core.Components; -using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Web.PublishedCache.NuCache.DataSource; @@ -12,11 +11,11 @@ namespace Umbraco.Web.PublishedCache.NuCache base.Compose(composition); // register the NuCache database data source - composition.Container.Register(); + composition.Register(); // register the NuCache published snapshot service // must register default options, required in the service ctor - composition.Container.Register(factory => new PublishedSnapshotService.Options()); + composition.Register(factory => new PublishedSnapshotService.Options()); composition.SetPublishedSnapshotService(); // add the NuCache health check (hidden from type finder) diff --git a/src/Umbraco.Web/Routing/PublishedRouter.cs b/src/Umbraco.Web/Routing/PublishedRouter.cs index 387ec8b579..bfaf9a8121 100644 --- a/src/Umbraco.Web/Routing/PublishedRouter.cs +++ b/src/Umbraco.Web/Routing/PublishedRouter.cs @@ -627,7 +627,7 @@ namespace Umbraco.Web.Routing { _logger.Debug("EnsurePublishedContentAccess: Page is protected, check for access"); - var membershipHelper = Current.Container.GetInstance(); + var membershipHelper = Current.Factory.GetInstance(); if (membershipHelper.IsLoggedIn() == false) { diff --git a/src/Umbraco.Web/Runtime/WebRuntime.cs b/src/Umbraco.Web/Runtime/WebRuntime.cs index 3e4d2c1c1f..d9283ce0d7 100644 --- a/src/Umbraco.Web/Runtime/WebRuntime.cs +++ b/src/Umbraco.Web/Runtime/WebRuntime.cs @@ -55,12 +55,10 @@ namespace Umbraco.Web.Runtime { base.Compose(composition); - var container = composition.Container; - // some components may want to initialize with the UmbracoApplicationBase // well, they should not - we should not do this // TODO remove this eventually. - container.RegisterInstance(_umbracoApplication); + composition.RegisterInstance(_umbracoApplication); } #region Getters diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs index 25b14ecadf..29e2cc1058 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs @@ -64,11 +64,9 @@ namespace Umbraco.Web.Runtime { base.Compose(composition); - var container = composition.Container; + composition.Register(); - container.Register(); - - container.RegisterSingleton(); // required for hybrid accessors + composition.RegisterSingleton(); // required for hybrid accessors composition.ComposeWebMappingProfiles(); @@ -78,49 +76,49 @@ namespace Umbraco.Web.Runtime composition.ComposeInstaller(); // register membership stuff - container.Register(factory => Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider()); - container.Register(factory => Roles.Enabled ? Roles.Provider : new MembersRoleProvider(factory.GetInstance())); - container.Register(); + composition.Register(factory => Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider()); + composition.Register(factory => Roles.Enabled ? Roles.Provider : new MembersRoleProvider(factory.GetInstance())); + composition.Register(); // register accessors for cultures - container.RegisterSingleton(); - container.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); // register the http context and umbraco context accessors // we *should* use the HttpContextUmbracoContextAccessor, however there are cases when // we have no http context, eg when booting Umbraco or in background threads, so instead // let's use an hybrid accessor that can fall back to a ThreadStatic context. - container.RegisterSingleton(); + composition.RegisterSingleton(); // register a per-request HttpContextBase object // is per-request so only one wrapper is created per request - container.Register(factory => new HttpContextWrapper(factory.GetInstance().HttpContext), Lifetime.Request); + composition.Register(factory => new HttpContextWrapper(factory.GetInstance().HttpContext), Lifetime.Request); // register the published snapshot accessor - the "current" published snapshot is in the umbraco context - container.RegisterSingleton(); + composition.RegisterSingleton(); // we should stop injecting UmbracoContext and always inject IUmbracoContextAccessor, however at the moment // there are tons of places (controllers...) which require UmbracoContext in their ctor - so let's register // a way to inject the UmbracoContext - and register it per-request to be more efficient //TODO: stop doing this - container.Register(factory => factory.GetInstance().UmbracoContext, Lifetime.Request); + composition.Register(factory => factory.GetInstance().UmbracoContext, Lifetime.Request); // register the umbraco helper - container.RegisterSingleton(); + composition.RegisterSingleton(); // register distributed cache - container.RegisterSingleton(f => new DistributedCache()); + composition.RegisterSingleton(f => new DistributedCache()); // replace some services - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); + composition.RegisterSingleton(); - container.RegisterSingleton(factory => ExamineManager.Instance); + composition.RegisterSingleton(factory => ExamineManager.Instance); // configure the container for web - container.ConfigureForWeb(); + composition.ConfigureForWeb(); composition .ComposeMvcControllers(GetType().Assembly) .ComposeApiControllers(GetType().Assembly); @@ -133,7 +131,7 @@ namespace Umbraco.Web.Runtime composition.GetCollectionBuilder(); - container.RegisterSingleton(); + composition.RegisterSingleton(); // set the default RenderMvcController Current.DefaultRenderMvcControllerType = typeof(RenderMvcController); // fixme WRONG! @@ -142,10 +140,10 @@ namespace Umbraco.Web.Runtime .Add(() => composition.TypeLoader.GetTypes()); var surfaceControllerTypes = new SurfaceControllerTypeCollection(composition.TypeLoader.GetSurfaceControllers()); - container.RegisterInstance(surfaceControllerTypes); + composition.RegisterInstance(surfaceControllerTypes); var umbracoApiControllerTypes = new UmbracoApiControllerTypeCollection(composition.TypeLoader.GetUmbracoApiControllers()); - container.RegisterInstance(umbracoApiControllerTypes); + composition.RegisterInstance(umbracoApiControllerTypes); // both TinyMceValueConverter (in Core) and RteMacroRenderingValueConverter (in Web) will be // discovered when CoreBootManager configures the converters. We HAVE to remove one of them @@ -167,7 +165,7 @@ namespace Umbraco.Web.Runtime .Append() .Append(); - container.RegisterSingleton(); + composition.RegisterSingleton(); composition.GetCollectionBuilder() // all built-in finders in the correct order, @@ -179,9 +177,9 @@ namespace Umbraco.Web.Runtime .Append() .Append(); - container.RegisterSingleton(); + composition.RegisterSingleton(); - container.RegisterSingleton(); + composition.RegisterSingleton(); // register *all* checks, except those marked [HideFromTypeFinder] of course composition.GetCollectionBuilder() @@ -191,17 +189,17 @@ namespace Umbraco.Web.Runtime .Add(() => composition.TypeLoader.GetTypes()); // auto-register views - container.RegisterAuto(typeof(UmbracoViewPage<>)); + composition.RegisterAuto(typeof(UmbracoViewPage<>)); // register published router - container.RegisterSingleton(); - container.Register(_ => UmbracoConfig.For.UmbracoSettings().WebRouting); + composition.RegisterSingleton(); + composition.Register(_ => UmbracoConfig.For.UmbracoSettings().WebRouting); // register preview SignalR hub - container.RegisterSingleton(_ => GlobalHost.ConnectionManager.GetHubContext()); + composition.RegisterSingleton(_ => GlobalHost.ConnectionManager.GetHubContext()); // register properties fallback - container.RegisterSingleton(); + composition.RegisterSingleton(); // register known content apps composition.GetCollectionBuilder() diff --git a/src/Umbraco.Web/Scheduling/BackgroundTaskRunner.cs b/src/Umbraco.Web/Scheduling/BackgroundTaskRunner.cs index 858692edc0..a73734fab8 100644 --- a/src/Umbraco.Web/Scheduling/BackgroundTaskRunner.cs +++ b/src/Umbraco.Web/Scheduling/BackgroundTaskRunner.cs @@ -72,7 +72,7 @@ namespace Umbraco.Web.Scheduling public static MainDomHook Create(Action install, Action release) { - return new MainDomHook(Core.Composing.Current.Container.GetInstance(), install, release); + return new MainDomHook(Core.Composing.Current.Factory.GetInstance(), install, release); } public static MainDomHook CreateForTest(Action install, Action release) diff --git a/src/Umbraco.Web/Security/WebSecurity.cs b/src/Umbraco.Web/Security/WebSecurity.cs index 4b2baf127d..18ef806ad1 100644 --- a/src/Umbraco.Web/Security/WebSecurity.cs +++ b/src/Umbraco.Web/Security/WebSecurity.cs @@ -53,7 +53,7 @@ namespace Umbraco.Web.Security { return false; } - var helper = Current.Container.GetInstance(); + var helper = Current.Factory.GetInstance(); return helper.IsMemberAuthorized(allowAll, allowTypes, allowGroups, allowMembers); } diff --git a/src/Umbraco.Web/SignalR/PreviewHubComponent.cs b/src/Umbraco.Web/SignalR/PreviewHubComponent.cs index d80eb05004..e0e47ca666 100644 --- a/src/Umbraco.Web/SignalR/PreviewHubComponent.cs +++ b/src/Umbraco.Web/SignalR/PreviewHubComponent.cs @@ -14,7 +14,7 @@ namespace Umbraco.Web.SignalR public override void Compose(Composition composition) { base.Compose(composition); - composition.Container.RegisterSingleton(_ => GlobalHost.ConnectionManager.GetHubContext()); + composition.RegisterSingleton(_ => GlobalHost.ConnectionManager.GetHubContext()); } // using a lazy arg here means that we won't create the hub until necessary diff --git a/src/Umbraco.Web/Templates/TemplateRenderer.cs b/src/Umbraco.Web/Templates/TemplateRenderer.cs index dca3c34ba8..282aef8a58 100644 --- a/src/Umbraco.Web/Templates/TemplateRenderer.cs +++ b/src/Umbraco.Web/Templates/TemplateRenderer.cs @@ -10,10 +10,10 @@ using Umbraco.Web.Models; using Umbraco.Web.Mvc; using Umbraco.Web.Routing; using umbraco; +using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Services; -using Umbraco.Web.Composing; -using ContainerExtensions = Umbraco.Core.Composing.ContainerExtensions; +using Current = Umbraco.Web.Composing.Current; namespace Umbraco.Web.Templates { @@ -41,7 +41,7 @@ namespace Umbraco.Web.Templates } // todo - inject! - private PublishedRouter PublishedRouter => ContainerExtensions.GetInstance(Core.Composing.Current.Container); + private PublishedRouter PublishedRouter => RegisterExtensions.GetInstance(Core.Composing.Current.Factory); /// diff --git a/src/Umbraco.Web/Tour/TourFilterCollectionBuilder.cs b/src/Umbraco.Web/Tour/TourFilterCollectionBuilder.cs index c5d7f7eadd..0d2f605cb1 100644 --- a/src/Umbraco.Web/Tour/TourFilterCollectionBuilder.cs +++ b/src/Umbraco.Web/Tour/TourFilterCollectionBuilder.cs @@ -15,9 +15,9 @@ namespace Umbraco.Web.Tour private readonly HashSet _instances = new HashSet(); /// - protected override IEnumerable CreateItems(/*params object[] args*/) + protected override IEnumerable CreateItems(IFactory factory) { - return base.CreateItems(/*args*/).Concat(_instances); + return base.CreateItems(factory).Concat(_instances); } /// diff --git a/src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs b/src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs index e1c81d9a35..e04952b2e6 100644 --- a/src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs +++ b/src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs @@ -2,12 +2,12 @@ using System.Web.Mvc; using System.Web.UI; using Umbraco.Core.Cache; +using Umbraco.Core.Composing; using Umbraco.Core.Logging; using Umbraco.Core.Services; -using Umbraco.Web.Composing; using Umbraco.Web.Security; using Umbraco.Web.UI.Pages; -using ContainerExtensions = Umbraco.Core.Composing.ContainerExtensions; +using Current = Umbraco.Web.Composing.Current; namespace Umbraco.Web.UI.Controls { @@ -30,7 +30,7 @@ namespace Umbraco.Web.UI.Controls if (umbracoContext == null) throw new ArgumentNullException(nameof(umbracoContext)); UmbracoContext = umbracoContext; Umbraco = new UmbracoHelper(umbracoContext, services, appCache); - Members = ContainerExtensions.GetInstance(Current.Container); + Members = RegisterExtensions.GetInstance(Current.Factory); // fixme inject somehow Logger = Current.Logger; diff --git a/src/Umbraco.Web/UmbracoContext.cs b/src/Umbraco.Web/UmbracoContext.cs index 8ee5910bae..57f2adbaa4 100644 --- a/src/Umbraco.Web/UmbracoContext.cs +++ b/src/Umbraco.Web/UmbracoContext.cs @@ -115,7 +115,7 @@ namespace Umbraco.Web UmbracoConfig.For.UmbracoSettings(), Composing.Current.UrlProviders, UmbracoConfig.For.GlobalSettings(), - Composing.Current.Container.GetInstance(), + Composing.Current.Factory.GetInstance(), true); // when the context will be disposed, it will be removed from the accessor diff --git a/src/Umbraco.Web/UmbracoHelper.cs b/src/Umbraco.Web/UmbracoHelper.cs index 6e5a25e867..8fcbb040b5 100644 --- a/src/Umbraco.Web/UmbracoHelper.cs +++ b/src/Umbraco.Web/UmbracoHelper.cs @@ -10,11 +10,11 @@ using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Services; using Umbraco.Core.Xml; -using Umbraco.Web.Composing; using Umbraco.Core.Cache; +using Umbraco.Core.Composing; using Umbraco.Web.Routing; using Umbraco.Web.Security; -using ContainerExtensions = Umbraco.Core.Composing.ContainerExtensions; +using Current = Umbraco.Web.Composing.Current; namespace Umbraco.Web { @@ -156,7 +156,7 @@ namespace Umbraco.Web /// Gets the membership helper. /// public MembershipHelper MembershipHelper => _membershipHelper - ?? (_membershipHelper = ContainerExtensions.GetInstance(Current.Container)); + ?? (_membershipHelper = RegisterExtensions.GetInstance(Current.Factory)); /// /// Gets the url provider. diff --git a/src/Umbraco.Web/WebApi/Filters/FeatureAuthorizeAttribute.cs b/src/Umbraco.Web/WebApi/Filters/FeatureAuthorizeAttribute.cs index df5f1a58c4..d7bc311941 100644 --- a/src/Umbraco.Web/WebApi/Filters/FeatureAuthorizeAttribute.cs +++ b/src/Umbraco.Web/WebApi/Filters/FeatureAuthorizeAttribute.cs @@ -20,7 +20,7 @@ namespace Umbraco.Web.WebApi.Filters public FeatureAuthorizeAttribute() { // attributes have to use Current.Container - _features = Current.Container?.TryGetInstance(); + _features = Current.Factory?.TryGetInstance(); } protected override bool IsAuthorized(HttpActionContext actionContext) diff --git a/src/Umbraco.Web/WebApi/UmbracoApiController.cs b/src/Umbraco.Web/WebApi/UmbracoApiController.cs index b35516b59d..4f2934abf4 100644 --- a/src/Umbraco.Web/WebApi/UmbracoApiController.cs +++ b/src/Umbraco.Web/WebApi/UmbracoApiController.cs @@ -14,12 +14,10 @@ namespace Umbraco.Web.WebApi public abstract class UmbracoApiController : UmbracoApiControllerBase, IDiscoverable { protected UmbracoApiController() - { - } + { } protected UmbracoApiController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, IProfilingLogger profilingLogger, IRuntimeState runtimeState) : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, profilingLogger, runtimeState) - { - } + { } } } diff --git a/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs b/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs index 2e5e4b81c3..27b06ee767 100644 --- a/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs +++ b/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs @@ -26,14 +26,6 @@ namespace Umbraco.Web.WebApi // for debugging purposes internal Guid InstanceId { get; } = Guid.NewGuid(); - // note - // properties marked as [Inject] below will be property-injected (vs constructor-injected) in - // order to keep the constuctor as light as possible, so that ppl implementing eg a SurfaceController - // don't need to implement complex constructors + need to refactor them each time we change ours. - // this means that these properties have a setter. - // what can go wrong? - // fixme remove that comment?! - /// /// Gets or sets the Umbraco context. /// @@ -97,19 +89,21 @@ namespace Umbraco.Web.WebApi protected UmbracoApiControllerBase() : this( - Current.Container.GetInstance(), - Current.Container.GetInstance(), - Current.Container.GetInstance(), - Current.Container.GetInstance(), - Current.Container.GetInstance(), - Current.Container.GetInstance(), - Current.Container.GetInstance(), - Current.Container.GetInstance() + Current.Factory.GetInstance(), + Current.Factory.GetInstance().UmbracoContext, + Current.Factory.GetInstance(), + Current.Factory.GetInstance(), + Current.Factory.GetInstance(), + Current.Factory.GetInstance(), + Current.Factory.GetInstance(), + Current.Factory.GetInstance() ) { } // fixme - Inject fewer things? (Aggregate more) + // fixme - inject the context accessor not the context itself? + // fixme - profiling logger is logger, merge! protected UmbracoApiControllerBase(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, IProfilingLogger profilingLogger, IRuntimeState runtimeState) { GlobalSettings = globalSettings; From f9a19ada04c4183310696339c7415166d32ff060 Mon Sep 17 00:00:00 2001 From: Stephan Date: Wed, 28 Nov 2018 12:59:40 +0100 Subject: [PATCH 106/469] IContainer.die.die.die --- src/Umbraco.Core/Components/Composition.cs | 8 +- .../Composing/FactoryExtensions.cs | 87 ++++++++++ src/Umbraco.Core/Composing/IContainer.cs | 149 ------------------ src/Umbraco.Core/Composing/IFactory.cs | 68 ++++++++ src/Umbraco.Core/Composing/IRegister.cs | 84 ++++++++++ .../LightInject/LightInjectContainer.cs | 17 +- .../Composing/RegisterExtensions.cs | 129 +++------------ ...ContainerFactory.cs => RegisterFactory.cs} | 12 +- src/Umbraco.Core/IRuntime.cs | 4 +- src/Umbraco.Core/Runtime/CoreRuntime.cs | 45 +++--- src/Umbraco.Core/RuntimeState.cs | 7 +- src/Umbraco.Core/Umbraco.Core.csproj | 6 +- .../DistributedCache/DistributedCacheTests.cs | 10 +- .../Composing/CollectionBuildersTests.cs | 34 ++-- .../Composing/ContainerImplementationTests.cs | 38 +++-- src/Umbraco.Tests/Composing/ContainerTests.cs | 124 +++++++++------ .../Composing/LazyCollectionBuilderTests.cs | 44 +++--- .../Composing/PackageActionCollectionTests.cs | 4 +- .../CoreThings/TryConvertToTests.cs | 2 +- src/Umbraco.Tests/IO/FileSystemsTests.cs | 33 ++-- .../Integration/ContentEventsTests.cs | 4 +- src/Umbraco.Tests/Issues/U9560.cs | 4 +- .../Manifest/ManifestParserTests.cs | 7 +- src/Umbraco.Tests/Models/ContentTests.cs | 6 +- .../Models/Mapping/AutoMapperTests.cs | 6 +- .../Mapping/ContentTypeModelMappingTests.cs | 12 +- .../Mapping/ContentWebModelMappingTests.cs | 2 +- src/Umbraco.Tests/Models/VariationTests.cs | 6 +- .../DataTypeDefinitionRepositoryTest.cs | 2 +- .../Repositories/DictionaryRepositoryTest.cs | 4 +- .../PartialViewRepositoryTests.cs | 2 +- .../Repositories/ScriptRepositoryTest.cs | 2 +- .../PropertyEditors/ImageCropperTest.cs | 5 +- .../PropertyEditorValueEditorTests.cs | 7 +- .../Published/ConvertersTests.cs | 12 +- .../PublishedContentLanguageVariantTests.cs | 4 +- .../PublishedContentSnapshotTestBase.cs | 2 +- .../PublishedContentTestBase.cs | 2 +- .../PublishedContent/PublishedContentTests.cs | 14 +- .../Routing/ContentFinderByIdTests.cs | 2 +- .../ContentFinderByUrlWithDomainsTests.cs | 4 +- .../Routing/DomainsAndCulturesTests.cs | 8 +- .../Routing/RenderRouteHandlerTests.cs | 12 +- .../Routing/UmbracoModuleTests.cs | 4 +- src/Umbraco.Tests/Routing/UrlProviderTests.cs | 2 +- .../Routing/UrlRoutingTestBase.cs | 4 +- .../Routing/UrlsProviderWithDomainsTests.cs | 4 +- .../Routing/UrlsWithNestedDomains.cs | 4 +- .../Runtimes/CoreRuntimeTests.cs | 4 +- .../Scoping/ScopeEventDispatcherTests.cs | 12 +- .../Scoping/ScopedNuCacheTests.cs | 6 +- .../Scoping/ScopedRepositoryTests.cs | 4 +- src/Umbraco.Tests/Scoping/ScopedXmlTests.cs | 4 +- .../Services/ContentServicePerformanceTest.cs | 2 +- .../Services/ContentServiceTests.cs | 2 +- .../ContentTypeServiceVariantsTests.cs | 8 +- .../Strings/DefaultShortStringHelperTests.cs | 2 +- .../Strings/StringExtensionsTests.cs | 2 +- .../TestHelpers/BaseUsingSqlCeSyntax.cs | 13 +- src/Umbraco.Tests/TestHelpers/BaseWebTest.cs | 4 +- src/Umbraco.Tests/TestHelpers/TestObjects.cs | 64 ++++---- .../TestHelpers/TestWithDatabaseBase.cs | 34 ++-- .../Testing/TestingTests/MockTests.cs | 10 +- src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 95 +++++------ .../TreesAndSections/SectionTests.cs | 2 +- .../UmbracoExamine/ExamineBaseTest.cs | 2 +- .../Web/Controllers/ContentControllerTests.cs | 16 +- .../Web/Controllers/UsersControllerTests.cs | 6 +- .../Web/Mvc/SurfaceControllerTests.cs | 2 +- ...aseServerRegistrarAndMessengerComponent.cs | 12 +- .../LightInject/LightInjectContainer.cs | 7 +- src/Umbraco.Web/HtmlHelperRenderExtensions.cs | 2 +- src/Umbraco.Web/Models/LoginStatusModel.cs | 2 +- src/Umbraco.Web/Models/ProfileModel.cs | 2 +- src/Umbraco.Web/Models/RegisterModel.cs | 2 +- .../EnsurePublishedContentRequestAttribute.cs | 2 +- .../Mvc/UmbracoViewPageOfTModel.cs | 4 +- src/Umbraco.Web/Runtime/WebRuntime.cs | 6 +- src/Umbraco.Web/Templates/TemplateRenderer.cs | 2 +- .../UI/Controls/UmbracoUserControl.cs | 2 +- src/Umbraco.Web/UmbracoApplicationBase.cs | 6 +- src/Umbraco.Web/UmbracoHelper.cs | 2 +- 82 files changed, 726 insertions(+), 671 deletions(-) create mode 100644 src/Umbraco.Core/Composing/FactoryExtensions.cs delete mode 100644 src/Umbraco.Core/Composing/IContainer.cs create mode 100644 src/Umbraco.Core/Composing/IFactory.cs create mode 100644 src/Umbraco.Core/Composing/IRegister.cs rename src/Umbraco.Core/Composing/{ContainerFactory.cs => RegisterFactory.cs} (90%) diff --git a/src/Umbraco.Core/Components/Composition.cs b/src/Umbraco.Core/Components/Composition.cs index 6032dd303d..c81fe388ba 100644 --- a/src/Umbraco.Core/Components/Composition.cs +++ b/src/Umbraco.Core/Components/Composition.cs @@ -78,13 +78,17 @@ namespace Umbraco.Core.Components => _register.RegisterAuto(serviceBaseType); /// - public IContainer ConfigureForWeb() + public void ConfigureForWeb() => _register.ConfigureForWeb(); /// - public IContainer EnablePerWebRequestScope() + public void EnablePerWebRequestScope() => _register.EnablePerWebRequestScope(); + /// + public IFactory CreateFactory() + => _register.CreateFactory(); + #endregion #region Collection Builders diff --git a/src/Umbraco.Core/Composing/FactoryExtensions.cs b/src/Umbraco.Core/Composing/FactoryExtensions.cs new file mode 100644 index 0000000000..2640b7f7e6 --- /dev/null +++ b/src/Umbraco.Core/Composing/FactoryExtensions.cs @@ -0,0 +1,87 @@ +using System; +using System.Linq; +using System.Reflection; + +namespace Umbraco.Core.Composing +{ + /// + /// Provides extension methods to the class. + /// + public static class FactoryExtensions + { + /// + /// Gets an instance of a service. + /// + /// The type of the service. + /// The factory. + /// An instance of the specified type. + /// Throws an exception if the factory failed to get an instance of the specified type. + public static T GetInstance(this IFactory factory) + => (T)factory.GetInstance(typeof(T)); + + /// + /// Tries to get an instance of a service. + /// + /// The type of the service. + /// An instance of the specified type, or null. + /// Returns null if the factory does not know how to get an instance + /// of the specified type. Throws an exception if the factory does know how + /// to get an instance of the specified type, but failed to do so. + public static T TryGetInstance(this IFactory factory) + => (T)factory.TryGetInstance(typeof(T)); + + /// + /// Creates an instance with arguments. + /// + /// The type of the instance. + /// The factory. + /// Arguments. + /// An instance of the specified type. + /// + /// Throws an exception if the factory failed to get an instance of the specified type. + /// The arguments are used as dependencies by the factory. + /// + public static T CreateInstance(this IFactory factory, params object[] args) + => (T)factory.CreateInstance(typeof(T), args); + + /// + /// Creates an instance of a service, with arguments. + /// + /// + /// The type of the instance. + /// Named arguments. + /// An instance of the specified type. + /// + /// The instance type does not need to be registered into the factory. + /// The arguments are used as dependencies by the factory. Other dependencies + /// are retrieved from the factory. + /// + public static object CreateInstance(this IFactory factory, Type type, params object[] args) + { + // LightInject has this, but then it requires RegisterConstructorDependency etc and has various oddities + // including the most annoying one, which is that it does not work on singletons (hard to fix) + //return factory.GetInstance(type, args); + + // this method is essentially used to build singleton instances, so it is assumed that it would be + // more expensive to build and cache a dynamic method ctor than to simply invoke the ctor, as we do + // here - this can be discussed + + // TODO: we currently try the ctor with most parameters, but we could want to fall back to others + + var ctor = type.GetConstructors(BindingFlags.Instance | BindingFlags.Public).OrderByDescending(x => x.GetParameters().Length).FirstOrDefault(); + if (ctor == null) throw new InvalidOperationException($"Could not find a public constructor for type {type.FullName}."); + + var ctorParameters = ctor.GetParameters(); + var ctorArgs = new object[ctorParameters.Length]; + var i = 0; + foreach (var parameter in ctorParameters) + { + // no! IsInstanceOfType is not ok here + // ReSharper disable once UseMethodIsInstanceOfType + var arg = args?.FirstOrDefault(a => parameter.ParameterType.IsAssignableFrom(a.GetType())); + ctorArgs[i++] = arg ?? factory.GetInstance(parameter.ParameterType); + } + return ctor.Invoke(ctorArgs); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Composing/IContainer.cs b/src/Umbraco.Core/Composing/IContainer.cs deleted file mode 100644 index 22b6ac3eae..0000000000 --- a/src/Umbraco.Core/Composing/IContainer.cs +++ /dev/null @@ -1,149 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace Umbraco.Core.Composing -{ - // Implementing IContainer: - // - // The factory - // - always picks the constructor with the most parameters - // - supports Lazy parameters (and prefers them over non-Lazy) in constructors - // - what happens with 'releasing' is unclear - // - // The registry - // - supports registering a service, even after some instances of other services have been created - // - supports re-registering a service, as long as no instance of that service has been created - // - throws when re-registering a service, and an instance of that service has been created - // - // - registers only one implementation of a nameless service, re-registering replaces the previous - // registration - names are required to register multiple implementations - and getting an - // IEnumerable of the service, nameless, returns them all - - /// - /// Defines a service register for Umbraco. - /// - public interface IRegister - { - /// - /// Gets the concrete container. - /// - object ConcreteContainer { get; } - - /// - /// Registers a service as its own implementation. - /// - void Register(Type serviceType, Lifetime lifetime = Lifetime.Transient); - - /// - /// Registers a service with an implementation type. - /// - void Register(Type serviceType, Type implementingType, Lifetime lifetime = Lifetime.Transient); - - /// - /// Registers a service with an implementation factory. - /// - void Register(Func factory, Lifetime lifetime = Lifetime.Transient); - - /// - /// Registers a service with an implementing instance. - /// - void RegisterInstance(Type serviceType, object instance); - - /// - /// Registers a base type for auto-registration. - /// - /// - /// Auto-registration means that anytime the container is asked to create an instance - /// of a type deriving from , it will first register that - /// type automatically. - /// This can be used for instance for views or controllers. Then, one just needs to - /// register a common base class or interface, and the container knows how to create instances. - /// - void RegisterAuto(Type serviceBaseType); - - #region Control - - /// - /// Configures the container for web support. - /// - /// The container. - /// - /// Enables support for MVC, WebAPI, but *not* per-request scope. This is used early in the boot - /// process, where anything "scoped" should not be linked to a web request. - /// - IContainer ConfigureForWeb(); - - /// - /// Enables per-request scope. - /// - /// The container. - /// - /// Ties scopes to web requests. - /// - IContainer EnablePerWebRequestScope(); - - #endregion - } - - /// - /// Defines a service factory for Umbraco. - /// - public interface IFactory - { - /// - /// Gets an instance of a service. - /// - /// The type of the service. - /// An instance of the specified type. - /// Throws an exception if the container failed to get an instance of the specified type. - object GetInstance(Type type); - - /// - /// Tries to get an instance of a service. - /// - /// The type of the service. - /// An instance of the specified type, or null. - /// Returns null if the container does not know how to get an instance - /// of the specified type. Throws an exception if the container does know how - /// to get an instance of the specified type, but failed to do so. - object TryGetInstance(Type type); - - /// - /// Gets all instances of a service. - /// - /// The type of the service. - IEnumerable GetAllInstances(Type serviceType); - - /// - /// Gets all instances of a service. - /// - /// The type of the service. - IEnumerable GetAllInstances(); - - /// - /// Releases an instance. - /// - /// The instance. - /// - /// See https://stackoverflow.com/questions/14072208 and http://kozmic.net/2010/08/27/must-i-release-everything-when-using-windsor/, - /// you only need to release instances you specifically resolved, and even then, if done right, that might never be needed. For - /// instance, LightInject does not require this and does not support it - should work with scopes. - /// - void Release(object instance); - - /// - /// Begins a scope. - /// - /// - /// When the scope is disposed, scoped instances that have been created during the scope are disposed. - /// Scopes can be nested. Each instance is disposed individually. - /// - IDisposable BeginScope(); - } - - /// - /// Defines a container for Umbraco. - /// - public interface IContainer : IRegister, IFactory, IDisposable // fixme kill? - { } -} diff --git a/src/Umbraco.Core/Composing/IFactory.cs b/src/Umbraco.Core/Composing/IFactory.cs new file mode 100644 index 0000000000..3e8cdf08e0 --- /dev/null +++ b/src/Umbraco.Core/Composing/IFactory.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; + +namespace Umbraco.Core.Composing +{ + // Implementing: + // + // The factory + // - always picks the constructor with the most parameters + // - supports Lazy parameters (and prefers them over non-Lazy) in constructors + // - what happens with 'releasing' is unclear + + /// + /// Defines a service factory for Umbraco. + /// + public interface IFactory + { + /// + /// Gets an instance of a service. + /// + /// The type of the service. + /// An instance of the specified type. + /// Throws an exception if the container failed to get an instance of the specified type. + object GetInstance(Type type); + + /// + /// Tries to get an instance of a service. + /// + /// The type of the service. + /// An instance of the specified type, or null. + /// Returns null if the container does not know how to get an instance + /// of the specified type. Throws an exception if the container does know how + /// to get an instance of the specified type, but failed to do so. + object TryGetInstance(Type type); + + /// + /// Gets all instances of a service. + /// + /// The type of the service. + IEnumerable GetAllInstances(Type serviceType); + + /// + /// Gets all instances of a service. + /// + /// The type of the service. + IEnumerable GetAllInstances(); + + /// + /// Releases an instance. + /// + /// The instance. + /// + /// See https://stackoverflow.com/questions/14072208 and http://kozmic.net/2010/08/27/must-i-release-everything-when-using-windsor/, + /// you only need to release instances you specifically resolved, and even then, if done right, that might never be needed. For + /// instance, LightInject does not require this and does not support it - should work with scopes. + /// + void Release(object instance); + + /// + /// Begins a scope. + /// + /// + /// When the scope is disposed, scoped instances that have been created during the scope are disposed. + /// Scopes can be nested. Each instance is disposed individually. + /// + IDisposable BeginScope(); + } +} diff --git a/src/Umbraco.Core/Composing/IRegister.cs b/src/Umbraco.Core/Composing/IRegister.cs new file mode 100644 index 0000000000..1ce7ae9f0b --- /dev/null +++ b/src/Umbraco.Core/Composing/IRegister.cs @@ -0,0 +1,84 @@ +using System; + +namespace Umbraco.Core.Composing +{ + // Implementing: + // + // The register + // - supports registering a service, even after some instances of other services have been created + // - supports re-registering a service, as long as no instance of that service has been created + // - throws when re-registering a service, and an instance of that service has been created + // + // - registers only one implementation of a nameless service, re-registering replaces the previous + // registration - names are required to register multiple implementations - and getting an + // IEnumerable of the service, nameless, returns them all + + /// + /// Defines a service register for Umbraco. + /// + public interface IRegister + { + /// + /// Gets the concrete container. + /// + object ConcreteContainer { get; } + + /// + /// Registers a service as its own implementation. + /// + void Register(Type serviceType, Lifetime lifetime = Lifetime.Transient); + + /// + /// Registers a service with an implementation type. + /// + void Register(Type serviceType, Type implementingType, Lifetime lifetime = Lifetime.Transient); + + /// + /// Registers a service with an implementation factory. + /// + void Register(Func factory, Lifetime lifetime = Lifetime.Transient); + + /// + /// Registers a service with an implementing instance. + /// + void RegisterInstance(Type serviceType, object instance); + + /// + /// Registers a base type for auto-registration. + /// + /// + /// Auto-registration means that anytime the container is asked to create an instance + /// of a type deriving from , it will first register that + /// type automatically. + /// This can be used for instance for views or controllers. Then, one just needs to + /// register a common base class or interface, and the container knows how to create instances. + /// + void RegisterAuto(Type serviceBaseType); + + #region Control + + /// + /// Configures the container for web support. + /// + /// + /// Enables support for MVC, WebAPI, but *not* per-request scope. This is used early in the boot + /// process, where anything "scoped" should not be linked to a web request. + /// + void ConfigureForWeb(); + + /// + /// Enables per-request scope. + /// + /// + /// Ties scopes to web requests. + /// + void EnablePerWebRequestScope(); + + /// + /// Creates the factory. + /// + IFactory CreateFactory(); + + #endregion + } +} diff --git a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs index a15bfdfb16..d94643e49a 100644 --- a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs +++ b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs @@ -1,16 +1,15 @@ using System; using System.Collections.Generic; using System.Reflection; -using System.Linq; using System.Threading; using LightInject; namespace Umbraco.Core.Composing.LightInject { /// - /// Implements with LightInject. + /// Implements DI with LightInject. /// - public class LightInjectContainer : IContainer + public class LightInjectContainer : IRegister, IFactory, IDisposable { private int _disposed; @@ -99,6 +98,9 @@ namespace Umbraco.Core.Composing.LightInject Container.Dispose(); } + /// + public IFactory CreateFactory() => this; + #region Factory /// @@ -246,18 +248,15 @@ namespace Umbraco.Core.Composing.LightInject => Container.BeginScope(); /// - public virtual IContainer ConfigureForWeb() - { - return this; - } + public virtual void ConfigureForWeb() + { } /// - public IContainer EnablePerWebRequestScope() + public void EnablePerWebRequestScope() { if (!(Container.ScopeManagerProvider is MixedLightInjectScopeManagerProvider smp)) throw new Exception("Container.ScopeManagerProvider is not MixedLightInjectScopeManagerProvider."); smp.EnablePerWebRequestScope(); - return this; } private class AssemblyScanner : IAssemblyScanner diff --git a/src/Umbraco.Core/Composing/RegisterExtensions.cs b/src/Umbraco.Core/Composing/RegisterExtensions.cs index fc6aa78f0b..cff51a7f53 100644 --- a/src/Umbraco.Core/Composing/RegisterExtensions.cs +++ b/src/Umbraco.Core/Composing/RegisterExtensions.cs @@ -1,171 +1,92 @@ using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; using Umbraco.Core.IO; namespace Umbraco.Core.Composing { /// - /// Provides extension methods to the class. + /// Provides extension methods to the class. /// public static class RegisterExtensions { - /// - /// Gets an instance of a service. - /// - /// The type of the service. - /// The container. - /// An instance of the specified type. - /// Throws an exception if the container failed to get an instance of the specified type. - public static T GetInstance(this IFactory container) - => (T) container.GetInstance(typeof(T)); - - /// - /// Tries to get an instance of a service. - /// - /// The type of the service. - /// An instance of the specified type, or null. - /// Returns null if the container does not know how to get an instance - /// of the specified type. Throws an exception if the container does know how - /// to get an instance of the specified type, but failed to do so. - public static T TryGetInstance(this IFactory container) - => (T) container.TryGetInstance(typeof(T)); - - /// - /// Creates an instance with arguments. - /// - /// The type of the instance. - /// The container. - /// Arguments. - /// An instance of the specified type. - /// - /// Throws an exception if the container failed to get an instance of the specified type. - /// The arguments are used as dependencies by the container. - /// - public static T CreateInstance(this IFactory container, params object[] args) - => (T) container.CreateInstance(typeof(T), args); - /// /// Registers a service with an implementation type. /// - public static void Register(this IRegister container, Lifetime lifetime = Lifetime.Transient) - => container.Register(typeof(TService), typeof(TImplementing), lifetime); + public static void Register(this IRegister register, Lifetime lifetime = Lifetime.Transient) + => register.Register(typeof(TService), typeof(TImplementing), lifetime); /// /// Registers a service as its own implementation. /// - public static void Register(this IRegister container, Lifetime lifetime = Lifetime.Transient) - => container.Register(typeof(TService), lifetime); + public static void Register(this IRegister register, Lifetime lifetime = Lifetime.Transient) + => register.Register(typeof(TService), lifetime); /// /// Registers a singleton service as its own implementation. /// - public static void RegisterSingleton(this IRegister container) - => container.Register(typeof(TService), Lifetime.Singleton); + public static void RegisterSingleton(this IRegister register) + => register.Register(typeof(TService), Lifetime.Singleton); /// /// Registers a singleton service with an implementation type. /// - public static void RegisterSingleton(this IRegister container) - => container.Register(typeof(TService), typeof(TImplementing), Lifetime.Singleton); + public static void RegisterSingleton(this IRegister register) + => register.Register(typeof(TService), typeof(TImplementing), Lifetime.Singleton); /// /// Registers a singleton service with an implementation factory. /// - public static void RegisterSingleton(this IRegister container, Func factory) - => container.Register(factory, Lifetime.Singleton); + public static void RegisterSingleton(this IRegister register, Func factory) + => register.Register(factory, Lifetime.Singleton); /// /// Registers a service with an implementing instance. /// - public static void RegisterInstance(this IRegister container, TService instance) - => container.RegisterInstance(typeof(TService), instance); + public static void RegisterInstance(this IRegister register, TService instance) + => register.RegisterInstance(typeof(TService), instance); /// /// Registers a base type for auto-registration. /// - public static void RegisterAuto(this IRegister container) - => container.RegisterAuto(typeof(TServiceBase)); - - /// - /// Creates an instance of a service, with arguments. - /// - /// - /// The type of the instance. - /// Named arguments. - /// An instance of the specified type. - /// - /// The instance type does not need to be registered into the container. - /// The arguments are used as dependencies by the container. Other dependencies - /// are retrieved from the container. - /// - public static object CreateInstance(this IFactory container, Type type, params object[] args) - { - // LightInject has this, but then it requires RegisterConstructorDependency etc and has various oddities - // including the most annoying one, which is that it does not work on singletons (hard to fix) - //return Container.GetInstance(type, args); - - // this method is essentially used to build singleton instances, so it is assumed that it would be - // more expensive to build and cache a dynamic method ctor than to simply invoke the ctor, as we do - // here - this can be discussed - - // TODO: we currently try the ctor with most parameters, but we could want to fall back to others - - var ctor = type.GetConstructors(BindingFlags.Instance | BindingFlags.Public).OrderByDescending(x => x.GetParameters().Length).FirstOrDefault(); - if (ctor == null) throw new InvalidOperationException($"Could not find a public constructor for type {type.FullName}."); - - var ctorParameters = ctor.GetParameters(); - var ctorArgs = new object[ctorParameters.Length]; - var i = 0; - foreach (var parameter in ctorParameters) - { - // no! IsInstanceOfType is not ok here - // ReSharper disable once UseMethodIsInstanceOfType - var arg = args?.FirstOrDefault(a => parameter.ParameterType.IsAssignableFrom(a.GetType())); - ctorArgs[i++] = arg ?? container.GetInstance(parameter.ParameterType); - } - return ctor.Invoke(ctorArgs); - } + public static void RegisterAuto(this IRegister register) + => register.RegisterAuto(typeof(TServiceBase)); /// /// Registers a filesystem. /// /// The type of the filesystem. /// The implementing type. - /// The container. + /// The register. /// A factory method creating the supporting filesystem. - /// The container. - public static IRegister RegisterFileSystem(this IRegister container, Func supportingFileSystemFactory) + /// The register. + public static IRegister RegisterFileSystem(this IRegister register, Func supportingFileSystemFactory) where TImplementing : FileSystemWrapper, TFileSystem { - container.RegisterSingleton(factory => + register.RegisterSingleton(factory => { var fileSystems = factory.GetInstance(); return fileSystems.GetFileSystem(supportingFileSystemFactory(factory)); }); - return container; + return register; } /// /// Registers a filesystem. /// /// The type of the filesystem. - /// The container. + /// The register. /// A factory method creating the supporting filesystem. - /// The container. - public static IRegister RegisterFileSystem(this IRegister container, Func supportingFileSystemFactory) + /// The register. + public static IRegister RegisterFileSystem(this IRegister register, Func supportingFileSystemFactory) where TFileSystem : FileSystemWrapper { - container.RegisterSingleton(factory => + register.RegisterSingleton(factory => { var fileSystems = factory.GetInstance(); return fileSystems.GetFileSystem(supportingFileSystemFactory(factory)); }); - return container; + return register; } } } diff --git a/src/Umbraco.Core/Composing/ContainerFactory.cs b/src/Umbraco.Core/Composing/RegisterFactory.cs similarity index 90% rename from src/Umbraco.Core/Composing/ContainerFactory.cs rename to src/Umbraco.Core/Composing/RegisterFactory.cs index fb2c5f6eb7..bb132c247a 100644 --- a/src/Umbraco.Core/Composing/ContainerFactory.cs +++ b/src/Umbraco.Core/Composing/RegisterFactory.cs @@ -7,7 +7,7 @@ namespace Umbraco.Core.Composing /// /// Creates the container. /// - public static class ContainerFactory + public static class RegisterFactory { // cannot use typeof().AssemblyQualifiedName on the web container - we don't reference it // a normal Umbraco site should run on the web container, but an app may run on the core one @@ -19,12 +19,14 @@ namespace Umbraco.Core.Composing /// /// /// To override the default LightInjectContainer, add an appSetting named umbracoContainerType with - /// a fully qualified type name to a class with a static method "Create" returning an IContainer. + /// a fully qualified type name to a class with a static method "Create" returning an IRegister. /// - public static IContainer Create() + public static IRegister Create() { Type type; + // fixme naming / container? + var configuredTypeName = ConfigurationManager.AppSettings["umbracoContainerType"]; if (configuredTypeName.IsNullOrWhiteSpace()) { @@ -46,9 +48,9 @@ namespace Umbraco.Core.Composing if (factoryMethod == null) throw new Exception($"Container factory class '{configuredTypeName}' does not have a public static method named Create."); - var container = factoryMethod.Invoke(null, Array.Empty()) as IContainer; + var container = factoryMethod.Invoke(null, Array.Empty()) as IRegister; if (container == null) - throw new Exception($"Container factory '{configuredTypeName}' did not return an IContainer implementation."); + throw new Exception($"Container factory '{configuredTypeName}' did not return an IRegister implementation."); return container; } diff --git a/src/Umbraco.Core/IRuntime.cs b/src/Umbraco.Core/IRuntime.cs index 12a189b781..8a62e76a5e 100644 --- a/src/Umbraco.Core/IRuntime.cs +++ b/src/Umbraco.Core/IRuntime.cs @@ -10,8 +10,8 @@ namespace Umbraco.Core /// /// Boots the runtime. /// - /// The application container. - void Boot(IContainer container); + /// The application register. + void Boot(IRegister register); /// /// Gets the runtime state. diff --git a/src/Umbraco.Core/Runtime/CoreRuntime.cs b/src/Umbraco.Core/Runtime/CoreRuntime.cs index 4793b1994b..9ccb45cf0f 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntime.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntime.cs @@ -27,8 +27,8 @@ namespace Umbraco.Core.Runtime public class CoreRuntime : IRuntime { private Components.Components _components; + private IFactory _factory; private RuntimeState _state; - private IContainer _container; /// /// Gets the logger. @@ -44,22 +44,19 @@ namespace Umbraco.Core.Runtime public IRuntimeState State => _state; /// - public virtual void Boot(IContainer container) + public virtual void Boot(IRegister register) { - // assign current container - Current.Factory = _container = container; - // create and register the essential services // ie the bare minimum required to boot // loggers var logger = GetLogger(); - container.RegisterInstance(logger); + register.RegisterInstance(logger); Logger = logger; var profiler = GetProfiler(); - container.RegisterInstance(profiler); + register.RegisterInstance(profiler); var profilingLogger = new ProfilingLogger(logger, profiler); - container.RegisterInstance(profilingLogger); + register.RegisterInstance(profilingLogger); ProfilingLogger = profilingLogger; // application environment @@ -69,32 +66,34 @@ namespace Umbraco.Core.Runtime // application caches var appCaches = GetAppCaches(); - container.RegisterInstance(appCaches); + register.RegisterInstance(appCaches); var runtimeCache = appCaches.RuntimeCache; - container.RegisterInstance(runtimeCache); + register.RegisterInstance(runtimeCache); // database factory var databaseFactory = GetDatabaseFactory(); - container.RegisterInstance(databaseFactory); - container.RegisterSingleton(factory => databaseFactory.SqlContext); + register.RegisterInstance(databaseFactory); + register.RegisterSingleton(_ => databaseFactory.SqlContext); // type loader var globalSettings = UmbracoConfig.For.GlobalSettings(); var typeLoader = new TypeLoader(runtimeCache, globalSettings, profilingLogger); - container.RegisterInstance(typeLoader); + register.RegisterInstance(typeLoader); // 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, UmbracoConfig.For.UmbracoSettings(), UmbracoConfig.For.GlobalSettings(), - new Lazy(container.GetInstance), - new Lazy(container.GetInstance)) + new Lazy(() => _factory.GetInstance()), + new Lazy(() => _factory.GetInstance())) { Level = RuntimeLevel.Boot }; - container.RegisterInstance(_state); + register.RegisterInstance(_state); // create the composition - var composition = new Composition(container, typeLoader, profilingLogger, RuntimeLevel.Boot); + var composition = new Composition(register, typeLoader, profilingLogger, RuntimeLevel.Boot); // register runtime-level services Compose(composition); @@ -121,7 +120,7 @@ namespace Umbraco.Core.Runtime logger.Debug("Runtime: {Runtime}", GetType().FullName); var mainDom = AquireMainDom(); - container.RegisterInstance(mainDom); + register.RegisterInstance(mainDom); DetermineRuntimeLevel(databaseFactory); @@ -130,13 +129,9 @@ namespace Umbraco.Core.Runtime _components.Compose(); - // fixme split Container into Register and Factory - // we should have a Current.Factory not a Current.Container - // we should compile the register into a factory *now* - // using the factory before this point should just throw - IFactory factory = container; + _factory = Current.Factory = register.CreateFactory(); - _components.Initialize(factory); + _components.Initialize(_factory); } catch (Exception e) { @@ -422,7 +417,7 @@ namespace Umbraco.Core.Runtime /// /// This is strictly internal, for tests only. protected internal virtual IUmbracoDatabaseFactory GetDatabaseFactory() - => new UmbracoDatabaseFactory(Logger, new Lazy(_container.GetInstance)); + => new UmbracoDatabaseFactory(Logger, new Lazy(() => _factory.GetInstance())); #endregion } diff --git a/src/Umbraco.Core/RuntimeState.cs b/src/Umbraco.Core/RuntimeState.cs index 4ba75ed89f..e98c67caeb 100644 --- a/src/Umbraco.Core/RuntimeState.cs +++ b/src/Umbraco.Core/RuntimeState.cs @@ -20,16 +20,13 @@ namespace Umbraco.Core private readonly IUmbracoSettingsSection _settings; private readonly IGlobalSettings _globalSettings; private readonly HashSet _applicationUrls = new HashSet(); + private readonly Lazy _mainDom; + private readonly Lazy _serverRegistrar; private RuntimeLevel _level; - private Lazy _mainDom; - private Lazy _serverRegistrar; /// /// Initializes a new instance of the class. /// - /// A logger. - /// Umbraco settings. - /// Global settings. public RuntimeState(ILogger logger, IUmbracoSettingsSection settings, IGlobalSettings globalSettings, Lazy mainDom, Lazy serverRegistrar) { diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 3dfde3b175..bc092271b7 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -177,13 +177,15 @@ - + + - + + diff --git a/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs b/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs index 2c68b1608a..5c2681e184 100644 --- a/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs +++ b/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs @@ -24,12 +24,12 @@ namespace Umbraco.Tests.Cache.DistributedCache [SetUp] public void Setup() { - var container = ContainerFactory.Create(); - Current.Factory = container; - var composition = new Composition(container, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); + var register = RegisterFactory.Create(); + Current.Factory = register.CreateFactory(); // fixme only for LightInject + var composition = new Composition(register, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); - container.Register(_ => new TestServerRegistrar()); - container.RegisterSingleton(_ => new TestServerMessenger()); + register.Register(_ => new TestServerRegistrar()); + register.RegisterSingleton(_ => new TestServerMessenger()); composition.GetCollectionBuilder() .Add(); diff --git a/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs b/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs index 6047b5bb9a..f30c9a36e3 100644 --- a/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs +++ b/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs @@ -5,9 +5,7 @@ using Moq; using NUnit.Framework; using Umbraco.Core.Composing; using Umbraco.Core; -using Umbraco.Core.Cache; using Umbraco.Core.Components; -using Umbraco.Core.Configuration; using Umbraco.Core.Logging; namespace Umbraco.Tests.Composing @@ -15,7 +13,7 @@ namespace Umbraco.Tests.Composing [TestFixture] public class CollectionBuildersTests { - private IContainer _container; + private IRegister _register; private IFactory _factory; private Composition _composition; @@ -24,10 +22,10 @@ namespace Umbraco.Tests.Composing { Current.Reset(); - _container = ContainerFactory.Create(); - _factory = _container; - Current.Factory = _container; - _composition = new Composition(_container, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); + _register = RegisterFactory.Create(); + _factory = _register.CreateFactory(); // fixme only works w/LightInject - would require we reorg tests! + Current.Factory = _factory; + _composition = new Composition(_register, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); } [TearDown] @@ -35,8 +33,8 @@ namespace Umbraco.Tests.Composing { Current.Reset(); - _container.Dispose(); - _container = null; + _register.DisposeIfDisposable(); + _register = null; } [Test] @@ -301,10 +299,10 @@ namespace Umbraco.Tests.Composing // but the container manages the scope, so to test the scope // the collection must come from the container - var col1 = _container.GetInstance(); + var col1 = _factory.GetInstance(); AssertCollection(col1, typeof(Resolved1), typeof(Resolved2)); - var col2 = _container.GetInstance(); + var col2 = _factory.GetInstance(); AssertCollection(col2, typeof(Resolved1), typeof(Resolved2)); AssertSameCollection(col1, col2); @@ -321,10 +319,10 @@ namespace Umbraco.Tests.Composing // but the container manages the scope, so to test the scope // the collection must come from the container - var col1 = _container.GetInstance(); + var col1 = _factory.GetInstance(); AssertCollection(col1, typeof(Resolved1), typeof(Resolved2)); - var col2 = _container.GetInstance(); + var col2 = _factory.GetInstance(); AssertCollection(col1, typeof(Resolved1), typeof(Resolved2)); AssertNotSameCollection(col1, col2); @@ -355,10 +353,10 @@ namespace Umbraco.Tests.Composing TestCollection col1A, col1B; - using (_container.BeginScope()) + using (_factory.BeginScope()) { - col1A = _container.GetInstance(); - col1B = _container.GetInstance(); + col1A = _factory.GetInstance(); + col1B = _factory.GetInstance(); } AssertCollection(col1A, typeof(Resolved1), typeof(Resolved2)); @@ -367,9 +365,9 @@ namespace Umbraco.Tests.Composing TestCollection col2; - using (_container.BeginScope()) + using (_factory.BeginScope()) { - col2 = _container.GetInstance(); + col2 = _factory.GetInstance(); } AssertCollection(col2, typeof(Resolved1), typeof(Resolved2)); diff --git a/src/Umbraco.Tests/Composing/ContainerImplementationTests.cs b/src/Umbraco.Tests/Composing/ContainerImplementationTests.cs index 7b0ac4acf9..6e0fdd0912 100644 --- a/src/Umbraco.Tests/Composing/ContainerImplementationTests.cs +++ b/src/Umbraco.Tests/Composing/ContainerImplementationTests.cs @@ -11,45 +11,49 @@ namespace Umbraco.Tests.Composing [TestFixture] public class ContainerImplementationTests // FIXME merge into ContainerTests or ContainerConformingTests { - private IContainer CreateContainer() => ContainerFactory.Create(); + private IRegister CreateRegister() => RegisterFactory.Create(); [Test] public void CanRegisterSingletonInterface() { - var container = CreateContainer(); - container.RegisterSingleton(); - var s1 = container.GetInstance(); - var s2 = container.GetInstance(); + var register = CreateRegister(); + register.RegisterSingleton(); + var factory = register.CreateFactory(); + var s1 = factory.GetInstance(); + var s2 = factory.GetInstance(); Assert.AreSame(s1, s2); } [Test] public void CanRegisterSingletonClass() { - var container = CreateContainer(); - container.RegisterSingleton(); - var s1 = container.GetInstance(); - var s2 = container.GetInstance(); + var register = CreateRegister(); + register.RegisterSingleton(); + var factory = register.CreateFactory(); + var s1 = factory.GetInstance(); + var s2 = factory.GetInstance(); Assert.AreSame(s1, s2); } [Test] public void CanReRegisterSingletonInterface() { - var container = CreateContainer(); - container.RegisterSingleton(); - container.RegisterSingleton(); - var s = container.GetInstance(); + var register = CreateRegister(); + register.RegisterSingleton(); + register.RegisterSingleton(); + var factory = register.CreateFactory(); + var s = factory.GetInstance(); Assert.IsInstanceOf(s); } [Test] public void CanRegisterSingletonWithCreate() { - var container = CreateContainer(); - container.RegisterSingleton(c => c.CreateInstance(new TestClass1())); - var s1 = container.GetInstance(); - var s2 = container.GetInstance(); + var register = CreateRegister(); + register.RegisterSingleton(c => c.CreateInstance(new TestClass1())); + var factory = register.CreateFactory(); + var s1 = factory.GetInstance(); + var s2 = factory.GetInstance(); Assert.AreSame(s1, s2); } diff --git a/src/Umbraco.Tests/Composing/ContainerTests.cs b/src/Umbraco.Tests/Composing/ContainerTests.cs index 62080ef626..b5be97ce38 100644 --- a/src/Umbraco.Tests/Composing/ContainerTests.cs +++ b/src/Umbraco.Tests/Composing/ContainerTests.cs @@ -12,16 +12,18 @@ namespace Umbraco.Tests.Composing { // tests that a container conforms - private IContainer GetContainer() => LightInjectContainer.Create(); + private IRegister GetRegister() => LightInjectContainer.Create(); [Test] public void CanRegisterAndGet() { - var container = GetContainer(); + var register = GetRegister(); - container.Register(); + register.Register(); - var thing = container.GetInstance(); + var factory = register.CreateFactory(); + + var thing = factory.GetInstance(); Assert.IsNotNull(thing); Assert.IsInstanceOf(thing); } @@ -29,11 +31,13 @@ namespace Umbraco.Tests.Composing [Test] public void CanRegisterAndGetLazy() { - var container = GetContainer(); + var register = GetRegister(); - container.Register(); + register.Register(); - var lazyThing = container.GetInstance>(); + var factory = register.CreateFactory(); + + var lazyThing = factory.GetInstance>(); Assert.IsNotNull(lazyThing); Assert.IsInstanceOf>(lazyThing); var thing = lazyThing.Value; @@ -44,31 +48,37 @@ namespace Umbraco.Tests.Composing [Test] public void CannotRegistedAndGetBase() { - var container = GetContainer(); + var register = GetRegister(); - container.Register(); + register.Register(); - Assert.IsNull(container.TryGetInstance()); + var factory = register.CreateFactory(); + + Assert.IsNull(factory.TryGetInstance()); } [Test] public void CannotRegisterAndGetInterface() { - var container = GetContainer(); + var register = GetRegister(); - container.Register(); + register.Register(); - Assert.IsNull(container.TryGetInstance()); + var factory = register.CreateFactory(); + + Assert.IsNull(factory.TryGetInstance()); } [Test] public void CanRegisterAndGetAllBase() { - var container = GetContainer(); + var register = GetRegister(); - container.Register(); + register.Register(); - var things = container.GetAllInstances(); + var factory = register.CreateFactory(); + + var things = factory.GetAllInstances(); Assert.AreEqual(1, things.Count()); // lightInject: would be zero with option EnableVariance set to false @@ -77,11 +87,13 @@ namespace Umbraco.Tests.Composing [Test] public void CanRegisterAndGetAllInterface() { - var container = GetContainer(); + var register = GetRegister(); - container.Register(); + register.Register(); - var things = container.GetAllInstances(); + var factory = register.CreateFactory(); + + var things = factory.GetAllInstances(); Assert.AreEqual(1, things.Count()); // lightInject: would be zero with option EnableVariance set to false @@ -90,11 +102,13 @@ namespace Umbraco.Tests.Composing [Test] public void CanRegisterBaseAndGet() { - var container = GetContainer(); + var register = GetRegister(); - container.Register(); + register.Register(); - var thing = container.GetInstance(); + var factory = register.CreateFactory(); + + var thing = factory.GetInstance(); Assert.IsNotNull(thing); Assert.IsInstanceOf(thing); } @@ -102,11 +116,13 @@ namespace Umbraco.Tests.Composing [Test] public void CanRegisterInterfaceAndGet() { - var container = GetContainer(); + var register = GetRegister(); - container.Register(); + register.Register(); - var thing = container.GetInstance(); + var factory = register.CreateFactory(); + + var thing = factory.GetInstance(); Assert.IsNotNull(thing); Assert.IsInstanceOf(thing); } @@ -114,21 +130,23 @@ namespace Umbraco.Tests.Composing [Test] public void NonSingletonServiceIsNotUnique() { - var container = GetContainer(); + var register = GetRegister(); - container.Register(); - container.Register(); + register.Register(); + register.Register(); - var things = container.GetInstance>(); + var factory = register.CreateFactory(); + + var things = factory.GetInstance>(); Assert.AreEqual(2, things.Count()); - Assert.IsNull(container.TryGetInstance()); + Assert.IsNull(factory.TryGetInstance()); } [Test] public void SingletonServiceIsUnique() { - var container = GetContainer(); + var register = GetRegister(); // for Core services that ppl may want to redefine in components, // it is important to be able to have a unique, singleton implementation, @@ -136,53 +154,61 @@ namespace Umbraco.Tests.Composing // on each container // redefine the service - container.Register(Lifetime.Singleton); - container.Register(Lifetime.Singleton); + register.Register(Lifetime.Singleton); + register.Register(Lifetime.Singleton); - var things = container.GetInstance>(); + var factory = register.CreateFactory(); + + var things = factory.GetInstance>(); Assert.AreEqual(1, things.Count()); - var thing = container.GetInstance(); + var thing = factory.GetInstance(); Assert.IsInstanceOf(thing); } [Test] public void SingletonImplementationIsNotUnique() { - var container = GetContainer(); + var register = GetRegister(); // define two implementations - container.Register(Lifetime.Singleton); - container.Register(Lifetime.Singleton); + register.Register(Lifetime.Singleton); + register.Register(Lifetime.Singleton); - var things = container.GetInstance>(); + var factory = register.CreateFactory(); + + var things = factory.GetInstance>(); Assert.AreEqual(2, things.Count()); - Assert.IsNull(container.TryGetInstance()); + Assert.IsNull(factory.TryGetInstance()); } [Test] public void CanInjectEnumerableOfBase() { - var container = GetContainer(); + var register = GetRegister(); - container.Register(); - container.Register(); - container.Register(); + register.Register(); + register.Register(); + register.Register(); - var needThings = container.GetInstance(); + var factory = register.CreateFactory(); + + var needThings = factory.GetInstance(); Assert.AreEqual(2, needThings.Things.Count()); } [Test] public void CanGetEnumerableOfBase() { - var container = GetContainer(); + var register = GetRegister(); - container.Register(); - container.Register(); + register.Register(); + register.Register(); - var things = container.GetInstance>(); + var factory = register.CreateFactory(); + + var things = factory.GetInstance>(); Assert.AreEqual(2, things. Count()); } diff --git a/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs b/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs index c39b7d6943..b3009ae90f 100644 --- a/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs +++ b/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs @@ -27,11 +27,9 @@ namespace Umbraco.Tests.Composing Current.Reset(); } - private IContainer CreateContainer() + private IRegister CreateRegister() { - var container = ContainerFactory.Create(); - Current.Factory = container; - return container; + return RegisterFactory.Create(); } // note @@ -41,7 +39,7 @@ namespace Umbraco.Tests.Composing [Test] public void LazyCollectionBuilderHandlesTypes() { - var container = CreateContainer(); + var container = CreateRegister(); var composition = new Composition(container, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); composition.GetCollectionBuilder() @@ -50,13 +48,15 @@ namespace Umbraco.Tests.Composing .Add() .Add(); - var values = container.GetInstance(); + var factory = composition.CreateFactory(); + + var values = factory.GetInstance(); Assert.AreEqual(3, values.Count()); Assert.IsTrue(values.Select(x => x.GetType()) .ContainsAll(new[] { typeof(TransientObject1), typeof(TransientObject2), typeof(TransientObject3) })); - var other = container.GetInstance(); + var other = factory.GetInstance(); Assert.AreNotSame(values, other); // transient var o1 = other.FirstOrDefault(x => x is TransientObject1); Assert.IsFalse(values.Contains(o1)); // transient @@ -65,7 +65,7 @@ namespace Umbraco.Tests.Composing [Test] public void LazyCollectionBuilderHandlesProducers() { - var container = CreateContainer(); + var container = CreateRegister(); var composition = new Composition(container, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); composition.GetCollectionBuilder() @@ -73,13 +73,15 @@ namespace Umbraco.Tests.Composing .Add(() => new[] { typeof(TransientObject3), typeof(TransientObject2) }) .Add(() => new[] { typeof(TransientObject1) }); - var values = container.GetInstance(); + var factory = composition.CreateFactory(); + + var values = factory.GetInstance(); Assert.AreEqual(3, values.Count()); Assert.IsTrue(values.Select(x => x.GetType()) .ContainsAll(new[] { typeof(TransientObject1), typeof(TransientObject2), typeof(TransientObject3) })); - var other = container.GetInstance(); + var other = factory.GetInstance(); Assert.AreNotSame(values, other); // transient var o1 = other.FirstOrDefault(x => x is TransientObject1); Assert.IsFalse(values.Contains(o1)); // transient @@ -88,7 +90,7 @@ namespace Umbraco.Tests.Composing [Test] public void LazyCollectionBuilderHandlesTypesAndProducers() { - var container = CreateContainer(); + var container = CreateRegister(); var composition = new Composition(container, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); composition.GetCollectionBuilder() @@ -97,13 +99,15 @@ namespace Umbraco.Tests.Composing .Add() .Add(() => new[] { typeof(TransientObject1) }); - var values = container.GetInstance(); + var factory = composition.CreateFactory(); + + var values = factory.GetInstance(); Assert.AreEqual(3, values.Count()); Assert.IsTrue(values.Select(x => x.GetType()) .ContainsAll(new[] { typeof(TransientObject1), typeof(TransientObject2), typeof(TransientObject3) })); - var other = container.GetInstance(); + var other = factory.GetInstance(); Assert.AreNotSame(values, other); // transient var o1 = other.FirstOrDefault(x => x is TransientObject1); Assert.IsFalse(values.Contains(o1)); // transient @@ -112,7 +116,7 @@ namespace Umbraco.Tests.Composing [Test] public void LazyCollectionBuilderThrowsOnIllegalTypes() { - var container = CreateContainer(); + var container = CreateRegister(); var composition = new Composition(container, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); composition.GetCollectionBuilder() @@ -124,17 +128,19 @@ namespace Umbraco.Tests.Composing // legal so far... .Add(() => new[] { typeof(TransientObject4) }); + var factory = composition.CreateFactory(); + Assert.Throws(() => { // but throws here when trying to register the types - var values = container.GetInstance(); + var values = factory.GetInstance(); }); } [Test] public void LazyCollectionBuilderCanExcludeTypes() { - var container = CreateContainer(); + var container = CreateRegister(); var composition = new Composition(container, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); composition.GetCollectionBuilder() @@ -142,7 +148,9 @@ namespace Umbraco.Tests.Composing .Add(() => new[] { typeof(TransientObject3), typeof(TransientObject2), typeof(TransientObject1) }) .Exclude(); - var values = container.GetInstance(); + var factory = composition.CreateFactory(); + + var values = factory.GetInstance(); Assert.AreEqual(2, values.Count()); Assert.IsFalse(values.Select(x => x.GetType()) @@ -150,7 +158,7 @@ namespace Umbraco.Tests.Composing Assert.IsTrue(values.Select(x => x.GetType()) .ContainsAll(new[] { typeof(TransientObject1), typeof(TransientObject2) })); - var other = container.GetInstance(); + var other = factory.GetInstance(); Assert.AreNotSame(values, other); // transient var o1 = other.FirstOrDefault(x => x is TransientObject1); Assert.IsFalse(values.Contains(o1)); // transient diff --git a/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs b/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs index c130165d69..1b201f3bc5 100644 --- a/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs +++ b/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs @@ -17,8 +17,8 @@ namespace Umbraco.Tests.Composing [Test] public void PackageActionCollectionBuilderWorks() { - var container = ContainerFactory.Create(); - Current.Factory = container; + var container = RegisterFactory.Create(); + Current.Factory = container.CreateFactory(); // fixme only for LightInject var composition = new Composition(container, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); composition.GetCollectionBuilder() diff --git a/src/Umbraco.Tests/CoreThings/TryConvertToTests.cs b/src/Umbraco.Tests/CoreThings/TryConvertToTests.cs index 2e187d85a5..d997a1bebd 100644 --- a/src/Umbraco.Tests/CoreThings/TryConvertToTests.cs +++ b/src/Umbraco.Tests/CoreThings/TryConvertToTests.cs @@ -18,7 +18,7 @@ namespace Umbraco.Tests.CoreThings var settings = SettingsForTests.GetDefaultUmbracoSettings(); // fixme - base should do it! - Container.RegisterSingleton(_ => new DefaultShortStringHelper(settings)); + Composition.RegisterSingleton(_ => new DefaultShortStringHelper(settings)); } [Test] diff --git a/src/Umbraco.Tests/IO/FileSystemsTests.cs b/src/Umbraco.Tests/IO/FileSystemsTests.cs index cd2d60395f..be1964cd72 100644 --- a/src/Umbraco.Tests/IO/FileSystemsTests.cs +++ b/src/Umbraco.Tests/IO/FileSystemsTests.cs @@ -21,7 +21,8 @@ namespace Umbraco.Tests.IO [TestFixture] public class FileSystemsTests { - private IContainer _container; + private IRegister _register; + private IFactory _factory; [SetUp] public void Setup() @@ -30,17 +31,19 @@ namespace Umbraco.Tests.IO var config = SettingsForTests.GetDefaultUmbracoSettings(); SettingsForTests.ConfigureSettings(config); - _container = ContainerFactory.Create(); - Current.Factory = _container; - var composition = new Composition(_container, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); + _register = RegisterFactory.Create(); - _container.Register(_ => Mock.Of()); - _container.Register(_ => Mock.Of()); - _container.Register(_ => Mock.Of()); - _container.RegisterSingleton(); + var composition = new Composition(_register, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); + + composition.Register(_ => Mock.Of()); + composition.Register(_ => Mock.Of()); + composition.Register(_ => Mock.Of()); + composition.RegisterSingleton(); composition.ComposeFileSystems(); + _factory = composition.CreateFactory(); + // make sure we start clean // because some tests will create corrupt or weird filesystems FileSystems.Reset(); @@ -53,37 +56,37 @@ namespace Umbraco.Tests.IO FileSystems.Reset(); Current.Reset(); - _container.Dispose(); + _register.DisposeIfDisposable(); } - private FileSystems FileSystems => _container.GetInstance(); + private FileSystems FileSystems => _factory.GetInstance(); [Test] public void Can_Get_MediaFileSystem() { - var fileSystem = _container.GetInstance(); + var fileSystem = _factory.GetInstance(); Assert.NotNull(fileSystem); } [Test] public void Can_Get_IMediaFileSystem() { - var fileSystem = _container.GetInstance(); + var fileSystem = _factory.GetInstance(); Assert.NotNull(fileSystem); } [Test] public void IMediaFileSystem_Is_Singleton() { - var fileSystem1 = _container.GetInstance(); - var fileSystem2 = _container.GetInstance(); + var fileSystem1 = _factory.GetInstance(); + var fileSystem2 = _factory.GetInstance(); Assert.AreSame(fileSystem1, fileSystem2); } [Test] public void Can_Delete_MediaFiles() { - var fs = _container.GetInstance(); + var fs = _factory.GetInstance(); var ms = new MemoryStream(Encoding.UTF8.GetBytes("test")); var virtPath = fs.GetMediaPath("file.txt", Guid.NewGuid(), Guid.NewGuid()); fs.AddFile(virtPath, ms); diff --git a/src/Umbraco.Tests/Integration/ContentEventsTests.cs b/src/Umbraco.Tests/Integration/ContentEventsTests.cs index 30dfabbbdc..df7bdb5ccf 100644 --- a/src/Umbraco.Tests/Integration/ContentEventsTests.cs +++ b/src/Umbraco.Tests/Integration/ContentEventsTests.cs @@ -49,8 +49,8 @@ namespace Umbraco.Tests.Integration { base.Compose(); - Container.Register(_ => new TestServerRegistrar()); // localhost-only - Container.RegisterSingleton(); + Composition.Register(_ => new TestServerRegistrar()); // localhost-only + Composition.RegisterSingleton(); Composition.GetCollectionBuilder() .Add() diff --git a/src/Umbraco.Tests/Issues/U9560.cs b/src/Umbraco.Tests/Issues/U9560.cs index 830a1fb84d..e422cbc86b 100644 --- a/src/Umbraco.Tests/Issues/U9560.cs +++ b/src/Umbraco.Tests/Issues/U9560.cs @@ -27,7 +27,7 @@ namespace Umbraco.Tests.Issues var aliasName = string.Empty; // read fields, same as what we do with PetaPoco Fetch - using (var db = Container.GetInstance().CreateDatabase()) + using (var db = Factory.GetInstance().CreateDatabase()) { db.OpenSharedConnection(); try @@ -55,7 +55,7 @@ namespace Umbraco.Tests.Issues Assert.AreEqual("Alias", aliasName); // try differently - using (var db = Container.GetInstance().CreateDatabase()) + using (var db = Factory.GetInstance().CreateDatabase()) { db.OpenSharedConnection(); try diff --git a/src/Umbraco.Tests/Manifest/ManifestParserTests.cs b/src/Umbraco.Tests/Manifest/ManifestParserTests.cs index 948171b0cb..a0cdb2b1bf 100644 --- a/src/Umbraco.Tests/Manifest/ManifestParserTests.cs +++ b/src/Umbraco.Tests/Manifest/ManifestParserTests.cs @@ -12,7 +12,6 @@ using Umbraco.Core.Manifest; using Umbraco.Core.PropertyEditors; using Umbraco.Core.PropertyEditors.Validators; using Umbraco.Core.Services; -using Umbraco.Web.ContentApps; namespace Umbraco.Tests.Manifest { @@ -25,13 +24,13 @@ namespace Umbraco.Tests.Manifest public void Setup() { Current.Reset(); - var container = Mock.Of(); - Current.Factory = container; + var factory = Mock.Of(); + Current.Factory = factory; var serviceContext = new ServiceContext( localizedTextService: Mock.Of()); - Mock.Get(container) + Mock.Get(factory) .Setup(x => x.GetInstance(It.IsAny())) .Returns(x => { diff --git a/src/Umbraco.Tests/Models/ContentTests.cs b/src/Umbraco.Tests/Models/ContentTests.cs index 37f2d4e62d..d30295c662 100644 --- a/src/Umbraco.Tests/Models/ContentTests.cs +++ b/src/Umbraco.Tests/Models/ContentTests.cs @@ -41,11 +41,11 @@ namespace Umbraco.Tests.Models { base.Compose(); - Container.Register(_ => Mock.Of()); + Composition.Register(_ => Mock.Of()); Composition.ComposeFileSystems(); - Container.Register(_ => Mock.Of()); - Container.Register(_ => Mock.Of()); + Composition.Register(_ => Mock.Of()); + Composition.Register(_ => Mock.Of()); } [Test] diff --git a/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs b/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs index 87698db400..4d813b5059 100644 --- a/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs +++ b/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs @@ -24,11 +24,11 @@ namespace Umbraco.Tests.Models.Mapping var manifestBuilder = new ManifestParser( CacheHelper.Disabled.RuntimeCache, new ManifestValueValidatorCollection(Enumerable.Empty()), - Logger) + Composition.Logger) { Path = TestHelper.CurrentAssemblyDirectory }; - Container.Register(_ => manifestBuilder); + Composition.Register(_ => manifestBuilder); Func> typeListProducerList = Enumerable.Empty; Composition.GetCollectionBuilder() @@ -39,7 +39,7 @@ namespace Umbraco.Tests.Models.Mapping [Test] public void AssertConfigurationIsValid() { - var profiles = Container.GetAllInstances().ToArray(); + var profiles = Factory.GetAllInstances().ToArray(); var config = new MapperConfiguration(cfg => { diff --git a/src/Umbraco.Tests/Models/Mapping/ContentTypeModelMappingTests.cs b/src/Umbraco.Tests/Models/Mapping/ContentTypeModelMappingTests.cs index 0d5c9548fd..d272dc9453 100644 --- a/src/Umbraco.Tests/Models/Mapping/ContentTypeModelMappingTests.cs +++ b/src/Umbraco.Tests/Models/Mapping/ContentTypeModelMappingTests.cs @@ -55,13 +55,13 @@ namespace Umbraco.Tests.Models.Mapping var dataEditors = new DataEditorCollection(editors); _editorsMock = new Mock(dataEditors); _editorsMock.Setup(x => x[It.IsAny()]).Returns(editors[0]); - Container.RegisterSingleton(f => _editorsMock.Object); + Composition.RegisterSingleton(f => _editorsMock.Object); - Container.RegisterSingleton(_ => _contentTypeService.Object); - Container.RegisterSingleton(_ => _contentService.Object); - Container.RegisterSingleton(_ => _dataTypeService.Object); - Container.RegisterSingleton(_ => _entityService.Object); - Container.RegisterSingleton(_ => _fileService.Object); + Composition.RegisterSingleton(_ => _contentTypeService.Object); + Composition.RegisterSingleton(_ => _contentService.Object); + Composition.RegisterSingleton(_ => _dataTypeService.Object); + Composition.RegisterSingleton(_ => _entityService.Object); + Composition.RegisterSingleton(_ => _fileService.Object); } [Test] diff --git a/src/Umbraco.Tests/Models/Mapping/ContentWebModelMappingTests.cs b/src/Umbraco.Tests/Models/Mapping/ContentWebModelMappingTests.cs index 03a59584a3..df375aca13 100644 --- a/src/Umbraco.Tests/Models/Mapping/ContentWebModelMappingTests.cs +++ b/src/Umbraco.Tests/Models/Mapping/ContentWebModelMappingTests.cs @@ -26,7 +26,7 @@ namespace Umbraco.Tests.Models.Mapping { base.Compose(); - Container.RegisterSingleton(f => Mock.Of()); + Composition.RegisterSingleton(f => Mock.Of()); } [DataEditor("Test.Test", "Test", "~/Test.html")] diff --git a/src/Umbraco.Tests/Models/VariationTests.cs b/src/Umbraco.Tests/Models/VariationTests.cs index c7bc269e61..3fdd3ee0db 100644 --- a/src/Umbraco.Tests/Models/VariationTests.cs +++ b/src/Umbraco.Tests/Models/VariationTests.cs @@ -26,8 +26,8 @@ namespace Umbraco.Tests.Models // need to be able to retrieve them all... Current.Reset(); - var container = Mock.Of(); - Current.Factory = container; + var factory = Mock.Of(); + Current.Factory = factory; var dataEditors = new DataEditorCollection(new IDataEditor[] { @@ -49,7 +49,7 @@ namespace Umbraco.Tests.Models dataTypeService: dataTypeService, localizedTextService: Mock.Of()); - Mock.Get(container) + Mock.Get(factory) .Setup(x => x.GetInstance(It.IsAny())) .Returns(x => { diff --git a/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs index f9b8281285..ce871d0d0a 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs @@ -20,7 +20,7 @@ namespace Umbraco.Tests.Persistence.Repositories { private IDataTypeRepository CreateRepository() { - return Container.GetInstance(); + return Factory.GetInstance(); } private EntityContainerRepository CreateContainerRepository(IScopeAccessor scopeAccessor) diff --git a/src/Umbraco.Tests/Persistence/Repositories/DictionaryRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DictionaryRepositoryTest.cs index bd66b83677..155ea1905c 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DictionaryRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DictionaryRepositoryTest.cs @@ -24,7 +24,7 @@ namespace Umbraco.Tests.Persistence.Repositories private IDictionaryRepository CreateRepository() { - return Container.GetInstance(); + return Factory.GetInstance(); } [Test] @@ -230,7 +230,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var languageRepository = Container.GetInstance(); + var languageRepository = Factory.GetInstance(); var repository = CreateRepository(); var language = languageRepository.Get(1); diff --git a/src/Umbraco.Tests/Persistence/Repositories/PartialViewRepositoryTests.cs b/src/Umbraco.Tests/Persistence/Repositories/PartialViewRepositoryTests.cs index da9e49876b..8109ffbf56 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/PartialViewRepositoryTests.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/PartialViewRepositoryTests.cs @@ -29,7 +29,7 @@ namespace Umbraco.Tests.Persistence.Repositories { base.Compose(); - Container.RegisterSingleton(f => new DataEditorCollection(Enumerable.Empty())); + Composition.RegisterSingleton(f => new DataEditorCollection(Enumerable.Empty())); } [Test] diff --git a/src/Umbraco.Tests/Persistence/Repositories/ScriptRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ScriptRepositoryTest.cs index 98bccaa313..4a07b3780c 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ScriptRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ScriptRepositoryTest.cs @@ -39,7 +39,7 @@ namespace Umbraco.Tests.Persistence.Repositories { base.Compose(); - Container.RegisterSingleton(f => new DataEditorCollection(Enumerable.Empty())); + Composition.RegisterSingleton(f => new DataEditorCollection(Enumerable.Empty())); } [Test] diff --git a/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs b/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs index 24aa1aaa55..8693f65d4d 100644 --- a/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs +++ b/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs @@ -69,12 +69,13 @@ namespace Umbraco.Tests.PropertyEditors { try { - var container = ContainerFactory.Create(); - Current.Factory = container; + var container = RegisterFactory.Create(); var composition = new Composition(container, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); composition.GetCollectionBuilder(); + Current.Factory = container.CreateFactory(); + var logger = Mock.Of(); var scheme = Mock.Of(); var config = Mock.Of(); diff --git a/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs b/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs index 17ca52ca61..2d2f1e8be7 100644 --- a/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs +++ b/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs @@ -21,11 +21,12 @@ namespace Umbraco.Tests.PropertyEditors //normalize culture Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture; - var container = ContainerFactory.Create(); - Current.Factory = container; + var register = RegisterFactory.Create(); - container.Register(_ + register.Register(_ => new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(SettingsForTests.GetDefaultUmbracoSettings()))); + + Current.Factory = register.CreateFactory(); } [TearDown] diff --git a/src/Umbraco.Tests/Published/ConvertersTests.cs b/src/Umbraco.Tests/Published/ConvertersTests.cs index 2a0aea1e8e..026aee4bb1 100644 --- a/src/Umbraco.Tests/Published/ConvertersTests.cs +++ b/src/Umbraco.Tests/Published/ConvertersTests.cs @@ -174,9 +174,9 @@ namespace Umbraco.Tests.Published public void SimpleConverter3Test() { Current.Reset(); - var container = ContainerFactory.Create(); - Current.Factory = container; - var composition = new Composition(container, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); + var register = RegisterFactory.Create(); + + var composition = new Composition(register, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); composition.GetCollectionBuilder() .Append() @@ -187,7 +187,9 @@ namespace Umbraco.Tests.Published typeof (PublishedSnapshotTestObjects.TestElementModel1), typeof (PublishedSnapshotTestObjects.TestElementModel2), typeof (PublishedSnapshotTestObjects.TestContentModel1), typeof (PublishedSnapshotTestObjects.TestContentModel2), }); - container.Register(f => factory); + register.Register(f => factory); + + Current.Factory = register.CreateFactory(); var cacheMock = new Mock(); var cacheContent = new Dictionary(); @@ -196,7 +198,7 @@ namespace Umbraco.Tests.Published publishedSnapshotMock.Setup(x => x.Content).Returns(cacheMock.Object); var publishedSnapshotAccessorMock = new Mock(); publishedSnapshotAccessorMock.Setup(x => x.PublishedSnapshot).Returns(publishedSnapshotMock.Object); - container.Register(f => publishedSnapshotAccessorMock.Object); + register.Register(f => publishedSnapshotAccessorMock.Object); var converters = Current.Factory.GetInstance(); diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentLanguageVariantTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentLanguageVariantTests.cs index 4b431d18e6..1d9247810f 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentLanguageVariantTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentLanguageVariantTests.cs @@ -23,12 +23,12 @@ namespace Umbraco.Tests.PublishedContent { base.Compose(); - Container.RegisterSingleton(_ => GetServiceContext()); + Composition.RegisterSingleton(_ => GetServiceContext()); } protected ServiceContext GetServiceContext() { - var serviceContext = TestObjects.GetServiceContextMock(Container); + var serviceContext = TestObjects.GetServiceContextMock(Factory); MockLocalizationService(serviceContext); return serviceContext; } diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs index c4f4d5304f..70faf18bf4 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs @@ -39,7 +39,7 @@ namespace Umbraco.Tests.PublishedContent { base.Compose(); - Container.RegisterSingleton(f => new PublishedModelFactory(f.GetInstance().GetTypes())); + Composition.RegisterSingleton(f => new PublishedModelFactory(f.GetInstance().GetTypes())); } protected override TypeLoader CreateTypeLoader(IRuntimeCacheProvider runtimeCache, IGlobalSettings globalSettings, IProfilingLogger logger) diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs index 80fb02ec0f..1c66f5a6d3 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs @@ -34,7 +34,7 @@ namespace Umbraco.Tests.PublishedContent { base.Initialize(); - var converters = Container.GetInstance(); + var converters = Factory.GetInstance(); var dataTypeService = new TestObjects.TestDataTypeService( new DataType(new RichTextPropertyEditor(Mock.Of())) { Id = 1 }); diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs index 9b3ceb21d1..b347f0d676 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs @@ -33,9 +33,9 @@ namespace Umbraco.Tests.PublishedContent { base.Compose(); - Container.RegisterSingleton(f => new PublishedModelFactory(f.GetInstance().GetTypes())); - Container.RegisterSingleton(); - Container.RegisterSingleton(); + Composition.RegisterSingleton(f => new PublishedModelFactory(f.GetInstance().GetTypes())); + Composition.RegisterSingleton(); + Composition.RegisterSingleton(); var logger = Mock.Of(); var dataTypeService = new TestObjects.TestDataTypeService( @@ -45,14 +45,14 @@ namespace Umbraco.Tests.PublishedContent new DataType(new IntegerPropertyEditor(logger)) { Id = 1003 }, new DataType(new TextboxPropertyEditor(logger)) { Id = 1004 }, new DataType(new MediaPickerPropertyEditor(logger)) { Id = 1005 }); - Container.RegisterSingleton(f => dataTypeService); + Composition.RegisterSingleton(f => dataTypeService); } protected override void Initialize() { base.Initialize(); - var factory = Container.GetInstance() as PublishedContentTypeFactory; + var factory = Factory.GetInstance() as PublishedContentTypeFactory; // need to specify a custom callback for unit tests // AutoPublishedContentTypes generates properties automatically @@ -818,7 +818,7 @@ namespace Umbraco.Tests.PublishedContent [Test] public void FragmentProperty() { - var factory = Container.GetInstance() as PublishedContentTypeFactory; + var factory = Factory.GetInstance() as PublishedContentTypeFactory; var pt = factory.CreatePropertyType("detached", 1003); var ct = factory.CreateContentType(0, "alias", new[] { pt }); @@ -837,7 +837,7 @@ namespace Umbraco.Tests.PublishedContent [Test] public void Fragment2() { - var factory = Container.GetInstance() as PublishedContentTypeFactory; + var factory = Factory.GetInstance() as PublishedContentTypeFactory; var pt1 = factory.CreatePropertyType("legend", 1004); var pt2 = factory.CreatePropertyType("image", 1005); diff --git a/src/Umbraco.Tests/Routing/ContentFinderByIdTests.cs b/src/Umbraco.Tests/Routing/ContentFinderByIdTests.cs index 0708287160..72848753e5 100644 --- a/src/Umbraco.Tests/Routing/ContentFinderByIdTests.cs +++ b/src/Umbraco.Tests/Routing/ContentFinderByIdTests.cs @@ -18,7 +18,7 @@ namespace Umbraco.Tests.Routing var umbracoContext = GetUmbracoContext(urlAsString); var publishedRouter = CreatePublishedRouter(); var frequest = publishedRouter.CreateRequest(umbracoContext); - var lookup = new ContentFinderByIdPath(Container.GetInstance().WebRouting, Logger); + var lookup = new ContentFinderByIdPath(Factory.GetInstance().WebRouting, Logger); var result = lookup.TryFindContent(frequest); diff --git a/src/Umbraco.Tests/Routing/ContentFinderByUrlWithDomainsTests.cs b/src/Umbraco.Tests/Routing/ContentFinderByUrlWithDomainsTests.cs index 5787d3e613..92aed90168 100644 --- a/src/Umbraco.Tests/Routing/ContentFinderByUrlWithDomainsTests.cs +++ b/src/Umbraco.Tests/Routing/ContentFinderByUrlWithDomainsTests.cs @@ -129,7 +129,7 @@ namespace Umbraco.Tests.Routing SettingsForTests.ConfigureSettings(globalSettingsMock.Object); var umbracoContext = GetUmbracoContext(url, globalSettings:globalSettingsMock.Object); - var publishedRouter = CreatePublishedRouter(Container); + var publishedRouter = CreatePublishedRouter(Factory); var frequest = publishedRouter.CreateRequest(umbracoContext); // must lookup domain else lookup by url fails @@ -172,7 +172,7 @@ namespace Umbraco.Tests.Routing SettingsForTests.ConfigureSettings(globalSettingsMock.Object); var umbracoContext = GetUmbracoContext(url, globalSettings:globalSettingsMock.Object); - var publishedRouter = CreatePublishedRouter(Container); + var publishedRouter = CreatePublishedRouter(Factory); var frequest = publishedRouter.CreateRequest(umbracoContext); // must lookup domain else lookup by url fails diff --git a/src/Umbraco.Tests/Routing/DomainsAndCulturesTests.cs b/src/Umbraco.Tests/Routing/DomainsAndCulturesTests.cs index df18ec0966..471fa27f82 100644 --- a/src/Umbraco.Tests/Routing/DomainsAndCulturesTests.cs +++ b/src/Umbraco.Tests/Routing/DomainsAndCulturesTests.cs @@ -15,7 +15,7 @@ namespace Umbraco.Tests.Routing { base.Compose(); - Container.Register(); + Composition.Register(); } private void SetDomains1() @@ -270,7 +270,7 @@ namespace Umbraco.Tests.Routing SettingsForTests.ConfigureSettings(globalSettings.Object); var umbracoContext = GetUmbracoContext(inputUrl, globalSettings:globalSettings.Object); - var publishedRouter = CreatePublishedRouter(Container); + var publishedRouter = CreatePublishedRouter(Factory); var frequest = publishedRouter.CreateRequest(umbracoContext); // lookup domain @@ -320,7 +320,7 @@ namespace Umbraco.Tests.Routing SettingsForTests.ConfigureSettings(globalSettings.Object); var umbracoContext = GetUmbracoContext(inputUrl, globalSettings:globalSettings.Object); - var publishedRouter = CreatePublishedRouter(Container); + var publishedRouter = CreatePublishedRouter(Factory); var frequest = publishedRouter.CreateRequest(umbracoContext); // lookup domain @@ -375,7 +375,7 @@ namespace Umbraco.Tests.Routing globalSettings.Setup(x => x.HideTopLevelNodeFromPath).Returns(false); SettingsForTests.ConfigureSettings(globalSettings.Object); var umbracoContext = GetUmbracoContext(inputUrl, globalSettings:globalSettings.Object); - var publishedRouter = CreatePublishedRouter(Container); + var publishedRouter = CreatePublishedRouter(Factory); var frequest = publishedRouter.CreateRequest(umbracoContext); // lookup domain diff --git a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs index 0bb12ebda5..949031cc65 100644 --- a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs +++ b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs @@ -48,7 +48,7 @@ namespace Umbraco.Tests.Routing : base(umbracoApplication) { } - public override void Boot(IContainer container) + public override void Boot(IRegister container) { // do it before anything else - this is the only place where it's possible var logger = Mock.Of(); @@ -68,13 +68,13 @@ namespace Umbraco.Tests.Routing // set the default RenderMvcController Current.DefaultRenderMvcControllerType = typeof(RenderMvcController); // fixme WRONG! - var surfaceControllerTypes = new SurfaceControllerTypeCollection(Current.TypeLoader.GetSurfaceControllers()); - Container.RegisterInstance(surfaceControllerTypes); + var surfaceControllerTypes = new SurfaceControllerTypeCollection(Composition.TypeLoader.GetSurfaceControllers()); + Composition.RegisterInstance(surfaceControllerTypes); - var umbracoApiControllerTypes = new UmbracoApiControllerTypeCollection(Current.TypeLoader.GetUmbracoApiControllers()); - Container.RegisterInstance(umbracoApiControllerTypes); + var umbracoApiControllerTypes = new UmbracoApiControllerTypeCollection(Composition.TypeLoader.GetUmbracoApiControllers()); + Composition.RegisterInstance(umbracoApiControllerTypes); - Container.RegisterSingleton(_ => new DefaultShortStringHelper(SettingsForTests.GetDefaultUmbracoSettings())); + Composition.RegisterSingleton(_ => new DefaultShortStringHelper(SettingsForTests.GetDefaultUmbracoSettings())); } public override void TearDown() diff --git a/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs b/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs index 7fef0147e7..7dea5bc4e9 100644 --- a/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs +++ b/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs @@ -39,8 +39,8 @@ namespace Umbraco.Tests.Routing ( globalSettings, Mock.Of(), - Container.GetInstance(), - Container.GetInstance(), + Factory.GetInstance(), + Factory.GetInstance(), new UrlProviderCollection(new IUrlProvider[0]), runtime, logger, diff --git a/src/Umbraco.Tests/Routing/UrlProviderTests.cs b/src/Umbraco.Tests/Routing/UrlProviderTests.cs index daac1492e4..6f29a312ae 100644 --- a/src/Umbraco.Tests/Routing/UrlProviderTests.cs +++ b/src/Umbraco.Tests/Routing/UrlProviderTests.cs @@ -25,7 +25,7 @@ namespace Umbraco.Tests.Routing protected override void Compose() { base.Compose(); - Container.Register(); + Composition.Register(); } private IUmbracoSettingsSection _umbracoSettings; diff --git a/src/Umbraco.Tests/Routing/UrlRoutingTestBase.cs b/src/Umbraco.Tests/Routing/UrlRoutingTestBase.cs index 663daf3083..100e814c83 100644 --- a/src/Umbraco.Tests/Routing/UrlRoutingTestBase.cs +++ b/src/Umbraco.Tests/Routing/UrlRoutingTestBase.cs @@ -34,13 +34,13 @@ namespace Umbraco.Tests.Routing { base.Compose(); - Container.RegisterSingleton(_ => GetServiceContext()); + Composition.RegisterSingleton(_ => GetServiceContext()); } protected ServiceContext GetServiceContext() { // get the mocked service context to get the mocked domain service - var serviceContext = TestObjects.GetServiceContextMock(Container); + var serviceContext = TestObjects.GetServiceContextMock(Factory); //setup mock domain service var domainService = Mock.Get(serviceContext.DomainService); diff --git a/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs b/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs index 7ef0f69dda..4ff732db01 100644 --- a/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs +++ b/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs @@ -20,8 +20,8 @@ namespace Umbraco.Tests.Routing { base.Compose(); - Container.RegisterSingleton(_ => Mock.Of()); - Container.Register(); + Composition.RegisterSingleton(_ => Mock.Of()); + Composition.Register(); } void SetDomains1() diff --git a/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs b/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs index dda9005506..e2c55b1003 100644 --- a/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs +++ b/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs @@ -22,8 +22,8 @@ namespace Umbraco.Tests.Routing protected override void Compose() { base.Compose(); - Container.RegisterSingleton(_ => Mock.Of()); - Container.Register(); + Composition.RegisterSingleton(_ => Mock.Of()); + Composition.Register(); } [Test] diff --git a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs index ceac7127f2..092ed54a35 100644 --- a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs +++ b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs @@ -136,10 +136,10 @@ namespace Umbraco.Tests.Runtimes private MainDom _mainDom; - public override void Boot(IContainer container) + public override void Boot(IRegister container) { base.Boot(container); - _mainDom = container.GetInstance(); + _mainDom = Current.Factory.GetInstance(); } public override void Terminate() diff --git a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs index fa1d0482cf..04703e3195 100644 --- a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs @@ -32,15 +32,17 @@ namespace Umbraco.Tests.Scoping DoThing2 = null; DoThing3 = null; - var container = ContainerFactory.Create(); - Current.Factory = container; - var composition = new Composition(container, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); + var register = RegisterFactory.Create(); - _testObjects = new TestObjects(container); + var composition = new Composition(register, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); - container.RegisterSingleton(factory => new FileSystems(container, factory.TryGetInstance())); + _testObjects = new TestObjects(register); + + register.RegisterSingleton(factory => new FileSystems(factory, factory.TryGetInstance())); composition.GetCollectionBuilder(); + Current.Factory = register.CreateFactory(); + SettingsForTests.Reset(); // ensure we have configuration } diff --git a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs index ada58942c3..50d0f42626 100644 --- a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs @@ -44,8 +44,8 @@ namespace Umbraco.Tests.Scoping // but then, it requires a lot of plumbing ;( // fixme - and we cannot inject a DistributedCache yet // so doing all this mess - Container.RegisterSingleton(); - Container.RegisterSingleton(f => Mock.Of()); + Composition.RegisterSingleton(); + Composition.RegisterSingleton(f => Mock.Of()); Composition.GetCollectionBuilder() .Add(() => Composition.TypeLoader.GetCacheRefreshers()); } @@ -94,7 +94,7 @@ namespace Umbraco.Tests.Scoping documentRepository, mediaRepository, memberRepository, DefaultCultureAccessor, new DatabaseDataSource(), - Container.GetInstance(), new SiteDomainHelper()); + Factory.GetInstance(), new SiteDomainHelper()); } protected UmbracoContext GetUmbracoContextNu(string url, int templateId = 1234, RouteData routeData = null, bool setSingleton = false, IUmbracoSettingsSection umbracoSettings = null, IEnumerable urlProviders = null) diff --git a/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs b/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs index a4040ca019..b00dfbaa03 100644 --- a/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs @@ -30,8 +30,8 @@ namespace Umbraco.Tests.Scoping // but then, it requires a lot of plumbing ;( // fixme - and we cannot inject a DistributedCache yet // so doing all this mess - Container.RegisterSingleton(); - Container.RegisterSingleton(f => Mock.Of()); + Composition.RegisterSingleton(); + Composition.RegisterSingleton(f => Mock.Of()); Composition.GetCollectionBuilder() .Add(() => Composition.TypeLoader.GetCacheRefreshers()); } diff --git a/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs b/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs index 9c98dcd538..c829643964 100644 --- a/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs @@ -32,8 +32,8 @@ namespace Umbraco.Tests.Scoping // but then, it requires a lot of plumbing ;( // fixme - and we cannot inject a DistributedCache yet // so doing all this mess - Container.RegisterSingleton(); - Container.RegisterSingleton(f => Mock.Of()); + Composition.RegisterSingleton(); + Composition.RegisterSingleton(f => Mock.Of()); Composition.GetCollectionBuilder() .Add(() => Composition.TypeLoader.GetCacheRefreshers()); } diff --git a/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs b/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs index ce673bcd47..cc2baafffc 100644 --- a/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs +++ b/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs @@ -36,7 +36,7 @@ namespace Umbraco.Tests.Services protected override void Compose() { base.Compose(); - Container.Register(); + Composition.Register(); } [Test] diff --git a/src/Umbraco.Tests/Services/ContentServiceTests.cs b/src/Umbraco.Tests/Services/ContentServiceTests.cs index 31f0f0308b..9b33b1d30d 100644 --- a/src/Umbraco.Tests/Services/ContentServiceTests.cs +++ b/src/Umbraco.Tests/Services/ContentServiceTests.cs @@ -57,7 +57,7 @@ namespace Umbraco.Tests.Services { base.Compose(); - Container.RegisterSingleton(factory => Mock.Of()); + Composition.RegisterSingleton(factory => Mock.Of()); } /// diff --git a/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs b/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs index 5b3d2f2583..17c31ca409 100644 --- a/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs +++ b/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs @@ -35,8 +35,8 @@ namespace Umbraco.Tests.Services base.Compose(); // pfew - see note in ScopedNuCacheTests? - Container.RegisterSingleton(); - Container.RegisterSingleton(f => Mock.Of()); + Composition.RegisterSingleton(); + Composition.RegisterSingleton(f => Mock.Of()); Composition.GetCollectionBuilder() .Add(() => Composition.TypeLoader.GetCacheRefreshers()); } @@ -50,7 +50,7 @@ namespace Umbraco.Tests.Services var contentTypeFactory = new PublishedContentTypeFactory(Mock.Of(), new PropertyValueConverterCollection(Array.Empty()), Mock.Of()); //var documentRepository = Mock.Of(); - var documentRepository = Container.GetInstance(); + var documentRepository = Factory.GetInstance(); var mediaRepository = Mock.Of(); var memberRepository = Mock.Of(); @@ -68,7 +68,7 @@ namespace Umbraco.Tests.Services documentRepository, mediaRepository, memberRepository, DefaultCultureAccessor, new DatabaseDataSource(), - Container.GetInstance(), new SiteDomainHelper()); + Factory.GetInstance(), new SiteDomainHelper()); } public class LocalServerMessenger : ServerMessengerBase diff --git a/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs b/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs index 5e8acf03bd..b64b4dbf16 100644 --- a/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs +++ b/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs @@ -69,7 +69,7 @@ namespace Umbraco.Tests.Strings })); // fixme - move to a "compose" thing? - Container.RegisterSingleton(f => _helper); + Composition.RegisterSingleton(f => _helper); } private static readonly Regex FrenchElisionsRegex = new Regex("\\b(c|d|j|l|m|n|qu|s|t)('|\u8217)", RegexOptions.Compiled | RegexOptions.IgnoreCase); diff --git a/src/Umbraco.Tests/Strings/StringExtensionsTests.cs b/src/Umbraco.Tests/Strings/StringExtensionsTests.cs index 81dec809c8..bcb6f0d60d 100644 --- a/src/Umbraco.Tests/Strings/StringExtensionsTests.cs +++ b/src/Umbraco.Tests/Strings/StringExtensionsTests.cs @@ -22,7 +22,7 @@ namespace Umbraco.Tests.Strings base.SetUp(); // fixme - in "compose"? - Container.RegisterSingleton(_ => new MockShortStringHelper()); + Composition.RegisterSingleton(_ => new MockShortStringHelper()); } [Test] diff --git a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs index 09ce5fb916..846fcfac5d 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs @@ -34,12 +34,12 @@ namespace Umbraco.Tests.TestHelpers var sqlSyntax = new SqlCeSyntaxProvider(); - var container = ContainerFactory.Create(); - Current.Factory = container; + var container = RegisterFactory.Create(); + var composition = new Composition(container, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); - container.RegisterSingleton(factory => Mock.Of()); - container.RegisterSingleton(factory => Mock.Of()); + container.RegisterSingleton(_ => Mock.Of()); + container.RegisterSingleton(_ => Mock.Of()); var logger = new ProfilingLogger(Mock.Of(), Mock.Of()); var pluginManager = new TypeLoader(NullCacheProvider.Instance, @@ -50,7 +50,10 @@ namespace Umbraco.Tests.TestHelpers composition.GetCollectionBuilder() .Add(() => Current.TypeLoader.GetAssignedMapperTypes()); - Mappers = container.GetInstance(); + + var factory = Current.Factory = container.CreateFactory(); + + Mappers = factory.GetInstance(); var pocoMappers = new NPoco.MapperCollection { new PocoMapper() }; var pocoDataFactory = new FluentPocoDataFactory((type, iPocoDataFactory) => new PocoDataBuilder(type, pocoMappers).Init()); diff --git a/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs b/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs index b1e9257918..832bbd141d 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs @@ -27,8 +27,8 @@ namespace Umbraco.Tests.TestHelpers { base.Compose(); - Container.RegisterSingleton(); - Container.RegisterSingleton(); + Composition.RegisterSingleton(); + Composition.RegisterSingleton(); } protected override void Initialize() diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects.cs b/src/Umbraco.Tests/TestHelpers/TestObjects.cs index 02e77ae1a5..13f85549f1 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects.cs @@ -30,11 +30,11 @@ namespace Umbraco.Tests.TestHelpers /// internal partial class TestObjects { - private readonly IContainer _container; + private readonly IRegister _register; - public TestObjects(IContainer container) + public TestObjects(IRegister register) { - _container = container; + _register = register; } /// @@ -67,7 +67,7 @@ namespace Umbraco.Tests.TestHelpers return new UmbracoDatabase(connection, sqlContext, logger); } - public void RegisterServices(IContainer container) + public void RegisterServices(IRegister register) { } /// @@ -93,7 +93,7 @@ namespace Umbraco.Tests.TestHelpers IEventMessagesFactory eventMessagesFactory, IEnumerable urlSegmentProviders, TypeLoader typeLoader, - IContainer container = null) + IFactory factory = null) { if (scopeProvider == null) throw new ArgumentNullException(nameof(scopeProvider)); if (scopeAccessor == null) throw new ArgumentNullException(nameof(scopeAccessor)); @@ -106,12 +106,12 @@ namespace Umbraco.Tests.TestHelpers var mediaFileSystem = new MediaFileSystem(Mock.Of(), config, scheme, logger); - var externalLoginService = GetLazyService(container, c => new ExternalLoginService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); - var publicAccessService = GetLazyService(container, c => new PublicAccessService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); - var domainService = GetLazyService(container, c => new DomainService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); - var auditService = GetLazyService(container, c => new AuditService(scopeProvider, logger, eventMessagesFactory, GetRepo(c), GetRepo(c))); + var externalLoginService = GetLazyService(factory, c => new ExternalLoginService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); + var publicAccessService = GetLazyService(factory, c => new PublicAccessService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); + var domainService = GetLazyService(factory, c => new DomainService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); + var auditService = GetLazyService(factory, c => new AuditService(scopeProvider, logger, eventMessagesFactory, GetRepo(c), GetRepo(c))); - var localizedTextService = GetLazyService(container, c => new LocalizedTextService( + var localizedTextService = GetLazyService(factory, c => new LocalizedTextService( new Lazy(() => { var mainLangFolder = new DirectoryInfo(IOHelper.MapPath(SystemDirectories.Umbraco + "/config/lang/")); @@ -146,34 +146,34 @@ namespace Umbraco.Tests.TestHelpers var runtimeState = Mock.Of(); var idkMap = new IdkMap(scopeProvider); - var localizationService = GetLazyService(container, c => new LocalizationService(scopeProvider, logger, eventMessagesFactory, GetRepo(c), GetRepo(c), GetRepo(c))); - var userService = GetLazyService(container, c => new UserService(scopeProvider, logger, eventMessagesFactory, runtimeState, GetRepo(c), GetRepo(c),globalSettings)); - var dataTypeService = GetLazyService(container, c => new DataTypeService(scopeProvider, logger, eventMessagesFactory, GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c))); - var contentService = GetLazyService(container, c => new ContentService(scopeProvider, logger, eventMessagesFactory, mediaFileSystem, GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c))); - var notificationService = GetLazyService(container, c => new NotificationService(scopeProvider, userService.Value, contentService.Value, localizationService.Value, logger, GetRepo(c), globalSettings, umbracoSettings.Content)); - var serverRegistrationService = GetLazyService(container, c => new ServerRegistrationService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); - var memberGroupService = GetLazyService(container, c => new MemberGroupService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); - var memberService = GetLazyService(container, c => new MemberService(scopeProvider, logger, eventMessagesFactory, memberGroupService.Value, mediaFileSystem, GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c))); - var mediaService = GetLazyService(container, c => new MediaService(scopeProvider, mediaFileSystem, logger, eventMessagesFactory, GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c))); - var contentTypeService = GetLazyService(container, c => new ContentTypeService(scopeProvider, logger, eventMessagesFactory, contentService.Value, GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c))); - var mediaTypeService = GetLazyService(container, c => new MediaTypeService(scopeProvider, logger, eventMessagesFactory, mediaService.Value, GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c))); - var fileService = GetLazyService(container, c => new FileService(scopeProvider, logger, eventMessagesFactory, GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c))); + var localizationService = GetLazyService(factory, c => new LocalizationService(scopeProvider, logger, eventMessagesFactory, GetRepo(c), GetRepo(c), GetRepo(c))); + var userService = GetLazyService(factory, c => new UserService(scopeProvider, logger, eventMessagesFactory, runtimeState, GetRepo(c), GetRepo(c),globalSettings)); + var dataTypeService = GetLazyService(factory, c => new DataTypeService(scopeProvider, logger, eventMessagesFactory, GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c))); + var contentService = GetLazyService(factory, c => new ContentService(scopeProvider, logger, eventMessagesFactory, mediaFileSystem, GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c))); + var notificationService = GetLazyService(factory, c => new NotificationService(scopeProvider, userService.Value, contentService.Value, localizationService.Value, logger, GetRepo(c), globalSettings, umbracoSettings.Content)); + var serverRegistrationService = GetLazyService(factory, c => new ServerRegistrationService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); + var memberGroupService = GetLazyService(factory, c => new MemberGroupService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); + var memberService = GetLazyService(factory, c => new MemberService(scopeProvider, logger, eventMessagesFactory, memberGroupService.Value, mediaFileSystem, GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c))); + var mediaService = GetLazyService(factory, c => new MediaService(scopeProvider, mediaFileSystem, logger, eventMessagesFactory, GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c))); + var contentTypeService = GetLazyService(factory, c => new ContentTypeService(scopeProvider, logger, eventMessagesFactory, contentService.Value, GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c))); + var mediaTypeService = GetLazyService(factory, c => new MediaTypeService(scopeProvider, logger, eventMessagesFactory, mediaService.Value, GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c))); + var fileService = GetLazyService(factory, c => new FileService(scopeProvider, logger, eventMessagesFactory, GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c))); - var memberTypeService = GetLazyService(container, c => new MemberTypeService(scopeProvider, logger, eventMessagesFactory, memberService.Value, GetRepo(c), GetRepo(c), GetRepo(c))); - var entityService = GetLazyService(container, c => new EntityService( + var memberTypeService = GetLazyService(factory, c => new MemberTypeService(scopeProvider, logger, eventMessagesFactory, memberService.Value, GetRepo(c), GetRepo(c), GetRepo(c))); + var entityService = GetLazyService(factory, c => new EntityService( scopeProvider, logger, eventMessagesFactory, contentService.Value, contentTypeService.Value, mediaService.Value, mediaTypeService.Value, dataTypeService.Value, memberService.Value, memberTypeService.Value, idkMap, GetRepo(c))); - var macroService = GetLazyService(container, c => new MacroService(scopeProvider, logger, eventMessagesFactory, GetRepo(c), GetRepo(c))); - var packagingService = GetLazyService(container, c => new PackagingService(logger, contentService.Value, contentTypeService.Value, mediaService.Value, macroService.Value, dataTypeService.Value, fileService.Value, localizationService.Value, entityService.Value, userService.Value, scopeProvider, urlSegmentProviders, GetRepo(c), GetRepo(c), new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty())))); - var relationService = GetLazyService(container, c => new RelationService(scopeProvider, logger, eventMessagesFactory, entityService.Value, GetRepo(c), GetRepo(c))); - var treeService = GetLazyService(container, c => new ApplicationTreeService(logger, cache, typeLoader)); - var tagService = GetLazyService(container, c => new TagService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); - var sectionService = GetLazyService(container, c => new SectionService(userService.Value, treeService.Value, scopeProvider, cache)); - var redirectUrlService = GetLazyService(container, c => new RedirectUrlService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); - var consentService = GetLazyService(container, c => new ConsentService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); + var macroService = GetLazyService(factory, c => new MacroService(scopeProvider, logger, eventMessagesFactory, GetRepo(c), GetRepo(c))); + var packagingService = GetLazyService(factory, c => new PackagingService(logger, contentService.Value, contentTypeService.Value, mediaService.Value, macroService.Value, dataTypeService.Value, fileService.Value, localizationService.Value, entityService.Value, userService.Value, scopeProvider, urlSegmentProviders, GetRepo(c), GetRepo(c), new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty())))); + var relationService = GetLazyService(factory, c => new RelationService(scopeProvider, logger, eventMessagesFactory, entityService.Value, GetRepo(c), GetRepo(c))); + var treeService = GetLazyService(factory, c => new ApplicationTreeService(logger, cache, typeLoader)); + var tagService = GetLazyService(factory, c => new TagService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); + var sectionService = GetLazyService(factory, c => new SectionService(userService.Value, treeService.Value, scopeProvider, cache)); + var redirectUrlService = GetLazyService(factory, c => new RedirectUrlService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); + var consentService = GetLazyService(factory, c => new ConsentService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); return new ServiceContext( publicAccessService, diff --git a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs index 8128666898..cc3ddb6f6a 100644 --- a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs +++ b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs @@ -58,7 +58,7 @@ namespace Umbraco.Tests.TestHelpers internal ScopeProvider ScopeProvider => Current.ScopeProvider as ScopeProvider; - protected ISqlContext SqlContext => Container.GetInstance(); + protected ISqlContext SqlContext => Factory.GetInstance(); public override void SetUp() { @@ -72,15 +72,15 @@ namespace Umbraco.Tests.TestHelpers { base.Compose(); - Container.Register(); - Container.Register(factory => PublishedSnapshotService); - Container.Register(factory => DefaultCultureAccessor); + Composition.Register(); + Composition.Register(factory => PublishedSnapshotService); + Composition.Register(factory => DefaultCultureAccessor); Composition.GetCollectionBuilder() .Clear() .Add(() => Composition.TypeLoader.GetDataEditors()); - Container.RegisterSingleton(f => + Composition.RegisterSingleton(f => { if (Options.Database == UmbracoTestOptions.Database.None) return TestObjects.GetDatabaseFactoryMock(); @@ -101,7 +101,7 @@ namespace Umbraco.Tests.TestHelpers public override void TearDown() { - var profilingLogger = Container.TryGetInstance(); + var profilingLogger = Factory.TryGetInstance(); var timer = profilingLogger?.TraceDuration("teardown"); // fixme move that one up try { @@ -250,10 +250,10 @@ namespace Umbraco.Tests.TestHelpers var cache = NullCacheProvider.Instance; ContentTypesCache = new PublishedContentTypeCache( - Container.GetInstance(), - Container.GetInstance(), - Container.GetInstance(), - Container.GetInstance(), + Factory.GetInstance(), + Factory.GetInstance(), + Factory.GetInstance(), + Factory.GetInstance(), Logger); // testing=true so XmlStore will not use the file nor the database @@ -262,13 +262,13 @@ namespace Umbraco.Tests.TestHelpers var variationContextAccessor = new TestVariationContextAccessor(); var service = new PublishedSnapshotService( ServiceContext, - Container.GetInstance(), + Factory.GetInstance(), ScopeProvider, cache, publishedSnapshotAccessor, variationContextAccessor, - Container.GetInstance(), Container.GetInstance(), Container.GetInstance(), + Factory.GetInstance(), Factory.GetInstance(), Factory.GetInstance(), DefaultCultureAccessor, Logger, - Container.GetInstance(), new SiteDomainHelper(), + Factory.GetInstance(), new SiteDomainHelper(), ContentTypesCache, null, true, Options.PublishedRepositoryEvents); @@ -369,11 +369,11 @@ namespace Umbraco.Tests.TestHelpers var umbracoContext = new UmbracoContext( httpContext, service, - new WebSecurity(httpContext, Container.GetInstance(), - Container.GetInstance()), - umbracoSettings ?? Container.GetInstance(), + new WebSecurity(httpContext, Factory.GetInstance(), + Factory.GetInstance()), + umbracoSettings ?? Factory.GetInstance(), urlProviders ?? Enumerable.Empty(), - globalSettings ?? Container.GetInstance(), + globalSettings ?? Factory.GetInstance(), new TestVariationContextAccessor()); if (setSingleton) diff --git a/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs b/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs index 1c4df69e54..5ffab2c3b3 100644 --- a/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs +++ b/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs @@ -53,11 +53,11 @@ namespace Umbraco.Tests.Testing.TestingTests var umbracoContext = TestObjects.GetUmbracoContextMock(); // unless we can inject them in MembershipHelper, we need need this - Container.Register(_ => Mock.Of()); - Container.Register(_ => Mock.Of()); - Container.Register(_ => Mock.Of()); - Container.Register(_ => CacheHelper.Disabled); - Container.Register(); + Composition.Register(_ => Mock.Of()); + Composition.Register(_ => Mock.Of()); + Composition.Register(_ => Mock.Of()); + Composition.Register(_ => CacheHelper.Disabled); + Composition.Register(); // ReSharper disable once UnusedVariable var helper = new UmbracoHelper(umbracoContext, diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index d81d71511c..37c5853c36 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -78,7 +78,7 @@ namespace Umbraco.Tests.Testing protected Composition Composition { get; private set; } - protected IContainer Container { get; private set; } + protected IFactory Factory { get; private set; } protected UmbracoTestAttribute Options { get; private set; } @@ -94,17 +94,17 @@ namespace Umbraco.Tests.Testing #region Accessors - protected ILogger Logger => Container.GetInstance(); + protected ILogger Logger => Factory.GetInstance(); - protected IProfiler Profiler => Container.GetInstance(); + protected IProfiler Profiler => Factory.GetInstance(); - protected virtual IProfilingLogger ProfilingLogger => Container.GetInstance(); + protected virtual IProfilingLogger ProfilingLogger => Factory.GetInstance(); - protected CacheHelper CacheHelper => Container.GetInstance(); + protected CacheHelper CacheHelper => Factory.GetInstance(); - protected virtual ISqlSyntaxProvider SqlSyntax => Container.GetInstance(); + protected virtual ISqlSyntaxProvider SqlSyntax => Factory.GetInstance(); - protected IMapperCollection Mappers => Container.GetInstance(); + protected IMapperCollection Mappers => Factory.GetInstance(); #endregion @@ -127,19 +127,19 @@ namespace Umbraco.Tests.Testing var globalSettings = SettingsForTests.GetDefaultGlobalSettings(); var typeLoader = GetTypeLoader(cacheHelper.RuntimeCache, globalSettings, proflogger, Options.TypeLoader); - Container = ContainerFactory.Create(); - Current.Factory = Container; + var register = RegisterFactory.Create(); - Container.RegisterInstance(typeLoader); - Container.RegisterInstance(logger); - Container.RegisterInstance(profiler); - Container.RegisterInstance(proflogger); - Container.RegisterInstance(cacheHelper); - Container.RegisterInstance(cacheHelper.RuntimeCache); + register.RegisterInstance(typeLoader); + register.RegisterInstance(logger); + register.RegisterInstance(profiler); + register.RegisterInstance(proflogger); + register.RegisterInstance(cacheHelper); + register.RegisterInstance(cacheHelper.RuntimeCache); - Composition = new Composition(Container, typeLoader, proflogger, RuntimeLevel.Run); - TestObjects = new TestObjects(Container); + Composition = new Composition(register, typeLoader, proflogger, RuntimeLevel.Run); + TestObjects = new TestObjects(register); Compose(); + Current.Factory = Factory = register.CreateFactory(); Initialize(); } @@ -210,11 +210,11 @@ namespace Umbraco.Tests.Testing Umbraco.Web.Composing.Current.UmbracoContextAccessor = new TestUmbracoContextAccessor(); // web - Container.Register(_ => Umbraco.Web.Composing.Current.UmbracoContextAccessor); - Container.RegisterSingleton(); + Composition.Register(_ => Umbraco.Web.Composing.Current.UmbracoContextAccessor); + Composition.RegisterSingleton(); Composition.GetCollectionBuilder(); - Container.Register(); - Container.Register(); + Composition.Register(); + Composition.Register(); } protected virtual void ComposeWtf() @@ -222,14 +222,14 @@ namespace Umbraco.Tests.Testing // what else? var runtimeStateMock = new Mock(); runtimeStateMock.Setup(x => x.Level).Returns(RuntimeLevel.Run); - Container.RegisterSingleton(f => runtimeStateMock.Object); + Composition.RegisterSingleton(f => runtimeStateMock.Object); // ah... Composition.GetCollectionBuilder(); Composition.GetCollectionBuilder(); - Container.RegisterSingleton(); + Composition.RegisterSingleton(); - Container.RegisterSingleton(); + Composition.RegisterSingleton(); // register empty content apps collection Composition.GetCollectionBuilder(); @@ -301,58 +301,58 @@ namespace Umbraco.Tests.Testing Composition.ComposeRepositories(); // register basic stuff that might need to be there for some container resolvers to work - Container.RegisterSingleton(factory => umbracoSettings); - Container.RegisterSingleton(factory => globalSettings); - Container.RegisterSingleton(factory => umbracoSettings.Content); - Container.RegisterSingleton(factory => umbracoSettings.Templates); - Container.RegisterSingleton(factory => umbracoSettings.WebRouting); + Composition.RegisterSingleton(factory => umbracoSettings); + Composition.RegisterSingleton(factory => globalSettings); + Composition.RegisterSingleton(factory => umbracoSettings.Content); + Composition.RegisterSingleton(factory => umbracoSettings.Templates); + Composition.RegisterSingleton(factory => umbracoSettings.WebRouting); - Container.RegisterSingleton(factory => ExamineManager.Instance); + Composition.RegisterSingleton(factory => ExamineManager.Instance); // register filesystems - Container.RegisterSingleton(factory => TestObjects.GetFileSystemsMock()); + Composition.RegisterSingleton(factory => TestObjects.GetFileSystemsMock()); var logger = Mock.Of(); var scheme = Mock.Of(); var config = Mock.Of(); var mediaFileSystem = new MediaFileSystem(Mock.Of(), config, scheme, logger); - Container.RegisterSingleton(factory => mediaFileSystem); + Composition.RegisterSingleton(factory => mediaFileSystem); // no factory (noop) - Container.RegisterSingleton(); + Composition.RegisterSingleton(); // register application stuff (database factory & context, services...) Composition.GetCollectionBuilder() .AddCoreMappers(); - Container.RegisterSingleton(_ => new TransientEventMessagesFactory()); - Container.RegisterSingleton(f => new UmbracoDatabaseFactory( + Composition.RegisterSingleton(_ => new TransientEventMessagesFactory()); + Composition.RegisterSingleton(f => new UmbracoDatabaseFactory( Constants.System.UmbracoConnectionName, Logger, new Lazy(() => Mock.Of()))); - Container.RegisterSingleton(f => f.TryGetInstance().SqlContext); + Composition.RegisterSingleton(f => f.TryGetInstance().SqlContext); Composition.GetCollectionBuilder(); // empty - Container.RegisterSingleton(factory + Composition.RegisterSingleton(factory => TestObjects.GetScopeProvider(factory.TryGetInstance(), factory.TryGetInstance(), factory.TryGetInstance())); - Container.RegisterSingleton(factory => (IScopeAccessor) factory.GetInstance()); + Composition.RegisterSingleton(factory => (IScopeAccessor) factory.GetInstance()); Composition.ComposeServices(); // composition root is doing weird things, fix - Container.RegisterSingleton(); - Container.RegisterSingleton(); + Composition.RegisterSingleton(); + Composition.RegisterSingleton(); // somehow property editor ends up wanting this Composition.GetCollectionBuilder(); - Container.RegisterSingleton(); + Composition.RegisterSingleton(); // note - don't register collections, use builders Composition.GetCollectionBuilder(); - Container.RegisterSingleton(); - Container.RegisterSingleton(); + Composition.RegisterSingleton(); + Composition.RegisterSingleton(); } #endregion @@ -365,7 +365,7 @@ namespace Umbraco.Tests.Testing Mapper.Initialize(configuration => { - var profiles = Container.GetAllInstances(); + var profiles = Factory.GetAllInstances(); foreach (var profile in profiles) configuration.AddProfile(profile); }); @@ -402,7 +402,7 @@ namespace Umbraco.Tests.Testing // reset and dispose scopes // ensures we don't leak an opened database connection // which would lock eg SqlCe .sdf files - if (Container?.TryGetInstance() is ScopeProvider scopeProvider) + if (Factory?.TryGetInstance() is ScopeProvider scopeProvider) { Core.Scoping.Scope scope; while ((scope = scopeProvider.AmbientScope) != null) @@ -414,8 +414,9 @@ namespace Umbraco.Tests.Testing Current.Reset(); - Container?.Dispose(); - Container = null; + // fixme what should we dispose? IRegister or IFactory or? + //Container?.Dispose(); + //Container = null; // reset all other static things that should not be static ;( UriUtility.ResetAppDomainAppVirtualPath(); diff --git a/src/Umbraco.Tests/TreesAndSections/SectionTests.cs b/src/Umbraco.Tests/TreesAndSections/SectionTests.cs index 077245fb82..91f2cef961 100644 --- a/src/Umbraco.Tests/TreesAndSections/SectionTests.cs +++ b/src/Umbraco.Tests/TreesAndSections/SectionTests.cs @@ -22,7 +22,7 @@ namespace Umbraco.Tests.TreesAndSections protected override void Compose() { base.Compose(); - Container.Register(); + Composition.Register(); } public override void SetUp() diff --git a/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs b/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs index e496d90dd1..eea755455d 100644 --- a/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs +++ b/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs @@ -28,7 +28,7 @@ namespace Umbraco.Tests.UmbracoExamine { base.Compose(); - Container.RegisterSingleton(_ => new DefaultShortStringHelper(SettingsForTests.GetDefaultUmbracoSettings())); + Composition.RegisterSingleton(_ => new DefaultShortStringHelper(SettingsForTests.GetDefaultUmbracoSettings())); } } } diff --git a/src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs b/src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs index 8abe2fcc18..8aae044c55 100644 --- a/src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs +++ b/src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs @@ -81,14 +81,14 @@ namespace Umbraco.Tests.Web.Controllers var textService = new Mock(); textService.Setup(x => x.Localize(It.IsAny(), It.IsAny(), It.IsAny>())).Returns(""); - Container.RegisterSingleton(f => Mock.Of()); - Container.RegisterSingleton(f => userServiceMock.Object); - Container.RegisterSingleton(f => entityService.Object); - Container.RegisterSingleton(f => dataTypeService.Object); - Container.RegisterSingleton(f => langService.Object); - Container.RegisterSingleton(f => textService.Object); - Container.RegisterSingleton(f => Mock.Of()); - Container.RegisterSingleton(f => new UmbracoApiControllerTypeCollection(new[] { typeof(ContentTreeController) })); + Composition.RegisterSingleton(f => Mock.Of()); + Composition.RegisterSingleton(f => userServiceMock.Object); + Composition.RegisterSingleton(f => entityService.Object); + Composition.RegisterSingleton(f => dataTypeService.Object); + Composition.RegisterSingleton(f => langService.Object); + Composition.RegisterSingleton(f => textService.Object); + Composition.RegisterSingleton(f => Mock.Of()); + Composition.RegisterSingleton(f => new UmbracoApiControllerTypeCollection(new[] { typeof(ContentTreeController) })); } private MultipartFormDataContent GetMultiPartRequestContent(string json) diff --git a/src/Umbraco.Tests/Web/Controllers/UsersControllerTests.cs b/src/Umbraco.Tests/Web/Controllers/UsersControllerTests.cs index 4292cffdb0..d62cf7b93c 100644 --- a/src/Umbraco.Tests/Web/Controllers/UsersControllerTests.cs +++ b/src/Umbraco.Tests/Web/Controllers/UsersControllerTests.cs @@ -38,12 +38,12 @@ namespace Umbraco.Tests.Web.Controllers // replace the true IUserService implementation with a mock // so that each test can configure the service to their liking - Container.RegisterSingleton(f => Mock.Of()); + Composition.RegisterSingleton(f => Mock.Of()); // kill the true IEntityService too - Container.RegisterSingleton(f => Mock.Of()); + Composition.RegisterSingleton(f => Mock.Of()); - Container.RegisterSingleton(); + Composition.RegisterSingleton(); } [Test] diff --git a/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs b/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs index ada96a3895..6d8f1e38c8 100644 --- a/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs +++ b/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs @@ -94,7 +94,7 @@ namespace Umbraco.Tests.Web.Mvc true); var controller = new TestSurfaceController(umbracoContext); - Container.Register(_ => umbracoContext); + Composition.Register(_ => umbracoContext); Assert.IsNotNull(controller.Umbraco); } diff --git a/src/Umbraco.Web/Components/DatabaseServerRegistrarAndMessengerComponent.cs b/src/Umbraco.Web/Components/DatabaseServerRegistrarAndMessengerComponent.cs index 8e01b61302..be632bdd14 100644 --- a/src/Umbraco.Web/Components/DatabaseServerRegistrarAndMessengerComponent.cs +++ b/src/Umbraco.Web/Components/DatabaseServerRegistrarAndMessengerComponent.cs @@ -54,12 +54,12 @@ namespace Umbraco.Web.Components { composition.SetServerMessenger(factory => { - var runtime = RegisterExtensions.GetInstance(factory); - var databaseFactory = RegisterExtensions.GetInstance(factory); - var globalSettings = RegisterExtensions.GetInstance(factory); - var proflog = RegisterExtensions.GetInstance(factory); - var scopeProvider = RegisterExtensions.GetInstance(factory); - var sqlContext = RegisterExtensions.GetInstance(factory); + var runtime = factory.GetInstance(); + var databaseFactory = factory.GetInstance(); + var globalSettings = factory.GetInstance(); + var proflog = factory.GetInstance(); + var scopeProvider = factory.GetInstance(); + var sqlContext = factory.GetInstance(); return new BatchedDatabaseServerMessenger( runtime, databaseFactory, scopeProvider, sqlContext, proflog, globalSettings, diff --git a/src/Umbraco.Web/Composing/LightInject/LightInjectContainer.cs b/src/Umbraco.Web/Composing/LightInject/LightInjectContainer.cs index 0237e2a641..ae7f769753 100644 --- a/src/Umbraco.Web/Composing/LightInject/LightInjectContainer.cs +++ b/src/Umbraco.Web/Composing/LightInject/LightInjectContainer.cs @@ -1,13 +1,12 @@ using System; using System.Web.Http; using LightInject; -using Umbraco.Core.Composing; using Umbraco.Core.Composing.LightInject; namespace Umbraco.Web.Composing.LightInject { /// - /// Implements with LightInject. + /// Implements DI with LightInject. /// public class LightInjectContainer : Core.Composing.LightInject.LightInjectContainer { @@ -25,7 +24,7 @@ namespace Umbraco.Web.Composing.LightInject => new LightInjectContainer(CreateServiceContainer()); /// - public override IContainer ConfigureForWeb() + public override void ConfigureForWeb() { // IoC setup for LightInject for MVC/WebApi // see comments on MixedLightInjectScopeManagerProvider for explainations of what we are doing here @@ -34,8 +33,6 @@ namespace Umbraco.Web.Composing.LightInject Container.EnableMvc(); // does container.EnablePerWebRequestScope() Container.ScopeManagerProvider = smp; // reverts - we will do it last (in WebRuntime) Container.EnableWebApi(GlobalConfiguration.Configuration); - - return this; } } } diff --git a/src/Umbraco.Web/HtmlHelperRenderExtensions.cs b/src/Umbraco.Web/HtmlHelperRenderExtensions.cs index 5183cd0c3c..4504c22161 100644 --- a/src/Umbraco.Web/HtmlHelperRenderExtensions.cs +++ b/src/Umbraco.Web/HtmlHelperRenderExtensions.cs @@ -94,7 +94,7 @@ namespace Umbraco.Web } if (cacheByMember) { - var helper = RegisterExtensions.GetInstance(Current.Factory); + var helper = Current.Factory.GetInstance(); var currentMember = helper.GetCurrentMember(); cacheKey.AppendFormat("m{0}-", currentMember == null ? 0 : currentMember.Id); } diff --git a/src/Umbraco.Web/Models/LoginStatusModel.cs b/src/Umbraco.Web/Models/LoginStatusModel.cs index 5f9391dc7c..d253a364ae 100644 --- a/src/Umbraco.Web/Models/LoginStatusModel.cs +++ b/src/Umbraco.Web/Models/LoginStatusModel.cs @@ -24,7 +24,7 @@ namespace Umbraco.Web.Models { if (doLookup && Current.UmbracoContext != null) { - var helper = RegisterExtensions.GetInstance(Current.Factory); + var helper = Current.Factory.GetInstance(); var model = helper.GetCurrentLoginStatus(); if (model != null) { diff --git a/src/Umbraco.Web/Models/ProfileModel.cs b/src/Umbraco.Web/Models/ProfileModel.cs index a3c26812a3..8e66042d21 100644 --- a/src/Umbraco.Web/Models/ProfileModel.cs +++ b/src/Umbraco.Web/Models/ProfileModel.cs @@ -28,7 +28,7 @@ namespace Umbraco.Web.Models MemberProperties = new List(); if (doLookup && Current.UmbracoContext != null) { - var helper = RegisterExtensions.GetInstance(Current.Factory); + var helper = Current.Factory.GetInstance(); var model = helper.GetCurrentMemberProfileModel(); MemberProperties = model.MemberProperties; } diff --git a/src/Umbraco.Web/Models/RegisterModel.cs b/src/Umbraco.Web/Models/RegisterModel.cs index 26c3d2428c..44845bfd43 100644 --- a/src/Umbraco.Web/Models/RegisterModel.cs +++ b/src/Umbraco.Web/Models/RegisterModel.cs @@ -32,7 +32,7 @@ namespace Umbraco.Web.Models CreatePersistentLoginCookie = true; if (doLookup && Current.UmbracoContext != null) { - var helper = RegisterExtensions.GetInstance(Current.Factory); + var helper = Current.Factory.GetInstance(); var model = helper.CreateRegistrationModel(MemberTypeAlias); MemberProperties = model.MemberProperties; } diff --git a/src/Umbraco.Web/Mvc/EnsurePublishedContentRequestAttribute.cs b/src/Umbraco.Web/Mvc/EnsurePublishedContentRequestAttribute.cs index 4c1c71a223..f243acd6d3 100644 --- a/src/Umbraco.Web/Mvc/EnsurePublishedContentRequestAttribute.cs +++ b/src/Umbraco.Web/Mvc/EnsurePublishedContentRequestAttribute.cs @@ -74,7 +74,7 @@ namespace Umbraco.Web.Mvc protected UmbracoContext UmbracoContext => _umbracoContext ?? (_umbracoContext = UmbracoContext.Current); // todo - try lazy property injection? - private PublishedRouter PublishedRouter => RegisterExtensions.GetInstance(Core.Composing.Current.Factory); + private PublishedRouter PublishedRouter => Core.Composing.Current.Factory.GetInstance(); /// /// Exposes an UmbracoHelper diff --git a/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs b/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs index b3449c245d..b51c0eddfc 100644 --- a/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs +++ b/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs @@ -109,8 +109,8 @@ namespace Umbraco.Web.Mvc protected UmbracoViewPage() : this( - RegisterExtensions.GetInstance(Current.Factory), - RegisterExtensions.GetInstance(Current.Factory) + Current.Factory.GetInstance(), + Current.Factory.GetInstance() ) { } diff --git a/src/Umbraco.Web/Runtime/WebRuntime.cs b/src/Umbraco.Web/Runtime/WebRuntime.cs index d9283ce0d7..621bab282d 100644 --- a/src/Umbraco.Web/Runtime/WebRuntime.cs +++ b/src/Umbraco.Web/Runtime/WebRuntime.cs @@ -28,7 +28,7 @@ namespace Umbraco.Web.Runtime } /// - public override void Boot(IContainer container) + public override void Boot(IRegister register) { // create and start asap to profile boot var debug = GlobalSettings.DebugMode; @@ -44,10 +44,10 @@ namespace Umbraco.Web.Runtime _webProfiler = new VoidProfiler(); } - base.Boot(container); + base.Boot(register); // now (and only now) is the time to switch over to perWebRequest scopes - container.EnablePerWebRequestScope(); + register.EnablePerWebRequestScope(); } /// diff --git a/src/Umbraco.Web/Templates/TemplateRenderer.cs b/src/Umbraco.Web/Templates/TemplateRenderer.cs index 282aef8a58..9c2c4973e0 100644 --- a/src/Umbraco.Web/Templates/TemplateRenderer.cs +++ b/src/Umbraco.Web/Templates/TemplateRenderer.cs @@ -41,7 +41,7 @@ namespace Umbraco.Web.Templates } // todo - inject! - private PublishedRouter PublishedRouter => RegisterExtensions.GetInstance(Core.Composing.Current.Factory); + private PublishedRouter PublishedRouter => Core.Composing.Current.Factory.GetInstance(); /// diff --git a/src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs b/src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs index e04952b2e6..d535d61ba4 100644 --- a/src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs +++ b/src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs @@ -30,7 +30,7 @@ namespace Umbraco.Web.UI.Controls if (umbracoContext == null) throw new ArgumentNullException(nameof(umbracoContext)); UmbracoContext = umbracoContext; Umbraco = new UmbracoHelper(umbracoContext, services, appCache); - Members = RegisterExtensions.GetInstance(Current.Factory); + Members = Current.Factory.GetInstance(); // fixme inject somehow Logger = Current.Logger; diff --git a/src/Umbraco.Web/UmbracoApplicationBase.cs b/src/Umbraco.Web/UmbracoApplicationBase.cs index b778a04967..7b8fa56201 100644 --- a/src/Umbraco.Web/UmbracoApplicationBase.cs +++ b/src/Umbraco.Web/UmbracoApplicationBase.cs @@ -23,11 +23,11 @@ namespace Umbraco.Web protected abstract IRuntime GetRuntime(); /// - /// Gets the application container. + /// Gets the application register. /// - protected virtual IContainer GetContainer() + protected virtual IRegister GetContainer() { - return ContainerFactory.Create(); + return RegisterFactory.Create(); } // events - in the order they trigger diff --git a/src/Umbraco.Web/UmbracoHelper.cs b/src/Umbraco.Web/UmbracoHelper.cs index 8fcbb040b5..03913ee027 100644 --- a/src/Umbraco.Web/UmbracoHelper.cs +++ b/src/Umbraco.Web/UmbracoHelper.cs @@ -156,7 +156,7 @@ namespace Umbraco.Web /// Gets the membership helper. /// public MembershipHelper MembershipHelper => _membershipHelper - ?? (_membershipHelper = RegisterExtensions.GetInstance(Current.Factory)); + ?? (_membershipHelper = Current.Factory.GetInstance()); /// /// Gets the url provider. From 8d49fb3e8b85a1e2e9926e5a606835f0000a6eb4 Mon Sep 17 00:00:00 2001 From: Stephan Date: Wed, 28 Nov 2018 16:19:50 +0100 Subject: [PATCH 107/469] Cleanup and document controller constructors --- .../Editors/AuthenticationController.cs | 32 +++--- .../Editors/DashboardController.cs | 10 +- src/Umbraco.Web/TagsController.cs | 16 +-- .../WebApi/UmbracoApiController.cs | 11 +- .../WebApi/UmbracoApiControllerBase.cs | 101 +++++++++--------- .../WebApi/UmbracoAuthorizedApiController.cs | 28 +++-- 6 files changed, 113 insertions(+), 85 deletions(-) diff --git a/src/Umbraco.Web/Editors/AuthenticationController.cs b/src/Umbraco.Web/Editors/AuthenticationController.cs index 3893afd62f..eee6997da2 100644 --- a/src/Umbraco.Web/Editors/AuthenticationController.cs +++ b/src/Umbraco.Web/Editors/AuthenticationController.cs @@ -40,27 +40,27 @@ namespace Umbraco.Web.Editors [IsBackOffice] public class AuthenticationController : UmbracoApiController { - - //fixme inject these private BackOfficeUserManager _userManager; private BackOfficeSignInManager _signInManager; - protected BackOfficeUserManager UserManager - { - get { return _userManager ?? (_userManager = TryGetOwinContext().Result.GetBackOfficeUserManager()); } - } - protected BackOfficeSignInManager SignInManager - { - get { return _signInManager ?? (_signInManager = TryGetOwinContext().Result.GetBackOfficeSignInManager()); } - } + /// + /// Initializes a new instance of the new class with auto dependencies. + /// public AuthenticationController() - { - } + { } - public AuthenticationController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, IProfilingLogger profilingLogger, IRuntimeState runtimeState) - : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, profilingLogger, runtimeState) - { - } + /// + /// Initializes a new instance of the class with all its dependencies. + /// + public AuthenticationController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) + : base(globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) + { } + + protected BackOfficeUserManager UserManager => _userManager + ?? (_userManager = TryGetOwinContext().Result.GetBackOfficeUserManager()); + + protected BackOfficeSignInManager SignInManager => _signInManager + ?? (_signInManager = TryGetOwinContext().Result.GetBackOfficeSignInManager()); /// /// Returns the configuration for the backoffice user membership provider - used to configure the change password dialog diff --git a/src/Umbraco.Web/Editors/DashboardController.cs b/src/Umbraco.Web/Editors/DashboardController.cs index 8a8db06d8d..b8a961ee5a 100644 --- a/src/Umbraco.Web/Editors/DashboardController.cs +++ b/src/Umbraco.Web/Editors/DashboardController.cs @@ -27,11 +27,17 @@ namespace Umbraco.Web.Editors [WebApi.UmbracoAuthorize] public class DashboardController : UmbracoApiController { + /// + /// Initializes a new instance of the with auto dependencies. + /// public DashboardController() { } - public DashboardController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, IProfilingLogger profilingLogger, IRuntimeState runtimeState) - : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, profilingLogger, runtimeState) + /// + /// Initializes a new instance of the with all its dependencies. + /// + public DashboardController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) + : base(globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) { } //we have just one instance of HttpClient shared for the entire application diff --git a/src/Umbraco.Web/TagsController.cs b/src/Umbraco.Web/TagsController.cs index a85b37c545..181b9f7da2 100644 --- a/src/Umbraco.Web/TagsController.cs +++ b/src/Umbraco.Web/TagsController.cs @@ -20,14 +20,18 @@ namespace Umbraco.Web.WebServices // TODO: This controller should be moved to a more suitable place. public class TagsController : UmbracoApiController { + /// + /// Initializes a new instance of the with auto dependencies. + /// public TagsController() - { - } + { } - public TagsController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, IProfilingLogger profilingLogger, IRuntimeState runtimeState) - : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, profilingLogger, runtimeState) - { - } + /// + /// Initializes a new instance of the with all its dependencies. + /// + public TagsController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) + : base(globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) + { } /// /// Get every tag stored in the database (with optional group) diff --git a/src/Umbraco.Web/WebApi/UmbracoApiController.cs b/src/Umbraco.Web/WebApi/UmbracoApiController.cs index 4f2934abf4..3db3610cc2 100644 --- a/src/Umbraco.Web/WebApi/UmbracoApiController.cs +++ b/src/Umbraco.Web/WebApi/UmbracoApiController.cs @@ -13,11 +13,18 @@ namespace Umbraco.Web.WebApi /// public abstract class UmbracoApiController : UmbracoApiControllerBase, IDiscoverable { + /// + /// Initializes a new instance of the with auto dependencies. + /// + /// Dependencies are obtained from the service locator. protected UmbracoApiController() { } - protected UmbracoApiController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, IProfilingLogger profilingLogger, IRuntimeState runtimeState) - : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, profilingLogger, runtimeState) + /// + /// Initialize a new instance of the with all its dependencies. + /// + protected UmbracoApiController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) + : base(globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) { } } } diff --git a/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs b/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs index 27b06ee767..4b23d4f0a8 100644 --- a/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs +++ b/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs @@ -21,48 +21,82 @@ namespace Umbraco.Web.WebApi [FeatureAuthorize] public abstract class UmbracoApiControllerBase : ApiController { + private readonly IUmbracoContextAccessor _umbracoContextAccessor; private UmbracoHelper _umbracoHelper; - // for debugging purposes + // note: all Umbraco controllers have two constructors: one with all dependencies, which should be used, + // and one with auto dependencies, ie no dependencies - and then dependencies are automatically obtained + // here from the Current service locator - this is obviously evil, but it allows us to add new dependencies + // without breaking compatibility. + + /// + /// Initializes a new instance of the class with auto dependencies. + /// + /// Dependencies are obtained from the service locator. + protected UmbracoApiControllerBase() + : this( + Current.Factory.GetInstance(), + Current.Factory.GetInstance(), + Current.Factory.GetInstance(), + Current.Factory.GetInstance(), + Current.Factory.GetInstance(), + Current.Factory.GetInstance(), + Current.Factory.GetInstance() + ) + { } + + /// + /// Initializes a new instance of the class with all its dependencies. + /// + protected UmbracoApiControllerBase(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) + { + GlobalSettings = globalSettings; + _umbracoContextAccessor = umbracoContextAccessor; + SqlContext = sqlContext; + Services = services; + ApplicationCache = applicationCache; + Logger = logger; + RuntimeState = runtimeState; + } + + /// + /// Gets a unique instance identifier. + /// + /// For debugging purposes. internal Guid InstanceId { get; } = Guid.NewGuid(); /// - /// Gets or sets the Umbraco context. + /// Gets the Umbraco context. /// public virtual IGlobalSettings GlobalSettings { get; } /// - /// Gets or sets the Umbraco context. + /// Gets the Umbraco context. /// - public virtual UmbracoContext UmbracoContext { get; } + public virtual UmbracoContext UmbracoContext => _umbracoContextAccessor.UmbracoContext; /// - /// Gets or sets the sql context. + /// Gets the sql context. /// public ISqlContext SqlContext { get; } /// - /// Gets or sets the services context. + /// Gets the services context. /// public ServiceContext Services { get; } /// - /// Gets or sets the application cache. + /// Gets the application cache. /// public CacheHelper ApplicationCache { get; } /// - /// Gets or sets the logger. + /// Gets the logger. /// - public ILogger Logger { get; } + public IProfilingLogger Logger { get; } /// - /// Gets or sets the profiling logger. - /// - public IProfilingLogger ProfilingLogger { get; } - - /// - /// Gets or sets the runtime state. + /// Gets the runtime state. /// internal IRuntimeState RuntimeState { get; } @@ -87,49 +121,16 @@ namespace Umbraco.Web.WebApi /// public WebSecurity Security => UmbracoContext.Security; - protected UmbracoApiControllerBase() - : this( - Current.Factory.GetInstance(), - Current.Factory.GetInstance().UmbracoContext, - Current.Factory.GetInstance(), - Current.Factory.GetInstance(), - Current.Factory.GetInstance(), - Current.Factory.GetInstance(), - Current.Factory.GetInstance(), - Current.Factory.GetInstance() - ) - { - } - - // fixme - Inject fewer things? (Aggregate more) - // fixme - inject the context accessor not the context itself? - // fixme - profiling logger is logger, merge! - protected UmbracoApiControllerBase(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, IProfilingLogger profilingLogger, IRuntimeState runtimeState) - { - GlobalSettings = globalSettings; - UmbracoContext = umbracoContext; - SqlContext = sqlContext; - Services = services; - ApplicationCache = applicationCache; - Logger = logger; - ProfilingLogger = profilingLogger; - RuntimeState = runtimeState; - } - /// /// Tries to get the current HttpContext. /// protected Attempt TryGetHttpContext() - { - return Request.TryGetHttpContext(); - } + => Request.TryGetHttpContext(); /// /// Tries to get the current OWIN context. /// protected Attempt TryGetOwinContext() - { - return Request.TryGetOwinContext(); - } + => Request.TryGetOwinContext(); } } diff --git a/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs b/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs index 82c172af79..4ae9c00a47 100644 --- a/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs +++ b/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs @@ -5,18 +5,18 @@ using Umbraco.Core.Logging; using Umbraco.Web.WebApi.Filters; using Umbraco.Core.Models.Identity; using Umbraco.Core.Persistence; -using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Web.Security; namespace Umbraco.Web.WebApi { /// - /// Provides a base class for autorized auto-routed Umbraco API controllers. + /// Provides a base class for authorized auto-routed Umbraco API controllers. /// /// - /// This controller will also append a custom header to the response if the user is logged in using forms authentication - /// which indicates the seconds remaining before their timeout expires. + /// This controller will also append a custom header to the response if the user + /// is logged in using forms authentication which indicates the seconds remaining + /// before their timeout expires. /// [IsBackOffice] [UmbracoUserTimeoutFilter] @@ -30,14 +30,24 @@ namespace Umbraco.Web.WebApi { private BackOfficeUserManager _userManager; - protected BackOfficeUserManager UserManager - => _userManager ?? (_userManager = TryGetOwinContext().Result.GetBackOfficeUserManager()); - + /// + /// Initializes a new instance of the with auto dependencies. + /// + /// Dependencies are obtained from the service locator. protected UmbracoAuthorizedApiController() { } - protected UmbracoAuthorizedApiController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, IProfilingLogger profilingLogger, IRuntimeState runtimeState) - : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, profilingLogger, runtimeState) + /// + /// Initializes a new instance of the class with all its dependencies. + /// + protected UmbracoAuthorizedApiController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) + : base(globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) { } + + /// + /// Gets the user manager. + /// + protected BackOfficeUserManager UserManager + => _userManager ?? (_userManager = TryGetOwinContext().Result.GetBackOfficeUserManager()); } } From b1651b8c9eb5c0b20779c578c0e4fbb9647def30 Mon Sep 17 00:00:00 2001 From: Stephan Date: Wed, 28 Nov 2018 16:22:20 +0100 Subject: [PATCH 108/469] Delete legacy code --- .../Actions/ActionCollectionBuilder.cs | 34 ------------------- 1 file changed, 34 deletions(-) delete mode 100644 src/Umbraco.Web/_Legacy/Actions/ActionCollectionBuilder.cs diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionCollectionBuilder.cs b/src/Umbraco.Web/_Legacy/Actions/ActionCollectionBuilder.cs deleted file mode 100644 index 1789e57e2d..0000000000 --- a/src/Umbraco.Web/_Legacy/Actions/ActionCollectionBuilder.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Collections.Generic; -using Umbraco.Core.Composing; - -namespace Umbraco.Web._Legacy.Actions -{ - internal class ActionCollectionBuilder : ICollectionBuilder - { - private Func> _producer; - private ActionCollection _collection; - - // for tests only - does not register the collection - public ActionCollectionBuilder() - { } - - public ActionCollectionBuilder(IContainer container) - { - // register the collection - container.RegisterSingleton(factory => factory.GetInstance().CreateCollection()); - } - - public ActionCollection CreateCollection() - { - // create a special collection that can be resetted (ouch) - return _collection = new ActionCollection(_producer); - } - - public void SetProducer(Func> producer) - { - _producer = producer; - _collection?.Reset(producer); - } - } -} From e42f140a2c82dc3a4a6b913b2c735a2bfcd01f7b Mon Sep 17 00:00:00 2001 From: Stephan Date: Wed, 28 Nov 2018 16:57:01 +0100 Subject: [PATCH 109/469] Cleanup --- src/Umbraco.Core/Composing/RegisterFactory.cs | 12 +-- .../Runtime/CoreRuntimeComponent.cs | 2 +- .../DistributedCache/DistributedCacheTests.cs | 5 +- .../Components/ComponentTests.cs | 5 - .../Composing/CollectionBuildersTests.cs | 91 +++++++++++-------- ...erTests.cs => ContainerConfirmingTests.cs} | 51 ++++++++++- .../Composing/ContainerImplementationTests.cs | 71 --------------- .../Composing/PackageActionCollectionTests.cs | 8 +- .../TestHelpers/TestObjects-Mocks.cs | 2 +- src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 16 +--- src/Umbraco.Tests/Umbraco.Tests.csproj | 3 +- src/Umbraco.Web/Editors/MacroController.cs | 2 +- src/Umbraco.Web/Editors/TourController.cs | 17 ++-- src/Umbraco.Web/Mvc/RenderRouteHandler.cs | 11 +-- src/Umbraco.Web/Templates/TemplateRenderer.cs | 27 +++--- src/Umbraco.Web/UmbracoComponentRenderer.cs | 5 - 16 files changed, 150 insertions(+), 178 deletions(-) rename src/Umbraco.Tests/Composing/{ContainerTests.cs => ContainerConfirmingTests.cs} (79%) delete mode 100644 src/Umbraco.Tests/Composing/ContainerImplementationTests.cs diff --git a/src/Umbraco.Core/Composing/RegisterFactory.cs b/src/Umbraco.Core/Composing/RegisterFactory.cs index bb132c247a..8ee6e5a94c 100644 --- a/src/Umbraco.Core/Composing/RegisterFactory.cs +++ b/src/Umbraco.Core/Composing/RegisterFactory.cs @@ -25,9 +25,7 @@ namespace Umbraco.Core.Composing { Type type; - // fixme naming / container? - - var configuredTypeName = ConfigurationManager.AppSettings["umbracoContainerType"]; + var configuredTypeName = ConfigurationManager.AppSettings["umbracoRegisterType"]; if (configuredTypeName.IsNullOrWhiteSpace()) { // try to get the web LightInject container type, @@ -37,20 +35,20 @@ namespace Umbraco.Core.Composing } else { - // try to get the configured container type + // try to get the configured type type = Type.GetType(configuredTypeName); } if (type == null) - throw new Exception($"Cannot find container factory class '{configuredTypeName}'."); + throw new Exception($"Cannot find register factory class '{configuredTypeName}'."); var factoryMethod = type.GetMethod("Create", BindingFlags.Public | BindingFlags.Static); if (factoryMethod == null) - throw new Exception($"Container factory class '{configuredTypeName}' does not have a public static method named Create."); + throw new Exception($"Register factory class '{configuredTypeName}' does not have a public static method named Create."); var container = factoryMethod.Invoke(null, Array.Empty()) as IRegister; if (container == null) - throw new Exception($"Container factory '{configuredTypeName}' did not return an IRegister implementation."); + throw new Exception($"Register factory '{configuredTypeName}' did not return an IRegister implementation."); return container; } diff --git a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs index c4167af2b0..63cd4e726b 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs @@ -74,7 +74,7 @@ namespace Umbraco.Core.Runtime composition.RegisterSingleton(); composition.RegisterSingleton(); - // register a server registrar, by default it's the db registrar + // register a server registrar, by default it's the db registrar composition.RegisterSingleton(f => { if ("true".InvariantEquals(ConfigurationManager.AppSettings["umbracoDisableElectionForSingleServer"])) diff --git a/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs b/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs index 5c2681e184..684e06b300 100644 --- a/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs +++ b/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs @@ -7,7 +7,6 @@ using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Components; using Umbraco.Core.Composing; -using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Sync; @@ -25,7 +24,7 @@ namespace Umbraco.Tests.Cache.DistributedCache public void Setup() { var register = RegisterFactory.Create(); - Current.Factory = register.CreateFactory(); // fixme only for LightInject + var composition = new Composition(register, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); register.Register(_ => new TestServerRegistrar()); @@ -34,6 +33,8 @@ namespace Umbraco.Tests.Cache.DistributedCache composition.GetCollectionBuilder() .Add(); + Current.Factory = register.CreateFactory(); + _distributedCache = new Umbraco.Web.Cache.DistributedCache(); } diff --git a/src/Umbraco.Tests/Components/ComponentTests.cs b/src/Umbraco.Tests/Components/ComponentTests.cs index e455f9e6e7..e68dae8a45 100644 --- a/src/Umbraco.Tests/Components/ComponentTests.cs +++ b/src/Umbraco.Tests/Components/ComponentTests.cs @@ -4,16 +4,13 @@ using System.Linq; using Moq; using NUnit.Framework; using Umbraco.Core; -using Umbraco.Core.Cache; using Umbraco.Core.Components; using Umbraco.Core.Composing; -using Umbraco.Core.Configuration; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Scoping; -using Umbraco.Tests.TestHelpers; namespace Umbraco.Tests.Components { @@ -53,8 +50,6 @@ namespace Umbraco.Tests.Components return new TypeLoader(); } - // fixme should we have Composition.Logger, which would be a profiling logger too? - [Test] public void Boot1A() { diff --git a/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs b/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs index f30c9a36e3..0d0374d37a 100644 --- a/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs +++ b/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs @@ -13,8 +13,6 @@ namespace Umbraco.Tests.Composing [TestFixture] public class CollectionBuildersTests { - private IRegister _register; - private IFactory _factory; private Composition _composition; [SetUp] @@ -22,19 +20,14 @@ namespace Umbraco.Tests.Composing { Current.Reset(); - _register = RegisterFactory.Create(); - _factory = _register.CreateFactory(); // fixme only works w/LightInject - would require we reorg tests! - Current.Factory = _factory; - _composition = new Composition(_register, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); + var register = RegisterFactory.Create(); + _composition = new Composition(register, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); } [TearDown] public void TearDown() { Current.Reset(); - - _register.DisposeIfDisposable(); - _register = null; } [Test] @@ -49,7 +42,8 @@ namespace Umbraco.Tests.Composing Assert.IsFalse(builder.Has()); //Assert.IsFalse(col.ContainsType()); // does not compile - var col = builder.CreateCollection(_factory); + var factory = _composition.CreateFactory(); + var col = builder.CreateCollection(factory); AssertCollection(col, typeof(Resolved1), typeof(Resolved2)); } @@ -64,7 +58,8 @@ namespace Umbraco.Tests.Composing Assert.IsFalse(builder.Has()); Assert.IsFalse(builder.Has()); - var col = builder.CreateCollection(_factory); + var factory = _composition.CreateFactory(); + var col = builder.CreateCollection(factory); AssertCollection(col); } @@ -75,7 +70,8 @@ namespace Umbraco.Tests.Composing .Append() .Append(); - var col = builder.CreateCollection(_factory); + var factory = _composition.CreateFactory(); + var col = builder.CreateCollection(factory); Assert.Throws(() => builder.Clear()); } @@ -91,7 +87,8 @@ namespace Umbraco.Tests.Composing Assert.IsTrue(builder.Has()); Assert.IsFalse(builder.Has()); - var col = builder.CreateCollection(_factory); + var factory = _composition.CreateFactory(); + var col = builder.CreateCollection(factory); AssertCollection(col, typeof(Resolved1), typeof(Resolved2)); } @@ -100,7 +97,8 @@ namespace Umbraco.Tests.Composing { var builder = _composition.GetCollectionBuilder(); - var col = builder.CreateCollection(_factory); + var factory = _composition.CreateFactory(); + var col = builder.CreateCollection(factory); Assert.Throws(() => builder.Append() @@ -114,7 +112,9 @@ namespace Umbraco.Tests.Composing builder.Append(); builder.Append(); - var col = builder.CreateCollection(_factory); + var factory = _composition.CreateFactory(); + + var col = builder.CreateCollection(factory); AssertCollection(col, typeof(Resolved1)); } @@ -122,6 +122,7 @@ namespace Umbraco.Tests.Composing public void CannotAppendInvalidTypeToBUilder() { var builder = _composition.GetCollectionBuilder(); + //builder.Append(); // does not compile Assert.Throws(() => builder.Append(new[] { typeof (Resolved4) }) // throws @@ -140,7 +141,8 @@ namespace Umbraco.Tests.Composing Assert.IsFalse(builder.Has()); Assert.IsFalse(builder.Has()); - var col = builder.CreateCollection(_factory); + var factory = _composition.CreateFactory(); + var col = builder.CreateCollection(factory); AssertCollection(col, typeof(Resolved1)); } @@ -152,7 +154,8 @@ namespace Umbraco.Tests.Composing .Append() .Remove(); - var col = builder.CreateCollection(_factory); + var factory = _composition.CreateFactory(); + var col = builder.CreateCollection(factory); AssertCollection(col, typeof(Resolved1), typeof(Resolved2)); } @@ -163,7 +166,8 @@ namespace Umbraco.Tests.Composing .Append() .Append(); - var col = builder.CreateCollection(_factory); + var factory = _composition.CreateFactory(); + var col = builder.CreateCollection(factory); Assert.Throws(() => builder.Remove() // throws ); @@ -181,7 +185,8 @@ namespace Umbraco.Tests.Composing Assert.IsTrue(builder.Has()); Assert.IsTrue(builder.Has()); - var col = builder.CreateCollection(_factory); + var factory = _composition.CreateFactory(); + var col = builder.CreateCollection(factory); AssertCollection(col, typeof(Resolved3), typeof(Resolved1), typeof(Resolved2)); } @@ -192,7 +197,8 @@ namespace Umbraco.Tests.Composing .Append() .Append(); - var col = builder.CreateCollection(_factory); + var factory = _composition.CreateFactory(); + var col = builder.CreateCollection(factory); Assert.Throws(() => builder.Insert() // throws ); @@ -206,7 +212,8 @@ namespace Umbraco.Tests.Composing .Append() .Insert(); - var col = builder.CreateCollection(_factory); + var factory = _composition.CreateFactory(); + var col = builder.CreateCollection(factory); AssertCollection(col, typeof(Resolved2), typeof(Resolved1)); } @@ -216,7 +223,8 @@ namespace Umbraco.Tests.Composing var builder = _composition.GetCollectionBuilder(); builder.Insert(); - var col = builder.CreateCollection(_factory); + var factory = _composition.CreateFactory(); + var col = builder.CreateCollection(factory); AssertCollection(col, typeof(Resolved2)); } @@ -248,7 +256,8 @@ namespace Umbraco.Tests.Composing Assert.IsTrue(builder.Has()); Assert.IsTrue(builder.Has()); - var col = builder.CreateCollection(_factory); + var factory = _composition.CreateFactory(); + var col = builder.CreateCollection(factory); AssertCollection(col, typeof(Resolved1), typeof(Resolved3), typeof(Resolved2)); } @@ -259,7 +268,8 @@ namespace Umbraco.Tests.Composing .Append() .Append(); - var col = builder.CreateCollection(_factory); + var factory = _composition.CreateFactory(); + var col = builder.CreateCollection(factory); Assert.Throws(() => builder.InsertBefore() ); @@ -273,7 +283,8 @@ namespace Umbraco.Tests.Composing .Append() .InsertBefore(); - var col = builder.CreateCollection(_factory); + var factory = _composition.CreateFactory(); + var col = builder.CreateCollection(factory); AssertCollection(col, typeof(Resolved2), typeof(Resolved1)); } @@ -299,10 +310,12 @@ namespace Umbraco.Tests.Composing // but the container manages the scope, so to test the scope // the collection must come from the container - var col1 = _factory.GetInstance(); + var factory = _composition.CreateFactory(); + + var col1 = factory.GetInstance(); AssertCollection(col1, typeof(Resolved1), typeof(Resolved2)); - var col2 = _factory.GetInstance(); + var col2 = factory.GetInstance(); AssertCollection(col2, typeof(Resolved1), typeof(Resolved2)); AssertSameCollection(col1, col2); @@ -319,10 +332,12 @@ namespace Umbraco.Tests.Composing // but the container manages the scope, so to test the scope // the collection must come from the container - var col1 = _factory.GetInstance(); + var factory = _composition.CreateFactory(); + + var col1 = factory.GetInstance(); AssertCollection(col1, typeof(Resolved1), typeof(Resolved2)); - var col2 = _factory.GetInstance(); + var col2 = factory.GetInstance(); AssertCollection(col1, typeof(Resolved1), typeof(Resolved2)); AssertNotSameCollection(col1, col2); @@ -336,7 +351,8 @@ namespace Umbraco.Tests.Composing .Insert() .InsertBefore(); - var col1 = builder.CreateCollection(_factory); + var factory = _composition.CreateFactory(); + var col1 = builder.CreateCollection(factory); AssertCollection(col1, typeof(Resolved1), typeof(Resolved2), typeof(Resolved3)); } @@ -353,10 +369,12 @@ namespace Umbraco.Tests.Composing TestCollection col1A, col1B; - using (_factory.BeginScope()) + var factory = _composition.CreateFactory(); + + using (factory.BeginScope()) { - col1A = _factory.GetInstance(); - col1B = _factory.GetInstance(); + col1A = factory.GetInstance(); + col1B = factory.GetInstance(); } AssertCollection(col1A, typeof(Resolved1), typeof(Resolved2)); @@ -365,9 +383,9 @@ namespace Umbraco.Tests.Composing TestCollection col2; - using (_factory.BeginScope()) + using (factory.BeginScope()) { - col2 = _factory.GetInstance(); + col2 = factory.GetInstance(); } AssertCollection(col2, typeof(Resolved1), typeof(Resolved2)); @@ -381,7 +399,8 @@ namespace Umbraco.Tests.Composing .Add() .Add(); - var col = builder.CreateCollection(_factory); + var factory = _composition.CreateFactory(); + var col = builder.CreateCollection(factory); AssertCollection(col, typeof(Resolved2), typeof(Resolved1)); } diff --git a/src/Umbraco.Tests/Composing/ContainerTests.cs b/src/Umbraco.Tests/Composing/ContainerConfirmingTests.cs similarity index 79% rename from src/Umbraco.Tests/Composing/ContainerTests.cs rename to src/Umbraco.Tests/Composing/ContainerConfirmingTests.cs index b5be97ce38..fd76dbe8bb 100644 --- a/src/Umbraco.Tests/Composing/ContainerTests.cs +++ b/src/Umbraco.Tests/Composing/ContainerConfirmingTests.cs @@ -8,7 +8,7 @@ using Umbraco.Core.Composing.LightInject; namespace Umbraco.Tests.Composing { [TestFixture] - public class ContainerTests + public class ContainerConfirmingTests { // tests that a container conforms @@ -212,12 +212,61 @@ namespace Umbraco.Tests.Composing Assert.AreEqual(2, things. Count()); } + [Test] + public void CanRegisterSingletonInterface() + { + var register = GetRegister(); + register.RegisterSingleton(); + var factory = register.CreateFactory(); + var s1 = factory.GetInstance(); + var s2 = factory.GetInstance(); + Assert.AreSame(s1, s2); + } + + [Test] + public void CanRegisterSingletonClass() + { + var register = GetRegister(); + register.RegisterSingleton(); + var factory = register.CreateFactory(); + var s1 = factory.GetInstance(); + var s2 = factory.GetInstance(); + Assert.AreSame(s1, s2); + } + + [Test] + public void CanReRegisterSingletonInterface() + { + var register = GetRegister(); + register.RegisterSingleton(); + register.RegisterSingleton(); + var factory = register.CreateFactory(); + var s = factory.GetInstance(); + Assert.IsInstanceOf(s); + } + + [Test] + public void CanRegisterSingletonWithCreate() + { + var register = GetRegister(); + register.RegisterSingleton(c => c.CreateInstance(new Thing1())); + var factory = register.CreateFactory(); + var s1 = factory.GetInstance(); + var s2 = factory.GetInstance(); + Assert.AreSame(s1, s2); + } + public interface IThing { } public abstract class ThingBase : IThing { } public class Thing1 : ThingBase { } public class Thing2 : ThingBase { } + public class Thing3 : ThingBase + { + public Thing3(Thing1 thing) { } + } + public class NeedThings { public NeedThings(IEnumerable things) diff --git a/src/Umbraco.Tests/Composing/ContainerImplementationTests.cs b/src/Umbraco.Tests/Composing/ContainerImplementationTests.cs deleted file mode 100644 index 6e0fdd0912..0000000000 --- a/src/Umbraco.Tests/Composing/ContainerImplementationTests.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System.Collections.Generic; -using NUnit.Framework; -using Umbraco.Core.Composing; - -namespace Umbraco.Tests.Composing -{ - // TODO - // this class should contain everything to ensure that a container implementation - // complies with Umbraco's requirements. - - [TestFixture] - public class ContainerImplementationTests // FIXME merge into ContainerTests or ContainerConformingTests - { - private IRegister CreateRegister() => RegisterFactory.Create(); - - [Test] - public void CanRegisterSingletonInterface() - { - var register = CreateRegister(); - register.RegisterSingleton(); - var factory = register.CreateFactory(); - var s1 = factory.GetInstance(); - var s2 = factory.GetInstance(); - Assert.AreSame(s1, s2); - } - - [Test] - public void CanRegisterSingletonClass() - { - var register = CreateRegister(); - register.RegisterSingleton(); - var factory = register.CreateFactory(); - var s1 = factory.GetInstance(); - var s2 = factory.GetInstance(); - Assert.AreSame(s1, s2); - } - - [Test] - public void CanReRegisterSingletonInterface() - { - var register = CreateRegister(); - register.RegisterSingleton(); - register.RegisterSingleton(); - var factory = register.CreateFactory(); - var s = factory.GetInstance(); - Assert.IsInstanceOf(s); - } - - [Test] - public void CanRegisterSingletonWithCreate() - { - var register = CreateRegister(); - register.RegisterSingleton(c => c.CreateInstance(new TestClass1())); - var factory = register.CreateFactory(); - var s1 = factory.GetInstance(); - var s2 = factory.GetInstance(); - Assert.AreSame(s1, s2); - } - - public interface ITestInterface{} - - public class TestClass1 : ITestInterface{} - - public class TestClass2 : ITestInterface{} - - public class TestClass3 - { - public TestClass3(TestClass1 c) {} - } - } -} diff --git a/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs b/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs index 1b201f3bc5..f66cab18c4 100644 --- a/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs +++ b/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs @@ -18,18 +18,20 @@ namespace Umbraco.Tests.Composing public void PackageActionCollectionBuilderWorks() { var container = RegisterFactory.Create(); - Current.Factory = container.CreateFactory(); // fixme only for LightInject + var composition = new Composition(container, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); composition.GetCollectionBuilder() .Add(() => TypeLoader.GetPackageActions()); + Current.Factory = container.CreateFactory(); + var actions = Current.PackageActions; Assert.AreEqual(2, actions.Count()); // order is unspecified, but both must be there - bool hasAction1 = actions.ElementAt(0) is PackageAction1 || actions.ElementAt(1) is PackageAction1; - bool hasAction2 = actions.ElementAt(0) is PackageAction2 || actions.ElementAt(1) is PackageAction2; + var hasAction1 = actions.ElementAt(0) is PackageAction1 || actions.ElementAt(1) is PackageAction1; + var hasAction2 = actions.ElementAt(0) is PackageAction2 || actions.ElementAt(1) is PackageAction2; Assert.IsTrue(hasAction1); Assert.IsTrue(hasAction2); } diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs b/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs index eeddfa6043..57bf940bc0 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs @@ -55,7 +55,7 @@ namespace Umbraco.Tests.TestHelpers /// A ServiceContext. public ServiceContext GetServiceContextMock(IFactory container = null) { - // fixme - else tests break - something's wrong + // fixme - else some tests break - figure it out container = null; return new ServiceContext( diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index 37c5853c36..e67fd912c8 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -120,7 +120,8 @@ namespace Umbraco.Tests.Testing // get/merge the attributes marking the method and/or the classes Options = TestOptionAttributeBase.GetTestOptions(); - // fixme see CoreRuntime and align! + // fixme - align to runtimes & components - don't redo everything here + var (logger, profiler) = GetLoggers(Options.Logger); var proflogger = new ProfilingLogger(logger, profiler); var cacheHelper = GetCacheHelper(); @@ -203,8 +204,6 @@ namespace Umbraco.Tests.Testing protected virtual void ComposeWeb() { - //TODO: Should we 'just' register the WebRuntimeComponent? - // imported from TestWithSettingsBase // which was inherited by TestWithApplicationBase so pretty much used everywhere Umbraco.Web.Composing.Current.UmbracoContextAccessor = new TestUmbracoContextAccessor(); @@ -284,7 +283,6 @@ namespace Umbraco.Tests.Testing // create the file // create the schema - } protected virtual void ComposeApplication(bool withApplication) @@ -330,7 +328,7 @@ namespace Umbraco.Tests.Testing Composition.RegisterSingleton(f => new UmbracoDatabaseFactory( Constants.System.UmbracoConnectionName, Logger, - new Lazy(() => Mock.Of()))); + new Lazy(Mock.Of))); Composition.RegisterSingleton(f => f.TryGetInstance().SqlContext); Composition.GetCollectionBuilder(); // empty @@ -404,7 +402,7 @@ namespace Umbraco.Tests.Testing // which would lock eg SqlCe .sdf files if (Factory?.TryGetInstance() is ScopeProvider scopeProvider) { - Core.Scoping.Scope scope; + Scope scope; while ((scope = scopeProvider.AmbientScope) != null) { scope.Reset(); @@ -412,11 +410,7 @@ namespace Umbraco.Tests.Testing } } - Current.Reset(); - - // fixme what should we dispose? IRegister or IFactory or? - //Container?.Dispose(); - //Container = null; + Current.Reset(); // disposes the factory // reset all other static things that should not be static ;( UriUtility.ResetAppDomainAppVirtualPath(); diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index 26b5f4c9ce..c84aef7256 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -116,8 +116,7 @@ - - + diff --git a/src/Umbraco.Web/Editors/MacroController.cs b/src/Umbraco.Web/Editors/MacroController.cs index 3c576befb9..9780c23504 100644 --- a/src/Umbraco.Web/Editors/MacroController.cs +++ b/src/Umbraco.Web/Editors/MacroController.cs @@ -136,7 +136,7 @@ namespace Umbraco.Web.Editors var legacyPage = new global::umbraco.page(doc, _variationContextAccessor); UmbracoContext.HttpContext.Items["pageElements"] = legacyPage.Elements; - UmbracoContext.HttpContext.Items[global::Umbraco.Core.Constants.Conventions.Url.AltTemplate] = null; + UmbracoContext.HttpContext.Items[Core.Constants.Conventions.Url.AltTemplate] = null; var renderer = new UmbracoComponentRenderer(UmbracoContext); diff --git a/src/Umbraco.Web/Editors/TourController.cs b/src/Umbraco.Web/Editors/TourController.cs index 021daff423..b45c233aec 100644 --- a/src/Umbraco.Web/Editors/TourController.cs +++ b/src/Umbraco.Web/Editors/TourController.cs @@ -3,8 +3,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; using Newtonsoft.Json; -using Umbraco.Core; -using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.IO; using Umbraco.Web.Models; @@ -16,6 +14,13 @@ namespace Umbraco.Web.Editors [PluginController("UmbracoApi")] public class TourController : UmbracoAuthorizedJsonController { + private readonly TourFilterCollection _filters; + + public TourController(TourFilterCollection filters) + { + _filters = filters; + } + public IEnumerable GetTours() { var result = new List(); @@ -23,13 +28,11 @@ namespace Umbraco.Web.Editors if (UmbracoConfig.For.UmbracoSettings().BackOffice.Tours.EnableTours == false) return result; - var filters = Current.Factory.GetInstance().ToList(); // fixme inject - //get all filters that will be applied to all tour aliases - var aliasOnlyFilters = filters.Where(x => x.PluginName == null && x.TourFileName == null).ToList(); + var aliasOnlyFilters = _filters.Where(x => x.PluginName == null && x.TourFileName == null).ToList(); //don't pass in any filters for core tours that have a plugin name assigned - var nonPluginFilters = filters.Where(x => x.PluginName == null).ToList(); + var nonPluginFilters = _filters.Where(x => x.PluginName == null).ToList(); //add core tour files var coreToursPath = Path.Combine(IOHelper.MapPath(SystemDirectories.Config), "BackOfficeTours"); @@ -45,7 +48,7 @@ namespace Umbraco.Web.Editors foreach (var plugin in Directory.EnumerateDirectories(IOHelper.MapPath(SystemDirectories.AppPlugins))) { var pluginName = Path.GetFileName(plugin.TrimEnd('\\')); - var pluginFilters = filters.Where(x => x.PluginName != null && x.PluginName.IsMatch(pluginName)).ToList(); + var pluginFilters = _filters.Where(x => x.PluginName != null && x.PluginName.IsMatch(pluginName)).ToList(); //If there is any filter applied to match the plugin only (no file or tour alias) then ignore the plugin entirely var isPluginFiltered = pluginFilters.Any(x => x.TourFileName == null && x.TourAlias == null); diff --git a/src/Umbraco.Web/Mvc/RenderRouteHandler.cs b/src/Umbraco.Web/Mvc/RenderRouteHandler.cs index 5ab597c5ca..29e861aec4 100644 --- a/src/Umbraco.Web/Mvc/RenderRouteHandler.cs +++ b/src/Umbraco.Web/Mvc/RenderRouteHandler.cs @@ -30,17 +30,12 @@ namespace Umbraco.Web.Mvc private readonly IUmbracoContextAccessor _umbracoContextAccessor; private readonly UmbracoContext _umbracoContext; - // fixme - that one could / should accept a PublishedRouter (engine) to work on the PublishedRequest (published content request) public RenderRouteHandler(IUmbracoContextAccessor umbracoContextAccessor, IControllerFactory controllerFactory) { _umbracoContextAccessor = umbracoContextAccessor ?? throw new ArgumentNullException(nameof(umbracoContextAccessor)); _controllerFactory = controllerFactory ?? throw new ArgumentNullException(nameof(controllerFactory)); } - // fixme - what about that one? - // called by TemplateRenderer - which is created in - // library - could get an engine without problem it's all ugly anyways - // UmbracoComponentRenderer - ?? that one is not so obvious public RenderRouteHandler(UmbracoContext umbracoContext, IControllerFactory controllerFactory) { _umbracoContext = umbracoContext ?? throw new ArgumentNullException(nameof(umbracoContext)); @@ -396,8 +391,6 @@ namespace Umbraco.Web.Mvc if ((request.HasTemplate == false && Features.Disabled.DisableTemplates == false) && routeDef.HasHijackedRoute == false) { - // fixme - better find a way to inject that engine? or at least Current.Engine of some sort! - var engine = Core.Composing.Current.Factory.GetInstance(); request.UpdateOnMissingTemplate(); // request will go 404 // HandleHttpResponseStatus returns a value indicating that the request should @@ -426,7 +419,7 @@ namespace Umbraco.Web.Mvc routeDef = GetUmbracoRouteDefinition(requestContext, request); } - //no post values, just route to the controller/action requried (local) + //no post values, just route to the controller/action required (local) requestContext.RouteData.Values["controller"] = routeDef.ControllerName; if (string.IsNullOrWhiteSpace(routeDef.ActionName) == false) @@ -448,7 +441,7 @@ namespace Umbraco.Web.Mvc /// internal static IHttpHandler GetWebFormsHandler() { - return (global::umbraco.UmbracoDefault)BuildManager.CreateInstanceFromVirtualPath("~/default.aspx", typeof(global::umbraco.UmbracoDefault)); + return (umbraco.UmbracoDefault) BuildManager.CreateInstanceFromVirtualPath("~/default.aspx", typeof(umbraco.UmbracoDefault)); } private SessionStateBehavior GetSessionStateBehavior(RequestContext requestContext, string controllerName) diff --git a/src/Umbraco.Web/Templates/TemplateRenderer.cs b/src/Umbraco.Web/Templates/TemplateRenderer.cs index 9c2c4973e0..0f5e486a50 100644 --- a/src/Umbraco.Web/Templates/TemplateRenderer.cs +++ b/src/Umbraco.Web/Templates/TemplateRenderer.cs @@ -25,23 +25,20 @@ namespace Umbraco.Web.Templates /// internal class TemplateRenderer { - private readonly IFileService _fileService = Current.Services.FileService; // fixme inject private readonly UmbracoContext _umbracoContext; - private object _oldPageId; private object _oldPageElements; private PublishedRequest _oldPublishedRequest; private object _oldAltTemplate; public TemplateRenderer(UmbracoContext umbracoContext, int pageId, int? altTemplateId) { - if (umbracoContext == null) throw new ArgumentNullException(nameof(umbracoContext)); PageId = pageId; AltTemplate = altTemplateId; - _umbracoContext = umbracoContext; + _umbracoContext = umbracoContext ?? throw new ArgumentNullException(nameof(umbracoContext)); } - // todo - inject! - private PublishedRouter PublishedRouter => Core.Composing.Current.Factory.GetInstance(); + private IFileService FileService => Current.Services.FileService; // fixme inject + private PublishedRouter PublishedRouter => Core.Composing.Current.Factory.GetInstance(); // fixme inject /// @@ -58,10 +55,9 @@ namespace Umbraco.Web.Templates { if (writer == null) throw new ArgumentNullException(nameof(writer)); - // instanciate a request a process + // instantiate a request and process // important to use CleanedUmbracoUrl - lowercase path-only version of the current url, though this isn't going to matter // terribly much for this implementation since we are just creating a doc content request to modify it's properties manually. - // fixme - previously that would create an aengine... var contentRequest = PublishedRouter.CreateRequest(_umbracoContext); var doc = contentRequest.UmbracoContext.ContentCache.GetById(PageId); @@ -91,8 +87,8 @@ namespace Umbraco.Web.Templates contentRequest.PublishedContent = doc; //set the template, either based on the AltTemplate found or the standard template of the doc contentRequest.TemplateModel = UmbracoConfig.For.UmbracoSettings().WebRouting.DisableAlternativeTemplates || AltTemplate.HasValue == false - ? _fileService.GetTemplate(doc.TemplateId) - : _fileService.GetTemplate(AltTemplate.Value); + ? FileService.GetTemplate(doc.TemplateId) + : FileService.GetTemplate(AltTemplate.Value); //if there is not template then exit if (contentRequest.HasTemplate == false) @@ -160,8 +156,8 @@ namespace Umbraco.Web.Templates break; case RenderingEngine.WebForms: default: - var webFormshandler = (global::umbraco.UmbracoDefault)BuildManager - .CreateInstanceFromVirtualPath("~/default.aspx", typeof(global::umbraco.UmbracoDefault)); + var webFormshandler = (UmbracoDefault) BuildManager + .CreateInstanceFromVirtualPath("~/default.aspx", typeof(UmbracoDefault)); //the 'true' parameter will ensure that the current query strings are carried through, we don't have // to build up the url again, it will just work. _umbracoContext.HttpContext.Server.Execute(webFormshandler, sw, true); @@ -213,11 +209,10 @@ namespace Umbraco.Web.Templates private void SaveExistingItems() { //Many objects require that these legacy items are in the http context items... before we render this template we need to first - //save the values in them so that we can re-set them after we render so the rest of the execution works as per normal - _oldPageId = _umbracoContext.PageId; + //save the values in them so that we can re-set them after we render so the rest of the execution works as per normal _oldPageElements = _umbracoContext.HttpContext.Items["pageElements"]; _oldPublishedRequest = _umbracoContext.PublishedRequest; - _oldAltTemplate = _umbracoContext.HttpContext.Items[Umbraco.Core.Constants.Conventions.Url.AltTemplate]; + _oldAltTemplate = _umbracoContext.HttpContext.Items[Core.Constants.Conventions.Url.AltTemplate]; } /// @@ -227,7 +222,7 @@ namespace Umbraco.Web.Templates { _umbracoContext.PublishedRequest = _oldPublishedRequest; _umbracoContext.HttpContext.Items["pageElements"] = _oldPageElements; - _umbracoContext.HttpContext.Items[Umbraco.Core.Constants.Conventions.Url.AltTemplate] = _oldAltTemplate; + _umbracoContext.HttpContext.Items[Core.Constants.Conventions.Url.AltTemplate] = _oldAltTemplate; } } } diff --git a/src/Umbraco.Web/UmbracoComponentRenderer.cs b/src/Umbraco.Web/UmbracoComponentRenderer.cs index 76a2f17636..e2d4ecfc39 100644 --- a/src/Umbraco.Web/UmbracoComponentRenderer.cs +++ b/src/Umbraco.Web/UmbracoComponentRenderer.cs @@ -1,17 +1,12 @@ using System; using System.Collections; -using System.Globalization; using System.IO; using System.Web; using System.Web.UI; using Umbraco.Core; -using Umbraco.Core.Models; using Umbraco.Web.Templates; using umbraco; using System.Collections.Generic; -using umbraco.presentation.templateControls; -using Umbraco.Core.Exceptions; -using Umbraco.Core.Models.PublishedContent; using Umbraco.Web.Composing; using Umbraco.Web.Macros; From e9de6c1fc90f394412dab0c4ea246b7888cfaecb Mon Sep 17 00:00:00 2001 From: Stephan Date: Wed, 28 Nov 2018 17:35:12 +0100 Subject: [PATCH 110/469] Naming is hard --- src/Umbraco.Core/Components/Composition.cs | 2 +- .../Components/CompositionExtensions.cs | 16 +++---- .../Runtime/CoreRuntimeComponent.cs | 16 +++---- .../DistributedCache/DistributedCacheTests.cs | 2 +- .../PublishedMediaCacheTests.cs | 2 +- .../Composing/CollectionBuildersTests.cs | 48 +++++++++---------- .../Composing/LazyCollectionBuilderTests.cs | 10 ++-- .../Composing/PackageActionCollectionTests.cs | 2 +- .../Integration/ContentEventsTests.cs | 2 +- .../Models/Mapping/AutoMapperTests.cs | 2 +- .../PropertyEditors/ImageCropperTest.cs | 2 +- .../Published/ConvertersTests.cs | 2 +- .../PublishedContentTestBase.cs | 2 +- .../PublishedContent/PublishedMediaTests.cs | 2 +- .../Scoping/ScopeEventDispatcherTests.cs | 2 +- .../Scoping/ScopedNuCacheTests.cs | 2 +- .../Scoping/ScopedRepositoryTests.cs | 2 +- src/Umbraco.Tests/Scoping/ScopedXmlTests.cs | 2 +- .../ContentTypeServiceVariantsTests.cs | 2 +- .../Services/Importing/PackageImportTests.cs | 2 +- .../TestHelpers/BaseUsingSqlCeSyntax.cs | 2 +- .../TestHelpers/TestWithDatabaseBase.cs | 2 +- src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 16 +++---- src/Umbraco.Web/CompositionExtensions.cs | 14 +++--- .../Runtime/WebRuntimeComponent.cs | 22 ++++----- 25 files changed, 89 insertions(+), 89 deletions(-) diff --git a/src/Umbraco.Core/Components/Composition.cs b/src/Umbraco.Core/Components/Composition.cs index c81fe388ba..525d8b773e 100644 --- a/src/Umbraco.Core/Components/Composition.cs +++ b/src/Umbraco.Core/Components/Composition.cs @@ -98,7 +98,7 @@ namespace Umbraco.Core.Components /// /// The type of the collection builder. /// The collection builder. - public TBuilder GetCollectionBuilder() + public TBuilder WithCollectionBuilder() where TBuilder: ICollectionBuilder, new() { var typeOfBuilder = typeof(TBuilder); diff --git a/src/Umbraco.Core/Components/CompositionExtensions.cs b/src/Umbraco.Core/Components/CompositionExtensions.cs index 8ac8c66bc1..f41ecf7186 100644 --- a/src/Umbraco.Core/Components/CompositionExtensions.cs +++ b/src/Umbraco.Core/Components/CompositionExtensions.cs @@ -24,56 +24,56 @@ namespace Umbraco.Core.Components /// /// The composition. public static CacheRefresherCollectionBuilder CacheRefreshers(this Composition composition) - => composition.GetCollectionBuilder(); + => composition.WithCollectionBuilder(); /// /// Gets the mappers collection builder. /// /// The composition. public static MapperCollectionBuilder Mappers(this Composition composition) - => composition.GetCollectionBuilder(); + => composition.WithCollectionBuilder(); /// /// Gets the package actions collection builder. /// /// The composition. internal static PackageActionCollectionBuilder PackageActions(this Composition composition) - => composition.GetCollectionBuilder(); + => composition.WithCollectionBuilder(); /// /// Gets the data editor collection builder. /// /// The composition. public static DataEditorCollectionBuilder DataEditors(this Composition composition) - => composition.GetCollectionBuilder(); + => composition.WithCollectionBuilder(); /// /// Gets the property value converters collection builder. /// /// The composition. public static PropertyValueConverterCollectionBuilder PropertyValueConverters(this Composition composition) - => composition.GetCollectionBuilder(); + => composition.WithCollectionBuilder(); /// /// Gets the url segment providers collection builder. /// /// The composition. public static UrlSegmentProviderCollectionBuilder UrlSegmentProviders(this Composition composition) - => composition.GetCollectionBuilder(); + => composition.WithCollectionBuilder(); /// /// Gets the validators collection builder. /// /// The composition. internal static ManifestValueValidatorCollectionBuilder Validators(this Composition composition) - => composition.GetCollectionBuilder(); + => composition.WithCollectionBuilder(); /// /// Gets the post-migrations collection builder. /// /// The composition. internal static PostMigrationCollectionBuilder PostMigrations(this Composition composition) - => composition.GetCollectionBuilder(); + => composition.WithCollectionBuilder(); #endregion diff --git a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs index 63cd4e726b..72d6d37010 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs @@ -45,7 +45,7 @@ namespace Umbraco.Core.Runtime // register persistence mappers - required by database factory so needs to be done here // means the only place the collection can be modified is in a runtime - afterwards it // has been frozen and it is too late - composition.GetCollectionBuilder().AddCoreMappers(); + composition.WithCollectionBuilder().AddCoreMappers(); // register the scope provider composition.RegisterSingleton(); // implements both IScopeProvider and IScopeAccessor @@ -60,7 +60,7 @@ namespace Umbraco.Core.Runtime composition.RegisterSingleton(); // register our predefined validators - composition.GetCollectionBuilder() + composition.WithCollectionBuilder() .Add() .Add() .Add() @@ -69,7 +69,7 @@ namespace Umbraco.Core.Runtime .Add(); // properties and parameters derive from data editors - composition.GetCollectionBuilder() + composition.WithCollectionBuilder() .Add(() => composition.TypeLoader.GetDataEditors()); composition.RegisterSingleton(); composition.RegisterSingleton(); @@ -96,13 +96,13 @@ namespace Umbraco.Core.Runtime factory.GetInstance(), true, new DatabaseServerMessengerOptions())); - composition.GetCollectionBuilder() + composition.WithCollectionBuilder() .Add(() => composition.TypeLoader.GetCacheRefreshers()); - composition.GetCollectionBuilder() + composition.WithCollectionBuilder() .Add(() => composition.TypeLoader.GetPackageActions()); - composition.GetCollectionBuilder() + composition.WithCollectionBuilder() .Append(composition.TypeLoader.GetTypes()); composition.RegisterSingleton(); @@ -110,10 +110,10 @@ namespace Umbraco.Core.Runtime composition.RegisterSingleton(factory => new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(factory.GetInstance()))); - composition.GetCollectionBuilder() + composition.WithCollectionBuilder() .Append(); - composition.GetCollectionBuilder() + composition.WithCollectionBuilder() .Add(() => composition.TypeLoader.GetTypes()); composition.RegisterSingleton(factory => new MigrationBuilder(factory)); diff --git a/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs b/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs index 684e06b300..a57ab93f3c 100644 --- a/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs +++ b/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs @@ -30,7 +30,7 @@ namespace Umbraco.Tests.Cache.DistributedCache register.Register(_ => new TestServerRegistrar()); register.RegisterSingleton(_ => new TestServerMessenger()); - composition.GetCollectionBuilder() + composition.WithCollectionBuilder() .Add(); Current.Factory = register.CreateFactory(); diff --git a/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs b/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs index a0ab75f0f9..ef50f0b48a 100644 --- a/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs +++ b/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs @@ -29,7 +29,7 @@ namespace Umbraco.Tests.Cache.PublishedCache { base.Compose(); - Composition.GetCollectionBuilder() + Composition.WithCollectionBuilder() .Clear() .Append(); } diff --git a/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs b/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs index 0d0374d37a..59230c356c 100644 --- a/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs +++ b/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs @@ -33,7 +33,7 @@ namespace Umbraco.Tests.Composing [Test] public void ContainsTypes() { - var builder = _composition.GetCollectionBuilder() + var builder = _composition.WithCollectionBuilder() .Append() .Append(); @@ -50,7 +50,7 @@ namespace Umbraco.Tests.Composing [Test] public void CanClearBuilderBeforeCollectionIsCreated() { - var builder = _composition.GetCollectionBuilder() + var builder = _composition.WithCollectionBuilder() .Append() .Append(); @@ -66,7 +66,7 @@ namespace Umbraco.Tests.Composing [Test] public void CannotClearBuilderOnceCollectionIsCreated() { - var builder = _composition.GetCollectionBuilder() + var builder = _composition.WithCollectionBuilder() .Append() .Append(); @@ -79,7 +79,7 @@ namespace Umbraco.Tests.Composing [Test] public void CanAppendToBuilder() { - var builder = _composition.GetCollectionBuilder(); + var builder = _composition.WithCollectionBuilder(); builder.Append(); builder.Append(); @@ -95,7 +95,7 @@ namespace Umbraco.Tests.Composing [Test] public void CannotAppendToBuilderOnceCollectionIsCreated() { - var builder = _composition.GetCollectionBuilder(); + var builder = _composition.WithCollectionBuilder(); var factory = _composition.CreateFactory(); var col = builder.CreateCollection(factory); @@ -108,7 +108,7 @@ namespace Umbraco.Tests.Composing [Test] public void CanAppendDuplicateToBuilderAndDeDuplicate() { - var builder = _composition.GetCollectionBuilder(); + var builder = _composition.WithCollectionBuilder(); builder.Append(); builder.Append(); @@ -121,7 +121,7 @@ namespace Umbraco.Tests.Composing [Test] public void CannotAppendInvalidTypeToBUilder() { - var builder = _composition.GetCollectionBuilder(); + var builder = _composition.WithCollectionBuilder(); //builder.Append(); // does not compile Assert.Throws(() => @@ -132,7 +132,7 @@ namespace Umbraco.Tests.Composing [Test] public void CanRemoveFromBuilder() { - var builder = _composition.GetCollectionBuilder() + var builder = _composition.WithCollectionBuilder() .Append() .Append() .Remove(); @@ -149,7 +149,7 @@ namespace Umbraco.Tests.Composing [Test] public void CanRemoveMissingFromBuilder() { - var builder = _composition.GetCollectionBuilder() + var builder = _composition.WithCollectionBuilder() .Append() .Append() .Remove(); @@ -162,7 +162,7 @@ namespace Umbraco.Tests.Composing [Test] public void CannotRemoveFromBuilderOnceCollectionIsCreated() { - var builder = _composition.GetCollectionBuilder() + var builder = _composition.WithCollectionBuilder() .Append() .Append(); @@ -176,7 +176,7 @@ namespace Umbraco.Tests.Composing [Test] public void CanInsertIntoBuilder() { - var builder = _composition.GetCollectionBuilder() + var builder = _composition.WithCollectionBuilder() .Append() .Append() .Insert(); @@ -193,7 +193,7 @@ namespace Umbraco.Tests.Composing [Test] public void CannotInsertIntoBuilderOnceCollectionIsCreated() { - var builder = _composition.GetCollectionBuilder() + var builder = _composition.WithCollectionBuilder() .Append() .Append(); @@ -207,7 +207,7 @@ namespace Umbraco.Tests.Composing [Test] public void CanInsertDuplicateIntoBuilderAndDeDuplicate() { - var builder = _composition.GetCollectionBuilder() + var builder = _composition.WithCollectionBuilder() .Append() .Append() .Insert(); @@ -220,7 +220,7 @@ namespace Umbraco.Tests.Composing [Test] public void CanInsertIntoEmptyBuilder() { - var builder = _composition.GetCollectionBuilder(); + var builder = _composition.WithCollectionBuilder(); builder.Insert(); var factory = _composition.CreateFactory(); @@ -231,7 +231,7 @@ namespace Umbraco.Tests.Composing [Test] public void CannotInsertIntoBuilderAtWrongIndex() { - var builder = _composition.GetCollectionBuilder() + var builder = _composition.WithCollectionBuilder() .Append() .Append(); @@ -247,7 +247,7 @@ namespace Umbraco.Tests.Composing [Test] public void CanInsertIntoBuilderBefore() { - var builder = _composition.GetCollectionBuilder() + var builder = _composition.WithCollectionBuilder() .Append() .Append() .InsertBefore(); @@ -264,7 +264,7 @@ namespace Umbraco.Tests.Composing [Test] public void CannotInsertIntoBuilderBeforeOnceCollectionIsCreated() { - var builder = _composition.GetCollectionBuilder() + var builder = _composition.WithCollectionBuilder() .Append() .Append(); @@ -278,7 +278,7 @@ namespace Umbraco.Tests.Composing [Test] public void CanInsertDuplicateIntoBuilderBeforeAndDeDuplicate() { - var builder = _composition.GetCollectionBuilder() + var builder = _composition.WithCollectionBuilder() .Append() .Append() .InsertBefore(); @@ -291,7 +291,7 @@ namespace Umbraco.Tests.Composing [Test] public void CannotInsertIntoBuilderBeforeMissing() { - var builder = _composition.GetCollectionBuilder() + var builder = _composition.WithCollectionBuilder() .Append(); Assert.Throws(() => @@ -302,7 +302,7 @@ namespace Umbraco.Tests.Composing [Test] public void ScopeBuilderCreatesScopedCollection() { - _composition.GetCollectionBuilder() + _composition.WithCollectionBuilder() .Append() .Append(); @@ -324,7 +324,7 @@ namespace Umbraco.Tests.Composing [Test] public void TransientBuilderCreatesTransientCollection() { - _composition.GetCollectionBuilder() + _composition.WithCollectionBuilder() .Append() .Append(); @@ -346,7 +346,7 @@ namespace Umbraco.Tests.Composing [Test] public void BuilderRespectsTypesOrder() { - var builder = _composition.GetCollectionBuilder() + var builder = _composition.WithCollectionBuilder() .Append() .Insert() .InsertBefore(); @@ -359,7 +359,7 @@ namespace Umbraco.Tests.Composing [Test] public void ScopeBuilderRespectsContainerScope() { - _composition.GetCollectionBuilder() + _composition.WithCollectionBuilder() .Append() .Append(); @@ -395,7 +395,7 @@ namespace Umbraco.Tests.Composing [Test] public void WeightedBuilderCreatesWeightedCollection() { - var builder = _composition.GetCollectionBuilder() + var builder = _composition.WithCollectionBuilder() .Add() .Add(); diff --git a/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs b/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs index b3009ae90f..656adedf52 100644 --- a/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs +++ b/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs @@ -42,7 +42,7 @@ namespace Umbraco.Tests.Composing var container = CreateRegister(); var composition = new Composition(container, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); - composition.GetCollectionBuilder() + composition.WithCollectionBuilder() .Add() .Add() .Add() @@ -68,7 +68,7 @@ namespace Umbraco.Tests.Composing var container = CreateRegister(); var composition = new Composition(container, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); - composition.GetCollectionBuilder() + composition.WithCollectionBuilder() .Add(() => new[] { typeof(TransientObject3), typeof(TransientObject2) }) .Add(() => new[] { typeof(TransientObject3), typeof(TransientObject2) }) .Add(() => new[] { typeof(TransientObject1) }); @@ -93,7 +93,7 @@ namespace Umbraco.Tests.Composing var container = CreateRegister(); var composition = new Composition(container, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); - composition.GetCollectionBuilder() + composition.WithCollectionBuilder() .Add() .Add() .Add() @@ -119,7 +119,7 @@ namespace Umbraco.Tests.Composing var container = CreateRegister(); var composition = new Composition(container, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); - composition.GetCollectionBuilder() + composition.WithCollectionBuilder() .Add() // illegal, does not implement the interface! @@ -143,7 +143,7 @@ namespace Umbraco.Tests.Composing var container = CreateRegister(); var composition = new Composition(container, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); - composition.GetCollectionBuilder() + composition.WithCollectionBuilder() .Add() .Add(() => new[] { typeof(TransientObject3), typeof(TransientObject2), typeof(TransientObject1) }) .Exclude(); diff --git a/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs b/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs index f66cab18c4..1f08e60375 100644 --- a/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs +++ b/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs @@ -21,7 +21,7 @@ namespace Umbraco.Tests.Composing var composition = new Composition(container, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); - composition.GetCollectionBuilder() + composition.WithCollectionBuilder() .Add(() => TypeLoader.GetPackageActions()); Current.Factory = container.CreateFactory(); diff --git a/src/Umbraco.Tests/Integration/ContentEventsTests.cs b/src/Umbraco.Tests/Integration/ContentEventsTests.cs index df7bdb5ccf..c138e48bfe 100644 --- a/src/Umbraco.Tests/Integration/ContentEventsTests.cs +++ b/src/Umbraco.Tests/Integration/ContentEventsTests.cs @@ -52,7 +52,7 @@ namespace Umbraco.Tests.Integration Composition.Register(_ => new TestServerRegistrar()); // localhost-only Composition.RegisterSingleton(); - Composition.GetCollectionBuilder() + Composition.WithCollectionBuilder() .Add() .Add() .Add(); diff --git a/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs b/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs index 4d813b5059..c908cca64e 100644 --- a/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs +++ b/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs @@ -31,7 +31,7 @@ namespace Umbraco.Tests.Models.Mapping Composition.Register(_ => manifestBuilder); Func> typeListProducerList = Enumerable.Empty; - Composition.GetCollectionBuilder() + Composition.WithCollectionBuilder() .Clear() .Add(typeListProducerList); } diff --git a/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs b/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs index 8693f65d4d..1a869183bb 100644 --- a/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs +++ b/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs @@ -72,7 +72,7 @@ namespace Umbraco.Tests.PropertyEditors var container = RegisterFactory.Create(); var composition = new Composition(container, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); - composition.GetCollectionBuilder(); + composition.WithCollectionBuilder(); Current.Factory = container.CreateFactory(); diff --git a/src/Umbraco.Tests/Published/ConvertersTests.cs b/src/Umbraco.Tests/Published/ConvertersTests.cs index 026aee4bb1..0937c5ea70 100644 --- a/src/Umbraco.Tests/Published/ConvertersTests.cs +++ b/src/Umbraco.Tests/Published/ConvertersTests.cs @@ -178,7 +178,7 @@ namespace Umbraco.Tests.Published var composition = new Composition(register, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); - composition.GetCollectionBuilder() + composition.WithCollectionBuilder() .Append() .Append(); diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs index 1c66f5a6d3..d18c6b6668 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs @@ -23,7 +23,7 @@ namespace Umbraco.Tests.PublishedContent // fixme - what about the if (PropertyValueConvertersResolver.HasCurrent == false) ?? // can we risk double - registering and then, what happens? - Composition.GetCollectionBuilder() + Composition.WithCollectionBuilder() .Clear() .Append() .Append() diff --git a/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs index 9d603a9569..be2f09b0dd 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs @@ -39,7 +39,7 @@ namespace Umbraco.Tests.PublishedContent { base.Compose(); - Composition.GetCollectionBuilder() + Composition.WithCollectionBuilder() .Clear() .Append(); } diff --git a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs index 04703e3195..933d8e9f7e 100644 --- a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs @@ -39,7 +39,7 @@ namespace Umbraco.Tests.Scoping _testObjects = new TestObjects(register); register.RegisterSingleton(factory => new FileSystems(factory, factory.TryGetInstance())); - composition.GetCollectionBuilder(); + composition.WithCollectionBuilder(); Current.Factory = register.CreateFactory(); diff --git a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs index 50d0f42626..1ab6f8d392 100644 --- a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs @@ -46,7 +46,7 @@ namespace Umbraco.Tests.Scoping // so doing all this mess Composition.RegisterSingleton(); Composition.RegisterSingleton(f => Mock.Of()); - Composition.GetCollectionBuilder() + Composition.WithCollectionBuilder() .Add(() => Composition.TypeLoader.GetCacheRefreshers()); } diff --git a/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs b/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs index b00dfbaa03..815da6e6a6 100644 --- a/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs @@ -32,7 +32,7 @@ namespace Umbraco.Tests.Scoping // so doing all this mess Composition.RegisterSingleton(); Composition.RegisterSingleton(f => Mock.Of()); - Composition.GetCollectionBuilder() + Composition.WithCollectionBuilder() .Add(() => Composition.TypeLoader.GetCacheRefreshers()); } diff --git a/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs b/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs index c829643964..8855bc5a13 100644 --- a/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs @@ -34,7 +34,7 @@ namespace Umbraco.Tests.Scoping // so doing all this mess Composition.RegisterSingleton(); Composition.RegisterSingleton(f => Mock.Of()); - Composition.GetCollectionBuilder() + Composition.WithCollectionBuilder() .Add(() => Composition.TypeLoader.GetCacheRefreshers()); } diff --git a/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs b/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs index 17c31ca409..5cd1cdd1bc 100644 --- a/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs +++ b/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs @@ -37,7 +37,7 @@ namespace Umbraco.Tests.Services // pfew - see note in ScopedNuCacheTests? Composition.RegisterSingleton(); Composition.RegisterSingleton(f => Mock.Of()); - Composition.GetCollectionBuilder() + Composition.WithCollectionBuilder() .Add(() => Composition.TypeLoader.GetCacheRefreshers()); } diff --git a/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs b/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs index 49b52f4276..8e67aa4e1f 100644 --- a/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs +++ b/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs @@ -49,7 +49,7 @@ namespace Umbraco.Tests.Services.Importing // pollute everything, they are ignored by the type finder and explicitely // added to the editors collection - Composition.GetCollectionBuilder() + Composition.WithCollectionBuilder() .Add() .Add(); } diff --git a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs index 846fcfac5d..9dd8324e9f 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs @@ -48,7 +48,7 @@ namespace Umbraco.Tests.TestHelpers false); container.RegisterInstance(pluginManager); - composition.GetCollectionBuilder() + composition.WithCollectionBuilder() .Add(() => Current.TypeLoader.GetAssignedMapperTypes()); var factory = Current.Factory = container.CreateFactory(); diff --git a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs index cc3ddb6f6a..72468f89b8 100644 --- a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs +++ b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs @@ -76,7 +76,7 @@ namespace Umbraco.Tests.TestHelpers Composition.Register(factory => PublishedSnapshotService); Composition.Register(factory => DefaultCultureAccessor); - Composition.GetCollectionBuilder() + Composition.WithCollectionBuilder() .Clear() .Add(() => Composition.TypeLoader.GetDataEditors()); diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index e67fd912c8..67fa8361ba 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -211,7 +211,7 @@ namespace Umbraco.Tests.Testing // web Composition.Register(_ => Umbraco.Web.Composing.Current.UmbracoContextAccessor); Composition.RegisterSingleton(); - Composition.GetCollectionBuilder(); + Composition.WithCollectionBuilder(); Composition.Register(); Composition.Register(); } @@ -224,14 +224,14 @@ namespace Umbraco.Tests.Testing Composition.RegisterSingleton(f => runtimeStateMock.Object); // ah... - Composition.GetCollectionBuilder(); - Composition.GetCollectionBuilder(); + Composition.WithCollectionBuilder(); + Composition.WithCollectionBuilder(); Composition.RegisterSingleton(); Composition.RegisterSingleton(); // register empty content apps collection - Composition.GetCollectionBuilder(); + Composition.WithCollectionBuilder(); } protected virtual void ComposeAutoMapper(bool configure) @@ -321,7 +321,7 @@ namespace Umbraco.Tests.Testing Composition.RegisterSingleton(); // register application stuff (database factory & context, services...) - Composition.GetCollectionBuilder() + Composition.WithCollectionBuilder() .AddCoreMappers(); Composition.RegisterSingleton(_ => new TransientEventMessagesFactory()); @@ -331,7 +331,7 @@ namespace Umbraco.Tests.Testing new Lazy(Mock.Of))); Composition.RegisterSingleton(f => f.TryGetInstance().SqlContext); - Composition.GetCollectionBuilder(); // empty + Composition.WithCollectionBuilder(); // empty Composition.RegisterSingleton(factory => TestObjects.GetScopeProvider(factory.TryGetInstance(), factory.TryGetInstance(), factory.TryGetInstance())); @@ -344,11 +344,11 @@ namespace Umbraco.Tests.Testing Composition.RegisterSingleton(); // somehow property editor ends up wanting this - Composition.GetCollectionBuilder(); + Composition.WithCollectionBuilder(); Composition.RegisterSingleton(); // note - don't register collections, use builders - Composition.GetCollectionBuilder(); + Composition.WithCollectionBuilder(); Composition.RegisterSingleton(); Composition.RegisterSingleton(); } diff --git a/src/Umbraco.Web/CompositionExtensions.cs b/src/Umbraco.Web/CompositionExtensions.cs index ee57ca98cb..7725fe6524 100644 --- a/src/Umbraco.Web/CompositionExtensions.cs +++ b/src/Umbraco.Web/CompositionExtensions.cs @@ -30,7 +30,7 @@ namespace Umbraco.Core.Components /// The composition. /// internal static ActionCollectionBuilder Actions(this Composition composition) - => composition.GetCollectionBuilder(); + => composition.WithCollectionBuilder(); /// /// Gets the content apps collection builder. @@ -38,7 +38,7 @@ namespace Umbraco.Core.Components /// The composition. /// public static ContentAppDefinitionCollectionBuilder ContentApps(this Composition composition) - => composition.GetCollectionBuilder(); + => composition.WithCollectionBuilder(); /// /// Gets the content finders collection builder. @@ -46,7 +46,7 @@ namespace Umbraco.Core.Components /// The composition. /// public static ContentFinderCollectionBuilder ContentFinders(this Composition composition) - => composition.GetCollectionBuilder(); + => composition.WithCollectionBuilder(); /// /// Gets the editor validators collection builder. @@ -54,7 +54,7 @@ namespace Umbraco.Core.Components /// The composition. /// internal static EditorValidatorCollectionBuilder EditorValidators(this Composition composition) - => composition.GetCollectionBuilder(); + => composition.WithCollectionBuilder(); /// /// Gets the filtered controller factories collection builder. @@ -62,21 +62,21 @@ namespace Umbraco.Core.Components /// The composition. /// public static FilteredControllerFactoryCollectionBuilder FilderedControllerFactory(this Composition composition) - => composition.GetCollectionBuilder(); + => composition.WithCollectionBuilder(); /// /// Gets the health checks collection builder. /// /// The composition. public static HealthCheckCollectionBuilder HealthChecks(this Composition composition) - => composition.GetCollectionBuilder(); + => composition.WithCollectionBuilder(); /// /// Gets the url providers collection builder. /// /// The composition. internal static UrlProviderCollectionBuilder UrlProviders(this Composition composition) - => composition.GetCollectionBuilder(); + => composition.WithCollectionBuilder(); #endregion diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs index 29e2cc1058..e5973b24bc 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs @@ -123,20 +123,20 @@ namespace Umbraco.Web.Runtime .ComposeMvcControllers(GetType().Assembly) .ComposeApiControllers(GetType().Assembly); - composition.GetCollectionBuilder() + composition.WithCollectionBuilder() .Add(() => composition.TypeLoader.GetTypes()); // fixme which searchable trees?! - composition.GetCollectionBuilder() + composition.WithCollectionBuilder() .Add(() => composition.TypeLoader.GetTypes()); - composition.GetCollectionBuilder(); + composition.WithCollectionBuilder(); composition.RegisterSingleton(); // set the default RenderMvcController Current.DefaultRenderMvcControllerType = typeof(RenderMvcController); // fixme WRONG! - composition.GetCollectionBuilder() + composition.WithCollectionBuilder() .Add(() => composition.TypeLoader.GetTypes()); var surfaceControllerTypes = new SurfaceControllerTypeCollection(composition.TypeLoader.GetSurfaceControllers()); @@ -150,24 +150,24 @@ namespace Umbraco.Web.Runtime // here because there cannot be two converters for one property editor - and we want the full // RteMacroRenderingValueConverter that converts macros, etc. So remove TinyMceValueConverter. // (the limited one, defined in Core, is there for tests) - same for others - composition.GetCollectionBuilder() + composition.WithCollectionBuilder() .Remove() .Remove() .Remove(); // add all known factories, devs can then modify this list on application // startup either by binding to events or in their own global.asax - composition.GetCollectionBuilder() + composition.WithCollectionBuilder() .Append(); - composition.GetCollectionBuilder() + composition.WithCollectionBuilder() .Append() .Append() .Append(); composition.RegisterSingleton(); - composition.GetCollectionBuilder() + composition.WithCollectionBuilder() // all built-in finders in the correct order, // devs can then modify this list on application startup .Append() @@ -182,10 +182,10 @@ namespace Umbraco.Web.Runtime composition.RegisterSingleton(); // register *all* checks, except those marked [HideFromTypeFinder] of course - composition.GetCollectionBuilder() + composition.WithCollectionBuilder() .Add(() => composition.TypeLoader.GetTypes()); - composition.GetCollectionBuilder() + composition.WithCollectionBuilder() .Add(() => composition.TypeLoader.GetTypes()); // auto-register views @@ -202,7 +202,7 @@ namespace Umbraco.Web.Runtime composition.RegisterSingleton(); // register known content apps - composition.GetCollectionBuilder() + composition.WithCollectionBuilder() .Append() .Append() .Append(); From c6891c6c7000f4e0bcda5d954379aff512d30ef5 Mon Sep 17 00:00:00 2001 From: Stephan Date: Thu, 29 Nov 2018 10:35:16 +0100 Subject: [PATCH 111/469] RegisterUnique --- src/Umbraco.Core/Components/Composition.cs | 85 +++++++- .../Components/CompositionExtensions.cs | 72 +++++-- .../Composers/FileSystemsComposer.cs | 6 +- .../Composers/RepositoriesComposer.cs | 70 +++--- .../Composing/Composers/ServicesComposer.cs | 62 +++--- .../Composing/CompositionExtensions.cs | 32 +++ src/Umbraco.Core/Composing/IFactory.cs | 8 + src/Umbraco.Core/Composing/IRegister.cs | 8 - src/Umbraco.Core/Composing/Lifetime.cs | 21 ++ .../LightInject/LightInjectContainer.cs | 12 +- .../LightInject}/LightInjectException.cs | 4 +- .../LightInject/LightInjectExtensions.cs | 199 ------------------ .../Composing/RegisterExtensions.cs | 62 +----- src/Umbraco.Core/IRuntime.cs | 3 +- src/Umbraco.Core/Runtime/CoreRuntime.cs | 27 +-- .../Runtime/CoreRuntimeComponent.cs | 24 +-- src/Umbraco.Core/Umbraco.Core.csproj | 4 +- .../DistributedCache/DistributedCacheTests.cs | 6 +- ...ngTests.cs => ContainerConformingTests.cs} | 57 ++++- .../Composing/PackageActionCollectionTests.cs | 2 +- .../CoreThings/TryConvertToTests.cs | 3 +- src/Umbraco.Tests/IO/FileSystemsTests.cs | 4 +- .../Integration/ContentEventsTests.cs | 2 +- .../Models/Mapping/AutoMapperTests.cs | 4 +- .../Mapping/ContentTypeModelMappingTests.cs | 14 +- .../Mapping/ContentWebModelMappingTests.cs | 5 +- .../PartialViewRepositoryTests.cs | 4 +- .../Repositories/ScriptRepositoryTest.cs | 4 +- .../PropertyEditors/ImageCropperTest.cs | 2 +- .../PropertyEditorValueEditorTests.cs | 5 +- .../Published/ConvertersTests.cs | 2 +- .../PublishedContentLanguageVariantTests.cs | 5 +- .../PublishedContentSnapshotTestBase.cs | 4 +- .../PublishedContent/PublishedContentTests.cs | 8 +- .../Routing/RenderRouteHandlerTests.cs | 19 +- .../Routing/UrlRoutingTestBase.cs | 2 +- .../Routing/UrlsProviderWithDomainsTests.cs | 2 +- .../Routing/UrlsWithNestedDomains.cs | 2 +- .../Runtimes/CoreRuntimeTests.cs | 11 +- .../Scoping/ScopeEventDispatcherTests.cs | 4 +- .../Scoping/ScopedNuCacheTests.cs | 4 +- .../Scoping/ScopedRepositoryTests.cs | 4 +- src/Umbraco.Tests/Scoping/ScopedXmlTests.cs | 4 +- .../Services/ContentServiceTests.cs | 12 +- .../ContentTypeServiceVariantsTests.cs | 5 +- .../Strings/DefaultShortStringHelperTests.cs | 2 +- .../Strings/StringExtensionsTests.cs | 12 +- .../TestHelpers/BaseUsingSqlCeSyntax.cs | 10 +- src/Umbraco.Tests/TestHelpers/BaseWebTest.cs | 4 +- .../TestHelpers/TestWithDatabaseBase.cs | 2 +- src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 69 +++--- .../TreesAndSections/SectionTests.cs | 4 +- src/Umbraco.Tests/Umbraco.Tests.csproj | 2 +- .../UmbracoExamine/ExamineBaseTest.cs | 2 +- .../Web/Controllers/ContentControllerTests.cs | 16 +- .../Web/Controllers/UsersControllerTests.cs | 6 +- .../Components/NotificationsComponent.cs | 2 +- .../LightInject/LightInjectContainer.cs | 2 +- src/Umbraco.Web/CompositionExtensions.cs | 21 +- src/Umbraco.Web/Runtime/WebRuntime.cs | 15 +- .../Runtime/WebRuntimeComponent.cs | 43 ++-- .../SignalR/PreviewHubComponent.cs | 3 +- src/Umbraco.Web/UmbracoApplicationBase.cs | 8 +- 63 files changed, 520 insertions(+), 602 deletions(-) create mode 100644 src/Umbraco.Core/Composing/CompositionExtensions.cs rename src/Umbraco.Core/{Exceptions => Composing/LightInject}/LightInjectException.cs (96%) delete mode 100644 src/Umbraco.Core/Composing/LightInject/LightInjectExtensions.cs rename src/Umbraco.Tests/Composing/{ContainerConfirmingTests.cs => ContainerConformingTests.cs} (80%) diff --git a/src/Umbraco.Core/Components/Composition.cs b/src/Umbraco.Core/Components/Composition.cs index 525d8b773e..2f5bd0f6ee 100644 --- a/src/Umbraco.Core/Components/Composition.cs +++ b/src/Umbraco.Core/Components/Composition.cs @@ -16,6 +16,7 @@ namespace Umbraco.Core.Components public class Composition : IRegister { private readonly Dictionary _builders = new Dictionary(); + private readonly Dictionary _uniques = new Dictionary(); private readonly IRegister _register; /// @@ -81,13 +82,87 @@ namespace Umbraco.Core.Components public void ConfigureForWeb() => _register.ConfigureForWeb(); - /// - public void EnablePerWebRequestScope() - => _register.EnablePerWebRequestScope(); - /// public IFactory CreateFactory() - => _register.CreateFactory(); + { + foreach (var unique in _uniques.Values) + unique.RegisterTo(_register); + + return _register.CreateFactory(); + } + + #endregion + + #region Unique + + /// + /// Registers a unique service. + /// + /// Unique services have one single implementation, and a Singleton lifetime. + public void RegisterUnique(Type serviceType, Type implementingType) + => _uniques[serviceType] = new Unique(serviceType, implementingType); + + /// + /// Registers a unique service. + /// + /// Unique services have one single implementation, and a Singleton lifetime. + public void RegisterUnique(Type serviceType, object instance) + => _uniques[serviceType] = new Unique(serviceType, instance); + + /// + /// Registers a unique service. + /// + /// Unique services have one single implementation, and a Singleton lifetime. + public void RegisterUnique(Func factory) + => _uniques[typeof(TService)] = new Unique(factory); + + private class Unique + { + private readonly Type _serviceType; + private readonly Type _implementingType; + private readonly object _instance; + + protected Unique(Type serviceType) + { + _serviceType = serviceType; + } + + public Unique(Type serviceType, Type implementingType) + : this(serviceType) + { + _implementingType = implementingType; + } + + public Unique(Type serviceType, object instance) + : this(serviceType) + { + _instance = instance; + } + + public virtual void RegisterTo(IRegister register) + { + if (_implementingType != null) + register.Register(_serviceType, _implementingType, Lifetime.Singleton); + else if (_instance != null) + register.RegisterInstance(_serviceType, _instance); + } + } + + private class Unique : Unique + { + private readonly Func _factory; + + public Unique(Func factory) + : base(typeof(TService)) + { + _factory = factory; + } + + public override void RegisterTo(IRegister register) + { + register.Register(_factory, Lifetime.Singleton); + } + } #endregion diff --git a/src/Umbraco.Core/Components/CompositionExtensions.cs b/src/Umbraco.Core/Components/CompositionExtensions.cs index f41ecf7186..fa98038455 100644 --- a/src/Umbraco.Core/Components/CompositionExtensions.cs +++ b/src/Umbraco.Core/Components/CompositionExtensions.cs @@ -2,6 +2,7 @@ using Umbraco.Core.Cache; using Umbraco.Core.Dictionary; using Umbraco.Core.Composing; +using Umbraco.Core.IO; using Umbraco.Core.Migrations; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Persistence.Mappers; @@ -17,6 +18,45 @@ namespace Umbraco.Core.Components /// public static class CompositionExtensions { + #region FileSystems + + /// + /// Registers a filesystem. + /// + /// The type of the filesystem. + /// The implementing type. + /// The composition. + /// A factory method creating the supporting filesystem. + /// The register. + public static void RegisterFileSystem(this Composition composition, Func supportingFileSystemFactory) + where TImplementing : FileSystemWrapper, TFileSystem + { + composition.RegisterUnique(factory => + { + var fileSystems = factory.GetInstance(); + return fileSystems.GetFileSystem(supportingFileSystemFactory(factory)); + }); + } + + /// + /// Registers a filesystem. + /// + /// The type of the filesystem. + /// The composition. + /// A factory method creating the supporting filesystem. + /// The register. + public static void RegisterFileSystem(this Composition composition, Func supportingFileSystemFactory) + where TFileSystem : FileSystemWrapper + { + composition.RegisterUnique(factory => + { + var fileSystems = factory.GetInstance(); + return fileSystems.GetFileSystem(supportingFileSystemFactory(factory)); + }); + } + + #endregion + #region Collection Builders /// @@ -77,7 +117,7 @@ namespace Umbraco.Core.Components #endregion - #region Singleton + #region Uniques /// /// Sets the culture dictionary factory. @@ -87,7 +127,7 @@ namespace Umbraco.Core.Components public static void SetCultureDictionaryFactory(this Composition composition) where T : ICultureDictionaryFactory { - composition.RegisterSingleton(); + composition.RegisterUnique(); } /// @@ -97,7 +137,7 @@ namespace Umbraco.Core.Components /// A function creating a culture dictionary factory. public static void SetCultureDictionaryFactory(this Composition composition, Func factory) { - composition.RegisterSingleton(factory); + composition.RegisterUnique(factory); } /// @@ -107,7 +147,7 @@ namespace Umbraco.Core.Components /// A factory. public static void SetCultureDictionaryFactory(this Composition composition, ICultureDictionaryFactory factory) { - composition.RegisterSingleton(_ => factory); + composition.RegisterUnique(_ => factory); } /// @@ -118,7 +158,7 @@ namespace Umbraco.Core.Components public static void SetPublishedContentModelFactory(this Composition composition) where T : IPublishedModelFactory { - composition.RegisterSingleton(); + composition.RegisterUnique(); } /// @@ -128,7 +168,7 @@ namespace Umbraco.Core.Components /// A function creating a published content model factory. public static void SetPublishedContentModelFactory(this Composition composition, Func factory) { - composition.RegisterSingleton(factory); + composition.RegisterUnique(factory); } /// @@ -138,7 +178,7 @@ namespace Umbraco.Core.Components /// A published content model factory. public static void SetPublishedContentModelFactory(this Composition composition, IPublishedModelFactory factory) { - composition.RegisterSingleton(_ => factory); + composition.RegisterUnique(_ => factory); } /// @@ -149,7 +189,7 @@ namespace Umbraco.Core.Components public static void SetServerRegistrar(this Composition composition) where T : IServerRegistrar { - composition.RegisterSingleton(); + composition.RegisterUnique(); } /// @@ -159,7 +199,7 @@ namespace Umbraco.Core.Components /// A function creating a server registar. public static void SetServerRegistrar(this Composition composition, Func factory) { - composition.RegisterSingleton(factory); + composition.RegisterUnique(factory); } /// @@ -169,7 +209,7 @@ namespace Umbraco.Core.Components /// A server registrar. public static void SetServerRegistrar(this Composition composition, IServerRegistrar registrar) { - composition.RegisterSingleton(_ => registrar); + composition.RegisterUnique(_ => registrar); } /// @@ -180,7 +220,7 @@ namespace Umbraco.Core.Components public static void SetServerMessenger(this Composition composition) where T : IServerMessenger { - composition.Register(Lifetime.Singleton); + composition.RegisterUnique(); } /// @@ -190,7 +230,7 @@ namespace Umbraco.Core.Components /// A function creating a server messenger. public static void SetServerMessenger(this Composition composition, Func factory) { - composition.RegisterSingleton(factory); + composition.RegisterUnique(factory); } /// @@ -200,7 +240,7 @@ namespace Umbraco.Core.Components /// A server messenger. public static void SetServerMessenger(this Composition composition, IServerMessenger registrar) { - composition.RegisterSingleton(_ => registrar); + composition.RegisterUnique(_ => registrar); } /// @@ -211,7 +251,7 @@ namespace Umbraco.Core.Components public static void SetShortStringHelper(this Composition composition) where T : IShortStringHelper { - composition.RegisterSingleton(); + composition.RegisterUnique(); } /// @@ -221,7 +261,7 @@ namespace Umbraco.Core.Components /// A function creating a short string helper. public static void SetShortStringHelper(this Composition composition, Func factory) { - composition.RegisterSingleton(factory); + composition.RegisterUnique(factory); } /// @@ -231,7 +271,7 @@ namespace Umbraco.Core.Components /// A short string helper. public static void SetShortStringHelper(this Composition composition, IShortStringHelper helper) { - composition.RegisterSingleton(_ => helper); + composition.RegisterUnique(_ => helper); } #endregion diff --git a/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs b/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs index 1970fc7f4c..f1fb095406 100644 --- a/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs @@ -71,13 +71,13 @@ namespace Umbraco.Core.Composing.Composers // it needs to be registered (not only the interface) because it provides additional // functionality eg for scoping, and is injected in the scope provider - whereas the // interface is really for end-users to get access to filesystems. - composition.RegisterSingleton(factory => factory.CreateInstance(factory)); + composition.RegisterUnique(factory => factory.CreateInstance(factory)); // register IFileSystems, which gives access too all filesystems - composition.RegisterSingleton(factory => factory.GetInstance()); + composition.RegisterUnique(factory => factory.GetInstance()); // register the scheme for media paths - composition.RegisterSingleton(); + composition.RegisterUnique(); // register the IMediaFileSystem implementation with a supporting filesystem composition.RegisterFileSystem( diff --git a/src/Umbraco.Core/Composing/Composers/RepositoriesComposer.cs b/src/Umbraco.Core/Composing/Composers/RepositoriesComposer.cs index 54f9ff3e53..62b92081c1 100644 --- a/src/Umbraco.Core/Composing/Composers/RepositoriesComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/RepositoriesComposer.cs @@ -12,41 +12,41 @@ namespace Umbraco.Core.Composing.Composers public static Composition ComposeRepositories(this Composition composition) { // repositories - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); return composition; } diff --git a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs index ec53f7efdc..1b77aaa7d6 100644 --- a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs @@ -17,49 +17,49 @@ namespace Umbraco.Core.Composing.Composers { // register a transient messages factory, which will be replaced by the web // boot manager when running in a web context - composition.RegisterSingleton(); + composition.RegisterUnique(); // register the service context - composition.RegisterSingleton(); + composition.RegisterUnique(); // register the special idk map - composition.RegisterSingleton(); + composition.RegisterUnique(); // register the services - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); composition.Register(SourcesFactory); - composition.RegisterSingleton(factory => new LocalizedTextService( + composition.RegisterUnique(factory => new LocalizedTextService( factory.GetInstance>(), factory.GetInstance())); //TODO: These are replaced in the web project - we need to declare them so that // something is wired up, just not sure this is very nice but will work for now. - composition.RegisterSingleton(); - composition.RegisterSingleton(); + composition.RegisterUnique(); + composition.RegisterUnique(); return composition; } diff --git a/src/Umbraco.Core/Composing/CompositionExtensions.cs b/src/Umbraco.Core/Composing/CompositionExtensions.cs new file mode 100644 index 0000000000..bab3bb7fa5 --- /dev/null +++ b/src/Umbraco.Core/Composing/CompositionExtensions.cs @@ -0,0 +1,32 @@ +using Umbraco.Core.Components; + +namespace Umbraco.Core.Composing +{ + /// + /// Provides extension methods to the class. + /// + public static class CompositionExtensions + { + #region Unique + + /// + /// Registers a unique service as its own implementation. + /// + public static void RegisterUnique(this Composition composition) + => composition.RegisterUnique(typeof(TService), typeof(TService)); + + /// + /// Registers a unique service with an implementation type. + /// + public static void RegisterUnique(this Composition composition) + => composition.RegisterUnique(typeof(TService), typeof(TImplementing)); + + /// + /// Registers a unique service with an implementing instance. + /// + public static void RegisterUnique(this Composition composition, TService instance) + => composition.RegisterUnique(typeof(TService), instance); + + #endregion + } +} diff --git a/src/Umbraco.Core/Composing/IFactory.cs b/src/Umbraco.Core/Composing/IFactory.cs index 3e8cdf08e0..b753b3a1df 100644 --- a/src/Umbraco.Core/Composing/IFactory.cs +++ b/src/Umbraco.Core/Composing/IFactory.cs @@ -64,5 +64,13 @@ namespace Umbraco.Core.Composing /// Scopes can be nested. Each instance is disposed individually. /// IDisposable BeginScope(); + + /// + /// Enables per-request scope. + /// + /// + /// Ties scopes to web requests. + /// + void EnablePerWebRequestScope(); } } diff --git a/src/Umbraco.Core/Composing/IRegister.cs b/src/Umbraco.Core/Composing/IRegister.cs index 1ce7ae9f0b..747f3447b6 100644 --- a/src/Umbraco.Core/Composing/IRegister.cs +++ b/src/Umbraco.Core/Composing/IRegister.cs @@ -66,14 +66,6 @@ namespace Umbraco.Core.Composing /// void ConfigureForWeb(); - /// - /// Enables per-request scope. - /// - /// - /// Ties scopes to web requests. - /// - void EnablePerWebRequestScope(); - /// /// Creates the factory. /// diff --git a/src/Umbraco.Core/Composing/Lifetime.cs b/src/Umbraco.Core/Composing/Lifetime.cs index a7ae1d4179..e1b9950c39 100644 --- a/src/Umbraco.Core/Composing/Lifetime.cs +++ b/src/Umbraco.Core/Composing/Lifetime.cs @@ -8,21 +8,42 @@ /// /// Always get a new instance. /// + /// Corresponds to Transient in LightInject, Castle Windsor + /// or MS.DI, PerDependency in Autofac. Transient, /// /// One unique instance per request. /// + // fixme - not what you think! + // currently, corresponds to 'Request' in LightInject which is 'Transient + disposed by Scope' + // but NOT (in LightInject) a per-web-request lifetime, more a TransientScoped + // + // we use it for controllers, httpContextBase and umbracoContext + // - so that they are automatically disposed at the end of the scope (ie request) + // - not sure they should not be simply 'scoped'? + // + // Castle has an extra PerWebRequest something, and others use scope + // what about Request before first request ie during application startup? + // see http://blog.ploeh.dk/2009/11/17/UsingCastleWindsor'sPerWebRequestlifestylewithASP.NETMVConIIS7/ + // Castle ends up requiring a special scope manager too + // see https://groups.google.com/forum/#!topic/castle-project-users/1E2W9LVIYR4 + // + // but maybe also - why are we requiring scoped services at startup? Request, /// /// One unique instance per container scope. /// + /// Corresponds to Scope in LightInject, Scoped in MS.DI + /// or Castle Windsor, PerLifetimeScope in Autofac. Scope, /// /// One unique instance per container. /// + /// Corresponds to Singleton in LightInject, Castle Windsor + /// or MS.DI and to SingleInstance in Autofac. Singleton } } diff --git a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs index d94643e49a..58bc8d2d44 100644 --- a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs +++ b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs @@ -145,10 +145,8 @@ namespace Umbraco.Core.Composing.LightInject break; case Lifetime.Request: case Lifetime.Scope: - Container.Register(serviceType, GetLifetime(lifetime)); - break; case Lifetime.Singleton: - Container.RegisterSingleton(serviceType); + Container.Register(serviceType, GetLifetime(lifetime)); break; default: throw new NotSupportedException($"Lifetime {lifetime} is not supported."); @@ -165,10 +163,8 @@ namespace Umbraco.Core.Composing.LightInject break; case Lifetime.Request: case Lifetime.Scope: - Container.Register(serviceType, implementingType, GetLifetime(lifetime)); - break; case Lifetime.Singleton: - Container.RegisterSingleton(serviceType, implementingType); + Container.Register(serviceType, implementingType, GetLifetime(lifetime)); break; default: throw new NotSupportedException($"Lifetime {lifetime} is not supported."); @@ -185,10 +181,8 @@ namespace Umbraco.Core.Composing.LightInject break; case Lifetime.Request: case Lifetime.Scope: - Container.Register(f => factory(this), GetLifetime(lifetime)); - break; case Lifetime.Singleton: - Container.RegisterSingleton(f => factory(this)); + Container.Register(f => factory(this), GetLifetime(lifetime)); break; default: throw new NotSupportedException($"Lifetime {lifetime} is not supported."); diff --git a/src/Umbraco.Core/Exceptions/LightInjectException.cs b/src/Umbraco.Core/Composing/LightInject/LightInjectException.cs similarity index 96% rename from src/Umbraco.Core/Exceptions/LightInjectException.cs rename to src/Umbraco.Core/Composing/LightInject/LightInjectException.cs index 03fd9f2f9f..fa0aed21ca 100644 --- a/src/Umbraco.Core/Exceptions/LightInjectException.cs +++ b/src/Umbraco.Core/Composing/LightInject/LightInjectException.cs @@ -1,9 +1,7 @@ using System; -using System.Collections.Generic; -using System.Linq; using System.Text; -namespace Umbraco.Core.Exceptions +namespace Umbraco.Core.Composing.LightInject { /// /// Represents errors that occur due to LightInject. diff --git a/src/Umbraco.Core/Composing/LightInject/LightInjectExtensions.cs b/src/Umbraco.Core/Composing/LightInject/LightInjectExtensions.cs deleted file mode 100644 index d9651ef1a1..0000000000 --- a/src/Umbraco.Core/Composing/LightInject/LightInjectExtensions.cs +++ /dev/null @@ -1,199 +0,0 @@ -using System; -using System.Linq; -using LightInject; - -namespace Umbraco.Core.Composing.LightInject -{ - /// - /// Provides extensions to LightInject. - /// - public static class LightInjectExtensions - { - /// - /// Registers the TService with the factory that describes the dependencies of the service, as a singleton. - /// - public static void RegisterSingleton(this IServiceRegistry container, Func factory, string serviceName) - { - var registration = container.GetAvailableService(serviceName); - if (registration == null) - { - container.Register(factory, serviceName, new PerContainerLifetime()); - } - else - { - if (registration.Lifetime is PerContainerLifetime == false) - throw new InvalidOperationException("Existing registration lifetime is not PerContainer."); - UpdateRegistration(registration, null, factory); - } - } - - /// - /// Registers a service with an implementation as a singleton. - /// - public static void RegisterSingleton(this IServiceRegistry container) - where TImplementation : TService - { - container.RegisterSingleton(typeof(TService), typeof(TImplementation)); - } - - /// - /// Registers a service with an implementation as a singleton. - /// - public static void RegisterSingleton(this IServiceRegistry container, Type serviceType, Type implementingType) - { - var registration = container.GetAvailableService(serviceType); - - if (registration == null) - { - container.Register(serviceType, implementingType, new PerContainerLifetime()); - } - else - { - if (registration.Lifetime is PerContainerLifetime == false) - throw new InvalidOperationException("Existing registration lifetime is not PerContainer."); - UpdateRegistration(registration, implementingType, null); - } - } - - /// - /// Registers a service with a named implementation as a singleton. - /// - public static void RegisterSingleton(this IServiceRegistry container, Type serviceType, Type implementingType, string name) - { - var registration = container.AvailableServices.FirstOrDefault(x => x.ServiceType == serviceType && x.ServiceName == name); - - if (registration == null) - { - container.Register(serviceType, implementingType, name, new PerContainerLifetime()); - } - else - { - if (registration.Lifetime is PerContainerLifetime == false) - throw new InvalidOperationException("Existing registration lifetime is not PerContainer."); - UpdateRegistration(registration, implementingType, null); - } - } - - /// - /// Registers a concrete type as a singleton service. - /// - public static void RegisterSingleton(this IServiceRegistry container) - { - container.RegisterSingleton(typeof(TImplementation)); - } - - /// - /// Registers a concrete type as a singleton service. - /// - public static void RegisterSingleton(this IServiceRegistry container, Type serviceType) - { - var registration = container.GetAvailableService(serviceType); - if (registration == null) - { - container.Register(serviceType, new PerContainerLifetime()); - } - else - { - if (registration.Lifetime is PerContainerLifetime == false) - throw new InvalidOperationException("Existing registration lifetime is not PerContainer."); - UpdateRegistration(registration, serviceType, null); - } - } - - /// - /// Registers the TService with the factory that describes the dependencies of the service, as a singleton. - /// - /// - /// - /// - public static void RegisterSingleton(this IServiceRegistry container, Func factory) - { - var registration = container.GetAvailableService(); - if (registration == null) - container.Register(factory, new PerContainerLifetime()); - else - UpdateRegistration(registration, null, factory); - } - - // note - what's below ALSO applies to non-singleton ie transient services - // - // see https://github.com/seesharper/LightInject/issues/133 - // - // note: we *could* use tracking lifetimes for singletons to ensure they have not been resolved - // already but that would not work for transient as the transient lifetime is null (and that is - // optimized in LightInject) - // - // also, RegisterSingleton above is dangerous because ppl could still use Register with a - // PerContainerLifetime and it will not work + the default Register would not work either for other - // lifetimes - // - // all in all, not sure we want to let ppl have direct access to the container - // we might instead want to expose some methods in UmbracoComponentBase or whatever? - - /// - /// Updates a registration. - /// - private static void UpdateRegistration(ServiceRegistration registration, Type implementingType, Delegate factoryExpression) - { - // if the container has compiled already then the registrations have been captured, - // and re-registering - although updating available services - does not modify the - // output of GetInstance - // - // so we have to rely on different methods - // - // assuming the service has NOT been resolved, both methods below work, but the first - // one looks simpler. it would be good to check whether the service HAS been resolved - // but I am not sure how to do it right now, depending on the lifetime - // - // if the service HAS been resolved then updating is probably a bad idea - - // not sure which is best? that one works, though, and looks simpler - registration.ImplementingType = implementingType; - registration.FactoryExpression = factoryExpression; - - //container.Override( - // r => r.ServiceType == typeof (TService) && (registration.ServiceName == null || r.ServiceName == registration.ServiceName), - // (f, r) => - // { - // r.ImplementingType = implementingType; - // r.FactoryExpression = factoryExpression; - // return r; - // }); - } - - /// - /// Gets the unique available service registration for a service type. - /// - /// The service type. - /// The container. - /// The unique service registration for the service type. - /// Can return null, but throws if more than one registration exist for the service type. - private static ServiceRegistration GetAvailableService(this IServiceRegistry container) - { - var typeofTService = typeof(TService); - return container.AvailableServices.SingleOrDefault(x => x.ServiceType == typeofTService); - } - - /// - /// Gets the unique available service registration for a service type. - /// - private static ServiceRegistration GetAvailableService(this IServiceRegistry container, Type serviceType) - { - return container.AvailableServices.SingleOrDefault(x => x.ServiceType == serviceType); - } - - /// - /// Gets the unique available service registration for a service type and a name. - /// - /// The service type. - /// The container. - /// The name. - /// The unique service registration for the service type and the name. - /// Can return null, but throws if more than one registration exist for the service type and the name. - private static ServiceRegistration GetAvailableService(this IServiceRegistry container, string name) - { - var typeofTService = typeof(TService); - return container.AvailableServices.SingleOrDefault(x => x.ServiceType == typeofTService && x.ServiceName == name); - } - } -} diff --git a/src/Umbraco.Core/Composing/RegisterExtensions.cs b/src/Umbraco.Core/Composing/RegisterExtensions.cs index cff51a7f53..4db1a2e9e4 100644 --- a/src/Umbraco.Core/Composing/RegisterExtensions.cs +++ b/src/Umbraco.Core/Composing/RegisterExtensions.cs @@ -1,7 +1,4 @@ -using System; -using Umbraco.Core.IO; - -namespace Umbraco.Core.Composing +namespace Umbraco.Core.Composing { /// /// Provides extension methods to the class. @@ -20,24 +17,6 @@ namespace Umbraco.Core.Composing public static void Register(this IRegister register, Lifetime lifetime = Lifetime.Transient) => register.Register(typeof(TService), lifetime); - /// - /// Registers a singleton service as its own implementation. - /// - public static void RegisterSingleton(this IRegister register) - => register.Register(typeof(TService), Lifetime.Singleton); - - /// - /// Registers a singleton service with an implementation type. - /// - public static void RegisterSingleton(this IRegister register) - => register.Register(typeof(TService), typeof(TImplementing), Lifetime.Singleton); - - /// - /// Registers a singleton service with an implementation factory. - /// - public static void RegisterSingleton(this IRegister register, Func factory) - => register.Register(factory, Lifetime.Singleton); - /// /// Registers a service with an implementing instance. /// @@ -49,44 +28,5 @@ namespace Umbraco.Core.Composing /// public static void RegisterAuto(this IRegister register) => register.RegisterAuto(typeof(TServiceBase)); - - /// - /// Registers a filesystem. - /// - /// The type of the filesystem. - /// The implementing type. - /// The register. - /// A factory method creating the supporting filesystem. - /// The register. - public static IRegister RegisterFileSystem(this IRegister register, Func supportingFileSystemFactory) - where TImplementing : FileSystemWrapper, TFileSystem - { - register.RegisterSingleton(factory => - { - var fileSystems = factory.GetInstance(); - return fileSystems.GetFileSystem(supportingFileSystemFactory(factory)); - }); - - return register; - } - - /// - /// Registers a filesystem. - /// - /// The type of the filesystem. - /// The register. - /// A factory method creating the supporting filesystem. - /// The register. - public static IRegister RegisterFileSystem(this IRegister register, Func supportingFileSystemFactory) - where TFileSystem : FileSystemWrapper - { - register.RegisterSingleton(factory => - { - var fileSystems = factory.GetInstance(); - return fileSystems.GetFileSystem(supportingFileSystemFactory(factory)); - }); - - return register; - } } } diff --git a/src/Umbraco.Core/IRuntime.cs b/src/Umbraco.Core/IRuntime.cs index 8a62e76a5e..d433dde12d 100644 --- a/src/Umbraco.Core/IRuntime.cs +++ b/src/Umbraco.Core/IRuntime.cs @@ -11,7 +11,8 @@ namespace Umbraco.Core /// Boots the runtime. /// /// The application register. - void Boot(IRegister register); + /// The application factory. + IFactory Boot(IRegister register); /// /// Gets the runtime state. diff --git a/src/Umbraco.Core/Runtime/CoreRuntime.cs b/src/Umbraco.Core/Runtime/CoreRuntime.cs index 9ccb45cf0f..978c4f2906 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntime.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntime.cs @@ -44,19 +44,16 @@ namespace Umbraco.Core.Runtime public IRuntimeState State => _state; /// - public virtual void Boot(IRegister register) + public virtual IFactory Boot(IRegister register) { // create and register the essential services // ie the bare minimum required to boot // loggers var logger = GetLogger(); - register.RegisterInstance(logger); Logger = logger; var profiler = GetProfiler(); - register.RegisterInstance(profiler); var profilingLogger = new ProfilingLogger(logger, profiler); - register.RegisterInstance(profilingLogger); ProfilingLogger = profilingLogger; // application environment @@ -66,19 +63,14 @@ namespace Umbraco.Core.Runtime // application caches var appCaches = GetAppCaches(); - register.RegisterInstance(appCaches); var runtimeCache = appCaches.RuntimeCache; - register.RegisterInstance(runtimeCache); // database factory var databaseFactory = GetDatabaseFactory(); - register.RegisterInstance(databaseFactory); - register.RegisterSingleton(_ => databaseFactory.SqlContext); // type loader var globalSettings = UmbracoConfig.For.GlobalSettings(); var typeLoader = new TypeLoader(runtimeCache, globalSettings, profilingLogger); - register.RegisterInstance(typeLoader); // runtime state // beware! must use '() => _factory.GetInstance()' and NOT '_factory.GetInstance' @@ -90,11 +82,20 @@ namespace Umbraco.Core.Runtime { Level = RuntimeLevel.Boot }; - register.RegisterInstance(_state); // create the composition var composition = new Composition(register, typeLoader, profilingLogger, RuntimeLevel.Boot); + composition.RegisterUnique(logger); + composition.RegisterUnique(profiler); + composition.RegisterUnique(profilingLogger); + composition.RegisterUnique(appCaches); + composition.RegisterUnique(runtimeCache); + composition.RegisterUnique(databaseFactory); + composition.RegisterUnique(_ => databaseFactory.SqlContext); + composition.RegisterUnique(typeLoader); + composition.RegisterUnique(_state); + // register runtime-level services Compose(composition); @@ -120,7 +121,7 @@ namespace Umbraco.Core.Runtime logger.Debug("Runtime: {Runtime}", GetType().FullName); var mainDom = AquireMainDom(); - register.RegisterInstance(mainDom); + composition.RegisterUnique(mainDom); DetermineRuntimeLevel(databaseFactory); @@ -129,7 +130,7 @@ namespace Umbraco.Core.Runtime _components.Compose(); - _factory = Current.Factory = register.CreateFactory(); + _factory = Current.Factory = composition.CreateFactory(); _components.Initialize(_factory); } @@ -147,6 +148,8 @@ namespace Umbraco.Core.Runtime // throw a BootFailedException for every requests. } } + + return _factory; } protected virtual void ConfigureUnhandledException() diff --git a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs index 72d6d37010..83405dc13a 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs @@ -48,16 +48,16 @@ namespace Umbraco.Core.Runtime composition.WithCollectionBuilder().AddCoreMappers(); // register the scope provider - composition.RegisterSingleton(); // implements both IScopeProvider and IScopeAccessor - composition.RegisterSingleton(f => f.GetInstance()); - composition.RegisterSingleton(f => f.GetInstance()); + composition.RegisterUnique(); // implements both IScopeProvider and IScopeAccessor + composition.RegisterUnique(f => f.GetInstance()); + composition.RegisterUnique(f => f.GetInstance()); // register database builder // *not* a singleton, don't want to keep it around composition.Register(); // register manifest parser, will be injected in collection builders where needed - composition.RegisterSingleton(); + composition.RegisterUnique(); // register our predefined validators composition.WithCollectionBuilder() @@ -71,11 +71,11 @@ namespace Umbraco.Core.Runtime // properties and parameters derive from data editors composition.WithCollectionBuilder() .Add(() => composition.TypeLoader.GetDataEditors()); - composition.RegisterSingleton(); - composition.RegisterSingleton(); + composition.RegisterUnique(); + composition.RegisterUnique(); // register a server registrar, by default it's the db registrar - composition.RegisterSingleton(f => + composition.RegisterUnique(f => { if ("true".InvariantEquals(ConfigurationManager.AppSettings["umbracoDisableElectionForSingleServer"])) return new SingleServerRegistrar(f.GetInstance()); @@ -87,7 +87,7 @@ namespace Umbraco.Core.Runtime // by default we'll use the database server messenger with default options (no callbacks), // this will be overridden by either the legacy thing or the db thing in the corresponding // components in the web project - fixme - should obsolete the legacy thing - composition.RegisterSingleton(factory + composition.RegisterUnique(factory => new DatabaseServerMessenger( factory.GetInstance(), factory.GetInstance(), @@ -105,9 +105,9 @@ namespace Umbraco.Core.Runtime composition.WithCollectionBuilder() .Append(composition.TypeLoader.GetTypes()); - composition.RegisterSingleton(); + composition.RegisterUnique(); - composition.RegisterSingleton(factory + composition.RegisterUnique(factory => new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(factory.GetInstance()))); composition.WithCollectionBuilder() @@ -116,10 +116,10 @@ namespace Umbraco.Core.Runtime composition.WithCollectionBuilder() .Add(() => composition.TypeLoader.GetTypes()); - composition.RegisterSingleton(factory => new MigrationBuilder(factory)); + composition.RegisterUnique(factory => new MigrationBuilder(factory)); // by default, register a noop factory - composition.RegisterSingleton(); + composition.RegisterUnique(); } internal void Initialize(IEnumerable mapperProfiles) diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index bc092271b7..4823811566 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -177,6 +177,7 @@ + @@ -188,7 +189,6 @@ - @@ -573,7 +573,7 @@ - + diff --git a/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs b/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs index a57ab93f3c..a70a3062b0 100644 --- a/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs +++ b/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs @@ -27,13 +27,13 @@ namespace Umbraco.Tests.Cache.DistributedCache var composition = new Composition(register, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); - register.Register(_ => new TestServerRegistrar()); - register.RegisterSingleton(_ => new TestServerMessenger()); + composition.RegisterUnique(_ => new TestServerRegistrar()); + composition.RegisterUnique(_ => new TestServerMessenger()); composition.WithCollectionBuilder() .Add(); - Current.Factory = register.CreateFactory(); + Current.Factory = composition.CreateFactory(); _distributedCache = new Umbraco.Web.Cache.DistributedCache(); } diff --git a/src/Umbraco.Tests/Composing/ContainerConfirmingTests.cs b/src/Umbraco.Tests/Composing/ContainerConformingTests.cs similarity index 80% rename from src/Umbraco.Tests/Composing/ContainerConfirmingTests.cs rename to src/Umbraco.Tests/Composing/ContainerConformingTests.cs index fd76dbe8bb..aace92a956 100644 --- a/src/Umbraco.Tests/Composing/ContainerConfirmingTests.cs +++ b/src/Umbraco.Tests/Composing/ContainerConformingTests.cs @@ -3,16 +3,15 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; using Umbraco.Core.Composing; -using Umbraco.Core.Composing.LightInject; namespace Umbraco.Tests.Composing { [TestFixture] - public class ContainerConfirmingTests + public class ContainerConformingTests { // tests that a container conforms - private IRegister GetRegister() => LightInjectContainer.Create(); + private IRegister GetRegister() => RegisterFactory.Create(); [Test] public void CanRegisterAndGet() @@ -144,10 +143,16 @@ namespace Umbraco.Tests.Composing } [Test] - public void SingletonServiceIsUnique() + public void SingletonServiceIsUnique() // fixme - but what is LightInject actually doing { var register = GetRegister(); + // fixme + // LightInject is 'unique' per serviceType+serviceName + // but that's not how all containers work + // and we should not rely on it + // if we need unique, use RegisterUnique + // for Core services that ppl may want to redefine in components, // it is important to be able to have a unique, singleton implementation, // and to redefine it - how it's done at container's level depends @@ -183,6 +188,40 @@ namespace Umbraco.Tests.Composing Assert.IsNull(factory.TryGetInstance()); } + [Test] + public void ActualInstanceIsNotUnique() + { + var register = GetRegister(); + + // define two instances + register.RegisterInstance(typeof(Thing1), new Thing1()); + register.RegisterInstance(typeof(Thing1), new Thing2()); + + var factory = register.CreateFactory(); + + var things = factory.GetInstance>(); + Assert.AreEqual(2, things.Count()); + + Assert.IsNull(factory.TryGetInstance()); + } + + [Test] + public void InterfaceInstanceIsNotUnique() + { + var register = GetRegister(); + + // define two instances + register.RegisterInstance(typeof(IThing), new Thing1()); + register.RegisterInstance(typeof(IThing), new Thing2()); + + var factory = register.CreateFactory(); + + var things = factory.GetInstance>(); + Assert.AreEqual(2, things.Count()); + + Assert.IsNull(factory.TryGetInstance()); + } + [Test] public void CanInjectEnumerableOfBase() { @@ -216,7 +255,7 @@ namespace Umbraco.Tests.Composing public void CanRegisterSingletonInterface() { var register = GetRegister(); - register.RegisterSingleton(); + register.Register(Lifetime.Singleton); var factory = register.CreateFactory(); var s1 = factory.GetInstance(); var s2 = factory.GetInstance(); @@ -227,7 +266,7 @@ namespace Umbraco.Tests.Composing public void CanRegisterSingletonClass() { var register = GetRegister(); - register.RegisterSingleton(); + register.Register(Lifetime.Singleton); var factory = register.CreateFactory(); var s1 = factory.GetInstance(); var s2 = factory.GetInstance(); @@ -238,8 +277,8 @@ namespace Umbraco.Tests.Composing public void CanReRegisterSingletonInterface() { var register = GetRegister(); - register.RegisterSingleton(); - register.RegisterSingleton(); + register.Register(Lifetime.Singleton); + register.Register(Lifetime.Singleton); var factory = register.CreateFactory(); var s = factory.GetInstance(); Assert.IsInstanceOf(s); @@ -249,7 +288,7 @@ namespace Umbraco.Tests.Composing public void CanRegisterSingletonWithCreate() { var register = GetRegister(); - register.RegisterSingleton(c => c.CreateInstance(new Thing1())); + register.Register(c => c.CreateInstance(new Thing1()), Lifetime.Singleton); var factory = register.CreateFactory(); var s1 = factory.GetInstance(); var s2 = factory.GetInstance(); diff --git a/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs b/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs index 1f08e60375..180ecb7d42 100644 --- a/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs +++ b/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs @@ -24,7 +24,7 @@ namespace Umbraco.Tests.Composing composition.WithCollectionBuilder() .Add(() => TypeLoader.GetPackageActions()); - Current.Factory = container.CreateFactory(); + Current.Factory = composition.CreateFactory(); var actions = Current.PackageActions; Assert.AreEqual(2, actions.Count()); diff --git a/src/Umbraco.Tests/CoreThings/TryConvertToTests.cs b/src/Umbraco.Tests/CoreThings/TryConvertToTests.cs index d997a1bebd..c7741deb04 100644 --- a/src/Umbraco.Tests/CoreThings/TryConvertToTests.cs +++ b/src/Umbraco.Tests/CoreThings/TryConvertToTests.cs @@ -3,7 +3,6 @@ using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Strings; using Umbraco.Tests.TestHelpers; -using Umbraco.Core.Composing; using Umbraco.Tests.Testing; namespace Umbraco.Tests.CoreThings @@ -18,7 +17,7 @@ namespace Umbraco.Tests.CoreThings var settings = SettingsForTests.GetDefaultUmbracoSettings(); // fixme - base should do it! - Composition.RegisterSingleton(_ => new DefaultShortStringHelper(settings)); + Composition.RegisterUnique(_ => new DefaultShortStringHelper(settings)); } [Test] diff --git a/src/Umbraco.Tests/IO/FileSystemsTests.cs b/src/Umbraco.Tests/IO/FileSystemsTests.cs index be1964cd72..d6ddac88d4 100644 --- a/src/Umbraco.Tests/IO/FileSystemsTests.cs +++ b/src/Umbraco.Tests/IO/FileSystemsTests.cs @@ -4,12 +4,10 @@ using System.Text; using Moq; using NUnit.Framework; using Umbraco.Core; -using Umbraco.Core.Cache; using Umbraco.Core.Components; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Composing; using Umbraco.Core.Composing.Composers; -using Umbraco.Core.Configuration; using Umbraco.Core.IO; using Umbraco.Core.IO.MediaPathSchemes; using Umbraco.Core.Logging; @@ -38,7 +36,7 @@ namespace Umbraco.Tests.IO composition.Register(_ => Mock.Of()); composition.Register(_ => Mock.Of()); composition.Register(_ => Mock.Of()); - composition.RegisterSingleton(); + composition.RegisterUnique(); composition.ComposeFileSystems(); diff --git a/src/Umbraco.Tests/Integration/ContentEventsTests.cs b/src/Umbraco.Tests/Integration/ContentEventsTests.cs index c138e48bfe..bb0556a0a8 100644 --- a/src/Umbraco.Tests/Integration/ContentEventsTests.cs +++ b/src/Umbraco.Tests/Integration/ContentEventsTests.cs @@ -50,7 +50,7 @@ namespace Umbraco.Tests.Integration base.Compose(); Composition.Register(_ => new TestServerRegistrar()); // localhost-only - Composition.RegisterSingleton(); + Composition.RegisterUnique(); Composition.WithCollectionBuilder() .Add() diff --git a/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs b/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs index c908cca64e..1f7c5624bf 100644 --- a/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs +++ b/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs @@ -3,9 +3,7 @@ using System.Collections.Generic; using System.Linq; using AutoMapper; using NUnit.Framework; -using Umbraco.Core; using Umbraco.Core.Cache; -using Umbraco.Core.Composing; using Umbraco.Core.Manifest; using Umbraco.Core.PropertyEditors; using Umbraco.Tests.TestHelpers; @@ -28,7 +26,7 @@ namespace Umbraco.Tests.Models.Mapping { Path = TestHelper.CurrentAssemblyDirectory }; - Composition.Register(_ => manifestBuilder); + Composition.RegisterUnique(_ => manifestBuilder); Func> typeListProducerList = Enumerable.Empty; Composition.WithCollectionBuilder() diff --git a/src/Umbraco.Tests/Models/Mapping/ContentTypeModelMappingTests.cs b/src/Umbraco.Tests/Models/Mapping/ContentTypeModelMappingTests.cs index d272dc9453..2c99bfeff1 100644 --- a/src/Umbraco.Tests/Models/Mapping/ContentTypeModelMappingTests.cs +++ b/src/Umbraco.Tests/Models/Mapping/ContentTypeModelMappingTests.cs @@ -1,11 +1,9 @@ using System; -using System.Collections.Generic; using System.Linq; using AutoMapper; using Moq; using NUnit.Framework; using Umbraco.Core; -using Umbraco.Core.Composing; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; @@ -55,13 +53,13 @@ namespace Umbraco.Tests.Models.Mapping var dataEditors = new DataEditorCollection(editors); _editorsMock = new Mock(dataEditors); _editorsMock.Setup(x => x[It.IsAny()]).Returns(editors[0]); - Composition.RegisterSingleton(f => _editorsMock.Object); + Composition.RegisterUnique(f => _editorsMock.Object); - Composition.RegisterSingleton(_ => _contentTypeService.Object); - Composition.RegisterSingleton(_ => _contentService.Object); - Composition.RegisterSingleton(_ => _dataTypeService.Object); - Composition.RegisterSingleton(_ => _entityService.Object); - Composition.RegisterSingleton(_ => _fileService.Object); + Composition.RegisterUnique(_ => _contentTypeService.Object); + Composition.RegisterUnique(_ => _contentService.Object); + Composition.RegisterUnique(_ => _dataTypeService.Object); + Composition.RegisterUnique(_ => _entityService.Object); + Composition.RegisterUnique(_ => _fileService.Object); } [Test] diff --git a/src/Umbraco.Tests/Models/Mapping/ContentWebModelMappingTests.cs b/src/Umbraco.Tests/Models/Mapping/ContentWebModelMappingTests.cs index df375aca13..cab9de9204 100644 --- a/src/Umbraco.Tests/Models/Mapping/ContentWebModelMappingTests.cs +++ b/src/Umbraco.Tests/Models/Mapping/ContentWebModelMappingTests.cs @@ -12,7 +12,6 @@ using Umbraco.Core.PropertyEditors; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Entities; using Umbraco.Web.Models.ContentEditing; -using Umbraco.Core.Composing; using Umbraco.Tests.Testing; using Current = Umbraco.Web.Composing.Current; @@ -26,7 +25,7 @@ namespace Umbraco.Tests.Models.Mapping { base.Compose(); - Composition.RegisterSingleton(f => Mock.Of()); + Composition.RegisterUnique(f => Mock.Of()); } [DataEditor("Test.Test", "Test", "~/Test.html")] @@ -158,7 +157,7 @@ namespace Umbraco.Tests.Models.Mapping AssertBasicProperty(invariantContent, p); AssertDisplayProperty(invariantContent, p); } - + Assert.AreEqual(content.PropertyGroups.Count(), invariantContent.Tabs.Count()); } diff --git a/src/Umbraco.Tests/Persistence/Repositories/PartialViewRepositoryTests.cs b/src/Umbraco.Tests/Persistence/Repositories/PartialViewRepositoryTests.cs index 8109ffbf56..9c326b3ddc 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/PartialViewRepositoryTests.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/PartialViewRepositoryTests.cs @@ -1,8 +1,6 @@ using System.Linq; using Moq; using NUnit.Framework; -using Umbraco.Core; -using Umbraco.Core.Composing; using Umbraco.Core.IO; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; @@ -29,7 +27,7 @@ namespace Umbraco.Tests.Persistence.Repositories { base.Compose(); - Composition.RegisterSingleton(f => new DataEditorCollection(Enumerable.Empty())); + Composition.RegisterUnique(f => new DataEditorCollection(Enumerable.Empty())); } [Test] diff --git a/src/Umbraco.Tests/Persistence/Repositories/ScriptRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ScriptRepositoryTest.cs index 4a07b3780c..36c1bbdfb4 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ScriptRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ScriptRepositoryTest.cs @@ -3,8 +3,6 @@ using System.Linq; using System.Text; using Moq; using NUnit.Framework; -using Umbraco.Core; -using Umbraco.Core.Composing; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; using Umbraco.Core.Models; @@ -39,7 +37,7 @@ namespace Umbraco.Tests.Persistence.Repositories { base.Compose(); - Composition.RegisterSingleton(f => new DataEditorCollection(Enumerable.Empty())); + Composition.RegisterUnique(f => new DataEditorCollection(Enumerable.Empty())); } [Test] diff --git a/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs b/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs index 1a869183bb..e801721f6b 100644 --- a/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs +++ b/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs @@ -74,7 +74,7 @@ namespace Umbraco.Tests.PropertyEditors composition.WithCollectionBuilder(); - Current.Factory = container.CreateFactory(); + Current.Factory = composition.CreateFactory(); var logger = Mock.Of(); var scheme = Mock.Of(); diff --git a/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs b/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs index 2d2f1e8be7..e78ebb7eb1 100644 --- a/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs +++ b/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs @@ -3,7 +3,9 @@ using System.Threading; using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Components; using Umbraco.Core.Composing; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Services; @@ -22,11 +24,12 @@ namespace Umbraco.Tests.PropertyEditors Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture; var register = RegisterFactory.Create(); + var composition = new Composition(register, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); register.Register(_ => new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(SettingsForTests.GetDefaultUmbracoSettings()))); - Current.Factory = register.CreateFactory(); + Current.Factory = composition.CreateFactory(); } [TearDown] diff --git a/src/Umbraco.Tests/Published/ConvertersTests.cs b/src/Umbraco.Tests/Published/ConvertersTests.cs index 0937c5ea70..b0be7b5eb6 100644 --- a/src/Umbraco.Tests/Published/ConvertersTests.cs +++ b/src/Umbraco.Tests/Published/ConvertersTests.cs @@ -189,7 +189,7 @@ namespace Umbraco.Tests.Published }); register.Register(f => factory); - Current.Factory = register.CreateFactory(); + Current.Factory = composition.CreateFactory(); var cacheMock = new Mock(); var cacheContent = new Dictionary(); diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentLanguageVariantTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentLanguageVariantTests.cs index 1d9247810f..7a96f670e6 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentLanguageVariantTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentLanguageVariantTests.cs @@ -2,13 +2,10 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; -using System.Reflection; using Moq; using NUnit.Framework; -using Umbraco.Core.Composing; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; -using Umbraco.Core.PropertyEditors; using Umbraco.Core.Services; using Umbraco.Tests.Testing; using Umbraco.Web; @@ -23,7 +20,7 @@ namespace Umbraco.Tests.PublishedContent { base.Compose(); - Composition.RegisterSingleton(_ => GetServiceContext()); + Composition.RegisterUnique(_ => GetServiceContext()); } protected ServiceContext GetServiceContext() diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs index 70faf18bf4..6b280832da 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs @@ -1,6 +1,5 @@ using System; using System.Linq; -using System.Collections.ObjectModel; using System.Web.Routing; using Moq; using Umbraco.Core.Models.PublishedContent; @@ -10,7 +9,6 @@ using Umbraco.Web.Routing; using Umbraco.Web.Security; using Umbraco.Core.Composing; using Current = Umbraco.Core.Composing.Current; -using LightInject; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; @@ -39,7 +37,7 @@ namespace Umbraco.Tests.PublishedContent { base.Compose(); - Composition.RegisterSingleton(f => new PublishedModelFactory(f.GetInstance().GetTypes())); + Composition.RegisterUnique(f => new PublishedModelFactory(f.GetInstance().GetTypes())); } protected override TypeLoader CreateTypeLoader(IRuntimeCacheProvider runtimeCache, IGlobalSettings globalSettings, IProfilingLogger logger) diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs index b347f0d676..914956dce1 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs @@ -33,9 +33,9 @@ namespace Umbraco.Tests.PublishedContent { base.Compose(); - Composition.RegisterSingleton(f => new PublishedModelFactory(f.GetInstance().GetTypes())); - Composition.RegisterSingleton(); - Composition.RegisterSingleton(); + Composition.RegisterUnique(f => new PublishedModelFactory(f.GetInstance().GetTypes())); + Composition.RegisterUnique(); + Composition.RegisterUnique(); var logger = Mock.Of(); var dataTypeService = new TestObjects.TestDataTypeService( @@ -45,7 +45,7 @@ namespace Umbraco.Tests.PublishedContent new DataType(new IntegerPropertyEditor(logger)) { Id = 1003 }, new DataType(new TextboxPropertyEditor(logger)) { Id = 1004 }, new DataType(new MediaPickerPropertyEditor(logger)) { Id = 1005 }); - Composition.RegisterSingleton(f => dataTypeService); + Composition.RegisterUnique(f => dataTypeService); } protected override void Initialize() diff --git a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs index 949031cc65..84f4f5dbd7 100644 --- a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs +++ b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs @@ -48,17 +48,8 @@ namespace Umbraco.Tests.Routing : base(umbracoApplication) { } - public override void Boot(IRegister container) - { - // do it before anything else - this is the only place where it's possible - var logger = Mock.Of(); - container.RegisterInstance(logger); - var profiler = Mock.Of(); - container.RegisterInstance(profiler); - container.RegisterInstance(new ProfilingLogger(logger, profiler)); - - base.Boot(container); - } + protected override ILogger GetLogger() => Mock.Of(); + protected override IProfiler GetProfiler() => Mock.Of(); } protected override void Compose() @@ -69,12 +60,12 @@ namespace Umbraco.Tests.Routing Current.DefaultRenderMvcControllerType = typeof(RenderMvcController); // fixme WRONG! var surfaceControllerTypes = new SurfaceControllerTypeCollection(Composition.TypeLoader.GetSurfaceControllers()); - Composition.RegisterInstance(surfaceControllerTypes); + Composition.RegisterUnique(surfaceControllerTypes); var umbracoApiControllerTypes = new UmbracoApiControllerTypeCollection(Composition.TypeLoader.GetUmbracoApiControllers()); - Composition.RegisterInstance(umbracoApiControllerTypes); + Composition.RegisterUnique(umbracoApiControllerTypes); - Composition.RegisterSingleton(_ => new DefaultShortStringHelper(SettingsForTests.GetDefaultUmbracoSettings())); + Composition.RegisterUnique(_ => new DefaultShortStringHelper(SettingsForTests.GetDefaultUmbracoSettings())); } public override void TearDown() diff --git a/src/Umbraco.Tests/Routing/UrlRoutingTestBase.cs b/src/Umbraco.Tests/Routing/UrlRoutingTestBase.cs index 100e814c83..7566c5372d 100644 --- a/src/Umbraco.Tests/Routing/UrlRoutingTestBase.cs +++ b/src/Umbraco.Tests/Routing/UrlRoutingTestBase.cs @@ -34,7 +34,7 @@ namespace Umbraco.Tests.Routing { base.Compose(); - Composition.RegisterSingleton(_ => GetServiceContext()); + Composition.RegisterUnique(_ => GetServiceContext()); } protected ServiceContext GetServiceContext() diff --git a/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs b/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs index 4ff732db01..3c6358f427 100644 --- a/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs +++ b/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs @@ -20,7 +20,7 @@ namespace Umbraco.Tests.Routing { base.Compose(); - Composition.RegisterSingleton(_ => Mock.Of()); + Composition.RegisterUnique(_ => Mock.Of()); Composition.Register(); } diff --git a/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs b/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs index e2c55b1003..13ec434608 100644 --- a/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs +++ b/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs @@ -22,7 +22,7 @@ namespace Umbraco.Tests.Routing protected override void Compose() { base.Compose(); - Composition.RegisterSingleton(_ => Mock.Of()); + Composition.RegisterUnique(_ => Mock.Of()); Composition.Register(); } diff --git a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs index 092ed54a35..2ef6480193 100644 --- a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs +++ b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs @@ -131,15 +131,16 @@ namespace Umbraco.Tests.Runtimes It.IsAny())) .Returns(Mock.Of()); - composition.RegisterInstance(scopeProvider); + composition.RegisterUnique(scopeProvider); } private MainDom _mainDom; - public override void Boot(IRegister container) + public override IFactory Boot(IRegister container) { - base.Boot(container); - _mainDom = Current.Factory.GetInstance(); + var factory = base.Boot(container); + _mainDom = factory.GetInstance(); + return factory; } public override void Terminate() @@ -184,7 +185,7 @@ namespace Umbraco.Tests.Runtimes base.Compose(composition); composition.Register(factory => SettingsForTests.GetDefaultUmbracoSettings()); - composition.RegisterSingleton(); + composition.RegisterUnique(); Composed = true; } diff --git a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs index 933d8e9f7e..6a1a7272e7 100644 --- a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs @@ -38,10 +38,10 @@ namespace Umbraco.Tests.Scoping _testObjects = new TestObjects(register); - register.RegisterSingleton(factory => new FileSystems(factory, factory.TryGetInstance())); + composition.RegisterUnique(factory => new FileSystems(factory, factory.TryGetInstance())); composition.WithCollectionBuilder(); - Current.Factory = register.CreateFactory(); + Current.Factory = composition.CreateFactory(); SettingsForTests.Reset(); // ensure we have configuration } diff --git a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs index 1ab6f8d392..6e173128e3 100644 --- a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs @@ -44,8 +44,8 @@ namespace Umbraco.Tests.Scoping // but then, it requires a lot of plumbing ;( // fixme - and we cannot inject a DistributedCache yet // so doing all this mess - Composition.RegisterSingleton(); - Composition.RegisterSingleton(f => Mock.Of()); + Composition.RegisterUnique(); + Composition.RegisterUnique(f => Mock.Of()); Composition.WithCollectionBuilder() .Add(() => Composition.TypeLoader.GetCacheRefreshers()); } diff --git a/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs b/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs index 815da6e6a6..0f990427ac 100644 --- a/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs @@ -30,8 +30,8 @@ namespace Umbraco.Tests.Scoping // but then, it requires a lot of plumbing ;( // fixme - and we cannot inject a DistributedCache yet // so doing all this mess - Composition.RegisterSingleton(); - Composition.RegisterSingleton(f => Mock.Of()); + Composition.RegisterUnique(); + Composition.RegisterUnique(f => Mock.Of()); Composition.WithCollectionBuilder() .Add(() => Composition.TypeLoader.GetCacheRefreshers()); } diff --git a/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs b/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs index 8855bc5a13..912dd317d7 100644 --- a/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs @@ -32,8 +32,8 @@ namespace Umbraco.Tests.Scoping // but then, it requires a lot of plumbing ;( // fixme - and we cannot inject a DistributedCache yet // so doing all this mess - Composition.RegisterSingleton(); - Composition.RegisterSingleton(f => Mock.Of()); + Composition.RegisterUnique(); + Composition.RegisterUnique(f => Mock.Of()); Composition.WithCollectionBuilder() .Add(() => Composition.TypeLoader.GetCacheRefreshers()); } diff --git a/src/Umbraco.Tests/Services/ContentServiceTests.cs b/src/Umbraco.Tests/Services/ContentServiceTests.cs index 9b33b1d30d..6b925ecb22 100644 --- a/src/Umbraco.Tests/Services/ContentServiceTests.cs +++ b/src/Umbraco.Tests/Services/ContentServiceTests.cs @@ -57,7 +57,7 @@ namespace Umbraco.Tests.Services { base.Compose(); - Composition.RegisterSingleton(factory => Mock.Of()); + Composition.RegisterUnique(factory => Mock.Of()); } /// @@ -279,7 +279,7 @@ namespace Umbraco.Tests.Services c.ContentSchedule.Add(now.AddSeconds(5), null); //release in 5 seconds var r = ServiceContext.ContentService.Save(c); Assert.IsTrue(r.Success, r.Result.ToString()); - } + } else { c.ContentSchedule.Add(null, now.AddSeconds(5)); //expire in 5 seconds @@ -315,7 +315,7 @@ namespace Umbraco.Tests.Services variant.Add(c); } - + var runSched = ServiceContext.ContentService.PerformScheduledPublish( now.AddMinutes(1)).ToList(); //process anything scheduled before a minute from now @@ -1305,7 +1305,7 @@ namespace Umbraco.Tests.Services public void Can_Unpublish_Content_Variation() { // Arrange - + var langUk = new Language("en-GB") { IsDefault = true }; var langFr = new Language("fr-FR"); @@ -1629,7 +1629,7 @@ namespace Umbraco.Tests.Services foreach (var x in descendants) Console.WriteLine(" ".Substring(0, x.Level) + x.Id); } - + Console.WriteLine(); // publish parent & its branch @@ -1983,7 +1983,7 @@ namespace Umbraco.Tests.Services var descendants = new List(); while(page * pageSize < total) descendants.AddRange(contentService.GetPagedDescendants(content.Id, page++, pageSize, out total)); - + Assert.AreNotEqual(-20, content.ParentId); Assert.IsFalse(content.Trashed); Assert.AreEqual(3, descendants.Count); diff --git a/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs b/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs index 5cd1cdd1bc..94d2126bd2 100644 --- a/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs +++ b/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Threading; -using LightInject; using Moq; using NUnit.Framework; using Umbraco.Core; @@ -35,8 +34,8 @@ namespace Umbraco.Tests.Services base.Compose(); // pfew - see note in ScopedNuCacheTests? - Composition.RegisterSingleton(); - Composition.RegisterSingleton(f => Mock.Of()); + Composition.RegisterUnique(); + Composition.RegisterUnique(f => Mock.Of()); Composition.WithCollectionBuilder() .Add(() => Composition.TypeLoader.GetCacheRefreshers()); } diff --git a/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs b/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs index b64b4dbf16..0ceaffa916 100644 --- a/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs +++ b/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs @@ -69,7 +69,7 @@ namespace Umbraco.Tests.Strings })); // fixme - move to a "compose" thing? - Composition.RegisterSingleton(f => _helper); + Composition.RegisterUnique(f => _helper); } private static readonly Regex FrenchElisionsRegex = new Regex("\\b(c|d|j|l|m|n|qu|s|t)('|\u8217)", RegexOptions.Compiled | RegexOptions.IgnoreCase); diff --git a/src/Umbraco.Tests/Strings/StringExtensionsTests.cs b/src/Umbraco.Tests/Strings/StringExtensionsTests.cs index bcb6f0d60d..349648dd98 100644 --- a/src/Umbraco.Tests/Strings/StringExtensionsTests.cs +++ b/src/Umbraco.Tests/Strings/StringExtensionsTests.cs @@ -1,15 +1,11 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.Globalization; using System.Linq; -using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Composing; -using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Strings; -using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; namespace Umbraco.Tests.Strings @@ -17,12 +13,10 @@ namespace Umbraco.Tests.Strings [TestFixture] public class StringExtensionsTests : UmbracoTestBase { - public override void SetUp() + protected override void Compose() { - base.SetUp(); - - // fixme - in "compose"? - Composition.RegisterSingleton(_ => new MockShortStringHelper()); + base.Compose(); + Composition.RegisterUnique(_ => new MockShortStringHelper()); } [Test] diff --git a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs index 9dd8324e9f..a88438efce 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs @@ -35,23 +35,23 @@ namespace Umbraco.Tests.TestHelpers var sqlSyntax = new SqlCeSyntaxProvider(); var container = RegisterFactory.Create(); - + var composition = new Composition(container, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); - container.RegisterSingleton(_ => Mock.Of()); - container.RegisterSingleton(_ => Mock.Of()); + composition.RegisterUnique(_ => Mock.Of()); + composition.RegisterUnique(_ => Mock.Of()); var logger = new ProfilingLogger(Mock.Of(), Mock.Of()); var pluginManager = new TypeLoader(NullCacheProvider.Instance, SettingsForTests.GenerateMockGlobalSettings(), logger, false); - container.RegisterInstance(pluginManager); + composition.RegisterUnique(pluginManager); composition.WithCollectionBuilder() .Add(() => Current.TypeLoader.GetAssignedMapperTypes()); - var factory = Current.Factory = container.CreateFactory(); + var factory = Current.Factory = composition.CreateFactory(); Mappers = factory.GetInstance(); diff --git a/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs b/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs index 832bbd141d..d969f8c3d3 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs @@ -27,8 +27,8 @@ namespace Umbraco.Tests.TestHelpers { base.Compose(); - Composition.RegisterSingleton(); - Composition.RegisterSingleton(); + Composition.RegisterUnique(); + Composition.RegisterUnique(); } protected override void Initialize() diff --git a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs index 72468f89b8..2daf86796b 100644 --- a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs +++ b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs @@ -80,7 +80,7 @@ namespace Umbraco.Tests.TestHelpers .Clear() .Add(() => Composition.TypeLoader.GetDataEditors()); - Composition.RegisterSingleton(f => + Composition.RegisterUnique(f => { if (Options.Database == UmbracoTestOptions.Database.None) return TestObjects.GetDatabaseFactoryMock(); diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index 67fa8361ba..72da9e9ef2 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -130,17 +130,18 @@ namespace Umbraco.Tests.Testing var register = RegisterFactory.Create(); - register.RegisterInstance(typeLoader); - register.RegisterInstance(logger); - register.RegisterInstance(profiler); - register.RegisterInstance(proflogger); - register.RegisterInstance(cacheHelper); - register.RegisterInstance(cacheHelper.RuntimeCache); - Composition = new Composition(register, typeLoader, proflogger, RuntimeLevel.Run); + + Composition.RegisterUnique(typeLoader); + Composition.RegisterUnique(logger); + Composition.RegisterUnique(profiler); + Composition.RegisterUnique(proflogger); + Composition.RegisterUnique(cacheHelper); + Composition.RegisterUnique(cacheHelper.RuntimeCache); + TestObjects = new TestObjects(register); Compose(); - Current.Factory = Factory = register.CreateFactory(); + Current.Factory = Factory = Composition.CreateFactory(); Initialize(); } @@ -209,11 +210,11 @@ namespace Umbraco.Tests.Testing Umbraco.Web.Composing.Current.UmbracoContextAccessor = new TestUmbracoContextAccessor(); // web - Composition.Register(_ => Umbraco.Web.Composing.Current.UmbracoContextAccessor); - Composition.RegisterSingleton(); + Composition.RegisterUnique(_ => Umbraco.Web.Composing.Current.UmbracoContextAccessor); + Composition.RegisterUnique(); Composition.WithCollectionBuilder(); - Composition.Register(); - Composition.Register(); + Composition.RegisterUnique(); + Composition.RegisterUnique(); } protected virtual void ComposeWtf() @@ -221,14 +222,14 @@ namespace Umbraco.Tests.Testing // what else? var runtimeStateMock = new Mock(); runtimeStateMock.Setup(x => x.Level).Returns(RuntimeLevel.Run); - Composition.RegisterSingleton(f => runtimeStateMock.Object); + Composition.RegisterUnique(f => runtimeStateMock.Object); // ah... Composition.WithCollectionBuilder(); Composition.WithCollectionBuilder(); - Composition.RegisterSingleton(); + Composition.RegisterUnique(); - Composition.RegisterSingleton(); + Composition.RegisterUnique(); // register empty content apps collection Composition.WithCollectionBuilder(); @@ -299,58 +300,58 @@ namespace Umbraco.Tests.Testing Composition.ComposeRepositories(); // register basic stuff that might need to be there for some container resolvers to work - Composition.RegisterSingleton(factory => umbracoSettings); - Composition.RegisterSingleton(factory => globalSettings); - Composition.RegisterSingleton(factory => umbracoSettings.Content); - Composition.RegisterSingleton(factory => umbracoSettings.Templates); - Composition.RegisterSingleton(factory => umbracoSettings.WebRouting); + Composition.RegisterUnique(factory => umbracoSettings); + Composition.RegisterUnique(factory => globalSettings); + Composition.RegisterUnique(factory => umbracoSettings.Content); + Composition.RegisterUnique(factory => umbracoSettings.Templates); + Composition.RegisterUnique(factory => umbracoSettings.WebRouting); - Composition.RegisterSingleton(factory => ExamineManager.Instance); + Composition.RegisterUnique(factory => ExamineManager.Instance); // register filesystems - Composition.RegisterSingleton(factory => TestObjects.GetFileSystemsMock()); + Composition.RegisterUnique(factory => TestObjects.GetFileSystemsMock()); var logger = Mock.Of(); var scheme = Mock.Of(); var config = Mock.Of(); var mediaFileSystem = new MediaFileSystem(Mock.Of(), config, scheme, logger); - Composition.RegisterSingleton(factory => mediaFileSystem); + Composition.RegisterUnique(factory => mediaFileSystem); // no factory (noop) - Composition.RegisterSingleton(); + Composition.RegisterUnique(); // register application stuff (database factory & context, services...) Composition.WithCollectionBuilder() .AddCoreMappers(); - Composition.RegisterSingleton(_ => new TransientEventMessagesFactory()); - Composition.RegisterSingleton(f => new UmbracoDatabaseFactory( + Composition.RegisterUnique(_ => new TransientEventMessagesFactory()); + Composition.RegisterUnique(f => new UmbracoDatabaseFactory( Constants.System.UmbracoConnectionName, Logger, new Lazy(Mock.Of))); - Composition.RegisterSingleton(f => f.TryGetInstance().SqlContext); + Composition.RegisterUnique(f => f.TryGetInstance().SqlContext); Composition.WithCollectionBuilder(); // empty - Composition.RegisterSingleton(factory + Composition.RegisterUnique(factory => TestObjects.GetScopeProvider(factory.TryGetInstance(), factory.TryGetInstance(), factory.TryGetInstance())); - Composition.RegisterSingleton(factory => (IScopeAccessor) factory.GetInstance()); + Composition.RegisterUnique(factory => (IScopeAccessor) factory.GetInstance()); Composition.ComposeServices(); // composition root is doing weird things, fix - Composition.RegisterSingleton(); - Composition.RegisterSingleton(); + Composition.RegisterUnique(); + Composition.RegisterUnique(); // somehow property editor ends up wanting this Composition.WithCollectionBuilder(); - Composition.RegisterSingleton(); + Composition.RegisterUnique(); // note - don't register collections, use builders Composition.WithCollectionBuilder(); - Composition.RegisterSingleton(); - Composition.RegisterSingleton(); + Composition.RegisterUnique(); + Composition.RegisterUnique(); } #endregion diff --git a/src/Umbraco.Tests/TreesAndSections/SectionTests.cs b/src/Umbraco.Tests/TreesAndSections/SectionTests.cs index 91f2cef961..1f4a01fd3d 100644 --- a/src/Umbraco.Tests/TreesAndSections/SectionTests.cs +++ b/src/Umbraco.Tests/TreesAndSections/SectionTests.cs @@ -3,8 +3,6 @@ using NUnit.Framework; using Umbraco.Core.Services; using Umbraco.Tests.TestHelpers; using System; -using System.Linq; -using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Tests.Testing; using Umbraco.Web.Services; @@ -22,7 +20,7 @@ namespace Umbraco.Tests.TreesAndSections protected override void Compose() { base.Compose(); - Composition.Register(); + Composition.RegisterUnique(); } public override void SetUp() diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index c84aef7256..09e8cd312d 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -116,7 +116,7 @@ - + diff --git a/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs b/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs index eea755455d..5be3fe2e7e 100644 --- a/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs +++ b/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs @@ -28,7 +28,7 @@ namespace Umbraco.Tests.UmbracoExamine { base.Compose(); - Composition.RegisterSingleton(_ => new DefaultShortStringHelper(SettingsForTests.GetDefaultUmbracoSettings())); + Composition.RegisterUnique(_ => new DefaultShortStringHelper(SettingsForTests.GetDefaultUmbracoSettings())); } } } diff --git a/src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs b/src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs index 8aae044c55..ec97b92c8e 100644 --- a/src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs +++ b/src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs @@ -81,14 +81,14 @@ namespace Umbraco.Tests.Web.Controllers var textService = new Mock(); textService.Setup(x => x.Localize(It.IsAny(), It.IsAny(), It.IsAny>())).Returns(""); - Composition.RegisterSingleton(f => Mock.Of()); - Composition.RegisterSingleton(f => userServiceMock.Object); - Composition.RegisterSingleton(f => entityService.Object); - Composition.RegisterSingleton(f => dataTypeService.Object); - Composition.RegisterSingleton(f => langService.Object); - Composition.RegisterSingleton(f => textService.Object); - Composition.RegisterSingleton(f => Mock.Of()); - Composition.RegisterSingleton(f => new UmbracoApiControllerTypeCollection(new[] { typeof(ContentTreeController) })); + Composition.RegisterUnique(f => Mock.Of()); + Composition.RegisterUnique(f => userServiceMock.Object); + Composition.RegisterUnique(f => entityService.Object); + Composition.RegisterUnique(f => dataTypeService.Object); + Composition.RegisterUnique(f => langService.Object); + Composition.RegisterUnique(f => textService.Object); + Composition.RegisterUnique(f => Mock.Of()); + Composition.RegisterUnique(f => new UmbracoApiControllerTypeCollection(new[] { typeof(ContentTreeController) })); } private MultipartFormDataContent GetMultiPartRequestContent(string json) diff --git a/src/Umbraco.Tests/Web/Controllers/UsersControllerTests.cs b/src/Umbraco.Tests/Web/Controllers/UsersControllerTests.cs index d62cf7b93c..857e922ac9 100644 --- a/src/Umbraco.Tests/Web/Controllers/UsersControllerTests.cs +++ b/src/Umbraco.Tests/Web/Controllers/UsersControllerTests.cs @@ -38,12 +38,12 @@ namespace Umbraco.Tests.Web.Controllers // replace the true IUserService implementation with a mock // so that each test can configure the service to their liking - Composition.RegisterSingleton(f => Mock.Of()); + Composition.RegisterUnique(f => Mock.Of()); // kill the true IEntityService too - Composition.RegisterSingleton(f => Mock.Of()); + Composition.RegisterUnique(f => Mock.Of()); - Composition.RegisterSingleton(); + Composition.RegisterUnique(); } [Test] diff --git a/src/Umbraco.Web/Components/NotificationsComponent.cs b/src/Umbraco.Web/Components/NotificationsComponent.cs index b54dce4e3e..685029f038 100644 --- a/src/Umbraco.Web/Components/NotificationsComponent.cs +++ b/src/Umbraco.Web/Components/NotificationsComponent.cs @@ -23,7 +23,7 @@ namespace Umbraco.Web.Components public override void Compose(Composition composition) { base.Compose(composition); - composition.RegisterSingleton(); + composition.RegisterUnique(); } public void Initialize(INotificationService notificationService, Notifier notifier, ActionCollection actions) diff --git a/src/Umbraco.Web/Composing/LightInject/LightInjectContainer.cs b/src/Umbraco.Web/Composing/LightInject/LightInjectContainer.cs index ae7f769753..103cd32912 100644 --- a/src/Umbraco.Web/Composing/LightInject/LightInjectContainer.cs +++ b/src/Umbraco.Web/Composing/LightInject/LightInjectContainer.cs @@ -27,7 +27,7 @@ namespace Umbraco.Web.Composing.LightInject public override void ConfigureForWeb() { // IoC setup for LightInject for MVC/WebApi - // see comments on MixedLightInjectScopeManagerProvider for explainations of what we are doing here + // see comments on MixedLightInjectScopeManagerProvider for explanations of what we are doing here if (!(Container.ScopeManagerProvider is MixedLightInjectScopeManagerProvider smp)) throw new Exception("Container.ScopeManagerProvider is not MixedLightInjectScopeManagerProvider."); Container.EnableMvc(); // does container.EnablePerWebRequestScope() diff --git a/src/Umbraco.Web/CompositionExtensions.cs b/src/Umbraco.Web/CompositionExtensions.cs index 7725fe6524..91aceebdc0 100644 --- a/src/Umbraco.Web/CompositionExtensions.cs +++ b/src/Umbraco.Web/CompositionExtensions.cs @@ -8,7 +8,6 @@ using Umbraco.Web.Mvc; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; using Umbraco.Web.ContentApps; -using Umbraco.Web.Features; // the namespace here is intentional - although defined in Umbraco.Web assembly, // this class should be visible when using Umbraco.Core.Components, alongside @@ -80,7 +79,7 @@ namespace Umbraco.Core.Components #endregion - #region Singletons + #region Uniques /// /// Sets the content last chance finder. @@ -90,7 +89,7 @@ namespace Umbraco.Core.Components public static void SetContentLastChanceFinder(this Composition composition) where T : IContentLastChanceFinder { - composition.RegisterSingleton(); + composition.RegisterUnique(); } /// @@ -100,7 +99,7 @@ namespace Umbraco.Core.Components /// A function creating a last chance finder. public static void SetContentLastChanceFinder(this Composition composition, Func factory) { - composition.RegisterSingleton(factory); + composition.RegisterUnique(factory); } /// @@ -110,7 +109,7 @@ namespace Umbraco.Core.Components /// A last chance finder. public static void SetContentLastChanceFinder(this Composition composition, IContentLastChanceFinder finder) { - composition.RegisterSingleton(_ => finder); + composition.RegisterUnique(_ => finder); } /// @@ -131,7 +130,7 @@ namespace Umbraco.Core.Components public static void SetPublishedSnapshotService(this Composition composition) where T : IPublishedSnapshotService { - composition.RegisterSingleton(); + composition.RegisterUnique(); } /// @@ -141,7 +140,7 @@ namespace Umbraco.Core.Components /// A function creating a published snapshot service. public static void SetPublishedSnapshotService(this Composition composition, Func factory) { - composition.RegisterSingleton(factory); + composition.RegisterUnique(factory); } /// @@ -151,7 +150,7 @@ namespace Umbraco.Core.Components /// A published snapshot service. public static void SetPublishedSnapshotService(this Composition composition, IPublishedSnapshotService service) { - composition.RegisterSingleton(_ => service); + composition.RegisterUnique(_ => service); } /// @@ -162,7 +161,7 @@ namespace Umbraco.Core.Components public static void SetSiteDomainHelper(this Composition composition) where T : ISiteDomainHelper { - composition.RegisterSingleton(); + composition.RegisterUnique(); } /// @@ -172,7 +171,7 @@ namespace Umbraco.Core.Components /// A function creating a helper. public static void SetSiteDomainHelper(this Composition composition, Func factory) { - composition.RegisterSingleton(factory); + composition.RegisterUnique(factory); } /// @@ -182,7 +181,7 @@ namespace Umbraco.Core.Components /// A helper. public static void SetSiteDomainHelper(this Composition composition, ISiteDomainHelper helper) { - composition.RegisterSingleton(_ => helper); + composition.RegisterUnique(_ => helper); } #endregion diff --git a/src/Umbraco.Web/Runtime/WebRuntime.cs b/src/Umbraco.Web/Runtime/WebRuntime.cs index 621bab282d..525a8abf77 100644 --- a/src/Umbraco.Web/Runtime/WebRuntime.cs +++ b/src/Umbraco.Web/Runtime/WebRuntime.cs @@ -28,7 +28,7 @@ namespace Umbraco.Web.Runtime } /// - public override void Boot(IRegister register) + public override IFactory Boot(IRegister register) { // create and start asap to profile boot var debug = GlobalSettings.DebugMode; @@ -44,10 +44,15 @@ namespace Umbraco.Web.Runtime _webProfiler = new VoidProfiler(); } - base.Boot(register); + var factory = base.Boot(register); - // now (and only now) is the time to switch over to perWebRequest scopes - register.EnablePerWebRequestScope(); + // now (and only now) is the time to switch over to perWebRequest scopes. + // up until that point we may not have a request, and scoped services would + // fail to resolve - but we run Initialize within a factory scope - and then, + // here, we switch the factory to bind scopes to requests + factory.EnablePerWebRequestScope(); + + return factory; } /// @@ -58,7 +63,7 @@ namespace Umbraco.Web.Runtime // some components may want to initialize with the UmbracoApplicationBase // well, they should not - we should not do this // TODO remove this eventually. - composition.RegisterInstance(_umbracoApplication); + composition.RegisterUnique(_umbracoApplication); } #region Getters diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs index e5973b24bc..1e5dd51c7d 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs @@ -66,7 +66,7 @@ namespace Umbraco.Web.Runtime composition.Register(); - composition.RegisterSingleton(); // required for hybrid accessors + composition.RegisterUnique(); // required for hybrid accessors composition.ComposeWebMappingProfiles(); @@ -81,21 +81,21 @@ namespace Umbraco.Web.Runtime composition.Register(); // register accessors for cultures - composition.RegisterSingleton(); - composition.RegisterSingleton(); + composition.RegisterUnique(); + composition.RegisterUnique(); // register the http context and umbraco context accessors // we *should* use the HttpContextUmbracoContextAccessor, however there are cases when // we have no http context, eg when booting Umbraco or in background threads, so instead // let's use an hybrid accessor that can fall back to a ThreadStatic context. - composition.RegisterSingleton(); + composition.RegisterUnique(); // register a per-request HttpContextBase object // is per-request so only one wrapper is created per request composition.Register(factory => new HttpContextWrapper(factory.GetInstance().HttpContext), Lifetime.Request); // register the published snapshot accessor - the "current" published snapshot is in the umbraco context - composition.RegisterSingleton(); + composition.RegisterUnique(); // we should stop injecting UmbracoContext and always inject IUmbracoContextAccessor, however at the moment // there are tons of places (controllers...) which require UmbracoContext in their ctor - so let's register @@ -104,21 +104,22 @@ namespace Umbraco.Web.Runtime composition.Register(factory => factory.GetInstance().UmbracoContext, Lifetime.Request); // register the umbraco helper - composition.RegisterSingleton(); + composition.RegisterUnique(); // register distributed cache - composition.RegisterSingleton(f => new DistributedCache()); + composition.RegisterUnique(f => new DistributedCache()); // replace some services - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); - composition.RegisterSingleton(factory => ExamineManager.Instance); + composition.RegisterUnique(factory => ExamineManager.Instance); // configure the container for web composition.ConfigureForWeb(); + composition .ComposeMvcControllers(GetType().Assembly) .ComposeApiControllers(GetType().Assembly); @@ -131,7 +132,7 @@ namespace Umbraco.Web.Runtime composition.WithCollectionBuilder(); - composition.RegisterSingleton(); + composition.RegisterUnique(); // set the default RenderMvcController Current.DefaultRenderMvcControllerType = typeof(RenderMvcController); // fixme WRONG! @@ -140,10 +141,10 @@ namespace Umbraco.Web.Runtime .Add(() => composition.TypeLoader.GetTypes()); var surfaceControllerTypes = new SurfaceControllerTypeCollection(composition.TypeLoader.GetSurfaceControllers()); - composition.RegisterInstance(surfaceControllerTypes); + composition.RegisterUnique(surfaceControllerTypes); var umbracoApiControllerTypes = new UmbracoApiControllerTypeCollection(composition.TypeLoader.GetUmbracoApiControllers()); - composition.RegisterInstance(umbracoApiControllerTypes); + composition.RegisterUnique(umbracoApiControllerTypes); // both TinyMceValueConverter (in Core) and RteMacroRenderingValueConverter (in Web) will be // discovered when CoreBootManager configures the converters. We HAVE to remove one of them @@ -165,7 +166,7 @@ namespace Umbraco.Web.Runtime .Append() .Append(); - composition.RegisterSingleton(); + composition.RegisterUnique(); composition.WithCollectionBuilder() // all built-in finders in the correct order, @@ -177,9 +178,9 @@ namespace Umbraco.Web.Runtime .Append() .Append(); - composition.RegisterSingleton(); + composition.RegisterUnique(); - composition.RegisterSingleton(); + composition.RegisterUnique(); // register *all* checks, except those marked [HideFromTypeFinder] of course composition.WithCollectionBuilder() @@ -192,14 +193,14 @@ namespace Umbraco.Web.Runtime composition.RegisterAuto(typeof(UmbracoViewPage<>)); // register published router - composition.RegisterSingleton(); + composition.RegisterUnique(); composition.Register(_ => UmbracoConfig.For.UmbracoSettings().WebRouting); // register preview SignalR hub - composition.RegisterSingleton(_ => GlobalHost.ConnectionManager.GetHubContext()); + composition.RegisterUnique(_ => GlobalHost.ConnectionManager.GetHubContext()); // register properties fallback - composition.RegisterSingleton(); + composition.RegisterUnique(); // register known content apps composition.WithCollectionBuilder() diff --git a/src/Umbraco.Web/SignalR/PreviewHubComponent.cs b/src/Umbraco.Web/SignalR/PreviewHubComponent.cs index e0e47ca666..984ba85522 100644 --- a/src/Umbraco.Web/SignalR/PreviewHubComponent.cs +++ b/src/Umbraco.Web/SignalR/PreviewHubComponent.cs @@ -2,7 +2,6 @@ using Microsoft.AspNet.SignalR; using Umbraco.Core; using Umbraco.Core.Components; -using Umbraco.Core.Composing; using Umbraco.Core.Sync; using Umbraco.Web.Cache; @@ -14,7 +13,7 @@ namespace Umbraco.Web.SignalR public override void Compose(Composition composition) { base.Compose(composition); - composition.RegisterSingleton(_ => GlobalHost.ConnectionManager.GetHubContext()); + composition.RegisterUnique(_ => GlobalHost.ConnectionManager.GetHubContext()); } // using a lazy arg here means that we won't create the hub until necessary diff --git a/src/Umbraco.Web/UmbracoApplicationBase.cs b/src/Umbraco.Web/UmbracoApplicationBase.cs index 7b8fa56201..650229a21b 100644 --- a/src/Umbraco.Web/UmbracoApplicationBase.cs +++ b/src/Umbraco.Web/UmbracoApplicationBase.cs @@ -25,7 +25,7 @@ namespace Umbraco.Web /// /// Gets the application register. /// - protected virtual IRegister GetContainer() + protected virtual IRegister GetRegister() { return RegisterFactory.Create(); } @@ -58,11 +58,11 @@ namespace Umbraco.Web { // ******** THIS IS WHERE EVERYTHING BEGINS ******** - // create the container for the application, and boot + // create the register for the application, and boot // the boot manager is responsible for registrations - var container = GetContainer(); + var register = GetRegister(); _runtime = GetRuntime(); - _runtime.Boot(container); + _runtime.Boot(register); } // called by ASP.NET (auto event wireup) once per app domain From eb0d2464aaf0941c2a21123a006400305845d5ce Mon Sep 17 00:00:00 2001 From: Stephan Date: Thu, 29 Nov 2018 12:27:16 +0100 Subject: [PATCH 112/469] Minor fixes --- src/Umbraco.Core/Runtime/CoreRuntime.cs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Core/Runtime/CoreRuntime.cs b/src/Umbraco.Core/Runtime/CoreRuntime.cs index 978c4f2906..d08d431221 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntime.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntime.cs @@ -94,7 +94,7 @@ namespace Umbraco.Core.Runtime composition.RegisterUnique(databaseFactory); composition.RegisterUnique(_ => databaseFactory.SqlContext); composition.RegisterUnique(typeLoader); - composition.RegisterUnique(_state); + composition.RegisterUnique(_state); // register runtime-level services Compose(composition); @@ -141,6 +141,18 @@ namespace Umbraco.Core.Runtime _state.BootFailedException = bfe; bootTimer.Fail(exception: bfe); // be sure to log the exception - even if we repeat ourselves + // if something goes wrong above, we may end up with no factory + // meaning nothing can get the runtime state, etc - so let's try + // to make sure we have a factory + if (_factory == null) + { + try + { + _factory = Current.Factory = composition.CreateFactory(); + } + catch { /* yea */ } + } + // throwing here can cause w3wp to hard-crash and we want to avoid it. // instead, we're logging the exception and setting level to BootFailed. // various parts of Umbraco such as UmbracoModule and UmbracoDefaultOwinStartup From 2c2873492fbf187fa98dea3c6bbefd4325dee2fb Mon Sep 17 00:00:00 2001 From: Stephan Date: Thu, 29 Nov 2018 12:48:13 +0100 Subject: [PATCH 113/469] Fix merge --- src/Umbraco.Core/Composing/TypeLoader.cs | 6 +++--- src/Umbraco.Web/Composing/Composers/ControllersComposer.cs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Core/Composing/TypeLoader.cs b/src/Umbraco.Core/Composing/TypeLoader.cs index 491ccb0c96..cba92ada64 100644 --- a/src/Umbraco.Core/Composing/TypeLoader.cs +++ b/src/Umbraco.Core/Composing/TypeLoader.cs @@ -530,7 +530,7 @@ namespace Umbraco.Core.Composing // if not caching, or not IDiscoverable, directly get types if (cache == false || typeof(IDiscoverable).IsAssignableFrom(typeof(T)) == false) { - _logger.Logger.Debug("Running a full, non-cached, scan for type {TypeName} (slow).", typeof(T).FullName); + _logger.Debug("Running a full, non-cached, scan for type {TypeName} (slow).", typeof(T).FullName); return GetTypesInternal( typeof (T), null, @@ -574,7 +574,7 @@ namespace Umbraco.Core.Composing // if not caching, or not IDiscoverable, directly get types if (cache == false || typeof(IDiscoverable).IsAssignableFrom(typeof(T)) == false) { - _logger.Logger.Debug("Running a full, non-cached, scan for type {TypeName} / attribute {AttributeName} (slow).", typeof(T).FullName, typeof(TAttribute).FullName); + _logger.Debug("Running a full, non-cached, scan for type {TypeName} / attribute {AttributeName} (slow).", typeof(T).FullName, typeof(TAttribute).FullName); return GetTypesInternal( typeof (T), typeof (TAttribute), @@ -617,7 +617,7 @@ namespace Umbraco.Core.Composing if (cache == false) { - _logger.Logger.Debug("Running a full, non-cached, scan for types / attribute {AttributeName} (slow).", typeof(TAttribute).FullName); + _logger.Debug("Running a full, non-cached, scan for types / attribute {AttributeName} (slow).", typeof(TAttribute).FullName); } return GetTypesInternal( diff --git a/src/Umbraco.Web/Composing/Composers/ControllersComposer.cs b/src/Umbraco.Web/Composing/Composers/ControllersComposer.cs index 0565e0d863..abc25dae49 100644 --- a/src/Umbraco.Web/Composing/Composers/ControllersComposer.cs +++ b/src/Umbraco.Web/Composing/Composers/ControllersComposer.cs @@ -71,11 +71,11 @@ namespace Umbraco.Web.Composing.Composers // scan and register every UmbracoApiController in everything (UmbracoApiController is IDiscoverable and IHttpController) var nonUmbracoWebApiControllers = composition.TypeLoader.GetTypes().Where(x => x.Assembly != umbracoWebAssembly); composition.RegisterControllers(nonUmbracoWebApiControllers); - + return composition; } - private static void RegisterControllers(this Composition composition, IEnumerable controllerTypes) + private static void RegisterControllers(this Composition composition, IEnumerable controllerTypes) { foreach (var controllerType in controllerTypes) composition.Register(controllerType, Lifetime.Request); From cb7c1f9bbda57f447e1ea6b4c3c274c34dc12585 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 4 Dec 2018 11:18:12 +0100 Subject: [PATCH 114/469] use table for installed packages --- .../src/views/packages/views/installed.html | 50 ++++++++++--------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/views/installed.html b/src/Umbraco.Web.UI.Client/src/views/packages/views/installed.html index a015748078..3c443e0bac 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/views/installed.html +++ b/src/Umbraco.Web.UI.Client/src/views/packages/views/installed.html @@ -7,29 +7,33 @@
Installed packages
-
- -
- -
- - -
- -
-
{{ installedPackage.name }}
-
- {{ installedPackage.version }} | {{ installedPackage.url }}| {{ installedPackage.author }} -
-
- -
- Uninstall -
- -
- -
+ + + + + + + +
+
+ + +
+
+
{{ installedPackage.name }}
+
+ {{ installedPackage.version }} | {{ installedPackage.url }}| {{ installedPackage.author }} +
+
+
+ + +
From 04e8fc7fa3e1c5ff0925710fd1c1c334b4348782 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 4 Dec 2018 11:18:32 +0100 Subject: [PATCH 115/469] fix missing form from install local package --- .../src/views/packages/views/install-local.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/views/install-local.html b/src/Umbraco.Web.UI.Client/src/views/packages/views/install-local.html index f7843fb0fc..7f22b7ace8 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/views/install-local.html +++ b/src/Umbraco.Web.UI.Client/src/views/packages/views/install-local.html @@ -4,7 +4,7 @@
-
+
Install a local package by selecting it from your machine. Only install packages from sources you know and trust.

- +
From bd455aaede8a6a354cb7d3fc4f20a224fd21c898 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 4 Dec 2018 11:19:08 +0100 Subject: [PATCH 116/469] fixing up styles to better fit new UI --- .../components/umb-package-local-install.less | 5 +- .../src/less/components/umb-packages.less | 67 +---- .../src/views/packages/views/repo.html | 270 +++++++++--------- 3 files changed, 148 insertions(+), 194 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-package-local-install.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-package-local-install.less index 75f58f983b..99759fcee7 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-package-local-install.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-package-local-install.less @@ -15,7 +15,7 @@ height: 300px; border: 2px dashed @gray-8; border-radius: 3px; - background: @gray-10; + background: @white; display: flex; flex-direction: column; justify-content: center; @@ -74,7 +74,6 @@ // Info state .umb-info-local-items { - border: 2px solid @gray-8; border-radius: 3px; background: @gray-10; display: flex; @@ -84,6 +83,8 @@ margin: 0 20px; width: 100%; max-width: 540px; + background: @white; + box-shadow: 0 1px 1px 0 rgba(0,0,0,.16); } .umb-info-local-items a { diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-packages.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-packages.less index e2cfb0bded..a517605c4a 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-packages.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-packages.less @@ -23,9 +23,7 @@ .umb-packages-search { width: 100%; - background: @gray-10; border-radius: 3px; - padding: 30px; box-sizing: border-box; } @@ -49,60 +47,14 @@ } .umb-packages { - margin: 0 -10px; - display: flex; - flex-wrap: wrap; + display: grid; + grid-gap: 20px; + grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); } // Cards .umb-package { - padding: 10px; box-sizing: border-box; - flex: 0 0 100%; - max-width: 100%; -} - -@media (min-width: 768px) { - .umb-package { - flex: 0 0 50%; - max-width: 50%; - } -} - -@media (min-width: 1200px) { - .umb-package { - flex: 0 0 33.33%; - max-width: 33.33%; - } -} - -@media (min-width: 1400px) { - .umb-package { - flex: 0 0 25%; - max-width: 25%; - } -} - -@media (min-width: 1700px) { - .umb-package { - flex: 0 0 20%; - max-width: 20%; - } -} - - -@media (min-width: 1900px) { - .umb-package { - flex: 0 0 16.66%; - max-width: 16.66%; - } -} - -@media (min-width: 2200px) { - .umb-package { - flex: 0 0 14.28%; - max-width: 14.28%; - } } .umb-package-link { @@ -114,10 +66,11 @@ box-sizing: border-box; height: 100%; width: 100%; - border: 1px solid @gray-9; border-radius: 3px; text-decoration: none !important; transition: border-color 100ms ease; + background-color: @white; + box-shadow: 0 1px 1px 0 rgba(0,0,0,0.16); &:hover { border-color: @turquoise; @@ -151,15 +104,8 @@ // Info .umb-package-info { - padding-right: 15px; - padding-bottom: 15px; - padding-left: 15px; - padding-top: 15px; + padding: 15px; text-align: center; - background: @gray-10; - border-bottom-left-radius: 3px; - border-bottom-right-radius: 3px; - border-top: 1px solid @gray-9; } @@ -251,6 +197,7 @@ border-bottom: 1px solid @gray-8; border-right: 1px solid @gray-8; padding: 10px 0; + background: @white; } diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/views/repo.html b/src/Umbraco.Web.UI.Client/src/views/packages/views/repo.html index 7b4b960c2c..fc272c86ff 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/views/repo.html +++ b/src/Umbraco.Web.UI.Client/src/views/packages/views/repo.html @@ -27,7 +27,7 @@

Popular

-
+
@@ -61,7 +61,7 @@

New Releases

Results for '{{ vm.searchQuery }}'

-
+
@@ -129,147 +129,153 @@
-
{{ vm.package.name }}
+ + +
{{ vm.package.name }}
+
+
+ + -
- - - - - + +
-
- - - - - - - -
- -
-
- -
- + + - -
+ action="vm.downloadPackage(vm.package)" + label-key="packager_packageInstall"> + + + + + + + +
+ +
+ + +
+ +
+
{{ vm.package.ownerInfo.owner }}
+
+ {{ vm.package.ownerInfo.owner }} has {{ vm.package.ownerInfo.karma }} karma points +
+
+
+
+
+ + + +
Information
-
{{ vm.package.ownerInfo.owner }}
-
- {{ vm.package.ownerInfo.owner }} has {{ vm.package.ownerInfo.karma }} karma points + +
+
Owner:
+
{{vm.package.ownerInfo.owner}}
+
+ +
+
Contributors:
+
+ {{ contributor }} +
+
+ +
+
Created:
+
{{vm.package.created | date:'yyyy-MM-dd HH:mm:ss'}}
+
+ +
+
Current version:
+
{{vm.package.latestVersion}}
+
+ +
+
.NET Version:
+
{{vm.package.information.netVersion}}
+
+ +
+
License:
+
{{vm.package.licenseName}}
+
+ +
+
Downloads:
+
{{vm.package.downloads}}
+
+ +
+
Likes:
+
{{vm.package.likes}}
+
+ +
+ + + + + +
Compatibility
+
This package is compatible with the following versions of Umbraco, as reported by community members. Full compatability cannot be gauranteed for versions reported below 100%
+
+
+ {{compatibility.version}} + ({{compatibility.percentage}}%) +
+ + +
+
+
+ + + +
External sources
+ -
-
- -
-
Information
-
- -
-
Owner:
-
{{vm.package.ownerInfo.owner}}
-
- -
-
Contributors:
-
- {{ contributor }} -
-
- -
-
Created:
-
{{vm.package.created | date:'yyyy-MM-dd HH:mm:ss'}}
-
- -
-
Current version:
-
{{vm.package.latestVersion}}
-
- -
-
.NET Version:
-
{{vm.package.information.netVersion}}
-
- -
-
License:
-
{{vm.package.licenseName}}
-
- -
-
Downloads:
-
{{vm.package.downloads}}
-
- -
-
Likes:
-
{{vm.package.likes}}
-
- -
-
- -
-
Compatibility
-
This package is compatible with the following versions of Umbraco, as reported by community members. Full compatability cannot be gauranteed for versions reported below 100%
-
-
- {{compatibility.version}} - ({{compatibility.percentage}}%) -
- - - - -
-
- -
-
External sources
- - -
+ +
From e5d12117d5ac23ccb52de57335b31fa8c0e6b268 Mon Sep 17 00:00:00 2001 From: Stephan Date: Wed, 5 Dec 2018 08:19:21 +0100 Subject: [PATCH 117/469] Composition can set default renderMvc controller --- src/Umbraco.Core/Components/Composition.cs | 8 +++++++ src/Umbraco.Web/CompositionExtensions.cs | 24 +++++++++++++++++++ .../Runtime/WebRuntimeComponent.cs | 6 ++--- 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Core/Components/Composition.cs b/src/Umbraco.Core/Components/Composition.cs index 2f5bd0f6ee..2d8b89fcda 100644 --- a/src/Umbraco.Core/Components/Composition.cs +++ b/src/Umbraco.Core/Components/Composition.cs @@ -85,12 +85,20 @@ namespace Umbraco.Core.Components /// public IFactory CreateFactory() { + foreach (var onCreating in OnCreatingFactory.Values) + onCreating(); + foreach (var unique in _uniques.Values) unique.RegisterTo(_register); return _register.CreateFactory(); } + /// + /// Gets a dictionary of action to execute when creating the factory. + /// + public Dictionary OnCreatingFactory { get; } = new Dictionary(); + #endregion #region Unique diff --git a/src/Umbraco.Web/CompositionExtensions.cs b/src/Umbraco.Web/CompositionExtensions.cs index 91aceebdc0..e3b946d7d7 100644 --- a/src/Umbraco.Web/CompositionExtensions.cs +++ b/src/Umbraco.Web/CompositionExtensions.cs @@ -184,6 +184,30 @@ namespace Umbraco.Core.Components composition.RegisterUnique(_ => helper); } + /// + /// Sets the default controller for rendering template views. + /// + /// The type of the controller. + /// The composition. + /// The controller type is registered to the container by the composition. + public static void SetDefaultRenderMvcController(this Composition composition) + => composition.SetDefaultRenderMvcController(typeof(TController)); + + /// + /// Sets the default controller for rendering template views. + /// + /// The composition. + /// The type of the controller. + /// The controller type is registered to the container by the composition. + public static void SetDefaultRenderMvcController(this Composition composition, Type controllerType) + { + composition.OnCreatingFactory["Umbraco.Core.DefaultRenderMvcController"] = () => + { + composition.Register(controllerType, Lifetime.Request); + Current.DefaultRenderMvcControllerType = controllerType; + }; + } + #endregion } } diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs index 601692b0e9..53ae6112af 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs @@ -121,7 +121,8 @@ namespace Umbraco.Web.Runtime composition.ConfigureForWeb(); composition - .ComposeUmbracoControllers(GetType().Assembly); + .ComposeUmbracoControllers(GetType().Assembly) + .SetDefaultRenderMvcController(); // default controller for template views composition.WithCollectionBuilder() .Add(() => composition.TypeLoader.GetTypes()); // fixme which searchable trees?! @@ -133,9 +134,6 @@ namespace Umbraco.Web.Runtime composition.RegisterUnique(); - // set the default RenderMvcController - Current.DefaultRenderMvcControllerType = typeof(RenderMvcController); // fixme WRONG! - composition.WithCollectionBuilder() .Add(() => composition.TypeLoader.GetTypes()); From a4bdcf99b19e5a85d3f20661bbd5db3950d92a88 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 5 Dec 2018 10:36:20 +0100 Subject: [PATCH 118/469] wip create package editor --- .../src/common/services/overlay.service.js | 5 + .../src/views/packages/edit.controller.js | 154 ++++++++++++ .../src/views/packages/edit.html | 227 ++++++++++++++++++ .../src/views/packages/overview.controller.js | 6 + .../packages/views/created.controller.js | 84 +++++++ .../src/views/packages/views/created.html | 45 ++++ 6 files changed, 521 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js create mode 100644 src/Umbraco.Web.UI.Client/src/views/packages/edit.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/packages/views/created.controller.js create mode 100644 src/Umbraco.Web.UI.Client/src/views/packages/views/created.html diff --git a/src/Umbraco.Web.UI.Client/src/common/services/overlay.service.js b/src/Umbraco.Web.UI.Client/src/common/services/overlay.service.js index 6c50e58490..6de0b4170b 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/overlay.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/overlay.service.js @@ -27,6 +27,11 @@ overlay.position = "center"; } + // use a default empty view if nothing is set + if(!overlay.view) { + overlay.view = "views/common/overlays/default/default.html"; + } + // option to disable backdrop clicks if(overlay.disableBackdropClick) { backdropOptions.disableEventsOnClick = true; diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js new file mode 100644 index 0000000000..a031baa26d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js @@ -0,0 +1,154 @@ +(function () { + "use strict"; + + function EditController($location) { + + const vm = this; + + vm.showBackButton = true; + + // open all expansion panels + vm.propertiesOpen = true; + vm.contentOpen = true; + vm.filesOpen = true; + vm.actionsOpen = true; + + vm.back = back; + vm.createPackage = createPackage; + vm.save = save; + + function onInit() { + // load package + + vm.package = { + "name": "My package" + }; + + vm.documentTypes = [ + { + "name": "Home" + }, + { + "name": "Blog" + }, + { + "name": "Blog Post" + }, + { + "name": "News" + }, + { + "name": "News Item" + }, + { + "name": "Contact" + }, + { + "name": "About" + } + ]; + + vm.templates = [ + { + "name": "Home" + }, + { + "name": "Blog" + }, + { + "name": "Blog Post" + }, + { + "name": "News" + }, + { + "name": "News Item" + }, + { + "name": "Contact" + }, + { + "name": "About" + } + ]; + + vm.stylesheets = [ + { + "name": "styles.css" + }, + { + "name": "carousel.css" + }, + { + "name": "fonts.css" + } + ]; + + vm.macros = [ + { + "name": "Macro 1" + }, + { + "name": "Macro 2" + }, + { + "name": "Macro 3" + } + ]; + + vm.languages = [ + { + "name": "English (United States)" + }, + { + "name": "Danish" + }, + { + "name": "Spanish" + } + ]; + + vm.dictionaryItems = [ + { + "name": "Item 1" + }, + { + "name": "Item 2" + }, + { + "name": "Item 3" + } + ]; + + vm.dataTypes = [ + { + "name": "Datatype 1" + }, + { + "name": "Datatype 2" + }, + { + "name": "Datatype 3" + } + ]; + } + + function back() { + $location.path("packages/packages/overview"); + } + + function createPackage() { + console.log("create package"); + } + + function save() { + console.log("save package"); + } + + onInit(); + + } + + angular.module("umbraco").controller("Umbraco.Editors.Packages.EditController", EditController); + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html new file mode 100644 index 0000000000..68e2a30b99 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html @@ -0,0 +1,227 @@ +
+ +
+ + + + + + + + + + +
+ +
+
Package Properties
+   +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +
+
Package Content
+   +
+ +
+ + + + +
+ +
+
+ + +
+ +
+
+ + +
+ +
+
+ + +
+ +
+
+ + +
+ +
+
+ + +
+ +
+
+ + +
+ +
+
+ +
+ +
+ +
+ +
+
Package Files
+   +
+ +
+ + + + + + + +
+ +
+ +
+
+
Package Actions
+   +
+
+ +
+ Documentation +
+ +
+
+
+
+
+ +
+ + + + + + + + + + + + +
+ +
+ +
\ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/overview.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/overview.controller.js index 42fcddaa56..43a9d0473e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/overview.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/overview.controller.js @@ -44,6 +44,12 @@ "view": "views/packages/views/install-local.html", "active": installPackageUri === "local", "alias": "umbInstallLocal" + }, + { + "name": "Created", + "icon": "icon-add", + "view": "views/packages/views/created.html", + "alias": "umbCreatedPackages" } ]; diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/views/created.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/views/created.controller.js new file mode 100644 index 0000000000..8c92f3553c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/packages/views/created.controller.js @@ -0,0 +1,84 @@ +(function () { + "use strict"; + + function CreatedController($timeout, $location, localizationService, overlayService) { + + const vm = this; + + vm.deleteCreatedPackage = deleteCreatedPackage; + vm.goToPackage = goToPackage; + vm.createPackage = createPackage; + + function onInit() { + + vm.createdPackages = []; + + //load created packages + $timeout(function(){ + vm.createdPackages = [ + { + "author": "Test", + "files": [], + "iconUrl": "", + "id": 1, + "license": "MIT License", + "licenseUrl": "http://opensource.org/licenses/MIT", + "name": "Test v8", + "url": "https://test.com", + "version": "0.0.0" + }, + { + "author": "Test", + "files": [], + "iconUrl": "", + "id": 2, + "license": "MIT License", + "licenseUrl": "http://opensource.org/licenses/MIT", + "name": "Another Test v8", + "url": "https://test.com", + "version": "0.0.0" + } + ]; + }, 1000); + + } + + function deleteCreatedPackage(createdPackage) { + + const dialog = { + submitButtonLabelKey: "contentTypeEditor_yesDelete", + submit: function (model) { + performDelete(createdPackage); + overlayService.close(); + }, + close: function () { + overlayService.close(); + } + }; + + localizationService.localize("general_delete").then(value => { + dialog.title = value; + overlayService.open(dialog); + }); + + } + + function performDelete(createdPackage) { + console.log("perform delete"); + } + + function goToPackage(createdPackage) { + $location.path("packages/packages/edit/" + createdPackage.id); + } + + function createPackage() { + console.log("create package"); + } + + onInit(); + + } + + angular.module("umbraco").controller("Umbraco.Editors.Packages.CreatedController", CreatedController); + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/views/created.html b/src/Umbraco.Web.UI.Client/src/views/packages/views/created.html new file mode 100644 index 0000000000..52f0cef9fd --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/packages/views/created.html @@ -0,0 +1,45 @@ +
+ + + + + + + + + + + + + + + + + +
+
+ + +
+
+
{{ createdPackage.name }}
+
+ {{ createdPackage.version }} | {{ createdPackage.url }}| {{ createdPackage.author }} +
+
+
+ + +
+ +
\ No newline at end of file From bd505a857446dacb7b7f5c9ad717bf70c5684aee Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 5 Dec 2018 13:37:01 +0100 Subject: [PATCH 119/469] get doctypes, datatypes, languages etc from the server and bind selection to model + add content picker --- .../src/views/packages/edit.controller.js | 151 ++++++------------ .../src/views/packages/edit.html | 66 ++++++-- 2 files changed, 102 insertions(+), 115 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js index a031baa26d..a161040c24 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js @@ -1,7 +1,7 @@ (function () { "use strict"; - function EditController($location) { + function EditController($location, contentTypeResource, templateResource, stylesheetResource, languageResource, dictionaryResource, dataTypeResource, editorService) { const vm = this; @@ -16,6 +16,8 @@ vm.back = back; vm.createPackage = createPackage; vm.save = save; + vm.removeContentItem = removeContentItem; + vm.openContentPicker = openContentPicker; function onInit() { // load package @@ -24,113 +26,39 @@ "name": "My package" }; - vm.documentTypes = [ - { - "name": "Home" - }, - { - "name": "Blog" - }, - { - "name": "Blog Post" - }, - { - "name": "News" - }, - { - "name": "News Item" - }, - { - "name": "Contact" - }, - { - "name": "About" - } - ]; + // get all doc types + contentTypeResource.getAll().then(documentTypes => { + vm.documentTypes = documentTypes; + }); - vm.templates = [ - { - "name": "Home" - }, - { - "name": "Blog" - }, - { - "name": "Blog Post" - }, - { - "name": "News" - }, - { - "name": "News Item" - }, - { - "name": "Contact" - }, - { - "name": "About" - } - ]; + // get all templates + templateResource.getAll().then(templates => { + vm.templates = templates; + }); - vm.stylesheets = [ - { - "name": "styles.css" - }, - { - "name": "carousel.css" - }, - { - "name": "fonts.css" - } - ]; + // get all stylesheets + stylesheetResource.getAll().then(stylesheets => { + vm.stylesheets = stylesheets; + }); - vm.macros = [ - { - "name": "Macro 1" - }, - { - "name": "Macro 2" - }, - { - "name": "Macro 3" - } - ]; + // TODO: implement macros + vm.macros = []; + + // get all languages + languageResource.getAll().then(languages => { + vm.languages = languages; + }); - vm.languages = [ - { - "name": "English (United States)" - }, - { - "name": "Danish" - }, - { - "name": "Spanish" - } - ]; + // get all dictionary items + dictionaryResource.getList().then(dictionaryItems => { + vm.dictionaryItems = dictionaryItems; + }); - vm.dictionaryItems = [ - { - "name": "Item 1" - }, - { - "name": "Item 2" - }, - { - "name": "Item 3" - } - ]; + // get all data types items + dataTypeResource.getAll().then(dataTypes => { + vm.dataTypes = dataTypes; + }); - vm.dataTypes = [ - { - "name": "Datatype 1" - }, - { - "name": "Datatype 2" - }, - { - "name": "Datatype 3" - } - ]; } function back() { @@ -145,6 +73,25 @@ console.log("save package"); } + function removeContentItem() { + vm.package.contentItem = null; + } + + function openContentPicker() { + const contentPicker = { + submit: function(model) { + if(model.selection && model.selection.length > 0) { + vm.package.contentItem = model.selection[0]; + } + editorService.close(); + }, + close: function() { + editorService.close(); + } + }; + editorService.contentPicker(contentPicker); + } + onInit(); } diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html index 68e2a30b99..1888c5d9c1 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html @@ -78,13 +78,43 @@
- + + + + + + + + Add + + + +
@@ -93,7 +123,10 @@
@@ -102,25 +135,26 @@
-
- -
+ NOT IMPLEMENTED
@@ -129,7 +163,10 @@
@@ -138,7 +175,10 @@
From e599685684b86f2e2b2b75f001e727b485b44a5f Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 5 Dec 2018 14:20:34 +0100 Subject: [PATCH 120/469] wip file pickers ui --- .../src/views/packages/edit.controller.js | 17 +++++++++++++++++ .../src/views/packages/edit.html | 17 +++++++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js index a161040c24..c8d6af5d6b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js @@ -18,6 +18,7 @@ vm.save = save; vm.removeContentItem = removeContentItem; vm.openContentPicker = openContentPicker; + vm.openFilePicker = openFilePicker; function onInit() { // load package @@ -92,6 +93,22 @@ editorService.contentPicker(contentPicker); } + function openFilePicker() { + const filePicker = { + treeAlias: "files", + section:"settings", + entityType: "file", + submit: function(model) { + console.log(model.selection); + editorService.close(); + }, + close: function() { + editorService.close(); + } + }; + editorService.contentPicker(filePicker); + } + onInit(); } diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html index 1888c5d9c1..a84d21d709 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html @@ -202,12 +202,25 @@ - + + Add + + - + + + + Add +
From d77796bcacfe4ce2e014b3929cd8d5b50f458454 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 5 Dec 2018 15:06:50 +0100 Subject: [PATCH 121/469] show selected files and control --- .../src/views/packages/edit.controller.js | 38 +++++++++++++++++++ .../src/views/packages/edit.html | 24 +++++++++++- 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js index c8d6af5d6b..dfc0350630 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js @@ -19,6 +19,9 @@ vm.removeContentItem = removeContentItem; vm.openContentPicker = openContentPicker; vm.openFilePicker = openFilePicker; + vm.removeFile = removeFile; + vm.openControlPicker = openControlPicker; + vm.removeControl = removeControl; function onInit() { // load package @@ -98,8 +101,17 @@ treeAlias: "files", section:"settings", entityType: "file", + multiPicker: true, submit: function(model) { console.log(model.selection); + + if(model && model.selection) { + vm.package.files = vm.package.files ? vm.package.files : []; + model.selection.forEach(selected => { + vm.package.files.push(selected); + }); + } + editorService.close(); }, close: function() { @@ -109,6 +121,32 @@ editorService.contentPicker(filePicker); } + function removeFile(index) { + vm.package.files.splice(index, 1); + } + + function openControlPicker() { + const controlPicker = { + treeAlias: "files", + section:"settings", + entityType: "file", + submit: function(model) { + if(model.selection && model.selection.length > 0) { + vm.package.control = model.selection[0]; + } + editorService.close(); + }, + close: function() { + editorService.close(); + } + }; + editorService.contentPicker(controlPicker); + } + + function removeControl() { + vm.package.control = null; + } + onInit(); } diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html index a84d21d709..d6309d812a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html @@ -202,25 +202,47 @@ + + + + Add + + + Add +
From 00428ec2de547c6bd1abadcb67f4d32f3e31ed2f Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Wed, 5 Dec 2018 14:28:07 +0000 Subject: [PATCH 122/469] Adds in new hidden aka initialized=false tree (so that it can be displayed only as a dialog/infinite editor) to display files & folders from root of the site for the package creator UI --- .../src/views/packages/edit.controller.js | 7 +++--- src/Umbraco.Web.UI/config/trees.config | 2 ++ src/Umbraco.Web/Trees/FilesTreeController.cs | 23 +++++++++++++++++++ src/Umbraco.Web/Umbraco.Web.csproj | 1 + 4 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 src/Umbraco.Web/Trees/FilesTreeController.cs diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js index c8d6af5d6b..ffdeee88bd 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js @@ -44,7 +44,7 @@ // TODO: implement macros vm.macros = []; - + // get all languages languageResource.getAll().then(languages => { vm.languages = languages; @@ -95,9 +95,10 @@ function openFilePicker() { const filePicker = { + section: "settings", treeAlias: "files", - section:"settings", entityType: "file", + onlyInitialized: false, submit: function(model) { console.log(model.selection); editorService.close(); @@ -106,7 +107,7 @@ editorService.close(); } }; - editorService.contentPicker(filePicker); + editorService.treePicker(filePicker); } onInit(); diff --git a/src/Umbraco.Web.UI/config/trees.config b/src/Umbraco.Web.UI/config/trees.config index 2b99f8751f..da6f75300a 100644 --- a/src/Umbraco.Web.UI/config/trees.config +++ b/src/Umbraco.Web.UI/config/trees.config @@ -20,6 +20,8 @@ + + diff --git a/src/Umbraco.Web/Trees/FilesTreeController.cs b/src/Umbraco.Web/Trees/FilesTreeController.cs new file mode 100644 index 0000000000..a435d3a668 --- /dev/null +++ b/src/Umbraco.Web/Trees/FilesTreeController.cs @@ -0,0 +1,23 @@ +using Umbraco.Core; +using Umbraco.Core.IO; +using Umbraco.Web.Models.Trees; + +namespace Umbraco.Web.Trees +{ + [CoreTree(TreeGroup = Constants.Trees.Groups.Templating)] + [Tree(Constants.Applications.Settings, "files", "Files", "icon-folder", "icon-folder", sortOrder: 13, initialize: false)] + public class FilesTreeController : FileSystemTreeController + { + protected override IFileSystem FileSystem => new PhysicalFileSystem("~/"); // fixme inject + + protected override string[] Extensions => new string[] { }; + + protected override string FileIcon => "icon-script"; + + protected override void OnRenderFolderNode(ref TreeNode treeNode) + { + //TODO: This isn't the best way to ensure a noop process for clicking a node but it works for now. + treeNode.AdditionalData["jsClickCallback"] = "javascript:void(0);"; + } + } +} diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 32134e7a45..717c2f508e 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -183,6 +183,7 @@ + From 749a25aabbb25fd497759a92c05228d7891a99ae Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 5 Dec 2018 15:41:55 +0100 Subject: [PATCH 123/469] user overlayService for ysods --- .../src/common/services/events.service.js | 1 - .../common/services/umbrequesthelper.service.js | 16 +++++----------- .../src/controllers/main.controller.js | 8 -------- src/Umbraco.Web.UI/Umbraco/Views/Default.cshtml | 6 ------ 4 files changed, 5 insertions(+), 26 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/events.service.js b/src/Umbraco.Web.UI.Client/src/common/services/events.service.js index 6bab8fda81..51f63e6787 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/events.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/events.service.js @@ -6,7 +6,6 @@ app.ready app.authenticated app.notAuthenticated - app.ysod app.reInitialize app.userRefresh app.navigationReady diff --git a/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js index fcb5585d5d..0834799be4 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js @@ -3,7 +3,7 @@ * @name umbraco.services.umbRequestHelper * @description A helper object used for sending requests to the server **/ -function umbRequestHelper($http, $q, notificationsService, eventsService, formHelper) { +function umbRequestHelper($http, $q, notificationsService, eventsService, formHelper, overlayService) { return { @@ -176,11 +176,8 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe //show a ysod dialog if (Umbraco.Sys.ServerVariables["isDebuggingEnabled"] === true) { - eventsService.emit('app.ysod', - { - errorMsg: 'An error occured', - data: response.data - }); + const error = { errorMsg: 'An error occured', data: response.data }; + overlayService.ysod(error); } else { //show a simple error notification @@ -290,11 +287,8 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe } else if (Umbraco.Sys.ServerVariables["isDebuggingEnabled"] === true) { //show a ysod dialog - eventsService.emit('app.ysod', - { - errorMsg: 'An error occured', - data: response.data - }); + const error = { errorMsg: 'An error occured', data: response.data }; + overlayService.ysod(error); } else { //show a simple error notification diff --git a/src/Umbraco.Web.UI.Client/src/controllers/main.controller.js b/src/Umbraco.Web.UI.Client/src/controllers/main.controller.js index 30a7e2ac7d..c2b2ba26d7 100644 --- a/src/Umbraco.Web.UI.Client/src/controllers/main.controller.js +++ b/src/Umbraco.Web.UI.Client/src/controllers/main.controller.js @@ -103,14 +103,6 @@ function MainController($scope, $location, appState, treeService, notificationsS })); - evts.push(eventsService.on("app.ysod", function (name, error) { - $scope.ysodOverlay = { - view: "ysod", - error: error, - show: true - }; - })); - // events for search evts.push(eventsService.on("appState.searchState.changed", function (e, args) { if (args.key === "show") { diff --git a/src/Umbraco.Web.UI/Umbraco/Views/Default.cshtml b/src/Umbraco.Web.UI/Umbraco/Views/Default.cshtml index 4659674c59..2ee71a6555 100644 --- a/src/Umbraco.Web.UI/Umbraco/Views/Default.cshtml +++ b/src/Umbraco.Web.UI/Umbraco/Views/Default.cshtml @@ -106,12 +106,6 @@ parent-scope="overlay.parentScope"> - - - From 74d9945e09e49a5ee7fc9755cf955a283ce3a156 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 5 Dec 2018 15:42:44 +0100 Subject: [PATCH 124/469] Add title to files and control pickers --- src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js index 8b1878d6fc..ff587dd540 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js @@ -98,6 +98,7 @@ function openFilePicker() { const filePicker = { + title: "Select files", section: "settings", treeAlias: "files", entityType: "file", @@ -128,6 +129,7 @@ function openControlPicker() { const controlPicker = { + title: "Select control", treeAlias: "files", section:"settings", entityType: "file", From 8425c3124d9771d0b8b48b4acaaa9a132f592feb Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Wed, 5 Dec 2018 15:15:45 +0000 Subject: [PATCH 125/469] Modify FileSystemTree Controller - that if * is used for file extension then we will return all files :) --- src/Umbraco.Web/Trees/FileSystemTreeController.cs | 4 ++++ src/Umbraco.Web/Trees/FilesTreeController.cs | 6 ++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web/Trees/FileSystemTreeController.cs b/src/Umbraco.Web/Trees/FileSystemTreeController.cs index 9babb656fe..bf301ebe60 100644 --- a/src/Umbraco.Web/Trees/FileSystemTreeController.cs +++ b/src/Umbraco.Web/Trees/FileSystemTreeController.cs @@ -57,6 +57,10 @@ namespace Umbraco.Web.Trees var files = FileSystem.GetFiles(path).Where(x => { var extension = Path.GetExtension(x); + + if (Extensions.Contains("*")) + return true; + return extension != null && Extensions.Contains(extension.Trim('.'), StringComparer.InvariantCultureIgnoreCase); }); diff --git a/src/Umbraco.Web/Trees/FilesTreeController.cs b/src/Umbraco.Web/Trees/FilesTreeController.cs index a435d3a668..947522747d 100644 --- a/src/Umbraco.Web/Trees/FilesTreeController.cs +++ b/src/Umbraco.Web/Trees/FilesTreeController.cs @@ -10,9 +10,11 @@ namespace Umbraco.Web.Trees { protected override IFileSystem FileSystem => new PhysicalFileSystem("~/"); // fixme inject - protected override string[] Extensions => new string[] { }; + private static readonly string[] ExtensionsStatic = { "*" }; - protected override string FileIcon => "icon-script"; + protected override string[] Extensions => ExtensionsStatic; + + protected override string FileIcon => "icon-document"; protected override void OnRenderFolderNode(ref TreeNode treeNode) { From 542b08650b3ce30c842bb07b4865892e859ab024 Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Wed, 5 Dec 2018 22:59:10 +0100 Subject: [PATCH 126/469] Also register RenderMvcControllers --- src/Umbraco.Web/Composing/Composers/ControllersComposer.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web/Composing/Composers/ControllersComposer.cs b/src/Umbraco.Web/Composing/Composers/ControllersComposer.cs index abc25dae49..8c9a78347c 100644 --- a/src/Umbraco.Web/Composing/Composers/ControllersComposer.cs +++ b/src/Umbraco.Web/Composing/Composers/ControllersComposer.cs @@ -59,7 +59,11 @@ namespace Umbraco.Web.Composing.Composers composition.RegisterControllers(umbracoWebControllers); // scan and register every PluginController in everything (PluginController is IDiscoverable and IController) - var nonUmbracoWebPluginController = composition.TypeLoader.GetTypes().Where(x => x.Assembly != umbracoWebAssembly); + var nonUmbracoWebPluginController = composition.TypeLoader + .GetTypes().Where(x => x.Assembly != umbracoWebAssembly) + .Union(composition.TypeLoader + .GetTypes().Where(x => x.Assembly != umbracoWebAssembly) + ); composition.RegisterControllers(nonUmbracoWebPluginController); // scan and register every IHttpController in Umbraco.Web From 72fd8534a629b4440e520738b3c777868d649f1b Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Wed, 5 Dec 2018 23:10:42 +0100 Subject: [PATCH 127/469] Update comments on controller registration --- src/Umbraco.Web/Composing/Composers/ControllersComposer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web/Composing/Composers/ControllersComposer.cs b/src/Umbraco.Web/Composing/Composers/ControllersComposer.cs index 8c9a78347c..f91d1da127 100644 --- a/src/Umbraco.Web/Composing/Composers/ControllersComposer.cs +++ b/src/Umbraco.Web/Composing/Composers/ControllersComposer.cs @@ -22,7 +22,7 @@ namespace Umbraco.Web.Composing.Composers // // We scan and auto-registers: // - every IController and IHttpController that *we* have in Umbraco.Web - // - PluginController and UmbracoApiController in every assembly + // - PluginController, RenderMvcController and UmbracoApiController in every assembly // // We do NOT scan: // - any IController or IHttpController (anything not PluginController nor UmbracoApiController), outside of Umbraco.Web From 849cc2d383cefa9cbc08551e2e0a7f71b5ddaffc Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 6 Dec 2018 10:20:48 +0100 Subject: [PATCH 128/469] remove tree sync for packages and users as we don't have a tree --- .../src/views/packages/overview.controller.js | 3 --- .../src/views/users/overview.controller.js | 4 ---- 2 files changed, 7 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/overview.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/overview.controller.js index 43a9d0473e..418861c636 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/overview.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/overview.controller.js @@ -53,9 +53,6 @@ } ]; - $timeout(function () { - navigationService.syncTree({ tree: "packages", path: "-1" }); - }); } } diff --git a/src/Umbraco.Web.UI.Client/src/views/users/overview.controller.js b/src/Umbraco.Web.UI.Client/src/views/users/overview.controller.js index 4d25419175..49e8007d8c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/users/overview.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/users/overview.controller.js @@ -25,10 +25,6 @@ setPageName(); - $timeout(function () { - navigationService.syncTree({ tree: "users", path: "-1" }); - }); - } function loadNavigation() { From 3546de32077f9d62c923f4737d9cfdbee5e228c8 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Thu, 6 Dec 2018 09:32:04 +0000 Subject: [PATCH 129/469] Update packages tree so that its a full screen app/section like users --- src/Umbraco.Web.UI/config/trees.config | 2 +- .../Trees/PackagesTreeController.cs | 86 +++---------------- src/Umbraco.Web/Trees/UserTreeController.cs | 2 - 3 files changed, 13 insertions(+), 77 deletions(-) diff --git a/src/Umbraco.Web.UI/config/trees.config b/src/Umbraco.Web.UI/config/trees.config index da6f75300a..dd9fac783f 100644 --- a/src/Umbraco.Web.UI/config/trees.config +++ b/src/Umbraco.Web.UI/config/trees.config @@ -23,7 +23,7 @@ - + diff --git a/src/Umbraco.Web/Trees/PackagesTreeController.cs b/src/Umbraco.Web/Trees/PackagesTreeController.cs index 8158b47985..b8acb98daa 100644 --- a/src/Umbraco.Web/Trees/PackagesTreeController.cs +++ b/src/Umbraco.Web/Trees/PackagesTreeController.cs @@ -1,21 +1,14 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net.Http.Formatting; +using System.Net.Http.Formatting; using Umbraco.Web.Models.Trees; using Umbraco.Web.Mvc; using Umbraco.Web.WebApi.Filters; -using umbraco; -using umbraco.cms.businesslogic.packager; -using Umbraco.Core.Services; -using Umbraco.Web.Actions; using Constants = Umbraco.Core.Constants; namespace Umbraco.Web.Trees { [UmbracoTreeAuthorize(Constants.Trees.Packages)] - [Tree(Constants.Applications.Packages, Constants.Trees.Packages, null, sortOrder: 0)] + [Tree(Constants.Applications.Packages, Constants.Trees.Packages, null, sortOrder: 0, isSingleNodeTree: true)] [PluginController("UmbracoTrees")] [CoreTree] public class PackagesTreeController : TreeController @@ -27,80 +20,25 @@ namespace Umbraco.Web.Trees protected override TreeNode CreateRootNode(FormDataCollection queryStrings) { var root = base.CreateRootNode(queryStrings); - - root.RoutePath = $"{Constants.Applications.Packages}/{Constants.Trees.Packages}/overview"; - + + //this will load in a custom UI instead of the dashboard for the root node + root.RoutePath = string.Format("{0}/{1}/{2}", Constants.Applications.Packages, Constants.Trees.Packages, "overview"); root.Icon = "icon-box"; - + + root.HasChildren = false; return root; } + protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) { - var nodes = new TreeNodeCollection(); - - var createdPackages = CreatedPackage.GetAllCreatedPackages(); - - if (id == "created") - { - nodes.AddRange( - createdPackages - .OrderBy(entity => entity.Data.Name) - .Select(dt => - { - var node = CreateTreeNode(dt.Data.Id.ToString(), id, queryStrings, dt.Data.Name, "icon-inbox", false, - $"/{queryStrings.GetValue("application")}/framed/{Uri.EscapeDataString("developer/Packages/EditPackage.aspx?id=" + dt.Data.Id)}"); - return node; - })); - } - else - { - //must be root - var node = CreateTreeNode( - "created", - id, - queryStrings, - Services.TextService.Localize("treeHeaders/createdPackages"), - "icon-folder", - createdPackages.Count > 0, - string.Empty); - - - - //TODO: This isn't the best way to ensure a noop process for clicking a node but it works for now. - node.AdditionalData["jsClickCallback"] = "javascript:void(0);"; - - nodes.Add(node); - } - - - - return nodes; + //full screen app without tree nodes + return TreeNodeCollection.Empty; } protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) { - var menu = new MenuItemCollection(); - - // Root actions - if (id == "-1") - { - menu.Items.Add(Services.TextService, opensDialog: true) - .ConvertLegacyMenuItem(null, Constants.Trees.Packages, queryStrings.GetValue("application")); - } - else if (id == "created") - { - menu.Items.Add(Services.TextService, opensDialog: true) - .ConvertLegacyMenuItem(null, Constants.Trees.Packages, queryStrings.GetValue("application")); - - menu.Items.Add(new RefreshNode(Services.TextService, true)); - } - else - { - //it's a package node - menu.Items.Add(Services.TextService, opensDialog: true); - } - - return menu; + //doesn't have a menu, this is a full screen app without tree nodes + return MenuItemCollection.Empty; } } } diff --git a/src/Umbraco.Web/Trees/UserTreeController.cs b/src/Umbraco.Web/Trees/UserTreeController.cs index f029a929de..57f5913fbb 100644 --- a/src/Umbraco.Web/Trees/UserTreeController.cs +++ b/src/Umbraco.Web/Trees/UserTreeController.cs @@ -1,6 +1,4 @@ using System.Net.Http.Formatting; -using Umbraco.Core; -using Umbraco.Core.Services; using Umbraco.Web.Models.Trees; using Umbraco.Web.Mvc; using Umbraco.Web.WebApi.Filters; From 17d489bb54dcbdd755dc15376662ae3b2872f02c Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Thu, 6 Dec 2018 09:50:05 +0000 Subject: [PATCH 130/469] Adds new API/Editor endpoint to deal with created packages - get methods --- src/Umbraco.Web/Editors/PackageController.cs | 49 ++++++++++++++++++++ src/Umbraco.Web/Umbraco.Web.csproj | 1 + 2 files changed, 50 insertions(+) create mode 100644 src/Umbraco.Web/Editors/PackageController.cs diff --git a/src/Umbraco.Web/Editors/PackageController.cs b/src/Umbraco.Web/Editors/PackageController.cs new file mode 100644 index 0000000000..e6d84e8288 --- /dev/null +++ b/src/Umbraco.Web/Editors/PackageController.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Web.Http; +using umbraco.cms.businesslogic.packager; +using Umbraco.Web.Mvc; +using Umbraco.Web.WebApi.Filters; + +namespace Umbraco.Web.Editors +{ + /// + /// A controller used for installing packages and managing all of the data in the packages section in the back office + /// + [PluginController("UmbracoApi")] + [UmbracoApplicationAuthorize(Core.Constants.Applications.Packages)] + public class PackageController : UmbracoAuthorizedJsonController + { + [HttpGet] + public List GetCreatedPackages() + { + //TODO: Packager stuff still lives in business logic - YUK + //TODO: Could be too much data down the wire + return CreatedPackage.GetAllCreatedPackages(); + + /* + * "author": "Test", + "files": [], + "iconUrl": "", + "id": 1, + "license": "MIT License", + "licenseUrl": "http://opensource.org/licenses/MIT", + "name": "Test v8", + "url": "https://test.com", + "version": "0.0.0" + */ + + + } + + [HttpGet] + public CreatedPackage GetCreatedPackageById(int id) + { + return CreatedPackage.GetById(id); + } + + } +} diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 717c2f508e..5b396c9486 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -111,6 +111,7 @@ + From 9df8c71bf4a06e944738ff4998e64727e60ecb78 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Thu, 6 Dec 2018 09:54:21 +0000 Subject: [PATCH 131/469] Adds in Delete method --- src/Umbraco.Web/Editors/PackageController.cs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web/Editors/PackageController.cs b/src/Umbraco.Web/Editors/PackageController.cs index e6d84e8288..6d4655f0be 100644 --- a/src/Umbraco.Web/Editors/PackageController.cs +++ b/src/Umbraco.Web/Editors/PackageController.cs @@ -1,8 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Collections.Generic; +using System.Net; +using System.Net.Http; using System.Web.Http; using umbraco.cms.businesslogic.packager; using Umbraco.Web.Mvc; @@ -45,5 +43,15 @@ namespace Umbraco.Web.Editors return CreatedPackage.GetById(id); } + [HttpDelete] + public HttpResponseMessage DeleteCreatedPackageById(int id) + { + var package = CreatedPackage.GetById(id); + package.Delete(); + + //204 No Content + return new HttpResponseMessage(HttpStatusCode.NoContent); + } + } } From cd8bb8ed99cdcee645e4c23061cf12592407b2b7 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Thu, 6 Dec 2018 10:07:53 +0000 Subject: [PATCH 132/469] Adds the package api controller to Umbraco.Sys JS object --- src/Umbraco.Web/Editors/BackOfficeServerVariables.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs b/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs index 23d8e2cc4e..472728e087 100644 --- a/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs +++ b/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs @@ -208,6 +208,10 @@ namespace Umbraco.Web.Editors "packageInstallApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl( controller => controller.Fetch(string.Empty)) }, + { + "packageApiBaseUrl ", _urlHelper.GetUmbracoApiServiceBaseUrl( + controller => controller.GetCreatedPackages()) + }, { "relationApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl( controller => controller.GetById(0)) From de86dace707cbab5c8b32c45cb23e59f54c2695b Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Thu, 6 Dec 2018 10:18:31 +0000 Subject: [PATCH 133/469] Adds a Create/Publish method - will need to figure out validation --- src/Umbraco.Web/Editors/PackageController.cs | 34 +++++++++++--------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/Umbraco.Web/Editors/PackageController.cs b/src/Umbraco.Web/Editors/PackageController.cs index 6d4655f0be..d192ee21f3 100644 --- a/src/Umbraco.Web/Editors/PackageController.cs +++ b/src/Umbraco.Web/Editors/PackageController.cs @@ -8,6 +8,8 @@ using Umbraco.Web.WebApi.Filters; namespace Umbraco.Web.Editors { + //TODO: Packager stuff still lives in business logic - YUK + /// /// A controller used for installing packages and managing all of the data in the packages section in the back office /// @@ -18,23 +20,8 @@ namespace Umbraco.Web.Editors [HttpGet] public List GetCreatedPackages() { - //TODO: Packager stuff still lives in business logic - YUK //TODO: Could be too much data down the wire return CreatedPackage.GetAllCreatedPackages(); - - /* - * "author": "Test", - "files": [], - "iconUrl": "", - "id": 1, - "license": "MIT License", - "licenseUrl": "http://opensource.org/licenses/MIT", - "name": "Test v8", - "url": "https://test.com", - "version": "0.0.0" - */ - - } [HttpGet] @@ -43,6 +30,23 @@ namespace Umbraco.Web.Editors return CreatedPackage.GetById(id); } + [HttpPost] + public CreatedPackage PostCreatePackage(PackageInstance model) + { + //TODO Validation on the model?! + var newPackage = new CreatedPackage + { + Data = model + }; + + //Save then publish + newPackage.Save(); + newPackage.Publish(); + + //We should have packagepath populated now + return newPackage; + } + [HttpDelete] public HttpResponseMessage DeleteCreatedPackageById(int id) { From 68006f78ee6ebf184a80d1719630a151aa344517 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 6 Dec 2018 11:33:03 +0100 Subject: [PATCH 134/469] wire up end point for get created packages --- .../src/common/resources/package.resource.js | 18 ++++++++++ .../src/views/packages/edit.controller.js | 21 ++++++++--- .../packages/views/created.controller.js | 35 ++++--------------- .../src/views/packages/views/created.html | 6 ++++ 4 files changed, 46 insertions(+), 34 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/package.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/package.resource.js index 8fd6836884..522423f5b2 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/package.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/package.resource.js @@ -151,7 +151,25 @@ function packageResource($q, $http, umbDataFormatter, umbRequestHelper) { "packageInstallApiBaseUrl", "CleanUp"), umbPackage), 'Failed to install package. Error during the step "CleanUp" '); + }, + + /** + * @ngdoc method + * @name umbraco.resources.packageInstallResource#getCreated + * @methodOf umbraco.resources.packageInstallResource + * + * @description + * Gets a list of created packages + */ + getAllCreated: function() { + return umbRequestHelper.resourcePromise( + $http.get( + umbRequestHelper.getApiUrl( + "packageApiBaseUrl", + "GetCreated")), + 'Failed to get created packages'); } + }; } diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js index ff587dd540..af17c44b60 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js @@ -1,7 +1,7 @@ (function () { "use strict"; - function EditController($location, contentTypeResource, templateResource, stylesheetResource, languageResource, dictionaryResource, dataTypeResource, editorService) { + function EditController($location, $routeParams, contentTypeResource, templateResource, stylesheetResource, languageResource, dictionaryResource, dataTypeResource, editorService) { const vm = this; @@ -24,11 +24,22 @@ vm.removeControl = removeControl; function onInit() { - // load package - vm.package = { - "name": "My package" - }; + const packageId = $routeParams.id; + const create = $routeParams.create; + + if(create) { + //pre populate package with some values + vm.package = { + "version": "1.0.0", + "license": "MIT License", + "licenseUrl": "http://opensource.org/licenses/MIT" + }; + + } else { + // load package + + } // get all doc types contentTypeResource.getAll().then(documentTypes => { diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/views/created.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/views/created.controller.js index 8c92f3553c..2a10a9e8fe 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/views/created.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/views/created.controller.js @@ -1,7 +1,7 @@ (function () { "use strict"; - function CreatedController($timeout, $location, localizationService, overlayService) { + function CreatedController($timeout, $location, packageResource, localizationService, overlayService) { const vm = this; @@ -13,33 +13,9 @@ vm.createdPackages = []; - //load created packages - $timeout(function(){ - vm.createdPackages = [ - { - "author": "Test", - "files": [], - "iconUrl": "", - "id": 1, - "license": "MIT License", - "licenseUrl": "http://opensource.org/licenses/MIT", - "name": "Test v8", - "url": "https://test.com", - "version": "0.0.0" - }, - { - "author": "Test", - "files": [], - "iconUrl": "", - "id": 2, - "license": "MIT License", - "licenseUrl": "http://opensource.org/licenses/MIT", - "name": "Another Test v8", - "url": "https://test.com", - "version": "0.0.0" - } - ]; - }, 1000); + packageResource.getAllCreated().then(createdPackages => { + vm.createdPackages = createdPackages; + }, angular.noop); } @@ -72,7 +48,8 @@ } function createPackage() { - console.log("create package"); + $location.search('create', null); + $location.path("packages/packages/edit/-1").search("create", "true"); } onInit(); diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/views/created.html b/src/Umbraco.Web.UI.Client/src/views/packages/views/created.html index 52f0cef9fd..53fd78b3c6 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/views/created.html +++ b/src/Umbraco.Web.UI.Client/src/views/packages/views/created.html @@ -42,4 +42,10 @@ + + No packages have been created yet + +
\ No newline at end of file From 17a005c1635f1fc9afe698c3b312a2945ed3a788 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Thu, 6 Dec 2018 10:42:05 +0000 Subject: [PATCH 135/469] Fix up Umbraco.Sys object URL to API endpoint --- src/Umbraco.Web/Editors/BackOfficeServerVariables.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs b/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs index 472728e087..86c232c449 100644 --- a/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs +++ b/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs @@ -209,7 +209,7 @@ namespace Umbraco.Web.Editors controller => controller.Fetch(string.Empty)) }, { - "packageApiBaseUrl ", _urlHelper.GetUmbracoApiServiceBaseUrl( + "packageApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl( controller => controller.GetCreatedPackages()) }, { From 452f97de625bddda1194511e17bb3e9783c3e98e Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 6 Dec 2018 11:53:26 +0100 Subject: [PATCH 136/469] wire up get created package by id --- .../src/common/resources/package.resource.js | 20 ++++++++++++++++++- .../src/views/packages/edit.controller.js | 7 ++++--- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/package.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/package.resource.js index 522423f5b2..6023a16d5b 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/package.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/package.resource.js @@ -166,8 +166,26 @@ function packageResource($q, $http, umbDataFormatter, umbRequestHelper) { $http.get( umbRequestHelper.getApiUrl( "packageApiBaseUrl", - "GetCreated")), + "GetCreatedPackages")), 'Failed to get created packages'); + }, + + /** + * @ngdoc method + * @name umbraco.resources.packageInstallResource#getCreatedById + * @methodOf umbraco.resources.packageInstallResource + * + * @description + * Gets a created package by id + */ + getCreatedById: function(id) { + return umbRequestHelper.resourcePromise( + $http.get( + umbRequestHelper.getApiUrl( + "packageApiBaseUrl", + "GetCreatedPackageById", + [{ id: id }])), + 'Failed to get package'); } }; diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js index af17c44b60..a3408e1360 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js @@ -1,7 +1,7 @@ (function () { "use strict"; - function EditController($location, $routeParams, contentTypeResource, templateResource, stylesheetResource, languageResource, dictionaryResource, dataTypeResource, editorService) { + function EditController($location, $routeParams, packageResource, contentTypeResource, templateResource, stylesheetResource, languageResource, dictionaryResource, dataTypeResource, editorService) { const vm = this; @@ -35,10 +35,11 @@ "license": "MIT License", "licenseUrl": "http://opensource.org/licenses/MIT" }; - } else { // load package - + packageResource.getCreatedById(packageId).then(createdPackage => { + vm.package = createdPackage; + }, angular.noop); } // get all doc types From c7e6cf44ed019e4e99c493c786e02e7b4c079301 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Thu, 6 Dec 2018 11:21:01 +0000 Subject: [PATCH 137/469] Anotate model so its camelCase friendly for API responses for Mads --- .../PackageInstance/PackageInstance.cs | 33 +++++++++++++++++-- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web/_Legacy/Packager/PackageInstance/PackageInstance.cs b/src/Umbraco.Web/_Legacy/Packager/PackageInstance/PackageInstance.cs index 8f7cb56320..63bd568b73 100644 --- a/src/Umbraco.Web/_Legacy/Packager/PackageInstance/PackageInstance.cs +++ b/src/Umbraco.Web/_Legacy/Packager/PackageInstance/PackageInstance.cs @@ -1,70 +1,97 @@ using System; - -using System.Xml; -using System.Xml.XPath; using System.Collections.Generic; +using System.Runtime.Serialization; namespace umbraco.cms.businesslogic.packager { + [DataContract(Name = "packageInstance")] public class PackageInstance { + [DataMember(Name = "id")] public int Id { get; set; } + [DataMember(Name = "repositoryGuid")] public string RepositoryGuid { get; set; } + [DataMember(Name = "packageGuid")] public string PackageGuid { get; set; } + [DataMember(Name = "hasUpdate")] public bool HasUpdate { get; set; } + [DataMember(Name = "name")] public string Name { get; set; } + [DataMember(Name = "url")] public string Url { get; set; } + [DataMember(Name = "folder")] public string Folder { get; set; } + [DataMember(Name = "packagePath")] public string PackagePath { get; set; } + [DataMember(Name = "version")] public string Version { get; set; } /// /// The minimum umbraco version that this package requires /// + [DataMember(Name = "umbracoVersion")] public Version UmbracoVersion { get; set; } + [DataMember(Name = "author")] public string Author { get; set; } + [DataMember(Name = "authorUrl")] public string AuthorUrl { get; set; } + [DataMember(Name = "license")] public string License { get; set; } + [DataMember(Name = "licenseUrl")] public string LicenseUrl { get; set; } + [DataMember(Name = "readme")] public string Readme { get; set; } + [DataMember(Name = "contentLoadChildNodes")] public bool ContentLoadChildNodes { get; set; } + [DataMember(Name = "contentNodeId")] public string ContentNodeId { get; set; } + [DataMember(Name = "macros")] public List Macros { get; set; } + [DataMember(Name = "languages")] public List Languages { get; set; } + [DataMember(Name = "dictionaryItems")] public List DictionaryItems { get; set; } + [DataMember(Name = "templates")] public List Templates { get; set; } + [DataMember(Name = "documenttypes")] public List Documenttypes { get; set; } + [DataMember(Name = "stylesheets")] public List Stylesheets { get; set; } + [DataMember(Name = "files")] public List Files { get; set; } + [DataMember(Name = "loadControl")] public string LoadControl { get; set; } + [DataMember(Name = "actions")] public string Actions { get; set; } + [DataMember(Name = "dataTypes")] public List DataTypes { get; set; } + [DataMember(Name = "iconUrl")] public string IconUrl { get; set; } public PackageInstance() From 465229fb39f4f49deb56f5eaec9822fcfb8f1553 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Thu, 6 Dec 2018 11:21:28 +0000 Subject: [PATCH 138/469] Return PackageInstance as opposed to CreatedPackage in API responses --- src/Umbraco.Web/Editors/PackageController.cs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/Umbraco.Web/Editors/PackageController.cs b/src/Umbraco.Web/Editors/PackageController.cs index d192ee21f3..652a7c29f8 100644 --- a/src/Umbraco.Web/Editors/PackageController.cs +++ b/src/Umbraco.Web/Editors/PackageController.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; using System.Net; using System.Net.Http; using System.Web.Http; @@ -18,20 +19,21 @@ namespace Umbraco.Web.Editors public class PackageController : UmbracoAuthorizedJsonController { [HttpGet] - public List GetCreatedPackages() + public List GetCreatedPackages() { //TODO: Could be too much data down the wire - return CreatedPackage.GetAllCreatedPackages(); + return CreatedPackage.GetAllCreatedPackages().Select(x => x.Data).ToList(); } [HttpGet] - public CreatedPackage GetCreatedPackageById(int id) + public PackageInstance GetCreatedPackageById(int id) { - return CreatedPackage.GetById(id); + //TODO throw an error if cant find by ID + return CreatedPackage.GetById(id).Data; } [HttpPost] - public CreatedPackage PostCreatePackage(PackageInstance model) + public PackageInstance PostCreatePackage(PackageInstance model) { //TODO Validation on the model?! var newPackage = new CreatedPackage @@ -42,14 +44,15 @@ namespace Umbraco.Web.Editors //Save then publish newPackage.Save(); newPackage.Publish(); - + //We should have packagepath populated now - return newPackage; + return newPackage.Data; } [HttpDelete] public HttpResponseMessage DeleteCreatedPackageById(int id) { + //TODO: Validation ensure can find it by ID var package = CreatedPackage.GetById(id); package.Delete(); From 3c399ade16d9d4481d8671bee094e8baf20a7273 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 6 Dec 2018 12:50:08 +0100 Subject: [PATCH 139/469] last textarea should be actions --- src/Umbraco.Web.UI.Client/src/views/packages/edit.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html index d6309d812a..a6ef4093a7 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html @@ -255,13 +255,13 @@
From 7df08696493461a0f12b33ee4c373e961d507bbb Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 6 Dec 2018 13:13:55 +0100 Subject: [PATCH 140/469] wire up delete --- .../packages/views/created.controller.js | 23 ++++++++++++++----- .../src/views/packages/views/created.html | 2 +- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/views/created.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/views/created.controller.js index 2a10a9e8fe..9d06ea1092 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/views/created.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/views/created.controller.js @@ -19,28 +19,39 @@ } - function deleteCreatedPackage(createdPackage) { + function deleteCreatedPackage(event, index, createdPackage) { + + event.stopPropagation(); + event.preventDefault(); const dialog = { submitButtonLabelKey: "contentTypeEditor_yesDelete", submit: function (model) { - performDelete(createdPackage); + performDelete(index, createdPackage); overlayService.close(); }, close: function () { overlayService.close(); } }; + + const keys = [ + "general_delete", + "defaultdialogs_confirmdelete" + ]; - localizationService.localize("general_delete").then(value => { - dialog.title = value; + localizationService.localizeMany(keys).then(values => { + dialog.title = values[0]; + dialog.content = values[1]; overlayService.open(dialog); }); } - function performDelete(createdPackage) { - console.log("perform delete"); + function performDelete(index, createdPackage) { + packageResource.deleteCreatedPackage(createdPackage.id).then(()=> { + vm.createdPackages.splice(index, 1); + }, angular.noop); } function goToPackage(createdPackage) { diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/views/created.html b/src/Umbraco.Web.UI.Client/src/views/packages/views/created.html index 53fd78b3c6..632d2e2b3c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/views/created.html +++ b/src/Umbraco.Web.UI.Client/src/views/packages/views/created.html @@ -35,7 +35,7 @@ size="xxs" label-key="general_delete" add-ellipsis="true" - action="vm.deleteCreatedPackage(createdPackage)"> + action="vm.deleteCreatedPackage($event, $index, createdPackage)"> From 9409b46ef41774b1107103bc5b56360bbb8ec9a4 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 6 Dec 2018 13:57:21 +0100 Subject: [PATCH 141/469] fix back buttons --- .../src/views/packages/overview.controller.js | 29 ++++++++++++++----- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/overview.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/overview.controller.js index 418861c636..4ca0015aa5 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/overview.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/overview.controller.js @@ -10,6 +10,8 @@ // we will refresh and then navigate there. var installPackageUri = localStorageService.get("packageInstallUri"); + const packageUri = $location.search().subview; + if (installPackageUri) { localStorageService.remove("packageInstallUri"); } @@ -28,28 +30,41 @@ "name": "Packages", "icon": "icon-cloud", "view": "views/packages/views/repo.html", - "active": !installPackageUri || installPackageUri === "navigation", - "alias": "umbPackages" + "active": !packageUri || installPackageUri === "navigation" || packageUri === "navigation", + "alias": "umbPackages", + "action": function() { + $location.search("subview", "navigation"); + } }, { "name": "Installed", "icon": "icon-box", "view": "views/packages/views/installed.html", - "active": installPackageUri === "installed", - "alias": "umbInstalled" + "active": installPackageUri === "installed" || packageUri === "installed", + "alias": "umbInstalled", + "action": function() { + $location.search("subview", "installed"); + } }, { "name": "Install local", "icon": "icon-add", "view": "views/packages/views/install-local.html", - "active": installPackageUri === "local", - "alias": "umbInstallLocal" + "active": installPackageUri === "local" || packageUri === "local", + "alias": "umbInstallLocal", + "action": function() { + $location.search("subview", "local"); + } }, { "name": "Created", "icon": "icon-add", "view": "views/packages/views/created.html", - "alias": "umbCreatedPackages" + "active": packageUri === "created", + "alias": "umbCreatedPackages", + "action": function() { + $location.search("subview", "created"); + } } ]; From 34dc81058a813115c5d74f07b4c5ae599d88b30c Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Thu, 6 Dec 2018 13:09:34 +0000 Subject: [PATCH 142/469] Move the Delete method over into our new controller --- src/Umbraco.Web/Editors/PackageController.cs | 19 ++++++++++++------ .../Editors/PackageInstallController.cs | 20 +------------------ .../PackageInstance/PackageInstance.cs | 2 +- 3 files changed, 15 insertions(+), 26 deletions(-) diff --git a/src/Umbraco.Web/Editors/PackageController.cs b/src/Umbraco.Web/Editors/PackageController.cs index 652a7c29f8..c2a78da1be 100644 --- a/src/Umbraco.Web/Editors/PackageController.cs +++ b/src/Umbraco.Web/Editors/PackageController.cs @@ -49,16 +49,23 @@ namespace Umbraco.Web.Editors return newPackage.Data; } + /// + /// Deletes a created package + /// + /// + /// + [HttpPost] [HttpDelete] - public HttpResponseMessage DeleteCreatedPackageById(int id) + public IHttpActionResult DeleteCreatedPackage(int packageId) { - //TODO: Validation ensure can find it by ID - var package = CreatedPackage.GetById(id); + var package = CreatedPackage.GetById(packageId); + if (package == null) + return NotFound(); + package.Delete(); - //204 No Content - return new HttpResponseMessage(HttpStatusCode.NoContent); + return Ok(); } - + } } diff --git a/src/Umbraco.Web/Editors/PackageInstallController.cs b/src/Umbraco.Web/Editors/PackageInstallController.cs index 94465feab8..7224ddfb98 100644 --- a/src/Umbraco.Web/Editors/PackageInstallController.cs +++ b/src/Umbraco.Web/Editors/PackageInstallController.cs @@ -289,25 +289,7 @@ namespace Umbraco.Web.Editors }) .ToList(); } - - /// - /// Deletes a created package - /// - /// - /// - [HttpPost] - [HttpDelete] - public IHttpActionResult DeleteCreatedPackage(int packageId) - { - var package = CreatedPackage.GetById(packageId); - if (package == null) - return NotFound(); - - package.Delete(); - - return Ok(); - } - + private void PopulateFromPackageData(LocalPackageInstallModel model) { var ins = new global::umbraco.cms.businesslogic.packager.Installer(Security.CurrentUser.Id); diff --git a/src/Umbraco.Web/_Legacy/Packager/PackageInstance/PackageInstance.cs b/src/Umbraco.Web/_Legacy/Packager/PackageInstance/PackageInstance.cs index 63bd568b73..68166c9dd5 100644 --- a/src/Umbraco.Web/_Legacy/Packager/PackageInstance/PackageInstance.cs +++ b/src/Umbraco.Web/_Legacy/Packager/PackageInstance/PackageInstance.cs @@ -39,7 +39,7 @@ namespace umbraco.cms.businesslogic.packager ///
[DataMember(Name = "umbracoVersion")] public Version UmbracoVersion { get; set; } - + [DataMember(Name = "author")] public string Author { get; set; } From e566e240b13d427d93cb493bcc911e146eb4c61f Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 6 Dec 2018 14:49:02 +0100 Subject: [PATCH 143/469] prefill umbraco version number --- .../src/views/packages/edit.controller.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js index a3408e1360..f9eb6f8c84 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js @@ -31,9 +31,10 @@ if(create) { //pre populate package with some values vm.package = { - "version": "1.0.0", + "version": "0.0.1", "license": "MIT License", - "licenseUrl": "http://opensource.org/licenses/MIT" + "licenseUrl": "http://opensource.org/licenses/MIT", + "umbracoVersion": Umbraco.Sys.ServerVariables.application.version }; } else { // load package From 6f5155b0f39c53c55c093a2f92364b53cbad0117 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Thu, 6 Dec 2018 13:54:38 +0000 Subject: [PATCH 144/469] Adds in new attribute to override the specific PackageController JSON Serializer to use the NewtonSoft built-in VersionConvertor --- src/Umbraco.Web/Editors/PackageController.cs | 3 +++ src/Umbraco.Web/Umbraco.Web.csproj | 1 + .../WebApi/SerializeVersionAttribute.cs | 15 +++++++++++++++ 3 files changed, 19 insertions(+) create mode 100644 src/Umbraco.Web/WebApi/SerializeVersionAttribute.cs diff --git a/src/Umbraco.Web/Editors/PackageController.cs b/src/Umbraco.Web/Editors/PackageController.cs index c2a78da1be..baacea53d8 100644 --- a/src/Umbraco.Web/Editors/PackageController.cs +++ b/src/Umbraco.Web/Editors/PackageController.cs @@ -2,9 +2,11 @@ using System.Linq; using System.Net; using System.Net.Http; +using System.Net.Http.Formatting; using System.Web.Http; using umbraco.cms.businesslogic.packager; using Umbraco.Web.Mvc; +using Umbraco.Web.WebApi; using Umbraco.Web.WebApi.Filters; namespace Umbraco.Web.Editors @@ -15,6 +17,7 @@ namespace Umbraco.Web.Editors /// A controller used for installing packages and managing all of the data in the packages section in the back office ///
[PluginController("UmbracoApi")] + [SerializeVersion] [UmbracoApplicationAuthorize(Core.Constants.Applications.Packages)] public class PackageController : UmbracoAuthorizedJsonController { diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 5b396c9486..e32d808be9 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -190,6 +190,7 @@ + diff --git a/src/Umbraco.Web/WebApi/SerializeVersionAttribute.cs b/src/Umbraco.Web/WebApi/SerializeVersionAttribute.cs new file mode 100644 index 0000000000..ea285434b3 --- /dev/null +++ b/src/Umbraco.Web/WebApi/SerializeVersionAttribute.cs @@ -0,0 +1,15 @@ +using Newtonsoft.Json.Converters; +using System; +using System.Web.Http.Controllers; + +namespace Umbraco.Web.WebApi +{ + internal class SerializeVersionAttribute : Attribute, IControllerConfiguration + { + public void Initialize(HttpControllerSettings controllerSettings, HttpControllerDescriptor controllerDescriptor) + { + var formatter = controllerSettings.Formatters.JsonFormatter; + formatter.SerializerSettings.Converters.Add(new VersionConverter()); + } + } +} From 57f462b2046eed5bec1cf531f12ed8cd7964aa98 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 6 Dec 2018 15:26:12 +0100 Subject: [PATCH 145/469] wire up create package --- .../src/common/resources/package.resource.js | 18 +++++++++++++++++- .../src/views/packages/edit.controller.js | 10 +++++++++- .../src/views/packages/edit.html | 16 ++++------------ 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/package.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/package.resource.js index 6023a16d5b..28a9f3b9ac 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/package.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/package.resource.js @@ -186,8 +186,24 @@ function packageResource($q, $http, umbDataFormatter, umbRequestHelper) { "GetCreatedPackageById", [{ id: id }])), 'Failed to get package'); + }, + + /** + * @ngdoc method + * @name umbraco.resources.packageInstallResource#createPackage + * @methodOf umbraco.resources.packageInstallResource + * + * @description + * Creates a new package + */ + createPackage: function (umbPackage) { + return umbRequestHelper.resourcePromise( + $http.post( + umbRequestHelper.getApiUrl( + "packageApiBaseUrl", + "PostCreatePackage"), umbPackage), + 'Failed to create package'); } - }; } diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js index f9eb6f8c84..d5571ba78c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js @@ -83,7 +83,15 @@ } function createPackage() { - console.log("create package"); + + vm.createPackageButtonState = "busy"; + + packageResource.createPackage(vm.package).then((updatedPackage) => { + vm.package = updatedPackage; + vm.createPackageButtonState = "success"; + }, function(error){ + vm.createPackageButtonState = "error"; + }); } function save() { diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html index a6ef4093a7..cc48dddf6f 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html @@ -47,7 +47,7 @@ - + @@ -268,25 +268,17 @@ +
{{vm.package | json}}
+ - - From 2013fd1619c56be965a0008f8ff5d932e15237a0 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Thu, 6 Dec 2018 14:41:53 +0000 Subject: [PATCH 146/469] Try the MakeNew method on CreatedPackage() --- src/Umbraco.Web/Editors/PackageController.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web/Editors/PackageController.cs b/src/Umbraco.Web/Editors/PackageController.cs index baacea53d8..3713674f84 100644 --- a/src/Umbraco.Web/Editors/PackageController.cs +++ b/src/Umbraco.Web/Editors/PackageController.cs @@ -38,11 +38,11 @@ namespace Umbraco.Web.Editors [HttpPost] public PackageInstance PostCreatePackage(PackageInstance model) { + + var newPackage = CreatedPackage.MakeNew(model.Name); + newPackage.Data = model; + //TODO Validation on the model?! - var newPackage = new CreatedPackage - { - Data = model - }; //Save then publish newPackage.Save(); From 7f380347dcc0a6047c59827c44f73e3f6e85580b Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Thu, 6 Dec 2018 15:35:40 +0000 Subject: [PATCH 147/469] Some WIP binding updates in the view - will mostly need to bind an array of integers back to items --- .../src/views/packages/edit.html | 92 ++++++++++--------- 1 file changed, 49 insertions(+), 43 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html index cc48dddf6f..9ba5421683 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html @@ -3,7 +3,7 @@
- + - + @@ -23,7 +23,7 @@
Package Properties
  - +
@@ -39,7 +39,7 @@ - + @@ -67,22 +67,24 @@
- + - +
Package Content
 
- +
+ + +
{{vm.documentTypes | json }} 
+
{{vm.templates | json }} 
- + +
{{vm.stylesheets | json }}
- NOT IMPLEMENTED + NOT IMPLEMENTED IN V8 YET +
{{vm.languages | json }}
@@ -254,9 +260,9 @@  
-
Documentation @@ -275,7 +281,7 @@ - - + - +
\ No newline at end of file From 6566a43ef9a26be1901f73b64e05fa8a3608d1dc Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 7 Dec 2018 10:05:31 +0100 Subject: [PATCH 148/469] change end point for delete created package --- .../src/common/resources/package.resource.js | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/package.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/package.resource.js index 28a9f3b9ac..0b74729cf6 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/package.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/package.resource.js @@ -33,15 +33,6 @@ function packageResource($q, $http, umbDataFormatter, umbRequestHelper) { 'Failed to validate package ' + name); }, - deleteCreatedPackage: function (packageId) { - return umbRequestHelper.resourcePromise( - $http.post( - umbRequestHelper.getApiUrl( - "packageInstallApiBaseUrl", - "DeleteCreatedPackage", { packageId: packageId })), - 'Failed to delete package ' + packageId); - }, - uninstall: function(packageId) { return umbRequestHelper.resourcePromise( $http.post( @@ -203,6 +194,23 @@ function packageResource($q, $http, umbDataFormatter, umbRequestHelper) { "packageApiBaseUrl", "PostCreatePackage"), umbPackage), 'Failed to create package'); + }, + + /** + * @ngdoc method + * @name umbraco.resources.packageInstallResource#deleteCreatedPackage + * @methodOf umbraco.resources.packageInstallResource + * + * @description + * Detes a created package + */ + deleteCreatedPackage: function (packageId) { + return umbRequestHelper.resourcePromise( + $http.post( + umbRequestHelper.getApiUrl( + "packageApiBaseUrl", + "DeleteCreatedPackage", { packageId: packageId })), + 'Failed to delete package ' + packageId); } }; } From fbf29f9f4718f1233939f69dc439962e694505bc Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 7 Dec 2018 10:13:55 +0100 Subject: [PATCH 149/469] bind stylesheets correctly --- src/Umbraco.Web.UI.Client/src/views/packages/edit.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html index 9ba5421683..796edff588 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html @@ -143,7 +143,7 @@ + checklist-value="stylesheet.name" /> {{stylesheet.path}}
From a9aba6731dbe41de27475c748b4287ba860efed5 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Fri, 7 Dec 2018 09:29:44 +0000 Subject: [PATCH 150/469] Update to CreatePackage API endpoint - the ID & Guid was getting overwritten by mistake --- src/Umbraco.Web/Editors/PackageController.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web/Editors/PackageController.cs b/src/Umbraco.Web/Editors/PackageController.cs index 3713674f84..a2505a1287 100644 --- a/src/Umbraco.Web/Editors/PackageController.cs +++ b/src/Umbraco.Web/Editors/PackageController.cs @@ -38,10 +38,16 @@ namespace Umbraco.Web.Editors [HttpPost] public PackageInstance PostCreatePackage(PackageInstance model) { - var newPackage = CreatedPackage.MakeNew(model.Name); - newPackage.Data = model; + var packageId = newPackage.Data.Id; + var packageGuid = newPackage.Data.PackageGuid; + //Need to reset the package ID - as the posted model the package ID is always 0 + //MakeNew will init create the XML & update the file and give us an ID to use + newPackage.Data = model; + newPackage.Data.Id = packageId; + newPackage.Data.PackageGuid = packageGuid; + //TODO Validation on the model?! //Save then publish From 5d3432db511af114b05b8dc6ea2dc75f0d62b673 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 7 Dec 2018 11:15:08 +0100 Subject: [PATCH 151/469] get render model for content item --- .../src/views/packages/edit.controller.js | 16 +++++++++++++--- .../src/views/packages/edit.html | 6 ++---- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js index d5571ba78c..6520a2ecf8 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js @@ -1,7 +1,7 @@ (function () { "use strict"; - function EditController($location, $routeParams, packageResource, contentTypeResource, templateResource, stylesheetResource, languageResource, dictionaryResource, dataTypeResource, editorService) { + function EditController($location, $routeParams, entityResource, packageResource, contentTypeResource, templateResource, stylesheetResource, languageResource, dictionaryResource, dataTypeResource, editorService) { const vm = this; @@ -40,6 +40,15 @@ // load package packageResource.getCreatedById(packageId).then(createdPackage => { vm.package = createdPackage; + + // get render model for content node + if(vm.package.contentNodeId) { + entityResource.getById(vm.package.contentNodeId, "Document") + .then((entity) => { + vm.contentNodeDisplayModel = entity; + }); + } + }, angular.noop); } @@ -99,14 +108,15 @@ } function removeContentItem() { - vm.package.contentItem = null; + vm.package.contentNodeId = null; } function openContentPicker() { const contentPicker = { submit: function(model) { if(model.selection && model.selection.length > 0) { - vm.package.contentItem = model.selection[0]; + vm.package.contentNodeId = model.selection[0].id.toString(); + vm.contentNodeDisplayModel = model.selection[0]; } editorService.close(); }, diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html index 796edff588..77743a1116 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html @@ -81,12 +81,10 @@ - - Date: Fri, 7 Dec 2018 10:22:33 +0000 Subject: [PATCH 152/469] Adds in validation to the POST / Create package to ensure name, author is set etc... --- src/Umbraco.Web/Editors/PackageController.cs | 16 +++++++++++----- .../Packager/PackageInstance/PackageInstance.cs | 8 ++++++++ 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web/Editors/PackageController.cs b/src/Umbraco.Web/Editors/PackageController.cs index a2505a1287..44efa44c21 100644 --- a/src/Umbraco.Web/Editors/PackageController.cs +++ b/src/Umbraco.Web/Editors/PackageController.cs @@ -24,20 +24,28 @@ namespace Umbraco.Web.Editors [HttpGet] public List GetCreatedPackages() { - //TODO: Could be too much data down the wire return CreatedPackage.GetAllCreatedPackages().Select(x => x.Data).ToList(); } [HttpGet] public PackageInstance GetCreatedPackageById(int id) { - //TODO throw an error if cant find by ID - return CreatedPackage.GetById(id).Data; + var package = CreatedPackage.GetById(id); + if (package == null) + throw new HttpResponseException(HttpStatusCode.NotFound); + + return package.Data; } [HttpPost] public PackageInstance PostCreatePackage(PackageInstance model) { + if (ModelState.IsValid == false) + { + //Throw/bubble up errors + throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState)); + } + var newPackage = CreatedPackage.MakeNew(model.Name); var packageId = newPackage.Data.Id; var packageGuid = newPackage.Data.PackageGuid; @@ -48,8 +56,6 @@ namespace Umbraco.Web.Editors newPackage.Data.Id = packageId; newPackage.Data.PackageGuid = packageGuid; - //TODO Validation on the model?! - //Save then publish newPackage.Save(); newPackage.Publish(); diff --git a/src/Umbraco.Web/_Legacy/Packager/PackageInstance/PackageInstance.cs b/src/Umbraco.Web/_Legacy/Packager/PackageInstance/PackageInstance.cs index 68166c9dd5..615d726dbc 100644 --- a/src/Umbraco.Web/_Legacy/Packager/PackageInstance/PackageInstance.cs +++ b/src/Umbraco.Web/_Legacy/Packager/PackageInstance/PackageInstance.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; namespace umbraco.cms.businesslogic.packager @@ -20,9 +21,12 @@ namespace umbraco.cms.businesslogic.packager public bool HasUpdate { get; set; } [DataMember(Name = "name")] + [Required] public string Name { get; set; } [DataMember(Name = "url")] + [Required] + [Url] public string Url { get; set; } [DataMember(Name = "folder")] @@ -32,6 +36,7 @@ namespace umbraco.cms.businesslogic.packager public string PackagePath { get; set; } [DataMember(Name = "version")] + [Required] public string Version { get; set; } /// @@ -41,9 +46,12 @@ namespace umbraco.cms.businesslogic.packager public Version UmbracoVersion { get; set; } [DataMember(Name = "author")] + [Required] public string Author { get; set; } [DataMember(Name = "authorUrl")] + [Required] + [Url] public string AuthorUrl { get; set; } [DataMember(Name = "license")] From 8252f4d95a34d824435c6012a24b050b2db69ac3 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 7 Dec 2018 11:31:33 +0100 Subject: [PATCH 153/469] clear create query string when using back button --- src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js index 6520a2ecf8..12a9ea0092 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js @@ -88,7 +88,7 @@ } function back() { - $location.path("packages/packages/overview"); + $location.path("packages/packages/overview").search('create', null);; } function createPackage() { From b35a8b406b8a6d3a2cd9aee1b393ce1dd3e29bdb Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Fri, 7 Dec 2018 10:37:33 +0000 Subject: [PATCH 154/469] Fix API Controller for Package create to support new entry & update existing entry --- src/Umbraco.Web/Editors/PackageController.cs | 33 +++++++++++++------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/src/Umbraco.Web/Editors/PackageController.cs b/src/Umbraco.Web/Editors/PackageController.cs index 44efa44c21..8b9e15f9d1 100644 --- a/src/Umbraco.Web/Editors/PackageController.cs +++ b/src/Umbraco.Web/Editors/PackageController.cs @@ -45,23 +45,34 @@ namespace Umbraco.Web.Editors //Throw/bubble up errors throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState)); } + + var package = new CreatedPackage + { + Data = model + }; - var newPackage = CreatedPackage.MakeNew(model.Name); - var packageId = newPackage.Data.Id; - var packageGuid = newPackage.Data.PackageGuid; + //If ID is 0 & PackageGuid is null - its brand new + if(model.Id == 0 && model.PackageGuid == null) + { + //Brand new + package = CreatedPackage.MakeNew(model.Name); - //Need to reset the package ID - as the posted model the package ID is always 0 - //MakeNew will init create the XML & update the file and give us an ID to use - newPackage.Data = model; - newPackage.Data.Id = packageId; - newPackage.Data.PackageGuid = packageGuid; + var packageId = package.Data.Id; + var packageGuid = package.Data.PackageGuid; + + //Need to reset the package ID - as the posted model the package ID is always 0 + //MakeNew will init create the XML & update the file and give us an ID to use + package.Data = model; + package.Data.Id = packageId; + package.Data.PackageGuid = packageGuid; + } //Save then publish - newPackage.Save(); - newPackage.Publish(); + package.Save(); + package.Publish(); //We should have packagepath populated now - return newPackage.Data; + return package.Data; } /// From bb5a561932ef9fc4c2f916b5a8189217844fd571 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Fri, 7 Dec 2018 11:43:36 +0000 Subject: [PATCH 155/469] Wiring up server side validation in the UI --- .../src/views/packages/edit.controller.js | 24 +++++---- .../src/views/packages/edit.html | 50 ++++++++++++++----- 2 files changed, 51 insertions(+), 23 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js index 12a9ea0092..494c26e8e8 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js @@ -1,7 +1,7 @@ (function () { "use strict"; - function EditController($location, $routeParams, entityResource, packageResource, contentTypeResource, templateResource, stylesheetResource, languageResource, dictionaryResource, dataTypeResource, editorService) { + function EditController($scope, $location, $routeParams, entityResource, packageResource, contentTypeResource, templateResource, stylesheetResource, languageResource, dictionaryResource, dataTypeResource, editorService, formHelper) { const vm = this; @@ -91,16 +91,20 @@ $location.path("packages/packages/overview").search('create', null);; } - function createPackage() { + function createPackage(editPackageForm) { - vm.createPackageButtonState = "busy"; + if (formHelper.submitForm({ formCtrl: editPackageForm, scope: $scope })) { - packageResource.createPackage(vm.package).then((updatedPackage) => { - vm.package = updatedPackage; - vm.createPackageButtonState = "success"; - }, function(error){ - vm.createPackageButtonState = "error"; - }); + vm.createPackageButtonState = "busy"; + + packageResource.createPackage(vm.package).then((updatedPackage) => { + vm.package = updatedPackage; + vm.createPackageButtonState = "success"; + }, function(err){ + formHelper.handleError(err); + vm.createPackageButtonState = "error"; + }); + } } function save() { @@ -144,7 +148,7 @@ vm.package.files.push(selected); }); } - + editorService.close(); }, close: function() { diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html index 77743a1116..5f63d74fe7 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html @@ -1,6 +1,6 @@ -
+
-
+ @@ -27,43 +27,67 @@
- + + + + Required + {{editPackageForm.url.errorMsg}} + - + + + + Required + {{editPackageForm.version.errorMsg}} + - + - + - + + + + {{editPackageForm.umbracoVersion.errorMsg}} + - + + + + Required + {{editPackageForm.author.errorMsg}} + - + + + + Required + {{editPackageForm.authorUrl.errorMsg}} + - + - + - +
@@ -281,7 +305,7 @@ Date: Fri, 7 Dec 2018 13:10:50 +0100 Subject: [PATCH 156/469] fix binding of documenttypes and templates --- .../src/views/packages/edit.controller.js | 10 ++++++++++ src/Umbraco.Web.UI.Client/src/views/packages/edit.html | 4 +--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js index 494c26e8e8..aa23b0209f 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js @@ -54,11 +54,21 @@ // get all doc types contentTypeResource.getAll().then(documentTypes => { + // a package stores the id as a string so we + // need to convert all ids to string for comparison + documentTypes.forEach(documentType => { + documentType.id = documentType.id.toString(); + }); vm.documentTypes = documentTypes; }); // get all templates templateResource.getAll().then(templates => { + // a package stores the id as a string so we + // need to convert all ids to string for comparison + templates.forEach(template => { + template.id = template.id.toString(); + }); vm.templates = templates; }); diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html index 5f63d74fe7..4fc3ea74d1 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html @@ -132,13 +132,12 @@ -
{{vm.documentTypes | json }} 
@@ -146,7 +145,6 @@ -
{{vm.templates | json }} 
- @@ -112,15 +113,15 @@ view="ysodOverlay.view"> - - @Html.BareMinimumServerVariablesScript(Url, Url.Action("ExternalLogin", "BackOffice", new { area = ViewBag.UmbracoPath }), Model.Features, UmbracoConfig.For.GlobalSettings()) + @Html.BareMinimumServerVariablesScript(Url, Url.Action("ExternalLogin", "BackOffice", new { area = ViewBag.UmbracoPath }), Model.Features, Current.Config.Global()) - - - - -
-

<%= Services.TextService.Localize("defaultdialogs/siterepublishHelp")%>

-
- - - - - -
- - -
-

<%= Services.TextService.Localize("defaultdialogs/siterepublished")%>

- -
- -
-
\ No newline at end of file diff --git a/src/Umbraco.Web/Actions/ActionChangeDocType.cs b/src/Umbraco.Web/Actions/ActionChangeDocType.cs index 73772699d0..56868e9fb0 100644 --- a/src/Umbraco.Web/Actions/ActionChangeDocType.cs +++ b/src/Umbraco.Web/Actions/ActionChangeDocType.cs @@ -5,16 +5,17 @@ using Umbraco.Web.UI.Pages; namespace Umbraco.Web.Actions { - /// - /// This action is invoked when the document type of a piece of content is changed - /// - public class ActionChangeDocType : IAction - { - public char Letter => '7'; - public string Alias => "changeDocType"; - public string Category => Constants.Conventions.PermissionCategories.AdministrationCategory; - public string Icon => "axis-rotation-2"; - public bool ShowInNotifier => true; - public bool CanBePermissionAssigned => true; - } + //TODO: Add this back in when we support this functionality again + ///// + ///// This action is invoked when the document type of a piece of content is changed + ///// + //public class ActionChangeDocType : IAction + //{ + // public char Letter => '7'; + // public string Alias => "changeDocType"; + // public string Category => Constants.Conventions.PermissionCategories.AdministrationCategory; + // public string Icon => "axis-rotation-2"; + // public bool ShowInNotifier => true; + // public bool CanBePermissionAssigned => true; + //} } diff --git a/src/Umbraco.Web/Trees/ContentTreeController.cs b/src/Umbraco.Web/Trees/ContentTreeController.cs index d7faae65cb..3da8540fe3 100644 --- a/src/Umbraco.Web/Trees/ContentTreeController.cs +++ b/src/Umbraco.Web/Trees/ContentTreeController.cs @@ -141,8 +141,6 @@ namespace Umbraco.Web.Trees } // add default actions for *all* users - // fixme - temp disable RePublish as the page itself (republish.aspx) has been temp disabled - //menu.Items.Add(Services.TextService.Localize("actions", ActionRePublish.Instance.Alias)).ConvertLegacyMenuItem(null, "content", "content"); menu.Items.Add(new RefreshNode(Services.TextService, true)); return menu; diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index eddb1ee6d3..180f69e2cc 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -1124,27 +1124,16 @@ - - - - - - - - - - - @@ -1183,9 +1172,6 @@ ASPXCodeBehind - - ASPXCodeBehind - ASPXCodeBehind @@ -1242,7 +1228,6 @@ Code - @@ -1252,26 +1237,6 @@ FeedProxy.aspx - - insertMasterpageContent.aspx - ASPXCodeBehind - - - insertMasterpageContent.aspx - - - insertMasterpagePlaceholder.aspx - ASPXCodeBehind - - - insertMasterpagePlaceholder.aspx - - - republish.aspx - - - republish.aspx - editPackage.aspx ASPXCodeBehind @@ -1324,15 +1289,6 @@ - - ASPXCodeBehind - - - ASPXCodeBehind - - - ASPXCodeBehind - ASPXCodeBehind diff --git a/src/Umbraco.Web/_Legacy/Controls/DataAttributes.cs b/src/Umbraco.Web/_Legacy/Controls/DataAttributes.cs deleted file mode 100644 index 0f83ecd53e..0000000000 --- a/src/Umbraco.Web/_Legacy/Controls/DataAttributes.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Collections.Generic; -using System.Web.UI.WebControls; - -namespace Umbraco.Web._Legacy.Controls -{ - internal class DataAttributes : Dictionary - { - - public void AppendTo(WebControl c) - { - foreach (var keyval in this) - c.Attributes.Add("data-" + keyval.Key, keyval.Value); - } - } -} diff --git a/src/Umbraco.Web/_Legacy/Controls/FieldDropDownList.cs b/src/Umbraco.Web/_Legacy/Controls/FieldDropDownList.cs deleted file mode 100644 index cf85b107e0..0000000000 --- a/src/Umbraco.Web/_Legacy/Controls/FieldDropDownList.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System.Web; -using System.Web.UI; -using System.Web.UI.WebControls; - -namespace Umbraco.Web._Legacy.Controls -{ - public class FieldDropDownList : DropDownList - { - private bool _customOptionsStarted; - private bool _standardOptionsStarted; - - public string CustomPropertiesLabel { get; set; } - public string StandardPropertiesLabel { get; set; } - public string ChooseText { get; set; } - - protected override void RenderContents(HtmlTextWriter writer) - { - if (Items.Count > 0 && Items[0].Text.StartsWith("#")) - { - Items.Insert(0, new ListItem(ChooseText, "")); - SelectedIndex = 0; - - base.RenderContents(writer); - return; - } - - writer.Write("", ChooseText); - - foreach (ListItem item in Items) - { - if (!_customOptionsStarted) - { - RenderOptionGroupBeginTag(CustomPropertiesLabel, writer); - _customOptionsStarted = true; - } - else if (item.Text.StartsWith("@") && !_standardOptionsStarted) - { - _standardOptionsStarted = true; - RenderOptionGroupEndTag(writer); - RenderOptionGroupBeginTag(StandardPropertiesLabel, writer); - } - - writer.WriteBeginTag("option"); - writer.WriteAttribute("value", item.Value, true); - - foreach (string key in item.Attributes.Keys) - writer.WriteAttribute(key, item.Attributes[key]); - - writer.Write(HtmlTextWriter.TagRightChar); - HttpUtility.HtmlEncode(item.Text.Replace("@", ""), writer); - writer.WriteEndTag("option"); - writer.WriteLine(); - } - - RenderOptionGroupEndTag(writer); - } - - private void RenderOptionGroupBeginTag(string name, HtmlTextWriter writer) - { - writer.WriteBeginTag("optgroup"); - writer.WriteAttribute("label", name); - writer.Write(HtmlTextWriter.TagRightChar); - writer.WriteLine(); - } - - private void RenderOptionGroupEndTag(HtmlTextWriter writer) - { - writer.WriteEndTag("optgroup"); - writer.WriteLine(); - } - } -} diff --git a/src/Umbraco.Web/_Legacy/Controls/MenuButton.cs b/src/Umbraco.Web/_Legacy/Controls/MenuButton.cs deleted file mode 100644 index bf44f3a379..0000000000 --- a/src/Umbraco.Web/_Legacy/Controls/MenuButton.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System; -using Umbraco.Core.IO; - -namespace Umbraco.Web._Legacy.Controls -{ - public class MenuButton : System.Web.UI.WebControls.LinkButton - { - public MenuButtonType ButtonType { get; set; } - internal DataAttributes Data { get; private set; } - public string Hotkey { get; set; } - - public string Icon { get; set; } - - public MenuButton() - { - Data = new DataAttributes(); - CssClass = "btn"; - } - - - protected override void Render(System.Web.UI.HtmlTextWriter writer) - { - //setup a hotkey if present - if (ButtonType == MenuButtonType.Primary && String.IsNullOrEmpty(Hotkey)) - Data.Add("hotkey", "ctrl+" + this.Text.ToLower()[0]); - else if (!string.IsNullOrEmpty(Hotkey)) - Data.Add("shortcut", Hotkey); - - Data.AppendTo(this); - - string cssClass = "btn"; - - if (Icon != null) - { - cssClass = "btn editorIcon"; - var i = Icon.Trim('.'); - - if (!string.IsNullOrEmpty(i)) - { - this.ToolTip = this.Text; - - if (i.Contains(".")) - this.Text = "" + this.ToolTip + " " + this.ToolTip; - else - this.Text = " " + this.ToolTip; - } - } - - cssClass += " btn-" + Enum.GetName(ButtonType.GetType(), ButtonType).ToLower() + " " + CssClass; - this.CssClass = cssClass.Trim(); - - - base.Render(writer); - } - - } - - - public enum MenuButtonType - { - Default, - Primary, - Info, - Success, - Warning, - Danger, - Inverse, - Link - } -} diff --git a/src/Umbraco.Web/_Legacy/Controls/MenuButtonI.cs b/src/Umbraco.Web/_Legacy/Controls/MenuButtonI.cs deleted file mode 100644 index 28ae95557a..0000000000 --- a/src/Umbraco.Web/_Legacy/Controls/MenuButtonI.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System; -using System.Collections; -using System.ComponentModel; -using System.Data; -using System.Drawing; -using System.Web; -using System.Web.SessionState; -using System.Web.UI; -using System.Web.UI.WebControls; -using System.Web.UI.HtmlControls; -using ClientDependency.Core; - -namespace Umbraco.Web._Legacy.Controls -{ - - public class MenuImageButton : System.Web.UI.WebControls.ImageButton, MenuIconI { - private string _OnClickCommand = ""; - - public string AltText { - get { return this.AlternateText; } - set { - this.AlternateText = value; - this.Attributes.Add("title", value); - } - } - public int IconWidth { - get { return (int)this.Width.Value; } - set { this.Width = value; } - } - public int IconHeight { - get { return (int)this.Height.Value; } - set { this.Height = value; } - } - - - public string ImageURL { - get { return base.ImageUrl; } - set { base.ImageUrl = value; } - } - - public string OnClickCommand { - get { return _OnClickCommand; } - set { _OnClickCommand = value; } - } - - protected override void CreateChildControls() - { - this.Width = Unit.Pixel(20); - this.Height = Unit.Pixel(20); - this.Style.Clear(); - this.Attributes.Add("class", "btn btn-default editorIcon"); - - - if (_OnClickCommand != "") - { - this.Attributes.Add("onClick", OnClickCommand); - } - base.CreateChildControls(); - } - } -} diff --git a/src/Umbraco.Web/_Legacy/Controls/MenuIcon.cs b/src/Umbraco.Web/_Legacy/Controls/MenuIcon.cs deleted file mode 100644 index fe8b654b8a..0000000000 --- a/src/Umbraco.Web/_Legacy/Controls/MenuIcon.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System.ComponentModel; -using System.Web.UI; -using ClientDependency.Core; - -namespace Umbraco.Web._Legacy.Controls -{ - - [ClientDependency(ClientDependencyType.Css, "menuicon/style.css", "UmbracoClient")] - internal class MenuIcon : System.Web.UI.WebControls.Image, MenuIconI - { - private string _OnClickCommand = ""; - private string _AltText = "init"; - - public string AltText { - get { return this.AlternateText; } - set { - _AltText = value; - this.AlternateText = value; - this.Attributes.Add("title", value); - } - } - public int IconWidth { - get { return (int)this.Width.Value; } - set { this.Width = value; } - } - public int IconHeight { - get { return (int)this.Height.Value; } - set { this.Height = value; } - } - - public string ImageURL { - get { return this.ImageUrl; } - set { this.ImageUrl = value; } - } - - public string OnClickCommand { - get { return _OnClickCommand; } - set { _OnClickCommand = value; } - } - - protected override void OnLoad(System.EventArgs EventArguments) { - - - // NH 17-01-2007. Trying to avoid inline styling soup - // Me.Width = WebControls.Unit.Pixel(22) - // Me.Height = WebControls.Unit.Pixel(23) - //Me.Style.Add("border", "0px") - this.Attributes.Add("class", "editorIcon"); - this.Attributes.Add("onMouseover", "this.className='editorIconOver'"); - string holder = ""; -// if (this.ID != "") { - //holder = this.ID.Substring(0, this.ID.LastIndexOf("_")) + "_menu"; - this.Attributes.Add("onMouseout", "hoverIconOut('" + holder + "','" + this.ID + "');"); - this.Attributes.Add("onMouseup", "hoverIconOut('" + holder + "','" + this.ID + "');"); -// } else { - this.Attributes.Add("onMouseout", "this.className='editorIcon'"); - this.Attributes.Add("onMouseup", "this.className='editorIcon'"); -// } - this.Attributes.Add("onMouseDown", "this.className='editorIconDown'; return false;"); - this.AlternateText = _AltText; - this.Attributes.Add("title", _AltText); - - if (_OnClickCommand != "") { - this.Attributes.Add("onClick", OnClickCommand); - } - } - - - } -} diff --git a/src/Umbraco.Web/_Legacy/Controls/MenuIconI.cs b/src/Umbraco.Web/_Legacy/Controls/MenuIconI.cs deleted file mode 100644 index 06716c6cb1..0000000000 --- a/src/Umbraco.Web/_Legacy/Controls/MenuIconI.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace Umbraco.Web._Legacy.Controls -{ - public interface MenuIconI { - string ImageURL { - get; - set; - } - string ID { - get; - set; - } - string OnClickCommand { - get; - set; - } - string AltText { - get; - set; - } - int IconWidth { - get; - set; - } - int IconHeight { - get; - set; - } - } -} diff --git a/src/Umbraco.Web/_Legacy/Controls/ProgressBar.cs b/src/Umbraco.Web/_Legacy/Controls/ProgressBar.cs deleted file mode 100644 index 7a30a5cbb1..0000000000 --- a/src/Umbraco.Web/_Legacy/Controls/ProgressBar.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using Umbraco.Core; -using Umbraco.Core.Composing; -using Umbraco.Core.Services; - -namespace Umbraco.Web._Legacy.Controls -{ - [Obsolete("Use Umbraco.Web.UI.Controls.ProgressBar")] - public class ProgressBar : System.Web.UI.WebControls.Panel - { - private string _title = Current.Services.TextService.Localize("publish/inProgress"); - public string Title { get; set; } - - protected override void Render(System.Web.UI.HtmlTextWriter writer) - { - if(!string.IsNullOrEmpty(Title)) - _title = Title; - - base.CssClass = "umb-loader"; - - base.Render(writer); - } - } -} diff --git a/src/Umbraco.Web/_Legacy/Controls/Splitter.cs b/src/Umbraco.Web/_Legacy/Controls/Splitter.cs deleted file mode 100644 index df6ade91bc..0000000000 --- a/src/Umbraco.Web/_Legacy/Controls/Splitter.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.ComponentModel; -using System.Web.UI; -using Umbraco.Core.IO; - -namespace Umbraco.Web._Legacy.Controls -{ - internal class Splitter : System.Web.UI.WebControls.Image { - - protected override void OnLoad(System.EventArgs EventArguments) { - this.Height = System.Web.UI.WebControls.Unit.Pixel(21); - this.Style.Add("border", "0px"); - this.Attributes.Add("class", "editorIconSplit"); - this.ImageUrl = "/menuicon/images/split.gif"; - } - } -} diff --git a/src/Umbraco.Web/_Legacy/Controls/feedback.cs b/src/Umbraco.Web/_Legacy/Controls/feedback.cs deleted file mode 100644 index 4c4b5bf143..0000000000 --- a/src/Umbraco.Web/_Legacy/Controls/feedback.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using ClientDependency.Core; - -namespace Umbraco.Web._Legacy.Controls -{ - - [ClientDependency(ClientDependencyType.Css, "ui/default.css", "UmbracoClient")] - public class Feedback : System.Web.UI.WebControls.Panel - { - - public Feedback() { - - } - - protected override void OnInit(EventArgs e) { - } - - protected override void OnLoad(System.EventArgs EventArguments) { - } - - public feedbacktype type { get; set; } - - private string _text = string.Empty; - public string Text { - get { - - return _text; - - } - set { _text = value; } - } - - public enum feedbacktype{ - notice, - error, - success - } - - protected override void Render(System.Web.UI.HtmlTextWriter writer) { - if (_text != string.Empty) { - base.CreateChildControls(); - - string styleString = ""; - foreach (string key in this.Style.Keys) { - styleString += key + ":" + this.Style[key] + ";"; - } - - writer.WriteLine("

"); - writer.WriteLine(_text); - writer.WriteLine("

"); - } - } - } -} diff --git a/src/Umbraco.Web/_Legacy/PackageActions/PackageHelper.cs b/src/Umbraco.Web/_Legacy/PackageActions/PackageHelper.cs index c479b720da..55171c2643 100644 --- a/src/Umbraco.Web/_Legacy/PackageActions/PackageHelper.cs +++ b/src/Umbraco.Web/_Legacy/PackageActions/PackageHelper.cs @@ -7,7 +7,7 @@ using Umbraco.Core.Xml; namespace Umbraco.Web._Legacy.PackageActions { - public class PackageHelper + internal class PackageHelper { //Helper method to replace umbraco tags that breaks the xml format.. public static string ParseToValidXml(ITemplate templateObj, ref bool hasAspNetContentBeginning, string template, bool toValid) diff --git a/src/Umbraco.Web/_Legacy/PackageActions/addApplicationTree.cs b/src/Umbraco.Web/_Legacy/PackageActions/addApplicationTree.cs deleted file mode 100644 index b83cb964c2..0000000000 --- a/src/Umbraco.Web/_Legacy/PackageActions/addApplicationTree.cs +++ /dev/null @@ -1,83 +0,0 @@ -using System.Xml; -using Umbraco.Core; -using Umbraco.Core._Legacy.PackageActions; -using Umbraco.Web.Composing; - -namespace Umbraco.Web._Legacy.PackageActions -{ - /*Build in standard actions */ - - /// - /// This class implements the IPackageAction Interface, used to execute code when packages are installed. - /// All IPackageActions only takes a PackageName and a XmlNode as input, and executes based on the data in the xmlnode. - /// - public class addApplicationTree : IPackageAction - { - - #region IPackageAction Members - - /// - /// Executes the specified package action. - /// - /// Name of the package. - /// The XML data. - /// - /// - /// - /// - public bool Execute(string packageName, XmlNode xmlData) - { - bool initialize = bool.Parse(xmlData.Attributes["initialize"].Value); - byte sortOrder = byte.Parse(xmlData.Attributes["sortOrder"].Value); - - string applicationAlias = xmlData.Attributes["applicationAlias"].Value; - string treeAlias = xmlData.Attributes["treeAlias"].Value; - string treeTitle = xmlData.Attributes["treeTitle"].Value; - string iconOpened = xmlData.Attributes["iconOpened"].Value; - string iconClosed = xmlData.Attributes["iconClosed"].Value; - string type = xmlData.Attributes["treeHandlerType"].Value; - - Current.Services.ApplicationTreeService.MakeNew(initialize, sortOrder, applicationAlias, treeAlias, treeTitle, iconClosed, iconOpened, type); - - return true; - } - - /// - /// Undoes the action - /// - /// Name of the package. - /// The XML data. - /// - public bool Undo(string packageName, XmlNode xmlData) - { - string treeAlias = xmlData.Attributes["treeAlias"].Value; - var found = Current.Services.ApplicationTreeService.GetByAlias(treeAlias); - if (found != null) - { - Current.Services.ApplicationTreeService.DeleteTree(found); - } - return true; - } - - /// - /// Action alias. - /// - /// - public string Alias() - { - return "addApplicationTree"; - } - - #endregion - - - public XmlNode SampleXml() - { - - string sample = ""; - return PackageHelper.ParseStringToXmlNode(sample); - } - } -} diff --git a/src/Umbraco.Web/_Legacy/PackageActions/moveRootDocument.cs b/src/Umbraco.Web/_Legacy/PackageActions/moveRootDocument.cs deleted file mode 100644 index 83d9387352..0000000000 --- a/src/Umbraco.Web/_Legacy/PackageActions/moveRootDocument.cs +++ /dev/null @@ -1,102 +0,0 @@ - -//TODO: MIgrate this to core: http://issues.umbraco.org/issue/U4-5857 - -//using System; -//using System.Xml; - -//namespace umbraco.cms.businesslogic.packager.standardPackageActions -//{ -// /// -// /// This class implements the IPackageAction Interface, used to execute code when packages are installed. -// /// All IPackageActions only takes a PackageName and a XmlNode as input, and executes based on the data in the xmlnode. -// /// -// public class moveRootDocument : umbraco.interfaces.IPackageAction -// { -// #region IPackageAction Members - -// /// -// /// Executes the specified package action. -// /// -// /// Name of the package. -// /// The XML data. -// /// -// /// -// /// -// /// True if executed succesfully -// public bool Execute(string packageName, XmlNode xmlData) -// { - -// string documentName = xmlData.Attributes["documentName"].Value; -// string parentDocumentType = xmlData.Attributes["parentDocumentType"].Value; -// string parentDocumentName = ""; - -// if (xmlData.Attributes["parentDocumentName"] != null) -// parentDocumentName = xmlData.Attributes["parentDocumentName"].Value; - -// int parentDocid = 0; - -// ContentType ct = ContentType.GetByAlias(parentDocumentType); -// Content[] docs = web.Document.getContentOfContentType(ct); - -// if (docs.Length > 0) -// { -// if (String.IsNullOrEmpty(parentDocumentName)) -// parentDocid = docs[0].Id; -// else -// { -// foreach (Content doc in docs) -// { -// if (doc.Text == parentDocumentName) -// parentDocid = doc.Id; -// } -// } -// } - -// if (parentDocid > 0) -// { -// web.Document[] rootDocs = web.Document.GetRootDocuments(); - -// foreach (web.Document rootDoc in rootDocs) -// { -// if (rootDoc.Text == documentName) -// { -// rootDoc.Move(parentDocid); -// rootDoc.PublishWithSubs(new umbraco.BusinessLogic.User(0)); -// } -// } -// } - - -// return true; -// } - -// //this has no undo. -// /// -// /// This action has no undo. -// /// -// /// Name of the package. -// /// The XML data. -// /// -// public bool Undo(string packageName, XmlNode xmlData) -// { -// return true; -// } - -// /// -// /// Action alias -// /// -// /// -// public string Alias() -// { -// return "moveRootDocument"; -// } - -// #endregion - -// public XmlNode SampleXml() -// { -// throw new NotImplementedException(); -// } - -// } -//} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/controls/dualSelectBox.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/controls/dualSelectBox.cs deleted file mode 100644 index 6e109b3327..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/controls/dualSelectBox.cs +++ /dev/null @@ -1,153 +0,0 @@ -using System; -using System.Web.Razor; -using System.Web.UI; -using System.Web.UI.WebControls; -using System.Web.UI.HtmlControls; -using ClientDependency.Core; -using Umbraco.Core; -using Umbraco.Core.Services; -using Umbraco.Web; -using Umbraco.Web.Composing; - -namespace umbraco.controls -{ - /// - /// Summary description for dualSelectbox. - /// - [ClientDependency(ClientDependencyType.Javascript, "js/dualSelectBox.js", "UmbracoRoot")] - public class DualSelectbox : System.Web.UI.WebControls.WebControl, System.Web.UI.INamingContainer - { - private ListItemCollection _items = new ListItemCollection(); - - private ListBox _possibleValues = new ListBox(); - private ListBox _selectedValues = new ListBox(); - private HtmlInputHidden _value = new HtmlInputHidden(); - private HtmlInputButton _add = new HtmlInputButton(); - private HtmlInputButton _remove = new HtmlInputButton(); - private int _rows = 8; - - - public ListItemCollection Items - { - get - { - EnsureChildControls(); - return _items; - } - } - - public new int Width - { - set - { - _possibleValues.Width = new Unit(value); - _selectedValues.Width = new Unit(value); - } - } - - public new int Height - { - set - { - _possibleValues.Height = new Unit(value); - _selectedValues.Height = new Unit(value); - } - } - - protected override void CreateChildControls() - { - _possibleValues.ID = "posVals"; - _selectedValues.ID = "selVals"; - _possibleValues.SelectionMode = ListSelectionMode.Multiple; - _selectedValues.SelectionMode = ListSelectionMode.Multiple; - _possibleValues.CssClass = "guiInputTextStandard"; - _selectedValues.CssClass = "guiInputTextStandard"; - _possibleValues.Rows = _rows; - _selectedValues.Rows = _rows; - - _value.ID = "theValue"; - - HtmlTable table = new HtmlTable(); - table.CellPadding = 5; - table.CellSpacing = 0; - table.Border = 0; - - HtmlTableRow header = new HtmlTableRow(); - header.Controls.Add(new HtmlTableCell { InnerHtml = Current.Services.TextService.Localize("content/notmemberof") }); - header.Controls.Add(new HtmlTableCell { InnerHtml= " " }); - header.Controls.Add(new HtmlTableCell { InnerHtml = Current.Services.TextService.Localize("content/memberof") }); - table.Controls.Add(header); - - HtmlTableRow row = new HtmlTableRow(); - table.Controls.Add(row); - HtmlTableCell cFirst = new HtmlTableCell(); - cFirst.Controls.Add(_possibleValues); - row.Controls.Add(cFirst); - HtmlTableCell cButtons = new HtmlTableCell(); - _add.Value = ">>"; - _add.Attributes.Add("class", "guiInputButton"); - _remove.Value = "<<"; - _remove.Attributes.Add("class", "guiInputButton"); - cButtons.Controls.Add(_add); - cButtons.Controls.Add(new LiteralControl("

")); - cButtons.Controls.Add(_remove); - row.Controls.Add(cButtons); - HtmlTableCell cSecond = new HtmlTableCell(); - cSecond.Controls.Add(_selectedValues); - row.Controls.Add(cSecond); - - this.Controls.Add(table); - this.Controls.Add(_value); - } - - public string Value - { - get - { - return _value.Value; - } - - set - { - _value.Value = value; - } - } - - public int Rows - { - set - { - _rows = value; - } - } - - public DualSelectbox() - { - } - - - protected override void OnPreRender(EventArgs e) - { - base.OnPreRender (e); - - _selectedValues.Items.Clear(); - _possibleValues.Items.Clear(); - - foreach(ListItem li in _items) - { - if (((string) (","+ this.Value +",")).IndexOf(","+li.Value+",") > -1) - _selectedValues.Items.Add(li); - else - _possibleValues.Items.Add(li); - } - - // add js to buttons here to ensure full clientids - _add.Attributes.Add("onClick", "dualSelectBoxShift('" + this.ClientID + "');"); - _remove.Attributes.Add("onClick", "dualSelectBoxShift('" + this.ClientID + "');"); - } - - - - - } -} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/insertMasterpageContent.aspx b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/insertMasterpageContent.aspx deleted file mode 100644 index b188df39eb..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/insertMasterpageContent.aspx +++ /dev/null @@ -1,32 +0,0 @@ -<%@ Page Title="" Language="C#" MasterPageFile="../masterpages/umbracoDialog.Master" AutoEventWireup="true" CodeBehind="insertMasterpageContent.aspx.cs" Inherits="umbraco.presentation.umbraco.dialogs.insertMasterpageContent" %> -<%@ Register TagPrefix="cc1" Namespace="Umbraco.Web._Legacy.Controls" %> - - - - - - - - - -

- <%= Services.TextService.Localize("defaultdialogs/templateContentPlaceHolderHelp")%> -

-
- - - -
- - - <%=Services.TextService.Localize("general/cancel")%> - " /> - -
\ No newline at end of file diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/insertMasterpageContent.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/insertMasterpageContent.aspx.cs deleted file mode 100644 index 96b1006de5..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/insertMasterpageContent.aspx.cs +++ /dev/null @@ -1,52 +0,0 @@ -using Umbraco.Core.Services; -using System; -using System.Linq; -using System.Web.UI.WebControls; -using Umbraco.Core; -using Umbraco.Core.IO; - -namespace umbraco.presentation.umbraco.dialogs -{ - public partial class insertMasterpageContent : Umbraco.Web.UI.Pages.UmbracoEnsuredPage - { - public insertMasterpageContent() - { - CurrentApp = Constants.Applications.Settings.ToString(); - } - - protected void Page_Load(object sender, EventArgs e) - { - //labels - pp_placeholder.Text = Services.TextService.Localize("placeHolderID"); - - //Add a default Item - var li = new ListItem("Choose ID..."); - li.Selected = true; - dd_detectedAlias.Items.Add(li); - - //var t = new cms.businesslogic.template.Template(int.Parse(Request["id"])); - var t = Services.FileService.GetTemplate(int.Parse(Request["id"])); - - - //if (t.MasterTemplate > 0) - if (string.IsNullOrWhiteSpace(t.MasterTemplateAlias) != true) - { - //t = new cms.businesslogic.template.Template(t.MasterTemplate); - t = Services.FileService.GetTemplate(t.MasterTemplateAlias); - - } - - //foreach (string cpId in t.contentPlaceholderIds()) - foreach (string cpId in MasterPageHelper.GetContentPlaceholderIds(t)) - { - dd_detectedAlias.Items.Add(cpId); - } - - if (dd_detectedAlias.Items.Count == 1) - dd_detectedAlias.Items.Add("ContentPlaceHolderDefault"); - - } - - - } -} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/insertMasterpageContent.aspx.designer.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/insertMasterpageContent.aspx.designer.cs deleted file mode 100644 index 7303e3d56b..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/insertMasterpageContent.aspx.designer.cs +++ /dev/null @@ -1,42 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace umbraco.presentation.umbraco.dialogs { - - - public partial class insertMasterpageContent { - - /// - /// pane_insert control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.Pane pane_insert; - - /// - /// pp_placeholder control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.PropertyPanel pp_placeholder; - - /// - /// dd_detectedAlias control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.DropDownList dd_detectedAlias; - } -} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/insertMasterpagePlaceholder.aspx b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/insertMasterpagePlaceholder.aspx deleted file mode 100644 index bb6bca8042..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/insertMasterpagePlaceholder.aspx +++ /dev/null @@ -1,34 +0,0 @@ -<%@ Page Title="" Language="C#" MasterPageFile="../masterpages/umbracoDialog.Master" AutoEventWireup="true" CodeBehind="insertMasterpagePlaceholder.aspx.cs" Inherits="umbraco.presentation.umbraco.dialogs.insertMasterpagePlaceholder" %> - - - - - - - - - -

- <%= Services.TextService.Localize("defaultdialogs/templateContentAreaHelp")%> -

-
- - - - -
- - - <%=Services.TextService.Localize("general/cancel")%> - " /> - -
\ No newline at end of file diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/insertMasterpagePlaceholder.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/insertMasterpagePlaceholder.aspx.cs deleted file mode 100644 index 48073a7f4f..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/insertMasterpagePlaceholder.aspx.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Umbraco.Core.Services; -using System; -using Umbraco.Core; - -namespace umbraco.presentation.umbraco.dialogs { - public partial class insertMasterpagePlaceholder : Umbraco.Web.UI.Pages.UmbracoEnsuredPage { - - public insertMasterpagePlaceholder() - { - CurrentApp = Constants.Applications.Settings.ToString(); - } - protected void Page_Load(object sender, EventArgs e) { - //labels - pp_placeholder.Text = Services.TextService.Localize("placeHolderID"); - - } - } -} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/insertMasterpagePlaceholder.aspx.designer.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/insertMasterpagePlaceholder.aspx.designer.cs deleted file mode 100644 index a12635e368..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/insertMasterpagePlaceholder.aspx.designer.cs +++ /dev/null @@ -1,26 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace umbraco.presentation.umbraco.dialogs { - - - public partial class insertMasterpagePlaceholder { - - /// - /// tb_alias control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox tb_alias; - - protected global::Umbraco.Web._Legacy.Controls.PropertyPanel pp_placeholder; - } -} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/republish.aspx b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/republish.aspx deleted file mode 100644 index c58ca0d8fc..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/republish.aspx +++ /dev/null @@ -1,40 +0,0 @@ -<%@ Page Language="c#" Codebehind="republish.aspx.cs" MasterPageFile="../masterpages/umbracoDialog.Master" AutoEventWireup="True" Inherits="umbraco.cms.presentation.republish" %> -<%@ Register TagPrefix="cc1" Namespace="Umbraco.Web._Legacy.Controls" %> - - - - - - - -
-

<%= Services.TextService.Localize("defaultdialogs/siterepublishHelp")%>

-
- -
- - <%= Services.TextService.Localize("or") %> - <%=Services.TextService.Localize("cancel")%> -
- - - -
- - -
-

<%= Services.TextService.Localize("defaultdialogs/siterepublished")%>

- -
- -
-
\ No newline at end of file diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/republish.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/republish.aspx.cs deleted file mode 100644 index 4fee44eabe..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/republish.aspx.cs +++ /dev/null @@ -1,68 +0,0 @@ -//TODO: Re-create this in angular and new APIS! then remove it - -//using System; -//using System.Collections; -//using System.ComponentModel; -//using System.Data; -//using System.Drawing; -//using System.Web; -//using System.Web.SessionState; -//using System.Web.UI; -//using System.Web.UI.WebControls; -//using System.Web.UI.HtmlControls; -//using Umbraco.Web; - -//namespace umbraco.cms.presentation -//{ -// /// -// /// Summary description for republish. -// /// -// public partial class republish : Umbraco.Web.UI.Pages.UmbracoEnsuredPage -// { -// public republish() -// { -// CurrentApp = Constants.Applications.Content.ToString(); - -// } -// protected void go(object sender, EventArgs e) { -// // re-create xml -// if (Request.GetItemAsString("xml") != "") -// { -// Server.ScriptTimeout = 100000; -// Services.ContentService.RePublishAll(); -// } -// else if (Request.GetItemAsString("previews") != "") -// { -// Server.ScriptTimeout = 100000; -// umbraco.cms.businesslogic.web.Document.RegeneratePreviews(); -// } -// else if (Request.GetItemAsString("refreshNodes") != "") -// { -// Server.ScriptTimeout = 100000; -// System.Xml.XmlDocument xd = new System.Xml.XmlDocument(); - -// var doc = new cms.businesslogic.web.Document(int.Parse(Request.GetItemAsString("refreshNodes"))); - -// foreach (cms.businesslogic.web.Document d in doc.Children) -// { -// d.XmlGenerate(xd); -// Response.Write("
  • Creating xml for " + d.Text + "
  • "); -// Response.Flush(); -// } -// } - -// //PPH changed this to a general library call for load balancing support -// library.RefreshContent(); - -// p_republish.Visible = false; -// p_done.Visible = true; -// } - -// protected void Page_Load(object sender, System.EventArgs e) -// { -// bt_go.Text = Services.TextService.Localize("republish"); -// } - - -// } -//} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/republish.aspx.designer.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/republish.aspx.designer.cs deleted file mode 100644 index a2311585a5..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/republish.aspx.designer.cs +++ /dev/null @@ -1,51 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace umbraco.cms.presentation { - - - public partial class republish { - - /// - /// p_republish control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Panel p_republish; - - /// - /// bt_go control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Button bt_go; - - /// - /// progbar control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.ProgressBar progbar; - - /// - /// p_done control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Panel p_done; - } -} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/umbracoField.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/umbracoField.aspx.cs deleted file mode 100644 index 244fdeb9da..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/umbracoField.aspx.cs +++ /dev/null @@ -1,251 +0,0 @@ -using System.Linq; -using System.Web.UI.WebControls; -using Umbraco.Core.Configuration; -using Umbraco.Core; -using Umbraco.Core.Services; -using Umbraco.Web; -using Umbraco.Web.Composing; - -namespace umbraco.dialogs -{ - /// - /// Summary description for umbracoField. - /// - public partial class umbracoField : Umbraco.Web.UI.Pages.UmbracoEnsuredPage - { - string[] preValuesSource = { "@createDate", "@creatorName", "@level", "@nodeType", "@nodeTypeAlias", "@pageID", "@pageName", "@parentID", "@path", "@template", "@updateDate", "@writerID", "@writerName" }; - bool m_IsDictionaryMode = false; - - public umbracoField() - { - CurrentApp = Constants.Applications.Settings.ToString(); - } - - protected void Page_Load(object sender, System.EventArgs e) - { - - //set labels on properties... - pp_insertAltField.Text = Services.TextService.Localize("templateEditor/alternativeField"); - pp_insertAltText.Text = Services.TextService.Localize("templateEditor/alternativeText"); - pp_insertBefore.Text = Services.TextService.Localize("templateEditor/preContent"); - pp_insertAfter.Text = Services.TextService.Localize("templateEditor/postContent"); - - pp_FormatAsDate.Text = Services.TextService.Localize("templateEditor/formatAsDate"); - pp_casing.Text = Services.TextService.Localize("templateEditor/casing"); - pp_encode.Text = Services.TextService.Localize("templateEditor/encoding"); - - tagName.Value = "umbraco:Item"; - - using (var scope = Current.ScopeProvider.CreateScope()) - { - // either get page fields or dictionary items - string fieldSql = ""; - if (Request.GetItemAsString("tagName") == "UMBRACOGETDICTIONARY") - { - fieldSql = "select '#'+[key] as alias from cmsDictionary order by alias"; - m_IsDictionaryMode = true; - pp_insertField.Text = "Insert Dictionary Item"; - } - else - { - //exclude built-in memberhip properties from showing up here - var exclude = Constants.Conventions.Member.GetStandardPropertyTypeStubs() - .Select(x => Current.SqlContext.SqlSyntax.GetQuotedValue(x.Key)).ToArray(); - - fieldSql = string.Format( - "select distinct alias from cmsPropertyType where alias not in ({0}) order by alias", - string.Join(",", exclude)); - pp_insertField.Text = Services.TextService.Localize("templateEditor/chooseField"); - } - - fieldPicker.ChooseText = Services.TextService.Localize("templateEditor/chooseField"); - fieldPicker.StandardPropertiesLabel = Services.TextService.Localize("templateEditor/standardFields"); - fieldPicker.CustomPropertiesLabel = Services.TextService.Localize("templateEditor/customFields"); - - var dataTypes = scope.Database.Fetch(fieldSql); - fieldPicker.DataTextField = "alias"; - fieldPicker.DataValueField = "alias"; - fieldPicker.DataSource = dataTypes; - fieldPicker.DataBind(); - fieldPicker.Attributes.Add("onChange", "document.forms[0].field.value = document.forms[0]." + fieldPicker.ClientID + "[document.forms[0]." + fieldPicker.ClientID + ".selectedIndex].value;"); - - altFieldPicker.ChooseText = Services.TextService.Localize("templateEditor/chooseField"); - altFieldPicker.StandardPropertiesLabel = Services.TextService.Localize("templateEditor/standardFields"); - altFieldPicker.CustomPropertiesLabel = Services.TextService.Localize("templateEditor/customFields"); - - var dataTypes2 = scope.Database.Fetch(fieldSql); - altFieldPicker.DataTextField = "alias"; - altFieldPicker.DataValueField = "alias"; - altFieldPicker.DataSource = dataTypes2; - altFieldPicker.DataBind(); - altFieldPicker.Attributes.Add("onChange", "document.forms[0].useIfEmpty.value = document.forms[0]." + altFieldPicker.ClientID + "[document.forms[0]." + altFieldPicker.ClientID + ".selectedIndex].value;"); - - scope.Complete(); - } - - // Pre values - if (!m_IsDictionaryMode) - { - foreach (string s in preValuesSource) - { - fieldPicker.Items.Add(new ListItem(s, s.Replace("@", ""))); - altFieldPicker.Items.Add(new ListItem(s, s.Replace("@", ""))); - } - } - } - - - /// - /// JsInclude1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::ClientDependency.Core.Controls.JsInclude JsInclude1; - - /// - /// JsInclude2 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::ClientDependency.Core.Controls.JsInclude JsInclude2; - - /// - /// tagName control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.HtmlControls.HtmlInputHidden tagName; - - /// - /// pane_form control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.Pane pane_form; - - /// - /// pp_insertField control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.PropertyPanel pp_insertField; - - /// - /// fieldPicker control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.FieldDropDownList fieldPicker; - - /// - /// pp_insertAltField control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.PropertyPanel pp_insertAltField; - - /// - /// altFieldPicker control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.FieldDropDownList altFieldPicker; - - /// - /// pp_insertAltText control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.PropertyPanel pp_insertAltText; - - /// - /// pp_recursive control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.PropertyPanel pp_recursive; - - /// - /// pp_insertBefore control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.PropertyPanel pp_insertBefore; - - /// - /// pp_insertAfter control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.PropertyPanel pp_insertAfter; - - /// - /// pp_FormatAsDate control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.PropertyPanel pp_FormatAsDate; - - /// - /// pp_casing control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.PropertyPanel pp_casing; - - /// - /// pp_encode control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.PropertyPanel pp_encode; - - /// - /// pp_convertLineBreaks control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.PropertyPanel pp_convertLineBreaks; - - /// - /// pp_removePTags control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.PropertyPanel pp_removePTags; - } -} From ec60ba142aae54da0ebfbe70f125932f591c948a Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Wed, 9 Jan 2019 10:50:27 +0100 Subject: [PATCH 258/469] Fixes #3993 Recent changes in color picker has caused incompatibility with existing picker --- .../propertyeditors/colorpicker/colorpicker.controller.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.controller.js index abb26ef4a2..3a6ddc5cfd 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.controller.js @@ -123,6 +123,11 @@ function ColorPickerController($scope) { if (!$scope.model.value) return false; + // Backwards compatibility, the color used to be stored as a hex value only + if ($scope.model.value.length === 6) { + $scope.model.value = { value: $scope.model.value, label: $scope.model.value }; + } + // Complex color (value and label)? if (!$scope.model.value.hasOwnProperty("value")) return $scope.model.value === color.value; From d41dbce60125cf9a8aa30e4d5a0bf39bddb59e1a Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Wed, 9 Jan 2019 11:20:34 +0100 Subject: [PATCH 259/469] Fix content picker dirty checking (#4003) --- .../contentpicker/contentpicker.controller.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js index c1fe21b1b5..ee8c193b4b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js @@ -35,7 +35,6 @@ function contentPickerController($scope, entityResource, editorState, iconHelper return $scope.model.config.idType === "udi" ? i.udi : i.id; }); $scope.model.value = trim(currIds.join(), ","); - angularHelper.getCurrentForm($scope).$setDirty(); //Validate! if ($scope.model.config && $scope.model.config.minNumber && parseInt($scope.model.config.minNumber) > $scope.renderModel.length) { @@ -84,7 +83,10 @@ function contentPickerController($scope, entityResource, editorState, iconHelper opacity: 0.7, tolerance: "pointer", scroll: true, - zIndex: 6000 + zIndex: 6000, + update: function (e, ui) { + angularHelper.getCurrentForm($scope).$setDirty(); + } }; if ($scope.model.config) { From a809e35e5d07117c9a2d3d54050685c3253335da Mon Sep 17 00:00:00 2001 From: Robert Date: Wed, 9 Jan 2019 11:29:42 +0100 Subject: [PATCH 260/469] Fixes - temp8-40120 tags-validation-bug --- .../directives/components/tags/umbtagseditor.directive.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/tags/umbtagseditor.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/tags/umbtagseditor.directive.js index 8bad5ae8fd..fea7528d5b 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/tags/umbtagseditor.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/tags/umbtagseditor.directive.js @@ -189,7 +189,7 @@ */ function validateMandatory() { return { - isValid: !vm.validation.mandatory || (vm.viewModel != null && vm.viewModel.length > 0), + isValid: !vm.validation.mandatory || (vm.viewModel != null && vm.viewModel.length > 0) || (vm.value != null && vm.value.length > 0), errorMsg: "Value cannot be empty", errorKey: "required" }; From fe689e68551d20e8c733752132f5cc216e5db43f Mon Sep 17 00:00:00 2001 From: elitsa Date: Wed, 9 Jan 2019 12:08:46 +0100 Subject: [PATCH 261/469] Added timeout to for rebinding editor shortcuts, and a shortcut for a media picker. --- .../src/common/services/editor.service.js | 10 ++++++---- .../infiniteeditors/mediapicker/mediapicker.html | 1 + 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js b/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js index 0d6432b01f..c495c4e7a1 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js @@ -162,7 +162,7 @@ When building a custom infinite editor view you can use the same components as a (function () { "use strict"; - function editorService(eventsService, keyboardService) { + function editorService(eventsService, keyboardService, $timeout) { let editorsKeyboardShorcuts = []; var editors = []; @@ -246,9 +246,11 @@ When building a custom infinite editor view you can use the same components as a // emit event to let components know an editor has been removed eventsService.emit("appState.editors.close", args); - // rebind keyboard shortcuts for the new editor in focus - rebindKeyboardShortcuts(); - + $timeout(function() { + // rebind keyboard shortcuts for the new editor in focus + rebindKeyboardShortcuts(); + }, 0); + } /** diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/mediapicker.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/mediapicker.html index 3bb694cac6..cac412df8b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/mediapicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/mediapicker.html @@ -171,6 +171,7 @@ From 10cf10b33a4333a18e816ed5f11be2b5d7e91a6d Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Wed, 9 Jan 2019 12:22:55 +0100 Subject: [PATCH 262/469] Set form as dirty when removing a tag --- .../src/views/propertyeditors/tags/tags.controller.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/tags/tags.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/tags/tags.controller.js index 688ac7693f..a61930f877 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/tags/tags.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/tags/tags.controller.js @@ -1,9 +1,12 @@ angular.module("umbraco") .controller("Umbraco.PropertyEditors.TagsController", - function ($scope) { + function ($scope, angularHelper) { $scope.valueChanged = function(value) { $scope.model.value = value; + // the model value seems to be a reference to the same array, so we need + // to set the form as dirty explicitly when the content of the array changes + angularHelper.getCurrentForm($scope).$setDirty(); } } From aea41937f7f468c32bcff8c6aa187c8b00c12c29 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Wed, 9 Jan 2019 13:18:27 +0100 Subject: [PATCH 263/469] Allow content app badges without "count" --- .../src/less/components/umb-editor-navigation.less | 5 +++++ .../src/views/components/editor/umb-editor-navigation.html | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation.less index 61cab3b477..95e6569727 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation.less @@ -60,6 +60,7 @@ font-weight: bold; padding: 2px; line-height: 16px; + display: block; &.-type-alert { background-color: @red-l1; @@ -67,6 +68,10 @@ &.-type-warning { background-color: @yellow-d2; } + &:empty { + height: 10px; + min-width: 10px; + } } .umb-sub-views-nav-item-text { diff --git a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-navigation.html b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-navigation.html index 1f973ea2f6..e278a8c401 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-navigation.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-navigation.html @@ -12,7 +12,7 @@ ng-class="{'is-active': item.active, '-has-error': item.hasError}"> {{ item.name }} -
    {{item.badge.count}}
    +
    {{item.badge.count}}
    From cd1338db82a6c9a0d5e92908bcbdecad8cbae298 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Wed, 9 Jan 2019 13:20:16 +0100 Subject: [PATCH 264/469] Make the count-less badge a little bit bigger --- .../src/less/components/umb-editor-navigation.less | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation.less index 95e6569727..d8b83af67a 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation.less @@ -69,8 +69,8 @@ background-color: @yellow-d2; } &:empty { - height: 10px; - min-width: 10px; + height: 12px; + min-width: 12px; } } From 39028cd240b436d0927bda2c43301638e5d41329 Mon Sep 17 00:00:00 2001 From: Stephan Date: Wed, 9 Jan 2019 14:09:05 +0100 Subject: [PATCH 265/469] Upgrade ModelsBuilder (bugfix) --- src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index 9969cea687..a8f37c5929 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -107,7 +107,7 @@ - 8.0.0-alpha.29 + 8.0.0-alpha.30 From ff085c97ce4f8c7d7abb0510401ad0ddb17f2ae7 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Wed, 9 Jan 2019 14:57:17 +0100 Subject: [PATCH 266/469] Revert "Added eslintignore file" This reverts commit 673735c2fed762d19fefec662bb79c435e49b763. --- src/Umbraco.Web.UI/.eslintignore | 3 --- src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 1 - 2 files changed, 4 deletions(-) delete mode 100644 src/Umbraco.Web.UI/.eslintignore diff --git a/src/Umbraco.Web.UI/.eslintignore b/src/Umbraco.Web.UI/.eslintignore deleted file mode 100644 index 6cac59fac0..0000000000 --- a/src/Umbraco.Web.UI/.eslintignore +++ /dev/null @@ -1,3 +0,0 @@ - -/Umbraco/** -/Umbraco_Client/** diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index 512d8637d8..dc9625f39e 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -520,7 +520,6 @@ - 404handlers.config From 49668a48bcf0bf3fcfb294cc96c6090cc145f9e1 Mon Sep 17 00:00:00 2001 From: Stephan Date: Wed, 9 Jan 2019 15:09:16 +0100 Subject: [PATCH 267/469] Upgrade ModelsBuilder (bugfix) --- src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index a8f37c5929..4ccead279a 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -107,7 +107,7 @@ - 8.0.0-alpha.30 + 8.0.0-alpha.31 From 2bc63b970014012fea4b8c8a6ca74a0f5e4fa642 Mon Sep 17 00:00:00 2001 From: Stephan Date: Wed, 9 Jan 2019 16:06:36 +0100 Subject: [PATCH 268/469] fix build --- build/NuSpecs/UmbracoCms.nuspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/NuSpecs/UmbracoCms.nuspec b/build/NuSpecs/UmbracoCms.nuspec index fc417147d3..565d693979 100644 --- a/build/NuSpecs/UmbracoCms.nuspec +++ b/build/NuSpecs/UmbracoCms.nuspec @@ -22,7 +22,7 @@ not want this to happen as the alpha of the next major is, really, the next major already. --> - + From 944d47f669b59e65ce58a4a2f8baa38e34dfc0a1 Mon Sep 17 00:00:00 2001 From: Stephan Date: Wed, 9 Jan 2019 17:39:32 +0100 Subject: [PATCH 269/469] Refactor filesystems registration --- src/Umbraco.Core/Components/Composition.cs | 123 +++++++++--------- .../Components/CompositionExtensions.cs | 13 +- .../Composing/CollectionBuilderBase.cs | 2 +- .../Composers/FileSystemsComposer.cs | 31 +++-- .../Composing/CompositionExtensions.cs | 9 +- .../Composing/FactoryExtensions.cs | 3 + src/Umbraco.Core/Composing/IFactory.cs | 12 +- src/Umbraco.Core/Composing/IRegister.cs | 21 ++- .../Composing/LazyCollectionBuilderBase.cs | 2 +- .../LightInject/LightInjectContainer.cs | 57 ++++---- .../Composing/OrderedCollectionBuilderBase.cs | 2 +- .../Composing/RegisterExtensions.cs | 10 ++ .../Composing/TargetedServiceProvider.cs | 18 +++ .../WeightedCollectionBuilderBase.cs | 2 +- src/Umbraco.Core/IO/SupportingFileSystems.cs | 11 ++ src/Umbraco.Core/Umbraco.Core.csproj | 2 + src/Umbraco.Web/Composing/ModuleInjector.cs | 5 +- 17 files changed, 211 insertions(+), 112 deletions(-) create mode 100644 src/Umbraco.Core/Composing/TargetedServiceProvider.cs create mode 100644 src/Umbraco.Core/IO/SupportingFileSystems.cs diff --git a/src/Umbraco.Core/Components/Composition.cs b/src/Umbraco.Core/Components/Composition.cs index dd0b83dcb3..6cd8c8e5f0 100644 --- a/src/Umbraco.Core/Components/Composition.cs +++ b/src/Umbraco.Core/Components/Composition.cs @@ -17,7 +17,7 @@ namespace Umbraco.Core.Components public class Composition : IRegister { private readonly Dictionary _builders = new Dictionary(); - private readonly Dictionary _uniques = new Dictionary(); + private readonly Dictionary> _uniques = new Dictionary>(); private readonly IRegister _register; /// @@ -81,14 +81,30 @@ namespace Umbraco.Core.Components public void Register(Type serviceType, Type implementingType, Lifetime lifetime = Lifetime.Transient) => _register.Register(serviceType, implementingType, lifetime); + /// + public void RegisterFor(Type implementingType, Lifetime lifetime = Lifetime.Transient) + where TService : class + => _register.RegisterFor(implementingType, lifetime); + /// public void Register(Func factory, Lifetime lifetime = Lifetime.Transient) + where TService : class => _register.Register(factory, lifetime); + /// + public void RegisterFor(Func factory, Lifetime lifetime = Lifetime.Transient) + where TService : class + => _register.RegisterFor(factory, lifetime); + /// public void RegisterInstance(Type serviceType, object instance) => _register.RegisterInstance(serviceType, instance); + /// + public void RegisterInstanceFor(TService instance) + where TService : class + => _register.RegisterInstanceFor(instance); + /// public void RegisterAuto(Type serviceBaseType) => _register.RegisterAuto(serviceBaseType); @@ -104,10 +120,12 @@ namespace Umbraco.Core.Components onCreating(); foreach (var unique in _uniques.Values) - unique.RegisterWith(_register); + unique(_register); + _uniques.Clear(); // no point keep them around foreach (var builder in _builders.Values) builder.RegisterWith(_register); + _builders.Clear(); // no point keep them around Configs.RegisterWith(_register); @@ -123,74 +141,63 @@ namespace Umbraco.Core.Components #region Unique - /// - /// Registers a unique service. - /// - /// Unique services have one single implementation, and a Singleton lifetime. - public void RegisterUnique(Type serviceType, Type implementingType) - => _uniques[serviceType] = new Unique(serviceType, implementingType); + private string GetUniqueName() + => GetUniqueName(typeof(TService)); + + private string GetUniqueName(Type serviceType) + => serviceType.FullName; + + private string GetUniqueName() + => GetUniqueName(typeof(TService), typeof(TTarget)); + + private string GetUniqueName(Type serviceType, Type targetType) + => serviceType.FullName + "::" + targetType.FullName; /// /// Registers a unique service. /// /// Unique services have one single implementation, and a Singleton lifetime. - public void RegisterUnique(Type serviceType, object instance) - => _uniques[serviceType] = new Unique(serviceType, instance); + public void RegisterUnique(Type serviceType, Type implementingType) + => _uniques[GetUniqueName(serviceType)] = register => register.Register(serviceType, implementingType, Lifetime.Singleton); + + /// + /// Registers a unique service, for a target. + /// + /// Unique services have one single implementation, and a Singleton lifetime. + public void RegisterUniqueFor(Type implementingType) + where TService : class + => _uniques[GetUniqueName()] = register => register.RegisterFor(implementingType, Lifetime.Singleton); + + /// + /// Registers a unique service. + /// + /// Unique services have one single implementation, and a Singleton lifetime. + public void RegisterUniqueInstance(Type serviceType, object instance) + => _uniques[GetUniqueName(serviceType)] = register => register.RegisterInstance(serviceType, instance); + + /// + /// Registers a unique service, for a target. + /// + /// Unique services have one single implementation, and a Singleton lifetime. + public void RegisterUniqueInstanceFor(TService instance) + where TService : class + => _uniques[GetUniqueName()] = register => register.RegisterInstanceFor(instance); /// /// Registers a unique service. /// /// Unique services have one single implementation, and a Singleton lifetime. public void RegisterUnique(Func factory) - => _uniques[typeof(TService)] = new Unique(factory); + where TService : class + => _uniques[GetUniqueName()] = register => register.Register(factory, Lifetime.Singleton); - private class Unique - { - private readonly Type _serviceType; - private readonly Type _implementingType; - private readonly object _instance; - - protected Unique(Type serviceType) - { - _serviceType = serviceType; - } - - public Unique(Type serviceType, Type implementingType) - : this(serviceType) - { - _implementingType = implementingType; - } - - public Unique(Type serviceType, object instance) - : this(serviceType) - { - _instance = instance; - } - - public virtual void RegisterWith(IRegister register) - { - if (_implementingType != null) - register.Register(_serviceType, _implementingType, Lifetime.Singleton); - else if (_instance != null) - register.RegisterInstance(_serviceType, _instance); - } - } - - private class Unique : Unique - { - private readonly Func _factory; - - public Unique(Func factory) - : base(typeof(TService)) - { - _factory = factory; - } - - public override void RegisterWith(IRegister register) - { - register.Register(_factory, Lifetime.Singleton); - } - } + /// + /// Registers a unique service, for a target. + /// + /// Unique services have one single implementation, and a Singleton lifetime. + public void RegisterUniqueFor(Func factory) + where TService : class + => _uniques[GetUniqueName()] = register => register.RegisterFor(factory, Lifetime.Singleton); #endregion diff --git a/src/Umbraco.Core/Components/CompositionExtensions.cs b/src/Umbraco.Core/Components/CompositionExtensions.cs index 93d190d17e..a4bc82cb4b 100644 --- a/src/Umbraco.Core/Components/CompositionExtensions.cs +++ b/src/Umbraco.Core/Components/CompositionExtensions.cs @@ -26,15 +26,16 @@ namespace Umbraco.Core.Components /// The type of the filesystem. /// The implementing type. /// The composition. - /// A factory method creating the supporting filesystem. /// The register. - public static void RegisterFileSystem(this Composition composition, Func supportingFileSystemFactory) + public static void RegisterFileSystem(this Composition composition) where TImplementing : FileSystemWrapper, TFileSystem + where TFileSystem : class { composition.RegisterUnique(factory => { var fileSystems = factory.GetInstance(); - return fileSystems.GetFileSystem(supportingFileSystemFactory(factory)); + var supporting = factory.GetInstance(); + return fileSystems.GetFileSystem(supporting.For()); }); } @@ -43,15 +44,15 @@ namespace Umbraco.Core.Components /// /// The type of the filesystem. /// The composition. - /// A factory method creating the supporting filesystem. /// The register. - public static void RegisterFileSystem(this Composition composition, Func supportingFileSystemFactory) + public static void RegisterFileSystem(this Composition composition) where TFileSystem : FileSystemWrapper { composition.RegisterUnique(factory => { var fileSystems = factory.GetInstance(); - return fileSystems.GetFileSystem(supportingFileSystemFactory(factory)); + var supporting = factory.GetInstance(); + return fileSystems.GetFileSystem(supporting.For()); }); } diff --git a/src/Umbraco.Core/Composing/CollectionBuilderBase.cs b/src/Umbraco.Core/Composing/CollectionBuilderBase.cs index 7633f6b001..41038ea4e9 100644 --- a/src/Umbraco.Core/Composing/CollectionBuilderBase.cs +++ b/src/Umbraco.Core/Composing/CollectionBuilderBase.cs @@ -12,7 +12,7 @@ namespace Umbraco.Core.Composing /// The type of the items. public abstract class CollectionBuilderBase : ICollectionBuilder where TBuilder: CollectionBuilderBase - where TCollection : IBuilderCollection + where TCollection : class, IBuilderCollection { private readonly List _types = new List(); private readonly object _locker = new object(); diff --git a/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs b/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs index f1fb095406..ab4bd015de 100644 --- a/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs @@ -12,10 +12,9 @@ namespace Umbraco.Core.Composing.Composers * * Create a component and use it to modify the composition by adding something like: * - * composition.Container.RegisterFileSystem( - * factory => new PhysicalFileSystem("~/somewhere")); + * composition.RegisterUniqueFor(...); * - * return whatever supporting filesystem you like. + * and register whatever supporting filesystem you like. * * * HOW TO IMPLEMENT MY OWN FILESYSTEM @@ -30,12 +29,15 @@ namespace Umbraco.Core.Composing.Composers * { } * } * - * The ctor can have more parameters that will be resolved by the container. + * The ctor can have more parameters, that will be resolved by the container. * * Register your filesystem, in a component: * - * composition.Container.RegisterFileSystem( - * factory => new PhysicalFileSystem("~/my")); + * composition.RegisterFileSystem(); + * + * Register the underlying filesystem: + * + * composition.RegisterUniqueFor(...); * * And that's it, you can inject MyFileSystem wherever it's needed. * @@ -48,8 +50,8 @@ namespace Umbraco.Core.Composing.Composers * Make the class implement the interface, then * register your filesystem, in a component: * - * composition.Container.RegisterFileSystem( - * factory => new PhysicalFileSystem("~/my")); + * composition.RegisterFileSystem(); + * composition.RegisterUniqueFor(...); * * And that's it, you can inject IMyFileSystem wherever it's needed. * @@ -79,9 +81,16 @@ namespace Umbraco.Core.Composing.Composers // register the scheme for media paths composition.RegisterUnique(); - // register the IMediaFileSystem implementation with a supporting filesystem - composition.RegisterFileSystem( - factory => new PhysicalFileSystem("~/media")); + // register the IMediaFileSystem implementation + composition.RegisterFileSystem(); + + // register the supporting filesystems provider + composition.Register(factory => new SupportingFileSystems(factory), Lifetime.Singleton); + + // register the IFileSystem supporting the IMediaFileSystem + // this is the only thing that need to be overriden to change the supporting filesystem + // and, SupportingFileSystem.For() returns the underlying filesystem + composition.RegisterUniqueFor(_ => new PhysicalFileSystem("~/media")); return composition; } diff --git a/src/Umbraco.Core/Composing/CompositionExtensions.cs b/src/Umbraco.Core/Composing/CompositionExtensions.cs index cfc465b59d..ac9a5d6409 100644 --- a/src/Umbraco.Core/Composing/CompositionExtensions.cs +++ b/src/Umbraco.Core/Composing/CompositionExtensions.cs @@ -51,11 +51,18 @@ namespace Umbraco.Core.Composing public static void RegisterUnique(this Composition composition) => composition.RegisterUnique(typeof(TService), typeof(TImplementing)); + /// + /// Registers a unique service with an implementation type, for a target. + /// + public static void RegisterUniqueFor(this Composition composition) + where TService : class + => composition.RegisterUniqueFor(typeof(TImplementing)); + /// /// Registers a unique service with an implementing instance. /// public static void RegisterUnique(this Composition composition, TService instance) - => composition.RegisterUnique(typeof(TService), instance); + => composition.RegisterUniqueInstance(typeof(TService), instance); #endregion } diff --git a/src/Umbraco.Core/Composing/FactoryExtensions.cs b/src/Umbraco.Core/Composing/FactoryExtensions.cs index 2640b7f7e6..8027f2c7a1 100644 --- a/src/Umbraco.Core/Composing/FactoryExtensions.cs +++ b/src/Umbraco.Core/Composing/FactoryExtensions.cs @@ -17,6 +17,7 @@ namespace Umbraco.Core.Composing /// An instance of the specified type. /// Throws an exception if the factory failed to get an instance of the specified type. public static T GetInstance(this IFactory factory) + where T : class => (T)factory.GetInstance(typeof(T)); /// @@ -28,6 +29,7 @@ namespace Umbraco.Core.Composing /// of the specified type. Throws an exception if the factory does know how /// to get an instance of the specified type, but failed to do so. public static T TryGetInstance(this IFactory factory) + where T : class => (T)factory.TryGetInstance(typeof(T)); /// @@ -42,6 +44,7 @@ namespace Umbraco.Core.Composing /// The arguments are used as dependencies by the factory. /// public static T CreateInstance(this IFactory factory, params object[] args) + where T : class => (T)factory.CreateInstance(typeof(T), args); /// diff --git a/src/Umbraco.Core/Composing/IFactory.cs b/src/Umbraco.Core/Composing/IFactory.cs index 9a59b1c052..20fbe33737 100644 --- a/src/Umbraco.Core/Composing/IFactory.cs +++ b/src/Umbraco.Core/Composing/IFactory.cs @@ -28,6 +28,15 @@ namespace Umbraco.Core.Composing /// Throws an exception if the container failed to get an instance of the specified type. object GetInstance(Type type); + /// + /// Gets a targeted instance of a service. + /// + /// The type of the service. + /// The type of the target. + /// The instance of the specified type for the specified target. + /// Throws an exception if the container failed to get an instance of the specified type. + TService GetInstanceFor(); + /// /// Tries to get an instance of a service. /// @@ -48,7 +57,8 @@ namespace Umbraco.Core.Composing /// Gets all instances of a service. /// /// The type of the service. - IEnumerable GetAllInstances(); + IEnumerable GetAllInstances() + where TService : class; /// /// Releases an instance. diff --git a/src/Umbraco.Core/Composing/IRegister.cs b/src/Umbraco.Core/Composing/IRegister.cs index 8ad3db5409..d145df8790 100644 --- a/src/Umbraco.Core/Composing/IRegister.cs +++ b/src/Umbraco.Core/Composing/IRegister.cs @@ -33,16 +33,35 @@ namespace Umbraco.Core.Composing /// void Register(Type serviceType, Type implementingType, Lifetime lifetime = Lifetime.Transient); + /// + /// Registers a service with an implementation type, for a target. + /// + void RegisterFor(Type implementingType, Lifetime lifetime = Lifetime.Transient) + where TService : class; + /// /// Registers a service with an implementation factory. /// - void Register(Func factory, Lifetime lifetime = Lifetime.Transient); + void Register(Func factory, Lifetime lifetime = Lifetime.Transient) + where TService : class; + + /// + /// Registers a service with an implementation factory, for a target. + /// + void RegisterFor(Func factory, Lifetime lifetime = Lifetime.Transient) + where TService : class; /// /// Registers a service with an implementing instance. /// void RegisterInstance(Type serviceType, object instance); + /// + /// Registers a service with an implementing instance, for a target. + /// + void RegisterInstanceFor(TService instance) + where TService : class; + /// /// Registers a base type for auto-registration. /// diff --git a/src/Umbraco.Core/Composing/LazyCollectionBuilderBase.cs b/src/Umbraco.Core/Composing/LazyCollectionBuilderBase.cs index a1a06621e9..46b06daf7d 100644 --- a/src/Umbraco.Core/Composing/LazyCollectionBuilderBase.cs +++ b/src/Umbraco.Core/Composing/LazyCollectionBuilderBase.cs @@ -12,7 +12,7 @@ namespace Umbraco.Core.Composing /// The type of the items. public abstract class LazyCollectionBuilderBase : CollectionBuilderBase where TBuilder : LazyCollectionBuilderBase - where TCollection : IBuilderCollection + where TCollection : class, IBuilderCollection { private readonly List>> _producers = new List>>(); private readonly List _excluded = new List(); diff --git a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs index b39622f66a..4ccc0ba838 100644 --- a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs +++ b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs @@ -102,18 +102,25 @@ namespace Umbraco.Core.Composing.LightInject /// public IFactory CreateFactory() => this; + private static string GetTargetedServiceName() => "TARGET:" + typeof(TTarget).FullName; + #region Factory /// public object GetInstance(Type type) => Container.GetInstance(type); + /// + public TService GetInstanceFor() + => Container.GetInstance(GetTargetedServiceName()); + /// public object TryGetInstance(Type type) => Container.TryGetInstance(type); /// public IEnumerable GetAllInstances() + where T : class => Container.GetAllInstances(); /// @@ -139,19 +146,7 @@ namespace Umbraco.Core.Composing.LightInject /// public void Register(Type serviceType, Lifetime lifetime = Lifetime.Transient) { - switch (lifetime) - { - case Lifetime.Transient: - Container.Register(serviceType); - break; - case Lifetime.Request: - case Lifetime.Scope: - case Lifetime.Singleton: - Container.Register(serviceType, GetLifetime(lifetime)); - break; - default: - throw new NotSupportedException($"Lifetime {lifetime} is not supported."); - } + Container.Register(serviceType, GetLifetime(lifetime)); } /// @@ -173,21 +168,24 @@ namespace Umbraco.Core.Composing.LightInject } /// - public void Register(Func factory, Lifetime lifetime = Lifetime.Transient) + public void RegisterFor(Type implementingType, Lifetime lifetime = Lifetime.Transient) + where TService : class { - switch (lifetime) - { - case Lifetime.Transient: - Container.Register(f => factory(this)); - break; - case Lifetime.Request: - case Lifetime.Scope: - case Lifetime.Singleton: - Container.Register(f => factory(this), GetLifetime(lifetime)); - break; - default: - throw new NotSupportedException($"Lifetime {lifetime} is not supported."); - } + Container.Register(typeof(TService), implementingType, GetTargetedServiceName(), GetLifetime(lifetime)); + } + + /// + public void Register(Func factory, Lifetime lifetime = Lifetime.Transient) + where TService : class + { + Container.Register(f => factory(this), GetLifetime(lifetime)); + } + + /// + public void RegisterFor(Func factory, Lifetime lifetime = Lifetime.Transient) + where TService : class + { + Container.Register(f => factory(this), GetTargetedServiceName(), GetLifetime(lifetime)); } private ILifetime GetLifetime(Lifetime lifetime) @@ -211,6 +209,11 @@ namespace Umbraco.Core.Composing.LightInject public void RegisterInstance(Type serviceType, object instance) => Container.RegisterInstance(serviceType, instance); + /// + public void RegisterInstanceFor(TService instance) + where TService : class + => Container.RegisterInstance(typeof(TService), instance, GetTargetedServiceName()); + /// public void RegisterAuto(Type serviceBaseType) { diff --git a/src/Umbraco.Core/Composing/OrderedCollectionBuilderBase.cs b/src/Umbraco.Core/Composing/OrderedCollectionBuilderBase.cs index bde1bf96c5..241b84d8d2 100644 --- a/src/Umbraco.Core/Composing/OrderedCollectionBuilderBase.cs +++ b/src/Umbraco.Core/Composing/OrderedCollectionBuilderBase.cs @@ -11,7 +11,7 @@ namespace Umbraco.Core.Composing /// The type of the items. public abstract class OrderedCollectionBuilderBase : CollectionBuilderBase where TBuilder : OrderedCollectionBuilderBase - where TCollection : IBuilderCollection + where TCollection : class, IBuilderCollection { protected abstract TBuilder This { get; } diff --git a/src/Umbraco.Core/Composing/RegisterExtensions.cs b/src/Umbraco.Core/Composing/RegisterExtensions.cs index 4db1a2e9e4..9afa41e4b3 100644 --- a/src/Umbraco.Core/Composing/RegisterExtensions.cs +++ b/src/Umbraco.Core/Composing/RegisterExtensions.cs @@ -11,22 +11,32 @@ public static void Register(this IRegister register, Lifetime lifetime = Lifetime.Transient) => register.Register(typeof(TService), typeof(TImplementing), lifetime); + /// + /// Registers a service with an implementation type, for a target. + /// + public static void RegisterFor(this IRegister register, Lifetime lifetime = Lifetime.Transient) + where TService : class + => register.RegisterFor(typeof(TImplementing), lifetime); + /// /// Registers a service as its own implementation. /// public static void Register(this IRegister register, Lifetime lifetime = Lifetime.Transient) + where TService : class => register.Register(typeof(TService), lifetime); /// /// Registers a service with an implementing instance. /// public static void RegisterInstance(this IRegister register, TService instance) + where TService : class => register.RegisterInstance(typeof(TService), instance); /// /// Registers a base type for auto-registration. /// public static void RegisterAuto(this IRegister register) + where TServiceBase : class => register.RegisterAuto(typeof(TServiceBase)); } } diff --git a/src/Umbraco.Core/Composing/TargetedServiceProvider.cs b/src/Umbraco.Core/Composing/TargetedServiceProvider.cs new file mode 100644 index 0000000000..3f88e1bc28 --- /dev/null +++ b/src/Umbraco.Core/Composing/TargetedServiceProvider.cs @@ -0,0 +1,18 @@ +namespace Umbraco.Core.Composing +{ + /// + /// Provides a base class for targeted service factories. + /// + /// + public abstract class TargetedServiceProvider + { + private readonly IFactory _factory; + + protected TargetedServiceProvider(IFactory factory) + { + _factory = factory; + } + + public TService For() => _factory.GetInstanceFor(); + } +} diff --git a/src/Umbraco.Core/Composing/WeightedCollectionBuilderBase.cs b/src/Umbraco.Core/Composing/WeightedCollectionBuilderBase.cs index da47c53bf8..f8ecc11d98 100644 --- a/src/Umbraco.Core/Composing/WeightedCollectionBuilderBase.cs +++ b/src/Umbraco.Core/Composing/WeightedCollectionBuilderBase.cs @@ -12,7 +12,7 @@ namespace Umbraco.Core.Composing /// The type of the items. public abstract class WeightedCollectionBuilderBase : CollectionBuilderBase where TBuilder : WeightedCollectionBuilderBase - where TCollection : IBuilderCollection + where TCollection : class, IBuilderCollection { protected abstract TBuilder This { get; } diff --git a/src/Umbraco.Core/IO/SupportingFileSystems.cs b/src/Umbraco.Core/IO/SupportingFileSystems.cs new file mode 100644 index 0000000000..c13ae203ee --- /dev/null +++ b/src/Umbraco.Core/IO/SupportingFileSystems.cs @@ -0,0 +1,11 @@ +using Umbraco.Core.Composing; + +namespace Umbraco.Core.IO +{ + public class SupportingFileSystems : TargetedServiceProvider + { + public SupportingFileSystems(IFactory factory) + : base(factory) + { } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index a01bbf1746..a592fd0f0e 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -196,6 +196,7 @@ + @@ -343,6 +344,7 @@ + diff --git a/src/Umbraco.Web/Composing/ModuleInjector.cs b/src/Umbraco.Web/Composing/ModuleInjector.cs index 01930d55fd..57ef766dea 100644 --- a/src/Umbraco.Web/Composing/ModuleInjector.cs +++ b/src/Umbraco.Web/Composing/ModuleInjector.cs @@ -1,5 +1,4 @@ -using System; -using System.Web; +using System.Web; using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Core.Exceptions; @@ -11,7 +10,7 @@ namespace Umbraco.Web.Composing /// /// The type of the injected module. public abstract class ModuleInjector : IHttpModule - where TModule : IHttpModule + where TModule : class, IHttpModule { protected TModule Module { get; private set; } From 5f972384b1968be616ff6873422ee5bbf3c43fee Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 10 Jan 2019 12:44:57 +1100 Subject: [PATCH 270/469] WIP - new IEntityXmlSerializer, IPackageCreation, PackageActionRunner, large refactor of entity serialization, no more IPackagingService.Export methods, ports legacy package creation code to new IPackageCreation, more more ExportEventArgs (makes no sense) --- .../Composing/Composers/ServicesComposer.cs | 7 + src/Umbraco.Core/Composing/Current.cs | 4 + src/Umbraco.Core/ContentExtensions.cs | 65 +- src/Umbraco.Core/Events/ExportEventArgs.cs | 86 --- .../Models/Packaging/ActionRunAt.cs | 9 + .../Models/Packaging/InstallationSummary.cs | 19 - .../InstallationSummaryExtentions.cs | 23 + .../Models/Packaging/PackageAction.cs | 10 +- .../Models/Packaging/PackageDefinition.cs | 108 ++++ .../Packaging}/UninstallationSummary.cs | 22 +- .../UninstallationSummaryExtentions.cs | 22 + .../Packaging/IPackageCreation.cs | 22 + .../Packaging/IPackageInstallation.cs | 3 + .../Packaging/PackageActionRunner.cs} | 32 +- src/Umbraco.Core/Packaging/PackageCreation.cs | 564 ++++++++++++++++++ .../Services/IEntityXmlSerializer.cs | 88 +++ .../Services/IPackagingService.cs | 118 +--- .../Services/Implement/EntityService.cs | 3 + .../{ => Implement}/EntityXmlSerializer.cs | 226 +++++-- .../Services/Implement/PackagingService.cs | 470 ++------------- src/Umbraco.Core/Umbraco.Core.csproj | 14 +- .../PackageActions/PackageActionCollection.cs | 2 +- .../PublishedContentCacheTests.cs | 3 +- .../PublishedMediaCacheTests.cs | 9 +- src/Umbraco.Tests/Models/ContentXmlTest.cs | 4 +- src/Umbraco.Tests/Models/MediaXmlTest.cs | 3 +- .../PublishedContent/NuCacheTests.cs | 3 +- .../PublishedContent/PublishedMediaTests.cs | 23 +- .../Scoping/ScopedNuCacheTests.cs | 3 +- .../ContentTypeServiceVariantsTests.cs | 3 +- .../Services/EntityXmlSerializerTests.cs | 101 ++++ .../Services/Importing/PackageImportTests.cs | 4 +- .../Services/PackagingServiceTests.cs | 88 +-- src/Umbraco.Tests/TestHelpers/TestObjects.cs | 6 +- .../TestHelpers/TestWithDatabaseBase.cs | 1 + src/Umbraco.Tests/UI/LegacyDialogTests.cs | 1 - src/Umbraco.Tests/Umbraco.Tests.csproj | 1 + .../Web/Mvc/UmbracoViewPageTests.cs | 6 +- src/Umbraco.Web/Composing/Current.cs | 3 + .../Editors/ContentTypeController.cs | 20 +- .../Editors/ContentTypeControllerBase.cs | 14 +- .../Editors/MediaTypeController.cs | 11 + .../Editors/MemberTypeController.cs | 12 + src/Umbraco.Web/Editors/PackageController.cs | 66 +- .../Editors/PackageInstallController.cs | 22 +- .../UmbracoAuthorizedJsonController.cs | 31 +- .../ContentEditing/UmbracoEntityTypes.cs | 2 + .../PublishedCache/NuCache/MemberCache.cs | 13 +- .../NuCache/PublishedSnapshotService.cs | 7 +- .../XmlPublishedCache/PublishedMediaCache.cs | 21 +- .../PublishedSnapshotService.cs | 38 +- .../XmlPublishedCache/XmlStore.cs | 44 +- src/Umbraco.Web/Services/SectionService.cs | 2 +- src/Umbraco.Web/Umbraco.Web.csproj | 4 - src/Umbraco.Web/_Legacy/Packager/Installer.cs | 8 +- .../PackageInstance/CreatedPackage.cs | 49 +- .../PackageInstance/IPackageInstance.cs | 27 - .../PackageInstance/InstalledPackage.cs | 8 +- .../PackageInstance/PackageInstance.cs | 132 ---- .../PackageInstance/PackagerUtility.cs | 51 +- src/Umbraco.Web/_Legacy/Packager/Settings.cs | 64 +- src/Umbraco.Web/_Legacy/Packager/data.cs | 40 +- .../umbraco/create/CreatedPackageTasks.cs | 45 -- .../developer/Packages/editPackage.aspx.cs | 68 ++- 64 files changed, 1543 insertions(+), 1435 deletions(-) delete mode 100644 src/Umbraco.Core/Events/ExportEventArgs.cs create mode 100644 src/Umbraco.Core/Models/Packaging/ActionRunAt.cs create mode 100644 src/Umbraco.Core/Models/Packaging/InstallationSummaryExtentions.cs create mode 100644 src/Umbraco.Core/Models/Packaging/PackageDefinition.cs rename src/Umbraco.Core/{Packaging/Models => Models/Packaging}/UninstallationSummary.cs (50%) create mode 100644 src/Umbraco.Core/Models/Packaging/UninstallationSummaryExtentions.cs create mode 100644 src/Umbraco.Core/Packaging/IPackageCreation.cs rename src/{Umbraco.Web/_Legacy/Packager/PackageInstance/PackageActions.cs => Umbraco.Core/Packaging/PackageActionRunner.cs} (58%) create mode 100644 src/Umbraco.Core/Packaging/PackageCreation.cs create mode 100644 src/Umbraco.Core/Services/IEntityXmlSerializer.cs rename src/Umbraco.Core/Services/{ => Implement}/EntityXmlSerializer.cs (70%) create mode 100644 src/Umbraco.Tests/Services/EntityXmlSerializerTests.cs delete mode 100644 src/Umbraco.Web/_Legacy/Packager/PackageInstance/IPackageInstance.cs delete mode 100644 src/Umbraco.Web/_Legacy/Packager/PackageInstance/PackageInstance.cs delete mode 100644 src/Umbraco.Web/umbraco.presentation/umbraco/create/CreatedPackageTasks.cs diff --git a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs index 1b77aaa7d6..6133d63377 100644 --- a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs @@ -6,6 +6,7 @@ using Umbraco.Core.Components; using Umbraco.Core.Events; using Umbraco.Core.IO; using Umbraco.Core.Logging; +using Umbraco.Core.Packaging; using Umbraco.Core.Services; using Umbraco.Core.Services.Implement; @@ -56,6 +57,12 @@ namespace Umbraco.Core.Composing.Composers factory.GetInstance>(), factory.GetInstance())); + composition.RegisterUnique(); + + composition.RegisterUnique(); + composition.RegisterUnique(); + + //TODO: These are replaced in the web project - we need to declare them so that // something is wired up, just not sure this is very nice but will work for now. composition.RegisterUnique(); diff --git a/src/Umbraco.Core/Composing/Current.cs b/src/Umbraco.Core/Composing/Current.cs index cf67409925..4bed76d86f 100644 --- a/src/Umbraco.Core/Composing/Current.cs +++ b/src/Umbraco.Core/Composing/Current.cs @@ -5,6 +5,7 @@ using Umbraco.Core.Dictionary; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models.PublishedContent; +using Umbraco.Core.Packaging; using Umbraco.Core.Persistence; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Scoping; @@ -161,6 +162,9 @@ namespace Umbraco.Core.Composing internal static PackageActionCollection PackageActions => Factory.GetInstance(); + internal static PackageActionRunner PackageActionRunner + => Factory.GetInstance(); + internal static PropertyValueConverterCollection PropertyValueConverters => Factory.GetInstance(); diff --git a/src/Umbraco.Core/ContentExtensions.cs b/src/Umbraco.Core/ContentExtensions.cs index 5e2d44c90d..8c27c23604 100644 --- a/src/Umbraco.Core/ContentExtensions.cs +++ b/src/Umbraco.Core/ContentExtensions.cs @@ -308,84 +308,45 @@ namespace Umbraco.Core /// Creates the full xml representation for the object and all of it's descendants /// /// to generate xml for - /// + /// /// Xml representation of the passed in - internal static XElement ToDeepXml(this IContent content, IPackagingService packagingService) + internal static XElement ToDeepXml(this IContent content, IEntityXmlSerializer serializer) { - return packagingService.Export(content, true, raiseEvents: false); - } - - - [Obsolete("Use the overload that declares the IPackagingService to use")] - public static XElement ToXml(this IContent content) - { - return Current.Services.PackagingService.Export(content, raiseEvents: false); + return serializer.Serialize(content, false, true); } /// /// Creates the xml representation for the object /// /// to generate xml for - /// + /// /// Xml representation of the passed in - public static XElement ToXml(this IContent content, IPackagingService packagingService) + public static XElement ToXml(this IContent content, IEntityXmlSerializer serializer) { - return packagingService.Export(content, raiseEvents: false); - } - - [Obsolete("Use the overload that declares the IPackagingService to use")] - public static XElement ToXml(this IMedia media) - { - return Current.Services.PackagingService.Export(media, raiseEvents: false); + return serializer.Serialize(content, false, false); } + /// /// Creates the xml representation for the object /// /// to generate xml for - /// + /// /// Xml representation of the passed in - public static XElement ToXml(this IMedia media, IPackagingService packagingService) + public static XElement ToXml(this IMedia media, IEntityXmlSerializer serializer) { - return packagingService.Export(media, raiseEvents: false); + return serializer.Serialize(media); } - /// - /// Creates the full xml representation for the object and all of it's descendants - /// - /// to generate xml for - /// - /// Xml representation of the passed in - internal static XElement ToDeepXml(this IMedia media, IPackagingService packagingService) - { - return packagingService.Export(media, true, raiseEvents: false); - } - - - /// - /// Creates the xml representation for the object - /// - /// to generate xml for - /// - /// Boolean indicating whether the xml should be generated for preview - /// Xml representation of the passed in - public static XElement ToXml(this IContent content, IPackagingService packagingService, bool isPreview) - { - //TODO Do a proper implementation of this - //If current IContent is published we should get latest unpublished version - return content.ToXml(packagingService); - } - - /// /// Creates the xml representation for the object /// /// to generate xml for - /// + /// /// Xml representation of the passed in - public static XElement ToXml(this IMember member, IPackagingService packagingService) + public static XElement ToXml(this IMember member, IEntityXmlSerializer serializer) { - return ((PackagingService)(packagingService)).Export(member); + return serializer.Serialize(member); } #endregion diff --git a/src/Umbraco.Core/Events/ExportEventArgs.cs b/src/Umbraco.Core/Events/ExportEventArgs.cs deleted file mode 100644 index f46cccf05c..0000000000 --- a/src/Umbraco.Core/Events/ExportEventArgs.cs +++ /dev/null @@ -1,86 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Xml.Linq; - -namespace Umbraco.Core.Events -{ - public class ExportEventArgs : CancellableObjectEventArgs>, IEquatable> - { - /// - /// Constructor accepting a single entity instance - /// - /// - /// - /// - public ExportEventArgs(TEntity eventObject, XElement xml, bool canCancel) - : base(new List { eventObject }, canCancel) - { - Xml = xml; - } - - /// - /// Constructor accepting a single entity instance - /// and cancellable by default - /// - /// - /// - public ExportEventArgs(TEntity eventObject, string elementName) : base(new List {eventObject}, true) - { - Xml = new XElement(elementName); - } - - protected ExportEventArgs(IEnumerable eventObject, bool canCancel) : base(eventObject, canCancel) - { - } - - protected ExportEventArgs(IEnumerable eventObject) : base(eventObject) - { - } - - /// - /// Returns all entities that were exported during the operation - /// - public IEnumerable ExportedEntities - { - get { return EventObject; } - } - - /// - /// Returns the xml relating to the export event - /// - public XElement Xml { get; private set; } - - public bool Equals(ExportEventArgs other) - { - if (ReferenceEquals(null, other)) return false; - if (ReferenceEquals(this, other)) return true; - return base.Equals(other) && Equals(Xml, other.Xml); - } - - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) return false; - return Equals((ExportEventArgs) obj); - } - - public override int GetHashCode() - { - unchecked - { - return (base.GetHashCode() * 397) ^ (Xml != null ? Xml.GetHashCode() : 0); - } - } - - public static bool operator ==(ExportEventArgs left, ExportEventArgs right) - { - return Equals(left, right); - } - - public static bool operator !=(ExportEventArgs left, ExportEventArgs right) - { - return !Equals(left, right); - } - } -} diff --git a/src/Umbraco.Core/Models/Packaging/ActionRunAt.cs b/src/Umbraco.Core/Models/Packaging/ActionRunAt.cs new file mode 100644 index 0000000000..0023d4dbed --- /dev/null +++ b/src/Umbraco.Core/Models/Packaging/ActionRunAt.cs @@ -0,0 +1,9 @@ +namespace Umbraco.Core.Models.Packaging +{ + public enum ActionRunAt + { + Undefined = 0, + Install, + Uninstall + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Packaging/InstallationSummary.cs b/src/Umbraco.Core/Models/Packaging/InstallationSummary.cs index 3eb397d728..39df529300 100644 --- a/src/Umbraco.Core/Models/Packaging/InstallationSummary.cs +++ b/src/Umbraco.Core/Models/Packaging/InstallationSummary.cs @@ -21,23 +21,4 @@ namespace Umbraco.Core.Models.Packaging public IEnumerable Actions { get; set; } public bool PackageInstalled { get; set; } } - - internal static class InstallationSummaryExtentions - { - public static InstallationSummary InitEmpty(this InstallationSummary summary) - { - summary.Actions = new List(); - summary.ContentInstalled = new List(); - summary.ContentTypesInstalled = new List(); - summary.DataTypesInstalled = new List(); - summary.DictionaryItemsInstalled = new List(); - summary.FilesInstalled = new List(); - summary.LanguagesInstalled = new List(); - summary.MacrosInstalled = new List(); - summary.MetaData = new MetaData(); - summary.TemplatesInstalled = new List(); - summary.PackageInstalled = false; - return summary; - } - } } diff --git a/src/Umbraco.Core/Models/Packaging/InstallationSummaryExtentions.cs b/src/Umbraco.Core/Models/Packaging/InstallationSummaryExtentions.cs new file mode 100644 index 0000000000..3b969d84dc --- /dev/null +++ b/src/Umbraco.Core/Models/Packaging/InstallationSummaryExtentions.cs @@ -0,0 +1,23 @@ +using System.Collections.Generic; + +namespace Umbraco.Core.Models.Packaging +{ + internal static class InstallationSummaryExtentions + { + public static InstallationSummary InitEmpty(this InstallationSummary summary) + { + summary.Actions = new List(); + summary.ContentInstalled = new List(); + summary.ContentTypesInstalled = new List(); + summary.DataTypesInstalled = new List(); + summary.DictionaryItemsInstalled = new List(); + summary.FilesInstalled = new List(); + summary.LanguagesInstalled = new List(); + summary.MacrosInstalled = new List(); + summary.MetaData = new MetaData(); + summary.TemplatesInstalled = new List(); + summary.PackageInstalled = false; + return summary; + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Packaging/PackageAction.cs b/src/Umbraco.Core/Models/Packaging/PackageAction.cs index e941c5729a..ab7b120eae 100644 --- a/src/Umbraco.Core/Models/Packaging/PackageAction.cs +++ b/src/Umbraco.Core/Models/Packaging/PackageAction.cs @@ -4,13 +4,9 @@ using System.Xml.Linq; namespace Umbraco.Core.Models.Packaging { - public enum ActionRunAt - { - Undefined = 0, - Install, - Uninstall - } - + /// + /// Defines a package action declared within a package manifest + /// [Serializable] [DataContract(IsReference = true)] public class PackageAction diff --git a/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs b/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs new file mode 100644 index 0000000000..783b11235f --- /dev/null +++ b/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs @@ -0,0 +1,108 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Runtime.Serialization; + +namespace Umbraco.Core.Models.Packaging +{ + [DataContract(Name = "packageInstance")] + public class PackageDefinition + { + [DataMember(Name = "id")] + public int Id { get; set; } + + //TODO: I don't see why this is necessary + [DataMember(Name = "repositoryGuid")] + public string RepositoryGuid { get; set; } + + [DataMember(Name = "packageGuid")] + public string PackageGuid { get; set; } + + [DataMember(Name = "hasUpdate")] + public bool HasUpdate { get; set; } + + [DataMember(Name = "name")] + [Required] + public string Name { get; set; } = string.Empty; + + [DataMember(Name = "url")] + [Required] + [Url] + public string Url { get; set; } = string.Empty; + + [DataMember(Name = "folder")] + public string Folder { get; set; } = string.Empty; + + [DataMember(Name = "packagePath")] + public string PackagePath { get; set; } = string.Empty; + + [DataMember(Name = "version")] + [Required] + public string Version { get; set; } = string.Empty; + + /// + /// The minimum umbraco version that this package requires + /// + [DataMember(Name = "umbracoVersion")] + public Version UmbracoVersion { get; set; } + + [DataMember(Name = "author")] + [Required] + public string Author { get; set; } = string.Empty; + + [DataMember(Name = "authorUrl")] + [Required] + [Url] + public string AuthorUrl { get; set; } = string.Empty; + + [DataMember(Name = "license")] + public string License { get; set; } = "MIT License"; + + [DataMember(Name = "licenseUrl")] + public string LicenseUrl { get; set; } = "http://opensource.org/licenses/MIT"; + + [DataMember(Name = "readme")] + public string Readme { get; set; } = string.Empty; + + [DataMember(Name = "contentLoadChildNodes")] + public bool ContentLoadChildNodes { get; set; } = false; + + [DataMember(Name = "contentNodeId")] + public string ContentNodeId { get; set; } = string.Empty; + + [DataMember(Name = "macros")] + public List Macros { get; set; } = new List(); + + [DataMember(Name = "languages")] + public List Languages { get; set; } = new List(); + + [DataMember(Name = "dictionaryItems")] + public List DictionaryItems { get; set; } = new List(); + + [DataMember(Name = "templates")] + public List Templates { get; set; } = new List(); + + [DataMember(Name = "documentTypes")] + public List DocumentTypes { get; set; } = new List(); + + [DataMember(Name = "stylesheets")] + public List Stylesheets { get; set; } = new List(); + + [DataMember(Name = "files")] + public List Files { get; set; } = new List(); + + //TODO: Change this to angular view + [DataMember(Name = "loadControl")] + public string LoadControl { get; set; } = string.Empty; + + [DataMember(Name = "actions")] + public string Actions { get; set; } + + [DataMember(Name = "dataTypes")] + public List DataTypes { get; set; } = new List(); + + [DataMember(Name = "iconUrl")] + public string IconUrl { get; set; } = string.Empty; + + } +} diff --git a/src/Umbraco.Core/Packaging/Models/UninstallationSummary.cs b/src/Umbraco.Core/Models/Packaging/UninstallationSummary.cs similarity index 50% rename from src/Umbraco.Core/Packaging/Models/UninstallationSummary.cs rename to src/Umbraco.Core/Models/Packaging/UninstallationSummary.cs index 1c31283ee8..cfa454f91c 100644 --- a/src/Umbraco.Core/Packaging/Models/UninstallationSummary.cs +++ b/src/Umbraco.Core/Models/Packaging/UninstallationSummary.cs @@ -1,10 +1,8 @@ using System; using System.Collections.Generic; using System.Runtime.Serialization; -using Umbraco.Core.Models; -using Umbraco.Core.Models.Packaging; -namespace Umbraco.Core.Packaging.Models +namespace Umbraco.Core.Models.Packaging { [Serializable] [DataContract(IsReference = true)] @@ -22,22 +20,4 @@ namespace Umbraco.Core.Packaging.Models public IEnumerable ContentUninstalled { get; set; } public bool PackageUninstalled { get; set; } } - - internal static class UninstallationSummaryExtentions - { - public static UninstallationSummary InitEmpty(this UninstallationSummary summary) - { - summary.ContentUninstalled = new List(); - summary.ContentTypesUninstalled = new List(); - summary.DataTypesUninstalled = new List(); - summary.DictionaryItemsUninstalled = new List(); - summary.FilesUninstalled = new List(); - summary.LanguagesUninstalled = new List(); - summary.MacrosUninstalled = new List(); - summary.MetaData = new MetaData(); - summary.TemplatesUninstalled = new List(); - summary.PackageUninstalled = false; - return summary; - } - } } diff --git a/src/Umbraco.Core/Models/Packaging/UninstallationSummaryExtentions.cs b/src/Umbraco.Core/Models/Packaging/UninstallationSummaryExtentions.cs new file mode 100644 index 0000000000..688b78fa1f --- /dev/null +++ b/src/Umbraco.Core/Models/Packaging/UninstallationSummaryExtentions.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; + +namespace Umbraco.Core.Models.Packaging +{ + internal static class UninstallationSummaryExtentions + { + public static UninstallationSummary InitEmpty(this UninstallationSummary summary) + { + summary.ContentUninstalled = new List(); + summary.ContentTypesUninstalled = new List(); + summary.DataTypesUninstalled = new List(); + summary.DictionaryItemsUninstalled = new List(); + summary.FilesUninstalled = new List(); + summary.LanguagesUninstalled = new List(); + summary.MacrosUninstalled = new List(); + summary.MetaData = new MetaData(); + summary.TemplatesUninstalled = new List(); + summary.PackageUninstalled = false; + return summary; + } + } +} diff --git a/src/Umbraco.Core/Packaging/IPackageCreation.cs b/src/Umbraco.Core/Packaging/IPackageCreation.cs new file mode 100644 index 0000000000..35397299a7 --- /dev/null +++ b/src/Umbraco.Core/Packaging/IPackageCreation.cs @@ -0,0 +1,22 @@ +using Umbraco.Core.Models.Packaging; + +namespace Umbraco.Core.Packaging +{ + /// + /// Creates packages + /// + public interface IPackageCreation + { + /// + /// Persists a package definition to storage + /// + /// + void SavePackageDefinition(PackageDefinition definition); + + /// + /// Creates the package file and returns it's physical path + /// + /// + string ExportPackageDefinition(PackageDefinition definition); + } +} diff --git a/src/Umbraco.Core/Packaging/IPackageInstallation.cs b/src/Umbraco.Core/Packaging/IPackageInstallation.cs index 1d0d46355c..6dc4f0fd4e 100644 --- a/src/Umbraco.Core/Packaging/IPackageInstallation.cs +++ b/src/Umbraco.Core/Packaging/IPackageInstallation.cs @@ -5,6 +5,9 @@ namespace Umbraco.Core.Packaging { internal interface IPackageInstallation { + //fixme: The reason why this isn't used currently is because package installation needs to be done in phases since + // there are app domain reboots involved so a single method cannot be used. This needs to either be split into several + // methods or return an object with a callback to proceed to the next step. InstallationSummary InstallPackage(string packageFilePath, int userId); MetaData GetMetaData(string packageFilePath); PreInstallWarnings GetPreInstallWarnings(string packageFilePath); diff --git a/src/Umbraco.Web/_Legacy/Packager/PackageInstance/PackageActions.cs b/src/Umbraco.Core/Packaging/PackageActionRunner.cs similarity index 58% rename from src/Umbraco.Web/_Legacy/Packager/PackageInstance/PackageActions.cs rename to src/Umbraco.Core/Packaging/PackageActionRunner.cs index bfd1030d85..c7545bdae8 100644 --- a/src/Umbraco.Web/_Legacy/Packager/PackageInstance/PackageActions.cs +++ b/src/Umbraco.Core/Packaging/PackageActionRunner.cs @@ -1,17 +1,24 @@ using System; using System.Xml; -using Umbraco.Core.Composing; using Umbraco.Core.Logging; using Umbraco.Core._Legacy.PackageActions; -namespace Umbraco.Web._Legacy.Packager.PackageInstance +namespace Umbraco.Core.Packaging { /// /// Package actions are executed on packge install / uninstall. /// - public class PackageAction + public sealed class PackageActionRunner { + private readonly ILogger _logger; + private readonly PackageActionCollection _packageActions; + + public PackageActionRunner(ILogger logger, PackageActionCollection packageActions) + { + _logger = logger; + _packageActions = packageActions; + } /// /// Runs the package action with the specified action alias. @@ -19,22 +26,19 @@ namespace Umbraco.Web._Legacy.Packager.PackageInstance /// Name of the package. /// The action alias. /// The action XML. - public static void RunPackageAction(string packageName, string actionAlias, XmlNode actionXml) + public void RunPackageAction(string packageName, string actionAlias, XmlNode actionXml) { - foreach (var ipa in Current.PackageActions) + foreach (var ipa in _packageActions) { try { if (ipa.Alias() == actionAlias) - { - ipa.Execute(packageName, actionXml); - } } catch (Exception ex) { - Current.Logger.Error(ex, "Error loading package action '{PackageActionAlias}' for package {PackageName}", ipa.Alias(), packageName); + _logger.Error(ex, "Error loading package action '{PackageActionAlias}' for package {PackageName}", ipa.Alias(), packageName); } } } @@ -45,22 +49,18 @@ namespace Umbraco.Web._Legacy.Packager.PackageInstance /// Name of the package. /// The action alias. /// The action XML. - public static void UndoPackageAction(string packageName, string actionAlias, System.Xml.XmlNode actionXml) + public void UndoPackageAction(string packageName, string actionAlias, System.Xml.XmlNode actionXml) { - - foreach (IPackageAction ipa in Current.PackageActions) + foreach (var ipa in _packageActions) { try { if (ipa.Alias() == actionAlias) - { - ipa.Undo(packageName, actionXml); - } } catch (Exception ex) { - Current.Logger.Error(ex, "Error undoing package action '{PackageActionAlias}' for package {PackageName}", ipa.Alias(), packageName); + _logger.Error(ex, "Error undoing package action '{PackageActionAlias}' for package {PackageName}", ipa.Alias(), packageName); } } } diff --git a/src/Umbraco.Core/Packaging/PackageCreation.cs b/src/Umbraco.Core/Packaging/PackageCreation.cs new file mode 100644 index 0000000000..615b844101 --- /dev/null +++ b/src/Umbraco.Core/Packaging/PackageCreation.cs @@ -0,0 +1,564 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Xml.Linq; +using Umbraco.Core.Configuration; +using Umbraco.Core.IO; +using Umbraco.Core.Logging; +using Umbraco.Core.Models; +using Umbraco.Core.Models.Packaging; +using Umbraco.Core.Services; +using File = System.IO.File; + +namespace Umbraco.Core.Packaging +{ + internal class PackageCreation : IPackageCreation + { + private readonly IContentService _contentService; + private readonly IContentTypeService _contentTypeService; + private readonly IDataTypeService _dataTypeService; + private readonly IFileService _fileService; + private readonly IMacroService _macroService; + private readonly ILocalizationService _languageService; + private readonly IEntityXmlSerializer _serializer; + private readonly ILogger _logger; + + public PackageCreation(IContentService contentService, IContentTypeService contentTypeService, + IDataTypeService dataTypeService, IFileService fileService, IMacroService macroService, + ILocalizationService languageService, + IEntityXmlSerializer serializer, ILogger logger) + { + _contentService = contentService; + _contentTypeService = contentTypeService; + _dataTypeService = dataTypeService; + _fileService = fileService; + _macroService = macroService; + _languageService = languageService; + _serializer = serializer; + _logger = logger; + } + + public static string CreatedPackagesFile => SystemDirectories.Packages + IOHelper.DirSepChar + "createdPackages.config"; + + public void SavePackageDefinition(PackageDefinition definition) + { + if (definition == null) throw new ArgumentNullException(nameof(definition)); + + var packagesXml = EnsureStorage(out var packagesFile); + + if (definition.Id == default) + { + //need to gen an id and persist + // Find max id + var maxId = packagesXml.Root.Elements("package").Max(x => x.AttributeValue("id")); + var newId = maxId + 1; + definition.Id = newId; + definition.PackageGuid = Guid.NewGuid().ToString(); + definition.Folder = Guid.NewGuid().ToString(); + var packageXml = PackageDefinitionToXml(definition); + packagesXml.Add(packageXml); + } + else + { + //existing + var packageXml = packagesXml.Root.Elements("package").FirstOrDefault(x => x.AttributeValue("id") == definition.Id); + if (packageXml == null) + throw new InvalidOperationException($"The package with id {definition.Id} was not found"); + + var updatedXml = PackageDefinitionToXml(definition); + packageXml.ReplaceWith(updatedXml); + } + + packagesXml.Save(packagesFile); + } + + public string ExportPackageDefinition(PackageDefinition definition) + { + if (definition.Id == default) throw new ArgumentException("The package definition does not have an ID, it must be saved before being exported"); + if (definition.PackageGuid.IsNullOrWhiteSpace()) throw new ArgumentException("the package definition does not have a GUID, it must be saved before being exported"); + + //Create a folder for building this package + var temporaryPath = IOHelper.MapPath(SystemDirectories.Data + "/TEMP/PackageFiles/" + definition.Folder); + if (Directory.Exists(temporaryPath) == false) + Directory.CreateDirectory(temporaryPath); + + try + { + //Init package file + var packageManifest = CreatePackageManifest(out var manifestRoot, out var filesXml); + + //Info section + packageManifest.Add(GetPackageInfoXml(definition)); + + PackageDocumentsAndTags(definition, manifestRoot); + PackageDocumentTypes(definition, manifestRoot); + PackageTemplates(definition, manifestRoot); + PackageStylesheets(definition, manifestRoot); + PackageMacros(definition, manifestRoot, filesXml, temporaryPath); + PackageDictionaryItems(definition, manifestRoot); + PackageLanguages(definition, manifestRoot); + PackageDataTypes(definition, manifestRoot); + + //Files + foreach (var fileName in definition.Files) + AppendFileToManifest(fileName, temporaryPath, filesXml); + + //Load control on install... + if (!string.IsNullOrEmpty(definition.LoadControl)) + { + var control = new XElement("control", definition.LoadControl); + AppendFileToManifest(definition.LoadControl, temporaryPath, filesXml); + manifestRoot.Add(control); + } + + //Actions + if (string.IsNullOrEmpty(definition.Actions) == false) + { + var actionsXml = new XElement("Actions"); + try + { + actionsXml.Add(XElement.Parse(definition.Actions)); + manifestRoot.Add(actionsXml); + } + catch (Exception e) + { + _logger.Warn(e, "Could not add package actions to the package manifest, the xml did not parse"); + } + } + + var manifestFileName = temporaryPath + "/package.xml"; + + if (File.Exists(manifestFileName)) + File.Delete(manifestFileName); + + packageManifest.Save(manifestFileName); + + // check if there's a packages directory below media + var packagesDirectory = SystemDirectories.Media + "/created-packages"; + if (Directory.Exists(IOHelper.MapPath(packagesDirectory)) == false) + Directory.CreateDirectory(IOHelper.MapPath(packagesDirectory)); + + var packPath = packagesDirectory + "/" + (definition.Name + "_" + definition.Version).Replace(' ', '_') + ".zip"; + ZipPackage(temporaryPath, IOHelper.MapPath(packPath)); + + return packPath; + } + finally + { + //Clean up + Directory.Delete(temporaryPath, true); + } + } + + private void PackageDataTypes(PackageDefinition definition, XContainer manifestRoot) + { + var dataTypes = new XElement("DataTypes"); + foreach (var dtId in definition.DataTypes) + { + if (!int.TryParse(dtId, out var outInt)) continue; + var dataType = _dataTypeService.GetDataType(outInt); + if (dataType == null) continue; + dataTypes.Add(_serializer.Serialize(dataType)); + } + manifestRoot.Add(dataTypes); + } + + private void PackageLanguages(PackageDefinition definition, XContainer manifestRoot) + { + var languages = new XElement("Languages"); + foreach (var langId in definition.Languages) + { + if (!int.TryParse(langId, out var outInt)) continue; + var lang = _languageService.GetLanguageById(outInt); + if (lang == null) continue; + languages.Add(_serializer.Serialize(lang)); + } + manifestRoot.Add(languages); + } + + private void PackageDictionaryItems(PackageDefinition definition, XContainer manifestRoot) + { + var dictionaryItems = new XElement("DictionaryItems"); + foreach (var dictionaryId in definition.DictionaryItems) + { + if (!int.TryParse(dictionaryId, out var outInt)) continue; + var di = _languageService.GetDictionaryItemById(outInt); + if (di == null) continue; + dictionaryItems.Add(_serializer.Serialize(di, false)); + } + manifestRoot.Add(dictionaryItems); + } + + private void PackageMacros(PackageDefinition definition, XContainer manifestRoot, XContainer filesXml, string temporaryPath) + { + var macros = new XElement("Macros"); + foreach (var macroId in definition.Macros) + { + if (!int.TryParse(macroId, out var outInt)) continue; + + var macroXml = GetMacroXml(outInt, out var macro); + if (macroXml == null) continue; + macros.Add(macroXml); + //if the macro has a file copy it to the manifest + if (!string.IsNullOrEmpty(macro.MacroSource)) + AppendFileToManifest(macro.MacroSource, temporaryPath, filesXml); + } + manifestRoot.Add(macros); + } + + private void PackageStylesheets(PackageDefinition definition, XContainer manifestRoot) + { + var stylesheetsXml = new XElement("Stylesheets"); + foreach (var stylesheetName in definition.Stylesheets) + { + if (stylesheetName.IsNullOrWhiteSpace()) continue; + var xml = GetStylesheetXml(stylesheetName, true); + if (xml != null) + stylesheetsXml.Add(xml); + } + manifestRoot.Add(stylesheetsXml); + } + + private void PackageTemplates(PackageDefinition definition, XContainer manifestRoot) + { + var templatesXml = new XElement("Templates"); + foreach (var templateId in definition.Templates) + { + if (!int.TryParse(templateId, out var outInt)) continue; + var template = _fileService.GetTemplate(outInt); + if (template == null) continue; + templatesXml.Add(_serializer.Serialize(template)); + } + manifestRoot.Add(templatesXml); + } + + private void PackageDocumentTypes(PackageDefinition definition, XContainer manifestRoot) + { + var contentTypes = new HashSet(); + var docTypesXml = new XElement("DocumentTypes"); + foreach (var dtId in definition.DocumentTypes) + { + if (!int.TryParse(dtId, out var outInt)) continue; + var contentType = _contentTypeService.Get(outInt); + if (contentType == null) continue; + AddDocumentType(contentType, contentTypes); + } + foreach (var contentType in contentTypes) + docTypesXml.Add(_serializer.Serialize(contentType)); + + manifestRoot.Add(docTypesXml); + } + + private void PackageDocumentsAndTags(PackageDefinition definition, XContainer manifestRoot) + { + //Documents and tags + if (string.IsNullOrEmpty(definition.ContentNodeId) == false && int.TryParse(definition.ContentNodeId, out var contentNodeId)) + { + if (contentNodeId > 0) + { + //load content from umbraco. + var content = _contentService.GetById(contentNodeId); + if (content != null) + { + var contentXml = definition.ContentLoadChildNodes ? content.ToDeepXml(_serializer) : content.ToXml(_serializer); + + //Create the Documents/DocumentSet node + + manifestRoot.Add( + new XElement("Documents", + new XElement("DocumentSet", + new XAttribute("importMode", "root"), + contentXml))); + + //TODO: I guess tags has been broken for a very long time for packaging, we should get this working again sometime + ////Create the TagProperties node - this is used to store a definition for all + //// document properties that are tags, this ensures that we can re-import tags properly + //XmlNode tagProps = new XElement("TagProperties"); + + ////before we try to populate this, we'll do a quick lookup to see if any of the documents + //// being exported contain published tags. + //var allExportedIds = documents.SelectNodes("//@id").Cast() + // .Select(x => x.Value.TryConvertTo()) + // .Where(x => x.Success) + // .Select(x => x.Result) + // .ToArray(); + //var allContentTags = new List(); + //foreach (var exportedId in allExportedIds) + //{ + // allContentTags.AddRange( + // Current.Services.TagService.GetTagsForEntity(exportedId)); + //} + + ////This is pretty round-about but it works. Essentially we need to get the properties that are tagged + //// but to do that we need to lookup by a tag (string) + //var allTaggedEntities = new List(); + //foreach (var group in allContentTags.Select(x => x.Group).Distinct()) + //{ + // allTaggedEntities.AddRange( + // Current.Services.TagService.GetTaggedContentByTagGroup(group)); + //} + + ////Now, we have all property Ids/Aliases and their referenced document Ids and tags + //var allExportedTaggedEntities = allTaggedEntities.Where(x => allExportedIds.Contains(x.EntityId)) + // .DistinctBy(x => x.EntityId) + // .OrderBy(x => x.EntityId); + + //foreach (var taggedEntity in allExportedTaggedEntities) + //{ + // foreach (var taggedProperty in taggedEntity.TaggedProperties.Where(x => x.Tags.Any())) + // { + // XmlNode tagProp = new XElement("TagProperty"); + // var docId = packageManifest.CreateAttribute("docId", ""); + // docId.Value = taggedEntity.EntityId.ToString(CultureInfo.InvariantCulture); + // tagProp.Attributes.Append(docId); + + // var propertyAlias = packageManifest.CreateAttribute("propertyAlias", ""); + // propertyAlias.Value = taggedProperty.PropertyTypeAlias; + // tagProp.Attributes.Append(propertyAlias); + + // var group = packageManifest.CreateAttribute("group", ""); + // group.Value = taggedProperty.Tags.First().Group; + // tagProp.Attributes.Append(group); + + // tagProp.AppendChild(packageManifest.CreateCDataSection( + // JsonConvert.SerializeObject(taggedProperty.Tags.Select(x => x.Text).ToArray()))); + + // tagProps.AppendChild(tagProp); + // } + //} + + //manifestRoot.Add(tagProps); + } + } + } + } + + /// + /// Zips the package. + /// + /// The path. + /// The save path. + private static void ZipPackage(string path, string savePath) + { + ZipFile.CreateFromDirectory(path, savePath); + } + + /// + /// Appends a file to package manifest and copies the file to the correct folder. + /// + /// The path. + /// The package directory. + /// The files xml node + private static void AppendFileToManifest(string path, string packageDirectory, XContainer filesXml) + { + if (!path.StartsWith("~/") && !path.StartsWith("/")) + path = "~/" + path; + + var serverPath = IOHelper.MapPath(path); + + if (File.Exists(serverPath)) + AppendFileXml(new FileInfo(serverPath), path, packageDirectory, filesXml); + else if (Directory.Exists(serverPath)) + ProcessDirectory(new DirectoryInfo(serverPath), path, packageDirectory, filesXml); + } + + //Process files in directory and add them to package + private static void ProcessDirectory(DirectoryInfo directory, string dirPath, string packageDirectory, XContainer filesXml) + { + if (directory == null) throw new ArgumentNullException(nameof(directory)); + if (string.IsNullOrWhiteSpace(packageDirectory)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(packageDirectory)); + if (string.IsNullOrWhiteSpace(dirPath)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(dirPath)); + if (!directory.Exists) return; + + foreach (var file in directory.GetFiles()) + AppendFileXml(new FileInfo(Path.Combine(directory.FullName, file.Name)), dirPath + "/" + file.Name, packageDirectory, filesXml); + + foreach (var dir in directory.GetDirectories()) + ProcessDirectory(dir, dirPath + "/" + dir.Name, packageDirectory, filesXml); + } + + private static void AppendFileXml(FileInfo file, string filePath, string packageDirectory, XContainer filesXml) + { + if (file == null) throw new ArgumentNullException(nameof(file)); + if (string.IsNullOrWhiteSpace(filePath)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(filePath)); + if (string.IsNullOrWhiteSpace(packageDirectory)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(packageDirectory)); + + var orgPath = filePath.Substring(0, (filePath.LastIndexOf('/'))); + var orgName = filePath.Substring((filePath.LastIndexOf('/') + 1)); + var newFileName = orgName; + + if (File.Exists(packageDirectory.EnsureEndsWith('/') + orgName)) + newFileName = Guid.NewGuid() + "_" + newFileName; + + //Copy file to directory for zipping... + File.Copy(file.FullName, packageDirectory + "/" + newFileName, true); + + filesXml.Add(new XElement("file", + new XElement("guid", newFileName), + new XElement("orgPath", orgPath == "" ? "/" : orgPath), + new XElement("orgName", orgName))); + } + + private XElement GetMacroXml(int macroId, out IMacro macro) + { + macro = _macroService.GetById(macroId); + if (macro == null) return null; + var xml = _serializer.Serialize(macro); + return xml; + } + + /// + /// Converts a umbraco stylesheet to a package xml node + /// + /// The name of the stylesheet. + /// if set to true [incluce properties]. + /// + private XElement GetStylesheetXml(string name, bool includeProperties) + { + if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(name)); +; + var sts = _fileService.GetStylesheetByName(name); + if (sts == null) return null; + var stylesheetXml = new XElement("Stylesheet"); + stylesheetXml.Add(new XElement("Name", sts.Alias)); + stylesheetXml.Add(new XElement("FileName", sts.Name)); + stylesheetXml.Add(new XElement("Content", new XCData(sts.Content))); + + if (!includeProperties) return stylesheetXml; + + var properties = new XElement("Properties"); + foreach (var ssP in sts.Properties) + { + var property = new XElement("Property"); + property.Add(new XElement("Name", ssP.Name)); + property.Add(new XElement("Alias", ssP.Alias)); + property.Add(new XElement("Value", ssP.Value)); + } + stylesheetXml.Add(properties); + return stylesheetXml; + } + + private void AddDocumentType(IContentType dt, HashSet dtl) + { + if (dt.ParentId > 0) + { + var parent = _contentTypeService.Get(dt.ParentId); + if (parent != null) // could be a container + AddDocumentType(parent, dtl); + } + + if (!dtl.Contains(dt)) + dtl.Add(dt); + } + + private static XElement GetPackageInfoXml(PackageDefinition definition) + { + var info = new XElement("info"); + + //Package info + var package = new XElement("package"); + package.Add(new XElement("name", definition.Name)); + package.Add(new XElement("version", definition.Version)); + package.Add(new XElement("iconUrl", definition.IconUrl)); + + var license = new XElement("license", definition.License); + license.Add(new XAttribute("url", definition.LicenseUrl)); + package.Add(license); + + package.Add(new XElement("url", definition.Url)); + + 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())); + + if (definition.UmbracoVersion != null) + requirements.Add(new XAttribute("type", "strict")); + + package.Add(requirements); + info.Add(package); + + //Author + var author = new XElement("author", ""); + author.Add(new XElement("name", definition.Author)); + author.Add(new XElement("website", definition.AuthorUrl)); + info.Add(author); + + info.Add(new XElement("readme", new XCData(definition.Readme))); + + return info; + } + + private static XDocument CreatePackageManifest(out XElement root, out XElement files) + { + files = new XElement("files"); + root = new XElement("umbPackage", files); + var packageManifest = new XDocument(); + return packageManifest; + } + + private static XDocument EnsureStorage(out string packagesFile) + { + var packagesFolder = IOHelper.MapPath(SystemDirectories.Packages); + //ensure it exists + Directory.CreateDirectory(packagesFolder); + + packagesFile = IOHelper.MapPath(CreatedPackagesFile); + if (!File.Exists(packagesFile)) + { + var xml = new XDocument(new XElement("packages")); + xml.Save(packagesFile); + } + + var packagesXml = XDocument.Load(packagesFile); + return packagesXml; + } + + private static XElement PackageDefinitionToXml(PackageDefinition def) + { + var packageXml = new XElement("package", + new XAttribute("id", def.Id), + new XAttribute("version", def.Version), + new XAttribute("url", def.Url), + new XAttribute("name", def.Name), + new XAttribute("folder", def.Folder), //fixme: What is this? + new XAttribute("packagepath", def.PackagePath), + new XAttribute("repositoryGuid", def.RepositoryGuid), + new XAttribute("iconUrl", def.IconUrl), + new XAttribute("umbVersion", def.UmbracoVersion), + new XAttribute("packageGuid", def.PackageGuid), + new XAttribute("hasUpdate", def.HasUpdate), //fixme: What is this? + + new XElement("license", + new XCData(def.License), + new XAttribute("url", def.LicenseUrl)), + + new XElement("author", + new XCData(def.Author), + new XAttribute("url", def.AuthorUrl)), + + new XElement("readme", def.Readme), + new XElement("actions", def.Actions), + new XElement("datatypes", string.Join(",", def.DataTypes)), + + new XElement("content", + new XAttribute("nodeId", def.ContentNodeId), + new XAttribute("loadChildNodes", def.ContentLoadChildNodes)), + + new XElement("templates", string.Join(",", def.Templates)), + new XElement("stylesheets", string.Join(",", def.Stylesheets)), + new XElement("documentTypes", string.Join(",", def.DocumentTypes)), + new XElement("macros", string.Join(",", def.Macros)), + new XElement("files", string.Join(",", def.Files)), + new XElement("languages", string.Join(",", def.Languages)), + new XElement("dictionaryitems", string.Join(",", def.DictionaryItems)), + new XElement("loadcontrol", "")); //fixme: no more loadcontrol, needs to be an angular view + + return packageXml; + } + + } +} diff --git a/src/Umbraco.Core/Services/IEntityXmlSerializer.cs b/src/Umbraco.Core/Services/IEntityXmlSerializer.cs new file mode 100644 index 0000000000..405fc47c3a --- /dev/null +++ b/src/Umbraco.Core/Services/IEntityXmlSerializer.cs @@ -0,0 +1,88 @@ +using System.Collections.Generic; +using System.Xml.Linq; +using Umbraco.Core.Models; + +namespace Umbraco.Core.Services +{ + /// + /// Serializes entities to XML + /// + public interface IEntityXmlSerializer + { + /// + /// Exports an IContent item as an XElement. + /// + XElement Serialize(IContent content, + bool published, + bool withDescendants = false) //fixme take care of usage! only used for the packager + ; + + /// + /// Exports an IMedia item as an XElement. + /// + XElement Serialize( + IMedia media, + bool withDescendants = false); + + /// + /// Exports an IMember item as an XElement. + /// + XElement Serialize(IMember member); + + /// + /// Exports a list of Data Types + /// + /// List of data types to export + /// containing the xml representation of the IDataTypeDefinition objects + XElement Serialize(IEnumerable dataTypeDefinitions); + + XElement Serialize(IDataType dataType); + + /// + /// Exports a list of items to xml as an + /// + /// List of dictionary items to export + /// Optional boolean indicating whether or not to include children + /// containing the xml representation of the IDictionaryItem objects + XElement Serialize(IEnumerable dictionaryItem, bool includeChildren = true); + + /// + /// Exports a single item to xml as an + /// + /// Dictionary Item to export + /// Optional boolean indicating whether or not to include children + /// containing the xml representation of the IDictionaryItem object + XElement Serialize(IDictionaryItem dictionaryItem, bool includeChildren); + + XElement Serialize(Stylesheet stylesheet); + + /// + /// Exports a list of items to xml as an + /// + /// List of Languages to export + /// containing the xml representation of the ILanguage objects + XElement Serialize(IEnumerable languages); + + XElement Serialize(ILanguage language); + XElement Serialize(ITemplate template); + + /// + /// Exports a list of items to xml as an + /// + /// + /// + XElement Serialize(IEnumerable templates); + + XElement Serialize(IMediaType mediaType); + + /// + /// Exports a list of items to xml as an + /// + /// Macros to export + /// containing the xml representation of the IMacro objects + XElement Serialize(IEnumerable macros); + + XElement Serialize(IMacro macro); + XElement Serialize(IContentType contentType); + } +} diff --git a/src/Umbraco.Core/Services/IPackagingService.cs b/src/Umbraco.Core/Services/IPackagingService.cs index ceab6e94bf..585ea36aa9 100644 --- a/src/Umbraco.Core/Services/IPackagingService.cs +++ b/src/Umbraco.Core/Services/IPackagingService.cs @@ -2,11 +2,21 @@ using System.Collections.Generic; using System.Xml.Linq; using Umbraco.Core.Models; +using Umbraco.Core.Models.Packaging; +using Umbraco.Core.Packaging; namespace Umbraco.Core.Services { public interface IPackagingService : IService { + #region Package Creation + /// + /// Persists a package definition to storage + /// + /// + void SavePackageDefinition(PackageDefinition definition); + #endregion + /// /// Imports and saves package xml as /// @@ -80,114 +90,6 @@ namespace Umbraco.Core.Services /// An enumrable list of generated Templates IEnumerable ImportTemplates(XElement element, int userId = 0, bool raiseEvents = true); - /// - /// Exports an to xml as an - /// - /// ContentType to export - /// Optional parameter indicating whether or not to raise events - /// containing the xml representation of the ContentType item - XElement Export(IContentType contentType, bool raiseEvents = true); - - /// - /// Exports an item to xml as an - /// - /// Content to export - /// Optional parameter indicating whether to include descendents - /// Optional parameter indicating whether or not to raise events - /// containing the xml representation of the Content object - XElement Export(IContent content, bool deep = false, bool raiseEvents = true); - - /// - /// Exports an item to xml as an - /// - /// Media to export - /// Optional parameter indicating whether to include descendents - /// Optional parameter indicating whether or not to raise events - /// containing the xml representation of the Media object - XElement Export(IMedia media, bool deep = false, bool raiseEvents = true); - - /// - /// Exports a list of items to xml as an - /// - /// List of Languages to export - /// Optional parameter indicating whether or not to raise events - /// containing the xml representation of the Language object - XElement Export(IEnumerable languages, bool raiseEvents = true); - - /// - /// Exports a single item to xml as an - /// - /// Language to export - /// Optional parameter indicating whether or not to raise events - /// containing the xml representation of the Language object - XElement Export(ILanguage language, bool raiseEvents = true); - - /// - /// Exports a list of items to xml as an - /// - /// List of dictionary items to export - /// Optional boolean indicating whether or not to include children - /// Optional parameter indicating whether or not to raise events - /// containing the xml representation of the IDictionaryItem objects - XElement Export(IEnumerable dictionaryItem, bool includeChildren = true, bool raiseEvents = true); - - /// - /// Exports a single item to xml as an - /// - /// Dictionary Item to export - /// Optional boolean indicating whether or not to include children - /// Optional parameter indicating whether or not to raise events - /// containing the xml representation of the IDictionaryItem object - XElement Export(IDictionaryItem dictionaryItem, bool includeChildren, bool raiseEvents = true); - - /// - /// Exports a list of Data Types - /// - /// List of data types to export - /// Optional parameter indicating whether or not to raise events - /// containing the xml representation of the IDataTypeDefinition objects - XElement Export(IEnumerable dataTypeDefinitions, bool raiseEvents = true); - - /// - /// Exports a single Data Type - /// - /// Data type to export - /// Optional parameter indicating whether or not to raise events - /// containing the xml representation of the IDataTypeDefinition object - XElement Export(IDataType dataType, bool raiseEvents = true); - - /// - /// Exports a list of items to xml as an - /// - /// List of Templates to export - /// Optional parameter indicating whether or not to raise events - /// containing the xml representation of the ITemplate objects - XElement Export(IEnumerable templates, bool raiseEvents = true); - - /// - /// Exports a single item to xml as an - /// - /// Template to export - /// Optional parameter indicating whether or not to raise events - /// containing the xml representation of the ITemplate object - XElement Export(ITemplate template, bool raiseEvents = true); - - /// - /// Exports a list of items to xml as an - /// - /// Macros to export - /// Optional parameter indicating whether or not to raise events - /// containing the xml representation of the IMacro objects - XElement Export(IEnumerable macros, bool raiseEvents = true); - - /// - /// Exports a single item to xml as an - /// - /// Macro to export - /// Optional parameter indicating whether or not to raise events - /// containing the xml representation of the IMacro object - XElement Export(IMacro macro, bool raiseEvents = true); - /// /// This will fetch an Umbraco package file from the package repository and return the relative file path to the downloaded package file /// diff --git a/src/Umbraco.Core/Services/Implement/EntityService.cs b/src/Umbraco.Core/Services/Implement/EntityService.cs index 4a3db29940..37b569b814 100644 --- a/src/Umbraco.Core/Services/Implement/EntityService.cs +++ b/src/Umbraco.Core/Services/Implement/EntityService.cs @@ -258,6 +258,9 @@ namespace Umbraco.Core.Services.Implement public virtual IEnumerable GetAll(UmbracoObjectTypes objectType, params int[] ids) { var entityType = objectType.GetClrType(); + if (entityType == null) + throw new NotSupportedException($"Type \"{objectType}\" is not supported here."); + GetGetters(entityType); using (ScopeProvider.CreateScope(autoComplete: true)) diff --git a/src/Umbraco.Core/Services/EntityXmlSerializer.cs b/src/Umbraco.Core/Services/Implement/EntityXmlSerializer.cs similarity index 70% rename from src/Umbraco.Core/Services/EntityXmlSerializer.cs rename to src/Umbraco.Core/Services/Implement/EntityXmlSerializer.cs index 5b64584dc6..e90d894fcd 100644 --- a/src/Umbraco.Core/Services/EntityXmlSerializer.cs +++ b/src/Umbraco.Core/Services/Implement/EntityXmlSerializer.cs @@ -7,49 +7,61 @@ using System.Xml.Linq; using Newtonsoft.Json; using Umbraco.Core.Composing; using Umbraco.Core.Models; -using Umbraco.Core.PropertyEditors; using Umbraco.Core.Strings; -namespace Umbraco.Core.Services +namespace Umbraco.Core.Services.Implement { - //TODO: Move the rest of the logic for the PackageService.Export methods to here! - /// - /// A helper class to serialize entities to XML + /// Serializes entities to XML /// - internal class EntityXmlSerializer + internal class EntityXmlSerializer : IEntityXmlSerializer { - /// - /// Exports an IContent item as an XElement. - /// - public static XElement Serialize( + private readonly IContentTypeService _contentTypeService; + private readonly IMediaService _mediaService; + private readonly IContentService _contentService; + private readonly IDataTypeService _dataTypeService; + private readonly IUserService _userService; + private readonly ILocalizationService _localizationService; + private readonly IEnumerable _urlSegmentProviders; + + public EntityXmlSerializer( IContentService contentService, + IMediaService mediaService, IDataTypeService dataTypeService, IUserService userService, ILocalizationService localizationService, - IEnumerable urlSegmentProviders, - IContent content, + IContentTypeService contentTypeService, + IEnumerable urlSegmentProviders) + { + _contentTypeService = contentTypeService; + _mediaService = mediaService; + _contentService = contentService; + _dataTypeService = dataTypeService; + _userService = userService; + _localizationService = localizationService; + _urlSegmentProviders = urlSegmentProviders; + } + + /// + /// Exports an IContent item as an XElement. + /// + public XElement Serialize(IContent content, bool published, bool withDescendants = false) //fixme take care of usage! only used for the packager { - if (contentService == null) throw new ArgumentNullException(nameof(contentService)); - if (dataTypeService == null) throw new ArgumentNullException(nameof(dataTypeService)); - if (userService == null) throw new ArgumentNullException(nameof(userService)); - if (localizationService == null) throw new ArgumentNullException(nameof(localizationService)); if (content == null) throw new ArgumentNullException(nameof(content)); - if (urlSegmentProviders == null) throw new ArgumentNullException(nameof(urlSegmentProviders)); // nodeName should match Casing.SafeAliasWithForcingCheck(content.ContentType.Alias); var nodeName = content.ContentType.Alias.ToSafeAliasWithForcingCheck(); - var xml = SerializeContentBase(dataTypeService, localizationService, content, content.GetUrlSegment(urlSegmentProviders), nodeName, published); + var xml = SerializeContentBase(content, content.GetUrlSegment(_urlSegmentProviders), nodeName, published); xml.Add(new XAttribute("nodeType", content.ContentType.Id)); xml.Add(new XAttribute("nodeTypeAlias", content.ContentType.Alias)); - xml.Add(new XAttribute("creatorName", content.GetCreatorProfile(userService)?.Name ?? "??")); + xml.Add(new XAttribute("creatorName", content.GetCreatorProfile(_userService)?.Name ?? "??")); //xml.Add(new XAttribute("creatorID", content.CreatorId)); - xml.Add(new XAttribute("writerName", content.GetWriterProfile(userService)?.Name ?? "??")); + xml.Add(new XAttribute("writerName", content.GetWriterProfile(_userService)?.Name ?? "??")); xml.Add(new XAttribute("writerID", content.WriterId)); xml.Add(new XAttribute("template", content.Template?.Id.ToString(CultureInfo.InvariantCulture) ?? "0")); @@ -63,8 +75,8 @@ namespace Umbraco.Core.Services var total = long.MaxValue; while(page * pageSize < total) { - var children = contentService.GetPagedChildren(content.Id, page++, pageSize, out total); - SerializeChildren(contentService, dataTypeService, userService, localizationService, urlSegmentProviders, children, xml, published); + var children = _contentService.GetPagedChildren(content.Id, page++, pageSize, out total); + SerializeChildren(children, xml, published); } } @@ -75,34 +87,29 @@ namespace Umbraco.Core.Services /// /// Exports an IMedia item as an XElement. /// - public static XElement Serialize( - IMediaService mediaService, - IDataTypeService dataTypeService, - IUserService userService, - ILocalizationService localizationService, - IEnumerable urlSegmentProviders, + public XElement Serialize( IMedia media, bool withDescendants = false) { - if (mediaService == null) throw new ArgumentNullException(nameof(mediaService)); - if (dataTypeService == null) throw new ArgumentNullException(nameof(dataTypeService)); - if (userService == null) throw new ArgumentNullException(nameof(userService)); - if (localizationService == null) throw new ArgumentNullException(nameof(localizationService)); + if (_mediaService == null) throw new ArgumentNullException(nameof(_mediaService)); + if (_dataTypeService == null) throw new ArgumentNullException(nameof(_dataTypeService)); + if (_userService == null) throw new ArgumentNullException(nameof(_userService)); + if (_localizationService == null) throw new ArgumentNullException(nameof(_localizationService)); if (media == null) throw new ArgumentNullException(nameof(media)); - if (urlSegmentProviders == null) throw new ArgumentNullException(nameof(urlSegmentProviders)); + if (_urlSegmentProviders == null) throw new ArgumentNullException(nameof(_urlSegmentProviders)); // nodeName should match Casing.SafeAliasWithForcingCheck(content.ContentType.Alias); var nodeName = media.ContentType.Alias.ToSafeAliasWithForcingCheck(); const bool published = false; // always false for media - var xml = SerializeContentBase(dataTypeService, localizationService, media, media.GetUrlSegment(urlSegmentProviders), nodeName, published); + var xml = SerializeContentBase(media, media.GetUrlSegment(_urlSegmentProviders), nodeName, published); xml.Add(new XAttribute("nodeType", media.ContentType.Id)); xml.Add(new XAttribute("nodeTypeAlias", media.ContentType.Alias)); //xml.Add(new XAttribute("creatorName", media.GetCreatorProfile(userService).Name)); //xml.Add(new XAttribute("creatorID", media.CreatorId)); - xml.Add(new XAttribute("writerName", media.GetWriterProfile(userService)?.Name ?? string.Empty)); + xml.Add(new XAttribute("writerName", media.GetWriterProfile(_userService)?.Name ?? string.Empty)); xml.Add(new XAttribute("writerID", media.WriterId)); //xml.Add(new XAttribute("template", 0)); // no template for media @@ -114,8 +121,8 @@ namespace Umbraco.Core.Services var total = long.MaxValue; while (page * pageSize < total) { - var children = mediaService.GetPagedChildren(media.Id, page++, pageSize, out total); - SerializeChildren(mediaService, dataTypeService, userService, localizationService, urlSegmentProviders, children, xml); + var children = _mediaService.GetPagedChildren(media.Id, page++, pageSize, out total); + SerializeChildren(children, xml); } } @@ -125,16 +132,13 @@ namespace Umbraco.Core.Services /// /// Exports an IMember item as an XElement. /// - public static XElement Serialize( - IDataTypeService dataTypeService, - ILocalizationService localizationService, - IMember member) + public XElement Serialize(IMember member) { // nodeName should match Casing.SafeAliasWithForcingCheck(content.ContentType.Alias); var nodeName = member.ContentType.Alias.ToSafeAliasWithForcingCheck(); const bool published = false; // always false for member - var xml = SerializeContentBase(dataTypeService, localizationService, member, "", nodeName, published); + var xml = SerializeContentBase(member, "", nodeName, published); xml.Add(new XAttribute("nodeType", member.ContentType.Id)); xml.Add(new XAttribute("nodeTypeAlias", member.ContentType.Alias)); @@ -148,7 +152,22 @@ namespace Umbraco.Core.Services return xml; } - public XElement Serialize(IDataTypeService dataTypeService, IDataType dataType) + /// + /// Exports a list of Data Types + /// + /// List of data types to export + /// containing the xml representation of the IDataTypeDefinition objects + public XElement Serialize(IEnumerable dataTypeDefinitions) + { + var container = new XElement("DataTypes"); + foreach (var dataTypeDefinition in dataTypeDefinitions) + { + container.Add(Serialize(dataTypeDefinition)); + } + return container; + } + + public XElement Serialize(IDataType dataType) { var xml = new XElement("DataType"); xml.Add(new XAttribute("Name", dataType.Name)); @@ -162,7 +181,7 @@ namespace Umbraco.Core.Services if (dataType.Level != 1) { //get url encoded folder names - var folders = dataTypeService.GetContainers(dataType) + var folders = _dataTypeService.GetContainers(dataType) .OrderBy(x => x.Level) .Select(x => HttpUtility.UrlEncode(x.Name)); @@ -175,7 +194,45 @@ namespace Umbraco.Core.Services return xml; } - public XElement Serialize(IDictionaryItem dictionaryItem) + /// + /// Exports a list of items to xml as an + /// + /// List of dictionary items to export + /// Optional boolean indicating whether or not to include children + /// containing the xml representation of the IDictionaryItem objects + public XElement Serialize(IEnumerable dictionaryItem, bool includeChildren = true) + { + var xml = new XElement("DictionaryItems"); + foreach (var item in dictionaryItem) + { + xml.Add(Serialize(item, includeChildren)); + } + return xml; + } + + /// + /// Exports a single item to xml as an + /// + /// Dictionary Item to export + /// Optional boolean indicating whether or not to include children + /// containing the xml representation of the IDictionaryItem object + public XElement Serialize(IDictionaryItem dictionaryItem, bool includeChildren) + { + var xml = Serialize(dictionaryItem); + + if (includeChildren) + { + var children = _localizationService.GetDictionaryItemChildren(dictionaryItem.Key); + foreach (var child in children) + { + xml.Add(Serialize(child, true)); + } + } + + return xml; + } + + private XElement Serialize(IDictionaryItem dictionaryItem) { var xml = new XElement("DictionaryItem", new XAttribute("Key", dictionaryItem.ItemKey)); foreach (var translation in dictionaryItem.Translations) @@ -210,6 +267,21 @@ namespace Umbraco.Core.Services return xml; } + /// + /// Exports a list of items to xml as an + /// + /// List of Languages to export + /// containing the xml representation of the ILanguage objects + public XElement Serialize(IEnumerable languages) + { + var xml = new XElement("Languages"); + foreach (var language in languages) + { + xml.Add(Serialize(language)); + } + return xml; + } + public XElement Serialize(ILanguage language) { var xml = new XElement("Language", @@ -240,7 +312,22 @@ namespace Umbraco.Core.Services return xml; } - public XElement Serialize(IDataTypeService dataTypeService, IMediaType mediaType) + /// + /// Exports a list of items to xml as an + /// + /// + /// + public XElement Serialize(IEnumerable templates) + { + var xml = new XElement("Templates"); + foreach (var item in templates) + { + xml.Add(Serialize(item)); + } + return xml; + } + + public XElement Serialize(IMediaType mediaType) { var info = new XElement("Info", new XElement("Name", mediaType.Name), @@ -263,7 +350,7 @@ namespace Umbraco.Core.Services var genericProperties = new XElement("GenericProperties"); // actually, all of them foreach (var propertyType in mediaType.PropertyTypes) { - var definition = dataTypeService.GetDataType(propertyType.DataTypeId); + var definition = _dataTypeService.GetDataType(propertyType.DataTypeId); var propertyGroup = propertyType.PropertyGroupId == null // true generic property ? null @@ -301,6 +388,21 @@ namespace Umbraco.Core.Services return xml; } + /// + /// Exports a list of items to xml as an + /// + /// Macros to export + /// containing the xml representation of the IMacro objects + public XElement Serialize(IEnumerable macros) + { + var xml = new XElement("Macros"); + foreach (var item in macros) + { + xml.Add(Serialize(item)); + } + return xml; + } + public XElement Serialize(IMacro macro) { var xml = new XElement("macro"); @@ -328,7 +430,7 @@ namespace Umbraco.Core.Services return xml; } - public XElement Serialize(IDataTypeService dataTypeService, IContentTypeService contentTypeService, IContentType contentType) + public XElement Serialize(IContentType contentType) { var info = new XElement("Info", new XElement("Name", contentType.Name), @@ -372,7 +474,7 @@ namespace Umbraco.Core.Services var genericProperties = new XElement("GenericProperties"); // actually, all of them foreach (var propertyType in contentType.PropertyTypes) { - var definition = dataTypeService.GetDataType(propertyType.DataTypeId); + var definition = _dataTypeService.GetDataType(propertyType.DataTypeId); var propertyGroup = propertyType.PropertyGroupId == null // true generic property ? null @@ -413,7 +515,7 @@ namespace Umbraco.Core.Services if (contentType.Level != 1 && masterContentType == null) { //get url encoded folder names - var folders = contentTypeService.GetContainers(contentType) + var folders = _contentTypeService.GetContainers(contentType) .OrderBy(x => x.Level) .Select(x => HttpUtility.UrlEncode(x.Name)); @@ -427,7 +529,7 @@ namespace Umbraco.Core.Services } // exports an IContentBase (IContent, IMedia or IMember) as an XElement. - private static XElement SerializeContentBase(IDataTypeService dataTypeService, ILocalizationService localizationService, IContentBase contentBase, string urlValue, string nodeName, bool published) + private XElement SerializeContentBase(IContentBase contentBase, string urlValue, string nodeName, bool published) { var xml = new XElement(nodeName, new XAttribute("id", contentBase.Id), @@ -444,13 +546,13 @@ namespace Umbraco.Core.Services new XAttribute("isDoc", "")); foreach (var property in contentBase.Properties) - xml.Add(SerializeProperty(dataTypeService, localizationService, property, published)); + xml.Add(SerializeProperty(property, published)); return xml; } // exports a property as XElements. - private static IEnumerable SerializeProperty(IDataTypeService dataTypeService, ILocalizationService localizationService, Property property, bool published) + private IEnumerable SerializeProperty(Property property, bool published) { var propertyType = property.PropertyType; @@ -458,16 +560,16 @@ namespace Umbraco.Core.Services var propertyEditor = Current.PropertyEditors[propertyType.PropertyEditorAlias]; return propertyEditor == null ? Array.Empty() - : propertyEditor.GetValueEditor().ConvertDbToXml(property, dataTypeService, localizationService, published); + : propertyEditor.GetValueEditor().ConvertDbToXml(property, _dataTypeService, _localizationService, published); } // exports an IContent item descendants. - private static void SerializeChildren(IContentService contentService, IDataTypeService dataTypeService, IUserService userService, ILocalizationService localizationService, IEnumerable urlSegmentProviders, IEnumerable children, XElement xml, bool published) + private void SerializeChildren(IEnumerable children, XElement xml, bool published) { foreach (var child in children) { // add the child xml - var childXml = Serialize(contentService, dataTypeService, userService, localizationService, urlSegmentProviders, child, published); + var childXml = Serialize(child, published); xml.Add(childXml); const int pageSize = 500; @@ -475,20 +577,20 @@ namespace Umbraco.Core.Services var total = long.MaxValue; while(page * pageSize < total) { - var grandChildren = contentService.GetPagedChildren(child.Id, page++, pageSize, out total); + var grandChildren = _contentService.GetPagedChildren(child.Id, page++, pageSize, out total); // recurse - SerializeChildren(contentService, dataTypeService, userService, localizationService, urlSegmentProviders, grandChildren, childXml, published); + SerializeChildren(grandChildren, childXml, published); } } } // exports an IMedia item descendants. - private static void SerializeChildren(IMediaService mediaService, IDataTypeService dataTypeService, IUserService userService, ILocalizationService localizationService, IEnumerable urlSegmentProviders, IEnumerable children, XElement xml) + private void SerializeChildren(IEnumerable children, XElement xml) { foreach (var child in children) { // add the child xml - var childXml = Serialize(mediaService, dataTypeService, userService, localizationService, urlSegmentProviders, child); + var childXml = Serialize(child); xml.Add(childXml); const int pageSize = 500; @@ -496,9 +598,9 @@ namespace Umbraco.Core.Services var total = long.MaxValue; while (page * pageSize < total) { - var grandChildren = mediaService.GetPagedChildren(child.Id, page++, pageSize, out total); + var grandChildren = _mediaService.GetPagedChildren(child.Id, page++, pageSize, out total); // recurse - SerializeChildren(mediaService, dataTypeService, userService, localizationService, urlSegmentProviders, grandChildren, childXml); + SerializeChildren(grandChildren, childXml); } } } diff --git a/src/Umbraco.Core/Services/Implement/PackagingService.cs b/src/Umbraco.Core/Services/Implement/PackagingService.cs index 106d2b9f12..203a2cb2e8 100644 --- a/src/Umbraco.Core/Services/Implement/PackagingService.cs +++ b/src/Umbraco.Core/Services/Implement/PackagingService.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.IO; using System.Linq; using System.Net.Http; @@ -8,8 +7,6 @@ using System.Text.RegularExpressions; using System.Web; using System.Xml.Linq; using Umbraco.Core.Collections; -using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Events; using Umbraco.Core.Exceptions; using Umbraco.Core.IO; @@ -18,8 +15,6 @@ using Umbraco.Core.Models; using Umbraco.Core.Models.Entities; using Umbraco.Core.Models.Packaging; using Umbraco.Core.Packaging; -using Umbraco.Core.Packaging.Models; -using Umbraco.Core.Persistence.Dtos; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.PropertyEditors; @@ -35,56 +30,53 @@ namespace Umbraco.Core.Services.Implement /// public class PackagingService : IPackagingService { + //fixme: inject when ready to use this + private IPackageInstallation _packageInstallation; + private readonly ILogger _logger; private readonly IContentService _contentService; private readonly IContentTypeService _contentTypeService; - private readonly IMediaService _mediaService; private readonly IMacroService _macroService; private readonly IDataTypeService _dataTypeService; private readonly IFileService _fileService; private readonly ILocalizationService _localizationService; private readonly IEntityService _entityService; private readonly IScopeProvider _scopeProvider; - private readonly IEnumerable _urlSegmentProviders; private Dictionary _importedContentTypes; - private IPackageInstallation _packageInstallation; - private readonly IUserService _userService; private readonly IAuditRepository _auditRepository; private readonly IContentTypeRepository _contentTypeRepository; private readonly PropertyEditorCollection _propertyEditors; + private readonly IPackageCreation _packageCreation; private static HttpClient _httpClient; public PackagingService( ILogger logger, IContentService contentService, IContentTypeService contentTypeService, - IMediaService mediaService, IMacroService macroService, IDataTypeService dataTypeService, IFileService fileService, ILocalizationService localizationService, IEntityService entityService, - IUserService userService, IScopeProvider scopeProvider, - UrlSegmentProviderCollection urlSegmentProviders, - IAuditRepository auditRepository, IContentTypeRepository contentTypeRepository, - PropertyEditorCollection propertyEditors) + IAuditRepository auditRepository, + IContentTypeRepository contentTypeRepository, + PropertyEditorCollection propertyEditors, + IPackageCreation packageCreation) { _logger = logger; _contentService = contentService; _contentTypeService = contentTypeService; - _mediaService = mediaService; _macroService = macroService; _dataTypeService = dataTypeService; _fileService = fileService; _localizationService = localizationService; _entityService = entityService; _scopeProvider = scopeProvider; - _urlSegmentProviders = urlSegmentProviders; _auditRepository = auditRepository; _contentTypeRepository = contentTypeRepository; _propertyEditors = propertyEditors; - _userService = userService; + _packageCreation = packageCreation; _importedContentTypes = new Dictionary(); } @@ -92,31 +84,7 @@ namespace Umbraco.Core.Services.Implement #region Content - /// - /// Exports an item to xml as an - /// - /// Content to export - /// Optional parameter indicating whether to include descendents - /// Optional parameter indicating whether or not to raise events - /// containing the xml representation of the Content object - public XElement Export(IContent content, bool deep = false, bool raiseEvents = true) - { - var nodeName = content.ContentType.Alias.ToSafeAliasWithForcingCheck(); - - if (raiseEvents) - { - if (ExportingContent.IsRaisedEventCancelled(new ExportEventArgs(content, nodeName), this)) - return new XElement(nodeName); - } - - const bool published = false; // fixme - what shall we export? - var xml = EntityXmlSerializer.Serialize(_contentService, _dataTypeService, _userService, _localizationService, _urlSegmentProviders, content, published, deep); - - if (raiseEvents) - ExportedContent.RaiseEvent(new ExportEventArgs(content, xml, false), this); - - return xml; - } + @@ -308,28 +276,7 @@ namespace Umbraco.Core.Services.Implement #region ContentTypes - /// - /// Exports an to xml as an - /// - /// ContentType to export - /// Optional parameter indicating whether or not to raise events - /// containing the xml representation of the ContentType item. - public XElement Export(IContentType contentType, bool raiseEvents = true) - { - if (raiseEvents) - { - if (ExportingContentType.IsRaisedEventCancelled(new ExportEventArgs(contentType, "DocumentType"), this)) - return new XElement("DocumentType"); - } - - var exporter = new EntityXmlSerializer(); - var xml = exporter.Serialize(_dataTypeService, _contentTypeService, contentType); - - if (raiseEvents) - ExportedContentType.RaiseEvent(new ExportEventArgs(contentType, xml, false), this); - - return xml; - } + /// /// Imports and saves package xml as @@ -804,44 +751,9 @@ namespace Umbraco.Core.Services.Implement #region DataTypes - /// - /// Exports a list of Data Types - /// - /// List of data types to export - /// Optional parameter indicating whether or not to raise events - /// containing the xml representation of the IDataTypeDefinition objects - public XElement Export(IEnumerable dataTypeDefinitions, bool raiseEvents = true) - { - var container = new XElement("DataTypes"); - foreach (var dataTypeDefinition in dataTypeDefinitions) - { - container.Add(Export(dataTypeDefinition, raiseEvents)); - } - return container; - } + - /// - /// Exports a single Data Type - /// - /// Data type to export - /// Optional parameter indicating whether or not to raise events - /// containing the xml representation of the IDataTypeDefinition object - public XElement Export(IDataType dataType, bool raiseEvents = true) - { - if (raiseEvents) - { - if (ExportingDataType.IsRaisedEventCancelled(new ExportEventArgs(dataType, "DataType"), this)) - return new XElement("DataType"); - } - - var exporter = new EntityXmlSerializer(); - var xml = exporter.Serialize(_dataTypeService, dataType); - - if (raiseEvents) - ExportedDataType.RaiseEvent(new ExportEventArgs(dataType, xml, false), this); - - return xml; - } + /// /// Imports and saves package xml as @@ -993,55 +905,9 @@ namespace Umbraco.Core.Services.Implement #region Dictionary Items - /// - /// Exports a list of items to xml as an - /// - /// List of dictionary items to export - /// Optional boolean indicating whether or not to include children - /// Optional parameter indicating whether or not to raise events - /// containing the xml representation of the IDictionaryItem objects - public XElement Export(IEnumerable dictionaryItem, bool includeChildren = true, bool raiseEvents = true) - { - var xml = new XElement("DictionaryItems"); - foreach (var item in dictionaryItem) - { - xml.Add(Export(item, includeChildren, raiseEvents)); - } - return xml; - } + - /// - /// Exports a single item to xml as an - /// - /// Dictionary Item to export - /// Optional boolean indicating whether or not to include children - /// Optional parameter indicating whether or not to raise events - /// containing the xml representation of the IDictionaryItem object - public XElement Export(IDictionaryItem dictionaryItem, bool includeChildren, bool raiseEvents = true) - { - if (raiseEvents) - { - if (ExportingDictionaryItem.IsRaisedEventCancelled(new ExportEventArgs(dictionaryItem, "DictionaryItem"), this)) - return new XElement("DictionaryItem"); - } - - var exporter = new EntityXmlSerializer(); - var xml = exporter.Serialize(dictionaryItem); - - if (includeChildren) - { - var children = _localizationService.GetDictionaryItemChildren(dictionaryItem.Key); - foreach (var child in children) - { - xml.Add(Export(child, true)); - } - } - - if (raiseEvents) - ExportedDictionaryItem.RaiseEvent(new ExportEventArgs(dictionaryItem, xml, false), this); - - return xml; - } + /// /// Imports and saves the 'DictionaryItems' part of the package xml as a list of @@ -1138,44 +1004,9 @@ namespace Umbraco.Core.Services.Implement #region Languages - /// - /// Exports a list of items to xml as an - /// - /// List of Languages to export - /// Optional parameter indicating whether or not to raise events - /// containing the xml representation of the ILanguage objects - public XElement Export(IEnumerable languages, bool raiseEvents = true) - { - var xml = new XElement("Languages"); - foreach (var language in languages) - { - xml.Add(Export(language, raiseEvents)); - } - return xml; - } + - /// - /// Exports a single item to xml as an - /// - /// Language to export - /// Optional parameter indicating whether or not to raise events - /// containing the xml representation of the ILanguage object - public XElement Export(ILanguage language, bool raiseEvents = true) - { - if (raiseEvents) - { - if (ExportingLanguage.IsRaisedEventCancelled(new ExportEventArgs(language, "Language"), this)) - return new XElement("Language"); - } - - var exporter = new EntityXmlSerializer(); - var xml = exporter.Serialize(language); - - if (raiseEvents) - ExportedLanguage.RaiseEvent(new ExportEventArgs(language, xml, false), this); - - return xml; - } + /// /// Imports and saves the 'Languages' part of a package xml as a list of @@ -1326,109 +1157,10 @@ namespace Umbraco.Core.Services.Implement return macro; } - /// - /// Exports a list of items to xml as an - /// - /// Macros to export - /// Optional parameter indicating whether or not to raise events - /// containing the xml representation of the IMacro objects - public XElement Export(IEnumerable macros, bool raiseEvents = true) - { - var xml = new XElement("Macros"); - foreach (var item in macros) - { - xml.Add(Export(item, raiseEvents)); - } - return xml; - } + - /// - /// Exports a single item to xml as an - /// - /// Macro to export - /// Optional parameter indicating whether or not to raise events - /// containing the xml representation of the IMacro object - public XElement Export(IMacro macro, bool raiseEvents = true) - { - if (raiseEvents) - { - if (ExportingMacro.IsRaisedEventCancelled(new ExportEventArgs(macro, "macro"), this)) - return new XElement("macro"); - } + - var exporter = new EntityXmlSerializer(); - var xml = exporter.Serialize(macro); - - if (raiseEvents) - ExportedMacro.RaiseEvent(new ExportEventArgs(macro, xml, false), this); - - return xml; - } - - #endregion - - #region Members - - /// - /// Exports an item to xml as an - /// - /// Member to export - /// containing the xml representation of the Member object - public XElement Export(IMember member) - { - return EntityXmlSerializer.Serialize(_dataTypeService, _localizationService, member); - } - - #endregion - - #region Media - - /// - /// Exports an item to xml as an - /// - /// Media to export - /// Optional parameter indicating whether to include descendents - /// Optional parameter indicating whether or not to raise events - /// containing the xml representation of the Media object - public XElement Export(IMedia media, bool deep = false, bool raiseEvents = true) - { - var nodeName = media.ContentType.Alias.ToSafeAliasWithForcingCheck(); - - if (raiseEvents) - { - if (ExportingMedia.IsRaisedEventCancelled(new ExportEventArgs(media, nodeName), this)) - return new XElement(nodeName); - } - - var xml = EntityXmlSerializer.Serialize(_mediaService, _dataTypeService, _userService, _localizationService, _urlSegmentProviders, media, deep); - - if (raiseEvents) - ExportedMedia.RaiseEvent(new ExportEventArgs(media, xml, false), this); - - return xml; - } - - - #endregion - - #region MediaTypes - - /// - /// Exports an to xml as an - /// - /// MediaType to export - /// containing the xml representation of the MediaType item. - internal XElement Export(IMediaType mediaType) - { - var exporter = new EntityXmlSerializer(); - var xml = exporter.Serialize(_dataTypeService, mediaType); - - return xml; - } - - #endregion - - #region Package Manifest #endregion #region Package Files @@ -1579,6 +1311,26 @@ namespace Umbraco.Core.Services.Implement } + private bool IsMasterPageSyntax(string code) + { + return Regex.IsMatch(code, @"<%@\s*Master", RegexOptions.IgnoreCase) || + code.InvariantContains(" ImportStylesheets(XElement element, int userId = 0, bool raiseEvents = true) { @@ -1601,69 +1353,12 @@ namespace Umbraco.Core.Services.Implement } - - private bool IsMasterPageSyntax(string code) - { - return Regex.IsMatch(code, @"<%@\s*Master", RegexOptions.IgnoreCase) || - code.InvariantContains(" - /// Exports a list of items to xml as an - /// - /// List of Templates to export - /// Optional parameter indicating whether or not to raise events - /// containing the xml representation of the ITemplate objects - public XElement Export(IEnumerable templates, bool raiseEvents = true) - { - var xml = new XElement("Templates"); - foreach (var item in templates) - { - xml.Add(Export(item, raiseEvents)); - } - return xml; - } - - /// - /// Exports a single item to xml as an - /// - /// Template to export - /// Optional parameter indicating whether or not to raise events - /// containing the xml representation of the ITemplate object - public XElement Export(ITemplate template, bool raiseEvents = true) - { - if (raiseEvents) - { - if (ExportingTemplate.IsRaisedEventCancelled(new ExportEventArgs(template, "Template"), this)) - return new XElement("Template"); - } - - var exporter = new EntityXmlSerializer(); - var xml = exporter.Serialize(template); - - if (raiseEvents) - ExportedTemplate.RaiseEvent(new ExportEventArgs(template, xml, false), this); - - return xml; - } - - #endregion - - #region Stylesheets #endregion #region Installation + //fixme: None of these methods are actually used! They have unit tests for them though, but we don't actively use this yet but we should! + internal IPackageInstallation PackageInstallation { private get { return _packageInstallation ?? new PackageInstallation(this, _macroService, _fileService, new PackageExtraction()); } @@ -1706,6 +1401,9 @@ namespace Umbraco.Core.Services.Implement #endregion #region Package Building + + public void SavePackageDefinition(PackageDefinition definition) => _packageCreation.SavePackageDefinition(definition); + #endregion /// @@ -1737,24 +1435,6 @@ namespace Umbraco.Core.Services.Implement /// public static event TypedEventHandler> ImportedContent; - - public static event TypedEventHandler> ExportingContent; - - /// - /// Occurs after Content is Exported to Xml - /// - public static event TypedEventHandler> ExportedContent; - - /// - /// Occurs before Exporting Media - /// - public static event TypedEventHandler> ExportingMedia; - - /// - /// Occurs after Media is Exported to Xml - /// - public static event TypedEventHandler> ExportedMedia; - /// /// Occurs before Importing ContentType /// @@ -1765,16 +1445,6 @@ namespace Umbraco.Core.Services.Implement /// public static event TypedEventHandler> ImportedContentType; - /// - /// Occurs before Exporting ContentType - /// - public static event TypedEventHandler> ExportingContentType; - - /// - /// Occurs after ContentType is Exported to Xml - /// - public static event TypedEventHandler> ExportedContentType; - /// /// Occurs before Importing DataType /// @@ -1785,16 +1455,6 @@ namespace Umbraco.Core.Services.Implement /// public static event TypedEventHandler> ImportedDataType; - /// - /// Occurs before Exporting DataType - /// - public static event TypedEventHandler> ExportingDataType; - - /// - /// Occurs after DataType is Exported to Xml - /// - public static event TypedEventHandler> ExportedDataType; - /// /// Occurs before Importing DictionaryItem /// @@ -1805,16 +1465,6 @@ namespace Umbraco.Core.Services.Implement /// public static event TypedEventHandler> ImportedDictionaryItem; - /// - /// Occurs before Exporting DictionaryItem - /// - public static event TypedEventHandler> ExportingDictionaryItem; - - /// - /// Occurs after DictionaryItem is Exported to Xml - /// - public static event TypedEventHandler> ExportedDictionaryItem; - /// /// Occurs before Importing Macro /// @@ -1825,16 +1475,6 @@ namespace Umbraco.Core.Services.Implement ///
    public static event TypedEventHandler> ImportedMacro; - /// - /// Occurs before Exporting Macro - /// - public static event TypedEventHandler> ExportingMacro; - - /// - /// Occurs after Macro is Exported to Xml - /// - public static event TypedEventHandler> ExportedMacro; - /// /// Occurs before Importing Language /// @@ -1845,16 +1485,6 @@ namespace Umbraco.Core.Services.Implement ///
    public static event TypedEventHandler> ImportedLanguage; - /// - /// Occurs before Exporting Language - /// - public static event TypedEventHandler> ExportingLanguage; - - /// - /// Occurs after Language is Exported to Xml - /// - public static event TypedEventHandler> ExportedLanguage; - /// /// Occurs before Importing Template /// @@ -1870,16 +1500,6 @@ namespace Umbraco.Core.Services.Implement ///
    public static event TypedEventHandler> ImportedTemplate; - /// - /// Occurs before Exporting Template - /// - public static event TypedEventHandler> ExportingTemplate; - - /// - /// Occurs after Template is Exported to Xml - /// - public static event TypedEventHandler> ExportedTemplate; - /// /// Occurs before Importing umbraco package /// @@ -1896,5 +1516,7 @@ namespace Umbraco.Core.Services.Implement public static event TypedEventHandler> UninstalledPackage; #endregion + + } } diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index a01bbf1746..58ba136cc4 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -429,6 +429,9 @@ + + + @@ -440,6 +443,10 @@ + + + + @@ -554,7 +561,6 @@ - @@ -883,7 +889,7 @@ - + @@ -1351,6 +1357,7 @@ + @@ -1370,7 +1377,7 @@ - + @@ -1525,6 +1532,7 @@ + \ No newline at end of file diff --git a/src/Umbraco.Core/_Legacy/PackageActions/PackageActionCollection.cs b/src/Umbraco.Core/_Legacy/PackageActions/PackageActionCollection.cs index 46ea3c1e39..a38c8cea56 100644 --- a/src/Umbraco.Core/_Legacy/PackageActions/PackageActionCollection.cs +++ b/src/Umbraco.Core/_Legacy/PackageActions/PackageActionCollection.cs @@ -3,7 +3,7 @@ using Umbraco.Core.Composing; namespace Umbraco.Core._Legacy.PackageActions { - internal class PackageActionCollection : BuilderCollectionBase + public sealed class PackageActionCollection : BuilderCollectionBase { public PackageActionCollection(IEnumerable items) : base(items) diff --git a/src/Umbraco.Tests/Cache/PublishedCache/PublishedContentCacheTests.cs b/src/Umbraco.Tests/Cache/PublishedCache/PublishedContentCacheTests.cs index 28e753cadc..12ea87087d 100644 --- a/src/Umbraco.Tests/Cache/PublishedCache/PublishedContentCacheTests.cs +++ b/src/Umbraco.Tests/Cache/PublishedCache/PublishedContentCacheTests.cs @@ -6,6 +6,7 @@ using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; +using Umbraco.Core.Services; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; using Umbraco.Tests.Testing.Objects.Accessors; @@ -66,7 +67,7 @@ namespace Umbraco.Tests.Cache.PublishedCache var domainCache = new DomainCache(ServiceContext.DomainService, DefaultCultureAccessor); var publishedShapshot = new Umbraco.Web.PublishedCache.XmlPublishedCache.PublishedSnapshot( new PublishedContentCache(xmlStore, domainCache, cacheProvider, globalSettings, new SiteDomainHelper(), ContentTypesCache, null, null), - new PublishedMediaCache(xmlStore, ServiceContext.MediaService, ServiceContext.UserService, cacheProvider, ContentTypesCache), + new PublishedMediaCache(xmlStore, ServiceContext.MediaService, ServiceContext.UserService, cacheProvider, ContentTypesCache, Factory.GetInstance()), new PublishedMemberCache(null, cacheProvider, Current.Services.MemberService, ContentTypesCache), domainCache); var publishedSnapshotService = new Mock(); diff --git a/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs b/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs index 5237b92ab8..acf76ca8d7 100644 --- a/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs +++ b/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs @@ -15,6 +15,7 @@ using Umbraco.Tests.Testing; using Current = Umbraco.Web.Composing.Current; using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; +using Umbraco.Core.Services; using Umbraco.Tests.PublishedContent; namespace Umbraco.Tests.Cache.PublishedCache @@ -74,7 +75,7 @@ namespace Umbraco.Tests.Cache.PublishedCache var mChild2 = MakeNewMedia("Child2", mType, user, mRoot2.Id); var ctx = GetUmbracoContext("/test"); - var cache = new PublishedMediaCache(new XmlStore((XmlDocument) null, null, null, null), ServiceContext.MediaService, ServiceContext.UserService, new StaticCacheProvider(), ContentTypesCache); + var cache = new PublishedMediaCache(new XmlStore((XmlDocument) null, null, null, null), ServiceContext.MediaService, ServiceContext.UserService, new StaticCacheProvider(), ContentTypesCache, Factory.GetInstance()); var roots = cache.GetAtRoot(); Assert.AreEqual(2, roots.Count()); Assert.IsTrue(roots.Select(x => x.Id).ContainsAll(new[] {mRoot1.Id, mRoot2.Id})); @@ -92,7 +93,7 @@ namespace Umbraco.Tests.Cache.PublishedCache //var publishedMedia = PublishedMediaTests.GetNode(mRoot.Id, GetUmbracoContext("/test", 1234)); var umbracoContext = GetUmbracoContext("/test"); - var cache = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), Current.Services.MediaService, Current.Services.UserService, new StaticCacheProvider(), ContentTypesCache); + var cache = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), Current.Services.MediaService, Current.Services.UserService, new StaticCacheProvider(), ContentTypesCache, Factory.GetInstance()); var publishedMedia = cache.GetById(mRoot.Id); Assert.IsNotNull(publishedMedia); @@ -203,7 +204,7 @@ namespace Umbraco.Tests.Cache.PublishedCache var result = new SearchResult("1234", 1, 1, () => fields.ToDictionary(x => x.Key, x => new List { x.Value })); - var store = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), ServiceContext.MediaService, ServiceContext.UserService, new StaticCacheProvider(), ContentTypesCache); + var store = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), ServiceContext.MediaService, ServiceContext.UserService, new StaticCacheProvider(), ContentTypesCache, Factory.GetInstance()); var doc = store.CreateFromCacheValues(store.ConvertFromSearchResult(result)); DoAssert(doc, 1234, key, 0, 0, "/media/test.jpg", "Image", 23, "Shannon", "Shannon", 0, 0, "-1,1234", DateTime.Parse("2012-07-17T10:34:09"), DateTime.Parse("2012-07-16T10:34:09"), 2); @@ -219,7 +220,7 @@ namespace Umbraco.Tests.Cache.PublishedCache var xmlDoc = GetMediaXml(); ((XmlElement)xmlDoc.DocumentElement.FirstChild).SetAttribute("key", key.ToString()); var navigator = xmlDoc.SelectSingleNode("/root/Image").CreateNavigator(); - var cache = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), ServiceContext.MediaService, ServiceContext.UserService, new StaticCacheProvider(), ContentTypesCache); + var cache = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), ServiceContext.MediaService, ServiceContext.UserService, new StaticCacheProvider(), ContentTypesCache, Factory.GetInstance()); var doc = cache.CreateFromCacheValues(cache.ConvertFromXPathNavigator(navigator, true)); DoAssert(doc, 2000, key, 0, 2, "image1", "Image", 23, "Shannon", "Shannon", 33, 33, "-1,2000", DateTime.Parse("2012-06-12T14:13:17"), DateTime.Parse("2012-07-20T18:50:43"), 1); diff --git a/src/Umbraco.Tests/Models/ContentXmlTest.cs b/src/Umbraco.Tests/Models/ContentXmlTest.cs index ab318ec1cb..3779993d22 100644 --- a/src/Umbraco.Tests/Models/ContentXmlTest.cs +++ b/src/Umbraco.Tests/Models/ContentXmlTest.cs @@ -2,7 +2,9 @@ using System.Xml.Linq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Composing; using Umbraco.Core.Models; +using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Entities; @@ -29,7 +31,7 @@ namespace Umbraco.Tests.Models var urlName = content.GetUrlSegment(new[]{new DefaultUrlSegmentProvider() }); // Act - XElement element = content.ToXml(); + XElement element = content.ToXml(Factory.GetInstance()); // Assert Assert.That(element, Is.Not.Null); diff --git a/src/Umbraco.Tests/Models/MediaXmlTest.cs b/src/Umbraco.Tests/Models/MediaXmlTest.cs index 1a56fac4eb..d0d00c64a6 100644 --- a/src/Umbraco.Tests/Models/MediaXmlTest.cs +++ b/src/Umbraco.Tests/Models/MediaXmlTest.cs @@ -3,6 +3,7 @@ using System.Xml.Linq; using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Composing; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; using Umbraco.Core.Logging; @@ -50,7 +51,7 @@ namespace Umbraco.Tests.Models var urlName = media.GetUrlSegment(new[] { new DefaultUrlSegmentProvider() }); // Act - XElement element = media.ToXml(); + XElement element = media.ToXml(Factory.GetInstance()); // Assert Assert.That(element, Is.Not.Null); diff --git a/src/Umbraco.Tests/PublishedContent/NuCacheTests.cs b/src/Umbraco.Tests/PublishedContent/NuCacheTests.cs index 3ba0ef64ce..ef37a822c1 100644 --- a/src/Umbraco.Tests/PublishedContent/NuCacheTests.cs +++ b/src/Umbraco.Tests/PublishedContent/NuCacheTests.cs @@ -152,7 +152,8 @@ namespace Umbraco.Tests.PublishedContent new TestDefaultCultureAccessor(), dataSource, globalSettings, - new SiteDomainHelper()); + new SiteDomainHelper(), + Mock.Of()); // get a snapshot, get a published content var snapshot = snapshotService.CreatePublishedSnapshot(previewToken: null); diff --git a/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs index 88b211d0ee..4f55b4fd71 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs @@ -22,6 +22,7 @@ using Umbraco.Tests.Testing; using Umbraco.Core.Composing; using Umbraco.Core.Models.Membership; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Services; namespace Umbraco.Tests.PublishedContent { @@ -66,7 +67,9 @@ namespace Umbraco.Tests.PublishedContent /// internal IPublishedContent GetNode(int id, UmbracoContext umbracoContext) { - var cache = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), Current.Services.MediaService, Current.Services.UserService, new StaticCacheProvider(), ContentTypesCache); + var cache = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), + ServiceContext.MediaService, ServiceContext.UserService, new StaticCacheProvider(), ContentTypesCache, + Factory.GetInstance()); var doc = cache.GetById(id); Assert.IsNotNull(doc); return doc; @@ -123,7 +126,7 @@ namespace Umbraco.Tests.PublishedContent var searcher = indexer.GetSearcher(); var ctx = GetUmbracoContext("/test"); - var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, indexer, new StaticCacheProvider(), ContentTypesCache); + var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new StaticCacheProvider(), ContentTypesCache, Factory.GetInstance()); //we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace var publishedMedia = cache.GetById(1111); @@ -153,7 +156,7 @@ namespace Umbraco.Tests.PublishedContent var searcher = indexer.GetSearcher(); var ctx = GetUmbracoContext("/test"); - var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, indexer, new StaticCacheProvider(), ContentTypesCache); + var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new StaticCacheProvider(), ContentTypesCache, Factory.GetInstance()); //ensure it is found var publishedMedia = cache.GetById(3113); @@ -200,7 +203,7 @@ namespace Umbraco.Tests.PublishedContent var searcher = indexer.GetSearcher(); var ctx = GetUmbracoContext("/test"); - var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, indexer, new StaticCacheProvider(), ContentTypesCache); + var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new StaticCacheProvider(), ContentTypesCache, Factory.GetInstance()); //we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace var publishedMedia = cache.GetById(1111); @@ -228,7 +231,7 @@ namespace Umbraco.Tests.PublishedContent var searcher = indexer.GetSearcher(); var ctx = GetUmbracoContext("/test"); - var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, indexer, new StaticCacheProvider(), ContentTypesCache); + var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new StaticCacheProvider(), ContentTypesCache, Factory.GetInstance()); //we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace var publishedMedia = cache.GetById(1111); @@ -256,7 +259,7 @@ namespace Umbraco.Tests.PublishedContent var searcher = indexer.GetSearcher(); var ctx = GetUmbracoContext("/test"); - var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, indexer, new StaticCacheProvider(), ContentTypesCache); + var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new StaticCacheProvider(), ContentTypesCache, Factory.GetInstance()); //we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace var publishedMedia = cache.GetById(1111); @@ -285,7 +288,7 @@ namespace Umbraco.Tests.PublishedContent var ctx = GetUmbracoContext("/test"); var searcher = indexer.GetSearcher(); - var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, indexer, new StaticCacheProvider(), ContentTypesCache); + var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new StaticCacheProvider(), ContentTypesCache, Factory.GetInstance()); //we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace var publishedMedia = cache.GetById(3113); @@ -311,7 +314,7 @@ namespace Umbraco.Tests.PublishedContent var ctx = GetUmbracoContext("/test"); var searcher = indexer.GetSearcher(); - var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, indexer, new StaticCacheProvider(), ContentTypesCache); + var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new StaticCacheProvider(), ContentTypesCache, Factory.GetInstance()); //we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace var publishedMedia = cache.GetById(3113); @@ -479,7 +482,7 @@ namespace Umbraco.Tests.PublishedContent "); var node = xml.DescendantsAndSelf("Image").Single(x => (int)x.Attribute("id") == nodeId); - var publishedMedia = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), ServiceContext.MediaService, ServiceContext.UserService, new StaticCacheProvider(), ContentTypesCache); + var publishedMedia = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), ServiceContext.MediaService, ServiceContext.UserService, new StaticCacheProvider(), ContentTypesCache, Factory.GetInstance()); var nav = node.CreateNavigator(); @@ -499,7 +502,7 @@ namespace Umbraco.Tests.PublishedContent var errorXml = new XElement("error", string.Format("No media is maching '{0}'", 1234)); var nav = errorXml.CreateNavigator(); - var publishedMedia = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), ServiceContext.MediaService, ServiceContext.UserService, new StaticCacheProvider(), ContentTypesCache); + var publishedMedia = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), ServiceContext.MediaService, ServiceContext.UserService, new StaticCacheProvider(), ContentTypesCache, Factory.GetInstance()); var converted = publishedMedia.ConvertFromXPathNodeIterator(nav.Select("/"), 1234); Assert.IsNull(converted); diff --git a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs index b273ee9526..e8f3463ca7 100644 --- a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs @@ -95,7 +95,8 @@ namespace Umbraco.Tests.Scoping documentRepository, mediaRepository, memberRepository, DefaultCultureAccessor, new DatabaseDataSource(), - Factory.GetInstance(), new SiteDomainHelper()); + Factory.GetInstance(), new SiteDomainHelper(), + Factory.GetInstance()); } protected UmbracoContext GetUmbracoContextNu(string url, int templateId = 1234, RouteData routeData = null, bool setSingleton = false, IUmbracoSettingsSection umbracoSettings = null, IEnumerable urlProviders = null) diff --git a/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs b/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs index 94d2126bd2..d0c0b93b48 100644 --- a/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs +++ b/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs @@ -67,7 +67,8 @@ namespace Umbraco.Tests.Services documentRepository, mediaRepository, memberRepository, DefaultCultureAccessor, new DatabaseDataSource(), - Factory.GetInstance(), new SiteDomainHelper()); + Factory.GetInstance(), new SiteDomainHelper(), + Factory.GetInstance()); } public class LocalServerMessenger : ServerMessengerBase diff --git a/src/Umbraco.Tests/Services/EntityXmlSerializerTests.cs b/src/Umbraco.Tests/Services/EntityXmlSerializerTests.cs new file mode 100644 index 0000000000..28c69344b7 --- /dev/null +++ b/src/Umbraco.Tests/Services/EntityXmlSerializerTests.cs @@ -0,0 +1,101 @@ +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Xml.Linq; +using NUnit.Framework; +using Umbraco.Core.Composing; +using Umbraco.Core.Models; +using Umbraco.Core.Services; +using Umbraco.Tests.Services.Importing; +using Umbraco.Tests.Testing; + +namespace Umbraco.Tests.Services +{ + [TestFixture] + [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)] + public class EntityXmlSerializerTests : TestWithSomeContentBase + { + private IEntityXmlSerializer Serializer => Factory.GetInstance(); + + [Test] + public void Can_Export_Macro() + { + // Arrange + var macro = new Macro("test1", "Test", "~/views/macropartials/test.cshtml", MacroTypes.PartialView); + ServiceContext.MacroService.Save(macro); + + // Act + var element = Serializer.Serialize(macro); + + // Assert + Assert.That(element, Is.Not.Null); + Assert.That(element.Element("name").Value, Is.EqualTo("Test")); + Assert.That(element.Element("alias").Value, Is.EqualTo("test1")); + Debug.Print(element.ToString()); + } + + [Test] + public void Can_Export_DictionaryItems() + { + // Arrange + CreateDictionaryData(); + var dictionaryItem = ServiceContext.LocalizationService.GetDictionaryItemByKey("Parent"); + + var newPackageXml = XElement.Parse(ImportResources.Dictionary_Package); + var dictionaryItemsElement = newPackageXml.Elements("DictionaryItems").First(); + + // Act + var xml = Serializer.Serialize(new[] { dictionaryItem }); + + // Assert + Assert.That(xml.ToString(), Is.EqualTo(dictionaryItemsElement.ToString())); + } + + [Test] + public void Can_Export_Languages() + { + // Arrange + var languageNbNo = new Language("nb-NO") { CultureName = "Norwegian" }; + ServiceContext.LocalizationService.Save(languageNbNo); + + var languageEnGb = new Language("en-GB") { CultureName = "English (United Kingdom)" }; + ServiceContext.LocalizationService.Save(languageEnGb); + + var newPackageXml = XElement.Parse(ImportResources.Dictionary_Package); + var languageItemsElement = newPackageXml.Elements("Languages").First(); + + // Act + var xml = Serializer.Serialize(new[] { languageNbNo, languageEnGb }); + + // Assert + Assert.That(xml.ToString(), Is.EqualTo(languageItemsElement.ToString())); + } + + private void CreateDictionaryData() + { + var languageNbNo = new Language("nb-NO") { CultureName = "nb-NO" }; + ServiceContext.LocalizationService.Save(languageNbNo); + + var languageEnGb = new Language("en-GB") { CultureName = "en-GB" }; + ServiceContext.LocalizationService.Save(languageEnGb); + + var parentItem = new DictionaryItem("Parent"); + var parentTranslations = new List + { + new DictionaryTranslation(languageNbNo, "ForelderVerdi"), + new DictionaryTranslation(languageEnGb, "ParentValue") + }; + parentItem.Translations = parentTranslations; + ServiceContext.LocalizationService.Save(parentItem); + + var childItem = new DictionaryItem(parentItem.Key, "Child"); + var childTranslations = new List + { + new DictionaryTranslation(languageNbNo, "BarnVerdi"), + new DictionaryTranslation(languageEnGb, "ChildValue") + }; + childItem.Translations = childTranslations; + ServiceContext.LocalizationService.Save(childItem); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs b/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs index 8e67aa4e1f..84eb75a4f7 100644 --- a/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs +++ b/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs @@ -10,6 +10,7 @@ using Umbraco.Core.Composing.Composers; using Umbraco.Core.Logging; using Umbraco.Core.Persistence.Dtos; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Services; using Umbraco.Tests.Testing; namespace Umbraco.Tests.Services.Importing @@ -416,11 +417,12 @@ namespace Umbraco.Tests.Services.Importing string strXml = ImportResources.SingleDocType; var docTypeElement = XElement.Parse(strXml); var packagingService = ServiceContext.PackagingService; + var serializer = Factory.GetInstance(); // Act var contentTypes = packagingService.ImportContentTypes(docTypeElement); var contentType = contentTypes.FirstOrDefault(); - var element = packagingService.Export(contentType); + var element = serializer.Serialize(contentType); // Assert Assert.That(element, Is.Not.Null); diff --git a/src/Umbraco.Tests/Services/PackagingServiceTests.cs b/src/Umbraco.Tests/Services/PackagingServiceTests.cs index 87225c1288..a87e7907b5 100644 --- a/src/Umbraco.Tests/Services/PackagingServiceTests.cs +++ b/src/Umbraco.Tests/Services/PackagingServiceTests.cs @@ -1,16 +1,9 @@ using System; -using System.Collections.Generic; -using System.Diagnostics; using System.IO; -using System.Linq; -using System.Xml.Linq; using NUnit.Framework; using Umbraco.Core.IO; -using Umbraco.Core.Models; using Umbraco.Core.Models.Packaging; -using Umbraco.Core.Services; using Umbraco.Core.Services.Implement; -using Umbraco.Tests.Services.Importing; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; @@ -20,59 +13,7 @@ namespace Umbraco.Tests.Services [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)] public class PackagingServiceTests : TestWithSomeContentBase { - [Test] - public void PackagingService_Can_Export_Macro() - { - // Arrange - var macro = new Macro("test1", "Test", "~/views/macropartials/test.cshtml", MacroTypes.PartialView); - ServiceContext.MacroService.Save(macro); - - // Act - var element = ServiceContext.PackagingService.Export(macro); - - // Assert - Assert.That(element, Is.Not.Null); - Assert.That(element.Element("name").Value, Is.EqualTo("Test")); - Assert.That(element.Element("alias").Value, Is.EqualTo("test1")); - Debug.Print(element.ToString()); - } - - [Test] - public void PackagingService_Can_Export_DictionaryItems() - { - // Arrange - CreateDictionaryData(); - var dictionaryItem = ServiceContext.LocalizationService.GetDictionaryItemByKey("Parent"); - - var newPackageXml = XElement.Parse(ImportResources.Dictionary_Package); - var dictionaryItemsElement = newPackageXml.Elements("DictionaryItems").First(); - - // Act - var xml = ServiceContext.PackagingService.Export(new []{dictionaryItem}); - - // Assert - Assert.That(xml.ToString(), Is.EqualTo(dictionaryItemsElement.ToString())); - } - - [Test] - public void PackagingService_Can_Export_Languages() - { - // Arrange - var languageNbNo = new Language("nb-NO") { CultureName = "Norwegian" }; - ServiceContext.LocalizationService.Save(languageNbNo); - - var languageEnGb = new Language("en-GB") { CultureName = "English (United Kingdom)" }; - ServiceContext.LocalizationService.Save(languageEnGb); - - var newPackageXml = XElement.Parse(ImportResources.Dictionary_Package); - var languageItemsElement = newPackageXml.Elements("Languages").First(); - - // Act - var xml = ServiceContext.PackagingService.Export(new[] { languageNbNo, languageEnGb }); - - // Assert - Assert.That(xml.ToString(), Is.EqualTo(languageItemsElement.ToString())); - } + private static string GetTestPackagePath(string packageName) { @@ -123,31 +64,6 @@ namespace Umbraco.Tests.Services Assert.IsNotNull(preInstallWarnings); } - private void CreateDictionaryData() - { - var languageNbNo = new Language("nb-NO") { CultureName = "nb-NO" }; - ServiceContext.LocalizationService.Save(languageNbNo); - - var languageEnGb = new Language("en-GB") { CultureName = "en-GB" }; - ServiceContext.LocalizationService.Save(languageEnGb); - - var parentItem = new DictionaryItem("Parent"); - var parentTranslations = new List - { - new DictionaryTranslation(languageNbNo, "ForelderVerdi"), - new DictionaryTranslation(languageEnGb, "ParentValue") - }; - parentItem.Translations = parentTranslations; - ServiceContext.LocalizationService.Save(parentItem); - - var childItem = new DictionaryItem(parentItem.Key, "Child"); - var childTranslations = new List - { - new DictionaryTranslation(languageNbNo, "BarnVerdi"), - new DictionaryTranslation(languageEnGb, "ChildValue") - }; - childItem.Translations = childTranslations; - ServiceContext.LocalizationService.Save(childItem); - } + } } diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects.cs b/src/Umbraco.Tests/TestHelpers/TestObjects.cs index cb36e6ca5f..120b0bcabb 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects.cs @@ -12,6 +12,7 @@ using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Events; using Umbraco.Core.IO; using Umbraco.Core.Logging; +using Umbraco.Core.Packaging; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Persistence.Repositories; @@ -167,7 +168,10 @@ namespace Umbraco.Tests.TestHelpers GetRepo(c))); var macroService = GetLazyService(factory, c => new MacroService(scopeProvider, logger, eventMessagesFactory, GetRepo(c), GetRepo(c))); - var packagingService = GetLazyService(factory, c => new PackagingService(logger, contentService.Value, contentTypeService.Value, mediaService.Value, macroService.Value, dataTypeService.Value, fileService.Value, localizationService.Value, entityService.Value, userService.Value, scopeProvider, urlSegmentProviders, GetRepo(c), GetRepo(c), new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty())))); + var packagingService = GetLazyService(factory, c => new PackagingService( + logger, contentService.Value, contentTypeService.Value, macroService.Value, dataTypeService.Value, fileService.Value, localizationService.Value, entityService.Value, scopeProvider, GetRepo(c), GetRepo(c), new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty())), + new PackageCreation(contentService.Value, contentTypeService.Value, dataTypeService.Value, fileService.Value, macroService.Value, localizationService.Value, + new EntityXmlSerializer(contentService.Value, mediaService.Value, dataTypeService.Value, userService.Value, localizationService.Value, contentTypeService.Value, urlSegmentProviders), logger))); var relationService = GetLazyService(factory, c => new RelationService(scopeProvider, logger, eventMessagesFactory, entityService.Value, GetRepo(c), GetRepo(c))); var treeService = GetLazyService(factory, c => new ApplicationTreeService(logger, cache, typeLoader)); var tagService = GetLazyService(factory, c => new TagService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); diff --git a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs index a2a0c35c56..0729aa0b6e 100644 --- a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs +++ b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs @@ -268,6 +268,7 @@ namespace Umbraco.Tests.TestHelpers DefaultCultureAccessor, Logger, Factory.GetInstance(), new SiteDomainHelper(), + Factory.GetInstance(), ContentTypesCache, null, true, Options.PublishedRepositoryEvents); diff --git a/src/Umbraco.Tests/UI/LegacyDialogTests.cs b/src/Umbraco.Tests/UI/LegacyDialogTests.cs index be9b0d4d7e..5c8a621e10 100644 --- a/src/Umbraco.Tests/UI/LegacyDialogTests.cs +++ b/src/Umbraco.Tests/UI/LegacyDialogTests.cs @@ -24,7 +24,6 @@ namespace Umbraco.Tests.UI } [TestCase(typeof(macroTasks), Constants.Applications.Settings)] - [TestCase(typeof(CreatedPackageTasks), Constants.Applications.Packages)] public void Check_Assigned_Apps_For_Tasks(Type taskType, string app) { var task = (LegacyDialogTask)Activator.CreateInstance(taskType); diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index 661ccb6ab8..12b830407e 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -139,6 +139,7 @@ + diff --git a/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs b/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs index 0ad3bff109..192b0975d1 100644 --- a/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs +++ b/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs @@ -419,11 +419,13 @@ namespace Umbraco.Tests.Web.Mvc //var provider = new ScopeUnitOfWorkProvider(databaseFactory, new RepositoryFactory(Mock.Of())); var scopeProvider = TestObjects.GetScopeProvider(Mock.Of()); var factory = Mock.Of(); - _service = new PublishedSnapshotService(svcCtx, factory, scopeProvider, cache, Enumerable.Empty(), + _service = new PublishedSnapshotService(svcCtx, factory, scopeProvider, cache, null, null, null, null, null, new TestDefaultCultureAccessor(), - Current.Logger, TestObjects.GetGlobalSettings(), new SiteDomainHelper(), null, true, false); // no events + Current.Logger, TestObjects.GetGlobalSettings(), new SiteDomainHelper(), + Factory.GetInstance(), + null, true, false); // no events var http = GetHttpContextFactory(url, routeData).HttpContext; diff --git a/src/Umbraco.Web/Composing/Current.cs b/src/Umbraco.Web/Composing/Current.cs index ffe07393e6..3e7c14147b 100644 --- a/src/Umbraco.Web/Composing/Current.cs +++ b/src/Umbraco.Web/Composing/Current.cs @@ -11,6 +11,7 @@ using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Persistence; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; +using Umbraco.Core.Packaging; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Scoping; using Umbraco.Core.Services; @@ -215,6 +216,8 @@ namespace Umbraco.Web.Composing internal static ManifestValueValidatorCollection ManifestValidators => CoreCurrent.ManifestValidators; + internal static PackageActionRunner PackageActionRunner => CoreCurrent.PackageActionRunner; + internal static PackageActionCollection PackageActions => CoreCurrent.PackageActions; internal static PropertyValueConverterCollection PropertyValueConverters => CoreCurrent.PropertyValueConverters; diff --git a/src/Umbraco.Web/Editors/ContentTypeController.cs b/src/Umbraco.Web/Editors/ContentTypeController.cs index 397f6b3e9d..0d56b34617 100644 --- a/src/Umbraco.Web/Editors/ContentTypeController.cs +++ b/src/Umbraco.Web/Editors/ContentTypeController.cs @@ -11,10 +11,15 @@ using System.Web.Http; using System.Xml; using System.Xml.Linq; using Umbraco.Core; +using Umbraco.Core.Cache; +using Umbraco.Core.Configuration; +using Umbraco.Core.Dictionary; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models; +using Umbraco.Core.Persistence; using Umbraco.Core.Services; +using Umbraco.Core.Services.Implement; using Umbraco.Web.Composing; using Umbraco.Web.Models; using Umbraco.Web.Models.ContentEditing; @@ -40,6 +45,13 @@ namespace Umbraco.Web.Editors [EnableOverrideAuthorization] public class ContentTypeController : ContentTypeControllerBase { + private readonly IEntityXmlSerializer _serializer; + + public ContentTypeController(IEntityXmlSerializer serializer, ICultureDictionaryFactory cultureDictionaryFactory, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) : base(cultureDictionaryFactory, globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) + { + _serializer = serializer; + } + public int GetCount() { return Services.ContentTypeService.Count(); @@ -444,11 +456,7 @@ namespace Umbraco.Web.Editors var contentType = Services.ContentTypeService.Get(id); if (contentType == null) throw new NullReferenceException("No content type found with id " + id); - var serializer = new EntityXmlSerializer(); - var xml = serializer.Serialize( - Services.DataTypeService, - Services.ContentTypeService, - contentType); + var xml = _serializer.Serialize(contentType); var response = new HttpResponseMessage { @@ -559,5 +567,7 @@ namespace Umbraco.Web.Editors return model; } + + } } diff --git a/src/Umbraco.Web/Editors/ContentTypeControllerBase.cs b/src/Umbraco.Web/Editors/ContentTypeControllerBase.cs index 2572bed816..898208319a 100644 --- a/src/Umbraco.Web/Editors/ContentTypeControllerBase.cs +++ b/src/Umbraco.Web/Editors/ContentTypeControllerBase.cs @@ -7,9 +7,13 @@ using System.Text; using System.Web.Http; using AutoMapper; using Umbraco.Core; +using Umbraco.Core.Cache; +using Umbraco.Core.Configuration; using Umbraco.Core.Dictionary; using Umbraco.Core.Exceptions; +using Umbraco.Core.Logging; using Umbraco.Core.Models; +using Umbraco.Core.Persistence; using Umbraco.Core.Services; using Umbraco.Web.Composing; using Umbraco.Web.Models.ContentEditing; @@ -26,8 +30,16 @@ namespace Umbraco.Web.Editors public abstract class ContentTypeControllerBase : UmbracoAuthorizedJsonController where TContentType : class, IContentTypeComposition { + private readonly ICultureDictionaryFactory _cultureDictionaryFactory; private ICultureDictionary _cultureDictionary; + protected ContentTypeControllerBase(ICultureDictionaryFactory cultureDictionaryFactory, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) : base(globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) + { + _cultureDictionaryFactory = cultureDictionaryFactory; + } + + + /// /// Returns the available composite content types for a given content type /// @@ -536,6 +548,6 @@ namespace Umbraco.Web.Editors } private ICultureDictionary CultureDictionary - => _cultureDictionary ?? (_cultureDictionary = Current.CultureDictionaryFactory.CreateDictionary()); + => _cultureDictionary ?? (_cultureDictionary = _cultureDictionaryFactory.CreateDictionary()); } } diff --git a/src/Umbraco.Web/Editors/MediaTypeController.cs b/src/Umbraco.Web/Editors/MediaTypeController.cs index f8455fc01d..f2b8fd3dda 100644 --- a/src/Umbraco.Web/Editors/MediaTypeController.cs +++ b/src/Umbraco.Web/Editors/MediaTypeController.cs @@ -15,6 +15,11 @@ using System; using System.ComponentModel; using System.Web.Http.Controllers; using Umbraco.Core; +using Umbraco.Core.Cache; +using Umbraco.Core.Configuration; +using Umbraco.Core.Dictionary; +using Umbraco.Core.Logging; +using Umbraco.Core.Persistence; using Umbraco.Web.Composing; namespace Umbraco.Web.Editors @@ -32,6 +37,10 @@ namespace Umbraco.Web.Editors [MediaTypeControllerControllerConfiguration] public class MediaTypeController : ContentTypeControllerBase { + public MediaTypeController(ICultureDictionaryFactory cultureDictionaryFactory, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) : base(cultureDictionaryFactory, globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) + { + } + /// /// Configures this controller with a custom action selector /// @@ -302,5 +311,7 @@ namespace Umbraco.Web.Editors getContentType: i => Services.MediaTypeService.Get(i), doCopy: (type, i) => Services.MediaTypeService.Copy(type, i)); } + + } } diff --git a/src/Umbraco.Web/Editors/MemberTypeController.cs b/src/Umbraco.Web/Editors/MemberTypeController.cs index 77ff974aaa..3abc0035d3 100644 --- a/src/Umbraco.Web/Editors/MemberTypeController.cs +++ b/src/Umbraco.Web/Editors/MemberTypeController.cs @@ -6,7 +6,13 @@ using System.Net.Http; using System.Web.Http; using System.Web.Security; using AutoMapper; +using Umbraco.Core; +using Umbraco.Core.Cache; +using Umbraco.Core.Configuration; +using Umbraco.Core.Dictionary; +using Umbraco.Core.Logging; using Umbraco.Core.Models; +using Umbraco.Core.Persistence; using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Web.Models.ContentEditing; @@ -24,6 +30,10 @@ namespace Umbraco.Web.Editors [UmbracoTreeAuthorize(new string[] { Constants.Trees.MemberTypes, Constants.Trees.Members})] public class MemberTypeController : ContentTypeControllerBase { + public MemberTypeController(ICultureDictionaryFactory cultureDictionaryFactory, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) : base(cultureDictionaryFactory, globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) + { + } + private readonly MembershipProvider _provider = Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider(); [UmbracoTreeAuthorize(Constants.Trees.MemberTypes)] @@ -166,5 +176,7 @@ namespace Umbraco.Web.Editors return display; } + + } } diff --git a/src/Umbraco.Web/Editors/PackageController.cs b/src/Umbraco.Web/Editors/PackageController.cs index 8b9e15f9d1..dfb8823a39 100644 --- a/src/Umbraco.Web/Editors/PackageController.cs +++ b/src/Umbraco.Web/Editors/PackageController.cs @@ -4,10 +4,12 @@ using System.Net; using System.Net.Http; using System.Net.Http.Formatting; using System.Web.Http; -using umbraco.cms.businesslogic.packager; +using Umbraco.Core.Models.Packaging; +using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Mvc; using Umbraco.Web.WebApi; using Umbraco.Web.WebApi.Filters; +using Umbraco.Web._Legacy.Packager.PackageInstance; namespace Umbraco.Web.Editors { @@ -21,14 +23,12 @@ namespace Umbraco.Web.Editors [UmbracoApplicationAuthorize(Core.Constants.Applications.Packages)] public class PackageController : UmbracoAuthorizedJsonController { - [HttpGet] - public List GetCreatedPackages() + public List GetCreatedPackages() { return CreatedPackage.GetAllCreatedPackages().Select(x => x.Data).ToList(); } - [HttpGet] - public PackageInstance GetCreatedPackageById(int id) + public PackageDefinition GetCreatedPackageById(int id) { var package = CreatedPackage.GetById(id); if (package == null) @@ -37,44 +37,46 @@ namespace Umbraco.Web.Editors return package.Data; } - [HttpPost] - public PackageInstance PostCreatePackage(PackageInstance model) + public PackageDefinition PostUpdatePackage(PackageDefinition model) { + var package = CreatedPackage.GetById(model.Id); + if (package == null) + throw new HttpResponseException(HttpStatusCode.NotFound); + if (ModelState.IsValid == false) { //Throw/bubble up errors - throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState)); + throw new HttpResponseException(Request.CreateValidationErrorResponse(ModelState)); } - - var package = new CreatedPackage - { - Data = model - }; - //If ID is 0 & PackageGuid is null - its brand new - if(model.Id == 0 && model.PackageGuid == null) - { - //Brand new - package = CreatedPackage.MakeNew(model.Name); - - var packageId = package.Data.Id; - var packageGuid = package.Data.PackageGuid; - - //Need to reset the package ID - as the posted model the package ID is always 0 - //MakeNew will init create the XML & update the file and give us an ID to use - package.Data = model; - package.Data.Id = packageId; - package.Data.PackageGuid = packageGuid; - } - - //Save then publish - package.Save(); - package.Publish(); + package.Data = model; //We should have packagepath populated now return package.Data; } + public PackageDefinition PostCreatePackage(PackageDefinition model) + { + //creating requires an empty model/package id + if (model.Id != 0 || model.PackageGuid != null) + throw new HttpResponseException(HttpStatusCode.NotFound); + + if (ModelState.IsValid == false) + { + //Throw/bubble up errors + throw new HttpResponseException(Request.CreateValidationErrorResponse(ModelState)); + } + + //save it + Services.PackagingService.SavePackageDefinition(model); + + //then publish to get the file + //package.Publish(); + //TODO: We need a link to the downloadable zip file, in packagepath ? + + return model; + } + /// /// Deletes a created package /// diff --git a/src/Umbraco.Web/Editors/PackageInstallController.cs b/src/Umbraco.Web/Editors/PackageInstallController.cs index 4898c54616..b58ed05bde 100644 --- a/src/Umbraco.Web/Editors/PackageInstallController.cs +++ b/src/Umbraco.Web/Editors/PackageInstallController.cs @@ -9,12 +9,15 @@ using System.Threading.Tasks; using System.Web.Http; using System.Xml; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Configuration; using Umbraco.Core.Events; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models; -using Umbraco.Core.Packaging.Models; +using Umbraco.Core.Models.Packaging; +using Umbraco.Core.Packaging; +using Umbraco.Core.Persistence; using Umbraco.Core.Services; using Umbraco.Core.Services.Implement; using Umbraco.Web.Composing; @@ -40,6 +43,16 @@ namespace Umbraco.Web.Editors [UmbracoApplicationAuthorize(Core.Constants.Applications.Packages)] public class PackageInstallController : UmbracoAuthorizedJsonController { + private readonly PackageActionRunner _packageActionRunner; + + public PackageInstallController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, + ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, + IProfilingLogger logger, IRuntimeState runtimeState, PackageActionRunner packageActionRunner) + : base(globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) + { + _packageActionRunner = packageActionRunner; + } + /// /// This checks if this package & version is alraedy installed /// @@ -128,14 +141,14 @@ namespace Umbraco.Web.Editors //Remove Document Types var contentTypes = new List(); var contentTypeService = Services.ContentTypeService; - foreach (var item in pack.Data.Documenttypes.ToArray()) + foreach (var item in pack.Data.DocumentTypes.ToArray()) { int nId; if (int.TryParse(item, out nId) == false) continue; var contentType = contentTypeService.Get(nId); if (contentType == null) continue; contentTypes.Add(contentType); - pack.Data.Documenttypes.Remove(nId.ToString(CultureInfo.InvariantCulture)); + pack.Data.DocumentTypes.Remove(nId.ToString(CultureInfo.InvariantCulture)); } //Order the DocumentTypes before removing them @@ -195,8 +208,7 @@ namespace Umbraco.Web.Editors { try { - global::Umbraco.Web._Legacy.Packager.PackageInstance.PackageAction - .UndoPackageAction(pack.Data.Name, n.Attributes["alias"].Value, n); + _packageActionRunner.UndoPackageAction(pack.Data.Name, n.Attributes["alias"].Value, n); } catch (Exception ex) { diff --git a/src/Umbraco.Web/Editors/UmbracoAuthorizedJsonController.cs b/src/Umbraco.Web/Editors/UmbracoAuthorizedJsonController.cs index 2b1fce884d..3baa5e85ff 100644 --- a/src/Umbraco.Web/Editors/UmbracoAuthorizedJsonController.cs +++ b/src/Umbraco.Web/Editors/UmbracoAuthorizedJsonController.cs @@ -1,4 +1,10 @@ -using Umbraco.Web.WebApi; +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.WebApi; using Umbraco.Web.WebApi.Filters; namespace Umbraco.Web.Editors @@ -13,5 +19,26 @@ namespace Umbraco.Web.Editors [ValidateAngularAntiForgeryToken] [AngularJsonOnlyConfiguration] public abstract class UmbracoAuthorizedJsonController : UmbracoAuthorizedApiController - { } + { + /// + /// Initializes a new instance of the with auto dependencies. + /// + protected UmbracoAuthorizedJsonController() + { + } + + /// + /// Initializes a new instance of the class with all its dependencies. + /// + /// + /// + /// + /// + /// + /// + /// + protected UmbracoAuthorizedJsonController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) : base(globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) + { + } + } } diff --git a/src/Umbraco.Web/Models/ContentEditing/UmbracoEntityTypes.cs b/src/Umbraco.Web/Models/ContentEditing/UmbracoEntityTypes.cs index 74e82ecfe9..04d06845d9 100644 --- a/src/Umbraco.Web/Models/ContentEditing/UmbracoEntityTypes.cs +++ b/src/Umbraco.Web/Models/ContentEditing/UmbracoEntityTypes.cs @@ -87,5 +87,7 @@ namespace Umbraco.Web.Models.ContentEditing /// Property Group ///
    PropertyGroup + + //TODO: Dictionary? } } diff --git a/src/Umbraco.Web/PublishedCache/NuCache/MemberCache.cs b/src/Umbraco.Web/PublishedCache/NuCache/MemberCache.cs index ce8b5835e2..f2392c9c3d 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/MemberCache.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/MemberCache.cs @@ -8,30 +8,29 @@ using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Security; using Umbraco.Core.Services; +using Umbraco.Core.Services.Implement; using Umbraco.Core.Xml.XPath; using Umbraco.Web.PublishedCache.NuCache.Navigable; namespace Umbraco.Web.PublishedCache.NuCache { - class MemberCache : IPublishedMemberCache, INavigableData + internal class MemberCache : IPublishedMemberCache, INavigableData { private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor; public readonly IVariationContextAccessor VariationContextAccessor; + private readonly IEntityXmlSerializer _entitySerializer; private readonly ICacheProvider _snapshotCache; private readonly IMemberService _memberService; - private readonly IDataTypeService _dataTypeService; - private readonly ILocalizationService _localizationService; private readonly PublishedContentTypeCache _contentTypeCache; private readonly bool _previewDefault; - public MemberCache(bool previewDefault, ICacheProvider snapshotCache, IMemberService memberService, IDataTypeService dataTypeService, ILocalizationService localizationService, PublishedContentTypeCache contentTypeCache, IPublishedSnapshotAccessor publishedSnapshotAccessor, IVariationContextAccessor variationContextAccessor) + public MemberCache(bool previewDefault, ICacheProvider snapshotCache, IMemberService memberService, PublishedContentTypeCache contentTypeCache, IPublishedSnapshotAccessor publishedSnapshotAccessor, IVariationContextAccessor variationContextAccessor, IEntityXmlSerializer entitySerializer) { _snapshotCache = snapshotCache; _publishedSnapshotAccessor = publishedSnapshotAccessor; VariationContextAccessor = variationContextAccessor; + _entitySerializer = entitySerializer; _memberService = memberService; - _dataTypeService = dataTypeService; - _localizationService = localizationService; _previewDefault = previewDefault; _contentTypeCache = contentTypeCache; } @@ -141,7 +140,7 @@ namespace Umbraco.Web.PublishedCache.NuCache var result = _memberService.GetById(id); if (result == null) return null; - var s = EntityXmlSerializer.Serialize(_dataTypeService, _localizationService, result); + var s = _entitySerializer.Serialize(result); var n = s.GetXmlNode(); return n.CreateNavigator(); } diff --git a/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs b/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs index 3aa33f0e2f..4ebddee6dc 100755 --- a/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs @@ -43,6 +43,7 @@ namespace Umbraco.Web.PublishedCache.NuCache private readonly IMemberRepository _memberRepository; private readonly IGlobalSettings _globalSettings; private readonly ISiteDomainHelper _siteDomainHelper; + private readonly IEntityXmlSerializer _entitySerializer; private readonly IDefaultCultureAccessor _defaultCultureAccessor; // volatile because we read it with no lock @@ -85,7 +86,8 @@ namespace Umbraco.Web.PublishedCache.NuCache ILogger logger, IScopeProvider scopeProvider, IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository, IDefaultCultureAccessor defaultCultureAccessor, - IDataSource dataSource, IGlobalSettings globalSettings, ISiteDomainHelper siteDomainHelper) + IDataSource dataSource, IGlobalSettings globalSettings, ISiteDomainHelper siteDomainHelper, + IEntityXmlSerializer entitySerializer) : base(publishedSnapshotAccessor, variationContextAccessor) { //if (Interlocked.Increment(ref _singletonCheck) > 1) @@ -102,6 +104,7 @@ namespace Umbraco.Web.PublishedCache.NuCache _defaultCultureAccessor = defaultCultureAccessor; _globalSettings = globalSettings; _siteDomainHelper = siteDomainHelper; + _entitySerializer = entitySerializer; // we always want to handle repository events, configured or not // assuming no repository event will trigger before the whole db is ready @@ -1011,7 +1014,7 @@ namespace Umbraco.Web.PublishedCache.NuCache { ContentCache = new ContentCache(previewDefault, contentSnap, snapshotCache, elementsCache, domainHelper, _globalSettings, _serviceContext.LocalizationService), MediaCache = new MediaCache(previewDefault, mediaSnap, snapshotCache, elementsCache), - MemberCache = new MemberCache(previewDefault, snapshotCache, _serviceContext.MemberService, _serviceContext.DataTypeService, _serviceContext.LocalizationService, memberTypeCache, PublishedSnapshotAccessor, VariationContextAccessor), + MemberCache = new MemberCache(previewDefault, snapshotCache, _serviceContext.MemberService, memberTypeCache, PublishedSnapshotAccessor, VariationContextAccessor, _entitySerializer), DomainCache = domainCache, SnapshotCache = snapshotCache, ElementsCache = elementsCache diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs index 229a981510..7ec935139e 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs @@ -17,6 +17,7 @@ using Umbraco.Core.Xml; using Umbraco.Examine; using Umbraco.Core.Cache; using Umbraco.Core.Services; +using Umbraco.Core.Services.Implement; using Umbraco.Web.Composing; namespace Umbraco.Web.PublishedCache.XmlPublishedCache @@ -37,14 +38,14 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache // method GetExamineManagerSafe(). // private readonly ISearcher _searchProvider; - private readonly IIndex _indexProvider; private readonly XmlStore _xmlStore; private readonly PublishedContentTypeCache _contentTypeCache; + private readonly IEntityXmlSerializer _entitySerializer; // must be specified by the ctor private readonly ICacheProvider _cacheProvider; - public PublishedMediaCache(XmlStore xmlStore, IMediaService mediaService, IUserService userService, ICacheProvider cacheProvider, PublishedContentTypeCache contentTypeCache) + public PublishedMediaCache(XmlStore xmlStore, IMediaService mediaService, IUserService userService, ICacheProvider cacheProvider, PublishedContentTypeCache contentTypeCache, IEntityXmlSerializer entitySerializer) : base(false) { _mediaService = mediaService ?? throw new ArgumentNullException(nameof(mediaService)); @@ -53,6 +54,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache _cacheProvider = cacheProvider; _xmlStore = xmlStore; _contentTypeCache = contentTypeCache; + _entitySerializer = entitySerializer; } /// @@ -61,18 +63,18 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache /// /// /// - /// /// /// - internal PublishedMediaCache(IMediaService mediaService, IUserService userService, ISearcher searchProvider, BaseIndexProvider indexProvider, ICacheProvider cacheProvider, PublishedContentTypeCache contentTypeCache) + /// + internal PublishedMediaCache(IMediaService mediaService, IUserService userService, ISearcher searchProvider, ICacheProvider cacheProvider, PublishedContentTypeCache contentTypeCache, IEntityXmlSerializer entitySerializer) : base(false) { _mediaService = mediaService ?? throw new ArgumentNullException(nameof(mediaService)); _userService = userService ?? throw new ArgumentNullException(nameof(userService)); _searchProvider = searchProvider ?? throw new ArgumentNullException(nameof(searchProvider)); - _indexProvider = indexProvider ?? throw new ArgumentNullException(nameof(indexProvider)); _cacheProvider = cacheProvider; _contentTypeCache = contentTypeCache; + _entitySerializer = entitySerializer; } static PublishedMediaCache() @@ -555,14 +557,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache return Enumerable.Empty(); } - var serialized = EntityXmlSerializer.Serialize( - Current.Services.MediaService, - Current.Services.DataTypeService, - Current.Services.UserService, - Current.Services.LocalizationService, - Current.UrlSegmentProviders, - media, - true); + var serialized = _entitySerializer.Serialize(media, true); var mediaIterator = serialized.CreateNavigator().Select("/"); diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedSnapshotService.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedSnapshotService.cs index 78585ba2e2..e286e9d95c 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedSnapshotService.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedSnapshotService.cs @@ -34,6 +34,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache private readonly IGlobalSettings _globalSettings; private readonly IDefaultCultureAccessor _defaultCultureAccessor; private readonly ISiteDomainHelper _siteDomainHelper; + private readonly IEntityXmlSerializer _entitySerializer; #region Constructors @@ -42,20 +43,20 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache IPublishedContentTypeFactory publishedContentTypeFactory, IScopeProvider scopeProvider, ICacheProvider requestCache, - IEnumerable segmentProviders, IPublishedSnapshotAccessor publishedSnapshotAccessor, IVariationContextAccessor variationContextAccessor, IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository, IDefaultCultureAccessor defaultCultureAccessor, ILogger logger, IGlobalSettings globalSettings, ISiteDomainHelper siteDomainHelper, + IEntityXmlSerializer entitySerializer, MainDom mainDom, bool testing = false, bool enableRepositoryEvents = true) - : this(serviceContext, publishedContentTypeFactory, scopeProvider, requestCache, segmentProviders, + : this(serviceContext, publishedContentTypeFactory, scopeProvider, requestCache, publishedSnapshotAccessor, variationContextAccessor, documentRepository, mediaRepository, memberRepository, defaultCultureAccessor, - logger, globalSettings, siteDomainHelper, null, mainDom, testing, enableRepositoryEvents) + logger, globalSettings, siteDomainHelper, entitySerializer, null, mainDom, testing, enableRepositoryEvents) { } // used in some tests @@ -69,27 +70,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache ILogger logger, IGlobalSettings globalSettings, ISiteDomainHelper siteDomainHelper, - PublishedContentTypeCache contentTypeCache, - MainDom mainDom, - bool testing, bool enableRepositoryEvents) - : this(serviceContext, publishedContentTypeFactory, scopeProvider, requestCache, Enumerable.Empty(), - publishedSnapshotAccessor, variationContextAccessor, - documentRepository, mediaRepository, memberRepository, - defaultCultureAccessor, - logger, globalSettings, siteDomainHelper, contentTypeCache, mainDom, testing, enableRepositoryEvents) - { } - - private PublishedSnapshotService(ServiceContext serviceContext, - IPublishedContentTypeFactory publishedContentTypeFactory, - IScopeProvider scopeProvider, - ICacheProvider requestCache, - IEnumerable segmentProviders, - IPublishedSnapshotAccessor publishedSnapshotAccessor, IVariationContextAccessor variationContextAccessor, - IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository, - IDefaultCultureAccessor defaultCultureAccessor, - ILogger logger, - IGlobalSettings globalSettings, - ISiteDomainHelper siteDomainHelper, + IEntityXmlSerializer entitySerializer, PublishedContentTypeCache contentTypeCache, MainDom mainDom, bool testing, bool enableRepositoryEvents) @@ -100,9 +81,9 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache _contentTypeCache = contentTypeCache ?? new PublishedContentTypeCache(serviceContext.ContentTypeService, serviceContext.MediaTypeService, serviceContext.MemberTypeService, publishedContentTypeFactory, logger); - _xmlStore = new XmlStore(serviceContext, scopeProvider, _routesCache, - _contentTypeCache, segmentProviders, publishedSnapshotAccessor, mainDom, testing, enableRepositoryEvents, - documentRepository, mediaRepository, memberRepository, globalSettings); + _xmlStore = new XmlStore(serviceContext.ContentTypeService, serviceContext.ContentService, scopeProvider, _routesCache, + _contentTypeCache, publishedSnapshotAccessor, mainDom, testing, enableRepositoryEvents, + documentRepository, mediaRepository, memberRepository, globalSettings, entitySerializer); _domainService = serviceContext.DomainService; _memberService = serviceContext.MemberService; @@ -113,6 +94,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache _requestCache = requestCache; _globalSettings = globalSettings; _siteDomainHelper = siteDomainHelper; + _entitySerializer = entitySerializer; } public override void Dispose() @@ -157,7 +139,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache return new PublishedSnapshot( new PublishedContentCache(_xmlStore, domainCache, _requestCache, _globalSettings, _siteDomainHelper, _contentTypeCache, _routesCache, previewToken), - new PublishedMediaCache(_xmlStore, _mediaService, _userService, _requestCache, _contentTypeCache), + new PublishedMediaCache(_xmlStore, _mediaService, _userService, _requestCache, _contentTypeCache, _entitySerializer), new PublishedMemberCache(_xmlStore, _requestCache, _memberService, _contentTypeCache), domainCache); } diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlStore.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlStore.cs index fef5039579..614515e433 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlStore.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlStore.cs @@ -44,15 +44,16 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache private readonly IMediaRepository _mediaRepository; private readonly IMemberRepository _memberRepository; private readonly IGlobalSettings _globalSettings; + private readonly IEntityXmlSerializer _entitySerializer; private XmlStoreFilePersister _persisterTask; private volatile bool _released; private bool _withRepositoryEvents; private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor; private readonly PublishedContentTypeCache _contentTypeCache; - private readonly IEnumerable _segmentProviders; private readonly RoutesCache _routesCache; - private readonly ServiceContext _serviceContext; // fixme WHY + private readonly IContentTypeService _contentTypeService; + private readonly IContentService _contentService; private readonly IScopeProvider _scopeProvider; #region Constructors @@ -61,22 +62,23 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache /// Initializes a new instance of the class. /// /// The default constructor will boot the cache, load data from file or database, /// wire events in order to manage changes, etc. - public XmlStore(ServiceContext serviceContext, IScopeProvider scopeProvider, RoutesCache routesCache, PublishedContentTypeCache contentTypeCache, - IEnumerable segmentProviders, IPublishedSnapshotAccessor publishedSnapshotAccessor, MainDom mainDom, IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository, IGlobalSettings globalSettings) - : this(serviceContext, scopeProvider, routesCache, contentTypeCache, segmentProviders, publishedSnapshotAccessor, mainDom, false, false, documentRepository, mediaRepository, memberRepository, globalSettings) + public XmlStore(IContentTypeService contentTypeService, IContentService contentService, IScopeProvider scopeProvider, RoutesCache routesCache, PublishedContentTypeCache contentTypeCache, + IPublishedSnapshotAccessor publishedSnapshotAccessor, MainDom mainDom, IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository, IGlobalSettings globalSettings, IEntityXmlSerializer entitySerializer) + : this(contentTypeService, contentService, scopeProvider, routesCache, contentTypeCache, publishedSnapshotAccessor, mainDom, false, false, documentRepository, mediaRepository, memberRepository, globalSettings, entitySerializer) { } // internal for unit tests // no file nor db, no config check // fixme - er, we DO have a DB? - internal XmlStore(ServiceContext serviceContext, IScopeProvider scopeProvider, RoutesCache routesCache, PublishedContentTypeCache contentTypeCache, - IEnumerable segmentProviders, IPublishedSnapshotAccessor publishedSnapshotAccessor, MainDom mainDom, - bool testing, bool enableRepositoryEvents, IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository, IGlobalSettings globalSettings) + internal XmlStore(IContentTypeService contentTypeService, IContentService contentService, IScopeProvider scopeProvider, RoutesCache routesCache, PublishedContentTypeCache contentTypeCache, + IPublishedSnapshotAccessor publishedSnapshotAccessor, MainDom mainDom, + bool testing, bool enableRepositoryEvents, IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository, IGlobalSettings globalSettings, IEntityXmlSerializer entitySerializer) { if (testing == false) EnsureConfigurationIsValid(); - _serviceContext = serviceContext; + _contentTypeService = contentTypeService; + _contentService = contentService; _scopeProvider = scopeProvider; _routesCache = routesCache; _contentTypeCache = contentTypeCache; @@ -85,8 +87,8 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache _mediaRepository = mediaRepository; _memberRepository = memberRepository; _globalSettings = globalSettings; + _entitySerializer = entitySerializer; _xmlFileName = IOHelper.MapPath(SystemFiles.GetContentCacheXml(_globalSettings)); - _segmentProviders = segmentProviders; if (testing) { @@ -399,7 +401,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache try { var dtdInner = new StringBuilder(); - var contentTypes = _serviceContext.ContentTypeService.GetAll(); + var contentTypes = _contentTypeService.GetAll(); // though aliases should be safe and non null already? var aliases = contentTypes.Select(x => x.Alias.ToSafeAlias()).WhereNotNull(); foreach (var alias in aliases) @@ -556,7 +558,7 @@ AND (umbracoNode.id=@id)"; public XmlDocument GetPreviewXml(int contentId, bool includeSubs) { - var content = _serviceContext.ContentService.GetById(contentId); + var content = _contentService.GetById(contentId); var doc = (XmlDocument)Xml.Clone(); if (content == null) return doc; @@ -1065,7 +1067,7 @@ ORDER BY umbracoNode.level, umbracoNode.sortOrder"; continue; } - var content = _serviceContext.ContentService.GetById(payload.Id); + var content = _contentService.GetById(payload.Id); var current = safeXml.Xml.GetElementById(payload.Id.ToInvariantString()); if (content == null || content.Published == false || content.Trashed) @@ -1536,7 +1538,7 @@ ORDER BY umbracoNode.level, umbracoNode.sortOrder"; var entity = args.Entity; // serialize edit values for preview - var editXml = EntityXmlSerializer.Serialize(_serviceContext.ContentService, _serviceContext.DataTypeService, _serviceContext.UserService, _serviceContext.LocalizationService, _segmentProviders, entity, false).ToDataString(); + var editXml = _entitySerializer.Serialize(entity, false).ToDataString(); // change below to write only one row - not one per version var dto1 = new PreviewXmlDto @@ -1565,7 +1567,7 @@ ORDER BY umbracoNode.level, umbracoNode.sortOrder"; return; // serialize published values for content cache - var publishedXml = EntityXmlSerializer.Serialize(_serviceContext.ContentService, _serviceContext.DataTypeService, _serviceContext.UserService, _serviceContext.LocalizationService, _segmentProviders, entity, true).ToDataString(); + var publishedXml = _entitySerializer.Serialize(entity, true).ToDataString(); var dto2 = new ContentXmlDto { NodeId = entity.Id, Xml = publishedXml }; OnRepositoryRefreshed(db, dto2); @@ -1581,7 +1583,7 @@ ORDER BY umbracoNode.level, umbracoNode.sortOrder"; if (entity.Trashed) db.Execute("DELETE FROM cmsContentXml WHERE nodeId=@id", new { id = entity.Id }); - var xml = EntityXmlSerializer.Serialize(_serviceContext.MediaService, _serviceContext.DataTypeService, _serviceContext.UserService, _serviceContext.LocalizationService, _segmentProviders, entity).ToDataString(); + var xml = _entitySerializer.Serialize(entity).ToDataString(); var dto1 = new ContentXmlDto { NodeId = entity.Id, Xml = xml }; OnRepositoryRefreshed(db, dto1); @@ -1592,7 +1594,7 @@ ORDER BY umbracoNode.level, umbracoNode.sortOrder"; var db = args.Scope.Database; var entity = args.Entity; - var xml = EntityXmlSerializer.Serialize(_serviceContext.DataTypeService, _serviceContext.LocalizationService, entity).ToDataString(); + var xml = _entitySerializer.Serialize(entity).ToDataString(); var dto1 = new ContentXmlDto { NodeId = entity.Id, Xml = xml }; OnRepositoryRefreshed(db, dto1); @@ -1749,7 +1751,7 @@ WHERE cmsContentXml.nodeId IN ( var descendants = _documentRepository.GetPage(query, pageIndex++, groupSize, out total, null, Ordering.By("Path")); const bool published = true; // contentXml contains published content! var items = descendants.Select(c => new ContentXmlDto { NodeId = c.Id, Xml = - EntityXmlSerializer.Serialize(_serviceContext.ContentService, _serviceContext.DataTypeService, _serviceContext.UserService, _serviceContext.LocalizationService, _segmentProviders, c, published).ToDataString() }).ToArray(); + _entitySerializer.Serialize(c, published).ToDataString() }).ToArray(); db.BulkInsertRecords(items); processed += items.Length; } while (processed < total); @@ -1824,7 +1826,7 @@ WHERE cmsPreviewXml.nodeId IN ( var items = descendants.Select(c => new PreviewXmlDto { NodeId = c.Id, - Xml = EntityXmlSerializer.Serialize(_serviceContext.ContentService, _serviceContext.DataTypeService, _serviceContext.UserService, _serviceContext.LocalizationService, _segmentProviders, c, published).ToDataString() + Xml = _entitySerializer.Serialize(c, published).ToDataString() }).ToArray(); db.BulkInsertRecords(items); processed += items.Length; @@ -1894,7 +1896,7 @@ WHERE cmsContentXml.nodeId IN ( { var descendants = _mediaRepository.GetPage(query, pageIndex++, groupSize, out total, null, Ordering.By("Path")); var items = descendants.Select(m => new ContentXmlDto { NodeId = m.Id, Xml = - EntityXmlSerializer.Serialize(_serviceContext.MediaService, _serviceContext.DataTypeService, _serviceContext.UserService, _serviceContext.LocalizationService, _segmentProviders, m).ToDataString() }).ToArray(); + _entitySerializer.Serialize(m).ToDataString() }).ToArray(); db.BulkInsertRecords(items); processed += items.Length; } while (processed < total); @@ -1962,7 +1964,7 @@ WHERE cmsContentXml.nodeId IN ( do { var descendants = _memberRepository.GetPage(query, pageIndex++, groupSize, out total, null, Ordering.By("Path")); - var items = descendants.Select(m => new ContentXmlDto { NodeId = m.Id, Xml = EntityXmlSerializer.Serialize(_serviceContext.DataTypeService, _serviceContext.LocalizationService, m).ToDataString() }).ToArray(); + var items = descendants.Select(m => new ContentXmlDto { NodeId = m.Id, Xml = _entitySerializer.Serialize(m).ToDataString() }).ToArray(); db.BulkInsertRecords(items); processed += items.Length; } while (processed < total); diff --git a/src/Umbraco.Web/Services/SectionService.cs b/src/Umbraco.Web/Services/SectionService.cs index 5d013d7e79..6337db67f9 100644 --- a/src/Umbraco.Web/Services/SectionService.cs +++ b/src/Umbraco.Web/Services/SectionService.cs @@ -298,7 +298,7 @@ namespace Umbraco.Web.Services //we need to interrogate the attributes for the data. Would be better to have a base class that contains //metadata populated by the attribute. Oh well i guess. var attrs = types.Select(x => x.GetCustomAttributes(false).Single()); - return Enumerable.ToArray
    (attrs.Select(x => new Section(x.Name, x.Alias, x.SortOrder))); + return attrs.Select(x => new Section(x.Name, x.Alias, x.SortOrder)).ToArray(); }); } diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 36f0a835b1..fdf7f48201 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -1144,9 +1144,6 @@ - - - @@ -1231,7 +1228,6 @@ Code - FeedProxy.aspx diff --git a/src/Umbraco.Web/_Legacy/Packager/Installer.cs b/src/Umbraco.Web/_Legacy/Packager/Installer.cs index 15ea222bda..9d7fe77e7b 100644 --- a/src/Umbraco.Web/_Legacy/Packager/Installer.cs +++ b/src/Umbraco.Web/_Legacy/Packager/Installer.cs @@ -14,18 +14,18 @@ using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Packaging; +using Umbraco.Core.Packaging; using Umbraco.Core.Services.Implement; using Umbraco.Core.Xml; using Umbraco.Web._Legacy.Packager.PackageInstance; using File = System.IO.File; -using PackageAction = Umbraco.Web._Legacy.Packager.PackageInstance.PackageAction; namespace Umbraco.Web._Legacy.Packager { /// /// The packager is a component which enables sharing of both data and functionality components between different umbraco installations. /// - /// The output is a .umb (a zip compressed file) which contains the exported documents/medias/macroes/documenttypes (etc.) + /// The output is a .umb (a zip compressed file) which contains the exported documents/medias/macroes/documentTypes (etc.) /// in a Xml document, along with the physical files used (images/usercontrols/xsl documents etc.) /// /// Partly implemented, import of packages is done, the export is *under construction*. @@ -420,7 +420,7 @@ namespace Umbraco.Web._Legacy.Packager var contentTypes = packagingService.ImportContentTypes(docTypeElement, currentUser.Id); foreach (var contentType in contentTypes) { - insPack.Data.Documenttypes.Add(contentType.Id.ToString(CultureInfo.InvariantCulture)); + insPack.Data.DocumentTypes.Add(contentType.Id.ToString(CultureInfo.InvariantCulture)); //saveNeeded = true; } } @@ -510,7 +510,7 @@ namespace Umbraco.Web._Legacy.Packager if (alias.IsNullOrWhiteSpace() == false) { - PackageAction.RunPackageAction(insPack.Data.Name, alias, n); + Current.PackageActionRunner.RunPackageAction(insPack.Data.Name, alias, n); } } } diff --git a/src/Umbraco.Web/_Legacy/Packager/PackageInstance/CreatedPackage.cs b/src/Umbraco.Web/_Legacy/Packager/PackageInstance/CreatedPackage.cs index 3bfcdd3f86..deff3b2ffd 100644 --- a/src/Umbraco.Web/_Legacy/Packager/PackageInstance/CreatedPackage.cs +++ b/src/Umbraco.Web/_Legacy/Packager/PackageInstance/CreatedPackage.cs @@ -7,11 +7,13 @@ using Umbraco.Core.Composing; using Umbraco.Core.IO; using Umbraco.Core.Models; using Umbraco.Core.Services; +using Umbraco.Core.Services.Implement; using File = System.IO.File; namespace Umbraco.Web._Legacy.Packager.PackageInstance { + //TODO: Fix this class , service + model + internal? public class CreatedPackage { @@ -22,14 +24,13 @@ namespace Umbraco.Web._Legacy.Packager.PackageInstance return pack; } - public static CreatedPackage MakeNew(string name) + public static CreatedPackage MakeNew(string name, Core.Models.Packaging.PackageDefinition packageData = null) { var pack = new CreatedPackage { - Data = data.MakeNew(name, IOHelper.MapPath(Settings.CreatedPackagesSettings)) + Data = packageData ?? data.MakeNew(name, IOHelper.MapPath(Settings.CreatedPackagesSettings)) }; - return pack; } @@ -43,7 +44,7 @@ namespace Umbraco.Web._Legacy.Packager.PackageInstance data.Delete(this.Data.Id, IOHelper.MapPath(Settings.CreatedPackagesSettings)); } - public PackageInstance Data { get; set; } + public Core.Models.Packaging.PackageDefinition Data { get; set; } public static List GetAllCreatedPackages() { @@ -81,7 +82,7 @@ namespace Umbraco.Web._Legacy.Packager.PackageInstance } - public void Publish() + public void Publish(IEntityXmlSerializer serializer) { var package = this; @@ -118,7 +119,7 @@ namespace Umbraco.Web._Legacy.Packager.PackageInstance //var umbDocument = new Document(contentNodeId); //var x = umbDocument.ToXml(_packageManifest, pack.ContentLoadChildNodes); var udoc = Current.Services.ContentService.GetById(contentNodeId); - var xe = pack.ContentLoadChildNodes ? udoc.ToDeepXml(Current.Services.PackagingService) : udoc.ToXml(Current.Services.PackagingService); + var xe = pack.ContentLoadChildNodes ? udoc.ToDeepXml(serializer) : udoc.ToXml(serializer); var x = xe.GetXmlNode(_packageManifest); documentSet.AppendChild(x); @@ -188,7 +189,7 @@ namespace Umbraco.Web._Legacy.Packager.PackageInstance //Document types.. var dtl = new List(); var docTypes = _packageManifest.CreateElement("DocumentTypes"); - foreach (var dtId in pack.Documenttypes) + foreach (var dtId in pack.DocumentTypes) { if (int.TryParse(dtId, out outInt)) { @@ -200,11 +201,9 @@ namespace Umbraco.Web._Legacy.Packager.PackageInstance } } - var exporter = new EntityXmlSerializer(); - foreach (var d in dtl) { - var xml = exporter.Serialize(Current.Services.DataTypeService, Current.Services.ContentTypeService, d); + var xml = serializer.Serialize(d); var xNode = xml.GetXmlNode(); var n = (XmlElement) _packageManifest.ImportNode(xNode, true); docTypes.AppendChild(n); @@ -220,7 +219,6 @@ namespace Umbraco.Web._Legacy.Packager.PackageInstance { var t = Current.Services.FileService.GetTemplate(outInt); - var serializer = new EntityXmlSerializer(); var serialized = serializer.Serialize(t); var n = serialized.GetXmlNode(_packageManifest); @@ -241,16 +239,16 @@ namespace Umbraco.Web._Legacy.Packager.PackageInstance } AppendElement(stylesheets); - //Macros - var macros = _packageManifest.CreateElement("Macros"); - foreach (var macroId in pack.Macros) - { - if (int.TryParse(macroId, out outInt)) - { - macros.AppendChild(PackagerUtility.Macro(int.Parse(macroId), true, localPath, _packageManifest)); - } - } - AppendElement(macros); + ////Macros + //var macros = _packageManifest.CreateElement("Macros"); + //foreach (var macroId in pack.Macros) + //{ + // if (int.TryParse(macroId, out outInt)) + // { + // macros.AppendChild(PackagerUtility.Macro(int.Parse(macroId), true, localPath, _packageManifest)); + // } + //} + //AppendElement(macros); //Dictionary Items var dictionaryItems = _packageManifest.CreateElement("DictionaryItems"); @@ -259,8 +257,7 @@ namespace Umbraco.Web._Legacy.Packager.PackageInstance if (int.TryParse(dictionaryId, out outInt)) { var di = Current.Services.LocalizationService.GetDictionaryItemById(outInt); - var entitySerializer = new EntityXmlSerializer(); - var xmlNode = entitySerializer.Serialize(di).GetXmlNode(_packageManifest); + var xmlNode = serializer.Serialize(di, false).GetXmlNode(_packageManifest); dictionaryItems.AppendChild(xmlNode); } } @@ -274,7 +271,6 @@ namespace Umbraco.Web._Legacy.Packager.PackageInstance { var lang = Current.Services.LocalizationService.GetLanguageById(outInt); - var serializer = new EntityXmlSerializer(); var xml = serializer.Serialize(lang); var n = xml.GetXmlNode(_packageManifest); @@ -328,7 +324,10 @@ namespace Umbraco.Web._Legacy.Packager.PackageInstance AppendElement(actions); } } - catch { } + catch + { + //TODO: Log!? + } } var manifestFileName = localPath + "/package.xml"; diff --git a/src/Umbraco.Web/_Legacy/Packager/PackageInstance/IPackageInstance.cs b/src/Umbraco.Web/_Legacy/Packager/PackageInstance/IPackageInstance.cs deleted file mode 100644 index b920c85a9f..0000000000 --- a/src/Umbraco.Web/_Legacy/Packager/PackageInstance/IPackageInstance.cs +++ /dev/null @@ -1,27 +0,0 @@ -namespace Umbraco.Web._Legacy.Packager.PackageInstance{ - public interface IPackageInstance { - string Actions { get; set; } - string Author { get; set; } - string AuthorUrl { get; set; } - bool ContentLoadChildNodes { get; set; } - string ContentNodeId { get; set; } - System.Collections.Generic.List Documenttypes { get; set; } - System.Collections.Generic.List Files { get; set; } - string Folder { get; set; } - bool HasUpdate { get; set; } - int Id { get; set; } - string License { get; set; } - string LicenseUrl { get; set; } - string LoadControl { get; set; } - System.Collections.Generic.List Macros { get; set; } - string Name { get; set; } - string PackageGuid { get; set; } - string PackagePath { get; set; } - string Readme { get; set; } - string RepositoryGuid { get; set; } - System.Collections.Generic.List Stylesheets { get; set; } - System.Collections.Generic.List Templates { get; set; } - string Url { get; set; } - string Version { get; set; } - } -} diff --git a/src/Umbraco.Web/_Legacy/Packager/PackageInstance/InstalledPackage.cs b/src/Umbraco.Web/_Legacy/Packager/PackageInstance/InstalledPackage.cs index 5842a456e5..8c106f142d 100644 --- a/src/Umbraco.Web/_Legacy/Packager/PackageInstance/InstalledPackage.cs +++ b/src/Umbraco.Web/_Legacy/Packager/PackageInstance/InstalledPackage.cs @@ -53,7 +53,7 @@ namespace Umbraco.Web._Legacy.Packager.PackageInstance List val = new List(); - foreach (PackageInstance pack in data.GetAllPackages(IOHelper.MapPath(Settings.InstalledPackagesSettings))) + foreach (Core.Models.Packaging.PackageDefinition pack in data.GetAllPackages(IOHelper.MapPath(Settings.InstalledPackagesSettings))) { InstalledPackage insPackage = new InstalledPackage(); insPackage.Data = pack; @@ -63,8 +63,8 @@ namespace Umbraco.Web._Legacy.Packager.PackageInstance return val; } - private PackageInstance m_data; - public PackageInstance Data + private Core.Models.Packaging.PackageDefinition m_data; + public Core.Models.Packaging.PackageDefinition Data { get { return m_data; } set { m_data = value; } @@ -156,7 +156,7 @@ namespace Umbraco.Web._Legacy.Packager.PackageInstance { var macros = TryGetIntegerIds(Data.Macros).Select(macroService.GetById).ToList(); var templates = TryGetIntegerIds(Data.Templates).Select(fileService.GetTemplate).ToList(); - var contentTypes = TryGetIntegerIds(Data.Documenttypes).Select(contentTypeService.Get).ToList(); // fixme - media types? + var contentTypes = TryGetIntegerIds(Data.DocumentTypes).Select(contentTypeService.Get).ToList(); // fixme - media types? var dataTypes = TryGetIntegerIds(Data.DataTypes).Select(dataTypeService.GetDataType).ToList(); var dictionaryItems = TryGetIntegerIds(Data.DictionaryItems).Select(localizationService.GetDictionaryItemById).ToList(); var languages = TryGetIntegerIds(Data.Languages).Select(localizationService.GetLanguageById).ToList(); diff --git a/src/Umbraco.Web/_Legacy/Packager/PackageInstance/PackageInstance.cs b/src/Umbraco.Web/_Legacy/Packager/PackageInstance/PackageInstance.cs deleted file mode 100644 index 8ec3c21bdb..0000000000 --- a/src/Umbraco.Web/_Legacy/Packager/PackageInstance/PackageInstance.cs +++ /dev/null @@ -1,132 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Runtime.Serialization; - -namespace Umbraco.Web._Legacy.Packager.PackageInstance -{ - [DataContract(Name = "packageInstance")] - public class PackageInstance - { - [DataMember(Name = "id")] - public int Id { get; set; } - - [DataMember(Name = "repositoryGuid")] - public string RepositoryGuid { get; set; } - - [DataMember(Name = "packageGuid")] - public string PackageGuid { get; set; } - - [DataMember(Name = "hasUpdate")] - public bool HasUpdate { get; set; } - - [DataMember(Name = "name")] - [Required] - public string Name { get; set; } - - [DataMember(Name = "url")] - [Required] - [Url] - public string Url { get; set; } - - [DataMember(Name = "folder")] - public string Folder { get; set; } - - [DataMember(Name = "packagePath")] - public string PackagePath { get; set; } - - [DataMember(Name = "version")] - [Required] - public string Version { get; set; } - - /// - /// The minimum umbraco version that this package requires - /// - [DataMember(Name = "umbracoVersion")] - public Version UmbracoVersion { get; set; } - - [DataMember(Name = "author")] - [Required] - public string Author { get; set; } - - [DataMember(Name = "authorUrl")] - [Required] - [Url] - public string AuthorUrl { get; set; } - - [DataMember(Name = "license")] - public string License { get; set; } - - [DataMember(Name = "licenseUrl")] - public string LicenseUrl { get; set; } - - [DataMember(Name = "readme")] - public string Readme { get; set; } - - [DataMember(Name = "contentLoadChildNodes")] - public bool ContentLoadChildNodes { get; set; } - - [DataMember(Name = "contentNodeId")] - public string ContentNodeId { get; set; } - - [DataMember(Name = "macros")] - public List Macros { get; set; } - - [DataMember(Name = "languages")] - public List Languages { get; set; } - - [DataMember(Name = "dictionaryItems")] - public List DictionaryItems { get; set; } - - [DataMember(Name = "templates")] - public List Templates { get; set; } - - [DataMember(Name = "documenttypes")] - public List Documenttypes { get; set; } - - [DataMember(Name = "stylesheets")] - public List Stylesheets { get; set; } - - [DataMember(Name = "files")] - public List Files { get; set; } - - [DataMember(Name = "loadControl")] - public string LoadControl { get; set; } - - [DataMember(Name = "actions")] - public string Actions { get; set; } - - [DataMember(Name = "dataTypes")] - public List DataTypes { get; set; } - - [DataMember(Name = "iconUrl")] - public string IconUrl { get; set; } - - public PackageInstance() - { - Name = string.Empty; - Url = string.Empty; - Folder = string.Empty; - PackagePath = string.Empty; - Version = string.Empty; - UmbracoVersion = null; - Author = string.Empty; - AuthorUrl = string.Empty; - License = string.Empty; - LicenseUrl = string.Empty; - Readme = string.Empty; - ContentNodeId = string.Empty; - IconUrl = string.Empty; - Macros = new List(); - Languages = new List(); - DictionaryItems = new List(); - Templates = new List(); - Documenttypes = new List(); - Stylesheets = new List(); - Files = new List(); - LoadControl = string.Empty; - DataTypes = new List(); - ContentLoadChildNodes = false; - } - } -} diff --git a/src/Umbraco.Web/_Legacy/Packager/PackageInstance/PackagerUtility.cs b/src/Umbraco.Web/_Legacy/Packager/PackageInstance/PackagerUtility.cs index d972977bad..af32e8c80a 100644 --- a/src/Umbraco.Web/_Legacy/Packager/PackageInstance/PackagerUtility.cs +++ b/src/Umbraco.Web/_Legacy/Packager/PackageInstance/PackagerUtility.cs @@ -7,6 +7,7 @@ using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Core.IO; using Umbraco.Core.Services; +using Umbraco.Core.Services.Implement; namespace Umbraco.Web._Legacy.Packager.PackageInstance { @@ -22,7 +23,7 @@ namespace Umbraco.Web._Legacy.Packager.PackageInstance /// The packinstance. /// The xml document. /// - public static XmlNode PackageInfo(PackageInstance pack, XmlDocument doc) + public static XmlNode PackageInfo(Core.Models.Packaging.PackageDefinition pack, XmlDocument doc) { XmlNode info = doc.CreateElement("info"); @@ -60,31 +61,6 @@ namespace Umbraco.Web._Legacy.Packager.PackageInstance return info; } - - /// - /// Converts an umbraco template to a package xml node - /// - /// The template id. - /// The xml doc. - /// - public static XmlNode Template(int templateId, XmlDocument doc) - { - var tmpl = Current.Services.FileService.GetTemplate(templateId); - //Template tmpl = new Template(templateId); - - XmlNode template = doc.CreateElement("Template"); - template.AppendChild(CreateNode("Name", tmpl.Name, doc)); - template.AppendChild(CreateNode("Alias", tmpl.Alias, doc)); - - //if (tmpl.MasterTemplate != 0) - if (string.IsNullOrWhiteSpace(tmpl.MasterTemplateAlias) == false) - template.AppendChild(CreateNode("Master", tmpl.MasterTemplateAlias, doc)); - - template.AppendChild(CreateNode("Design", "", doc)); - - return template; - } - /// /// Converts a umbraco stylesheet to a package xml node /// @@ -118,29 +94,6 @@ namespace Umbraco.Web._Legacy.Packager.PackageInstance return stylesheet; } - /// - /// Converts a macro to a package xml node - /// - /// The macro id. - /// if set to true [append file]. - /// The package directory. - /// The doc. - /// - public static XmlNode Macro(int macroId, bool appendFile, string packageDirectory, XmlDocument doc) - { - var mcr = Current.Services.MacroService.GetById(macroId); - - if (appendFile) - { - if (!string.IsNullOrEmpty(mcr.MacroSource)) - AppendFileToManifest(mcr.MacroSource, packageDirectory, doc); - } - - var serializer = new EntityXmlSerializer(); - var xml = serializer.Serialize(mcr); - return xml.GetXmlNode(doc); - } - /// /// Appends a file to package manifest and copies the file to the correct folder. diff --git a/src/Umbraco.Web/_Legacy/Packager/Settings.cs b/src/Umbraco.Web/_Legacy/Packager/Settings.cs index 57ab4b9ea4..92b0ae030a 100644 --- a/src/Umbraco.Web/_Legacy/Packager/Settings.cs +++ b/src/Umbraco.Web/_Legacy/Packager/Settings.cs @@ -6,69 +6,11 @@ namespace Umbraco.Web._Legacy.Packager { public class Settings { + public static string InstalledPackagesSettings => SystemDirectories.Packages + IOHelper.DirSepChar + "installedPackages.config"; - public static string PackagerRoot - { - get { return SystemDirectories.Packages; } - } - - public static string PackagesStorage - { - get { return SystemDirectories.Packages + IOHelper.DirSepChar + "created"; } - } - - public static string InstalledPackagesStorage - { - get { return SystemDirectories.Packages + IOHelper.DirSepChar + "installed"; } - } - - public static string InstalledPackagesSettings - { - get { return SystemDirectories.Packages + IOHelper.DirSepChar + "installed" + IOHelper.DirSepChar + "installedPackages.config"; } - } - - public static string CreatedPackagesSettings - { - get { return SystemDirectories.Packages + IOHelper.DirSepChar + "created" + IOHelper.DirSepChar + "createdPackages.config"; } - } - - public static string PackageFileExtension - { - get { return "zip"; } - } - - public static bool HasFileAccess(ref Exception exp) - { - bool hasAccess = false; - StreamWriter sw1 = null; - StreamWriter sw2 = null; - try - { - sw1 = System.IO.File.AppendText(IOHelper.MapPath(InstalledPackagesSettings)); - sw1.Close(); - - sw2 = System.IO.File.AppendText(IOHelper.MapPath(CreatedPackagesSettings)); - sw1.Close(); - - System.IO.Directory.CreateDirectory(IOHelper.MapPath(PackagesStorage) + IOHelper.DirSepChar + "__testFolder__"); - System.IO.Directory.CreateDirectory(IOHelper.MapPath(InstalledPackagesStorage) + IOHelper.DirSepChar + "__testFolder__"); - - System.IO.Directory.Delete(IOHelper.MapPath(PackagesStorage) + IOHelper.DirSepChar + "__testFolder__", true); - System.IO.Directory.Delete(IOHelper.MapPath(InstalledPackagesStorage) + IOHelper.DirSepChar + "__testFolder__", true); - - hasAccess = true; - } - finally - { - if (sw1 != null) - sw1.Close(); - if (sw2 != null) - sw2.Close(); - } - - return hasAccess; - } + public static string CreatedPackagesSettings => SystemDirectories.Packages + IOHelper.DirSepChar + "createdPackages.config"; + public static string PackageFileExtension => "zip"; } diff --git a/src/Umbraco.Web/_Legacy/Packager/data.cs b/src/Umbraco.Web/_Legacy/Packager/data.cs index 962b7d5ed4..1882c151d2 100644 --- a/src/Umbraco.Web/_Legacy/Packager/data.cs +++ b/src/Umbraco.Web/_Legacy/Packager/data.cs @@ -23,20 +23,12 @@ namespace Umbraco.Web._Legacy.Packager //do some error checking and create the folders/files if they don't exist if (!File.Exists(dataSource)) { - if (!Directory.Exists(IOHelper.MapPath(Settings.PackagerRoot))) + if (!Directory.Exists(IOHelper.MapPath(SystemDirectories.Packages))) { - Directory.CreateDirectory(IOHelper.MapPath(Settings.PackagerRoot)); - } - if (!Directory.Exists(IOHelper.MapPath(Settings.PackagesStorage))) - { - Directory.CreateDirectory(IOHelper.MapPath(Settings.PackagesStorage)); - } - if (!Directory.Exists(IOHelper.MapPath(Settings.InstalledPackagesStorage))) - { - Directory.CreateDirectory(IOHelper.MapPath(Settings.InstalledPackagesStorage)); + Directory.CreateDirectory(IOHelper.MapPath(SystemDirectories.Packages)); } - using (StreamWriter sw = File.CreateText(dataSource)) + using (var sw = File.CreateText(dataSource)) { sw.Write($@"{Environment.NewLine}{Environment.NewLine}"); sw.Flush(); @@ -85,7 +77,7 @@ namespace Umbraco.Web._Legacy.Packager return Source.SelectSingleNode("/packages/package [@packageGuid = '" + guid + "']"); } - public static PackageInstance.PackageInstance MakeNew(string Name, string dataSource) + public static Core.Models.Packaging.PackageDefinition MakeNew(string name, string dataSource) { Reload(dataSource); @@ -101,7 +93,7 @@ namespace Umbraco.Web._Legacy.Packager instance.Attributes.Append(XmlHelper.AddAttribute(Source, "id", maxId.ToString())); instance.Attributes.Append(XmlHelper.AddAttribute(Source, "version", "")); instance.Attributes.Append(XmlHelper.AddAttribute(Source, "url", "")); - instance.Attributes.Append(XmlHelper.AddAttribute(Source, "name", Name)); + instance.Attributes.Append(XmlHelper.AddAttribute(Source, "name", name)); instance.Attributes.Append(XmlHelper.AddAttribute(Source, "folder", Guid.NewGuid().ToString())); instance.Attributes.Append(XmlHelper.AddAttribute(Source, "packagepath", "")); instance.Attributes.Append(XmlHelper.AddAttribute(Source, "repositoryGuid", "")); @@ -137,7 +129,7 @@ namespace Umbraco.Web._Legacy.Packager instance.AppendChild(XmlHelper.AddTextNode(Source, "templates", "")); instance.AppendChild(XmlHelper.AddTextNode(Source, "stylesheets", "")); - instance.AppendChild(XmlHelper.AddTextNode(Source, "documenttypes", "")); + instance.AppendChild(XmlHelper.AddTextNode(Source, "documentTypes", "")); instance.AppendChild(XmlHelper.AddTextNode(Source, "macros", "")); instance.AppendChild(XmlHelper.AddTextNode(Source, "files", "")); instance.AppendChild(XmlHelper.AddTextNode(Source, "languages", "")); @@ -151,26 +143,26 @@ namespace Umbraco.Web._Legacy.Packager return retVal; } - public static PackageInstance.PackageInstance Package(int id, string datasource) + public static Core.Models.Packaging.PackageDefinition Package(int id, string datasource) { return ConvertXmlToPackage(GetFromId(id, datasource, true)); } - public static PackageInstance.PackageInstance Package(string guid, string datasource) + public static Core.Models.Packaging.PackageDefinition Package(string guid, string datasource) { XmlNode node = GetFromGuid(guid, datasource, true); if (node != null) return ConvertXmlToPackage(node); else - return new PackageInstance.PackageInstance(); + return new Core.Models.Packaging.PackageDefinition(); } - public static List GetAllPackages(string dataSource) + public static List GetAllPackages(string dataSource) { Reload(dataSource); XmlNodeList nList = data.Source.SelectNodes("packages/package"); - List retVal = new List(); + List retVal = new List(); for (int i = 0; i < nList.Count; i++) { @@ -187,9 +179,9 @@ namespace Umbraco.Web._Legacy.Packager return retVal; } - private static PackageInstance.PackageInstance ConvertXmlToPackage(XmlNode n) + private static Core.Models.Packaging.PackageDefinition ConvertXmlToPackage(XmlNode n) { - PackageInstance.PackageInstance retVal = new PackageInstance.PackageInstance(); + Core.Models.Packaging.PackageDefinition retVal = new Core.Models.Packaging.PackageDefinition(); if (n != null) { @@ -227,7 +219,7 @@ namespace Umbraco.Web._Legacy.Packager retVal.Macros = new List(SafeNodeValue(n.SelectSingleNode("macros")).Trim(',').Split(',')); retVal.Templates = new List(SafeNodeValue(n.SelectSingleNode("templates")).Trim(',').Split(',')); retVal.Stylesheets = new List(SafeNodeValue(n.SelectSingleNode("stylesheets")).Trim(',').Split(',')); - retVal.Documenttypes = new List(SafeNodeValue(n.SelectSingleNode("documenttypes")).Trim(',').Split(',')); + retVal.DocumentTypes = new List(SafeNodeValue(n.SelectSingleNode("documentTypes")).Trim(',').Split(',')); retVal.Languages = new List(SafeNodeValue(n.SelectSingleNode("languages")).Trim(',').Split(',')); retVal.DictionaryItems = new List(SafeNodeValue(n.SelectSingleNode("dictionaryitems")).Trim(',').Split(',')); retVal.DataTypes = new List(SafeNodeValue(n.SelectSingleNode("datatypes")).Trim(',').Split(',')); @@ -263,7 +255,7 @@ namespace Umbraco.Web._Legacy.Packager } - public static void Save(PackageInstance.PackageInstance package, string dataSource) + public static void Save(Core.Models.Packaging.PackageDefinition package, string dataSource) { Reload(dataSource); var xmlDef = GetFromId(package.Id, dataSource, false); @@ -311,7 +303,7 @@ namespace Umbraco.Web._Legacy.Packager XmlHelper.SetTextNode(Source, xmlDef, "macros", JoinList(package.Macros, ',')); XmlHelper.SetTextNode(Source, xmlDef, "templates", JoinList(package.Templates, ',')); XmlHelper.SetTextNode(Source, xmlDef, "stylesheets", JoinList(package.Stylesheets, ',')); - XmlHelper.SetTextNode(Source, xmlDef, "documenttypes", JoinList(package.Documenttypes, ',')); + XmlHelper.SetTextNode(Source, xmlDef, "documentTypes", JoinList(package.DocumentTypes, ',')); XmlHelper.SetTextNode(Source, xmlDef, "languages", JoinList(package.Languages, ',')); XmlHelper.SetTextNode(Source, xmlDef, "dictionaryitems", JoinList(package.DictionaryItems, ',')); XmlHelper.SetTextNode(Source, xmlDef, "datatypes", JoinList(package.DataTypes, ',')); diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/create/CreatedPackageTasks.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/create/CreatedPackageTasks.cs deleted file mode 100644 index 47980f2808..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/create/CreatedPackageTasks.cs +++ /dev/null @@ -1,45 +0,0 @@ -using Umbraco.Core.Logging; -using Umbraco.Web.UI; -using Umbraco.Core; -using Umbraco.Web; -using Umbraco.Web.Composing; -using Umbraco.Web._Legacy.Packager.PackageInstance; -using Umbraco.Web._Legacy.UI; - -namespace Umbraco.Web -{ - public class CreatedPackageTasks : LegacyDialogTask - { - - public override bool PerformSave() - { - Current.Logger.Info("Xml save started"); - int id = CreatedPackage.MakeNew(Alias).Data.Id; - _returnUrl = string.Format("developer/packages/editPackage.aspx?id={0}", id); - return true; - } - - public override bool PerformDelete() - { - // we need to grab the id from the alias as the new tree needs to prefix the NodeID with "package_" - if (ParentID == 0) - { - ParentID = int.Parse(Alias.Substring("package_".Length)); - } - CreatedPackage.GetById(ParentID).Delete(); - return true; - } - - private string _returnUrl = ""; - - public override string ReturnUrl - { - get { return _returnUrl; } - } - - public override string AssignedApp - { - get { return Constants.Applications.Packages.ToString(); } - } - } -} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/editPackage.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/editPackage.aspx.cs index 645aa088f2..3b863895a4 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/editPackage.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/editPackage.aspx.cs @@ -10,6 +10,8 @@ using System.Xml; using umbraco.controls; using Umbraco.Core; using Umbraco.Core.IO; +using Umbraco.Core.Models.Packaging; +using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.UI; using Umbraco.Web.UI.Pages; using Umbraco.Web._Legacy.Packager.PackageInstance; @@ -32,7 +34,7 @@ namespace umbraco.presentation.developer.packages public Umbraco.Web._Legacy.Controls.TabPage packageActions; protected ContentPicker cp; - private PackageInstance pack; + private PackageDefinition pack; private CreatedPackage createdPackage; protected void Page_Load(object sender, EventArgs e) @@ -102,7 +104,7 @@ namespace umbraco.presentation.developer.packages foreach (var dc in nContentTypes) { ListItem li = new ListItem(dc.Name, dc.Id.ToString()); - if (pack.Documenttypes.Contains(dc.Id.ToString())) + if (pack.DocumentTypes.Contains(dc.Id.ToString())) li.Selected = true; documentTypes.Items.Add(li); @@ -223,41 +225,41 @@ namespace umbraco.presentation.developer.packages e.IsValid = true; } - protected void saveOrPublish(object sender, CommandEventArgs e) - { + //protected void saveOrPublish(object sender, CommandEventArgs e) + //{ - if (!Page.IsValid) - { - this.ClientTools.ShowSpeechBubble(SpeechBubbleIcon.Error, "Saved failed.", "Some fields have not been filled-out correctly"); - } - else - { - if (e.CommandName == "save") - SavePackage(true); + // if (!Page.IsValid) + // { + // this.ClientTools.ShowSpeechBubble(SpeechBubbleIcon.Error, "Saved failed.", "Some fields have not been filled-out correctly"); + // } + // else + // { + // if (e.CommandName == "save") + // SavePackage(true); - if (e.CommandName == "publish") - { - SavePackage(false); - int packageID = int.Parse(Request.QueryString["id"]); - //string packFileName = cms.businesslogic.packager. Publish.publishPackage(packageID); + // if (e.CommandName == "publish") + // { + // SavePackage(false); + // int packageID = int.Parse(Request.QueryString["id"]); + // //string packFileName = cms.businesslogic.packager. Publish.publishPackage(packageID); - createdPackage.Publish(); + // createdPackage.Publish(); - if (!string.IsNullOrEmpty(pack.PackagePath)) - { + // if (!string.IsNullOrEmpty(pack.PackagePath)) + // { - packageUmbFile.Text = "   Download"; + // packageUmbFile.Text = "   Download"; - this.ClientTools.ShowSpeechBubble(SpeechBubbleIcon.Success, "Package saved and published", ""); - } - else - { - this.ClientTools.ShowSpeechBubble(SpeechBubbleIcon.Error, "Save failed", "check your umbraco log."); - } - } - } - } + // this.ClientTools.ShowSpeechBubble(SpeechBubbleIcon.Success, "Package saved and published", ""); + // } + // else + // { + // this.ClientTools.ShowSpeechBubble(SpeechBubbleIcon.Error, "Save failed", "check your umbraco log."); + // } + // } + // } + //} private void SavePackage(bool showNotification) @@ -300,7 +302,7 @@ namespace umbraco.presentation.developer.packages if (li.Selected) tmpDoctypes += li.Value + ","; } - pack.Documenttypes = new List(tmpDoctypes.Trim(',').Split(',')); + pack.DocumentTypes = new List(tmpDoctypes.Trim(',').Split(',')); string tmpMacros = ""; @@ -361,7 +363,7 @@ namespace umbraco.presentation.developer.packages if (newPath.Trim() != "") { CreatedPackage createdPackage = CreatedPackage.GetById(int.Parse(Request.QueryString["id"])); - PackageInstance pack = createdPackage.Data; + PackageDefinition pack = createdPackage.Data; pack.Files.Add(newPath); @@ -388,7 +390,7 @@ namespace umbraco.presentation.developer.packages } CreatedPackage createdPackage = CreatedPackage.GetById(int.Parse(Request.QueryString["id"])); - PackageInstance pack = createdPackage.Data; + PackageDefinition pack = createdPackage.Data; pack.Files = new List(tmpFilePathString.Trim('�').Split('�')); pack.Files.TrimExcess(); From 28d93175d553f0ceb3f84a3aef9c2a5f85925f15 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Thu, 10 Jan 2019 06:56:56 +0100 Subject: [PATCH 271/469] #3642 - When saving content the first time, we need to save all variants (even when save is not true), otherwise we loose the information when the url are updated. --- src/Umbraco.Web/Editors/ContentController.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs index c444fd8d39..7189c378d5 100644 --- a/src/Umbraco.Web/Editors/ContentController.cs +++ b/src/Umbraco.Web/Editors/ContentController.cs @@ -1741,12 +1741,18 @@ namespace Umbraco.Web.Editors bool Varies(Property property) => property.PropertyType.VariesByCulture(); var variantIndex = 0; - + var newContent = (contentSave.Action == ContentSaveAction.SaveNew + || contentSave.Action == ContentSaveAction.PublishNew + || contentSave.Action == ContentSaveAction.ScheduleNew + || contentSave.Action == ContentSaveAction.SendPublishNew + || contentSave.Action == ContentSaveAction.PublishWithDescendantsNew + || contentSave.Action == ContentSaveAction.PublishWithDescendantsForceNew + ); //loop through each variant, set the correct name and property values foreach (var variant in contentSave.Variants) { //Don't update anything for this variant if Save is not true - if (!variant.Save) continue; + if (!variant.Save && !newContent) continue; //Don't update the name if it is empty if (!variant.Name.IsNullOrWhiteSpace()) From 8594af3fe3a77747bfc36d962ab858b341da6a82 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Thu, 10 Jan 2019 06:58:12 +0100 Subject: [PATCH 272/469] #3642 - Also do dirty checks if we have changed the culture. --- .../src/common/directives/validation/valformmanager.directive.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js index eaf67bcb91..29920ebf00 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js @@ -146,7 +146,6 @@ function valFormManager(serverValidationManager, $rootScope, $timeout, $location var infiniteEditors = editorService.getEditors(); if (!formCtrl.$dirty && infiniteEditors.length === 0 || isSavingNewItem && infiniteEditors.length === 0) { - confirmed = true; return; } From 74213783309cbbd9eca05b4898d6bedf1a2c2a40 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Thu, 10 Jan 2019 07:03:08 +0100 Subject: [PATCH 273/469] #3642 - use nameof instead of magic strings that has to be equal to variable name --- src/Umbraco.Web/Editors/ContentController.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs index 7189c378d5..26698b227f 100644 --- a/src/Umbraco.Web/Editors/ContentController.cs +++ b/src/Umbraco.Web/Editors/ContentController.cs @@ -516,17 +516,13 @@ namespace Umbraco.Web.Editors public SimpleNotificationModel CreateBlueprintFromContent([FromUri]int contentId, [FromUri]string name) { if (string.IsNullOrWhiteSpace(name)) - { - throw new ArgumentException("Value cannot be null or whitespace.", "name"); - } + throw new ArgumentException("Value cannot be null or whitespace.", nameof(name)); var content = Services.ContentService.GetById(contentId); if (content == null) - { throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound)); - } - EnsureUniqueName(name, content, "name"); + EnsureUniqueName(name, content, nameof(name)); var blueprint = Services.ContentService.CreateContentFromBlueprint(content, name, Security.GetUserId().ResultOr(0)); From b8d2309b9c1fae3e21a21d86744d27a10a997056 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 10 Jan 2019 17:18:47 +1100 Subject: [PATCH 274/469] Gets the IPackageBuilder working and tested, now the controller can create and update packages, validation is also working, need to do some more tests for adding other entities , removes more of the old packaging code. --- .../Composing/Composers/ServicesComposer.cs | 7 +- src/Umbraco.Core/IO/SystemDirectories.cs | 4 +- .../Models/Packaging/PackageDefinition.cs | 36 +- src/Umbraco.Core/Packaging/IPackageBuilder.cs | 30 + .../Packaging/IPackageCreation.cs | 22 - .../{PackageCreation.cs => PackageBuilder.cs} | 190 ++++-- .../Packaging}/RequirementsType.cs | 2 +- .../Services/IPackagingService.cs | 20 +- .../Services/Implement/PackagingService.cs | 16 +- src/Umbraco.Core/Umbraco.Core.csproj | 5 +- .../Composing/TypeFinderTests.cs | 2 +- .../Services/PackagingServiceTests.cs | 3 +- src/Umbraco.Tests/TestHelpers/TestObjects.cs | 2 +- src/Umbraco.Tests/Umbraco.Tests.csproj | 3 + .../src/common/resources/package.resource.js | 17 +- .../src/common/services/formhelper.service.js | 2 + .../services/umbrequesthelper.service.js | 2 + .../content/content.delete.controller.js | 1 + .../views/media/media.delete.controller.js | 1 + .../src/views/packages/edit.controller.js | 58 +- .../src/views/packages/edit.html | 17 +- src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 10 - .../Umbraco/config/create/UI.Release.xml | 28 - .../Umbraco/config/create/UI.xml | 28 - .../Packages/DirectoryBrowser.aspx.cs | 140 ---- .../DirectoryBrowser.aspx.designer.cs | 42 -- .../developer/Packages/directoryBrowser.aspx | 26 - .../developer/Packages/editPackage.aspx | 232 ------- .../Umbraco/developer/Packages/installer.aspx | 10 - .../developer/Packages/editPackage.aspx | 232 ------- src/Umbraco.Web/Editors/PackageController.cs | 55 +- .../Editors/PackageInstallController.cs | 3 +- .../Controllers/InstallPackageController.cs | 2 +- .../InstallSteps/StarterKitDownloadStep.cs | 2 +- src/Umbraco.Web/Umbraco.Web.csproj | 13 - src/Umbraco.Web/_Legacy/Packager/Installer.cs | 17 +- .../PackageInstance/CreatedPackage.cs | 387 ----------- .../PackageInstance/InstalledPackage.cs | 2 +- .../PackageInstance/PackagerUtility.cs | 279 -------- src/Umbraco.Web/_Legacy/Packager/Settings.cs | 4 - src/Umbraco.Web/_Legacy/Packager/data.cs | 18 +- .../developer/Packages/editPackage.aspx | 232 ------- .../developer/Packages/editPackage.aspx.cs | 453 ------------- .../Packages/editPackage.aspx.designer.cs | 609 ------------------ 44 files changed, 333 insertions(+), 2931 deletions(-) create mode 100644 src/Umbraco.Core/Packaging/IPackageBuilder.cs delete mode 100644 src/Umbraco.Core/Packaging/IPackageCreation.cs rename src/Umbraco.Core/Packaging/{PackageCreation.cs => PackageBuilder.cs} (72%) rename src/{Umbraco.Web/_Legacy/Packager => Umbraco.Core/Packaging}/RequirementsType.cs (65%) delete mode 100644 src/Umbraco.Web.UI/Umbraco/developer/Packages/DirectoryBrowser.aspx.cs delete mode 100644 src/Umbraco.Web.UI/Umbraco/developer/Packages/DirectoryBrowser.aspx.designer.cs delete mode 100644 src/Umbraco.Web.UI/Umbraco/developer/Packages/directoryBrowser.aspx delete mode 100644 src/Umbraco.Web.UI/Umbraco/developer/Packages/editPackage.aspx delete mode 100644 src/Umbraco.Web.UI/Umbraco/developer/Packages/installer.aspx delete mode 100644 src/Umbraco.Web.UI/umbraco/developer/Packages/editPackage.aspx delete mode 100644 src/Umbraco.Web/_Legacy/Packager/PackageInstance/CreatedPackage.cs delete mode 100644 src/Umbraco.Web/_Legacy/Packager/PackageInstance/PackagerUtility.cs delete mode 100644 src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/editPackage.aspx delete mode 100644 src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/editPackage.aspx.cs delete mode 100644 src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/editPackage.aspx.designer.cs diff --git a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs index 6133d63377..6395a2c6db 100644 --- a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs @@ -60,8 +60,11 @@ namespace Umbraco.Core.Composing.Composers composition.RegisterUnique(); composition.RegisterUnique(); - composition.RegisterUnique(); - + composition.RegisterUnique(factory => + new PackageBuilder( //we are using a factory because there are optional ctor args + factory.GetInstance(), factory.GetInstance(), factory.GetInstance(), + factory.GetInstance(), factory.GetInstance(), factory.GetInstance(), + factory.GetInstance(), factory.GetInstance())); //TODO: These are replaced in the web project - we need to declare them so that // something is wired up, just not sure this is very nice but will work for now. diff --git a/src/Umbraco.Core/IO/SystemDirectories.cs b/src/Umbraco.Core/IO/SystemDirectories.cs index 183d48e3d9..94aa7b16cc 100644 --- a/src/Umbraco.Core/IO/SystemDirectories.cs +++ b/src/Umbraco.Core/IO/SystemDirectories.cs @@ -43,9 +43,9 @@ namespace Umbraco.Core.IO [Obsolete("Only used by legacy load balancing which is obsolete and should be removed")] public static string WebServices => IOHelper.ReturnPath("umbracoWebservicesPath", Umbraco.EnsureEndsWith("/") + "webservices"); - public static string Packages => Data + IOHelper.DirSepChar + "packages"; + public static string Packages => Data + "/packages"; - public static string Preview => Data + IOHelper.DirSepChar + "preview"; + public static string Preview => Data + "/preview"; private static string _root; diff --git a/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs b/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs index 783b11235f..16934dc4c4 100644 --- a/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs +++ b/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs @@ -11,15 +11,8 @@ namespace Umbraco.Core.Models.Packaging [DataMember(Name = "id")] public int Id { get; set; } - //TODO: I don't see why this is necessary - [DataMember(Name = "repositoryGuid")] - public string RepositoryGuid { get; set; } - [DataMember(Name = "packageGuid")] - public string PackageGuid { get; set; } - - [DataMember(Name = "hasUpdate")] - public bool HasUpdate { get; set; } + public Guid PackageId { get; set; } [DataMember(Name = "name")] [Required] @@ -30,21 +23,24 @@ namespace Umbraco.Core.Models.Packaging [Url] public string Url { get; set; } = string.Empty; + /// + /// This is a generated GUID which is used to determine a temporary folder name for processing the package + /// [DataMember(Name = "folder")] - public string Folder { get; set; } = string.Empty; + public Guid FolderId { get; set; } [DataMember(Name = "packagePath")] public string PackagePath { get; set; } = string.Empty; [DataMember(Name = "version")] [Required] - public string Version { get; set; } = string.Empty; + public string Version { get; set; } = "1.0.0"; /// /// The minimum umbraco version that this package requires /// [DataMember(Name = "umbracoVersion")] - public Version UmbracoVersion { get; set; } + public Version UmbracoVersion { get; set; } = Configuration.UmbracoVersion.Current; [DataMember(Name = "author")] [Required] @@ -65,31 +61,31 @@ namespace Umbraco.Core.Models.Packaging public string Readme { get; set; } = string.Empty; [DataMember(Name = "contentLoadChildNodes")] - public bool ContentLoadChildNodes { get; set; } = false; + public bool ContentLoadChildNodes { get; set; } [DataMember(Name = "contentNodeId")] public string ContentNodeId { get; set; } = string.Empty; [DataMember(Name = "macros")] - public List Macros { get; set; } = new List(); + public IList Macros { get; set; } = new List(); [DataMember(Name = "languages")] - public List Languages { get; set; } = new List(); + public IList Languages { get; set; } = new List(); [DataMember(Name = "dictionaryItems")] - public List DictionaryItems { get; set; } = new List(); + public IList DictionaryItems { get; set; } = new List(); [DataMember(Name = "templates")] - public List Templates { get; set; } = new List(); + public IList Templates { get; set; } = new List(); [DataMember(Name = "documentTypes")] - public List DocumentTypes { get; set; } = new List(); + public IList DocumentTypes { get; set; } = new List(); [DataMember(Name = "stylesheets")] - public List Stylesheets { get; set; } = new List(); + public IList Stylesheets { get; set; } = new List(); [DataMember(Name = "files")] - public List Files { get; set; } = new List(); + public IList Files { get; set; } = new List(); //TODO: Change this to angular view [DataMember(Name = "loadControl")] @@ -99,7 +95,7 @@ namespace Umbraco.Core.Models.Packaging public string Actions { get; set; } [DataMember(Name = "dataTypes")] - public List DataTypes { get; set; } = new List(); + public IList DataTypes { get; set; } = new List(); [DataMember(Name = "iconUrl")] public string IconUrl { get; set; } = string.Empty; diff --git a/src/Umbraco.Core/Packaging/IPackageBuilder.cs b/src/Umbraco.Core/Packaging/IPackageBuilder.cs new file mode 100644 index 0000000000..5a7449545f --- /dev/null +++ b/src/Umbraco.Core/Packaging/IPackageBuilder.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using Umbraco.Core.Models.Packaging; + +namespace Umbraco.Core.Packaging +{ + /// + /// Creates packages + /// + public interface IPackageBuilder + { + IEnumerable GetAll(); + PackageDefinition GetById(int id); + void Delete(int id); + + /// + /// Persists a package definition to storage + /// + /// + /// true if creating/updating the package was successful, otherwise false + /// + bool SavePackage(PackageDefinition definition); + + /// + /// Creates the package file and returns it's physical path + /// + /// + string ExportPackage(PackageDefinition definition); + } +} diff --git a/src/Umbraco.Core/Packaging/IPackageCreation.cs b/src/Umbraco.Core/Packaging/IPackageCreation.cs deleted file mode 100644 index 35397299a7..0000000000 --- a/src/Umbraco.Core/Packaging/IPackageCreation.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Umbraco.Core.Models.Packaging; - -namespace Umbraco.Core.Packaging -{ - /// - /// Creates packages - /// - public interface IPackageCreation - { - /// - /// Persists a package definition to storage - /// - /// - void SavePackageDefinition(PackageDefinition definition); - - /// - /// Creates the package file and returns it's physical path - /// - /// - string ExportPackageDefinition(PackageDefinition definition); - } -} diff --git a/src/Umbraco.Core/Packaging/PackageCreation.cs b/src/Umbraco.Core/Packaging/PackageBuilder.cs similarity index 72% rename from src/Umbraco.Core/Packaging/PackageCreation.cs rename to src/Umbraco.Core/Packaging/PackageBuilder.cs index 615b844101..cc77f9bc78 100644 --- a/src/Umbraco.Core/Packaging/PackageCreation.cs +++ b/src/Umbraco.Core/Packaging/PackageBuilder.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.IO; using System.IO.Compression; using System.Linq; @@ -14,7 +15,7 @@ using File = System.IO.File; namespace Umbraco.Core.Packaging { - internal class PackageCreation : IPackageCreation + internal class PackageBuilder : IPackageBuilder { private readonly IContentService _contentService; private readonly IContentTypeService _contentTypeService; @@ -24,11 +25,15 @@ namespace Umbraco.Core.Packaging private readonly ILocalizationService _languageService; private readonly IEntityXmlSerializer _serializer; private readonly ILogger _logger; - - public PackageCreation(IContentService contentService, IContentTypeService contentTypeService, + private readonly string _mediaFolderPath; + private readonly string _packagesFolderPath; + private readonly string _tempFolderPath; + + public PackageBuilder(IContentService contentService, IContentTypeService contentTypeService, IDataTypeService dataTypeService, IFileService fileService, IMacroService macroService, ILocalizationService languageService, - IEntityXmlSerializer serializer, ILogger logger) + IEntityXmlSerializer serializer, ILogger logger, + string tempFolderPath = null, string packagesFolderPath = null, string mediaFolderPath = null) { _contentService = contentService; _contentTypeService = contentTypeService; @@ -38,49 +43,87 @@ namespace Umbraco.Core.Packaging _languageService = languageService; _serializer = serializer; _logger = logger; + + _tempFolderPath = tempFolderPath ?? SystemDirectories.Data + "/TEMP/PackageFiles"; + _packagesFolderPath = packagesFolderPath ?? SystemDirectories.Packages; + _mediaFolderPath = mediaFolderPath ?? SystemDirectories.Media + "/created-packages"; } - public static string CreatedPackagesFile => SystemDirectories.Packages + IOHelper.DirSepChar + "createdPackages.config"; + private string CreatedPackagesFile => _packagesFolderPath.EnsureEndsWith('/') + "createdPackages.config"; - public void SavePackageDefinition(PackageDefinition definition) + public IEnumerable GetAll() + { + var packagesXml = EnsureStorage(out _); + foreach (var packageXml in packagesXml.Root.Elements("package")) + yield return XmlToPackageDefinition(packageXml); + } + + public PackageDefinition GetById(int id) + { + var packagesXml = EnsureStorage(out _); + var packageXml = packagesXml.Root.Elements("package").FirstOrDefault(x => x.AttributeValue("id") == id); + return packageXml == null ? null : XmlToPackageDefinition(packageXml); + } + + public void Delete(int id) + { + var packagesXml = EnsureStorage(out var packagesFile); + var packageXml = packagesXml.Root.Elements("package").FirstOrDefault(x => x.AttributeValue("id") == id); + if (packageXml == null) return; + + packageXml.Remove(); + + packagesXml.Save(packagesFile); + } + + public bool SavePackage(PackageDefinition definition) { if (definition == null) throw new ArgumentNullException(nameof(definition)); var packagesXml = EnsureStorage(out var packagesFile); + //ensure it's valid + ValidatePackage(definition); + if (definition.Id == default) { //need to gen an id and persist // Find max id - var maxId = packagesXml.Root.Elements("package").Max(x => x.AttributeValue("id")); + var maxId = packagesXml.Root.Elements("package").Max(x => x.AttributeValue("id")) ?? 0; var newId = maxId + 1; definition.Id = newId; - definition.PackageGuid = Guid.NewGuid().ToString(); - definition.Folder = Guid.NewGuid().ToString(); + definition.PackageId = Guid.NewGuid(); + definition.FolderId = Guid.NewGuid(); var packageXml = PackageDefinitionToXml(definition); - packagesXml.Add(packageXml); + packagesXml.Root.Add(packageXml); } else { //existing var packageXml = packagesXml.Root.Elements("package").FirstOrDefault(x => x.AttributeValue("id") == definition.Id); if (packageXml == null) - throw new InvalidOperationException($"The package with id {definition.Id} was not found"); + return false; var updatedXml = PackageDefinitionToXml(definition); packageXml.ReplaceWith(updatedXml); } packagesXml.Save(packagesFile); + + return true; } - public string ExportPackageDefinition(PackageDefinition definition) + public string ExportPackage(PackageDefinition definition) { if (definition.Id == default) throw new ArgumentException("The package definition does not have an ID, it must be saved before being exported"); - if (definition.PackageGuid.IsNullOrWhiteSpace()) throw new ArgumentException("the package definition does not have a GUID, it must be saved before being exported"); + if (definition.PackageId == default) throw new ArgumentException("the package definition does not have a GUID, it must be saved before being exported"); + if (definition.FolderId == default) throw new ArgumentException("the package definition does not have a folder GUID, it must be saved before being exported"); + + //ensure it's valid + ValidatePackage(definition); //Create a folder for building this package - var temporaryPath = IOHelper.MapPath(SystemDirectories.Data + "/TEMP/PackageFiles/" + definition.Folder); + var temporaryPath = IOHelper.MapPath(_tempFolderPath.EnsureEndsWith('/') + definition.FolderId); if (Directory.Exists(temporaryPath) == false) Directory.CreateDirectory(temporaryPath); @@ -90,7 +133,7 @@ namespace Umbraco.Core.Packaging var packageManifest = CreatePackageManifest(out var manifestRoot, out var filesXml); //Info section - packageManifest.Add(GetPackageInfoXml(definition)); + manifestRoot.Add(GetPackageInfoXml(definition)); PackageDocumentsAndTags(definition, manifestRoot); PackageDocumentTypes(definition, manifestRoot); @@ -124,7 +167,7 @@ namespace Umbraco.Core.Packaging } catch (Exception e) { - _logger.Warn(e, "Could not add package actions to the package manifest, the xml did not parse"); + _logger.Warn(e, "Could not add package actions to the package manifest, the xml did not parse"); } } @@ -136,13 +179,17 @@ namespace Umbraco.Core.Packaging packageManifest.Save(manifestFileName); // check if there's a packages directory below media - var packagesDirectory = SystemDirectories.Media + "/created-packages"; - if (Directory.Exists(IOHelper.MapPath(packagesDirectory)) == false) - Directory.CreateDirectory(IOHelper.MapPath(packagesDirectory)); + + if (Directory.Exists(IOHelper.MapPath(_mediaFolderPath)) == false) + Directory.CreateDirectory(IOHelper.MapPath(_mediaFolderPath)); - var packPath = packagesDirectory + "/" + (definition.Name + "_" + definition.Version).Replace(' ', '_') + ".zip"; + var packPath = _mediaFolderPath.EnsureEndsWith('/') + (definition.Name + "_" + definition.Version).Replace(' ', '_') + ".zip"; ZipPackage(temporaryPath, IOHelper.MapPath(packPath)); + //we need to update the package path and save it + definition.PackagePath = packPath; + SavePackage(definition); + return packPath; } finally @@ -152,6 +199,16 @@ namespace Umbraco.Core.Packaging } } + private void ValidatePackage(PackageDefinition definition) + { + //ensure it's valid + var context = new ValidationContext(definition, serviceProvider: null, items: null); + var results = new List(); + var isValid = Validator.TryValidateObject(definition, context, results); + if (!isValid) + throw new InvalidOperationException("Validation failed, there is invalid data on the model: " + string.Join(", ", results.Select(x => x.ErrorMessage))); + } + private void PackageDataTypes(PackageDefinition definition, XContainer manifestRoot) { var dataTypes = new XElement("DataTypes"); @@ -342,6 +399,8 @@ namespace Umbraco.Core.Packaging /// The save path. private static void ZipPackage(string path, string savePath) { + if (File.Exists(savePath)) + File.Delete(savePath); ZipFile.CreateFromDirectory(path, savePath); } @@ -476,7 +535,7 @@ namespace Umbraco.Core.Packaging requirements.Add(new XElement("patch", definition.UmbracoVersion == null ? UmbracoVersion.SemanticVersion.Patch.ToInvariantString() : definition.UmbracoVersion.Build.ToInvariantString())); if (definition.UmbracoVersion != null) - requirements.Add(new XAttribute("type", "strict")); + requirements.Add(new XAttribute("type", RequirementsType.Strict.ToString())); package.Add(requirements); info.Add(package); @@ -496,13 +555,13 @@ namespace Umbraco.Core.Packaging { files = new XElement("files"); root = new XElement("umbPackage", files); - var packageManifest = new XDocument(); + var packageManifest = new XDocument(root); return packageManifest; } - private static XDocument EnsureStorage(out string packagesFile) + private XDocument EnsureStorage(out string packagesFile) { - var packagesFolder = IOHelper.MapPath(SystemDirectories.Packages); + var packagesFolder = IOHelper.MapPath(_packagesFolderPath); //ensure it exists Directory.CreateDirectory(packagesFolder); @@ -517,45 +576,80 @@ namespace Umbraco.Core.Packaging return packagesXml; } + private static PackageDefinition XmlToPackageDefinition(XElement xml) + { + if (xml == null) return null; + + var retVal = new PackageDefinition + { + Id = xml.AttributeValue("id"), + Name = xml.AttributeValue("name") ?? string.Empty, + FolderId = xml.AttributeValue("folder"), + PackagePath = xml.AttributeValue("packagePath") ?? string.Empty, + Version = xml.AttributeValue("version") ?? string.Empty, + Url = xml.AttributeValue("url") ?? string.Empty, + PackageId = xml.AttributeValue("packageGuid"), + IconUrl = xml.AttributeValue("iconUrl") ?? string.Empty, + UmbracoVersion = xml.AttributeValue("umbVersion"), + License = xml.Element("license")?.Value ?? string.Empty, + LicenseUrl = xml.Element("license")?.AttributeValue("url") ?? string.Empty, + Author = xml.Element("author")?.Value ?? string.Empty, + AuthorUrl = xml.Element("author")?.AttributeValue("url") ?? string.Empty, + Readme = xml.Element("readme")?.Value ?? string.Empty, + Actions = xml.Element("actions")?.ToString() ?? string.Empty, + ContentNodeId = xml.Element("content")?.AttributeValue("nodeId") ?? string.Empty, + ContentLoadChildNodes = xml.Element("content")?.AttributeValue("loadChildNodes") ?? false, + Macros = xml.Element("macros")?.Value.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(), + Templates = xml.Element("templates")?.Value.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(), + Stylesheets = xml.Element("stylesheets")?.Value.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(), + DocumentTypes = xml.Element("documentTypes")?.Value.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(), + Languages = xml.Element("languages")?.Value.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(), + DictionaryItems = xml.Element("dictionaryitems")?.Value.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(), + DataTypes = xml.Element("datatypes")?.Value.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(), + Files = xml.Element("files")?.Elements("file").Select(x => x.Value).ToList() ?? new List(), + LoadControl = xml.Element("loadcontrol")?.Value ?? string.Empty + }; + + return retVal; + } + private static XElement PackageDefinitionToXml(PackageDefinition def) { var packageXml = new XElement("package", new XAttribute("id", def.Id), - new XAttribute("version", def.Version), - new XAttribute("url", def.Url), - new XAttribute("name", def.Name), - new XAttribute("folder", def.Folder), //fixme: What is this? - new XAttribute("packagepath", def.PackagePath), - new XAttribute("repositoryGuid", def.RepositoryGuid), - new XAttribute("iconUrl", def.IconUrl), + new XAttribute("version", def.Version ?? string.Empty), + new XAttribute("url", def.Url ?? string.Empty), + new XAttribute("name", def.Name ?? string.Empty), + new XAttribute("folder", def.FolderId), + new XAttribute("packagePath", def.PackagePath ?? string.Empty), + new XAttribute("iconUrl", def.IconUrl ?? string.Empty), new XAttribute("umbVersion", def.UmbracoVersion), - new XAttribute("packageGuid", def.PackageGuid), - new XAttribute("hasUpdate", def.HasUpdate), //fixme: What is this? + new XAttribute("packageGuid", def.PackageId), new XElement("license", - new XCData(def.License), - new XAttribute("url", def.LicenseUrl)), + new XCData(def.License ?? string.Empty), + new XAttribute("url", def.LicenseUrl ?? string.Empty)), new XElement("author", - new XCData(def.Author), - new XAttribute("url", def.AuthorUrl)), + new XCData(def.Author ?? string.Empty), + new XAttribute("url", def.AuthorUrl ?? string.Empty)), - new XElement("readme", def.Readme), - new XElement("actions", def.Actions), - new XElement("datatypes", string.Join(",", def.DataTypes)), + new XElement("readme", def.Readme ?? string.Empty), + new XElement("actions", def.Actions ?? string.Empty), + new XElement("datatypes", string.Join(",", def.DataTypes ?? Array.Empty())), new XElement("content", new XAttribute("nodeId", def.ContentNodeId), new XAttribute("loadChildNodes", def.ContentLoadChildNodes)), - new XElement("templates", string.Join(",", def.Templates)), - new XElement("stylesheets", string.Join(",", def.Stylesheets)), - new XElement("documentTypes", string.Join(",", def.DocumentTypes)), - new XElement("macros", string.Join(",", def.Macros)), - new XElement("files", string.Join(",", def.Files)), - new XElement("languages", string.Join(",", def.Languages)), - new XElement("dictionaryitems", string.Join(",", def.DictionaryItems)), - new XElement("loadcontrol", "")); //fixme: no more loadcontrol, needs to be an angular view + new XElement("templates", string.Join(",", def.Templates ?? Array.Empty())), + new XElement("stylesheets", string.Join(",", def.Stylesheets ?? Array.Empty())), + new XElement("documentTypes", string.Join(",", def.DocumentTypes ?? Array.Empty())), + new XElement("macros", string.Join(",", def.Macros ?? Array.Empty())), + new XElement("files", (def.Files ?? Array.Empty()).Where(x => !x.IsNullOrWhiteSpace()).Select(x => new XElement("file", x))), + new XElement("languages", string.Join(",", def.Languages ?? Array.Empty())), + new XElement("dictionaryitems", string.Join(",", def.DictionaryItems ?? Array.Empty())), + new XElement("loadcontrol", def.LoadControl ?? string.Empty)); //fixme: no more loadcontrol, needs to be an angular view return packageXml; } diff --git a/src/Umbraco.Web/_Legacy/Packager/RequirementsType.cs b/src/Umbraco.Core/Packaging/RequirementsType.cs similarity index 65% rename from src/Umbraco.Web/_Legacy/Packager/RequirementsType.cs rename to src/Umbraco.Core/Packaging/RequirementsType.cs index ca91626128..38cac482c2 100644 --- a/src/Umbraco.Web/_Legacy/Packager/RequirementsType.cs +++ b/src/Umbraco.Core/Packaging/RequirementsType.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Web._Legacy.Packager +namespace Umbraco.Core.Packaging { public enum RequirementsType { diff --git a/src/Umbraco.Core/Services/IPackagingService.cs b/src/Umbraco.Core/Services/IPackagingService.cs index 585ea36aa9..4d60f3dca4 100644 --- a/src/Umbraco.Core/Services/IPackagingService.cs +++ b/src/Umbraco.Core/Services/IPackagingService.cs @@ -9,14 +9,27 @@ namespace Umbraco.Core.Services { public interface IPackagingService : IService { - #region Package Creation + #region Package Building + + IEnumerable GetAll(); + PackageDefinition GetById(int id); + void Delete(int id); + /// /// Persists a package definition to storage /// /// - void SavePackageDefinition(PackageDefinition definition); + bool SavePackage(PackageDefinition definition); + + /// + /// Creates the package file and returns it's physical path + /// + /// + string ExportPackage(PackageDefinition definition); + #endregion + #region Importing /// /// Imports and saves package xml as /// @@ -88,7 +101,8 @@ namespace Umbraco.Core.Services /// Optional id of the User performing the operation. Default is zero (admin) /// Optional parameter indicating whether or not to raise events /// An enumrable list of generated Templates - IEnumerable ImportTemplates(XElement element, int userId = 0, bool raiseEvents = true); + IEnumerable ImportTemplates(XElement element, int userId = 0, bool raiseEvents = true); + #endregion /// /// This will fetch an Umbraco package file from the package repository and return the relative file path to the downloaded package file diff --git a/src/Umbraco.Core/Services/Implement/PackagingService.cs b/src/Umbraco.Core/Services/Implement/PackagingService.cs index 203a2cb2e8..17959f0983 100644 --- a/src/Umbraco.Core/Services/Implement/PackagingService.cs +++ b/src/Umbraco.Core/Services/Implement/PackagingService.cs @@ -46,7 +46,7 @@ namespace Umbraco.Core.Services.Implement private readonly IAuditRepository _auditRepository; private readonly IContentTypeRepository _contentTypeRepository; private readonly PropertyEditorCollection _propertyEditors; - private readonly IPackageCreation _packageCreation; + private readonly IPackageBuilder _packageBuilder; private static HttpClient _httpClient; public PackagingService( @@ -62,7 +62,7 @@ namespace Umbraco.Core.Services.Implement IAuditRepository auditRepository, IContentTypeRepository contentTypeRepository, PropertyEditorCollection propertyEditors, - IPackageCreation packageCreation) + IPackageBuilder packageBuilder) { _logger = logger; _contentService = contentService; @@ -76,7 +76,7 @@ namespace Umbraco.Core.Services.Implement _auditRepository = auditRepository; _contentTypeRepository = contentTypeRepository; _propertyEditors = propertyEditors; - _packageCreation = packageCreation; + _packageBuilder = packageBuilder; _importedContentTypes = new Dictionary(); } @@ -1402,7 +1402,15 @@ namespace Umbraco.Core.Services.Implement #region Package Building - public void SavePackageDefinition(PackageDefinition definition) => _packageCreation.SavePackageDefinition(definition); + public void Delete(int id) => _packageBuilder.Delete(id); + + public IEnumerable GetAll() => _packageBuilder.GetAll(); + + public PackageDefinition GetById(int id) => _packageBuilder.GetById(id); + + public bool SavePackage(PackageDefinition definition) => _packageBuilder.SavePackage(definition); + + public string ExportPackage(PackageDefinition definition) => _packageBuilder.ExportPackage(definition); #endregion diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 58ba136cc4..00179f562a 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -444,9 +444,10 @@ - + - + + diff --git a/src/Umbraco.Tests/Composing/TypeFinderTests.cs b/src/Umbraco.Tests/Composing/TypeFinderTests.cs index 2b9474310b..49c807b19f 100644 --- a/src/Umbraco.Tests/Composing/TypeFinderTests.cs +++ b/src/Umbraco.Tests/Composing/TypeFinderTests.cs @@ -90,7 +90,7 @@ namespace Umbraco.Tests.Composing Assert.AreEqual(0, typesFound.Count()); // 0 classes in _assemblies are marked with [Tree] typesFound = TypeFinder.FindClassesWithAttribute(new[] { typeof (UmbracoContext).Assembly }); - Assert.AreEqual(21, typesFound.Count()); // + classes in Umbraco.Web are marked with [Tree] + Assert.AreEqual(22, typesFound.Count()); // + classes in Umbraco.Web are marked with [Tree] } private static IProfilingLogger GetTestProfilingLogger() diff --git a/src/Umbraco.Tests/Services/PackagingServiceTests.cs b/src/Umbraco.Tests/Services/PackagingServiceTests.cs index a87e7907b5..2caf3e08b3 100644 --- a/src/Umbraco.Tests/Services/PackagingServiceTests.cs +++ b/src/Umbraco.Tests/Services/PackagingServiceTests.cs @@ -1,5 +1,4 @@ -using System; -using System.IO; +using System.IO; using NUnit.Framework; using Umbraco.Core.IO; using Umbraco.Core.Models.Packaging; diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects.cs b/src/Umbraco.Tests/TestHelpers/TestObjects.cs index 120b0bcabb..c6602fc54e 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects.cs @@ -170,7 +170,7 @@ namespace Umbraco.Tests.TestHelpers var macroService = GetLazyService(factory, c => new MacroService(scopeProvider, logger, eventMessagesFactory, GetRepo(c), GetRepo(c))); var packagingService = GetLazyService(factory, c => new PackagingService( logger, contentService.Value, contentTypeService.Value, macroService.Value, dataTypeService.Value, fileService.Value, localizationService.Value, entityService.Value, scopeProvider, GetRepo(c), GetRepo(c), new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty())), - new PackageCreation(contentService.Value, contentTypeService.Value, dataTypeService.Value, fileService.Value, macroService.Value, localizationService.Value, + new PackageBuilder(contentService.Value, contentTypeService.Value, dataTypeService.Value, fileService.Value, macroService.Value, localizationService.Value, new EntityXmlSerializer(contentService.Value, mediaService.Value, dataTypeService.Value, userService.Value, localizationService.Value, contentTypeService.Value, urlSegmentProviders), logger))); var relationService = GetLazyService(factory, c => new RelationService(scopeProvider, logger, eventMessagesFactory, entityService.Value, GetRepo(c), GetRepo(c))); var treeService = GetLazyService(factory, c => new ApplicationTreeService(logger, cache, typeLoader)); diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index 12b830407e..3e619c6f00 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -62,6 +62,8 @@ + + @@ -140,6 +142,7 @@ + diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/package.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/package.resource.js index 0b74729cf6..ce2a557390 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/package.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/package.resource.js @@ -179,20 +179,29 @@ function packageResource($q, $http, umbDataFormatter, umbRequestHelper) { 'Failed to get package'); }, + getEmpty: function () { + return umbRequestHelper.resourcePromise( + $http.get( + umbRequestHelper.getApiUrl( + "packageApiBaseUrl", + "getEmpty")), + 'Failed to get scaffold'); + }, + /** * @ngdoc method - * @name umbraco.resources.packageInstallResource#createPackage + * @name umbraco.resources.packageInstallResource#savePackage * @methodOf umbraco.resources.packageInstallResource * * @description - * Creates a new package + * Creates or updates a package */ - createPackage: function (umbPackage) { + savePackage: function (umbPackage) { return umbRequestHelper.resourcePromise( $http.post( umbRequestHelper.getApiUrl( "packageApiBaseUrl", - "PostCreatePackage"), umbPackage), + "PostSavePackage"), umbPackage), 'Failed to create package'); }, diff --git a/src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js index f3b64e0c28..b21909f573 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js @@ -119,6 +119,8 @@ function formHelper(angularHelper, serverValidationManager, notificationsService serverValidationManager.notifyAndClearAllSubscriptions(); } else { + + //TODO: All YSOD handling should be done with an interceptor overlayService.ysod(err); } } diff --git a/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js index 0834799be4..fb1a1b8d5e 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js @@ -177,6 +177,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe //show a ysod dialog if (Umbraco.Sys.ServerVariables["isDebuggingEnabled"] === true) { const error = { errorMsg: 'An error occured', data: response.data }; + //TODO: All YSOD handling should be done with an interceptor overlayService.ysod(error); } else { @@ -288,6 +289,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe else if (Umbraco.Sys.ServerVariables["isDebuggingEnabled"] === true) { //show a ysod dialog const error = { errorMsg: 'An error occured', data: response.data }; + //TODO: All YSOD handling should be done with an interceptor overlayService.ysod(error); } else { diff --git a/src/Umbraco.Web.UI.Client/src/views/content/content.delete.controller.js b/src/Umbraco.Web.UI.Client/src/views/content/content.delete.controller.js index 92e02d0d14..e594bae2f4 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/content.delete.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/content/content.delete.controller.js @@ -65,6 +65,7 @@ function ContentDeleteController($scope, $timeout, contentResource, treeService, //check if response is ysod if (err.status && err.status >= 500) { + //TODO: All YSOD handling should be done with an interceptor overlayService.ysod(err); } }); diff --git a/src/Umbraco.Web.UI.Client/src/views/media/media.delete.controller.js b/src/Umbraco.Web.UI.Client/src/views/media/media.delete.controller.js index e5e95e94df..70b5120ebe 100644 --- a/src/Umbraco.Web.UI.Client/src/views/media/media.delete.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/media/media.delete.controller.js @@ -59,6 +59,7 @@ function MediaDeleteController($scope, mediaResource, treeService, navigationSer //check if response is ysod if (err.status && err.status >= 500) { + //TODO: All YSOD handling should be done with an interceptor overlayService.ysod(err); } diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js index f30c14816b..5f3832f79b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js @@ -1,7 +1,7 @@ (function () { "use strict"; - function EditController($scope, $location, $routeParams, entityResource, packageResource, contentTypeResource, templateResource, stylesheetResource, languageResource, dictionaryResource, dataTypeResource, editorService, formHelper) { + function EditController($scope, $location, $routeParams, entityResource, stylesheetResource, languageResource, packageResource, dictionaryResource, editorService, formHelper) { const vm = this; @@ -12,10 +12,9 @@ vm.contentOpen = true; vm.filesOpen = true; vm.actionsOpen = true; - + vm.loading = true; vm.back = back; - vm.createPackage = createPackage; - vm.save = save; + vm.createOrUpdatePackage = createOrUpdatePackage; vm.removeContentItem = removeContentItem; vm.openContentPicker = openContentPicker; vm.openFilePicker = openFilePicker; @@ -23,24 +22,23 @@ vm.openControlPicker = openControlPicker; vm.removeControl = removeControl; - function onInit() { + const packageId = $routeParams.id; + const create = $routeParams.create; - const packageId = $routeParams.id; - const create = $routeParams.create; + function onInit() { if(create) { //pre populate package with some values - vm.package = { - "version": "0.0.1", - "license": "MIT License", - "licenseUrl": "http://opensource.org/licenses/MIT", - "umbracoVersion": Umbraco.Sys.ServerVariables.application.version - }; + packageResource.getEmpty().then(scaffold => { + vm.package = scaffold; + vm.loading = false; + }); + vm.buttonLabel = "Create"; } else { // load package packageResource.getCreatedById(packageId).then(createdPackage => { vm.package = createdPackage; - + vm.loading = false; // get render model for content node if(vm.package.contentNodeId) { entityResource.getById(vm.package.contentNodeId, "Document") @@ -49,11 +47,12 @@ }); } - }, angular.noop); + }); + vm.buttonLabel = "Save"; } // get all doc types - contentTypeResource.getAll().then(documentTypes => { + entityResource.getAll("DocumentType").then(documentTypes => { // a package stores the id as a string so we // need to convert all ids to string for comparison documentTypes.forEach(documentType => { @@ -63,7 +62,7 @@ }); // get all templates - templateResource.getAll().then(templates => { + entityResource.getAll("Template").then(templates => { // a package stores the id as a string so we // need to convert all ids to string for comparison templates.forEach(template => { @@ -101,7 +100,7 @@ }); // get all data types items - dataTypeResource.getAll().then(dataTypes => { + entityResource.getAll("DataType").then(dataTypes => { // a package stores the id as a string so we // need to convert all ids to string for comparison dataTypes.forEach(dataType => { @@ -116,26 +115,31 @@ $location.path("packages/packages/overview").search('create', null);; } - function createPackage(editPackageForm) { + function createOrUpdatePackage(editPackageForm) { if (formHelper.submitForm({ formCtrl: editPackageForm, scope: $scope })) { - vm.createPackageButtonState = "busy"; + vm.buttonState = "busy"; + + packageResource.savePackage(vm.package).then((updatedPackage) => { - packageResource.createPackage(vm.package).then((updatedPackage) => { vm.package = updatedPackage; - vm.createPackageButtonState = "success"; + vm.buttonState = "success"; + + if (create) { + //if we are creating, then redirect to the correct url and reload + $location.path("packages/packages/overview/" + vm.package.id).search("subview", "created"); + //don't add a browser history for this + $location.replace(); + } + }, function(err){ formHelper.handleError(err); - vm.createPackageButtonState = "error"; + vm.buttonState = "error"; }); } } - function save() { - console.log("save package"); - } - function removeContentItem() { vm.package.contentNodeId = null; } diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html index bf33c24d4d..b1a417fd6f 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html @@ -300,14 +300,15 @@ - + + + @@ -316,4 +317,4 @@ - \ No newline at end of file + diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index 9969cea687..9105b1170f 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -157,13 +157,6 @@ editMacro.aspx - - directoryBrowser.aspx - ASPXCodeBehind - - - directoryBrowser.aspx - default.Master ASPXCodeBehind @@ -209,7 +202,6 @@ - @@ -307,8 +299,6 @@ - - Designer diff --git a/src/Umbraco.Web.UI/Umbraco/config/create/UI.Release.xml b/src/Umbraco.Web.UI/Umbraco/config/create/UI.Release.xml index 0ebdb5cd48..635174b9da 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/create/UI.Release.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/create/UI.Release.xml @@ -15,32 +15,4 @@ - -
    Package
    - /create/simple.ascx - - - -
    - -
    Package
    - /create/simple.ascx - - - -
    - -
    Package
    - /create/simple.ascx - - - -
    - -
    Package
    - /create/simple.ascx - - - -
    diff --git a/src/Umbraco.Web.UI/Umbraco/config/create/UI.xml b/src/Umbraco.Web.UI/Umbraco/config/create/UI.xml index d6be62ff88..c075a0b8b9 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/create/UI.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/create/UI.xml @@ -15,32 +15,4 @@ - -
    Package
    - /create/simple.ascx - - - -
    - -
    Package
    - /create/simple.ascx - - - -
    - -
    Package
    - /create/simple.ascx - - - -
    - -
    Package
    - /create/simple.ascx - - - -
    diff --git a/src/Umbraco.Web.UI/Umbraco/developer/Packages/DirectoryBrowser.aspx.cs b/src/Umbraco.Web.UI/Umbraco/developer/Packages/DirectoryBrowser.aspx.cs deleted file mode 100644 index 3e2edd1471..0000000000 --- a/src/Umbraco.Web.UI/Umbraco/developer/Packages/DirectoryBrowser.aspx.cs +++ /dev/null @@ -1,140 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using System.Web; -using System.Web.UI; -using Umbraco.Core; -using Umbraco.Core.IO; -using Umbraco.Web.UI.Pages; - -namespace Umbraco.Web.UI.Umbraco.Developer.Packages -{ - public partial class DirectoryBrowser : UmbracoEnsuredPage - { - public DirectoryBrowser() - { - CurrentApp = Constants.Applications.Packages; - } - - string _lsScriptName; - string _lsWebPath; - protected string Target = ""; - private readonly Regex _xssElementIdClean = new Regex(@"^([a-zA-Z0-9-_:\.]+)"); - - private readonly StringBuilder _sb = new StringBuilder(); - - protected override void OnLoad(EventArgs e) - { - base.OnLoad(e); - - Response.Cache.SetExpires(DateTime.Now.AddSeconds(5)); - Response.Cache.SetCacheability(HttpCacheability.Public); - - //we need to clean this string: - //http://issues.umbraco.org/issue/U4-2027 - var target = Request.QueryString.Get("target"); - if (target.IsNullOrWhiteSpace()) - throw new InvalidOperationException("The target query string must be set to a valid html element id"); - var matched = _xssElementIdClean.Matches(target); - if (matched.Count == 0) - throw new InvalidOperationException("The target query string must be set to a valid html element id"); - - Target = matched[0].Value; - - try - { - - //Variables used in script - var sebChar = IOHelper.DirSepChar.ToString(); - - //Work on path and ensure no back tracking - string sSubDir = Request.QueryString.Get("path"); - if (string.IsNullOrEmpty(sSubDir)) { sSubDir = "/"; } - - sSubDir = sSubDir.Replace(IOHelper.DirSepChar.ToString(), ""); - sSubDir = sSubDir.Replace("//", "/"); - sSubDir = sSubDir.Replace("..", "./"); - sSubDir = sSubDir.Replace('/', IOHelper.DirSepChar); - - //Clean path for processing and collect path varitations - if (sSubDir.Substring(0, 1) != sebChar) { sSubDir = sebChar + sSubDir; } - if (sSubDir.Substring(sSubDir.Length - 1, 1) != "\\") { sSubDir = sSubDir + sebChar; } - - //Get name of the browser script file - _lsScriptName = Request.ServerVariables.Get("SCRIPT_NAME"); - var j = _lsScriptName.LastIndexOf("/"); - if (j > 0) { _lsScriptName = _lsScriptName.Substring(j + 1, _lsScriptName.Length - (j + 1)).ToLower(); } - - //Create navigation string and other path strings - GetNavLink("", "root"); - if (sSubDir != sebChar) - { - j = 0; int i = 0; - do - { - i = sSubDir.IndexOf(sebChar, j + 1); - _lsWebPath += sSubDir.Substring(j + 1, i - (j + 1)) + "/"; - GetNavLink(_lsWebPath, sSubDir.Substring(j + 1, i - (j + 1))); - j = i; - } while (i != sSubDir.Length - 1); - } - - //Output header - _sb.Append(""); - - //Output directorys - var oDirInfo = new DirectoryInfo(IOHelper.MapPath("~/" + sSubDir)); - var oDirs = oDirInfo.GetDirectories(); - foreach (var oDir in oDirs) - { - try - { - _sb.Append(""); - } - catch (Exception) - { - _sb.Append(""); - } - } - - //Ouput files - var oFiles = oDirInfo.GetFiles(); - foreach (var oFile in oFiles.Where(oFile => oFile.Name.ToLower() != _lsScriptName)) - { - decimal iLen = oFile.Length; - string sLen; - if (iLen >= 1048960) { iLen = iLen / 1048960; sLen = "mb"; } else { iLen = iLen / 1024; sLen = "kb"; } - sLen = Decimal.Round(iLen, 2).ToString() + sLen; - _sb.Append(""); - } - - //Output footer - _sb.Append("
    " + oDir.Name + " (Include entire folder)
    " + oDir.Name + " (Access Denied)
    " + oFile.Name + "
    "); - - } - catch (Exception ex) - { - RptErr(ex.Message); - } - } - - protected override void OnPreRender(EventArgs e) - { - base.OnPreRender(e); - Output.Controls.Add(new LiteralControl(_sb.ToString())); - } - - private void RptErr(string psMessage) - { - _sb.Append("
    Script Reported Error:  " + psMessage + "

    "); - } - - private string GetNavLink(string psHref, string psText) - { - return ("/" + psText + ""); - } - - } -} diff --git a/src/Umbraco.Web.UI/Umbraco/developer/Packages/DirectoryBrowser.aspx.designer.cs b/src/Umbraco.Web.UI/Umbraco/developer/Packages/DirectoryBrowser.aspx.designer.cs deleted file mode 100644 index 22bf0892b7..0000000000 --- a/src/Umbraco.Web.UI/Umbraco/developer/Packages/DirectoryBrowser.aspx.designer.cs +++ /dev/null @@ -1,42 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Umbraco.Web.UI.Umbraco.Developer.Packages { - - - public partial class DirectoryBrowser { - - /// - /// CssInclude1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::ClientDependency.Core.Controls.CssInclude CssInclude1; - - /// - /// pane control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.Pane pane; - - /// - /// Output control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.PlaceHolder Output; - } -} diff --git a/src/Umbraco.Web.UI/Umbraco/developer/Packages/directoryBrowser.aspx b/src/Umbraco.Web.UI/Umbraco/developer/Packages/directoryBrowser.aspx deleted file mode 100644 index c6d2645ab3..0000000000 --- a/src/Umbraco.Web.UI/Umbraco/developer/Packages/directoryBrowser.aspx +++ /dev/null @@ -1,26 +0,0 @@ -<%@ Page Language="C#" AutoEventWireup="True" MasterPageFile="../../masterpages/umbracoDialog.Master" CodeBehind="DirectoryBrowser.aspx.cs" Inherits="Umbraco.Web.UI.Umbraco.Developer.Packages.DirectoryBrowser" %> - -<%@ Register TagPrefix="cc1" Namespace="Umbraco.Web._Legacy.Controls" Assembly="Umbraco.Web" %> -<%@ Register TagPrefix="cdf" Namespace="ClientDependency.Core.Controls" Assembly="ClientDependency.Core" %> - - - - - - - - - - -
    - - - -
    -
    diff --git a/src/Umbraco.Web.UI/Umbraco/developer/Packages/editPackage.aspx b/src/Umbraco.Web.UI/Umbraco/developer/Packages/editPackage.aspx deleted file mode 100644 index 956c17fe4a..0000000000 --- a/src/Umbraco.Web.UI/Umbraco/developer/Packages/editPackage.aspx +++ /dev/null @@ -1,232 +0,0 @@ -<%@ Page Language="C#" ValidateRequest="false" AutoEventWireup="true" MasterPageFile="../../masterpages/umbracoPage.Master" - Title="Package and export content" CodeBehind="editPackage.aspx.cs" Inherits="umbraco.presentation.developer.packages._Default" %> - -<%@ Register TagPrefix="cc2" Namespace="Umbraco.Web._Legacy.Controls" Assembly="Umbraco.Web" %> - - - - - - - - - * - - - - * - - - - * - - - - - - - - - - - - - - * - Invalid version number (eg. 7.5.0) - - - - - - - * - - - - * - - - - - - - * - - - - * - - - - - - - - - - -
    - - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - Remember: .ascx files for your macros - will be added automaticly, but you will still need to add assemblies, - images and script files manually to the list below. -
    -
    - - - - - - - - - - - - - - - - - -
    - Absolute path to file (ie: /bin/umbraco.bin) - -
    - - - -
    - - - - - - -
    -
    - - - - - - - - -
    - Load control after installation (ex: /usercontrols/installer.ascx) -
    - - - - -
    -
    - - - - - - - - - - - -
    -

    - Here you can add custom installer / uninstaller events to perform certain tasks - during installation and uninstallation. -
    - All actions are formed as a xml node, containing data for the action to be performed. - Package actions documentation -

    - -
    - Actions: -
    - -
    -
    - -
    diff --git a/src/Umbraco.Web.UI/Umbraco/developer/Packages/installer.aspx b/src/Umbraco.Web.UI/Umbraco/developer/Packages/installer.aspx deleted file mode 100644 index 1beda45dae..0000000000 --- a/src/Umbraco.Web.UI/Umbraco/developer/Packages/installer.aspx +++ /dev/null @@ -1,10 +0,0 @@ -<%@ Page Language="c#" MasterPageFile="../../masterpages/umbracoPage.Master" -AutoEventWireup="True" Inherits="umbraco.presentation.developer.packages.Installer" Trace="false" ValidateRequest="false" %> -<%@ Register TagPrefix="cc1" Namespace="Umbraco.Web._Legacy.Controls" Assembly="Umbraco.Web" %> - - - - - - - diff --git a/src/Umbraco.Web.UI/umbraco/developer/Packages/editPackage.aspx b/src/Umbraco.Web.UI/umbraco/developer/Packages/editPackage.aspx deleted file mode 100644 index 956c17fe4a..0000000000 --- a/src/Umbraco.Web.UI/umbraco/developer/Packages/editPackage.aspx +++ /dev/null @@ -1,232 +0,0 @@ -<%@ Page Language="C#" ValidateRequest="false" AutoEventWireup="true" MasterPageFile="../../masterpages/umbracoPage.Master" - Title="Package and export content" CodeBehind="editPackage.aspx.cs" Inherits="umbraco.presentation.developer.packages._Default" %> - -<%@ Register TagPrefix="cc2" Namespace="Umbraco.Web._Legacy.Controls" Assembly="Umbraco.Web" %> - - - - - - - - - * - - - - * - - - - * - - - - - - - - - - - - - - * - Invalid version number (eg. 7.5.0) - - - - - - - * - - - - * - - - - - - - * - - - - * - - - - - - - - - - -
    - - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - Remember: .ascx files for your macros - will be added automaticly, but you will still need to add assemblies, - images and script files manually to the list below. -
    -
    - - - - - - - - - - - - - - - - - -
    - Absolute path to file (ie: /bin/umbraco.bin) - -
    - - - -
    - - - - - - -
    -
    - - - - - - - - -
    - Load control after installation (ex: /usercontrols/installer.ascx) -
    - - - - -
    -
    - - - - - - - - - - - -
    -

    - Here you can add custom installer / uninstaller events to perform certain tasks - during installation and uninstallation. -
    - All actions are formed as a xml node, containing data for the action to be performed. - Package actions documentation -

    - -
    - Actions: -
    - -
    -
    - -
    diff --git a/src/Umbraco.Web/Editors/PackageController.cs b/src/Umbraco.Web/Editors/PackageController.cs index dfb8823a39..66a0349417 100644 --- a/src/Umbraco.Web/Editors/PackageController.cs +++ b/src/Umbraco.Web/Editors/PackageController.cs @@ -23,57 +23,42 @@ namespace Umbraco.Web.Editors [UmbracoApplicationAuthorize(Core.Constants.Applications.Packages)] public class PackageController : UmbracoAuthorizedJsonController { - public List GetCreatedPackages() + public IEnumerable GetCreatedPackages() { - return CreatedPackage.GetAllCreatedPackages().Select(x => x.Data).ToList(); + return Services.PackagingService.GetAll(); } public PackageDefinition GetCreatedPackageById(int id) { - var package = CreatedPackage.GetById(id); + var package = Services.PackagingService.GetById(id); if (package == null) throw new HttpResponseException(HttpStatusCode.NotFound); - return package.Data; + return package; } - public PackageDefinition PostUpdatePackage(PackageDefinition model) + public PackageDefinition GetEmpty() { - var package = CreatedPackage.GetById(model.Id); - if (package == null) - throw new HttpResponseException(HttpStatusCode.NotFound); - - if (ModelState.IsValid == false) - { - //Throw/bubble up errors - throw new HttpResponseException(Request.CreateValidationErrorResponse(ModelState)); - } - - package.Data = model; - - //We should have packagepath populated now - return package.Data; + return new PackageDefinition(); } - public PackageDefinition PostCreatePackage(PackageDefinition model) + /// + /// Creates or updates a package + /// + /// + /// + public PackageDefinition PostSavePackage(PackageDefinition model) { - //creating requires an empty model/package id - if (model.Id != 0 || model.PackageGuid != null) - throw new HttpResponseException(HttpStatusCode.NotFound); - if (ModelState.IsValid == false) - { - //Throw/bubble up errors throw new HttpResponseException(Request.CreateValidationErrorResponse(ModelState)); - } //save it - Services.PackagingService.SavePackageDefinition(model); + if (!Services.PackagingService.SavePackage(model)) + throw new HttpResponseException(Request.CreateNotificationValidationErrorResponse("The package with id {definition.Id} was not found")); - //then publish to get the file - //package.Publish(); - //TODO: We need a link to the downloadable zip file, in packagepath ? - + Services.PackagingService.ExportPackage(model); + + //the packagePath will be on the model return model; } @@ -86,11 +71,7 @@ namespace Umbraco.Web.Editors [HttpDelete] public IHttpActionResult DeleteCreatedPackage(int packageId) { - var package = CreatedPackage.GetById(packageId); - if (package == null) - return NotFound(); - - package.Delete(); + Services.PackagingService.Delete(packageId); return Ok(); } diff --git a/src/Umbraco.Web/Editors/PackageInstallController.cs b/src/Umbraco.Web/Editors/PackageInstallController.cs index b58ed05bde..55e843aceb 100644 --- a/src/Umbraco.Web/Editors/PackageInstallController.cs +++ b/src/Umbraco.Web/Editors/PackageInstallController.cs @@ -510,7 +510,7 @@ namespace Umbraco.Web.Editors } model.TemporaryDirectoryPath = Path.Combine(SystemDirectories.Data, tempPath); - model.Id = ins.CreateManifest(IOHelper.MapPath(model.TemporaryDirectoryPath), model.PackageGuid.ToString(), model.RepositoryGuid.ToString()); + model.Id = ins.CreateManifest(IOHelper.MapPath(model.TemporaryDirectoryPath), model.PackageGuid, model.RepositoryGuid.ToString()); return model; } @@ -584,6 +584,7 @@ namespace Umbraco.Web.Editors var redirectUrl = ""; if (ins.Control.IsNullOrWhiteSpace() == false) { + //fixme: this needs to be replaced with an angular view the installer.aspx no longer exists. redirectUrl = string.Format("/developer/framed/{0}", Uri.EscapeDataString( string.Format("/umbraco/developer/Packages/installer.aspx?installing=custominstaller&dir={0}&pId={1}&customControl={2}&customUrl={3}", tempDir, model.Id, ins.Control, ins.Url))); diff --git a/src/Umbraco.Web/Install/Controllers/InstallPackageController.cs b/src/Umbraco.Web/Install/Controllers/InstallPackageController.cs index 1fd2ac27bb..55680084e5 100644 --- a/src/Umbraco.Web/Install/Controllers/InstallPackageController.cs +++ b/src/Umbraco.Web/Install/Controllers/InstallPackageController.cs @@ -60,7 +60,7 @@ namespace Umbraco.Web.Install.Controllers var tempFile = installer.Import(packageFile); installer.LoadConfig(tempFile); - var pId = installer.CreateManifest(tempFile, model.KitGuid.ToString(), RepoGuid); + var pId = installer.CreateManifest(tempFile, model.KitGuid, RepoGuid); return Json(new { success = true, diff --git a/src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs b/src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs index 8f9f9242d7..c79be96a93 100644 --- a/src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs @@ -68,7 +68,7 @@ namespace Umbraco.Web.Install.InstallSteps var tempFile = installer.Import(packageFile); installer.LoadConfig(tempFile); - var pId = installer.CreateManifest(tempFile, kitGuid.ToString(), RepoGuid); + var pId = installer.CreateManifest(tempFile, kitGuid, RepoGuid); InstallPackageFiles(pId, tempFile); diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index fdf7f48201..b9a6c17ef7 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -1142,10 +1142,7 @@ - - - @@ -1236,13 +1233,6 @@ FeedProxy.aspx - - editPackage.aspx - ASPXCodeBehind - - - editPackage.aspx - @@ -1288,9 +1278,6 @@ - - ASPXCodeBehind - diff --git a/src/Umbraco.Web/_Legacy/Packager/Installer.cs b/src/Umbraco.Web/_Legacy/Packager/Installer.cs index 9d7fe77e7b..15a7839227 100644 --- a/src/Umbraco.Web/_Legacy/Packager/Installer.cs +++ b/src/Umbraco.Web/_Legacy/Packager/Installer.cs @@ -209,7 +209,7 @@ namespace Umbraco.Web._Legacy.Packager return Import(inputFile, true); } - public int CreateManifest(string tempDir, string guid, string repoGuid) + public int CreateManifest(string tempDir, Guid guid, string repoGuid) { //This is the new improved install rutine, which chops up the process into 3 steps, creating the manifest, moving files, and finally handling umb objects var packName = XmlHelper.GetNodeValue(Config.DocumentElement.SelectSingleNode("/umbPackage/info/package/name")); @@ -243,8 +243,7 @@ namespace Umbraco.Web._Legacy.Packager insPack.Data.Url = packUrl; insPack.Data.IconUrl = iconUrl; - insPack.Data.PackageGuid = guid; //the package unique key. - insPack.Data.RepositoryGuid = repoGuid; //the repository unique key, if the package is a file install, the repository will not get logged. + insPack.Data.PackageId = guid; //the package unique key. insPack.Save(); return insPack.Data.Id; @@ -324,7 +323,7 @@ namespace Umbraco.Web._Legacy.Packager { Current.Services.AuditService.Add(AuditType.PackagerInstall, _currentUserId, - -1, "Package", string.Format("Package '{0}' installed. Package guid: {1}", insPack.Data.Name, insPack.Data.PackageGuid)); + -1, "Package", string.Format("Package '{0}' installed. Package guid: {1}", insPack.Data.Name, insPack.Data.PackageId)); } insPack.Save(); @@ -373,7 +372,8 @@ namespace Umbraco.Web._Legacy.Packager if (languageItemsElement != null) { var insertedLanguages = packagingService.ImportLanguages(languageItemsElement); - insPack.Data.Languages.AddRange(insertedLanguages.Select(l => l.Id.ToString(CultureInfo.InvariantCulture))); + foreach(var x in insertedLanguages.Select(l => l.Id.ToString(CultureInfo.InvariantCulture))) + insPack.Data.Languages.Add(x); } #endregion @@ -383,7 +383,8 @@ namespace Umbraco.Web._Legacy.Packager if (dictionaryItemsElement != null) { var insertedDictionaryItems = packagingService.ImportDictionaryItems(dictionaryItemsElement); - insPack.Data.DictionaryItems.AddRange(insertedDictionaryItems.Select(d => d.Id.ToString(CultureInfo.InvariantCulture))); + foreach (var x in insertedDictionaryItems.Select(d => d.Id.ToString(CultureInfo.InvariantCulture))) + insPack.Data.DictionaryItems.Add(x); } #endregion @@ -392,7 +393,9 @@ namespace Umbraco.Web._Legacy.Packager if (macroItemsElement != null) { var insertedMacros = packagingService.ImportMacros(macroItemsElement); - insPack.Data.Macros.AddRange(insertedMacros.Select(m => m.Id.ToString(CultureInfo.InvariantCulture))); + foreach (var x in insertedMacros.Select(m => m.Id.ToString(CultureInfo.InvariantCulture))) + insPack.Data.Macros.Add(x); + } #endregion diff --git a/src/Umbraco.Web/_Legacy/Packager/PackageInstance/CreatedPackage.cs b/src/Umbraco.Web/_Legacy/Packager/PackageInstance/CreatedPackage.cs deleted file mode 100644 index deff3b2ffd..0000000000 --- a/src/Umbraco.Web/_Legacy/Packager/PackageInstance/CreatedPackage.cs +++ /dev/null @@ -1,387 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Xml; -using Umbraco.Core; -using Umbraco.Core.Composing; -using Umbraco.Core.IO; -using Umbraco.Core.Models; -using Umbraco.Core.Services; -using Umbraco.Core.Services.Implement; -using File = System.IO.File; - - -namespace Umbraco.Web._Legacy.Packager.PackageInstance -{ - //TODO: Fix this class , service + model + internal? - public class CreatedPackage - { - - public static CreatedPackage GetById(int id) - { - var pack = new CreatedPackage(); - pack.Data = data.Package(id, IOHelper.MapPath(Settings.CreatedPackagesSettings)); - return pack; - } - - public static CreatedPackage MakeNew(string name, Core.Models.Packaging.PackageDefinition packageData = null) - { - var pack = new CreatedPackage - { - Data = packageData ?? data.MakeNew(name, IOHelper.MapPath(Settings.CreatedPackagesSettings)) - }; - - return pack; - } - - public void Save() - { - data.Save(this.Data, IOHelper.MapPath(Settings.CreatedPackagesSettings)); - } - - public void Delete() - { - data.Delete(this.Data.Id, IOHelper.MapPath(Settings.CreatedPackagesSettings)); - } - - public Core.Models.Packaging.PackageDefinition Data { get; set; } - - public static List GetAllCreatedPackages() - { - var val = new List(); - - foreach (var pack in data.GetAllPackages(IOHelper.MapPath(Settings.CreatedPackagesSettings))) - { - var crPack = new CreatedPackage(); - crPack.Data = pack; - val.Add(crPack); - } - - return val; - } - - private static XmlDocument _packageManifest; - private static void CreatePackageManifest() - { - _packageManifest = new XmlDocument(); - var xmldecl = _packageManifest.CreateXmlDeclaration("1.0", "UTF-8", "no"); - - _packageManifest.AppendChild(xmldecl); - - //root node - XmlNode umbPackage = _packageManifest.CreateElement("umbPackage"); - _packageManifest.AppendChild(umbPackage); - //Files node - umbPackage.AppendChild(_packageManifest.CreateElement("files")); - } - - private static void AppendElement(XmlNode node) - { - var root = _packageManifest.SelectSingleNode("/umbPackage"); - root.AppendChild(node); - } - - - public void Publish(IEntityXmlSerializer serializer) - { - - var package = this; - var pack = package.Data; - - var outInt = 0; - - //Path checking... - var localPath = IOHelper.MapPath(SystemDirectories.Media + "/" + pack.Folder); - - if (Directory.Exists(localPath) == false) - Directory.CreateDirectory(localPath); - - //Init package file... - CreatePackageManifest(); - //Info section.. - AppendElement(PackagerUtility.PackageInfo(pack, _packageManifest)); - - //Documents and tags... - var contentNodeId = 0; - if (string.IsNullOrEmpty(pack.ContentNodeId) == false && int.TryParse(pack.ContentNodeId, out contentNodeId)) - { - if (contentNodeId > 0) - { - //Create the Documents/DocumentSet node - XmlNode documents = _packageManifest.CreateElement("Documents"); - XmlNode documentSet = _packageManifest.CreateElement("DocumentSet"); - XmlAttribute importMode = _packageManifest.CreateAttribute("importMode", ""); - importMode.Value = "root"; - documentSet.Attributes.Append(importMode); - documents.AppendChild(documentSet); - - //load content from umbraco. - //var umbDocument = new Document(contentNodeId); - //var x = umbDocument.ToXml(_packageManifest, pack.ContentLoadChildNodes); - var udoc = Current.Services.ContentService.GetById(contentNodeId); - var xe = pack.ContentLoadChildNodes ? udoc.ToDeepXml(serializer) : udoc.ToXml(serializer); - var x = xe.GetXmlNode(_packageManifest); - documentSet.AppendChild(x); - - AppendElement(documents); - - ////Create the TagProperties node - this is used to store a definition for all - //// document properties that are tags, this ensures that we can re-import tags properly - //XmlNode tagProps = _packageManifest.CreateElement("TagProperties"); - - ////before we try to populate this, we'll do a quick lookup to see if any of the documents - //// being exported contain published tags. - //var allExportedIds = documents.SelectNodes("//@id").Cast() - // .Select(x => x.Value.TryConvertTo()) - // .Where(x => x.Success) - // .Select(x => x.Result) - // .ToArray(); - //var allContentTags = new List(); - //foreach (var exportedId in allExportedIds) - //{ - // allContentTags.AddRange( - // Current.Services.TagService.GetTagsForEntity(exportedId)); - //} - - ////This is pretty round-about but it works. Essentially we need to get the properties that are tagged - //// but to do that we need to lookup by a tag (string) - //var allTaggedEntities = new List(); - //foreach (var group in allContentTags.Select(x => x.Group).Distinct()) - //{ - // allTaggedEntities.AddRange( - // Current.Services.TagService.GetTaggedContentByTagGroup(group)); - //} - - ////Now, we have all property Ids/Aliases and their referenced document Ids and tags - //var allExportedTaggedEntities = allTaggedEntities.Where(x => allExportedIds.Contains(x.EntityId)) - // .DistinctBy(x => x.EntityId) - // .OrderBy(x => x.EntityId); - - //foreach (var taggedEntity in allExportedTaggedEntities) - //{ - // foreach (var taggedProperty in taggedEntity.TaggedProperties.Where(x => x.Tags.Any())) - // { - // XmlNode tagProp = _packageManifest.CreateElement("TagProperty"); - // var docId = _packageManifest.CreateAttribute("docId", ""); - // docId.Value = taggedEntity.EntityId.ToString(CultureInfo.InvariantCulture); - // tagProp.Attributes.Append(docId); - - // var propertyAlias = _packageManifest.CreateAttribute("propertyAlias", ""); - // propertyAlias.Value = taggedProperty.PropertyTypeAlias; - // tagProp.Attributes.Append(propertyAlias); - - // var group = _packageManifest.CreateAttribute("group", ""); - // group.Value = taggedProperty.Tags.First().Group; - // tagProp.Attributes.Append(group); - - // tagProp.AppendChild(_packageManifest.CreateCDataSection( - // JsonConvert.SerializeObject(taggedProperty.Tags.Select(x => x.Text).ToArray()))); - - // tagProps.AppendChild(tagProp); - // } - //} - - //AppendElement(tagProps); - - } - } - - //Document types.. - var dtl = new List(); - var docTypes = _packageManifest.CreateElement("DocumentTypes"); - foreach (var dtId in pack.DocumentTypes) - { - if (int.TryParse(dtId, out outInt)) - { - var docT = Current.Services.ContentTypeService.Get(outInt); - //DocumentType docT = new DocumentType(outInt); - - AddDocumentType(docT, ref dtl); - - } - } - - foreach (var d in dtl) - { - var xml = serializer.Serialize(d); - var xNode = xml.GetXmlNode(); - var n = (XmlElement) _packageManifest.ImportNode(xNode, true); - docTypes.AppendChild(n); - } - - AppendElement(docTypes); - - //Templates - var templates = _packageManifest.CreateElement("Templates"); - foreach (var templateId in pack.Templates) - { - if (int.TryParse(templateId, out outInt)) - { - var t = Current.Services.FileService.GetTemplate(outInt); - - var serialized = serializer.Serialize(t); - var n = serialized.GetXmlNode(_packageManifest); - - - templates.AppendChild(n); - } - } - AppendElement(templates); - - //Stylesheets - var stylesheets = _packageManifest.CreateElement("Stylesheets"); - foreach (var stylesheetName in pack.Stylesheets) - { - if (stylesheetName.IsNullOrWhiteSpace()) continue; - var stylesheetXmlNode = PackagerUtility.Stylesheet(stylesheetName, true, _packageManifest); - if (stylesheetXmlNode != null) - stylesheets.AppendChild(stylesheetXmlNode); - } - AppendElement(stylesheets); - - ////Macros - //var macros = _packageManifest.CreateElement("Macros"); - //foreach (var macroId in pack.Macros) - //{ - // if (int.TryParse(macroId, out outInt)) - // { - // macros.AppendChild(PackagerUtility.Macro(int.Parse(macroId), true, localPath, _packageManifest)); - // } - //} - //AppendElement(macros); - - //Dictionary Items - var dictionaryItems = _packageManifest.CreateElement("DictionaryItems"); - foreach (var dictionaryId in pack.DictionaryItems) - { - if (int.TryParse(dictionaryId, out outInt)) - { - var di = Current.Services.LocalizationService.GetDictionaryItemById(outInt); - var xmlNode = serializer.Serialize(di, false).GetXmlNode(_packageManifest); - dictionaryItems.AppendChild(xmlNode); - } - } - AppendElement(dictionaryItems); - - //Languages - var languages = _packageManifest.CreateElement("Languages"); - foreach (var langId in pack.Languages) - { - if (int.TryParse(langId, out outInt)) - { - var lang = Current.Services.LocalizationService.GetLanguageById(outInt); - - var xml = serializer.Serialize(lang); - var n = xml.GetXmlNode(_packageManifest); - - languages.AppendChild(n); - } - } - AppendElement(languages); - - //TODO: Fix this! ... actually once we use the new packager we don't need to - - ////Datatypes - //var dataTypes = _packageManifest.CreateElement("DataTypes"); - //foreach (var dtId in pack.DataTypes) - //{ - // if (int.TryParse(dtId, out outInt)) - // { - // datatype.DataTypeDefinition dtd = new datatype.DataTypeDefinition(outInt); - // dataTypes.AppendChild(dtd.ToXml(_packageManifest)); - // } - //} - //AppendElement(dataTypes); - - //Files - foreach (var fileName in pack.Files) - { - PackagerUtility.AppendFileToManifest(fileName, localPath, _packageManifest); - } - - //Load control on install... - if (string.IsNullOrEmpty(pack.LoadControl) == false) - { - XmlNode control = _packageManifest.CreateElement("control"); - control.InnerText = pack.LoadControl; - PackagerUtility.AppendFileToManifest(pack.LoadControl, localPath, _packageManifest); - AppendElement(control); - } - - //Actions - if (string.IsNullOrEmpty(pack.Actions) == false) - { - try - { - var xdActions = new XmlDocument(); - xdActions.LoadXml("" + pack.Actions + ""); - var actions = xdActions.DocumentElement.SelectSingleNode("."); - - - if (actions != null) - { - actions = _packageManifest.ImportNode(actions, true).Clone(); - AppendElement(actions); - } - } - catch - { - //TODO: Log!? - } - } - - var manifestFileName = localPath + "/package.xml"; - - if (File.Exists(manifestFileName)) - File.Delete(manifestFileName); - - _packageManifest.Save(manifestFileName); - _packageManifest = null; - - - //string packPath = Settings.PackagerRoot.Replace(System.IO.Path.DirectorySeparatorChar.ToString(), "/") + "/" + pack.Name.Replace(' ', '_') + "_" + pack.Version.Replace(' ', '_') + "." + Settings.PackageFileExtension; - - // check if there's a packages directory below media - var packagesDirectory = SystemDirectories.Media + "/created-packages"; - if (Directory.Exists(IOHelper.MapPath(packagesDirectory)) == false) - { - Directory.CreateDirectory(IOHelper.MapPath(packagesDirectory)); - } - - - var packPath = packagesDirectory + "/" + (pack.Name + "_" + pack.Version).Replace(' ', '_') + "." + Settings.PackageFileExtension; - PackagerUtility.ZipPackage(localPath, IOHelper.MapPath(packPath)); - - pack.PackagePath = packPath; - - if (pack.PackageGuid.Trim() == "") - pack.PackageGuid = Guid.NewGuid().ToString(); - - package.Save(); - - //Clean up.. - File.Delete(localPath + "/package.xml"); - Directory.Delete(localPath, true); - } - - private void AddDocumentType(IContentType dt, ref List dtl) - { - if (dt.ParentId > 0) - { - var parent = Current.Services.ContentTypeService.Get(dt.ParentId); - if (parent != null) // could be a container - { - AddDocumentType(parent, ref dtl); - } - } - - if (dtl.Contains(dt) == false) - { - dtl.Add(dt); - } - } - - - - } -} diff --git a/src/Umbraco.Web/_Legacy/Packager/PackageInstance/InstalledPackage.cs b/src/Umbraco.Web/_Legacy/Packager/PackageInstance/InstalledPackage.cs index 8c106f142d..d7ea239a3f 100644 --- a/src/Umbraco.Web/_Legacy/Packager/PackageInstance/InstalledPackage.cs +++ b/src/Umbraco.Web/_Legacy/Packager/PackageInstance/InstalledPackage.cs @@ -72,7 +72,7 @@ namespace Umbraco.Web._Legacy.Packager.PackageInstance public void Delete(int userId) { - Current.Services.AuditService.Add(AuditType.PackagerUninstall, userId, -1, "Package", string.Format("Package '{0}' uninstalled. Package guid: {1}", Data.Name, Data.PackageGuid)); + Current.Services.AuditService.Add(AuditType.PackagerUninstall, userId, -1, "Package", string.Format("Package '{0}' uninstalled. Package guid: {1}", Data.Name, Data.PackageId)); Delete(); } diff --git a/src/Umbraco.Web/_Legacy/Packager/PackageInstance/PackagerUtility.cs b/src/Umbraco.Web/_Legacy/Packager/PackageInstance/PackagerUtility.cs deleted file mode 100644 index af32e8c80a..0000000000 --- a/src/Umbraco.Web/_Legacy/Packager/PackageInstance/PackagerUtility.cs +++ /dev/null @@ -1,279 +0,0 @@ -using System; -using System.Collections; -using System.IO; -using System.Xml; -using ICSharpCode.SharpZipLib.Zip; -using Umbraco.Core; -using Umbraco.Core.Composing; -using Umbraco.Core.IO; -using Umbraco.Core.Services; -using Umbraco.Core.Services.Implement; - -namespace Umbraco.Web._Legacy.Packager.PackageInstance -{ - /// - /// A utillity class for working with packager data. - /// It provides basic methods for adding new items to a package manifest, moving files and other misc. - /// - public class PackagerUtility - { - /// - /// Creates a package manifest containing name, license, version and other meta data. - /// - /// The packinstance. - /// The xml document. - /// - public static XmlNode PackageInfo(Core.Models.Packaging.PackageDefinition pack, XmlDocument doc) - { - XmlNode info = doc.CreateElement("info"); - - //Package info - XmlNode package = doc.CreateElement("package"); - package.AppendChild(CreateNode("name", pack.Name, doc)); - package.AppendChild(CreateNode("version", pack.Version, doc)); - package.AppendChild(CreateNode("iconUrl", pack.IconUrl, doc)); - - XmlNode license = CreateNode("license", pack.License, doc); - license.Attributes.Append(CreateAttribute("url", pack.LicenseUrl, doc)); - package.AppendChild(license); - - package.AppendChild(CreateNode("url", pack.Url, doc)); - - XmlNode requirements = doc.CreateElement("requirements"); - //NOTE: The defaults are 3.0.0 - I'm just leaving that here since that's the way it's been //SD - requirements.AppendChild(CreateNode("major", pack.UmbracoVersion == null ? "3" : pack.UmbracoVersion.Major.ToInvariantString(), doc)); - requirements.AppendChild(CreateNode("minor", pack.UmbracoVersion == null ? "0" : pack.UmbracoVersion.Minor.ToInvariantString(), doc)); - requirements.AppendChild(CreateNode("patch", pack.UmbracoVersion == null ? "0" : pack.UmbracoVersion.Build.ToInvariantString(), doc)); - if (pack.UmbracoVersion != null) - requirements.Attributes.Append(CreateAttribute("type", "strict", doc)); - - package.AppendChild(requirements); - info.AppendChild(package); - - //Author - XmlNode author = CreateNode("author", "", doc); - author.AppendChild(CreateNode("name", pack.Author, doc)); - author.AppendChild(CreateNode("website", pack.AuthorUrl, doc)); - info.AppendChild(author); - - info.AppendChild(CreateNode("readme", "", doc)); - - return info; - } - - /// - /// Converts a umbraco stylesheet to a package xml node - /// - /// The name of the stylesheet. - /// if set to true [incluce properties]. - /// The doc. - /// - public static XmlNode Stylesheet(string name, bool includeProperties, XmlDocument doc) - { - if (doc == null) throw new ArgumentNullException("doc"); - if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value cannot be null or whitespace.", "name"); - - var fileService = Current.Services.FileService; - var sts = fileService.GetStylesheetByName(name); - var stylesheet = doc.CreateElement("Stylesheet"); - stylesheet.AppendChild(CreateNode("Name", sts.Alias, doc)); - stylesheet.AppendChild(CreateNode("FileName", sts.Name, doc)); - stylesheet.AppendChild(CreateNode("Content", "", doc)); - if (includeProperties) - { - var properties = doc.CreateElement("Properties"); - foreach (var ssP in sts.Properties) - { - var property = doc.CreateElement("Property"); - property.AppendChild(CreateNode("Name", ssP.Name, doc)); - property.AppendChild(CreateNode("Alias", ssP.Alias, doc)); - property.AppendChild(CreateNode("Value", ssP.Value, doc)); - } - stylesheet.AppendChild(properties); - } - return stylesheet; - } - - - /// - /// Appends a file to package manifest and copies the file to the correct folder. - /// - /// The path. - /// The package directory. - /// The doc. - public static void AppendFileToManifest(string path, string packageDirectory, XmlDocument doc) - { - if (!path.StartsWith("~/") && !path.StartsWith("/")) - path = "~/" + path; - - string serverPath = IOHelper.MapPath(path); - - if (System.IO.File.Exists(serverPath)) - - AppendFileXml(path, packageDirectory, doc); - else if (System.IO.Directory.Exists(serverPath)) - ProcessDirectory(path, packageDirectory, doc); - } - - - - //Process files in directory and add them to package - private static void ProcessDirectory(string path, string packageDirectory, XmlDocument doc) - { - string serverPath = IOHelper.MapPath(path); - if (System.IO.Directory.Exists(serverPath)) - { - System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(serverPath); - - foreach (System.IO.FileInfo file in di.GetFiles()) - AppendFileXml(path + "/" + file.Name, packageDirectory, doc); - - foreach (System.IO.DirectoryInfo dir in di.GetDirectories()) - ProcessDirectory(path + "/" + dir.Name, packageDirectory, doc); - } - } - - private static void AppendFileXml(string path, string packageDirectory, XmlDocument doc) - { - - string serverPath = IOHelper.MapPath(path); - - string orgPath = path.Substring(0, (path.LastIndexOf('/'))); - string orgName = path.Substring((path.LastIndexOf('/') + 1)); - string newFileName = orgName; - - if (System.IO.File.Exists(packageDirectory + "/" + orgName)) - { - string fileGuid = System.Guid.NewGuid().ToString(); - newFileName = fileGuid + "_" + newFileName; - } - - //Copy file to directory for zipping... - System.IO.File.Copy(serverPath, packageDirectory + "/" + newFileName, true); - - //Append file info to files xml node - XmlNode files = doc.SelectSingleNode("/umbPackage/files"); - - XmlNode file = doc.CreateElement("file"); - file.AppendChild(CreateNode("guid", newFileName, doc)); - file.AppendChild(CreateNode("orgPath", orgPath == "" ? "/" : orgPath, doc)); - file.AppendChild(CreateNode("orgName", orgName, doc)); - - files.AppendChild(file); - } - - /// - /// Determines whether the file is in the package manifest - /// - /// The GUID. - /// The doc. - /// - /// true if [is file in manifest]; otherwise, false. - /// - public static bool IsFileInManifest(string guid, XmlDocument doc) - { - return false; - } - - private static XmlNode CreateNode(string name, string value, XmlDocument doc) - { - var node = doc.CreateElement(name); - node.InnerXml = value; - return node; - } - - private static XmlAttribute CreateAttribute(string name, string value, XmlDocument doc) - { - var attribute = doc.CreateAttribute(name); - attribute.Value = value; - return attribute; - } - - /// - /// Zips the package. - /// - /// The path. - /// The save path. - public static void ZipPackage(string Path, string savePath) - { - string OutPath = savePath; - - ArrayList ar = GenerateFileList(Path); - // generate file list - // find number of chars to remove from orginal file path - int TrimLength = (Directory.GetParent(Path)).ToString().Length; - - TrimLength += 1; - - //remove '\' - FileStream ostream; - - byte[] obuffer; - - ZipOutputStream oZipStream = new ZipOutputStream(System.IO.File.Create(OutPath)); - // create zip stream - - - oZipStream.SetLevel(9); - // 9 = maximum compression level - ZipEntry oZipEntry; - - foreach (string Fil in ar) // for each file, generate a zipentry - { - oZipEntry = new ZipEntry(Fil.Remove(0, TrimLength)); - oZipStream.PutNextEntry(oZipEntry); - - - if (!Fil.EndsWith(@"/")) // if a file ends with '/' its a directory - { - ostream = File.OpenRead(Fil); - - obuffer = new byte[ostream.Length]; - - // byte buffer - ostream.Read(obuffer, 0, obuffer.Length); - - oZipStream.Write(obuffer, 0, obuffer.Length); - ostream.Close(); - } - } - oZipStream.Finish(); - oZipStream.Close(); - oZipStream.Dispose(); - oZipStream = null; - - oZipEntry = null; - - - ostream = null; - ar.Clear(); - ar = null; - } - - private static ArrayList GenerateFileList(string Dir) - { - ArrayList mid = new ArrayList(); - - bool Empty = true; - - // add each file in directory - foreach (string file in Directory.GetFiles(Dir)) - { - mid.Add(file); - Empty = false; - } - - // if directory is completely empty, add it - if (Empty && Directory.GetDirectories(Dir).Length == 0) - mid.Add(Dir + @"/"); - - // do this recursively - foreach (string dirs in Directory.GetDirectories(Dir)) - { - foreach (object obj in GenerateFileList(dirs)) - mid.Add(obj); - } - return mid; // return file list - } - } -} diff --git a/src/Umbraco.Web/_Legacy/Packager/Settings.cs b/src/Umbraco.Web/_Legacy/Packager/Settings.cs index 92b0ae030a..e88f18262f 100644 --- a/src/Umbraco.Web/_Legacy/Packager/Settings.cs +++ b/src/Umbraco.Web/_Legacy/Packager/Settings.cs @@ -8,10 +8,6 @@ namespace Umbraco.Web._Legacy.Packager { public static string InstalledPackagesSettings => SystemDirectories.Packages + IOHelper.DirSepChar + "installedPackages.config"; - public static string CreatedPackagesSettings => SystemDirectories.Packages + IOHelper.DirSepChar + "createdPackages.config"; - - public static string PackageFileExtension => "zip"; - } } diff --git a/src/Umbraco.Web/_Legacy/Packager/data.cs b/src/Umbraco.Web/_Legacy/Packager/data.cs index 1882c151d2..51f0799689 100644 --- a/src/Umbraco.Web/_Legacy/Packager/data.cs +++ b/src/Umbraco.Web/_Legacy/Packager/data.cs @@ -95,7 +95,7 @@ namespace Umbraco.Web._Legacy.Packager instance.Attributes.Append(XmlHelper.AddAttribute(Source, "url", "")); instance.Attributes.Append(XmlHelper.AddAttribute(Source, "name", name)); instance.Attributes.Append(XmlHelper.AddAttribute(Source, "folder", Guid.NewGuid().ToString())); - instance.Attributes.Append(XmlHelper.AddAttribute(Source, "packagepath", "")); + instance.Attributes.Append(XmlHelper.AddAttribute(Source, "packagePath", "")); instance.Attributes.Append(XmlHelper.AddAttribute(Source, "repositoryGuid", "")); instance.Attributes.Append(XmlHelper.AddAttribute(Source, "iconUrl", "")); //set to current version @@ -187,13 +187,11 @@ namespace Umbraco.Web._Legacy.Packager { retVal.Id = int.Parse(SafeAttribute("id", n)); retVal.Name = SafeAttribute("name", n); - retVal.Folder = SafeAttribute("folder", n); - retVal.PackagePath = SafeAttribute("packagepath", n); + retVal.FolderId = Guid.Parse(SafeAttribute("folder", n)); + retVal.PackagePath = SafeAttribute("packagePath", n); retVal.Version = SafeAttribute("version", n); retVal.Url = SafeAttribute("url", n); - retVal.RepositoryGuid = SafeAttribute("repositoryGuid", n); - retVal.PackageGuid = SafeAttribute("packageGuid", n); - retVal.HasUpdate = bool.Parse(SafeAttribute("hasUpdate", n)); + retVal.PackageId = Guid.Parse(SafeAttribute("packageGuid", n)); retVal.IconUrl = SafeAttribute("iconUrl", n); var umbVersion = SafeAttribute("umbVersion", n); @@ -262,10 +260,8 @@ namespace Umbraco.Web._Legacy.Packager XmlHelper.SetAttribute(Source, xmlDef, "name", package.Name); XmlHelper.SetAttribute(Source, xmlDef, "version", package.Version); XmlHelper.SetAttribute(Source, xmlDef, "url", package.Url); - XmlHelper.SetAttribute(Source, xmlDef, "packagepath", package.PackagePath); - XmlHelper.SetAttribute(Source, xmlDef, "repositoryGuid", package.RepositoryGuid); - XmlHelper.SetAttribute(Source, xmlDef, "packageGuid", package.PackageGuid); - XmlHelper.SetAttribute(Source, xmlDef, "hasUpdate", package.HasUpdate.ToString()); + XmlHelper.SetAttribute(Source, xmlDef, "packagePath", package.PackagePath); + XmlHelper.SetAttribute(Source, xmlDef, "packageGuid", package.PackageId.ToString()); XmlHelper.SetAttribute(Source, xmlDef, "iconUrl", package.IconUrl); if (package.UmbracoVersion != null) XmlHelper.SetAttribute(Source, xmlDef, "umbVersion", package.UmbracoVersion.ToString(3)); @@ -359,7 +355,7 @@ namespace Umbraco.Web._Legacy.Packager } - private static string JoinList(List list, char seperator) + private static string JoinList(IList list, char seperator) { string retVal = ""; foreach (string str in list) diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/editPackage.aspx b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/editPackage.aspx deleted file mode 100644 index d7b71ecde1..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/editPackage.aspx +++ /dev/null @@ -1,232 +0,0 @@ -<%@ Page Language="C#" ValidateRequest="false" AutoEventWireup="true" MasterPageFile="../../masterpages/umbracoPage.Master" - Title="Package and export content" CodeBehind="editPackage.aspx.cs" Inherits="umbraco.presentation.developer.packages._Default" %> - -<%@ Register TagPrefix="cc2" Namespace="Umbraco.Web._Legacy.Controls" Assembly="Umbraco.Web" %> - - - - - - - - - * - - - - * - - - - * - - - - - - - - - - - - - - * - Invalid version number (eg. 7.5.0) - - - - - - - * - - - - * - - - - - - - * - - - - * - - - - - - - - - - -
    - - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - Remember: .xslt and .ascx files for your macros - will be added automaticly, but you will still need to add assemblies, - images and script files manually to the list below. -
    -
    - - - - - - - - - - - - - - - - - -
    - Absolute path to file (ie: /bin/umbraco.bin) - -
    - - - -
    - - - - - - -
    -
    - - - - - - - - -
    - Load control after installation (ex: /usercontrols/installer.ascx) -
    - - - - -
    -
    - - - - - - - - - - - -
    -

    - Here you can add custom installer / uninstaller events to perform certain tasks - during installation and uninstallation. -
    - All actions are formed as a xml node, containing data for the action to be performed. - Package actions documentation -

    - -
    - Actions: -
    - -
    -
    - -
    diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/editPackage.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/editPackage.aspx.cs deleted file mode 100644 index 3b863895a4..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/editPackage.aspx.cs +++ /dev/null @@ -1,453 +0,0 @@ -using Umbraco.Core.Services; -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Web.UI; -using System.Web.UI.WebControls; - -using System.Xml; -using umbraco.controls; -using Umbraco.Core; -using Umbraco.Core.IO; -using Umbraco.Core.Models.Packaging; -using Umbraco.Web.Models.ContentEditing; -using Umbraco.Web.UI; -using Umbraco.Web.UI.Pages; -using Umbraco.Web._Legacy.Packager.PackageInstance; - -namespace umbraco.presentation.developer.packages -{ - public partial class _Default : UmbracoEnsuredPage - { - - public _Default() - { - CurrentApp = Constants.Applications.Packages.ToString(); - - } - public Umbraco.Web._Legacy.Controls.TabPage packageInfo; - public Umbraco.Web._Legacy.Controls.TabPage packageContents; - public Umbraco.Web._Legacy.Controls.TabPage packageFiles; - public Umbraco.Web._Legacy.Controls.TabPage packageOutput; - public Umbraco.Web._Legacy.Controls.TabPage packageAbout; - public Umbraco.Web._Legacy.Controls.TabPage packageActions; - - protected ContentPicker cp; - private PackageDefinition pack; - private CreatedPackage createdPackage; - - protected void Page_Load(object sender, EventArgs e) - { - if (Request.QueryString["id"] != null) - { - createdPackage = CreatedPackage.GetById(int.Parse(Request.QueryString["id"])); - pack = createdPackage.Data; - - /* CONTENT */ - - cp = new ContentPicker(); - content.Controls.Add(cp); - - if (string.IsNullOrEmpty(pack.PackagePath) == false) - { - packageUmbFile.Text = "   Download"; - } - else - { - packageUmbFile.Text = "This package is not published"; - } - - if (Page.IsPostBack == false) - { - ClientTools - .SyncTree("-1,created," + createdPackage.Data.Id, false); - - packageAuthorName.Text = pack.Author; - packageAuthorUrl.Text = pack.AuthorUrl; - packageLicenseName.Text = pack.License; - packageLicenseUrl.Text = pack.LicenseUrl; - packageName.Text = pack.Name; - packageReadme.Text = pack.Readme; - packageVersion.Text = pack.Version; - packageUrl.Text = pack.Url; - iconUrl.Text = pack.IconUrl; - umbracoVersion.Text = pack.UmbracoVersion != null ? pack.UmbracoVersion.ToString(3) : string.Empty; - - /*ACTIONS XML*/ - tb_actions.Text = pack.Actions; - - cp.Value = pack.ContentNodeId.ToString(); - - //startNode.Value = pack.ContentNodeId.ToString(); - - packageContentSubdirs.Checked = pack.ContentLoadChildNodes; - - - /*TEMPLATES */ - var nTemplates = Services.FileService.GetTemplates(); - //Template[] umbTemplates = Template.GetAllAsList().ToArray(); - foreach (var tmp in nTemplates) - { - ListItem li = new ListItem(tmp.Name, tmp.Id.ToString()); - - if (pack.Templates.Contains(tmp.Id.ToString())) - li.Selected = true; - - templates.Items.Add(li); - } - - /* DOC TYPES */ - // fixme - media types? member types? - var nContentTypes = Services.ContentTypeService.GetAll(); - //DocumentType[] docs = DocumentType.GetAllAsList().ToArray(); - foreach (var dc in nContentTypes) - { - ListItem li = new ListItem(dc.Name, dc.Id.ToString()); - if (pack.DocumentTypes.Contains(dc.Id.ToString())) - li.Selected = true; - - documentTypes.Items.Add(li); - } - - /*Stylesheets */ - var sheets = Services.FileService.GetStylesheets(); - foreach (var st in sheets) - { - if (string.IsNullOrEmpty(st.Name) == false) - { - var li = new ListItem(st.Alias, st.Name); - if (pack.Stylesheets.Contains(st.Name)) - li.Selected = true; - stylesheets.Items.Add(li); - } - } - - /* MACROS */ - var nMacros = Services.MacroService.GetAll(); - //Macro[] umbMacros = Macro.GetAll(); - foreach (var m in nMacros) - { - ListItem li = new ListItem(m.Name, m.Id.ToString()); - if (pack.Macros.Contains(m.Id.ToString())) - li.Selected = true; - - macros.Items.Add(li); - } - - /*Langauges */ - var nLanguages = Services.LocalizationService.GetAllLanguages(); - //Language[] umbLanguages = Language.getAll; - foreach (var l in nLanguages) - { - ListItem li = new ListItem(l.CultureName, l.Id.ToString()); - if (pack.Languages.Contains(l.Id.ToString())) - li.Selected = true; - - languages.Items.Add(li); - } - - /*Dictionary Items*/ - var umbDictionary = Services.LocalizationService.GetRootDictionaryItems(); - foreach (var d in umbDictionary) - { - - string liName = d.ItemKey; - var children = Services.LocalizationService.GetDictionaryItemChildren(d.Key); - if (children.Any()) - liName += " (Including all child items)"; - - var li = new ListItem(liName, d.Id.ToString()); - - if (pack.DictionaryItems.Contains(d.Id.ToString())) - li.Selected = true; - - dictionary.Items.Add(li); - } - - //TODO: Fix this with the new services and apis! and then remove since this should all be in angular - - ///*Data types */ - //cms.businesslogic.datatype.DataTypeDefinition[] umbDataType = cms.businesslogic.datatype.DataTypeDefinition.GetAll(); - - // sort array by name - //Array.Sort(umbDataType, delegate(cms.businesslogic.datatype.DataTypeDefinition umbDataType1, cms.businesslogic.datatype.DataTypeDefinition umbDataType2) - //{ - // return umbDataType1.Text.CompareTo(umbDataType2.Text); - //}); - - //foreach (cms.businesslogic.datatype.DataTypeDefinition umbDtd in umbDataType) - //{ - - // ListItem li = new ListItem(umbDtd.Text, umbDtd.Id.ToString()); - - // if (pack.DataTypes.Contains(umbDtd.Id.ToString())) - // li.Selected = true; - - // cbl_datatypes.Items.Add(li); - //} - - /* FILES */ - packageFilesRepeater.DataSource = pack.Files; - packageFilesRepeater.DataBind(); - - packageControlPath.Text = pack.LoadControl; - } - else - { - ClientTools - .SyncTree("-1,created," + createdPackage.Data.Id, true); - } - } - } - - protected void validateActions(object sender, ServerValidateEventArgs e) - { - string actions = tb_actions.Text; - if (!string.IsNullOrEmpty(actions)) - { - - actions = "" + actions + ""; - - try - { - //we try to load an xml document with the potential malformed xml to ensure that this is actual action xml... - XmlDocument xd = new XmlDocument(); - xd.LoadXml(actions); - e.IsValid = true; - } - catch - { - e.IsValid = false; - } - } - else - e.IsValid = true; - } - - //protected void saveOrPublish(object sender, CommandEventArgs e) - //{ - - // if (!Page.IsValid) - // { - // this.ClientTools.ShowSpeechBubble(SpeechBubbleIcon.Error, "Saved failed.", "Some fields have not been filled-out correctly"); - // } - // else - // { - // if (e.CommandName == "save") - // SavePackage(true); - - // if (e.CommandName == "publish") - // { - // SavePackage(false); - // int packageID = int.Parse(Request.QueryString["id"]); - // //string packFileName = cms.businesslogic.packager. Publish.publishPackage(packageID); - - // createdPackage.Publish(); - - - // if (!string.IsNullOrEmpty(pack.PackagePath)) - // { - - // packageUmbFile.Text = "   Download"; - - // this.ClientTools.ShowSpeechBubble(SpeechBubbleIcon.Success, "Package saved and published", ""); - // } - // else - // { - // this.ClientTools.ShowSpeechBubble(SpeechBubbleIcon.Error, "Save failed", "check your umbraco log."); - // } - // } - // } - //} - - - private void SavePackage(bool showNotification) - { - pack.Author = packageAuthorName.Text; - pack.AuthorUrl = packageAuthorUrl.Text; - - pack.License = packageLicenseName.Text; - pack.LicenseUrl = packageLicenseUrl.Text; - - pack.Readme = packageReadme.Text; - pack.Actions = tb_actions.Text; - - pack.Name = packageName.Text; - pack.Url = packageUrl.Text; - pack.Version = packageVersion.Text; - pack.IconUrl = iconUrl.Text; - pack.UmbracoVersion = Version.Parse(umbracoVersion.Text); - - pack.ContentLoadChildNodes = packageContentSubdirs.Checked; - - if (string.IsNullOrEmpty(cp.Value) == false) - pack.ContentNodeId = cp.Value; - else - pack.ContentNodeId = ""; - - - string tmpStylesheets = ""; - foreach (ListItem li in stylesheets.Items) - { - if (li.Selected) - tmpStylesheets += li.Value + ","; - } - pack.Stylesheets = new List(tmpStylesheets.Trim(',').Split(',')); - - - string tmpDoctypes = ""; - foreach (ListItem li in documentTypes.Items) - { - if (li.Selected) - tmpDoctypes += li.Value + ","; - } - pack.DocumentTypes = new List(tmpDoctypes.Trim(',').Split(',')); - - - string tmpMacros = ""; - foreach (ListItem li in macros.Items) - { - if (li.Selected) - tmpMacros += li.Value + ","; - } - pack.Macros = new List(tmpMacros.Trim(',').Split(',')); - - - string tmpLanguages = ""; - foreach (ListItem li in languages.Items) - { - if (li.Selected) - tmpLanguages += li.Value + ","; - } - pack.Languages = new List(tmpLanguages.Trim(',').Split(',')); - - string tmpDictionaries = ""; - foreach (ListItem li in dictionary.Items) - { - if (li.Selected) - tmpDictionaries += li.Value + ","; - } - pack.DictionaryItems = new List(tmpDictionaries.Trim(',').Split(',')); - - - string tmpTemplates = ""; - foreach (ListItem li in templates.Items) - { - if (li.Selected) - tmpTemplates += li.Value + ","; - } - pack.Templates = new List(tmpTemplates.Trim(',').Split(',')); - - string tmpDataTypes = ""; - foreach (ListItem li in cbl_datatypes.Items) - { - if (li.Selected) - tmpDataTypes += li.Value + ","; - } - pack.DataTypes = new List(tmpDataTypes.Trim(',').Split(',')); - - pack.LoadControl = packageControlPath.Text; - - - createdPackage.Save(); - - if (showNotification) - this.ClientTools.ShowSpeechBubble(SpeechBubbleIcon.Save, "Package Saved", ""); - } - - protected void addFileToPackage(object sender, EventArgs e) - { - string newPath = packageFilePathNew.Text; - - if (newPath.Trim() != "") - { - CreatedPackage createdPackage = CreatedPackage.GetById(int.Parse(Request.QueryString["id"])); - PackageDefinition pack = createdPackage.Data; - - pack.Files.Add(newPath); - - createdPackage.Save(); - - packageFilePathNew.Text = ""; - - packageFilesRepeater.DataSource = pack.Files; - packageFilesRepeater.DataBind(); - } - } - - protected void deleteFileFromPackage(object sender, EventArgs e) - { - TextBox filePathControl = (TextBox)((Control)sender).Parent.FindControl("packageFilePath"); - filePathControl.Text = ""; - - string tmpFilePathString = ""; - foreach (RepeaterItem rItem in packageFilesRepeater.Items) - { - string tmpFFFF = ((TextBox)rItem.FindControl("packageFilePath")).Text; - if (tmpFFFF.Trim() != "") - tmpFilePathString += tmpFFFF + "�"; - } - - CreatedPackage createdPackage = CreatedPackage.GetById(int.Parse(Request.QueryString["id"])); - PackageDefinition pack = createdPackage.Data; - - pack.Files = new List(tmpFilePathString.Trim('�').Split('�')); - pack.Files.TrimExcess(); - - createdPackage.Save(); - - packageFilesRepeater.DataSource = pack.Files; - packageFilesRepeater.DataBind(); - } - - protected override void OnInit(EventArgs e) - { - // Tab setup - packageInfo = TabView1.NewTabPage("Package Properties"); - packageInfo.Controls.Add(Pane1); - packageInfo.Controls.Add(Pane5); - packageInfo.Controls.Add(Pane1_1); - packageInfo.Controls.Add(Pane1_2); - packageInfo.Controls.Add(Pane1_3); - - - packageContents = TabView1.NewTabPage("Package Contents"); - packageContents.Controls.Add(Pane2); - packageContents.Controls.Add(Pane2_1); - packageContents.Controls.Add(Pane2_2); - packageContents.Controls.Add(Pane2_3); - packageContents.Controls.Add(Pane2_4); - packageContents.Controls.Add(Pane2_5); - packageContents.Controls.Add(Pane2_6); - packageContents.Controls.Add(Pane2_7); - - packageFiles = TabView1.NewTabPage("Package Files"); - packageFiles.Controls.Add(Pane3); - packageFiles.Controls.Add(Pane3_1); - packageFiles.Controls.Add(Pane3_2); - - packageActions = TabView1.NewTabPage("Package Actions"); - packageActions.Controls.Add(Pane4); - - //var pubs = TabView1.Menu.NewButton(); - //pubs.Text = Services.TextService.Localize("publish"); - //pubs.CommandName = "publish"; - //pubs.Command += new CommandEventHandler(saveOrPublish); - //pubs.ID = "saveAndPublish"; - - //var saves = TabView1.Menu.NewButton(); - //saves.Text = Services.TextService.Localize("save"); - //saves.CommandName = "save"; - //saves.Command += new CommandEventHandler(saveOrPublish); - //saves.ButtonType = Umbraco.Web._Legacy.Controls.MenuButtonType.Primary; - //saves.ID = "save"; - - - - - base.OnInit(e); - } - - } -} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/editPackage.aspx.designer.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/editPackage.aspx.designer.cs deleted file mode 100644 index d41967444a..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/editPackage.aspx.designer.cs +++ /dev/null @@ -1,609 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace umbraco.presentation.developer.packages { - - - public partial class _Default { - - /// - /// TabView1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.TabView TabView1; - - /// - /// Pane1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.Pane Pane1; - - /// - /// pp_name control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.PropertyPanel pp_name; - - /// - /// packageName control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox packageName; - - /// - /// RequiredFieldValidator0 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.RequiredFieldValidator RequiredFieldValidator0; - - /// - /// pp_url control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.PropertyPanel pp_url; - - /// - /// packageUrl control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox packageUrl; - - /// - /// RequiredFieldValidator1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.RequiredFieldValidator RequiredFieldValidator1; - - /// - /// pp_version control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.PropertyPanel pp_version; - - /// - /// packageVersion control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox packageVersion; - - /// - /// RequiredFieldValidator2 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.RequiredFieldValidator RequiredFieldValidator2; - - /// - /// pp_icon control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.PropertyPanel pp_icon; - - /// - /// iconUrl control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox iconUrl; - - /// - /// pp_file control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.PropertyPanel pp_file; - - /// - /// packageUmbFile control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Literal packageUmbFile; - - /// - /// Pane5 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.Pane Pane5; - - /// - /// pp_umbracoVersion control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.PropertyPanel pp_umbracoVersion; - - /// - /// umbracoVersion control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox umbracoVersion; - - /// - /// RequiredFieldValidator7 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.RequiredFieldValidator RequiredFieldValidator7; - - /// - /// VersionValidator control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.RegularExpressionValidator VersionValidator; - - /// - /// Pane1_1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.Pane Pane1_1; - - /// - /// pp_author control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.PropertyPanel pp_author; - - /// - /// packageAuthorName control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox packageAuthorName; - - /// - /// RequiredFieldValidator3 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.RequiredFieldValidator RequiredFieldValidator3; - - /// - /// pp_author_url control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.PropertyPanel pp_author_url; - - /// - /// packageAuthorUrl control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox packageAuthorUrl; - - /// - /// RequiredFieldValidator4 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.RequiredFieldValidator RequiredFieldValidator4; - - /// - /// Pane1_2 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.Pane Pane1_2; - - /// - /// pp_licens control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.PropertyPanel pp_licens; - - /// - /// packageLicenseName control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox packageLicenseName; - - /// - /// RequiredFieldValidator5 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.RequiredFieldValidator RequiredFieldValidator5; - - /// - /// pp_license_url control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.PropertyPanel pp_license_url; - - /// - /// packageLicenseUrl control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox packageLicenseUrl; - - /// - /// RequiredFieldValidator6 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.RequiredFieldValidator RequiredFieldValidator6; - - /// - /// Pane1_3 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.Pane Pane1_3; - - /// - /// pp_readme control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.PropertyPanel pp_readme; - - /// - /// packageReadme control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox packageReadme; - - /// - /// Pane2 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.Pane Pane2; - - /// - /// pp_content control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.PropertyPanel pp_content; - - /// - /// content control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.PlaceHolder content; - - /// - /// packageContentSubdirs control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.CheckBox packageContentSubdirs; - - /// - /// packageContentSubdirsLabel control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Label packageContentSubdirsLabel; - - /// - /// Pane2_1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.Pane Pane2_1; - - /// - /// documentTypes control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.CheckBoxList documentTypes; - - /// - /// Pane2_2 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.Pane Pane2_2; - - /// - /// templates control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.CheckBoxList templates; - - /// - /// Pane2_3 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.Pane Pane2_3; - - /// - /// stylesheets control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.CheckBoxList stylesheets; - - /// - /// Pane2_4 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.Pane Pane2_4; - - /// - /// macros control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.CheckBoxList macros; - - /// - /// Pane2_5 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.Pane Pane2_5; - - /// - /// languages control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.CheckBoxList languages; - - /// - /// Pane2_6 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.Pane Pane2_6; - - /// - /// dictionary control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.CheckBoxList dictionary; - - /// - /// Pane2_7 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.Pane Pane2_7; - - /// - /// cbl_datatypes control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.CheckBoxList cbl_datatypes; - - /// - /// Pane3 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.Pane Pane3; - - /// - /// Pane3_1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.Pane Pane3_1; - - /// - /// packageFilesRepeater control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Repeater packageFilesRepeater; - - /// - /// packageFilePathNew control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox packageFilePathNew; - - /// - /// createNewFilePath control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Button createNewFilePath; - - /// - /// Pane3_2 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.Pane Pane3_2; - - /// - /// packageControlPath control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox packageControlPath; - - /// - /// Pane4 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.Pane Pane4; - - /// - /// actionsVal control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.CustomValidator actionsVal; - - /// - /// tb_actions control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox tb_actions; - } -} From b0b0477dab7f30c2b482af792038818808f86342 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Thu, 10 Jan 2019 07:34:28 +0100 Subject: [PATCH 275/469] #3642 -bugfix for nonvariant --- src/Umbraco.Core/Services/Implement/ContentService.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Core/Services/Implement/ContentService.cs b/src/Umbraco.Core/Services/Implement/ContentService.cs index d44ce2a0dc..1e89e190c8 100644 --- a/src/Umbraco.Core/Services/Implement/ContentService.cs +++ b/src/Umbraco.Core/Services/Implement/ContentService.cs @@ -2754,7 +2754,10 @@ namespace Umbraco.Core.Services.Implement } content.Name = blueprint.Name; - content.SetCultureInfo(culture, blueprint.GetCultureName(culture), now); + if (!string.IsNullOrEmpty(culture)) + { + content.SetCultureInfo(culture, blueprint.GetCultureName(culture), now); + } } From d672531b0bedf50b072515878b0f479bde3bb567 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Thu, 10 Jan 2019 07:58:45 +0100 Subject: [PATCH 276/469] #3642 - reuse method for determine if the content is new --- src/Umbraco.Web/Editors/ContentController.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs index 26698b227f..94c040f4d6 100644 --- a/src/Umbraco.Web/Editors/ContentController.cs +++ b/src/Umbraco.Web/Editors/ContentController.cs @@ -1737,18 +1737,12 @@ namespace Umbraco.Web.Editors bool Varies(Property property) => property.PropertyType.VariesByCulture(); var variantIndex = 0; - var newContent = (contentSave.Action == ContentSaveAction.SaveNew - || contentSave.Action == ContentSaveAction.PublishNew - || contentSave.Action == ContentSaveAction.ScheduleNew - || contentSave.Action == ContentSaveAction.SendPublishNew - || contentSave.Action == ContentSaveAction.PublishWithDescendantsNew - || contentSave.Action == ContentSaveAction.PublishWithDescendantsForceNew - ); + //loop through each variant, set the correct name and property values foreach (var variant in contentSave.Variants) { //Don't update anything for this variant if Save is not true - if (!variant.Save && !newContent) continue; + if (!variant.Save && !IsCreatingAction(contentSave.Action)) continue; //Don't update the name if it is empty if (!variant.Name.IsNullOrWhiteSpace()) From 091c9471bb3cc7b63b1f7870ebf6bebc07392024 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 10 Jan 2019 18:51:02 +1100 Subject: [PATCH 277/469] Gets macros in packages, gets the download button working to download a created package, more tests --- .../Models/Packaging/PackageDefinition.cs | 2 + src/Umbraco.Core/Packaging/PackageBuilder.cs | 22 +++++++--- .../src/views/packages/edit.controller.js | 24 +++++++++-- .../src/views/packages/edit.html | 25 +++++++++-- src/Umbraco.Web/Editors/PackageController.cs | 41 ++++++++++++++++++- 5 files changed, 101 insertions(+), 13 deletions(-) diff --git a/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs b/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs index 16934dc4c4..67d0c2970f 100644 --- a/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs +++ b/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; @@ -29,6 +30,7 @@ namespace Umbraco.Core.Models.Packaging [DataMember(Name = "folder")] public Guid FolderId { get; set; } + [ReadOnly(true)] [DataMember(Name = "packagePath")] public string PackagePath { get; set; } = string.Empty; diff --git a/src/Umbraco.Core/Packaging/PackageBuilder.cs b/src/Umbraco.Core/Packaging/PackageBuilder.cs index cc77f9bc78..6b26b09cbe 100644 --- a/src/Umbraco.Core/Packaging/PackageBuilder.cs +++ b/src/Umbraco.Core/Packaging/PackageBuilder.cs @@ -162,7 +162,9 @@ namespace Umbraco.Core.Packaging var actionsXml = new XElement("Actions"); try { - actionsXml.Add(XElement.Parse(definition.Actions)); + //this will be formatted like a full xml block like ... and we want the child nodes + var parsed = XElement.Parse(definition.Actions); + actionsXml.Add(parsed.Elements()); manifestRoot.Add(actionsXml); } catch (Exception e) @@ -596,7 +598,7 @@ namespace Umbraco.Core.Packaging Author = xml.Element("author")?.Value ?? string.Empty, AuthorUrl = xml.Element("author")?.AttributeValue("url") ?? string.Empty, Readme = xml.Element("readme")?.Value ?? string.Empty, - Actions = xml.Element("actions")?.ToString() ?? string.Empty, + Actions = xml.Element("actions")?.ToString(SaveOptions.None) ?? string.Empty, //take the entire outer xml value ContentNodeId = xml.Element("content")?.AttributeValue("nodeId") ?? string.Empty, ContentLoadChildNodes = xml.Element("content")?.AttributeValue("loadChildNodes") ?? false, Macros = xml.Element("macros")?.Value.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(), @@ -613,8 +615,18 @@ namespace Umbraco.Core.Packaging return retVal; } - private static XElement PackageDefinitionToXml(PackageDefinition def) + private XElement PackageDefinitionToXml(PackageDefinition def) { + var actionsXml = new XElement("actions"); + try + { + actionsXml = XElement.Parse(def.Actions); + } + catch (Exception e) + { + _logger.Warn(e, "Could not add package actions to the package xml definition, the xml did not parse"); + } + var packageXml = new XElement("package", new XAttribute("id", def.Id), new XAttribute("version", def.Version ?? string.Empty), @@ -634,8 +646,8 @@ namespace Umbraco.Core.Packaging new XCData(def.Author ?? string.Empty), new XAttribute("url", def.AuthorUrl ?? string.Empty)), - new XElement("readme", def.Readme ?? string.Empty), - new XElement("actions", def.Actions ?? string.Empty), + new XElement("readme", new XCData(def.Readme ?? string.Empty)), + actionsXml, new XElement("datatypes", string.Join(",", def.DataTypes ?? Array.Empty())), new XElement("content", diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js index 5f3832f79b..f351456609 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js @@ -1,7 +1,7 @@ (function () { "use strict"; - function EditController($scope, $location, $routeParams, entityResource, stylesheetResource, languageResource, packageResource, dictionaryResource, editorService, formHelper) { + function EditController($scope, $location, $routeParams, umbRequestHelper, entityResource, stylesheetResource, languageResource, packageResource, dictionaryResource, editorService, formHelper) { const vm = this; @@ -21,6 +21,7 @@ vm.removeFile = removeFile; vm.openControlPicker = openControlPicker; vm.removeControl = removeControl; + vm.downloadFile = downloadFile; const packageId = $routeParams.id; const create = $routeParams.create; @@ -76,8 +77,14 @@ vm.stylesheets = stylesheets; }); - // TODO: implement macros - vm.macros = []; + entityResource.getAll("Macro").then(macros => { + // a package stores the id as a string so we + // need to convert all ids to string for comparison + macros.forEach(macro => { + macro.id = macro.id.toString(); + }); + vm.macros = macros; + }); // get all languages languageResource.getAll().then(languages => { @@ -111,6 +118,17 @@ } + function downloadFile(id) { + var url = umbRequestHelper.getApiUrl( + "packageApiBaseUrl", + "DownloadCreatedPackage", + { id: id }); + + umbRequestHelper.downloadFile(url).then(function () { + + }); + } + function back() { $location.path("packages/packages/overview").search('create', null);; } diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html index b1a417fd6f..20bc4277f8 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html @@ -48,9 +48,10 @@ + @@ -170,7 +171,15 @@ - NOT IMPLEMENTED IN V8 YET +
    + +
    +
    @@ -301,6 +310,14 @@ + + + + + diff --git a/src/Umbraco.Web/Editors/PackageController.cs b/src/Umbraco.Web/Editors/PackageController.cs index 66a0349417..0369e3eb24 100644 --- a/src/Umbraco.Web/Editors/PackageController.cs +++ b/src/Umbraco.Web/Editors/PackageController.cs @@ -1,9 +1,12 @@ using System.Collections.Generic; +using System.IO; using System.Linq; using System.Net; using System.Net.Http; using System.Net.Http.Formatting; +using System.Net.Http.Headers; using System.Web.Http; +using Umbraco.Core.IO; using Umbraco.Core.Models.Packaging; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Mvc; @@ -33,7 +36,7 @@ namespace Umbraco.Web.Editors var package = Services.PackagingService.GetById(id); if (package == null) throw new HttpResponseException(HttpStatusCode.NotFound); - + return package; } @@ -75,6 +78,40 @@ namespace Umbraco.Web.Editors return Ok(); } - + + [HttpGet] + public HttpResponseMessage DownloadCreatedPackage(int id) + { + var package = Services.PackagingService.GetById(id); + if (package == null) + return Request.CreateResponse(HttpStatusCode.NotFound); + + var fullPath = IOHelper.MapPath(package.PackagePath); + if (!File.Exists(fullPath)) + return Request.CreateNotificationValidationErrorResponse("No file found for path " + package.PackagePath); + + var fileName = Path.GetFileName(package.PackagePath); + + var response = new HttpResponseMessage + { + Content = new StreamContent(File.OpenRead(fullPath)) + { + Headers = + { + ContentDisposition = new ContentDispositionHeaderValue("attachment") + { + FileName = fileName + }, + ContentType = new MediaTypeHeaderValue( "application/octet-stream") + } + } + }; + + // Set custom header so umbRequestHelper.downloadFile can save the correct filename + response.Headers.Add("x-filename", fileName); + + return response; + } + } } From 5cb99bfddceafccb44d900b5ed3ef2bec56a1709 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 10 Jan 2019 18:55:24 +1100 Subject: [PATCH 278/469] forgot to add the test class --- .../Packaging/PackageBuilderTests.cs | 200 ++++++++++++++++++ .../src/views/packages/edit.html | 3 - 2 files changed, 200 insertions(+), 3 deletions(-) create mode 100644 src/Umbraco.Tests/Packaging/PackageBuilderTests.cs diff --git a/src/Umbraco.Tests/Packaging/PackageBuilderTests.cs b/src/Umbraco.Tests/Packaging/PackageBuilderTests.cs new file mode 100644 index 0000000000..6368001c11 --- /dev/null +++ b/src/Umbraco.Tests/Packaging/PackageBuilderTests.cs @@ -0,0 +1,200 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Xml.Linq; +using NUnit.Framework; +using Umbraco.Core; +using Umbraco.Core.Composing; +using Umbraco.Core.IO; +using Umbraco.Core.Models.Packaging; +using Umbraco.Core.Packaging; +using Umbraco.Core.Services; +using Umbraco.Tests.Services; +using Umbraco.Tests.TestHelpers; +using Umbraco.Tests.Testing; + +namespace Umbraco.Tests.Packaging +{ + [TestFixture] + [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerFixture)] + public class PackageBuilderTests : TestWithDatabaseBase + { + private Guid _testBaseFolder; + + public override void SetUp() + { + base.SetUp(); + _testBaseFolder = Guid.NewGuid(); + } + + public override void TearDown() + { + base.TearDown(); + + //clear out files/folders + Directory.Delete(IOHelper.MapPath("~/" + _testBaseFolder), true); + } + + public IPackageBuilder PackageBuilder => new PackageBuilder( + ServiceContext.ContentService, ServiceContext.ContentTypeService, ServiceContext.DataTypeService, + ServiceContext.FileService, ServiceContext.MacroService, ServiceContext.LocalizationService, + Factory.GetInstance(), Logger, + //temp paths + tempFolderPath: "~/" + _testBaseFolder + "/temp", + packagesFolderPath: "~/" + _testBaseFolder + "/packages", + mediaFolderPath: "~/" + _testBaseFolder + "/media"); + + [Test] + public void Delete() + { + var def1 = new PackageDefinition + { + Name = "test", + Url = "http://test.com", + Author = "Someone", + AuthorUrl = "http://test.com" + }; + + var result = PackageBuilder.SavePackage(def1); + Assert.IsTrue(result); + + PackageBuilder.Delete(def1.Id); + + def1 = PackageBuilder.GetById(def1.Id); + Assert.IsNull(def1); + } + + [Test] + public void Create_New() + { + var def1 = new PackageDefinition + { + Name = "test", + Url = "http://test.com", + Author = "Someone", + AuthorUrl = "http://test.com" + }; + + var result = PackageBuilder.SavePackage(def1); + + Assert.IsTrue(result); + Assert.AreEqual(1, def1.Id); + Assert.AreNotEqual(default(Guid).ToString(), def1.PackageId); + Assert.AreNotEqual(default(Guid).ToString(), def1.FolderId); + + var def2 = new PackageDefinition + { + Name = "test", + Url = "http://test.com", + Author = "Someone", + AuthorUrl = "http://test.com" + }; + + result = PackageBuilder.SavePackage(def2); + + Assert.IsTrue(result); + Assert.AreEqual(2, def2.Id); + Assert.AreNotEqual(default(Guid).ToString(), def2.PackageId); + Assert.AreNotEqual(default(Guid).ToString(), def2.FolderId); + } + + [Test] + public void Update_Not_Found() + { + var def = new PackageDefinition + { + Id = 3, //doesn't exist + Name = "test", + Url = "http://test.com", + Author = "Someone", + AuthorUrl = "http://test.com" + }; + + var result = PackageBuilder.SavePackage(def); + + Assert.IsFalse(result); + } + + [Test] + public void Update() + { + var def = new PackageDefinition + { + Name = "test", + Url = "http://test.com", + Author = "Someone", + AuthorUrl = "http://test.com" + }; + var result = PackageBuilder.SavePackage(def); + + def.Name = "updated"; + def.Files = new List {"hello.txt", "world.png"}; + result = PackageBuilder.SavePackage(def); + Assert.IsTrue(result); + + //re-get + def = PackageBuilder.GetById(def.Id); + Assert.AreEqual("updated", def.Name); + Assert.AreEqual(2, def.Files.Count); + //TODO: There's a whole lot more assertions to be done + + } + + [Test] + public void Export() + { + var file1 = $"~/{_testBaseFolder}/App_Plugins/MyPlugin/package.manifest"; + var file2 = $"~/{_testBaseFolder}/App_Plugins/MyPlugin/styles.css"; + var mappedFile1 = IOHelper.MapPath(file1); + var mappedFile2 = IOHelper.MapPath(file2); + Directory.CreateDirectory(Path.GetDirectoryName(mappedFile1)); + Directory.CreateDirectory(Path.GetDirectoryName(mappedFile2)); + File.WriteAllText(mappedFile1, "hello world"); + File.WriteAllText(mappedFile2, "hello world"); + + var def = new PackageDefinition + { + Name = "test", + Url = "http://test.com", + Author = "Someone", + AuthorUrl = "http://test.com", + Files = new List { file1, file2 }, + Actions = "" + }; + var result = PackageBuilder.SavePackage(def); + Assert.IsTrue(result); + Assert.IsTrue(def.PackagePath.IsNullOrWhiteSpace()); + + var zip = PackageBuilder.ExportPackage(def); + + def = PackageBuilder.GetById(def.Id); //re-get + Assert.IsNotNull(def.PackagePath); + + using (var archive = ZipFile.OpenRead(IOHelper.MapPath(zip))) + { + Assert.AreEqual(3, archive.Entries.Count); + + //the 2 files we manually added + Assert.IsNotNull(archive.Entries.Where(x => x.Name == "package.manifest")); + Assert.IsNotNull(archive.Entries.Where(x => x.Name == "styles.css")); + + //this is the actual package definition/manifest (not the developer manifest!) + var packageXml = archive.Entries.FirstOrDefault(x => x.Name == "package.xml"); + Assert.IsNotNull(packageXml); + + using (var stream = packageXml.Open()) + { + var xml = XDocument.Load(stream); + Assert.AreEqual("umbPackage", xml.Root.Name.ToString()); + Assert.AreEqual(2, xml.Root.Element("files").Elements("file").Count()); + + Assert.AreEqual("", xml.Element("umbPackage").Element("Actions").ToString(SaveOptions.DisableFormatting)); + + //TODO: There's a whole lot more assertions to be done + } + } + } + } +} diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html index 20bc4277f8..955676b806 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html @@ -158,7 +158,6 @@ -
    {{vm.stylesheets | json }}
    -
    {{vm.package | json}}
    - From 568d5c2583baf8bb691283ba406e0817718d0712 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 10 Jan 2019 19:08:52 +1100 Subject: [PATCH 279/469] Fixes issue with redirect --- src/Umbraco.Core/Models/Packaging/PackageDefinition.cs | 2 +- src/Umbraco.Core/Packaging/PackageBuilder.cs | 2 +- src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs b/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs index 67d0c2970f..01d10fa2e1 100644 --- a/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs +++ b/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs @@ -94,7 +94,7 @@ namespace Umbraco.Core.Models.Packaging public string LoadControl { get; set; } = string.Empty; [DataMember(Name = "actions")] - public string Actions { get; set; } + public string Actions { get; set; } = ""; [DataMember(Name = "dataTypes")] public IList DataTypes { get; set; } = new List(); diff --git a/src/Umbraco.Core/Packaging/PackageBuilder.cs b/src/Umbraco.Core/Packaging/PackageBuilder.cs index 6b26b09cbe..ae5accf794 100644 --- a/src/Umbraco.Core/Packaging/PackageBuilder.cs +++ b/src/Umbraco.Core/Packaging/PackageBuilder.cs @@ -598,7 +598,7 @@ namespace Umbraco.Core.Packaging Author = xml.Element("author")?.Value ?? string.Empty, AuthorUrl = xml.Element("author")?.AttributeValue("url") ?? string.Empty, Readme = xml.Element("readme")?.Value ?? string.Empty, - Actions = xml.Element("actions")?.ToString(SaveOptions.None) ?? string.Empty, //take the entire outer xml value + Actions = xml.Element("actions")?.ToString(SaveOptions.None) ?? "", //take the entire outer xml value ContentNodeId = xml.Element("content")?.AttributeValue("nodeId") ?? string.Empty, ContentLoadChildNodes = xml.Element("content")?.AttributeValue("loadChildNodes") ?? false, Macros = xml.Element("macros")?.Value.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(), diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js index f351456609..057f1160c2 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js @@ -146,7 +146,7 @@ if (create) { //if we are creating, then redirect to the correct url and reload - $location.path("packages/packages/overview/" + vm.package.id).search("subview", "created"); + $location.path("packages/packages/edit/" + vm.package.id).search("subview", "created").search("create", null); //don't add a browser history for this $location.replace(); } From 4bf3c1d05b9b228246e580c63785b72b83833311 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 10 Jan 2019 19:27:25 +1100 Subject: [PATCH 280/469] Handles trying to create a package with a duplicate name --- src/Umbraco.Core/Packaging/PackageBuilder.cs | 5 +++++ .../src/common/services/formhelper.service.js | 10 +++++----- src/Umbraco.Web/Editors/PackageController.cs | 6 +++++- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Core/Packaging/PackageBuilder.cs b/src/Umbraco.Core/Packaging/PackageBuilder.cs index ae5accf794..523ed6ed93 100644 --- a/src/Umbraco.Core/Packaging/PackageBuilder.cs +++ b/src/Umbraco.Core/Packaging/PackageBuilder.cs @@ -87,6 +87,11 @@ namespace Umbraco.Core.Packaging if (definition.Id == default) { + //check if the name already exists + var existsByName = packagesXml.Root.Elements("package").Any(x => x.AttributeValue("name") == definition.Name); + if (existsByName) + return false; + //need to gen an id and persist // Find max id var maxId = packagesXml.Root.Elements("package").Max(x => x.AttributeValue("id")) ?? 0; diff --git a/src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js index b21909f573..191e0a22c0 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js @@ -110,7 +110,7 @@ function formHelper(angularHelper, serverValidationManager, notificationsService //Or, some strange server error if (err.status === 400) { //now we need to look through all the validation errors - if (err.data && (err.data.ModelState)) { + if (err.data && err.data.ModelState) { //wire up the server validation errs this.handleServerValidation(err.data.ModelState); @@ -118,11 +118,11 @@ function formHelper(angularHelper, serverValidationManager, notificationsService //execute all server validation events and subscribers serverValidationManager.notifyAndClearAllSubscriptions(); } - else { + } + else { - //TODO: All YSOD handling should be done with an interceptor - overlayService.ysod(err); - } + //TODO: All YSOD handling should be done with an interceptor + overlayService.ysod(err); } }, diff --git a/src/Umbraco.Web/Editors/PackageController.cs b/src/Umbraco.Web/Editors/PackageController.cs index 0369e3eb24..215c81faac 100644 --- a/src/Umbraco.Web/Editors/PackageController.cs +++ b/src/Umbraco.Web/Editors/PackageController.cs @@ -57,7 +57,11 @@ namespace Umbraco.Web.Editors //save it if (!Services.PackagingService.SavePackage(model)) - throw new HttpResponseException(Request.CreateNotificationValidationErrorResponse("The package with id {definition.Id} was not found")); + throw new HttpResponseException( + Request.CreateNotificationValidationErrorResponse( + model.Id == default + ? $"A package with the name {model.Name} already exists" + : $"The package with id {model.Id} was not found")); Services.PackagingService.ExportPackage(model); From d2baf0311976cc45d6161853c08336656091c344 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Wed, 9 Jan 2019 11:20:34 +0100 Subject: [PATCH 281/469] Fix content picker dirty checking (#4003) (cherry picked from commit d41dbce60125cf9a8aa30e4d5a0bf39bddb59e1a) --- .../contentpicker/contentpicker.controller.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js index c1fe21b1b5..ee8c193b4b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js @@ -35,7 +35,6 @@ function contentPickerController($scope, entityResource, editorState, iconHelper return $scope.model.config.idType === "udi" ? i.udi : i.id; }); $scope.model.value = trim(currIds.join(), ","); - angularHelper.getCurrentForm($scope).$setDirty(); //Validate! if ($scope.model.config && $scope.model.config.minNumber && parseInt($scope.model.config.minNumber) > $scope.renderModel.length) { @@ -84,7 +83,10 @@ function contentPickerController($scope, entityResource, editorState, iconHelper opacity: 0.7, tolerance: "pointer", scroll: true, - zIndex: 6000 + zIndex: 6000, + update: function (e, ui) { + angularHelper.getCurrentForm($scope).$setDirty(); + } }; if ($scope.model.config) { From 228fca04ecf979b03ec725e64044800fe947b877 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Thu, 10 Jan 2019 10:06:42 +0100 Subject: [PATCH 282/469] #3642 - moved functionality to frontend about saving all variants the first time. --- .../views/content/overlays/save.controller.js | 40 ++++- .../src/views/content/overlays/save.html | 152 ++++++++++++------ .../Umbraco/config/lang/en_us.xml | 1 + src/Umbraco.Web/Editors/ContentController.cs | 4 +- 4 files changed, 139 insertions(+), 58 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/content/overlays/save.controller.js b/src/Umbraco.Web.UI.Client/src/views/content/overlays/save.controller.js index a99da13811..8d21234aee 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/overlays/save.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/content/overlays/save.controller.js @@ -1,16 +1,17 @@ (function () { "use strict"; - + function SaveContentController($scope, localizationService) { var vm = this; vm.loading = true; vm.hasPristineVariants = false; + vm.isNew = true; vm.changeSelection = changeSelection; vm.dirtyVariantFilter = dirtyVariantFilter; vm.pristineVariantFilter = pristineVariantFilter; - + function changeSelection(variant) { var firstSelected = _.find(vm.variants, function (v) { return v.save; @@ -30,8 +31,28 @@ return !(dirtyVariantFilter(variant)); } - function onInit() { + function hasAnyData(variant) { + var result = variant.isDirty != null || (variant.name != null && variant.name.length > 0); + if(result) return true; + + for (var t=0; t < variant.tabs.length; t++){ + for (var p=0; p < variant.tabs[t].properties.length; p++){ + + var property = variant.tabs[t].properties[p]; + + if(property.culture == null) continue; + + result = result || (property.value != null && property.value.length > 0); + + if(result) return true; + } + } + + return result; + } + + function onInit() { vm.variants = $scope.model.variants; if(!$scope.model.title) { @@ -42,6 +63,13 @@ vm.hasPristineVariants = false; + _.each(vm.variants, + function (variant) { + if(variant.state !== "NotCreated"){ + vm.isNew = false; + } + }); + _.each(vm.variants, function (variant) { variant.compositeId = variant.language.culture + "_" + (variant.segment ? variant.segment : ""); @@ -51,6 +79,10 @@ if (!vm.hasPristineVariants) { vm.hasPristineVariants = pristineVariantFilter(variant); } + + if(vm.isNew && hasAnyData(variant)){ + variant.save = true; + } }); if (vm.variants.length !== 0) { @@ -88,5 +120,5 @@ } angular.module("umbraco").controller("Umbraco.Overlays.SaveContentController", SaveContentController); - + })(); diff --git a/src/Umbraco.Web.UI.Client/src/views/content/overlays/save.html b/src/Umbraco.Web.UI.Client/src/views/content/overlays/save.html index 6f4aef4e84..c4dcd5b767 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/overlays/save.html +++ b/src/Umbraco.Web.UI.Client/src/views/content/overlays/save.html @@ -1,72 +1,120 @@
    -
    -

    -
    +
    -
    -
    - -
    - -
    - - -
    - -
    - -
    -
    {{saveVariantSelectorForm.saveVariantSelector.errorMsg}}
    -
    - -
    -
    {{notification.message}}
    -
    - -
    -
    - -
    +
    +
    +

    +
    + +
    + +
    + +
    + +
    + + +
    + +
    + +
    +
    {{saveVariantSelectorForm.saveVariantSelector.errorMsg}}
    +
    + +
    +
    {{notification.message}}
    +
    + +
    +
    + +
    +
    +
    -
    -
    -
    -

    +
    +
    +

    -
    -
    -
    - {{ variant.language.name }} - * -
    +
    -
    - -
    +
    + +
    + +
    + -
    -
    {{notification.message}}
    +
    + +
    + +
    +
    {{saveVariantSelectorForm.saveVariantSelector.errorMsg}}
    +
    + +
    +
    {{notification.message}}
    +
    + +
    +
    + + +
    +
    +
    + +
    +
    +

    +
    + +
    +
    +
    + {{ variant.language.name }} + * +
    + +
    + +
    + +
    +
    {{notification.message}}
    +
    -
    diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml index a96abadbbe..07ec0c9909 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml @@ -272,6 +272,7 @@ This value is hidden. What languages would you like to publish? What languages would you like to save? + All languages with content are saved on creation! What languages would you like to send for approval? What languages would you like to schedule? Select the languages to unpublish. Unpublishing a mandatory language will unpublish all languages. diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs index 94c040f4d6..80ba00d07a 100644 --- a/src/Umbraco.Web/Editors/ContentController.cs +++ b/src/Umbraco.Web/Editors/ContentController.cs @@ -613,7 +613,7 @@ namespace Umbraco.Web.Editors var msKey = $"Variants[{variantCount}].Name"; if (ModelState.ContainsKey(msKey)) { - if (!variant.Save) + if (!variant.Save || IsCreatingAction(contentItem.Action)) ModelState.Remove(msKey); else variantNameErrors.Add(variant.Culture); @@ -1742,7 +1742,7 @@ namespace Umbraco.Web.Editors foreach (var variant in contentSave.Variants) { //Don't update anything for this variant if Save is not true - if (!variant.Save && !IsCreatingAction(contentSave.Action)) continue; + if (!variant.Save) continue; //Don't update the name if it is empty if (!variant.Name.IsNullOrWhiteSpace()) From eafbf6dcaeecc981748b7f6dafb4c9e9717f8eab Mon Sep 17 00:00:00 2001 From: Robert Date: Thu, 10 Jan 2019 12:07:53 +0100 Subject: [PATCH 283/469] Update current urls on 'node.updateDate' --- .../content/umbcontentnodeinfo.directive.js | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js index f2e8b261c3..46afc77d02 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js @@ -22,14 +22,7 @@ // set currentVariant scope.currentVariant = _.find(scope.node.variants, (v) => v.active); - // find the urls for the currently selected language - if(scope.node.variants.length > 1) { - // nodes with variants - scope.currentUrls = _.filter(scope.node.urls, (url) => scope.currentVariant.language.culture === url.culture); - } else { - // invariant nodes - scope.currentUrls = scope.node.urls; - } + updateCurrentUrls(); // if there are any infinite editors open we are in infinite editing scope.isInfiniteMode = editorService.getNumberOfEditors() > 0 ? true : false; @@ -304,6 +297,17 @@ }); } + function updateCurrentUrls() { + // find the urls for the currently selected language + if (scope.node.variants.length > 1) { + // nodes with variants + scope.currentUrls = _.filter(scope.node.urls, (url) => scope.currentVariant.language.culture === url.culture); + } else { + // invariant nodes + scope.currentUrls = scope.node.urls; + } + } + // load audit trail and redirects when on the info tab evts.push(eventsService.on("app.tabChange", function (event, args) { $timeout(function () { @@ -328,6 +332,7 @@ loadAuditTrail(); loadRedirectUrls(); setNodePublishStatus(); + updateCurrentUrls(); } }); From b000ead96be631c9474606d7adf4eaf8edbb64c5 Mon Sep 17 00:00:00 2001 From: Robert Date: Thu, 10 Jan 2019 12:09:44 +0100 Subject: [PATCH 284/469] CTRL+K+D --- .../content/umbcontentnodeinfo.directive.js | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js index 46afc77d02..71fbabe943 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js @@ -3,7 +3,7 @@ function ContentNodeInfoDirective($timeout, logResource, eventsService, userService, localizationService, dateHelper, editorService, redirectUrlsResource, overlayService) { - function link(scope, element, attrs, umbVariantContentCtrl) { + function link(scope, umbVariantContentCtrl) { var evts = []; var isInfoTab = false; @@ -27,7 +27,7 @@ // if there are any infinite editors open we are in infinite editing scope.isInfiniteMode = editorService.getNumberOfEditors() > 0 ? true : false; - userService.getCurrentUser().then(function(user){ + userService.getCurrentUser().then(function (user) { // only allow change of media type if user has access to the settings sections const hasAccessToSettings = user.allowedSections.indexOf("settings") !== -1 ? true : false; scope.allowChangeDocumentType = hasAccessToSettings; @@ -35,8 +35,8 @@ }); var keys = [ - "general_deleted", - "content_unpublished", + "general_deleted", + "content_unpublished", "content_published", "content_publishedPendingChanges", "content_notCreated", @@ -48,7 +48,7 @@ ]; localizationService.localizeMany(keys) - .then(function(data){ + .then(function (data) { labels.deleted = data[0]; labels.unpublished = data[1]; //aka draft labels.published = data[2]; @@ -57,9 +57,9 @@ labels.unsavedChanges = data[5]; labels.doctypeChangeWarning = data[6]; labels.notPublished = data[9]; - + scope.historyLabel = scope.node.variants && scope.node.variants.length === 1 ? data[7] : data[8]; - + setNodePublishStatus(); if (scope.currentUrls.length === 0) { @@ -116,23 +116,23 @@ scope.openDocumentType = function (documentType) { - const variantIsDirty = _.some(scope.node.variants, function(variant) { + const variantIsDirty = _.some(scope.node.variants, function (variant) { return variant.isDirty; }); // add confirmation dialog before opening the doc type editor - if(variantIsDirty) { + if (variantIsDirty) { const confirm = { title: labels.unsavedChanges, view: "default", content: labels.doctypeChangeWarning, submitButtonLabelKey: "general_continue", closeButtonLabelKey: "general_cancel", - submit: function() { + submit: function () { openDocTypeEditor(documentType); overlayService.close(); }, - close: function() { + close: function () { overlayService.close(); } }; @@ -146,12 +146,12 @@ function openDocTypeEditor(documentType) { const editor = { id: documentType.id, - submit: function(model) { + submit: function (model) { const args = { node: scope.node }; eventsService.emit('editors.content.reload', args); editorService.close(); }, - close: function() { + close: function () { editorService.close(); } }; @@ -161,10 +161,10 @@ scope.openTemplate = function () { var templateEditor = { id: scope.node.templateId, - submit: function(model) { + submit: function (model) { editorService.close(); }, - close: function() { + close: function () { editorService.close(); } }; @@ -176,16 +176,16 @@ scope.node.template = templateAlias; }; - scope.openRollback = function() { - + scope.openRollback = function () { + var rollback = { node: scope.node, - submit: function(model) { + submit: function (model) { const args = { node: scope.node }; eventsService.emit("editors.content.reload", args); editorService.close(); }, - close: function() { + close: function () { editorService.close(); } }; From 10d0c79c1ddc78ccab9bef919488f71bcf93fd9d Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Thu, 10 Jan 2019 14:28:22 +0100 Subject: [PATCH 285/469] #3642 - also save all languages with content on publish --- .../content/overlays/publish.controller.js | 51 +++++++++++++++++-- .../src/views/content/overlays/publish.html | 4 +- .../Umbraco/config/lang/en_us.xml | 1 + 3 files changed, 50 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/content/overlays/publish.controller.js b/src/Umbraco.Web.UI.Client/src/views/content/overlays/publish.controller.js index 9fcd81b2ed..9074834ee6 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/overlays/publish.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/content/overlays/publish.controller.js @@ -6,11 +6,12 @@ var vm = this; vm.loading = true; vm.hasPristineVariants = false; + vm.isNew = true; vm.changeSelection = changeSelection; vm.dirtyVariantFilter = dirtyVariantFilter; vm.pristineVariantFilter = pristineVariantFilter; - + /** Returns true if publishing is possible based on if there are un-published mandatory languages */ function canPublish() { var selected = []; @@ -22,7 +23,7 @@ var published = !(variant.state === "NotCreated" || variant.state === "Draft"); if ((variant.language.isMandatory && !published) && (!publishable || !variant.publish)) { - //if a mandatory variant isn't published + //if a mandatory variant isn't published //and it's not publishable or not selected to be published //then we cannot continue @@ -53,12 +54,35 @@ return (variant.active || variant.isDirty || variant.state === "Draft" || variant.state === "PublishedPendingChanges" || variant.state === "NotCreated"); } + function hasAnyData(variant) { + var result = variant.isDirty != null || (variant.name != null && variant.name.length > 0); + + if(result) return true; + + for (var t=0; t < variant.tabs.length; t++){ + for (var p=0; p < variant.tabs[t].properties.length; p++){ + + var property = variant.tabs[t].properties[p]; + + if(property.culture == null) continue; + + result = result || (property.value != null && property.value.length > 0); + + if(result) return true; + } + } + + return result; + } + function pristineVariantFilter(variant) { return !(dirtyVariantFilter(variant)); } function onInit() { + + vm.variants = $scope.model.variants; if (!$scope.model.title) { @@ -69,6 +93,13 @@ vm.hasPristineVariants = false; + _.each(vm.variants, + function (variant) { + if(variant.state !== "NotCreated"){ + vm.isNew = false; + } + }); + _.each(vm.variants, function (variant) { variant.compositeId = variant.language.culture + "_" + (variant.segment ? variant.segment : ""); @@ -78,6 +109,10 @@ if (!vm.hasPristineVariants) { vm.hasPristineVariants = pristineVariantFilter(variant); } + + if(vm.isNew && hasAnyData(variant)){ + variant.save = true; + } }); if (vm.variants.length !== 0) { @@ -103,8 +138,16 @@ $scope.model.disableSubmitButton = true; } - vm.loading = false; - + var labelKey = vm.isNew ? "content_languagesToPublishForFirstTime" : "content_languagesToPublish"; + + localizationService.localize(labelKey).then(function (value) { + vm.headline = value; + + vm.loading = false; + }); + + + } onInit(); diff --git a/src/Umbraco.Web.UI.Client/src/views/content/overlays/publish.html b/src/Umbraco.Web.UI.Client/src/views/content/overlays/publish.html index 8ca8b78b23..b33b7ccbfc 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/overlays/publish.html +++ b/src/Umbraco.Web.UI.Client/src/views/content/overlays/publish.html @@ -1,7 +1,7 @@
    -

    +

    {{vm.headline}}

    @@ -65,7 +65,7 @@
    {{notification.message}}
    - +
    diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml index 07ec0c9909..eaa1c6c39e 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml @@ -270,6 +270,7 @@ Include drafts: also publish unpublished content items. This value is hidden. If you need access to view this value please contact your website administrator. This value is hidden. + What languages would you like to publish? All languages with content are saved! What languages would you like to publish? What languages would you like to save? All languages with content are saved on creation! From d69f0fe9ddf8c8d37f4fe4d27b5974cddf4f88d3 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Thu, 10 Jan 2019 15:35:48 +0100 Subject: [PATCH 286/469] #3993 Move color picker fix to correct method and update backwards compatibility test --- .../colorpicker/colorpicker.controller.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.controller.js index 3a6ddc5cfd..9b3be511a4 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.controller.js @@ -123,11 +123,6 @@ function ColorPickerController($scope) { if (!$scope.model.value) return false; - // Backwards compatibility, the color used to be stored as a hex value only - if ($scope.model.value.length === 6) { - $scope.model.value = { value: $scope.model.value, label: $scope.model.value }; - } - // Complex color (value and label)? if (!$scope.model.value.hasOwnProperty("value")) return $scope.model.value === color.value; @@ -144,6 +139,11 @@ function ColorPickerController($scope) { if (!$scope.model.value) return; + // Backwards compatibility, the color used to be stored as a hex value only + if (typeof $scope.model.value === "string") { + $scope.model.value = { value: $scope.model.value, label: $scope.model.value }; + } + // Complex color (value and label)? if (!$scope.model.value.hasOwnProperty("value")) return; From 003907358dd7a273992e930d49ca2303e86b50af Mon Sep 17 00:00:00 2001 From: Stephan Date: Thu, 10 Jan 2019 14:03:25 +0100 Subject: [PATCH 287/469] Better runtime state detection, to support auto-install --- .../Components/RuntimeLevelAttribute.cs | 15 +++- src/Umbraco.Core/IRuntimeState.cs | 5 ++ .../Install/DatabaseSchemaCreator.cs | 12 ++-- .../Persistence/IUmbracoDatabaseFactory.cs | 6 ++ .../Persistence/UmbracoDatabaseFactory.cs | 11 +++ src/Umbraco.Core/Runtime/CoreRuntime.cs | 3 +- src/Umbraco.Core/RuntimeLevel.cs | 3 + src/Umbraco.Core/RuntimeLevelReason.cs | 68 +++++++++++++++++++ src/Umbraco.Core/RuntimeState.cs | 43 ++++++++++-- src/Umbraco.Core/Umbraco.Core.csproj | 1 + 10 files changed, 153 insertions(+), 14 deletions(-) create mode 100644 src/Umbraco.Core/RuntimeLevelReason.cs diff --git a/src/Umbraco.Core/Components/RuntimeLevelAttribute.cs b/src/Umbraco.Core/Components/RuntimeLevelAttribute.cs index 51920660d4..2c698a671a 100644 --- a/src/Umbraco.Core/Components/RuntimeLevelAttribute.cs +++ b/src/Umbraco.Core/Components/RuntimeLevelAttribute.cs @@ -1,13 +1,22 @@ using System; +using Umbraco.Core.Composing; namespace Umbraco.Core.Components { + /// + /// Marks a composer to indicate a minimum and/or maximum runtime level for which the composer would compose. + /// [AttributeUsage(AttributeTargets.Class /*, AllowMultiple = false, Inherited = true*/)] public class RuntimeLevelAttribute : Attribute { - //public RuntimeLevelAttribute() - //{ } + /// + /// Gets or sets the minimum runtime level for which the composer would compose. + /// + public RuntimeLevel MinLevel { get; set; } = RuntimeLevel.Install; - public RuntimeLevel MinLevel { get; set; } = RuntimeLevel.Boot; + /// + /// Gets or sets the maximum runtime level for which the composer would compose. + /// + public RuntimeLevel MaxLevel { get; set; } = RuntimeLevel.Run; } } diff --git a/src/Umbraco.Core/IRuntimeState.cs b/src/Umbraco.Core/IRuntimeState.cs index 5fcfab1518..30c768ab01 100644 --- a/src/Umbraco.Core/IRuntimeState.cs +++ b/src/Umbraco.Core/IRuntimeState.cs @@ -57,6 +57,11 @@ namespace Umbraco.Core ///
    RuntimeLevel Level { get; } + /// + /// Gets the reason for the runtime level of execution. + /// + RuntimeLevelReason Reason { get; } + /// /// Gets the current migration state. /// diff --git a/src/Umbraco.Core/Migrations/Install/DatabaseSchemaCreator.cs b/src/Umbraco.Core/Migrations/Install/DatabaseSchemaCreator.cs index 5525cc4a50..f9f3e5da30 100644 --- a/src/Umbraco.Core/Migrations/Install/DatabaseSchemaCreator.cs +++ b/src/Umbraco.Core/Migrations/Install/DatabaseSchemaCreator.cs @@ -14,7 +14,7 @@ namespace Umbraco.Core.Migrations.Install /// /// Creates the initial database schema during install. /// - internal class DatabaseSchemaCreator + public class DatabaseSchemaCreator { private readonly IUmbracoDatabase _database; private readonly ILogger _logger; @@ -28,7 +28,7 @@ namespace Umbraco.Core.Migrations.Install private ISqlSyntaxProvider SqlSyntax => _database.SqlContext.SqlSyntax; // all tables, in order - public static readonly List OrderedTables = new List + internal static readonly List OrderedTables = new List { typeof (UserDto), typeof (NodeDto), @@ -138,7 +138,7 @@ namespace Umbraco.Core.Migrations.Install /// /// Validates the schema of the current database. /// - public DatabaseSchemaResult ValidateSchema() + internal DatabaseSchemaResult ValidateSchema() { var result = new DatabaseSchemaResult(SqlSyntax); @@ -387,7 +387,7 @@ namespace Umbraco.Core.Migrations.Install /// If has been decorated with an , the name from that /// attribute will be used for the table name. If the attribute is not present, the name /// will be used instead. - /// + /// /// If a table with the same name already exists, the parameter will determine /// whether the table is overwritten. If true, the table will be overwritten, whereas this method will /// not do anything if the parameter is false. @@ -409,14 +409,14 @@ namespace Umbraco.Core.Migrations.Install /// If has been decorated with an , the name from /// that attribute will be used for the table name. If the attribute is not present, the name /// will be used instead. - /// + /// /// If a table with the same name already exists, the parameter will determine /// whether the table is overwritten. If true, the table will be overwritten, whereas this method will /// not do anything if the parameter is false. /// /// This need to execute as part of a transaction. /// - public void CreateTable(bool overwrite, Type modelType, DatabaseDataCreator dataCreation) + internal void CreateTable(bool overwrite, Type modelType, DatabaseDataCreator dataCreation) { if (!_database.InTransaction) throw new InvalidOperationException("Database is not in a transaction."); diff --git a/src/Umbraco.Core/Persistence/IUmbracoDatabaseFactory.cs b/src/Umbraco.Core/Persistence/IUmbracoDatabaseFactory.cs index 9ef320e187..0236fc4bd5 100644 --- a/src/Umbraco.Core/Persistence/IUmbracoDatabaseFactory.cs +++ b/src/Umbraco.Core/Persistence/IUmbracoDatabaseFactory.cs @@ -18,6 +18,12 @@ namespace Umbraco.Core.Persistence ///
    bool Configured { get; } + /// + /// Gets the connection string. + /// + /// Throws if the factory is not configured. + string ConnectionString { get; } + /// /// Gets a value indicating whether the database can connect. /// diff --git a/src/Umbraco.Core/Persistence/UmbracoDatabaseFactory.cs b/src/Umbraco.Core/Persistence/UmbracoDatabaseFactory.cs index c9a509fe94..9ed52ca148 100644 --- a/src/Umbraco.Core/Persistence/UmbracoDatabaseFactory.cs +++ b/src/Umbraco.Core/Persistence/UmbracoDatabaseFactory.cs @@ -2,6 +2,7 @@ using System.Configuration; using System.Data.Common; using System.Threading; +using LightInject; using NPoco; using NPoco.FluentMappings; using Umbraco.Core.Exceptions; @@ -102,6 +103,16 @@ namespace Umbraco.Core.Persistence /// public bool Configured { get; private set; } + /// + public string ConnectionString + { + get + { + EnsureConfigured(); + return _connectionString; + } + } + /// public bool CanConnect { diff --git a/src/Umbraco.Core/Runtime/CoreRuntime.cs b/src/Umbraco.Core/Runtime/CoreRuntime.cs index 5d2359d04c..d6f68d339f 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntime.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntime.cs @@ -252,7 +252,7 @@ namespace Umbraco.Core.Runtime { _state.DetermineRuntimeLevel(databaseFactory, profilingLogger); - profilingLogger.Debug("Runtime level: {RuntimeLevel}", _state.Level); + profilingLogger.Debug("Runtime level: {RuntimeLevel} - {RuntimeLevelReason}", _state.Level, _state.Reason); if (_state.Level == RuntimeLevel.Upgrade) { @@ -263,6 +263,7 @@ namespace Umbraco.Core.Runtime catch { _state.Level = RuntimeLevel.BootFailed; + _state.Reason = RuntimeLevelReason.BootFailedOnException; timer.Fail(); throw; } diff --git a/src/Umbraco.Core/RuntimeLevel.cs b/src/Umbraco.Core/RuntimeLevel.cs index f9ec3c90c5..2645e89226 100644 --- a/src/Umbraco.Core/RuntimeLevel.cs +++ b/src/Umbraco.Core/RuntimeLevel.cs @@ -1,5 +1,8 @@ namespace Umbraco.Core { + /// + /// Describes the levels in which the runtime can run. + /// public enum RuntimeLevel { /// diff --git a/src/Umbraco.Core/RuntimeLevelReason.cs b/src/Umbraco.Core/RuntimeLevelReason.cs new file mode 100644 index 0000000000..c10ac8b206 --- /dev/null +++ b/src/Umbraco.Core/RuntimeLevelReason.cs @@ -0,0 +1,68 @@ +namespace Umbraco.Core +{ + /// + /// Describes the reason for the runtime level. + /// + public enum RuntimeLevelReason + { + /// + /// The code version is lower than the version indicated in web.config, and + /// downgrading Umbraco is not supported. + /// + BootFailedCannotDowngrade, + + /// + /// The runtime cannot connect to the configured database. + /// + BootFailedCannotConnectToDatabase, + + /// + /// The runtime can connect to the configured database, but it cannot + /// retrieve the migrations status. + /// + BootFailedCannotCheckUpgradeState, + + /// + /// An exception was thrown during boot. + /// + BootFailedOnException, + + /// + /// Umbraco is not installed at all. + /// + InstallNoVersion, + + /// + /// A version is specified in web.config but the database is not configured. + /// + /// This is a weird state. + InstallNoDatabase, + + /// + /// A version is specified in web.config and a database is configured, but the + /// database is missing, and installing over a missing database has been enabled. + /// + InstallMissingDatabase, + + /// + /// A version is specified in web.config and a database is configured, but the + /// database is empty, and installing over an empty database has been enabled. + /// + InstallEmptyDatabase, + + /// + /// Umbraco runs an old version. + /// + UpgradeOldVersion, + + /// + /// Umbraco runs the current version but some migrations have not run. + /// + UpgradeMigrations, + + /// + /// Umbraco is running. + /// + Run + } +} diff --git a/src/Umbraco.Core/RuntimeState.cs b/src/Umbraco.Core/RuntimeState.cs index df2ee44a7d..e344a67920 100644 --- a/src/Umbraco.Core/RuntimeState.cs +++ b/src/Umbraco.Core/RuntimeState.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Configuration; using System.Threading; using System.Web; using Semver; @@ -93,6 +94,9 @@ namespace Umbraco.Core internal set { _level = value; if (value == RuntimeLevel.Run) _runLevel.Set(); } } + /// + public RuntimeLevelReason Reason { get; internal set; } + /// /// Ensures that the property has a value. /// @@ -129,6 +133,11 @@ namespace Umbraco.Core /// public BootFailedException BootFailedException { get; internal set; } + // currently configured via app settings + private static bool BoolSetting(string key, bool missing) => ConfigurationManager.AppSettings[key]?.InvariantEquals("true") ?? missing; + private bool InstallMissingDatabase { get; } = BoolSetting("Umbraco.Core.RuntimeState.InstallMissingDatabase", false); + private bool InstallEmptyDatabase { get; } = BoolSetting("Umbraco.Core.RuntimeState.InstallEmptyDatabase", false); + /// /// Determines the runtime level. /// @@ -143,6 +152,7 @@ namespace Umbraco.Core // there is no local version, we are not installed logger.Debug("No local version, need to install Umbraco."); Level = RuntimeLevel.Install; + Reason = RuntimeLevelReason.InstallNoVersion; return; } @@ -152,12 +162,14 @@ namespace Umbraco.Core // need to upgrade logger.Debug("Local version '{LocalVersion}' < code version '{CodeVersion}', need to upgrade Umbraco.", localVersion, codeVersion); Level = RuntimeLevel.Upgrade; + Reason = RuntimeLevelReason.UpgradeOldVersion; } else if (localVersion > codeVersion) { logger.Warn("Local version '{LocalVersion}' > code version '{CodeVersion}', downgrading is not supported.", localVersion, codeVersion); // in fact, this is bad enough that we want to throw + Reason = RuntimeLevelReason.BootFailedCannotDowngrade; throw new BootFailedException($"Local version \"{localVersion}\" > code version \"{codeVersion}\", downgrading is not supported."); } else if (databaseFactory.Configured == false) @@ -166,16 +178,18 @@ namespace Umbraco.Core // install (again? this is a weird situation...) logger.Debug("Database is not configured, need to install Umbraco."); Level = RuntimeLevel.Install; + Reason = RuntimeLevelReason.InstallNoDatabase; return; } // 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) - for (var i = 0; i < 5; i++) + var tries = InstallMissingDatabase ? 2 : 5; + for (var i = 0;;) { connect = databaseFactory.CanConnect; - if (connect) break; + if (connect || ++i == tries) break; logger.Debug("Could not immediately connect to database, trying again."); Thread.Sleep(1000); } @@ -185,7 +199,16 @@ namespace Umbraco.Core // cannot connect to configured database, this is bad, fail logger.Debug("Could not connect to database."); - // in fact, this is bad enough that we want to throw + if (InstallMissingDatabase) + { + // ok to install on a configured but missing database + Level = RuntimeLevel.Install; + Reason = RuntimeLevelReason.InstallMissingDatabase; + return; + } + + // else it is bad enough that we want to throw + Reason = RuntimeLevelReason.BootFailedCannotConnectToDatabase; throw new BootFailedException("A connection string is configured but Umbraco could not connect to the database."); } @@ -195,7 +218,6 @@ namespace Umbraco.Core // else // look for a matching migration entry - bypassing services entirely - they are not 'up' yet - // fixme - in a LB scenario, ensure that the DB gets upgraded only once! bool noUpgrade; try { @@ -205,6 +227,17 @@ 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 (InstallEmptyDatabase) + { + // ok to install on an empty database + Level = RuntimeLevel.Install; + Reason = RuntimeLevelReason.InstallEmptyDatabase; + return; + } + + // else it is bad enough that we want to throw + Reason = RuntimeLevelReason.BootFailedCannotCheckUpgradeState; throw new BootFailedException("Could not check the upgrade state.", e); } @@ -216,6 +249,7 @@ namespace Umbraco.Core { // the database version matches the code & files version, all clear, can run Level = RuntimeLevel.Run; + Reason = RuntimeLevelReason.Run; return; } @@ -226,6 +260,7 @@ namespace Umbraco.Core // which means the local files have been upgraded but not the database - need to upgrade logger.Debug("Has not reached the final upgrade step, need to upgrade Umbraco."); Level = RuntimeLevel.Upgrade; + Reason = RuntimeLevelReason.UpgradeMigrations; } protected virtual bool EnsureUmbracoUpgradeState(IUmbracoDatabaseFactory databaseFactory, ILogger logger) diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index a01bbf1746..fd5dfe9294 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -490,6 +490,7 @@ + From 2baf3b5b413d62118b25b401c38750e75d02325d Mon Sep 17 00:00:00 2001 From: Stephan Date: Thu, 10 Jan 2019 18:31:13 +0100 Subject: [PATCH 288/469] Fixes --- .../Implement/DocumentRepository.cs | 6 ++-- src/Umbraco.Examine/ContentValueSetBuilder.cs | 4 +-- src/Umbraco.Web/Editors/ContentController.cs | 33 ++++++++++--------- 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs index 40ce07f193..054ab8cb4b 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs @@ -1078,19 +1078,19 @@ namespace Umbraco.Core.Persistence.Repositories.Implement // assign templates and properties foreach (var temp in temps) { - // complete the item - // fixme - this makes no sense, no need to manage templates on TEMP anymore?! + // set the template ID if it matches an existing template if (temp.Template1Id.HasValue && templates.ContainsKey(temp.Template1Id.Value)) temp.Content.TemplateId = temp.Template1Id; if (temp.Template2Id.HasValue && templates.ContainsKey(temp.Template2Id.Value)) temp.Content.PublishTemplateId = temp.Template2Id; + // set properties if (properties.ContainsKey(temp.VersionId)) temp.Content.Properties = properties[temp.VersionId]; else throw new InvalidOperationException($"No property data found for version: '{temp.VersionId}'."); - //load in the schedule + // load in the schedule if (schedule.TryGetValue(temp.Content.Id, out var s)) temp.Content.ContentSchedule = s; } diff --git a/src/Umbraco.Examine/ContentValueSetBuilder.cs b/src/Umbraco.Examine/ContentValueSetBuilder.cs index 07e5e4565b..5674698b20 100644 --- a/src/Umbraco.Examine/ContentValueSetBuilder.cs +++ b/src/Umbraco.Examine/ContentValueSetBuilder.cs @@ -53,14 +53,14 @@ namespace Umbraco.Examine {"updateDate", new object[] {c.UpdateDate}}, //Always add invariant updateDate {"nodeName", PublishedValuesOnly //Always add invariant nodeName ? c.PublishName.Yield() - : c.Name.Yield()}, + : c.Name.Yield()}, {"urlName", urlValue.Yield()}, //Always add invariant urlName {"path", c.Path.Yield()}, {"nodeType", new object[] {c.ContentType.Id}}, {"creatorName", (c.GetCreatorProfile(_userService)?.Name ?? "??").Yield() }, {"writerName",(c.GetWriterProfile(_userService)?.Name ?? "??").Yield() }, {"writerID", new object[] {c.WriterId}}, - {"template", new object[] {c.Template?.Id ?? 0}}, + {"templateID", new object[] {c.TemplateId ?? 0}}, {UmbracoContentIndex.VariesByCultureFieldName, new object[] {0}}, }; diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs index 46a053bb77..9458ec6b8d 100644 --- a/src/Umbraco.Web/Editors/ContentController.cs +++ b/src/Umbraco.Web/Editors/ContentController.cs @@ -1780,24 +1780,25 @@ namespace Umbraco.Web.Editors variantIndex++; } - // If the template was set. - // fixme review this - what if template has been cleared? - if (contentSave.TemplateAlias != null) + // handle template + if (string.IsNullOrWhiteSpace(contentSave.TemplateAlias)) // cleared: clear if not already null { - //only set the template if it didn't change - var template = Services.FileService.GetTemplate(contentSave.TemplateAlias); - if (contentSave.PersistedContent.TemplateId != template.Id) + if (contentSave.PersistedContent.TemplateId != null) { - if (template == null && contentSave.TemplateAlias.IsNullOrWhiteSpace() == false) - { - //ModelState.AddModelError("Template", "No template exists with the specified alias: " + contentItem.TemplateAlias); - Logger.Warn("No template exists with the specified alias: {TemplateAlias}", contentSave.TemplateAlias); - } - else - { - //NOTE: this could be null if there was a template and the posted template is null, this should remove the assigned template - contentSave.PersistedContent.TemplateId = template.Id; - } + contentSave.PersistedContent.TemplateId = null; + } + } + else // set: update if different + { + var template = Services.FileService.GetTemplate(contentSave.TemplateAlias); + if (template == null) + { + //ModelState.AddModelError("Template", "No template exists with the specified alias: " + contentItem.TemplateAlias); + Logger.Warn("No template exists with the specified alias: {TemplateAlias}", contentSave.TemplateAlias); + } + else if (template.Id != contentSave.PersistedContent.TemplateId) + { + contentSave.PersistedContent.TemplateId = template.Id; } } } From cc13b99787de8f94b40c0cd6d289b2b9bdc3251e Mon Sep 17 00:00:00 2001 From: Sebastian Hoffback Date: Thu, 10 Jan 2019 11:21:17 +0100 Subject: [PATCH 289/469] Removed already deleted file canvasdesigner.panel.js from canvasdesigner.loader.js --- src/Umbraco.Web.UI.Client/src/canvasdesigner.loader.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/canvasdesigner.loader.js b/src/Umbraco.Web.UI.Client/src/canvasdesigner.loader.js index c5d2f70075..8ed149fee1 100644 --- a/src/Umbraco.Web.UI.Client/src/canvasdesigner.loader.js +++ b/src/Umbraco.Web.UI.Client/src/canvasdesigner.loader.js @@ -11,8 +11,7 @@ LazyLoad.js([ '../js/umbraco.security.js', '../ServerVariables', '../lib/spectrum/spectrum.js', - '../js/umbraco.canvasdesigner.js', - '../js/canvasdesigner.panel.js' + '../js/umbraco.canvasdesigner.js' ], function () { jQuery(document).ready(function () { angular.bootstrap(document, ['Umbraco.canvasdesigner']); From 4170faf76eddee2bae14470ace42886e12601c3d Mon Sep 17 00:00:00 2001 From: Quan Tran Date: Wed, 9 Jan 2019 09:02:15 +0100 Subject: [PATCH 290/469] add null checking --- .../umbraco.presentation/umbraco/translation/details.aspx.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/translation/details.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/translation/details.aspx.cs index 46a00927db..b8968d4329 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/translation/details.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/translation/details.aspx.cs @@ -88,7 +88,10 @@ namespace umbraco.presentation.umbraco.translation { foreach (PropertyType pt in page.ContentType.PropertyTypes) { pageRow = pageTable.NewRow(); pageRow[ui.Text("name")] = pt.Name; - pageRow[ui.Text("value")] = page.getProperty(pt.Alias).Value; + if (page.getProperty(pt.Alias) != null && page.getProperty(pt.Alias).Value != null) + { + pageRow[ui.Text("value")] = page.getProperty(pt.Alias).Value; + } pageTable.Rows.Add(pageRow); } From 59349dd355313063718c136b6b641de487af3e5b Mon Sep 17 00:00:00 2001 From: Quan Tran Date: Thu, 10 Jan 2019 10:21:07 +0100 Subject: [PATCH 291/469] Fix - refine code --- .../umbraco/translation/details.aspx.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/translation/details.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/translation/details.aspx.cs index b8968d4329..d4ae4a8587 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/translation/details.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/translation/details.aspx.cs @@ -84,17 +84,19 @@ namespace umbraco.presentation.umbraco.translation { pageRow[ui.Text("name")] = ui.Text("nodeName"); pageRow[ui.Text("value")] = page.Text; pageTable.Rows.Add(pageRow); - - foreach (PropertyType pt in page.ContentType.PropertyTypes) { + + foreach (PropertyType pt in page.ContentType.PropertyTypes) + { pageRow = pageTable.NewRow(); pageRow[ui.Text("name")] = pt.Name; - if (page.getProperty(pt.Alias) != null && page.getProperty(pt.Alias).Value != null) + var property = page.getProperty(pt.Alias); + if (property != null && property.Value != null) { - pageRow[ui.Text("value")] = page.getProperty(pt.Alias).Value; + pageRow[ui.Text("value")] = property.Value; } pageTable.Rows.Add(pageRow); } - + dg_fields.DataSource = pageTable; dg_fields.DataBind(); } From 74c01af3695e218aa30d5397a22d24ed856b6e06 Mon Sep 17 00:00:00 2001 From: Shannon Date: Fri, 11 Jan 2019 10:35:37 +1100 Subject: [PATCH 292/469] Splits logic for IPackageBuilder into ICreatedPackagesRepository and IInstalledPackagesRepository since it's nearly the same for both --- .../Composing/Composers/ServicesComposer.cs | 4 +- ...uilder.cs => CreatedPackagesRepository.cs} | 8 +- .../Packaging/ICreatedPackagesRepository.cs | 13 + .../Packaging/IInstalledPackagesRepository.cs | 14 + ...der.cs => IPackageDefinitionRepository.cs} | 15 +- .../Services/IPackagingService.cs | 12 +- .../Services/Implement/PackagingService.cs | 16 +- src/Umbraco.Core/Umbraco.Core.csproj | 6 +- ...s.cs => CreatedPackagesRepositoryTests.cs} | 4 +- src/Umbraco.Tests/TestHelpers/TestObjects.cs | 2 +- src/Umbraco.Tests/Umbraco.Tests.csproj | 2 +- src/Umbraco.Web/Editors/PackageController.cs | 18 +- src/Umbraco.Web/Umbraco.Web.csproj | 2 - .../_Legacy/Controls/BaseTreePicker.cs | 299 ------------------ .../PackageInstance/InstalledPackage.cs | 77 +---- .../umbraco/controls/ContentPicker.cs | 60 ---- 16 files changed, 66 insertions(+), 486 deletions(-) rename src/Umbraco.Core/Packaging/{PackageBuilder.cs => CreatedPackagesRepository.cs} (98%) create mode 100644 src/Umbraco.Core/Packaging/ICreatedPackagesRepository.cs create mode 100644 src/Umbraco.Core/Packaging/IInstalledPackagesRepository.cs rename src/Umbraco.Core/Packaging/{IPackageBuilder.cs => IPackageDefinitionRepository.cs} (61%) rename src/Umbraco.Tests/Packaging/{PackageBuilderTests.cs => CreatedPackagesRepositoryTests.cs} (97%) delete mode 100644 src/Umbraco.Web/_Legacy/Controls/BaseTreePicker.cs delete mode 100644 src/Umbraco.Web/umbraco.presentation/umbraco/controls/ContentPicker.cs diff --git a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs index 6395a2c6db..9692a2d87c 100644 --- a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs @@ -60,8 +60,8 @@ namespace Umbraco.Core.Composing.Composers composition.RegisterUnique(); composition.RegisterUnique(); - composition.RegisterUnique(factory => - new PackageBuilder( //we are using a factory because there are optional ctor args + composition.RegisterUnique(factory => + new CreatedPackagesRepository( //we are using a factory because there are optional ctor args factory.GetInstance(), factory.GetInstance(), factory.GetInstance(), factory.GetInstance(), factory.GetInstance(), factory.GetInstance(), factory.GetInstance(), factory.GetInstance())); diff --git a/src/Umbraco.Core/Packaging/PackageBuilder.cs b/src/Umbraco.Core/Packaging/CreatedPackagesRepository.cs similarity index 98% rename from src/Umbraco.Core/Packaging/PackageBuilder.cs rename to src/Umbraco.Core/Packaging/CreatedPackagesRepository.cs index 523ed6ed93..169b161fbc 100644 --- a/src/Umbraco.Core/Packaging/PackageBuilder.cs +++ b/src/Umbraco.Core/Packaging/CreatedPackagesRepository.cs @@ -15,7 +15,7 @@ using File = System.IO.File; namespace Umbraco.Core.Packaging { - internal class PackageBuilder : IPackageBuilder + internal class CreatedPackagesRepository : ICreatedPackagesRepository { private readonly IContentService _contentService; private readonly IContentTypeService _contentTypeService; @@ -29,7 +29,7 @@ namespace Umbraco.Core.Packaging private readonly string _packagesFolderPath; private readonly string _tempFolderPath; - public PackageBuilder(IContentService contentService, IContentTypeService contentTypeService, + public CreatedPackagesRepository(IContentService contentService, IContentTypeService contentTypeService, IDataTypeService dataTypeService, IFileService fileService, IMacroService macroService, ILocalizationService languageService, IEntityXmlSerializer serializer, ILogger logger, @@ -174,7 +174,7 @@ namespace Umbraco.Core.Packaging } catch (Exception e) { - _logger.Warn(e, "Could not add package actions to the package manifest, the xml did not parse"); + _logger.Warn(e, "Could not add package actions to the package manifest, the xml did not parse"); } } @@ -629,7 +629,7 @@ namespace Umbraco.Core.Packaging } catch (Exception e) { - _logger.Warn(e, "Could not add package actions to the package xml definition, the xml did not parse"); + _logger.Warn(e, "Could not add package actions to the package xml definition, the xml did not parse"); } var packageXml = new XElement("package", diff --git a/src/Umbraco.Core/Packaging/ICreatedPackagesRepository.cs b/src/Umbraco.Core/Packaging/ICreatedPackagesRepository.cs new file mode 100644 index 0000000000..52a16ddff0 --- /dev/null +++ b/src/Umbraco.Core/Packaging/ICreatedPackagesRepository.cs @@ -0,0 +1,13 @@ +using Umbraco.Core.Models.Packaging; + +namespace Umbraco.Core.Packaging +{ + public interface ICreatedPackagesRepository : IPackageDefinitionRepository + { + /// + /// Creates the package file and returns it's physical path + /// + /// + string ExportPackage(PackageDefinition definition); + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Packaging/IInstalledPackagesRepository.cs b/src/Umbraco.Core/Packaging/IInstalledPackagesRepository.cs new file mode 100644 index 0000000000..3d601d6b1d --- /dev/null +++ b/src/Umbraco.Core/Packaging/IInstalledPackagesRepository.cs @@ -0,0 +1,14 @@ +using System; + +namespace Umbraco.Core.Packaging +{ + + //TODO: We need to figure out how we want to do this + // we have 2x repositories for saving created and installed packages + // created packages can also be exported + // maybe the below will work? + + public interface IInstalledPackagesRepository : IPackageDefinitionRepository + { + } +} diff --git a/src/Umbraco.Core/Packaging/IPackageBuilder.cs b/src/Umbraco.Core/Packaging/IPackageDefinitionRepository.cs similarity index 61% rename from src/Umbraco.Core/Packaging/IPackageBuilder.cs rename to src/Umbraco.Core/Packaging/IPackageDefinitionRepository.cs index 5a7449545f..343a0a05ea 100644 --- a/src/Umbraco.Core/Packaging/IPackageBuilder.cs +++ b/src/Umbraco.Core/Packaging/IPackageDefinitionRepository.cs @@ -1,13 +1,12 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using Umbraco.Core.Models.Packaging; namespace Umbraco.Core.Packaging { /// - /// Creates packages + /// Defines methods for persisting package definitions to storage /// - public interface IPackageBuilder + public interface IPackageDefinitionRepository { IEnumerable GetAll(); PackageDefinition GetById(int id); @@ -20,11 +19,5 @@ namespace Umbraco.Core.Packaging /// true if creating/updating the package was successful, otherwise false /// bool SavePackage(PackageDefinition definition); - - /// - /// Creates the package file and returns it's physical path - /// - /// - string ExportPackage(PackageDefinition definition); } -} +} \ No newline at end of file diff --git a/src/Umbraco.Core/Services/IPackagingService.cs b/src/Umbraco.Core/Services/IPackagingService.cs index 4d60f3dca4..32d5cd4c59 100644 --- a/src/Umbraco.Core/Services/IPackagingService.cs +++ b/src/Umbraco.Core/Services/IPackagingService.cs @@ -9,23 +9,23 @@ namespace Umbraco.Core.Services { public interface IPackagingService : IService { - #region Package Building + #region Created Packages - IEnumerable GetAll(); - PackageDefinition GetById(int id); - void Delete(int id); + IEnumerable GetAllCreatedPackages(); + PackageDefinition GetCreatedPackageById(int id); + void DeleteCreatedPackage(int id); /// /// Persists a package definition to storage /// /// - bool SavePackage(PackageDefinition definition); + bool SaveCreatedPackage(PackageDefinition definition); /// /// Creates the package file and returns it's physical path /// /// - string ExportPackage(PackageDefinition definition); + string ExportCreatedPackage(PackageDefinition definition); #endregion diff --git a/src/Umbraco.Core/Services/Implement/PackagingService.cs b/src/Umbraco.Core/Services/Implement/PackagingService.cs index 17959f0983..d6003dc842 100644 --- a/src/Umbraco.Core/Services/Implement/PackagingService.cs +++ b/src/Umbraco.Core/Services/Implement/PackagingService.cs @@ -46,7 +46,7 @@ namespace Umbraco.Core.Services.Implement private readonly IAuditRepository _auditRepository; private readonly IContentTypeRepository _contentTypeRepository; private readonly PropertyEditorCollection _propertyEditors; - private readonly IPackageBuilder _packageBuilder; + private readonly ICreatedPackagesRepository _createdPackages; private static HttpClient _httpClient; public PackagingService( @@ -62,7 +62,7 @@ namespace Umbraco.Core.Services.Implement IAuditRepository auditRepository, IContentTypeRepository contentTypeRepository, PropertyEditorCollection propertyEditors, - IPackageBuilder packageBuilder) + ICreatedPackagesRepository createdPackages) { _logger = logger; _contentService = contentService; @@ -76,7 +76,7 @@ namespace Umbraco.Core.Services.Implement _auditRepository = auditRepository; _contentTypeRepository = contentTypeRepository; _propertyEditors = propertyEditors; - _packageBuilder = packageBuilder; + _createdPackages = createdPackages; _importedContentTypes = new Dictionary(); } @@ -1402,15 +1402,15 @@ namespace Umbraco.Core.Services.Implement #region Package Building - public void Delete(int id) => _packageBuilder.Delete(id); + public void DeleteCreatedPackage(int id) => _createdPackages.Delete(id); - public IEnumerable GetAll() => _packageBuilder.GetAll(); + public IEnumerable GetAllCreatedPackages() => _createdPackages.GetAll(); - public PackageDefinition GetById(int id) => _packageBuilder.GetById(id); + public PackageDefinition GetCreatedPackageById(int id) => _createdPackages.GetById(id); - public bool SavePackage(PackageDefinition definition) => _packageBuilder.SavePackage(definition); + public bool SaveCreatedPackage(PackageDefinition definition) => _createdPackages.SavePackage(definition); - public string ExportPackage(PackageDefinition definition) => _packageBuilder.ExportPackage(definition); + public string ExportCreatedPackage(PackageDefinition definition) => _createdPackages.ExportPackage(definition); #endregion diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 00179f562a..bad9ba7ccd 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -444,9 +444,11 @@ - + + + - + diff --git a/src/Umbraco.Tests/Packaging/PackageBuilderTests.cs b/src/Umbraco.Tests/Packaging/CreatedPackagesRepositoryTests.cs similarity index 97% rename from src/Umbraco.Tests/Packaging/PackageBuilderTests.cs rename to src/Umbraco.Tests/Packaging/CreatedPackagesRepositoryTests.cs index 6368001c11..3bd9b50ed4 100644 --- a/src/Umbraco.Tests/Packaging/PackageBuilderTests.cs +++ b/src/Umbraco.Tests/Packaging/CreatedPackagesRepositoryTests.cs @@ -19,7 +19,7 @@ namespace Umbraco.Tests.Packaging { [TestFixture] [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerFixture)] - public class PackageBuilderTests : TestWithDatabaseBase + public class CreatedPackagesRepositoryTests : TestWithDatabaseBase { private Guid _testBaseFolder; @@ -37,7 +37,7 @@ namespace Umbraco.Tests.Packaging Directory.Delete(IOHelper.MapPath("~/" + _testBaseFolder), true); } - public IPackageBuilder PackageBuilder => new PackageBuilder( + public ICreatedPackagesRepository PackageBuilder => new CreatedPackagesRepository( ServiceContext.ContentService, ServiceContext.ContentTypeService, ServiceContext.DataTypeService, ServiceContext.FileService, ServiceContext.MacroService, ServiceContext.LocalizationService, Factory.GetInstance(), Logger, diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects.cs b/src/Umbraco.Tests/TestHelpers/TestObjects.cs index c6602fc54e..105bc440cc 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects.cs @@ -170,7 +170,7 @@ namespace Umbraco.Tests.TestHelpers var macroService = GetLazyService(factory, c => new MacroService(scopeProvider, logger, eventMessagesFactory, GetRepo(c), GetRepo(c))); var packagingService = GetLazyService(factory, c => new PackagingService( logger, contentService.Value, contentTypeService.Value, macroService.Value, dataTypeService.Value, fileService.Value, localizationService.Value, entityService.Value, scopeProvider, GetRepo(c), GetRepo(c), new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty())), - new PackageBuilder(contentService.Value, contentTypeService.Value, dataTypeService.Value, fileService.Value, macroService.Value, localizationService.Value, + new CreatedPackagesRepository(contentService.Value, contentTypeService.Value, dataTypeService.Value, fileService.Value, macroService.Value, localizationService.Value, new EntityXmlSerializer(contentService.Value, mediaService.Value, dataTypeService.Value, userService.Value, localizationService.Value, contentTypeService.Value, urlSegmentProviders), logger))); var relationService = GetLazyService(factory, c => new RelationService(scopeProvider, logger, eventMessagesFactory, entityService.Value, GetRepo(c), GetRepo(c))); var treeService = GetLazyService(factory, c => new ApplicationTreeService(logger, cache, typeLoader)); diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index 3e619c6f00..7ea7d5d8b1 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -142,7 +142,7 @@ - + diff --git a/src/Umbraco.Web/Editors/PackageController.cs b/src/Umbraco.Web/Editors/PackageController.cs index 215c81faac..86f3e48b7c 100644 --- a/src/Umbraco.Web/Editors/PackageController.cs +++ b/src/Umbraco.Web/Editors/PackageController.cs @@ -1,23 +1,17 @@ using System.Collections.Generic; using System.IO; -using System.Linq; using System.Net; using System.Net.Http; -using System.Net.Http.Formatting; using System.Net.Http.Headers; using System.Web.Http; using Umbraco.Core.IO; using Umbraco.Core.Models.Packaging; -using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Mvc; using Umbraco.Web.WebApi; using Umbraco.Web.WebApi.Filters; -using Umbraco.Web._Legacy.Packager.PackageInstance; namespace Umbraco.Web.Editors { - //TODO: Packager stuff still lives in business logic - YUK - /// /// A controller used for installing packages and managing all of the data in the packages section in the back office /// @@ -28,12 +22,12 @@ namespace Umbraco.Web.Editors { public IEnumerable GetCreatedPackages() { - return Services.PackagingService.GetAll(); + return Services.PackagingService.GetAllCreatedPackages(); } public PackageDefinition GetCreatedPackageById(int id) { - var package = Services.PackagingService.GetById(id); + var package = Services.PackagingService.GetCreatedPackageById(id); if (package == null) throw new HttpResponseException(HttpStatusCode.NotFound); @@ -56,14 +50,14 @@ namespace Umbraco.Web.Editors throw new HttpResponseException(Request.CreateValidationErrorResponse(ModelState)); //save it - if (!Services.PackagingService.SavePackage(model)) + if (!Services.PackagingService.SaveCreatedPackage(model)) throw new HttpResponseException( Request.CreateNotificationValidationErrorResponse( model.Id == default ? $"A package with the name {model.Name} already exists" : $"The package with id {model.Id} was not found")); - Services.PackagingService.ExportPackage(model); + Services.PackagingService.ExportCreatedPackage(model); //the packagePath will be on the model return model; @@ -78,7 +72,7 @@ namespace Umbraco.Web.Editors [HttpDelete] public IHttpActionResult DeleteCreatedPackage(int packageId) { - Services.PackagingService.Delete(packageId); + Services.PackagingService.DeleteCreatedPackage(packageId); return Ok(); } @@ -86,7 +80,7 @@ namespace Umbraco.Web.Editors [HttpGet] public HttpResponseMessage DownloadCreatedPackage(int id) { - var package = Services.PackagingService.GetById(id); + var package = Services.PackagingService.GetCreatedPackageById(id); if (package == null) return Request.CreateResponse(HttpStatusCode.NotFound); diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index b9a6c17ef7..ed423b509b 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -1126,7 +1126,6 @@ - @@ -1224,7 +1223,6 @@ Code - FeedProxy.aspx diff --git a/src/Umbraco.Web/_Legacy/Controls/BaseTreePicker.cs b/src/Umbraco.Web/_Legacy/Controls/BaseTreePicker.cs deleted file mode 100644 index c2298e4906..0000000000 --- a/src/Umbraco.Web/_Legacy/Controls/BaseTreePicker.cs +++ /dev/null @@ -1,299 +0,0 @@ -using System; -using System.Web.UI; -using System.Web.UI.WebControls; -using System.Web.UI.HtmlControls; -using Umbraco.Core.Composing; -using Umbraco.Core.Services; - -namespace Umbraco.Web._Legacy.Controls -{ - [ValidationProperty("Value")] - public abstract class BaseTreePicker : Control, INamingContainer - { - - protected HiddenField ItemIdValue; - protected HtmlAnchor DeleteLink; - protected HtmlAnchor ChooseLink; - protected HtmlGenericControl ItemTitle; - protected HtmlGenericControl ButtonContainer; - protected HtmlGenericControl RootContainer; - - public BaseTreePicker() - { - ShowDelete = true; - ModalHeight = 400; - ModalWidth = 300; - ShowHeader = true; - } - - /// - /// Wraps the hidden vield value - /// - public string Value - { - get - { - EnsureChildControls(); - return ItemIdValue.Value; - } - set - { - EnsureChildControls(); - ItemIdValue.Value = value; - } - } - - public int ModalWidth { get; set; } - public int ModalHeight { get; set; } - public bool ShowDelete { get; set; } - public bool ShowHeader { get; set; } - - /// - /// Need to specify the tree picker url (iframe) - /// - public abstract string TreePickerUrl { get; } - - /// - /// The title to specify for the picker window - /// - public abstract string ModalWindowTitle { get; } - - /// - /// If item has been selected or stored, this will query the db for its title - /// - protected virtual string GetItemTitle() - { - if (!string.IsNullOrEmpty(ItemIdValue.Value)) - { - try - { - return Current.Services.EntityService.Get(int.Parse(ItemIdValue.Value)).Name; - } - catch (ArgumentException) { /*the node does not exist! we will ignore*/ } - } - return ""; - } - - /// - /// Just like GetItemTitle, except returns the full path (breadcrumbs) of the node - /// - protected virtual string GetItemBreadcrumbs() - { - //TODO: Shouldn't this use the same/similar logic as the EntityController.GetResultForAncestors ? - - if (!string.IsNullOrEmpty(ItemIdValue.Value)) - { - try - { - int nodeId = -1; - if (int.TryParse(ItemIdValue.Value, out nodeId)) - { - var n = Current.Services.EntityService.Get(nodeId); - string title = n.Name; - string separator = " > "; - while (n.Level > 1) - { - n = Current.Services.EntityService.Get(n.ParentId); - title = n.Name + separator + title; - } - return title; - } - else - { - return ItemIdValue.Value; - } - - } - catch (ArgumentException) { /*the node does not exist! we will ignore*/ } - } - return ""; - } - - /// - /// Outputs the JavaScript instances used to make this control work - /// - protected virtual string GetJSScript() - { - /* 0 = this control's client id - * 1 = label - * 2 = itemIdValueClientID - * 3 = itemTitleClientID - * 4 = itemPickerUrl - * 5 = popup width - * 6 = popup height - * 7 = show header - * 8 = umbraco path - */ - return string.Format(@" - var mc_{0} = new Umbraco.Controls.TreePicker('{0}','{1}','{2}','{3}','{4}',{5},{6},{7},'{8}');", - new string[] - { - this.ClientID, - ModalWindowTitle, - ItemIdValue.ClientID, - ItemTitle.ClientID, - TreePickerUrl, - ModalWidth.ToString(), - ModalHeight.ToString(), - ShowHeader.ToString().ToLower(), - Umbraco.Core.IO.IOHelper.ResolveUrl(Umbraco.Core.IO.SystemDirectories.Umbraco).TrimEnd('/') - }); - } - - /// - /// Registers the required JS classes required to make this control work - /// - protected virtual void RenderJSComponents() - { - const string BaseTreePickerScriptJs = @"/// -(function ($) { - $(document).ready(function () { - // Tooltip only Text - $('.umb-tree-picker a.choose').click(function () { - var that = this; - var s = $(that).data(""section""); - UmbClientMgr.openAngularModalWindow({ - template: 'views/common/dialogs/treepicker.html', - section: s, - callback: function (data) { - //this returns the content object picked - var p = jQuery(that).parent(); - p.find("".buttons"").show(); - - p.find(""input"").val(data.id); - p.find("".treePickerTitle"").text(data.name).show(); - p.find("".clear"").show(); - } - }); - - return false; - }); - - $('.umb-tree-picker a.clear').click(function () { - jQuery(this).parent().parent().find(""input"").val(""-1""); - jQuery(this).parent().parent().find("".treePickerTitle"").text("""").hide(); - jQuery(this).hide(); - }); - }); -})(jQuery); -"; - - const string scriptKey = "BaseTreePickerScripts"; - if (ScriptManager.GetCurrent(Page).IsInAsyncPostBack) - { - ScriptManager.RegisterStartupScript(this, this.GetType(), scriptKey, BaseTreePickerScriptJs, true); - } - else - { - Page.ClientScript.RegisterClientScriptBlock(typeof(BaseTreePicker), scriptKey, BaseTreePickerScriptJs, true); - } - } - - protected override void OnInit(EventArgs e) - { - base.OnInit(e); - - EnsureChildControls(); - - //disable view state for this control - this.EnableViewState = false; - } - - /// - /// Create the native .net child controls for this control - /// - protected override void CreateChildControls() - { - base.CreateChildControls(); - - RootContainer = new HtmlGenericControl("span"); - RootContainer.Attributes.Add("class", "umb-tree-picker"); - this.Controls.Add(RootContainer); - - //create the hidden field - ItemIdValue = new HiddenField(); - ItemIdValue.ID = "ContentIdValue"; - RootContainer.Controls.Add(ItemIdValue); - - - ButtonContainer = new HtmlGenericControl("span"); - ButtonContainer.ID = "btns"; - - //add item title with padding - ItemTitle = new HtmlGenericControl("span"); - ItemTitle.ID = "title"; - ItemTitle.Style.Add(HtmlTextWriterStyle.FontWeight, "bold"); - ItemTitle.Attributes.Add("class", "treePickerTitle"); // solely for styling, e.g. with an underline or dotted border, etc. - ButtonContainer.Controls.Add(ItemTitle); - ButtonContainer.Attributes.Add("class", "buttons"); - ButtonContainer.Controls.Add(new LiteralControl(" ")); - ButtonContainer.Controls.Add(new LiteralControl(" ")); - - //add the delete link with padding - DeleteLink = new HtmlAnchor(); - DeleteLink.HRef = "#"; //set on pre-render - DeleteLink.Style.Add(HtmlTextWriterStyle.Color, "red"); - DeleteLink.Title = Current.Services.TextService.Localize("delete"); - DeleteLink.InnerText = Current.Services.TextService.Localize("delete"); - DeleteLink.Attributes.Add("class", "clear"); - - ButtonContainer.Controls.Add(DeleteLink); - ButtonContainer.Controls.Add(new LiteralControl(" ")); - ButtonContainer.Controls.Add(new LiteralControl(" ")); - if (!ShowDelete) - { - DeleteLink.Style.Add(HtmlTextWriterStyle.Display, "none"); - } - - RootContainer.Controls.Add(ButtonContainer); - - //add choose link with padding - ChooseLink = new HtmlAnchor(); - ChooseLink.HRef = "#"; //filled in on pre-render - ChooseLink.InnerText = Current.Services.TextService.Localize("choose") + "..."; - ChooseLink.Attributes.Add("data-section", this.TreePickerUrl); - ChooseLink.Attributes.Add("class", "choose"); - - RootContainer.Controls.Add(ChooseLink); - } - - /// - /// Registers the JavaScript required for the control to function and hides/shows controls depending on it's properties - /// - /// - protected override void OnPreRender(EventArgs e) - { - base.OnPreRender(e); - - //hide the buttons if no item, otherwise get the item title - if (string.IsNullOrEmpty(ItemIdValue.Value)) - { - ButtonContainer.Style.Add(HtmlTextWriterStyle.Display, "none"); - } - else - { - ItemTitle.InnerText = GetItemTitle(); - ItemTitle.Attributes.Add("title", GetItemBreadcrumbs()); // Adding full path/meta info (Issue U4-192) - } - /* - ChooseLink.HRef = string.Format("javascript:mc_{0}.LaunchPicker();", this.ClientID); - DeleteLink.HRef = string.Format("javascript:mc_{0}.ClearSelection();", this.ClientID); - */ - - RenderJSComponents(); - - /* - if (ScriptManager.GetCurrent(Page).IsInAsyncPostBack) - { - ScriptManager.RegisterStartupScript(this, this.GetType(), this.ClientID + "TreePicker", GetJSScript(), true); - } - else - { - Page.ClientScript.RegisterStartupScript(this.GetType(), this.ClientID + "TreePicker", GetJSScript(), true); - }*/ - - } - - - } -} diff --git a/src/Umbraco.Web/_Legacy/Packager/PackageInstance/InstalledPackage.cs b/src/Umbraco.Web/_Legacy/Packager/PackageInstance/InstalledPackage.cs index d7ea239a3f..e5af44b747 100644 --- a/src/Umbraco.Web/_Legacy/Packager/PackageInstance/InstalledPackage.cs +++ b/src/Umbraco.Web/_Legacy/Packager/PackageInstance/InstalledPackage.cs @@ -22,18 +22,10 @@ namespace Umbraco.Web._Legacy.Packager.PackageInstance return pack; } - public static InstalledPackage GetByGuid(string packageGuid) - { - InstalledPackage pack = new InstalledPackage(); - pack.Data = data.Package(packageGuid, IOHelper.MapPath(Settings.InstalledPackagesSettings)); - return pack; - } - public static InstalledPackage MakeNew(string name) { InstalledPackage pack = new InstalledPackage(); pack.Data = data.MakeNew(name, IOHelper.MapPath(Settings.InstalledPackagesSettings)); - pack.OnNew(EventArgs.Empty); return pack; } @@ -43,9 +35,7 @@ namespace Umbraco.Web._Legacy.Packager.PackageInstance _saveHitCount++; Current.Logger.Info("The InstalledPackage class save method has been hit {Total} times.", _saveHitCount); #endif - this.FireBeforeSave(EventArgs.Empty); data.Save(this.Data, IOHelper.MapPath(Settings.InstalledPackagesSettings)); - this.FireAfterSave(EventArgs.Empty); } public static List GetAllInstalledPackages() @@ -63,12 +53,7 @@ namespace Umbraco.Web._Legacy.Packager.PackageInstance return val; } - private Core.Models.Packaging.PackageDefinition m_data; - public Core.Models.Packaging.PackageDefinition Data - { - get { return m_data; } - set { m_data = value; } - } + public Core.Models.Packaging.PackageDefinition Data { get; set; } public void Delete(int userId) { @@ -78,69 +63,9 @@ namespace Umbraco.Web._Legacy.Packager.PackageInstance public void Delete() { - this.FireBeforeDelete(EventArgs.Empty); data.Delete(this.Data.Id, IOHelper.MapPath(Settings.InstalledPackagesSettings)); - this.FireAfterDelete(EventArgs.Empty); } - public static bool isPackageInstalled(string packageGuid) - { - try - { - if (data.GetFromGuid(packageGuid, IOHelper.MapPath(Settings.InstalledPackagesSettings), true) == null) - return false; - else - return true; - } - catch (Exception ex) - { - Current.Logger.Error(ex, "An error occured in isPackagedInstalled"); - return false; - } - } - - //EVENTS - public delegate void SaveEventHandler(InstalledPackage sender, EventArgs e); - public delegate void NewEventHandler(InstalledPackage sender, EventArgs e); - public delegate void DeleteEventHandler(InstalledPackage sender, EventArgs e); - - /// - /// Occurs when a macro is saved. - /// - public static event SaveEventHandler BeforeSave; - protected virtual void FireBeforeSave(EventArgs e) - { - if (BeforeSave != null) - BeforeSave(this, e); - } - - public static event SaveEventHandler AfterSave; - protected virtual void FireAfterSave(EventArgs e) - { - if (AfterSave != null) - AfterSave(this, e); - } - - public static event NewEventHandler New; - protected virtual void OnNew(EventArgs e) - { - if (New != null) - New(this, e); - } - - public static event DeleteEventHandler BeforeDelete; - protected virtual void FireBeforeDelete(EventArgs e) - { - if (BeforeDelete != null) - BeforeDelete(this, e); - } - - public static event DeleteEventHandler AfterDelete; - protected virtual void FireAfterDelete(EventArgs e) - { - if (AfterDelete != null) - AfterDelete(this, e); - } /// diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/controls/ContentPicker.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/controls/ContentPicker.cs deleted file mode 100644 index 018c49a249..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/controls/ContentPicker.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System; -using Umbraco.Web._Legacy.Controls; -using Umbraco.Core; -using Umbraco.Core.Services; -using Umbraco.Web; -using Umbraco.Web.Composing; - -namespace umbraco.controls -{ - - public class ContentPicker : BaseTreePicker - { - - public ContentPicker() - { - AppAlias = Constants.Applications.Content; - TreeAlias = "content"; - } - - - public string AppAlias { get; set; } - public string TreeAlias { get; set; } - - public override string TreePickerUrl - { - get - { - return AppAlias; - } - } - - public override string ModalWindowTitle - { - get - { - return Current.Services.TextService.Localize("general/choose") + " " + Current.Services.TextService.Localize("sections/" + TreeAlias.ToLower()); - } - } - - protected override string GetItemTitle() - { - string tempTitle = ""; - try - { - if (Value != "" && Value != "-1") - { - //tempTitle = new cms.businesslogic.CMSNode(int.Parse(Value)).Text; - tempTitle = Current.Services.EntityService.Get(int.Parse(Value)).Name; - } - else - { - tempTitle = (!string.IsNullOrEmpty(TreeAlias) ? Current.Services.TextService.Localize(TreeAlias) : Current.Services.TextService.Localize(AppAlias)); - - } - } - catch { } - return tempTitle; - } - } -} From c89b50f0b82063e459d60ed08c664f6911ea8786 Mon Sep 17 00:00:00 2001 From: Shannon Date: Fri, 11 Jan 2019 14:30:04 +1100 Subject: [PATCH 293/469] large refactor/cleanup of most of the old package installer logic dealing with persisting the installedPackages.config which is now in the services, creates new parsers and removes a ton of old code, changes fetching packages to be async, uses XElement instead of old XmlNode apis, next we need to do the actual package installer updates --- .../Composing/Composers/ServicesComposer.cs | 19 +- .../Events/ImportPackageEventArgs.cs | 6 +- .../Events/UninstallPackageEventArgs.cs | 8 +- .../Models/Packaging/CompiledPackage.cs | 48 +++ .../Models/Packaging/IPackageInfo.cs | 19 + .../Models/Packaging/InstallationSummary.cs | 65 ++- .../InstallationSummaryExtentions.cs | 23 -- src/Umbraco.Core/Models/Packaging/MetaData.cs | 23 -- .../Models/Packaging/PackageDefinition.cs | 6 +- .../Packaging/RequirementsType.cs | 2 +- .../Models/Packaging/UninstallationSummary.cs | 21 +- .../UninstallationSummaryExtentions.cs | 22 -- .../Packaging/ICreatedPackagesRepository.cs | 5 +- .../Packaging/IInstalledPackagesRepository.cs | 9 +- .../Packaging/IPackageExtraction.cs | 2 +- .../Packaging/IPackageInstallation.cs | 3 +- .../Packaging/PackageActionRunner.cs | 6 +- .../Packaging/PackageBinaryInspector.cs | 295 -------------- .../Packaging/PackageDefinitionXmlParser.cs | 165 ++++++++ .../Packaging/PackageInstallation.cs | 28 +- ...gesRepository.cs => PackagesRepository.cs} | 153 +++---- .../Services/IPackagingService.cs | 19 +- .../Services/Implement/PackagingService.cs | 199 ++++------ src/Umbraco.Core/Umbraco.Core.csproj | 12 +- src/Umbraco.Core/Xml/XmlHelper.cs | 165 +------- .../_Legacy/PackageActions/IPackageAction.cs | 6 +- .../Composing/PackageActionCollectionTests.cs | 9 +- .../CreatedPackagesRepositoryTests.cs | 3 +- .../Services/PackagingServiceTests.cs | 2 +- src/Umbraco.Tests/TestHelpers/TestObjects.cs | 8 +- src/Umbraco.Web/Editors/PackageController.cs | 2 +- .../Editors/PackageInstallController.cs | 122 +++--- .../Controllers/InstallPackageController.cs | 18 +- .../InstallSteps/ConfigureMachineKey.cs | 5 +- .../InstallSteps/DatabaseConfigureStep.cs | 5 +- .../InstallSteps/DatabaseInstallStep.cs | 7 +- .../InstallSteps/DatabaseUpgradeStep.cs | 5 +- .../InstallSteps/FilePermissionsStep.cs | 5 +- .../Install/InstallSteps/NewInstallStep.cs | 5 +- .../InstallSteps/SetUmbracoVersionStep.cs | 7 +- .../InstallSteps/StarterKitCleanupStep.cs | 5 +- .../InstallSteps/StarterKitDownloadStep.cs | 24 +- .../InstallSteps/StarterKitInstallStep.cs | 5 +- .../Install/InstallSteps/UpgradeStep.cs | 3 +- .../Install/Models/InstallSetupStep.cs | 14 +- .../Models/LocalPackageInstallModel.cs | 3 - src/Umbraco.Web/Umbraco.Web.csproj | 5 - .../_Legacy/PackageActions/PackageHelper.cs | 84 ---- .../_Legacy/PackageActions/addApplication.cs | 20 +- .../PackageActions/addDashboardSection.cs | 44 +-- .../PackageActions/addProxyFeedHost.cs | 81 ++-- .../PackageActions/addStringToHtmlElement.cs | 202 ---------- .../_Legacy/PackageActions/allowDoctype.cs | 17 +- .../PackageActions/publishRootDocument.cs | 16 +- .../removeStringFromTemplate.cs | 34 -- src/Umbraco.Web/_Legacy/Packager/Installer.cs | 247 +++++------- .../PackageInstance/InstalledPackage.cs | 136 ------- src/Umbraco.Web/_Legacy/Packager/data.cs | 374 ------------------ 58 files changed, 810 insertions(+), 2036 deletions(-) create mode 100644 src/Umbraco.Core/Models/Packaging/CompiledPackage.cs create mode 100644 src/Umbraco.Core/Models/Packaging/IPackageInfo.cs delete mode 100644 src/Umbraco.Core/Models/Packaging/InstallationSummaryExtentions.cs delete mode 100644 src/Umbraco.Core/Models/Packaging/MetaData.cs rename src/Umbraco.Core/{ => Models}/Packaging/RequirementsType.cs (65%) delete mode 100644 src/Umbraco.Core/Models/Packaging/UninstallationSummaryExtentions.cs delete mode 100644 src/Umbraco.Core/Packaging/PackageBinaryInspector.cs create mode 100644 src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs rename src/Umbraco.Core/Packaging/{CreatedPackagesRepository.cs => PackagesRepository.cs} (79%) delete mode 100644 src/Umbraco.Web/_Legacy/PackageActions/PackageHelper.cs delete mode 100644 src/Umbraco.Web/_Legacy/PackageActions/addStringToHtmlElement.cs delete mode 100644 src/Umbraco.Web/_Legacy/PackageActions/removeStringFromTemplate.cs delete mode 100644 src/Umbraco.Web/_Legacy/Packager/PackageInstance/InstalledPackage.cs delete mode 100644 src/Umbraco.Web/_Legacy/Packager/data.cs diff --git a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs index 9692a2d87c..98f239de3b 100644 --- a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs @@ -60,11 +60,9 @@ namespace Umbraco.Core.Composing.Composers composition.RegisterUnique(); composition.RegisterUnique(); - composition.RegisterUnique(factory => - new CreatedPackagesRepository( //we are using a factory because there are optional ctor args - factory.GetInstance(), factory.GetInstance(), factory.GetInstance(), - factory.GetInstance(), factory.GetInstance(), factory.GetInstance(), - factory.GetInstance(), factory.GetInstance())); + + composition.RegisterUnique(factory => CreatePackageRepository(factory, "createdPackages.config")); + composition.RegisterUnique(factory => CreatePackageRepository(factory, "installedPackages.config")); //TODO: These are replaced in the web project - we need to declare them so that // something is wired up, just not sure this is very nice but will work for now. @@ -74,6 +72,17 @@ namespace Umbraco.Core.Composing.Composers return composition; } + /// + /// Creates an instance of PackagesRepository for either the ICreatedPackagesRepository or the IInstalledPackagesRepository + /// + /// + /// + /// + private static PackagesRepository CreatePackageRepository(IFactory factory, string packageRepoFileName) + => new PackagesRepository( + factory.GetInstance(), factory.GetInstance(), factory.GetInstance(), factory.GetInstance(), factory.GetInstance(), factory.GetInstance(), factory.GetInstance(), factory.GetInstance(), + packageRepoFileName); + private static LocalizedTextServiceFileSources SourcesFactory(IFactory container) { var mainLangFolder = new DirectoryInfo(IOHelper.MapPath(SystemDirectories.Umbraco + "/config/lang/")); diff --git a/src/Umbraco.Core/Events/ImportPackageEventArgs.cs b/src/Umbraco.Core/Events/ImportPackageEventArgs.cs index ba356ff952..61369af59d 100644 --- a/src/Umbraco.Core/Events/ImportPackageEventArgs.cs +++ b/src/Umbraco.Core/Events/ImportPackageEventArgs.cs @@ -7,19 +7,19 @@ namespace Umbraco.Core.Events { public class ImportPackageEventArgs : CancellableEnumerableObjectEventArgs, IEquatable> { - public ImportPackageEventArgs(TEntity eventObject, MetaData packageMetaData, bool canCancel) + public ImportPackageEventArgs(TEntity eventObject, IPackageInfo packageMetaData, bool canCancel) : base(new[] { eventObject }, canCancel) { PackageMetaData = packageMetaData ?? throw new ArgumentNullException(nameof(packageMetaData)); } - public ImportPackageEventArgs(TEntity eventObject, MetaData packageMetaData) + public ImportPackageEventArgs(TEntity eventObject, IPackageInfo packageMetaData) : this(eventObject, packageMetaData, true) { } - public MetaData PackageMetaData { get; } + public IPackageInfo PackageMetaData { get; } public IEnumerable InstallationSummary => EventObject; diff --git a/src/Umbraco.Core/Events/UninstallPackageEventArgs.cs b/src/Umbraco.Core/Events/UninstallPackageEventArgs.cs index 13c260bf3e..2618d04e17 100644 --- a/src/Umbraco.Core/Events/UninstallPackageEventArgs.cs +++ b/src/Umbraco.Core/Events/UninstallPackageEventArgs.cs @@ -5,17 +5,13 @@ namespace Umbraco.Core.Events { public class UninstallPackageEventArgs : CancellableObjectEventArgs> { - public UninstallPackageEventArgs(TEntity eventObject, bool canCancel) + public UninstallPackageEventArgs(TEntity eventObject, IPackageInfo packageMetaData, bool canCancel) : base(new[] { eventObject }, canCancel) - { } - - public UninstallPackageEventArgs(TEntity eventObject, MetaData packageMetaData) - : base(new[] { eventObject }) { PackageMetaData = packageMetaData; } - public MetaData PackageMetaData { get; } + public IPackageInfo PackageMetaData { get; } public IEnumerable UninstallationSummary => EventObject; } diff --git a/src/Umbraco.Core/Models/Packaging/CompiledPackage.cs b/src/Umbraco.Core/Models/Packaging/CompiledPackage.cs new file mode 100644 index 0000000000..cb3fbd7eee --- /dev/null +++ b/src/Umbraco.Core/Models/Packaging/CompiledPackage.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Umbraco.Core.Models.Packaging +{ + /// + /// The model of the package definition within an umbraco (zip) package file + /// + public class CompiledPackage : IPackageInfo + { + public string Name { get; set; } + + public string Version { get; set; } + + public string Url { get; set; } + + public string License { get; set; } + + public string LicenseUrl { get; set; } + + public Version UmbracoVersion { get; set; } + + public RequirementsType UmbracoVersionRequirementsType { get; set; } + + public string Author { get; set; } + + public string AuthorUrl { get; set; } + + public string Readme { get; set; } + + public string Control { get; set; } + + public string IconUrl { get; set; } + + public List Files { get; set; } = new List(); + + } + + public class CompiledPackageFile + { + public string OriginalPath { get; set; } + public string UniqueFileName { get; set; } + public string OriginalName { get; set; } + } + + +} diff --git a/src/Umbraco.Core/Models/Packaging/IPackageInfo.cs b/src/Umbraco.Core/Models/Packaging/IPackageInfo.cs new file mode 100644 index 0000000000..8722ee7811 --- /dev/null +++ b/src/Umbraco.Core/Models/Packaging/IPackageInfo.cs @@ -0,0 +1,19 @@ +using System; + +namespace Umbraco.Core.Models.Packaging +{ + public interface IPackageInfo + { + string Name { get; } + string Version { get; } + string Url { get; } + string License { get; } + string LicenseUrl { get; } + Version UmbracoVersion { get; } + string Author { get; } + string AuthorUrl { get; } + string Readme { get; } + string Control { get; } //fixme - this needs to be an angular view + string IconUrl { get; } + } +} diff --git a/src/Umbraco.Core/Models/Packaging/InstallationSummary.cs b/src/Umbraco.Core/Models/Packaging/InstallationSummary.cs index 39df529300..ddecf53653 100644 --- a/src/Umbraco.Core/Models/Packaging/InstallationSummary.cs +++ b/src/Umbraco.Core/Models/Packaging/InstallationSummary.cs @@ -1,6 +1,9 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Runtime.Serialization; +using Umbraco.Core.IO; +using Umbraco.Core.Services; namespace Umbraco.Core.Models.Packaging { @@ -8,17 +11,57 @@ namespace Umbraco.Core.Models.Packaging [DataContract(IsReference = true)] public class InstallationSummary { - public MetaData MetaData { get; set; } - public IEnumerable DataTypesInstalled { get; set; } - public IEnumerable LanguagesInstalled { get; set; } - public IEnumerable DictionaryItemsInstalled { get; set; } - public IEnumerable MacrosInstalled { get; set; } - public IEnumerable FilesInstalled { get; set; } - public IEnumerable TemplatesInstalled { get; set; } - public IEnumerable ContentTypesInstalled { get; set; } - public IEnumerable StylesheetsInstalled { get; set; } - public IEnumerable ContentInstalled { get; set; } - public IEnumerable Actions { get; set; } + public IPackageInfo MetaData { get; set; } + public IEnumerable DataTypesInstalled { get; set; } = Enumerable.Empty(); + public IEnumerable LanguagesInstalled { get; set; } = Enumerable.Empty(); + public IEnumerable DictionaryItemsInstalled { get; set; } = Enumerable.Empty(); + public IEnumerable MacrosInstalled { get; set; } = Enumerable.Empty(); + public IEnumerable FilesInstalled { get; set; } = Enumerable.Empty(); + public IEnumerable TemplatesInstalled { get; set; } = Enumerable.Empty(); + public IEnumerable ContentTypesInstalled { get; set; } = Enumerable.Empty(); + public IEnumerable StylesheetsInstalled { get; set; } = Enumerable.Empty(); + public IEnumerable ContentInstalled { get; set; } = Enumerable.Empty(); + public IEnumerable Actions { get; set; } = Enumerable.Empty(); public bool PackageInstalled { get; set; } + + public static InstallationSummary FromPackageDefinition(PackageDefinition def, IContentTypeService contentTypeService, IDataTypeService dataTypeService, IFileService fileService, ILocalizationService localizationService, IMacroService macroService) + { + var macros = TryGetIntegerIds(def.Macros).Select(macroService.GetById).ToList(); + var templates = TryGetIntegerIds(def.Templates).Select(fileService.GetTemplate).ToList(); + var contentTypes = TryGetIntegerIds(def.DocumentTypes).Select(contentTypeService.Get).ToList(); // fixme - media types? + var dataTypes = TryGetIntegerIds(def.DataTypes).Select(dataTypeService.GetDataType).ToList(); + var dictionaryItems = TryGetIntegerIds(def.DictionaryItems).Select(localizationService.GetDictionaryItemById).ToList(); + var languages = TryGetIntegerIds(def.Languages).Select(localizationService.GetLanguageById).ToList(); + + for (var i = 0; i < def.Files.Count; i++) + { + var filePath = def.Files[i]; + def.Files[i] = filePath.GetRelativePath(); + } + + return new InstallationSummary + { + ContentTypesInstalled = contentTypes, + DataTypesInstalled = dataTypes, + DictionaryItemsInstalled = dictionaryItems, + FilesInstalled = def.Files, + LanguagesInstalled = languages, + MacrosInstalled = macros, + MetaData = def, + TemplatesInstalled = templates, + }; + } + + private static IEnumerable TryGetIntegerIds(IEnumerable ids) + { + var intIds = new List(); + foreach (var id in ids) + { + if (int.TryParse(id, out var parsed)) + intIds.Add(parsed); + } + return intIds; + } } + } diff --git a/src/Umbraco.Core/Models/Packaging/InstallationSummaryExtentions.cs b/src/Umbraco.Core/Models/Packaging/InstallationSummaryExtentions.cs deleted file mode 100644 index 3b969d84dc..0000000000 --- a/src/Umbraco.Core/Models/Packaging/InstallationSummaryExtentions.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Collections.Generic; - -namespace Umbraco.Core.Models.Packaging -{ - internal static class InstallationSummaryExtentions - { - public static InstallationSummary InitEmpty(this InstallationSummary summary) - { - summary.Actions = new List(); - summary.ContentInstalled = new List(); - summary.ContentTypesInstalled = new List(); - summary.DataTypesInstalled = new List(); - summary.DictionaryItemsInstalled = new List(); - summary.FilesInstalled = new List(); - summary.LanguagesInstalled = new List(); - summary.MacrosInstalled = new List(); - summary.MetaData = new MetaData(); - summary.TemplatesInstalled = new List(); - summary.PackageInstalled = false; - return summary; - } - } -} \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Packaging/MetaData.cs b/src/Umbraco.Core/Models/Packaging/MetaData.cs deleted file mode 100644 index a1cb450c5b..0000000000 --- a/src/Umbraco.Core/Models/Packaging/MetaData.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Runtime.Serialization; - -namespace Umbraco.Core.Models.Packaging -{ - [Serializable] - [DataContract(IsReference = true)] - public class MetaData - { - public string Name { get; set; } - public string Version { get; set; } - public string Url { get; set; } - public string License { get; set; } - public string LicenseUrl { get; set; } - public int ReqMajor { get; set; } - public int ReqMinor { get; set; } - public int ReqPatch { get; set; } - public string AuthorName { get; set; } - public string AuthorUrl { get; set; } - public string Readme { get; set; } - public string Control { get; set; } - } -} diff --git a/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs b/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs index 01d10fa2e1..65e26419f0 100644 --- a/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs +++ b/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs @@ -7,7 +7,7 @@ using System.Runtime.Serialization; namespace Umbraco.Core.Models.Packaging { [DataContract(Name = "packageInstance")] - public class PackageDefinition + public class PackageDefinition : IPackageInfo { [DataMember(Name = "id")] public int Id { get; set; } @@ -89,9 +89,9 @@ namespace Umbraco.Core.Models.Packaging [DataMember(Name = "files")] public IList Files { get; set; } = new List(); - //TODO: Change this to angular view + //fixme: Change this to angular view [DataMember(Name = "loadControl")] - public string LoadControl { get; set; } = string.Empty; + public string Control { get; set; } = string.Empty; [DataMember(Name = "actions")] public string Actions { get; set; } = ""; diff --git a/src/Umbraco.Core/Packaging/RequirementsType.cs b/src/Umbraco.Core/Models/Packaging/RequirementsType.cs similarity index 65% rename from src/Umbraco.Core/Packaging/RequirementsType.cs rename to src/Umbraco.Core/Models/Packaging/RequirementsType.cs index 38cac482c2..2b6894ed0f 100644 --- a/src/Umbraco.Core/Packaging/RequirementsType.cs +++ b/src/Umbraco.Core/Models/Packaging/RequirementsType.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Core.Packaging +namespace Umbraco.Core.Models.Packaging { public enum RequirementsType { diff --git a/src/Umbraco.Core/Models/Packaging/UninstallationSummary.cs b/src/Umbraco.Core/Models/Packaging/UninstallationSummary.cs index cfa454f91c..20cbedbcf0 100644 --- a/src/Umbraco.Core/Models/Packaging/UninstallationSummary.cs +++ b/src/Umbraco.Core/Models/Packaging/UninstallationSummary.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Runtime.Serialization; namespace Umbraco.Core.Models.Packaging @@ -8,16 +9,16 @@ namespace Umbraco.Core.Models.Packaging [DataContract(IsReference = true)] public class UninstallationSummary { - public MetaData MetaData { get; set; } - public IEnumerable DataTypesUninstalled { get; set; } - public IEnumerable LanguagesUninstalled { get; set; } - public IEnumerable DictionaryItemsUninstalled { get; set; } - public IEnumerable MacrosUninstalled { get; set; } - public IEnumerable FilesUninstalled { get; set; } - public IEnumerable TemplatesUninstalled { get; set; } - public IEnumerable ContentTypesUninstalled { get; set; } - public IEnumerable StylesheetsUninstalled { get; set; } - public IEnumerable ContentUninstalled { get; set; } + public IPackageInfo MetaData { get; set; } + public IEnumerable DataTypesUninstalled { get; set; } = Enumerable.Empty(); + public IEnumerable LanguagesUninstalled { get; set; } = Enumerable.Empty(); + public IEnumerable DictionaryItemsUninstalled { get; set; } = Enumerable.Empty(); + public IEnumerable MacrosUninstalled { get; set; } = Enumerable.Empty(); + public IEnumerable FilesUninstalled { get; set; } = Enumerable.Empty(); + public IEnumerable TemplatesUninstalled { get; set; } = Enumerable.Empty(); + public IEnumerable ContentTypesUninstalled { get; set; } = Enumerable.Empty(); + public IEnumerable StylesheetsUninstalled { get; set; } = Enumerable.Empty(); + public IEnumerable ContentUninstalled { get; set; } = Enumerable.Empty(); public bool PackageUninstalled { get; set; } } } diff --git a/src/Umbraco.Core/Models/Packaging/UninstallationSummaryExtentions.cs b/src/Umbraco.Core/Models/Packaging/UninstallationSummaryExtentions.cs deleted file mode 100644 index 688b78fa1f..0000000000 --- a/src/Umbraco.Core/Models/Packaging/UninstallationSummaryExtentions.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Collections.Generic; - -namespace Umbraco.Core.Models.Packaging -{ - internal static class UninstallationSummaryExtentions - { - public static UninstallationSummary InitEmpty(this UninstallationSummary summary) - { - summary.ContentUninstalled = new List(); - summary.ContentTypesUninstalled = new List(); - summary.DataTypesUninstalled = new List(); - summary.DictionaryItemsUninstalled = new List(); - summary.FilesUninstalled = new List(); - summary.LanguagesUninstalled = new List(); - summary.MacrosUninstalled = new List(); - summary.MetaData = new MetaData(); - summary.TemplatesUninstalled = new List(); - summary.PackageUninstalled = false; - return summary; - } - } -} diff --git a/src/Umbraco.Core/Packaging/ICreatedPackagesRepository.cs b/src/Umbraco.Core/Packaging/ICreatedPackagesRepository.cs index 52a16ddff0..42606da6ef 100644 --- a/src/Umbraco.Core/Packaging/ICreatedPackagesRepository.cs +++ b/src/Umbraco.Core/Packaging/ICreatedPackagesRepository.cs @@ -2,6 +2,9 @@ namespace Umbraco.Core.Packaging { + /// + /// Manages the storage of created package definitions + /// public interface ICreatedPackagesRepository : IPackageDefinitionRepository { /// @@ -10,4 +13,4 @@ namespace Umbraco.Core.Packaging /// string ExportPackage(PackageDefinition definition); } -} \ No newline at end of file +} diff --git a/src/Umbraco.Core/Packaging/IInstalledPackagesRepository.cs b/src/Umbraco.Core/Packaging/IInstalledPackagesRepository.cs index 3d601d6b1d..61f611edc5 100644 --- a/src/Umbraco.Core/Packaging/IInstalledPackagesRepository.cs +++ b/src/Umbraco.Core/Packaging/IInstalledPackagesRepository.cs @@ -2,12 +2,9 @@ namespace Umbraco.Core.Packaging { - - //TODO: We need to figure out how we want to do this - // we have 2x repositories for saving created and installed packages - // created packages can also be exported - // maybe the below will work? - + /// + /// Manages the storage of installed package definitions + /// public interface IInstalledPackagesRepository : IPackageDefinitionRepository { } diff --git a/src/Umbraco.Core/Packaging/IPackageExtraction.cs b/src/Umbraco.Core/Packaging/IPackageExtraction.cs index 21a5198f55..02e98dc539 100644 --- a/src/Umbraco.Core/Packaging/IPackageExtraction.cs +++ b/src/Umbraco.Core/Packaging/IPackageExtraction.cs @@ -3,7 +3,7 @@ namespace Umbraco.Core.Packaging { /// - /// Used to access an umbraco package file + /// Used to access an umbraco package (zip) file /// Remeber that filenames must be unique /// use "FindDubletFileNames" for sanitycheck /// diff --git a/src/Umbraco.Core/Packaging/IPackageInstallation.cs b/src/Umbraco.Core/Packaging/IPackageInstallation.cs index 6dc4f0fd4e..e8950390e4 100644 --- a/src/Umbraco.Core/Packaging/IPackageInstallation.cs +++ b/src/Umbraco.Core/Packaging/IPackageInstallation.cs @@ -9,8 +9,7 @@ namespace Umbraco.Core.Packaging // there are app domain reboots involved so a single method cannot be used. This needs to either be split into several // methods or return an object with a callback to proceed to the next step. InstallationSummary InstallPackage(string packageFilePath, int userId); - MetaData GetMetaData(string packageFilePath); + IPackageInfo GetMetaData(string packageFilePath); PreInstallWarnings GetPreInstallWarnings(string packageFilePath); - XElement GetConfigXmlElement(string packageFilePath); } } diff --git a/src/Umbraco.Core/Packaging/PackageActionRunner.cs b/src/Umbraco.Core/Packaging/PackageActionRunner.cs index c7545bdae8..64b913989c 100644 --- a/src/Umbraco.Core/Packaging/PackageActionRunner.cs +++ b/src/Umbraco.Core/Packaging/PackageActionRunner.cs @@ -1,5 +1,5 @@ using System; -using System.Xml; +using System.Xml.Linq; using Umbraco.Core.Logging; using Umbraco.Core._Legacy.PackageActions; @@ -26,7 +26,7 @@ namespace Umbraco.Core.Packaging /// Name of the package. /// The action alias. /// The action XML. - public void RunPackageAction(string packageName, string actionAlias, XmlNode actionXml) + public void RunPackageAction(string packageName, string actionAlias, XElement actionXml) { foreach (var ipa in _packageActions) @@ -49,7 +49,7 @@ namespace Umbraco.Core.Packaging /// Name of the package. /// The action alias. /// The action XML. - public void UndoPackageAction(string packageName, string actionAlias, System.Xml.XmlNode actionXml) + public void UndoPackageAction(string packageName, string actionAlias, XElement actionXml) { foreach (var ipa in _packageActions) { diff --git a/src/Umbraco.Core/Packaging/PackageBinaryInspector.cs b/src/Umbraco.Core/Packaging/PackageBinaryInspector.cs deleted file mode 100644 index 7cacb30bd3..0000000000 --- a/src/Umbraco.Core/Packaging/PackageBinaryInspector.cs +++ /dev/null @@ -1,295 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Security; -using System.Security.Permissions; -using Umbraco.Core.Composing; -using Umbraco.Core.Logging; - -namespace Umbraco.Core.Packaging -{ - // Note - // That class uses ReflectionOnlyLoad which does NOT handle policies (bindingRedirect) and - // therefore raised warnings when installing a package, if an exact dependency could not be - // found, though it would be found via policies. So we have to explicitely apply policies - // where appropriate. - - internal class PackageBinaryInspector : MarshalByRefObject - { - /// - /// Entry point to call from your code - /// - /// - /// - /// - /// - /// - /// Will perform the assembly scan in a separate app domain - /// - public static IEnumerable ScanAssembliesForTypeReference(IEnumerable assemblys, out string[] errorReport) - { - // need to wrap in a safe call context in order to prevent whatever Umbraco stores - // in the logical call context from flowing to the created app domain (eg, the - // UmbracoDatabase is *not* serializable and cannot and should not flow). - using (new SafeCallContext()) - { - var appDomain = GetTempAppDomain(); - var type = typeof(PackageBinaryInspector); - try - { - var value = (PackageBinaryInspector)appDomain.CreateInstanceAndUnwrap( - type.Assembly.FullName, - type.FullName); - // do NOT turn PerformScan into static (even if ReSharper says so)! - var result = value.PerformScan(assemblys.ToArray(), out errorReport); - return result; - } - finally - { - AppDomain.Unload(appDomain); - } - } - } - - /// - /// Entry point to call from your code - /// - /// - /// - /// - /// - /// - /// Will perform the assembly scan in a separate app domain - /// - public static IEnumerable ScanAssembliesForTypeReference(string dllPath, out string[] errorReport) - { - var appDomain = GetTempAppDomain(); - var type = typeof(PackageBinaryInspector); - try - { - var value = (PackageBinaryInspector)appDomain.CreateInstanceAndUnwrap( - type.Assembly.FullName, - type.FullName); - // do NOT turn PerformScan into static (even if ReSharper says so)! - var result = value.PerformScan(dllPath, out errorReport); - return result; - } - finally - { - AppDomain.Unload(appDomain); - } - } - - /// - /// Performs the assembly scanning - /// - /// - /// - /// - /// - /// - /// This method is executed in a separate app domain - /// - private IEnumerable PerformScan(IEnumerable assemblies, out string[] errorReport) - { - //we need this handler to resolve assembly dependencies when loading below - AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += (s, e) => - { - var name = AppDomain.CurrentDomain.ApplyPolicy(e.Name); - var a = Assembly.ReflectionOnlyLoad(name); - if (a == null) throw new TypeLoadException("Could not load assembly " + e.Name); - return a; - }; - - //First load each dll file into the context - // do NOT apply policy here: we want to scan the dlls that are in the binaries - var loaded = assemblies.Select(Assembly.ReflectionOnlyLoad).ToList(); - - //scan - return PerformScan(loaded, out errorReport); - } - - /// - /// Performs the assembly scanning - /// - /// - /// - /// - /// - /// - /// This method is executed in a separate app domain - /// - private IEnumerable PerformScan(string dllPath, out string[] errorReport) - { - if (Directory.Exists(dllPath) == false) - { - throw new DirectoryNotFoundException("Could not find directory " + dllPath); - } - - //we need this handler to resolve assembly dependencies when loading below - AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += (s, e) => - { - var name = AppDomain.CurrentDomain.ApplyPolicy(e.Name); - var a = Assembly.ReflectionOnlyLoad(name); - if (a == null) throw new TypeLoadException("Could not load assembly " + e.Name); - return a; - }; - - //First load each dll file into the context - // do NOT apply policy here: we want to scan the dlls that are in the path - var files = Directory.GetFiles(dllPath, "*.dll"); - var loaded = files.Select(Assembly.ReflectionOnlyLoadFrom).ToList(); - - //scan - return PerformScan(loaded, out errorReport); - } - - private static IEnumerable PerformScan(IList loaded, out string[] errorReport) - { - var dllsWithReference = new List(); - var errors = new List(); - var assembliesWithErrors = new List(); - - //load each of the LoadFrom assemblies into the Load context too - foreach (var a in loaded) - { - var name = AppDomain.CurrentDomain.ApplyPolicy(a.FullName); - Assembly.ReflectionOnlyLoad(name); - } - - //get the list of assembly names to compare below - var loadedNames = loaded.Select(x => x.GetName().Name).ToArray(); - - //Then load each referenced assembly into the context - foreach (var a in loaded) - { - //don't load any referenced assemblies that are already found in the loaded array - this is based on name - // regardless of version. We'll assume that if the assembly found in the folder matches the assembly name - // being looked for, that is the version the user has shipped their package with and therefore it 'must' be correct - foreach (var assemblyName in a.GetReferencedAssemblies().Where(ass => loadedNames.Contains(ass.Name) == false)) - { - try - { - var name = AppDomain.CurrentDomain.ApplyPolicy(assemblyName.FullName); - Assembly.ReflectionOnlyLoad(name); - } - catch (FileNotFoundException) - { - //if an exception occurs it means that a referenced assembly could not be found - errors.Add( - string.Concat("This package references the assembly '", - assemblyName.Name, - "' which was not found")); - assembliesWithErrors.Add(a); - } - catch (Exception ex) - { - //if an exception occurs it means that a referenced assembly could not be found - errors.Add( - string.Concat("This package could not be verified for compatibility. An error occurred while loading a referenced assembly '", - assemblyName.Name, - "' see error log for full details.")); - assembliesWithErrors.Add(a); - Current.Logger.Error(ex, "An error occurred scanning package assembly '{AssemblyName}'", assemblyName.FullName); - } - } - } - - var contractType = GetLoadFromContractType(); - - //now that we have all referenced types into the context we can look up stuff - foreach (var a in loaded.Except(assembliesWithErrors)) - { - //now we need to see if they contain any type 'T' - var reflectedAssembly = a; - - try - { - var found = reflectedAssembly.GetExportedTypes() - .Where(contractType.IsAssignableFrom); - - if (found.Any()) - { - dllsWithReference.Add(reflectedAssembly.FullName); - } - } - catch (Exception ex) - { - //This is a hack that nobody can seem to get around, I've read everything and it seems that - // this is quite a common thing when loading types into reflection only load context, so - // we're just going to ignore this specific one for now - var typeLoadEx = ex as TypeLoadException; - if (typeLoadEx != null) - { - if (typeLoadEx.Message.InvariantContains("does not have an implementation")) - { - //ignore - continue; - } - } - else - { - errors.Add( - string.Concat("This package could not be verified for compatibility. An error occurred while scanning a packaged assembly '", - a.GetName().Name, - "' see error log for full details.")); - assembliesWithErrors.Add(a); - Current.Logger.Error(ex, "An error occurred scanning package assembly '{AssemblyName}'", a.GetName().FullName); - } - } - - } - - errorReport = errors.ToArray(); - return dllsWithReference; - } - - /// - /// In order to compare types, the types must be in the same context, this method will return the type that - /// we are checking against but from the Load context. - /// - /// - /// - private static Type GetLoadFromContractType() - { - var name = AppDomain.CurrentDomain.ApplyPolicy(typeof(T).Assembly.FullName); - var contractAssemblyLoadFrom = Assembly.ReflectionOnlyLoad(name); - - var contractType = contractAssemblyLoadFrom.GetExportedTypes() - .FirstOrDefault(x => x.FullName == typeof(T).FullName && x.Assembly.FullName == typeof(T).Assembly.FullName); - - if (contractType == null) - { - throw new InvalidOperationException("Could not find type " + typeof(T) + " in the LoadFrom assemblies"); - } - return contractType; - } - - /// - /// Create an app domain - /// - /// - private static AppDomain GetTempAppDomain() - { - //copy the current app domain setup but don't shadow copy files - var appName = "TempDomain" + Guid.NewGuid(); - var domainSetup = new AppDomainSetup - { - ApplicationName = appName, - ShadowCopyFiles = "false", - ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase, - ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile, - DynamicBase = AppDomain.CurrentDomain.SetupInformation.DynamicBase, - LicenseFile = AppDomain.CurrentDomain.SetupInformation.LicenseFile, - LoaderOptimization = AppDomain.CurrentDomain.SetupInformation.LoaderOptimization, - PrivateBinPath = AppDomain.CurrentDomain.SetupInformation.PrivateBinPath, - PrivateBinPathProbe = AppDomain.CurrentDomain.SetupInformation.PrivateBinPathProbe - }; - - // create new domain with full trust - return AppDomain.CreateDomain(appName, AppDomain.CurrentDomain.Evidence, domainSetup, new PermissionSet(PermissionState.Unrestricted)); - } - } -} diff --git a/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs b/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs new file mode 100644 index 0000000000..6f3e4a3603 --- /dev/null +++ b/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs @@ -0,0 +1,165 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Xml.Linq; +using System.Xml.XPath; +using Umbraco.Core.Logging; +using Umbraco.Core.Models.Packaging; + +namespace Umbraco.Core.Packaging +{ + /// + /// Parses the xml document contained in a compiled (zip) Umbraco package + /// + public class CompiledPackageXmlParser + { + public CompiledPackageXmlParser() + { + + } + + public CompiledPackage ToCompiledPackage(XDocument xml) + { + if (xml == null) throw new ArgumentNullException(nameof(xml)); + if (xml.Root == null) throw new ArgumentException(nameof(xml), "The xml document is invalid"); + if (xml.Root.Name != Constants.Packaging.UmbPackageNodeName) throw new FormatException("The xml document is invalid"); + + var info = xml.Root.Element("info"); + if (info == null) throw new FormatException("The xml document is invalid"); + var package = xml.Element("package"); + if (package == null) throw new FormatException("The xml document is invalid"); + var author = package.Element("author"); + if (author == null) throw new FormatException("The xml document is invalid"); + var requirements = package.Element("requirements"); + if (requirements == null) throw new FormatException("The xml document is invalid"); + + var def = new CompiledPackage + { + Name = package.Element("name")?.Value, + Author = author.Element("name")?.Value, + AuthorUrl = author.Element("website")?.Value, + Version = package.Element("version")?.Value, + Readme = info.Element("readme")?.Value, + License = package.Element("license")?.Value, + LicenseUrl = package.Element("license")?.AttributeValue("url"), + Url = package.Element("url")?.Value, + IconUrl = package.Element("iconUrl")?.Value, + UmbracoVersion = new Version((int)requirements.Element("major"), (int)requirements.Element("minor"), (int)requirements.Element("patch")), + UmbracoVersionRequirementsType = Enum.Parse(requirements.AttributeValue("type")), + Control = package.Element("control")?.Value, + + Files = xml.Root.Element("files")?.Elements("files")?.Select(x => new CompiledPackageFile + { + UniqueFileName = x.Element("guid")?.Value, + OriginalName = x.Element("orgPath")?.Value, + OriginalPath = x.Element("orgName")?.Value + }).ToList() ?? new List(), + + }; + + return def; + } + + } + + /// + /// Converts a to and from XML + /// + public class PackageDefinitionXmlParser + { + private readonly ILogger _logger; + + public PackageDefinitionXmlParser(ILogger logger) + { + _logger = logger; + } + + public PackageDefinition ToPackageDefinition(XElement xml) + { + if (xml == null) return null; + + var retVal = new PackageDefinition + { + Id = xml.AttributeValue("id"), + Name = xml.AttributeValue("name") ?? string.Empty, + FolderId = xml.AttributeValue("folder"), + PackagePath = xml.AttributeValue("packagePath") ?? string.Empty, + Version = xml.AttributeValue("version") ?? string.Empty, + Url = xml.AttributeValue("url") ?? string.Empty, + PackageId = xml.AttributeValue("packageGuid"), + IconUrl = xml.AttributeValue("iconUrl") ?? string.Empty, + UmbracoVersion = xml.AttributeValue("umbVersion"), + License = xml.Element("license")?.Value ?? string.Empty, + LicenseUrl = xml.Element("license")?.AttributeValue("url") ?? string.Empty, + Author = xml.Element("author")?.Value ?? string.Empty, + AuthorUrl = xml.Element("author")?.AttributeValue("url") ?? string.Empty, + Readme = xml.Element("readme")?.Value ?? string.Empty, + Actions = xml.Element("actions")?.ToString(SaveOptions.None) ?? "", //take the entire outer xml value + ContentNodeId = xml.Element("content")?.AttributeValue("nodeId") ?? string.Empty, + ContentLoadChildNodes = xml.Element("content")?.AttributeValue("loadChildNodes") ?? false, + Macros = xml.Element("macros")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(), + Templates = xml.Element("templates")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(), + Stylesheets = xml.Element("stylesheets")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(), + DocumentTypes = xml.Element("documentTypes")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(), + Languages = xml.Element("languages")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(), + DictionaryItems = xml.Element("dictionaryitems")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(), + DataTypes = xml.Element("datatypes")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(), + Files = xml.Element("files")?.Elements("file").Select(x => x.Value).ToList() ?? new List(), + Control = xml.Element("loadcontrol")?.Value ?? string.Empty + }; + + return retVal; + } + + public XElement ToXml(PackageDefinition def) + { + var actionsXml = new XElement("actions"); + try + { + actionsXml = XElement.Parse(def.Actions); + } + catch (Exception e) + { + _logger.Warn(e, "Could not add package actions to the package xml definition, the xml did not parse"); + } + + var packageXml = new XElement("package", + new XAttribute("id", def.Id), + new XAttribute("version", def.Version ?? string.Empty), + new XAttribute("url", def.Url ?? string.Empty), + new XAttribute("name", def.Name ?? string.Empty), + new XAttribute("folder", def.FolderId), + new XAttribute("packagePath", def.PackagePath ?? string.Empty), + new XAttribute("iconUrl", def.IconUrl ?? string.Empty), + new XAttribute("umbVersion", def.UmbracoVersion), + new XAttribute("packageGuid", def.PackageId), + + new XElement("license", + new XCData(def.License ?? string.Empty), + new XAttribute("url", def.LicenseUrl ?? string.Empty)), + + new XElement("author", + new XCData(def.Author ?? string.Empty), + new XAttribute("url", def.AuthorUrl ?? string.Empty)), + + new XElement("readme", new XCData(def.Readme ?? string.Empty)), + actionsXml, + new XElement("datatypes", string.Join(",", def.DataTypes ?? Array.Empty())), + + new XElement("content", + new XAttribute("nodeId", def.ContentNodeId), + new XAttribute("loadChildNodes", def.ContentLoadChildNodes)), + + new XElement("templates", string.Join(",", def.Templates ?? Array.Empty())), + new XElement("stylesheets", string.Join(",", def.Stylesheets ?? Array.Empty())), + new XElement("documentTypes", string.Join(",", def.DocumentTypes ?? Array.Empty())), + new XElement("macros", string.Join(",", def.Macros ?? Array.Empty())), + new XElement("files", (def.Files ?? Array.Empty()).Where(x => !x.IsNullOrWhiteSpace()).Select(x => new XElement("file", x))), + new XElement("languages", string.Join(",", def.Languages ?? Array.Empty())), + new XElement("dictionaryitems", string.Join(",", def.DictionaryItems ?? Array.Empty())), + new XElement("loadcontrol", def.Control ?? string.Empty)); //fixme: no more loadcontrol, needs to be an angular view + + return packageXml; + } + } +} diff --git a/src/Umbraco.Core/Packaging/PackageInstallation.cs b/src/Umbraco.Core/Packaging/PackageInstallation.cs index 556c5203ec..6c9cd57451 100644 --- a/src/Umbraco.Core/Packaging/PackageInstallation.cs +++ b/src/Umbraco.Core/Packaging/PackageInstallation.cs @@ -78,7 +78,7 @@ namespace Umbraco.Core.Packaging } } - public MetaData GetMetaData(string packageFilePath) + public IPackageInfo GetMetaData(string packageFilePath) { try { @@ -117,14 +117,14 @@ namespace Umbraco.Core.Packaging XElement documentSet; XElement documents; XElement actions; - MetaData metaData; + IPackageInfo metaData; InstallationSummary installationSummary; try { XElement rootElement = GetConfigXmlElement(packageFile); PackageSupportedCheck(rootElement); - PackageStructureSanetyCheck(packageFile, rootElement); + PackageStructureSanityCheck(packageFile, rootElement); dataTypes = rootElement.Element(Constants.Packaging.DataTypesNodeName); languages = rootElement.Element(Constants.Packaging.LanguagesNodeName); dictionaryItems = rootElement.Element(Constants.Packaging.DictionaryItemsNodeName); @@ -220,7 +220,7 @@ namespace Umbraco.Core.Packaging public XElement GetConfigXmlElement(string packageFilePath) { - XDocument document = GetConfigXmlDoc(packageFilePath); + var document = GetConfigXmlDoc(packageFilePath); if (document.Root == null || document.Root.Name.LocalName.Equals(Constants.Packaging.UmbPackageNodeName) == false) { @@ -229,13 +229,7 @@ namespace Umbraco.Core.Packaging return document.Root; } - internal void PackageStructureSanetyCheck(string packageFilePath) - { - XElement rootElement = GetConfigXmlElement(packageFilePath); - PackageStructureSanetyCheck(packageFilePath, rootElement); - } - - private void PackageStructureSanetyCheck(string packageFilePath, XElement rootElement) + private void PackageStructureSanityCheck(string packageFilePath, XElement rootElement) { XElement filesElement = rootElement.Element(Constants.Packaging.FilesNodeName); if (filesElement != null) @@ -513,7 +507,7 @@ namespace Umbraco.Core.Packaging return pathElement.TrimStart(new[] {'\\', '/', '~'}).Replace("/", "\\"); } - private MetaData GetMetaData(XElement xRootElement) + private IPackageInfo GetMetaData(XElement xRootElement) { XElement infoElement = xRootElement.Element(Constants.Packaging.InfoNodeName); @@ -535,21 +529,19 @@ namespace Umbraco.Core.Packaging var readmeElement = infoElement.XPathSelectElement(Constants.Packaging.ReadmeXpath); XElement controlElement = xRootElement.Element(Constants.Packaging.ControlNodeName); - - return new MetaData + + return new PackageDefinition { Name = StringValue(nameElement), Version = StringValue(versionElement), Url = StringValue(urlElement), License = StringValue(licenseElement), LicenseUrl = StringAttribute(licenseElement, Constants.Packaging.PackageLicenseXpathUrlAttribute), - AuthorName = StringValue(authorNameElement), + Author = StringValue(authorNameElement), AuthorUrl = StringValue(authorUrlElement), Readme = StringValue(readmeElement), Control = StringValue(controlElement), - ReqMajor = IntValue(majorElement), - ReqMinor = IntValue(minorElement), - ReqPatch = IntValue(patchElement) + UmbracoVersion = new Version(IntValue(majorElement), IntValue(minorElement), IntValue(patchElement)) }; } diff --git a/src/Umbraco.Core/Packaging/CreatedPackagesRepository.cs b/src/Umbraco.Core/Packaging/PackagesRepository.cs similarity index 79% rename from src/Umbraco.Core/Packaging/CreatedPackagesRepository.cs rename to src/Umbraco.Core/Packaging/PackagesRepository.cs index 169b161fbc..9f37f8a546 100644 --- a/src/Umbraco.Core/Packaging/CreatedPackagesRepository.cs +++ b/src/Umbraco.Core/Packaging/PackagesRepository.cs @@ -15,7 +15,10 @@ using File = System.IO.File; namespace Umbraco.Core.Packaging { - internal class CreatedPackagesRepository : ICreatedPackagesRepository + /// + /// Manages the storage of installed/created package definitions + /// + internal class PackagesRepository : ICreatedPackagesRepository, IInstalledPackagesRepository { private readonly IContentService _contentService; private readonly IContentTypeService _contentTypeService; @@ -25,16 +28,37 @@ namespace Umbraco.Core.Packaging private readonly ILocalizationService _languageService; private readonly IEntityXmlSerializer _serializer; private readonly ILogger _logger; + private readonly string _packageRepositoryFileName; private readonly string _mediaFolderPath; private readonly string _packagesFolderPath; private readonly string _tempFolderPath; - - public CreatedPackagesRepository(IContentService contentService, IContentTypeService contentTypeService, + private readonly PackageDefinitionXmlParser _parser; + + /// + /// Constructor + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// The file name for storing the package definitions (i.e. "createdPackages.config") + /// + /// + /// + /// + public PackagesRepository(IContentService contentService, IContentTypeService contentTypeService, IDataTypeService dataTypeService, IFileService fileService, IMacroService macroService, ILocalizationService languageService, IEntityXmlSerializer serializer, ILogger logger, + string packageRepositoryFileName, string tempFolderPath = null, string packagesFolderPath = null, string mediaFolderPath = null) { + if (string.IsNullOrWhiteSpace(packageRepositoryFileName)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(packageRepositoryFileName)); _contentService = contentService; _contentTypeService = contentTypeService; _dataTypeService = dataTypeService; @@ -43,32 +67,38 @@ namespace Umbraco.Core.Packaging _languageService = languageService; _serializer = serializer; _logger = logger; - + _packageRepositoryFileName = packageRepositoryFileName; + _tempFolderPath = tempFolderPath ?? SystemDirectories.Data + "/TEMP/PackageFiles"; _packagesFolderPath = packagesFolderPath ?? SystemDirectories.Packages; _mediaFolderPath = mediaFolderPath ?? SystemDirectories.Media + "/created-packages"; + + _parser = new PackageDefinitionXmlParser(logger); } - private string CreatedPackagesFile => _packagesFolderPath.EnsureEndsWith('/') + "createdPackages.config"; + private string CreatedPackagesFile => _packagesFolderPath.EnsureEndsWith('/') + _packageRepositoryFileName; public IEnumerable GetAll() { var packagesXml = EnsureStorage(out _); + if (packagesXml?.Root == null) + yield break;; + foreach (var packageXml in packagesXml.Root.Elements("package")) - yield return XmlToPackageDefinition(packageXml); + yield return _parser.ToPackageDefinition(packageXml); } public PackageDefinition GetById(int id) { var packagesXml = EnsureStorage(out _); - var packageXml = packagesXml.Root.Elements("package").FirstOrDefault(x => x.AttributeValue("id") == id); - return packageXml == null ? null : XmlToPackageDefinition(packageXml); + var packageXml = packagesXml?.Root?.Elements("package").FirstOrDefault(x => x.AttributeValue("id") == id); + return packageXml == null ? null : _parser.ToPackageDefinition(packageXml); } public void Delete(int id) { var packagesXml = EnsureStorage(out var packagesFile); - var packageXml = packagesXml.Root.Elements("package").FirstOrDefault(x => x.AttributeValue("id") == id); + var packageXml = packagesXml?.Root?.Elements("package").FirstOrDefault(x => x.AttributeValue("id") == id); if (packageXml == null) return; packageXml.Remove(); @@ -82,6 +112,9 @@ namespace Umbraco.Core.Packaging var packagesXml = EnsureStorage(out var packagesFile); + if (packagesXml?.Root == null) + return false; + //ensure it's valid ValidatePackage(definition); @@ -97,9 +130,9 @@ namespace Umbraco.Core.Packaging var maxId = packagesXml.Root.Elements("package").Max(x => x.AttributeValue("id")) ?? 0; var newId = maxId + 1; definition.Id = newId; - definition.PackageId = Guid.NewGuid(); + definition.PackageId = definition.PackageId == default ? Guid.NewGuid() : definition.PackageId; definition.FolderId = Guid.NewGuid(); - var packageXml = PackageDefinitionToXml(definition); + var packageXml = _parser.ToXml(definition); packagesXml.Root.Add(packageXml); } else @@ -109,7 +142,7 @@ namespace Umbraco.Core.Packaging if (packageXml == null) return false; - var updatedXml = PackageDefinitionToXml(definition); + var updatedXml = _parser.ToXml(definition); packageXml.ReplaceWith(updatedXml); } @@ -154,10 +187,10 @@ namespace Umbraco.Core.Packaging AppendFileToManifest(fileName, temporaryPath, filesXml); //Load control on install... - if (!string.IsNullOrEmpty(definition.LoadControl)) + if (!string.IsNullOrEmpty(definition.Control)) { - var control = new XElement("control", definition.LoadControl); - AppendFileToManifest(definition.LoadControl, temporaryPath, filesXml); + var control = new XElement("control", definition.Control); + AppendFileToManifest(definition.Control, temporaryPath, filesXml); manifestRoot.Add(control); } @@ -174,7 +207,7 @@ namespace Umbraco.Core.Packaging } catch (Exception e) { - _logger.Warn(e, "Could not add package actions to the package manifest, the xml did not parse"); + _logger.Warn(e, "Could not add package actions to the package manifest, the xml did not parse"); } } @@ -583,93 +616,9 @@ namespace Umbraco.Core.Packaging return packagesXml; } - private static PackageDefinition XmlToPackageDefinition(XElement xml) - { - if (xml == null) return null; + - var retVal = new PackageDefinition - { - Id = xml.AttributeValue("id"), - Name = xml.AttributeValue("name") ?? string.Empty, - FolderId = xml.AttributeValue("folder"), - PackagePath = xml.AttributeValue("packagePath") ?? string.Empty, - Version = xml.AttributeValue("version") ?? string.Empty, - Url = xml.AttributeValue("url") ?? string.Empty, - PackageId = xml.AttributeValue("packageGuid"), - IconUrl = xml.AttributeValue("iconUrl") ?? string.Empty, - UmbracoVersion = xml.AttributeValue("umbVersion"), - License = xml.Element("license")?.Value ?? string.Empty, - LicenseUrl = xml.Element("license")?.AttributeValue("url") ?? string.Empty, - Author = xml.Element("author")?.Value ?? string.Empty, - AuthorUrl = xml.Element("author")?.AttributeValue("url") ?? string.Empty, - Readme = xml.Element("readme")?.Value ?? string.Empty, - Actions = xml.Element("actions")?.ToString(SaveOptions.None) ?? "", //take the entire outer xml value - ContentNodeId = xml.Element("content")?.AttributeValue("nodeId") ?? string.Empty, - ContentLoadChildNodes = xml.Element("content")?.AttributeValue("loadChildNodes") ?? false, - Macros = xml.Element("macros")?.Value.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(), - Templates = xml.Element("templates")?.Value.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(), - Stylesheets = xml.Element("stylesheets")?.Value.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(), - DocumentTypes = xml.Element("documentTypes")?.Value.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(), - Languages = xml.Element("languages")?.Value.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(), - DictionaryItems = xml.Element("dictionaryitems")?.Value.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(), - DataTypes = xml.Element("datatypes")?.Value.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(), - Files = xml.Element("files")?.Elements("file").Select(x => x.Value).ToList() ?? new List(), - LoadControl = xml.Element("loadcontrol")?.Value ?? string.Empty - }; - - return retVal; - } - - private XElement PackageDefinitionToXml(PackageDefinition def) - { - var actionsXml = new XElement("actions"); - try - { - actionsXml = XElement.Parse(def.Actions); - } - catch (Exception e) - { - _logger.Warn(e, "Could not add package actions to the package xml definition, the xml did not parse"); - } - - var packageXml = new XElement("package", - new XAttribute("id", def.Id), - new XAttribute("version", def.Version ?? string.Empty), - new XAttribute("url", def.Url ?? string.Empty), - new XAttribute("name", def.Name ?? string.Empty), - new XAttribute("folder", def.FolderId), - new XAttribute("packagePath", def.PackagePath ?? string.Empty), - new XAttribute("iconUrl", def.IconUrl ?? string.Empty), - new XAttribute("umbVersion", def.UmbracoVersion), - new XAttribute("packageGuid", def.PackageId), - - new XElement("license", - new XCData(def.License ?? string.Empty), - new XAttribute("url", def.LicenseUrl ?? string.Empty)), - - new XElement("author", - new XCData(def.Author ?? string.Empty), - new XAttribute("url", def.AuthorUrl ?? string.Empty)), - - new XElement("readme", new XCData(def.Readme ?? string.Empty)), - actionsXml, - new XElement("datatypes", string.Join(",", def.DataTypes ?? Array.Empty())), - - new XElement("content", - new XAttribute("nodeId", def.ContentNodeId), - new XAttribute("loadChildNodes", def.ContentLoadChildNodes)), - - new XElement("templates", string.Join(",", def.Templates ?? Array.Empty())), - new XElement("stylesheets", string.Join(",", def.Stylesheets ?? Array.Empty())), - new XElement("documentTypes", string.Join(",", def.DocumentTypes ?? Array.Empty())), - new XElement("macros", string.Join(",", def.Macros ?? Array.Empty())), - new XElement("files", (def.Files ?? Array.Empty()).Where(x => !x.IsNullOrWhiteSpace()).Select(x => new XElement("file", x))), - new XElement("languages", string.Join(",", def.Languages ?? Array.Empty())), - new XElement("dictionaryitems", string.Join(",", def.DictionaryItems ?? Array.Empty())), - new XElement("loadcontrol", def.LoadControl ?? string.Empty)); //fixme: no more loadcontrol, needs to be an angular view - - return packageXml; - } + } } diff --git a/src/Umbraco.Core/Services/IPackagingService.cs b/src/Umbraco.Core/Services/IPackagingService.cs index 32d5cd4c59..5b432d3339 100644 --- a/src/Umbraco.Core/Services/IPackagingService.cs +++ b/src/Umbraco.Core/Services/IPackagingService.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Threading.Tasks; using System.Xml.Linq; using Umbraco.Core.Models; using Umbraco.Core.Models.Packaging; @@ -9,11 +10,25 @@ namespace Umbraco.Core.Services { public interface IPackagingService : IService { + #region Installed Packages + + IEnumerable GetAllInstalledPackages(); + PackageDefinition GetInstalledPackageById(int id); + void DeleteInstalledPackage(int packageId, int userId = 0); + + /// + /// Persists a package definition to storage + /// + /// + bool SaveInstalledPackage(PackageDefinition definition); + + #endregion + #region Created Packages IEnumerable GetAllCreatedPackages(); PackageDefinition GetCreatedPackageById(int id); - void DeleteCreatedPackage(int id); + void DeleteCreatedPackage(int id, int userId = 0); /// /// Persists a package definition to storage @@ -111,6 +126,6 @@ namespace Umbraco.Core.Services /// /// The current user id performing the operation /// - string FetchPackageFile(Guid packageId, Version umbracoVersion, int userId); + Task FetchPackageFileAsync(Guid packageId, Version umbracoVersion, int userId); } } diff --git a/src/Umbraco.Core/Services/Implement/PackagingService.cs b/src/Umbraco.Core/Services/Implement/PackagingService.cs index d6003dc842..e7b33dd86d 100644 --- a/src/Umbraco.Core/Services/Implement/PackagingService.cs +++ b/src/Umbraco.Core/Services/Implement/PackagingService.cs @@ -4,6 +4,7 @@ using System.IO; using System.Linq; using System.Net.Http; using System.Text.RegularExpressions; +using System.Threading.Tasks; using System.Web; using System.Xml.Linq; using Umbraco.Core.Collections; @@ -41,12 +42,11 @@ namespace Umbraco.Core.Services.Implement private readonly IFileService _fileService; private readonly ILocalizationService _localizationService; private readonly IEntityService _entityService; - private readonly IScopeProvider _scopeProvider; private Dictionary _importedContentTypes; - private readonly IAuditRepository _auditRepository; - private readonly IContentTypeRepository _contentTypeRepository; + private readonly IAuditService _auditService; private readonly PropertyEditorCollection _propertyEditors; private readonly ICreatedPackagesRepository _createdPackages; + private readonly IInstalledPackagesRepository _installedPackages; private static HttpClient _httpClient; public PackagingService( @@ -58,11 +58,10 @@ namespace Umbraco.Core.Services.Implement IFileService fileService, ILocalizationService localizationService, IEntityService entityService, - IScopeProvider scopeProvider, - IAuditRepository auditRepository, - IContentTypeRepository contentTypeRepository, + IAuditService auditService, PropertyEditorCollection propertyEditors, - ICreatedPackagesRepository createdPackages) + ICreatedPackagesRepository createdPackages, + IInstalledPackagesRepository installedPackages) { _logger = logger; _contentService = contentService; @@ -72,21 +71,15 @@ namespace Umbraco.Core.Services.Implement _fileService = fileService; _localizationService = localizationService; _entityService = entityService; - _scopeProvider = scopeProvider; - _auditRepository = auditRepository; - _contentTypeRepository = contentTypeRepository; + _auditService = auditService; _propertyEditors = propertyEditors; _createdPackages = createdPackages; + _installedPackages = installedPackages; _importedContentTypes = new Dictionary(); } - protected IQuery Query() => _scopeProvider.SqlContext.Query(); - #region Content - - - /// /// Imports and saves package xml as @@ -229,43 +222,17 @@ namespace Umbraco.Core.Services.Implement content.Key = key; } - using (var scope = _scopeProvider.CreateScope(autoComplete: true)) + foreach (var property in properties) { - foreach (var property in properties) + string propertyTypeAlias = property.Name.LocalName; + if (content.HasProperty(propertyTypeAlias)) { - string propertyTypeAlias = property.Name.LocalName; - if (content.HasProperty(propertyTypeAlias)) - { - var propertyValue = property.Value; + var propertyValue = property.Value; - var propertyType = contentType.PropertyTypes.FirstOrDefault(pt => pt.Alias == propertyTypeAlias); + var propertyType = contentType.PropertyTypes.FirstOrDefault(pt => pt.Alias == propertyTypeAlias); - //TODO: It would be heaps nicer if we didn't have to hard code references to specific property editors - // we'd have to modify the packaging format to denote how to parse/store the value instead of relying on this - - if (propertyType != null) - { - // fixme - wtf is this very specific thing here?! - //if (propertyType.PropertyEditorAlias == Constants.PropertyEditors.Aliases.CheckBoxList) - //{ - - // //TODO: We need to refactor this so the packager isn't making direct db calls for an 'edge' case - // var database = scope.Database; - // var dtos = database.Fetch("WHERE datatypeNodeId = @Id", new { Id = propertyType.DataTypeId }); - - // var propertyValueList = new List(); - // foreach (var preValue in propertyValue.Split(',')) - // { - // propertyValueList.Add(dtos.Single(x => x.Value == preValue).Id.ToString(CultureInfo.InvariantCulture)); - // } - - // propertyValue = string.Join(",", propertyValueList.ToArray()); - - //} - } - //set property value - content.SetValue(propertyTypeAlias, propertyValue); - } + //set property value + content.SetValue(propertyTypeAlias, propertyValue); } } @@ -734,17 +701,12 @@ namespace Umbraco.Core.Services.Implement /// private IContentType FindContentTypeByAlias(string contentTypeAlias) { - using (var scope = _scopeProvider.CreateScope()) - { - var query = Query().Where(x => x.Alias == contentTypeAlias); - var contentType = _contentTypeRepository.Get(query).FirstOrDefault(); + var contentType = _contentTypeService.Get(contentTypeAlias); - if (contentType == null) - throw new Exception($"ContentType matching the passed in Alias: '{contentTypeAlias}' was null"); + if (contentType == null) + throw new Exception($"ContentType matching the passed in Alias: '{contentTypeAlias}' was null"); - scope.Complete(); - return contentType; - } + return contentType; } #endregion @@ -1165,59 +1127,45 @@ namespace Umbraco.Core.Services.Implement #region Package Files - /// - /// This will fetch an Umbraco package file from the package repository and return the relative file path to the downloaded package file - /// - /// - /// - /// /// The current user id performing the operation - /// - public string FetchPackageFile(Guid packageId, Version umbracoVersion, int userId) + /// + public async Task FetchPackageFileAsync(Guid packageId, Version umbracoVersion, int userId) { - using (var scope = _scopeProvider.CreateScope()) + //includeHidden = true because we don't care if it's hidden we want to get the file regardless + var url = $"{Constants.PackageRepository.RestApiBaseUrl}/{packageId}?version={umbracoVersion.ToString(3)}&includeHidden=true&asFile=true"; + byte[] bytes; + try { - //includeHidden = true because we don't care if it's hidden we want to get the file regardless - var url = $"{Constants.PackageRepository.RestApiBaseUrl}/{packageId}?version={umbracoVersion.ToString(3)}&includeHidden=true&asFile=true"; - byte[] bytes; - try + if (_httpClient == null) { - if (_httpClient == null) - { - _httpClient = new HttpClient(); - } - bytes = _httpClient.GetByteArrayAsync(url).GetAwaiter().GetResult(); + _httpClient = new HttpClient(); } - catch (HttpRequestException ex) - { - throw new ConnectionException("An error occuring downloading the package from " + url, ex); - } - - //successfull - if (bytes.Length > 0) - { - var packagePath = IOHelper.MapPath(SystemDirectories.Packages); - - // Check for package directory - if (Directory.Exists(packagePath) == false) - Directory.CreateDirectory(packagePath); - - var packageFilePath = Path.Combine(packagePath, packageId + ".umb"); - - using (var fs1 = new FileStream(packageFilePath, FileMode.Create)) - { - fs1.Write(bytes, 0, bytes.Length); - return "packages\\" + packageId + ".umb"; - } - } - - Audit(AuditType.PackagerInstall, $"Package {packageId} fetched from {Constants.PackageRepository.DefaultRepositoryId}", userId, -1); - return null; + bytes = await _httpClient.GetByteArrayAsync(url); + } + catch (HttpRequestException ex) + { + throw new ConnectionException("An error occuring downloading the package from " + url, ex); } - } - private void Audit(AuditType type, string message, int userId, int objectId) - { - _auditRepository.Save(new AuditItem(objectId, type, userId, "Package", message)); + //successfull + if (bytes.Length > 0) + { + var packagePath = IOHelper.MapPath(SystemDirectories.Packages); + + // Check for package directory + if (Directory.Exists(packagePath) == false) + Directory.CreateDirectory(packagePath); + + var packageFilePath = Path.Combine(packagePath, packageId + ".umb"); + + using (var fs1 = new FileStream(packageFilePath, FileMode.Create)) + { + fs1.Write(bytes, 0, bytes.Length); + return "packages\\" + packageId + ".umb"; + } + } + + _auditService.Add(AuditType.PackagerInstall, userId, -1, "Package", $"Package {packageId} fetched from {Constants.PackageRepository.DefaultRepositoryId}"); + return null; } #endregion @@ -1369,21 +1317,13 @@ namespace Umbraco.Core.Services.Implement { var metaData = GetPackageMetaData(packageFilePath); - if (raiseEvents) - { - if (ImportingPackage.IsRaisedEventCancelled(new ImportPackageEventArgs(packageFilePath, metaData), this)) - { - var initEmpty = new InstallationSummary().InitEmpty(); - initEmpty.MetaData = metaData; - return initEmpty; - } - } + if (raiseEvents && ImportingPackage.IsRaisedEventCancelled(new ImportPackageEventArgs(packageFilePath, metaData), this)) + return new InstallationSummary { MetaData = metaData }; + var installationSummary = PackageInstallation.InstallPackage(packageFilePath, userId); if (raiseEvents) - { ImportedPackage.RaiseEvent(new ImportPackageEventArgs(installationSummary, metaData, false), this); - } return installationSummary; } @@ -1393,16 +1333,23 @@ namespace Umbraco.Core.Services.Implement return PackageInstallation.GetPreInstallWarnings(packageFilePath); } - internal MetaData GetPackageMetaData(string packageFilePath) + internal IPackageInfo GetPackageMetaData(string packageFilePath) { return PackageInstallation.GetMetaData(packageFilePath); } #endregion - #region Package Building + #region Created/Installed Package Repositories - public void DeleteCreatedPackage(int id) => _createdPackages.Delete(id); + public void DeleteCreatedPackage(int id, int userId = 0) + { + var package = GetCreatedPackageById(id); + if (package == null) return; + + _auditService.Add(AuditType.PackagerUninstall, userId, -1, "Package", $"Created package '{package.Name}' deleted. Package id: {package.Id}"); + _createdPackages.Delete(id); + } public IEnumerable GetAllCreatedPackages() => _createdPackages.GetAll(); @@ -1412,6 +1359,22 @@ namespace Umbraco.Core.Services.Implement public string ExportCreatedPackage(PackageDefinition definition) => _createdPackages.ExportPackage(definition); + + public IEnumerable GetAllInstalledPackages() => _installedPackages.GetAll(); + + public PackageDefinition GetInstalledPackageById(int id) => _installedPackages.GetById(id); + + public bool SaveInstalledPackage(PackageDefinition definition) => _installedPackages.SavePackage(definition); + + public void DeleteInstalledPackage(int packageId, int userId = 0) + { + var package = GetInstalledPackageById(packageId); + if (package == null) return; + + _auditService.Add(AuditType.PackagerUninstall, userId, -1, "Package", $"Installed package '{package.Name}' deleted. Package id: {package.Id}"); + _installedPackages.Delete(packageId); + } + #endregion /// diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index bad9ba7ccd..038d531bd4 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -430,7 +430,8 @@ - + + @@ -443,13 +444,13 @@ - - - + + + @@ -769,7 +770,6 @@ - @@ -893,7 +893,6 @@ - @@ -1535,7 +1534,6 @@ - \ No newline at end of file diff --git a/src/Umbraco.Core/Xml/XmlHelper.cs b/src/Umbraco.Core/Xml/XmlHelper.cs index d4f2d40656..e058858799 100644 --- a/src/Umbraco.Core/Xml/XmlHelper.cs +++ b/src/Umbraco.Core/Xml/XmlHelper.cs @@ -14,7 +14,7 @@ namespace Umbraco.Core.Xml /// /// The XmlHelper class contains general helper methods for working with xml in umbraco. /// - public class XmlHelper + internal class XmlHelper { /// /// Creates or sets an attribute on the XmlNode if an Attributes collection is available @@ -126,44 +126,6 @@ namespace Umbraco.Core.Xml return false; } - /// - /// Tries to create a new XElement from a property value. - /// - /// The value of the property. - /// The Xml element. - /// A value indicating whether it has been possible to create the element. - /// The value can be anything... Performance-wise, this is bad. - public static bool TryCreateXElementFromPropertyValue(object value, out XElement elt) - { - // see note above in TryCreateXPathDocumentFromPropertyValue... - - elt = null; - var xml = value as string; - if (xml == null) return false; // not a string - if (CouldItBeXml(xml) == false) return false; // string does not look like it's xml - if (IsXmlWhitespace(xml)) return false; // string is whitespace, xml-wise - - try - { - elt = XElement.Parse(xml, LoadOptions.None); - } - catch - { - elt = null; - return false; // string can't be parsed into xml - } - - //SD: This used to do this but the razor macros and the entire razor macros section is gone, it was all legacy, it seems this method isn't even - // used apart from for tests so don't think this matters. In any case, we no longer check for this! - - //var name = elt.Name.LocalName; // must not match an excluded tag - //if (UmbracoConfig.For.UmbracoSettings().Scripting.NotDynamicXmlDocumentElements.All(x => x.Element.InvariantEquals(name) == false)) - // return true; - //elt = null; - //return false; - - return true; - } /// /// Sorts the children of a parentNode. @@ -186,47 +148,6 @@ namespace Umbraco.Core.Xml parentNode.AppendChild(node); // moves the node to the last position } - /// - /// Sorts the children of a parentNode if needed. - /// - /// The parent node. - /// An XPath expression to select children of to sort. - /// A function returning the value to order the nodes by. - /// A value indicating whether sorting was needed. - /// same as SortNodes but will do nothing if nodes are already sorted - should improve performances. - internal static bool SortNodesIfNeeded( - XmlNode parentNode, - string childNodesXPath, - Func orderBy) - { - // ensure orderBy runs only once per node - // checks whether nodes are already ordered - // and actually sorts only if needed - - var childNodesAndOrder = parentNode.SelectNodes(childNodesXPath).Cast() - .Select(x => Tuple.Create(x, orderBy(x))).ToArray(); - - var a = 0; - foreach (var x in childNodesAndOrder) - { - if (a > x.Item2) - { - a = -1; - break; - } - a = x.Item2; - } - - if (a >= 0) - return false; - - // append child nodes to last position, in sort-order - // so all child nodes will go after the property nodes - foreach (var x in childNodesAndOrder.OrderBy(x => x.Item2)) - parentNode.AppendChild(x.Item1); // moves the node to the last position - - return true; - } /// /// Sorts a single child node of a parentNode. @@ -281,72 +202,6 @@ namespace Umbraco.Core.Xml return false; } - // used by DynamicNode only, see note in TryCreateXPathDocumentFromPropertyValue - public static string StripDashesInElementOrAttributeNames(string xml) - { - using (var outputms = new MemoryStream()) - { - using (TextWriter outputtw = new StreamWriter(outputms)) - { - using (var ms = new MemoryStream()) - { - using (var tw = new StreamWriter(ms)) - { - tw.Write(xml); - tw.Flush(); - ms.Position = 0; - using (var tr = new StreamReader(ms)) - { - bool IsInsideElement = false, IsInsideQuotes = false; - int ic = 0; - while ((ic = tr.Read()) != -1) - { - if (ic == (int)'<' && !IsInsideQuotes) - { - if (tr.Peek() != (int)'!') - { - IsInsideElement = true; - } - } - if (ic == (int)'>' && !IsInsideQuotes) - { - IsInsideElement = false; - } - if (ic == (int)'"') - { - IsInsideQuotes = !IsInsideQuotes; - } - if (!IsInsideElement || ic != (int)'-' || IsInsideQuotes) - { - outputtw.Write((char)ic); - } - } - - } - } - } - outputtw.Flush(); - outputms.Position = 0; - using (TextReader outputtr = new StreamReader(outputms)) - { - return outputtr.ReadToEnd(); - } - } - } - } - - - /// - /// Imports a XML node from text. - /// - /// The text. - /// The XML doc. - /// - public static XmlNode ImportXmlNodeFromText(string text, ref XmlDocument xmlDoc) - { - xmlDoc.LoadXml(text); - return xmlDoc.FirstChild; - } /// /// Opens a file as a XmlDocument. @@ -355,16 +210,14 @@ namespace Umbraco.Core.Xml /// Returns a XmlDocument class public static XmlDocument OpenAsXmlDocument(string filePath) { - - var reader = new XmlTextReader(IOHelper.MapPath(filePath)) {WhitespaceHandling = WhitespaceHandling.All}; - - var xmlDoc = new XmlDocument(); - //Load the file into the XmlDocument - xmlDoc.Load(reader); - //Close off the connection to the file. - reader.Close(); - - return xmlDoc; + using (var reader = new XmlTextReader(IOHelper.MapPath(filePath)) {WhitespaceHandling = WhitespaceHandling.All}) + { + var xmlDoc = new XmlDocument(); + //Load the file into the XmlDocument + xmlDoc.Load(reader); + + return xmlDoc; + } } /// diff --git a/src/Umbraco.Core/_Legacy/PackageActions/IPackageAction.cs b/src/Umbraco.Core/_Legacy/PackageActions/IPackageAction.cs index 502aee36b3..b58ea34a60 100644 --- a/src/Umbraco.Core/_Legacy/PackageActions/IPackageAction.cs +++ b/src/Umbraco.Core/_Legacy/PackageActions/IPackageAction.cs @@ -1,13 +1,13 @@ using System.Xml; +using System.Xml.Linq; using Umbraco.Core.Composing; namespace Umbraco.Core._Legacy.PackageActions { public interface IPackageAction : IDiscoverable { - bool Execute(string packageName, XmlNode xmlData); + bool Execute(string packageName, XElement xmlData); string Alias(); - bool Undo(string packageName, XmlNode xmlData); - XmlNode SampleXml(); + bool Undo(string packageName, XElement xmlData); } } diff --git a/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs b/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs index d100713102..75030decbf 100644 --- a/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs +++ b/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using System.Xml; +using System.Xml.Linq; using Moq; using NUnit.Framework; using Umbraco.Core; @@ -41,7 +42,7 @@ namespace Umbraco.Tests.Composing public class PackageAction1 : IPackageAction { - public bool Execute(string packageName, XmlNode xmlData) + public bool Execute(string packageName, XElement xmlData) { throw new NotImplementedException(); } @@ -51,7 +52,7 @@ namespace Umbraco.Tests.Composing return "pa1"; } - public bool Undo(string packageName, XmlNode xmlData) + public bool Undo(string packageName, XElement xmlData) { throw new NotImplementedException(); } @@ -64,7 +65,7 @@ namespace Umbraco.Tests.Composing public class PackageAction2 : IPackageAction { - public bool Execute(string packageName, XmlNode xmlData) + public bool Execute(string packageName, XElement xmlData) { throw new NotImplementedException(); } @@ -74,7 +75,7 @@ namespace Umbraco.Tests.Composing return "pa2"; } - public bool Undo(string packageName, XmlNode xmlData) + public bool Undo(string packageName, XElement xmlData) { throw new NotImplementedException(); } diff --git a/src/Umbraco.Tests/Packaging/CreatedPackagesRepositoryTests.cs b/src/Umbraco.Tests/Packaging/CreatedPackagesRepositoryTests.cs index 3bd9b50ed4..40500d6bcb 100644 --- a/src/Umbraco.Tests/Packaging/CreatedPackagesRepositoryTests.cs +++ b/src/Umbraco.Tests/Packaging/CreatedPackagesRepositoryTests.cs @@ -37,10 +37,11 @@ namespace Umbraco.Tests.Packaging Directory.Delete(IOHelper.MapPath("~/" + _testBaseFolder), true); } - public ICreatedPackagesRepository PackageBuilder => new CreatedPackagesRepository( + public ICreatedPackagesRepository PackageBuilder => new PackagesRepository( ServiceContext.ContentService, ServiceContext.ContentTypeService, ServiceContext.DataTypeService, ServiceContext.FileService, ServiceContext.MacroService, ServiceContext.LocalizationService, Factory.GetInstance(), Logger, + "createdPackages.config", //temp paths tempFolderPath: "~/" + _testBaseFolder + "/temp", packagesFolderPath: "~/" + _testBaseFolder + "/packages", diff --git a/src/Umbraco.Tests/Services/PackagingServiceTests.cs b/src/Umbraco.Tests/Services/PackagingServiceTests.cs index 2caf3e08b3..0f57298c88 100644 --- a/src/Umbraco.Tests/Services/PackagingServiceTests.cs +++ b/src/Umbraco.Tests/Services/PackagingServiceTests.cs @@ -46,7 +46,7 @@ namespace Umbraco.Tests.Services string testPackagePath = GetTestPackagePath(documentTypePickerUmb); - MetaData packageMetaData = packagingService.GetPackageMetaData(testPackagePath); + var packageMetaData = packagingService.GetPackageMetaData(testPackagePath); Assert.IsNotNull(packageMetaData); } diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects.cs b/src/Umbraco.Tests/TestHelpers/TestObjects.cs index 105bc440cc..f48b72daf9 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects.cs @@ -169,9 +169,11 @@ namespace Umbraco.Tests.TestHelpers var macroService = GetLazyService(factory, c => new MacroService(scopeProvider, logger, eventMessagesFactory, GetRepo(c), GetRepo(c))); var packagingService = GetLazyService(factory, c => new PackagingService( - logger, contentService.Value, contentTypeService.Value, macroService.Value, dataTypeService.Value, fileService.Value, localizationService.Value, entityService.Value, scopeProvider, GetRepo(c), GetRepo(c), new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty())), - new CreatedPackagesRepository(contentService.Value, contentTypeService.Value, dataTypeService.Value, fileService.Value, macroService.Value, localizationService.Value, - new EntityXmlSerializer(contentService.Value, mediaService.Value, dataTypeService.Value, userService.Value, localizationService.Value, contentTypeService.Value, urlSegmentProviders), logger))); + logger, contentService.Value, contentTypeService.Value, macroService.Value, dataTypeService.Value, fileService.Value, localizationService.Value, entityService.Value, auditService.Value, new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty())), + createdPackages: new PackagesRepository(contentService.Value, contentTypeService.Value, dataTypeService.Value, fileService.Value, macroService.Value, localizationService.Value, + new EntityXmlSerializer(contentService.Value, mediaService.Value, dataTypeService.Value, userService.Value, localizationService.Value, contentTypeService.Value, urlSegmentProviders), logger, "createdPackages.config"), + installedPackages: new PackagesRepository(contentService.Value, contentTypeService.Value, dataTypeService.Value, fileService.Value, macroService.Value, localizationService.Value, + new EntityXmlSerializer(contentService.Value, mediaService.Value, dataTypeService.Value, userService.Value, localizationService.Value, contentTypeService.Value, urlSegmentProviders), logger, "installedPackages.config"))); var relationService = GetLazyService(factory, c => new RelationService(scopeProvider, logger, eventMessagesFactory, entityService.Value, GetRepo(c), GetRepo(c))); var treeService = GetLazyService(factory, c => new ApplicationTreeService(logger, cache, typeLoader)); var tagService = GetLazyService(factory, c => new TagService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); diff --git a/src/Umbraco.Web/Editors/PackageController.cs b/src/Umbraco.Web/Editors/PackageController.cs index 86f3e48b7c..4b452ac6a6 100644 --- a/src/Umbraco.Web/Editors/PackageController.cs +++ b/src/Umbraco.Web/Editors/PackageController.cs @@ -72,7 +72,7 @@ namespace Umbraco.Web.Editors [HttpDelete] public IHttpActionResult DeleteCreatedPackage(int packageId) { - Services.PackagingService.DeleteCreatedPackage(packageId); + Services.PackagingService.DeleteCreatedPackage(packageId, Security.GetUserId().ResultOr(0)); return Ok(); } diff --git a/src/Umbraco.Web/Editors/PackageInstallController.cs b/src/Umbraco.Web/Editors/PackageInstallController.cs index 55e843aceb..73d50eb48a 100644 --- a/src/Umbraco.Web/Editors/PackageInstallController.cs +++ b/src/Umbraco.Web/Editors/PackageInstallController.cs @@ -8,6 +8,7 @@ using System.Net.Http; using System.Threading.Tasks; using System.Web.Http; using System.Xml; +using System.Xml.Linq; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; @@ -29,7 +30,6 @@ using Umbraco.Web.UI.JavaScript; using Umbraco.Web.WebApi; using Umbraco.Web.WebApi.Filters; using Umbraco.Web._Legacy.Packager; -using Umbraco.Web._Legacy.Packager.PackageInstance; using File = System.IO.File; using Notification = Umbraco.Web.Models.ContentEditing.Notification; using Version = System.Version; @@ -73,17 +73,17 @@ namespace Umbraco.Web.Editors { try { - var pack = InstalledPackage.GetById(packageId); - if (pack == null) return NotFound(); + var package = Services.PackagingService.GetInstalledPackageById(packageId); + if (package == null) return NotFound(); - PerformUninstall(pack); + PerformUninstall(package); //now get all other packages by this name since we'll uninstall all versions - foreach (var installed in InstalledPackage.GetAllInstalledPackages() - .Where(x => x.Data.Name == pack.Data.Name && x.Data.Id != pack.Data.Id)) + foreach (var installed in Services.PackagingService.GetAllInstalledPackages() + .Where(x => x.Name == package.Name && x.Id != package.Id)) { - //remove from teh xml - installed.Delete(Security.GetUserId().ResultOr(0)); + //remove from the xml + Services.PackagingService.DeleteInstalledPackage(installed.Id, Security.GetUserId().ResultOr(0)); } } catch (Exception ex) @@ -98,10 +98,10 @@ namespace Umbraco.Web.Editors /// /// SORRY :( I didn't have time to put this in a service somewhere - the old packager did this all manually too /// - /// - protected void PerformUninstall(InstalledPackage pack) + /// + protected void PerformUninstall(PackageDefinition package) { - if (pack == null) throw new ArgumentNullException("pack"); + if (package == null) throw new ArgumentNullException("package"); var removedTemplates = new List(); var removedMacros = new List(); @@ -111,7 +111,7 @@ namespace Umbraco.Web.Editors var removedFiles = new List(); //Uninstall templates - foreach (var item in pack.Data.Templates.ToArray()) + foreach (var item in package.Templates.ToArray()) { int nId; if (int.TryParse(item, out nId) == false) continue; @@ -121,11 +121,11 @@ namespace Umbraco.Web.Editors removedTemplates.Add(found); Services.FileService.DeleteTemplate(found.Alias, Security.GetUserId().ResultOr(0)); } - pack.Data.Templates.Remove(nId.ToString()); + package.Templates.Remove(nId.ToString()); } //Uninstall macros - foreach (var item in pack.Data.Macros.ToArray()) + foreach (var item in package.Macros.ToArray()) { int nId; if (int.TryParse(item, out nId) == false) continue; @@ -135,20 +135,20 @@ namespace Umbraco.Web.Editors removedMacros.Add(macro); Services.MacroService.Delete(macro); } - pack.Data.Macros.Remove(nId.ToString()); + package.Macros.Remove(nId.ToString()); } //Remove Document Types var contentTypes = new List(); var contentTypeService = Services.ContentTypeService; - foreach (var item in pack.Data.DocumentTypes.ToArray()) + foreach (var item in package.DocumentTypes.ToArray()) { int nId; if (int.TryParse(item, out nId) == false) continue; var contentType = contentTypeService.Get(nId); if (contentType == null) continue; contentTypes.Add(contentType); - pack.Data.DocumentTypes.Remove(nId.ToString(CultureInfo.InvariantCulture)); + package.DocumentTypes.Remove(nId.ToString(CultureInfo.InvariantCulture)); } //Order the DocumentTypes before removing them @@ -163,7 +163,7 @@ namespace Umbraco.Web.Editors } //Remove Dictionary items - foreach (var item in pack.Data.DictionaryItems.ToArray()) + foreach (var item in package.DictionaryItems.ToArray()) { int nId; if (int.TryParse(item, out nId) == false) continue; @@ -173,11 +173,11 @@ namespace Umbraco.Web.Editors removedDictionaryItems.Add(di); Services.LocalizationService.Delete(di); } - pack.Data.DictionaryItems.Remove(nId.ToString()); + package.DictionaryItems.Remove(nId.ToString()); } //Remove Data types - foreach (var item in pack.Data.DataTypes.ToArray()) + foreach (var item in package.DataTypes.ToArray()) { int nId; if (int.TryParse(item, out nId) == false) continue; @@ -187,28 +187,27 @@ namespace Umbraco.Web.Editors removedDataTypes.Add(dtd); Services.DataTypeService.Delete(dtd); } - pack.Data.DataTypes.Remove(nId.ToString()); + package.DataTypes.Remove(nId.ToString()); } - pack.Save(); + Services.PackagingService.SaveInstalledPackage(package); // uninstall actions //TODO: We should probably report errors to the UI!! // This never happened before though, but we should do something now - if (pack.Data.Actions.IsNullOrWhiteSpace() == false) + if (package.Actions.IsNullOrWhiteSpace() == false) { try { - var actionsXml = new XmlDocument(); - actionsXml.LoadXml("" + pack.Data.Actions + ""); + var actionsXml = XDocument.Parse("" + package.Actions + ""); - Logger.Debug("Executing undo actions: {UndoActionsXml}", actionsXml.OuterXml); + Logger.Debug("Executing undo actions: {UndoActionsXml}", actionsXml.ToString(SaveOptions.DisableFormatting)); - foreach (XmlNode n in actionsXml.DocumentElement.SelectNodes("//Action")) + foreach (var n in actionsXml.Root.Elements("Action")) { try { - _packageActionRunner.UndoPackageAction(pack.Data.Name, n.Attributes["alias"].Value, n); + _packageActionRunner.UndoPackageAction(package.Name, n.AttributeValue("alias"), n); } catch (Exception ex) { @@ -224,7 +223,7 @@ namespace Umbraco.Web.Editors //moved remove of files here so custom package actions can still undo //Remove files - foreach (var item in pack.Data.Files.ToArray()) + foreach (var item in package.Files.ToArray()) { removedFiles.Add(item.GetRelativePath()); @@ -240,15 +239,17 @@ namespace Umbraco.Web.Editors File.Delete(filePath); } - pack.Data.Files.Remove(file); + package.Files.Remove(file); } - pack.Save(); - pack.Delete(Security.GetUserId().ResultOr(0)); + + Services.PackagingService.SaveInstalledPackage(package); + + Services.PackagingService.DeleteInstalledPackage(package.Id, Security.GetUserId().ResultOr(0)); // create a summary of what was actually removed, for PackagingService.UninstalledPackage var summary = new UninstallationSummary { - MetaData = pack.GetMetaData(), + MetaData = package, TemplatesUninstalled = removedTemplates, MacrosUninstalled = removedMacros, ContentTypesUninstalled = removedContentTypes, @@ -259,7 +260,7 @@ namespace Umbraco.Web.Editors }; // trigger the UninstalledPackage event - PackagingService.OnUninstalledPackage(new UninstallPackageEventArgs(summary, false)); + PackagingService.OnUninstalledPackage(new UninstallPackageEventArgs(summary, package, false)); } @@ -269,18 +270,14 @@ namespace Umbraco.Web.Editors /// public IEnumerable GetInstalled() { - return InstalledPackage.GetAllInstalledPackages() + return Services.PackagingService.GetAllInstalledPackages() .GroupBy( //group by name - x => x.Data.Name, + x => x.Name, //select the package with a parsed version - pck => - { - Version pckVersion; - return Version.TryParse(pck.Data.Version, out pckVersion) - ? new { package = pck, version = pckVersion } - : new { package = pck, version = new Version(0, 0, 0) }; - }) + pck => Version.TryParse(pck.Version, out var pckVersion) + ? new { package = pck, version = pckVersion } + : new { package = pck, version = new Version(0, 0, 0) }) .Select(grouping => { //get the max version for the package @@ -290,15 +287,15 @@ namespace Umbraco.Web.Editors }) .Select(pack => new InstalledPackageModel { - Name = pack.Data.Name, - Id = pack.Data.Id, - Author = pack.Data.Author, - Version = pack.Data.Version, - Url = pack.Data.Url, - License = pack.Data.License, - LicenseUrl = pack.Data.LicenseUrl, - Files = pack.Data.Files, - IconUrl = pack.Data.IconUrl + Name = pack.Name, + Id = pack.Id, + Author = pack.Author, + Version = pack.Version, + Url = pack.Url, + License = pack.License, + LicenseUrl = pack.LicenseUrl, + Files = pack.Files, + IconUrl = pack.IconUrl }) .ToList(); } @@ -320,7 +317,6 @@ namespace Umbraco.Web.Editors model.ConflictingMacroAliases = ins.ConflictingMacroAliases; model.ConflictingStyleSheetNames = ins.ConflictingStyleSheetNames; model.ConflictingTemplateAliases = ins.ConflictingTemplateAliases; - model.ContainsBinaryFileErrors = ins.ContainsBinaryFileErrors; model.ContainsMacroConflict = ins.ContainsMacroConflict; model.ContainsStyleSheetConflicts = ins.ContainsStyleSheeConflicts; model.ContainsTemplateConflicts = ins.ContainsTemplateConflicts; @@ -346,19 +342,17 @@ namespace Umbraco.Web.Editors private bool ValidateInstalledInternal(string name, string version) { - var allInstalled = InstalledPackage.GetAllInstalledPackages(); + var allInstalled = Services.PackagingService.GetAllInstalledPackages(); var found = allInstalled.FirstOrDefault(x => { - if (x.Data.Name != name) return false; + if (x.Name != name) return false; //match the exact version - if (x.Data.Version == version) + if (x.Version == version) { return true; } //now try to compare the versions - Version installed; - Version selected; - if (Version.TryParse(x.Data.Version, out installed) && Version.TryParse(version, out selected)) + if (Version.TryParse(x.Version, out var installed) && Version.TryParse(version, out var selected)) { if (installed >= selected) return true; } @@ -456,13 +450,13 @@ namespace Umbraco.Web.Editors /// /// [HttpGet] - public LocalPackageInstallModel Fetch(string packageGuid) + public async Task Fetch(string packageGuid) { //Default path string path = Path.Combine("packages", packageGuid + ".umb"); if (File.Exists(IOHelper.MapPath(Path.Combine(SystemDirectories.Data, path))) == false) { - path = Services.PackagingService.FetchPackageFile(Guid.Parse(packageGuid), UmbracoVersion.Current, Security.GetUserId().ResultOr(0)); + path = await Services.PackagingService.FetchPackageFileAsync(Guid.Parse(packageGuid), UmbracoVersion.Current, Security.GetUserId().ResultOr(0)); } var model = new LocalPackageInstallModel @@ -495,7 +489,7 @@ namespace Umbraco.Web.Editors [HttpPost] public PackageInstallModel Import(PackageInstallModel model) { - var ins = new global::Umbraco.Web._Legacy.Packager.Installer(Security.CurrentUser.Id); + var ins = new Installer(Security.CurrentUser.Id); var tempPath = ins.Import(model.ZipFilePath); //now we need to check for version comparison @@ -510,7 +504,7 @@ namespace Umbraco.Web.Editors } model.TemporaryDirectoryPath = Path.Combine(SystemDirectories.Data, tempPath); - model.Id = ins.CreateManifest(IOHelper.MapPath(model.TemporaryDirectoryPath), model.PackageGuid, model.RepositoryGuid.ToString()); + model.Id = ins.CreateManifest(model.PackageGuid); return model; } @@ -523,7 +517,7 @@ namespace Umbraco.Web.Editors [HttpPost] public PackageInstallModel InstallFiles(PackageInstallModel model) { - var ins = new global::Umbraco.Web._Legacy.Packager.Installer(Security.CurrentUser.Id); + var ins = new Installer(Security.CurrentUser.Id); ins.LoadConfig(IOHelper.MapPath(model.TemporaryDirectoryPath)); ins.InstallFiles(model.Id, IOHelper.MapPath(model.TemporaryDirectoryPath)); diff --git a/src/Umbraco.Web/Install/Controllers/InstallPackageController.cs b/src/Umbraco.Web/Install/Controllers/InstallPackageController.cs index 55680084e5..ac859ee3aa 100644 --- a/src/Umbraco.Web/Install/Controllers/InstallPackageController.cs +++ b/src/Umbraco.Web/Install/Controllers/InstallPackageController.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Net; using System.Net.Http; using System.Text; +using System.Threading.Tasks; using System.Web; using System.Web.Http; using Newtonsoft.Json.Linq; @@ -10,6 +11,7 @@ using umbraco; using Umbraco.Core; using Umbraco.Web.Cache; using Umbraco.Core.Configuration; +using Umbraco.Core.Services; using Umbraco.Web.Composing; using Umbraco.Web.Install.Models; using Umbraco.Web.WebApi; @@ -28,8 +30,12 @@ namespace Umbraco.Web.Install.Controllers [Obsolete("This is only used for the legacy way of installing starter kits in the back office")] public class InstallPackageController : ApiController { - public InstallPackageController() - { } + private readonly IPackagingService _packagingService; + + public InstallPackageController(IPackagingService packagingService) + { + _packagingService = packagingService; + } private const string RepoGuid = "65194810-1f85-11dd-bd0b-0800200c9a66"; @@ -49,18 +55,18 @@ namespace Umbraco.Web.Install.Controllers /// /// [HttpPost] - public HttpResponseMessage DownloadPackageFiles(InstallPackageModel model) + public async Task DownloadPackageFiles(InstallPackageModel model) { - var packageFile = Current.Services.PackagingService.FetchPackageFile( + var packageFile = await _packagingService.FetchPackageFileAsync( model.KitGuid, UmbracoVersion.Current, UmbracoContext.Current.Security.CurrentUser.Id); - var installer = new global::Umbraco.Web._Legacy.Packager.Installer(UmbracoContext.Current.Security.CurrentUser.Id); + var installer = new _Legacy.Packager.Installer(UmbracoContext.Current.Security.CurrentUser.Id); var tempFile = installer.Import(packageFile); installer.LoadConfig(tempFile); - var pId = installer.CreateManifest(tempFile, model.KitGuid, RepoGuid); + var pId = installer.CreateManifest(model.KitGuid); return Json(new { success = true, diff --git a/src/Umbraco.Web/Install/InstallSteps/ConfigureMachineKey.cs b/src/Umbraco.Web/Install/InstallSteps/ConfigureMachineKey.cs index de53fd60cf..f71d486f5a 100644 --- a/src/Umbraco.Web/Install/InstallSteps/ConfigureMachineKey.cs +++ b/src/Umbraco.Web/Install/InstallSteps/ConfigureMachineKey.cs @@ -1,4 +1,5 @@ using System.Linq; +using System.Threading.Tasks; using System.Web.Configuration; using System.Xml.Linq; using Umbraco.Core.IO; @@ -30,7 +31,7 @@ namespace Umbraco.Web.Install.InstallSteps /// /// /// - public override InstallSetupResult Execute(bool? model) + public override Task ExecuteAsync(bool? model) { if (model.HasValue && model.Value == false) return null; @@ -50,7 +51,7 @@ namespace Umbraco.Web.Install.InstallSteps xml.Save(fileName, SaveOptions.DisableFormatting); - return null; + return Task.FromResult(null); } public override bool RequiresExecution(bool? model) diff --git a/src/Umbraco.Web/Install/InstallSteps/DatabaseConfigureStep.cs b/src/Umbraco.Web/Install/InstallSteps/DatabaseConfigureStep.cs index 2fe6c0ceda..9d1aec1c71 100644 --- a/src/Umbraco.Web/Install/InstallSteps/DatabaseConfigureStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/DatabaseConfigureStep.cs @@ -1,5 +1,6 @@ using System; using System.Configuration; +using System.Threading.Tasks; using Umbraco.Core; using Umbraco.Core.Logging; using Umbraco.Core.Migrations.Install; @@ -20,7 +21,7 @@ namespace Umbraco.Web.Install.InstallSteps _databaseBuilder = databaseBuilder; } - public override InstallSetupResult Execute(DatabaseModel database) + public override Task ExecuteAsync(DatabaseModel database) { //if the database model is null then we will apply the defaults if (database == null) @@ -33,7 +34,7 @@ namespace Umbraco.Web.Install.InstallSteps throw new InstallException("Could not connect to the database"); } ConfigureConnection(database); - return null; + return Task.FromResult(null); } private void ConfigureConnection(DatabaseModel database) diff --git a/src/Umbraco.Web/Install/InstallSteps/DatabaseInstallStep.cs b/src/Umbraco.Web/Install/InstallSteps/DatabaseInstallStep.cs index a9daee6e95..812889b977 100644 --- a/src/Umbraco.Web/Install/InstallSteps/DatabaseInstallStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/DatabaseInstallStep.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Configuration; +using System.Threading.Tasks; using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; @@ -24,7 +25,7 @@ namespace Umbraco.Web.Install.InstallSteps _logger = logger; } - public override InstallSetupResult Execute(object model) + public override Task ExecuteAsync(object model) { if (_runtime.Level == RuntimeLevel.Run) throw new Exception("Umbraco is already configured!"); @@ -43,10 +44,10 @@ namespace Umbraco.Web.Install.InstallSteps } //upgrade is required so set the flag for the next step - return new InstallSetupResult(new Dictionary + return Task.FromResult(new InstallSetupResult(new Dictionary { {"upgrade", true} - }); + })); } internal static void HandleConnectionStrings(ILogger logger) diff --git a/src/Umbraco.Web/Install/InstallSteps/DatabaseUpgradeStep.cs b/src/Umbraco.Web/Install/InstallSteps/DatabaseUpgradeStep.cs index 8283eb6bef..e8046bd196 100644 --- a/src/Umbraco.Web/Install/InstallSteps/DatabaseUpgradeStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/DatabaseUpgradeStep.cs @@ -1,6 +1,7 @@ using System; using System.Configuration; using System.Linq; +using System.Threading.Tasks; using Umbraco.Core; using Umbraco.Core.Logging; using Umbraco.Core.Migrations.Install; @@ -23,7 +24,7 @@ namespace Umbraco.Web.Install.InstallSteps _logger = logger; } - public override InstallSetupResult Execute(object model) + public override Task ExecuteAsync(object model) { var installSteps = InstallStatusTracker.GetStatus().ToArray(); var previousStep = installSteps.Single(x => x.Name == "DatabaseInstall"); @@ -43,7 +44,7 @@ namespace Umbraco.Web.Install.InstallSteps DatabaseInstallStep.HandleConnectionStrings(_logger); } - return null; + return Task.FromResult(null); } public override bool RequiresExecution(object model) diff --git a/src/Umbraco.Web/Install/InstallSteps/FilePermissionsStep.cs b/src/Umbraco.Web/Install/InstallSteps/FilePermissionsStep.cs index 6d07190b4f..c5bc9ac047 100644 --- a/src/Umbraco.Web/Install/InstallSteps/FilePermissionsStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/FilePermissionsStep.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Threading.Tasks; using umbraco; using Umbraco.Core; using Umbraco.Core.IO; @@ -13,7 +14,7 @@ namespace Umbraco.Web.Install.InstallSteps PerformsAppRestart = true)] internal class FilePermissionsStep : InstallSetupStep { - public override InstallSetupResult Execute(object model) + public override Task ExecuteAsync(object model) { // validate file permissions Dictionary> report; @@ -22,7 +23,7 @@ namespace Umbraco.Web.Install.InstallSteps if (permissionsOk == false) throw new InstallException("Permission check failed", "permissionsreport", new { errors = report }); - return null; + return Task.FromResult(null); } public override bool RequiresExecution(object model) diff --git a/src/Umbraco.Web/Install/InstallSteps/NewInstallStep.cs b/src/Umbraco.Web/Install/InstallSteps/NewInstallStep.cs index 64b8568fe5..9132f5cd49 100644 --- a/src/Umbraco.Web/Install/InstallSteps/NewInstallStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/NewInstallStep.cs @@ -4,6 +4,7 @@ using System.Configuration; using System.Net; using System.Net.Http; using System.Text; +using System.Threading.Tasks; using System.Web; using System.Web.Security; using Newtonsoft.Json; @@ -51,7 +52,7 @@ namespace Umbraco.Web.Install.InstallSteps } } - public override InstallSetupResult Execute(UserModel user) + public override Task ExecuteAsync(UserModel user) { var admin = _userService.GetUserById(Constants.Security.SuperUserId); if (admin == null) @@ -99,7 +100,7 @@ namespace Umbraco.Web.Install.InstallSteps catch { /* fail in silence */ } } - return null; + return Task.FromResult(null); } /// diff --git a/src/Umbraco.Web/Install/InstallSteps/SetUmbracoVersionStep.cs b/src/Umbraco.Web/Install/InstallSteps/SetUmbracoVersionStep.cs index 0cac3fe91f..3e836397fd 100644 --- a/src/Umbraco.Web/Install/InstallSteps/SetUmbracoVersionStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/SetUmbracoVersionStep.cs @@ -1,4 +1,5 @@ -using System.Web; +using System.Threading.Tasks; +using System.Web; using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; @@ -31,7 +32,7 @@ namespace Umbraco.Web.Install.InstallSteps _distributedCache = distributedCache; } - public override InstallSetupResult Execute(object model) + public override Task ExecuteAsync(object model) { //During a new install we'll log the default user in (which is id = 0). // During an upgrade, the user will already need to be logged in in order to run the installer. @@ -56,7 +57,7 @@ namespace Umbraco.Web.Install.InstallSteps //reports the ended install _installHelper.InstallStatus(true, ""); - return null; + return Task.FromResult(null); } public override bool RequiresExecution(object model) diff --git a/src/Umbraco.Web/Install/InstallSteps/StarterKitCleanupStep.cs b/src/Umbraco.Web/Install/InstallSteps/StarterKitCleanupStep.cs index 9345a0fc96..075a61ca95 100644 --- a/src/Umbraco.Web/Install/InstallSteps/StarterKitCleanupStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/StarterKitCleanupStep.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using System.Threading.Tasks; using System.Web; using Umbraco.Web.Install.Models; using Umbraco.Web._Legacy.Packager; @@ -10,7 +11,7 @@ namespace Umbraco.Web.Install.InstallSteps "StarterKitCleanup", 32, "Almost done")] internal class StarterKitCleanupStep : InstallSetupStep { - public override InstallSetupResult Execute(object model) + public override Task ExecuteAsync(object model) { var installSteps = InstallStatusTracker.GetStatus().ToArray(); var previousStep = installSteps.Single(x => x.Name == "StarterKitDownload"); @@ -19,7 +20,7 @@ namespace Umbraco.Web.Install.InstallSteps CleanupInstallation(manifestId, packageFile); - return null; + return Task.FromResult(null); } private void CleanupInstallation(int manifestId, string packageFile) diff --git a/src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs b/src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs index c79be96a93..66d1b0a20c 100644 --- a/src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs @@ -1,14 +1,13 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using System.Web; using Umbraco.Core.Services; using Umbraco.Core.Configuration; using Umbraco.Web.Composing; using Umbraco.Web.Install.Models; -using Umbraco.Web.Security; using Umbraco.Web._Legacy.Packager; -using Umbraco.Web._Legacy.Packager.PackageInstance; namespace Umbraco.Web.Install.InstallSteps { @@ -20,17 +19,19 @@ namespace Umbraco.Web.Install.InstallSteps private readonly InstallHelper _installHelper; private readonly UmbracoContext _umbracoContext; private readonly IContentService _contentService; + private readonly IPackagingService _packageService; - public StarterKitDownloadStep(IContentService contentService, InstallHelper installHelper, UmbracoContext umbracoContext) + public StarterKitDownloadStep(IContentService contentService, IPackagingService packageService, InstallHelper installHelper, UmbracoContext umbracoContext) { _installHelper = installHelper; _umbracoContext = umbracoContext; _contentService = contentService; + _packageService = packageService; } private const string RepoGuid = "65194810-1f85-11dd-bd0b-0800200c9a66"; - public override InstallSetupResult Execute(Guid? starterKitId) + public override async Task ExecuteAsync(Guid? starterKitId) { //if there is no value assigned then use the default starter kit if (starterKitId.HasValue == false) @@ -48,7 +49,7 @@ namespace Umbraco.Web.Install.InstallSteps return null; } - var result = DownloadPackageFiles(starterKitId.Value); + var result = await DownloadPackageFilesAsync(starterKitId.Value); Current.RestartAppPool(); @@ -59,16 +60,16 @@ namespace Umbraco.Web.Install.InstallSteps }); } - private Tuple DownloadPackageFiles(Guid kitGuid) + private async Task> DownloadPackageFilesAsync(Guid kitGuid) { var installer = new Installer(); //Go get the package file from the package repo - var packageFile = Current.Services.PackagingService.FetchPackageFile(kitGuid, UmbracoVersion.Current, _umbracoContext.Security.GetUserId().ResultOr(0)); + var packageFile = await _packageService.FetchPackageFileAsync(kitGuid, UmbracoVersion.Current, _umbracoContext.Security.GetUserId().ResultOr(0)); var tempFile = installer.Import(packageFile); installer.LoadConfig(tempFile); - var pId = installer.CreateManifest(tempFile, kitGuid, RepoGuid); + var pId = installer.CreateManifest(kitGuid); InstallPackageFiles(pId, tempFile); @@ -84,10 +85,7 @@ namespace Umbraco.Web.Install.InstallSteps } - public override string View - { - get { return (InstalledPackage.GetAllInstalledPackages().Count > 0) ? string.Empty : base.View; } - } + public override string View => _packageService.GetAllInstalledPackages().Any() ? string.Empty : base.View; public override bool RequiresExecution(Guid? model) { @@ -97,7 +95,7 @@ namespace Umbraco.Web.Install.InstallSteps return false; } - if (InstalledPackage.GetAllInstalledPackages().Count > 0) + if (_packageService.GetAllInstalledPackages().Any()) return false; if (_contentService.GetRootContent().Any()) diff --git a/src/Umbraco.Web/Install/InstallSteps/StarterKitInstallStep.cs b/src/Umbraco.Web/Install/InstallSteps/StarterKitInstallStep.cs index 8bec4ca199..0e189c5a6d 100644 --- a/src/Umbraco.Web/Install/InstallSteps/StarterKitInstallStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/StarterKitInstallStep.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using System.Threading.Tasks; using System.Web; using Umbraco.Web.Composing; using Umbraco.Web.Install.Models; @@ -20,7 +21,7 @@ namespace Umbraco.Web.Install.InstallSteps } - public override InstallSetupResult Execute(object model) + public override Task ExecuteAsync(object model) { var installSteps = InstallStatusTracker.GetStatus().ToArray(); var previousStep = installSteps.Single(x => x.Name == "StarterKitDownload"); @@ -31,7 +32,7 @@ namespace Umbraco.Web.Install.InstallSteps Current.RestartAppPool(_httContext); - return null; + return Task.FromResult(null); } private void InstallBusinessLogic(int manifestId, string packageFile) diff --git a/src/Umbraco.Web/Install/InstallSteps/UpgradeStep.cs b/src/Umbraco.Web/Install/InstallSteps/UpgradeStep.cs index 7ed3de6471..5f44555092 100644 --- a/src/Umbraco.Web/Install/InstallSteps/UpgradeStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/UpgradeStep.cs @@ -1,4 +1,5 @@ using System; +using System.Threading.Tasks; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Web.Install.Models; @@ -13,7 +14,7 @@ namespace Umbraco.Web.Install.InstallSteps { public override bool RequiresExecution(object model) => true; - public override InstallSetupResult Execute(object model) => null; + public override Task ExecuteAsync(object model) => Task.FromResult(null); public override object ViewModel { diff --git a/src/Umbraco.Web/Install/Models/InstallSetupStep.cs b/src/Umbraco.Web/Install/Models/InstallSetupStep.cs index 36cf838a82..3b017368f9 100644 --- a/src/Umbraco.Web/Install/Models/InstallSetupStep.cs +++ b/src/Umbraco.Web/Install/Models/InstallSetupStep.cs @@ -1,5 +1,6 @@ using System; using System.Runtime.Serialization; +using System.Threading.Tasks; using Umbraco.Core; namespace Umbraco.Web.Install.Models @@ -14,17 +15,14 @@ namespace Umbraco.Web.Install.Models /// Defines the step model type on the server side so we can bind it /// [IgnoreDataMember] - public override Type StepType - { - get { return typeof(T); } - } + public override Type StepType => typeof(T); /// /// The step execution method /// /// /// - public abstract InstallSetupResult Execute(T model); + public abstract Task ExecuteAsync(T model); /// /// Determines if this step needs to execute based on the current state of the application and/or install process @@ -86,10 +84,6 @@ namespace Umbraco.Web.Install.Models public abstract Type StepType { get; } [IgnoreDataMember] - public bool HasUIElement - { - get { return View.IsNullOrWhiteSpace() == false; } - } - + public bool HasUIElement => View.IsNullOrWhiteSpace() == false; } } diff --git a/src/Umbraco.Web/Models/LocalPackageInstallModel.cs b/src/Umbraco.Web/Models/LocalPackageInstallModel.cs index 06216597cb..64ce51f539 100644 --- a/src/Umbraco.Web/Models/LocalPackageInstallModel.cs +++ b/src/Umbraco.Web/Models/LocalPackageInstallModel.cs @@ -55,9 +55,6 @@ namespace Umbraco.Web.Models [DataMember(Name = "containsMacroConflict")] public bool ContainsMacroConflict { get; set; } - [DataMember(Name = "containsBinaryFileErrors")] - public bool ContainsBinaryFileErrors { get; set; } - [DataMember(Name = "conflictingTemplateAliases")] public IDictionary ConflictingTemplateAliases { get; set; } diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 3d11684c8a..1bd2860781 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -1134,14 +1134,9 @@ - - - - - diff --git a/src/Umbraco.Web/_Legacy/PackageActions/PackageHelper.cs b/src/Umbraco.Web/_Legacy/PackageActions/PackageHelper.cs deleted file mode 100644 index 55171c2643..0000000000 --- a/src/Umbraco.Web/_Legacy/PackageActions/PackageHelper.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System; -using System.Xml; -using Umbraco.Core; -using Umbraco.Core.IO; -using Umbraco.Core.Models; -using Umbraco.Core.Xml; - -namespace Umbraco.Web._Legacy.PackageActions -{ - internal class PackageHelper - { - //Helper method to replace umbraco tags that breaks the xml format.. - public static string ParseToValidXml(ITemplate templateObj, ref bool hasAspNetContentBeginning, string template, bool toValid) - { - string retVal = template; - if (toValid) - { - // test for asp:content as the first part of the design - if (retVal.StartsWith("") + 1); - retVal = retVal.Substring(0, retVal.Length - 14); - } - //shorten empty macro tags.. - retVal = retVal.Replace(">", " />"); - retVal = retVal.Replace(">", " />"); - - retVal = retVal.Replace("", ""); - retVal = retVal.Replace("", ""); - retVal = retVal.Replace("", ""); - - // add asp content element - if (hasAspNetContentBeginning) - { - retVal = MasterPageHelper.GetMasterContentElement(templateObj/*templateObj.MasterTemplate*/) + retVal + ""; - } - } - - return retVal; - } - - public static XmlNode ParseStringToXmlNode(string value) - { - XmlDocument doc = new XmlDocument(); - XmlNode node = XmlHelper.AddTextNode(doc, "error", ""); - - try - { - doc.LoadXml(value); - return doc.SelectSingleNode("."); - } - catch - { - return node; - } - - } - } -} diff --git a/src/Umbraco.Web/_Legacy/PackageActions/addApplication.cs b/src/Umbraco.Web/_Legacy/PackageActions/addApplication.cs index 09c6df23c4..75614f68aa 100644 --- a/src/Umbraco.Web/_Legacy/PackageActions/addApplication.cs +++ b/src/Umbraco.Web/_Legacy/PackageActions/addApplication.cs @@ -1,5 +1,6 @@ using System; using System.Xml; +using System.Xml.Linq; using Umbraco.Core; using Umbraco.Core._Legacy.PackageActions; using Umbraco.Web.Composing; @@ -24,20 +25,20 @@ namespace Umbraco.Web._Legacy.PackageActions /// /// /// true if successfull - public bool Execute(string packageName, XmlNode xmlData) + public bool Execute(string packageName, XElement xmlData) { - string name = xmlData.Attributes["appName"].Value; - string alias = xmlData.Attributes["appAlias"].Value; - string icon = xmlData.Attributes["appIcon"].Value; + string name = xmlData.AttributeValue("appName"); + string alias = xmlData.AttributeValue("appAlias"); + string icon = xmlData.AttributeValue("appIcon"); Current.Services.SectionService.MakeNew(name, alias, icon); return true; } - public bool Undo(string packageName, XmlNode xmlData) + public bool Undo(string packageName, XElement xmlData) { - string alias = xmlData.Attributes["appAlias"].Value; + string alias = xmlData.AttributeValue("appAlias"); var section = Current.Services.SectionService.GetByAlias(alias); if (section != null) { @@ -55,11 +56,6 @@ namespace Umbraco.Web._Legacy.PackageActions } #endregion - - public XmlNode SampleXml() - { - throw new NotImplementedException(); - } - + } } diff --git a/src/Umbraco.Web/_Legacy/PackageActions/addDashboardSection.cs b/src/Umbraco.Web/_Legacy/PackageActions/addDashboardSection.cs index 9b3bc5829b..1e2e396d2c 100644 --- a/src/Umbraco.Web/_Legacy/PackageActions/addDashboardSection.cs +++ b/src/Umbraco.Web/_Legacy/PackageActions/addDashboardSection.cs @@ -1,5 +1,8 @@ using System; +using System.Linq; using System.Xml; +using System.Xml.Linq; +using System.Xml.XPath; using Umbraco.Core; using Umbraco.Core.IO; using Umbraco.Core.Xml; @@ -39,30 +42,23 @@ namespace Umbraco.Web._Legacy.PackageActions /// /// /// - public bool Execute(string packageName, XmlNode xmlData) + public bool Execute(string packageName, XElement xmlData) { //this will need a complete section node to work... - if (xmlData.HasChildNodes) + if (xmlData.HasElements) { - string sectionAlias = xmlData.Attributes["dashboardAlias"].Value; + string sectionAlias = xmlData.AttributeValue("dashboardAlias"); string dbConfig = SystemFiles.DashboardConfig; - XmlNode section = xmlData.SelectSingleNode("./section"); - XmlDocument dashboardFile = XmlHelper.OpenAsXmlDocument(dbConfig); + var section = xmlData.Element("section"); + var dashboardFile = XDocument.Load(IOHelper.MapPath(dbConfig)); //don't continue if it already exists - var found = dashboardFile.SelectNodes("//section[@alias='" + sectionAlias + "']"); - if (found == null || found.Count <= 0) + var found = dashboardFile.XPathSelectElements("//section[@alias='" + sectionAlias + "']"); + if (!found.Any()) { - - XmlNode importedSection = dashboardFile.ImportNode(section, true); - - XmlAttribute alias = XmlHelper.AddAttribute(dashboardFile, "alias", sectionAlias); - importedSection.Attributes.Append(alias); - - dashboardFile.DocumentElement.AppendChild(importedSection); - + dashboardFile.Root.Add(section); dashboardFile.Save(IOHelper.MapPath(dbConfig)); } @@ -78,19 +74,18 @@ namespace Umbraco.Web._Legacy.PackageActions return "addDashboardSection"; } - public bool Undo(string packageName, XmlNode xmlData) + public bool Undo(string packageName, XElement xmlData) { - string sectionAlias = xmlData.Attributes["dashboardAlias"].Value; + string sectionAlias = xmlData.AttributeValue("dashboardAlias"); string dbConfig = SystemFiles.DashboardConfig; - XmlDocument dashboardFile = XmlHelper.OpenAsXmlDocument(dbConfig); + var dashboardFile = XDocument.Load(IOHelper.MapPath(dbConfig)); - XmlNode section = dashboardFile.SelectSingleNode("//section [@alias = '" + sectionAlias + "']"); + var section = dashboardFile.XPathSelectElement("//section [@alias = '" + sectionAlias + "']"); if (section != null) { - - dashboardFile.SelectSingleNode("/dashBoard").RemoveChild(section); + section.Remove(); dashboardFile.Save(IOHelper.MapPath(dbConfig)); } @@ -98,11 +93,6 @@ namespace Umbraco.Web._Legacy.PackageActions } #endregion - - public XmlNode SampleXml() - { - throw new NotImplementedException(); - } - + } } diff --git a/src/Umbraco.Web/_Legacy/PackageActions/addProxyFeedHost.cs b/src/Umbraco.Web/_Legacy/PackageActions/addProxyFeedHost.cs index ac02bc0c33..bcd7d7c52f 100644 --- a/src/Umbraco.Web/_Legacy/PackageActions/addProxyFeedHost.cs +++ b/src/Umbraco.Web/_Legacy/PackageActions/addProxyFeedHost.cs @@ -1,4 +1,5 @@ using System.Xml; +using System.Xml.Linq; using Umbraco.Core; using Umbraco.Core.IO; using Umbraco.Core.Xml; @@ -10,42 +11,32 @@ namespace Umbraco.Web._Legacy.PackageActions { #region IPackageAction Members - public bool Execute(string packageName, XmlNode xmlData) + public bool Execute(string packageName, XElement xmlData) { - var hostname = xmlData.Attributes["host"].Value; + var hostname = xmlData.AttributeValue("host"); if (string.IsNullOrEmpty(hostname)) return false; - var xdoc = XmlHelper.OpenAsXmlDocument(SystemFiles.FeedProxyConfig); + var xdoc = XDocument.Load(IOHelper.MapPath(SystemFiles.FeedProxyConfig)); - xdoc.PreserveWhitespace = true; + var insert = true; - var xn = xdoc.SelectSingleNode("//feedProxy"); - if (xn != null) + if (xdoc.Root.HasElements) { - var insert = true; - - if (xn.HasChildNodes) + foreach (var node in xdoc.Root.Elements("allow")) { - foreach (XmlNode node in xn.SelectNodes("//allow")) - { - if (node.Attributes["host"] != null && node.Attributes["host"].Value == hostname) - insert = false; - } - } - - if (insert) - { - var newHostname = XmlHelper.AddTextNode(xdoc, "allow", string.Empty); - newHostname.Attributes.Append(XmlHelper.AddAttribute(xdoc, "host", hostname)); - xn.AppendChild(newHostname); - - xdoc.Save(IOHelper.MapPath(SystemFiles.FeedProxyConfig)); - - return true; + if (node.AttributeValue("host") != null && node.AttributeValue("host") == hostname) + insert = false; } } + if (insert) + { + xdoc.Root.Add(new XElement("allow", new XAttribute("host", hostname))); + xdoc.Save(IOHelper.MapPath(SystemFiles.FeedProxyConfig)); + + return true; + } return false; } @@ -54,47 +45,37 @@ namespace Umbraco.Web._Legacy.PackageActions return "addProxyFeedHost"; } - public bool Undo(string packageName, XmlNode xmlData) + public bool Undo(string packageName, XElement xmlData) { - var hostname = xmlData.Attributes["host"].Value; + var hostname = xmlData.AttributeValue("host"); if (string.IsNullOrEmpty(hostname)) return false; - var xdoc = XmlHelper.OpenAsXmlDocument(SystemFiles.FeedProxyConfig); - xdoc.PreserveWhitespace = true; + var xdoc = XDocument.Load(IOHelper.MapPath(SystemFiles.FeedProxyConfig)); - var xn = xdoc.SelectSingleNode("//feedProxy"); - if (xn != null) + bool inserted = false; + if (xdoc.Root.HasElements) { - bool inserted = false; - if (xn.HasChildNodes) + foreach (var node in xdoc.Root.Elements("allow")) { - foreach (XmlNode node in xn.SelectNodes("//allow")) + if (node.AttributeValue("host") != null && node.AttributeValue("host") == hostname) { - if (node.Attributes["host"] != null && node.Attributes["host"].Value == hostname) - { - xn.RemoveChild(node); - inserted = true; - } + node.Remove(); + inserted = true; } } + } - if (inserted) - { - xdoc.Save(IOHelper.MapPath(SystemFiles.FeedProxyConfig)); - return true; - } + if (inserted) + { + xdoc.Save(IOHelper.MapPath(SystemFiles.FeedProxyConfig)); + return true; } return false; } #endregion - - public XmlNode SampleXml() - { - string sample = ""; - return PackageHelper.ParseStringToXmlNode(sample); - } + } } diff --git a/src/Umbraco.Web/_Legacy/PackageActions/addStringToHtmlElement.cs b/src/Umbraco.Web/_Legacy/PackageActions/addStringToHtmlElement.cs deleted file mode 100644 index 56ebb76980..0000000000 --- a/src/Umbraco.Web/_Legacy/PackageActions/addStringToHtmlElement.cs +++ /dev/null @@ -1,202 +0,0 @@ -using System; -using System.Xml; -using Umbraco.Core; -using Umbraco.Core.Configuration; -using Umbraco.Core.IO; -using Umbraco.Core.Logging; -using Umbraco.Core.Models; -using Umbraco.Core.Xml; -using Umbraco.Core._Legacy.PackageActions; -using Umbraco.Web.Composing; - -namespace Umbraco.Web._Legacy.PackageActions -{ - /// - /// This class implements the IPackageAction Interface, used to execute code when packages are installed. - /// All IPackageActions only takes a PackageName and a XmlNode as input, and executes based on the data in the xmlnode. - /// addStringToHtmlElement adds a string to specific HTML element in a specific template, and can either append or prepend it. - /// It uses the action xml node to do this, exemple action xml node: - /// - /// The above will add the string "hello world!" to the first html element with the id "newsSection" in the template "news" - /// - public class addStringToHtmlElement : IPackageAction - { - #region IPackageAction Members - - /// - /// Executes the specified package action. - /// - /// Name of the package. - /// The XML data. - /// - /// - /// - /// True if executed successfully - public bool Execute(string packageName, XmlNode xmlData) - { - - - string templateAlias = xmlData.Attributes["templateAlias"].Value; - string htmlElementId = xmlData.Attributes["htmlElementId"].Value; - string position = xmlData.Attributes["position"].Value; - string value = XmlHelper.GetNodeValue(xmlData); - var tmp = Current.Services.FileService.GetTemplate(templateAlias); - - value = MasterPageHelper.EnsureMasterPageSyntax(templateAlias, value); - - _addStringToHtmlElement(tmp, value, htmlElementId, position); - - return true; - } - - - /// - /// Undoes the addStringToHtml Execute() method, by removing the same string from the same template. - /// - /// Name of the package. - /// The XML data. - /// - public bool Undo(string packageName, XmlNode xmlData) - { - string templateAlias = xmlData.Attributes["templateAlias"].Value; - string htmlElementId = xmlData.Attributes["htmlElementId"].Value; - string value = XmlHelper.GetNodeValue(xmlData); - var tmp = Current.Services.FileService.GetTemplate(templateAlias); - - value = MasterPageHelper.EnsureMasterPageSyntax(templateAlias, value); - - _removeStringFromHtmlElement(tmp, value, htmlElementId); - return true; - } - - /// - /// Action alias. - /// - /// - public string Alias() - { - return "addStringToHtmlElement"; - } - - private void _addStringToHtmlElement(ITemplate tmp, string value, string htmlElementId, string position) - { - bool hasAspNetContentBeginning = false; - string design = ""; - string directive = ""; - - if (tmp != null) - { - try - { - XmlDocument templateXml = new XmlDocument(); - templateXml.PreserveWhitespace = true; - - //Make sure that directive is remove before hacked non html4 compatiple replacement action... - design = tmp.Content; - - - splitDesignAndDirective(ref design, ref directive); - - //making sure that the template xml has a root node... - if (string.IsNullOrWhiteSpace(tmp.MasterTemplateAlias) == false) - templateXml.LoadXml(PackageHelper.ParseToValidXml(tmp, ref hasAspNetContentBeginning, "" + design + "", true)); - else - templateXml.LoadXml(PackageHelper.ParseToValidXml(tmp, ref hasAspNetContentBeginning, design, true)); - - XmlNode xmlElement = templateXml.SelectSingleNode("//* [@id = '" + htmlElementId + "']"); - - if (xmlElement != null) - { - - if (position == "beginning") - { - xmlElement.InnerXml = "\n" + PackageHelper.ParseToValidXml(tmp, ref hasAspNetContentBeginning, value, true) + "\n" + xmlElement.InnerXml; - } - else - { - xmlElement.InnerXml = xmlElement.InnerXml + "\n" + PackageHelper.ParseToValidXml(tmp, ref hasAspNetContentBeginning, value, true) + "\n"; - } - } - - tmp.Content = directive + "\n" + PackageHelper.ParseToValidXml(tmp, ref hasAspNetContentBeginning, templateXml.OuterXml, false); - Current.Services.FileService.SaveTemplate(tmp); - } - catch (Exception ex) - { - Current.Logger.Error(ex, "An error occurred"); - } - } - else - { - Current.Logger.Debug("template not found"); - } - } - - private void _removeStringFromHtmlElement(ITemplate tmp, string value, string htmlElementId) - { - bool hasAspNetContentBeginning = false; - string design = ""; - string directive = ""; - - - if (tmp != null) - { - try - { - XmlDocument templateXml = new XmlDocument(); - templateXml.PreserveWhitespace = true; - - //Make sure that directive is remove before hacked non html4 compatiple replacement action... - design = tmp.Content; - splitDesignAndDirective(ref design, ref directive); - - //making sure that the template xml has a root node... - if (string.IsNullOrWhiteSpace(tmp.MasterTemplateAlias) == false) - templateXml.LoadXml(PackageHelper.ParseToValidXml(tmp, ref hasAspNetContentBeginning, "" + design + "", true)); - else - templateXml.LoadXml(PackageHelper.ParseToValidXml(tmp, ref hasAspNetContentBeginning, design, true)); - - XmlNode xmlElement = templateXml.SelectSingleNode("//* [@id = '" + htmlElementId + "']"); - - - - if (xmlElement != null) - { - string repValue = PackageHelper.ParseToValidXml(tmp, ref hasAspNetContentBeginning, value, true); - xmlElement.InnerXml = xmlElement.InnerXml.Replace(repValue, ""); - } - - tmp.Content = directive + "\n" + PackageHelper.ParseToValidXml(tmp, ref hasAspNetContentBeginning, templateXml.OuterXml, false); - Current.Services.FileService.SaveTemplate(tmp); - } - catch (Exception ex) - { - Current.Logger.Error(ex, "An error occurred"); - } - } - else - { - Current.Logger.Debug("template not found"); - } - } - - - - private void splitDesignAndDirective(ref string design, ref string directive) - { - if (design.StartsWith("<%@")) - { - directive = design.Substring(0, design.IndexOf("%>") + 2).Trim(Environment.NewLine.ToCharArray()); - design = design.Substring(design.IndexOf("%>") + 3).Trim(Environment.NewLine.ToCharArray()); - } - } - - #endregion - - public XmlNode SampleXml() - { - throw new NotImplementedException(); - } - - } -} diff --git a/src/Umbraco.Web/_Legacy/PackageActions/allowDoctype.cs b/src/Umbraco.Web/_Legacy/PackageActions/allowDoctype.cs index 146925b85f..2ed16e3842 100644 --- a/src/Umbraco.Web/_Legacy/PackageActions/allowDoctype.cs +++ b/src/Umbraco.Web/_Legacy/PackageActions/allowDoctype.cs @@ -2,6 +2,8 @@ using System.Collections; using System.Linq; using System.Xml; +using System.Xml.Linq; +using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core._Legacy.PackageActions; using Umbraco.Web.Composing; @@ -26,10 +28,10 @@ namespace Umbraco.Web._Legacy.PackageActions /// /// /// Returns true on success - public bool Execute(string packageName, XmlNode xmlData) + public bool Execute(string packageName, XElement xmlData) { - string doctypeName = xmlData.Attributes["documentTypeAlias"].Value; - string parentDoctypeName = xmlData.Attributes["parentDocumentTypeAlias"].Value; + string doctypeName = xmlData.AttributeValue("documentTypeAlias"); + string parentDoctypeName = xmlData.AttributeValue("parentDocumentTypeAlias"); //global::umbraco.cms.businesslogic.ContentType ct = global::umbraco.cms.businesslogic.ContentType.GetByAlias(doctypeName); //global::umbraco.cms.businesslogic.ContentType parentct = global::umbraco.cms.businesslogic.ContentType.GetByAlias(parentDoctypeName); @@ -73,7 +75,7 @@ namespace Umbraco.Web._Legacy.PackageActions /// Name of the package. /// The XML data. /// - public bool Undo(string packageName, XmlNode xmlData) + public bool Undo(string packageName, XElement xmlData) { return true; } @@ -88,11 +90,6 @@ namespace Umbraco.Web._Legacy.PackageActions } #endregion - - public XmlNode SampleXml() - { - throw new NotImplementedException(); - } - + } } diff --git a/src/Umbraco.Web/_Legacy/PackageActions/publishRootDocument.cs b/src/Umbraco.Web/_Legacy/PackageActions/publishRootDocument.cs index 32147342f6..f4fe17e999 100644 --- a/src/Umbraco.Web/_Legacy/PackageActions/publishRootDocument.cs +++ b/src/Umbraco.Web/_Legacy/PackageActions/publishRootDocument.cs @@ -1,5 +1,6 @@ using System; using System.Xml; +using System.Xml.Linq; using Umbraco.Core; using Umbraco.Core._Legacy.PackageActions; using Umbraco.Web.Composing; @@ -23,17 +24,17 @@ namespace Umbraco.Web._Legacy.PackageActions /// /// /// True if executed succesfully - public bool Execute(string packageName, XmlNode xmlData) + public bool Execute(string packageName, XElement xmlData) { - string documentName = xmlData.Attributes["documentName"].Value; + string documentName = xmlData.AttributeValue("documentName"); //global::umbraco.cms.businesslogic.web.Document[] rootDocs = global::umbraco.cms.businesslogic.web.Document.GetRootDocuments(); var rootDocs = Current.Services.ContentService.GetRootContent(); foreach (var rootDoc in rootDocs) { - if (rootDoc.Name.Trim() == documentName.Trim() && rootDoc != null && rootDoc.ContentType != null) + if (rootDoc.Name.Trim() == documentName.Trim() && rootDoc.ContentType != null) { // fixme variants? Current.Services.ContentService.SaveAndPublishBranch(rootDoc, true); @@ -50,7 +51,7 @@ namespace Umbraco.Web._Legacy.PackageActions /// Name of the package. /// The XML data. /// - public bool Undo(string packageName, XmlNode xmlData) + public bool Undo(string packageName, XElement xmlData) { return true; } @@ -64,11 +65,6 @@ namespace Umbraco.Web._Legacy.PackageActions return "publishRootDocument"; } #endregion - - public XmlNode SampleXml() - { - throw new NotImplementedException(); - } - + } } diff --git a/src/Umbraco.Web/_Legacy/PackageActions/removeStringFromTemplate.cs b/src/Umbraco.Web/_Legacy/PackageActions/removeStringFromTemplate.cs deleted file mode 100644 index fd2f40178b..0000000000 --- a/src/Umbraco.Web/_Legacy/PackageActions/removeStringFromTemplate.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Xml; -using Umbraco.Core._Legacy.PackageActions; - -namespace Umbraco.Web._Legacy.PackageActions -{ - public class removeStringFromTemplate : IPackageAction - { - #region IPackageAction Members - - public bool Execute(string packageName, XmlNode xmlData) - { - addStringToHtmlElement ast = new addStringToHtmlElement(); - return ast.Undo(packageName, xmlData); - } - - public string Alias() - { - return "removeStringFromHtmlElement"; - } - - public bool Undo(string packageName, XmlNode xmlData) - { - return true; - } - - public XmlNode SampleXml() - { - throw new NotImplementedException(); - } - - #endregion - } -} diff --git a/src/Umbraco.Web/_Legacy/Packager/Installer.cs b/src/Umbraco.Web/_Legacy/Packager/Installer.cs index 15a7839227..286f41f61a 100644 --- a/src/Umbraco.Web/_Legacy/Packager/Installer.cs +++ b/src/Umbraco.Web/_Legacy/Packager/Installer.cs @@ -6,6 +6,8 @@ using System.IO; using System.Linq; using System.Net; using System.Xml; +using System.Xml.Linq; +using System.Xml.XPath; using ICSharpCode.SharpZipLib.Zip; using Umbraco.Core; using Umbraco.Core.Composing; @@ -16,8 +18,6 @@ using Umbraco.Core.Models; using Umbraco.Core.Models.Packaging; using Umbraco.Core.Packaging; using Umbraco.Core.Services.Implement; -using Umbraco.Core.Xml; -using Umbraco.Web._Legacy.Packager.PackageInstance; using File = System.IO.File; namespace Umbraco.Web._Legacy.Packager @@ -66,16 +66,6 @@ namespace Umbraco.Web._Legacy.Packager public bool ContainsTemplateConflicts { get; private set; } public IDictionary ConflictingTemplateAliases => _conflictingTemplateAliases; - /// - /// Indicates that the package contains assembly reference errors - /// - public bool ContainsBinaryFileErrors { get; private set; } - - /// - /// List each assembly reference error - /// - public List BinaryFileErrors { get; } = new List(); - public bool ContainsStyleSheeConflicts { get; private set; } public IDictionary ConflictingStyleSheetNames => _conflictingStyleSheetNames; @@ -88,9 +78,9 @@ namespace Umbraco.Web._Legacy.Packager public string IconUrl { get; private set; } /// - /// The xmldocument, describing the contents of a package. + /// The xml of the compiled package /// - public XmlDocument Config { get; private set; } + public XDocument Config { get; private set; } /// /// Constructor @@ -108,7 +98,6 @@ namespace Umbraco.Web._Legacy.Packager private void Initialize() { - ContainsBinaryFileErrors = false; ContainsTemplateConflicts = false; ContainsUnsecureFiles = false; ContainsMacroConflict = false; @@ -136,7 +125,6 @@ namespace Umbraco.Web._Legacy.Packager /// public Installer(string name, string version, string url, string license, string licenseUrl, string author, string authorUrl, int requirementsMajor, int requirementsMinor, int requirementsPatch, string readme, string control, RequirementsType requirementsType, string iconUrl) { - ContainsBinaryFileErrors = false; ContainsTemplateConflicts = false; ContainsUnsecureFiles = false; ContainsMacroConflict = false; @@ -209,54 +197,46 @@ namespace Umbraco.Web._Legacy.Packager return Import(inputFile, true); } - public int CreateManifest(string tempDir, Guid guid, string repoGuid) + public int CreateManifest(Guid guid) { //This is the new improved install rutine, which chops up the process into 3 steps, creating the manifest, moving files, and finally handling umb objects - var packName = XmlHelper.GetNodeValue(Config.DocumentElement.SelectSingleNode("/umbPackage/info/package/name")); - var packAuthor = XmlHelper.GetNodeValue(Config.DocumentElement.SelectSingleNode("/umbPackage/info/author/name")); - var packAuthorUrl = XmlHelper.GetNodeValue(Config.DocumentElement.SelectSingleNode("/umbPackage/info/author/website")); - var packVersion = XmlHelper.GetNodeValue(Config.DocumentElement.SelectSingleNode("/umbPackage/info/package/version")); - var packReadme = XmlHelper.GetNodeValue(Config.DocumentElement.SelectSingleNode("/umbPackage/info/readme")); - var packLicense = XmlHelper.GetNodeValue(Config.DocumentElement.SelectSingleNode("/umbPackage/info/package/license ")); - var packUrl = XmlHelper.GetNodeValue(Config.DocumentElement.SelectSingleNode("/umbPackage/info/package/url ")); - var iconUrl = XmlHelper.GetNodeValue(Config.DocumentElement.SelectSingleNode("/umbPackage/info/package/iconUrl")); - var enableSkins = false; - var skinRepoGuid = ""; + var parser = new CompiledPackageXmlParser(); + var def = parser.ToCompiledPackage(Config); - if (Config.DocumentElement.SelectSingleNode("/umbPackage/enableSkins") != null) + //create a new entry in the installedPackages.config + var installedPackage = new PackageDefinition { - var skinNode = Config.DocumentElement.SelectSingleNode("/umbPackage/enableSkins"); - enableSkins = bool.Parse(XmlHelper.GetNodeValue(skinNode)); - if (skinNode.Attributes["repository"] != null && string.IsNullOrEmpty(skinNode.Attributes["repository"].Value) == false) - skinRepoGuid = skinNode.Attributes["repository"].Value; - } + Author = def.Author, + AuthorUrl = def.AuthorUrl, + Control = def.Control, + IconUrl = def.IconUrl, + License = def.License, + LicenseUrl = def.LicenseUrl, + Name = def.Name, + Readme = def.Readme, + UmbracoVersion = def.UmbracoVersion, + Url = def.Url, + Version = def.Version, + PackageId = guid + }; - //Create a new package instance to record all the installed package adds - this is the same format as the created packages has. - //save the package meta data - var insPack = InstalledPackage.MakeNew(packName); - insPack.Data.Author = packAuthor; - insPack.Data.AuthorUrl = packAuthorUrl; - insPack.Data.Version = packVersion; - insPack.Data.Readme = packReadme; - insPack.Data.License = packLicense; - insPack.Data.Url = packUrl; - insPack.Data.IconUrl = iconUrl; + if (!Current.Services.PackagingService.SaveInstalledPackage(installedPackage)) + throw new InvalidOperationException("Could not save package definition"); - insPack.Data.PackageId = guid; //the package unique key. - insPack.Save(); - - return insPack.Data.Id; + return installedPackage.Id; } public void InstallFiles(int packageId, string tempDir) { + var parser = new CompiledPackageXmlParser(); + using (Current.ProfilingLogger.DebugDuration( "Installing package files for package id " + packageId + " into temp folder " + tempDir, "Package file installation complete for package id " + packageId)) { //retrieve the manifest to continue installation - var insPack = InstalledPackage.GetById(packageId); + var insPack = Current.Services.PackagingService.GetInstalledPackageById(packageId); //TODO: Depending on some files, some files should be installed differently. //i.e. if stylsheets should probably be installed via business logic, media items should probably use the media IFileSystem! @@ -265,13 +245,15 @@ namespace Umbraco.Web._Legacy.Packager //string virtualBasePath = System.Web.HttpContext.Current.Request.ApplicationPath; string basePath = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath; + var def = parser.ToCompiledPackage(Config); + try { - foreach (XmlNode n in Config.DocumentElement.SelectNodes("//file")) + foreach (var f in def.Files) { - var destPath = GetFileName(basePath, XmlHelper.GetNodeValue(n.SelectSingleNode("orgPath"))); - var sourceFile = GetFileName(tempDir, XmlHelper.GetNodeValue(n.SelectSingleNode("guid"))); - var destFile = GetFileName(destPath, XmlHelper.GetNodeValue(n.SelectSingleNode("orgName"))); + var destPath = GetFileName(basePath, f.OriginalPath); + var sourceFile = GetFileName(tempDir, f.UniqueFileName); + var destFile = GetFileName(destPath, f.OriginalName); // Create the destination directory if it doesn't exist if (Directory.Exists(destPath) == false) @@ -300,14 +282,14 @@ namespace Umbraco.Web._Legacy.Packager File.Copy(sourceFile, destFile); //PPH log file install - insPack.Data.Files.Add(XmlHelper.GetNodeValue(n.SelectSingleNode("orgPath")) + "/" + XmlHelper.GetNodeValue(n.SelectSingleNode("orgName"))); + insPack.Files.Add(f.OriginalPath.EnsureEndsWith('/') + f.OriginalName); } // Once we're done copying, remove all the files - foreach (XmlNode n in Config.DocumentElement.SelectNodes("//file")) + foreach (var f in def.Files) { - var sourceFile = GetFileName(tempDir, XmlHelper.GetNodeValue(n.SelectSingleNode("guid"))); + var sourceFile = GetFileName(tempDir, f.UniqueFileName); if (File.Exists(sourceFile)) File.Delete(sourceFile); } @@ -323,10 +305,10 @@ namespace Umbraco.Web._Legacy.Packager { Current.Services.AuditService.Add(AuditType.PackagerInstall, _currentUserId, - -1, "Package", string.Format("Package '{0}' installed. Package guid: {1}", insPack.Data.Name, insPack.Data.PackageId)); + -1, "Package", string.Format("Package '{0}' installed. Package guid: {1}", insPack.Name, insPack.PackageId)); } - insPack.Save(); + Current.Services.PackagingService.SaveInstalledPackage(insPack); } } @@ -336,11 +318,11 @@ namespace Umbraco.Web._Legacy.Packager "Installing business logic for package id " + packageId + " into temp folder " + tempDir, "Package business logic installation complete for package id " + packageId)) { - InstalledPackage insPack; + PackageDefinition insPack; try { //retrieve the manifest to continue installation - insPack = InstalledPackage.GetById(packageId); + insPack = Current.Services.PackagingService.GetInstalledPackageById(packageId); //bool saveNeeded = false; // Get current user, with a fallback @@ -348,9 +330,7 @@ namespace Umbraco.Web._Legacy.Packager //TODO: Get rid of this entire class! Until then all packages will be installed by the admin user - - //Xml as XElement which is used with the new PackagingService - var rootElement = Config.DocumentElement.GetXElement(); + var rootElement = Config.Root; var packagingService = Current.Services.PackagingService; //Perhaps it would have been a good idea to put the following into methods eh?!? @@ -362,7 +342,7 @@ namespace Umbraco.Web._Legacy.Packager var dataTypeDefinitions = packagingService.ImportDataTypeDefinitions(dataTypeElement, currentUser.Id); foreach (var dataTypeDefinition in dataTypeDefinitions) { - insPack.Data.DataTypes.Add(dataTypeDefinition.Id.ToString(CultureInfo.InvariantCulture)); + insPack.DataTypes.Add(dataTypeDefinition.Id.ToString(CultureInfo.InvariantCulture)); } } #endregion @@ -373,7 +353,7 @@ namespace Umbraco.Web._Legacy.Packager { var insertedLanguages = packagingService.ImportLanguages(languageItemsElement); foreach(var x in insertedLanguages.Select(l => l.Id.ToString(CultureInfo.InvariantCulture))) - insPack.Data.Languages.Add(x); + insPack.Languages.Add(x); } #endregion @@ -384,7 +364,7 @@ namespace Umbraco.Web._Legacy.Packager { var insertedDictionaryItems = packagingService.ImportDictionaryItems(dictionaryItemsElement); foreach (var x in insertedDictionaryItems.Select(d => d.Id.ToString(CultureInfo.InvariantCulture))) - insPack.Data.DictionaryItems.Add(x); + insPack.DictionaryItems.Add(x); } #endregion @@ -394,7 +374,7 @@ namespace Umbraco.Web._Legacy.Packager { var insertedMacros = packagingService.ImportMacros(macroItemsElement); foreach (var x in insertedMacros.Select(m => m.Id.ToString(CultureInfo.InvariantCulture))) - insPack.Data.Macros.Add(x); + insPack.Macros.Add(x); } #endregion @@ -406,7 +386,7 @@ namespace Umbraco.Web._Legacy.Packager var templates = packagingService.ImportTemplates(templateElement, currentUser.Id); foreach (var template in templates) { - insPack.Data.Templates.Add(template.Id.ToString(CultureInfo.InvariantCulture)); + insPack.Templates.Add(template.Id.ToString(CultureInfo.InvariantCulture)); } } #endregion @@ -423,32 +403,35 @@ namespace Umbraco.Web._Legacy.Packager var contentTypes = packagingService.ImportContentTypes(docTypeElement, currentUser.Id); foreach (var contentType in contentTypes) { - insPack.Data.DocumentTypes.Add(contentType.Id.ToString(CultureInfo.InvariantCulture)); + insPack.DocumentTypes.Add(contentType.Id.ToString(CultureInfo.InvariantCulture)); //saveNeeded = true; } } #endregion #region Stylesheets - foreach (XmlNode n in Config.DocumentElement.SelectNodes("Stylesheets/Stylesheet")) + foreach (var n in Config.Root.XPathSelectElements("Stylesheets/Stylesheet")) { - //StyleSheet s = StyleSheet.Import(n, currentUser); + string stylesheetName = n.Element("Name")?.Value; + if (stylesheetName.IsNullOrWhiteSpace()) continue; - - string stylesheetName = XmlHelper.GetNodeValue(n.SelectSingleNode("Name")); - //StyleSheet s = GetByName(stylesheetName); var s = Current.Services.FileService.GetStylesheetByName(stylesheetName); if (s == null) { - s = new Stylesheet(XmlHelper.GetNodeValue(n.SelectSingleNode("FileName"))) { Content = XmlHelper.GetNodeValue(n.SelectSingleNode("Content")) }; + var fileName = n.Element("FileName")?.Value; + if (fileName == null) continue; + var content = n.Element("Content")?.Value; + if (content == null) continue; + + s = new Stylesheet(fileName) { Content = content }; Current.Services.FileService.SaveStylesheet(s); } - foreach (XmlNode prop in n.SelectNodes("Properties/Property")) + foreach (var prop in n.XPathSelectElements("Properties/Property")) { - string alias = XmlHelper.GetNodeValue(prop.SelectSingleNode("Alias")); + string alias = prop.Element("Alias")?.Value; var sp = s.Properties.SingleOrDefault(p => p != null && p.Alias == alias); - string name = XmlHelper.GetNodeValue(prop.SelectSingleNode("Name")); + string name = prop.Element("Name")?.Value; if (sp == null) { //sp = StylesheetProperty.MakeNew( @@ -472,7 +455,7 @@ namespace Umbraco.Web._Legacy.Packager } } sp.Alias = alias; - sp.Value = XmlHelper.GetNodeValue(prop.SelectSingleNode("Value")); + sp.Value = prop.Element("Value")?.Value; } //s.saveCssToFile(); Current.Services.FileService.SaveStylesheet(s); @@ -480,7 +463,7 @@ namespace Umbraco.Web._Legacy.Packager - insPack.Data.Stylesheets.Add(s.Id.ToString(CultureInfo.InvariantCulture)); + insPack.Stylesheets.Add(s.Id.ToString(CultureInfo.InvariantCulture)); //saveNeeded = true; } @@ -493,33 +476,34 @@ namespace Umbraco.Web._Legacy.Packager { var content = packagingService.ImportContent(documentElement, -1, currentUser.Id); var firstContentItem = content.First(); - insPack.Data.ContentNodeId = firstContentItem.Id.ToString(CultureInfo.InvariantCulture); + insPack.ContentNodeId = firstContentItem.Id.ToString(CultureInfo.InvariantCulture); } #endregion #region Package Actions - foreach (XmlNode n in Config.DocumentElement.SelectNodes("Actions/Action")) + foreach (var n in Config.Root.XPathSelectElements("Actions/Action")) { - if (n.Attributes["undo"] == null || n.Attributes["undo"].Value == "true") + var undo = n.AttributeValue("undo"); + if (undo == null || undo == "true") { - insPack.Data.Actions += n.OuterXml; + insPack.Actions += n.ToString(); } //Run the actions tagged only for 'install' + var runat = n.AttributeValue("runat"); - if (n.Attributes["runat"] != null && n.Attributes["runat"].Value == "install") + if (runat != null && runat == "install") { - var alias = n.Attributes["alias"] != null ? n.Attributes["alias"].Value : ""; - + var alias = n.AttributeValue("alias"); if (alias.IsNullOrWhiteSpace() == false) { - Current.PackageActionRunner.RunPackageAction(insPack.Data.Name, alias, n); + Current.PackageActionRunner.RunPackageAction(insPack.Name, alias, n); } } } #endregion - insPack.Save(); + Current.Services.PackagingService.SaveInstalledPackage(insPack); } catch (Exception ex) { @@ -527,7 +511,6 @@ namespace Umbraco.Web._Legacy.Packager throw; } - OnPackageBusinessLogicInstalled(insPack); OnPackageInstalled(insPack); } } @@ -551,40 +534,35 @@ namespace Umbraco.Web._Legacy.Packager /// The folder to which the contents of the package is extracted public void LoadConfig(string tempDir) { - Config = new XmlDocument(); - Config.Load(tempDir + Path.DirectorySeparatorChar + "package.xml"); + Config = XDocument.Load(tempDir + Path.DirectorySeparatorChar + "package.xml"); - Name = Config.DocumentElement.SelectSingleNode("/umbPackage/info/package/name").FirstChild.Value; - Version = Config.DocumentElement.SelectSingleNode("/umbPackage/info/package/version").FirstChild.Value; - Url = Config.DocumentElement.SelectSingleNode("/umbPackage/info/package/url").FirstChild.Value; - License = Config.DocumentElement.SelectSingleNode("/umbPackage/info/package/license").FirstChild.Value; - LicenseUrl = Config.DocumentElement.SelectSingleNode("/umbPackage/info/package/license").Attributes.GetNamedItem("url").Value; + var parser = new CompiledPackageXmlParser(); + var def = parser.ToCompiledPackage(Config); - RequirementsMajor = int.Parse(Config.DocumentElement.SelectSingleNode("/umbPackage/info/package/requirements/major").FirstChild.Value); - RequirementsMinor = int.Parse(Config.DocumentElement.SelectSingleNode("/umbPackage/info/package/requirements/minor").FirstChild.Value); - RequirementsPatch = int.Parse(Config.DocumentElement.SelectSingleNode("/umbPackage/info/package/requirements/patch").FirstChild.Value); + Name = def.Name; + Version = def.Version; + Url = def.Url; + License = def.License; + LicenseUrl = def.LicenseUrl; - var reqNode = Config.DocumentElement.SelectSingleNode("/umbPackage/info/package/requirements"); - RequirementsType = reqNode != null && reqNode.Attributes != null && reqNode.Attributes["type"] != null - ? Enum.Parse(reqNode.Attributes["type"].Value, true) - : RequirementsType.Legacy; - var iconNode = Config.DocumentElement.SelectSingleNode("/umbPackage/info/package/iconUrl"); - if (iconNode != null && iconNode.FirstChild != null) - { - IconUrl = iconNode.FirstChild.Value; - } - - Author = Config.DocumentElement.SelectSingleNode("/umbPackage/info/author/name").FirstChild.Value; - AuthorUrl = Config.DocumentElement.SelectSingleNode("/umbPackage/info/author/website").FirstChild.Value; + RequirementsMajor = def.UmbracoVersion.Major; + RequirementsMinor = def.UmbracoVersion.Minor; + RequirementsPatch = def.UmbracoVersion.Build; + RequirementsType = def.UmbracoVersionRequirementsType; + IconUrl = def.IconUrl; + Author = def.Author; + AuthorUrl = def.AuthorUrl; + ReadMe = def.Readme; + Control = def.Control; var basePath = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath; var dllBinFiles = new List(); - foreach (XmlNode n in Config.DocumentElement.SelectNodes("//file")) + foreach (var f in def.Files) { var badFile = false; - var destPath = GetFileName(basePath, XmlHelper.GetNodeValue(n.SelectSingleNode("orgPath"))); - var orgName = XmlHelper.GetNodeValue(n.SelectSingleNode("orgName")); + var destPath = GetFileName(basePath, f.OriginalPath); + var orgName = f.OriginalName; var destFile = GetFileName(destPath, orgName); if (destPath.ToLower().Contains(IOHelper.DirSepChar + "app_code")) @@ -606,7 +584,7 @@ namespace Umbraco.Web._Legacy.Packager if (badFile) { ContainsUnsecureFiles = true; - UnsecureFiles.Add(XmlHelper.GetNodeValue(n.SelectSingleNode("orgName"))); + UnsecureFiles.Add(f.OriginalName); } } @@ -614,9 +592,9 @@ namespace Umbraco.Web._Legacy.Packager //this will check for existing macros with the same alias //since we will not overwrite on import it's a good idea to inform the user what will be overwritten - foreach (XmlNode n in Config.DocumentElement.SelectNodes("//macro")) + foreach (var n in Config.Root.XPathSelectElements("//macro")) { - var alias = n.SelectSingleNode("alias").InnerText; + var alias = n.Element("alias")?.Value; if (!string.IsNullOrEmpty(alias)) { var m = Current.Services.MacroService.GetByAlias(alias); @@ -631,9 +609,9 @@ namespace Umbraco.Web._Legacy.Packager } } - foreach (XmlNode n in Config.DocumentElement.SelectNodes("Templates/Template")) + foreach (var n in Config.Root.XPathSelectElements("Templates/Template")) { - var alias = n.SelectSingleNode("Alias").InnerText; + var alias = n.Element("Alias")?.Value; if (!string.IsNullOrEmpty(alias)) { var t = Current.Services.FileService.GetTemplate(alias); @@ -648,9 +626,9 @@ namespace Umbraco.Web._Legacy.Packager } } - foreach (XmlNode n in Config.DocumentElement.SelectNodes("Stylesheets/Stylesheet")) + foreach (var n in Config.Root.XPathSelectElements("Stylesheets/Stylesheet")) { - var alias = n.SelectSingleNode("Name").InnerText; + var alias = n.Element("Name")?.Value; if (!string.IsNullOrEmpty(alias)) { var s = Current.Services.FileService.GetStylesheetByName(alias); @@ -665,17 +643,7 @@ namespace Umbraco.Web._Legacy.Packager } } - var readmeNode = Config.DocumentElement.SelectSingleNode("/umbPackage/info/readme"); - if (readmeNode != null) - { - ReadMe = XmlHelper.GetNodeValue(readmeNode); - } - - var controlNode = Config.DocumentElement.SelectSingleNode("/umbPackage/control"); - if (controlNode != null) - { - Control = XmlHelper.GetNodeValue(controlNode); - } + } /// @@ -815,15 +783,8 @@ namespace Umbraco.Web._Legacy.Packager #endregion - internal static event EventHandler PackageBusinessLogicInstalled; - private static void OnPackageBusinessLogicInstalled(InstalledPackage e) - { - var handler = PackageBusinessLogicInstalled; - handler?.Invoke(null, e); - } - - private void OnPackageInstalled(InstalledPackage insPack) + private void OnPackageInstalled(PackageDefinition insPack) { // getting an InstallationSummary for sending to the PackagingService.ImportedPackage event var fileService = Current.Services.FileService; @@ -832,12 +793,10 @@ namespace Umbraco.Web._Legacy.Packager var dataTypeService = Current.Services.DataTypeService; var localizationService = Current.Services.LocalizationService; - var installationSummary = insPack.GetInstallationSummary(contentTypeService, dataTypeService, fileService, localizationService, macroService); + var installationSummary = InstallationSummary.FromPackageDefinition(insPack, contentTypeService, dataTypeService, fileService, localizationService, macroService); installationSummary.PackageInstalled = true; - var meta = insPack.GetMetaData(); - - var args = new ImportPackageEventArgs(installationSummary, meta, false); + var args = new ImportPackageEventArgs(installationSummary, insPack, false); PackagingService.OnImportedPackage(args); } } diff --git a/src/Umbraco.Web/_Legacy/Packager/PackageInstance/InstalledPackage.cs b/src/Umbraco.Web/_Legacy/Packager/PackageInstance/InstalledPackage.cs deleted file mode 100644 index e5af44b747..0000000000 --- a/src/Umbraco.Web/_Legacy/Packager/PackageInstance/InstalledPackage.cs +++ /dev/null @@ -1,136 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Umbraco.Core.Composing; -using Umbraco.Core.IO; -using Umbraco.Core.Logging; -using Umbraco.Core.Models; -using Umbraco.Core.Models.Packaging; -using Umbraco.Core.Services; - -namespace Umbraco.Web._Legacy.Packager.PackageInstance -{ - public class InstalledPackage - { - - private int _saveHitCount = 0; - - public static InstalledPackage GetById(int id) - { - InstalledPackage pack = new InstalledPackage(); - pack.Data = data.Package(id, IOHelper.MapPath(Settings.InstalledPackagesSettings)); - return pack; - } - - public static InstalledPackage MakeNew(string name) - { - InstalledPackage pack = new InstalledPackage(); - pack.Data = data.MakeNew(name, IOHelper.MapPath(Settings.InstalledPackagesSettings)); - return pack; - } - - public void Save() - { -#if DEBUG - _saveHitCount++; - Current.Logger.Info("The InstalledPackage class save method has been hit {Total} times.", _saveHitCount); -#endif - data.Save(this.Data, IOHelper.MapPath(Settings.InstalledPackagesSettings)); - } - - public static List GetAllInstalledPackages() - { - - List val = new List(); - - foreach (Core.Models.Packaging.PackageDefinition pack in data.GetAllPackages(IOHelper.MapPath(Settings.InstalledPackagesSettings))) - { - InstalledPackage insPackage = new InstalledPackage(); - insPackage.Data = pack; - val.Add(insPackage); - } - - return val; - } - - public Core.Models.Packaging.PackageDefinition Data { get; set; } - - public void Delete(int userId) - { - Current.Services.AuditService.Add(AuditType.PackagerUninstall, userId, -1, "Package", string.Format("Package '{0}' uninstalled. Package guid: {1}", Data.Name, Data.PackageId)); - Delete(); - } - - public void Delete() - { - data.Delete(this.Data.Id, IOHelper.MapPath(Settings.InstalledPackagesSettings)); - } - - - - /// - /// Used internally for creating an InstallationSummary (used in new PackagingService) representation of this InstalledPackage object. - /// - /// - /// - /// - /// - /// - /// - internal InstallationSummary GetInstallationSummary(IContentTypeService contentTypeService, IDataTypeService dataTypeService, IFileService fileService, ILocalizationService localizationService, IMacroService macroService) - { - var macros = TryGetIntegerIds(Data.Macros).Select(macroService.GetById).ToList(); - var templates = TryGetIntegerIds(Data.Templates).Select(fileService.GetTemplate).ToList(); - var contentTypes = TryGetIntegerIds(Data.DocumentTypes).Select(contentTypeService.Get).ToList(); // fixme - media types? - var dataTypes = TryGetIntegerIds(Data.DataTypes).Select(dataTypeService.GetDataType).ToList(); - var dictionaryItems = TryGetIntegerIds(Data.DictionaryItems).Select(localizationService.GetDictionaryItemById).ToList(); - var languages = TryGetIntegerIds(Data.Languages).Select(localizationService.GetLanguageById).ToList(); - - for (var i = 0; i < Data.Files.Count; i++) - { - var filePath = Data.Files[i]; - Data.Files[i] = filePath.GetRelativePath(); - } - - return new InstallationSummary - { - ContentTypesInstalled = contentTypes, - DataTypesInstalled = dataTypes, - DictionaryItemsInstalled = dictionaryItems, - FilesInstalled = Data.Files, - LanguagesInstalled = languages, - MacrosInstalled = macros, - MetaData = GetMetaData(), - TemplatesInstalled = templates, - }; - } - - internal MetaData GetMetaData() - { - return new MetaData() - { - AuthorName = Data.Author, - AuthorUrl = Data.AuthorUrl, - Control = Data.LoadControl, - License = Data.License, - LicenseUrl = Data.LicenseUrl, - Name = Data.Name, - Readme = Data.Readme, - Url = Data.Url, - Version = Data.Version - }; - } - - private static IEnumerable TryGetIntegerIds(IEnumerable ids) - { - var intIds = new List(); - foreach (var id in ids) - { - int parsed; - if (int.TryParse(id, out parsed)) - intIds.Add(parsed); - } - return intIds; - } - } -} diff --git a/src/Umbraco.Web/_Legacy/Packager/data.cs b/src/Umbraco.Web/_Legacy/Packager/data.cs deleted file mode 100644 index 51f0799689..0000000000 --- a/src/Umbraco.Web/_Legacy/Packager/data.cs +++ /dev/null @@ -1,374 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Xml; -using Umbraco.Core; -using Umbraco.Core.Composing; -using Umbraco.Core.Configuration; -using Umbraco.Core.IO; -using Umbraco.Core.Logging; -using Umbraco.Core.Xml; - -namespace Umbraco.Web._Legacy.Packager -{ - /// - /// This is the xml data for installed packages. This is not the same xml as a pckage format! - /// - public class data - { - public static XmlDocument Source { get; private set; } - - public static void Reload(string dataSource) - { - //do some error checking and create the folders/files if they don't exist - if (!File.Exists(dataSource)) - { - if (!Directory.Exists(IOHelper.MapPath(SystemDirectories.Packages))) - { - Directory.CreateDirectory(IOHelper.MapPath(SystemDirectories.Packages)); - } - - using (var sw = File.CreateText(dataSource)) - { - sw.Write($@"{Environment.NewLine}{Environment.NewLine}"); - sw.Flush(); - } - - } - - if (Source == null) - { - Source = new XmlDocument(); - } - - //error checking here - if (File.Exists(dataSource)) - { - var isEmpty = false; - using (var sr = new StreamReader(dataSource)) - { - if (sr.ReadToEnd().IsNullOrWhiteSpace()) - { - isEmpty = true; - } - } - if (isEmpty) - { - File.WriteAllText(dataSource, @""); - } - } - - Source.Load(dataSource); - } - - public static XmlNode GetFromId(int Id, string dataSource, bool reload) - { - if (reload) - Reload(dataSource); - - return Source.SelectSingleNode("/packages/package [@id = '" + Id.ToString().ToUpper() + "']"); - } - - public static XmlNode GetFromGuid(string guid, string dataSource, bool reload) - { - if (reload) - Reload(dataSource); - - return Source.SelectSingleNode("/packages/package [@packageGuid = '" + guid + "']"); - } - - public static Core.Models.Packaging.PackageDefinition MakeNew(string name, string dataSource) - { - Reload(dataSource); - - int maxId = 1; - // Find max id - foreach (XmlNode n in Source.SelectNodes("packages/package")) - { - if (int.Parse(n.Attributes.GetNamedItem("id").Value) >= maxId) - maxId = int.Parse(n.Attributes.GetNamedItem("id").Value) + 1; - } - - XmlElement instance = Source.CreateElement("package"); - instance.Attributes.Append(XmlHelper.AddAttribute(Source, "id", maxId.ToString())); - instance.Attributes.Append(XmlHelper.AddAttribute(Source, "version", "")); - instance.Attributes.Append(XmlHelper.AddAttribute(Source, "url", "")); - instance.Attributes.Append(XmlHelper.AddAttribute(Source, "name", name)); - instance.Attributes.Append(XmlHelper.AddAttribute(Source, "folder", Guid.NewGuid().ToString())); - instance.Attributes.Append(XmlHelper.AddAttribute(Source, "packagePath", "")); - instance.Attributes.Append(XmlHelper.AddAttribute(Source, "repositoryGuid", "")); - instance.Attributes.Append(XmlHelper.AddAttribute(Source, "iconUrl", "")); - //set to current version - instance.Attributes.Append(XmlHelper.AddAttribute(Source, "umbVersion", UmbracoVersion.Current.ToString(3))); - instance.Attributes.Append(XmlHelper.AddAttribute(Source, "packageGuid", Guid.NewGuid().ToString())); - instance.Attributes.Append(XmlHelper.AddAttribute(Source, "hasUpdate", "false")); - - instance.Attributes.Append(XmlHelper.AddAttribute(Source, "enableSkins", "false")); - instance.Attributes.Append(XmlHelper.AddAttribute(Source, "skinRepoGuid", "")); - - XmlElement license = Source.CreateElement("license"); - license.InnerText = "MIT License"; - license.Attributes.Append(XmlHelper.AddAttribute(Source, "url", "http://opensource.org/licenses/MIT")); - instance.AppendChild(license); - - XmlElement author = Source.CreateElement("author"); - author.InnerText = ""; - author.Attributes.Append(XmlHelper.AddAttribute(Source, "url", "")); - instance.AppendChild(author); - - instance.AppendChild(XmlHelper.AddTextNode(Source, "readme", "")); - instance.AppendChild(XmlHelper.AddTextNode(Source, "actions", "")); - - instance.AppendChild(XmlHelper.AddTextNode(Source, "datatypes", "")); - - XmlElement content = Source.CreateElement("content"); - content.InnerText = ""; - content.Attributes.Append(XmlHelper.AddAttribute(Source, "nodeId", "")); - content.Attributes.Append(XmlHelper.AddAttribute(Source, "loadChildNodes", "false")); - instance.AppendChild(content); - - instance.AppendChild(XmlHelper.AddTextNode(Source, "templates", "")); - instance.AppendChild(XmlHelper.AddTextNode(Source, "stylesheets", "")); - instance.AppendChild(XmlHelper.AddTextNode(Source, "documentTypes", "")); - instance.AppendChild(XmlHelper.AddTextNode(Source, "macros", "")); - instance.AppendChild(XmlHelper.AddTextNode(Source, "files", "")); - instance.AppendChild(XmlHelper.AddTextNode(Source, "languages", "")); - instance.AppendChild(XmlHelper.AddTextNode(Source, "dictionaryitems", "")); - instance.AppendChild(XmlHelper.AddTextNode(Source, "loadcontrol", "")); - - Source.SelectSingleNode("packages").AppendChild(instance); - Source.Save(dataSource); - var retVal = data.Package(maxId, dataSource); - - return retVal; - } - - public static Core.Models.Packaging.PackageDefinition Package(int id, string datasource) - { - return ConvertXmlToPackage(GetFromId(id, datasource, true)); - } - - public static Core.Models.Packaging.PackageDefinition Package(string guid, string datasource) - { - XmlNode node = GetFromGuid(guid, datasource, true); - if (node != null) - return ConvertXmlToPackage(node); - else - return new Core.Models.Packaging.PackageDefinition(); - } - - public static List GetAllPackages(string dataSource) - { - Reload(dataSource); - XmlNodeList nList = data.Source.SelectNodes("packages/package"); - - List retVal = new List(); - - for (int i = 0; i < nList.Count; i++) - { - try - { - retVal.Add(ConvertXmlToPackage(nList[i])); - } - catch (Exception ex) - { - Current.Logger.Error(ex, "An error occurred in GetAllPackages"); - } - } - - return retVal; - } - - private static Core.Models.Packaging.PackageDefinition ConvertXmlToPackage(XmlNode n) - { - Core.Models.Packaging.PackageDefinition retVal = new Core.Models.Packaging.PackageDefinition(); - - if (n != null) - { - retVal.Id = int.Parse(SafeAttribute("id", n)); - retVal.Name = SafeAttribute("name", n); - retVal.FolderId = Guid.Parse(SafeAttribute("folder", n)); - retVal.PackagePath = SafeAttribute("packagePath", n); - retVal.Version = SafeAttribute("version", n); - retVal.Url = SafeAttribute("url", n); - retVal.PackageId = Guid.Parse(SafeAttribute("packageGuid", n)); - - retVal.IconUrl = SafeAttribute("iconUrl", n); - var umbVersion = SafeAttribute("umbVersion", n); - Version parsedVersion; - if (umbVersion.IsNullOrWhiteSpace() == false && Version.TryParse(umbVersion, out parsedVersion)) - { - retVal.UmbracoVersion = parsedVersion; - } - - retVal.License = SafeNodeValue(n.SelectSingleNode("license")); - retVal.LicenseUrl = n.SelectSingleNode("license").Attributes.GetNamedItem("url").Value; - - retVal.Author = SafeNodeValue(n.SelectSingleNode("author")); - retVal.AuthorUrl = SafeAttribute("url", n.SelectSingleNode("author")); - - retVal.Readme = SafeNodeValue(n.SelectSingleNode("readme")); - retVal.Actions = SafeNodeInnerXml(n.SelectSingleNode("actions")); - - retVal.ContentNodeId = SafeAttribute("nodeId", n.SelectSingleNode("content")); - retVal.ContentLoadChildNodes = bool.Parse(SafeAttribute("loadChildNodes", n.SelectSingleNode("content"))); - - retVal.Macros = new List(SafeNodeValue(n.SelectSingleNode("macros")).Trim(',').Split(',')); - retVal.Macros = new List(SafeNodeValue(n.SelectSingleNode("macros")).Trim(',').Split(',')); - retVal.Templates = new List(SafeNodeValue(n.SelectSingleNode("templates")).Trim(',').Split(',')); - retVal.Stylesheets = new List(SafeNodeValue(n.SelectSingleNode("stylesheets")).Trim(',').Split(',')); - retVal.DocumentTypes = new List(SafeNodeValue(n.SelectSingleNode("documentTypes")).Trim(',').Split(',')); - retVal.Languages = new List(SafeNodeValue(n.SelectSingleNode("languages")).Trim(',').Split(',')); - retVal.DictionaryItems = new List(SafeNodeValue(n.SelectSingleNode("dictionaryitems")).Trim(',').Split(',')); - retVal.DataTypes = new List(SafeNodeValue(n.SelectSingleNode("datatypes")).Trim(',').Split(',')); - - XmlNodeList xmlFiles = n.SelectNodes("files/file"); - retVal.Files = new List(); - - for (int i = 0; i < xmlFiles.Count; i++) - retVal.Files.Add(xmlFiles[i].InnerText); - - retVal.LoadControl = SafeNodeValue(n.SelectSingleNode("loadcontrol")); - } - - return retVal; - } - - public static void Delete(int Id, string dataSource) - { - Reload(dataSource); - // Remove physical xml file if any - //PackageInstance p = new PackageInstance(Id); - - //TODO DELETE PACKAGE FOLDER... - //p.Folder - - XmlNode n = data.GetFromId(Id, dataSource, true); - if (n != null) - { - data.Source.SelectSingleNode("/packages").RemoveChild(n); - data.Source.Save(dataSource); - } - - } - - - public static void Save(Core.Models.Packaging.PackageDefinition package, string dataSource) - { - Reload(dataSource); - var xmlDef = GetFromId(package.Id, dataSource, false); - XmlHelper.SetAttribute(Source, xmlDef, "name", package.Name); - XmlHelper.SetAttribute(Source, xmlDef, "version", package.Version); - XmlHelper.SetAttribute(Source, xmlDef, "url", package.Url); - XmlHelper.SetAttribute(Source, xmlDef, "packagePath", package.PackagePath); - XmlHelper.SetAttribute(Source, xmlDef, "packageGuid", package.PackageId.ToString()); - XmlHelper.SetAttribute(Source, xmlDef, "iconUrl", package.IconUrl); - if (package.UmbracoVersion != null) - XmlHelper.SetAttribute(Source, xmlDef, "umbVersion", package.UmbracoVersion.ToString(3)); - - var licenseNode = xmlDef.SelectSingleNode("license"); - if (licenseNode == null) - { - licenseNode = Source.CreateElement("license"); - xmlDef.AppendChild(licenseNode); - } - licenseNode.InnerText = package.License; - XmlHelper.SetAttribute(Source, licenseNode, "url", package.LicenseUrl); - - var authorNode = xmlDef.SelectSingleNode("author"); - if (authorNode == null) - { - authorNode = Source.CreateElement("author"); - xmlDef.AppendChild(authorNode); - } - authorNode.InnerText = package.Author; - XmlHelper.SetAttribute(Source, authorNode, "url", package.AuthorUrl); - - XmlHelper.SetCDataNode(Source, xmlDef, "readme", package.Readme); - XmlHelper.SetInnerXmlNode(Source, xmlDef, "actions", package.Actions); - - var contentNode = xmlDef.SelectSingleNode("content"); - if (contentNode == null) - { - contentNode = Source.CreateElement("content"); - xmlDef.AppendChild(contentNode); - } - XmlHelper.SetAttribute(Source, contentNode, "nodeId", package.ContentNodeId); - XmlHelper.SetAttribute(Source, contentNode, "loadChildNodes", package.ContentLoadChildNodes.ToString()); - - XmlHelper.SetTextNode(Source, xmlDef, "macros", JoinList(package.Macros, ',')); - XmlHelper.SetTextNode(Source, xmlDef, "templates", JoinList(package.Templates, ',')); - XmlHelper.SetTextNode(Source, xmlDef, "stylesheets", JoinList(package.Stylesheets, ',')); - XmlHelper.SetTextNode(Source, xmlDef, "documentTypes", JoinList(package.DocumentTypes, ',')); - XmlHelper.SetTextNode(Source, xmlDef, "languages", JoinList(package.Languages, ',')); - XmlHelper.SetTextNode(Source, xmlDef, "dictionaryitems", JoinList(package.DictionaryItems, ',')); - XmlHelper.SetTextNode(Source, xmlDef, "datatypes", JoinList(package.DataTypes, ',')); - - var filesNode = xmlDef.SelectSingleNode("files"); - if (filesNode == null) - { - filesNode = Source.CreateElement("files"); - xmlDef.AppendChild(filesNode); - } - filesNode.InnerXml = ""; - - foreach (var fileStr in package.Files) - { - if (string.IsNullOrWhiteSpace(fileStr) == false) - filesNode.AppendChild(XmlHelper.AddTextNode(Source, "file", fileStr)); - } - - XmlHelper.SetTextNode(Source, xmlDef, "loadcontrol", package.LoadControl); - - Source.Save(dataSource); - } - - - - private static string SafeAttribute(string name, XmlNode n) - { - return n.Attributes == null || n.Attributes[name] == null ? string.Empty : n.Attributes[name].Value; - } - - private static string SafeNodeValue(XmlNode n) - { - try - { - return XmlHelper.GetNodeValue(n); - } - catch - { - return string.Empty; - } - } - - private static string SafeNodeInnerXml(XmlNode n) - { - try - { - return n.InnerXml; - } - catch - { - return string.Empty; - } - } - - - private static string JoinList(IList list, char seperator) - { - string retVal = ""; - foreach (string str in list) - { - retVal += str + seperator; - } - - return retVal.Trim(seperator); - } - - public data() - { - - } - } -} From a5630a34480cd938f95ae992ec94bcb0b02b2547 Mon Sep 17 00:00:00 2001 From: Aaron Powell Date: Fri, 11 Jan 2019 14:35:24 +1100 Subject: [PATCH 294/469] Fixing 4033 by using the right Logger instance --- src/Umbraco.Core/Runtime/CoreRuntime.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Core/Runtime/CoreRuntime.cs b/src/Umbraco.Core/Runtime/CoreRuntime.cs index 5d2359d04c..cb6a1cb031 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntime.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntime.cs @@ -319,7 +319,7 @@ namespace Umbraco.Core.Runtime /// Gets a profiler. /// protected virtual IProfiler GetProfiler() - => new LogProfiler(ProfilingLogger); + => new LogProfiler(Logger); /// /// Gets the application caches. From 677311aa4973d525f17f63bf7d2da1e27b0bfaeb Mon Sep 17 00:00:00 2001 From: Stephan Date: Fri, 11 Jan 2019 08:06:12 +0100 Subject: [PATCH 295/469] reduce allocs --- src/Umbraco.Core/Services/Implement/ContentService.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Core/Services/Implement/ContentService.cs b/src/Umbraco.Core/Services/Implement/ContentService.cs index 1e89e190c8..9943893473 100644 --- a/src/Umbraco.Core/Services/Implement/ContentService.cs +++ b/src/Umbraco.Core/Services/Implement/ContentService.cs @@ -2733,6 +2733,8 @@ namespace Umbraco.Core.Services.Implement } } + private static readonly string[] ArrayOfOneNullString = { null }; + public IContent CreateContentFromBlueprint(IContent blueprint, string name, int userId = 0) { if (blueprint == null) throw new ArgumentNullException(nameof(blueprint)); @@ -2745,7 +2747,7 @@ namespace Umbraco.Core.Services.Implement content.WriterId = userId; var now = DateTime.Now; - var cultures = blueprint.CultureInfos.Any() ? blueprint.CultureInfos.Select(x=>x.Key) : new[] {(string)null}; + var cultures = blueprint.CultureInfos.Any() ? blueprint.CultureInfos.Select(x=>x.Key) : ArrayOfOneNullString; foreach (var culture in cultures) { foreach (var property in blueprint.Properties) From ba282ab81ab7ec85b3a6bf54c1c7a2d7adbae100 Mon Sep 17 00:00:00 2001 From: Stephan Date: Fri, 11 Jan 2019 08:26:53 +0100 Subject: [PATCH 296/469] Comments --- src/Umbraco.Web/IPublishedContentQuery.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Umbraco.Web/IPublishedContentQuery.cs b/src/Umbraco.Web/IPublishedContentQuery.cs index c3a065b9dc..76e7be5e97 100644 --- a/src/Umbraco.Web/IPublishedContentQuery.cs +++ b/src/Umbraco.Web/IPublishedContentQuery.cs @@ -40,6 +40,7 @@ namespace Umbraco.Web /// Optional index name. /// /// When the is not specified, all cultures are searched. + /// While enumerating results, the ambient culture is changed to be the searched culture. /// IEnumerable Search(string term, string culture = null, string indexName = null); @@ -54,17 +55,24 @@ namespace Umbraco.Web /// Optional index name. /// /// When the is not specified, all cultures are searched. + /// While enumerating results, the ambient culture is changed to be the searched culture. /// IEnumerable Search(string term, int skip, int take, out long totalRecords, string culture = null, string indexName = null); /// /// Executes the query and converts the results to PublishedSearchResult. /// + /// + /// While enumerating results, the ambient culture is changed to be the searched culture. + /// IEnumerable Search(IQueryExecutor query); /// /// Executes the query and converts the results to PublishedSearchResult. /// + /// + /// While enumerating results, the ambient culture is changed to be the searched culture. + /// IEnumerable Search(IQueryExecutor query, int skip, int take, out long totalRecords); } } From 250c24de40f70a9f1b995934e45f394f1b4597ff Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Fri, 11 Jan 2019 12:54:50 +0000 Subject: [PATCH 297/469] Adds in chart.js & the angular wrapper library --- src/Umbraco.Web.UI.Client/package-lock.json | 56 ++++++++++++++++++- src/Umbraco.Web.UI.Client/package.json | 2 + src/Umbraco.Web/UI/JavaScript/JsInitialize.js | 5 +- 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/package-lock.json b/src/Umbraco.Web.UI.Client/package-lock.json index 7c3fe8b4f9..b12843fbf7 100644 --- a/src/Umbraco.Web.UI.Client/package-lock.json +++ b/src/Umbraco.Web.UI.Client/package-lock.json @@ -852,6 +852,26 @@ "resolved": "https://registry.npmjs.org/angular-animate/-/angular-animate-1.7.5.tgz", "integrity": "sha512-kU/fHIGf2a4a3bH7E1tzALTHk+QfoUSCK9fEcMFisd6ZWvNDwPzXWAilItqOC3EDiAXPmGHaNc9/aXiD9xrAxQ==" }, + "angular-chart.js": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/angular-chart.js/-/angular-chart.js-1.1.1.tgz", + "integrity": "sha1-SfDhjQgXYrbUyXkeSHr/L7sw9a4=", + "requires": { + "angular": "1.x", + "chart.js": "2.3.x" + }, + "dependencies": { + "chart.js": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-2.3.0.tgz", + "integrity": "sha1-QEYOSOLEF8BfwzJc2E97AA3H19Y=", + "requires": { + "chartjs-color": "^2.0.0", + "moment": "^2.10.6" + } + } + } + }, "angular-cookies": { "version": "1.7.5", "resolved": "https://registry.npmjs.org/angular-cookies/-/angular-cookies-1.7.5.tgz", @@ -1970,6 +1990,39 @@ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "dev": true }, + "chart.js": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-2.7.3.tgz", + "integrity": "sha512-3+7k/DbR92m6BsMUYP6M0dMsMVZpMnwkUyNSAbqolHKsbIzH2Q4LWVEHHYq7v0fmEV8whXE0DrjANulw9j2K5g==", + "requires": { + "chartjs-color": "^2.1.0", + "moment": "^2.10.2" + } + }, + "chartjs-color": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/chartjs-color/-/chartjs-color-2.2.0.tgz", + "integrity": "sha1-hKL7dVeH7YXDndbdjHsdiEKbrq4=", + "requires": { + "chartjs-color-string": "^0.5.0", + "color-convert": "^0.5.3" + }, + "dependencies": { + "color-convert": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz", + "integrity": "sha1-vbbGnOZg+t/+CwAHzER+G59ygr0=" + } + } + }, + "chartjs-color-string": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/chartjs-color-string/-/chartjs-color-string-0.5.0.tgz", + "integrity": "sha512-amWNvCOXlOUYxZVDSa0YOab5K/lmEhbFNKI55PWc4mlv28BDzA7zaoQTGxSBgJMHIW+hGX8YUrvw/FH4LyhwSQ==", + "requires": { + "color-name": "^1.0.0" + } + }, "chokidar": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", @@ -2216,8 +2269,7 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "color-string": { "version": "1.5.3", diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index 2002cca0a1..e35fdc3442 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -8,6 +8,7 @@ "ace-builds": "1.4.2", "angular": "1.7.5", "angular-animate": "1.7.5", + "angular-chart.js": "^1.1.1", "angular-cookies": "1.7.5", "angular-dynamic-locale": "0.1.37", "angular-i18n": "1.7.5", @@ -20,6 +21,7 @@ "angular-ui-sortable": "0.19.0", "animejs": "2.2.0", "bootstrap-social": "5.1.1", + "chart.js": "^2.7.3", "clipboard": "2.0.4", "diff": "3.5.0", "flatpickr": "4.5.2", diff --git a/src/Umbraco.Web/UI/JavaScript/JsInitialize.js b/src/Umbraco.Web/UI/JavaScript/JsInitialize.js index 75ca46437a..62d294ee6f 100644 --- a/src/Umbraco.Web/UI/JavaScript/JsInitialize.js +++ b/src/Umbraco.Web/UI/JavaScript/JsInitialize.js @@ -23,8 +23,11 @@ 'lib/ng-file-upload/ng-file-upload.min.js', 'lib/angular-local-storage/angular-local-storage.min.js', + 'lib/chart.js/chart.min.js', + 'lib/angular-chart.js/angular-chart.min.js', + 'lib/umbraco/Extensions.js', - + 'lib/umbraco/NamespaceManager.js', 'lib/umbraco/LegacySpeechBubble.js', From 8f1cd8110d9488bfc9608055b14ce4cccdbd0b92 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Fri, 11 Jan 2019 13:27:39 +0000 Subject: [PATCH 298/469] Adds in the missing chart.js & wrapper lib (part of it was put in the solution it seems but not fully merged in correctly perhaps?!) --- src/Umbraco.Web.UI.Client/gulpfile.js | 11 +++++++++++ src/Umbraco.Web.UI.Client/src/app.js | 5 +++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/gulpfile.js b/src/Umbraco.Web.UI.Client/gulpfile.js index 0af327d148..22ac11b991 100644 --- a/src/Umbraco.Web.UI.Client/gulpfile.js +++ b/src/Umbraco.Web.UI.Client/gulpfile.js @@ -248,6 +248,17 @@ gulp.task('dependencies', function () { "src": ["./node_modules/bootstrap-social/bootstrap-social.css"], "base": "./node_modules/bootstrap-social" }, + + { + "name": "angular-chart.js", + "src": ["./node_modules/angular-chart.js/dist/angular-chart.min.js"], + "base": "./node_modules/angular-chart.js/dist" + }, + { + "name": "chart.js", + "src": ["./node_modules/chart.js/dist/chart.min.js"], + "base": "./node_modules/chart.js/dist" + }, { "name": "clipboard", "src": ["./node_modules/clipboard/dist/clipboard.min.js"], diff --git a/src/Umbraco.Web.UI.Client/src/app.js b/src/Umbraco.Web.UI.Client/src/app.js index c7b813c1bf..8e0eaa4943 100644 --- a/src/Umbraco.Web.UI.Client/src/app.js +++ b/src/Umbraco.Web.UI.Client/src/app.js @@ -14,7 +14,8 @@ var app = angular.module('umbraco', [ 'ngMessages', 'tmh.dynamicLocale', 'ngFileUpload', - 'LocalStorageModule' + 'LocalStorageModule', + 'chart.js' ]); app.config(['$compileProvider', function ($compileProvider) { @@ -76,7 +77,7 @@ angular.module("umbraco.viewcache", []) var _op = (url.indexOf("?") > 0) ? "&" : "?"; url += _op + "umb__rnd=" + rnd; } - + return get(url, config); }; return $delegate; From fded793f8e96e40fe77fe87684932c04e8824835 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Fri, 11 Jan 2019 13:32:45 +0000 Subject: [PATCH 299/469] Removes the accidently Web.UI.csproj V7 port numbers for IISExpress when merging up from V7 to V8 --- src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index 05bc1dca73..7a59b15eb3 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -433,12 +433,6 @@ 8000 / http://localhost:8000 - 7140 - / - http://localhost:7140 - 7131 - / - http://localhost:7131 False False From ca75b2f4d369f4705d5df7efca00d2c006c04914 Mon Sep 17 00:00:00 2001 From: Stephan Date: Fri, 11 Jan 2019 14:53:55 +0100 Subject: [PATCH 300/469] Fix recent Examine changes --- .../XmlPublishedCache/DictionaryPublishedContent.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/DictionaryPublishedContent.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/DictionaryPublishedContent.cs index a845be286f..6f6a39144a 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/DictionaryPublishedContent.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/DictionaryPublishedContent.cs @@ -52,7 +52,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache LoadedFromExamine = fromExamine; ValidateAndSetProperty(valueDictionary, val => _id = Int32.Parse(val), "id", "nodeId", "__NodeId"); //should validate the int! - ValidateAndSetProperty(valueDictionary, val => _key = Guid.Parse(val), "key"); + ValidateAndSetProperty(valueDictionary, val => _key = Guid.Parse(val), "key", "__key", "__Key"); //ValidateAndSetProperty(valueDictionary, val => _templateId = int.Parse(val), "template", "templateId"); ValidateAndSetProperty(valueDictionary, val => _sortOrder = Int32.Parse(val), "sortOrder"); ValidateAndSetProperty(valueDictionary, val => _name = val, "nodeName"); From 29390a3624bb275d829da5d12af0eeb424b3fb75 Mon Sep 17 00:00:00 2001 From: Robert Date: Fri, 11 Jan 2019 15:15:59 +0100 Subject: [PATCH 301/469] Fixes string to int conversion error --- .../PropertyEditors/MultiNodePickerConfigurationTreeSource.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web/PropertyEditors/MultiNodePickerConfigurationTreeSource.cs b/src/Umbraco.Web/PropertyEditors/MultiNodePickerConfigurationTreeSource.cs index ffedf6c7dc..65115afc63 100644 --- a/src/Umbraco.Web/PropertyEditors/MultiNodePickerConfigurationTreeSource.cs +++ b/src/Umbraco.Web/PropertyEditors/MultiNodePickerConfigurationTreeSource.cs @@ -15,6 +15,6 @@ namespace Umbraco.Web.PropertyEditors public string StartNodeQuery {get;set;} [JsonProperty("id")] - public int? StartNodeId {get;set;} + public string StartNodeId {get;set;} } } From 8f41fe8d3840cccb5235ba632a6d69a2f8efbcc4 Mon Sep 17 00:00:00 2001 From: Robert Date: Fri, 11 Jan 2019 15:17:29 +0100 Subject: [PATCH 302/469] Fixes MNTP only being able to open contentPicker --- .../contentpicker/contentpicker.controller.js | 45 ++++++++++++------- .../contentpicker/contentpicker.html | 2 +- 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js index af3ce50609..e084d7116a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js @@ -52,18 +52,18 @@ function contentPickerController($scope, entityResource, editorState, iconHelper } function startWatch() { - + //due to the way angular-sortable works, it needs to update a model, we don't want it to update renderModel since renderModel //is updated based on changes to model.value so if we bound angular-sortable to that and put a watch on it we'd end up in a //infinite loop. Instead we have a custom array model for angular-sortable and we'll watch that which we'll use to sync the model.value //which in turn will sync the renderModel. - $scope.$watchCollection("sortableModel", function(newVal, oldVal) { + $scope.$watchCollection("sortableModel", function (newVal, oldVal) { $scope.model.value = newVal.join(); }); //if the underlying model changes, update the view model, this ensures that the view is always consistent with the underlying //model if it changes (i.e. based on server updates, or if used in split view, etc...) - $scope.$watch("model.value", function(newVal, oldVal) { + $scope.$watch("model.value", function (newVal, oldVal) { if (newVal !== oldVal) { syncRenderModel(); } @@ -195,25 +195,38 @@ function contentPickerController($scope, entityResource, editorState, iconHelper } //dialog - $scope.openContentPicker = function () { - $scope.contentPicker = dialogOptions; + $scope.openCurrentPicker = function () { + $scope.currentPicker = dialogOptions; - $scope.contentPicker.submit = function (model) { + $scope.currentPicker.submit = function (model) { if (angular.isArray(model.selection)) { _.each(model.selection, function (item, i) { $scope.add(item); }); - angularHelper.getCurrentForm($scope).$setDirty(); + angularHelper.getCurrentForm($scope).$setDirty(); } angularHelper.getCurrentForm($scope).$setDirty(); editorService.close(); } - $scope.contentPicker.close = function () { + $scope.currentPicker.close = function () { editorService.close(); } - editorService.contentPicker($scope.contentPicker); + //open the correct editor based on the entity type + switch (entityType) { + case "Document": + editorService.contentPicker($scope.currentPicker); + break; + case "Media": + editorService.mediaPicker($scope.currentPicker); + break; + case "Member": + editorService.memberGroupPicker($scope.currentPicker); + break; + + default: + } }; @@ -256,7 +269,7 @@ function contentPickerController($scope, entityResource, editorState, iconHelper $scope.model.value = null; }; - $scope.openContentEditor = function (node)  { + $scope.openContentEditor = function (node) { var contentEditor = { id: node.id, submit: function (model) { @@ -296,7 +309,7 @@ function contentPickerController($scope, entityResource, editorState, iconHelper if (valueIds.length > 0) { //need to determine which items we already have loaded - var renderModelIds = _.map($scope.renderModel, function(d) { + var renderModelIds = _.map($scope.renderModel, function (d) { return $scope.model.config.idType === "udi" ? d.udi : d.id; }); @@ -313,11 +326,11 @@ function contentPickerController($scope, entityResource, editorState, iconHelper var missingIds = _.difference(valueIds, renderModelIds); if (missingIds.length > 0) { - return entityResource.getByIds(missingIds, entityType).then(function(data) { + return entityResource.getByIds(missingIds, entityType).then(function (data) { _.each(valueIds, - function(id, i) { - var entity = _.find(data, function(d) { + function (id, i) { + var entity = _.find(data, function (d) { return $scope.model.config.idType === "udi" ? (d.udi == id) : (d.id == id); }); @@ -330,7 +343,7 @@ function contentPickerController($scope, entityResource, editorState, iconHelper if (doValidation) { validate(); } - + setSortingState($scope.renderModel); return $q.when(true); }); @@ -342,7 +355,7 @@ function contentPickerController($scope, entityResource, editorState, iconHelper $scope.renderModel = []; for (var k = 0; k < valueIds.length; k++) { var id = valueIds[k]; - var found = _.find(current, function(d) { + var found = _.find(current, function (d) { return $scope.model.config.idType === "udi" ? (d.udi == id) : (d.id == id); }); if (found) { diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.html index 2f1303077c..a589cf8947 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.html @@ -22,7 +22,7 @@ Add From e88c789b88f85e36e672ce7881fec6d0995b7145 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Fri, 11 Jan 2019 15:44:54 +0100 Subject: [PATCH 303/469] Add some defensive coding to avoid JS errors --- .../components/content/umbcontentnodeinfo.directive.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js index 71fbabe943..b65bf447e7 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js @@ -97,9 +97,9 @@ } //load in the audit trail if we are currently looking at the INFO tab - if (umbVariantContentCtrl) { + if (umbVariantContentCtrl && umbVariantContentCtrl.editor) { var activeApp = _.find(umbVariantContentCtrl.editor.content.apps, a => a.active); - if (activeApp.alias === "umbInfo") { + if (activeApp && activeApp.alias === "umbInfo") { isInfoTab = true; loadAuditTrail(); loadRedirectUrls(); From 291d58900ff2ad3f4e3772857748301aa70a1f3b Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Sun, 13 Jan 2019 12:42:42 +0100 Subject: [PATCH 304/469] V8: Remember editor language between sessions (#4035) --- .../src/controllers/navigation.controller.js | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/controllers/navigation.controller.js b/src/Umbraco.Web.UI.Client/src/controllers/navigation.controller.js index 06b82d6eab..335fe99e7c 100644 --- a/src/Umbraco.Web.UI.Client/src/controllers/navigation.controller.js +++ b/src/Umbraco.Web.UI.Client/src/controllers/navigation.controller.js @@ -9,7 +9,7 @@ * * @param {navigationService} navigationService A reference to the navigationService */ -function NavigationController($scope, $rootScope, $location, $log, $q, $routeParams, $timeout, treeService, appState, navigationService, keyboardService, historyService, eventsService, angularHelper, languageResource, contentResource) { +function NavigationController($scope, $rootScope, $location, $log, $q, $routeParams, $timeout, $cookies, treeService, appState, navigationService, keyboardService, historyService, eventsService, angularHelper, languageResource, contentResource) { //this is used to trigger the tree to start loading once everything is ready var treeInitPromise = $q.defer(); @@ -344,9 +344,6 @@ function NavigationController($scope, $rootScope, $location, $log, $q, $routePar $scope.languages = languages; if ($scope.languages.length > 1) { - var defaultLang = _.find($scope.languages, function (l) { - return l.isDefault; - }); //if there's already one set, check if it exists var currCulture = null; var mainCulture = $location.search().mculture; @@ -356,7 +353,18 @@ function NavigationController($scope, $rootScope, $location, $log, $q, $routePar }); } if (!currCulture) { - $location.search("mculture", defaultLang ? defaultLang.culture : null); + // no culture in the request, let's look for one in the cookie that's set when changing language + var defaultCulture = $cookies.get("UMB_MCULTURE"); + if (!defaultCulture) { + // no luck either, look for the default language + var defaultLang = _.find($scope.languages, function (l) { + return l.isDefault; + }); + if (defaultLang) { + defaultCulture = defaultLang.culture; + } + } + $location.search("mculture", defaultCulture ? defaultCulture : null); } } @@ -391,6 +399,9 @@ function NavigationController($scope, $rootScope, $location, $log, $q, $routePar $scope.selectLanguage = function (language) { $location.search("mculture", language.culture); + // add the selected culture to a cookie so the user will log back into the same culture later on (cookie max age is one year = 31536000 seconds) + // NOTE: $cookies doesn't support max-age, so we need to go the good ol' JS way about setting the cookie + document.cookie = "UMB_MCULTURE=" +language.culture + ";path=/;max-age=31536000;"; // close the language selector $scope.page.languageSelectorIsOpen = false; From c619b79276be80db73442cee0b4dfd4b975bfed9 Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Sun, 13 Jan 2019 13:06:16 +0100 Subject: [PATCH 305/469] Fix placeholder text when empty alias input after generating alias (#4032) --- .../components/umbGenerateAlias.directive.js | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbGenerateAlias.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbGenerateAlias.directive.js index 47d1431e13..56a18a217e 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbGenerateAlias.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbGenerateAlias.directive.js @@ -86,20 +86,21 @@ angular.module("umbraco.directives") function generateAlias(value) { if (generateAliasTimeout) { - $timeout.cancel(generateAliasTimeout); + $timeout.cancel(generateAliasTimeout); } - if( value !== undefined && value !== "" && value !== null) { + if (value !== undefined && value !== "" && value !== null) { - scope.alias = ""; + scope.alias = ""; scope.placeholderText = scope.labels.busy; generateAliasTimeout = $timeout(function () { updateAlias = true; entityResource.getSafeAlias(value, true).then(function (safeAlias) { if (updateAlias) { - scope.alias = safeAlias.alias; - } + scope.alias = safeAlias.alias; + } + scope.placeholderText = scope.labels.idle; }); }, 500); @@ -108,7 +109,6 @@ angular.module("umbraco.directives") scope.alias = ""; scope.placeholderText = scope.labels.idle; } - } // if alias gets unlocked - stop watching alias @@ -119,17 +119,17 @@ angular.module("umbraco.directives") })); // validate custom entered alias - eventBindings.push(scope.$watch('alias', function(newValue, oldValue){ - - if(scope.alias === "" && bindWatcher === true || scope.alias === null && bindWatcher === true) { - // add watcher - eventBindings.push(scope.$watch('aliasFrom', function(newValue, oldValue) { - if(bindWatcher) { - generateAlias(newValue); - } - })); - } - + eventBindings.push(scope.$watch('alias', function (newValue, oldValue) { + if (scope.alias === "" || scope.alias === null || scope.alias === undefined) { + if (bindWatcher === true) { + // add watcher + eventBindings.push(scope.$watch('aliasFrom', function (newValue, oldValue) { + if (bindWatcher) { + generateAlias(newValue); + } + })); + } + } })); // clean up From 2ebd7a077cc5e71bd476f3f71d18d6ab16723e0c Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Sun, 13 Jan 2019 13:06:16 +0100 Subject: [PATCH 306/469] Fix placeholder text when empty alias input after generating alias (#4032) (cherry picked from commit c619b79276be80db73442cee0b4dfd4b975bfed9) --- .../components/umbGenerateAlias.directive.js | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbGenerateAlias.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbGenerateAlias.directive.js index 9b4bd17a12..b6c53d3876 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbGenerateAlias.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbGenerateAlias.directive.js @@ -86,20 +86,21 @@ angular.module("umbraco.directives") function generateAlias(value) { if (generateAliasTimeout) { - $timeout.cancel(generateAliasTimeout); + $timeout.cancel(generateAliasTimeout); } - if( value !== undefined && value !== "" && value !== null) { + if (value !== undefined && value !== "" && value !== null) { - scope.alias = ""; + scope.alias = ""; scope.placeholderText = scope.labels.busy; generateAliasTimeout = $timeout(function () { updateAlias = true; entityResource.getSafeAlias(encodeURIComponent(value), true).then(function (safeAlias) { if (updateAlias) { - scope.alias = safeAlias.alias; - } + scope.alias = safeAlias.alias; + } + scope.placeholderText = scope.labels.idle; }); }, 500); @@ -108,7 +109,6 @@ angular.module("umbraco.directives") scope.alias = ""; scope.placeholderText = scope.labels.idle; } - } // if alias gets unlocked - stop watching alias @@ -119,17 +119,17 @@ angular.module("umbraco.directives") })); // validate custom entered alias - eventBindings.push(scope.$watch('alias', function(newValue, oldValue){ - - if(scope.alias === "" && bindWatcher === true || scope.alias === null && bindWatcher === true) { - // add watcher - eventBindings.push(scope.$watch('aliasFrom', function(newValue, oldValue) { - if(bindWatcher) { - generateAlias(newValue); - } - })); - } - + eventBindings.push(scope.$watch('alias', function (newValue, oldValue) { + if (scope.alias === "" || scope.alias === null || scope.alias === undefined) { + if (bindWatcher === true) { + // add watcher + eventBindings.push(scope.$watch('aliasFrom', function (newValue, oldValue) { + if (bindWatcher) { + generateAlias(newValue); + } + })); + } + } })); // clean up From cd6cdcfda468bba4c6d07bf9d9b1886ec072023b Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Sun, 13 Jan 2019 13:54:30 +0100 Subject: [PATCH 307/469] Visualize image transparency in upload and image cropper thumbnails (#4050) --- .../src/less/property-editors.less | 28 +++++++++++++++---- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/property-editors.less b/src/Umbraco.Web.UI.Client/src/less/property-editors.less index e9d598a8cf..73de7aeee7 100644 --- a/src/Umbraco.Web.UI.Client/src/less/property-editors.less +++ b/src/Umbraco.Web.UI.Client/src/less/property-editors.less @@ -1,3 +1,5 @@ +@checkered-background: url(../img/checkered-background.png); + // // Container styles // -------------------------------------------------- @@ -386,7 +388,7 @@ div.umb-codeeditor .umb-btn-toolbar { max-height:100%; margin:auto; display:block; - background-image: url(../img/checkered-background.png); + background-image: @checkered-background; } .umb-sortable-thumbnails li .trashed { @@ -599,12 +601,18 @@ div.umb-codeeditor .umb-btn-toolbar { vertical-align: top; } - .gravity-container .viewport { - max-width: 600px; - } + .gravity-container { + border: 1px solid @gray-8; + line-height: 0; - .gravity-container .viewport:hover { - cursor: pointer; + .viewport { + max-width: 600px; + background: @checkered-background; + + &:hover { + cursor: pointer; + } + } } .imagecropper { @@ -617,6 +625,10 @@ div.umb-codeeditor .umb-btn-toolbar { float: left; max-width: 100%; } + + .viewport img { + background: @checkered-background; + } } .imagecropper .umb-cropper__container { @@ -884,6 +896,10 @@ div.umb-codeeditor .umb-btn-toolbar { list-style: none; vertical-align: middle; margin-bottom: 0; + + img { + background: @checkered-background; + } } .umb-fileupload label { From d1cfe847235198c49ae6640e56a0dc3d50fe35fd Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Sat, 12 Jan 2019 17:05:52 +0100 Subject: [PATCH 308/469] Set the form dirty when changing focal point and editing crops --- .../imaging/umbimagegravity.directive.js | 18 +++++++++--------- .../imagecropper/imagecropper.controller.js | 5 +++++ .../imagecropper/imagecropper.html | 3 ++- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/imaging/umbimagegravity.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/imaging/umbimagegravity.directive.js index bb364b79ee..7d1b1c5a18 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/imaging/umbimagegravity.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/imaging/umbimagegravity.directive.js @@ -14,7 +14,8 @@ angular.module("umbraco.directives") scope: { src: '=', center: "=", - onImageLoaded: "&" + onImageLoaded: "&", + onGravityChanged: "&" }, link: function(scope, element, attrs) { @@ -52,7 +53,7 @@ angular.module("umbraco.directives") calculateGravity(offsetX, offsetY); - lazyEndEvent(); + gravityChanged(); }; var setDimensions = function () { @@ -77,12 +78,11 @@ angular.module("umbraco.directives") scope.center.top = (scope.dimensions.top+10) / scope.dimensions.height; }; - var lazyEndEvent = _.debounce(function(){ - scope.$apply(function(){ - scope.$emit("imageFocalPointStop"); - }); - }, 2000); - + var gravityChanged = function () { + if (angular.isFunction(scope.onGravityChanged)) { + scope.onGravityChanged(); + } + }; //Drag and drop positioning, using jquery ui draggable //TODO ensure that the point doesnt go outside the box @@ -100,7 +100,7 @@ angular.module("umbraco.directives") calculateGravity(offsetX, offsetY); }); - lazyEndEvent(); + gravityChanged(); } }); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.controller.js index 47442495f7..d9131e88a4 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.controller.js @@ -52,6 +52,7 @@ angular.module('umbraco') }); editedCrop.coordinates = $scope.currentCrop.coordinates; $scope.close(); + angularHelper.getCurrentForm($scope).$setDirty(); }; //reset the current crop @@ -98,6 +99,10 @@ angular.module('umbraco') $scope.hasDimensions = hasDimensions; }; + $scope.focalPointChanged = function () { + angularHelper.getCurrentForm($scope).$setDirty(); + } + //on image selected, update the cropper $scope.$on("filesSelected", function (ev, args) { $scope.model.value = config; diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.html index a8f513f006..6e1cb52822 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.html @@ -40,7 +40,8 @@ + on-image-loaded="imageLoaded(isCroppable, hasDimensions)" + on-gravity-changed="focalPointChanged()"> Remove file From 0f7cb7c17737632bdd759300de003eb1f3095afe Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Fri, 11 Jan 2019 14:36:45 +0100 Subject: [PATCH 309/469] Use built-in localization for Nested Content + fix element picker title --- .../nestedcontent/nestedcontent.controller.js | 26 +++++-------------- .../nestedcontent/nestedcontent.html | 6 ++--- 2 files changed, 9 insertions(+), 23 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js index 6e67d2d251..79e00fa453 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js @@ -81,25 +81,6 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.NestedContent.Prop : undefined; }); - $scope.editIconTitle = ''; - $scope.moveIconTitle = ''; - $scope.deleteIconTitle = ''; - - // localize the edit icon title - localizationService.localize('general_edit').then(function (value) { - $scope.editIconTitle = value; - }); - - // localize the delete icon title - localizationService.localize('general_delete').then(function (value) { - $scope.deleteIconTitle = value; - }); - - // localize the move icon title - localizationService.localize('actions_move').then(function (value) { - $scope.moveIconTitle = value; - }); - $scope.nodes = []; $scope.currentNode = undefined; $scope.realCurrentNode = undefined; @@ -116,6 +97,11 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.NestedContent.Prop $scope.showIcons = $scope.model.config.showIcons || true; $scope.wideMode = $scope.model.config.hideLabel == "1"; + $scope.labels = {}; + localizationService.localizeMany(["grid_insertControl"]).then(function(data) { + $scope.labels.docTypePickerTitle = data[0]; + }); + // helper to force the current form into the dirty state $scope.setDirty = function () { if ($scope.propertyForm) { @@ -138,7 +124,7 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.NestedContent.Prop } $scope.overlayMenu = { - title: localizationService.localize('grid_insertControl'), + title: $scope.labels.docTypePickerTitle, show: false, style: {}, filter: $scope.scaffolds.length > 15 ? true : false, diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.html index 1ff6666907..572021aebd 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.html @@ -12,13 +12,13 @@
    From d350ab0789f7d97202bdff299ef32d9acce4b30e Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Fri, 11 Jan 2019 15:07:04 +0100 Subject: [PATCH 310/469] Ensure some spacing between properties within Nested Content items --- .../src/less/components/umb-nested-content.less | 7 +++++++ .../nestedcontent/nestedcontent.editor.html | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-nested-content.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-nested-content.less index df8977a2bf..6ddd9d8d50 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-nested-content.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-nested-content.less @@ -3,6 +3,13 @@ position: relative; } +.umb-nested-content-property-container { + position: relative; + &:not(:last-child){ + margin-bottom: 12px; + } +} + .umb-nested-content--not-supported { opacity: 0.3; pointer-events: none; diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.editor.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.editor.html index 83076b54a0..0cf67022c6 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.editor.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.editor.html @@ -1,5 +1,5 @@ 
    -
    +
    From f620d0deca457d3733755a8e6bb71082511fd1f2 Mon Sep 17 00:00:00 2001 From: Steve Date: Fri, 11 Jan 2019 11:16:46 +0000 Subject: [PATCH 311/469] Fixes #4016 unpublished content styling in list view --- src/Umbraco.Web.UI.Client/src/less/components/umb-table.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-table.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-table.less index 2c1fc4a701..217d94bc00 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-table.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-table.less @@ -165,7 +165,7 @@ input.umb-table__input { } -.-content :not(.with-unpublished-version).-unpublished { +.-content .-unpublished:not(.with-unpublished-version) { .umb-table__name > * { opacity: .4; } From b354eda7ac9ed2f3f650ef4c169425f2d39dc1a7 Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Tue, 8 Jan 2019 00:39:45 +0100 Subject: [PATCH 312/469] Add styles for umb-property-file-upload and move styles for umb-upload-big-button --- src/Umbraco.Web.UI.Client/src/less/belle.less | 1 + .../components/umb-property-file-upload.less | 28 +++++++++++++++++++ .../src/less/property-editors.less | 13 +-------- .../upload/umb-property-file-upload.html | 3 +- 4 files changed, 32 insertions(+), 13 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/less/components/umb-property-file-upload.less diff --git a/src/Umbraco.Web.UI.Client/src/less/belle.less b/src/Umbraco.Web.UI.Client/src/less/belle.less index a28c128706..a65b94444e 100644 --- a/src/Umbraco.Web.UI.Client/src/less/belle.less +++ b/src/Umbraco.Web.UI.Client/src/less/belle.less @@ -161,6 +161,7 @@ @import "components/umb-file-dropzone.less"; @import "components/umb-node-preview.less"; @import "components/umb-mini-editor.less"; +@import "components/umb-property-file-upload.less"; @import "components/users/umb-user-cards.less"; @import "components/users/umb-user-details.less"; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-property-file-upload.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-property-file-upload.less new file mode 100644 index 0000000000..08b1a1b5e1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-property-file-upload.less @@ -0,0 +1,28 @@ +.umb-property-file-upload { + + .umb-upload-button-big { + display: block; + padding: 20px; + opacity: 1; + border: 1px dashed @gray-8; + background: none; + text-align: center; + font-size: 14px; + + &, &:hover { + color: @gray-8; + } + + i.icon { + font-size: 55px; + line-height: 70px + } + + input { + left: 0; + bottom: 0; + height: 100%; + width: 100%; + } + } +} diff --git a/src/Umbraco.Web.UI.Client/src/less/property-editors.less b/src/Umbraco.Web.UI.Client/src/less/property-editors.less index 7e3d3f1491..3ec8c383da 100644 --- a/src/Umbraco.Web.UI.Client/src/less/property-editors.less +++ b/src/Umbraco.Web.UI.Client/src/less/property-editors.less @@ -699,7 +699,7 @@ // // folder-browser // -------------------------------------------------- -.umb-folderbrowser .add-link{ +.umb-folderbrowser .add-link { display: inline-block; height: 120px; width: 120px; @@ -708,17 +708,6 @@ line-height: 120px } -.umb-upload-button-big:hover{color: @gray-8;} - -.umb-upload-button-big {display: block} -.umb-upload-button-big input { - left: 0; - bottom: 0; - height: 100%; - width: 100%; -} - - // // File upload // -------------------------------------------------- diff --git a/src/Umbraco.Web.UI.Client/src/views/components/upload/umb-property-file-upload.html b/src/Umbraco.Web.UI.Client/src/views/components/upload/umb-property-file-upload.html index f205dffa57..dea532b7ea 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/upload/umb-property-file-upload.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/upload/umb-property-file-upload.html @@ -1,4 +1,5 @@ -
    +
    +
    Date: Tue, 8 Jan 2019 00:40:23 +0100 Subject: [PATCH 313/469] Only show extension if media item has a file --- .../src/views/components/umb-media-grid.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/components/umb-media-grid.html b/src/Umbraco.Web.UI.Client/src/views/components/umb-media-grid.html index 2591789a36..360c6b2bb7 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/umb-media-grid.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/umb-media-grid.html @@ -24,7 +24,7 @@ - .{{item.extension}} + .{{item.extension}}
    From 9968cd257d072e049fdc163e6862cbe6da9c7487 Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Tue, 8 Jan 2019 00:41:26 +0100 Subject: [PATCH 314/469] Rename wrapper class on umb-file-dropzone --- .../src/less/components/umb-file-dropzone.less | 2 +- .../src/views/components/upload/umb-file-dropzone.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-file-dropzone.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-file-dropzone.less index 4803c05f6e..b7c58ad3cf 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-file-dropzone.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-file-dropzone.less @@ -1,5 +1,5 @@ -.umb-file-dropzone-directive{ +.umb-file-dropzone { // drop zone // tall and small version - animate height diff --git a/src/Umbraco.Web.UI.Client/src/views/components/upload/umb-file-dropzone.html b/src/Umbraco.Web.UI.Client/src/views/components/upload/umb-file-dropzone.html index 9d2997625e..c99655b7fc 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/upload/umb-file-dropzone.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/upload/umb-file-dropzone.html @@ -1,4 +1,4 @@ -
    +
    From 1213551ca951db86acc0fda3f40b0a1d4efad4a5 Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Tue, 8 Jan 2019 00:40:23 +0100 Subject: [PATCH 315/469] Only show extension if media item has a file (cherry picked from commit 168febae248cb80a6c87ca9d0c840b70f97121fc) --- .../src/views/components/umb-media-grid.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/components/umb-media-grid.html b/src/Umbraco.Web.UI.Client/src/views/components/umb-media-grid.html index bad1ccc1ce..e97c91b414 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/umb-media-grid.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/umb-media-grid.html @@ -23,7 +23,7 @@ - .{{item.extension}} + .{{item.extension}}
    From 8d1733fd1275ba18f3420e995613bc52e0b51344 Mon Sep 17 00:00:00 2001 From: Jannik Anker Date: Tue, 2 Oct 2018 18:43:12 +0200 Subject: [PATCH 316/469] Issue 3018 - non-admin users cannot create groups --- .../Editors/UserGroupEditorAuthorizationHelper.cs | 14 +++++++++++++- src/Umbraco.Web/Editors/UserGroupsController.cs | 11 ++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web/Editors/UserGroupEditorAuthorizationHelper.cs b/src/Umbraco.Web/Editors/UserGroupEditorAuthorizationHelper.cs index 6bc39b376d..5e6458f93a 100644 --- a/src/Umbraco.Web/Editors/UserGroupEditorAuthorizationHelper.cs +++ b/src/Umbraco.Web/Editors/UserGroupEditorAuthorizationHelper.cs @@ -53,6 +53,18 @@ namespace Umbraco.Web.Editors if (currentUser.IsAdmin()) return Attempt.Succeed(); + // var derp = ((userGroupSave.Id == null || (int)userGroupSave.Id <= 0) && Services.SectionService.GetAllowedSections(Security.CurrentUser.Id).Select(x => x.Alias).Contains(Constants.Applications.Users)) ? Attempt.Succeed() : Attempt.Failed(); + + var existingGroups = _userService.GetUserGroupsByAlias(groupAliases); + + if(!existingGroups.Any()) + { + // We're dealing with new groups, + // so authorization should be given to any user with access to Users section + if (currentUser.AllowedSections.Contains(Constants.Applications.Users)) + return Attempt.Succeed(); + } + var userGroups = currentUser.Groups.Select(x => x.Alias).ToArray(); var missingAccess = groupAliases.Except(userGroups).ToArray(); return missingAccess.Length == 0 @@ -119,4 +131,4 @@ namespace Umbraco.Web.Editors return Attempt.Succeed(); } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Web/Editors/UserGroupsController.cs b/src/Umbraco.Web/Editors/UserGroupsController.cs index 66011e01b2..7d08560b6f 100644 --- a/src/Umbraco.Web/Editors/UserGroupsController.cs +++ b/src/Umbraco.Web/Editors/UserGroupsController.cs @@ -30,6 +30,7 @@ namespace Umbraco.Web.Editors //authorize that the user has access to save this user group var authHelper = new UserGroupEditorAuthorizationHelper( Services.UserService, Services.ContentService, Services.MediaService, Services.EntityService); + var isAuthorized = authHelper.AuthorizeGroupAccess(Security.CurrentUser, userGroupSave.Alias); if (isAuthorized == false) throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.Unauthorized, isAuthorized.Result)); @@ -50,6 +51,14 @@ namespace Umbraco.Web.Editors if (isAuthorized == false) throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.Unauthorized, isAuthorized.Result)); + //current user needs to be added to a new group if not an admin (possibly only if no other users are added?) to avoid a 401 + if(!Security.CurrentUser.IsAdmin() && (userGroupSave.Id == null || Convert.ToInt32(userGroupSave.Id) >= 0)/* && !userGroupSave.Users.Any() */) + { + var userIds = userGroupSave.Users.ToList(); + userIds.Add(Security.CurrentUser.Id); + userGroupSave.Users = userIds; + } + //save the group Services.UserService.Save(userGroupSave.PersistedUserGroup, userGroupSave.Users.ToArray()); @@ -148,4 +157,4 @@ namespace Umbraco.Web.Editors Services.TextService.Localize("speechBubbles/deleteUserGroupSuccess", new[] {userGroups[0].Name})); } } -} \ No newline at end of file +} From 1224f682977d32b0526fa36d0605618b31fdca1f Mon Sep 17 00:00:00 2001 From: Jannik Anker Date: Tue, 2 Oct 2018 18:45:44 +0200 Subject: [PATCH 317/469] Issue 3018 - non-admin users cannot create groups (derpness cleanup) --- src/Umbraco.Web/Editors/UserGroupEditorAuthorizationHelper.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Umbraco.Web/Editors/UserGroupEditorAuthorizationHelper.cs b/src/Umbraco.Web/Editors/UserGroupEditorAuthorizationHelper.cs index 5e6458f93a..1f7601379e 100644 --- a/src/Umbraco.Web/Editors/UserGroupEditorAuthorizationHelper.cs +++ b/src/Umbraco.Web/Editors/UserGroupEditorAuthorizationHelper.cs @@ -53,8 +53,6 @@ namespace Umbraco.Web.Editors if (currentUser.IsAdmin()) return Attempt.Succeed(); - // var derp = ((userGroupSave.Id == null || (int)userGroupSave.Id <= 0) && Services.SectionService.GetAllowedSections(Security.CurrentUser.Id).Select(x => x.Alias).Contains(Constants.Applications.Users)) ? Attempt.Succeed() : Attempt.Failed(); - var existingGroups = _userService.GetUserGroupsByAlias(groupAliases); if(!existingGroups.Any()) From 282ac2b9c5da047cb6b725a74500a18e21890c73 Mon Sep 17 00:00:00 2001 From: christophnz Date: Fri, 14 Dec 2018 22:46:35 +1300 Subject: [PATCH 318/469] Added 2 HtmlHelper extension methods for rendering RelatedLinks, including Unit tests --- .../Mvc/HtmlHelperExtensionMethodsTests.cs | 29 +++++++++++++++-- src/Umbraco.Web/HtmlHelperRenderExtensions.cs | 32 +++++++++++++++++++ 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Tests/Web/Mvc/HtmlHelperExtensionMethodsTests.cs b/src/Umbraco.Tests/Web/Mvc/HtmlHelperExtensionMethodsTests.cs index adf5772f76..e7e4f363c1 100644 --- a/src/Umbraco.Tests/Web/Mvc/HtmlHelperExtensionMethodsTests.cs +++ b/src/Umbraco.Tests/Web/Mvc/HtmlHelperExtensionMethodsTests.cs @@ -29,5 +29,30 @@ namespace Umbraco.Tests.Web.Mvc var output = _htmlHelper.Wrap("div", "hello world", new {style = "color:red;", onclick = "void();"}); Assert.AreEqual("
    hello world
    ", output.ToHtmlString()); } - } -} \ No newline at end of file + + [Test] + public void GetRelatedLinkHtml_Simple() + { + var relatedLink = new Umbraco.Web.Models.RelatedLink { + Caption = "Link Caption", + NewWindow = true, + Link = "https://www.google.com/" + }; + var output = _htmlHelper.GetRelatedLinkHtml(relatedLink); + Assert.AreEqual("Link Caption", output.ToHtmlString()); + } + + [Test] + public void GetRelatedLinkHtml_HtmlAttributes() + { + var relatedLink = new Umbraco.Web.Models.RelatedLink + { + Caption = "Link Caption", + NewWindow = true, + Link = "https://www.google.com/" + }; + var output = _htmlHelper.GetRelatedLinkHtml(relatedLink, new { @class = "test-class"}); + Assert.AreEqual("Link Caption", output.ToHtmlString()); + } + } +} diff --git a/src/Umbraco.Web/HtmlHelperRenderExtensions.cs b/src/Umbraco.Web/HtmlHelperRenderExtensions.cs index 30b4e64e33..90bc97ca19 100644 --- a/src/Umbraco.Web/HtmlHelperRenderExtensions.cs +++ b/src/Umbraco.Web/HtmlHelperRenderExtensions.cs @@ -965,5 +965,37 @@ namespace Umbraco.Web #endregion + #region RelatedLink + + /// + /// Renders an anchor element for a RelatedLink instance. + /// Format: <a href="relatedLink.Link" target="_blank/_self">relatedLink.Caption</a> + /// + /// The HTML helper instance that this method extends. + /// The RelatedLink instance + /// An anchor element + public static MvcHtmlString GetRelatedLinkHtml(this HtmlHelper htmlHelper, RelatedLink relatedLink) + { + return htmlHelper.GetRelatedLinkHtml(relatedLink, null); + } + + /// + /// Renders an anchor element for a RelatedLink instance, accepting htmlAttributes. + /// Format: <a href="relatedLink.Link" target="_blank/_self" htmlAttributes>relatedLink.Caption</a> + /// + /// The HTML helper instance that this method extends. + /// The RelatedLink instance + /// An object that contains the HTML attributes to set for the element. + /// + public static MvcHtmlString GetRelatedLinkHtml(this HtmlHelper htmlHelper, RelatedLink relatedLink, object htmlAttributes) + { + var tagBuilder = new TagBuilder("a"); + tagBuilder.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes)); + tagBuilder.MergeAttribute("href", relatedLink.Link); + tagBuilder.MergeAttribute("target", relatedLink.NewWindow ? "_blank" : "_self"); + tagBuilder.InnerHtml = HttpUtility.HtmlEncode(relatedLink.Caption); + return MvcHtmlString.Create(tagBuilder.ToString(TagRenderMode.Normal)); + } + #endregion } } From 74986d24f15637093bb1b6662ea4351e40e417fc Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Sun, 13 Jan 2019 15:49:37 +0100 Subject: [PATCH 319/469] V8: Add "Move" option for deleted items in the content tree (#3931) --- .../content/content.restore.controller.js | 128 +++++++++++++----- .../src/views/content/restore.html | 109 +++++++++++---- src/Umbraco.Web.UI/Umbraco/config/lang/en.xml | 4 +- .../Umbraco/config/lang/en_us.xml | 4 +- 4 files changed, 180 insertions(+), 65 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/content/content.restore.controller.js b/src/Umbraco.Web.UI.Client/src/views/content/content.restore.controller.js index 859e6281c0..24457f6980 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/content.restore.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/content/content.restore.controller.js @@ -1,26 +1,91 @@ angular.module("umbraco").controller("Umbraco.Editors.Content.RestoreController", - function ($scope, relationResource, contentResource, entityResource, navigationService, appState, treeService, localizationService) { + function ($scope, relationResource, contentResource, entityResource, navigationService, appState, treeService, userService) { $scope.source = _.clone($scope.currentNode); - $scope.error = null; - $scope.success = false; + $scope.error = null; $scope.loading = true; + $scope.moving = false; + $scope.success = false; + + $scope.dialogTreeApi = {}; + $scope.searchInfo = { + showSearch: false, + results: [], + selectedSearchResults: [] + } + $scope.treeModel = { + hideHeader: false + } + userService.getCurrentUser().then(function (userData) { + $scope.treeModel.hideHeader = userData.startContentIds.length > 0 && userData.startContentIds.indexOf(-1) == -1; + }); + + function nodeSelectHandler(args) { + + if (args && args.event) { + args.event.preventDefault(); + args.event.stopPropagation(); + } + + if ($scope.target) { + //un-select if there's a current one selected + $scope.target.selected = false; + } + + $scope.target = args.node; + $scope.target.selected = true; + + } + + function nodeExpandedHandler(args) { + // open mini list view for list views + if (args.node.metaData.isContainer) { + openMiniListView(args.node); + } + } + + $scope.hideSearch = function () { + $scope.searchInfo.showSearch = false; + $scope.searchInfo.results = []; + } + + // method to select a search result + $scope.selectResult = function (evt, result) { + result.selected = result.selected === true ? false : true; + nodeSelectHandler(evt, { event: evt, node: result }); + }; + + //callback when there are search results + $scope.onSearchResults = function (results) { + $scope.searchInfo.results = results; + $scope.searchInfo.showSearch = true; + }; + + $scope.onTreeInit = function () { + $scope.dialogTreeApi.callbacks.treeNodeSelect(nodeSelectHandler); + $scope.dialogTreeApi.callbacks.treeNodeExpanded(nodeExpandedHandler); + } + + // Mini list view + $scope.selectListViewNode = function (node) { + node.selected = node.selected === true ? false : true; + nodeSelectHandler({}, { node: node }); + }; + + $scope.closeMiniListView = function () { + $scope.miniListView = undefined; + }; + + function openMiniListView(node) { + $scope.miniListView = node; + } relationResource.getByChildId($scope.source.id, "relateParentDocumentOnDelete").then(function (data) { $scope.loading = false; if (!data.length) { - localizationService.localizeMany(["recycleBin_itemCannotBeRestored", "recycleBin_noRestoreRelation"]) - .then(function(values) { - $scope.success = false; - $scope.error = { - errorMsg: values[0], - data: { - Message: values[1] - } - } - }); + $scope.moving = true; return; } @@ -30,40 +95,32 @@ angular.module("umbraco").controller("Umbraco.Editors.Content.RestoreController" $scope.target = { id: -1, name: "Root" }; } else { - $scope.loading = true; + $scope.loading = true; + entityResource.getById($scope.relation.parentId, "Document").then(function (data) { $scope.loading = false; - $scope.target = data; - // make sure the target item isn't in the recycle bin - if($scope.target.path.indexOf("-20") !== -1) { - localizationService.localizeMany(["recycleBin_itemCannotBeRestored", "recycleBin_restoreUnderRecycled"]) - .then(function (values) { - $scope.success = false; - $scope.error = { - errorMsg: values[0], - data: { - Message: values[1].replace('%0%', $scope.target.name) - } - } - }); - $scope.success = false; - } + $scope.target = data; + // make sure the target item isn't in the recycle bin + if ($scope.target.path.indexOf("-20") !== -1) { + $scope.moving = true; + $scope.target = null; + } }, function (err) { - $scope.success = false; - $scope.error = err; $scope.loading = false; + $scope.error = err; }); } }, function (err) { - $scope.success = false; - $scope.error = err; + $scope.loading = false; + $scope.error = err; }); $scope.restore = function () { $scope.loading = true; - // this code was copied from `content.move.controller.js` + + // this code was copied from `content.move.controller.js` contentResource.move({ parentId: $scope.target.id, id: $scope.source.id }) .then(function (path) { @@ -88,9 +145,8 @@ angular.module("umbraco").controller("Umbraco.Editors.Content.RestoreController" }); }, function (err) { - $scope.success = false; - $scope.error = err; $scope.loading = false; + $scope.error = err; }); }; diff --git a/src/Umbraco.Web.UI.Client/src/views/content/restore.html b/src/Umbraco.Web.UI.Client/src/views/content/restore.html index 83a69effb6..ead6ed91ab 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/restore.html +++ b/src/Umbraco.Web.UI.Client/src/views/content/restore.html @@ -1,34 +1,93 @@
    -
    - +
    + + + - - +
    +
    +
    {{error.errorMsg}}
    +
    {{error.data.Message}}
    +
    +
    -

    - Restore {{source.name}} under {{target.name}}? -

    +
    +
    + {{source.name}} + was restored under + was moved underneath + {{target.name}} +
    + +
    -
    -
    -
    {{error.errorMsg}}
    -
    {{error.data.Message}}
    -
    -
    +
    -
    -
    - {{source.name}} was moved underneath {{target.name}} -
    - -
    +

    + Restore {{source.name}} under {{target.name}}? +

    - +
    + +
    +
    +
    +
    Cannot automatically restore this item
    +
    There is no location where this item can be automatically restored. You can move the item manually using the tree below.
    +
    +
    + +
    + + + +
    + + + + +
    + + +
    +
    + + + + +
    + +
    - + + +
    diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml index 69f106a775..993286f4c6 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml @@ -1968,8 +1968,8 @@ To manage your website, simply open the Umbraco back office and start adding con Trashed content with Id: {0} related to original parent content with Id: {1} Trashed media with Id: {0} related to original parent media item with Id: {1} Cannot automatically restore this item - There is no 'restore' relation found for this node. Use the Move menu item to move it manually. - The item you want to restore it under ('%0%') is in the recycle bin. Use the Move menu item to move the item manually. + There is no location where this item can be automatically restored. You can move the item manually using the tree below. + was restored under Direction diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml index eaa1c6c39e..b15ff24729 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml @@ -2024,8 +2024,8 @@ To manage your website, simply open the Umbraco back office and start adding con Trashed content with Id: {0} related to original parent content with Id: {1} Trashed media with Id: {0} related to original parent media item with Id: {1} Cannot automatically restore this item - There is no 'restore' relation found for this node. Use the Move menu item to move it manually. - The item you want to restore it under ('%0%') is in the recycle bin. Use the Move menu item to move the item manually. + There is no location where this item can be automatically restored. You can move the item manually using the tree below. + was restored under Direction From 3b8a570c3c3356c745aa8a51d5347e0173d4e03b Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Sun, 13 Jan 2019 15:53:42 +0100 Subject: [PATCH 320/469] V8: Safeguard against invalid culture in UMB_MCULTURE cookie (#4051) --- .../src/controllers/navigation.controller.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/controllers/navigation.controller.js b/src/Umbraco.Web.UI.Client/src/controllers/navigation.controller.js index 335fe99e7c..e023c6d23c 100644 --- a/src/Umbraco.Web.UI.Client/src/controllers/navigation.controller.js +++ b/src/Umbraco.Web.UI.Client/src/controllers/navigation.controller.js @@ -355,7 +355,9 @@ function NavigationController($scope, $rootScope, $location, $log, $q, $routePar if (!currCulture) { // no culture in the request, let's look for one in the cookie that's set when changing language var defaultCulture = $cookies.get("UMB_MCULTURE"); - if (!defaultCulture) { + if (!defaultCulture || !_.find($scope.languages, function (l) { + return l.culture.toLowerCase() === defaultCulture.toLowerCase(); + })) { // no luck either, look for the default language var defaultLang = _.find($scope.languages, function (l) { return l.isDefault; @@ -399,9 +401,10 @@ function NavigationController($scope, $rootScope, $location, $log, $q, $routePar $scope.selectLanguage = function (language) { $location.search("mculture", language.culture); - // add the selected culture to a cookie so the user will log back into the same culture later on (cookie max age is one year = 31536000 seconds) - // NOTE: $cookies doesn't support max-age, so we need to go the good ol' JS way about setting the cookie - document.cookie = "UMB_MCULTURE=" +language.culture + ";path=/;max-age=31536000;"; + // add the selected culture to a cookie so the user will log back into the same culture later on (cookie lifetime = one year) + var expireDate = new Date(); + expireDate.setDate(expireDate.getDate() + 365); + $cookies.put("UMB_MCULTURE", language.culture, {path: "/", expires: expireDate}); // close the language selector $scope.page.languageSelectorIsOpen = false; From be44741bf986c1961fed8ff7119f6e10b1b984fa Mon Sep 17 00:00:00 2001 From: Anders Bjerner Date: Sun, 13 Jan 2019 15:58:31 +0100 Subject: [PATCH 321/469] Localized parts of the codefile and template resources (#3495) --- .../src/common/resources/codefile.resource.js | 17 +++++++++++++---- .../src/common/resources/template.resource.js | 7 +++++-- .../src/views/partialviews/create.html | 2 +- .../src/views/partialviews/delete.controller.js | 6 ++++++ .../src/views/partialviews/delete.html | 7 +++++++ .../src/views/templates/delete.controller.js | 7 +++++++ .../src/views/templates/delete.html | 9 ++++++++- src/Umbraco.Web.UI/umbraco/config/lang/da.xml | 7 +++++++ src/Umbraco.Web.UI/umbraco/config/lang/en.xml | 7 +++++++ .../umbraco/config/lang/en_us.xml | 7 +++++++ 10 files changed, 68 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/codefile.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/codefile.resource.js index 7cd55b268a..c7bbbe9227 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/codefile.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/codefile.resource.js @@ -3,7 +3,7 @@ * @name umbraco.resources.codefileResource * @description Loads in data for files that contain code such as js scripts, partial views and partial view macros **/ -function codefileResource($q, $http, umbDataFormatter, umbRequestHelper) { +function codefileResource($q, $http, umbDataFormatter, umbRequestHelper, localizationService) { return { @@ -106,13 +106,16 @@ function codefileResource($q, $http, umbDataFormatter, umbRequestHelper) { * */ deleteByPath: function (type, virtualpath) { + + var promise = localizationService.localize("codefile_deleteItemFailed", [virtualpath]); + return umbRequestHelper.resourcePromise( $http.post( umbRequestHelper.getApiUrl( "codeFileApiBaseUrl", "Delete", [{ type: type }, { virtualPath: virtualpath}])), - "Failed to delete item: " + virtualpath); + promise); }, /** @@ -236,13 +239,19 @@ function codefileResource($q, $http, umbDataFormatter, umbRequestHelper) { * */ - createContainer: function(type, parentId, name) { + createContainer: function (type, parentId, name) { + + // Is the parent ID numeric? + var key = "codefile_createFolderFailedBy" + (isNaN(parseInt(parentId)) ? "Name" : "Id"); + + var promise = localizationService.localize(key, [parentId]); + return umbRequestHelper.resourcePromise( $http.post(umbRequestHelper.getApiUrl( "codeFileApiBaseUrl", "PostCreateContainer", { type: type, parentId: parentId, name: encodeURIComponent(name) })), - 'Failed to create a folder under parent id ' + parentId); + promise); } }; diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/template.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/template.resource.js index f969864ba1..377bb415fc 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/template.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/template.resource.js @@ -3,7 +3,7 @@ * @name umbraco.resources.templateResource * @description Loads in data for templates **/ -function templateResource($q, $http, umbDataFormatter, umbRequestHelper) { +function templateResource($q, $http, umbDataFormatter, umbRequestHelper, localizationService) { return { @@ -152,13 +152,16 @@ function templateResource($q, $http, umbDataFormatter, umbRequestHelper) { * */ deleteById: function(id) { + + var promise = localizationService.localize("template_deleteByIdFailed", [id]); + return umbRequestHelper.resourcePromise( $http.post( umbRequestHelper.getApiUrl( "templateApiBaseUrl", "DeleteById", [{ id: id }])), - "Failed to delete item " + id); + promise); }, /** diff --git a/src/Umbraco.Web.UI.Client/src/views/partialviews/create.html b/src/Umbraco.Web.UI.Client/src/views/partialviews/create.html index 4d15ab6c01..5cd739adf5 100644 --- a/src/Umbraco.Web.UI.Client/src/views/partialviews/create.html +++ b/src/Umbraco.Web.UI.Client/src/views/partialviews/create.html @@ -57,7 +57,7 @@
    - + diff --git a/src/Umbraco.Web.UI.Client/src/views/partialviews/delete.controller.js b/src/Umbraco.Web.UI.Client/src/views/partialviews/delete.controller.js index b25ac3c7b8..1e615ad0d4 100644 --- a/src/Umbraco.Web.UI.Client/src/views/partialviews/delete.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/partialviews/delete.controller.js @@ -12,6 +12,9 @@ function PartialViewsDeleteController($scope, codefileResource, treeService, nav //mark it for deletion (used in the UI) $scope.currentNode.loading = true; + + // Reset the error message + $scope.error = null; codefileResource.deleteByPath('partialViews', $scope.currentNode.id) .then(function() { @@ -21,6 +24,9 @@ function PartialViewsDeleteController($scope, codefileResource, treeService, nav //TODO: Need to sync tree, etc... treeService.removeNode($scope.currentNode); navigationService.hideMenu(); + }, function (err) { + $scope.currentNode.loading = false; + $scope.error = err; }); }; diff --git a/src/Umbraco.Web.UI.Client/src/views/partialviews/delete.html b/src/Umbraco.Web.UI.Client/src/views/partialviews/delete.html index 0f75e8514e..c0fdf2c77f 100644 --- a/src/Umbraco.Web.UI.Client/src/views/partialviews/delete.html +++ b/src/Umbraco.Web.UI.Client/src/views/partialviews/delete.html @@ -1,6 +1,13 @@
    +
    +
    +
    {{error.errorMsg}}
    +
    {{error.data.message}}
    +
    +
    +

    Are you sure you want to delete {{currentNode.name}} ?

    diff --git a/src/Umbraco.Web.UI.Client/src/views/templates/delete.controller.js b/src/Umbraco.Web.UI.Client/src/views/templates/delete.controller.js index 8995cb1a31..d019a44a10 100644 --- a/src/Umbraco.Web.UI.Client/src/views/templates/delete.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/templates/delete.controller.js @@ -12,6 +12,10 @@ function TemplatesDeleteController($scope, templateResource , treeService, navig //mark it for deletion (used in the UI) $scope.currentNode.loading = true; + + // Reset the error message + $scope.error = null; + templateResource.deleteById($scope.currentNode.id).then(function () { $scope.currentNode.loading = false; @@ -21,6 +25,9 @@ function TemplatesDeleteController($scope, templateResource , treeService, navig //TODO: Need to sync tree, etc... treeService.removeNode($scope.currentNode); navigationService.hideMenu(); + }, function (err) { + $scope.currentNode.loading = false; + $scope.error = err; }); }; diff --git a/src/Umbraco.Web.UI.Client/src/views/templates/delete.html b/src/Umbraco.Web.UI.Client/src/views/templates/delete.html index 34648aa43e..c98677f764 100644 --- a/src/Umbraco.Web.UI.Client/src/views/templates/delete.html +++ b/src/Umbraco.Web.UI.Client/src/views/templates/delete.html @@ -1,11 +1,18 @@
    +
    +
    +
    {{error.errorMsg}}
    +
    {{error.data.message}}
    +
    +
    +

    Are you sure you want to delete {{currentNode.name}} ?

    - +
    diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/da.xml b/src/Umbraco.Web.UI/umbraco/config/lang/da.xml index 658dd091f6..b4ab08422e 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/da.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/da.xml @@ -182,6 +182,11 @@ Overførsel af egenskaber kunne ikke fuldføres, da en eller flere egenskaber er indstillet til at blive overført mere end én gang. Kun andre dokumenttyper, der er gyldige på denne placering, vises. + + Oprettelse af mappen under parent med ID %0% fejlede + Oprettelse af mappen under parent med navnet %0% fejlede + Sletning af filen/mappen fejlede: %0% + Udgivet Om siden @@ -282,6 +287,7 @@ Hvor ønsker du at oprette den nye %0% Opret under Vælg den dokumenttype, du vil oprette en indholdsskabelon til + Angiv et navn for mappen Vælg en type og skriv en titel "dokument typer".]]> "media typer".]]> @@ -1158,6 +1164,7 @@ Mange hilsner fra Umbraco robotten + Sletning af skabelonen med ID %0% fejlede Rediger skabelon Sektioner diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml index cd5f32da0d..7d3bfa7c99 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml @@ -188,6 +188,11 @@ Could not complete property mapping as one or more properties have more than one mapping defined. Only alternate types valid for the current location are displayed. + + Failed to create a folder under parent with ID %0% + Failed to create a folder under parent with name %0% + Failed to delete item: %0% + Is Published About this page @@ -290,6 +295,7 @@ Where do you want to create the new %0% Create an item under Select the document type you want to make a content template for + Enter a folder name Choose a type and a title "document types".]]> "media types".]]> @@ -1483,6 +1489,7 @@ To manage your website, simply open the Umbraco back office and start adding con + Failed to delete template with ID %0% Edit template Sections diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml index 88b736a34f..0a1756038f 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml @@ -189,6 +189,11 @@ Could not complete property mapping as one or more properties have more than one mapping defined. Only alternate types valid for the current location are displayed. + + Failed to create a folder under parent with ID %0% + Failed to create a folder under parent with name %0% + Failed to delete item: %0% + Is Published About this page @@ -292,6 +297,7 @@ Where do you want to create the new %0% Create an item under Select the document type you want to make a content template for + Enter a folder name Choose a type and a title "document types".]]> "media types".]]> @@ -1481,6 +1487,7 @@ To manage your website, simply open the Umbraco back office and start adding con Styles + Failed to delete template with ID %0% Edit template Sections From 941baf09cefe0cf32aae027c17f820f68e1390b9 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Sun, 13 Jan 2019 16:17:44 +0100 Subject: [PATCH 322/469] Fix linkpicker overlay issues (#3718) --- .../linkpicker/linkpicker.controller.js | 41 +++++++++++-------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/linkpicker/linkpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/linkpicker/linkpicker.controller.js index 7b890edbf4..fcce34621b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/linkpicker/linkpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/linkpicker/linkpicker.controller.js @@ -25,30 +25,31 @@ angular.module("umbraco").controller("Umbraco.Overlays.LinkPickerController", $scope.showTarget = $scope.model.hideTarget !== true; if (dialogOptions.currentTarget) { - $scope.model.target = dialogOptions.currentTarget; + // clone the current target so we don't accidentally update the caller's model while manipulating $scope.model.target + $scope.model.target = angular.copy(dialogOptions.currentTarget); //if we have a node ID, we fetch the current node to build the form data if ($scope.model.target.id || $scope.model.target.udi) { //will be either a udi or an int var id = $scope.model.target.udi ? $scope.model.target.udi : $scope.model.target.id; - if (!$scope.model.target.path) { + // is it a content link? + if (!$scope.model.target.isMedia) { + // get the content path + entityResource.getPath(id, "Document").then(function(path) { + //now sync the tree to this path + $scope.dialogTreeEventHandler.syncTree({ + path: path, + tree: "content" + }); + }); - entityResource.getPath(id, "Document").then(function (path) { - $scope.model.target.path = path; - //now sync the tree to this path - $scope.dialogTreeEventHandler.syncTree({ - path: $scope.model.target.path, - tree: "content" - }); - }); - } - - // if a link exists, get the properties to build the anchor name list - contentResource.getById(id).then(function (resp) { - $scope.model.target.url = resp.urls[0]; - $scope.anchorValues = tinyMceService.getAnchorNames(JSON.stringify(resp.properties)); - }); + // get the content properties to build the anchor name list + contentResource.getById(id).then(function (resp) { + $scope.model.target.url = resp.urls[0]; + $scope.anchorValues = tinyMceService.getAnchorNames(JSON.stringify(resp.properties)); + }); + } } else if ($scope.model.target.url.length) { // a url but no id/udi indicates an external link - trim the url to remove the anchor/qs // only do the substring if there's a # or a ? @@ -122,6 +123,12 @@ angular.module("umbraco").controller("Umbraco.Overlays.LinkPickerController", $scope.mediaPickerOverlay.show = false; $scope.mediaPickerOverlay = null; + + // make sure the content tree has nothing highlighted + $scope.dialogTreeEventHandler.syncTree({ + path: "-1", + tree: "content" + }); } }; }); From 18c90c532574ae4630b3f58e2080471b6d9a3084 Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 14 Jan 2019 14:28:00 +1100 Subject: [PATCH 323/469] Package file installation logic all migrated and tests are running, now to do the package data installation --- .../Composing/Composers/ServicesComposer.cs | 10 + .../Models/Packaging/CompiledPackage.cs | 23 +- .../Models/Packaging/InstallationSummary.cs | 70 +- .../Models/Packaging/PackageDefinition.cs | 31 + .../Models/Packaging/PreInstallWarnings.cs | 15 +- .../Packaging/CompiledPackageXmlParser.cs | 150 ++ .../Packaging/ConflictingPackageData.cs | 61 +- .../Packaging/IConflictingPackageData.cs | 13 - .../Packaging/IPackageExtraction.cs | 62 - .../Packaging/IPackageInstallation.cs | 34 +- .../Packaging/PackageDefinitionXmlParser.cs | 54 - .../Packaging/PackageExtraction.cs | 76 +- .../Packaging/PackageFileInstallation.cs | 63 + .../Packaging/PackageInstallation.cs | 574 ++----- .../Services/IPackagingService.cs | 36 +- .../Services/Implement/PackagingService.cs | 56 +- src/Umbraco.Core/Umbraco.Core.csproj | 6 +- .../CreatedPackagesRepositoryTests.cs | 8 +- .../Packaging/PackageExtractionTests.cs | 4 +- .../Packaging/PackageInstallationTest.cs | 151 +- .../Services/PackagingServiceTests.cs | 49 +- .../views/packages/views/install-local.html | 2 +- .../src/views/packages/views/repo.html | 2 +- src/Umbraco.Web/Composing/Current.cs | 4 +- .../Editors/PackageInstallController.cs | 72 +- .../Controllers/InstallPackageController.cs | 58 +- .../InstallSteps/StarterKitCleanupStep.cs | 16 +- .../InstallSteps/StarterKitDownloadStep.cs | 31 +- .../InstallSteps/StarterKitInstallStep.cs | 24 +- .../Install/Models/InstallPackageModel.cs | 6 +- .../Models/LocalPackageInstallModel.cs | 19 +- src/Umbraco.Web/Models/PackageInstallModel.cs | 3 +- src/Umbraco.Web/Umbraco.Web.csproj | 1 - src/Umbraco.Web/_Legacy/Packager/Installer.cs | 1471 ++++++++--------- src/Umbraco.Web/_Legacy/Packager/Settings.cs | 13 - 35 files changed, 1534 insertions(+), 1734 deletions(-) create mode 100644 src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs delete mode 100644 src/Umbraco.Core/Packaging/IConflictingPackageData.cs delete mode 100644 src/Umbraco.Core/Packaging/IPackageExtraction.cs create mode 100644 src/Umbraco.Core/Packaging/PackageFileInstallation.cs delete mode 100644 src/Umbraco.Web/_Legacy/Packager/Settings.cs diff --git a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs index 98f239de3b..ac8f4beeb0 100644 --- a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs @@ -61,8 +61,18 @@ namespace Umbraco.Core.Composing.Composers composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); composition.RegisterUnique(factory => CreatePackageRepository(factory, "createdPackages.config")); composition.RegisterUnique(factory => CreatePackageRepository(factory, "installedPackages.config")); + composition.RegisterUnique(); + var appRoot = new DirectoryInfo(IOHelper.GetRootDirectorySafe()); + composition.RegisterUnique(factory => //factory required because we need to pass in a string path + new PackageInstallation( + factory.GetInstance(), factory.GetInstance(), + factory.GetInstance(), + SystemDirectories.Packages, + appRoot, appRoot)); //TODO: These are replaced in the web project - we need to declare them so that // something is wired up, just not sure this is very nice but will work for now. diff --git a/src/Umbraco.Core/Models/Packaging/CompiledPackage.cs b/src/Umbraco.Core/Models/Packaging/CompiledPackage.cs index cb3fbd7eee..96159d1bbf 100644 --- a/src/Umbraco.Core/Models/Packaging/CompiledPackage.cs +++ b/src/Umbraco.Core/Models/Packaging/CompiledPackage.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Xml.Linq; namespace Umbraco.Core.Models.Packaging { @@ -9,32 +10,31 @@ namespace Umbraco.Core.Models.Packaging ///
    public class CompiledPackage : IPackageInfo { + public string PackageFileName { get; set; } + public string Name { get; set; } - public string Version { get; set; } - public string Url { get; set; } - public string License { get; set; } - public string LicenseUrl { get; set; } - public Version UmbracoVersion { get; set; } - public RequirementsType UmbracoVersionRequirementsType { get; set; } - public string Author { get; set; } - public string AuthorUrl { get; set; } - public string Readme { get; set; } - public string Control { get; set; } - public string IconUrl { get; set; } + public string Actions { get; set; } //fixme: Should we make this strongly typed to IEnumerable ? + + public PreInstallWarnings Warnings { get; set; } = new PreInstallWarnings(); + public List Files { get; set; } = new List(); + public IEnumerable Macros { get; set; } //fixme: make strongly typed + public IEnumerable Templates { get; set; } //fixme: make strongly typed + public IEnumerable Stylesheets { get; set; } //fixme: make strongly typed + } public class CompiledPackageFile @@ -42,6 +42,7 @@ namespace Umbraco.Core.Models.Packaging public string OriginalPath { get; set; } public string UniqueFileName { get; set; } public string OriginalName { get; set; } + } diff --git a/src/Umbraco.Core/Models/Packaging/InstallationSummary.cs b/src/Umbraco.Core/Models/Packaging/InstallationSummary.cs index ddecf53653..1405259da2 100644 --- a/src/Umbraco.Core/Models/Packaging/InstallationSummary.cs +++ b/src/Umbraco.Core/Models/Packaging/InstallationSummary.cs @@ -24,44 +24,44 @@ namespace Umbraco.Core.Models.Packaging public IEnumerable Actions { get; set; } = Enumerable.Empty(); public bool PackageInstalled { get; set; } - public static InstallationSummary FromPackageDefinition(PackageDefinition def, IContentTypeService contentTypeService, IDataTypeService dataTypeService, IFileService fileService, ILocalizationService localizationService, IMacroService macroService) - { - var macros = TryGetIntegerIds(def.Macros).Select(macroService.GetById).ToList(); - var templates = TryGetIntegerIds(def.Templates).Select(fileService.GetTemplate).ToList(); - var contentTypes = TryGetIntegerIds(def.DocumentTypes).Select(contentTypeService.Get).ToList(); // fixme - media types? - var dataTypes = TryGetIntegerIds(def.DataTypes).Select(dataTypeService.GetDataType).ToList(); - var dictionaryItems = TryGetIntegerIds(def.DictionaryItems).Select(localizationService.GetDictionaryItemById).ToList(); - var languages = TryGetIntegerIds(def.Languages).Select(localizationService.GetLanguageById).ToList(); + //public static InstallationSummary FromPackageDefinition(PackageDefinition def, IContentTypeService contentTypeService, IDataTypeService dataTypeService, IFileService fileService, ILocalizationService localizationService, IMacroService macroService) + //{ + // var macros = TryGetIntegerIds(def.Macros).Select(macroService.GetById).ToList(); + // var templates = TryGetIntegerIds(def.Templates).Select(fileService.GetTemplate).ToList(); + // var contentTypes = TryGetIntegerIds(def.DocumentTypes).Select(contentTypeService.Get).ToList(); // fixme - media types? + // var dataTypes = TryGetIntegerIds(def.DataTypes).Select(dataTypeService.GetDataType).ToList(); + // var dictionaryItems = TryGetIntegerIds(def.DictionaryItems).Select(localizationService.GetDictionaryItemById).ToList(); + // var languages = TryGetIntegerIds(def.Languages).Select(localizationService.GetLanguageById).ToList(); - for (var i = 0; i < def.Files.Count; i++) - { - var filePath = def.Files[i]; - def.Files[i] = filePath.GetRelativePath(); - } + // for (var i = 0; i < def.Files.Count; i++) + // { + // var filePath = def.Files[i]; + // def.Files[i] = filePath.GetRelativePath(); + // } - return new InstallationSummary - { - ContentTypesInstalled = contentTypes, - DataTypesInstalled = dataTypes, - DictionaryItemsInstalled = dictionaryItems, - FilesInstalled = def.Files, - LanguagesInstalled = languages, - MacrosInstalled = macros, - MetaData = def, - TemplatesInstalled = templates, - }; - } + // return new InstallationSummary + // { + // ContentTypesInstalled = contentTypes, + // DataTypesInstalled = dataTypes, + // DictionaryItemsInstalled = dictionaryItems, + // FilesInstalled = def.Files, + // LanguagesInstalled = languages, + // MacrosInstalled = macros, + // MetaData = def, + // TemplatesInstalled = templates, + // }; + //} - private static IEnumerable TryGetIntegerIds(IEnumerable ids) - { - var intIds = new List(); - foreach (var id in ids) - { - if (int.TryParse(id, out var parsed)) - intIds.Add(parsed); - } - return intIds; - } + //private static IEnumerable TryGetIntegerIds(IEnumerable ids) + //{ + // var intIds = new List(); + // foreach (var id in ids) + // { + // if (int.TryParse(id, out var parsed)) + // intIds.Add(parsed); + // } + // return intIds; + //} } } diff --git a/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs b/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs index 65e26419f0..56a316ff81 100644 --- a/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs +++ b/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.DataAnnotations; +using System.Linq; using System.Runtime.Serialization; namespace Umbraco.Core.Models.Packaging @@ -9,6 +10,35 @@ namespace Umbraco.Core.Models.Packaging [DataContract(Name = "packageInstance")] public class PackageDefinition : IPackageInfo { + /// + /// Converts a model to a model + /// + /// + /// + /// + /// This is used only for conversions and will not 'get' a PackageDefinition from the repository with a valid ID + /// + internal static PackageDefinition FromCompiledPackage(CompiledPackage compiled) + { + return new PackageDefinition + { + Actions = compiled.Actions, + Author = compiled.Author, + AuthorUrl = compiled.AuthorUrl, + Control = compiled.Control, + IconUrl = compiled.IconUrl, + License = compiled.License, + LicenseUrl = compiled.LicenseUrl, + Name = compiled.Name, + Readme = compiled.Readme, + UmbracoVersion = compiled.UmbracoVersion, + Url = compiled.Url, + Version = compiled.Version, + //fixme: Is OriginalPath correct here? + Files = compiled.Files.Select(x => x.OriginalPath).ToList() + }; + } + [DataMember(Name = "id")] public int Id { get; set; } @@ -24,6 +54,7 @@ namespace Umbraco.Core.Models.Packaging [Url] public string Url { get; set; } = string.Empty; + //fixme: remove this /// /// This is a generated GUID which is used to determine a temporary folder name for processing the package /// diff --git a/src/Umbraco.Core/Models/Packaging/PreInstallWarnings.cs b/src/Umbraco.Core/Models/Packaging/PreInstallWarnings.cs index 5850e2321c..18b63ced88 100644 --- a/src/Umbraco.Core/Models/Packaging/PreInstallWarnings.cs +++ b/src/Umbraco.Core/Models/Packaging/PreInstallWarnings.cs @@ -1,17 +1,16 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Runtime.Serialization; namespace Umbraco.Core.Models.Packaging { - [Serializable] - [DataContract(IsReference = true)] - internal class PreInstallWarnings + public class PreInstallWarnings { - public KeyValuePair[] UnsecureFiles { get; set; } - public KeyValuePair[] FilesReplaced { get; set; } - public IEnumerable ConflictingMacroAliases { get; set; } - public IEnumerable ConflictingTemplateAliases { get; set; } - public IEnumerable ConflictingStylesheetNames { get; set; } + public IEnumerable UnsecureFiles { get; set; } = Enumerable.Empty(); + public IEnumerable FilesReplaced { get; set; } = Enumerable.Empty(); + public IEnumerable ConflictingMacros { get; set; } = Enumerable.Empty(); + public IEnumerable ConflictingTemplates { get; set; } = Enumerable.Empty(); + public IEnumerable ConflictingStylesheets { get; set; } = Enumerable.Empty(); } } diff --git a/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs b/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs new file mode 100644 index 0000000000..44dbded5d2 --- /dev/null +++ b/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs @@ -0,0 +1,150 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Xml.Linq; +using Umbraco.Core.IO; +using Umbraco.Core.Models; +using Umbraco.Core.Models.Packaging; +using File = System.IO.File; + +namespace Umbraco.Core.Packaging +{ + /// + /// Parses the xml document contained in a compiled (zip) Umbraco package + /// + internal class CompiledPackageXmlParser + { + private readonly ConflictingPackageData _conflictingPackageData; + + public CompiledPackageXmlParser(ConflictingPackageData conflictingPackageData) + { + _conflictingPackageData = conflictingPackageData; + } + + public CompiledPackage ToCompiledPackage(XDocument xml, string packageFileName, string applicationRootFolder) + { + if (xml == null) throw new ArgumentNullException(nameof(xml)); + if (xml.Root == null) throw new ArgumentException(nameof(xml), "The xml document is invalid"); + if (xml.Root.Name != Constants.Packaging.UmbPackageNodeName) throw new FormatException("The xml document is invalid"); + + var info = xml.Root.Element("info"); + if (info == null) throw new FormatException("The xml document is invalid"); + var package = info.Element("package"); + if (package == null) throw new FormatException("The xml document is invalid"); + var author = info.Element("author"); + if (author == null) throw new FormatException("The xml document is invalid"); + var requirements = package.Element("requirements"); + if (requirements == null) throw new FormatException("The xml document is invalid"); + + var def = new CompiledPackage + { + PackageFileName = packageFileName, + Name = package.Element("name")?.Value, + Author = author.Element("name")?.Value, + AuthorUrl = author.Element("website")?.Value, + Version = package.Element("version")?.Value, + Readme = info.Element("readme")?.Value, + License = package.Element("license")?.Value, + LicenseUrl = package.Element("license")?.AttributeValue("url"), + Url = package.Element("url")?.Value, + IconUrl = package.Element("iconUrl")?.Value, + UmbracoVersion = new Version((int)requirements.Element("major"), (int)requirements.Element("minor"), (int)requirements.Element("patch")), + UmbracoVersionRequirementsType = requirements.AttributeValue("type").IsNullOrWhiteSpace() ? RequirementsType.Legacy : Enum.Parse(requirements.AttributeValue("type")), + Control = package.Element("control")?.Value, + Actions = xml.Element("Actions")?.ToString(SaveOptions.None) ?? "", //take the entire outer xml value + + Files = xml.Root.Element("files")?.Elements("file")?.Select(x => new CompiledPackageFile + { + UniqueFileName = x.Element("guid")?.Value, + OriginalName = x.Element("orgName")?.Value, + OriginalPath = x.Element("orgPath")?.Value + }).ToList() ?? new List(), + + Macros = xml.Element("Macros")?.Elements("macro") ?? Enumerable.Empty(), + Templates = xml.Element("Templates")?.Elements("Template") ?? Enumerable.Empty(), + Stylesheets = xml.Element("Stylesheets")?.Elements("styleSheet") ?? Enumerable.Empty(), + + }; + + def.Warnings = GetPreInstallWarnings(def, applicationRootFolder); + + return def; + } + + private PreInstallWarnings GetPreInstallWarnings(CompiledPackage package, string applicationRootFolder) + { + var sourceDestination = ExtractSourceDestinationFileInformation(package.Files); + + var installWarnings = new PreInstallWarnings + { + ConflictingMacros = _conflictingPackageData.FindConflictingMacros(package.Macros), + ConflictingTemplates = _conflictingPackageData.FindConflictingTemplates(package.Templates), + ConflictingStylesheets = _conflictingPackageData.FindConflictingStylesheets(package.Stylesheets), + UnsecureFiles = FindUnsecureFiles(sourceDestination), + FilesReplaced = FindFilesToBeReplaced(sourceDestination, applicationRootFolder) + }; + + return installWarnings; + } + + /// + /// Returns a tuple of the zip file's unique file name and it's application relative path + /// + /// + /// + public (string packageUniqueFile, string appRelativePath)[] ExtractSourceDestinationFileInformation(IEnumerable packageFiles) + { + return packageFiles + .Select(e => + { + var fileName = PrepareAsFilePathElement(e.OriginalName); + var relativeDir = UpdatePathPlaceholders(PrepareAsFilePathElement(e.OriginalPath)); + var relativePath = Path.Combine(relativeDir, fileName); + return (e.UniqueFileName, relativePath); + }).ToArray(); + } + + private IEnumerable FindFilesToBeReplaced(IEnumerable<(string packageUniqueFile, string appRelativePath)> sourceDestination, string applicationRootFolder) + { + return sourceDestination.Where(sd => File.Exists(Path.Combine(applicationRootFolder, sd.appRelativePath))) + .Select(x => x.appRelativePath) + .ToArray(); + } + + private IEnumerable FindUnsecureFiles(IEnumerable<(string packageUniqueFile, string appRelativePath)> sourceDestinationPair) + { + return sourceDestinationPair.Where(sd => IsFileDestinationUnsecure(sd.appRelativePath)) + .Select(x => x.appRelativePath) + .ToList(); + } + + private bool IsFileDestinationUnsecure(string destination) + { + var unsecureDirNames = new[] { "bin", "app_code" }; + if (unsecureDirNames.Any(ud => destination.StartsWith(ud, StringComparison.InvariantCultureIgnoreCase))) + return true; + + string extension = Path.GetExtension(destination); + return extension != null && extension.Equals(".dll", StringComparison.InvariantCultureIgnoreCase); + } + + private static string PrepareAsFilePathElement(string pathElement) + { + return pathElement.TrimStart(new[] { '\\', '/', '~' }).Replace("/", "\\"); + } + + //fixme: This is duplicated in the parser + public static string UpdatePathPlaceholders(string path) + { + if (path.Contains("[$")) + { + //this is experimental and undocumented... + path = path.Replace("[$UMBRACO]", SystemDirectories.Umbraco); + path = path.Replace("[$CONFIG]", SystemDirectories.Config); + path = path.Replace("[$DATA]", SystemDirectories.Data); + } + return path; + } + } +} diff --git a/src/Umbraco.Core/Packaging/ConflictingPackageData.cs b/src/Umbraco.Core/Packaging/ConflictingPackageData.cs index b0424067bf..401d3b6a85 100644 --- a/src/Umbraco.Core/Packaging/ConflictingPackageData.cs +++ b/src/Umbraco.Core/Packaging/ConflictingPackageData.cs @@ -7,82 +7,53 @@ using Umbraco.Core.Services; namespace Umbraco.Core.Packaging { - internal class ConflictingPackageData : IConflictingPackageData + internal class ConflictingPackageData { private readonly IMacroService _macroService; private readonly IFileService _fileService; - public ConflictingPackageData(IMacroService macroService, - IFileService fileService) + public ConflictingPackageData(IMacroService macroService, IFileService fileService) { - if (fileService != null) _fileService = fileService; - else throw new ArgumentNullException("fileService"); - if (macroService != null) _macroService = macroService; - else throw new ArgumentNullException("macroService"); + _fileService = fileService ?? throw new ArgumentNullException(nameof(fileService)); + _macroService = macroService ?? throw new ArgumentNullException(nameof(macroService)); } - public IEnumerable FindConflictingStylesheets(XElement stylesheetNotes) + public IEnumerable FindConflictingStylesheets(IEnumerable stylesheetNodes) { - if (string.Equals(Constants.Packaging.StylesheetsNodeName, stylesheetNotes.Name.LocalName) == false) - { - throw new ArgumentException("the root element must be \"" + Constants.Packaging.StylesheetsNodeName + "\"", "stylesheetNotes"); - } - - return stylesheetNotes.Elements(Constants.Packaging.StylesheetNodeName) + return stylesheetNodes .Select(n => { - XElement xElement = n.Element(Constants.Packaging.NameNodeName); + var xElement = n.Element(Constants.Packaging.NameNodeName); if (xElement == null) - { - throw new ArgumentException("Missing \"" + Constants.Packaging.NameNodeName + "\" element", - "stylesheetNotes"); - } + throw new FormatException($"Missing \"{Constants.Packaging.NameNodeName}\" element"); return _fileService.GetStylesheetByName(xElement.Value) as IFile; }) .Where(v => v != null); } - public IEnumerable FindConflictingTemplates(XElement templateNotes) + public IEnumerable FindConflictingTemplates(IEnumerable templateNodes) { - if (string.Equals(Constants.Packaging.TemplatesNodeName, templateNotes.Name.LocalName) == false) - { - throw new ArgumentException("Node must be a \"" + Constants.Packaging.TemplatesNodeName + "\" node", - "templateNotes"); - } - - return templateNotes.Elements(Constants.Packaging.TemplateNodeName) + return templateNodes .Select(n => { - XElement xElement = n.Element(Constants.Packaging.AliasNodeNameCapital) ?? n.Element(Constants.Packaging.AliasNodeNameSmall); + var xElement = n.Element(Constants.Packaging.AliasNodeNameCapital) ?? n.Element(Constants.Packaging.AliasNodeNameSmall); if (xElement == null) - { - throw new ArgumentException("missing a \"" + Constants.Packaging.AliasNodeNameCapital + "\" element", - "templateNotes"); - } + throw new FormatException($"missing a \"{Constants.Packaging.AliasNodeNameCapital}\" element"); return _fileService.GetTemplate(xElement.Value); }) .Where(v => v != null); } - public IEnumerable FindConflictingMacros(XElement macroNodes) + public IEnumerable FindConflictingMacros(IEnumerable macroNodes) { - if (string.Equals(Constants.Packaging.MacrosNodeName, macroNodes.Name.LocalName) == false) - { - throw new ArgumentException("Node must be a \"" + Constants.Packaging.MacrosNodeName + "\" node", - "macroNodes"); - } - - return macroNodes.Elements(Constants.Packaging.MacroNodeName) + return macroNodes .Select(n => { - XElement xElement = n.Element(Constants.Packaging.AliasNodeNameSmall) ?? n.Element(Constants.Packaging.AliasNodeNameCapital); + var xElement = n.Element(Constants.Packaging.AliasNodeNameSmall) ?? n.Element(Constants.Packaging.AliasNodeNameCapital); if (xElement == null) - { - throw new ArgumentException(string.Format("missing a \"{0}\" element in {0} element", Constants.Packaging.AliasNodeNameSmall), - "macroNodes"); - } + throw new FormatException($"missing a \"{Constants.Packaging.AliasNodeNameSmall}\" element in {Constants.Packaging.AliasNodeNameSmall} element"); return _macroService.GetByAlias(xElement.Value); }) diff --git a/src/Umbraco.Core/Packaging/IConflictingPackageData.cs b/src/Umbraco.Core/Packaging/IConflictingPackageData.cs deleted file mode 100644 index 12f3e8f8a4..0000000000 --- a/src/Umbraco.Core/Packaging/IConflictingPackageData.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Collections.Generic; -using System.Xml.Linq; -using Umbraco.Core.Models; - -namespace Umbraco.Core.Packaging -{ - internal interface IConflictingPackageData - { - IEnumerable FindConflictingStylesheets(XElement stylesheetNotes); - IEnumerable FindConflictingTemplates(XElement templateNotes); - IEnumerable FindConflictingMacros(XElement macroNodes); - } -} diff --git a/src/Umbraco.Core/Packaging/IPackageExtraction.cs b/src/Umbraco.Core/Packaging/IPackageExtraction.cs deleted file mode 100644 index 02e98dc539..0000000000 --- a/src/Umbraco.Core/Packaging/IPackageExtraction.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System.Collections.Generic; - -namespace Umbraco.Core.Packaging -{ - /// - /// Used to access an umbraco package (zip) file - /// Remeber that filenames must be unique - /// use "FindDubletFileNames" for sanitycheck - /// - internal interface IPackageExtraction - { - /// - /// Returns the content of the file with the given filename - /// - /// Full path to the umbraco package file - /// filename of the file for wich to get the text content - /// this is the relative directory for the location of the file in the package - /// I dont know why umbraco packages contains directories in the first place?? - /// text content of the file - string ReadTextFileFromArchive(string packageFilePath, string fileToRead, out string directoryInPackage); - - /// - /// Copies a file from package to given destination - /// - /// Full path to the ubraco package file - /// filename of the file to copy - /// destination path (including destination filename) - /// True a file was overwritten - void CopyFileFromArchive(string packageFilePath, string fileInPackageName, string destinationfilePath); - - /// - /// Copies a file from package to given destination - /// - /// Full path to the ubraco package file - /// Key: Source file in package. Value: Destination path inclusive file name - void CopyFilesFromArchive(string packageFilePath, IEnumerable> sourceDestination); - - /// - /// Check if given list of files can be found in the package - /// - /// Full path to the umbraco package file - /// a list of files you would like to find in the package - /// a subset if any of the files in "expectedFiles" that could not be found in the package - IEnumerable FindMissingFiles(string packageFilePath, IEnumerable expectedFiles); - - - /// - /// Sanitycheck - should return en empty collection if package is valid - /// - /// Full path to the umbraco package file - /// list of files that are found more than ones (accross directories) in the package - IEnumerable FindDubletFileNames(string packageFilePath); - - /// - /// Reads the given files from archive and returns them as a collection of byte arrays - /// - /// - /// - /// - IEnumerable ReadFilesFromArchive(string packageFilePath, IEnumerable filesToGet); - } -} diff --git a/src/Umbraco.Core/Packaging/IPackageInstallation.cs b/src/Umbraco.Core/Packaging/IPackageInstallation.cs index e8950390e4..8ef3546c3d 100644 --- a/src/Umbraco.Core/Packaging/IPackageInstallation.cs +++ b/src/Umbraco.Core/Packaging/IPackageInstallation.cs @@ -1,15 +1,35 @@ -using System.Xml.Linq; +using System.Collections.Generic; +using System.Xml.Linq; using Umbraco.Core.Models.Packaging; namespace Umbraco.Core.Packaging { internal interface IPackageInstallation { - //fixme: The reason why this isn't used currently is because package installation needs to be done in phases since - // there are app domain reboots involved so a single method cannot be used. This needs to either be split into several - // methods or return an object with a callback to proceed to the next step. - InstallationSummary InstallPackage(string packageFilePath, int userId); - IPackageInfo GetMetaData(string packageFilePath); - PreInstallWarnings GetPreInstallWarnings(string packageFilePath); + + /// + /// Installs a packages data and entities + /// + /// + /// + /// + /// + InstallationSummary InstallPackageData(PackageDefinition packageDefinition, CompiledPackage compiledPackage, int userId); + + /// + /// Installs a packages files + /// + /// + /// + /// + /// + IEnumerable InstallPackageFiles(PackageDefinition packageDefinition, CompiledPackage compiledPackage, int userId); + + /// + /// Reads the package (zip) file and returns the model + /// + /// + /// + CompiledPackage ReadPackage(string packageFileName); } } diff --git a/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs b/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs index 6f3e4a3603..9a996d201f 100644 --- a/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs +++ b/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs @@ -8,60 +8,6 @@ using Umbraco.Core.Models.Packaging; namespace Umbraco.Core.Packaging { - /// - /// Parses the xml document contained in a compiled (zip) Umbraco package - /// - public class CompiledPackageXmlParser - { - public CompiledPackageXmlParser() - { - - } - - public CompiledPackage ToCompiledPackage(XDocument xml) - { - if (xml == null) throw new ArgumentNullException(nameof(xml)); - if (xml.Root == null) throw new ArgumentException(nameof(xml), "The xml document is invalid"); - if (xml.Root.Name != Constants.Packaging.UmbPackageNodeName) throw new FormatException("The xml document is invalid"); - - var info = xml.Root.Element("info"); - if (info == null) throw new FormatException("The xml document is invalid"); - var package = xml.Element("package"); - if (package == null) throw new FormatException("The xml document is invalid"); - var author = package.Element("author"); - if (author == null) throw new FormatException("The xml document is invalid"); - var requirements = package.Element("requirements"); - if (requirements == null) throw new FormatException("The xml document is invalid"); - - var def = new CompiledPackage - { - Name = package.Element("name")?.Value, - Author = author.Element("name")?.Value, - AuthorUrl = author.Element("website")?.Value, - Version = package.Element("version")?.Value, - Readme = info.Element("readme")?.Value, - License = package.Element("license")?.Value, - LicenseUrl = package.Element("license")?.AttributeValue("url"), - Url = package.Element("url")?.Value, - IconUrl = package.Element("iconUrl")?.Value, - UmbracoVersion = new Version((int)requirements.Element("major"), (int)requirements.Element("minor"), (int)requirements.Element("patch")), - UmbracoVersionRequirementsType = Enum.Parse(requirements.AttributeValue("type")), - Control = package.Element("control")?.Value, - - Files = xml.Root.Element("files")?.Elements("files")?.Select(x => new CompiledPackageFile - { - UniqueFileName = x.Element("guid")?.Value, - OriginalName = x.Element("orgPath")?.Value, - OriginalPath = x.Element("orgName")?.Value - }).ToList() ?? new List(), - - }; - - return def; - } - - } - /// /// Converts a to and from XML /// diff --git a/src/Umbraco.Core/Packaging/PackageExtraction.cs b/src/Umbraco.Core/Packaging/PackageExtraction.cs index cc3c394732..48093da45f 100644 --- a/src/Umbraco.Core/Packaging/PackageExtraction.cs +++ b/src/Umbraco.Core/Packaging/PackageExtraction.cs @@ -6,15 +6,15 @@ using System.IO.Compression; namespace Umbraco.Core.Packaging { - internal class PackageExtraction : IPackageExtraction + internal class PackageExtraction { - public string ReadTextFileFromArchive(string packageFilePath, string fileToRead, out string directoryInPackage) + public string ReadTextFileFromArchive(FileInfo packageFile, string fileToRead, out string directoryInPackage) { string retVal = null; bool fileFound = false; string foundDir = null; - ReadZipfileEntries(packageFilePath, entry => + ReadZipfileEntries(packageFile, entry => { string fileName = Path.GetFileName(entry.Name); @@ -36,55 +36,50 @@ namespace Umbraco.Core.Packaging if (fileFound == false) { directoryInPackage = null; - throw new FileNotFoundException(string.Format("Could not find file in package {0}", packageFilePath), fileToRead); + throw new FileNotFoundException($"Could not find file in package {packageFile}", fileToRead); } directoryInPackage = foundDir; return retVal; } - private static void CheckPackageExists(string packageFilePath) + private static void CheckPackageExists(FileInfo packageFile) { - if (string.IsNullOrEmpty(packageFilePath)) - { - throw new ArgumentNullException("packageFilePath"); - } + if (packageFile == null) throw new ArgumentNullException(nameof(packageFile)); + + if (!packageFile.Exists) + throw new ArgumentException($"Package file: {packageFile} could not be found"); - if (File.Exists(packageFilePath) == false) - { - if (File.Exists(packageFilePath) == false) - throw new ArgumentException(string.Format("Package file: {0} could not be found", packageFilePath)); - } - - string extension = Path.GetExtension(packageFilePath).ToLower(); + var extension = packageFile.Extension; var alowedExtension = new[] { ".umb", ".zip" }; // Check if the file is a valid package - if (alowedExtension.All(ae => ae.Equals(extension) == false)) + if (alowedExtension.All(ae => ae.InvariantEquals(extension) == false)) { - throw new ArgumentException( - string.Format("Error - file isn't a package. only extentions: \"{0}\" is allowed", string.Join(", ", alowedExtension))); + throw new ArgumentException("Error - file isn't a package. only extentions: \"{string.Join(", ", alowedExtension)}\" is allowed"); } } - public void CopyFileFromArchive(string packageFilePath, string fileInPackageName, string destinationfilePath) + public void CopyFileFromArchive(FileInfo packageFile, string fileInPackageName, string destinationfilePath) { - CopyFilesFromArchive(packageFilePath, new[]{new KeyValuePair(fileInPackageName, destinationfilePath) } ); + CopyFilesFromArchive(packageFile, new[] {(fileInPackageName, destinationfilePath)}); } - public void CopyFilesFromArchive(string packageFilePath, IEnumerable> sourceDestination) + public void CopyFilesFromArchive(FileInfo packageFile, IEnumerable<(string packageUniqueFile, string appAbsolutePath)> sourceDestination) { - var d = sourceDestination.ToDictionary(k => k.Key.ToLower(), v => v.Value); + var d = sourceDestination.ToDictionary(k => k.packageUniqueFile.ToLower(), v => v.appAbsolutePath); - ReadZipfileEntries(packageFilePath, entry => + ReadZipfileEntries(packageFile, entry => { - string fileName = (Path.GetFileName(entry.Name) ?? string.Empty).ToLower(); + var fileName = (Path.GetFileName(entry.Name) ?? string.Empty).ToLower(); if (fileName == string.Empty) { return true; } - string destination; - if (string.IsNullOrEmpty(fileName) == false && d.TryGetValue(fileName, out destination)) + if (string.IsNullOrEmpty(fileName) == false && d.TryGetValue(fileName, out var destination)) { + //ensure the dir exists + Directory.CreateDirectory(Path.GetDirectoryName(destination)); + using (var streamWriter = File.Open(destination, FileMode.Create)) using (var entryStream = entry.Open()) { @@ -99,15 +94,15 @@ namespace Umbraco.Core.Packaging if (d.Any()) { - throw new ArgumentException(string.Format("The following source file(s): \"{0}\" could not be found in archive: \"{1}\"", string.Join("\", \"",d.Keys), packageFilePath)); + throw new ArgumentException(string.Format("The following source file(s): \"{0}\" could not be found in archive: \"{1}\"", string.Join("\", \"",d.Keys), packageFile)); } } - public IEnumerable FindMissingFiles(string packageFilePath, IEnumerable expectedFiles) + public IEnumerable FindMissingFiles(FileInfo packageFile, IEnumerable expectedFiles) { var retVal = expectedFiles.ToList(); - ReadZipfileEntries(packageFilePath, zipEntry => + ReadZipfileEntries(packageFile, zipEntry => { string fileName = Path.GetFileName(zipEntry.Name); @@ -121,17 +116,16 @@ namespace Umbraco.Core.Packaging } - public IEnumerable FindDubletFileNames(string packageFilePath) + public IEnumerable FindDuplicateFileNames(FileInfo packageFile) { var dictionary = new Dictionary>(); - ReadZipfileEntries(packageFilePath, entry => + ReadZipfileEntries(packageFile, entry => { - string fileName = (Path.GetFileName(entry.Name) ?? string.Empty).ToLower(); + var fileName = (Path.GetFileName(entry.Name) ?? string.Empty).ToLower(); - List list; - if (dictionary.TryGetValue(fileName, out list) == false) + if (dictionary.TryGetValue(fileName, out var list) == false) { list = new List(); dictionary.Add(fileName, list); @@ -145,13 +139,13 @@ namespace Umbraco.Core.Packaging return dictionary.Values.Where(v => v.Count > 1).SelectMany(v => v); } - public IEnumerable ReadFilesFromArchive(string packageFilePath, IEnumerable filesToGet) + public IEnumerable ReadFilesFromArchive(FileInfo packageFile, IEnumerable filesToGet) { - CheckPackageExists(packageFilePath); + CheckPackageExists(packageFile); var files = new HashSet(filesToGet.Select(f => f.ToLowerInvariant())); - using (var fs = File.OpenRead(packageFilePath)) + using (var fs = packageFile.OpenRead()) using (var zipArchive = new ZipArchive(fs)) { foreach (var zipEntry in zipArchive.Entries) @@ -172,11 +166,11 @@ namespace Umbraco.Core.Packaging } } - private void ReadZipfileEntries(string packageFilePath, Func entryFunc, bool skipsDirectories = true) + private void ReadZipfileEntries(FileInfo packageFile, Func entryFunc, bool skipsDirectories = true) { - CheckPackageExists(packageFilePath); + CheckPackageExists(packageFile); - using (var fs = File.OpenRead(packageFilePath)) + using (var fs = packageFile.OpenRead()) using (var zipArchive = new ZipArchive(fs)) { foreach (var zipEntry in zipArchive.Entries) diff --git a/src/Umbraco.Core/Packaging/PackageFileInstallation.cs b/src/Umbraco.Core/Packaging/PackageFileInstallation.cs new file mode 100644 index 0000000000..55b8bdc63e --- /dev/null +++ b/src/Umbraco.Core/Packaging/PackageFileInstallation.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Xml.Linq; +using Umbraco.Core.IO; +using Umbraco.Core.Logging; +using Umbraco.Core.Models; +using Umbraco.Core.Models.Packaging; +using Umbraco.Core.Services; +using File = System.IO.File; + +namespace Umbraco.Core.Packaging +{ + /// + /// Installs package files + /// + internal class PackageFileInstallation + { + private readonly CompiledPackageXmlParser _parser; + private readonly IProfilingLogger _logger; + private readonly PackageExtraction _packageExtraction; + + public PackageFileInstallation(CompiledPackageXmlParser parser, IProfilingLogger logger) + { + _parser = parser; + _logger = logger; + _packageExtraction = new PackageExtraction(); + } + + /// + /// Returns a list of all installed file paths + /// + /// + /// + /// + /// The absolute path of where to extract the package files (normally the application root) + /// + /// + public IEnumerable InstallFiles(CompiledPackage compiledPackage, FileInfo packageFile, string targetRootFolder) + { + using (_logger.DebugDuration( + "Installing package files for package " + compiledPackage.Name, + "Package file installation complete for package " + compiledPackage.Name)) + { + var sourceAndRelativeDest = _parser.ExtractSourceDestinationFileInformation(compiledPackage.Files); + var sourceAndAbsDest = AppendRootToDestination(targetRootFolder, sourceAndRelativeDest); + + _packageExtraction.CopyFilesFromArchive(packageFile, sourceAndAbsDest); + + return sourceAndRelativeDest.Select(sd => sd.appRelativePath).ToArray(); + } + } + + private static IEnumerable<(string packageUniqueFile, string appAbsolutePath)> AppendRootToDestination(string applicationRootFolder, IEnumerable<(string packageUniqueFile, string appRelativePath)> sourceDestination) + { + return + sourceDestination.Select( + sd => (sd.packageUniqueFile, Path.Combine(applicationRootFolder, sd.appRelativePath))).ToArray(); + } + } +} diff --git a/src/Umbraco.Core/Packaging/PackageInstallation.cs b/src/Umbraco.Core/Packaging/PackageInstallation.cs index 6c9cd57451..5dd88e5a56 100644 --- a/src/Umbraco.Core/Packaging/PackageInstallation.cs +++ b/src/Umbraco.Core/Packaging/PackageInstallation.cs @@ -1,262 +1,221 @@ using System; using System.Collections.Generic; -using System.Data; using System.IO; using System.Linq; using System.Xml.Linq; -using System.Xml.XPath; -using Umbraco.Core.Configuration; using Umbraco.Core.IO; using Umbraco.Core.Models; using Umbraco.Core.Models.Packaging; using Umbraco.Core.Services; -using File = System.IO.File; namespace Umbraco.Core.Packaging { + internal class PackageInstallation : IPackageInstallation { - private readonly IFileService _fileService; - private readonly IMacroService _macroService; private readonly IPackagingService _packagingService; - private IConflictingPackageData _conflictingPackageData; - private readonly IPackageExtraction _packageExtraction; - private string _fullPathToRoot; - - public PackageInstallation(IPackagingService packagingService, IMacroService macroService, - IFileService fileService, IPackageExtraction packageExtraction) - : this(packagingService, macroService, fileService, packageExtraction, IOHelper.GetRootDirectorySafe()) - {} - - public PackageInstallation(IPackagingService packagingService, IMacroService macroService, - IFileService fileService, IPackageExtraction packageExtraction, string fullPathToRoot) - { - if (packageExtraction != null) _packageExtraction = packageExtraction; - else throw new ArgumentNullException("packageExtraction"); - - if (macroService != null) _macroService = macroService; - else throw new ArgumentNullException("macroService"); - - if (fileService != null) _fileService = fileService; - else throw new ArgumentNullException("fileService"); - - if (packagingService != null) _packagingService = packagingService; - else throw new ArgumentNullException("packagingService"); - - _fullPathToRoot = fullPathToRoot; - } - - public IConflictingPackageData ConflictingPackageData - { - private get - { - return _conflictingPackageData ?? - (_conflictingPackageData = new ConflictingPackageData(_macroService, _fileService)); - } - set - { - if (_conflictingPackageData != null) - { - throw new PropertyConstraintException("This property already have a value"); - } - _conflictingPackageData = value; - } - } - - public string FullPathToRoot - { - private get { return _fullPathToRoot; } - set - { - - if (_fullPathToRoot != null) - { - throw new PropertyConstraintException("This property already have a value"); - } - - _fullPathToRoot = value; - } - } - - public IPackageInfo GetMetaData(string packageFilePath) - { - try - { - XElement rootElement = GetConfigXmlElement(packageFilePath); - return GetMetaData(rootElement); - } - catch (Exception e) - { - throw new Exception("Error reading " + packageFilePath, e); - } - } - - public PreInstallWarnings GetPreInstallWarnings(string packageFilePath) - { - try - { - XElement rootElement = GetConfigXmlElement(packageFilePath); - return GetPreInstallWarnings(rootElement); - } - catch (Exception e) - { - throw new Exception("Error reading " + packageFilePath, e); - } - } - - public InstallationSummary InstallPackage(string packageFile, int userId) - { - XElement dataTypes; - XElement languages; - XElement dictionaryItems; - XElement macroes; - XElement files; - XElement templates; - XElement documentTypes; - XElement styleSheets; - XElement documentSet; - XElement documents; - XElement actions; - IPackageInfo metaData; - InstallationSummary installationSummary; - - try - { - XElement rootElement = GetConfigXmlElement(packageFile); - PackageSupportedCheck(rootElement); - PackageStructureSanityCheck(packageFile, rootElement); - dataTypes = rootElement.Element(Constants.Packaging.DataTypesNodeName); - languages = rootElement.Element(Constants.Packaging.LanguagesNodeName); - dictionaryItems = rootElement.Element(Constants.Packaging.DictionaryItemsNodeName); - macroes = rootElement.Element(Constants.Packaging.MacrosNodeName); - files = rootElement.Element(Constants.Packaging.FilesNodeName); - templates = rootElement.Element(Constants.Packaging.TemplatesNodeName); - documentTypes = rootElement.Element(Constants.Packaging.DocumentTypesNodeName); - styleSheets = rootElement.Element(Constants.Packaging.StylesheetsNodeName); - documentSet = rootElement.Element(Constants.Packaging.DocumentSetNodeName); - documents = rootElement.Element(Constants.Packaging.DocumentsNodeName); - actions = rootElement.Element(Constants.Packaging.ActionsNodeName); - - metaData = GetMetaData(rootElement); - installationSummary = new InstallationSummary {MetaData = metaData}; - } - catch (Exception e) - { - throw new Exception("Error reading " + packageFile, e); - } - - try - { - var dataTypeDefinitions = EmptyEnumerableIfNull(dataTypes) ?? InstallDataTypes(dataTypes, userId); - installationSummary.DataTypesInstalled = dataTypeDefinitions; - - var languagesInstalled = EmptyEnumerableIfNull(languages) ?? InstallLanguages(languages, userId); - installationSummary.LanguagesInstalled = languagesInstalled; - - var dictionaryInstalled = EmptyEnumerableIfNull(dictionaryItems) ?? InstallDictionaryItems(dictionaryItems); - installationSummary.DictionaryItemsInstalled = dictionaryInstalled; - - var macros = EmptyEnumerableIfNull(macroes) ?? InstallMacros(macroes, userId); - installationSummary.MacrosInstalled = macros; - - var keyValuePairs = EmptyEnumerableIfNull(packageFile) ?? InstallFiles(packageFile, files); - installationSummary.FilesInstalled = keyValuePairs; - - var templatesInstalled = EmptyEnumerableIfNull(templates) ?? InstallTemplats(templates, userId); - installationSummary.TemplatesInstalled = templatesInstalled; - - var documentTypesInstalled = EmptyEnumerableIfNull(documentTypes) ?? InstallDocumentTypes(documentTypes, userId); - installationSummary.ContentTypesInstalled =documentTypesInstalled; - - var stylesheetsInstalled = EmptyEnumerableIfNull(styleSheets) ?? InstallStylesheets(styleSheets); - installationSummary.StylesheetsInstalled = stylesheetsInstalled; - - var documentsInstalled = documents != null ? InstallDocuments(documents, userId) - : EmptyEnumerableIfNull(documentSet) - ?? InstallDocuments(documentSet, userId); - installationSummary.ContentInstalled = documentsInstalled; - - var packageActions = EmptyEnumerableIfNull(actions) ?? GetPackageActions(actions, metaData.Name); - installationSummary.Actions = packageActions; - - installationSummary.PackageInstalled = true; - - return installationSummary; - } - catch (Exception e) - { - throw new Exception("Error installing package " + packageFile, e); - } - } + private readonly PackageExtraction _packageExtraction; + private readonly PackageFileInstallation _packageFileInstallation; + private readonly CompiledPackageXmlParser _parser; + private readonly string _packagesFolderPath; + private readonly DirectoryInfo _packageExtractionFolder; + private readonly DirectoryInfo _applicationRootFolder; /// - /// Temperary check to test that we support stylesheets + /// Constructor /// - /// - private void PackageSupportedCheck(XElement rootElement) + /// + /// + /// + /// + /// The relative path of the package storage folder (i.e. ~/App_Data/Packages ) + /// + /// + /// The root folder of the application + /// + /// + /// The destination root folder to extract the package files (generally the same as applicationRoot) but can be modified for testing + /// + public PackageInstallation(IPackagingService packagingService, PackageFileInstallation packageFileInstallation, CompiledPackageXmlParser parser, + string packagesFolderPath, DirectoryInfo applicationRootFolder, DirectoryInfo packageExtractionFolder) { - XElement styleSheets = rootElement.Element(Constants.Packaging.StylesheetsNodeName); - if (styleSheets != null && styleSheets.Elements().Any()) - throw new NotSupportedException("Stylesheets is not suported in this version of umbraco"); + _packageExtraction = new PackageExtraction(); + _packageFileInstallation = packageFileInstallation; + _packagingService = packagingService ?? throw new ArgumentNullException(nameof(packagingService)); + _parser = parser; + _packagesFolderPath = packagesFolderPath; + _applicationRootFolder = applicationRootFolder; + _packageExtractionFolder = packageExtractionFolder; } - private static T[] EmptyArrayIfNull(object obj) + public CompiledPackage ReadPackage(string packageFileName) { - return obj == null ? new T[0] : null; + if (packageFileName == null) throw new ArgumentNullException(nameof(packageFileName)); + var packageZipFile = GetPackageZipFile(packageFileName); + var doc = GetConfigXmlDoc(packageZipFile); + + var compiledPackage = _parser.ToCompiledPackage(doc, Path.GetFileName(packageZipFile.FullName), _applicationRootFolder.FullName); + + ValidatePackageFile(packageZipFile, compiledPackage); + + return compiledPackage; } + //fixme: Should we move all of the ImportXXXX methods here instead of on the IPackagingService? we don't want to have cicurlar refs + + public IEnumerable InstallPackageFiles(PackageDefinition packageDefinition, CompiledPackage compiledPackage, int userId) + { + if (packageDefinition == null) throw new ArgumentNullException(nameof(packageDefinition)); + if (compiledPackage == null) throw new ArgumentNullException(nameof(compiledPackage)); + + //these should be the same, TODO: we should have a better validator for this + if (packageDefinition.Name != compiledPackage.Name) + throw new InvalidOperationException("The package definition does not match the compiled package manifest"); + + var packageZipFile = GetPackageZipFile(compiledPackage.PackageFileName); + + return _packageFileInstallation.InstallFiles(compiledPackage, packageZipFile, _packageExtractionFolder.FullName); + } + + public InstallationSummary InstallPackageData(PackageDefinition packageDefinition, CompiledPackage compiledPackage, int userId) + { + //fixme: fill this in + throw new NotImplementedException(); + } + + //public InstallationSummary InstallPackage(FileInfo packageFile, int userId) + //{ + // XElement dataTypes; + // XElement languages; + // XElement dictionaryItems; + // XElement macroes; + // XElement files; + // XElement templates; + // XElement documentTypes; + // XElement styleSheets; + // XElement documentSet; + // XElement documents; + // XElement actions; + // IPackageInfo metaData; + // InstallationSummary installationSummary; + + // try + // { + // XElement rootElement = GetConfigXmlElement(packageFile); + // PackageSupportedCheck(rootElement); + // PackageStructureSanityCheck(packageFile, rootElement); + // dataTypes = rootElement.Element(Constants.Packaging.DataTypesNodeName); + // languages = rootElement.Element(Constants.Packaging.LanguagesNodeName); + // dictionaryItems = rootElement.Element(Constants.Packaging.DictionaryItemsNodeName); + // macroes = rootElement.Element(Constants.Packaging.MacrosNodeName); + // files = rootElement.Element(Constants.Packaging.FilesNodeName); + // templates = rootElement.Element(Constants.Packaging.TemplatesNodeName); + // documentTypes = rootElement.Element(Constants.Packaging.DocumentTypesNodeName); + // styleSheets = rootElement.Element(Constants.Packaging.StylesheetsNodeName); + // documentSet = rootElement.Element(Constants.Packaging.DocumentSetNodeName); + // documents = rootElement.Element(Constants.Packaging.DocumentsNodeName); + // actions = rootElement.Element(Constants.Packaging.ActionsNodeName); + + // metaData = GetMetaData(rootElement); + // installationSummary = new InstallationSummary {MetaData = metaData}; + // } + // catch (Exception e) + // { + // throw new Exception("Error reading " + packageFile, e); + // } + + // try + // { + // var dataTypeDefinitions = EmptyEnumerableIfNull(dataTypes) ?? InstallDataTypes(dataTypes, userId); + // installationSummary.DataTypesInstalled = dataTypeDefinitions; + + // var languagesInstalled = EmptyEnumerableIfNull(languages) ?? InstallLanguages(languages, userId); + // installationSummary.LanguagesInstalled = languagesInstalled; + + // var dictionaryInstalled = EmptyEnumerableIfNull(dictionaryItems) ?? InstallDictionaryItems(dictionaryItems); + // installationSummary.DictionaryItemsInstalled = dictionaryInstalled; + + // var macros = EmptyEnumerableIfNull(macroes) ?? InstallMacros(macroes, userId); + // installationSummary.MacrosInstalled = macros; + + // var templatesInstalled = EmptyEnumerableIfNull(templates) ?? InstallTemplats(templates, userId); + // installationSummary.TemplatesInstalled = templatesInstalled; + + // var documentTypesInstalled = EmptyEnumerableIfNull(documentTypes) ?? InstallDocumentTypes(documentTypes, userId); + // installationSummary.ContentTypesInstalled =documentTypesInstalled; + + // var stylesheetsInstalled = EmptyEnumerableIfNull(styleSheets) ?? InstallStylesheets(styleSheets); + // installationSummary.StylesheetsInstalled = stylesheetsInstalled; + + // var documentsInstalled = documents != null ? InstallDocuments(documents, userId) + // : EmptyEnumerableIfNull(documentSet) + // ?? InstallDocuments(documentSet, userId); + // installationSummary.ContentInstalled = documentsInstalled; + + // var packageActions = EmptyEnumerableIfNull(actions) ?? GetPackageActions(actions, metaData.Name); + // installationSummary.Actions = packageActions; + + // installationSummary.PackageInstalled = true; + + // return installationSummary; + // } + // catch (Exception e) + // { + // throw new Exception("Error installing package " + packageFile, e); + // } + //} + + private FileInfo GetPackageZipFile(string packageFileName) => new FileInfo(IOHelper.MapPath(_packagesFolderPath).EnsureEndsWith('\\') + packageFileName); + private static IEnumerable EmptyEnumerableIfNull(object obj) { return obj == null ? Enumerable.Empty() : null; } - private XDocument GetConfigXmlDoc(string packageFilePath) + private XDocument GetConfigXmlDoc(FileInfo packageFile) { - var configXmlContent = _packageExtraction.ReadTextFileFromArchive(packageFilePath, - Constants.Packaging.PackageXmlFileName, out _); + var configXmlContent = _packageExtraction.ReadTextFileFromArchive(packageFile, Constants.Packaging.PackageXmlFileName, out _); - return XDocument.Parse(configXmlContent); - } + var document = XDocument.Parse(configXmlContent); - public XElement GetConfigXmlElement(string packageFilePath) - { - var document = GetConfigXmlDoc(packageFilePath); if (document.Root == null || document.Root.Name.LocalName.Equals(Constants.Packaging.UmbPackageNodeName) == false) - { - throw new ArgumentException("xml does not have a root node called \"umbPackage\"", packageFilePath); - } + throw new FormatException("xml does not have a root node called \"umbPackage\""); + + return document; + } + + public XElement GetConfigXmlElement(FileInfo packageFile) + { + var document = GetConfigXmlDoc(packageFile); return document.Root; } - private void PackageStructureSanityCheck(string packageFilePath, XElement rootElement) + private void ValidatePackageFile(FileInfo packageFile, CompiledPackage package) { - XElement filesElement = rootElement.Element(Constants.Packaging.FilesNodeName); - if (filesElement != null) + if (!(package.Files?.Count > 0)) return; + + var sourceDestination = _parser.ExtractSourceDestinationFileInformation(package.Files).ToArray(); + + var missingFiles = _packageExtraction.FindMissingFiles(packageFile, sourceDestination.Select(i => i.packageUniqueFile)).ToArray(); + + if (missingFiles.Any()) { - var sourceDestination = ExtractSourceDestinationFileInformation(filesElement).ToArray(); + throw new Exception("The following file(s) are missing in the package: " + + string.Join(", ", missingFiles.Select( + mf => + { + var sd = sourceDestination.Single(fi => fi.packageUniqueFile == mf); + return $"source: \"{sd.packageUniqueFile}\" destination: \"{sd.appRelativePath}\""; + }))); + } - var missingFiles = _packageExtraction.FindMissingFiles(packageFilePath, sourceDestination.Select(i => i.Key)).ToArray(); + IEnumerable duplicates = _packageExtraction.FindDuplicateFileNames(packageFile).ToArray(); - if (missingFiles.Any()) - { - throw new Exception("The following file(s) are missing in the package: " + - string.Join(", ", missingFiles.Select( - mf => - { - var sd = sourceDestination.Single(fi => fi.Key == mf); - return string.Format("source: \"{0}\" destination: \"{1}\"", - sd.Key, sd.Value); - }))); - } - - IEnumerable dubletFileNames = _packageExtraction.FindDubletFileNames(packageFilePath).ToArray(); - - if (dubletFileNames.Any()) - { - throw new Exception("The following filename(s) are found more than one time in the package, since the filename is used ad primary key, this is not allowed: " + - string.Join(", ", dubletFileNames)); - } + if (duplicates.Any()) + { + throw new Exception("The following filename(s) are found more than one time in the package, since the filename is used ad primary key, this is not allowed: " + + string.Join(", ", duplicates)); } } @@ -346,7 +305,7 @@ namespace Umbraco.Core.Packaging return _packagingService.ImportContentTypes(documentTypes, userId); } - private IEnumerable InstallTemplats(XElement templateElement, int userId = 0) + private IEnumerable InstallTemplates(XElement templateElement, int userId = 0) { if (string.Equals(Constants.Packaging.TemplatesNodeName, templateElement.Name.LocalName) == false) { @@ -356,23 +315,6 @@ namespace Umbraco.Core.Packaging return _packagingService.ImportTemplates(templateElement, userId); } - private IEnumerable InstallFiles(string packageFilePath, XElement filesElement) - { - var sourceDestination = ExtractSourceDestinationFileInformation(filesElement); - sourceDestination = AppendRootToDestination(FullPathToRoot, sourceDestination); - - _packageExtraction.CopyFilesFromArchive(packageFilePath, sourceDestination); - - return sourceDestination.Select(sd => sd.Value).ToArray(); - } - - private KeyValuePair[] AppendRootToDestination(string fullpathToRoot, IEnumerable> sourceDestination) - { - return - sourceDestination.Select( - sd => new KeyValuePair(sd.Key, Path.Combine(fullpathToRoot, sd.Value))).ToArray(); - } - private IEnumerable InstallMacros(XElement macroElements, int userId = 0) { if (string.Equals(Constants.Packaging.MacrosNodeName, macroElements.Name.LocalName) == false) @@ -414,164 +356,6 @@ namespace Umbraco.Core.Packaging } return _packagingService.ImportDataTypeDefinitions(dataTypeElements, userId); } - - private PreInstallWarnings GetPreInstallWarnings(XElement rootElement) - { - XElement files = rootElement.Element(Constants.Packaging.FilesNodeName); - XElement styleSheets = rootElement.Element(Constants.Packaging.StylesheetsNodeName); - XElement templates = rootElement.Element(Constants.Packaging.TemplatesNodeName); - XElement alias = rootElement.Element(Constants.Packaging.MacrosNodeName); - - var sourceDestination = EmptyArrayIfNull>(files) ?? ExtractSourceDestinationFileInformation(files); - - var installWarnings = new PreInstallWarnings(); - - var macroAliases = EmptyEnumerableIfNull(alias) ?? ConflictingPackageData.FindConflictingMacros(alias); - installWarnings.ConflictingMacroAliases = macroAliases; - - var templateAliases = EmptyEnumerableIfNull(templates) ?? ConflictingPackageData.FindConflictingTemplates(templates); - installWarnings.ConflictingTemplateAliases = templateAliases; - - var stylesheetNames = EmptyEnumerableIfNull(styleSheets) ?? ConflictingPackageData.FindConflictingStylesheets(styleSheets); - installWarnings.ConflictingStylesheetNames = stylesheetNames; - - installWarnings.UnsecureFiles = FindUnsecureFiles(sourceDestination); - installWarnings.FilesReplaced = FindFilesToBeReplaced(sourceDestination); - - return installWarnings; - } - - private KeyValuePair[] FindFilesToBeReplaced(IEnumerable> sourceDestination) - { - return sourceDestination.Where(sd => File.Exists(Path.Combine(FullPathToRoot, sd.Value))).ToArray(); - } - - private KeyValuePair[] FindUnsecureFiles(IEnumerable> sourceDestinationPair) - { - return sourceDestinationPair.Where(sd => IsFileDestinationUnsecure(sd.Value)).ToArray(); - } - - private bool IsFileDestinationUnsecure(string destination) - { - var unsecureDirNames = new[] {"bin", "app_code"}; - if(unsecureDirNames.Any(ud => destination.StartsWith(ud, StringComparison.InvariantCultureIgnoreCase))) - return true; - - string extension = Path.GetExtension(destination); - return extension != null && extension.Equals(".dll", StringComparison.InvariantCultureIgnoreCase); - } - - private KeyValuePair[] ExtractSourceDestinationFileInformation(XElement filesElement) - { - if (string.Equals(Constants.Packaging.FilesNodeName, filesElement.Name.LocalName) == false) - { - throw new ArgumentException("the root element must be \"Files\"", "filesElement"); - } - - return filesElement.Elements(Constants.Packaging.FileNodeName) - .Select(e => - { - XElement guidElement = e.Element(Constants.Packaging.GuidNodeName); - if (guidElement == null) - { - throw new ArgumentException("Missing element \"" + Constants.Packaging.GuidNodeName + "\"", - "filesElement"); - } - - XElement orgPathElement = e.Element(Constants.Packaging.OrgPathNodeName); - if (orgPathElement == null) - { - throw new ArgumentException("Missing element \"" + Constants.Packaging.OrgPathNodeName + "\"", - "filesElement"); - } - - XElement orgNameElement = e.Element(Constants.Packaging.OrgNameNodeName); - if (orgNameElement == null) - { - throw new ArgumentException("Missing element \"" + Constants.Packaging.OrgNameNodeName + "\"", - "filesElement"); - } - - var fileName = PrepareAsFilePathElement(orgNameElement.Value); - var relativeDir = UpdatePathPlaceholders(PrepareAsFilePathElement(orgPathElement.Value)); - - var relativePath = Path.Combine(relativeDir, fileName); - - - return new KeyValuePair(guidElement.Value, relativePath); - }).ToArray(); - } - - private static string PrepareAsFilePathElement(string pathElement) - { - return pathElement.TrimStart(new[] {'\\', '/', '~'}).Replace("/", "\\"); - } - - private IPackageInfo GetMetaData(XElement xRootElement) - { - XElement infoElement = xRootElement.Element(Constants.Packaging.InfoNodeName); - - if (infoElement == null) - { - throw new ArgumentException("Did not hold a \"" + Constants.Packaging.InfoNodeName + "\" element", - "xRootElement"); - } - - var majorElement = infoElement.XPathSelectElement(Constants.Packaging.PackageRequirementsMajorXpath); - var minorElement = infoElement.XPathSelectElement(Constants.Packaging.PackageRequirementsMinorXpath); - var patchElement = infoElement.XPathSelectElement(Constants.Packaging.PackageRequirementsPatchXpath); - var nameElement = infoElement.XPathSelectElement(Constants.Packaging.PackageNameXpath); - var versionElement = infoElement.XPathSelectElement(Constants.Packaging.PackageVersionXpath); - var urlElement = infoElement.XPathSelectElement(Constants.Packaging.PackageUrlXpath); - var licenseElement = infoElement.XPathSelectElement(Constants.Packaging.PackageLicenseXpath); - var authorNameElement = infoElement.XPathSelectElement(Constants.Packaging.AuthorNameXpath); - var authorUrlElement = infoElement.XPathSelectElement(Constants.Packaging.AuthorWebsiteXpath); - var readmeElement = infoElement.XPathSelectElement(Constants.Packaging.ReadmeXpath); - - XElement controlElement = xRootElement.Element(Constants.Packaging.ControlNodeName); - - return new PackageDefinition - { - Name = StringValue(nameElement), - Version = StringValue(versionElement), - Url = StringValue(urlElement), - License = StringValue(licenseElement), - LicenseUrl = StringAttribute(licenseElement, Constants.Packaging.PackageLicenseXpathUrlAttribute), - Author = StringValue(authorNameElement), - AuthorUrl = StringValue(authorUrlElement), - Readme = StringValue(readmeElement), - Control = StringValue(controlElement), - UmbracoVersion = new Version(IntValue(majorElement), IntValue(minorElement), IntValue(patchElement)) - }; - } - - private static string StringValue(XElement xElement, string defaultValue = "") - { - return xElement == null ? defaultValue : xElement.Value; - } - - private static string StringAttribute(XElement xElement, string attribute, string defaultValue = "") - { - return xElement == null - ? defaultValue - : xElement.HasAttributes ? xElement.AttributeValue(attribute) : defaultValue; - } - - private static int IntValue(XElement xElement, int defaultValue = 0) - { - return xElement == null ? defaultValue : int.TryParse(xElement.Value, out var val) ? val : defaultValue; - } - - private static string UpdatePathPlaceholders(string path) - { - if (path.Contains("[$")) - { - //this is experimental and undocumented... - path = path.Replace("[$UMBRACO]", SystemDirectories.Umbraco); - path = path.Replace("[$CONFIG]", SystemDirectories.Config); - path = path.Replace("[$DATA]", SystemDirectories.Data); - } - return path; - } + } } diff --git a/src/Umbraco.Core/Services/IPackagingService.cs b/src/Umbraco.Core/Services/IPackagingService.cs index 5b432d3339..fcb0c66401 100644 --- a/src/Umbraco.Core/Services/IPackagingService.cs +++ b/src/Umbraco.Core/Services/IPackagingService.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.IO; using System.Threading.Tasks; using System.Xml.Linq; using Umbraco.Core.Models; @@ -10,6 +11,33 @@ namespace Umbraco.Core.Services { public interface IPackagingService : IService { + #region Package Installation + + /// + /// Returns a result from an umbraco package file (zip) + /// + /// + /// + CompiledPackage GetCompiledPackageInfo(string packageFileName); + + /// + /// Installs the package files contained in an umbraco package file (zip) + /// + /// + /// + /// + IEnumerable InstallCompiledPackageFiles(PackageDefinition packageDefinition, string packageFileName, int userId = 0); + + /// + /// Installs the data, entities, objects contained in an umbraco package file (zip) + /// + /// + /// + /// + InstallationSummary InstallCompiledPackageData(PackageDefinition packageDefinition, string packageFileName, int userId = 0); + + #endregion + #region Installed Packages IEnumerable GetAllInstalledPackages(); @@ -116,16 +144,18 @@ namespace Umbraco.Core.Services /// Optional id of the User performing the operation. Default is zero (admin) /// Optional parameter indicating whether or not to raise events /// An enumrable list of generated Templates - IEnumerable ImportTemplates(XElement element, int userId = 0, bool raiseEvents = true); + IEnumerable ImportTemplates(XElement element, int userId = 0, bool raiseEvents = true); #endregion /// - /// This will fetch an Umbraco package file from the package repository and return the relative file path to the downloaded package file + /// This will fetch an Umbraco package file from the package repository and return the file name of the downloaded package /// /// /// /// The current user id performing the operation - /// + /// + /// The file name of the downloaded package which will exist in ~/App_Data/packages + /// Task FetchPackageFileAsync(Guid packageId, Version umbracoVersion, int userId); } } diff --git a/src/Umbraco.Core/Services/Implement/PackagingService.cs b/src/Umbraco.Core/Services/Implement/PackagingService.cs index e7b33dd86d..7c379dc2dc 100644 --- a/src/Umbraco.Core/Services/Implement/PackagingService.cs +++ b/src/Umbraco.Core/Services/Implement/PackagingService.cs @@ -32,7 +32,7 @@ namespace Umbraco.Core.Services.Implement public class PackagingService : IPackagingService { //fixme: inject when ready to use this - private IPackageInstallation _packageInstallation; + private readonly IPackageInstallation _packageInstallation; private readonly ILogger _logger; private readonly IContentService _contentService; @@ -961,9 +961,6 @@ namespace Umbraco.Core.Services.Implement #endregion - #region Files - #endregion - #region Languages @@ -1160,7 +1157,7 @@ namespace Umbraco.Core.Services.Implement using (var fs1 = new FileStream(packageFilePath, FileMode.Create)) { fs1.Write(bytes, 0, bytes.Length); - return "packages\\" + packageId + ".umb"; + return packageId + ".umb"; } } @@ -1305,37 +1302,46 @@ namespace Umbraco.Core.Services.Implement #region Installation - //fixme: None of these methods are actually used! They have unit tests for them though, but we don't actively use this yet but we should! + public CompiledPackage GetCompiledPackageInfo(string packageFileName) => _packageInstallation.ReadPackage(packageFileName); - internal IPackageInstallation PackageInstallation + public IEnumerable InstallCompiledPackageFiles(PackageDefinition packageDefinition, string packageFileName, int userId = 0) { - private get { return _packageInstallation ?? new PackageInstallation(this, _macroService, _fileService, new PackageExtraction()); } - set { _packageInstallation = value; } + if (packageDefinition == null) throw new ArgumentNullException(nameof(packageDefinition)); + if (packageDefinition.Id == default) throw new ArgumentException("The package definition has not been persisted"); + if (packageDefinition.Name == default) throw new ArgumentException("The package definition has incomplete information"); + + var compiledPackage = GetCompiledPackageInfo(packageFileName); + if (compiledPackage == null) throw new InvalidOperationException("Could not read the package file " + packageFileName); + + var files = _packageInstallation.InstallPackageFiles(packageDefinition, compiledPackage, userId); + + SaveInstalledPackage(packageDefinition); + + if (userId > -1) + _auditService.Add(AuditType.PackagerInstall, userId, -1, "Package", $"Package files installed for package '{compiledPackage.Name}'."); + + return files; } - internal InstallationSummary InstallPackage(string packageFilePath, int userId = 0, bool raiseEvents = false) + public InstallationSummary InstallCompiledPackageData(PackageDefinition packageDefinition, string packageFileName, int userId = 0) { - var metaData = GetPackageMetaData(packageFilePath); + if (packageDefinition == null) throw new ArgumentNullException(nameof(packageDefinition)); + if (packageDefinition.Id == default) throw new ArgumentException("The package definition has not been persisted"); + if (packageDefinition.Name == default) throw new ArgumentException("The package definition has incomplete information"); - if (raiseEvents && ImportingPackage.IsRaisedEventCancelled(new ImportPackageEventArgs(packageFilePath, metaData), this)) - return new InstallationSummary { MetaData = metaData }; + var compiledPackage = GetCompiledPackageInfo(packageFileName); + if (compiledPackage == null) throw new InvalidOperationException("Could not read the package file " + packageFileName); - var installationSummary = PackageInstallation.InstallPackage(packageFilePath, userId); + if (ImportingPackage.IsRaisedEventCancelled(new ImportPackageEventArgs(packageFileName, compiledPackage), this)) + return new InstallationSummary { MetaData = compiledPackage }; - if (raiseEvents) - ImportedPackage.RaiseEvent(new ImportPackageEventArgs(installationSummary, metaData, false), this); + var summary = _packageInstallation.InstallPackageData(packageDefinition, compiledPackage, userId); - return installationSummary; - } + _auditService.Add(AuditType.PackagerInstall, userId, -1, "Package", $"Package data installed for package '{compiledPackage.Name}'."); - internal PreInstallWarnings GetPackageWarnings(string packageFilePath) - { - return PackageInstallation.GetPreInstallWarnings(packageFilePath); - } + ImportedPackage.RaiseEvent(new ImportPackageEventArgs(summary, compiledPackage, false), this); - internal IPackageInfo GetPackageMetaData(string packageFilePath) - { - return PackageInstallation.GetMetaData(packageFilePath); + return summary; } #endregion diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 038d531bd4..2ee5d13f6d 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -444,11 +444,14 @@ + + + @@ -889,9 +892,6 @@ - - - diff --git a/src/Umbraco.Tests/Packaging/CreatedPackagesRepositoryTests.cs b/src/Umbraco.Tests/Packaging/CreatedPackagesRepositoryTests.cs index 40500d6bcb..e059d87524 100644 --- a/src/Umbraco.Tests/Packaging/CreatedPackagesRepositoryTests.cs +++ b/src/Umbraco.Tests/Packaging/CreatedPackagesRepositoryTests.cs @@ -87,10 +87,10 @@ namespace Umbraco.Tests.Packaging var def2 = new PackageDefinition { - Name = "test", - Url = "http://test.com", - Author = "Someone", - AuthorUrl = "http://test.com" + Name = "test2", + Url = "http://test2.com", + Author = "Someone2", + AuthorUrl = "http://test2.com" }; result = PackageBuilder.SavePackage(def2); diff --git a/src/Umbraco.Tests/Packaging/PackageExtractionTests.cs b/src/Umbraco.Tests/Packaging/PackageExtractionTests.cs index 5416162ed2..61494166ff 100644 --- a/src/Umbraco.Tests/Packaging/PackageExtractionTests.cs +++ b/src/Umbraco.Tests/Packaging/PackageExtractionTests.cs @@ -12,11 +12,11 @@ namespace Umbraco.Tests.Packaging { private const string PackageFileName = "Document_Type_Picker_1.1.umb"; - private static string GetTestPackagePath(string packageName) + private static FileInfo GetTestPackagePath(string packageName) { const string testPackagesDirName = "Packaging\\Packages"; string path = Path.Combine(IOHelper.GetRootDirectorySafe(), testPackagesDirName, packageName); - return path; + return new FileInfo(path); } [Test] diff --git a/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs b/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs index 0855d81548..fe7a5fbe5c 100644 --- a/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs +++ b/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs @@ -1,74 +1,113 @@ -using Moq; +using System; +using System.IO; +using System.Linq; +using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.IO; using Umbraco.Core.Models.Packaging; using Umbraco.Core.Packaging; using Umbraco.Core.Services; +using Umbraco.Core.Services.Implement; +using Umbraco.Tests.TestHelpers; +using Umbraco.Tests.Testing; namespace Umbraco.Tests.Packaging { [TestFixture] - public class PackageInstallationTest + [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerFixture)] + public class PackageInstallationTest : TestWithDatabaseBase { - private const string Xml = @" - - - 095e064b-ba4d-442d-9006-3050983c13d8.dll/binAuros.DocumentTypePicker.dll - - - Document Type Picker - 1.1 - MIT - http://www.auros.co.uk - - 3 - 0 - 0 - - - - @tentonipete - auros.co.uk - - - - - - - - - - - - - - -"; + private Guid _testBaseFolder; + + public override void SetUp() + { + base.SetUp(); + _testBaseFolder = Guid.NewGuid(); + } + + public override void TearDown() + { + base.TearDown(); + + //clear out files/folders + var path = IOHelper.MapPath("~/" + _testBaseFolder); + if (Directory.Exists(path)) + Directory.Delete(path, true); + } + + private CompiledPackageXmlParser Parser => new CompiledPackageXmlParser(new ConflictingPackageData(ServiceContext.MacroService, ServiceContext.FileService)); + + private IPackageInstallation PackageInstallation => new PackageInstallation( + ServiceContext.PackagingService, + new PackageFileInstallation(Parser, ProfilingLogger), + Parser, + packagesFolderPath: "~/Packaging/packages",//this is where our test zip file is + applicationRootFolder: new DirectoryInfo(IOHelper.GetRootDirectorySafe()), + packageExtractionFolder: new DirectoryInfo(IOHelper.MapPath("~/" + _testBaseFolder))); //we don't want to extract package files to the real root, so extract to a test folder + + const string documentTypePickerUmb = "Document_Type_Picker_1.1.umb"; + + //[Test] + //public void PackagingService_Can_ImportPackage() + //{ + // const string documentTypePickerUmb = "Document_Type_Picker_1.1.umb"; + + // string testPackagePath = GetTestPackagePath(documentTypePickerUmb); + + // InstallationSummary installationSummary = packagingService.InstallPackage(testPackagePath); + + // Assert.IsNotNull(installationSummary); + //} + [Test] - public void Test() + public void Can_Read_Compiled_Package() { - // Arrange - const string pagePath = "Test.umb"; + var package = PackageInstallation.ReadPackage(documentTypePickerUmb); + Assert.IsNotNull(package); + Assert.AreEqual(1, package.Files.Count); + Assert.AreEqual("095e064b-ba4d-442d-9006-3050983c13d8.dll", package.Files[0].UniqueFileName); + Assert.AreEqual("/bin", package.Files[0].OriginalPath); + Assert.AreEqual("Auros.DocumentTypePicker.dll", package.Files[0].OriginalName); + Assert.AreEqual("Document Type Picker", package.Name); + Assert.AreEqual("1.1", package.Version); + Assert.AreEqual("http://www.opensource.org/licenses/mit-license.php", package.LicenseUrl); + Assert.AreEqual("MIT", package.License); + Assert.AreEqual(3, package.UmbracoVersion.Major); + Assert.AreEqual(RequirementsType.Legacy, package.UmbracoVersionRequirementsType); + Assert.AreEqual("@tentonipete", package.Author); + Assert.AreEqual("auros.co.uk", package.AuthorUrl); + Assert.AreEqual("Document Type Picker datatype that enables back office user to select one or many document types.", package.Readme); - var packageExtraction = new Mock(); - - string test; - packageExtraction.Setup(a => a.ReadTextFileFromArchive(pagePath, Constants.Packaging.PackageXmlFileName, out test)).Returns(Xml); - - var fileService = new Mock(); - var macroService = new Mock(); - var packagingService = new Mock(); - - var sut = new PackageInstallation(packagingService.Object, macroService.Object, fileService.Object, packageExtraction.Object); - - // Act - InstallationSummary installationSummary = sut.InstallPackage(pagePath, -1); - - // Assert - Assert.IsNotNull(installationSummary); - //Assert.Inconclusive("Lots of more tests can be written"); } + [Test] + public void Can_Read_Compiled_Package_Warnings() + { + + + var preInstallWarnings = PackageInstallation.ReadPackage(documentTypePickerUmb).Warnings; + Assert.IsNotNull(preInstallWarnings); + + //TODO: Assert! + } + + [Test] + public void Install_Files() + { + var package = PackageInstallation.ReadPackage(documentTypePickerUmb); + var def = PackageDefinition.FromCompiledPackage(package); + def.Id = 1; + def.PackageId = Guid.NewGuid(); + + var result = PackageInstallation.InstallPackageFiles(def, package, -1).ToList(); + + Assert.AreEqual(1, result.Count); + Assert.AreEqual("bin\\Auros.DocumentTypePicker.dll", result[0]); + Assert.IsTrue(File.Exists(Path.Combine(IOHelper.MapPath("~/" + _testBaseFolder), result[0]))); + } + + } } diff --git a/src/Umbraco.Tests/Services/PackagingServiceTests.cs b/src/Umbraco.Tests/Services/PackagingServiceTests.cs index 0f57298c88..f6878e9407 100644 --- a/src/Umbraco.Tests/Services/PackagingServiceTests.cs +++ b/src/Umbraco.Tests/Services/PackagingServiceTests.cs @@ -14,54 +14,7 @@ namespace Umbraco.Tests.Services { - private static string GetTestPackagePath(string packageName) - { - const string testPackagesDirName = "Packaging\\Packages"; - string path = Path.Combine(IOHelper.GetRootDirectorySafe(), testPackagesDirName, packageName); - return path; - } - - - [Test] - public void PackagingService_Can_ImportPackage() - { - var packagingService = (PackagingService)ServiceContext.PackagingService; - - const string documentTypePickerUmb = "Document_Type_Picker_1.1.umb"; - - string testPackagePath = GetTestPackagePath(documentTypePickerUmb); - - InstallationSummary installationSummary = packagingService.InstallPackage(testPackagePath); - - Assert.IsNotNull(installationSummary); - } - - - [Test] - public void PackagingService_Can_GetPackageMetaData() - { - var packagingService = (PackagingService)ServiceContext.PackagingService; - - const string documentTypePickerUmb = "Document_Type_Picker_1.1.umb"; - - string testPackagePath = GetTestPackagePath(documentTypePickerUmb); - - var packageMetaData = packagingService.GetPackageMetaData(testPackagePath); - Assert.IsNotNull(packageMetaData); - } - - [Test] - public void PackagingService_Can_GetPackageWarnings() - { - var packagingService = (PackagingService)ServiceContext.PackagingService; - - const string documentTypePickerUmb = "Document_Type_Picker_1.1.umb"; - - string testPackagePath = GetTestPackagePath(documentTypePickerUmb); - - PreInstallWarnings preInstallWarnings = packagingService.GetPackageWarnings(testPackagePath); - Assert.IsNotNull(preInstallWarnings); - } + } diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/views/install-local.html b/src/Umbraco.Web.UI.Client/src/views/packages/views/install-local.html index 7f22b7ace8..5e3ef6ad1c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/views/install-local.html +++ b/src/Umbraco.Web.UI.Client/src/views/packages/views/install-local.html @@ -128,7 +128,7 @@
    Read me
    - +
    diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/views/repo.html b/src/Umbraco.Web.UI.Client/src/views/packages/views/repo.html index fc272c86ff..93c2ce05ed 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/views/repo.html +++ b/src/Umbraco.Web.UI.Client/src/views/packages/views/repo.html @@ -325,7 +325,7 @@
    Read me
    - +
    diff --git a/src/Umbraco.Web/Composing/Current.cs b/src/Umbraco.Web/Composing/Current.cs index 3e7c14147b..daf152c29b 100644 --- a/src/Umbraco.Web/Composing/Current.cs +++ b/src/Umbraco.Web/Composing/Current.cs @@ -161,7 +161,7 @@ namespace Umbraco.Web.Composing #region Web Actions - public static void RestartAppPool() + internal static void RestartAppPool() { // see notes in overload @@ -175,7 +175,7 @@ namespace Umbraco.Web.Composing HttpRuntime.UnloadAppDomain(); } - public static void RestartAppPool(HttpContextBase httpContext) + internal static void RestartAppPool(HttpContextBase httpContext) { // we're going to put an application wide flag to show that the application is about to restart. // we're doing this because if there is a script checking if the app pool is fully restarted, then diff --git a/src/Umbraco.Web/Editors/PackageInstallController.cs b/src/Umbraco.Web/Editors/PackageInstallController.cs index 73d50eb48a..24cc999c6b 100644 --- a/src/Umbraco.Web/Editors/PackageInstallController.cs +++ b/src/Umbraco.Web/Editors/PackageInstallController.cs @@ -29,7 +29,6 @@ using Umbraco.Web.UI; using Umbraco.Web.UI.JavaScript; using Umbraco.Web.WebApi; using Umbraco.Web.WebApi.Filters; -using Umbraco.Web._Legacy.Packager; using File = System.IO.File; using Notification = Umbraco.Web.Models.ContentEditing.Notification; using Version = System.Version; @@ -302,37 +301,31 @@ namespace Umbraco.Web.Editors private void PopulateFromPackageData(LocalPackageInstallModel model) { - var ins = new global::Umbraco.Web._Legacy.Packager.Installer(Security.CurrentUser.Id); - //this will load in all the metadata too - var tempDir = ins.Import(model.ZipFilePath, false); + var ins = Services.PackagingService.GetCompiledPackageInfo(model.ZipFilePath); - model.TemporaryDirectoryPath = Path.Combine(SystemDirectories.Data, tempDir); model.Name = ins.Name; model.Author = ins.Author; model.AuthorUrl = ins.AuthorUrl; model.IconUrl = ins.IconUrl; model.License = ins.License; model.LicenseUrl = ins.LicenseUrl; - model.ReadMe = ins.ReadMe; - model.ConflictingMacroAliases = ins.ConflictingMacroAliases; - model.ConflictingStyleSheetNames = ins.ConflictingStyleSheetNames; - model.ConflictingTemplateAliases = ins.ConflictingTemplateAliases; - model.ContainsMacroConflict = ins.ContainsMacroConflict; - model.ContainsStyleSheetConflicts = ins.ContainsStyleSheeConflicts; - model.ContainsTemplateConflicts = ins.ContainsTemplateConflicts; - model.ContainsUnsecureFiles = ins.ContainsUnsecureFiles; + model.Readme = ins.Readme; + model.ConflictingMacroAliases = ins.Warnings.ConflictingMacros.ToDictionary(x => x.Name, x => x.Alias); + model.ConflictingStyleSheetNames = ins.Warnings.ConflictingStylesheets.ToDictionary(x => x.Name, x => x.Alias); ; + model.ConflictingTemplateAliases = ins.Warnings.ConflictingTemplates.ToDictionary(x => x.Name, x => x.Alias); ; + model.ContainsUnsecureFiles = ins.Warnings.UnsecureFiles.Any(); model.Url = ins.Url; model.Version = ins.Version; - model.UmbracoVersion = ins.RequirementsType == RequirementsType.Strict - ? string.Format("{0}.{1}.{2}", ins.RequirementsMajor, ins.RequirementsMinor, ins.RequirementsPatch) + model.UmbracoVersion = ins.UmbracoVersionRequirementsType == RequirementsType.Strict + ? ins.UmbracoVersion.ToString(3) : string.Empty; //now we need to check for version comparison model.IsCompatible = true; - if (ins.RequirementsType == RequirementsType.Strict) + if (ins.UmbracoVersionRequirementsType == RequirementsType.Strict) { - var packageMinVersion = new System.Version(ins.RequirementsMajor, ins.RequirementsMinor, ins.RequirementsPatch); + var packageMinVersion = ins.UmbracoVersion; if (UmbracoVersion.Current < packageMinVersion) { model.IsCompatible = false; @@ -489,13 +482,12 @@ namespace Umbraco.Web.Editors [HttpPost] public PackageInstallModel Import(PackageInstallModel model) { - var ins = new Installer(Security.CurrentUser.Id); + var packageInfo = Services.PackagingService.GetCompiledPackageInfo(model.ZipFilePath); - var tempPath = ins.Import(model.ZipFilePath); //now we need to check for version comparison - if (ins.RequirementsType == RequirementsType.Strict) + if (packageInfo.UmbracoVersionRequirementsType == RequirementsType.Strict) { - var packageMinVersion = new System.Version(ins.RequirementsMajor, ins.RequirementsMinor, ins.RequirementsPatch); + var packageMinVersion = packageInfo.UmbracoVersion; if (UmbracoVersion.Current < packageMinVersion) { throw new HttpResponseException(Request.CreateNotificationValidationErrorResponse( @@ -503,8 +495,13 @@ namespace Umbraco.Web.Editors } } - model.TemporaryDirectoryPath = Path.Combine(SystemDirectories.Data, tempPath); - model.Id = ins.CreateManifest(model.PackageGuid); + var packageDefinition = PackageDefinition.FromCompiledPackage(packageInfo); + + //save to the installedPackages.config + packageDefinition.PackageId = model.PackageGuid; //fixme: why are we doing this? + Services.PackagingService.SaveInstalledPackage(packageDefinition); + + model.Id = packageDefinition.Id; return model; } @@ -517,9 +514,10 @@ namespace Umbraco.Web.Editors [HttpPost] public PackageInstallModel InstallFiles(PackageInstallModel model) { - var ins = new Installer(Security.CurrentUser.Id); - ins.LoadConfig(IOHelper.MapPath(model.TemporaryDirectoryPath)); - ins.InstallFiles(model.Id, IOHelper.MapPath(model.TemporaryDirectoryPath)); + var definition = Services.PackagingService.GetInstalledPackageById(model.Id); + if (definition == null) throw new InvalidOperationException("Not package definition found with id " + model.Id); + + Services.PackagingService.InstallCompiledPackageFiles(definition, model.ZipFilePath, Security.GetUserId().ResultOr(0)); //set a restarting marker and reset the app pool Current.RestartAppPool(Request.TryGetHttpContext().Result); @@ -551,9 +549,10 @@ namespace Umbraco.Web.Editors [HttpPost] public PackageInstallModel InstallData(PackageInstallModel model) { - var ins = new global::Umbraco.Web._Legacy.Packager.Installer(Security.CurrentUser.Id); - ins.LoadConfig(IOHelper.MapPath(model.TemporaryDirectoryPath)); - ins.InstallBusinessLogic(model.Id, IOHelper.MapPath(model.TemporaryDirectoryPath)); + var definition = Services.PackagingService.GetInstalledPackageById(model.Id); + if (definition == null) throw new InvalidOperationException("Not package definition found with id " + model.Id); + + Services.PackagingService.InstallCompiledPackageData(definition, model.ZipFilePath, Security.GetUserId().ResultOr(0)); return model; } @@ -565,23 +564,21 @@ namespace Umbraco.Web.Editors [HttpPost] public PackageInstallResult CleanUp(PackageInstallModel model) { - var ins = new global::Umbraco.Web._Legacy.Packager.Installer(Security.CurrentUser.Id); - var tempDir = IOHelper.MapPath(model.TemporaryDirectoryPath); - ins.LoadConfig(IOHelper.MapPath(model.TemporaryDirectoryPath)); - ins.InstallCleanUp(model.Id, IOHelper.MapPath(model.TemporaryDirectoryPath)); + var packageInfo = Services.PackagingService.GetCompiledPackageInfo(model.ZipFilePath); var clientDependencyConfig = new ClientDependencyConfiguration(Logger); var clientDependencyUpdated = clientDependencyConfig.UpdateVersionNumber( UmbracoVersion.SemanticVersion, DateTime.UtcNow, "yyyyMMdd"); + //fixme: when do we delete the zip file? var redirectUrl = ""; - if (ins.Control.IsNullOrWhiteSpace() == false) + if (packageInfo.Control.IsNullOrWhiteSpace() == false) { //fixme: this needs to be replaced with an angular view the installer.aspx no longer exists. - redirectUrl = string.Format("/developer/framed/{0}", - Uri.EscapeDataString( - string.Format("/umbraco/developer/Packages/installer.aspx?installing=custominstaller&dir={0}&pId={1}&customControl={2}&customUrl={3}", tempDir, model.Id, ins.Control, ins.Url))); + //redirectUrl = string.Format("/developer/framed/{0}", + // Uri.EscapeDataString( + // string.Format("/umbraco/developer/Packages/installer.aspx?installing=custominstaller&dir={0}&pId={1}&customControl={2}&customUrl={3}", tempDir, model.Id, ins.Control, ins.Url))); } return new PackageInstallResult @@ -590,7 +587,6 @@ namespace Umbraco.Web.Editors ZipFilePath = model.ZipFilePath, PackageGuid = model.PackageGuid, RepositoryGuid = model.RepositoryGuid, - TemporaryDirectoryPath = model.TemporaryDirectoryPath, PostInstallationPath = redirectUrl }; diff --git a/src/Umbraco.Web/Install/Controllers/InstallPackageController.cs b/src/Umbraco.Web/Install/Controllers/InstallPackageController.cs index ac859ee3aa..dd9b0a42d0 100644 --- a/src/Umbraco.Web/Install/Controllers/InstallPackageController.cs +++ b/src/Umbraco.Web/Install/Controllers/InstallPackageController.cs @@ -11,6 +11,7 @@ using umbraco; using Umbraco.Core; using Umbraco.Web.Cache; using Umbraco.Core.Configuration; +using Umbraco.Core.Models.Packaging; using Umbraco.Core.Services; using Umbraco.Web.Composing; using Umbraco.Web.Install.Models; @@ -28,17 +29,18 @@ namespace Umbraco.Web.Install.Controllers [HttpInstallAuthorize] [AngularJsonOnlyConfiguration] [Obsolete("This is only used for the legacy way of installing starter kits in the back office")] + //fixme: Is this used anymore?? public class InstallPackageController : ApiController { private readonly IPackagingService _packagingService; + private readonly UmbracoContext _umbracoContext; - public InstallPackageController(IPackagingService packagingService) + public InstallPackageController(IPackagingService packagingService, UmbracoContext umbracoContext) { _packagingService = packagingService; + _umbracoContext = umbracoContext; } - private const string RepoGuid = "65194810-1f85-11dd-bd0b-0800200c9a66"; - /// /// Empty action, useful for retrieving the base url for this controller /// @@ -50,7 +52,7 @@ namespace Umbraco.Web.Install.Controllers } /// - /// Connects to the repo, downloads the package and creates the manifest + /// Connects to the repo, downloads the package and creates the definition /// /// /// @@ -62,16 +64,19 @@ namespace Umbraco.Web.Install.Controllers UmbracoVersion.Current, UmbracoContext.Current.Security.CurrentUser.Id); - var installer = new _Legacy.Packager.Installer(UmbracoContext.Current.Security.CurrentUser.Id); + + var packageInfo = _packagingService.GetCompiledPackageInfo(packageFile); + if (packageInfo == null) throw new InvalidOperationException("Could not read package file " + packageFile); + + //save to the installedPackages.config + var packageDefinition = PackageDefinition.FromCompiledPackage(packageInfo); + _packagingService.SaveInstalledPackage(packageDefinition); - var tempFile = installer.Import(packageFile); - installer.LoadConfig(tempFile); - var pId = installer.CreateManifest(model.KitGuid); return Json(new { success = true, - manifestId = pId, - packageFile = tempFile, + packageId = packageDefinition.Id, + packageFile = packageInfo.PackageFileName, percentage = 10, message = "Downloading starter kit files..." }, HttpStatusCode.OK); @@ -85,13 +90,16 @@ namespace Umbraco.Web.Install.Controllers public HttpResponseMessage InstallPackageFiles(InstallPackageModel model) { model.PackageFile = HttpUtility.UrlDecode(model.PackageFile); - var installer = new global::Umbraco.Web._Legacy.Packager.Installer(UmbracoContext.Current.Security.CurrentUser.Id); - installer.LoadConfig(model.PackageFile); - installer.InstallFiles(model.ManifestId, model.PackageFile); + + var definition = _packagingService.GetInstalledPackageById(model.PackageId); + if (definition == null) throw new InvalidOperationException("Not package definition found with id " + model.PackageId); + + _packagingService.InstallCompiledPackageFiles(definition, model.PackageFile, _umbracoContext.Security.GetUserId().ResultOr(0)); + return Json(new { success = true, - model.ManifestId, + ManifestId = model.PackageId, model.PackageFile, percentage = 20, message = "Installing starter kit files" @@ -141,13 +149,16 @@ namespace Umbraco.Web.Install.Controllers public HttpResponseMessage InstallBusinessLogic(InstallPackageModel model) { model.PackageFile = HttpUtility.UrlDecode(model.PackageFile); - var installer = new global::Umbraco.Web._Legacy.Packager.Installer(UmbracoContext.Current.Security.CurrentUser.Id); - installer.LoadConfig(model.PackageFile); - installer.InstallBusinessLogic(model.ManifestId, model.PackageFile); + + var definition = _packagingService.GetInstalledPackageById(model.PackageId); + if (definition == null) throw new InvalidOperationException("Not package definition found with id " + model.PackageId); + + _packagingService.InstallCompiledPackageData(definition, model.PackageFile, _umbracoContext.Security.GetUserId().ResultOr(0)); + return Json(new { success = true, - model.ManifestId, + ManifestId = model.PackageId, model.PackageFile, percentage = 70, message = "Installing starter kit files" @@ -162,18 +173,11 @@ namespace Umbraco.Web.Install.Controllers public HttpResponseMessage CleanupInstallation(InstallPackageModel model) { model.PackageFile = HttpUtility.UrlDecode(model.PackageFile); - var installer = new global::Umbraco.Web._Legacy.Packager.Installer(UmbracoContext.Current.Security.CurrentUser.Id); - installer.LoadConfig(model.PackageFile); - installer.InstallCleanUp(model.ManifestId, model.PackageFile); - - // library.RefreshContent is obsolete, would need to RefreshAll... snapshot, - // but it should be managed automatically by services and caches! - //DistributedCache.Instance.RefreshAll...(); - + return Json(new { success = true, - model.ManifestId, + ManifestId = model.PackageId, model.PackageFile, percentage = 100, message = "Starter kit has been installed" diff --git a/src/Umbraco.Web/Install/InstallSteps/StarterKitCleanupStep.cs b/src/Umbraco.Web/Install/InstallSteps/StarterKitCleanupStep.cs index 075a61ca95..8c168f7230 100644 --- a/src/Umbraco.Web/Install/InstallSteps/StarterKitCleanupStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/StarterKitCleanupStep.cs @@ -3,7 +3,6 @@ using System.Linq; using System.Threading.Tasks; using System.Web; using Umbraco.Web.Install.Models; -using Umbraco.Web._Legacy.Packager; namespace Umbraco.Web.Install.InstallSteps { @@ -15,31 +14,26 @@ namespace Umbraco.Web.Install.InstallSteps { var installSteps = InstallStatusTracker.GetStatus().ToArray(); var previousStep = installSteps.Single(x => x.Name == "StarterKitDownload"); - var manifestId = Convert.ToInt32(previousStep.AdditionalData["manifestId"]); + var packageId = Convert.ToInt32(previousStep.AdditionalData["packageId"]); var packageFile = (string)previousStep.AdditionalData["packageFile"]; - CleanupInstallation(manifestId, packageFile); + CleanupInstallation(packageId, packageFile); return Task.FromResult(null); } - private void CleanupInstallation(int manifestId, string packageFile) + private void CleanupInstallation(int packageId, string packageFile) { packageFile = HttpUtility.UrlDecode(packageFile); - var installer = new Installer(); - installer.LoadConfig(packageFile); - installer.InstallCleanUp(manifestId, packageFile); - // library.RefreshContent is obsolete, would need to RefreshAll... snapshot, - // but it should be managed automatically by services and caches! - //DistributedCache.Instance.RefreshAll...(); + //fixme: When does the zip file get deleted? } public override bool RequiresExecution(object model) { var installSteps = InstallStatusTracker.GetStatus().ToArray(); //this step relies on the preious one completed - because it has stored some information we need - if (installSteps.Any(x => x.Name == "StarterKitDownload" && x.AdditionalData.ContainsKey("manifestId")) == false) + if (installSteps.Any(x => x.Name == "StarterKitDownload" && x.AdditionalData.ContainsKey("packageId")) == false) { return false; } diff --git a/src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs b/src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs index 66d1b0a20c..0fe1e333d3 100644 --- a/src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs @@ -5,9 +5,9 @@ using System.Threading.Tasks; using System.Web; using Umbraco.Core.Services; using Umbraco.Core.Configuration; +using Umbraco.Core.Models.Packaging; using Umbraco.Web.Composing; using Umbraco.Web.Install.Models; -using Umbraco.Web._Legacy.Packager; namespace Umbraco.Web.Install.InstallSteps { @@ -29,7 +29,7 @@ namespace Umbraco.Web.Install.InstallSteps _packageService = packageService; } - private const string RepoGuid = "65194810-1f85-11dd-bd0b-0800200c9a66"; + //private const string RepoGuid = "65194810-1f85-11dd-bd0b-0800200c9a66"; public override async Task ExecuteAsync(Guid? starterKitId) { @@ -55,34 +55,33 @@ namespace Umbraco.Web.Install.InstallSteps return new InstallSetupResult(new Dictionary { - {"manifestId", result.Item2}, + {"packageId", result.Item2}, {"packageFile", result.Item1} }); } private async Task> DownloadPackageFilesAsync(Guid kitGuid) { - var installer = new Installer(); - //Go get the package file from the package repo - var packageFile = await _packageService.FetchPackageFileAsync(kitGuid, UmbracoVersion.Current, _umbracoContext.Security.GetUserId().ResultOr(0)); + var packageFileName = await _packageService.FetchPackageFileAsync(kitGuid, UmbracoVersion.Current, _umbracoContext.Security.GetUserId().ResultOr(0)); + if (packageFileName == null) throw new InvalidOperationException("Could not fetch package file " + kitGuid); - var tempFile = installer.Import(packageFile); - installer.LoadConfig(tempFile); - var pId = installer.CreateManifest(kitGuid); + //add an entry to the installedPackages.config + var compiledPackage = _packageService.GetCompiledPackageInfo(packageFileName); + var packageDefinition = PackageDefinition.FromCompiledPackage(compiledPackage); + _packageService.SaveInstalledPackage(packageDefinition); - InstallPackageFiles(pId, tempFile); + InstallPackageFiles(packageDefinition, compiledPackage.PackageFileName); - return new Tuple(tempFile, pId); + return new Tuple(compiledPackage.PackageFileName, packageDefinition.Id); } - private void InstallPackageFiles(int manifestId, string packageFile) + private void InstallPackageFiles(PackageDefinition packageDefinition, string packageFileName) { - packageFile = HttpUtility.UrlDecode(packageFile); - var installer = new Installer(); - installer.LoadConfig(packageFile); - installer.InstallFiles(manifestId, packageFile); + if (packageDefinition == null) throw new ArgumentNullException(nameof(packageDefinition)); + packageFileName = HttpUtility.UrlDecode(packageFileName); + _packageService.InstallCompiledPackageData(packageDefinition, packageFileName, _umbracoContext.Security.GetUserId().ResultOr(0)); } public override string View => _packageService.GetAllInstalledPackages().Any() ? string.Empty : base.View; diff --git a/src/Umbraco.Web/Install/InstallSteps/StarterKitInstallStep.cs b/src/Umbraco.Web/Install/InstallSteps/StarterKitInstallStep.cs index 0e189c5a6d..9d3f38b061 100644 --- a/src/Umbraco.Web/Install/InstallSteps/StarterKitInstallStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/StarterKitInstallStep.cs @@ -2,9 +2,9 @@ using System.Linq; using System.Threading.Tasks; using System.Web; +using Umbraco.Core.Services; using Umbraco.Web.Composing; using Umbraco.Web.Install.Models; -using Umbraco.Web._Legacy.Packager; namespace Umbraco.Web.Install.InstallSteps { @@ -14,10 +14,14 @@ namespace Umbraco.Web.Install.InstallSteps internal class StarterKitInstallStep : InstallSetupStep { private readonly HttpContextBase _httContext; + private readonly UmbracoContext _umbracoContext; + private readonly IPackagingService _packagingService; - public StarterKitInstallStep(HttpContextBase httContext) + public StarterKitInstallStep(HttpContextBase httContext, UmbracoContext umbracoContext, IPackagingService packagingService) { _httContext = httContext; + _umbracoContext = umbracoContext; + _packagingService = packagingService; } @@ -25,29 +29,31 @@ namespace Umbraco.Web.Install.InstallSteps { var installSteps = InstallStatusTracker.GetStatus().ToArray(); var previousStep = installSteps.Single(x => x.Name == "StarterKitDownload"); - var manifestId = Convert.ToInt32(previousStep.AdditionalData["manifestId"]); + var packageId = Convert.ToInt32(previousStep.AdditionalData["packageId"]); var packageFile = (string)previousStep.AdditionalData["packageFile"]; - InstallBusinessLogic(manifestId, packageFile); + InstallBusinessLogic(packageId, packageFile); Current.RestartAppPool(_httContext); return Task.FromResult(null); } - private void InstallBusinessLogic(int manifestId, string packageFile) + private void InstallBusinessLogic(int packageId, string packageFile) { packageFile = HttpUtility.UrlDecode(packageFile); - var installer = new Installer(); - installer.LoadConfig(packageFile); - installer.InstallBusinessLogic(manifestId, packageFile); + + var definition = _packagingService.GetInstalledPackageById(packageId); + if (definition == null) throw new InvalidOperationException("Not package definition found with id " + packageId); + + _packagingService.InstallCompiledPackageData(definition, packageFile, _umbracoContext.Security.GetUserId().ResultOr(0)); } public override bool RequiresExecution(object model) { var installSteps = InstallStatusTracker.GetStatus().ToArray(); //this step relies on the preious one completed - because it has stored some information we need - if (installSteps.Any(x => x.Name == "StarterKitDownload" && x.AdditionalData.ContainsKey("manifestId")) == false) + if (installSteps.Any(x => x.Name == "StarterKitDownload" && x.AdditionalData.ContainsKey("packageId")) == false) { return false; } diff --git a/src/Umbraco.Web/Install/Models/InstallPackageModel.cs b/src/Umbraco.Web/Install/Models/InstallPackageModel.cs index 01eb368b6a..3ab74fa5e4 100644 --- a/src/Umbraco.Web/Install/Models/InstallPackageModel.cs +++ b/src/Umbraco.Web/Install/Models/InstallPackageModel.cs @@ -7,15 +7,15 @@ using System.Threading.Tasks; namespace Umbraco.Web.Install.Models { - + //fixme: do we need this? [Obsolete("This is only used for the obsolete controller InstallPackageController")] [DataContract(Name = "installPackage", Namespace = "")] public class InstallPackageModel { [DataMember(Name = "kitGuid")] public Guid KitGuid { get; set; } - [DataMember(Name = "manifestId")] - public int ManifestId { get; set; } + [DataMember(Name = "packageId")] + public int PackageId { get; set; } [DataMember(Name = "packageFile")] public string PackageFile { get; set; } diff --git a/src/Umbraco.Web/Models/LocalPackageInstallModel.cs b/src/Umbraco.Web/Models/LocalPackageInstallModel.cs index 64ce51f539..d1d51e1fcc 100644 --- a/src/Umbraco.Web/Models/LocalPackageInstallModel.cs +++ b/src/Umbraco.Web/Models/LocalPackageInstallModel.cs @@ -47,25 +47,34 @@ namespace Umbraco.Web.Models public bool ContainsUnsecureFiles { get; set; } [DataMember(Name = "containsTemplateConflicts")] - public bool ContainsTemplateConflicts { get; set; } + public bool ContainsTemplateConflicts => ConflictingTemplateAliases != null && ConflictingTemplateAliases.Count > 0; [DataMember(Name = "containsStyleSheetConflicts")] - public bool ContainsStyleSheetConflicts { get; set; } + public bool ContainsStyleSheetConflicts => ConflictingStyleSheetNames != null && ConflictingStyleSheetNames.Count > 0; [DataMember(Name = "containsMacroConflict")] - public bool ContainsMacroConflict { get; set; } + public bool ContainsMacroConflict => ConflictingMacroAliases != null && ConflictingMacroAliases.Count > 0; + /// + /// Key value of name + alias + /// [DataMember(Name = "conflictingTemplateAliases")] public IDictionary ConflictingTemplateAliases { get; set; } + /// + /// Key value of name + alias + /// [DataMember(Name = "conflictingStyleSheetNames")] public IDictionary ConflictingStyleSheetNames { get; set; } + /// + /// Key value of name + alias + /// [DataMember(Name = "conflictingMacroAliases")] public IDictionary ConflictingMacroAliases { get; set; } - [DataMember(Name = "readMe")] - public string ReadMe { get; set; } + [DataMember(Name = "readme")] + public string Readme { get; set; } [DataMember(Name = "licenseUrl")] public string LicenseUrl { get; set; } diff --git a/src/Umbraco.Web/Models/PackageInstallModel.cs b/src/Umbraco.Web/Models/PackageInstallModel.cs index 7748129a40..1cf4a483ae 100644 --- a/src/Umbraco.Web/Models/PackageInstallModel.cs +++ b/src/Umbraco.Web/Models/PackageInstallModel.cs @@ -15,11 +15,10 @@ namespace Umbraco.Web.Models [DataMember(Name = "packageGuid")] public Guid PackageGuid { get; set; } + //TODO: Do we need this? [DataMember(Name = "repositoryGuid")] public Guid RepositoryGuid { get; set; } - [DataMember(Name = "temporaryDirectoryPath")] - public string TemporaryDirectoryPath { get; set; } [DataMember(Name = "zipFilePath")] public string ZipFilePath { get; set; } diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 1bd2860781..64e17af221 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -1137,7 +1137,6 @@ - diff --git a/src/Umbraco.Web/_Legacy/Packager/Installer.cs b/src/Umbraco.Web/_Legacy/Packager/Installer.cs index 286f41f61a..89dff406b0 100644 --- a/src/Umbraco.Web/_Legacy/Packager/Installer.cs +++ b/src/Umbraco.Web/_Legacy/Packager/Installer.cs @@ -1,803 +1,688 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Net; -using System.Xml; -using System.Xml.Linq; -using System.Xml.XPath; -using ICSharpCode.SharpZipLib.Zip; -using Umbraco.Core; -using Umbraco.Core.Composing; -using Umbraco.Core.Events; -using Umbraco.Core.IO; -using Umbraco.Core.Logging; -using Umbraco.Core.Models; -using Umbraco.Core.Models.Packaging; -using Umbraco.Core.Packaging; -using Umbraco.Core.Services.Implement; -using File = System.IO.File; - -namespace Umbraco.Web._Legacy.Packager -{ - /// - /// The packager is a component which enables sharing of both data and functionality components between different umbraco installations. - /// - /// The output is a .umb (a zip compressed file) which contains the exported documents/medias/macroes/documentTypes (etc.) - /// in a Xml document, along with the physical files used (images/usercontrols/xsl documents etc.) - /// - /// Partly implemented, import of packages is done, the export is *under construction*. - /// - /// - /// Ruben Verborgh 31/12/2007: I had to change some code, I marked my changes with "DATALAYER". - /// Reason: @@IDENTITY can't be used with the new datalayer. - /// I wasn't able to test the code, since I'm not aware how the code functions. - /// - public class Installer - { - private const string PackageServer = "packages.umbraco.org"; - - private readonly Dictionary _conflictingMacroAliases = new Dictionary(); - private readonly Dictionary _conflictingTemplateAliases = new Dictionary(); - private readonly Dictionary _conflictingStyleSheetNames = new Dictionary(); - - private readonly int _currentUserId = -1; - private static WebClient _webClient; - - - public string Name { get; private set; } - public string Version { get; private set; } - public string Url { get; private set; } - public string License { get; private set; } - public string LicenseUrl { get; private set; } - public string Author { get; private set; } - public string AuthorUrl { get; private set; } - public string ReadMe { get; private set; } - public string Control { get; private set; } - - public bool ContainsMacroConflict { get; private set; } - public IDictionary ConflictingMacroAliases => _conflictingMacroAliases; - - public bool ContainsUnsecureFiles { get; private set; } - public List UnsecureFiles { get; } = new List(); - - public bool ContainsTemplateConflicts { get; private set; } - public IDictionary ConflictingTemplateAliases => _conflictingTemplateAliases; - - public bool ContainsStyleSheeConflicts { get; private set; } - public IDictionary ConflictingStyleSheetNames => _conflictingStyleSheetNames; - - public int RequirementsMajor { get; private set; } - public int RequirementsMinor { get; private set; } - public int RequirementsPatch { get; private set; } - - public RequirementsType RequirementsType { get; private set; } - - public string IconUrl { get; private set; } - - /// - /// The xml of the compiled package - /// - public XDocument Config { get; private set; } - - /// - /// Constructor - /// - public Installer() - { - Initialize(); - } - - public Installer(int currentUserId) - { - Initialize(); - _currentUserId = currentUserId; - } - - private void Initialize() - { - ContainsTemplateConflicts = false; - ContainsUnsecureFiles = false; - ContainsMacroConflict = false; - ContainsStyleSheeConflicts = false; - } - - - - /// - /// Constructor - /// - /// The name of the package - /// The version of the package - /// The url to a descriptionpage - /// The license under which the package is released (preferably GPL ;)) - /// The url to a licensedescription - /// The original author of the package - /// The url to the Authors website - /// Umbraco version major - /// Umbraco version minor - /// Umbraco version patch - /// The readme text - /// The name of the usercontrol used to configure the package after install - /// - /// - public Installer(string name, string version, string url, string license, string licenseUrl, string author, string authorUrl, int requirementsMajor, int requirementsMinor, int requirementsPatch, string readme, string control, RequirementsType requirementsType, string iconUrl) - { - ContainsTemplateConflicts = false; - ContainsUnsecureFiles = false; - ContainsMacroConflict = false; - ContainsStyleSheeConflicts = false; - this.Name = name; - this.Version = version; - this.Url = url; - this.License = license; - this.LicenseUrl = licenseUrl; - this.RequirementsMajor = requirementsMajor; - this.RequirementsMinor = requirementsMinor; - this.RequirementsPatch = requirementsPatch; - this.RequirementsType = requirementsType; - this.Author = author; - this.AuthorUrl = authorUrl; - this.IconUrl = iconUrl; - ReadMe = readme; - this.Control = control; - } - - #region Public Methods - - /// - /// Imports the specified package - /// - /// Filename of the umbracopackage - /// true if the input file should be deleted after import - /// - public string Import(string inputFile, bool deleteFile) - { - using (Current.ProfilingLogger.DebugDuration( - $"Importing package file {inputFile}.", - $"Package file {inputFile} imported.")) - { - var tempDir = ""; - if (File.Exists(IOHelper.MapPath(SystemDirectories.Data + Path.DirectorySeparatorChar + inputFile))) - { - var fi = new FileInfo(IOHelper.MapPath(SystemDirectories.Data + Path.DirectorySeparatorChar + inputFile)); - // Check if the file is a valid package - if (fi.Extension.ToLower() == ".umb") - { - try - { - tempDir = UnPack(fi.FullName, deleteFile); - LoadConfig(tempDir); - } - catch (Exception ex) - { - Current.Logger.Error(ex, "Error importing file {FileName}", fi.FullName); - throw; - } - } - else - throw new Exception("Error - file isn't a package (doesn't have a .umb extension). Check if the file automatically got named '.zip' upon download."); - } - else - throw new Exception("Error - file not found. Could find file named '" + IOHelper.MapPath(SystemDirectories.Data + Path.DirectorySeparatorChar + inputFile) + "'"); - return tempDir; - } - - } - - /// - /// Imports the specified package - /// - /// Filename of the umbracopackage - /// - public string Import(string inputFile) - { - return Import(inputFile, true); - } - - public int CreateManifest(Guid guid) - { - //This is the new improved install rutine, which chops up the process into 3 steps, creating the manifest, moving files, and finally handling umb objects - - var parser = new CompiledPackageXmlParser(); - var def = parser.ToCompiledPackage(Config); - - //create a new entry in the installedPackages.config - var installedPackage = new PackageDefinition - { - Author = def.Author, - AuthorUrl = def.AuthorUrl, - Control = def.Control, - IconUrl = def.IconUrl, - License = def.License, - LicenseUrl = def.LicenseUrl, - Name = def.Name, - Readme = def.Readme, - UmbracoVersion = def.UmbracoVersion, - Url = def.Url, - Version = def.Version, - PackageId = guid - }; - - if (!Current.Services.PackagingService.SaveInstalledPackage(installedPackage)) - throw new InvalidOperationException("Could not save package definition"); - - return installedPackage.Id; - } - - public void InstallFiles(int packageId, string tempDir) - { - var parser = new CompiledPackageXmlParser(); - - using (Current.ProfilingLogger.DebugDuration( - "Installing package files for package id " + packageId + " into temp folder " + tempDir, - "Package file installation complete for package id " + packageId)) - { - //retrieve the manifest to continue installation - var insPack = Current.Services.PackagingService.GetInstalledPackageById(packageId); - - //TODO: Depending on some files, some files should be installed differently. - //i.e. if stylsheets should probably be installed via business logic, media items should probably use the media IFileSystem! - - // Move files - //string virtualBasePath = System.Web.HttpContext.Current.Request.ApplicationPath; - string basePath = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath; - - var def = parser.ToCompiledPackage(Config); - - try - { - foreach (var f in def.Files) - { - var destPath = GetFileName(basePath, f.OriginalPath); - var sourceFile = GetFileName(tempDir, f.UniqueFileName); - var destFile = GetFileName(destPath, f.OriginalName); - - // Create the destination directory if it doesn't exist - if (Directory.Exists(destPath) == false) - Directory.CreateDirectory(destPath); - //If a file with this name exists, delete it - else if (File.Exists(destFile)) - File.Delete(destFile); - - // Copy the file - // SJ: Note - this used to do a move but some packages included the same file to be - // copied to multiple locations like so: - // - // - // my-icon.png - // /umbraco/Images/ - // my-icon.png - // - // - // my-icon.png - // /App_Plugins/MyPlugin/Images - // my-icon.png - // - // - // Since this file unzips as a flat list of files, moving the file the first time means - // that when you try to do that a second time, it would result in a FileNotFoundException - File.Copy(sourceFile, destFile); - - //PPH log file install - insPack.Files.Add(f.OriginalPath.EnsureEndsWith('/') + f.OriginalName); - - } - - // Once we're done copying, remove all the files - foreach (var f in def.Files) - { - var sourceFile = GetFileName(tempDir, f.UniqueFileName); - if (File.Exists(sourceFile)) - File.Delete(sourceFile); - } - } - catch (Exception ex) - { - Current.Logger.Error(ex, "Package install error"); - throw; - } - - // log that a user has install files - if (_currentUserId > -1) - { - Current.Services.AuditService.Add(AuditType.PackagerInstall, - _currentUserId, - -1, "Package", string.Format("Package '{0}' installed. Package guid: {1}", insPack.Name, insPack.PackageId)); - } - - Current.Services.PackagingService.SaveInstalledPackage(insPack); - } - } - - public void InstallBusinessLogic(int packageId, string tempDir) - { - using (Current.ProfilingLogger.DebugDuration( - "Installing business logic for package id " + packageId + " into temp folder " + tempDir, - "Package business logic installation complete for package id " + packageId)) - { - PackageDefinition insPack; - try - { - //retrieve the manifest to continue installation - insPack = Current.Services.PackagingService.GetInstalledPackageById(packageId); - //bool saveNeeded = false; - - // Get current user, with a fallback - var currentUser = Current.Services.UserService.GetUserById(Constants.Security.SuperUserId); - - //TODO: Get rid of this entire class! Until then all packages will be installed by the admin user - - var rootElement = Config.Root; - var packagingService = Current.Services.PackagingService; - - //Perhaps it would have been a good idea to put the following into methods eh?!? - - #region DataTypes - var dataTypeElement = rootElement.Descendants("DataTypes").FirstOrDefault(); - if (dataTypeElement != null) - { - var dataTypeDefinitions = packagingService.ImportDataTypeDefinitions(dataTypeElement, currentUser.Id); - foreach (var dataTypeDefinition in dataTypeDefinitions) - { - insPack.DataTypes.Add(dataTypeDefinition.Id.ToString(CultureInfo.InvariantCulture)); - } - } - #endregion - - #region Languages - var languageItemsElement = rootElement.Descendants("Languages").FirstOrDefault(); - if (languageItemsElement != null) - { - var insertedLanguages = packagingService.ImportLanguages(languageItemsElement); - foreach(var x in insertedLanguages.Select(l => l.Id.ToString(CultureInfo.InvariantCulture))) - insPack.Languages.Add(x); - } - - #endregion - - #region Dictionary items - var dictionaryItemsElement = rootElement.Descendants("DictionaryItems").FirstOrDefault(); - if (dictionaryItemsElement != null) - { - var insertedDictionaryItems = packagingService.ImportDictionaryItems(dictionaryItemsElement); - foreach (var x in insertedDictionaryItems.Select(d => d.Id.ToString(CultureInfo.InvariantCulture))) - insPack.DictionaryItems.Add(x); - } - #endregion - - #region Macros - var macroItemsElement = rootElement.Descendants("Macros").FirstOrDefault(); - if (macroItemsElement != null) - { - var insertedMacros = packagingService.ImportMacros(macroItemsElement); - foreach (var x in insertedMacros.Select(m => m.Id.ToString(CultureInfo.InvariantCulture))) - insPack.Macros.Add(x); - - } - #endregion - - #region Templates - var templateElement = rootElement.Descendants("Templates").FirstOrDefault(); - if (templateElement != null) - { - var templates = packagingService.ImportTemplates(templateElement, currentUser.Id); - foreach (var template in templates) - { - insPack.Templates.Add(template.Id.ToString(CultureInfo.InvariantCulture)); - } - } - #endregion - - #region DocumentTypes - //Check whether the root element is a doc type rather then a complete package - var docTypeElement = rootElement.Name.LocalName.Equals("DocumentType") || - rootElement.Name.LocalName.Equals("DocumentTypes") - ? rootElement - : rootElement.Descendants("DocumentTypes").FirstOrDefault(); - - if (docTypeElement != null) - { - var contentTypes = packagingService.ImportContentTypes(docTypeElement, currentUser.Id); - foreach (var contentType in contentTypes) - { - insPack.DocumentTypes.Add(contentType.Id.ToString(CultureInfo.InvariantCulture)); - //saveNeeded = true; - } - } - #endregion - - #region Stylesheets - foreach (var n in Config.Root.XPathSelectElements("Stylesheets/Stylesheet")) - { - string stylesheetName = n.Element("Name")?.Value; - if (stylesheetName.IsNullOrWhiteSpace()) continue; - - var s = Current.Services.FileService.GetStylesheetByName(stylesheetName); - if (s == null) - { - var fileName = n.Element("FileName")?.Value; - if (fileName == null) continue; - var content = n.Element("Content")?.Value; - if (content == null) continue; - - s = new Stylesheet(fileName) { Content = content }; - Current.Services.FileService.SaveStylesheet(s); - } - - foreach (var prop in n.XPathSelectElements("Properties/Property")) - { - string alias = prop.Element("Alias")?.Value; - var sp = s.Properties.SingleOrDefault(p => p != null && p.Alias == alias); - string name = prop.Element("Name")?.Value; - if (sp == null) - { - //sp = StylesheetProperty.MakeNew( - // name, - // s, - // u); - - sp = new StylesheetProperty(name, "#" + name.ToSafeAlias(), ""); - s.AddProperty(sp); - } - else - { - //sp.Text = name; - //Changing the name requires removing the current property and then adding another new one - if (sp.Name != name) - { - s.RemoveProperty(sp.Name); - var newProp = new StylesheetProperty(name, sp.Alias, sp.Value); - s.AddProperty(newProp); - sp = newProp; - } - } - sp.Alias = alias; - sp.Value = prop.Element("Value")?.Value; - } - //s.saveCssToFile(); - Current.Services.FileService.SaveStylesheet(s); - - - - - insPack.Stylesheets.Add(s.Id.ToString(CultureInfo.InvariantCulture)); - //saveNeeded = true; - } - - //if (saveNeeded) { insPack.Save(); saveNeeded = false; } - #endregion - - #region Documents - var documentElement = rootElement.Descendants("DocumentSet").FirstOrDefault(); - if (documentElement != null) - { - var content = packagingService.ImportContent(documentElement, -1, currentUser.Id); - var firstContentItem = content.First(); - insPack.ContentNodeId = firstContentItem.Id.ToString(CultureInfo.InvariantCulture); - } - #endregion - - #region Package Actions - foreach (var n in Config.Root.XPathSelectElements("Actions/Action")) - { - var undo = n.AttributeValue("undo"); - if (undo == null || undo == "true") - { - insPack.Actions += n.ToString(); - } - - //Run the actions tagged only for 'install' - var runat = n.AttributeValue("runat"); - - if (runat != null && runat == "install") - { - var alias = n.AttributeValue("alias"); - if (alias.IsNullOrWhiteSpace() == false) - { - Current.PackageActionRunner.RunPackageAction(insPack.Name, alias, n); - } - } - } - #endregion - - Current.Services.PackagingService.SaveInstalledPackage(insPack); - } - catch (Exception ex) - { - Current.Logger.Error(ex, "Error installing businesslogic"); - throw; - } - - OnPackageInstalled(insPack); - } - } - - /// - /// Remove the temp installation folder - /// - /// - /// - public void InstallCleanUp(int packageId, string tempDir) - { - if (Directory.Exists(tempDir)) - { - Directory.Delete(tempDir, true); - } - } - - /// - /// Reads the configuration of the package from the configuration xmldocument - /// - /// The folder to which the contents of the package is extracted - public void LoadConfig(string tempDir) - { - Config = XDocument.Load(tempDir + Path.DirectorySeparatorChar + "package.xml"); - - var parser = new CompiledPackageXmlParser(); - var def = parser.ToCompiledPackage(Config); - - Name = def.Name; - Version = def.Version; - Url = def.Url; - License = def.License; - LicenseUrl = def.LicenseUrl; - - RequirementsMajor = def.UmbracoVersion.Major; - RequirementsMinor = def.UmbracoVersion.Minor; - RequirementsPatch = def.UmbracoVersion.Build; - RequirementsType = def.UmbracoVersionRequirementsType; - IconUrl = def.IconUrl; - Author = def.Author; - AuthorUrl = def.AuthorUrl; - ReadMe = def.Readme; - Control = def.Control; - - var basePath = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath; - var dllBinFiles = new List(); - - foreach (var f in def.Files) - { - var badFile = false; - var destPath = GetFileName(basePath, f.OriginalPath); - var orgName = f.OriginalName; - var destFile = GetFileName(destPath, orgName); - - if (destPath.ToLower().Contains(IOHelper.DirSepChar + "app_code")) - { - badFile = true; - } - - if (destPath.ToLower().Contains(IOHelper.DirSepChar + "bin")) - { - badFile = true; - } - - if (destFile.ToLower().EndsWith(".dll")) - { - badFile = true; - dllBinFiles.Add(Path.Combine(tempDir, orgName)); - } - - if (badFile) - { - ContainsUnsecureFiles = true; - UnsecureFiles.Add(f.OriginalName); - } - } - - - - //this will check for existing macros with the same alias - //since we will not overwrite on import it's a good idea to inform the user what will be overwritten - foreach (var n in Config.Root.XPathSelectElements("//macro")) - { - var alias = n.Element("alias")?.Value; - if (!string.IsNullOrEmpty(alias)) - { - var m = Current.Services.MacroService.GetByAlias(alias); - if (m != null) - { - ContainsMacroConflict = true; - if (_conflictingMacroAliases.ContainsKey(m.Name) == false) - { - _conflictingMacroAliases.Add(m.Name, alias); - } - } - } - } - - foreach (var n in Config.Root.XPathSelectElements("Templates/Template")) - { - var alias = n.Element("Alias")?.Value; - if (!string.IsNullOrEmpty(alias)) - { - var t = Current.Services.FileService.GetTemplate(alias); - if (t != null) - { - ContainsTemplateConflicts = true; - if (_conflictingTemplateAliases.ContainsKey(t.Alias) == false) - { - _conflictingTemplateAliases.Add(t.Alias, alias); - } - } - } - } - - foreach (var n in Config.Root.XPathSelectElements("Stylesheets/Stylesheet")) - { - var alias = n.Element("Name")?.Value; - if (!string.IsNullOrEmpty(alias)) - { - var s = Current.Services.FileService.GetStylesheetByName(alias); - if (s != null) - { - ContainsStyleSheeConflicts = true; - if (_conflictingStyleSheetNames.ContainsKey(s.Alias) == false) - { - _conflictingStyleSheetNames.Add(s.Alias, alias); - } - } - } - } +//using System; +//using System.Collections.Generic; +//using System.Diagnostics; +//using System.Globalization; +//using System.IO; +//using System.Linq; +//using System.Net; +//using System.Xml; +//using System.Xml.Linq; +//using System.Xml.XPath; +//using ICSharpCode.SharpZipLib.Zip; +//using Umbraco.Core; +//using Umbraco.Core.Composing; +//using Umbraco.Core.Events; +//using Umbraco.Core.IO; +//using Umbraco.Core.Logging; +//using Umbraco.Core.Models; +//using Umbraco.Core.Models.Packaging; +//using Umbraco.Core.Packaging; +//using Umbraco.Core.Services.Implement; +//using File = System.IO.File; + +//namespace Umbraco.Web._Legacy.Packager +//{ +// /// +// /// The packager is a component which enables sharing of both data and functionality components between different umbraco installations. +// /// +// /// The output is a .umb (a zip compressed file) which contains the exported documents/medias/macroes/documentTypes (etc.) +// /// in a Xml document, along with the physical files used (images/usercontrols/xsl documents etc.) +// /// +// /// Partly implemented, import of packages is done, the export is *under construction*. +// /// +// /// +// /// Ruben Verborgh 31/12/2007: I had to change some code, I marked my changes with "DATALAYER". +// /// Reason: @@IDENTITY can't be used with the new datalayer. +// /// I wasn't able to test the code, since I'm not aware how the code functions. +// /// +// public class Installer +// { +// private const string PackageServer = "packages.umbraco.org"; + +// private readonly Dictionary _conflictingMacroAliases = new Dictionary(); +// private readonly Dictionary _conflictingTemplateAliases = new Dictionary(); +// private readonly Dictionary _conflictingStyleSheetNames = new Dictionary(); + +// private readonly int _currentUserId = -1; +// private static WebClient _webClient; + + +// public string Name { get; private set; } +// public string Version { get; private set; } +// public string Url { get; private set; } +// public string License { get; private set; } +// public string LicenseUrl { get; private set; } +// public string Author { get; private set; } +// public string AuthorUrl { get; private set; } +// public string ReadMe { get; private set; } +// public string Control { get; private set; } + +// public bool ContainsMacroConflict { get; private set; } +// public IDictionary ConflictingMacroAliases => _conflictingMacroAliases; + +// public bool ContainsUnsecureFiles { get; private set; } +// public List UnsecureFiles { get; } = new List(); + +// public bool ContainsTemplateConflicts { get; private set; } +// public IDictionary ConflictingTemplateAliases => _conflictingTemplateAliases; + +// public bool ContainsStyleSheeConflicts { get; private set; } +// public IDictionary ConflictingStyleSheetNames => _conflictingStyleSheetNames; + +// public int RequirementsMajor { get; private set; } +// public int RequirementsMinor { get; private set; } +// public int RequirementsPatch { get; private set; } + +// public RequirementsType RequirementsType { get; private set; } + +// public string IconUrl { get; private set; } + +// /// +// /// The xml of the compiled package +// /// +// public XDocument Config { get; private set; } + +// /// +// /// Constructor +// /// +// public Installer() +// { +// Initialize(); +// } + +// public Installer(int currentUserId) +// { +// Initialize(); +// _currentUserId = currentUserId; +// } + +// private void Initialize() +// { +// ContainsTemplateConflicts = false; +// ContainsUnsecureFiles = false; +// ContainsMacroConflict = false; +// ContainsStyleSheeConflicts = false; +// } + + + +// /// +// /// Constructor +// /// +// /// The name of the package +// /// The version of the package +// /// The url to a descriptionpage +// /// The license under which the package is released (preferably GPL ;)) +// /// The url to a licensedescription +// /// The original author of the package +// /// The url to the Authors website +// /// Umbraco version major +// /// Umbraco version minor +// /// Umbraco version patch +// /// The readme text +// /// The name of the usercontrol used to configure the package after install +// /// +// /// +// public Installer(string name, string version, string url, string license, string licenseUrl, string author, string authorUrl, int requirementsMajor, int requirementsMinor, int requirementsPatch, string readme, string control, RequirementsType requirementsType, string iconUrl) +// { +// ContainsTemplateConflicts = false; +// ContainsUnsecureFiles = false; +// ContainsMacroConflict = false; +// ContainsStyleSheeConflicts = false; +// this.Name = name; +// this.Version = version; +// this.Url = url; +// this.License = license; +// this.LicenseUrl = licenseUrl; +// this.RequirementsMajor = requirementsMajor; +// this.RequirementsMinor = requirementsMinor; +// this.RequirementsPatch = requirementsPatch; +// this.RequirementsType = requirementsType; +// this.Author = author; +// this.AuthorUrl = authorUrl; +// this.IconUrl = iconUrl; +// ReadMe = readme; +// this.Control = control; +// } + +// #region Public Methods + +// /// +// /// Imports the specified package +// /// +// /// Filename of the umbracopackage +// /// true if the input file should be deleted after import +// /// +// public string Import(string inputFile, bool deleteFile) +// { +// using (Current.ProfilingLogger.DebugDuration( +// $"Importing package file {inputFile}.", +// $"Package file {inputFile} imported.")) +// { +// var tempDir = ""; +// if (File.Exists(IOHelper.MapPath(SystemDirectories.Data + "/" + inputFile))) +// { +// var fi = new FileInfo(IOHelper.MapPath(SystemDirectories.Data + "/" + inputFile)); +// // Check if the file is a valid package +// if (fi.Extension.ToLower() == ".umb") +// { +// try +// { +// tempDir = UnPack(fi.FullName, deleteFile); +// LoadConfig(tempDir); +// } +// catch (Exception ex) +// { +// Current.Logger.Error(ex, "Error importing file {FileName}", fi.FullName); +// throw; +// } +// } +// else +// throw new Exception("Error - file isn't a package (doesn't have a .umb extension). Check if the file automatically got named '.zip' upon download."); +// } +// else +// throw new Exception("Error - file not found. Could find file named '" + IOHelper.MapPath(SystemDirectories.Data + Path.DirectorySeparatorChar + inputFile) + "'"); +// return tempDir; +// } + +// } + +// /// +// /// Imports the specified package +// /// +// /// Filename of the umbracopackage +// /// +// public string Import(string inputFile) +// { +// return Import(inputFile, true); +// } + +// public int CreateManifest(Guid guid) +// { +// //This is the new improved install rutine, which chops up the process into 3 steps, creating the manifest, moving files, and finally handling umb objects + +// var parser = new CompiledPackageXmlParser(); +// var def = parser.ToCompiledPackage(Config); + +// //create a new entry in the installedPackages.config +// var installedPackage = new PackageDefinition +// { +// Author = def.Author, +// AuthorUrl = def.AuthorUrl, +// Control = def.Control, +// IconUrl = def.IconUrl, +// License = def.License, +// LicenseUrl = def.LicenseUrl, +// Name = def.Name, +// Readme = def.Readme, +// UmbracoVersion = def.UmbracoVersion, +// Url = def.Url, +// Version = def.Version, +// PackageId = guid +// }; + +// if (!Current.Services.PackagingService.SaveInstalledPackage(installedPackage)) +// throw new InvalidOperationException("Could not save package definition"); + +// return installedPackage.Id; +// } + +// public void InstallFiles(int packageId, string tempDir) +// { +// var parser = new CompiledPackageXmlParser(); + +// using (Current.ProfilingLogger.DebugDuration( +// "Installing package files for package id " + packageId + " into temp folder " + tempDir, +// "Package file installation complete for package id " + packageId)) +// { +// //retrieve the manifest to continue installation +// var insPack = Current.Services.PackagingService.GetInstalledPackageById(packageId); + +// //TODO: Depending on some files, some files should be installed differently. +// //i.e. if stylsheets should probably be installed via business logic, media items should probably use the media IFileSystem! + +// // Move files +// //string virtualBasePath = System.Web.HttpContext.Current.Request.ApplicationPath; +// string basePath = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath; + +// var def = parser.ToCompiledPackage(Config); + +// try +// { +// foreach (var f in def.Files) +// { +// var destPath = GetFileName(basePath, f.OriginalPath); +// var sourceFile = GetFileName(tempDir, f.UniqueFileName); +// var destFile = GetFileName(destPath, f.OriginalName); + +// // Create the destination directory if it doesn't exist +// if (Directory.Exists(destPath) == false) +// Directory.CreateDirectory(destPath); +// //If a file with this name exists, delete it +// else if (File.Exists(destFile)) +// File.Delete(destFile); + +// // Copy the file +// // SJ: Note - this used to do a move but some packages included the same file to be +// // copied to multiple locations like so: +// // +// // +// // my-icon.png +// // /umbraco/Images/ +// // my-icon.png +// // +// // +// // my-icon.png +// // /App_Plugins/MyPlugin/Images +// // my-icon.png +// // +// // +// // Since this file unzips as a flat list of files, moving the file the first time means +// // that when you try to do that a second time, it would result in a FileNotFoundException +// File.Copy(sourceFile, destFile); + +// //PPH log file install +// insPack.Files.Add(f.OriginalPath.EnsureEndsWith('/') + f.OriginalName); + +// } + +// // Once we're done copying, remove all the files +// foreach (var f in def.Files) +// { +// var sourceFile = GetFileName(tempDir, f.UniqueFileName); +// if (File.Exists(sourceFile)) +// File.Delete(sourceFile); +// } +// } +// catch (Exception ex) +// { +// Current.Logger.Error(ex, "Package install error"); +// throw; +// } + +// // log that a user has install files +// if (_currentUserId > -1) +// { +// Current.Services.AuditService.Add(AuditType.PackagerInstall, +// _currentUserId, +// -1, "Package", string.Format("Package '{0}' installed. Package guid: {1}", insPack.Name, insPack.PackageId)); +// } + +// Current.Services.PackagingService.SaveInstalledPackage(insPack); +// } +// } + +// public void InstallBusinessLogic(int packageId, string tempDir) +// { +// using (Current.ProfilingLogger.DebugDuration( +// "Installing business logic for package id " + packageId + " into temp folder " + tempDir, +// "Package business logic installation complete for package id " + packageId)) +// { +// PackageDefinition insPack; +// try +// { +// //retrieve the manifest to continue installation +// insPack = Current.Services.PackagingService.GetInstalledPackageById(packageId); +// //bool saveNeeded = false; + +// // Get current user, with a fallback +// var currentUser = Current.Services.UserService.GetUserById(Constants.Security.SuperUserId); + +// //TODO: Get rid of this entire class! Until then all packages will be installed by the admin user + +// var rootElement = Config.Root; +// var packagingService = Current.Services.PackagingService; + +// //Perhaps it would have been a good idea to put the following into methods eh?!? + +// #region DataTypes +// var dataTypeElement = rootElement.Descendants("DataTypes").FirstOrDefault(); +// if (dataTypeElement != null) +// { +// var dataTypeDefinitions = packagingService.ImportDataTypeDefinitions(dataTypeElement, currentUser.Id); +// foreach (var dataTypeDefinition in dataTypeDefinitions) +// { +// insPack.DataTypes.Add(dataTypeDefinition.Id.ToString(CultureInfo.InvariantCulture)); +// } +// } +// #endregion + +// #region Languages +// var languageItemsElement = rootElement.Descendants("Languages").FirstOrDefault(); +// if (languageItemsElement != null) +// { +// var insertedLanguages = packagingService.ImportLanguages(languageItemsElement); +// foreach(var x in insertedLanguages.Select(l => l.Id.ToString(CultureInfo.InvariantCulture))) +// insPack.Languages.Add(x); +// } + +// #endregion + +// #region Dictionary items +// var dictionaryItemsElement = rootElement.Descendants("DictionaryItems").FirstOrDefault(); +// if (dictionaryItemsElement != null) +// { +// var insertedDictionaryItems = packagingService.ImportDictionaryItems(dictionaryItemsElement); +// foreach (var x in insertedDictionaryItems.Select(d => d.Id.ToString(CultureInfo.InvariantCulture))) +// insPack.DictionaryItems.Add(x); +// } +// #endregion + +// #region Macros +// var macroItemsElement = rootElement.Descendants("Macros").FirstOrDefault(); +// if (macroItemsElement != null) +// { +// var insertedMacros = packagingService.ImportMacros(macroItemsElement); +// foreach (var x in insertedMacros.Select(m => m.Id.ToString(CultureInfo.InvariantCulture))) +// insPack.Macros.Add(x); + +// } +// #endregion + +// #region Templates +// var templateElement = rootElement.Descendants("Templates").FirstOrDefault(); +// if (templateElement != null) +// { +// var templates = packagingService.ImportTemplates(templateElement, currentUser.Id); +// foreach (var template in templates) +// { +// insPack.Templates.Add(template.Id.ToString(CultureInfo.InvariantCulture)); +// } +// } +// #endregion + +// #region DocumentTypes +// //Check whether the root element is a doc type rather then a complete package +// var docTypeElement = rootElement.Name.LocalName.Equals("DocumentType") || +// rootElement.Name.LocalName.Equals("DocumentTypes") +// ? rootElement +// : rootElement.Descendants("DocumentTypes").FirstOrDefault(); + +// if (docTypeElement != null) +// { +// var contentTypes = packagingService.ImportContentTypes(docTypeElement, currentUser.Id); +// foreach (var contentType in contentTypes) +// { +// insPack.DocumentTypes.Add(contentType.Id.ToString(CultureInfo.InvariantCulture)); +// //saveNeeded = true; +// } +// } +// #endregion + +// #region Stylesheets +// foreach (var n in Config.Root.XPathSelectElements("Stylesheets/Stylesheet")) +// { +// string stylesheetName = n.Element("Name")?.Value; +// if (stylesheetName.IsNullOrWhiteSpace()) continue; + +// var s = Current.Services.FileService.GetStylesheetByName(stylesheetName); +// if (s == null) +// { +// var fileName = n.Element("FileName")?.Value; +// if (fileName == null) continue; +// var content = n.Element("Content")?.Value; +// if (content == null) continue; + +// s = new Stylesheet(fileName) { Content = content }; +// Current.Services.FileService.SaveStylesheet(s); +// } + +// foreach (var prop in n.XPathSelectElements("Properties/Property")) +// { +// string alias = prop.Element("Alias")?.Value; +// var sp = s.Properties.SingleOrDefault(p => p != null && p.Alias == alias); +// string name = prop.Element("Name")?.Value; +// if (sp == null) +// { +// //sp = StylesheetProperty.MakeNew( +// // name, +// // s, +// // u); + +// sp = new StylesheetProperty(name, "#" + name.ToSafeAlias(), ""); +// s.AddProperty(sp); +// } +// else +// { +// //sp.Text = name; +// //Changing the name requires removing the current property and then adding another new one +// if (sp.Name != name) +// { +// s.RemoveProperty(sp.Name); +// var newProp = new StylesheetProperty(name, sp.Alias, sp.Value); +// s.AddProperty(newProp); +// sp = newProp; +// } +// } +// sp.Alias = alias; +// sp.Value = prop.Element("Value")?.Value; +// } +// //s.saveCssToFile(); +// Current.Services.FileService.SaveStylesheet(s); + + + + +// insPack.Stylesheets.Add(s.Id.ToString(CultureInfo.InvariantCulture)); +// //saveNeeded = true; +// } + +// //if (saveNeeded) { insPack.Save(); saveNeeded = false; } +// #endregion + +// #region Documents +// var documentElement = rootElement.Descendants("DocumentSet").FirstOrDefault(); +// if (documentElement != null) +// { +// var content = packagingService.ImportContent(documentElement, -1, currentUser.Id); +// var firstContentItem = content.First(); +// insPack.ContentNodeId = firstContentItem.Id.ToString(CultureInfo.InvariantCulture); +// } +// #endregion + +// #region Package Actions +// foreach (var n in Config.Root.XPathSelectElements("Actions/Action")) +// { +// var undo = n.AttributeValue("undo"); +// if (undo == null || undo == "true") +// { +// insPack.Actions += n.ToString(); +// } + +// //Run the actions tagged only for 'install' +// var runat = n.AttributeValue("runat"); + +// if (runat != null && runat == "install") +// { +// var alias = n.AttributeValue("alias"); +// if (alias.IsNullOrWhiteSpace() == false) +// { +// Current.PackageActionRunner.RunPackageAction(insPack.Name, alias, n); +// } +// } +// } +// #endregion + +// Current.Services.PackagingService.SaveInstalledPackage(insPack); +// } +// catch (Exception ex) +// { +// Current.Logger.Error(ex, "Error installing businesslogic"); +// throw; +// } + +// OnPackageInstalled(insPack); +// } +// } + +// /// +// /// Remove the temp installation folder +// /// +// /// +// /// +// public void InstallCleanUp(int packageId, string tempDir) +// { +// if (Directory.Exists(tempDir)) +// { +// Directory.Delete(tempDir, true); +// } +// } + +// /// +// /// Reads the configuration of the package from the configuration xmldocument +// /// +// /// The folder to which the contents of the package is extracted +// public void LoadConfig(string tempDir) +// { +// Config = XDocument.Load(tempDir + Path.DirectorySeparatorChar + "package.xml"); + +// var parser = new CompiledPackageXmlParser(); +// var def = parser.ToCompiledPackage(Config); + +// Name = def.Name; +// Version = def.Version; +// Url = def.Url; +// License = def.License; +// LicenseUrl = def.LicenseUrl; + +// RequirementsMajor = def.UmbracoVersion.Major; +// RequirementsMinor = def.UmbracoVersion.Minor; +// RequirementsPatch = def.UmbracoVersion.Build; +// RequirementsType = def.UmbracoVersionRequirementsType; +// IconUrl = def.IconUrl; +// Author = def.Author; +// AuthorUrl = def.AuthorUrl; +// ReadMe = def.Readme; +// Control = def.Control; + +// var basePath = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath; +// var dllBinFiles = new List(); + +// foreach (var f in def.Files) +// { +// var badFile = false; +// var destPath = GetFileName(basePath, f.OriginalPath); +// var orgName = f.OriginalName; +// var destFile = GetFileName(destPath, orgName); + +// if (destPath.ToLower().Contains(IOHelper.DirSepChar + "app_code")) +// { +// badFile = true; +// } + +// if (destPath.ToLower().Contains(IOHelper.DirSepChar + "bin")) +// { +// badFile = true; +// } + +// if (destFile.ToLower().EndsWith(".dll")) +// { +// badFile = true; +// dllBinFiles.Add(Path.Combine(tempDir, orgName)); +// } + +// if (badFile) +// { +// ContainsUnsecureFiles = true; +// UnsecureFiles.Add(f.OriginalName); +// } +// } + + + +// //this will check for existing macros with the same alias +// //since we will not overwrite on import it's a good idea to inform the user what will be overwritten +// foreach (var n in Config.Root.XPathSelectElements("//macro")) +// { +// var alias = n.Element("alias")?.Value; +// if (!string.IsNullOrEmpty(alias)) +// { +// var m = Current.Services.MacroService.GetByAlias(alias); +// if (m != null) +// { +// ContainsMacroConflict = true; +// if (_conflictingMacroAliases.ContainsKey(m.Name) == false) +// { +// _conflictingMacroAliases.Add(m.Name, alias); +// } +// } +// } +// } + +// foreach (var n in Config.Root.XPathSelectElements("Templates/Template")) +// { +// var alias = n.Element("Alias")?.Value; +// if (!string.IsNullOrEmpty(alias)) +// { +// var t = Current.Services.FileService.GetTemplate(alias); +// if (t != null) +// { +// ContainsTemplateConflicts = true; +// if (_conflictingTemplateAliases.ContainsKey(t.Alias) == false) +// { +// _conflictingTemplateAliases.Add(t.Alias, alias); +// } +// } +// } +// } + +// foreach (var n in Config.Root.XPathSelectElements("Stylesheets/Stylesheet")) +// { +// var alias = n.Element("Name")?.Value; +// if (!string.IsNullOrEmpty(alias)) +// { +// var s = Current.Services.FileService.GetStylesheetByName(alias); +// if (s != null) +// { +// ContainsStyleSheeConflicts = true; +// if (_conflictingStyleSheetNames.ContainsKey(s.Alias) == false) +// { +// _conflictingStyleSheetNames.Add(s.Alias, alias); +// } +// } +// } +// } - } +// } - /// - /// This uses the old method of fetching and only supports the packages.umbraco.org repository. - /// - /// - /// - public string Fetch(Guid Package) - { - // Check for package directory - if (Directory.Exists(IOHelper.MapPath(SystemDirectories.Packages)) == false) - Directory.CreateDirectory(IOHelper.MapPath(SystemDirectories.Packages)); +// /// +// /// This uses the old method of fetching and only supports the packages.umbraco.org repository. +// /// +// /// +// /// +// public string Fetch(Guid Package) +// { +// // Check for package directory +// if (Directory.Exists(IOHelper.MapPath(SystemDirectories.Packages)) == false) +// Directory.CreateDirectory(IOHelper.MapPath(SystemDirectories.Packages)); - if (_webClient == null) - _webClient = new WebClient(); +// if (_webClient == null) +// _webClient = new WebClient(); - _webClient.DownloadFile( - "http://" + PackageServer + "/fetch?package=" + Package.ToString(), - IOHelper.MapPath(SystemDirectories.Packages + "/" + Package + ".umb")); +// _webClient.DownloadFile( +// "http://" + PackageServer + "/fetch?package=" + Package.ToString(), +// IOHelper.MapPath(SystemDirectories.Packages + "/" + Package + ".umb")); - return "packages\\" + Package + ".umb"; - } +// return "packages\\" + Package + ".umb"; +// } - #endregion +// #endregion - #region Private Methods +// private void OnPackageInstalled(PackageDefinition insPack) +// { +// // getting an InstallationSummary for sending to the PackagingService.ImportedPackage event +// var fileService = Current.Services.FileService; +// var macroService = Current.Services.MacroService; +// var contentTypeService = Current.Services.ContentTypeService; +// var dataTypeService = Current.Services.DataTypeService; +// var localizationService = Current.Services.LocalizationService; - /// - /// Gets the name of the file in the specified path. - /// Corrects possible problems with slashes that would result from a simple concatenation. - /// Can also be used to concatenate paths. - /// - /// The path. - /// Name of the file. - /// The name of the file in the specified path. - private static string GetFileName(string path, string fileName) - { - // virtual dir support - fileName = IOHelper.FindFile(fileName); +// var installationSummary = InstallationSummary.FromPackageDefinition(insPack, contentTypeService, dataTypeService, fileService, localizationService, macroService); +// installationSummary.PackageInstalled = true; - if (path.Contains("[$")) - { - //this is experimental and undocumented... - path = path.Replace("[$UMBRACO]", SystemDirectories.Umbraco); - path = path.Replace("[$CONFIG]", SystemDirectories.Config); - path = path.Replace("[$DATA]", SystemDirectories.Data); - } - - //to support virtual dirs we try to lookup the file... - path = IOHelper.FindFile(path); - - - - Debug.Assert(path != null && path.Length >= 1); - Debug.Assert(fileName != null && fileName.Length >= 1); - - path = path.Replace('/', '\\'); - fileName = fileName.Replace('/', '\\'); - - // Does filename start with a slash? Does path end with one? - bool fileNameStartsWithSlash = (fileName[0] == Path.DirectorySeparatorChar); - bool pathEndsWithSlash = (path[path.Length - 1] == Path.DirectorySeparatorChar); - - // Path ends with a slash - if (pathEndsWithSlash) - { - if (!fileNameStartsWithSlash) - // No double slash, just concatenate - return path + fileName; - return path + fileName.Substring(1); - } - if (fileNameStartsWithSlash) - // Required slash specified, just concatenate - return path + fileName; - return path + Path.DirectorySeparatorChar + fileName; - } - - private static string UnPack(string zipName, bool deleteFile) - { - // Unzip - - //the temp directory will be the package GUID - this keeps it consistent! - //the zipName is always the package Guid.umb - - var packageFileName = Path.GetFileNameWithoutExtension(zipName); - var packageId = Guid.NewGuid(); - Guid.TryParse(packageFileName, out packageId); - - string tempDir = IOHelper.MapPath(SystemDirectories.Data) + Path.DirectorySeparatorChar + packageId.ToString(); - //clear the directory if it exists - if (Directory.Exists(tempDir)) Directory.Delete(tempDir, true); - Directory.CreateDirectory(tempDir); - - var s = new ZipInputStream(File.OpenRead(zipName)); - - ZipEntry theEntry; - while ((theEntry = s.GetNextEntry()) != null) - { - string fileName = Path.GetFileName(theEntry.Name); - - if (fileName != String.Empty) - { - FileStream streamWriter = File.Create(tempDir + Path.DirectorySeparatorChar + fileName); - - int size = 2048; - byte[] data = new byte[2048]; - while (true) - { - size = s.Read(data, 0, data.Length); - if (size > 0) - { - streamWriter.Write(data, 0, size); - } - else - { - break; - } - } - - streamWriter.Close(); - - } - } - - // Clean up - s.Close(); - - if (deleteFile) - { - File.Delete(zipName); - } - - - return tempDir; - - } - - #endregion - - - private void OnPackageInstalled(PackageDefinition insPack) - { - // getting an InstallationSummary for sending to the PackagingService.ImportedPackage event - var fileService = Current.Services.FileService; - var macroService = Current.Services.MacroService; - var contentTypeService = Current.Services.ContentTypeService; - var dataTypeService = Current.Services.DataTypeService; - var localizationService = Current.Services.LocalizationService; - - var installationSummary = InstallationSummary.FromPackageDefinition(insPack, contentTypeService, dataTypeService, fileService, localizationService, macroService); - installationSummary.PackageInstalled = true; - - var args = new ImportPackageEventArgs(installationSummary, insPack, false); - PackagingService.OnImportedPackage(args); - } - } -} +// var args = new ImportPackageEventArgs(installationSummary, insPack, false); +// PackagingService.OnImportedPackage(args); +// } +// } +//} diff --git a/src/Umbraco.Web/_Legacy/Packager/Settings.cs b/src/Umbraco.Web/_Legacy/Packager/Settings.cs deleted file mode 100644 index e88f18262f..0000000000 --- a/src/Umbraco.Web/_Legacy/Packager/Settings.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.IO; -using Umbraco.Core.IO; - -namespace Umbraco.Web._Legacy.Packager -{ - public class Settings - { - public static string InstalledPackagesSettings => SystemDirectories.Packages + IOHelper.DirSepChar + "installedPackages.config"; - - } - -} From 92c278c593353aaa4af3011f68242734cc4e66b4 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Mon, 14 Jan 2019 07:12:21 +0100 Subject: [PATCH 324/469] Adds missing translation, fixes #4054 --- src/Umbraco.Web.UI/Umbraco/config/lang/en.xml | 1 + src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml | 1 + 2 files changed, 2 insertions(+) diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml index 02b10fe22f..386d3af518 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml @@ -1254,6 +1254,7 @@ To manage your website, simply open the Umbraco back office and start adding con This Content Type uses as a Master Content Type. Tabs from Master Content Types are not shown and can only be edited on the Master Content Type itself No properties defined on this tab. Click on the "add a new property" link at the top to create a new property. + Create matching template Add icon diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml index 83d6b9224b..5de373f571 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml @@ -1278,6 +1278,7 @@ To manage your website, simply open the Umbraco back office and start adding con This Content Type uses as a Master Content Type. Tabs from Master Content Types are not shown and can only be edited on the Master Content Type itself No properties defined on this tab. Click on the "add a new property" link at the top to create a new property. + Create matching template Add icon From 65e98928d4b5bd96b7ec919978abead1f39d4171 Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 14 Jan 2019 17:46:12 +1100 Subject: [PATCH 325/469] Package data installation is now all migrated --- .../Composing/Composers/ServicesComposer.cs | 7 +- src/Umbraco.Core/Composing/Current.cs | 4 +- src/Umbraco.Core/Constants-Packaging.cs | 55 - src/Umbraco.Core/Events/ImportEventArgs.cs | 84 -- .../Models/Packaging/CompiledPackage.cs | 6 +- .../Models/Packaging/InstallationSummary.cs | 2 +- .../Packaging/CompiledPackageXmlParser.cs | 49 +- .../Packaging/ConflictingPackageData.cs | 12 +- .../Packaging/IPackageActionRunner.cs | 23 + .../Packaging/IPackageInstallation.cs | 3 +- .../Packaging/PackageActionRunner.cs | 3 +- .../Packaging/PackageDataInstallation.cs | 1144 +++++++++++++++ .../Packaging/PackageInstallation.cs | 306 +--- .../Services/IPackagingService.cs | 75 - .../Services/Implement/PackagingService.cs | 1303 +---------------- src/Umbraco.Core/Umbraco.Core.csproj | 4 +- .../Packaging/PackageInstallationTest.cs | 12 +- .../Services/Importing/PackageImportTests.cs | 126 +- src/Umbraco.Tests/TestHelpers/TestObjects.cs | 27 +- src/Umbraco.Web/Composing/Current.cs | 2 +- .../Editors/ContentTypeController.cs | 29 +- .../Editors/PackageInstallController.cs | 5 +- src/Umbraco.Web/Umbraco.Web.csproj | 1 - src/Umbraco.Web/_Legacy/Packager/Installer.cs | 688 --------- 24 files changed, 1424 insertions(+), 2546 deletions(-) delete mode 100644 src/Umbraco.Core/Constants-Packaging.cs delete mode 100644 src/Umbraco.Core/Events/ImportEventArgs.cs create mode 100644 src/Umbraco.Core/Packaging/IPackageActionRunner.cs create mode 100644 src/Umbraco.Core/Packaging/PackageDataInstallation.cs delete mode 100644 src/Umbraco.Web/_Legacy/Packager/Installer.cs diff --git a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs index ac8f4beeb0..a09462c806 100644 --- a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs @@ -59,18 +59,19 @@ namespace Umbraco.Core.Composing.Composers composition.RegisterUnique(); - composition.RegisterUnique(); + composition.RegisterUnique(); composition.RegisterUnique(); composition.RegisterUnique(); composition.RegisterUnique(factory => CreatePackageRepository(factory, "createdPackages.config")); composition.RegisterUnique(factory => CreatePackageRepository(factory, "installedPackages.config")); + composition.RegisterUnique(); composition.RegisterUnique(); var appRoot = new DirectoryInfo(IOHelper.GetRootDirectorySafe()); composition.RegisterUnique(factory => //factory required because we need to pass in a string path new PackageInstallation( - factory.GetInstance(), factory.GetInstance(), - factory.GetInstance(), + factory.GetInstance(), factory.GetInstance(), + factory.GetInstance(), factory.GetInstance(), SystemDirectories.Packages, appRoot, appRoot)); diff --git a/src/Umbraco.Core/Composing/Current.cs b/src/Umbraco.Core/Composing/Current.cs index 4bed76d86f..5c8351924f 100644 --- a/src/Umbraco.Core/Composing/Current.cs +++ b/src/Umbraco.Core/Composing/Current.cs @@ -162,8 +162,8 @@ namespace Umbraco.Core.Composing internal static PackageActionCollection PackageActions => Factory.GetInstance(); - internal static PackageActionRunner PackageActionRunner - => Factory.GetInstance(); + internal static IPackageActionRunner PackageActionRunner + => Factory.GetInstance(); internal static PropertyValueConverterCollection PropertyValueConverters => Factory.GetInstance(); diff --git a/src/Umbraco.Core/Constants-Packaging.cs b/src/Umbraco.Core/Constants-Packaging.cs deleted file mode 100644 index 37f2c23fa3..0000000000 --- a/src/Umbraco.Core/Constants-Packaging.cs +++ /dev/null @@ -1,55 +0,0 @@ -namespace Umbraco.Core -{ - public static partial class Constants - { - /// - /// Defines the constants used for Umbraco packages in the package.config xml - /// - public static class Packaging - { - public const string UmbPackageNodeName = "umbPackage"; - public const string DataTypesNodeName = "DataTypes"; - public const string PackageXmlFileName = "package.xml"; - public const string UmbracoPackageExtention = ".umb"; - public const string DataTypeNodeName = "DataType"; - public const string LanguagesNodeName = "Languages"; - public const string FilesNodeName = "files"; - public const string StylesheetsNodeName = "Stylesheets"; - public const string TemplatesNodeName = "Templates"; - public const string NameNodeName = "Name"; - public const string TemplateNodeName = "Template"; - public const string AliasNodeNameSmall = "alias"; - public const string AliasNodeNameCapital = "Alias"; - public const string DictionaryItemsNodeName = "DictionaryItems"; - public const string DictionaryItemNodeName = "DictionaryItem"; - public const string MacrosNodeName = "Macros"; - public const string DocumentsNodeName = "Documents"; - public const string DocumentSetNodeName = "DocumentSet"; - public const string DocumentTypesNodeName = "DocumentTypes"; - public const string DocumentTypeNodeName = "DocumentType"; - public const string FileNodeName = "file"; - public const string OrgNameNodeName = "orgName"; - public const string OrgPathNodeName = "orgPath"; - public const string GuidNodeName = "guid"; - public const string StylesheetNodeName = "styleSheet"; - public const string MacroNodeName = "macro"; - public const string InfoNodeName = "info"; - public const string PackageRequirementsMajorXpath = "./package/requirements/major"; - public const string PackageRequirementsMinorXpath = "./package/requirements/minor"; - public const string PackageRequirementsPatchXpath = "./package/requirements/patch"; - public const string PackageNameXpath = "./package/name"; - public const string PackageVersionXpath = "./package/version"; - public const string PackageUrlXpath = "./package/url"; - public const string PackageLicenseXpath = "./package/license"; - public const string PackageLicenseXpathUrlAttribute = "url"; - public const string AuthorNameXpath = "./author/name"; - public const string AuthorWebsiteXpath = "./author/website"; - public const string ReadmeXpath = "./readme"; - public const string ControlNodeName = "control"; - public const string ActionNodeName = "Action"; - public const string ActionsNodeName = "Actions"; - public const string UndoNodeAttribute = "undo"; - public const string RunatNodeAttribute = "runat"; - } - } -} diff --git a/src/Umbraco.Core/Events/ImportEventArgs.cs b/src/Umbraco.Core/Events/ImportEventArgs.cs deleted file mode 100644 index fb8f7d4936..0000000000 --- a/src/Umbraco.Core/Events/ImportEventArgs.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Xml.Linq; - -namespace Umbraco.Core.Events -{ - public class ImportEventArgs : CancellableEnumerableObjectEventArgs, IEquatable> - { - /// - /// Constructor accepting an XElement with the xml being imported - /// - /// - public ImportEventArgs(XElement xml) : base(new List(), true) - { - Xml = xml; - } - - /// - /// Constructor accepting a list of entities and an XElement with the imported xml - /// - /// - /// - /// - public ImportEventArgs(IEnumerable eventObject, XElement xml, bool canCancel) - : base(eventObject, canCancel) - { - Xml = xml; - } - - protected ImportEventArgs(IEnumerable eventObject, bool canCancel) : base(eventObject, canCancel) - { - } - - protected ImportEventArgs(IEnumerable eventObject) : base(eventObject) - { - } - - /// - /// Returns all entities that were imported during the operation - /// - public IEnumerable ImportedEntities - { - get { return EventObject; } - } - - /// - /// Returns the xml relating to the import event - /// - public XElement Xml { get; private set; } - - public bool Equals(ImportEventArgs other) - { - if (ReferenceEquals(null, other)) return false; - if (ReferenceEquals(this, other)) return true; - return base.Equals(other) && Equals(Xml, other.Xml); - } - - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) return false; - return Equals((ImportEventArgs) obj); - } - - public override int GetHashCode() - { - unchecked - { - return (base.GetHashCode() * 397) ^ (Xml != null ? Xml.GetHashCode() : 0); - } - } - - public static bool operator ==(ImportEventArgs left, ImportEventArgs right) - { - return Equals(left, right); - } - - public static bool operator !=(ImportEventArgs left, ImportEventArgs right) - { - return !Equals(left, right); - } - } -} diff --git a/src/Umbraco.Core/Models/Packaging/CompiledPackage.cs b/src/Umbraco.Core/Models/Packaging/CompiledPackage.cs index 96159d1bbf..266c1f5518 100644 --- a/src/Umbraco.Core/Models/Packaging/CompiledPackage.cs +++ b/src/Umbraco.Core/Models/Packaging/CompiledPackage.cs @@ -34,7 +34,11 @@ namespace Umbraco.Core.Models.Packaging public IEnumerable Macros { get; set; } //fixme: make strongly typed public IEnumerable Templates { get; set; } //fixme: make strongly typed public IEnumerable Stylesheets { get; set; } //fixme: make strongly typed - + public IEnumerable DataTypes { get; set; } //fixme: make strongly typed + public IEnumerable Languages { get; set; } //fixme: make strongly typed + public IEnumerable DictionaryItems { get; set; } //fixme: make strongly typed + public IEnumerable DocumentTypes { get; set; } //fixme: make strongly typed + public IEnumerable Documents { get; set; } //fixme: make strongly typed } public class CompiledPackageFile diff --git a/src/Umbraco.Core/Models/Packaging/InstallationSummary.cs b/src/Umbraco.Core/Models/Packaging/InstallationSummary.cs index 1405259da2..b14e3d2a92 100644 --- a/src/Umbraco.Core/Models/Packaging/InstallationSummary.cs +++ b/src/Umbraco.Core/Models/Packaging/InstallationSummary.cs @@ -18,7 +18,7 @@ namespace Umbraco.Core.Models.Packaging public IEnumerable MacrosInstalled { get; set; } = Enumerable.Empty(); public IEnumerable FilesInstalled { get; set; } = Enumerable.Empty(); public IEnumerable TemplatesInstalled { get; set; } = Enumerable.Empty(); - public IEnumerable ContentTypesInstalled { get; set; } = Enumerable.Empty(); + public IEnumerable DocumentTypesInstalled { get; set; } = Enumerable.Empty(); public IEnumerable StylesheetsInstalled { get; set; } = Enumerable.Empty(); public IEnumerable ContentInstalled { get; set; } = Enumerable.Empty(); public IEnumerable Actions { get; set; } = Enumerable.Empty(); diff --git a/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs b/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs index 44dbded5d2..76f206f478 100644 --- a/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs +++ b/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs @@ -26,7 +26,7 @@ namespace Umbraco.Core.Packaging { if (xml == null) throw new ArgumentNullException(nameof(xml)); if (xml.Root == null) throw new ArgumentException(nameof(xml), "The xml document is invalid"); - if (xml.Root.Name != Constants.Packaging.UmbPackageNodeName) throw new FormatException("The xml document is invalid"); + if (xml.Root.Name != "umbPackage") throw new FormatException("The xml document is invalid"); var info = xml.Root.Element("info"); if (info == null) throw new FormatException("The xml document is invalid"); @@ -53,7 +53,6 @@ namespace Umbraco.Core.Packaging UmbracoVersionRequirementsType = requirements.AttributeValue("type").IsNullOrWhiteSpace() ? RequirementsType.Legacy : Enum.Parse(requirements.AttributeValue("type")), Control = package.Element("control")?.Value, Actions = xml.Element("Actions")?.ToString(SaveOptions.None) ?? "", //take the entire outer xml value - Files = xml.Root.Element("files")?.Elements("file")?.Select(x => new CompiledPackageFile { UniqueFileName = x.Element("guid")?.Value, @@ -64,7 +63,11 @@ namespace Umbraco.Core.Packaging Macros = xml.Element("Macros")?.Elements("macro") ?? Enumerable.Empty(), Templates = xml.Element("Templates")?.Elements("Template") ?? Enumerable.Empty(), Stylesheets = xml.Element("Stylesheets")?.Elements("styleSheet") ?? Enumerable.Empty(), - + DataTypes = xml.Element("DataTypes")?.Elements("DataType") ?? Enumerable.Empty(), + Languages = xml.Element("Languages")?.Elements("Language") ?? Enumerable.Empty(), + DictionaryItems = xml.Element("DictionaryItems")?.Elements("DictionaryItem") ?? Enumerable.Empty(), + DocumentTypes = xml.Element("DocumentTypes")?.Elements("DocumentType") ?? Enumerable.Empty(), + Documents = xml.Element("Documents")?.Elements("DocumentSet") ?? Enumerable.Empty(), }; def.Warnings = GetPreInstallWarnings(def, applicationRootFolder); @@ -133,9 +136,8 @@ namespace Umbraco.Core.Packaging { return pathElement.TrimStart(new[] { '\\', '/', '~' }).Replace("/", "\\"); } - - //fixme: This is duplicated in the parser - public static string UpdatePathPlaceholders(string path) + + private static string UpdatePathPlaceholders(string path) { if (path.Contains("[$")) { @@ -146,5 +148,40 @@ namespace Umbraco.Core.Packaging } return path; } + + public IEnumerable GetPackageActions(XElement actionsElement, string packageName) + { + if (actionsElement == null) { return new PackageAction[0]; } + + if (string.Equals("Actions", actionsElement.Name.LocalName) == false) + throw new ArgumentException($"Must be \"Actions\" as root", nameof(actionsElement)); + + return actionsElement.Elements("Action") + .Select(elemet => + { + var aliasAttr = elemet.Attribute("Alias"); + if (aliasAttr == null) + throw new ArgumentException("missing \"Alias\" atribute in alias element", nameof(actionsElement)); + + var packageAction = new PackageAction + { + XmlData = elemet, + Alias = aliasAttr.Value, + PackageName = packageName, + }; + + + var attr = elemet.Attribute("runat"); + + if (attr != null && Enum.TryParse(attr.Value, true, out ActionRunAt runAt)) { packageAction.RunAt = runAt; } + + attr = elemet.Attribute("undo"); + + if (attr != null && bool.TryParse(attr.Value, out var undo)) { packageAction.Undo = undo; } + + + return packageAction; + }).ToArray(); + } } } diff --git a/src/Umbraco.Core/Packaging/ConflictingPackageData.cs b/src/Umbraco.Core/Packaging/ConflictingPackageData.cs index 401d3b6a85..a37195806e 100644 --- a/src/Umbraco.Core/Packaging/ConflictingPackageData.cs +++ b/src/Umbraco.Core/Packaging/ConflictingPackageData.cs @@ -23,9 +23,9 @@ namespace Umbraco.Core.Packaging return stylesheetNodes .Select(n => { - var xElement = n.Element(Constants.Packaging.NameNodeName); + var xElement = n.Element("Name"); if (xElement == null) - throw new FormatException($"Missing \"{Constants.Packaging.NameNodeName}\" element"); + throw new FormatException("Missing \"Name\" element"); return _fileService.GetStylesheetByName(xElement.Value) as IFile; }) @@ -37,9 +37,9 @@ namespace Umbraco.Core.Packaging return templateNodes .Select(n => { - var xElement = n.Element(Constants.Packaging.AliasNodeNameCapital) ?? n.Element(Constants.Packaging.AliasNodeNameSmall); + var xElement = n.Element("Alias") ?? n.Element("alias"); if (xElement == null) - throw new FormatException($"missing a \"{Constants.Packaging.AliasNodeNameCapital}\" element"); + throw new FormatException("missing a \"Alias\" element"); return _fileService.GetTemplate(xElement.Value); }) @@ -51,9 +51,9 @@ namespace Umbraco.Core.Packaging return macroNodes .Select(n => { - var xElement = n.Element(Constants.Packaging.AliasNodeNameSmall) ?? n.Element(Constants.Packaging.AliasNodeNameCapital); + var xElement = n.Element("alias") ?? n.Element("Alias"); if (xElement == null) - throw new FormatException($"missing a \"{Constants.Packaging.AliasNodeNameSmall}\" element in {Constants.Packaging.AliasNodeNameSmall} element"); + throw new FormatException("missing a \"alias\" element in alias element"); return _macroService.GetByAlias(xElement.Value); }) diff --git a/src/Umbraco.Core/Packaging/IPackageActionRunner.cs b/src/Umbraco.Core/Packaging/IPackageActionRunner.cs new file mode 100644 index 0000000000..d5c6327115 --- /dev/null +++ b/src/Umbraco.Core/Packaging/IPackageActionRunner.cs @@ -0,0 +1,23 @@ +using System.Xml.Linq; + +namespace Umbraco.Core.Packaging +{ + public interface IPackageActionRunner + { + /// + /// Runs the package action with the specified action alias. + /// + /// Name of the package. + /// The action alias. + /// The action XML. + void RunPackageAction(string packageName, string actionAlias, XElement actionXml); + + /// + /// Undos the package action with the specified action alias. + /// + /// Name of the package. + /// The action alias. + /// The action XML. + void UndoPackageAction(string packageName, string actionAlias, XElement actionXml); + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Packaging/IPackageInstallation.cs b/src/Umbraco.Core/Packaging/IPackageInstallation.cs index 8ef3546c3d..83a21dcd2f 100644 --- a/src/Umbraco.Core/Packaging/IPackageInstallation.cs +++ b/src/Umbraco.Core/Packaging/IPackageInstallation.cs @@ -4,9 +4,8 @@ using Umbraco.Core.Models.Packaging; namespace Umbraco.Core.Packaging { - internal interface IPackageInstallation + public interface IPackageInstallation { - /// /// Installs a packages data and entities /// diff --git a/src/Umbraco.Core/Packaging/PackageActionRunner.cs b/src/Umbraco.Core/Packaging/PackageActionRunner.cs index 64b913989c..37103b0473 100644 --- a/src/Umbraco.Core/Packaging/PackageActionRunner.cs +++ b/src/Umbraco.Core/Packaging/PackageActionRunner.cs @@ -5,11 +5,10 @@ using Umbraco.Core._Legacy.PackageActions; namespace Umbraco.Core.Packaging { - /// /// Package actions are executed on packge install / uninstall. /// - public sealed class PackageActionRunner + internal class PackageActionRunner : IPackageActionRunner { private readonly ILogger _logger; private readonly PackageActionCollection _packageActions; diff --git a/src/Umbraco.Core/Packaging/PackageDataInstallation.cs b/src/Umbraco.Core/Packaging/PackageDataInstallation.cs new file mode 100644 index 0000000000..8ef99502c8 --- /dev/null +++ b/src/Umbraco.Core/Packaging/PackageDataInstallation.cs @@ -0,0 +1,1144 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using System.Web; +using System.Xml.Linq; +using System.Xml.XPath; +using Umbraco.Core.Collections; +using Umbraco.Core.IO; +using Umbraco.Core.Logging; +using Umbraco.Core.Models; +using Umbraco.Core.Models.Entities; +using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Services; +using Umbraco.Core.Services.Implement; + +namespace Umbraco.Core.Packaging +{ + internal class PackageDataInstallation + { + private readonly ILogger _logger; + private readonly IFileService _fileService; + private readonly IMacroService _macroService; + private readonly ILocalizationService _localizationService; + private readonly IDataTypeService _dataTypeService; + private readonly PropertyEditorCollection _propertyEditors; + private readonly IEntityService _entityService; + private readonly IContentTypeService _contentTypeService; + private readonly IContentService _contentService; + + public PackageDataInstallation(ILogger logger, IFileService fileService, IMacroService macroService, ILocalizationService localizationService, + IDataTypeService dataTypeService, IEntityService entityService, IContentTypeService contentTypeService, + IContentService contentService, PropertyEditorCollection propertyEditors) + { + _logger = logger; + _fileService = fileService; + _macroService = macroService; + _localizationService = localizationService; + _dataTypeService = dataTypeService; + _propertyEditors = propertyEditors; + _entityService = entityService; + _contentTypeService = contentTypeService; + _contentService = contentService; + } + + #region Content + + + public IEnumerable ImportContent(IEnumerable element, IDictionary importedDocumentTypes, int userId) + { + return element.Elements("DocumentSet").SelectMany(x => ImportContent(x, -1, importedDocumentTypes, userId)); + } + + /// + /// Imports and saves package xml as + /// + /// Xml to import + /// Optional parent Id for the content being imported + /// A dictionary of already imported document types (basically used as a cache) + /// Optional Id of the user performing the import + /// An enumrable list of generated content + public IEnumerable ImportContent(XElement element, int parentId, IDictionary importedDocumentTypes, int userId) + { + var name = element.Name.LocalName; + if (name.Equals("DocumentSet")) + { + //This is a regular deep-structured import + var roots = from doc in element.Elements() + where (string)doc.Attribute("isDoc") == "" + select doc; + + var contents = ParseDocumentRootXml(roots, parentId, importedDocumentTypes).ToList(); + if (contents.Any()) + _contentService.Save(contents, userId); + + return contents; + } + + var attribute = element.Attribute("isDoc"); + if (attribute != null) + { + //This is a single doc import + var elements = new List { element }; + var contents = ParseDocumentRootXml(elements, parentId, importedDocumentTypes).ToList(); + if (contents.Any()) + _contentService.Save(contents, userId); + + return contents; + } + + throw new ArgumentException( + "The passed in XElement is not valid! It does not contain a root element called " + + "'DocumentSet' (for structured imports) nor is the first element a Document (for single document import)."); + } + + private IEnumerable ParseDocumentRootXml(IEnumerable roots, int parentId, IDictionary importedContentTypes) + { + var contents = new List(); + foreach (var root in roots) + { + var contentTypeAlias = root.Name.LocalName; + + if (!importedContentTypes.ContainsKey(contentTypeAlias)) + { + var contentType = FindContentTypeByAlias(contentTypeAlias); + importedContentTypes.Add(contentTypeAlias, contentType); + } + + var content = CreateContentFromXml(root, importedContentTypes[contentTypeAlias], null, parentId); + contents.Add(content); + + var children = (from child in root.Elements() + where (string)child.Attribute("isDoc") == "" + select child) + .ToList(); + if (children.Any()) + contents.AddRange(CreateContentFromXml(children, content, importedContentTypes)); + } + return contents; + } + + private IEnumerable CreateContentFromXml(IEnumerable children, IContent parent, IDictionary importedContentTypes) + { + var list = new List(); + foreach (var child in children) + { + string contentTypeAlias = child.Name.LocalName; + + if (importedContentTypes.ContainsKey(contentTypeAlias) == false) + { + var contentType = FindContentTypeByAlias(contentTypeAlias); + importedContentTypes.Add(contentTypeAlias, contentType); + } + + //Create and add the child to the list + var content = CreateContentFromXml(child, importedContentTypes[contentTypeAlias], parent, default); + list.Add(content); + + //Recursive call + XElement child1 = child; + var grandChildren = (from grand in child1.Elements() + where (string)grand.Attribute("isDoc") == "" + select grand).ToList(); + + if (grandChildren.Any()) + list.AddRange(CreateContentFromXml(grandChildren, content, importedContentTypes)); + } + + return list; + } + + private IContent CreateContentFromXml(XElement element, IContentType contentType, IContent parent, int parentId) + { + var id = element.Attribute("id").Value; + var level = element.Attribute("level").Value; + var sortOrder = element.Attribute("sortOrder").Value; + var nodeName = element.Attribute("nodeName").Value; + var path = element.Attribute("path").Value; + //TODO: Shouldn't we be using this value??? + var template = element.Attribute("template").Value; + var key = Guid.Empty; + + var properties = from property in element.Elements() + where property.Attribute("isDoc") == null + select property; + + IContent content = parent == null + ? new Content(nodeName, parentId, contentType) + { + Level = int.Parse(level), + SortOrder = int.Parse(sortOrder) + } + : new Content(nodeName, parent, contentType) + { + Level = int.Parse(level), + SortOrder = int.Parse(sortOrder) + }; + + if (element.Attribute("key") != null && Guid.TryParse(element.Attribute("key").Value, out key)) + { + // update the Guid (for UDI support) + content.Key = key; + } + + foreach (var property in properties) + { + string propertyTypeAlias = property.Name.LocalName; + if (content.HasProperty(propertyTypeAlias)) + { + var propertyValue = property.Value; + + var propertyType = contentType.PropertyTypes.FirstOrDefault(pt => pt.Alias == propertyTypeAlias); + + //set property value + content.SetValue(propertyTypeAlias, propertyValue); + } + } + + return content; + } + + #endregion + + #region ContentTypes + + public IEnumerable ImportDocumentType(XElement docTypeElement, int userId) + { + return ImportDocumentTypes(new []{ docTypeElement }, userId); + } + + /// + /// Imports and saves package xml as + /// + /// Xml to import + /// Optional id of the User performing the operation. Default is zero (admin). + /// An enumrable list of generated ContentTypes + public IEnumerable ImportDocumentTypes(IEnumerable docTypeElements, int userId) + { + return ImportDocumentTypes(docTypeElements.ToList(), true, userId); + } + + /// + /// Imports and saves package xml as + /// + /// Xml to import + /// Boolean indicating whether or not to import the + /// Optional id of the User performing the operation. Default is zero (admin). + /// An enumrable list of generated ContentTypes + public IEnumerable ImportDocumentTypes(IReadOnlyCollection unsortedDocumentTypes, bool importStructure, int userId) + { + var importedContentTypes = new Dictionary(); + + //When you are importing a single doc type we have to assume that the depedencies are already there. + //Otherwise something like uSync won't work. + var graph = new TopoGraph>(x => x.Key, x => x.Dependencies); + var isSingleDocTypeImport = unsortedDocumentTypes.Count == 1; + + var importedFolders = CreateContentTypeFolderStructure(unsortedDocumentTypes); + + if (isSingleDocTypeImport == false) + { + //NOTE Here we sort the doctype XElements based on dependencies + //before creating the doc types - this should also allow for a better structure/inheritance support. + foreach (var documentType in unsortedDocumentTypes) + { + var elementCopy = documentType; + var infoElement = elementCopy.Element("Info"); + var dependencies = new HashSet(); + + //Add the Master as a dependency + if (string.IsNullOrEmpty((string)infoElement.Element("Master")) == false) + { + dependencies.Add(infoElement.Element("Master").Value); + } + + //Add compositions as dependencies + var compositionsElement = infoElement.Element("Compositions"); + if (compositionsElement != null && compositionsElement.HasElements) + { + var compositions = compositionsElement.Elements("Composition"); + if (compositions.Any()) + { + foreach (var composition in compositions) + { + dependencies.Add(composition.Value); + } + } + } + + graph.AddItem(TopoGraph.CreateNode(infoElement.Element("Alias").Value, elementCopy, dependencies.ToArray())); + } + } + + //Sorting the Document Types based on dependencies - if its not a single doc type import ref. #U4-5921 + var documentTypes = isSingleDocTypeImport + ? unsortedDocumentTypes.ToList() + : graph.GetSortedItems().Select(x => x.Item).ToList(); + + //Iterate the sorted document types and create them as IContentType objects + foreach (var documentType in documentTypes) + { + var alias = documentType.Element("Info").Element("Alias").Value; + if (importedContentTypes.ContainsKey(alias) == false) + { + var contentType = _contentTypeService.Get(alias); + importedContentTypes.Add(alias, contentType == null + ? CreateContentTypeFromXml(documentType, importedContentTypes) + : UpdateContentTypeFromXml(documentType, contentType, importedContentTypes)); + } + } + + foreach (var contentType in importedContentTypes) + { + var ct = contentType.Value; + if (importedFolders.ContainsKey(ct.Alias)) + { + ct.ParentId = importedFolders[ct.Alias]; + } + } + + //Save the newly created/updated IContentType objects + var list = importedContentTypes.Select(x => x.Value).ToList(); + _contentTypeService.Save(list, userId); + + //Now we can finish the import by updating the 'structure', + //which requires the doc types to be saved/available in the db + if (importStructure) + { + var updatedContentTypes = new List(); + //Update the structure here - we can't do it untill all DocTypes have been created + foreach (var documentType in documentTypes) + { + var alias = documentType.Element("Info").Element("Alias").Value; + var structureElement = documentType.Element("Structure"); + //Ensure that we only update ContentTypes which has actual structure-elements + if (structureElement == null || structureElement.Elements("DocumentType").Any() == false) continue; + + var updated = UpdateContentTypesStructure(importedContentTypes[alias], structureElement, importedContentTypes); + updatedContentTypes.Add(updated); + } + //Update ContentTypes with a newly added structure/list of allowed children + if (updatedContentTypes.Any()) + _contentTypeService.Save(updatedContentTypes, userId); + } + + return list; + } + + private Dictionary CreateContentTypeFolderStructure(IEnumerable unsortedDocumentTypes) + { + var importedFolders = new Dictionary(); + foreach (var documentType in unsortedDocumentTypes) + { + var foldersAttribute = documentType.Attribute("Folders"); + var infoElement = documentType.Element("Info"); + if (foldersAttribute != null && infoElement != null + //don't import any folder if this is a child doc type - the parent doc type will need to + //exist which contains it's folders + && ((string)infoElement.Element("Master")).IsNullOrWhiteSpace()) + { + var alias = documentType.Element("Info").Element("Alias").Value; + var folders = foldersAttribute.Value.Split('/'); + var rootFolder = HttpUtility.UrlDecode(folders[0]); + //level 1 = root level folders, there can only be one with the same name + var current = _contentTypeService.GetContainers(rootFolder, 1).FirstOrDefault(); + + if (current == null) + { + var tryCreateFolder = _contentTypeService.CreateContainer(-1, rootFolder); + if (tryCreateFolder == false) + { + _logger.Error(tryCreateFolder.Exception, "Could not create folder: {FolderName}", rootFolder); + throw tryCreateFolder.Exception; + } + var rootFolderId = tryCreateFolder.Result.Entity.Id; + current = _contentTypeService.GetContainer(rootFolderId); + } + + importedFolders.Add(alias, current.Id); + + for (var i = 1; i < folders.Length; i++) + { + var folderName = HttpUtility.UrlDecode(folders[i]); + current = CreateContentTypeChildFolder(folderName, current); + importedFolders[alias] = current.Id; + } + } + } + + return importedFolders; + } + + private EntityContainer CreateContentTypeChildFolder(string folderName, IUmbracoEntity current) + { + var children = _entityService.GetChildren(current.Id).ToArray(); + var found = children.Any(x => x.Name.InvariantEquals(folderName)); + if (found) + { + var containerId = children.Single(x => x.Name.InvariantEquals(folderName)).Id; + return _contentTypeService.GetContainer(containerId); + } + + var tryCreateFolder = _contentTypeService.CreateContainer(current.Id, folderName); + if (tryCreateFolder == false) + { + _logger.Error(tryCreateFolder.Exception, "Could not create folder: {FolderName}", folderName); + throw tryCreateFolder.Exception; + } + return _contentTypeService.GetContainer(tryCreateFolder.Result.Entity.Id); + } + + private IContentType CreateContentTypeFromXml(XElement documentType, IReadOnlyDictionary importedContentTypes) + { + var infoElement = documentType.Element("Info"); + + //Name of the master corresponds to the parent + var masterElement = infoElement.Element("Master"); + IContentType parent = null; + if (masterElement != null) + { + var masterAlias = masterElement.Value; + parent = importedContentTypes.ContainsKey(masterAlias) + ? importedContentTypes[masterAlias] + : _contentTypeService.Get(masterAlias); + } + + var alias = infoElement.Element("Alias").Value; + var contentType = parent == null + ? new ContentType(-1) { Alias = alias } + : new ContentType(parent, alias); + + if (parent != null) + contentType.AddContentType(parent); + + return UpdateContentTypeFromXml(documentType, contentType, importedContentTypes); + } + + private IContentType UpdateContentTypeFromXml(XElement documentType, IContentType contentType, IReadOnlyDictionary importedContentTypes) + { + var infoElement = documentType.Element("Info"); + var defaultTemplateElement = infoElement.Element("DefaultTemplate"); + + contentType.Name = infoElement.Element("Name").Value; + contentType.Icon = infoElement.Element("Icon").Value; + contentType.Thumbnail = infoElement.Element("Thumbnail").Value; + contentType.Description = infoElement.Element("Description").Value; + + //NOTE AllowAtRoot is a new property in the package xml so we need to verify it exists before using it. + var allowAtRoot = infoElement.Element("AllowAtRoot"); + if (allowAtRoot != null) + contentType.AllowedAsRoot = allowAtRoot.Value.InvariantEquals("true"); + + //NOTE IsListView is a new property in the package xml so we need to verify it exists before using it. + var isListView = infoElement.Element("IsListView"); + if (isListView != null) + contentType.IsContainer = isListView.Value.InvariantEquals("true"); + + //Name of the master corresponds to the parent and we need to ensure that the Parent Id is set + var masterElement = infoElement.Element("Master"); + if (masterElement != null) + { + var masterAlias = masterElement.Value; + IContentType parent = importedContentTypes.ContainsKey(masterAlias) + ? importedContentTypes[masterAlias] + : _contentTypeService.Get(masterAlias); + + contentType.SetParent(parent); + } + + //Update Compositions on the ContentType to ensure that they are as is defined in the package xml + var compositionsElement = infoElement.Element("Compositions"); + if (compositionsElement != null && compositionsElement.HasElements) + { + var compositions = compositionsElement.Elements("Composition"); + if (compositions.Any()) + { + foreach (var composition in compositions) + { + var compositionAlias = composition.Value; + var compositionContentType = importedContentTypes.ContainsKey(compositionAlias) + ? importedContentTypes[compositionAlias] + : _contentTypeService.Get(compositionAlias); + var added = contentType.AddContentType(compositionContentType); + } + } + } + + UpdateContentTypesAllowedTemplates(contentType, infoElement.Element("AllowedTemplates"), defaultTemplateElement); + UpdateContentTypesTabs(contentType, documentType.Element("Tabs")); + UpdateContentTypesProperties(contentType, documentType.Element("GenericProperties")); + + return contentType; + } + + private void UpdateContentTypesAllowedTemplates(IContentType contentType, + XElement allowedTemplatesElement, XElement defaultTemplateElement) + { + if (allowedTemplatesElement != null && allowedTemplatesElement.Elements("Template").Any()) + { + var allowedTemplates = contentType.AllowedTemplates.ToList(); + foreach (var templateElement in allowedTemplatesElement.Elements("Template")) + { + var alias = templateElement.Value; + var template = _fileService.GetTemplate(alias.ToSafeAlias()); + if (template != null) + { + if (allowedTemplates.Any(x => x.Id == template.Id)) continue; + allowedTemplates.Add(template); + } + else + { + _logger.Warn("Packager: Error handling allowed templates. Template with alias '{TemplateAlias}' could not be found.", alias); + } + } + + contentType.AllowedTemplates = allowedTemplates; + } + + if (string.IsNullOrEmpty((string)defaultTemplateElement) == false) + { + var defaultTemplate = _fileService.GetTemplate(defaultTemplateElement.Value.ToSafeAlias()); + if (defaultTemplate != null) + { + contentType.SetDefaultTemplate(defaultTemplate); + } + else + { + _logger.Warn("Packager: Error handling default template. Default template with alias '{DefaultTemplateAlias}' could not be found.", defaultTemplateElement.Value); + } + } + } + + private void UpdateContentTypesTabs(IContentType contentType, XElement tabElement) + { + if (tabElement == null) + return; + + var tabs = tabElement.Elements("Tab"); + foreach (var tab in tabs) + { + var id = tab.Element("Id").Value;//Do we need to use this for tracking? + var caption = tab.Element("Caption").Value; + + if (contentType.PropertyGroups.Contains(caption) == false) + { + contentType.AddPropertyGroup(caption); + + } + + int sortOrder; + if (tab.Element("SortOrder") != null && int.TryParse(tab.Element("SortOrder").Value, out sortOrder)) + { + // Override the sort order with the imported value + contentType.PropertyGroups[caption].SortOrder = sortOrder; + } + } + } + + private void UpdateContentTypesProperties(IContentType contentType, XElement genericPropertiesElement) + { + var properties = genericPropertiesElement.Elements("GenericProperty"); + foreach (var property in properties) + { + var dataTypeDefinitionId = new Guid(property.Element("Definition").Value);//Unique Id for a DataTypeDefinition + + var dataTypeDefinition = _dataTypeService.GetDataType(dataTypeDefinitionId); + + //If no DataTypeDefinition with the guid from the xml wasn't found OR the ControlId on the DataTypeDefinition didn't match the DataType Id + //We look up a DataTypeDefinition that matches + + + //get the alias as a string for use below + var propertyEditorAlias = property.Element("Type").Value.Trim(); + + //If no DataTypeDefinition with the guid from the xml wasn't found OR the ControlId on the DataTypeDefinition didn't match the DataType Id + //We look up a DataTypeDefinition that matches + + if (dataTypeDefinition == null) + { + var dataTypeDefinitions = _dataTypeService.GetByEditorAlias(propertyEditorAlias); + if (dataTypeDefinitions != null && dataTypeDefinitions.Any()) + { + dataTypeDefinition = dataTypeDefinitions.FirstOrDefault(); + } + } + else if (dataTypeDefinition.EditorAlias != propertyEditorAlias) + { + var dataTypeDefinitions = _dataTypeService.GetByEditorAlias(propertyEditorAlias); + if (dataTypeDefinitions != null && dataTypeDefinitions.Any()) + { + dataTypeDefinition = dataTypeDefinitions.FirstOrDefault(); + } + } + + // For backwards compatibility, if no datatype with that ID can be found, we're letting this fail silently. + // This means that the property will not be created. + if (dataTypeDefinition == null) + { + _logger.Warn("Packager: Error handling creation of PropertyType '{PropertyType}'. Could not find DataTypeDefintion with unique id '{DataTypeDefinitionId}' nor one referencing the DataType with a property editor alias (or legacy control id) '{PropertyEditorAlias}'. Did the package creator forget to package up custom datatypes? This property will be converted to a label/readonly editor if one exists.", + property.Element("Name").Value, dataTypeDefinitionId, property.Element("Type").Value.Trim()); + + //convert to a label! + dataTypeDefinition = _dataTypeService.GetByEditorAlias(Constants.PropertyEditors.Aliases.NoEdit).FirstOrDefault(); + //if for some odd reason this isn't there then ignore + if (dataTypeDefinition == null) continue; + } + + var sortOrder = 0; + var sortOrderElement = property.Element("SortOrder"); + if (sortOrderElement != null) + int.TryParse(sortOrderElement.Value, out sortOrder); + var propertyType = new PropertyType(dataTypeDefinition, property.Element("Alias").Value) + { + Name = property.Element("Name").Value, + Description = (string)property.Element("Description"), + Mandatory = property.Element("Mandatory") != null ? property.Element("Mandatory").Value.ToLowerInvariant().Equals("true") : false, + ValidationRegExp = (string)property.Element("Validation"), + SortOrder = sortOrder + }; + + var tab = (string)property.Element("Tab"); + if (string.IsNullOrEmpty(tab)) + { + contentType.AddPropertyType(propertyType); + } + else + { + contentType.AddPropertyType(propertyType, tab); + } + } + } + + private IContentType UpdateContentTypesStructure(IContentType contentType, XElement structureElement, IReadOnlyDictionary importedContentTypes) + { + var allowedChildren = contentType.AllowedContentTypes.ToList(); + int sortOrder = allowedChildren.Any() ? allowedChildren.Last().SortOrder : 0; + foreach (var element in structureElement.Elements("DocumentType")) + { + var alias = element.Value; + + var allowedChild = importedContentTypes.ContainsKey(alias) ? importedContentTypes[alias] : _contentTypeService.Get(alias); + if (allowedChild == null) + { + _logger.Warn( + "Packager: Error handling DocumentType structure. DocumentType with alias '{DoctypeAlias}' could not be found and was not added to the structure for '{DoctypeStructureAlias}'.", + alias, contentType.Alias); + continue; + } + + if (allowedChildren.Any(x => x.Id.IsValueCreated && x.Id.Value == allowedChild.Id)) continue; + + allowedChildren.Add(new ContentTypeSort(new Lazy(() => allowedChild.Id), sortOrder, allowedChild.Alias)); + sortOrder++; + } + + contentType.AllowedContentTypes = allowedChildren; + return contentType; + } + + /// + /// Used during Content import to ensure that the ContentType of a content item exists + /// + /// + /// + private IContentType FindContentTypeByAlias(string contentTypeAlias) + { + var contentType = _contentTypeService.Get(contentTypeAlias); + + if (contentType == null) + throw new Exception($"ContentType matching the passed in Alias: '{contentTypeAlias}' was null"); + + return contentType; + } + + #endregion + + #region DataTypes + + /// + /// Imports and saves package xml as + /// + /// Xml to import + /// Optional id of the user + /// An enumrable list of generated DataTypeDefinitions + public IEnumerable ImportDataTypes(IReadOnlyCollection dataTypeElements, int userId) + { + var dataTypes = new List(); + + var importedFolders = CreateDataTypeFolderStructure(dataTypeElements); + + foreach (var dataTypeElement in dataTypeElements) + { + var dataTypeDefinitionName = dataTypeElement.AttributeValue("Name"); + + var dataTypeDefinitionId = dataTypeElement.AttributeValue("Definition"); + var databaseTypeAttribute = dataTypeElement.Attribute("DatabaseType"); + + var parentId = -1; + if (importedFolders.ContainsKey(dataTypeDefinitionName)) + parentId = importedFolders[dataTypeDefinitionName]; + + var definition = _dataTypeService.GetDataType(dataTypeDefinitionId); + //If the datatypedefinition doesn't already exist we create a new new according to the one in the package xml + if (definition == null) + { + var databaseType = databaseTypeAttribute?.Value.EnumParse(true) ?? ValueStorageType.Ntext; + + // the Id field is actually the string property editor Alias + // however, the actual editor with this alias could be installed with the package, and + // therefore not yet part of the _propertyEditors collection, so we cannot try and get + // the actual editor - going with a void editor + + var editorAlias = dataTypeElement.Attribute("Id")?.Value?.Trim(); + if (!_propertyEditors.TryGet(editorAlias, out var editor)) + editor = new VoidEditor(_logger) { Alias = editorAlias }; + + var dataType = new DataType(editor) + { + Key = dataTypeDefinitionId, + Name = dataTypeDefinitionName, + DatabaseType = databaseType, + ParentId = parentId + }; + + var configurationAttributeValue = dataTypeElement.Attribute("Configuration")?.Value; + if (!string.IsNullOrWhiteSpace(configurationAttributeValue)) + dataType.Configuration = editor.GetConfigurationEditor().FromDatabase(configurationAttributeValue); + + dataTypes.Add(dataType); + } + else + { + definition.ParentId = parentId; + _dataTypeService.Save(definition, userId); + } + } + + if (dataTypes.Count > 0) + { + _dataTypeService.Save(dataTypes, userId, true); + } + + return dataTypes; + } + + private Dictionary CreateDataTypeFolderStructure(IEnumerable datatypeElements) + { + var importedFolders = new Dictionary(); + foreach (var datatypeElement in datatypeElements) + { + var foldersAttribute = datatypeElement.Attribute("Folders"); + if (foldersAttribute != null) + { + var name = datatypeElement.Attribute("Name").Value; + var folders = foldersAttribute.Value.Split('/'); + var rootFolder = HttpUtility.UrlDecode(folders[0]); + //there will only be a single result by name for level 1 (root) containers + var current = _dataTypeService.GetContainers(rootFolder, 1).FirstOrDefault(); + + if (current == null) + { + var tryCreateFolder = _dataTypeService.CreateContainer(-1, rootFolder); + if (tryCreateFolder == false) + { + _logger.Error(tryCreateFolder.Exception, "Could not create folder: {FolderName}", rootFolder); + throw tryCreateFolder.Exception; + } + current = _dataTypeService.GetContainer(tryCreateFolder.Result.Entity.Id); + } + + importedFolders.Add(name, current.Id); + + for (var i = 1; i < folders.Length; i++) + { + var folderName = HttpUtility.UrlDecode(folders[i]); + current = CreateDataTypeChildFolder(folderName, current); + importedFolders[name] = current.Id; + } + } + } + + return importedFolders; + } + + private EntityContainer CreateDataTypeChildFolder(string folderName, IUmbracoEntity current) + { + var children = _entityService.GetChildren(current.Id).ToArray(); + var found = children.Any(x => x.Name.InvariantEquals(folderName)); + if (found) + { + var containerId = children.Single(x => x.Name.InvariantEquals(folderName)).Id; + return _dataTypeService.GetContainer(containerId); + } + + var tryCreateFolder = _dataTypeService.CreateContainer(current.Id, folderName); + if (tryCreateFolder == false) + { + _logger.Error(tryCreateFolder.Exception, "Could not create folder: {FolderName}", folderName); + throw tryCreateFolder.Exception; + } + return _dataTypeService.GetContainer(tryCreateFolder.Result.Entity.Id); + } + + #endregion + + #region Dictionary Items + + /// + /// Imports and saves the 'DictionaryItems' part of the package xml as a list of + /// + /// Xml to import + /// + /// An enumerable list of dictionary items + public IEnumerable ImportDictionaryItems(IEnumerable dictionaryItemElementList, int userId) + { + var languages = _localizationService.GetAllLanguages().ToList(); + return ImportDictionaryItems(dictionaryItemElementList, languages, null, userId); + } + + private IEnumerable ImportDictionaryItems(IEnumerable dictionaryItemElementList, List languages, Guid? parentId, int userId) + { + var items = new List(); + foreach (var dictionaryItemElement in dictionaryItemElementList) + items.AddRange(ImportDictionaryItem(dictionaryItemElement, languages, parentId, userId)); + + return items; + } + + private IEnumerable ImportDictionaryItem(XElement dictionaryItemElement, List languages, Guid? parentId, int userId) + { + var items = new List(); + + IDictionaryItem dictionaryItem; + var key = dictionaryItemElement.Attribute("Key").Value; + if (_localizationService.DictionaryItemExists(key)) + dictionaryItem = GetAndUpdateDictionaryItem(key, dictionaryItemElement, languages); + else + dictionaryItem = CreateNewDictionaryItem(key, dictionaryItemElement, languages, parentId); + _localizationService.Save(dictionaryItem, userId); + items.Add(dictionaryItem); + + items.AddRange(ImportDictionaryItems(dictionaryItemElement.Elements("DictionaryItem"), languages, dictionaryItem.Key, userId)); + return items; + } + + private IDictionaryItem GetAndUpdateDictionaryItem(string key, XElement dictionaryItemElement, List languages) + { + var dictionaryItem = _localizationService.GetDictionaryItemByKey(key); + var translations = dictionaryItem.Translations.ToList(); + foreach (var valueElement in dictionaryItemElement.Elements("Value").Where(v => DictionaryValueIsNew(translations, v))) + AddDictionaryTranslation(translations, valueElement, languages); + dictionaryItem.Translations = translations; + return dictionaryItem; + } + + private static DictionaryItem CreateNewDictionaryItem(string key, XElement dictionaryItemElement, List languages, Guid? parentId) + { + var dictionaryItem = parentId.HasValue ? new DictionaryItem(parentId.Value, key) : new DictionaryItem(key); + var translations = new List(); + + foreach (var valueElement in dictionaryItemElement.Elements("Value")) + AddDictionaryTranslation(translations, valueElement, languages); + + dictionaryItem.Translations = translations; + return dictionaryItem; + } + + private static bool DictionaryValueIsNew(IEnumerable translations, XElement valueElement) + { + return translations.All(t => + String.Compare(t.Language.IsoCode, valueElement.Attribute("LanguageCultureAlias").Value, + StringComparison.InvariantCultureIgnoreCase) != 0 + ); + } + + private static void AddDictionaryTranslation(ICollection translations, XElement valueElement, IEnumerable languages) + { + var languageId = valueElement.Attribute("LanguageCultureAlias").Value; + var language = languages.SingleOrDefault(l => l.IsoCode == languageId); + if (language == null) + return; + var translation = new DictionaryTranslation(language, valueElement.Value); + translations.Add(translation); + } + + #endregion + + #region Languages + + + /// + /// Imports and saves the 'Languages' part of a package xml as a list of + /// + /// Xml to import + /// Optional id of the User performing the operation + /// An enumerable list of generated languages + public IEnumerable ImportLanguages(IEnumerable languageElements, int userId) + { + var list = new List(); + foreach (var languageElement in languageElements) + { + var isoCode = languageElement.AttributeValue("CultureAlias"); + var existingLanguage = _localizationService.GetLanguageByIsoCode(isoCode); + if (existingLanguage != null) continue; + var langauge = new Language(isoCode) + { + CultureName = languageElement.AttributeValue("FriendlyName") + }; + _localizationService.Save(langauge, userId); + list.Add(langauge); + } + + return list; + } + + #endregion + + #region Macros + + /// + /// Imports and saves the 'Macros' part of a package xml as a list of + /// + /// Xml to import + /// Optional id of the User performing the operation + /// + public IEnumerable ImportMacros(IEnumerable macroElements, int userId) + { + var macros = macroElements.Select(ParseMacroElement).ToList(); + + foreach (var macro in macros) + { + var existing = _macroService.GetByAlias(macro.Alias); + if (existing != null) + macro.Id = existing.Id; + + _macroService.Save(macro, userId); + } + + return macros; + } + + private IMacro ParseMacroElement(XElement macroElement) + { + var macroName = macroElement.Element("name").Value; + var macroAlias = macroElement.Element("alias").Value; + var macroType = Enum.Parse(macroElement.Element("macroType").Value); + var macroSource = macroElement.Element("macroSource").Value; + + //Following xml elements are treated as nullable properties + var useInEditorElement = macroElement.Element("useInEditor"); + var useInEditor = false; + if (useInEditorElement != null && string.IsNullOrEmpty((string)useInEditorElement) == false) + { + useInEditor = bool.Parse(useInEditorElement.Value); + } + var cacheDurationElement = macroElement.Element("refreshRate"); + var cacheDuration = 0; + if (cacheDurationElement != null && string.IsNullOrEmpty((string)cacheDurationElement) == false) + { + cacheDuration = int.Parse(cacheDurationElement.Value); + } + var cacheByMemberElement = macroElement.Element("cacheByMember"); + var cacheByMember = false; + if (cacheByMemberElement != null && string.IsNullOrEmpty((string)cacheByMemberElement) == false) + { + cacheByMember = bool.Parse(cacheByMemberElement.Value); + } + var cacheByPageElement = macroElement.Element("cacheByPage"); + var cacheByPage = false; + if (cacheByPageElement != null && string.IsNullOrEmpty((string)cacheByPageElement) == false) + { + cacheByPage = bool.Parse(cacheByPageElement.Value); + } + var dontRenderElement = macroElement.Element("dontRender"); + var dontRender = true; + if (dontRenderElement != null && string.IsNullOrEmpty((string)dontRenderElement) == false) + { + dontRender = bool.Parse(dontRenderElement.Value); + } + + var existingMacro = _macroService.GetByAlias(macroAlias) as Macro; + var macro = existingMacro ?? new Macro(macroAlias, macroName, macroSource, macroType, + cacheByPage, cacheByMember, dontRender, useInEditor, cacheDuration); + + var properties = macroElement.Element("properties"); + if (properties != null) + { + int sortOrder = 0; + foreach (var property in properties.Elements()) + { + var propertyName = property.Attribute("name").Value; + var propertyAlias = property.Attribute("alias").Value; + var editorAlias = property.Attribute("propertyType").Value; + var sortOrderAttribute = property.Attribute("sortOrder"); + if (sortOrderAttribute != null) + { + sortOrder = int.Parse(sortOrderAttribute.Value); + } + + if (macro.Properties.Values.Any(x => string.Equals(x.Alias, propertyAlias, StringComparison.OrdinalIgnoreCase))) continue; + macro.Properties.Add(new MacroProperty(propertyAlias, propertyName, sortOrder, editorAlias)); + sortOrder++; + } + } + return macro; + } + + + + + + #endregion + + #region Stylesheets + + public IEnumerable ImportStylesheets(IEnumerable stylesheetElements, int userId) + { + var result = new List(); + + foreach (var n in stylesheetElements) + { + var stylesheetName = n.Element("Name")?.Value; + if (stylesheetName.IsNullOrWhiteSpace()) continue; + + var s = _fileService.GetStylesheetByName(stylesheetName); + if (s == null) + { + var fileName = n.Element("FileName")?.Value; + if (fileName == null) continue; + var content = n.Element("Content")?.Value; + if (content == null) continue; + + s = new Stylesheet(fileName) { Content = content }; + _fileService.SaveStylesheet(s); + } + + foreach (var prop in n.XPathSelectElements("Properties/Property")) + { + var alias = prop.Element("Alias")?.Value; + var sp = s.Properties.SingleOrDefault(p => p != null && p.Alias == alias); + var name = prop.Element("Name")?.Value; + if (sp == null) + { + sp = new StylesheetProperty(name, "#" + name.ToSafeAlias(), ""); + s.AddProperty(sp); + } + else + { + //sp.Text = name; + //Changing the name requires removing the current property and then adding another new one + if (sp.Name != name) + { + s.RemoveProperty(sp.Name); + var newProp = new StylesheetProperty(name, sp.Alias, sp.Value); + s.AddProperty(newProp); + sp = newProp; + } + } + sp.Alias = alias; + sp.Value = prop.Element("Value")?.Value; + } + _fileService.SaveStylesheet(s); + result.Add(s); + } + + return result; + } + + #endregion + + #region Templates + + public IEnumerable ImportTemplate(XElement templateElement, int userId) + { + return ImportTemplates(new[] {templateElement}, userId); + } + + /// + /// Imports and saves package xml as + /// + /// Xml to import + /// Optional user id + /// An enumrable list of generated Templates + public IEnumerable ImportTemplates(IReadOnlyCollection templateElements, int userId) + { + var templates = new List(); + + var graph = new TopoGraph>(x => x.Key, x => x.Dependencies); + + foreach (var tempElement in templateElements) + { + var dependencies = new List(); + var elementCopy = tempElement; + //Ensure that the Master of the current template is part of the import, otherwise we ignore this dependency as part of the dependency sorting. + if (string.IsNullOrEmpty((string)elementCopy.Element("Master")) == false && + templateElements.Any(x => (string)x.Element("Alias") == (string)elementCopy.Element("Master"))) + { + dependencies.Add((string)elementCopy.Element("Master")); + } + else if (string.IsNullOrEmpty((string)elementCopy.Element("Master")) == false && + templateElements.Any(x => (string)x.Element("Alias") == (string)elementCopy.Element("Master")) == false) + { + _logger.Info( + "Template '{TemplateAlias}' has an invalid Master '{TemplateMaster}', so the reference has been ignored.", + (string)elementCopy.Element("Alias"), + (string)elementCopy.Element("Master")); + } + + graph.AddItem(TopoGraph.CreateNode((string)elementCopy.Element("Alias"), elementCopy, dependencies)); + } + + //Sort templates by dependencies to a potential master template + var sorted = graph.GetSortedItems(); + foreach (var item in sorted) + { + var templateElement = item.Item; + + var templateName = templateElement.Element("Name").Value; + var alias = templateElement.Element("Alias").Value; + var design = templateElement.Element("Design").Value; + var masterElement = templateElement.Element("Master"); + + var isMasterPage = IsMasterPageSyntax(design); + var path = isMasterPage ? MasterpagePath(alias) : ViewPath(alias); + + var existingTemplate = _fileService.GetTemplate(alias) as Template; + var template = existingTemplate ?? new Template(templateName, alias); + template.Content = design; + if (masterElement != null && string.IsNullOrEmpty((string)masterElement) == false) + { + template.MasterTemplateAlias = masterElement.Value; + var masterTemplate = templates.FirstOrDefault(x => x.Alias == masterElement.Value); + if (masterTemplate != null) + template.MasterTemplateId = new Lazy(() => masterTemplate.Id); + } + templates.Add(template); + } + + if (templates.Any()) + _fileService.SaveTemplate(templates, userId); + + return templates; + } + + + private bool IsMasterPageSyntax(string code) + { + return Regex.IsMatch(code, @"<%@\s*Master", RegexOptions.IgnoreCase) || + code.InvariantContains(" /// Constructor /// - /// + /// /// /// + /// /// /// The relative path of the package storage folder (i.e. ~/App_Data/Packages ) /// @@ -36,13 +38,14 @@ namespace Umbraco.Core.Packaging /// /// The destination root folder to extract the package files (generally the same as applicationRoot) but can be modified for testing /// - public PackageInstallation(IPackagingService packagingService, PackageFileInstallation packageFileInstallation, CompiledPackageXmlParser parser, + public PackageInstallation(PackageDataInstallation packageDataInstallation, PackageFileInstallation packageFileInstallation, CompiledPackageXmlParser parser, IPackageActionRunner packageActionRunner, string packagesFolderPath, DirectoryInfo applicationRootFolder, DirectoryInfo packageExtractionFolder) { _packageExtraction = new PackageExtraction(); - _packageFileInstallation = packageFileInstallation; - _packagingService = packagingService ?? throw new ArgumentNullException(nameof(packagingService)); + _packageFileInstallation = packageFileInstallation ?? throw new ArgumentNullException(nameof(packageFileInstallation)); + _packageDataInstallation = packageDataInstallation ?? throw new ArgumentNullException(nameof(packageDataInstallation)); _parser = parser; + _packageActionRunner = packageActionRunner; _packagesFolderPath = packagesFolderPath; _applicationRootFolder = applicationRootFolder; _packageExtractionFolder = packageExtractionFolder; @@ -61,8 +64,6 @@ namespace Umbraco.Core.Packaging return compiledPackage; } - //fixme: Should we move all of the ImportXXXX methods here instead of on the IPackagingService? we don't want to have cicurlar refs - public IEnumerable InstallPackageFiles(PackageDefinition packageDefinition, CompiledPackage compiledPackage, int userId) { if (packageDefinition == null) throw new ArgumentNullException(nameof(packageDefinition)); @@ -79,118 +80,77 @@ namespace Umbraco.Core.Packaging public InstallationSummary InstallPackageData(PackageDefinition packageDefinition, CompiledPackage compiledPackage, int userId) { - //fixme: fill this in - throw new NotImplementedException(); + //TODO: Update the PackageDefinition! + + var installationSummary = new InstallationSummary + { + DataTypesInstalled = _packageDataInstallation.ImportDataTypes(compiledPackage.DataTypes.ToList(), userId), + LanguagesInstalled = _packageDataInstallation.ImportLanguages(compiledPackage.Languages, userId), + DictionaryItemsInstalled = _packageDataInstallation.ImportDictionaryItems(compiledPackage.DictionaryItems, userId), + MacrosInstalled = _packageDataInstallation.ImportMacros(compiledPackage.Macros, userId), + TemplatesInstalled = _packageDataInstallation.ImportTemplates(compiledPackage.Templates.ToList(), userId), + DocumentTypesInstalled = _packageDataInstallation.ImportDocumentTypes(compiledPackage.DocumentTypes, userId) + }; + + //we need a reference to the imported doc types to continue + var importedDocTypes = installationSummary.DocumentTypesInstalled.ToDictionary(x => x.Alias, x => x); + + installationSummary.StylesheetsInstalled = _packageDataInstallation.ImportStylesheets(compiledPackage.Stylesheets, userId); + installationSummary.ContentInstalled = _packageDataInstallation.ImportContent(compiledPackage.Documents, importedDocTypes, userId); + installationSummary.Actions = _parser.GetPackageActions(XElement.Parse(compiledPackage.Actions), compiledPackage.Name); + installationSummary.MetaData = compiledPackage; + //fixme: Verify that this will work! + installationSummary.FilesInstalled = packageDefinition.Files; + installationSummary.PackageInstalled = true; + + //make sure the definition is up to date with everything + + foreach (var x in installationSummary.DataTypesInstalled) packageDefinition.DataTypes.Add(x.Id.ToInvariantString()); + foreach (var x in installationSummary.LanguagesInstalled) packageDefinition.Languages.Add(x.Id.ToInvariantString()); + foreach (var x in installationSummary.DictionaryItemsInstalled) packageDefinition.DictionaryItems.Add(x.Id.ToInvariantString()); + foreach (var x in installationSummary.MacrosInstalled) packageDefinition.Macros.Add(x.Id.ToInvariantString()); + foreach (var x in installationSummary.TemplatesInstalled) packageDefinition.Templates.Add(x.Id.ToInvariantString()); + foreach (var x in installationSummary.DocumentTypesInstalled) packageDefinition.DocumentTypes.Add(x.Id.ToInvariantString()); + foreach (var x in installationSummary.StylesheetsInstalled) packageDefinition.Stylesheets.Add(x.Id.ToInvariantString()); + var contentInstalled = installationSummary.ContentInstalled.ToList(); + packageDefinition.ContentNodeId = contentInstalled.Count > 0 ? contentInstalled[0].Id.ToInvariantString() : null; + + RunPackageActions(packageDefinition, installationSummary.Actions); + + return installationSummary; } - //public InstallationSummary InstallPackage(FileInfo packageFile, int userId) - //{ - // XElement dataTypes; - // XElement languages; - // XElement dictionaryItems; - // XElement macroes; - // XElement files; - // XElement templates; - // XElement documentTypes; - // XElement styleSheets; - // XElement documentSet; - // XElement documents; - // XElement actions; - // IPackageInfo metaData; - // InstallationSummary installationSummary; + private void RunPackageActions(PackageDefinition packageDefinition, IEnumerable actions) + { + foreach (var n in actions) + { + var undo = n.Undo; + if (undo) + packageDefinition.Actions += n.XmlData.ToString(); - // try - // { - // XElement rootElement = GetConfigXmlElement(packageFile); - // PackageSupportedCheck(rootElement); - // PackageStructureSanityCheck(packageFile, rootElement); - // dataTypes = rootElement.Element(Constants.Packaging.DataTypesNodeName); - // languages = rootElement.Element(Constants.Packaging.LanguagesNodeName); - // dictionaryItems = rootElement.Element(Constants.Packaging.DictionaryItemsNodeName); - // macroes = rootElement.Element(Constants.Packaging.MacrosNodeName); - // files = rootElement.Element(Constants.Packaging.FilesNodeName); - // templates = rootElement.Element(Constants.Packaging.TemplatesNodeName); - // documentTypes = rootElement.Element(Constants.Packaging.DocumentTypesNodeName); - // styleSheets = rootElement.Element(Constants.Packaging.StylesheetsNodeName); - // documentSet = rootElement.Element(Constants.Packaging.DocumentSetNodeName); - // documents = rootElement.Element(Constants.Packaging.DocumentsNodeName); - // actions = rootElement.Element(Constants.Packaging.ActionsNodeName); + //Run the actions tagged only for 'install' + if (n.RunAt != ActionRunAt.Install) continue; - // metaData = GetMetaData(rootElement); - // installationSummary = new InstallationSummary {MetaData = metaData}; - // } - // catch (Exception e) - // { - // throw new Exception("Error reading " + packageFile, e); - // } - - // try - // { - // var dataTypeDefinitions = EmptyEnumerableIfNull(dataTypes) ?? InstallDataTypes(dataTypes, userId); - // installationSummary.DataTypesInstalled = dataTypeDefinitions; - - // var languagesInstalled = EmptyEnumerableIfNull(languages) ?? InstallLanguages(languages, userId); - // installationSummary.LanguagesInstalled = languagesInstalled; - - // var dictionaryInstalled = EmptyEnumerableIfNull(dictionaryItems) ?? InstallDictionaryItems(dictionaryItems); - // installationSummary.DictionaryItemsInstalled = dictionaryInstalled; - - // var macros = EmptyEnumerableIfNull(macroes) ?? InstallMacros(macroes, userId); - // installationSummary.MacrosInstalled = macros; - - // var templatesInstalled = EmptyEnumerableIfNull(templates) ?? InstallTemplats(templates, userId); - // installationSummary.TemplatesInstalled = templatesInstalled; - - // var documentTypesInstalled = EmptyEnumerableIfNull(documentTypes) ?? InstallDocumentTypes(documentTypes, userId); - // installationSummary.ContentTypesInstalled =documentTypesInstalled; - - // var stylesheetsInstalled = EmptyEnumerableIfNull(styleSheets) ?? InstallStylesheets(styleSheets); - // installationSummary.StylesheetsInstalled = stylesheetsInstalled; - - // var documentsInstalled = documents != null ? InstallDocuments(documents, userId) - // : EmptyEnumerableIfNull(documentSet) - // ?? InstallDocuments(documentSet, userId); - // installationSummary.ContentInstalled = documentsInstalled; - - // var packageActions = EmptyEnumerableIfNull(actions) ?? GetPackageActions(actions, metaData.Name); - // installationSummary.Actions = packageActions; - - // installationSummary.PackageInstalled = true; - - // return installationSummary; - // } - // catch (Exception e) - // { - // throw new Exception("Error installing package " + packageFile, e); - // } - //} + if (n.Alias.IsNullOrWhiteSpace() == false) + _packageActionRunner.RunPackageAction(packageDefinition.Name, n.Alias, n.XmlData); + } + } private FileInfo GetPackageZipFile(string packageFileName) => new FileInfo(IOHelper.MapPath(_packagesFolderPath).EnsureEndsWith('\\') + packageFileName); - private static IEnumerable EmptyEnumerableIfNull(object obj) - { - return obj == null ? Enumerable.Empty() : null; - } - private XDocument GetConfigXmlDoc(FileInfo packageFile) { - var configXmlContent = _packageExtraction.ReadTextFileFromArchive(packageFile, Constants.Packaging.PackageXmlFileName, out _); + var configXmlContent = _packageExtraction.ReadTextFileFromArchive(packageFile, "package.xml", out _); var document = XDocument.Parse(configXmlContent); if (document.Root == null || - document.Root.Name.LocalName.Equals(Constants.Packaging.UmbPackageNodeName) == false) + document.Root.Name.LocalName.Equals("umbPackage") == false) throw new FormatException("xml does not have a root node called \"umbPackage\""); return document; } - public XElement GetConfigXmlElement(FileInfo packageFile) - { - var document = GetConfigXmlDoc(packageFile); - return document.Root; - } - private void ValidatePackageFile(FileInfo packageFile, CompiledPackage package) { if (!(package.Files?.Count > 0)) return; @@ -205,8 +165,8 @@ namespace Umbraco.Core.Packaging string.Join(", ", missingFiles.Select( mf => { - var sd = sourceDestination.Single(fi => fi.packageUniqueFile == mf); - return $"source: \"{sd.packageUniqueFile}\" destination: \"{sd.appRelativePath}\""; + var (packageUniqueFile, appRelativePath) = sourceDestination.Single(fi => fi.packageUniqueFile == mf); + return $"source: \"{packageUniqueFile}\" destination: \"{appRelativePath}\""; }))); } @@ -219,143 +179,7 @@ namespace Umbraco.Core.Packaging } } - private static IEnumerable GetPackageActions(XElement actionsElement, string packageName) - { - if (actionsElement == null) { return new PackageAction[0]; } - - if (string.Equals(Constants.Packaging.ActionsNodeName, actionsElement.Name.LocalName) == false) - { - throw new ArgumentException("Must be \"" + Constants.Packaging.ActionsNodeName + "\" as root", - "actionsElement"); - } - - return actionsElement.Elements(Constants.Packaging.ActionNodeName) - .Select(elemet => - { - XAttribute aliasAttr = elemet.Attribute(Constants.Packaging.AliasNodeNameCapital); - if (aliasAttr == null) - throw new ArgumentException( - "missing \"" + Constants.Packaging.AliasNodeNameCapital + "\" atribute in alias element", - "actionsElement"); - - var packageAction = new PackageAction - { - XmlData = elemet, - Alias = aliasAttr.Value, - PackageName = packageName, - }; - - - var attr = elemet.Attribute(Constants.Packaging.RunatNodeAttribute); - - if (attr != null && Enum.TryParse(attr.Value, true, out ActionRunAt runAt)) { packageAction.RunAt = runAt; } - - attr = elemet.Attribute(Constants.Packaging.UndoNodeAttribute); - - if (attr != null && bool.TryParse(attr.Value, out var undo)) { packageAction.Undo = undo; } - - - return packageAction; - }).ToArray(); - } - - private IEnumerable InstallDocuments(XElement documentsElement, int userId = 0) - { - if ((string.Equals(Constants.Packaging.DocumentSetNodeName, documentsElement.Name.LocalName) == false) - && (string.Equals(Constants.Packaging.DocumentsNodeName, documentsElement.Name.LocalName) == false)) - { - throw new ArgumentException("Must be \"" + Constants.Packaging.DocumentsNodeName + "\" as root", - "documentsElement"); - } - - if (string.Equals(Constants.Packaging.DocumentSetNodeName, documentsElement.Name.LocalName)) - return _packagingService.ImportContent(documentsElement, -1, userId); - - return - documentsElement.Elements(Constants.Packaging.DocumentSetNodeName) - .SelectMany(documentSetElement => _packagingService.ImportContent(documentSetElement, -1, userId)) - .ToArray(); - } - - private IEnumerable InstallStylesheets(XElement styleSheetsElement) - { - if (string.Equals(Constants.Packaging.StylesheetsNodeName, styleSheetsElement.Name.LocalName) == false) - { - throw new ArgumentException("Must be \"" + Constants.Packaging.StylesheetsNodeName + "\" as root", - "styleSheetsElement"); - } - - // TODO: Call _packagingService when import stylesheets import has been implimentet - if (styleSheetsElement.HasElements == false) { return new List(); } - - throw new NotImplementedException("The packaging service do not yes have a method for importing stylesheets"); - } - - private IEnumerable InstallDocumentTypes(XElement documentTypes, int userId = 0) - { - if (string.Equals(Constants.Packaging.DocumentTypesNodeName, documentTypes.Name.LocalName) == false) - { - if (string.Equals(Constants.Packaging.DocumentTypeNodeName, documentTypes.Name.LocalName) == false) - throw new ArgumentException( - "Must be \"" + Constants.Packaging.DocumentTypesNodeName + "\" as root", "documentTypes"); - - documentTypes = new XElement(Constants.Packaging.DocumentTypesNodeName, documentTypes); - } - - return _packagingService.ImportContentTypes(documentTypes, userId); - } - - private IEnumerable InstallTemplates(XElement templateElement, int userId = 0) - { - if (string.Equals(Constants.Packaging.TemplatesNodeName, templateElement.Name.LocalName) == false) - { - throw new ArgumentException("Must be \"" + Constants.Packaging.TemplatesNodeName + "\" as root", - "templateElement"); - } - return _packagingService.ImportTemplates(templateElement, userId); - } - - private IEnumerable InstallMacros(XElement macroElements, int userId = 0) - { - if (string.Equals(Constants.Packaging.MacrosNodeName, macroElements.Name.LocalName) == false) - { - throw new ArgumentException("Must be \"" + Constants.Packaging.MacrosNodeName + "\" as root", - "macroElements"); - } - return _packagingService.ImportMacros(macroElements, userId); - } - - private IEnumerable InstallDictionaryItems(XElement dictionaryItemsElement) - { - if (string.Equals(Constants.Packaging.DictionaryItemsNodeName, dictionaryItemsElement.Name.LocalName) == - false) - { - throw new ArgumentException("Must be \"" + Constants.Packaging.DictionaryItemsNodeName + "\" as root", - "dictionaryItemsElement"); - } - return _packagingService.ImportDictionaryItems(dictionaryItemsElement); - } - - private IEnumerable InstallLanguages(XElement languageElement, int userId = 0) - { - if (string.Equals(Constants.Packaging.LanguagesNodeName, languageElement.Name.LocalName) == false) - { - throw new ArgumentException("Must be \"" + Constants.Packaging.LanguagesNodeName + "\" as root", "languageElement"); - } - return _packagingService.ImportLanguages(languageElement, userId); - } - - private IEnumerable InstallDataTypes(XElement dataTypeElements, int userId = 0) - { - if (string.Equals(Constants.Packaging.DataTypesNodeName, dataTypeElements.Name.LocalName) == false) - { - if (string.Equals(Constants.Packaging.DataTypeNodeName, dataTypeElements.Name.LocalName) == false) - { - throw new ArgumentException("Must be \"" + Constants.Packaging.DataTypeNodeName + "\" as root", "dataTypeElements"); - } - } - return _packagingService.ImportDataTypeDefinitions(dataTypeElements, userId); - } + } } diff --git a/src/Umbraco.Core/Services/IPackagingService.cs b/src/Umbraco.Core/Services/IPackagingService.cs index fcb0c66401..8aa936c8ff 100644 --- a/src/Umbraco.Core/Services/IPackagingService.cs +++ b/src/Umbraco.Core/Services/IPackagingService.cs @@ -72,81 +72,6 @@ namespace Umbraco.Core.Services #endregion - #region Importing - /// - /// Imports and saves package xml as - /// - /// Xml to import - /// Optional parent Id for the content being imported - /// Optional Id of the user performing the import - /// Optional parameter indicating whether or not to raise events - /// An enumrable list of generated content - IEnumerable ImportContent(XElement element, int parentId = -1, int userId = 0, bool raiseEvents = true); - - /// - /// Imports and saves package xml as - /// - /// Xml to import - /// Optional id of the User performing the operation. Default is zero (admin) - /// Optional parameter indicating whether or not to raise events - /// An enumrable list of generated ContentTypes - IEnumerable ImportContentTypes(XElement element, int userId = 0, bool raiseEvents = true); - - /// - /// Imports and saves package xml as - /// - /// Xml to import - /// Boolean indicating whether or not to import the - /// Optional id of the User performing the operation. Default is zero (admin) - /// Optional parameter indicating whether or not to raise events - /// An enumrable list of generated ContentTypes - IEnumerable ImportContentTypes(XElement element, bool importStructure, int userId = 0, bool raiseEvents = true); - - /// - /// Imports and saves package xml as - /// - /// Xml to import - /// Optional id of the User performing the operation. Default is zero (admin). - /// Optional parameter indicating whether or not to raise events - /// An enumrable list of generated DataTypeDefinitions - IEnumerable ImportDataTypeDefinitions(XElement element, int userId = 0, bool raiseEvents = true); - - /// - /// Imports and saves the 'DictionaryItems' part of the package xml as a list of - /// - /// Xml to import - /// Optional parameter indicating whether or not to raise events - /// An enumerable list of dictionary items - IEnumerable ImportDictionaryItems(XElement dictionaryItemElementList, bool raiseEvents = true); - - /// - /// Imports and saves the 'Languages' part of a package xml as a list of - /// - /// Xml to import - /// Optional id of the User performing the operation. Default is zero (admin) - /// Optional parameter indicating whether or not to raise events - /// An enumerable list of generated languages - IEnumerable ImportLanguages(XElement languageElementList, int userId = 0, bool raiseEvents = true); - - /// - /// Imports and saves the 'Macros' part of a package xml as a list of - /// - /// Xml to import - /// Optional id of the User performing the operation - /// Optional parameter indicating whether or not to raise events - /// - IEnumerable ImportMacros(XElement element, int userId = 0, bool raiseEvents = true); - - /// - /// Imports and saves package xml as - /// - /// Xml to import - /// Optional id of the User performing the operation. Default is zero (admin) - /// Optional parameter indicating whether or not to raise events - /// An enumrable list of generated Templates - IEnumerable ImportTemplates(XElement element, int userId = 0, bool raiseEvents = true); - #endregion - /// /// This will fetch an Umbraco package file from the package repository and return the file name of the downloaded package /// diff --git a/src/Umbraco.Core/Services/Implement/PackagingService.cs b/src/Umbraco.Core/Services/Implement/PackagingService.cs index 7c379dc2dc..ba5d30f8d7 100644 --- a/src/Umbraco.Core/Services/Implement/PackagingService.cs +++ b/src/Umbraco.Core/Services/Implement/PackagingService.cs @@ -31,1097 +31,25 @@ namespace Umbraco.Core.Services.Implement /// public class PackagingService : IPackagingService { - //fixme: inject when ready to use this - private readonly IPackageInstallation _packageInstallation; - private readonly ILogger _logger; - private readonly IContentService _contentService; - private readonly IContentTypeService _contentTypeService; - private readonly IMacroService _macroService; - private readonly IDataTypeService _dataTypeService; - private readonly IFileService _fileService; - private readonly ILocalizationService _localizationService; - private readonly IEntityService _entityService; - private Dictionary _importedContentTypes; + private readonly IPackageInstallation _packageInstallation; private readonly IAuditService _auditService; - private readonly PropertyEditorCollection _propertyEditors; private readonly ICreatedPackagesRepository _createdPackages; private readonly IInstalledPackagesRepository _installedPackages; private static HttpClient _httpClient; public PackagingService( - ILogger logger, - IContentService contentService, - IContentTypeService contentTypeService, - IMacroService macroService, - IDataTypeService dataTypeService, - IFileService fileService, - ILocalizationService localizationService, - IEntityService entityService, IAuditService auditService, - PropertyEditorCollection propertyEditors, ICreatedPackagesRepository createdPackages, - IInstalledPackagesRepository installedPackages) - { - _logger = logger; - _contentService = contentService; - _contentTypeService = contentTypeService; - _macroService = macroService; - _dataTypeService = dataTypeService; - _fileService = fileService; - _localizationService = localizationService; - _entityService = entityService; + IInstalledPackagesRepository installedPackages, + IPackageInstallation packageInstallation) + { _auditService = auditService; - _propertyEditors = propertyEditors; _createdPackages = createdPackages; _installedPackages = installedPackages; - _importedContentTypes = new Dictionary(); + _packageInstallation = packageInstallation; } - #region Content - - - /// - /// Imports and saves package xml as - /// - /// Xml to import - /// Optional parent Id for the content being imported - /// Optional Id of the user performing the import - /// Optional parameter indicating whether or not to raise events - /// An enumrable list of generated content - public IEnumerable ImportContent(XElement element, int parentId = -1, int userId = 0, bool raiseEvents = true) - { - if (raiseEvents) - { - if (ImportingContent.IsRaisedEventCancelled(new ImportEventArgs(element), this)) - return Enumerable.Empty(); - } - - var name = element.Name.LocalName; - if (name.Equals("DocumentSet")) - { - //This is a regular deep-structured import - var roots = from doc in element.Elements() - where (string)doc.Attribute("isDoc") == "" - select doc; - - var contents = ParseDocumentRootXml(roots, parentId).ToList(); - if (contents.Any()) - _contentService.Save(contents, userId); - - if (raiseEvents) - ImportedContent.RaiseEvent(new ImportEventArgs(contents, element, false), this); - return contents; - } - - var attribute = element.Attribute("isDoc"); - if (attribute != null) - { - //This is a single doc import - var elements = new List { element }; - var contents = ParseDocumentRootXml(elements, parentId).ToList(); - if (contents.Any()) - _contentService.Save(contents, userId); - - if (raiseEvents) - ImportedContent.RaiseEvent(new ImportEventArgs(contents, element, false), this); - return contents; - } - - throw new ArgumentException( - "The passed in XElement is not valid! It does not contain a root element called " + - "'DocumentSet' (for structured imports) nor is the first element a Document (for single document import)."); - } - - private IEnumerable ParseDocumentRootXml(IEnumerable roots, int parentId) - { - var contents = new List(); - foreach (var root in roots) - { - var contentTypeAlias = root.Name.LocalName; - - if (_importedContentTypes.ContainsKey(contentTypeAlias) == false) - { - var contentType = FindContentTypeByAlias(contentTypeAlias); - _importedContentTypes.Add(contentTypeAlias, contentType); - } - - var content = CreateContentFromXml(root, _importedContentTypes[contentTypeAlias], null, parentId); - contents.Add(content); - - var children = (from child in root.Elements() - where (string)child.Attribute("isDoc") == "" - select child) - .ToList(); - if (children.Any()) - contents.AddRange(CreateContentFromXml(children, content)); - } - return contents; - } - - private IEnumerable CreateContentFromXml(IEnumerable children, IContent parent) - { - var list = new List(); - foreach (var child in children) - { - string contentTypeAlias = child.Name.LocalName; - - if (_importedContentTypes.ContainsKey(contentTypeAlias) == false) - { - var contentType = FindContentTypeByAlias(contentTypeAlias); - _importedContentTypes.Add(contentTypeAlias, contentType); - } - - //Create and add the child to the list - var content = CreateContentFromXml(child, _importedContentTypes[contentTypeAlias], parent, default(int)); - list.Add(content); - - //Recursive call - XElement child1 = child; - var grandChildren = (from grand in child1.Elements() - where (string) grand.Attribute("isDoc") == "" - select grand).ToList(); - - if (grandChildren.Any()) - list.AddRange(CreateContentFromXml(grandChildren, content)); - } - - return list; - } - - private IContent CreateContentFromXml(XElement element, IContentType contentType, IContent parent, int parentId) - { - var id = element.Attribute("id").Value; - var level = element.Attribute("level").Value; - var sortOrder = element.Attribute("sortOrder").Value; - var nodeName = element.Attribute("nodeName").Value; - var path = element.Attribute("path").Value; - //TODO: Shouldn't we be using this value??? - var template = element.Attribute("template").Value; - var key = Guid.Empty; - - var properties = from property in element.Elements() - where property.Attribute("isDoc") == null - select property; - - IContent content = parent == null - ? new Content(nodeName, parentId, contentType) - { - Level = int.Parse(level), - SortOrder = int.Parse(sortOrder) - } - : new Content(nodeName, parent, contentType) - { - Level = int.Parse(level), - SortOrder = int.Parse(sortOrder) - }; - - if (element.Attribute("key") != null && Guid.TryParse(element.Attribute("key").Value, out key)) - { - // update the Guid (for UDI support) - content.Key = key; - } - - foreach (var property in properties) - { - string propertyTypeAlias = property.Name.LocalName; - if (content.HasProperty(propertyTypeAlias)) - { - var propertyValue = property.Value; - - var propertyType = contentType.PropertyTypes.FirstOrDefault(pt => pt.Alias == propertyTypeAlias); - - //set property value - content.SetValue(propertyTypeAlias, propertyValue); - } - } - - return content; - } - - #endregion - - #region ContentTypes - - - - /// - /// Imports and saves package xml as - /// - /// Xml to import - /// Optional id of the User performing the operation. Default is zero (admin). - /// Optional parameter indicating whether or not to raise events - /// An enumrable list of generated ContentTypes - public IEnumerable ImportContentTypes(XElement element, int userId = 0, bool raiseEvents = true) - { - return ImportContentTypes(element, true, userId); - } - - /// - /// Imports and saves package xml as - /// - /// Xml to import - /// Boolean indicating whether or not to import the - /// Optional id of the User performing the operation. Default is zero (admin). - /// Optional parameter indicating whether or not to raise events - /// An enumrable list of generated ContentTypes - public IEnumerable ImportContentTypes(XElement element, bool importStructure, int userId = 0, bool raiseEvents = true) - { - if (raiseEvents) - { - if (ImportingContentType.IsRaisedEventCancelled(new ImportEventArgs(element), this)) - return Enumerable.Empty(); - } - - var name = element.Name.LocalName; - if (name.Equals("DocumentTypes") == false && name.Equals("DocumentType") == false) - { - throw new ArgumentException("The passed in XElement is not valid! It does not contain a root element called 'DocumentTypes' for multiple imports or 'DocumentType' for a single import."); - } - - _importedContentTypes = new Dictionary(); - var unsortedDocumentTypes = name.Equals("DocumentTypes") - ? (from doc in element.Elements("DocumentType") select doc).ToList() - : new List { element }; - - //When you are importing a single doc type we have to assume that the depedencies are already there. - //Otherwise something like uSync won't work. - var graph = new TopoGraph>(x => x.Key, x => x.Dependencies); - var isSingleDocTypeImport = unsortedDocumentTypes.Count == 1; - - var importedFolders = CreateContentTypeFolderStructure(unsortedDocumentTypes); - - if (isSingleDocTypeImport == false) - { - //NOTE Here we sort the doctype XElements based on dependencies - //before creating the doc types - this should also allow for a better structure/inheritance support. - foreach (var documentType in unsortedDocumentTypes) - { - var elementCopy = documentType; - var infoElement = elementCopy.Element("Info"); - var dependencies = new HashSet(); - - //Add the Master as a dependency - if (string.IsNullOrEmpty((string)infoElement.Element("Master")) == false) - { - dependencies.Add(infoElement.Element("Master").Value); - } - - //Add compositions as dependencies - var compositionsElement = infoElement.Element("Compositions"); - if (compositionsElement != null && compositionsElement.HasElements) - { - var compositions = compositionsElement.Elements("Composition"); - if (compositions.Any()) - { - foreach (var composition in compositions) - { - dependencies.Add(composition.Value); - } - } - } - - graph.AddItem(TopoGraph.CreateNode(infoElement.Element("Alias").Value, elementCopy, dependencies.ToArray())); - } - } - - //Sorting the Document Types based on dependencies - if its not a single doc type import ref. #U4-5921 - var documentTypes = isSingleDocTypeImport - ? unsortedDocumentTypes.ToList() - : graph.GetSortedItems().Select(x => x.Item).ToList(); - - //Iterate the sorted document types and create them as IContentType objects - foreach (var documentType in documentTypes) - { - var alias = documentType.Element("Info").Element("Alias").Value; - if (_importedContentTypes.ContainsKey(alias) == false) - { - var contentType = _contentTypeService.Get(alias); - _importedContentTypes.Add(alias, contentType == null - ? CreateContentTypeFromXml(documentType) - : UpdateContentTypeFromXml(documentType, contentType)); - } - } - - foreach (var contentType in _importedContentTypes) - { - var ct = contentType.Value; - if (importedFolders.ContainsKey(ct.Alias)) - { - ct.ParentId = importedFolders[ct.Alias]; - } - } - - //Save the newly created/updated IContentType objects - var list = _importedContentTypes.Select(x => x.Value).ToList(); - _contentTypeService.Save(list, userId); - - //Now we can finish the import by updating the 'structure', - //which requires the doc types to be saved/available in the db - if (importStructure) - { - var updatedContentTypes = new List(); - //Update the structure here - we can't do it untill all DocTypes have been created - foreach (var documentType in documentTypes) - { - var alias = documentType.Element("Info").Element("Alias").Value; - var structureElement = documentType.Element("Structure"); - //Ensure that we only update ContentTypes which has actual structure-elements - if (structureElement == null || structureElement.Elements("DocumentType").Any() == false) continue; - - var updated = UpdateContentTypesStructure(_importedContentTypes[alias], structureElement); - updatedContentTypes.Add(updated); - } - //Update ContentTypes with a newly added structure/list of allowed children - if (updatedContentTypes.Any()) - _contentTypeService.Save(updatedContentTypes, userId); - } - - if (raiseEvents) - ImportedContentType.RaiseEvent(new ImportEventArgs(list, element, false), this); - - return list; - } - - private Dictionary CreateContentTypeFolderStructure(IEnumerable unsortedDocumentTypes) - { - var importedFolders = new Dictionary(); - foreach (var documentType in unsortedDocumentTypes) - { - var foldersAttribute = documentType.Attribute("Folders"); - var infoElement = documentType.Element("Info"); - if (foldersAttribute != null && infoElement != null - //don't import any folder if this is a child doc type - the parent doc type will need to - //exist which contains it's folders - && ((string)infoElement.Element("Master")).IsNullOrWhiteSpace()) - { - var alias = documentType.Element("Info").Element("Alias").Value; - var folders = foldersAttribute.Value.Split('/'); - var rootFolder = HttpUtility.UrlDecode(folders[0]); - //level 1 = root level folders, there can only be one with the same name - var current = _contentTypeService.GetContainers(rootFolder, 1).FirstOrDefault(); - - if (current == null) - { - var tryCreateFolder = _contentTypeService.CreateContainer(-1, rootFolder); - if (tryCreateFolder == false) - { - _logger.Error(tryCreateFolder.Exception, "Could not create folder: {FolderName}", rootFolder); - throw tryCreateFolder.Exception; - } - var rootFolderId = tryCreateFolder.Result.Entity.Id; - current = _contentTypeService.GetContainer(rootFolderId); - } - - importedFolders.Add(alias, current.Id); - - for (var i = 1; i < folders.Length; i++) - { - var folderName = HttpUtility.UrlDecode(folders[i]); - current = CreateContentTypeChildFolder(folderName, current); - importedFolders[alias] = current.Id; - } - } - } - - return importedFolders; - } - - private EntityContainer CreateContentTypeChildFolder(string folderName, IUmbracoEntity current) - { - var children = _entityService.GetChildren(current.Id).ToArray(); - var found = children.Any(x => x.Name.InvariantEquals(folderName)); - if (found) - { - var containerId = children.Single(x => x.Name.InvariantEquals(folderName)).Id; - return _contentTypeService.GetContainer(containerId); - } - - var tryCreateFolder = _contentTypeService.CreateContainer(current.Id, folderName); - if (tryCreateFolder == false) - { - _logger.Error(tryCreateFolder.Exception, "Could not create folder: {FolderName}", folderName); - throw tryCreateFolder.Exception; - } - return _contentTypeService.GetContainer(tryCreateFolder.Result.Entity.Id); - } - - private IContentType CreateContentTypeFromXml(XElement documentType) - { - var infoElement = documentType.Element("Info"); - - //Name of the master corresponds to the parent - var masterElement = infoElement.Element("Master"); - IContentType parent = null; - if (masterElement != null) - { - var masterAlias = masterElement.Value; - parent = _importedContentTypes.ContainsKey(masterAlias) - ? _importedContentTypes[masterAlias] - : _contentTypeService.Get(masterAlias); - } - - var alias = infoElement.Element("Alias").Value; - var contentType = parent == null - ? new ContentType(-1) { Alias = alias } - : new ContentType(parent, alias); - - if (parent != null) - contentType.AddContentType(parent); - - return UpdateContentTypeFromXml(documentType, contentType); - } - - private IContentType UpdateContentTypeFromXml(XElement documentType, IContentType contentType) - { - var infoElement = documentType.Element("Info"); - var defaultTemplateElement = infoElement.Element("DefaultTemplate"); - - contentType.Name = infoElement.Element("Name").Value; - contentType.Icon = infoElement.Element("Icon").Value; - contentType.Thumbnail = infoElement.Element("Thumbnail").Value; - contentType.Description = infoElement.Element("Description").Value; - - //NOTE AllowAtRoot is a new property in the package xml so we need to verify it exists before using it. - var allowAtRoot = infoElement.Element("AllowAtRoot"); - if (allowAtRoot != null) - contentType.AllowedAsRoot = allowAtRoot.Value.InvariantEquals("true"); - - //NOTE IsListView is a new property in the package xml so we need to verify it exists before using it. - var isListView = infoElement.Element("IsListView"); - if (isListView != null) - contentType.IsContainer = isListView.Value.InvariantEquals("true"); - - //Name of the master corresponds to the parent and we need to ensure that the Parent Id is set - var masterElement = infoElement.Element("Master"); - if (masterElement != null) - { - var masterAlias = masterElement.Value; - IContentType parent = _importedContentTypes.ContainsKey(masterAlias) - ? _importedContentTypes[masterAlias] - : _contentTypeService.Get(masterAlias); - - contentType.SetParent(parent); - } - - //Update Compositions on the ContentType to ensure that they are as is defined in the package xml - var compositionsElement = infoElement.Element("Compositions"); - if (compositionsElement != null && compositionsElement.HasElements) - { - var compositions = compositionsElement.Elements("Composition"); - if (compositions.Any()) - { - foreach (var composition in compositions) - { - var compositionAlias = composition.Value; - var compositionContentType = _importedContentTypes.ContainsKey(compositionAlias) - ? _importedContentTypes[compositionAlias] - : _contentTypeService.Get(compositionAlias); - var added = contentType.AddContentType(compositionContentType); - } - } - } - - UpdateContentTypesAllowedTemplates(contentType, infoElement.Element("AllowedTemplates"), defaultTemplateElement); - UpdateContentTypesTabs(contentType, documentType.Element("Tabs")); - UpdateContentTypesProperties(contentType, documentType.Element("GenericProperties")); - - return contentType; - } - - private void UpdateContentTypesAllowedTemplates(IContentType contentType, - XElement allowedTemplatesElement, XElement defaultTemplateElement) - { - if (allowedTemplatesElement != null && allowedTemplatesElement.Elements("Template").Any()) - { - var allowedTemplates = contentType.AllowedTemplates.ToList(); - foreach (var templateElement in allowedTemplatesElement.Elements("Template")) - { - var alias = templateElement.Value; - var template = _fileService.GetTemplate(alias.ToSafeAlias()); - if (template != null) - { - if (allowedTemplates.Any(x => x.Id == template.Id)) continue; - allowedTemplates.Add(template); - } - else - { - _logger.Warn("Packager: Error handling allowed templates. Template with alias '{TemplateAlias}' could not be found.", alias); - } - } - - contentType.AllowedTemplates = allowedTemplates; - } - - if (string.IsNullOrEmpty((string)defaultTemplateElement) == false) - { - var defaultTemplate = _fileService.GetTemplate(defaultTemplateElement.Value.ToSafeAlias()); - if (defaultTemplate != null) - { - contentType.SetDefaultTemplate(defaultTemplate); - } - else - { - _logger.Warn("Packager: Error handling default template. Default template with alias '{DefaultTemplateAlias}' could not be found.", defaultTemplateElement.Value); - } - } - } - - private void UpdateContentTypesTabs(IContentType contentType, XElement tabElement) - { - if (tabElement == null) - return; - - var tabs = tabElement.Elements("Tab"); - foreach (var tab in tabs) - { - var id = tab.Element("Id").Value;//Do we need to use this for tracking? - var caption = tab.Element("Caption").Value; - - if (contentType.PropertyGroups.Contains(caption) == false) - { - contentType.AddPropertyGroup(caption); - - } - - int sortOrder; - if (tab.Element("SortOrder") != null && int.TryParse(tab.Element("SortOrder").Value, out sortOrder)) - { - // Override the sort order with the imported value - contentType.PropertyGroups[caption].SortOrder = sortOrder; - } - } - } - - private void UpdateContentTypesProperties(IContentType contentType, XElement genericPropertiesElement) - { - var properties = genericPropertiesElement.Elements("GenericProperty"); - foreach (var property in properties) - { - var dataTypeDefinitionId = new Guid(property.Element("Definition").Value);//Unique Id for a DataTypeDefinition - - var dataTypeDefinition = _dataTypeService.GetDataType(dataTypeDefinitionId); - - //If no DataTypeDefinition with the guid from the xml wasn't found OR the ControlId on the DataTypeDefinition didn't match the DataType Id - //We look up a DataTypeDefinition that matches - - - //get the alias as a string for use below - var propertyEditorAlias = property.Element("Type").Value.Trim(); - - //If no DataTypeDefinition with the guid from the xml wasn't found OR the ControlId on the DataTypeDefinition didn't match the DataType Id - //We look up a DataTypeDefinition that matches - - if (dataTypeDefinition == null) - { - var dataTypeDefinitions = _dataTypeService.GetByEditorAlias(propertyEditorAlias); - if (dataTypeDefinitions != null && dataTypeDefinitions.Any()) - { - dataTypeDefinition = dataTypeDefinitions.FirstOrDefault(); - } - } - else if (dataTypeDefinition.EditorAlias != propertyEditorAlias) - { - var dataTypeDefinitions = _dataTypeService.GetByEditorAlias(propertyEditorAlias); - if (dataTypeDefinitions != null && dataTypeDefinitions.Any()) - { - dataTypeDefinition = dataTypeDefinitions.FirstOrDefault(); - } - } - - // For backwards compatibility, if no datatype with that ID can be found, we're letting this fail silently. - // This means that the property will not be created. - if (dataTypeDefinition == null) - { - _logger.Warn("Packager: Error handling creation of PropertyType '{PropertyType}'. Could not find DataTypeDefintion with unique id '{DataTypeDefinitionId}' nor one referencing the DataType with a property editor alias (or legacy control id) '{PropertyEditorAlias}'. Did the package creator forget to package up custom datatypes? This property will be converted to a label/readonly editor if one exists.", - property.Element("Name").Value, dataTypeDefinitionId, property.Element("Type").Value.Trim()); - - //convert to a label! - dataTypeDefinition = _dataTypeService.GetByEditorAlias(Constants.PropertyEditors.Aliases.NoEdit).FirstOrDefault(); - //if for some odd reason this isn't there then ignore - if (dataTypeDefinition == null) continue; - } - - var sortOrder = 0; - var sortOrderElement = property.Element("SortOrder"); - if (sortOrderElement != null) - int.TryParse(sortOrderElement.Value, out sortOrder); - var propertyType = new PropertyType(dataTypeDefinition, property.Element("Alias").Value) - { - Name = property.Element("Name").Value, - Description = (string)property.Element("Description"), - Mandatory = property.Element("Mandatory") != null ? property.Element("Mandatory").Value.ToLowerInvariant().Equals("true") : false, - ValidationRegExp = (string)property.Element("Validation"), - SortOrder = sortOrder - }; - - var tab = (string)property.Element("Tab"); - if (string.IsNullOrEmpty(tab)) - { - contentType.AddPropertyType(propertyType); - } - else - { - contentType.AddPropertyType(propertyType, tab); - } - } - } - - private IContentType UpdateContentTypesStructure(IContentType contentType, XElement structureElement) - { - var allowedChildren = contentType.AllowedContentTypes.ToList(); - int sortOrder = allowedChildren.Any() ? allowedChildren.Last().SortOrder : 0; - foreach (var element in structureElement.Elements("DocumentType")) - { - var alias = element.Value; - - var allowedChild = _importedContentTypes.ContainsKey(alias) ? _importedContentTypes[alias] : _contentTypeService.Get(alias); - if (allowedChild == null) - { - _logger.Warn( - "Packager: Error handling DocumentType structure. DocumentType with alias '{DoctypeAlias}' could not be found and was not added to the structure for '{DoctypeStructureAlias}'.", - alias, contentType.Alias); - continue; - } - - if (allowedChildren.Any(x => x.Id.IsValueCreated && x.Id.Value == allowedChild.Id)) continue; - - allowedChildren.Add(new ContentTypeSort(new Lazy(() => allowedChild.Id), sortOrder, allowedChild.Alias)); - sortOrder++; - } - - contentType.AllowedContentTypes = allowedChildren; - return contentType; - } - - /// - /// Used during Content import to ensure that the ContentType of a content item exists - /// - /// - /// - private IContentType FindContentTypeByAlias(string contentTypeAlias) - { - var contentType = _contentTypeService.Get(contentTypeAlias); - - if (contentType == null) - throw new Exception($"ContentType matching the passed in Alias: '{contentTypeAlias}' was null"); - - return contentType; - } - - #endregion - - #region DataTypes - - - - - - /// - /// Imports and saves package xml as - /// - /// Xml to import - /// Optional id of the user - /// Optional parameter indicating whether or not to raise events - /// An enumrable list of generated DataTypeDefinitions - public IEnumerable ImportDataTypeDefinitions(XElement element, int userId = 0, bool raiseEvents = true) - { - if (raiseEvents) - { - if (ImportingDataType.IsRaisedEventCancelled(new ImportEventArgs(element), this)) - return Enumerable.Empty(); - } - - var name = element.Name.LocalName; - if (name.Equals("DataTypes") == false && name.Equals("DataType") == false) - { - throw new ArgumentException("The passed in XElement is not valid! It does not contain a root element called 'DataTypes' for multiple imports or 'DataType' for a single import."); - } - - var dataTypes = new List(); - var dataTypeElements = name.Equals("DataTypes") - ? (from doc in element.Elements("DataType") select doc).ToList() - : new List { element }; - - var importedFolders = CreateDataTypeFolderStructure(dataTypeElements); - - foreach (var dataTypeElement in dataTypeElements) - { - var dataTypeDefinitionName = dataTypeElement.Attribute("Name").Value; - - var dataTypeDefinitionId = new Guid(dataTypeElement.Attribute("Definition").Value); - var databaseTypeAttribute = dataTypeElement.Attribute("DatabaseType"); - - var parentId = -1; - if (importedFolders.ContainsKey(dataTypeDefinitionName)) - parentId = importedFolders[dataTypeDefinitionName]; - - var definition = _dataTypeService.GetDataType(dataTypeDefinitionId); - //If the datatypedefinition doesn't already exist we create a new new according to the one in the package xml - if (definition == null) - { - var databaseType = databaseTypeAttribute != null - ? databaseTypeAttribute.Value.EnumParse(true) - : ValueStorageType.Ntext; - - // the Id field is actually the string property editor Alias - // however, the actual editor with this alias could be installed with the package, and - // therefore not yet part of the _propertyEditors collection, so we cannot try and get - // the actual editor - going with a void editor - - var editorAlias = dataTypeElement.Attribute("Id")?.Value?.Trim(); - if (!_propertyEditors.TryGet(editorAlias, out var editor)) - editor = new VoidEditor(_logger) { Alias = editorAlias }; - - var dataType = new DataType(editor) - { - Key = dataTypeDefinitionId, - Name = dataTypeDefinitionName, - DatabaseType = databaseType, - ParentId = parentId - }; - - var configurationAttributeValue = dataTypeElement.Attribute("Configuration")?.Value; - if (!string.IsNullOrWhiteSpace(configurationAttributeValue)) - dataType.Configuration = editor.GetConfigurationEditor().FromDatabase(configurationAttributeValue); - - dataTypes.Add(dataType); - } - else - { - definition.ParentId = parentId; - _dataTypeService.Save(definition, userId); - } - } - - if (dataTypes.Count > 0) - { - _dataTypeService.Save(dataTypes, userId, true); - } - - if (raiseEvents) - ImportedDataType.RaiseEvent(new ImportEventArgs(dataTypes, element, false), this); - - return dataTypes; - } - - private Dictionary CreateDataTypeFolderStructure(IEnumerable datatypeElements) - { - var importedFolders = new Dictionary(); - foreach (var datatypeElement in datatypeElements) - { - var foldersAttribute = datatypeElement.Attribute("Folders"); - if (foldersAttribute != null) - { - var name = datatypeElement.Attribute("Name").Value; - var folders = foldersAttribute.Value.Split('/'); - var rootFolder = HttpUtility.UrlDecode(folders[0]); - //there will only be a single result by name for level 1 (root) containers - var current = _dataTypeService.GetContainers(rootFolder, 1).FirstOrDefault(); - - if (current == null) - { - var tryCreateFolder = _dataTypeService.CreateContainer(-1, rootFolder); - if (tryCreateFolder == false) - { - _logger.Error(tryCreateFolder.Exception, "Could not create folder: {FolderName}", rootFolder); - throw tryCreateFolder.Exception; - } - current = _dataTypeService.GetContainer(tryCreateFolder.Result.Entity.Id); - } - - importedFolders.Add(name, current.Id); - - for (var i = 1; i < folders.Length; i++) - { - var folderName = HttpUtility.UrlDecode(folders[i]); - current = CreateDataTypeChildFolder(folderName, current); - importedFolders[name] = current.Id; - } - } - } - - return importedFolders; - } - - private EntityContainer CreateDataTypeChildFolder(string folderName, IUmbracoEntity current) - { - var children = _entityService.GetChildren(current.Id).ToArray(); - var found = children.Any(x => x.Name.InvariantEquals(folderName)); - if (found) - { - var containerId = children.Single(x => x.Name.InvariantEquals(folderName)).Id; - return _dataTypeService.GetContainer(containerId); - } - - var tryCreateFolder = _dataTypeService.CreateContainer(current.Id, folderName); - if (tryCreateFolder == false) - { - _logger.Error(tryCreateFolder.Exception, "Could not create folder: {FolderName}", folderName); - throw tryCreateFolder.Exception; - } - return _dataTypeService.GetContainer(tryCreateFolder.Result.Entity.Id); - } - - #endregion - - #region Dictionary Items - - - - - - /// - /// Imports and saves the 'DictionaryItems' part of the package xml as a list of - /// - /// Xml to import - /// Optional parameter indicating whether or not to raise events - /// An enumerable list of dictionary items - public IEnumerable ImportDictionaryItems(XElement dictionaryItemElementList, bool raiseEvents = true) - { - if (raiseEvents) - { - if (ImportingDictionaryItem.IsRaisedEventCancelled(new ImportEventArgs(dictionaryItemElementList), this)) - return Enumerable.Empty(); - } - - var languages = _localizationService.GetAllLanguages().ToList(); - return ImportDictionaryItems(dictionaryItemElementList, languages, raiseEvents); - } - - private IEnumerable ImportDictionaryItems(XElement dictionaryItemElementList, List languages, bool raiseEvents, Guid? parentId = null) - { - var items = new List(); - foreach (var dictionaryItemElement in dictionaryItemElementList.Elements("DictionaryItem")) - items.AddRange(ImportDictionaryItem(dictionaryItemElement, languages, raiseEvents, parentId)); - - - if (raiseEvents) - ImportedDictionaryItem.RaiseEvent(new ImportEventArgs(items, dictionaryItemElementList, false), this); - - return items; - } - - private IEnumerable ImportDictionaryItem(XElement dictionaryItemElement, List languages, bool raiseEvents, Guid? parentId) - { - var items = new List(); - - IDictionaryItem dictionaryItem; - var key = dictionaryItemElement.Attribute("Key").Value; - if (_localizationService.DictionaryItemExists(key)) - dictionaryItem = GetAndUpdateDictionaryItem(key, dictionaryItemElement, languages); - else - dictionaryItem = CreateNewDictionaryItem(key, dictionaryItemElement, languages, parentId); - _localizationService.Save(dictionaryItem); - items.Add(dictionaryItem); - - items.AddRange(ImportDictionaryItems(dictionaryItemElement, languages, raiseEvents, dictionaryItem.Key)); - return items; - } - - private IDictionaryItem GetAndUpdateDictionaryItem(string key, XElement dictionaryItemElement, List languages) - { - var dictionaryItem = _localizationService.GetDictionaryItemByKey(key); - var translations = dictionaryItem.Translations.ToList(); - foreach (var valueElement in dictionaryItemElement.Elements("Value").Where(v => DictionaryValueIsNew(translations, v))) - AddDictionaryTranslation(translations, valueElement, languages); - dictionaryItem.Translations = translations; - return dictionaryItem; - } - - private static DictionaryItem CreateNewDictionaryItem(string key, XElement dictionaryItemElement, List languages, Guid? parentId) - { - var dictionaryItem = parentId.HasValue ? new DictionaryItem(parentId.Value, key) : new DictionaryItem(key); - var translations = new List(); - - foreach (var valueElement in dictionaryItemElement.Elements("Value")) - AddDictionaryTranslation(translations, valueElement, languages); - - dictionaryItem.Translations = translations; - return dictionaryItem; - } - - private static bool DictionaryValueIsNew(IEnumerable translations, XElement valueElement) - { - return translations.All(t => - String.Compare(t.Language.IsoCode, valueElement.Attribute("LanguageCultureAlias").Value, - StringComparison.InvariantCultureIgnoreCase) != 0 - ); - } - - private static void AddDictionaryTranslation(ICollection translations, XElement valueElement, IEnumerable languages) - { - var languageId = valueElement.Attribute("LanguageCultureAlias").Value; - var language = languages.SingleOrDefault(l => l.IsoCode == languageId); - if (language == null) - return; - var translation = new DictionaryTranslation(language, valueElement.Value); - translations.Add(translation); - } - - #endregion - - #region Languages - - - - - - /// - /// Imports and saves the 'Languages' part of a package xml as a list of - /// - /// Xml to import - /// Optional id of the User performing the operation - /// Optional parameter indicating whether or not to raise events - /// An enumerable list of generated languages - public IEnumerable ImportLanguages(XElement languageElementList, int userId = 0, bool raiseEvents = true) - { - if (raiseEvents) - { - if (ImportingLanguage.IsRaisedEventCancelled(new ImportEventArgs(languageElementList), this)) - return Enumerable.Empty(); - } - - var list = new List(); - foreach (var languageElement in languageElementList.Elements("Language")) - { - var isoCode = languageElement.Attribute("CultureAlias").Value; - var existingLanguage = _localizationService.GetLanguageByIsoCode(isoCode); - if (existingLanguage == null) - { - var langauge = new Language(isoCode) - { - CultureName = languageElement.Attribute("FriendlyName").Value - }; - _localizationService.Save(langauge); - list.Add(langauge); - } - } - - if (raiseEvents) - ImportedLanguage.RaiseEvent(new ImportEventArgs(list, languageElementList, false), this); - - return list; - } - - #endregion - - #region Macros - - /// - /// Imports and saves the 'Macros' part of a package xml as a list of - /// - /// Xml to import - /// Optional id of the User performing the operation - /// Optional parameter indicating whether or not to raise events - /// - public IEnumerable ImportMacros(XElement element, int userId = 0, bool raiseEvents = true) - { - if (raiseEvents) - { - if (ImportingMacro.IsRaisedEventCancelled(new ImportEventArgs(element), this)) - return Enumerable.Empty(); - } - - var name = element.Name.LocalName; - if (name.Equals("Macros") == false && name.Equals("macro") == false) - { - throw new ArgumentException("The passed in XElement is not valid! It does not contain a root element called 'Macros' for multiple imports or 'macro' for a single import."); - } - - var macroElements = name.Equals("Macros") - ? (from doc in element.Elements("macro") select doc).ToList() - : new List { element }; - - var macros = macroElements.Select(ParseMacroElement).ToList(); - - foreach (var macro in macros) - { - var existing = _macroService.GetByAlias(macro.Alias); - if (existing != null) - macro.Id = existing.Id; - - _macroService.Save(macro, userId); - } - - if (raiseEvents) - ImportedMacro.RaiseEvent(new ImportEventArgs(macros, element, false), this); - - return macros; - } - - private IMacro ParseMacroElement(XElement macroElement) - { - var macroName = macroElement.Element("name").Value; - var macroAlias = macroElement.Element("alias").Value; - var macroType = Enum.Parse(macroElement.Element("macroType").Value); - var macroSource = macroElement.Element("macroSource").Value; - - //Following xml elements are treated as nullable properties - var useInEditorElement = macroElement.Element("useInEditor"); - var useInEditor = false; - if (useInEditorElement != null && string.IsNullOrEmpty((string)useInEditorElement) == false) - { - useInEditor = bool.Parse(useInEditorElement.Value); - } - var cacheDurationElement = macroElement.Element("refreshRate"); - var cacheDuration = 0; - if (cacheDurationElement != null && string.IsNullOrEmpty((string)cacheDurationElement) == false) - { - cacheDuration = int.Parse(cacheDurationElement.Value); - } - var cacheByMemberElement = macroElement.Element("cacheByMember"); - var cacheByMember = false; - if (cacheByMemberElement != null && string.IsNullOrEmpty((string)cacheByMemberElement) == false) - { - cacheByMember = bool.Parse(cacheByMemberElement.Value); - } - var cacheByPageElement = macroElement.Element("cacheByPage"); - var cacheByPage = false; - if (cacheByPageElement != null && string.IsNullOrEmpty((string)cacheByPageElement) == false) - { - cacheByPage = bool.Parse(cacheByPageElement.Value); - } - var dontRenderElement = macroElement.Element("dontRender"); - var dontRender = true; - if (dontRenderElement != null && string.IsNullOrEmpty((string)dontRenderElement) == false) - { - dontRender = bool.Parse(dontRenderElement.Value); - } - - var existingMacro = _macroService.GetByAlias(macroAlias) as Macro; - var macro = existingMacro ?? new Macro(macroAlias, macroName, macroSource, macroType, - cacheByPage, cacheByMember, dontRender, useInEditor, cacheDuration); - - var properties = macroElement.Element("properties"); - if (properties != null) - { - int sortOrder = 0; - foreach (var property in properties.Elements()) - { - var propertyName = property.Attribute("name").Value; - var propertyAlias = property.Attribute("alias").Value; - var editorAlias = property.Attribute("propertyType").Value; - var sortOrderAttribute = property.Attribute("sortOrder"); - if (sortOrderAttribute != null) - { - sortOrder = int.Parse(sortOrderAttribute.Value); - } - - if (macro.Properties.Values.Any(x => string.Equals(x.Alias, propertyAlias, StringComparison.OrdinalIgnoreCase))) continue; - macro.Properties.Add(new MacroProperty(propertyAlias, propertyName, sortOrder, editorAlias)); - sortOrder++; - } - } - return macro; - } - - - - - - #endregion - #region Package Files /// @@ -1167,139 +95,6 @@ namespace Umbraco.Core.Services.Implement #endregion - #region Templates - - /// - /// Imports and saves package xml as - /// - /// Xml to import - /// Optional user id - /// Optional parameter indicating whether or not to raise events - /// An enumrable list of generated Templates - public IEnumerable ImportTemplates(XElement element, int userId = 0, bool raiseEvents = true) - { - if (raiseEvents) - { - if (ImportingTemplate.IsRaisedEventCancelled(new ImportEventArgs(element), this)) - return Enumerable.Empty(); - } - - var name = element.Name.LocalName; - if (name.Equals("Templates") == false && name.Equals("Template") == false) - { - throw new ArgumentException("The passed in XElement is not valid! It does not contain a root element called 'Templates' for multiple imports or 'Template' for a single import."); - } - - var templates = new List(); - var templateElements = name.Equals("Templates") - ? (from doc in element.Elements("Template") select doc).ToList() - : new List { element }; - - var graph = new TopoGraph>(x => x.Key, x => x.Dependencies); - - foreach (XElement tempElement in templateElements) - { - var dependencies = new List(); - var elementCopy = tempElement; - //Ensure that the Master of the current template is part of the import, otherwise we ignore this dependency as part of the dependency sorting. - if (string.IsNullOrEmpty((string)elementCopy.Element("Master")) == false && - templateElements.Any(x => (string)x.Element("Alias") == (string)elementCopy.Element("Master"))) - { - dependencies.Add((string)elementCopy.Element("Master")); - } - else if (string.IsNullOrEmpty((string)elementCopy.Element("Master")) == false && - templateElements.Any(x => (string)x.Element("Alias") == (string)elementCopy.Element("Master")) == false) - { - _logger.Info( - "Template '{TemplateAlias}' has an invalid Master '{TemplateMaster}', so the reference has been ignored.", - (string) elementCopy.Element("Alias"), - (string) elementCopy.Element("Master")); - } - - graph.AddItem(TopoGraph.CreateNode((string) elementCopy.Element("Alias"), elementCopy, dependencies)); - } - - //Sort templates by dependencies to a potential master template - var sorted = graph.GetSortedItems(); - foreach (var item in sorted) - { - var templateElement = item.Item; - - var templateName = templateElement.Element("Name").Value; - var alias = templateElement.Element("Alias").Value; - var design = templateElement.Element("Design").Value; - var masterElement = templateElement.Element("Master"); - - var isMasterPage = IsMasterPageSyntax(design); - var path = isMasterPage ? MasterpagePath(alias) : ViewPath(alias); - - var existingTemplate = _fileService.GetTemplate(alias) as Template; - var template = existingTemplate ?? new Template(templateName, alias); - template.Content = design; - if (masterElement != null && string.IsNullOrEmpty((string)masterElement) == false) - { - template.MasterTemplateAlias = masterElement.Value; - var masterTemplate = templates.FirstOrDefault(x => x.Alias == masterElement.Value); - if (masterTemplate != null) - template.MasterTemplateId = new Lazy(() => masterTemplate.Id); - } - templates.Add(template); - } - - if (templates.Any()) - _fileService.SaveTemplate(templates, userId); - - if (raiseEvents) - ImportedTemplate.RaiseEvent(new ImportEventArgs(templates, element, false), this); - - return templates; - } - - - private bool IsMasterPageSyntax(string code) - { - return Regex.IsMatch(code, @"<%@\s*Master", RegexOptions.IgnoreCase) || - code.InvariantContains(" ImportStylesheets(XElement element, int userId = 0, bool raiseEvents = true) - { - - if (raiseEvents) - { - if (ImportingStylesheets.IsRaisedEventCancelled(new ImportEventArgs(element), this)) - return Enumerable.Empty(); - } - - IEnumerable styleSheets = Enumerable.Empty(); - - if (element.Elements().Any()) - throw new NotImplementedException("This needs to be implimentet"); - - - if (raiseEvents) - ImportingStylesheets.RaiseEvent(new ImportEventArgs(styleSheets, element, false), this); - - return styleSheets; - - } - - #endregion - #region Installation public CompiledPackage GetCompiledPackageInfo(string packageFileName) => _packageInstallation.ReadPackage(packageFileName); @@ -1317,8 +112,7 @@ namespace Umbraco.Core.Services.Implement SaveInstalledPackage(packageDefinition); - if (userId > -1) - _auditService.Add(AuditType.PackagerInstall, userId, -1, "Package", $"Package files installed for package '{compiledPackage.Name}'."); + _auditService.Add(AuditType.PackagerInstall, userId, -1, "Package", $"Package files installed for package '{compiledPackage.Name}'."); return files; } @@ -1337,6 +131,8 @@ namespace Umbraco.Core.Services.Implement var summary = _packageInstallation.InstallPackageData(packageDefinition, compiledPackage, userId); + SaveInstalledPackage(packageDefinition); + _auditService.Add(AuditType.PackagerInstall, userId, -1, "Package", $"Package data installed for package '{compiledPackage.Name}'."); ImportedPackage.RaiseEvent(new ImportPackageEventArgs(summary, compiledPackage, false), this); @@ -1383,15 +179,6 @@ namespace Umbraco.Core.Services.Implement #endregion - /// - /// This method can be used to trigger the 'ImportedPackage' event when a package is installed by something else but this service. - /// - /// - internal static void OnImportedPackage(ImportPackageEventArgs args) - { - ImportedPackage.RaiseEvent(args, null); - } - /// /// This method can be used to trigger the 'UninstalledPackage' event when a package is uninstalled by something else but this service. /// @@ -1402,80 +189,6 @@ namespace Umbraco.Core.Services.Implement } #region Event Handlers - /// - /// Occurs before Importing Content - /// - public static event TypedEventHandler> ImportingContent; - - /// - /// Occurs after Content is Imported and Saved - /// - public static event TypedEventHandler> ImportedContent; - - /// - /// Occurs before Importing ContentType - /// - public static event TypedEventHandler> ImportingContentType; - - /// - /// Occurs after ContentType is Imported and Saved - /// - public static event TypedEventHandler> ImportedContentType; - - /// - /// Occurs before Importing DataType - /// - public static event TypedEventHandler> ImportingDataType; - - /// - /// Occurs after DataType is Imported and Saved - /// - public static event TypedEventHandler> ImportedDataType; - - /// - /// Occurs before Importing DictionaryItem - /// - public static event TypedEventHandler> ImportingDictionaryItem; - - /// - /// Occurs after DictionaryItem is Imported and Saved - /// - public static event TypedEventHandler> ImportedDictionaryItem; - - /// - /// Occurs before Importing Macro - /// - public static event TypedEventHandler> ImportingMacro; - - /// - /// Occurs after Macro is Imported and Saved - /// - public static event TypedEventHandler> ImportedMacro; - - /// - /// Occurs before Importing Language - /// - public static event TypedEventHandler> ImportingLanguage; - - /// - /// Occurs after Language is Imported and Saved - /// - public static event TypedEventHandler> ImportedLanguage; - - /// - /// Occurs before Importing Template - /// - public static event TypedEventHandler> ImportingTemplate; - - /// - /// Occurs before Importing Stylesheets - /// - public static event TypedEventHandler> ImportingStylesheets; - - /// - /// Occurs after Template is Imported and Saved - /// - public static event TypedEventHandler> ImportedTemplate; /// /// Occurs before Importing umbraco package diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 2ee5d13f6d..b59a5190bd 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -320,7 +320,6 @@ - @@ -447,9 +446,11 @@ + + @@ -573,7 +574,6 @@ - diff --git a/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs b/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs index fe7a5fbe5c..964f0c47de 100644 --- a/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs +++ b/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs @@ -4,9 +4,11 @@ using System.Linq; using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Composing; using Umbraco.Core.IO; using Umbraco.Core.Models.Packaging; using Umbraco.Core.Packaging; +using Umbraco.Core.PropertyEditors; using Umbraco.Core.Services; using Umbraco.Core.Services.Implement; using Umbraco.Tests.TestHelpers; @@ -38,10 +40,16 @@ namespace Umbraco.Tests.Packaging private CompiledPackageXmlParser Parser => new CompiledPackageXmlParser(new ConflictingPackageData(ServiceContext.MacroService, ServiceContext.FileService)); + private PackageDataInstallation PackageDataInstallation => new PackageDataInstallation( + Logger, ServiceContext.FileService, ServiceContext.MacroService, ServiceContext.LocalizationService, + ServiceContext.DataTypeService, ServiceContext.EntityService, + ServiceContext.ContentTypeService, ServiceContext.ContentService, + Factory.GetInstance()); + private IPackageInstallation PackageInstallation => new PackageInstallation( - ServiceContext.PackagingService, + PackageDataInstallation, new PackageFileInstallation(Parser, ProfilingLogger), - Parser, + Parser, Mock.Of(), packagesFolderPath: "~/Packaging/packages",//this is where our test zip file is applicationRootFolder: new DirectoryInfo(IOHelper.GetRootDirectorySafe()), packageExtractionFolder: new DirectoryInfo(IOHelper.MapPath("~/" + _testBaseFolder))); //we don't want to extract package files to the real root, so extract to a test folder diff --git a/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs b/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs index 84eb75a4f7..f29a43c504 100644 --- a/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs +++ b/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs @@ -8,6 +8,7 @@ using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Core.Composing.Composers; using Umbraco.Core.Logging; +using Umbraco.Core.Packaging; using Umbraco.Core.Persistence.Dtos; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Services; @@ -65,6 +66,8 @@ namespace Umbraco.Tests.Services.Importing Composition.ComposeFileSystems(); } + private PackageDataInstallation PackagingService => Factory.GetInstance(); + [Test] public void PackagingService_Can_Import_uBlogsy_ContentTypes_And_Verify_Structure() { @@ -74,12 +77,11 @@ namespace Umbraco.Tests.Services.Importing var dataTypeElement = xml.Descendants("DataTypes").First(); var templateElement = xml.Descendants("Templates").First(); var docTypeElement = xml.Descendants("DocumentTypes").First(); - var packagingService = ServiceContext.PackagingService; // Act - var dataTypes = packagingService.ImportDataTypeDefinitions(dataTypeElement); - var templates = packagingService.ImportTemplates(templateElement); - var contentTypes = packagingService.ImportContentTypes(docTypeElement); + var dataTypes = PackagingService.ImportDataTypes(dataTypeElement.Elements("DataType").ToList(), 0); + var templates = PackagingService.ImportTemplates(templateElement.Elements("Template").ToList(), 0); + var contentTypes = PackagingService.ImportDocumentTypes(docTypeElement.Elements("DocumentType"), 0); var numberOfTemplates = (from doc in templateElement.Elements("Template") select doc).Count(); var numberOfDocTypes = (from doc in docTypeElement.Elements("DocumentType") select doc).Count(); @@ -122,12 +124,11 @@ namespace Umbraco.Tests.Services.Importing var dataTypeElement = xml.Descendants("DataTypes").First(); var templateElement = xml.Descendants("Templates").First(); var docTypeElement = xml.Descendants("DocumentTypes").First(); - var packagingService = ServiceContext.PackagingService; // Act - var dataTypes = packagingService.ImportDataTypeDefinitions(dataTypeElement); - var templates = packagingService.ImportTemplates(templateElement); - var contentTypes = packagingService.ImportContentTypes(docTypeElement); + var dataTypes = PackagingService.ImportDataTypes(dataTypeElement.Elements("DataType").ToList(), 0); + var templates = PackagingService.ImportTemplates(templateElement.Elements("Template").ToList(), 0); + var contentTypes = PackagingService.ImportDocumentTypes(docTypeElement.Elements("DocumentType"), 0); // Assert var mRBasePage = contentTypes.First(x => x.Alias == "MRBasePage"); @@ -148,12 +149,11 @@ namespace Umbraco.Tests.Services.Importing var dataTypeElement = xml.Descendants("DataTypes").First(); var templateElement = xml.Descendants("Templates").First(); var docTypeElement = xml.Descendants("DocumentTypes").First(); - var packagingService = ServiceContext.PackagingService; // Act - var dataTypes = packagingService.ImportDataTypeDefinitions(dataTypeElement); - var templates = packagingService.ImportTemplates(templateElement); - var contentTypes = packagingService.ImportContentTypes(docTypeElement); + var dataTypes = PackagingService.ImportDataTypes(dataTypeElement.Elements("DataType").ToList(), 0); + var templates = PackagingService.ImportTemplates(templateElement.Elements("Template").ToList(), 0); + var contentTypes = PackagingService.ImportDocumentTypes(docTypeElement.Elements("DocumentType"), 0); var numberOfDocTypes = (from doc in docTypeElement.Elements("DocumentType") select doc).Count(); @@ -186,11 +186,11 @@ namespace Umbraco.Tests.Services.Importing string strXml = ImportResources.StandardMvc_Package; var xml = XElement.Parse(strXml); var element = xml.Descendants("Templates").First(); - var packagingService = ServiceContext.PackagingService; + var init = ServiceContext.FileService.GetTemplates().Count(); // Act - var templates = packagingService.ImportTemplates(element); + var templates = PackagingService.ImportTemplates(element.Elements("Template").ToList(), 0); var numberOfTemplates = (from doc in element.Elements("Template") select doc).Count(); var allTemplates = ServiceContext.FileService.GetTemplates(); @@ -209,11 +209,11 @@ namespace Umbraco.Tests.Services.Importing // Arrange string strXml = ImportResources.StandardMvc_Package; var xml = XElement.Parse(strXml); - var element = xml.Descendants("Templates").First().Element("Template"); - var packagingService = ServiceContext.PackagingService; + var element = xml.Descendants("Templates").First(); + // Act - var templates = packagingService.ImportTemplates(element); + var templates = PackagingService.ImportTemplate(element.Elements("Template").First(), 0); // Assert Assert.That(templates, Is.Not.Null); @@ -230,12 +230,12 @@ namespace Umbraco.Tests.Services.Importing var dataTypeElement = xml.Descendants("DataTypes").First(); var templateElement = xml.Descendants("Templates").First(); var docTypeElement = xml.Descendants("DocumentTypes").First(); - var packagingService = ServiceContext.PackagingService; + // Act - var dataTypeDefinitions = packagingService.ImportDataTypeDefinitions(dataTypeElement); - var templates = packagingService.ImportTemplates(templateElement); - var contentTypes = packagingService.ImportContentTypes(docTypeElement); + var dataTypeDefinitions = PackagingService.ImportDataTypes(dataTypeElement.Elements("DataType").ToList(), 0); + var templates = PackagingService.ImportTemplates(templateElement.Elements("Template").ToList(), 0); + var contentTypes = PackagingService.ImportDocumentTypes(docTypeElement.Elements("DocumentType"), 0); var numberOfDocTypes = (from doc in docTypeElement.Elements("DocumentType") select doc).Count(); // Assert @@ -268,13 +268,13 @@ namespace Umbraco.Tests.Services.Importing var docTypeElement = xml.Descendants("DocumentTypes").First(); // Act - var dataTypeDefinitions = ServiceContext.PackagingService.ImportDataTypeDefinitions(dataTypeElement); - var templates = ServiceContext.PackagingService.ImportTemplates(templateElement); - var contentTypes = ServiceContext.PackagingService.ImportContentTypes(docTypeElement); + var dataTypeDefinitions = PackagingService.ImportDataTypes(dataTypeElement.Elements("DataType").ToList(), 0); + var templates = PackagingService.ImportTemplates(templateElement.Elements("Template").ToList(), 0); + var contentTypes = PackagingService.ImportDocumentTypes(docTypeElement.Elements("DocumentType"), 0); var numberOfDocTypes = (from doc in docTypeElement.Elements("DocumentType") select doc).Count(); //Assert - Re-Import contenttypes doesn't throw - Assert.DoesNotThrow(() => ServiceContext.PackagingService.ImportContentTypes(docTypeElement)); + Assert.DoesNotThrow(() => PackagingService.ImportDocumentTypes(docTypeElement.Elements("DocumentType"), 0)); Assert.That(contentTypes.Count(), Is.EqualTo(numberOfDocTypes)); Assert.That(dataTypeDefinitions, Is.Not.Null); Assert.That(dataTypeDefinitions.Any(), Is.True); @@ -292,13 +292,13 @@ namespace Umbraco.Tests.Services.Importing var docTypeElement = xml.Descendants("DocumentTypes").First(); // Act - var dataTypeDefinitions = ServiceContext.PackagingService.ImportDataTypeDefinitions(dataTypeElement); - var templates = ServiceContext.PackagingService.ImportTemplates(templateElement); - var contentTypes = ServiceContext.PackagingService.ImportContentTypes(docTypeElement); + var dataTypeDefinitions = PackagingService.ImportDataTypes(dataTypeElement.Elements("DataType").ToList(), 0); + var templates = PackagingService.ImportTemplates(templateElement.Elements("Template").ToList(), 0); + var contentTypes = PackagingService.ImportDocumentTypes(docTypeElement.Elements("DocumentType"), 0); var numberOfDocTypes = (from doc in docTypeElement.Elements("DocumentType") select doc).Count(); //Assert - Re-Import contenttypes doesn't throw - Assert.DoesNotThrow(() => ServiceContext.PackagingService.ImportContentTypes(docTypeElement)); + Assert.DoesNotThrow(() => PackagingService.ImportDocumentTypes(docTypeElement.Elements("DocumentType"), 0)); Assert.That(contentTypes.Count(), Is.EqualTo(numberOfDocTypes)); Assert.That(dataTypeDefinitions, Is.Not.Null); Assert.That(dataTypeDefinitions.Any(), Is.True); @@ -314,12 +314,13 @@ namespace Umbraco.Tests.Services.Importing var dataTypeElement = xml.Descendants("DataTypes").First(); var docTypesElement = xml.Descendants("DocumentTypes").First(); var element = xml.Descendants("DocumentSet").First(); - var packagingService = ServiceContext.PackagingService; + // Act - var dataTypeDefinitions = packagingService.ImportDataTypeDefinitions(dataTypeElement); - var contentTypes = packagingService.ImportContentTypes(docTypesElement); - var contents = packagingService.ImportContent(element); + var dataTypeDefinitions = PackagingService.ImportDataTypes(dataTypeElement.Elements("DataType").ToList(), 0); + var contentTypes = PackagingService.ImportDocumentTypes(docTypesElement.Elements("DocumentType"), 0); + var importedContentTypes = contentTypes.ToDictionary(x => x.Alias, x => x); + var contents = PackagingService.ImportContent(element, -1, importedContentTypes, 0); var numberOfDocs = (from doc in element.Descendants() where (string) doc.Attribute("isDoc") == "" select doc).Count(); @@ -347,12 +348,13 @@ namespace Umbraco.Tests.Services.Importing var dataTypeElement = xml.Descendants("DataTypes").First(); var docTypesElement = xml.Descendants("DocumentTypes").First(); var element = xml.Descendants("DocumentSet").First(); - var packagingService = ServiceContext.PackagingService; + // Act - var dataTypeDefinitions = packagingService.ImportDataTypeDefinitions(dataTypeElement); - var contentTypes = packagingService.ImportContentTypes(docTypesElement); - var contents = packagingService.ImportContent(element); + var dataTypeDefinitions = PackagingService.ImportDataTypes(dataTypeElement.Elements("DataType").ToList(), 0); + var contentTypes = PackagingService.ImportDocumentTypes(docTypesElement.Elements("DocumentType"), 0); + var importedContentTypes = contentTypes.ToDictionary(x => x.Alias, x => x); + var contents = PackagingService.ImportContent(element, -1, importedContentTypes, 0); var numberOfDocs = (from doc in element.Descendants() where (string)doc.Attribute("isDoc") == "" select doc).Count(); @@ -382,10 +384,10 @@ namespace Umbraco.Tests.Services.Importing string strXml = ImportResources.XsltSearch_Package; var xml = XElement.Parse(strXml); var templateElement = xml.Descendants("Templates").First(); - var packagingService = ServiceContext.PackagingService; + // Act - var templates = packagingService.ImportTemplates(templateElement); + var templates = PackagingService.ImportTemplates(templateElement.Elements("Template").ToList(), 0); var numberOfTemplates = (from doc in templateElement.Elements("Template") select doc).Count(); // Assert @@ -399,10 +401,10 @@ namespace Umbraco.Tests.Services.Importing // Arrange string strXml = ImportResources.SingleDocType; var docTypeElement = XElement.Parse(strXml); - var packagingService = ServiceContext.PackagingService; + // Act - var contentTypes = packagingService.ImportContentTypes(docTypeElement); + var contentTypes = PackagingService.ImportDocumentType(docTypeElement, 0); // Assert Assert.That(contentTypes.Any(), Is.True); @@ -416,11 +418,11 @@ namespace Umbraco.Tests.Services.Importing // Arrange string strXml = ImportResources.SingleDocType; var docTypeElement = XElement.Parse(strXml); - var packagingService = ServiceContext.PackagingService; + var serializer = Factory.GetInstance(); // Act - var contentTypes = packagingService.ImportContentTypes(docTypeElement); + var contentTypes = PackagingService.ImportDocumentType(docTypeElement, 0); var contentType = contentTypes.FirstOrDefault(); var element = serializer.Serialize(contentType); @@ -442,8 +444,8 @@ namespace Umbraco.Tests.Services.Importing var docTypeElement = XElement.Parse(strXml); // Act - var contentTypes = ServiceContext.PackagingService.ImportContentTypes(docTypeElement); - var contentTypesUpdated = ServiceContext.PackagingService.ImportContentTypes(docTypeElement); + var contentTypes = PackagingService.ImportDocumentType(docTypeElement, 0); + var contentTypesUpdated = PackagingService.ImportDocumentType(docTypeElement, 0); // Assert Assert.That(contentTypes.Any(), Is.True); @@ -465,7 +467,7 @@ namespace Umbraco.Tests.Services.Importing var templateElement = newPackageXml.Descendants("Templates").First(); var templateElementUpdated = updatedPackageXml.Descendants("Templates").First(); - var packagingService = ServiceContext.PackagingService; + var fileService = ServiceContext.FileService; // kill default test data @@ -473,8 +475,8 @@ namespace Umbraco.Tests.Services.Importing // Act var numberOfTemplates = (from doc in templateElement.Elements("Template") select doc).Count(); - var templates = packagingService.ImportTemplates(templateElement); - var templatesAfterUpdate = packagingService.ImportTemplates(templateElementUpdated); + var templates = PackagingService.ImportTemplates(templateElement.Elements("Template").ToList(), 0); + var templatesAfterUpdate = PackagingService.ImportTemplates(templateElementUpdated.Elements("Template").ToList(), 0); var allTemplates = fileService.GetTemplates(); // Assert @@ -500,7 +502,7 @@ namespace Umbraco.Tests.Services.Importing AddLanguages(); // Act - ServiceContext.PackagingService.ImportDictionaryItems(dictionaryItemsElement); + PackagingService.ImportDictionaryItems(dictionaryItemsElement.Elements("DictionaryItem"), 0); // Assert AssertDictionaryItem("Parent", expectedEnglishParentValue, "en-GB"); @@ -522,7 +524,7 @@ namespace Umbraco.Tests.Services.Importing AddLanguages(); // Act - var dictionaryItems = ServiceContext.PackagingService.ImportDictionaryItems(dictionaryItemsElement); + var dictionaryItems = PackagingService.ImportDictionaryItems(dictionaryItemsElement.Elements("DictionaryItem"), 0); // Assert Assert.That(ServiceContext.LocalizationService.DictionaryItemExists(parentKey), "DictionaryItem parentKey does not exist"); @@ -551,7 +553,7 @@ namespace Umbraco.Tests.Services.Importing AddExistingEnglishAndNorwegianParentDictionaryItem(expectedEnglishParentValue, expectedNorwegianParentValue); // Act - ServiceContext.PackagingService.ImportDictionaryItems(dictionaryItemsElement); + PackagingService.ImportDictionaryItems(dictionaryItemsElement.Elements("DictionaryItem"), 0); // Assert AssertDictionaryItem("Parent", expectedEnglishParentValue, "en-GB"); @@ -576,7 +578,7 @@ namespace Umbraco.Tests.Services.Importing AddExistingEnglishParentDictionaryItem(expectedEnglishParentValue); // Act - ServiceContext.PackagingService.ImportDictionaryItems(dictionaryItemsElement); + PackagingService.ImportDictionaryItems(dictionaryItemsElement.Elements("DictionaryItem"), 0); // Assert AssertDictionaryItem("Parent", expectedEnglishParentValue, "en-GB"); @@ -593,7 +595,7 @@ namespace Umbraco.Tests.Services.Importing var LanguageItemsElement = newPackageXml.Elements("Languages").First(); // Act - var languages = ServiceContext.PackagingService.ImportLanguages(LanguageItemsElement); + var languages = PackagingService.ImportLanguages(LanguageItemsElement.Elements("Language"), 0); var allLanguages = ServiceContext.LocalizationService.GetAllLanguages(); // Assert @@ -611,10 +613,10 @@ namespace Umbraco.Tests.Services.Importing string strXml = ImportResources.uBlogsy_Package; var xml = XElement.Parse(strXml); var macrosElement = xml.Descendants("Macros").First(); - var packagingService = ServiceContext.PackagingService; + // Act - var macros = packagingService.ImportMacros(macrosElement).ToList(); + var macros = PackagingService.ImportMacros(macrosElement.Elements("macro"), 0).ToList(); // Assert Assert.That(macros.Any(), Is.True); @@ -633,10 +635,10 @@ namespace Umbraco.Tests.Services.Importing string strXml = ImportResources.XsltSearch_Package; var xml = XElement.Parse(strXml); var macrosElement = xml.Descendants("Macros").First(); - var packagingService = ServiceContext.PackagingService; + // Act - var macros = packagingService.ImportMacros(macrosElement).ToList(); + var macros = PackagingService.ImportMacros(macrosElement.Elements("macro"), 0).ToList(); // Assert Assert.That(macros.Any(), Is.True); @@ -657,11 +659,11 @@ namespace Umbraco.Tests.Services.Importing var xml = XElement.Parse(strXml); var templateElement = xml.Descendants("Templates").First(); var docTypeElement = xml.Descendants("DocumentTypes").First(); - var packagingService = ServiceContext.PackagingService; + // Act - var templates = packagingService.ImportTemplates(templateElement); - var contentTypes = packagingService.ImportContentTypes(docTypeElement); + var templates = PackagingService.ImportTemplates(templateElement.Elements("Template").ToList(), 0); + var contentTypes = PackagingService.ImportDocumentTypes(docTypeElement.Elements("DocumentType"), 0); var numberOfDocTypes = (from doc in docTypeElement.Elements("DocumentType") select doc).Count(); // Assert @@ -685,10 +687,10 @@ namespace Umbraco.Tests.Services.Importing string strXml = ImportResources.CompositionsTestPackage_Random; var xml = XElement.Parse(strXml); var docTypeElement = xml.Descendants("DocumentTypes").First(); - var packagingService = ServiceContext.PackagingService; + // Act - var contentTypes = packagingService.ImportContentTypes(docTypeElement); + var contentTypes = PackagingService.ImportDocumentTypes(docTypeElement.Elements("DocumentType"), 0); var numberOfDocTypes = (from doc in docTypeElement.Elements("DocumentType") select doc).Count(); // Assert diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects.cs b/src/Umbraco.Tests/TestHelpers/TestObjects.cs index f48b72daf9..412a492376 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects.cs @@ -22,6 +22,7 @@ using Umbraco.Core.Scoping; using Umbraco.Core.Services; using Umbraco.Core.Services.Implement; using Umbraco.Core.Strings; +using Umbraco.Tests.TestHelpers.Stubs; using Umbraco.Web.Services; namespace Umbraco.Tests.TestHelpers @@ -78,9 +79,11 @@ namespace Umbraco.Tests.TestHelpers /// A cache. /// A logger. /// + /// /// An event messages factory. /// Some url segment providers. - /// A container. + /// + /// A container. /// /// A ServiceContext. /// Should be used sparingly for integration tests only - for unit tests @@ -168,12 +171,22 @@ namespace Umbraco.Tests.TestHelpers GetRepo(c))); var macroService = GetLazyService(factory, c => new MacroService(scopeProvider, logger, eventMessagesFactory, GetRepo(c), GetRepo(c))); - var packagingService = GetLazyService(factory, c => new PackagingService( - logger, contentService.Value, contentTypeService.Value, macroService.Value, dataTypeService.Value, fileService.Value, localizationService.Value, entityService.Value, auditService.Value, new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty())), - createdPackages: new PackagesRepository(contentService.Value, contentTypeService.Value, dataTypeService.Value, fileService.Value, macroService.Value, localizationService.Value, - new EntityXmlSerializer(contentService.Value, mediaService.Value, dataTypeService.Value, userService.Value, localizationService.Value, contentTypeService.Value, urlSegmentProviders), logger, "createdPackages.config"), - installedPackages: new PackagesRepository(contentService.Value, contentTypeService.Value, dataTypeService.Value, fileService.Value, macroService.Value, localizationService.Value, - new EntityXmlSerializer(contentService.Value, mediaService.Value, dataTypeService.Value, userService.Value, localizationService.Value, contentTypeService.Value, urlSegmentProviders), logger, "installedPackages.config"))); + var packagingService = GetLazyService(factory, c => + { + var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty())); + var compiledPackageXmlParser = new CompiledPackageXmlParser(new ConflictingPackageData(macroService.Value, fileService.Value)); + return new PackagingService( + auditService.Value, + new PackagesRepository(contentService.Value, contentTypeService.Value, dataTypeService.Value, fileService.Value, macroService.Value, localizationService.Value, + new EntityXmlSerializer(contentService.Value, mediaService.Value, dataTypeService.Value, userService.Value, localizationService.Value, contentTypeService.Value, urlSegmentProviders), logger, "createdPackages.config"), + new PackagesRepository(contentService.Value, contentTypeService.Value, dataTypeService.Value, fileService.Value, macroService.Value, localizationService.Value, + new EntityXmlSerializer(contentService.Value, mediaService.Value, dataTypeService.Value, userService.Value, localizationService.Value, contentTypeService.Value, urlSegmentProviders), logger, "installedPackages.config"), + new PackageInstallation( + new PackageDataInstallation(logger, fileService.Value, macroService.Value, localizationService.Value, dataTypeService.Value, entityService.Value, contentTypeService.Value, contentService.Value, propertyEditorCollection), + new PackageFileInstallation(compiledPackageXmlParser, new ProfilingLogger(logger, new TestProfiler())), + compiledPackageXmlParser, Mock.Of(), + "", null, null)); + }); var relationService = GetLazyService(factory, c => new RelationService(scopeProvider, logger, eventMessagesFactory, entityService.Value, GetRepo(c), GetRepo(c))); var treeService = GetLazyService(factory, c => new ApplicationTreeService(logger, cache, typeLoader)); var tagService = GetLazyService(factory, c => new TagService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); diff --git a/src/Umbraco.Web/Composing/Current.cs b/src/Umbraco.Web/Composing/Current.cs index daf152c29b..860d3ec88e 100644 --- a/src/Umbraco.Web/Composing/Current.cs +++ b/src/Umbraco.Web/Composing/Current.cs @@ -216,7 +216,7 @@ namespace Umbraco.Web.Composing internal static ManifestValueValidatorCollection ManifestValidators => CoreCurrent.ManifestValidators; - internal static PackageActionRunner PackageActionRunner => CoreCurrent.PackageActionRunner; + internal static IPackageActionRunner PackageActionRunner => CoreCurrent.PackageActionRunner; internal static PackageActionCollection PackageActions => CoreCurrent.PackageActions; diff --git a/src/Umbraco.Web/Editors/ContentTypeController.cs b/src/Umbraco.Web/Editors/ContentTypeController.cs index 0d56b34617..97f7ff3589 100644 --- a/src/Umbraco.Web/Editors/ContentTypeController.cs +++ b/src/Umbraco.Web/Editors/ContentTypeController.cs @@ -17,7 +17,9 @@ using Umbraco.Core.Dictionary; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models; +using Umbraco.Core.Packaging; using Umbraco.Core.Persistence; +using Umbraco.Core.PropertyEditors; using Umbraco.Core.Services; using Umbraco.Core.Services.Implement; using Umbraco.Web.Composing; @@ -46,10 +48,19 @@ namespace Umbraco.Web.Editors public class ContentTypeController : ContentTypeControllerBase { private readonly IEntityXmlSerializer _serializer; + private readonly PropertyEditorCollection _propertyEditors; - public ContentTypeController(IEntityXmlSerializer serializer, ICultureDictionaryFactory cultureDictionaryFactory, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) : base(cultureDictionaryFactory, globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) + public ContentTypeController(IEntityXmlSerializer serializer, + ICultureDictionaryFactory cultureDictionaryFactory, + IGlobalSettings globalSettings, + IUmbracoContextAccessor umbracoContextAccessor, + ISqlContext sqlContext, PropertyEditorCollection propertyEditors, + ServiceContext services, CacheHelper applicationCache, + IProfilingLogger logger, IRuntimeState runtimeState) + : base(cultureDictionaryFactory, globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) { _serializer = serializer; + _propertyEditors = propertyEditors; } public int GetCount() @@ -162,8 +173,8 @@ namespace Umbraco.Web.Editors throw new HttpResponseException(HttpStatusCode.NotFound); } - var configuration = Current.Services.DataTypeService.GetDataType(id).Configuration; - var editor = Current.PropertyEditors[dataTypeDiff.EditorAlias]; + var configuration = Services.DataTypeService.GetDataType(id).Configuration; + var editor = _propertyEditors[dataTypeDiff.EditorAlias]; return new ContentPropertyDisplay() { @@ -488,14 +499,16 @@ namespace Umbraco.Web.Editors { return Request.CreateResponse(HttpStatusCode.NotFound); } + + var dataInstaller = new PackageDataInstallation(Logger, Services.FileService, Services.MacroService, Services.LocalizationService, + Services.DataTypeService, Services.EntityService, Services.ContentTypeService, Services.ContentService, _propertyEditors); - var xd = new XmlDocument(); - xd.XmlResolver = null; + var xd = new XmlDocument {XmlResolver = null}; xd.Load(filePath); - var userId = Security.GetUserId(); + var userId = Security.GetUserId().ResultOr(0); var element = XElement.Parse(xd.InnerXml); - Current.Services.PackagingService.ImportContentTypes(element, userId); + dataInstaller.ImportDocumentType(element, userId); // Try to clean up the temporary file. try @@ -504,7 +517,7 @@ namespace Umbraco.Web.Editors } catch (Exception ex) { - Current.Logger.Error(ex, "Error cleaning up temporary udt file in App_Data: {File}", filePath); + Logger.Error(ex, "Error cleaning up temporary udt file in App_Data: {File}", filePath); } return Request.CreateResponse(HttpStatusCode.OK); diff --git a/src/Umbraco.Web/Editors/PackageInstallController.cs b/src/Umbraco.Web/Editors/PackageInstallController.cs index 24cc999c6b..bfaec3f82c 100644 --- a/src/Umbraco.Web/Editors/PackageInstallController.cs +++ b/src/Umbraco.Web/Editors/PackageInstallController.cs @@ -42,11 +42,11 @@ namespace Umbraco.Web.Editors [UmbracoApplicationAuthorize(Core.Constants.Applications.Packages)] public class PackageInstallController : UmbracoAuthorizedJsonController { - private readonly PackageActionRunner _packageActionRunner; + private readonly IPackageActionRunner _packageActionRunner; public PackageInstallController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, - IProfilingLogger logger, IRuntimeState runtimeState, PackageActionRunner packageActionRunner) + IProfilingLogger logger, IRuntimeState runtimeState, IPackageActionRunner packageActionRunner) : base(globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) { _packageActionRunner = packageActionRunner; @@ -259,6 +259,7 @@ namespace Umbraco.Web.Editors }; // trigger the UninstalledPackage event + // fixme: This all needs to be part of the service! PackagingService.OnUninstalledPackage(new UninstallPackageEventArgs(summary, package, false)); } diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 64e17af221..89260e59f6 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -1136,7 +1136,6 @@ - diff --git a/src/Umbraco.Web/_Legacy/Packager/Installer.cs b/src/Umbraco.Web/_Legacy/Packager/Installer.cs deleted file mode 100644 index 89dff406b0..0000000000 --- a/src/Umbraco.Web/_Legacy/Packager/Installer.cs +++ /dev/null @@ -1,688 +0,0 @@ -//using System; -//using System.Collections.Generic; -//using System.Diagnostics; -//using System.Globalization; -//using System.IO; -//using System.Linq; -//using System.Net; -//using System.Xml; -//using System.Xml.Linq; -//using System.Xml.XPath; -//using ICSharpCode.SharpZipLib.Zip; -//using Umbraco.Core; -//using Umbraco.Core.Composing; -//using Umbraco.Core.Events; -//using Umbraco.Core.IO; -//using Umbraco.Core.Logging; -//using Umbraco.Core.Models; -//using Umbraco.Core.Models.Packaging; -//using Umbraco.Core.Packaging; -//using Umbraco.Core.Services.Implement; -//using File = System.IO.File; - -//namespace Umbraco.Web._Legacy.Packager -//{ -// /// -// /// The packager is a component which enables sharing of both data and functionality components between different umbraco installations. -// /// -// /// The output is a .umb (a zip compressed file) which contains the exported documents/medias/macroes/documentTypes (etc.) -// /// in a Xml document, along with the physical files used (images/usercontrols/xsl documents etc.) -// /// -// /// Partly implemented, import of packages is done, the export is *under construction*. -// /// -// /// -// /// Ruben Verborgh 31/12/2007: I had to change some code, I marked my changes with "DATALAYER". -// /// Reason: @@IDENTITY can't be used with the new datalayer. -// /// I wasn't able to test the code, since I'm not aware how the code functions. -// /// -// public class Installer -// { -// private const string PackageServer = "packages.umbraco.org"; - -// private readonly Dictionary _conflictingMacroAliases = new Dictionary(); -// private readonly Dictionary _conflictingTemplateAliases = new Dictionary(); -// private readonly Dictionary _conflictingStyleSheetNames = new Dictionary(); - -// private readonly int _currentUserId = -1; -// private static WebClient _webClient; - - -// public string Name { get; private set; } -// public string Version { get; private set; } -// public string Url { get; private set; } -// public string License { get; private set; } -// public string LicenseUrl { get; private set; } -// public string Author { get; private set; } -// public string AuthorUrl { get; private set; } -// public string ReadMe { get; private set; } -// public string Control { get; private set; } - -// public bool ContainsMacroConflict { get; private set; } -// public IDictionary ConflictingMacroAliases => _conflictingMacroAliases; - -// public bool ContainsUnsecureFiles { get; private set; } -// public List UnsecureFiles { get; } = new List(); - -// public bool ContainsTemplateConflicts { get; private set; } -// public IDictionary ConflictingTemplateAliases => _conflictingTemplateAliases; - -// public bool ContainsStyleSheeConflicts { get; private set; } -// public IDictionary ConflictingStyleSheetNames => _conflictingStyleSheetNames; - -// public int RequirementsMajor { get; private set; } -// public int RequirementsMinor { get; private set; } -// public int RequirementsPatch { get; private set; } - -// public RequirementsType RequirementsType { get; private set; } - -// public string IconUrl { get; private set; } - -// /// -// /// The xml of the compiled package -// /// -// public XDocument Config { get; private set; } - -// /// -// /// Constructor -// /// -// public Installer() -// { -// Initialize(); -// } - -// public Installer(int currentUserId) -// { -// Initialize(); -// _currentUserId = currentUserId; -// } - -// private void Initialize() -// { -// ContainsTemplateConflicts = false; -// ContainsUnsecureFiles = false; -// ContainsMacroConflict = false; -// ContainsStyleSheeConflicts = false; -// } - - - -// /// -// /// Constructor -// /// -// /// The name of the package -// /// The version of the package -// /// The url to a descriptionpage -// /// The license under which the package is released (preferably GPL ;)) -// /// The url to a licensedescription -// /// The original author of the package -// /// The url to the Authors website -// /// Umbraco version major -// /// Umbraco version minor -// /// Umbraco version patch -// /// The readme text -// /// The name of the usercontrol used to configure the package after install -// /// -// /// -// public Installer(string name, string version, string url, string license, string licenseUrl, string author, string authorUrl, int requirementsMajor, int requirementsMinor, int requirementsPatch, string readme, string control, RequirementsType requirementsType, string iconUrl) -// { -// ContainsTemplateConflicts = false; -// ContainsUnsecureFiles = false; -// ContainsMacroConflict = false; -// ContainsStyleSheeConflicts = false; -// this.Name = name; -// this.Version = version; -// this.Url = url; -// this.License = license; -// this.LicenseUrl = licenseUrl; -// this.RequirementsMajor = requirementsMajor; -// this.RequirementsMinor = requirementsMinor; -// this.RequirementsPatch = requirementsPatch; -// this.RequirementsType = requirementsType; -// this.Author = author; -// this.AuthorUrl = authorUrl; -// this.IconUrl = iconUrl; -// ReadMe = readme; -// this.Control = control; -// } - -// #region Public Methods - -// /// -// /// Imports the specified package -// /// -// /// Filename of the umbracopackage -// /// true if the input file should be deleted after import -// /// -// public string Import(string inputFile, bool deleteFile) -// { -// using (Current.ProfilingLogger.DebugDuration( -// $"Importing package file {inputFile}.", -// $"Package file {inputFile} imported.")) -// { -// var tempDir = ""; -// if (File.Exists(IOHelper.MapPath(SystemDirectories.Data + "/" + inputFile))) -// { -// var fi = new FileInfo(IOHelper.MapPath(SystemDirectories.Data + "/" + inputFile)); -// // Check if the file is a valid package -// if (fi.Extension.ToLower() == ".umb") -// { -// try -// { -// tempDir = UnPack(fi.FullName, deleteFile); -// LoadConfig(tempDir); -// } -// catch (Exception ex) -// { -// Current.Logger.Error(ex, "Error importing file {FileName}", fi.FullName); -// throw; -// } -// } -// else -// throw new Exception("Error - file isn't a package (doesn't have a .umb extension). Check if the file automatically got named '.zip' upon download."); -// } -// else -// throw new Exception("Error - file not found. Could find file named '" + IOHelper.MapPath(SystemDirectories.Data + Path.DirectorySeparatorChar + inputFile) + "'"); -// return tempDir; -// } - -// } - -// /// -// /// Imports the specified package -// /// -// /// Filename of the umbracopackage -// /// -// public string Import(string inputFile) -// { -// return Import(inputFile, true); -// } - -// public int CreateManifest(Guid guid) -// { -// //This is the new improved install rutine, which chops up the process into 3 steps, creating the manifest, moving files, and finally handling umb objects - -// var parser = new CompiledPackageXmlParser(); -// var def = parser.ToCompiledPackage(Config); - -// //create a new entry in the installedPackages.config -// var installedPackage = new PackageDefinition -// { -// Author = def.Author, -// AuthorUrl = def.AuthorUrl, -// Control = def.Control, -// IconUrl = def.IconUrl, -// License = def.License, -// LicenseUrl = def.LicenseUrl, -// Name = def.Name, -// Readme = def.Readme, -// UmbracoVersion = def.UmbracoVersion, -// Url = def.Url, -// Version = def.Version, -// PackageId = guid -// }; - -// if (!Current.Services.PackagingService.SaveInstalledPackage(installedPackage)) -// throw new InvalidOperationException("Could not save package definition"); - -// return installedPackage.Id; -// } - -// public void InstallFiles(int packageId, string tempDir) -// { -// var parser = new CompiledPackageXmlParser(); - -// using (Current.ProfilingLogger.DebugDuration( -// "Installing package files for package id " + packageId + " into temp folder " + tempDir, -// "Package file installation complete for package id " + packageId)) -// { -// //retrieve the manifest to continue installation -// var insPack = Current.Services.PackagingService.GetInstalledPackageById(packageId); - -// //TODO: Depending on some files, some files should be installed differently. -// //i.e. if stylsheets should probably be installed via business logic, media items should probably use the media IFileSystem! - -// // Move files -// //string virtualBasePath = System.Web.HttpContext.Current.Request.ApplicationPath; -// string basePath = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath; - -// var def = parser.ToCompiledPackage(Config); - -// try -// { -// foreach (var f in def.Files) -// { -// var destPath = GetFileName(basePath, f.OriginalPath); -// var sourceFile = GetFileName(tempDir, f.UniqueFileName); -// var destFile = GetFileName(destPath, f.OriginalName); - -// // Create the destination directory if it doesn't exist -// if (Directory.Exists(destPath) == false) -// Directory.CreateDirectory(destPath); -// //If a file with this name exists, delete it -// else if (File.Exists(destFile)) -// File.Delete(destFile); - -// // Copy the file -// // SJ: Note - this used to do a move but some packages included the same file to be -// // copied to multiple locations like so: -// // -// // -// // my-icon.png -// // /umbraco/Images/ -// // my-icon.png -// // -// // -// // my-icon.png -// // /App_Plugins/MyPlugin/Images -// // my-icon.png -// // -// // -// // Since this file unzips as a flat list of files, moving the file the first time means -// // that when you try to do that a second time, it would result in a FileNotFoundException -// File.Copy(sourceFile, destFile); - -// //PPH log file install -// insPack.Files.Add(f.OriginalPath.EnsureEndsWith('/') + f.OriginalName); - -// } - -// // Once we're done copying, remove all the files -// foreach (var f in def.Files) -// { -// var sourceFile = GetFileName(tempDir, f.UniqueFileName); -// if (File.Exists(sourceFile)) -// File.Delete(sourceFile); -// } -// } -// catch (Exception ex) -// { -// Current.Logger.Error(ex, "Package install error"); -// throw; -// } - -// // log that a user has install files -// if (_currentUserId > -1) -// { -// Current.Services.AuditService.Add(AuditType.PackagerInstall, -// _currentUserId, -// -1, "Package", string.Format("Package '{0}' installed. Package guid: {1}", insPack.Name, insPack.PackageId)); -// } - -// Current.Services.PackagingService.SaveInstalledPackage(insPack); -// } -// } - -// public void InstallBusinessLogic(int packageId, string tempDir) -// { -// using (Current.ProfilingLogger.DebugDuration( -// "Installing business logic for package id " + packageId + " into temp folder " + tempDir, -// "Package business logic installation complete for package id " + packageId)) -// { -// PackageDefinition insPack; -// try -// { -// //retrieve the manifest to continue installation -// insPack = Current.Services.PackagingService.GetInstalledPackageById(packageId); -// //bool saveNeeded = false; - -// // Get current user, with a fallback -// var currentUser = Current.Services.UserService.GetUserById(Constants.Security.SuperUserId); - -// //TODO: Get rid of this entire class! Until then all packages will be installed by the admin user - -// var rootElement = Config.Root; -// var packagingService = Current.Services.PackagingService; - -// //Perhaps it would have been a good idea to put the following into methods eh?!? - -// #region DataTypes -// var dataTypeElement = rootElement.Descendants("DataTypes").FirstOrDefault(); -// if (dataTypeElement != null) -// { -// var dataTypeDefinitions = packagingService.ImportDataTypeDefinitions(dataTypeElement, currentUser.Id); -// foreach (var dataTypeDefinition in dataTypeDefinitions) -// { -// insPack.DataTypes.Add(dataTypeDefinition.Id.ToString(CultureInfo.InvariantCulture)); -// } -// } -// #endregion - -// #region Languages -// var languageItemsElement = rootElement.Descendants("Languages").FirstOrDefault(); -// if (languageItemsElement != null) -// { -// var insertedLanguages = packagingService.ImportLanguages(languageItemsElement); -// foreach(var x in insertedLanguages.Select(l => l.Id.ToString(CultureInfo.InvariantCulture))) -// insPack.Languages.Add(x); -// } - -// #endregion - -// #region Dictionary items -// var dictionaryItemsElement = rootElement.Descendants("DictionaryItems").FirstOrDefault(); -// if (dictionaryItemsElement != null) -// { -// var insertedDictionaryItems = packagingService.ImportDictionaryItems(dictionaryItemsElement); -// foreach (var x in insertedDictionaryItems.Select(d => d.Id.ToString(CultureInfo.InvariantCulture))) -// insPack.DictionaryItems.Add(x); -// } -// #endregion - -// #region Macros -// var macroItemsElement = rootElement.Descendants("Macros").FirstOrDefault(); -// if (macroItemsElement != null) -// { -// var insertedMacros = packagingService.ImportMacros(macroItemsElement); -// foreach (var x in insertedMacros.Select(m => m.Id.ToString(CultureInfo.InvariantCulture))) -// insPack.Macros.Add(x); - -// } -// #endregion - -// #region Templates -// var templateElement = rootElement.Descendants("Templates").FirstOrDefault(); -// if (templateElement != null) -// { -// var templates = packagingService.ImportTemplates(templateElement, currentUser.Id); -// foreach (var template in templates) -// { -// insPack.Templates.Add(template.Id.ToString(CultureInfo.InvariantCulture)); -// } -// } -// #endregion - -// #region DocumentTypes -// //Check whether the root element is a doc type rather then a complete package -// var docTypeElement = rootElement.Name.LocalName.Equals("DocumentType") || -// rootElement.Name.LocalName.Equals("DocumentTypes") -// ? rootElement -// : rootElement.Descendants("DocumentTypes").FirstOrDefault(); - -// if (docTypeElement != null) -// { -// var contentTypes = packagingService.ImportContentTypes(docTypeElement, currentUser.Id); -// foreach (var contentType in contentTypes) -// { -// insPack.DocumentTypes.Add(contentType.Id.ToString(CultureInfo.InvariantCulture)); -// //saveNeeded = true; -// } -// } -// #endregion - -// #region Stylesheets -// foreach (var n in Config.Root.XPathSelectElements("Stylesheets/Stylesheet")) -// { -// string stylesheetName = n.Element("Name")?.Value; -// if (stylesheetName.IsNullOrWhiteSpace()) continue; - -// var s = Current.Services.FileService.GetStylesheetByName(stylesheetName); -// if (s == null) -// { -// var fileName = n.Element("FileName")?.Value; -// if (fileName == null) continue; -// var content = n.Element("Content")?.Value; -// if (content == null) continue; - -// s = new Stylesheet(fileName) { Content = content }; -// Current.Services.FileService.SaveStylesheet(s); -// } - -// foreach (var prop in n.XPathSelectElements("Properties/Property")) -// { -// string alias = prop.Element("Alias")?.Value; -// var sp = s.Properties.SingleOrDefault(p => p != null && p.Alias == alias); -// string name = prop.Element("Name")?.Value; -// if (sp == null) -// { -// //sp = StylesheetProperty.MakeNew( -// // name, -// // s, -// // u); - -// sp = new StylesheetProperty(name, "#" + name.ToSafeAlias(), ""); -// s.AddProperty(sp); -// } -// else -// { -// //sp.Text = name; -// //Changing the name requires removing the current property and then adding another new one -// if (sp.Name != name) -// { -// s.RemoveProperty(sp.Name); -// var newProp = new StylesheetProperty(name, sp.Alias, sp.Value); -// s.AddProperty(newProp); -// sp = newProp; -// } -// } -// sp.Alias = alias; -// sp.Value = prop.Element("Value")?.Value; -// } -// //s.saveCssToFile(); -// Current.Services.FileService.SaveStylesheet(s); - - - - -// insPack.Stylesheets.Add(s.Id.ToString(CultureInfo.InvariantCulture)); -// //saveNeeded = true; -// } - -// //if (saveNeeded) { insPack.Save(); saveNeeded = false; } -// #endregion - -// #region Documents -// var documentElement = rootElement.Descendants("DocumentSet").FirstOrDefault(); -// if (documentElement != null) -// { -// var content = packagingService.ImportContent(documentElement, -1, currentUser.Id); -// var firstContentItem = content.First(); -// insPack.ContentNodeId = firstContentItem.Id.ToString(CultureInfo.InvariantCulture); -// } -// #endregion - -// #region Package Actions -// foreach (var n in Config.Root.XPathSelectElements("Actions/Action")) -// { -// var undo = n.AttributeValue("undo"); -// if (undo == null || undo == "true") -// { -// insPack.Actions += n.ToString(); -// } - -// //Run the actions tagged only for 'install' -// var runat = n.AttributeValue("runat"); - -// if (runat != null && runat == "install") -// { -// var alias = n.AttributeValue("alias"); -// if (alias.IsNullOrWhiteSpace() == false) -// { -// Current.PackageActionRunner.RunPackageAction(insPack.Name, alias, n); -// } -// } -// } -// #endregion - -// Current.Services.PackagingService.SaveInstalledPackage(insPack); -// } -// catch (Exception ex) -// { -// Current.Logger.Error(ex, "Error installing businesslogic"); -// throw; -// } - -// OnPackageInstalled(insPack); -// } -// } - -// /// -// /// Remove the temp installation folder -// /// -// /// -// /// -// public void InstallCleanUp(int packageId, string tempDir) -// { -// if (Directory.Exists(tempDir)) -// { -// Directory.Delete(tempDir, true); -// } -// } - -// /// -// /// Reads the configuration of the package from the configuration xmldocument -// /// -// /// The folder to which the contents of the package is extracted -// public void LoadConfig(string tempDir) -// { -// Config = XDocument.Load(tempDir + Path.DirectorySeparatorChar + "package.xml"); - -// var parser = new CompiledPackageXmlParser(); -// var def = parser.ToCompiledPackage(Config); - -// Name = def.Name; -// Version = def.Version; -// Url = def.Url; -// License = def.License; -// LicenseUrl = def.LicenseUrl; - -// RequirementsMajor = def.UmbracoVersion.Major; -// RequirementsMinor = def.UmbracoVersion.Minor; -// RequirementsPatch = def.UmbracoVersion.Build; -// RequirementsType = def.UmbracoVersionRequirementsType; -// IconUrl = def.IconUrl; -// Author = def.Author; -// AuthorUrl = def.AuthorUrl; -// ReadMe = def.Readme; -// Control = def.Control; - -// var basePath = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath; -// var dllBinFiles = new List(); - -// foreach (var f in def.Files) -// { -// var badFile = false; -// var destPath = GetFileName(basePath, f.OriginalPath); -// var orgName = f.OriginalName; -// var destFile = GetFileName(destPath, orgName); - -// if (destPath.ToLower().Contains(IOHelper.DirSepChar + "app_code")) -// { -// badFile = true; -// } - -// if (destPath.ToLower().Contains(IOHelper.DirSepChar + "bin")) -// { -// badFile = true; -// } - -// if (destFile.ToLower().EndsWith(".dll")) -// { -// badFile = true; -// dllBinFiles.Add(Path.Combine(tempDir, orgName)); -// } - -// if (badFile) -// { -// ContainsUnsecureFiles = true; -// UnsecureFiles.Add(f.OriginalName); -// } -// } - - - -// //this will check for existing macros with the same alias -// //since we will not overwrite on import it's a good idea to inform the user what will be overwritten -// foreach (var n in Config.Root.XPathSelectElements("//macro")) -// { -// var alias = n.Element("alias")?.Value; -// if (!string.IsNullOrEmpty(alias)) -// { -// var m = Current.Services.MacroService.GetByAlias(alias); -// if (m != null) -// { -// ContainsMacroConflict = true; -// if (_conflictingMacroAliases.ContainsKey(m.Name) == false) -// { -// _conflictingMacroAliases.Add(m.Name, alias); -// } -// } -// } -// } - -// foreach (var n in Config.Root.XPathSelectElements("Templates/Template")) -// { -// var alias = n.Element("Alias")?.Value; -// if (!string.IsNullOrEmpty(alias)) -// { -// var t = Current.Services.FileService.GetTemplate(alias); -// if (t != null) -// { -// ContainsTemplateConflicts = true; -// if (_conflictingTemplateAliases.ContainsKey(t.Alias) == false) -// { -// _conflictingTemplateAliases.Add(t.Alias, alias); -// } -// } -// } -// } - -// foreach (var n in Config.Root.XPathSelectElements("Stylesheets/Stylesheet")) -// { -// var alias = n.Element("Name")?.Value; -// if (!string.IsNullOrEmpty(alias)) -// { -// var s = Current.Services.FileService.GetStylesheetByName(alias); -// if (s != null) -// { -// ContainsStyleSheeConflicts = true; -// if (_conflictingStyleSheetNames.ContainsKey(s.Alias) == false) -// { -// _conflictingStyleSheetNames.Add(s.Alias, alias); -// } -// } -// } -// } - - -// } - -// /// -// /// This uses the old method of fetching and only supports the packages.umbraco.org repository. -// /// -// /// -// /// -// public string Fetch(Guid Package) -// { -// // Check for package directory -// if (Directory.Exists(IOHelper.MapPath(SystemDirectories.Packages)) == false) -// Directory.CreateDirectory(IOHelper.MapPath(SystemDirectories.Packages)); - -// if (_webClient == null) -// _webClient = new WebClient(); - -// _webClient.DownloadFile( -// "http://" + PackageServer + "/fetch?package=" + Package.ToString(), -// IOHelper.MapPath(SystemDirectories.Packages + "/" + Package + ".umb")); - -// return "packages\\" + Package + ".umb"; -// } - -// #endregion - -// private void OnPackageInstalled(PackageDefinition insPack) -// { -// // getting an InstallationSummary for sending to the PackagingService.ImportedPackage event -// var fileService = Current.Services.FileService; -// var macroService = Current.Services.MacroService; -// var contentTypeService = Current.Services.ContentTypeService; -// var dataTypeService = Current.Services.DataTypeService; -// var localizationService = Current.Services.LocalizationService; - -// var installationSummary = InstallationSummary.FromPackageDefinition(insPack, contentTypeService, dataTypeService, fileService, localizationService, macroService); -// installationSummary.PackageInstalled = true; - -// var args = new ImportPackageEventArgs(installationSummary, insPack, false); -// PackagingService.OnImportedPackage(args); -// } -// } -//} From aa6342cc30d2d0d13a72881ae63dd25e4ba68c83 Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 14 Jan 2019 17:56:41 +1100 Subject: [PATCH 326/469] adds test --- .../Packaging/CompiledPackageXmlParser.cs | 18 +++++++-------- .../Packaging/PackageInstallationTest.cs | 22 ++++++++++++++++++- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs b/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs index 76f206f478..0f3119f697 100644 --- a/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs +++ b/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs @@ -52,7 +52,7 @@ namespace Umbraco.Core.Packaging UmbracoVersion = new Version((int)requirements.Element("major"), (int)requirements.Element("minor"), (int)requirements.Element("patch")), UmbracoVersionRequirementsType = requirements.AttributeValue("type").IsNullOrWhiteSpace() ? RequirementsType.Legacy : Enum.Parse(requirements.AttributeValue("type")), Control = package.Element("control")?.Value, - Actions = xml.Element("Actions")?.ToString(SaveOptions.None) ?? "", //take the entire outer xml value + Actions = xml.Root.Element("Actions")?.ToString(SaveOptions.None) ?? "", //take the entire outer xml value Files = xml.Root.Element("files")?.Elements("file")?.Select(x => new CompiledPackageFile { UniqueFileName = x.Element("guid")?.Value, @@ -60,14 +60,14 @@ namespace Umbraco.Core.Packaging OriginalPath = x.Element("orgPath")?.Value }).ToList() ?? new List(), - Macros = xml.Element("Macros")?.Elements("macro") ?? Enumerable.Empty(), - Templates = xml.Element("Templates")?.Elements("Template") ?? Enumerable.Empty(), - Stylesheets = xml.Element("Stylesheets")?.Elements("styleSheet") ?? Enumerable.Empty(), - DataTypes = xml.Element("DataTypes")?.Elements("DataType") ?? Enumerable.Empty(), - Languages = xml.Element("Languages")?.Elements("Language") ?? Enumerable.Empty(), - DictionaryItems = xml.Element("DictionaryItems")?.Elements("DictionaryItem") ?? Enumerable.Empty(), - DocumentTypes = xml.Element("DocumentTypes")?.Elements("DocumentType") ?? Enumerable.Empty(), - Documents = xml.Element("Documents")?.Elements("DocumentSet") ?? Enumerable.Empty(), + Macros = xml.Root.Element("Macros")?.Elements("macro") ?? Enumerable.Empty(), + Templates = xml.Root.Element("Templates")?.Elements("Template") ?? Enumerable.Empty(), + Stylesheets = xml.Root.Element("Stylesheets")?.Elements("styleSheet") ?? Enumerable.Empty(), + DataTypes = xml.Root.Element("DataTypes")?.Elements("DataType") ?? Enumerable.Empty(), + Languages = xml.Root.Element("Languages")?.Elements("Language") ?? Enumerable.Empty(), + DictionaryItems = xml.Root.Element("DictionaryItems")?.Elements("DictionaryItem") ?? Enumerable.Empty(), + DocumentTypes = xml.Root.Element("DocumentTypes")?.Elements("DocumentType") ?? Enumerable.Empty(), + Documents = xml.Root.Element("Documents")?.Elements("DocumentSet") ?? Enumerable.Empty(), }; def.Warnings = GetPreInstallWarnings(def, applicationRootFolder); diff --git a/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs b/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs index 964f0c47de..609d26aec9 100644 --- a/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs +++ b/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs @@ -87,7 +87,7 @@ namespace Umbraco.Tests.Packaging Assert.AreEqual("@tentonipete", package.Author); Assert.AreEqual("auros.co.uk", package.AuthorUrl); Assert.AreEqual("Document Type Picker datatype that enables back office user to select one or many document types.", package.Readme); - + Assert.AreEqual(1, package.DataTypes.Count()); } [Test] @@ -114,6 +114,26 @@ namespace Umbraco.Tests.Packaging Assert.AreEqual(1, result.Count); Assert.AreEqual("bin\\Auros.DocumentTypePicker.dll", result[0]); Assert.IsTrue(File.Exists(Path.Combine(IOHelper.MapPath("~/" + _testBaseFolder), result[0]))); + + //make sure the def is updated too + Assert.AreEqual(result.Count(), def.Files.Count); + } + + [Test] + public void Install_Data() + { + var package = PackageInstallation.ReadPackage(documentTypePickerUmb); + var def = PackageDefinition.FromCompiledPackage(package); + def.Id = 1; + def.PackageId = Guid.NewGuid(); + + var summary = PackageInstallation.InstallPackageData(def, package, -1); + + Assert.AreEqual(1, summary.DataTypesInstalled.Count()); + + + //make sure the def is updated too + Assert.AreEqual(summary.DataTypesInstalled.Count(), def.DataTypes.Count); } From b3585b008395e28bcdeeaae02c0a42ea5255c24e Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 14 Jan 2019 18:03:06 +1100 Subject: [PATCH 327/469] some cleanup --- .../Models/Packaging/InstallationSummary.cs | 42 +------------------ .../Models/Packaging/PackageDefinition.cs | 8 ---- .../Packaging/PackageDefinitionXmlParser.cs | 2 - .../Packaging/PackagesRepository.cs | 4 +- .../CreatedPackagesRepositoryTests.cs | 2 - 5 files changed, 2 insertions(+), 56 deletions(-) diff --git a/src/Umbraco.Core/Models/Packaging/InstallationSummary.cs b/src/Umbraco.Core/Models/Packaging/InstallationSummary.cs index b14e3d2a92..7d81f48dd2 100644 --- a/src/Umbraco.Core/Models/Packaging/InstallationSummary.cs +++ b/src/Umbraco.Core/Models/Packaging/InstallationSummary.cs @@ -2,8 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; -using Umbraco.Core.IO; -using Umbraco.Core.Services; namespace Umbraco.Core.Models.Packaging { @@ -23,45 +21,7 @@ namespace Umbraco.Core.Models.Packaging public IEnumerable ContentInstalled { get; set; } = Enumerable.Empty(); public IEnumerable Actions { get; set; } = Enumerable.Empty(); public bool PackageInstalled { get; set; } - - //public static InstallationSummary FromPackageDefinition(PackageDefinition def, IContentTypeService contentTypeService, IDataTypeService dataTypeService, IFileService fileService, ILocalizationService localizationService, IMacroService macroService) - //{ - // var macros = TryGetIntegerIds(def.Macros).Select(macroService.GetById).ToList(); - // var templates = TryGetIntegerIds(def.Templates).Select(fileService.GetTemplate).ToList(); - // var contentTypes = TryGetIntegerIds(def.DocumentTypes).Select(contentTypeService.Get).ToList(); // fixme - media types? - // var dataTypes = TryGetIntegerIds(def.DataTypes).Select(dataTypeService.GetDataType).ToList(); - // var dictionaryItems = TryGetIntegerIds(def.DictionaryItems).Select(localizationService.GetDictionaryItemById).ToList(); - // var languages = TryGetIntegerIds(def.Languages).Select(localizationService.GetLanguageById).ToList(); - - // for (var i = 0; i < def.Files.Count; i++) - // { - // var filePath = def.Files[i]; - // def.Files[i] = filePath.GetRelativePath(); - // } - - // return new InstallationSummary - // { - // ContentTypesInstalled = contentTypes, - // DataTypesInstalled = dataTypes, - // DictionaryItemsInstalled = dictionaryItems, - // FilesInstalled = def.Files, - // LanguagesInstalled = languages, - // MacrosInstalled = macros, - // MetaData = def, - // TemplatesInstalled = templates, - // }; - //} - - //private static IEnumerable TryGetIntegerIds(IEnumerable ids) - //{ - // var intIds = new List(); - // foreach (var id in ids) - // { - // if (int.TryParse(id, out var parsed)) - // intIds.Add(parsed); - // } - // return intIds; - //} + } } diff --git a/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs b/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs index 56a316ff81..de8415ddd2 100644 --- a/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs +++ b/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs @@ -34,7 +34,6 @@ namespace Umbraco.Core.Models.Packaging UmbracoVersion = compiled.UmbracoVersion, Url = compiled.Url, Version = compiled.Version, - //fixme: Is OriginalPath correct here? Files = compiled.Files.Select(x => x.OriginalPath).ToList() }; } @@ -54,13 +53,6 @@ namespace Umbraco.Core.Models.Packaging [Url] public string Url { get; set; } = string.Empty; - //fixme: remove this - /// - /// This is a generated GUID which is used to determine a temporary folder name for processing the package - /// - [DataMember(Name = "folder")] - public Guid FolderId { get; set; } - [ReadOnly(true)] [DataMember(Name = "packagePath")] public string PackagePath { get; set; } = string.Empty; diff --git a/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs b/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs index 9a996d201f..1f0e5ec92e 100644 --- a/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs +++ b/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs @@ -28,7 +28,6 @@ namespace Umbraco.Core.Packaging { Id = xml.AttributeValue("id"), Name = xml.AttributeValue("name") ?? string.Empty, - FolderId = xml.AttributeValue("folder"), PackagePath = xml.AttributeValue("packagePath") ?? string.Empty, Version = xml.AttributeValue("version") ?? string.Empty, Url = xml.AttributeValue("url") ?? string.Empty, @@ -74,7 +73,6 @@ namespace Umbraco.Core.Packaging new XAttribute("version", def.Version ?? string.Empty), new XAttribute("url", def.Url ?? string.Empty), new XAttribute("name", def.Name ?? string.Empty), - new XAttribute("folder", def.FolderId), new XAttribute("packagePath", def.PackagePath ?? string.Empty), new XAttribute("iconUrl", def.IconUrl ?? string.Empty), new XAttribute("umbVersion", def.UmbracoVersion), diff --git a/src/Umbraco.Core/Packaging/PackagesRepository.cs b/src/Umbraco.Core/Packaging/PackagesRepository.cs index 9f37f8a546..c0620820a2 100644 --- a/src/Umbraco.Core/Packaging/PackagesRepository.cs +++ b/src/Umbraco.Core/Packaging/PackagesRepository.cs @@ -131,7 +131,6 @@ namespace Umbraco.Core.Packaging var newId = maxId + 1; definition.Id = newId; definition.PackageId = definition.PackageId == default ? Guid.NewGuid() : definition.PackageId; - definition.FolderId = Guid.NewGuid(); var packageXml = _parser.ToXml(definition); packagesXml.Root.Add(packageXml); } @@ -155,13 +154,12 @@ namespace Umbraco.Core.Packaging { if (definition.Id == default) throw new ArgumentException("The package definition does not have an ID, it must be saved before being exported"); if (definition.PackageId == default) throw new ArgumentException("the package definition does not have a GUID, it must be saved before being exported"); - if (definition.FolderId == default) throw new ArgumentException("the package definition does not have a folder GUID, it must be saved before being exported"); //ensure it's valid ValidatePackage(definition); //Create a folder for building this package - var temporaryPath = IOHelper.MapPath(_tempFolderPath.EnsureEndsWith('/') + definition.FolderId); + var temporaryPath = IOHelper.MapPath(_tempFolderPath.EnsureEndsWith('/') + Guid.NewGuid()); if (Directory.Exists(temporaryPath) == false) Directory.CreateDirectory(temporaryPath); diff --git a/src/Umbraco.Tests/Packaging/CreatedPackagesRepositoryTests.cs b/src/Umbraco.Tests/Packaging/CreatedPackagesRepositoryTests.cs index e059d87524..010572abec 100644 --- a/src/Umbraco.Tests/Packaging/CreatedPackagesRepositoryTests.cs +++ b/src/Umbraco.Tests/Packaging/CreatedPackagesRepositoryTests.cs @@ -83,7 +83,6 @@ namespace Umbraco.Tests.Packaging Assert.IsTrue(result); Assert.AreEqual(1, def1.Id); Assert.AreNotEqual(default(Guid).ToString(), def1.PackageId); - Assert.AreNotEqual(default(Guid).ToString(), def1.FolderId); var def2 = new PackageDefinition { @@ -98,7 +97,6 @@ namespace Umbraco.Tests.Packaging Assert.IsTrue(result); Assert.AreEqual(2, def2.Id); Assert.AreNotEqual(default(Guid).ToString(), def2.PackageId); - Assert.AreNotEqual(default(Guid).ToString(), def2.FolderId); } [Test] From eb6b172be26e30ef5a3b4808e0ca4d3216978d51 Mon Sep 17 00:00:00 2001 From: Stephan Date: Fri, 11 Jan 2019 16:24:16 +0100 Subject: [PATCH 328/469] Cleanup --- .../PublishedCache/NuCache/PublishedSnapshotService.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs b/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs index 3aa33f0e2f..0647e1c806 100755 --- a/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; -using System.Web.Hosting; using CSharpTest.Net.Collections; using Newtonsoft.Json; using Umbraco.Core; @@ -15,7 +14,6 @@ using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Persistence.Dtos; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; @@ -26,7 +24,6 @@ using Umbraco.Core.Services.Implement; using Umbraco.Web.Cache; using Umbraco.Web.Install; using Umbraco.Web.PublishedCache.NuCache.DataSource; -using Umbraco.Web.PublishedCache.XmlPublishedCache; using Umbraco.Web.Routing; namespace Umbraco.Web.PublishedCache.NuCache From c17ee34edb380229b55a8bd812d88517b921e5a8 Mon Sep 17 00:00:00 2001 From: Stephan Date: Fri, 11 Jan 2019 16:34:58 +0100 Subject: [PATCH 329/469] Support enlisting in exiting scope contexts (why not?) --- src/Umbraco.Core/Scoping/ScopeContext.cs | 30 +++++++++++++----------- src/Umbraco.Tests/Scoping/ScopeTests.cs | 16 ++++--------- 2 files changed, 20 insertions(+), 26 deletions(-) diff --git a/src/Umbraco.Core/Scoping/ScopeContext.cs b/src/Umbraco.Core/Scoping/ScopeContext.cs index dd26fda85e..4ba1999474 100644 --- a/src/Umbraco.Core/Scoping/ScopeContext.cs +++ b/src/Umbraco.Core/Scoping/ScopeContext.cs @@ -7,27 +7,32 @@ namespace Umbraco.Core.Scoping internal class ScopeContext : IScopeContext, IInstanceIdentifiable { private Dictionary _enlisted; - private bool _exiting; public void ScopeExit(bool completed) { if (_enlisted == null) return; - _exiting = true; + // fixme - can we create infinite loops? + // fixme - what about nested events? will they just be plainly ignored = really bad? List exceptions = null; - foreach (var enlisted in _enlisted.Values.OrderBy(x => x.Priority)) + List orderedEnlisted; + while ((orderedEnlisted = _enlisted.Values.OrderBy(x => x.Priority).ToList()).Count > 0) { - try + _enlisted.Clear(); + foreach (var enlisted in orderedEnlisted) { - enlisted.Execute(completed); - } - catch (Exception e) - { - if (exceptions == null) - exceptions = new List(); - exceptions.Add(e); + try + { + enlisted.Execute(completed); + } + catch (Exception e) + { + if (exceptions == null) + exceptions = new List(); + exceptions.Add(e); + } } } @@ -74,9 +79,6 @@ namespace Umbraco.Core.Scoping public T Enlist(string key, Func creator, Action action = null, int priority = 100) { - if (_exiting) - throw new InvalidOperationException("Cannot enlist now, context is exiting."); - var enlistedObjects = _enlisted ?? (_enlisted = new Dictionary()); if (enlistedObjects.TryGetValue(key, out var enlisted)) diff --git a/src/Umbraco.Tests/Scoping/ScopeTests.cs b/src/Umbraco.Tests/Scoping/ScopeTests.cs index 3f2740291b..6c5e9a74b5 100644 --- a/src/Umbraco.Tests/Scoping/ScopeTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopeTests.cs @@ -540,7 +540,7 @@ namespace Umbraco.Tests.Scoping var scopeProvider = ScopeProvider; bool? completed = null; - Exception exception = null; + bool? completed2 = null; Assert.IsNull(scopeProvider.AmbientScope); using (var scope = scopeProvider.CreateScope()) @@ -551,15 +551,7 @@ namespace Umbraco.Tests.Scoping // at that point the scope is gone, but the context is still there var ambientContext = scopeProvider.AmbientContext; - - try - { - ambientContext.Enlist("another", c2 => { }); - } - catch (Exception e) - { - exception = e; - } + ambientContext.Enlist("another", c2 => { completed2 = c2; }); }); if (complete) scope.Complete(); @@ -567,8 +559,8 @@ namespace Umbraco.Tests.Scoping Assert.IsNull(scopeProvider.AmbientScope); Assert.IsNull(scopeProvider.AmbientContext); Assert.IsNotNull(completed); - Assert.IsNotNull(exception); - Assert.IsInstanceOf(exception); + Assert.AreEqual(complete,completed.Value); + Assert.AreEqual(complete, completed2.Value); } [Test] From 05fbf6c38a91cbc0e611c510b1d785b888f11c99 Mon Sep 17 00:00:00 2001 From: Stephan Date: Mon, 14 Jan 2019 08:05:37 +0100 Subject: [PATCH 330/469] Fix DistributedCacheBinder ContentService.TreeChanged event --- src/Umbraco.Web/Cache/DistributedCacheBinder_Handlers.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web/Cache/DistributedCacheBinder_Handlers.cs b/src/Umbraco.Web/Cache/DistributedCacheBinder_Handlers.cs index 81b133b9ef..d522e54de6 100644 --- a/src/Umbraco.Web/Cache/DistributedCacheBinder_Handlers.cs +++ b/src/Umbraco.Web/Cache/DistributedCacheBinder_Handlers.cs @@ -142,8 +142,8 @@ namespace Umbraco.Web.Cache () => ContentService.Saved -= ContentService_Saved); Bind(() => ContentService.Copied += ContentService_Copied, // needed for permissions () => ContentService.Copied -= ContentService_Copied); - Bind(() => ContentService.TreeChanged += ContentService_Changed,// handles all content changes - () => ContentService.TreeChanged -= ContentService_Changed); + Bind(() => ContentService.TreeChanged += ContentService_TreeChanged,// handles all content changes + () => ContentService.TreeChanged -= ContentService_TreeChanged); // TreeChanged should also deal with this //Bind(() => ContentService.SavedBlueprint += ContentService_SavedBlueprint, @@ -206,7 +206,7 @@ namespace Umbraco.Web.Cache { } - private void ContentService_Changed(IContentService sender, TreeChange.EventArgs args) + private void ContentService_TreeChanged(IContentService sender, TreeChange.EventArgs args) { _distributedCache.RefreshContentCache(args.Changes.ToArray()); } From fbf60fbac47eb0fe19074bab6e96c87330f6f220 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Mon, 22 Oct 2018 09:39:22 +0200 Subject: [PATCH 331/469] Don't add the "Notification" tree menu item if Umbraco can't send emails --- src/Umbraco.Web/Trees/ContentTreeController.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web/Trees/ContentTreeController.cs b/src/Umbraco.Web/Trees/ContentTreeController.cs index 293cc3d36a..54adb24b74 100644 --- a/src/Umbraco.Web/Trees/ContentTreeController.cs +++ b/src/Umbraco.Web/Trees/ContentTreeController.cs @@ -238,7 +238,10 @@ namespace Umbraco.Web.Trees menu.Items.Add(ui.Text("actions", ActionRights.Instance.Alias), true); menu.Items.Add(ui.Text("actions", ActionProtect.Instance.Alias), true).ConvertLegacyMenuItem(item, "content", "content"); - menu.Items.Add(ui.Text("actions", ActionNotify.Instance.Alias), true); + if (EmailSender.CanSendRequiredEmail) + { + menu.Items.Add(ui.Text("actions", ActionNotify.Instance.Alias), true); + } menu.Items.Add(ui.Text("actions", ActionSendToTranslate.Instance.Alias)).ConvertLegacyMenuItem(item, "content", "content"); menu.Items.Add(ui.Text("actions", ActionRefresh.Instance.Alias), true); From b08e9226001f59d144fca943c59c5486964569b0 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Wed, 7 Nov 2018 12:27:50 +0100 Subject: [PATCH 332/469] Only allow setting up scheduled publishing if the user has the correct permissions to do so --- .../components/content/umbcontentnodeinfo.directive.js | 3 +++ .../src/views/components/content/umb-content-node-info.html | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js index 8f613469a3..c753ac67d2 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js @@ -53,6 +53,9 @@ if (scope.documentType !== null) { scope.previewOpenUrl = '#/settings/documenttypes/edit/' + scope.documentType.id; } + + // only allow configuring scheduled publishing if the user has publish ("U") and unpublish ("Z") permissions on this node + scope.allowScheduledPublishing = _.contains(scope.node.allowedActions, "U") && _.contains(scope.node.allowedActions, "Z"); } scope.auditTrailPageChange = function (pageNumber) { diff --git a/src/Umbraco.Web.UI.Client/src/views/components/content/umb-content-node-info.html b/src/Umbraco.Web.UI.Client/src/views/components/content/umb-content-node-info.html index 7085babf59..0ed3986fe3 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/content/umb-content-node-info.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/content/umb-content-node-info.html @@ -107,7 +107,7 @@
    - + From 05f1a24caff54e2ae9b6ec3f5289b9eb95410df9 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Mon, 14 Jan 2019 08:28:58 +0100 Subject: [PATCH 333/469] Fix duplicate IIS Express settings --- src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index 81ca9c5a37..fc24d2b40f 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -1041,9 +1041,6 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.1\x86\*.* "$(TargetDir)x86\" 7140 / http://localhost:7140 - 7131 - / - http://localhost:7131 False False From db8954e0a5d532943e9885581ef154cb21872cc4 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Mon, 14 Jan 2019 08:52:02 +0100 Subject: [PATCH 334/469] Verify that the current member is approved and not locked out (#3588) --- .../Routing/PublishedContentRequestEngine.cs | 853 +++++++++--------- 1 file changed, 438 insertions(+), 415 deletions(-) diff --git a/src/Umbraco.Web/Routing/PublishedContentRequestEngine.cs b/src/Umbraco.Web/Routing/PublishedContentRequestEngine.cs index 217f407f02..0341c083f9 100644 --- a/src/Umbraco.Web/Routing/PublishedContentRequestEngine.cs +++ b/src/Umbraco.Web/Routing/PublishedContentRequestEngine.cs @@ -26,61 +26,61 @@ using RenderingEngine = Umbraco.Core.RenderingEngine; namespace Umbraco.Web.Routing { internal class PublishedContentRequestEngine - { - private readonly PublishedContentRequest _pcr; - private readonly RoutingContext _routingContext; - private readonly IWebRoutingSection _webRoutingSection; + { + private readonly PublishedContentRequest _pcr; + private readonly RoutingContext _routingContext; + private readonly IWebRoutingSection _webRoutingSection; - /// - /// Initializes a new instance of the class with a content request. - /// - /// - /// The content request. - public PublishedContentRequestEngine( + /// + /// Initializes a new instance of the class with a content request. + /// + /// + /// The content request. + public PublishedContentRequestEngine( IWebRoutingSection webRoutingSection, PublishedContentRequest pcr) - { - if (pcr == null) throw new ArgumentException("pcr is null."); - if (webRoutingSection == null) throw new ArgumentNullException("webRoutingSection"); - - _pcr = pcr; - _webRoutingSection = webRoutingSection; + { + if (pcr == null) throw new ArgumentException("pcr is null."); + if (webRoutingSection == null) throw new ArgumentNullException("webRoutingSection"); - _routingContext = pcr.RoutingContext; - if (_routingContext == null) throw new ArgumentException("pcr.RoutingContext is null."); - - var umbracoContext = _routingContext.UmbracoContext; - if (umbracoContext == null) throw new ArgumentException("pcr.RoutingContext.UmbracoContext is null."); - if (umbracoContext.RoutingContext != _routingContext) throw new ArgumentException("RoutingContext confusion."); - // no! not set yet. - //if (umbracoContext.PublishedContentRequest != _pcr) throw new ArgumentException("PublishedContentRequest confusion."); - } + _pcr = pcr; + _webRoutingSection = webRoutingSection; + + _routingContext = pcr.RoutingContext; + if (_routingContext == null) throw new ArgumentException("pcr.RoutingContext is null."); + + var umbracoContext = _routingContext.UmbracoContext; + if (umbracoContext == null) throw new ArgumentException("pcr.RoutingContext.UmbracoContext is null."); + if (umbracoContext.RoutingContext != _routingContext) throw new ArgumentException("RoutingContext confusion."); + // no! not set yet. + //if (umbracoContext.PublishedContentRequest != _pcr) throw new ArgumentException("PublishedContentRequest confusion."); + } protected ProfilingLogger ProfilingLogger - { + { get { return _routingContext.UmbracoContext.Application.ProfilingLogger; } - } + } - protected ServiceContext Services - { + protected ServiceContext Services + { get { return _routingContext.UmbracoContext.Application.Services; } - } + } - #region Public + #region Public /// /// Tries to route the request. /// - internal bool TryRouteRequest() - { + internal bool TryRouteRequest() + { // disabled - is it going to change the routing? //_pcr.OnPreparing(); FindDomain(); - if (_pcr.IsRedirect) return false; - if (_pcr.HasPublishedContent) return true; - FindPublishedContent(); + if (_pcr.IsRedirect) return false; + if (_pcr.HasPublishedContent) return true; + FindPublishedContent(); if (_pcr.IsRedirect) return false; // don't handle anything - we just want to ensure that we find the content @@ -93,51 +93,51 @@ namespace Umbraco.Web.Routing //_pcr.OnPrepared(); return _pcr.HasPublishedContent; - } + } - /// - /// Prepares the request. - /// - /// - /// Returns false if the request was not successfully prepared - /// - public bool PrepareRequest() - { - // note - at that point the original legacy module did something do handle IIS custom 404 errors - // ie pages looking like /anything.aspx?404;/path/to/document - I guess the reason was to support - // "directory urls" without having to do wildcard mapping to ASP.NET on old IIS. This is a pain - // to maintain and probably not used anymore - removed as of 06/2012. @zpqrtbnk. - // - // to trigger Umbraco's not-found, one should configure IIS and/or ASP.NET custom 404 errors - // so that they point to a non-existing page eg /redirect-404.aspx - // TODO: SD: We need more information on this for when we release 4.10.0 as I'm not sure what this means. + /// + /// Prepares the request. + /// + /// + /// Returns false if the request was not successfully prepared + /// + public bool PrepareRequest() + { + // note - at that point the original legacy module did something do handle IIS custom 404 errors + // ie pages looking like /anything.aspx?404;/path/to/document - I guess the reason was to support + // "directory urls" without having to do wildcard mapping to ASP.NET on old IIS. This is a pain + // to maintain and probably not used anymore - removed as of 06/2012. @zpqrtbnk. + // + // to trigger Umbraco's not-found, one should configure IIS and/or ASP.NET custom 404 errors + // so that they point to a non-existing page eg /redirect-404.aspx + // TODO: SD: We need more information on this for when we release 4.10.0 as I'm not sure what this means. // trigger the Preparing event - at that point anything can still be changed // the idea is that it is possible to change the uri // - _pcr.OnPreparing(); + _pcr.OnPreparing(); - //find domain - FindDomain(); + //find domain + FindDomain(); - // if request has been flagged to redirect then return - // whoever called us is in charge of actually redirecting - if (_pcr.IsRedirect) - { - return false; - } + // if request has been flagged to redirect then return + // whoever called us is in charge of actually redirecting + if (_pcr.IsRedirect) + { + return false; + } - // set the culture on the thread - once, so it's set when running document lookups - Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture = _pcr.Culture; + // set the culture on the thread - once, so it's set when running document lookups + Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture = _pcr.Culture; //find the published content if it's not assigned. This could be manually assigned with a custom route handler, or // with something like EnsurePublishedContentRequestAttribute or UmbracoVirtualNodeRouteHandler. Those in turn call this method // to setup the rest of the pipeline but we don't want to run the finders since there's one assigned. - if (_pcr.PublishedContent == null) - { + if (_pcr.PublishedContent == null) + { // find the document & template FindPublishedContentAndTemplate(); - } + } // handle wildcard domains HandleWildcardDomains(); @@ -145,19 +145,19 @@ namespace Umbraco.Web.Routing // set the culture on the thread -- again, 'cos it might have changed due to a finder or wildcard domain Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture = _pcr.Culture; - // trigger the Prepared event - at that point it is still possible to change about anything + // trigger the Prepared event - at that point it is still possible to change about anything // even though the request might be flagged for redirection - we'll redirect _after_ the event // // also, OnPrepared() will make the PublishedContentRequest readonly, so nothing can change // - _pcr.OnPrepared(); + _pcr.OnPrepared(); // we don't take care of anything so if the content has changed, it's up to the user // to find out the appropriate template //complete the PCR and assign the remaining values - return ConfigureRequest(); - } + return ConfigureRequest(); + } /// /// Called by PrepareRequest once everything has been discovered, resolved and assigned to the PCR. This method @@ -210,73 +210,73 @@ namespace Umbraco.Web.Routing return true; } - /// - /// Updates the request when there is no template to render the content. - /// - /// This is called from Mvc when there's a document to render but no template. - public void UpdateRequestOnMissingTemplate() - { - // clear content - var content = _pcr.PublishedContent; - _pcr.PublishedContent = null; + /// + /// Updates the request when there is no template to render the content. + /// + /// This is called from Mvc when there's a document to render but no template. + public void UpdateRequestOnMissingTemplate() + { + // clear content + var content = _pcr.PublishedContent; + _pcr.PublishedContent = null; - HandlePublishedContent(); // will go 404 - FindTemplate(); + HandlePublishedContent(); // will go 404 + FindTemplate(); - // if request has been flagged to redirect then return - // whoever called us is in charge of redirecting - if (_pcr.IsRedirect) - return; + // if request has been flagged to redirect then return + // whoever called us is in charge of redirecting + if (_pcr.IsRedirect) + return; - if (_pcr.HasPublishedContent == false) - { - // means the engine could not find a proper document to handle 404 - // restore the saved content so we know it exists - _pcr.PublishedContent = content; - return; - } + if (_pcr.HasPublishedContent == false) + { + // means the engine could not find a proper document to handle 404 + // restore the saved content so we know it exists + _pcr.PublishedContent = content; + return; + } - if (_pcr.HasTemplate == false) - { - // means we may have a document, but we have no template - // at that point there isn't much we can do and there is no point returning - // to Mvc since Mvc can't do much either - return; - } + if (_pcr.HasTemplate == false) + { + // means we may have a document, but we have no template + // at that point there isn't much we can do and there is no point returning + // to Mvc since Mvc can't do much either + return; + } // see note in PrepareRequest() - // assign the legacy page back to the docrequest - // handlers like default.aspx will want it and most macros currently need it - _pcr.UmbracoPage = new page(_pcr); + // assign the legacy page back to the docrequest + // handlers like default.aspx will want it and most macros currently need it + _pcr.UmbracoPage = new page(_pcr); - // these two are used by many legacy objects - _routingContext.UmbracoContext.HttpContext.Items["pageID"] = _pcr.PublishedContent.Id; - _routingContext.UmbracoContext.HttpContext.Items["pageElements"] = _pcr.UmbracoPage.Elements; - } + // these two are used by many legacy objects + _routingContext.UmbracoContext.HttpContext.Items["pageID"] = _pcr.PublishedContent.Id; + _routingContext.UmbracoContext.HttpContext.Items["pageElements"] = _pcr.UmbracoPage.Elements; + } - #endregion + #endregion - #region Domain + #region Domain - /// - /// Finds the site root (if any) matching the http request, and updates the PublishedContentRequest accordingly. - /// - /// A value indicating whether a domain was found. - internal bool FindDomain() - { - const string tracePrefix = "FindDomain: "; + /// + /// Finds the site root (if any) matching the http request, and updates the PublishedContentRequest accordingly. + /// + /// A value indicating whether a domain was found. + internal bool FindDomain() + { + const string tracePrefix = "FindDomain: "; - // note - we are not handling schemes nor ports here. + // note - we are not handling schemes nor ports here. - ProfilingLogger.Logger.Debug("{0}Uri=\"{1}\"", () => tracePrefix, () => _pcr.Uri); + ProfilingLogger.Logger.Debug("{0}Uri=\"{1}\"", () => tracePrefix, () => _pcr.Uri); - // try to find a domain matching the current request + // try to find a domain matching the current request var domainAndUri = DomainHelper.DomainForUri(Services.DomainService.GetAll(false), _pcr.Uri); - // handle domain - if (domainAndUri != null && domainAndUri.UmbracoDomain.LanguageIsoCode.IsNullOrWhiteSpace() == false) - { + // handle domain + if (domainAndUri != null && domainAndUri.UmbracoDomain.LanguageIsoCode.IsNullOrWhiteSpace() == false) + { // matching an existing domain ProfilingLogger.Logger.Debug("{0}Matches domain=\"{1}\", rootId={2}, culture=\"{3}\"", () => tracePrefix, @@ -296,49 +296,49 @@ namespace Umbraco.Web.Routing // } } else - { - // not matching any existing domain - ProfilingLogger.Logger.Debug("{0}Matches no domain", () => tracePrefix); + { + // not matching any existing domain + ProfilingLogger.Logger.Debug("{0}Matches no domain", () => tracePrefix); var defaultLanguage = Services.LocalizationService.GetAllLanguages().FirstOrDefault(); - _pcr.Culture = defaultLanguage == null ? CultureInfo.CurrentUICulture : new CultureInfo(defaultLanguage.IsoCode); - } + _pcr.Culture = defaultLanguage == null ? CultureInfo.CurrentUICulture : new CultureInfo(defaultLanguage.IsoCode); + } - ProfilingLogger.Logger.Debug("{0}Culture=\"{1}\"", () => tracePrefix, () => _pcr.Culture.Name); + ProfilingLogger.Logger.Debug("{0}Culture=\"{1}\"", () => tracePrefix, () => _pcr.Culture.Name); - return _pcr.UmbracoDomain != null; - } + return _pcr.UmbracoDomain != null; + } - /// - /// Looks for wildcard domains in the path and updates Culture accordingly. - /// - internal void HandleWildcardDomains() - { - const string tracePrefix = "HandleWildcardDomains: "; + /// + /// Looks for wildcard domains in the path and updates Culture accordingly. + /// + internal void HandleWildcardDomains() + { + const string tracePrefix = "HandleWildcardDomains: "; - if (_pcr.HasPublishedContent == false) - return; + if (_pcr.HasPublishedContent == false) + return; - var nodePath = _pcr.PublishedContent.Path; - ProfilingLogger.Logger.Debug("{0}Path=\"{1}\"", () => tracePrefix, () => nodePath); + var nodePath = _pcr.PublishedContent.Path; + ProfilingLogger.Logger.Debug("{0}Path=\"{1}\"", () => tracePrefix, () => nodePath); var rootNodeId = _pcr.HasDomain ? _pcr.UmbracoDomain.RootContentId : (int?)null; var domain = DomainHelper.FindWildcardDomainInPath(Services.DomainService.GetAll(true), nodePath, rootNodeId); - if (domain != null && domain.LanguageIsoCode.IsNullOrWhiteSpace() == false) - { + if (domain != null && domain.LanguageIsoCode.IsNullOrWhiteSpace() == false) + { _pcr.Culture = new CultureInfo(domain.LanguageIsoCode); ProfilingLogger.Logger.Debug("{0}Got domain on node {1}, set culture to \"{2}\".", () => tracePrefix, () => domain.RootContentId, () => _pcr.Culture.Name); } - else - { - ProfilingLogger.Logger.Debug("{0}No match.", () => tracePrefix); - } - } + else + { + ProfilingLogger.Logger.Debug("{0}No match.", () => tracePrefix); + } + } - #endregion + #endregion - #region Rendering engine + #region Rendering engine /// /// Finds the rendering engine to use to render a template specified by its alias. @@ -383,264 +383,287 @@ namespace Umbraco.Web.Routing return directory.GetFiles().Any(f => extensions.Any(e => f.Name.InvariantEquals(alias + e))); } - #endregion + #endregion - #region Document and template + #region Document and template - /// - /// Finds the Umbraco document (if any) matching the request, and updates the PublishedContentRequest accordingly. - /// - /// A value indicating whether a document and template were found. - private void FindPublishedContentAndTemplate() - { - const string tracePrefix = "FindPublishedContentAndTemplate: "; - ProfilingLogger.Logger.Debug("{0}Path=\"{1}\"", () => tracePrefix, () => _pcr.Uri.AbsolutePath); + /// + /// Finds the Umbraco document (if any) matching the request, and updates the PublishedContentRequest accordingly. + /// + /// A value indicating whether a document and template were found. + private void FindPublishedContentAndTemplate() + { + const string tracePrefix = "FindPublishedContentAndTemplate: "; + ProfilingLogger.Logger.Debug("{0}Path=\"{1}\"", () => tracePrefix, () => _pcr.Uri.AbsolutePath); - // run the document finders - FindPublishedContent(); + // run the document finders + FindPublishedContent(); // if request has been flagged to redirect then return // whoever called us is in charge of actually redirecting // -- do not process anything any further -- if (_pcr.IsRedirect) - return; + return; - // not handling umbracoRedirect here but after LookupDocument2 - // so internal redirect, 404, etc has precedence over redirect + // not handling umbracoRedirect here but after LookupDocument2 + // so internal redirect, 404, etc has precedence over redirect - // handle not-found, redirects, access... - HandlePublishedContent(); + // handle not-found, redirects, access... + HandlePublishedContent(); - // find a template - FindTemplate(); + // find a template + FindTemplate(); - // handle umbracoRedirect - FollowExternalRedirect(); - } + // handle umbracoRedirect + FollowExternalRedirect(); + } - /// - /// Tries to find the document matching the request, by running the IPublishedContentFinder instances. - /// + /// + /// Tries to find the document matching the request, by running the IPublishedContentFinder instances. + /// /// There is no finder collection. - internal void FindPublishedContent() - { - const string tracePrefix = "FindPublishedContent: "; + internal void FindPublishedContent() + { + const string tracePrefix = "FindPublishedContent: "; - // look for the document - // the first successful finder, if any, will set this.PublishedContent, and may also set this.Template - // some finders may implement caching + // look for the document + // the first successful finder, if any, will set this.PublishedContent, and may also set this.Template + // some finders may implement caching using (ProfilingLogger.DebugDuration( - string.Format("{0}Begin finders", tracePrefix), - string.Format("{0}End finders, {1}", tracePrefix, (_pcr.HasPublishedContent ? "a document was found" : "no document was found")))) - { - if (_routingContext.PublishedContentFinders == null) + string.Format("{0}Begin finders", tracePrefix), + string.Format("{0}End finders, {1}", tracePrefix, (_pcr.HasPublishedContent ? "a document was found" : "no document was found")))) + { + if (_routingContext.PublishedContentFinders == null) throw new InvalidOperationException("There is no finder collection."); //iterate but return on first one that finds it - var found = _routingContext.PublishedContentFinders.Any(finder => finder.TryFindContent(_pcr)); - } + var found = _routingContext.PublishedContentFinders.Any(finder => finder.TryFindContent(_pcr)); + } - // indicate that the published content (if any) we have at the moment is the - // one that was found by the standard finders before anything else took place. - _pcr.SetIsInitialPublishedContent(); - } + // indicate that the published content (if any) we have at the moment is the + // one that was found by the standard finders before anything else took place. + _pcr.SetIsInitialPublishedContent(); + } - /// - /// Handles the published content (if any). - /// - /// - /// Handles "not found", internal redirects, access validation... - /// things that must be handled in one place because they can create loops - /// - private void HandlePublishedContent() - { - const string tracePrefix = "HandlePublishedContent: "; + /// + /// Handles the published content (if any). + /// + /// + /// Handles "not found", internal redirects, access validation... + /// things that must be handled in one place because they can create loops + /// + private void HandlePublishedContent() + { + const string tracePrefix = "HandlePublishedContent: "; - // because these might loop, we have to have some sort of infinite loop detection - int i = 0, j = 0; - const int maxLoop = 8; - do - { - ProfilingLogger.Logger.Debug("{0}{1}", () => tracePrefix, () => (i == 0 ? "Begin" : "Loop")); + // because these might loop, we have to have some sort of infinite loop detection + int i = 0, j = 0; + const int maxLoop = 8; + do + { + ProfilingLogger.Logger.Debug("{0}{1}", () => tracePrefix, () => (i == 0 ? "Begin" : "Loop")); - // handle not found - if (_pcr.HasPublishedContent == false) - { - _pcr.Is404 = true; - ProfilingLogger.Logger.Debug("{0}No document, try last chance lookup", () => tracePrefix); + // handle not found + if (_pcr.HasPublishedContent == false) + { + _pcr.Is404 = true; + ProfilingLogger.Logger.Debug("{0}No document, try last chance lookup", () => tracePrefix); - // if it fails then give up, there isn't much more that we can do - var lastChance = _routingContext.PublishedContentLastChanceFinder; - if (lastChance == null || lastChance.TryFindContent(_pcr) == false) - { - ProfilingLogger.Logger.Debug("{0}Failed to find a document, give up", () => tracePrefix); - break; - } + // if it fails then give up, there isn't much more that we can do + var lastChance = _routingContext.PublishedContentLastChanceFinder; + if (lastChance == null || lastChance.TryFindContent(_pcr) == false) + { + ProfilingLogger.Logger.Debug("{0}Failed to find a document, give up", () => tracePrefix); + break; + } - ProfilingLogger.Logger.Debug("{0}Found a document", () => tracePrefix); - } + ProfilingLogger.Logger.Debug("{0}Found a document", () => tracePrefix); + } - // follow internal redirects as long as it's not running out of control ie infinite loop of some sort - j = 0; - while (FollowInternalRedirects() && j++ < maxLoop) - { } - if (j == maxLoop) // we're running out of control - break; + // follow internal redirects as long as it's not running out of control ie infinite loop of some sort + j = 0; + while (FollowInternalRedirects() && j++ < maxLoop) + { } + if (j == maxLoop) // we're running out of control + break; - // ensure access - if (_pcr.HasPublishedContent) - EnsurePublishedContentAccess(); + // ensure access + if (_pcr.HasPublishedContent) + EnsurePublishedContentAccess(); - // loop while we don't have page, ie the redirect or access - // got us to nowhere and now we need to run the notFoundLookup again - // as long as it's not running out of control ie infinite loop of some sort + // loop while we don't have page, ie the redirect or access + // got us to nowhere and now we need to run the notFoundLookup again + // as long as it's not running out of control ie infinite loop of some sort - } while (_pcr.HasPublishedContent == false && i++ < maxLoop); + } while (_pcr.HasPublishedContent == false && i++ < maxLoop); - if (i == maxLoop || j == maxLoop) - { - ProfilingLogger.Logger.Debug("{0}Looks like we're running into an infinite loop, abort", () => tracePrefix); - _pcr.PublishedContent = null; - } + if (i == maxLoop || j == maxLoop) + { + ProfilingLogger.Logger.Debug("{0}Looks like we're running into an infinite loop, abort", () => tracePrefix); + _pcr.PublishedContent = null; + } - ProfilingLogger.Logger.Debug("{0}End", () => tracePrefix); - } + ProfilingLogger.Logger.Debug("{0}End", () => tracePrefix); + } - /// - /// Follows internal redirections through the umbracoInternalRedirectId document property. - /// - /// A value indicating whether redirection took place and led to a new published document. - /// - /// Redirecting to a different site root and/or culture will not pick the new site root nor the new culture. - /// As per legacy, if the redirect does not work, we just ignore it. - /// - private bool FollowInternalRedirects() - { - const string tracePrefix = "FollowInternalRedirects: "; + /// + /// Follows internal redirections through the umbracoInternalRedirectId document property. + /// + /// A value indicating whether redirection took place and led to a new published document. + /// + /// Redirecting to a different site root and/or culture will not pick the new site root nor the new culture. + /// As per legacy, if the redirect does not work, we just ignore it. + /// + private bool FollowInternalRedirects() + { + const string tracePrefix = "FollowInternalRedirects: "; + + if (_pcr.PublishedContent == null) + throw new InvalidOperationException("There is no PublishedContent."); - if (_pcr.PublishedContent == null) - throw new InvalidOperationException("There is no PublishedContent."); - // don't try to find a redirect if the property doesn't exist - if (_pcr.PublishedContent.HasProperty(Constants.Conventions.Content.InternalRedirectId) == false) - return false; + if (_pcr.PublishedContent.HasProperty(Constants.Conventions.Content.InternalRedirectId) == false) + return false; var redirect = false; - IPublishedContent internalRedirectNode = null; - var internalRedirectId = - _pcr.PublishedContent.GetPropertyValue(Constants.Conventions.Content.InternalRedirectId, -1); - var valueValid = false; - if (internalRedirectId > 0) - { - valueValid = true; - // Try and get the redirect node from a legacy integer ID - internalRedirectNode = _routingContext.UmbracoContext.ContentCache.GetById(internalRedirectId); - } - else - { - var udiInternalRedirectId = - _pcr.PublishedContent.GetPropertyValue(Constants.Conventions.Content.InternalRedirectId); + IPublishedContent internalRedirectNode = null; + var internalRedirectId = + _pcr.PublishedContent.GetPropertyValue(Constants.Conventions.Content.InternalRedirectId, -1); + var valueValid = false; + if (internalRedirectId > 0) + { + valueValid = true; + // Try and get the redirect node from a legacy integer ID + internalRedirectNode = _routingContext.UmbracoContext.ContentCache.GetById(internalRedirectId); + } + else + { + var udiInternalRedirectId = + _pcr.PublishedContent.GetPropertyValue(Constants.Conventions.Content.InternalRedirectId); if (udiInternalRedirectId != null) - { - valueValid = true; - // Try and get the redirect node from a UDI Guid - internalRedirectNode = - _routingContext.UmbracoContext.ContentCache.GetById(udiInternalRedirectId.Guid); - } - } + { + valueValid = true; + // Try and get the redirect node from a UDI Guid + internalRedirectNode = + _routingContext.UmbracoContext.ContentCache.GetById(udiInternalRedirectId.Guid); + } + } if (valueValid == false) - { + { // bad redirect - log and display the current page (legacy behavior) ProfilingLogger - .Logger.Debug( - "{0}Failed to redirect, value of '{1}' is not an int nor a GuidUdi", - () => tracePrefix, () => Constants.Conventions.Content.InternalRedirectId); - } + .Logger.Debug( + "{0}Failed to redirect, value of '{1}' is not an int nor a GuidUdi", + () => tracePrefix, () => Constants.Conventions.Content.InternalRedirectId); + } - if (internalRedirectNode == null) - { - ProfilingLogger.Logger.Debug( - "{0}Failed to redirect, value of '{1}' does not lead to a published document", () => tracePrefix, - () => Constants.Conventions.Content.InternalRedirectId); - } - else if (internalRedirectNode.Id == _pcr.PublishedContent.Id) - { - // redirect to self - ProfilingLogger.Logger.Debug("{0}Redirecting to self, ignore", - () => tracePrefix); - } - else - { - // Redirect to another page - _pcr.SetInternalRedirectPublishedContent(internalRedirectNode); - redirect = true; - ProfilingLogger.Logger.Debug("{0}Redirecting to id={1}", () => tracePrefix, - () => internalRedirectNode.Id); - } + if (internalRedirectNode == null) + { + ProfilingLogger.Logger.Debug( + "{0}Failed to redirect, value of '{1}' does not lead to a published document", () => tracePrefix, + () => Constants.Conventions.Content.InternalRedirectId); + } + else if (internalRedirectNode.Id == _pcr.PublishedContent.Id) + { + // redirect to self + ProfilingLogger.Logger.Debug("{0}Redirecting to self, ignore", + () => tracePrefix); + } + else + { + // Redirect to another page + _pcr.SetInternalRedirectPublishedContent(internalRedirectNode); + redirect = true; + ProfilingLogger.Logger.Debug("{0}Redirecting to id={1}", () => tracePrefix, + () => internalRedirectNode.Id); + } - return redirect; - } + return redirect; + } - /// - /// Ensures that access to current node is permitted. - /// - /// Redirecting to a different site root and/or culture will not pick the new site root nor the new culture. - private void EnsurePublishedContentAccess() - { - const string tracePrefix = "EnsurePublishedContentAccess: "; + /// + /// Ensures that access to current node is permitted. + /// + /// Redirecting to a different site root and/or culture will not pick the new site root nor the new culture. + private void EnsurePublishedContentAccess() + { + const string tracePrefix = "EnsurePublishedContentAccess: "; - if (_pcr.PublishedContent == null) - throw new InvalidOperationException("There is no PublishedContent."); + if (_pcr.PublishedContent == null) + throw new InvalidOperationException("There is no PublishedContent."); - var path = _pcr.PublishedContent.Path; + var path = _pcr.PublishedContent.Path; - var publicAccessAttempt = Services.PublicAccessService.IsProtected(path); + var publicAccessAttempt = Services.PublicAccessService.IsProtected(path); if (publicAccessAttempt) - { - ProfilingLogger.Logger.Debug("{0}Page is protected, check for access", () => tracePrefix); + { + ProfilingLogger.Logger.Debug("{0}Page is protected, check for access", () => tracePrefix); - var membershipHelper = new MembershipHelper(_routingContext.UmbracoContext); + var membershipHelper = new MembershipHelper(_routingContext.UmbracoContext); - if (membershipHelper.IsLoggedIn() == false) - { - ProfilingLogger.Logger.Debug("{0}Not logged in, redirect to login page", () => tracePrefix); + if (membershipHelper.IsLoggedIn() == false) + { + ProfilingLogger.Logger.Debug("{0}Not logged in, redirect to login page", () => tracePrefix); var loginPageId = publicAccessAttempt.Result.LoginNodeId; - if (loginPageId != _pcr.PublishedContent.Id) + if (loginPageId != _pcr.PublishedContent.Id) _pcr.PublishedContent = _routingContext.UmbracoContext.ContentCache.GetById(loginPageId); - } + } else if (Services.PublicAccessService.HasAccess(_pcr.PublishedContent.Id, Services.ContentService, _pcr.GetRolesForLogin(membershipHelper.CurrentUserName)) == false) - { - ProfilingLogger.Logger.Debug("{0}Current member has not access, redirect to error page", () => tracePrefix); - var errorPageId = publicAccessAttempt.Result.NoAccessNodeId; - if (errorPageId != _pcr.PublishedContent.Id) + { + ProfilingLogger.Logger.Debug("{0}Current member has not access, redirect to error page", () => tracePrefix); + var errorPageId = publicAccessAttempt.Result.NoAccessNodeId; + if (errorPageId != _pcr.PublishedContent.Id) _pcr.PublishedContent = _routingContext.UmbracoContext.ContentCache.GetById(errorPageId); - } - else - { - ProfilingLogger.Logger.Debug("{0}Current member has access", () => tracePrefix); - } - } - else - { - ProfilingLogger.Logger.Debug("{0}Page is not protected", () => tracePrefix); - } - } + } + else + { + // grab the current member + var member = membershipHelper.GetCurrentMember(); + // if the member has the "approved" and/or "locked out" properties, make sure they're correctly set before allowing access + var memberIsActive = true; + if (member != null) + { + if (member.HasProperty(Constants.Conventions.Member.IsApproved) == false) + memberIsActive = member.GetPropertyValue(Constants.Conventions.Member.IsApproved); - /// - /// Finds a template for the current node, if any. - /// - private void FindTemplate() - { - // NOTE: at the moment there is only 1 way to find a template, and then ppl must - // use the Prepared event to change the template if they wish. Should we also - // implement an ITemplateFinder logic? + if (member.HasProperty(Constants.Conventions.Member.IsLockedOut) == false) + memberIsActive = member.GetPropertyValue(Constants.Conventions.Member.IsLockedOut) == false; + } - const string tracePrefix = "FindTemplate: "; + if (memberIsActive == false) + { + ProfilingLogger.Logger.Debug("{0}Current member is either unapproved or locked out, redirect to error page", () => tracePrefix); + var errorPageId = publicAccessAttempt.Result.NoAccessNodeId; + if (errorPageId != _pcr.PublishedContent.Id) + _pcr.PublishedContent = _routingContext.UmbracoContext.ContentCache.GetById(errorPageId); + } + else + { + ProfilingLogger.Logger.Debug("{0}Current member has access", () => tracePrefix); + } + } + } + else + { + ProfilingLogger.Logger.Debug("{0}Page is not protected", () => tracePrefix); + } + } + + /// + /// Finds a template for the current node, if any. + /// + private void FindTemplate() + { + // NOTE: at the moment there is only 1 way to find a template, and then ppl must + // use the Prepared event to change the template if they wish. Should we also + // implement an ITemplateFinder logic? + + const string tracePrefix = "FindTemplate: "; if (_pcr.PublishedContent == null) { @@ -648,49 +671,49 @@ namespace Umbraco.Web.Routing return; } - // read the alternate template alias, from querystring, form, cookie or server vars, - // only if the published content is the initial once, else the alternate template - // does not apply + // read the alternate template alias, from querystring, form, cookie or server vars, + // only if the published content is the initial once, else the alternate template + // does not apply // + optionnally, apply the alternate template on internal redirects var useAltTemplate = _pcr.IsInitialPublishedContent || (_webRoutingSection.InternalRedirectPreservesTemplate && _pcr.IsInternalRedirectPublishedContent); string altTemplate = useAltTemplate ? _routingContext.UmbracoContext.HttpContext.Request[Constants.Conventions.Url.AltTemplate] - : null; + : null; - if (string.IsNullOrWhiteSpace(altTemplate)) - { - // we don't have an alternate template specified. use the current one if there's one already, - // which can happen if a content lookup also set the template (LookupByNiceUrlAndTemplate...), - // else lookup the template id on the document then lookup the template with that id. + if (string.IsNullOrWhiteSpace(altTemplate)) + { + // we don't have an alternate template specified. use the current one if there's one already, + // which can happen if a content lookup also set the template (LookupByNiceUrlAndTemplate...), + // else lookup the template id on the document then lookup the template with that id. - if (_pcr.HasTemplate) - { - ProfilingLogger.Logger.Debug("{0}Has a template already, and no alternate template.", () => tracePrefix); - return; - } + if (_pcr.HasTemplate) + { + ProfilingLogger.Logger.Debug("{0}Has a template already, and no alternate template.", () => tracePrefix); + return; + } - // TODO: When we remove the need for a database for templates, then this id should be irrelavent, - // not sure how were going to do this nicely. + // TODO: When we remove the need for a database for templates, then this id should be irrelavent, + // not sure how were going to do this nicely. - var templateId = _pcr.PublishedContent.TemplateId; + var templateId = _pcr.PublishedContent.TemplateId; // This code was moved to GetTemplateModel to allow the same functionality on a failed altTemplate (U4-8550) // The only change is a diffent logger prefix and null will be set to _pcr.TemplateModel if the templateId is <= 0 // rather than no set taking place _pcr.TemplateModel = GetTemplateModel(_pcr.PublishedContent.TemplateId); } - else - { - // we have an alternate template specified. lookup the template with that alias - // this means the we override any template that a content lookup might have set - // so /path/to/page/template1?altTemplate=template2 will use template2 + else + { + // we have an alternate template specified. lookup the template with that alias + // this means the we override any template that a content lookup might have set + // so /path/to/page/template1?altTemplate=template2 will use template2 - // ignore if the alias does not match - just trace + // ignore if the alias does not match - just trace - if (_pcr.HasTemplate) - ProfilingLogger.Logger.Debug("{0}Has a template already, but also an alternate template.", () => tracePrefix); - ProfilingLogger.Logger.Debug("{0}Look for alternate template alias=\"{1}\"", () => tracePrefix, () => altTemplate); + if (_pcr.HasTemplate) + ProfilingLogger.Logger.Debug("{0}Has a template already, but also an alternate template.", () => tracePrefix); + ProfilingLogger.Logger.Debug("{0}Look for alternate template alias=\"{1}\"", () => tracePrefix, () => altTemplate); if (_pcr.PublishedContent.IsAllowedTemplate(altTemplate)) { @@ -705,26 +728,26 @@ namespace Umbraco.Web.Routing LogHelper.Warn("{0}Configuration settings prevent template \"{1}\" from showing for node \"{2}\"", () => tracePrefix, () => altTemplate, () => _pcr.PublishedContent.Id); _pcr.TemplateModel = GetTemplateModel(_pcr.PublishedContent.TemplateId); } - } + } - if (_pcr.HasTemplate == false) - { - ProfilingLogger.Logger.Debug("{0}No template was found.", () => tracePrefix); + if (_pcr.HasTemplate == false) + { + ProfilingLogger.Logger.Debug("{0}No template was found.", () => tracePrefix); - // initial idea was: if we're not already 404 and UmbracoSettings.HandleMissingTemplateAs404 is true - // then reset _pcr.Document to null to force a 404. - // - // but: because we want to let MVC hijack routes even though no template is defined, we decide that - // a missing template is OK but the request will then be forwarded to MVC, which will need to take - // care of everything. - // - // so, don't set _pcr.Document to null here - } - else - { - ProfilingLogger.Logger.Debug("{0}Running with template id={1} alias=\"{2}\"", () => tracePrefix, () => _pcr.TemplateModel.Id, () => _pcr.TemplateModel.Alias); - } - } + // initial idea was: if we're not already 404 and UmbracoSettings.HandleMissingTemplateAs404 is true + // then reset _pcr.Document to null to force a 404. + // + // but: because we want to let MVC hijack routes even though no template is defined, we decide that + // a missing template is OK but the request will then be forwarded to MVC, which will need to take + // care of everything. + // + // so, don't set _pcr.Document to null here + } + else + { + ProfilingLogger.Logger.Debug("{0}Running with template id={1} alias=\"{2}\"", () => tracePrefix, () => _pcr.TemplateModel.Id, () => _pcr.TemplateModel.Alias); + } + } private ITemplate GetTemplateModel(int templateId) { @@ -751,32 +774,32 @@ namespace Umbraco.Web.Routing /// /// As per legacy, if the redirect does not work, we just ignore it. private void FollowExternalRedirect() - { - if (_pcr.HasPublishedContent == false) return; + { + if (_pcr.HasPublishedContent == false) return; - // don't try to find a redirect if the property doesn't exist + // don't try to find a redirect if the property doesn't exist if (_pcr.PublishedContent.HasProperty(Constants.Conventions.Content.Redirect) == false) - return; - - var redirectId = _pcr.PublishedContent.GetPropertyValue(Constants.Conventions.Content.Redirect, -1); + return; - var redirectUrl = "#"; - if (redirectId > 0) - { - redirectUrl = _routingContext.UrlProvider.GetUrl(redirectId); - } - else - { + var redirectId = _pcr.PublishedContent.GetPropertyValue(Constants.Conventions.Content.Redirect, -1); + + var redirectUrl = "#"; + if (redirectId > 0) + { + redirectUrl = _routingContext.UrlProvider.GetUrl(redirectId); + } + else + { // might be a UDI instead of an int Id - var redirectUdi = _pcr.PublishedContent.GetPropertyValue(Constants.Conventions.Content.Redirect); - if (redirectUdi != null) - redirectUrl = _routingContext.UrlProvider.GetUrl(redirectUdi.Guid); - } - if (redirectUrl != "#") - { - _pcr.SetRedirect(redirectUrl); - } - } - #endregion - } + var redirectUdi = _pcr.PublishedContent.GetPropertyValue(Constants.Conventions.Content.Redirect); + if (redirectUdi != null) + redirectUrl = _routingContext.UrlProvider.GetUrl(redirectUdi.Guid); + } + if (redirectUrl != "#") + { + _pcr.SetRedirect(redirectUrl); + } + } + #endregion + } } From 561b359a721ef002e98c2beb48d374ad683736e1 Mon Sep 17 00:00:00 2001 From: Stephan Date: Mon, 14 Jan 2019 08:53:04 +0100 Subject: [PATCH 335/469] Name change --- .../{TargetedServiceProvider.cs => TargetedServiceFactory.cs} | 4 ++-- src/Umbraco.Core/IO/SupportingFileSystems.cs | 4 ++-- src/Umbraco.Core/Umbraco.Core.csproj | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) rename src/Umbraco.Core/Composing/{TargetedServiceProvider.cs => TargetedServiceFactory.cs} (76%) diff --git a/src/Umbraco.Core/Composing/TargetedServiceProvider.cs b/src/Umbraco.Core/Composing/TargetedServiceFactory.cs similarity index 76% rename from src/Umbraco.Core/Composing/TargetedServiceProvider.cs rename to src/Umbraco.Core/Composing/TargetedServiceFactory.cs index 3f88e1bc28..53022c0043 100644 --- a/src/Umbraco.Core/Composing/TargetedServiceProvider.cs +++ b/src/Umbraco.Core/Composing/TargetedServiceFactory.cs @@ -4,11 +4,11 @@ /// Provides a base class for targeted service factories. /// /// - public abstract class TargetedServiceProvider + public abstract class TargetedServiceFactory { private readonly IFactory _factory; - protected TargetedServiceProvider(IFactory factory) + protected TargetedServiceFactory(IFactory factory) { _factory = factory; } diff --git a/src/Umbraco.Core/IO/SupportingFileSystems.cs b/src/Umbraco.Core/IO/SupportingFileSystems.cs index c13ae203ee..43ac2ba85a 100644 --- a/src/Umbraco.Core/IO/SupportingFileSystems.cs +++ b/src/Umbraco.Core/IO/SupportingFileSystems.cs @@ -2,10 +2,10 @@ namespace Umbraco.Core.IO { - public class SupportingFileSystems : TargetedServiceProvider + public class SupportingFileSystems : TargetedServiceFactory { public SupportingFileSystems(IFactory factory) : base(factory) { } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index a592fd0f0e..609befd233 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -196,7 +196,7 @@ - + From b9430158cedb0bf5b1c0b93f543ec5383d8bec41 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Mon, 14 Jan 2019 09:25:59 +0100 Subject: [PATCH 336/469] Move member group picker property data store from NVarchar to NText (#3712) --- .../UpdateMemberGroupPickerData.cs | 36 +++++++++++++++++++ src/Umbraco.Core/Umbraco.Core.csproj | 1 + .../MemberGroupPickerPropertyEditor.cs | 2 +- 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFourteenZero/UpdateMemberGroupPickerData.cs diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFourteenZero/UpdateMemberGroupPickerData.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFourteenZero/UpdateMemberGroupPickerData.cs new file mode 100644 index 0000000000..2dbc69e58a --- /dev/null +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFourteenZero/UpdateMemberGroupPickerData.cs @@ -0,0 +1,36 @@ +using Umbraco.Core.Logging; +using Umbraco.Core.Persistence.SqlSyntax; + +namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenFourteenZero +{ + /// + /// Migrates member group picker properties from NVarchar to NText. See https://github.com/umbraco/Umbraco-CMS/issues/3268. + /// + [Migration("7.14.0", 1, Constants.System.UmbracoMigrationName)] + public class UpdateMemberGroupPickerData : MigrationBase + { + public UpdateMemberGroupPickerData(ISqlSyntaxProvider sqlSyntax, ILogger logger) : base(sqlSyntax, logger) + { + } + + public override void Up() + { + // move the data for all member group properties from the NVarchar to the NText column and clear the NVarchar column + Execute.Sql(@"UPDATE cmsPropertyData SET dataNtext = dataNvarchar, dataNvarchar = NULL + WHERE dataNtext IS NULL AND id IN ( + SELECT id FROM cmsPropertyData WHERE propertyTypeId in ( + SELECT id from cmsPropertyType where dataTypeID IN ( + SELECT nodeId FROM cmsDataType WHERE propertyEditorAlias = 'Umbraco.MemberGroupPicker' + ) + ) + )"); + + // ensure that all exising member group properties are defined as NText + Execute.Sql("UPDATE cmsDataType SET dbType = 'Ntext' WHERE propertyEditorAlias = 'Umbraco.MemberGroupPicker'"); + } + + public override void Down() + { + } + } +} diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index c7393e524f..8ee29e777f 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -572,6 +572,7 @@ + diff --git a/src/Umbraco.Web/PropertyEditors/MemberGroupPickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/MemberGroupPickerPropertyEditor.cs index 433199c536..6d7dd9e344 100644 --- a/src/Umbraco.Web/PropertyEditors/MemberGroupPickerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/MemberGroupPickerPropertyEditor.cs @@ -8,7 +8,7 @@ using Umbraco.Core.PropertyEditors; namespace Umbraco.Web.PropertyEditors { - [PropertyEditor(Constants.PropertyEditors.MemberGroupPickerAlias, "Member Group Picker", "membergrouppicker", Group="People", Icon="icon-users")] + [PropertyEditor(Constants.PropertyEditors.MemberGroupPickerAlias, "Member Group Picker", PropertyEditorValueTypes.Text, "membergrouppicker", Group="People", Icon="icon-users")] public class MemberGroupPickerPropertyEditor : PropertyEditor { } From 2ce3249c5e99fc27656f2af84b014bec937ea412 Mon Sep 17 00:00:00 2001 From: Robert Date: Mon, 14 Jan 2019 13:23:00 +0100 Subject: [PATCH 337/469] Renaming variable to allow MNTP media selection --- .../src/common/services/tinymce.service.js | 2 +- .../linkpicker/linkpicker.controller.js | 2 +- .../mediapicker/mediapicker.controller.js | 24 +++++++++---------- .../prevalueeditors/imagepicker.controller.js | 2 +- .../grid/editors/media.controller.js | 2 +- .../markdowneditor.controller.js | 2 +- .../mediapicker/mediapicker.controller.js | 2 +- 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js b/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js index 3fc11f8225..97d939bac1 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js @@ -1316,7 +1316,7 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s startNodeId: userData.startMediaIds.length !== 1 ? -1 : userData.startMediaIds[0], startNodeIsVirtual: userData.startMediaIds.length !== 1, submit: function (model) { - self.insertMediaInEditor(args.editor, model.selectedImages[0]); + self.insertMediaInEditor(args.editor, model.selection[0]); editorService.close(); }, close: function () { diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/linkpicker/linkpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/linkpicker/linkpicker.controller.js index 81dfcfd5d3..4faa5fd03a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/linkpicker/linkpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/linkpicker/linkpicker.controller.js @@ -118,7 +118,7 @@ angular.module("umbraco").controller("Umbraco.Editors.LinkPickerController", startNodeId: userData.startMediaIds.length !== 1 ? -1 : userData.startMediaIds[0], startNodeIsVirtual: userData.startMediaIds.length !== 1, submit: function (model) { - var media = model.selectedImages[0]; + var media = model.selection[0]; $scope.model.target.id = media.id; $scope.model.target.udi = media.udi; diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/mediapicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/mediapicker.controller.js index a274c25287..7b3d13937f 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/mediapicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/mediapicker.controller.js @@ -41,7 +41,7 @@ angular.module("umbraco") $scope.maxFileSize = umbracoSettings.maxFileSize + "KB"; - $scope.model.selectedImages = []; + $scope.model.selection = []; $scope.acceptedMediatypes = []; mediaTypeHelper.getAllowedImagetypes($scope.startNodeId) @@ -145,7 +145,7 @@ angular.module("umbraco") $scope.gotoFolder = function(folder) { if (!$scope.multiPicker) { - deselectAllImages($scope.model.selectedImages); + deselectAllImages($scope.model.selection); } if (!folder) { @@ -212,19 +212,19 @@ angular.module("umbraco") function selectImage(image) { if (image.selected) { - for (var i = 0; $scope.model.selectedImages.length > i; i++) { - var imageInSelection = $scope.model.selectedImages[i]; + for (var i = 0; $scope.model.selection.length > i; i++) { + var imageInSelection = $scope.model.selection[i]; if (image.key === imageInSelection.key) { image.selected = false; - $scope.model.selectedImages.splice(i, 1); + $scope.model.selection.splice(i, 1); } } } else { if (!$scope.multiPicker) { - deselectAllImages($scope.model.selectedImages); + deselectAllImages($scope.model.selection); } image.selected = true; - $scope.model.selectedImages.push(image); + $scope.model.selection.push(image); } } @@ -238,7 +238,7 @@ angular.module("umbraco") $scope.onUploadComplete = function(files) { $scope.gotoFolder($scope.currentFolder).then(function() { - if (files.length === 1 && $scope.model.selectedImages.length === 0) { + if (files.length === 1 && $scope.model.selection.length === 0) { var image = $scope.images[$scope.images.length - 1]; $scope.target = image; $scope.target.url = mediaHelper.resolveFile(image); @@ -275,7 +275,7 @@ angular.module("umbraco") $scope.mediaPickerDetailsOverlay.show = true; $scope.mediaPickerDetailsOverlay.submit = function(model) { - $scope.model.selectedImages.push($scope.target); + $scope.model.selection.push($scope.target); $scope.model.submit($scope.model); $scope.mediaPickerDetailsOverlay.show = false; @@ -384,11 +384,11 @@ angular.module("umbraco") var folderImage = $scope.images[folderImageIndex]; var imageIsSelected = false; - if ($scope.model && angular.isArray($scope.model.selectedImages)) { + if ($scope.model && angular.isArray($scope.model.selection)) { for (var selectedImageIndex = 0; - selectedImageIndex < $scope.model.selectedImages.length; + selectedImageIndex < $scope.model.selection.length; selectedImageIndex++) { - var selectedImage = $scope.model.selectedImages[selectedImageIndex]; + var selectedImage = $scope.model.selection[selectedImageIndex]; if (folderImage.key === selectedImage.key) { imageIsSelected = true; diff --git a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/imagepicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/imagepicker.controller.js index 6e7071a7e4..fc3da3510e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/imagepicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/imagepicker.controller.js @@ -7,7 +7,7 @@ function imageFilePickerController($scope) { onlyImages: true, show: true, submit: function (model) { - $scope.model.value = model.selectedImages[0].image; + $scope.model.value = model.selection[0].image; $scope.mediaPickerOverlay.show = false; $scope.mediaPickerOverlay = null; }, diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/editors/media.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/editors/media.controller.js index c240d6b37d..e267133cf4 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/editors/media.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/editors/media.controller.js @@ -27,7 +27,7 @@ angular.module("umbraco") disableFolderSelect: true, onlyImages: true, submit: function(model) { - var selectedImage = model.selectedImages[0]; + var selectedImage = model.selection[0]; $scope.control.value = { focalPoint: selectedImage.focalPoint, diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/markdowneditor/markdowneditor.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/markdowneditor/markdowneditor.controller.js index b3c014f54a..67a5630909 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/markdowneditor/markdowneditor.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/markdowneditor/markdowneditor.controller.js @@ -16,7 +16,7 @@ function MarkdownEditorController($scope, $element, assetsService, editorService var mediaPicker = { disableFolderSelect: true, submit: function(model) { - var selectedImagePath = model.selectedImages[0].image; + var selectedImagePath = model.selection[0].image; callback(selectedImagePath); editorService.close(); }, diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js index 361354c524..bac8eb903a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js @@ -176,7 +176,7 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl editorService.close(); - _.each(model.selectedImages, function (media, i) { + _.each(model.selection, function (media, i) { // if there is no thumbnail, try getting one if the media is not a placeholder item if (!media.thumbnail && media.id && media.metaData) { media.thumbnail = mediaHelper.resolveFileFromEntity(media, true); From 1ac8bbc570ab4a3a9d7f5ee24c66f0ad8a5dee85 Mon Sep 17 00:00:00 2001 From: Robert Date: Mon, 14 Jan 2019 13:23:57 +0100 Subject: [PATCH 338/469] Fixes MNTP member selection tree --- .../propertyeditors/contentpicker/contentpicker.controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js index e084d7116a..b72d81f16d 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js @@ -222,7 +222,7 @@ function contentPickerController($scope, entityResource, editorState, iconHelper editorService.mediaPicker($scope.currentPicker); break; case "Member": - editorService.memberGroupPicker($scope.currentPicker); + editorService.treePicker($scope.currentPicker); break; default: From 8e4090fb84d40b8aa3efa3d45119b4c8e3fa9692 Mon Sep 17 00:00:00 2001 From: Robert Date: Mon, 14 Jan 2019 14:00:17 +0100 Subject: [PATCH 339/469] Added proper memberPicker in the editorService --- .../src/common/services/editor.service.js | 26 ++++++++++++++++++- .../contentpicker/contentpicker.controller.js | 2 +- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js b/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js index 0d6432b01f..6cdb8fd0f3 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js @@ -748,6 +748,29 @@ When building a custom infinite editor view you can use the same components as a open(editor); } + /** + * @ngdoc method + * @name umbraco.services.editorService#memberPicker + * @methodOf umbraco.services.editorService + * + * @description + * Opens a member picker in infinite editing, the submit callback returns an array of selected items + * + * @param {Object} editor rendering options + * @param {Boolean} editor.multiPicker Pick one or multiple items + * @param {Function} editor.submit Callback function when the submit button is clicked. Returns the editor model object + * @param {Function} editor.close Callback function when the close button is clicked. + * + * @returns {Object} editor object + */ + function memberPicker(editor) { + editor.view = "views/common/infiniteeditors/treepicker/treepicker.html"; + editor.size = "small"; + editor.section = "member"; + editor.treeAlias = "member"; + open(editor); + } + /////////////////////// /** @@ -824,7 +847,8 @@ When building a custom infinite editor view you can use the same components as a userPicker: userPicker, itemPicker: itemPicker, macroPicker: macroPicker, - memberGroupPicker: memberGroupPicker + memberGroupPicker: memberGroupPicker, + memberPicker: memberPicker }; return service; diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js index b72d81f16d..37a97e928c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js @@ -222,7 +222,7 @@ function contentPickerController($scope, entityResource, editorState, iconHelper editorService.mediaPicker($scope.currentPicker); break; case "Member": - editorService.treePicker($scope.currentPicker); + editorService.memberPicker($scope.currentPicker); break; default: From a68b19f1ee2bbd58975a14a91533b5c7f5c9daf9 Mon Sep 17 00:00:00 2001 From: Stephan Date: Mon, 14 Jan 2019 14:28:19 +0100 Subject: [PATCH 340/469] More composition / filesystems fixes --- src/Umbraco.Core/Components/Composition.cs | 94 +++++++++++-------- .../Composing/CompositionExtensions.cs | 2 +- src/Umbraco.Core/Composing/IFactory.cs | 7 -- src/Umbraco.Core/Composing/IRegister.cs | 45 ++++----- .../LightInject/LightInjectContainer.cs | 65 +++++-------- .../MixedLightInjectScopeManagerProvider.cs | 3 + .../Composing/RegisterExtensions.cs | 6 +- src/Umbraco.Core/Configuration/Configs.cs | 2 +- .../Composing/ContainerConformingTests.cs | 8 +- 9 files changed, 115 insertions(+), 117 deletions(-) diff --git a/src/Umbraco.Core/Components/Composition.cs b/src/Umbraco.Core/Components/Composition.cs index 6cd8c8e5f0..6df86d793f 100644 --- a/src/Umbraco.Core/Components/Composition.cs +++ b/src/Umbraco.Core/Components/Composition.cs @@ -81,29 +81,34 @@ namespace Umbraco.Core.Components public void Register(Type serviceType, Type implementingType, Lifetime lifetime = Lifetime.Transient) => _register.Register(serviceType, implementingType, lifetime); - /// - public void RegisterFor(Type implementingType, Lifetime lifetime = Lifetime.Transient) - where TService : class - => _register.RegisterFor(implementingType, lifetime); - /// public void Register(Func factory, Lifetime lifetime = Lifetime.Transient) where TService : class => _register.Register(factory, lifetime); + /// + public void Register(Type serviceType, object instance) + => _register.Register(serviceType, instance); + + /// + public void RegisterFor(Lifetime lifetime = Lifetime.Transient) + where TService : class + => _register.RegisterFor(lifetime); + + /// + public void RegisterFor(Type implementingType, Lifetime lifetime = Lifetime.Transient) + where TService : class + => _register.RegisterFor(implementingType, lifetime); + /// public void RegisterFor(Func factory, Lifetime lifetime = Lifetime.Transient) where TService : class => _register.RegisterFor(factory, lifetime); /// - public void RegisterInstance(Type serviceType, object instance) - => _register.RegisterInstance(serviceType, instance); - - /// - public void RegisterInstanceFor(TService instance) + public void RegisterFor(TService instance) where TService : class - => _register.RegisterInstanceFor(instance); + => _register.RegisterFor(instance); /// public void RegisterAuto(Type serviceBaseType) @@ -154,37 +159,21 @@ namespace Umbraco.Core.Components => serviceType.FullName + "::" + targetType.FullName; /// - /// Registers a unique service. + /// Registers a unique service as its own implementation. + /// + /// Unique services have one single implementation, and a Singleton lifetime. + public void RegisterUnique(Type serviceType) + => _uniques[GetUniqueName(serviceType)] = register => register.Register(serviceType, Lifetime.Singleton); + + /// + /// Registers a unique service with an implementation type. /// /// Unique services have one single implementation, and a Singleton lifetime. public void RegisterUnique(Type serviceType, Type implementingType) => _uniques[GetUniqueName(serviceType)] = register => register.Register(serviceType, implementingType, Lifetime.Singleton); /// - /// Registers a unique service, for a target. - /// - /// Unique services have one single implementation, and a Singleton lifetime. - public void RegisterUniqueFor(Type implementingType) - where TService : class - => _uniques[GetUniqueName()] = register => register.RegisterFor(implementingType, Lifetime.Singleton); - - /// - /// Registers a unique service. - /// - /// Unique services have one single implementation, and a Singleton lifetime. - public void RegisterUniqueInstance(Type serviceType, object instance) - => _uniques[GetUniqueName(serviceType)] = register => register.RegisterInstance(serviceType, instance); - - /// - /// Registers a unique service, for a target. - /// - /// Unique services have one single implementation, and a Singleton lifetime. - public void RegisterUniqueInstanceFor(TService instance) - where TService : class - => _uniques[GetUniqueName()] = register => register.RegisterInstanceFor(instance); - - /// - /// Registers a unique service. + /// Registers a unique service with an implementation factory. /// /// Unique services have one single implementation, and a Singleton lifetime. public void RegisterUnique(Func factory) @@ -192,13 +181,44 @@ namespace Umbraco.Core.Components => _uniques[GetUniqueName()] = register => register.Register(factory, Lifetime.Singleton); /// - /// Registers a unique service, for a target. + /// Registers a unique service with an implementing instance. + /// + /// Unique services have one single implementation, and a Singleton lifetime. + public void RegisterUnique(Type serviceType, object instance) + => _uniques[GetUniqueName(serviceType)] = register => register.Register(serviceType, instance); + + /// + /// Registers a unique service for a target, as its own implementation. + /// + /// Unique services have one single implementation, and a Singleton lifetime. + public void RegisterUniqueFor() + where TService : class + => _uniques[GetUniqueName()] = register => register.RegisterFor(Lifetime.Singleton); + + /// + /// Registers a unique service for a target, with an implementing type. + /// + /// Unique services have one single implementation, and a Singleton lifetime. + public void RegisterUniqueFor(Type implementingType) + where TService : class + => _uniques[GetUniqueName()] = register => register.RegisterFor(implementingType, Lifetime.Singleton); + + /// + /// Registers a unique service for a target, with an implementation factory. /// /// Unique services have one single implementation, and a Singleton lifetime. public void RegisterUniqueFor(Func factory) where TService : class => _uniques[GetUniqueName()] = register => register.RegisterFor(factory, Lifetime.Singleton); + /// + /// Registers a unique service for a target, with an implementing instance. + /// + /// Unique services have one single implementation, and a Singleton lifetime. + public void RegisterUniqueFor(TService instance) + where TService : class + => _uniques[GetUniqueName()] = register => register.RegisterFor(instance); + #endregion #region Collection Builders diff --git a/src/Umbraco.Core/Composing/CompositionExtensions.cs b/src/Umbraco.Core/Composing/CompositionExtensions.cs index ac9a5d6409..2307d757c9 100644 --- a/src/Umbraco.Core/Composing/CompositionExtensions.cs +++ b/src/Umbraco.Core/Composing/CompositionExtensions.cs @@ -62,7 +62,7 @@ namespace Umbraco.Core.Composing /// Registers a unique service with an implementing instance. ///
    public static void RegisterUnique(this Composition composition, TService instance) - => composition.RegisterUniqueInstance(typeof(TService), instance); + => composition.RegisterUnique(typeof(TService), instance); #endregion } diff --git a/src/Umbraco.Core/Composing/IFactory.cs b/src/Umbraco.Core/Composing/IFactory.cs index 20fbe33737..768b9207a3 100644 --- a/src/Umbraco.Core/Composing/IFactory.cs +++ b/src/Umbraco.Core/Composing/IFactory.cs @@ -3,13 +3,6 @@ using System.Collections.Generic; namespace Umbraco.Core.Composing { - // Implementing: - // - // The factory - // - always picks the constructor with the most parameters - // - supports Lazy parameters (and prefers them over non-Lazy) in constructors - // - what happens with 'releasing' is unclear - /// /// Defines a service factory for Umbraco. /// diff --git a/src/Umbraco.Core/Composing/IRegister.cs b/src/Umbraco.Core/Composing/IRegister.cs index d145df8790..3e6aed67ee 100644 --- a/src/Umbraco.Core/Composing/IRegister.cs +++ b/src/Umbraco.Core/Composing/IRegister.cs @@ -2,17 +2,6 @@ namespace Umbraco.Core.Composing { - // Implementing: - // - // The register - // - supports registering a service, even after some instances of other services have been created - // - supports re-registering a service, as long as no instance of that service has been created - // - throws when re-registering a service, and an instance of that service has been created - // - // - registers only one implementation of a nameless service, re-registering replaces the previous - // registration - names are required to register multiple implementations - and getting an - // IEnumerable of the service, nameless, returns them all - /// /// Defines a service register for Umbraco. /// @@ -33,12 +22,6 @@ namespace Umbraco.Core.Composing /// void Register(Type serviceType, Type implementingType, Lifetime lifetime = Lifetime.Transient); - /// - /// Registers a service with an implementation type, for a target. - /// - void RegisterFor(Type implementingType, Lifetime lifetime = Lifetime.Transient) - where TService : class; - /// /// Registers a service with an implementation factory. /// @@ -46,20 +29,32 @@ namespace Umbraco.Core.Composing where TService : class; /// - /// Registers a service with an implementation factory, for a target. + /// Registers a service with an implementing instance. + /// + void Register(Type serviceType, object instance); + + /// + /// Registers a service for a target, as its own implementation. + /// + void RegisterFor(Lifetime lifetime = Lifetime.Transient) + where TService : class; + + /// + /// Registers a service for a target, with an implementation type. + /// + void RegisterFor(Type implementingType, Lifetime lifetime = Lifetime.Transient) + where TService : class; + + /// + /// Registers a service for a target, with an implementation factory. /// void RegisterFor(Func factory, Lifetime lifetime = Lifetime.Transient) where TService : class; /// - /// Registers a service with an implementing instance. + /// Registers a service for a target, with an implementing instance. /// - void RegisterInstance(Type serviceType, object instance); - - /// - /// Registers a service with an implementing instance, for a target. - /// - void RegisterInstanceFor(TService instance) + void RegisterFor(TService instance) where TService : class; /// diff --git a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs index 4ccc0ba838..d8a554ee8c 100644 --- a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs +++ b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs @@ -145,9 +145,7 @@ namespace Umbraco.Core.Composing.LightInject /// public void Register(Type serviceType, Lifetime lifetime = Lifetime.Transient) - { - Container.Register(serviceType, GetLifetime(lifetime)); - } + => Container.Register(serviceType, GetLifetime(lifetime)); /// public void Register(Type serviceType, Type implementingType, Lifetime lifetime = Lifetime.Transient) @@ -167,13 +165,6 @@ namespace Umbraco.Core.Composing.LightInject } } - /// - public void RegisterFor(Type implementingType, Lifetime lifetime = Lifetime.Transient) - where TService : class - { - Container.Register(typeof(TService), implementingType, GetTargetedServiceName(), GetLifetime(lifetime)); - } - /// public void Register(Func factory, Lifetime lifetime = Lifetime.Transient) where TService : class @@ -181,13 +172,36 @@ namespace Umbraco.Core.Composing.LightInject Container.Register(f => factory(this), GetLifetime(lifetime)); } + /// + public void Register(Type serviceType, object instance) + => Container.RegisterInstance(serviceType, instance); + + /// + public void RegisterFor(Lifetime lifetime = Lifetime.Transient) + where TService : class + => RegisterFor(typeof(TService), lifetime); + + /// + public void RegisterFor(Type implementingType, Lifetime lifetime = Lifetime.Transient) + where TService : class + { + // note that there can only be one implementation or instance registered "for" a service + Container.Register(typeof(TService), implementingType, GetTargetedServiceName(), GetLifetime(lifetime)); + } + /// public void RegisterFor(Func factory, Lifetime lifetime = Lifetime.Transient) where TService : class { + // note that there can only be one implementation or instance registered "for" a service Container.Register(f => factory(this), GetTargetedServiceName(), GetLifetime(lifetime)); } + /// + public void RegisterFor(TService instance) + where TService : class + => Container.RegisterInstance(typeof(TService), instance, GetTargetedServiceName()); + private ILifetime GetLifetime(Lifetime lifetime) { switch (lifetime) @@ -205,15 +219,6 @@ namespace Umbraco.Core.Composing.LightInject } } - /// - public void RegisterInstance(Type serviceType, object instance) - => Container.RegisterInstance(serviceType, instance); - - /// - public void RegisterInstanceFor(TService instance) - where TService : class - => Container.RegisterInstance(typeof(TService), instance, GetTargetedServiceName()); - /// public void RegisterAuto(Type serviceBaseType) { @@ -226,17 +231,6 @@ namespace Umbraco.Core.Composing.LightInject }, null); } - // was the Light-Inject specific way of dealing with args, but we've replaced it with our own - // beware! does NOT work on singletons, see https://github.com/seesharper/LightInject/issues/294 - // - ///// - //public void RegisterConstructorDependency(Func factory) - // => Container.RegisterConstructorDependency((f, x) => factory(this, x)); - // - ///// - //public void RegisterConstructorDependency(Func factory) - // => Container.RegisterConstructorDependency((f, x, a) => factory(this, x, a)); - #endregion #region Control @@ -259,21 +253,14 @@ namespace Umbraco.Core.Composing.LightInject private class AssemblyScanner : IAssemblyScanner { - //private readonly IAssemblyScanner _scanner; - - //public AssemblyScanner(IAssemblyScanner scanner) - //{ - // _scanner = scanner; - //} - public void Scan(Assembly assembly, IServiceRegistry serviceRegistry, Func lifetime, Func shouldRegister, Func serviceNameProvider) { - // nothing - we *could* scan non-Umbraco assemblies, though + // nothing - we don't want LightInject to scan } public void Scan(Assembly assembly, IServiceRegistry serviceRegistry) { - // nothing - we *could* scan non-Umbraco assemblies, though + // nothing - we don't want LightInject to scan } } diff --git a/src/Umbraco.Core/Composing/LightInject/MixedLightInjectScopeManagerProvider.cs b/src/Umbraco.Core/Composing/LightInject/MixedLightInjectScopeManagerProvider.cs index 470079c6c0..897c58dd43 100644 --- a/src/Umbraco.Core/Composing/LightInject/MixedLightInjectScopeManagerProvider.cs +++ b/src/Umbraco.Core/Composing/LightInject/MixedLightInjectScopeManagerProvider.cs @@ -13,6 +13,9 @@ namespace Umbraco.Core.Composing.LightInject // of PerWebRequestScopeManagerProvider - but all delegates see is the mixed one - and therefore // they can transition without issues. // + // The PerWebRequestScopeManager maintains the scope in HttpContext and LightInject registers a + // module (PreApplicationStartMethod) which disposes it on EndRequest + // // the mixed provider is installed in container.ConfigureUmbracoCore() and then, // when doing eg container.EnableMvc() or anything that does container.EnablePerWebRequestScope() // we need to take great care to preserve the mixed scope manager provider! diff --git a/src/Umbraco.Core/Composing/RegisterExtensions.cs b/src/Umbraco.Core/Composing/RegisterExtensions.cs index 9afa41e4b3..d1eacc0c0f 100644 --- a/src/Umbraco.Core/Composing/RegisterExtensions.cs +++ b/src/Umbraco.Core/Composing/RegisterExtensions.cs @@ -14,7 +14,7 @@ /// /// Registers a service with an implementation type, for a target. /// - public static void RegisterFor(this IRegister register, Lifetime lifetime = Lifetime.Transient) + public static void RegisterFor(this IRegister register, Lifetime lifetime = Lifetime.Transient) where TService : class => register.RegisterFor(typeof(TImplementing), lifetime); @@ -28,9 +28,9 @@ /// /// Registers a service with an implementing instance. /// - public static void RegisterInstance(this IRegister register, TService instance) + public static void Register(this IRegister register, TService instance) where TService : class - => register.RegisterInstance(typeof(TService), instance); + => register.Register(typeof(TService), instance); /// /// Registers a base type for auto-registration. diff --git a/src/Umbraco.Core/Configuration/Configs.cs b/src/Umbraco.Core/Configuration/Configs.cs index 3dbbe5d4ff..51e1a327a0 100644 --- a/src/Umbraco.Core/Configuration/Configs.cs +++ b/src/Umbraco.Core/Configuration/Configs.cs @@ -100,7 +100,7 @@ namespace Umbraco.Core.Configuration if (_registerings == null) throw new InvalidOperationException("Configurations have already been registered."); - register.RegisterInstance(this); + register.Register(this); foreach (var registering in _registerings.Values) registering(register); diff --git a/src/Umbraco.Tests/Composing/ContainerConformingTests.cs b/src/Umbraco.Tests/Composing/ContainerConformingTests.cs index 9585c98cb2..21ea961636 100644 --- a/src/Umbraco.Tests/Composing/ContainerConformingTests.cs +++ b/src/Umbraco.Tests/Composing/ContainerConformingTests.cs @@ -194,8 +194,8 @@ namespace Umbraco.Tests.Composing var register = GetRegister(); // define two instances - register.RegisterInstance(typeof(Thing1), new Thing1()); - register.RegisterInstance(typeof(Thing1), new Thing2()); + register.Register(typeof(Thing1), new Thing1()); + register.Register(typeof(Thing1), new Thing2()); var factory = register.CreateFactory(); @@ -212,8 +212,8 @@ namespace Umbraco.Tests.Composing var register = GetRegister(); // define two instances - register.RegisterInstance(typeof(IThing), new Thing1()); - register.RegisterInstance(typeof(IThing), new Thing2()); + register.Register(typeof(IThing), new Thing1()); + register.Register(typeof(IThing), new Thing2()); var factory = register.CreateFactory(); From e2fe1c82608244e3bb77596079f7884bff8beaaf Mon Sep 17 00:00:00 2001 From: Stephan Date: Mon, 14 Jan 2019 15:01:24 +0100 Subject: [PATCH 341/469] Refactor IValueConnector for Deploy --- src/Umbraco.Core/Deploy/IValueConnector.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Umbraco.Core/Deploy/IValueConnector.cs b/src/Umbraco.Core/Deploy/IValueConnector.cs index 35304e3fde..92589ab6cf 100644 --- a/src/Umbraco.Core/Deploy/IValueConnector.cs +++ b/src/Umbraco.Core/Deploy/IValueConnector.cs @@ -17,19 +17,19 @@ namespace Umbraco.Core.Deploy IEnumerable PropertyEditorAliases { get; } /// - /// Gets the deploy property corresponding to a content property. + /// Gets the deploy property value corresponding to a content property value, and gather dependencies. /// - /// The content property. + /// The content property value. /// The content dependencies. /// The deploy property value. - string GetValue(Property property, ICollection dependencies); + string ToArtifact(object value, ICollection dependencies); /// - /// Sets a content property value using a deploy property. + /// Gets the content property value corresponding to a deploy property value. /// - /// The content item. - /// The property alias. /// The deploy property value. - void SetValue(IContentBase content, string alias, string value); + /// The current content property value. + /// The content property value. + object FromArtifact(string value, object currentValue); } } From 9ba3f4769056ed9889a2662ea1083b4ac59d0d7a Mon Sep 17 00:00:00 2001 From: Stephan Date: Mon, 14 Jan 2019 15:55:18 +0100 Subject: [PATCH 342/469] Cleanup --- .../Components/CompositionExtensions.cs | 16 ++++++++++++++++ .../Composing/Composers/FileSystemsComposer.cs | 4 ++-- src/Umbraco.Core/Composing/IRegister.cs | 16 ++++++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Core/Components/CompositionExtensions.cs b/src/Umbraco.Core/Components/CompositionExtensions.cs index a4bc82cb4b..bb23e89b81 100644 --- a/src/Umbraco.Core/Components/CompositionExtensions.cs +++ b/src/Umbraco.Core/Components/CompositionExtensions.cs @@ -281,6 +281,22 @@ namespace Umbraco.Core.Components composition.RegisterUnique(_ => helper); } + /// + /// Sets the underlying media filesystem. + /// + /// A composition. + /// A filesystem factory. + public static void SetMediaFileSystem(this Composition composition, Func filesystemFactory) + => composition.RegisterUniqueFor(filesystemFactory); + + /// + /// Sets the underlying media filesystem. + /// + /// A composition. + /// A filesystem factory. + public static void SetMediaFileSystem(this Composition composition, Func filesystemFactory) + => composition.RegisterUniqueFor(_ => filesystemFactory()); + #endregion } } diff --git a/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs b/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs index ab4bd015de..4c598f27e4 100644 --- a/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs @@ -88,9 +88,9 @@ namespace Umbraco.Core.Composing.Composers composition.Register(factory => new SupportingFileSystems(factory), Lifetime.Singleton); // register the IFileSystem supporting the IMediaFileSystem - // this is the only thing that need to be overriden to change the supporting filesystem + // THIS IS THE ONLY THING THAT NEEDS TO CHANGE, IN ORDER TO REPLACE THE UNDERLYING FILESYSTEM // and, SupportingFileSystem.For() returns the underlying filesystem - composition.RegisterUniqueFor(_ => new PhysicalFileSystem("~/media")); + composition.SetMediaFileSystem(() => new PhysicalFileSystem("~/media")); return composition; } diff --git a/src/Umbraco.Core/Composing/IRegister.cs b/src/Umbraco.Core/Composing/IRegister.cs index 3e6aed67ee..cbf12f54a3 100644 --- a/src/Umbraco.Core/Composing/IRegister.cs +++ b/src/Umbraco.Core/Composing/IRegister.cs @@ -36,24 +36,40 @@ namespace Umbraco.Core.Composing /// /// Registers a service for a target, as its own implementation. /// + /// + /// There can only be one implementation or instanced registered for a service and target; + /// what happens if many are registered is not specified. + /// void RegisterFor(Lifetime lifetime = Lifetime.Transient) where TService : class; /// /// Registers a service for a target, with an implementation type. /// + /// + /// There can only be one implementation or instanced registered for a service and target; + /// what happens if many are registered is not specified. + /// void RegisterFor(Type implementingType, Lifetime lifetime = Lifetime.Transient) where TService : class; /// /// Registers a service for a target, with an implementation factory. /// + /// + /// There can only be one implementation or instanced registered for a service and target; + /// what happens if many are registered is not specified. + /// void RegisterFor(Func factory, Lifetime lifetime = Lifetime.Transient) where TService : class; /// /// Registers a service for a target, with an implementing instance. /// + /// + /// There can only be one implementation or instanced registered for a service and target; + /// what happens if many are registered is not specified. + /// void RegisterFor(TService instance) where TService : class; From 4ad2505bea438f3e0d35c02cce350d7d58c13d93 Mon Sep 17 00:00:00 2001 From: Stephan Date: Mon, 14 Jan 2019 15:48:24 +0100 Subject: [PATCH 343/469] Identify element types --- .../Migrations/Upgrade/UmbracoPlan.cs | 1 + .../V_8_0_0/AddContentTypeIsElementColumn.cs | 15 ++++++++++ src/Umbraco.Core/Models/ContentTypeBase.cs | 10 +++++++ .../Models/ContentTypeBaseExtensions.cs | 3 +- src/Umbraco.Core/Models/IContentTypeBase.cs | 12 +++++++- .../PublishedContent/PublishedItemType.cs | 7 ++++- .../Persistence/Dtos/ContentTypeDto.cs | 4 +++ .../Factories/ContentTypeFactory.cs | 2 ++ .../Persistence/Mappers/ContentTypeMapper.cs | 1 + .../Persistence/Mappers/MediaTypeMapper.cs | 1 + .../Persistence/Mappers/MemberTypeMapper.cs | 1 + .../Implement/ContentTypeRepositoryBase.cs | 6 ++-- .../Services/EntityXmlSerializer.cs | 3 +- .../Services/Implement/PackagingService.cs | 4 +++ src/Umbraco.Core/Umbraco.Core.csproj | 1 + .../PublishedContent/PublishedContentTests.cs | 1 - .../Services/ContentTypeServiceTests.cs | 30 +++++++++++++++++++ .../ContentEditing/ContentItemDisplay.cs | 8 ++++- .../Models/Mapping/ContentMapperProfile.cs | 5 ++-- 19 files changed, 105 insertions(+), 10 deletions(-) create mode 100644 src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/AddContentTypeIsElementColumn.cs diff --git a/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs b/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs index b469c02a3c..9ec970f1fe 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs @@ -121,6 +121,7 @@ namespace Umbraco.Core.Migrations.Upgrade To("{648A2D5F-7467-48F8-B309-E99CEEE00E2A}"); // fixed version To("{C39BF2A7-1454-4047-BBFE-89E40F66ED63}"); To("{64EBCE53-E1F0-463A-B40B-E98EFCCA8AE2}"); + To("{0009109C-A0B8-4F3F-8FEB-C137BBDDA268}"); //FINAL diff --git a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/AddContentTypeIsElementColumn.cs b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/AddContentTypeIsElementColumn.cs new file mode 100644 index 0000000000..1df11a3e99 --- /dev/null +++ b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/AddContentTypeIsElementColumn.cs @@ -0,0 +1,15 @@ +using Umbraco.Core.Persistence.Dtos; + +namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0 +{ + public class AddContentTypeIsElementColumn : MigrationBase + { + public AddContentTypeIsElementColumn(IMigrationContext context) : base(context) + { } + + public override void Migrate() + { + AddColumn("isElement"); + } + } +} diff --git a/src/Umbraco.Core/Models/ContentTypeBase.cs b/src/Umbraco.Core/Models/ContentTypeBase.cs index 88b1179f6d..b6ea9f50a0 100644 --- a/src/Umbraco.Core/Models/ContentTypeBase.cs +++ b/src/Umbraco.Core/Models/ContentTypeBase.cs @@ -26,6 +26,7 @@ namespace Umbraco.Core.Models private string _thumbnail = "folder.png"; private bool _allowedAsRoot; // note: only one that's not 'pure element type' private bool _isContainer; + private bool _isElement; private PropertyGroupCollection _propertyGroups; private PropertyTypeCollection _noGroupPropertyTypes; private IEnumerable _allowedContentTypes; @@ -90,6 +91,7 @@ namespace Umbraco.Core.Models public readonly PropertyInfo IconSelector = ExpressionHelper.GetPropertyInfo(x => x.Icon); public readonly PropertyInfo ThumbnailSelector = ExpressionHelper.GetPropertyInfo(x => x.Thumbnail); public readonly PropertyInfo AllowedAsRootSelector = ExpressionHelper.GetPropertyInfo(x => x.AllowedAsRoot); + public readonly PropertyInfo IsElementSelector = ExpressionHelper.GetPropertyInfo(x => x.IsElement); public readonly PropertyInfo IsContainerSelector = ExpressionHelper.GetPropertyInfo(x => x.IsContainer); public readonly PropertyInfo AllowedContentTypesSelector = ExpressionHelper.GetPropertyInfo>(x => x.AllowedContentTypes); public readonly PropertyInfo PropertyGroupsSelector = ExpressionHelper.GetPropertyInfo(x => x.PropertyGroups); @@ -180,6 +182,14 @@ namespace Umbraco.Core.Models set => SetPropertyValueAndDetectChanges(value, ref _isContainer, Ps.Value.IsContainerSelector); } + /// + [DataMember] + public bool IsElement + { + get => _isElement; + set => SetPropertyValueAndDetectChanges(value, ref _isElement, Ps.Value.IsElementSelector); + } + /// /// Gets or sets a list of integer Ids for allowed ContentTypes /// diff --git a/src/Umbraco.Core/Models/ContentTypeBaseExtensions.cs b/src/Umbraco.Core/Models/ContentTypeBaseExtensions.cs index 8af48bb881..adbc3de54f 100644 --- a/src/Umbraco.Core/Models/ContentTypeBaseExtensions.cs +++ b/src/Umbraco.Core/Models/ContentTypeBaseExtensions.cs @@ -15,7 +15,8 @@ namespace Umbraco.Core.Models { var type = contentType.GetType(); var itemType = PublishedItemType.Unknown; - if (typeof(IContentType).IsAssignableFrom(type)) itemType = PublishedItemType.Content; + if (contentType.IsElement) itemType = PublishedItemType.Element; + else if (typeof(IContentType).IsAssignableFrom(type)) itemType = PublishedItemType.Content; else if (typeof(IMediaType).IsAssignableFrom(type)) itemType = PublishedItemType.Media; else if (typeof(IMemberType).IsAssignableFrom(type)) itemType = PublishedItemType.Member; return itemType; diff --git a/src/Umbraco.Core/Models/IContentTypeBase.cs b/src/Umbraco.Core/Models/IContentTypeBase.cs index a1d4aee02f..787e347b37 100644 --- a/src/Umbraco.Core/Models/IContentTypeBase.cs +++ b/src/Umbraco.Core/Models/IContentTypeBase.cs @@ -25,7 +25,7 @@ namespace Umbraco.Core.Models /// the icon (eg. icon-home) along with an optional CSS class name representing the /// color (eg. icon-blue). Put together, the value for this scenario would be /// icon-home color-blue. - /// + /// /// If a class name for the color isn't specified, the icon color will default to black. /// string Icon { get; set; } @@ -48,6 +48,16 @@ namespace Umbraco.Core.Models /// bool IsContainer { get; set; } + /// + /// Gets or sets a value indicating whether this content type is for an element. + /// + /// + /// By default a content type is for a true media, member or document, but + /// it can also be for an element, ie a subset that can for instance be used in + /// nested content. + /// + bool IsElement { get; set; } + /// /// Gets or sets the content variation of the content type. /// diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedItemType.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedItemType.cs index e55fe66945..42e9c9538d 100644 --- a/src/Umbraco.Core/Models/PublishedContent/PublishedItemType.cs +++ b/src/Umbraco.Core/Models/PublishedContent/PublishedItemType.cs @@ -4,13 +4,18 @@ /// The type of published element. /// /// Can be a simple element, or a document, a media, a member. - public enum PublishedItemType // fixme - need to rename to PublishedElementType but then conflicts? + public enum PublishedItemType { /// /// Unknown. /// Unknown = 0, + /// + /// An element. + /// + Element, + /// /// A document. /// diff --git a/src/Umbraco.Core/Persistence/Dtos/ContentTypeDto.cs b/src/Umbraco.Core/Persistence/Dtos/ContentTypeDto.cs index d930abc54c..4f3a67aa91 100644 --- a/src/Umbraco.Core/Persistence/Dtos/ContentTypeDto.cs +++ b/src/Umbraco.Core/Persistence/Dtos/ContentTypeDto.cs @@ -41,6 +41,10 @@ namespace Umbraco.Core.Persistence.Dtos [Constraint(Default = "0")] public bool IsContainer { get; set; } + [Column("isElement")] + [Constraint(Default = "0")] + public bool IsElement { get; set; } + [Column("allowAtRoot")] [Constraint(Default = "0")] public bool AllowAtRoot { get; set; } diff --git a/src/Umbraco.Core/Persistence/Factories/ContentTypeFactory.cs b/src/Umbraco.Core/Persistence/Factories/ContentTypeFactory.cs index 38a1aa2aab..7a04a6d0d9 100644 --- a/src/Umbraco.Core/Persistence/Factories/ContentTypeFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/ContentTypeFactory.cs @@ -107,6 +107,7 @@ namespace Umbraco.Core.Persistence.Factories entity.CreatorId = dto.NodeDto.UserId ?? Constants.Security.UnknownUserId; entity.AllowedAsRoot = dto.AllowAtRoot; entity.IsContainer = dto.IsContainer; + entity.IsElement = dto.IsElement; entity.Trashed = dto.NodeDto.Trashed; entity.Variations = (ContentVariation) dto.Variations; } @@ -132,6 +133,7 @@ namespace Umbraco.Core.Persistence.Factories NodeId = entity.Id, AllowAtRoot = entity.AllowedAsRoot, IsContainer = entity.IsContainer, + IsElement = entity.IsElement, Variations = (byte) entity.Variations, NodeDto = BuildNodeDto(entity, nodeObjectType) }; diff --git a/src/Umbraco.Core/Persistence/Mappers/ContentTypeMapper.cs b/src/Umbraco.Core/Persistence/Mappers/ContentTypeMapper.cs index c692a75474..a24963bace 100644 --- a/src/Umbraco.Core/Persistence/Mappers/ContentTypeMapper.cs +++ b/src/Umbraco.Core/Persistence/Mappers/ContentTypeMapper.cs @@ -35,6 +35,7 @@ namespace Umbraco.Core.Persistence.Mappers CacheMap(src => src.Description, dto => dto.Description); CacheMap(src => src.Icon, dto => dto.Icon); CacheMap(src => src.IsContainer, dto => dto.IsContainer); + CacheMap(src => src.IsElement, dto => dto.IsElement); CacheMap(src => src.Thumbnail, dto => dto.Thumbnail); } } diff --git a/src/Umbraco.Core/Persistence/Mappers/MediaTypeMapper.cs b/src/Umbraco.Core/Persistence/Mappers/MediaTypeMapper.cs index 3f5a6e24bc..6cf83bc7aa 100644 --- a/src/Umbraco.Core/Persistence/Mappers/MediaTypeMapper.cs +++ b/src/Umbraco.Core/Persistence/Mappers/MediaTypeMapper.cs @@ -35,6 +35,7 @@ namespace Umbraco.Core.Persistence.Mappers CacheMap(src => src.Description, dto => dto.Description); CacheMap(src => src.Icon, dto => dto.Icon); CacheMap(src => src.IsContainer, dto => dto.IsContainer); + CacheMap(src => src.IsElement, dto => dto.IsElement); CacheMap(src => src.Thumbnail, dto => dto.Thumbnail); } } diff --git a/src/Umbraco.Core/Persistence/Mappers/MemberTypeMapper.cs b/src/Umbraco.Core/Persistence/Mappers/MemberTypeMapper.cs index 28dc19171f..9a4e4ec040 100644 --- a/src/Umbraco.Core/Persistence/Mappers/MemberTypeMapper.cs +++ b/src/Umbraco.Core/Persistence/Mappers/MemberTypeMapper.cs @@ -35,6 +35,7 @@ namespace Umbraco.Core.Persistence.Mappers CacheMap(src => src.Description, dto => dto.Description); CacheMap(src => src.Icon, dto => dto.Icon); CacheMap(src => src.IsContainer, dto => dto.IsContainer); + CacheMap(src => src.IsElement, dto => dto.IsElement); CacheMap(src => src.Thumbnail, dto => dto.Thumbnail); } } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs index 662254d1ee..683df047f8 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs @@ -1283,7 +1283,7 @@ AND umbracoNode.id <> @id", if (db == null) throw new ArgumentNullException(nameof(db)); var sql = @"SELECT cmsContentType.pk as ctPk, cmsContentType.alias as ctAlias, cmsContentType.allowAtRoot as ctAllowAtRoot, cmsContentType.description as ctDesc, cmsContentType.variations as ctVariations, - cmsContentType.icon as ctIcon, cmsContentType.isContainer as ctIsContainer, cmsContentType.nodeId as ctId, cmsContentType.thumbnail as ctThumb, + cmsContentType.icon as ctIcon, cmsContentType.isContainer as ctIsContainer, cmsContentType.IsElement as ctIsElement, cmsContentType.nodeId as ctId, cmsContentType.thumbnail as ctThumb, AllowedTypes.AllowedId as ctaAllowedId, AllowedTypes.SortOrder as ctaSortOrder, AllowedTypes.alias as ctaAlias, ParentTypes.parentContentTypeId as chtParentId, ParentTypes.parentContentTypeKey as chtParentKey, umbracoNode.createDate as nCreateDate, umbracoNode." + sqlSyntax.GetQuotedColumnName("level") + @" as nLevel, umbracoNode.nodeObjectType as nObjectType, umbracoNode.nodeUser as nUser, @@ -1384,6 +1384,7 @@ AND umbracoNode.id <> @id", Description = currCt.ctDesc, Icon = currCt.ctIcon, IsContainer = currCt.ctIsContainer, + IsElement = currCt.ctIsElement, NodeId = currCt.ctId, PrimaryKey = currCt.ctPk, Thumbnail = currCt.ctThumb, @@ -1422,7 +1423,7 @@ AND umbracoNode.id <> @id", var sql = @"SELECT cmsDocumentType.IsDefault as dtIsDefault, cmsDocumentType.templateNodeId as dtTemplateId, cmsContentType.pk as ctPk, cmsContentType.alias as ctAlias, cmsContentType.allowAtRoot as ctAllowAtRoot, cmsContentType.description as ctDesc, cmsContentType.variations as ctVariations, - cmsContentType.icon as ctIcon, cmsContentType.isContainer as ctIsContainer, cmsContentType.nodeId as ctId, cmsContentType.thumbnail as ctThumb, + cmsContentType.icon as ctIcon, cmsContentType.isContainer as ctIsContainer, cmsContentType.IsElement as ctIsElement, cmsContentType.nodeId as ctId, cmsContentType.thumbnail as ctThumb, AllowedTypes.AllowedId as ctaAllowedId, AllowedTypes.SortOrder as ctaSortOrder, AllowedTypes.alias as ctaAlias, ParentTypes.parentContentTypeId as chtParentId,ParentTypes.parentContentTypeKey as chtParentKey, umbracoNode.createDate as nCreateDate, umbracoNode." + sqlSyntax.GetQuotedColumnName("level") + @" as nLevel, umbracoNode.nodeObjectType as nObjectType, umbracoNode.nodeUser as nUser, @@ -1559,6 +1560,7 @@ AND umbracoNode.id <> @id", Description = currCt.ctDesc, Icon = currCt.ctIcon, IsContainer = currCt.ctIsContainer, + IsElement = currCt.ctIsElement, NodeId = currCt.ctId, PrimaryKey = currCt.ctPk, Thumbnail = currCt.ctThumb, diff --git a/src/Umbraco.Core/Services/EntityXmlSerializer.cs b/src/Umbraco.Core/Services/EntityXmlSerializer.cs index d938e032a8..38d5471bb7 100644 --- a/src/Umbraco.Core/Services/EntityXmlSerializer.cs +++ b/src/Umbraco.Core/Services/EntityXmlSerializer.cs @@ -337,7 +337,8 @@ namespace Umbraco.Core.Services new XElement("Thumbnail", contentType.Thumbnail), new XElement("Description", contentType.Description), new XElement("AllowAtRoot", contentType.AllowedAsRoot.ToString()), - new XElement("IsListView", contentType.IsContainer.ToString())); + new XElement("IsListView", contentType.IsContainer.ToString()), + new XElement("IsElement", contentType.IsElement.ToString())); var masterContentType = contentType.ContentTypeComposition.FirstOrDefault(x => x.Id == contentType.ParentId); if(masterContentType != null) diff --git a/src/Umbraco.Core/Services/Implement/PackagingService.cs b/src/Umbraco.Core/Services/Implement/PackagingService.cs index 106d2b9f12..8f6c287cf1 100644 --- a/src/Umbraco.Core/Services/Implement/PackagingService.cs +++ b/src/Umbraco.Core/Services/Implement/PackagingService.cs @@ -578,6 +578,10 @@ namespace Umbraco.Core.Services.Implement if (isListView != null) contentType.IsContainer = isListView.Value.InvariantEquals("true"); + var isElement = infoElement.Element("IsElement"); + if (isListView != null) + contentType.IsElement = isElement.Value.InvariantEquals("true"); + //Name of the master corresponds to the parent and we need to ensure that the Parent Id is set var masterElement = infoElement.Element("Master"); if (masterElement != null) diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index a01bbf1746..33858c0f91 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -375,6 +375,7 @@ + diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs index 914956dce1..ab65ac82b1 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs @@ -233,7 +233,6 @@ namespace Umbraco.Tests.PublishedContent } [Test] - [Ignore("Fails as long as PublishedContentModel is internal.")] // fixme public void Is_Last_From_Where_Filter2() { var doc = GetNode(1173); diff --git a/src/Umbraco.Tests/Services/ContentTypeServiceTests.cs b/src/Umbraco.Tests/Services/ContentTypeServiceTests.cs index b1a8fa26a8..8dc8a2b45c 100644 --- a/src/Umbraco.Tests/Services/ContentTypeServiceTests.cs +++ b/src/Umbraco.Tests/Services/ContentTypeServiceTests.cs @@ -22,6 +22,36 @@ namespace Umbraco.Tests.Services [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest, PublishedRepositoryEvents = true)] public class ContentTypeServiceTests : TestWithSomeContentBase { + [Test] + public void CanSaveAndGetIsElement() + { + //create content type with a property type that varies by culture + IContentType contentType = MockedContentTypes.CreateBasicContentType(); + contentType.Variations = ContentVariation.Nothing; + var contentCollection = new PropertyTypeCollection(true); + contentCollection.Add(new PropertyType("test", ValueStorageType.Ntext) + { + Alias = "title", + Name = "Title", + Description = "", + Mandatory = false, + SortOrder = 1, + DataTypeId = -88, + Variations = ContentVariation.Nothing + }); + contentType.PropertyGroups.Add(new PropertyGroup(contentCollection) { Name = "Content", SortOrder = 1 }); + ServiceContext.ContentTypeService.Save(contentType); + + contentType = ServiceContext.ContentTypeService.Get(contentType.Id); + Assert.IsFalse(contentType.IsElement); + + contentType.IsElement = true; + ServiceContext.ContentTypeService.Save(contentType); + + contentType = ServiceContext.ContentTypeService.Get(contentType.Id); + Assert.IsTrue(contentType.IsElement); + } + [Test] public void Change_Content_Type_Variation_Clears_Redirects() { diff --git a/src/Umbraco.Web/Models/ContentEditing/ContentItemDisplay.cs b/src/Umbraco.Web/Models/ContentEditing/ContentItemDisplay.cs index 4908025351..80358bfc7a 100644 --- a/src/Umbraco.Web/Models/ContentEditing/ContentItemDisplay.cs +++ b/src/Umbraco.Web/Models/ContentEditing/ContentItemDisplay.cs @@ -86,6 +86,12 @@ namespace Umbraco.Web.Models.ContentEditing [DataMember(Name = "isContainer")] public bool IsContainer { get; set; } + /// + /// Indicates if the content is configured as an element + /// + [DataMember(Name = "isElement")] + public bool IsElement { get; set; } + /// /// Property indicating if this item is part of a list view parent /// @@ -117,7 +123,7 @@ namespace Umbraco.Web.Models.ContentEditing /// [DataMember(Name = "updateDate")] public DateTime UpdateDate { get; set; } - + [DataMember(Name = "template")] public string TemplateAlias { get; set; } diff --git a/src/Umbraco.Web/Models/Mapping/ContentMapperProfile.cs b/src/Umbraco.Web/Models/Mapping/ContentMapperProfile.cs index 6de3bdc02c..1caf81a1eb 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentMapperProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentMapperProfile.cs @@ -46,6 +46,7 @@ namespace Umbraco.Web.Models.Mapping .ForMember(dest => dest.ContentTypeAlias, opt => opt.MapFrom(src => src.ContentType.Alias)) .ForMember(dest => dest.ContentTypeName, opt => opt.MapFrom(src => src.ContentType.Name)) .ForMember(dest => dest.IsContainer, opt => opt.MapFrom(src => src.ContentType.IsContainer)) + .ForMember(dest => dest.IsElement, opt => opt.MapFrom(src => src.ContentType.IsElement)) .ForMember(dest => dest.IsBlueprint, opt => opt.MapFrom(src => src.Blueprint)) .ForMember(dest => dest.IsChildOfListView, opt => opt.ResolveUsing(childOfListViewResolver)) .ForMember(dest => dest.Trashed, opt => opt.MapFrom(src => src.Trashed)) @@ -59,7 +60,7 @@ namespace Umbraco.Web.Models.Mapping .ForMember(dest => dest.AllowedTemplates, opt => opt.MapFrom(content => content.ContentType.AllowedTemplates .Where(t => t.Alias.IsNullOrWhiteSpace() == false && t.Name.IsNullOrWhiteSpace() == false) - .ToDictionary(t => t.Alias, t => t.Name))) + .ToDictionary(t => t.Alias, t => t.Name))) .ForMember(dest => dest.AllowedActions, opt => opt.ResolveUsing(src => actionButtonsResolver.Resolve(src))) .ForMember(dest => dest.AdditionalData, opt => opt.Ignore()); @@ -140,5 +141,5 @@ namespace Umbraco.Web.Models.Mapping return source.CultureInfos.TryGetValue(culture, out var name) && !name.Name.IsNullOrWhiteSpace() ? name.Name : $"(({source.Name}))"; } } - } + } } From f7671ec9a7653082d432352a7801e5bedb621c5c Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Tue, 15 Jan 2019 08:39:43 +0100 Subject: [PATCH 344/469] Fixes #4071 - Error executing scheduled task - This instance has already started one or more requests. --- src/Umbraco.Web/Scheduling/ScheduledTasks.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web/Scheduling/ScheduledTasks.cs b/src/Umbraco.Web/Scheduling/ScheduledTasks.cs index 4278b82c34..7387bca000 100644 --- a/src/Umbraco.Web/Scheduling/ScheduledTasks.cs +++ b/src/Umbraco.Web/Scheduling/ScheduledTasks.cs @@ -63,10 +63,11 @@ namespace Umbraco.Web.Scheduling private async Task GetTaskByHttpAync(string url, CancellationToken token) { if (_httpClient == null) - _httpClient = new HttpClient(); - - if (Uri.TryCreate(_appContext.UmbracoApplicationUrl, UriKind.Absolute, out var baseUri)) - _httpClient.BaseAddress = baseUri; + { + _httpClient = Uri.TryCreate(_appContext.UmbracoApplicationUrl, UriKind.Absolute, out var baseUri) + ? new HttpClient { BaseAddress = baseUri } + : new HttpClient(); + } var request = new HttpRequestMessage(HttpMethod.Get, url); From 64469fcb5c72074cb9f410687ca90329db63d6b1 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Tue, 15 Jan 2019 10:03:10 +0100 Subject: [PATCH 345/469] Force select the content app for both views when opening split view --- .../content/umbvariantcontenteditors.directive.js | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbvariantcontenteditors.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbvariantcontenteditors.directive.js index 1987c897f0..e413701a26 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbvariantcontenteditors.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbvariantcontenteditors.directive.js @@ -215,9 +215,15 @@ * @param {any} selectedVariant */ function openSplitView(selectedVariant) { - var selectedCulture = selectedVariant.language.culture; + //Find the whole variant model based on the culture that was chosen + var variant = _.find(vm.content.variants, function (v) { + return v.language.culture === selectedCulture; + }); + + insertVariantEditor(vm.editors.length, initVariant(variant, vm.editors.length)); + //only the content app can be selected since no other apps are shown, and because we copy all of these apps //to the "editors" we need to update this across all editors for (var e = 0; e < vm.editors.length; e++) { @@ -233,13 +239,6 @@ } } - //Find the whole variant model based on the culture that was chosen - var variant = _.find(vm.content.variants, function (v) { - return v.language.culture === selectedCulture; - }); - - insertVariantEditor(vm.editors.length, initVariant(variant, vm.editors.length)); - //TODO: hacking animation states - these should hopefully be easier to do when we upgrade angular editor.collapsed = true; editor.loading = true; From 9bc047c03f50e4795fc0d13b71af8218889d1e5a Mon Sep 17 00:00:00 2001 From: Robert Date: Tue, 15 Jan 2019 10:17:26 +0100 Subject: [PATCH 346/469] Adding code to re-validate on value change --- .../directives/components/tags/umbtagseditor.directive.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/tags/umbtagseditor.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/tags/umbtagseditor.directive.js index fea7528d5b..125f5ffb65 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/tags/umbtagseditor.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/tags/umbtagseditor.directive.js @@ -182,6 +182,9 @@ else { vm.onValueChanged({ value: [] }); } + + //this is required to re-validate + $scope.propertyForm.tagCount.$setViewValue($scope.model.value.length); } /** @@ -189,7 +192,7 @@ */ function validateMandatory() { return { - isValid: !vm.validation.mandatory || (vm.viewModel != null && vm.viewModel.length > 0) || (vm.value != null && vm.value.length > 0), + isValid: !vm.validation.mandatory || (vm.viewModel != null && vm.viewModel.length > 0), errorMsg: "Value cannot be empty", errorKey: "required" }; From 0092cac394037f1ec2696718954e6e4be4f1d90a Mon Sep 17 00:00:00 2001 From: Robert Date: Tue, 15 Jan 2019 10:31:12 +0100 Subject: [PATCH 347/469] DRY --- .../components/tags/umbtagseditor.directive.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/tags/umbtagseditor.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/tags/umbtagseditor.directive.js index 125f5ffb65..92c9d57ee8 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/tags/umbtagseditor.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/tags/umbtagseditor.directive.js @@ -130,8 +130,7 @@ if (!changes.value.isFirstChange() && changes.value.currentValue !== changes.value.previousValue) { configureViewModel(); - //this is required to re-validate - vm.tagEditorForm.tagCount.$setViewValue(vm.viewModel.length); + reValidate() } } @@ -183,8 +182,7 @@ vm.onValueChanged({ value: [] }); } - //this is required to re-validate - $scope.propertyForm.tagCount.$setViewValue($scope.model.value.length); + reValidate(); } /** @@ -273,8 +271,12 @@ return ($.inArray(suggestion.value, vm.viewModel) === -1); }); } - - + + function reValidate() { + //this is required to re-validate + vm.tagEditorForm.tagCount.$setViewValue(vm.viewModel.length); + { + } })(); From ba38b67b9d4cdd58d33a729b62181700b3d51dbe Mon Sep 17 00:00:00 2001 From: Stephan Date: Tue, 15 Jan 2019 11:30:30 +0100 Subject: [PATCH 348/469] Support IContentType.IsElement --- .../services/umbdataformatter.service.js | 18 +++++++-------- .../permissions/permissions.controller.js | 22 +++++++------------ .../views/permissions/permissions.html | 20 +++++++++++++++-- src/Umbraco.Web.UI/Umbraco/config/lang/en.xml | 2 ++ .../Umbraco/config/lang/en_us.xml | 2 ++ .../ContentTypeCompositionDisplay.cs | 4 ++++ .../Models/ContentEditing/ContentTypeSave.cs | 3 +++ 7 files changed, 46 insertions(+), 25 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/umbdataformatter.service.js b/src/Umbraco.Web.UI.Client/src/common/services/umbdataformatter.service.js index e31742e660..1e6fc5d643 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/umbdataformatter.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/umbdataformatter.service.js @@ -64,7 +64,7 @@ var saveModel = _.pick(displayModel, 'compositeContentTypes', 'isContainer', 'allowAsRoot', 'allowedTemplates', 'allowedContentTypes', 'alias', 'description', 'thumbnail', 'name', 'id', 'icon', 'trashed', - 'key', 'parentId', 'alias', 'path', 'allowCultureVariant'); + 'key', 'parentId', 'alias', 'path', 'allowCultureVariant', 'isElement'); //TODO: Map these saveModel.allowedTemplates = _.map(displayModel.allowedTemplates, function (t) { return t.alias; }); @@ -262,7 +262,7 @@ saveModel[props[m]] = startId.id; } - saveModel.parentId = -1; + saveModel.parentId = -1; return saveModel; }, @@ -293,7 +293,7 @@ }); saveModel.email = propEmail.value.trim(); saveModel.username = propLogin.value.trim(); - + saveModel.password = this.formatChangePasswordModel(propPass.value); var selectedGroups = []; @@ -336,7 +336,7 @@ /** formats the display model used to display the media to the model used to save the media */ formatMediaPostData: function (displayModel, action) { - //NOTE: the display model inherits from the save model so we can in theory just post up the display model but + //NOTE: the display model inherits from the save model so we can in theory just post up the display model but // we don't want to post all of the data as it is unecessary. var saveModel = { id: displayModel.id, @@ -354,7 +354,7 @@ /** formats the display model used to display the content to the model used to save the content */ formatContentPostData: function (displayModel, action) { - //NOTE: the display model inherits from the save model so we can in theory just post up the display model but + //NOTE: the display model inherits from the save model so we can in theory just post up the display model but // we don't want to post all of the data as it is unecessary. var saveModel = { id: displayModel.id, @@ -379,7 +379,7 @@ var propExpireDate = displayModel.removeDate; var propReleaseDate = displayModel.releaseDate; var propTemplate = displayModel.template; - + saveModel.expireDate = propExpireDate ? propExpireDate : null; saveModel.releaseDate = propReleaseDate ? propReleaseDate : null; saveModel.templateAlias = propTemplate ? propTemplate : null; @@ -389,8 +389,8 @@ /** * This formats the server GET response for a content display item - * @param {} displayModel - * @returns {} + * @param {} displayModel + * @returns {} */ formatContentGetData: function(displayModel) { @@ -418,7 +418,7 @@ } }); }); - + //now assign this same invariant property instance to the same index of the other variants property array for (var j = 1; j < displayModel.variants.length; j++) { diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.controller.js b/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.controller.js index 4a7a870618..317fe094ae 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.controller.js @@ -25,6 +25,7 @@ vm.removeChild = removeChild; vm.toggleAllowAsRoot = toggleAllowAsRoot; vm.toggleAllowCultureVariants = toggleAllowCultureVariants; + vm.toggleIsElement = toggleIsElement; /* ---------- INIT ---------- */ @@ -84,25 +85,18 @@ $scope.model.allowedContentTypes.splice(selectedChildIndex, 1); } - /** - * Toggle the $scope.model.allowAsRoot value to either true or false - */ - function toggleAllowAsRoot(){ - if($scope.model.allowAsRoot){ - $scope.model.allowAsRoot = false; - return; - } + // note: "safe toggling" here ie handling cases where the value is undefined, etc - $scope.model.allowAsRoot = true; + function toggleAllowAsRoot() { + $scope.model.allowAsRoot = $scope.model.allowAsRoot ? false : true; } function toggleAllowCultureVariants() { - if ($scope.model.allowCultureVariant) { - $scope.model.allowCultureVariant = false; - return; - } + $scope.model.allowCultureVariant = $scope.model.allowCultureVariant ? false : true; + } - $scope.model.allowCultureVariant = true; + function toggleIsElement() { + $scope.model.isElement = $scope.model.isElement ? false : true; } } diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.html b/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.html index ec1e528f8c..0d74c655d7 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.html +++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.html @@ -53,9 +53,25 @@ hotkey="alt+shift+v"> - + - +
    + +
    +
    + +
    + +
    + + +
    + +
    + + diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml index 386d3af518..987203442a 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml @@ -1518,6 +1518,8 @@ To manage your website, simply open the Umbraco back office and start adding con Allow varying by culture Allow editors to create content of this type in different languages Allow varying by culture + Is an Element type + An Element type is meant to be used for instance in Nested Content, and not in the tree Building models diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml index 5de373f571..1860d3afc9 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml @@ -1559,6 +1559,8 @@ To manage your website, simply open the Umbraco back office and start adding con Allow varying by culture Allow editors to create content of this type in different languages Allow varying by culture + Is an Element type + An Element type is meant to be used for instance in Nested Content, and not in the tree Add language diff --git a/src/Umbraco.Web/Models/ContentEditing/ContentTypeCompositionDisplay.cs b/src/Umbraco.Web/Models/ContentEditing/ContentTypeCompositionDisplay.cs index 7211ddbf61..e5e74c2749 100644 --- a/src/Umbraco.Web/Models/ContentEditing/ContentTypeCompositionDisplay.cs +++ b/src/Umbraco.Web/Models/ContentEditing/ContentTypeCompositionDisplay.cs @@ -26,6 +26,10 @@ namespace Umbraco.Web.Models.ContentEditing [DataMember(Name = "isContainer")] public bool IsContainer { get; set; } + //Element + [DataMember(Name = "isElement")] + public bool IsElement { get; set; } + [DataMember(Name = "listViewEditorName")] [ReadOnly(true)] public string ListViewEditorName { get; set; } diff --git a/src/Umbraco.Web/Models/ContentEditing/ContentTypeSave.cs b/src/Umbraco.Web/Models/ContentEditing/ContentTypeSave.cs index c2ec70d3dc..b1d24c5fd2 100644 --- a/src/Umbraco.Web/Models/ContentEditing/ContentTypeSave.cs +++ b/src/Umbraco.Web/Models/ContentEditing/ContentTypeSave.cs @@ -25,6 +25,9 @@ namespace Umbraco.Web.Models.ContentEditing [DataMember(Name = "isContainer")] public bool IsContainer { get; set; } + [DataMember(Name = "isElement")] + public bool IsElement { get; set; } + [DataMember(Name = "allowAsRoot")] public bool AllowAsRoot { get; set; } From 44ab0991ceaa653befbd0eede1277902d047fff0 Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 15 Jan 2019 22:08:08 +1100 Subject: [PATCH 349/469] Package installing is working --- .../Composing/Composers/ServicesComposer.cs | 1 - src/Umbraco.Core/Composing/TypeLoader.cs | 2 +- src/Umbraco.Core/IO/IOHelper.cs | 54 --- src/Umbraco.Core/IO/ShadowWrapper.cs | 2 +- src/Umbraco.Core/IO/SystemDirectories.cs | 4 + .../Models/Packaging/CompiledPackage.cs | 3 +- .../Models/Packaging/InstallationSummary.cs | 2 +- .../Models/Packaging/PackageDefinition.cs | 3 + .../Models/Packaging/UninstallationSummary.cs | 6 +- .../Packaging/CompiledPackageXmlParser.cs | 4 +- .../Packaging/IPackageActionRunner.cs | 11 +- .../Packaging/IPackageInstallation.cs | 13 +- .../Packaging/PackageActionRunner.cs | 29 +- .../Packaging/PackageDataInstallation.cs | 127 ++++++- .../Packaging/PackageDefinitionXmlParser.cs | 2 +- .../Packaging/PackageFileInstallation.cs | 26 ++ .../Packaging/PackageInstallation.cs | 77 ++-- .../Packaging/PackagesRepository.cs | 2 +- .../Services/IPackagingService.cs | 16 +- .../Services/Implement/PackagingService.cs | 48 +-- .../Sync/DatabaseServerMessenger.cs | 2 +- src/Umbraco.Examine/LuceneIndexCreator.cs | 2 +- .../Composing/TypeLoaderTests.cs | 2 +- src/Umbraco.Tests/IO/ShadowFileSystemTests.cs | 8 +- .../Packaging/PackageInstallationTest.cs | 20 +- .../Scoping/ScopeFileSystemsTests.cs | 2 +- src/Umbraco.Tests/TestHelpers/TestObjects.cs | 3 +- .../src/views/packages/edit.controller.js | 2 + .../src/views/packages/edit.html | 2 +- .../views/install-local.controller.js | 131 ++++--- .../Binders/ContentModelBinderHelper.cs | 3 +- .../Editors/ContentTypeController.cs | 19 +- src/Umbraco.Web/Editors/MediaController.cs | 2 +- src/Umbraco.Web/Editors/PackageController.cs | 2 +- .../Editors/PackageInstallController.cs | 258 +++---------- src/Umbraco.Web/Editors/UsersController.cs | 2 +- .../Controllers/InstallPackageController.cs | 346 +++++++++--------- src/Umbraco.Web/Install/InstallHelper.cs | 25 -- .../Install/InstallStatusTracker.cs | 4 +- .../InstallSteps/StarterKitDownloadStep.cs | 24 +- .../InstallSteps/StarterKitInstallStep.cs | 10 +- .../Models/ContentTypeImportModel.cs | 12 +- .../Models/LocalPackageInstallModel.cs | 10 +- src/Umbraco.Web/Models/PackageInstallModel.cs | 10 +- .../Runtime/WebRuntimeComponent.cs | 5 +- src/Umbraco.Web/Umbraco.Web.csproj | 1 - .../FileUploadCleanupFilterAttribute.cs | 16 +- .../_Legacy/PackageActions/addApplication.cs | 2 +- .../PackageActions/addDashboardSection.cs | 98 ----- .../PackageActions/addProxyFeedHost.cs | 2 +- .../_Legacy/PackageActions/allowDoctype.cs | 3 +- .../PackageActions/publishRootDocument.cs | 4 +- 52 files changed, 669 insertions(+), 795 deletions(-) delete mode 100644 src/Umbraco.Web/_Legacy/PackageActions/addDashboardSection.cs diff --git a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs index a09462c806..bd07123fb2 100644 --- a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs @@ -72,7 +72,6 @@ namespace Umbraco.Core.Composing.Composers new PackageInstallation( factory.GetInstance(), factory.GetInstance(), factory.GetInstance(), factory.GetInstance(), - SystemDirectories.Packages, appRoot, appRoot)); //TODO: These are replaced in the web project - we need to declare them so that diff --git a/src/Umbraco.Core/Composing/TypeLoader.cs b/src/Umbraco.Core/Composing/TypeLoader.cs index 3121e869c3..acb12ab575 100644 --- a/src/Umbraco.Core/Composing/TypeLoader.cs +++ b/src/Umbraco.Core/Composing/TypeLoader.cs @@ -405,7 +405,7 @@ namespace Umbraco.Core.Composing break; case LocalTempStorage.Default: default: - var tempFolder = IOHelper.MapPath("~/App_Data/TEMP/TypesCache"); + var tempFolder = IOHelper.MapPath(SystemDirectories.TempData.EnsureEndsWith('/') + "TypesCache"); _fileBasePath = Path.Combine(tempFolder, "umbraco-types." + NetworkHelper.FileSafeMachineName); break; } diff --git a/src/Umbraco.Core/IO/IOHelper.cs b/src/Umbraco.Core/IO/IOHelper.cs index 7773f378a5..76e7631482 100644 --- a/src/Umbraco.Core/IO/IOHelper.cs +++ b/src/Umbraco.Core/IO/IOHelper.cs @@ -31,16 +31,6 @@ namespace Umbraco.Core.IO public static char DirSepChar => Path.DirectorySeparatorChar; - internal static void UnZip(string zipFilePath, string unPackDirectory, bool deleteZipFile) - { - // Unzip - var tempDir = unPackDirectory; - Directory.CreateDirectory(tempDir); - ZipFile.ExtractToDirectory(zipFilePath, unPackDirectory); - if (deleteZipFile) - File.Delete(zipFilePath); - } - //helper to try and match the old path to a new virtual one public static string FindFile(string virtualPath) { @@ -123,11 +113,6 @@ namespace Umbraco.Core.IO return MapPath(path, true); } - public static string MapPathIfVirtual(string path) - { - return path.StartsWith("~/") ? MapPath(path) : path; - } - //use a tilde character instead of the complete path internal static string ReturnPath(string settingsKey, string standardPath, bool useTilde) { @@ -156,20 +141,6 @@ namespace Umbraco.Core.IO return VerifyEditPath(filePath, new[] { validDir }); } - /// - /// Validates that the current filepath matches a directory where the user is allowed to edit a file. - /// - /// The filepath to validate. - /// The valid directory. - /// True, if the filepath is valid, else an exception is thrown. - /// The filepath is invalid. - internal static bool ValidateEditPath(string filePath, string validDir) - { - if (VerifyEditPath(filePath, validDir) == false) - throw new FileSecurityException(String.Format("The filepath '{0}' is not within an allowed directory for this type of files", filePath.Replace(MapPath(SystemDirectories.Root), ""))); - return true; - } - /// /// Verifies that the current filepath matches one of several directories where the user is allowed to edit a file. /// @@ -221,20 +192,6 @@ namespace Umbraco.Core.IO return ext != null && validFileExtensions.Contains(ext.TrimStart('.')); } - /// - /// Validates that the current filepath has one of several authorized extensions. - /// - /// The filepath to validate. - /// The valid extensions. - /// True, if the filepath is valid, else an exception is thrown. - /// The filepath is invalid. - internal static bool ValidateFileExtension(string filePath, List validFileExtensions) - { - if (VerifyFileExtension(filePath, validFileExtensions) == false) - throw new FileSecurityException(String.Format("The extension for the current file '{0}' is not of an allowed type for this editor. This is typically controlled from either the installed MacroEngines or based on configuration in /config/umbracoSettings.config", filePath.Replace(MapPath(SystemDirectories.Root), ""))); - return true; - } - public static bool PathStartsWith(string path, string root, char separator) { // either it is identical to root, @@ -329,17 +286,6 @@ namespace Umbraco.Core.IO Directory.CreateDirectory(absolutePath); } - public static void EnsureFileExists(string path, string contents) - { - var absolutePath = IOHelper.MapPath(path); - if (File.Exists(absolutePath)) return; - - using (var writer = File.CreateText(absolutePath)) - { - writer.Write(contents); - } - } - /// /// Checks if a given path is a full path including drive letter /// diff --git a/src/Umbraco.Core/IO/ShadowWrapper.cs b/src/Umbraco.Core/IO/ShadowWrapper.cs index 6493238391..d71f328713 100644 --- a/src/Umbraco.Core/IO/ShadowWrapper.cs +++ b/src/Umbraco.Core/IO/ShadowWrapper.cs @@ -7,7 +7,7 @@ namespace Umbraco.Core.IO { internal class ShadowWrapper : IFileSystem { - private const string ShadowFsPath = "~/App_Data/TEMP/ShadowFs"; + private static readonly string ShadowFsPath = SystemDirectories.TempData.EnsureEndsWith('/') + "ShadowFs"; private readonly Func _isScoped; private readonly IFileSystem _innerFileSystem; diff --git a/src/Umbraco.Core/IO/SystemDirectories.cs b/src/Umbraco.Core/IO/SystemDirectories.cs index 94aa7b16cc..4ea3ed64d5 100644 --- a/src/Umbraco.Core/IO/SystemDirectories.cs +++ b/src/Umbraco.Core/IO/SystemDirectories.cs @@ -12,6 +12,10 @@ namespace Umbraco.Core.IO public static string Data => "~/App_Data"; + public static string TempData => Data + "/TEMP"; + + public static string TempFileUploads => TempData + "/FileUploads"; + public static string Install => "~/install"; //fixme: remove this diff --git a/src/Umbraco.Core/Models/Packaging/CompiledPackage.cs b/src/Umbraco.Core/Models/Packaging/CompiledPackage.cs index 266c1f5518..d458337bf9 100644 --- a/src/Umbraco.Core/Models/Packaging/CompiledPackage.cs +++ b/src/Umbraco.Core/Models/Packaging/CompiledPackage.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Xml.Linq; @@ -10,7 +11,7 @@ namespace Umbraco.Core.Models.Packaging /// public class CompiledPackage : IPackageInfo { - public string PackageFileName { get; set; } + public FileInfo PackageFile { get; set; } public string Name { get; set; } public string Version { get; set; } diff --git a/src/Umbraco.Core/Models/Packaging/InstallationSummary.cs b/src/Umbraco.Core/Models/Packaging/InstallationSummary.cs index 7d81f48dd2..1cab17e220 100644 --- a/src/Umbraco.Core/Models/Packaging/InstallationSummary.cs +++ b/src/Umbraco.Core/Models/Packaging/InstallationSummary.cs @@ -20,7 +20,7 @@ namespace Umbraco.Core.Models.Packaging public IEnumerable StylesheetsInstalled { get; set; } = Enumerable.Empty(); public IEnumerable ContentInstalled { get; set; } = Enumerable.Empty(); public IEnumerable Actions { get; set; } = Enumerable.Empty(); - public bool PackageInstalled { get; set; } + public IEnumerable ActionErrors { get; set; } = Enumerable.Empty(); } diff --git a/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs b/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs index de8415ddd2..bab52c63f6 100644 --- a/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs +++ b/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs @@ -53,6 +53,9 @@ namespace Umbraco.Core.Models.Packaging [Url] public string Url { get; set; } = string.Empty; + /// + /// The full path to the package's zip file when it was installed (or is being installed) + /// [ReadOnly(true)] [DataMember(Name = "packagePath")] public string PackagePath { get; set; } = string.Empty; diff --git a/src/Umbraco.Core/Models/Packaging/UninstallationSummary.cs b/src/Umbraco.Core/Models/Packaging/UninstallationSummary.cs index 20cbedbcf0..fd39954f6b 100644 --- a/src/Umbraco.Core/Models/Packaging/UninstallationSummary.cs +++ b/src/Umbraco.Core/Models/Packaging/UninstallationSummary.cs @@ -16,9 +16,9 @@ namespace Umbraco.Core.Models.Packaging public IEnumerable MacrosUninstalled { get; set; } = Enumerable.Empty(); public IEnumerable FilesUninstalled { get; set; } = Enumerable.Empty(); public IEnumerable TemplatesUninstalled { get; set; } = Enumerable.Empty(); - public IEnumerable ContentTypesUninstalled { get; set; } = Enumerable.Empty(); + public IEnumerable DocumentTypesUninstalled { get; set; } = Enumerable.Empty(); public IEnumerable StylesheetsUninstalled { get; set; } = Enumerable.Empty(); - public IEnumerable ContentUninstalled { get; set; } = Enumerable.Empty(); - public bool PackageUninstalled { get; set; } + public IEnumerable Actions { get; set; } = Enumerable.Empty(); + public IEnumerable ActionErrors { get; set; } = Enumerable.Empty(); } } diff --git a/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs b/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs index 0f3119f697..eb9cf46008 100644 --- a/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs +++ b/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs @@ -22,7 +22,7 @@ namespace Umbraco.Core.Packaging _conflictingPackageData = conflictingPackageData; } - public CompiledPackage ToCompiledPackage(XDocument xml, string packageFileName, string applicationRootFolder) + public CompiledPackage ToCompiledPackage(XDocument xml, FileInfo packageFile, string applicationRootFolder) { if (xml == null) throw new ArgumentNullException(nameof(xml)); if (xml.Root == null) throw new ArgumentException(nameof(xml), "The xml document is invalid"); @@ -39,7 +39,7 @@ namespace Umbraco.Core.Packaging var def = new CompiledPackage { - PackageFileName = packageFileName, + PackageFile = packageFile, Name = package.Element("name")?.Value, Author = author.Element("name")?.Value, AuthorUrl = author.Element("website")?.Value, diff --git a/src/Umbraco.Core/Packaging/IPackageActionRunner.cs b/src/Umbraco.Core/Packaging/IPackageActionRunner.cs index d5c6327115..1f8c134364 100644 --- a/src/Umbraco.Core/Packaging/IPackageActionRunner.cs +++ b/src/Umbraco.Core/Packaging/IPackageActionRunner.cs @@ -1,4 +1,5 @@ -using System.Xml.Linq; +using System.Collections.Generic; +using System.Xml.Linq; namespace Umbraco.Core.Packaging { @@ -10,7 +11,8 @@ namespace Umbraco.Core.Packaging /// Name of the package. /// The action alias. /// The action XML. - void RunPackageAction(string packageName, string actionAlias, XElement actionXml); + /// + bool RunPackageAction(string packageName, string actionAlias, XElement actionXml, out IEnumerable errors); /// /// Undos the package action with the specified action alias. @@ -18,6 +20,7 @@ namespace Umbraco.Core.Packaging /// Name of the package. /// The action alias. /// The action XML. - void UndoPackageAction(string packageName, string actionAlias, XElement actionXml); + /// + bool UndoPackageAction(string packageName, string actionAlias, XElement actionXml, out IEnumerable errors); } -} \ No newline at end of file +} diff --git a/src/Umbraco.Core/Packaging/IPackageInstallation.cs b/src/Umbraco.Core/Packaging/IPackageInstallation.cs index 83a21dcd2f..5dae76674d 100644 --- a/src/Umbraco.Core/Packaging/IPackageInstallation.cs +++ b/src/Umbraco.Core/Packaging/IPackageInstallation.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.IO; using System.Xml.Linq; using Umbraco.Core.Models.Packaging; @@ -6,6 +7,14 @@ namespace Umbraco.Core.Packaging { public interface IPackageInstallation { + /// + /// Uninstalls a package including all data, entities and files + /// + /// + /// + /// + UninstallationSummary UninstallPackage(PackageDefinition packageDefinition, int userId); + /// /// Installs a packages data and entities /// @@ -27,8 +36,8 @@ namespace Umbraco.Core.Packaging /// /// Reads the package (zip) file and returns the model /// - /// + /// /// - CompiledPackage ReadPackage(string packageFileName); + CompiledPackage ReadPackage(FileInfo packageFile); } } diff --git a/src/Umbraco.Core/Packaging/PackageActionRunner.cs b/src/Umbraco.Core/Packaging/PackageActionRunner.cs index 37103b0473..38275d5f0a 100644 --- a/src/Umbraco.Core/Packaging/PackageActionRunner.cs +++ b/src/Umbraco.Core/Packaging/PackageActionRunner.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Xml.Linq; using Umbraco.Core.Logging; using Umbraco.Core._Legacy.PackageActions; @@ -19,15 +20,10 @@ namespace Umbraco.Core.Packaging _packageActions = packageActions; } - /// - /// Runs the package action with the specified action alias. - /// - /// Name of the package. - /// The action alias. - /// The action XML. - public void RunPackageAction(string packageName, string actionAlias, XElement actionXml) + /// + public bool RunPackageAction(string packageName, string actionAlias, XElement actionXml, out IEnumerable errors) { - + var e = new List(); foreach (var ipa in _packageActions) { try @@ -37,19 +33,19 @@ namespace Umbraco.Core.Packaging } catch (Exception ex) { + e.Add($"{ipa.Alias()} - {ex.Message}"); _logger.Error(ex, "Error loading package action '{PackageActionAlias}' for package {PackageName}", ipa.Alias(), packageName); } } + + errors = e; + return e.Count == 0; } - /// - /// Undos the package action with the specified action alias. - /// - /// Name of the package. - /// The action alias. - /// The action XML. - public void UndoPackageAction(string packageName, string actionAlias, XElement actionXml) + /// + public bool UndoPackageAction(string packageName, string actionAlias, XElement actionXml, out IEnumerable errors) { + var e = new List(); foreach (var ipa in _packageActions) { try @@ -59,9 +55,12 @@ namespace Umbraco.Core.Packaging } catch (Exception ex) { + e.Add($"{ipa.Alias()} - {ex.Message}"); _logger.Error(ex, "Error undoing package action '{PackageActionAlias}' for package {PackageName}", ipa.Alias(), packageName); } } + errors = e; + return e.Count == 0; } } diff --git a/src/Umbraco.Core/Packaging/PackageDataInstallation.cs b/src/Umbraco.Core/Packaging/PackageDataInstallation.cs index 8ef99502c8..1743bb0041 100644 --- a/src/Umbraco.Core/Packaging/PackageDataInstallation.cs +++ b/src/Umbraco.Core/Packaging/PackageDataInstallation.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Text.RegularExpressions; using System.Web; @@ -10,6 +11,7 @@ using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Entities; +using Umbraco.Core.Models.Packaging; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Services; using Umbraco.Core.Services.Implement; @@ -43,6 +45,128 @@ namespace Umbraco.Core.Packaging _contentService = contentService; } + #region Uninstall + + public UninstallationSummary UninstallPackageData(PackageDefinition package, int userId) + { + if (package == null) throw new ArgumentNullException(nameof(package)); + + var removedTemplates = new List(); + var removedMacros = new List(); + var removedContentTypes = new List(); + var removedDictionaryItems = new List(); + var removedDataTypes = new List(); + var removedLanguages = new List(); + + + //Uninstall templates + foreach (var item in package.Templates.ToArray()) + { + if (int.TryParse(item, out var nId) == false) continue; + var found = _fileService.GetTemplate(nId); + if (found != null) + { + removedTemplates.Add(found); + _fileService.DeleteTemplate(found.Alias, userId); + } + package.Templates.Remove(nId.ToString()); + } + + //Uninstall macros + foreach (var item in package.Macros.ToArray()) + { + if (int.TryParse(item, out var nId) == false) continue; + var macro = _macroService.GetById(nId); + if (macro != null) + { + removedMacros.Add(macro); + _macroService.Delete(macro, userId); + } + package.Macros.Remove(nId.ToString()); + } + + //Remove Document Types + var contentTypes = new List(); + var contentTypeService = _contentTypeService; + foreach (var item in package.DocumentTypes.ToArray()) + { + if (int.TryParse(item, out var nId) == false) continue; + var contentType = contentTypeService.Get(nId); + if (contentType == null) continue; + contentTypes.Add(contentType); + package.DocumentTypes.Remove(nId.ToString(CultureInfo.InvariantCulture)); + } + + //Order the DocumentTypes before removing them + if (contentTypes.Any()) + { + //TODO: I don't think this ordering is necessary + var orderedTypes = (from contentType in contentTypes + orderby contentType.ParentId descending, contentType.Id descending + select contentType).ToList(); + removedContentTypes.AddRange(orderedTypes); + contentTypeService.Delete(orderedTypes, userId); + } + + //Remove Dictionary items + foreach (var item in package.DictionaryItems.ToArray()) + { + if (int.TryParse(item, out var nId) == false) continue; + var di = _localizationService.GetDictionaryItemById(nId); + if (di != null) + { + removedDictionaryItems.Add(di); + _localizationService.Delete(di, userId); + } + package.DictionaryItems.Remove(nId.ToString()); + } + + //Remove Data types + foreach (var item in package.DataTypes.ToArray()) + { + if (int.TryParse(item, out var nId) == false) continue; + var dtd = _dataTypeService.GetDataType(nId); + if (dtd != null) + { + removedDataTypes.Add(dtd); + _dataTypeService.Delete(dtd, userId); + } + package.DataTypes.Remove(nId.ToString()); + } + + //Remove Langs + foreach (var item in package.Languages.ToArray()) + { + if (int.TryParse(item, out var nId) == false) continue; + var lang = _localizationService.GetLanguageById(nId); + if (lang != null) + { + removedLanguages.Add(lang); + _localizationService.Delete(lang, userId); + } + package.Languages.Remove(nId.ToString()); + } + + // create a summary of what was actually removed, for PackagingService.UninstalledPackage + var summary = new UninstallationSummary + { + MetaData = package, + TemplatesUninstalled = removedTemplates, + MacrosUninstalled = removedMacros, + DocumentTypesUninstalled = removedContentTypes, + DictionaryItemsUninstalled = removedDictionaryItems, + DataTypesUninstalled = removedDataTypes, + LanguagesUninstalled = removedLanguages, + + }; + + return summary; + + + } + + #endregion + #region Content @@ -201,7 +325,7 @@ namespace Umbraco.Core.Packaging #endregion - #region ContentTypes + #region DocumentTypes public IEnumerable ImportDocumentType(XElement docTypeElement, int userId) { @@ -576,6 +700,7 @@ namespace Umbraco.Core.Packaging // This means that the property will not be created. if (dataTypeDefinition == null) { + //TODO: We should expose this to the UI during install! _logger.Warn("Packager: Error handling creation of PropertyType '{PropertyType}'. Could not find DataTypeDefintion with unique id '{DataTypeDefinitionId}' nor one referencing the DataType with a property editor alias (or legacy control id) '{PropertyEditorAlias}'. Did the package creator forget to package up custom datatypes? This property will be converted to a label/readonly editor if one exists.", property.Element("Name").Value, dataTypeDefinitionId, property.Element("Type").Value.Trim()); diff --git a/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs b/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs index 1f0e5ec92e..0d7adf8ece 100644 --- a/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs +++ b/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs @@ -91,7 +91,7 @@ namespace Umbraco.Core.Packaging new XElement("datatypes", string.Join(",", def.DataTypes ?? Array.Empty())), new XElement("content", - new XAttribute("nodeId", def.ContentNodeId), + new XAttribute("nodeId", def.ContentNodeId ?? string.Empty), new XAttribute("loadChildNodes", def.ContentLoadChildNodes)), new XElement("templates", string.Join(",", def.Templates ?? Array.Empty())), diff --git a/src/Umbraco.Core/Packaging/PackageFileInstallation.cs b/src/Umbraco.Core/Packaging/PackageFileInstallation.cs index 55b8bdc63e..7c0891175b 100644 --- a/src/Umbraco.Core/Packaging/PackageFileInstallation.cs +++ b/src/Umbraco.Core/Packaging/PackageFileInstallation.cs @@ -53,6 +53,32 @@ namespace Umbraco.Core.Packaging } } + public IEnumerable UninstallFiles(PackageDefinition package) + { + var removedFiles = new List(); + + foreach (var item in package.Files.ToArray()) + { + removedFiles.Add(item.GetRelativePath()); + + //here we need to try to find the file in question as most packages does not support the tilde char + var file = IOHelper.FindFile(item); + if (file != null) + { + //TODO: Surely this should be ~/ ? + file = file.EnsureStartsWith("/"); + var filePath = IOHelper.MapPath(file); + + if (File.Exists(filePath)) + File.Delete(filePath); + + } + package.Files.Remove(file); + } + + return removedFiles; + } + private static IEnumerable<(string packageUniqueFile, string appAbsolutePath)> AppendRootToDestination(string applicationRootFolder, IEnumerable<(string packageUniqueFile, string appRelativePath)> sourceDestination) { return diff --git a/src/Umbraco.Core/Packaging/PackageInstallation.cs b/src/Umbraco.Core/Packaging/PackageInstallation.cs index 12d4769235..4563d31560 100644 --- a/src/Umbraco.Core/Packaging/PackageInstallation.cs +++ b/src/Umbraco.Core/Packaging/PackageInstallation.cs @@ -18,7 +18,6 @@ namespace Umbraco.Core.Packaging private readonly PackageFileInstallation _packageFileInstallation; private readonly CompiledPackageXmlParser _parser; private readonly IPackageActionRunner _packageActionRunner; - private readonly string _packagesFolderPath; private readonly DirectoryInfo _packageExtractionFolder; private readonly DirectoryInfo _applicationRootFolder; @@ -29,9 +28,6 @@ namespace Umbraco.Core.Packaging /// /// /// - /// - /// The relative path of the package storage folder (i.e. ~/App_Data/Packages ) - /// /// /// The root folder of the application /// @@ -39,27 +35,25 @@ namespace Umbraco.Core.Packaging /// The destination root folder to extract the package files (generally the same as applicationRoot) but can be modified for testing /// public PackageInstallation(PackageDataInstallation packageDataInstallation, PackageFileInstallation packageFileInstallation, CompiledPackageXmlParser parser, IPackageActionRunner packageActionRunner, - string packagesFolderPath, DirectoryInfo applicationRootFolder, DirectoryInfo packageExtractionFolder) + DirectoryInfo applicationRootFolder, DirectoryInfo packageExtractionFolder) { _packageExtraction = new PackageExtraction(); _packageFileInstallation = packageFileInstallation ?? throw new ArgumentNullException(nameof(packageFileInstallation)); _packageDataInstallation = packageDataInstallation ?? throw new ArgumentNullException(nameof(packageDataInstallation)); - _parser = parser; - _packageActionRunner = packageActionRunner; - _packagesFolderPath = packagesFolderPath; - _applicationRootFolder = applicationRootFolder; - _packageExtractionFolder = packageExtractionFolder; + _parser = parser ?? throw new ArgumentNullException(nameof(parser)); + _packageActionRunner = packageActionRunner ?? throw new ArgumentNullException(nameof(packageActionRunner)); + _applicationRootFolder = applicationRootFolder ?? throw new ArgumentNullException(nameof(applicationRootFolder)); + _packageExtractionFolder = packageExtractionFolder ?? throw new ArgumentNullException(nameof(packageExtractionFolder)); } - public CompiledPackage ReadPackage(string packageFileName) + public CompiledPackage ReadPackage(FileInfo packageFile) { - if (packageFileName == null) throw new ArgumentNullException(nameof(packageFileName)); - var packageZipFile = GetPackageZipFile(packageFileName); - var doc = GetConfigXmlDoc(packageZipFile); + if (packageFile == null) throw new ArgumentNullException(nameof(packageFile)); + var doc = GetConfigXmlDoc(packageFile); - var compiledPackage = _parser.ToCompiledPackage(doc, Path.GetFileName(packageZipFile.FullName), _applicationRootFolder.FullName); + var compiledPackage = _parser.ToCompiledPackage(doc, packageFile, _applicationRootFolder.FullName); - ValidatePackageFile(packageZipFile, compiledPackage); + ValidatePackageFile(packageFile, compiledPackage); return compiledPackage; } @@ -73,15 +67,28 @@ namespace Umbraco.Core.Packaging if (packageDefinition.Name != compiledPackage.Name) throw new InvalidOperationException("The package definition does not match the compiled package manifest"); - var packageZipFile = GetPackageZipFile(compiledPackage.PackageFileName); + var packageZipFile = compiledPackage.PackageFile; return _packageFileInstallation.InstallFiles(compiledPackage, packageZipFile, _packageExtractionFolder.FullName); } + public UninstallationSummary UninstallPackage(PackageDefinition package, int userId) + { + //running this will update the PackageDefinition with the items being removed + var summary = _packageDataInstallation.UninstallPackageData(package, userId); + summary.Actions = _parser.GetPackageActions(XElement.Parse(package.Actions), package.Name); + + //run actions before files are removed + summary.ActionErrors = UndoPackageActions(package, summary.Actions).ToList(); + + var filesRemoved = _packageFileInstallation.UninstallFiles(package); + summary.FilesUninstalled = filesRemoved; + + return summary; + } + public InstallationSummary InstallPackageData(PackageDefinition packageDefinition, CompiledPackage compiledPackage, int userId) { - //TODO: Update the PackageDefinition! - var installationSummary = new InstallationSummary { DataTypesInstalled = _packageDataInstallation.ImportDataTypes(compiledPackage.DataTypes.ToList(), userId), @@ -101,10 +108,8 @@ namespace Umbraco.Core.Packaging installationSummary.MetaData = compiledPackage; //fixme: Verify that this will work! installationSummary.FilesInstalled = packageDefinition.Files; - installationSummary.PackageInstalled = true; - + //make sure the definition is up to date with everything - foreach (var x in installationSummary.DataTypesInstalled) packageDefinition.DataTypes.Add(x.Id.ToInvariantString()); foreach (var x in installationSummary.LanguagesInstalled) packageDefinition.Languages.Add(x.Id.ToInvariantString()); foreach (var x in installationSummary.DictionaryItemsInstalled) packageDefinition.DictionaryItems.Add(x.Id.ToInvariantString()); @@ -115,15 +120,17 @@ namespace Umbraco.Core.Packaging var contentInstalled = installationSummary.ContentInstalled.ToList(); packageDefinition.ContentNodeId = contentInstalled.Count > 0 ? contentInstalled[0].Id.ToInvariantString() : null; - RunPackageActions(packageDefinition, installationSummary.Actions); + //run package actions + installationSummary.ActionErrors = RunPackageActions(packageDefinition, installationSummary.Actions).ToList(); return installationSummary; } - private void RunPackageActions(PackageDefinition packageDefinition, IEnumerable actions) + private IEnumerable RunPackageActions(PackageDefinition packageDefinition, IEnumerable actions) { foreach (var n in actions) { + //if there is an undo section then save it to the definition so we can run it at uninstallation var undo = n.Undo; if (undo) packageDefinition.Actions += n.XmlData.ToString(); @@ -131,12 +138,28 @@ namespace Umbraco.Core.Packaging //Run the actions tagged only for 'install' if (n.RunAt != ActionRunAt.Install) continue; - if (n.Alias.IsNullOrWhiteSpace() == false) - _packageActionRunner.RunPackageAction(packageDefinition.Name, n.Alias, n.XmlData); + if (n.Alias.IsNullOrWhiteSpace()) continue; + + //run the actions and report errors + if (!_packageActionRunner.RunPackageAction(packageDefinition.Name, n.Alias, n.XmlData, out var err)) + foreach (var e in err) yield return e; } } - private FileInfo GetPackageZipFile(string packageFileName) => new FileInfo(IOHelper.MapPath(_packagesFolderPath).EnsureEndsWith('\\') + packageFileName); + private IEnumerable UndoPackageActions(IPackageInfo packageDefinition, IEnumerable actions) + { + foreach (var n in actions) + { + //Run the actions tagged only for 'uninstall' + if (n.RunAt != ActionRunAt.Uninstall) continue; + + if (n.Alias.IsNullOrWhiteSpace()) continue; + + //run the actions and report errors + if (!_packageActionRunner.UndoPackageAction(packageDefinition.Name, n.Alias, n.XmlData, out var err)) + foreach (var e in err) yield return e; + } + } private XDocument GetConfigXmlDoc(FileInfo packageFile) { diff --git a/src/Umbraco.Core/Packaging/PackagesRepository.cs b/src/Umbraco.Core/Packaging/PackagesRepository.cs index c0620820a2..af5c7ffded 100644 --- a/src/Umbraco.Core/Packaging/PackagesRepository.cs +++ b/src/Umbraco.Core/Packaging/PackagesRepository.cs @@ -69,7 +69,7 @@ namespace Umbraco.Core.Packaging _logger = logger; _packageRepositoryFileName = packageRepositoryFileName; - _tempFolderPath = tempFolderPath ?? SystemDirectories.Data + "/TEMP/PackageFiles"; + _tempFolderPath = tempFolderPath ?? SystemDirectories.TempData.EnsureEndsWith('/') + "PackageFiles"; _packagesFolderPath = packagesFolderPath ?? SystemDirectories.Packages; _mediaFolderPath = mediaFolderPath ?? SystemDirectories.Media + "/created-packages"; diff --git a/src/Umbraco.Core/Services/IPackagingService.cs b/src/Umbraco.Core/Services/IPackagingService.cs index 8aa936c8ff..a31fc2d6cf 100644 --- a/src/Umbraco.Core/Services/IPackagingService.cs +++ b/src/Umbraco.Core/Services/IPackagingService.cs @@ -16,25 +16,27 @@ namespace Umbraco.Core.Services /// /// Returns a result from an umbraco package file (zip) /// - /// + /// /// - CompiledPackage GetCompiledPackageInfo(string packageFileName); + CompiledPackage GetCompiledPackageInfo(FileInfo packageFile); /// /// Installs the package files contained in an umbraco package file (zip) /// /// - /// + /// /// - IEnumerable InstallCompiledPackageFiles(PackageDefinition packageDefinition, string packageFileName, int userId = 0); + IEnumerable InstallCompiledPackageFiles(PackageDefinition packageDefinition, FileInfo packageFile, int userId = 0); /// /// Installs the data, entities, objects contained in an umbraco package file (zip) /// /// - /// + /// /// - InstallationSummary InstallCompiledPackageData(PackageDefinition packageDefinition, string packageFileName, int userId = 0); + InstallationSummary InstallCompiledPackageData(PackageDefinition packageDefinition, FileInfo packageFile, int userId = 0); + + UninstallationSummary UninstallPackage(PackageDefinition packageDefinition, int userId = 0); #endregion @@ -81,6 +83,6 @@ namespace Umbraco.Core.Services /// /// The file name of the downloaded package which will exist in ~/App_Data/packages /// - Task FetchPackageFileAsync(Guid packageId, Version umbracoVersion, int userId); + Task FetchPackageFileAsync(Guid packageId, Version umbracoVersion, int userId); } } diff --git a/src/Umbraco.Core/Services/Implement/PackagingService.cs b/src/Umbraco.Core/Services/Implement/PackagingService.cs index ba5d30f8d7..362b1fc67b 100644 --- a/src/Umbraco.Core/Services/Implement/PackagingService.cs +++ b/src/Umbraco.Core/Services/Implement/PackagingService.cs @@ -53,7 +53,7 @@ namespace Umbraco.Core.Services.Implement #region Package Files /// - public async Task FetchPackageFileAsync(Guid packageId, Version umbracoVersion, int userId) + public async Task FetchPackageFileAsync(Guid packageId, Version umbracoVersion, int userId) { //includeHidden = true because we don't care if it's hidden we want to get the file regardless var url = $"{Constants.PackageRepository.RestApiBaseUrl}/{packageId}?version={umbracoVersion.ToString(3)}&includeHidden=true&asFile=true"; @@ -85,7 +85,7 @@ namespace Umbraco.Core.Services.Implement using (var fs1 = new FileStream(packageFilePath, FileMode.Create)) { fs1.Write(bytes, 0, bytes.Length); - return packageId + ".umb"; + return new FileInfo(packageFilePath); } } @@ -97,18 +97,19 @@ namespace Umbraco.Core.Services.Implement #region Installation - public CompiledPackage GetCompiledPackageInfo(string packageFileName) => _packageInstallation.ReadPackage(packageFileName); + public CompiledPackage GetCompiledPackageInfo(FileInfo packageFile) => _packageInstallation.ReadPackage(packageFile); - public IEnumerable InstallCompiledPackageFiles(PackageDefinition packageDefinition, string packageFileName, int userId = 0) + public IEnumerable InstallCompiledPackageFiles(PackageDefinition packageDefinition, FileInfo packageFile, int userId = 0) { if (packageDefinition == null) throw new ArgumentNullException(nameof(packageDefinition)); if (packageDefinition.Id == default) throw new ArgumentException("The package definition has not been persisted"); if (packageDefinition.Name == default) throw new ArgumentException("The package definition has incomplete information"); - var compiledPackage = GetCompiledPackageInfo(packageFileName); - if (compiledPackage == null) throw new InvalidOperationException("Could not read the package file " + packageFileName); + var compiledPackage = GetCompiledPackageInfo(packageFile); + if (compiledPackage == null) throw new InvalidOperationException("Could not read the package file " + packageFile); - var files = _packageInstallation.InstallPackageFiles(packageDefinition, compiledPackage, userId); + var files = _packageInstallation.InstallPackageFiles(packageDefinition, compiledPackage, userId).ToList(); + packageDefinition.Files = files; SaveInstalledPackage(packageDefinition); @@ -117,16 +118,16 @@ namespace Umbraco.Core.Services.Implement return files; } - public InstallationSummary InstallCompiledPackageData(PackageDefinition packageDefinition, string packageFileName, int userId = 0) + public InstallationSummary InstallCompiledPackageData(PackageDefinition packageDefinition, FileInfo packageFile, int userId = 0) { if (packageDefinition == null) throw new ArgumentNullException(nameof(packageDefinition)); if (packageDefinition.Id == default) throw new ArgumentException("The package definition has not been persisted"); if (packageDefinition.Name == default) throw new ArgumentException("The package definition has incomplete information"); - var compiledPackage = GetCompiledPackageInfo(packageFileName); - if (compiledPackage == null) throw new InvalidOperationException("Could not read the package file " + packageFileName); + var compiledPackage = GetCompiledPackageInfo(packageFile); + if (compiledPackage == null) throw new InvalidOperationException("Could not read the package file " + packageFile); - if (ImportingPackage.IsRaisedEventCancelled(new ImportPackageEventArgs(packageFileName, compiledPackage), this)) + if (ImportingPackage.IsRaisedEventCancelled(new ImportPackageEventArgs(packageFile.Name, compiledPackage), this)) return new InstallationSummary { MetaData = compiledPackage }; var summary = _packageInstallation.InstallPackageData(packageDefinition, compiledPackage, userId); @@ -140,6 +141,20 @@ namespace Umbraco.Core.Services.Implement return summary; } + public UninstallationSummary UninstallPackage(PackageDefinition package, int userId = 0) + { + var summary = _packageInstallation.UninstallPackage(package, userId); + + SaveInstalledPackage(package); + + DeleteInstalledPackage(package.Id, userId); + + // trigger the UninstalledPackage event + UninstalledPackage.RaiseEvent(new UninstallPackageEventArgs(summary, package, false), this); + + return summary; + } + #endregion #region Created/Installed Package Repositories @@ -179,21 +194,12 @@ namespace Umbraco.Core.Services.Implement #endregion - /// - /// This method can be used to trigger the 'UninstalledPackage' event when a package is uninstalled by something else but this service. - /// - /// - internal static void OnUninstalledPackage(UninstallPackageEventArgs args) - { - UninstalledPackage.RaiseEvent(args, null); - } - #region Event Handlers /// /// Occurs before Importing umbraco package /// - internal static event TypedEventHandler> ImportingPackage; + public static event TypedEventHandler> ImportingPackage; /// /// Occurs after a package is imported diff --git a/src/Umbraco.Core/Sync/DatabaseServerMessenger.cs b/src/Umbraco.Core/Sync/DatabaseServerMessenger.cs index 5cfcb501e5..6844e6e75c 100644 --- a/src/Umbraco.Core/Sync/DatabaseServerMessenger.cs +++ b/src/Umbraco.Core/Sync/DatabaseServerMessenger.cs @@ -551,7 +551,7 @@ namespace Umbraco.Core.Sync break; case LocalTempStorage.Default: default: - var tempFolder = IOHelper.MapPath("~/App_Data/TEMP/DistCache"); + var tempFolder = IOHelper.MapPath(SystemDirectories.TempData.EnsureEndsWith('/') + "DistCache"); distCacheFilePath = Path.Combine(tempFolder, fileName); break; } diff --git a/src/Umbraco.Examine/LuceneIndexCreator.cs b/src/Umbraco.Examine/LuceneIndexCreator.cs index 0e83b37dc5..806d0edc7a 100644 --- a/src/Umbraco.Examine/LuceneIndexCreator.cs +++ b/src/Umbraco.Examine/LuceneIndexCreator.cs @@ -29,7 +29,7 @@ namespace Umbraco.Examine public virtual Lucene.Net.Store.Directory CreateFileSystemLuceneDirectory(string folderName) { - var dirInfo = new DirectoryInfo(Path.Combine(IOHelper.MapPath(SystemDirectories.Data), "TEMP", "ExamineIndexes", folderName)); + var dirInfo = new DirectoryInfo(Path.Combine(IOHelper.MapPath(SystemDirectories.TempData), "ExamineIndexes", folderName)); if (!dirInfo.Exists) System.IO.Directory.CreateDirectory(dirInfo.FullName); diff --git a/src/Umbraco.Tests/Composing/TypeLoaderTests.cs b/src/Umbraco.Tests/Composing/TypeLoaderTests.cs index 5148c7eb1b..1649f3675d 100644 --- a/src/Umbraco.Tests/Composing/TypeLoaderTests.cs +++ b/src/Umbraco.Tests/Composing/TypeLoaderTests.cs @@ -30,7 +30,7 @@ namespace Umbraco.Tests.Composing // this ensures it's reset _typeLoader = new TypeLoader(NullCacheProvider.Instance, LocalTempStorage.Default, new ProfilingLogger(Mock.Of(), Mock.Of())); - foreach (var file in Directory.GetFiles(IOHelper.MapPath("~/App_Data/TEMP/TypesCache"))) + foreach (var file in Directory.GetFiles(IOHelper.MapPath(SystemDirectories.TempData.EnsureEndsWith('/') + "TypesCache"))) File.Delete(file); // for testing, we'll specify which assemblies are scanned for the PluginTypeResolver diff --git a/src/Umbraco.Tests/IO/ShadowFileSystemTests.cs b/src/Umbraco.Tests/IO/ShadowFileSystemTests.cs index 262b026cae..2244f9085d 100644 --- a/src/Umbraco.Tests/IO/ShadowFileSystemTests.cs +++ b/src/Umbraco.Tests/IO/ShadowFileSystemTests.cs @@ -41,7 +41,7 @@ namespace Umbraco.Tests.IO private static void ClearFiles() { TestHelper.DeleteDirectory(IOHelper.MapPath("FileSysTests")); - TestHelper.DeleteDirectory(IOHelper.MapPath("App_Data/TEMP/ShadowFs")); + TestHelper.DeleteDirectory(IOHelper.MapPath(SystemDirectories.TempData.EnsureEndsWith('/') + "ShadowFs")); } private static string NormPath(string path) @@ -388,7 +388,7 @@ namespace Umbraco.Tests.IO var logger = Mock.Of(); var path = IOHelper.MapPath("FileSysTests"); - var shadowfs = IOHelper.MapPath("App_Data/TEMP/ShadowFs"); + var shadowfs = IOHelper.MapPath(SystemDirectories.TempData.EnsureEndsWith('/') + "ShadowFs"); Directory.CreateDirectory(path); Directory.CreateDirectory(shadowfs); @@ -482,7 +482,7 @@ namespace Umbraco.Tests.IO var logger = Mock.Of(); var path = IOHelper.MapPath("FileSysTests"); - var shadowfs = IOHelper.MapPath("App_Data/TEMP/ShadowFs"); + var shadowfs = IOHelper.MapPath(SystemDirectories.TempData.EnsureEndsWith('/') + "ShadowFs"); Directory.CreateDirectory(path); var scopedFileSystems = false; @@ -535,7 +535,7 @@ namespace Umbraco.Tests.IO var logger = Mock.Of(); var path = IOHelper.MapPath("FileSysTests"); - var shadowfs = IOHelper.MapPath("App_Data/TEMP/ShadowFs"); + var shadowfs = IOHelper.MapPath(SystemDirectories.TempData.EnsureEndsWith('/') + "ShadowFs"); Directory.CreateDirectory(path); var scopedFileSystems = false; diff --git a/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs b/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs index 609d26aec9..7514eea00b 100644 --- a/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs +++ b/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs @@ -50,11 +50,10 @@ namespace Umbraco.Tests.Packaging PackageDataInstallation, new PackageFileInstallation(Parser, ProfilingLogger), Parser, Mock.Of(), - packagesFolderPath: "~/Packaging/packages",//this is where our test zip file is applicationRootFolder: new DirectoryInfo(IOHelper.GetRootDirectorySafe()), packageExtractionFolder: new DirectoryInfo(IOHelper.MapPath("~/" + _testBaseFolder))); //we don't want to extract package files to the real root, so extract to a test folder - const string documentTypePickerUmb = "Document_Type_Picker_1.1.umb"; + private const string DocumentTypePickerUmb = "Document_Type_Picker_1.1.umb"; //[Test] //public void PackagingService_Can_ImportPackage() @@ -72,7 +71,9 @@ namespace Umbraco.Tests.Packaging [Test] public void Can_Read_Compiled_Package() { - var package = PackageInstallation.ReadPackage(documentTypePickerUmb); + var package = PackageInstallation.ReadPackage( + //this is where our test zip file is + new FileInfo(Path.Combine(IOHelper.MapPath("~/Packaging/packages"), DocumentTypePickerUmb))); Assert.IsNotNull(package); Assert.AreEqual(1, package.Files.Count); Assert.AreEqual("095e064b-ba4d-442d-9006-3050983c13d8.dll", package.Files[0].UniqueFileName); @@ -95,7 +96,10 @@ namespace Umbraco.Tests.Packaging { - var preInstallWarnings = PackageInstallation.ReadPackage(documentTypePickerUmb).Warnings; + var preInstallWarnings = PackageInstallation.ReadPackage( + //this is where our test zip file is + new FileInfo(Path.Combine(IOHelper.MapPath("~/Packaging/packages"), DocumentTypePickerUmb))) + .Warnings; Assert.IsNotNull(preInstallWarnings); //TODO: Assert! @@ -104,7 +108,9 @@ namespace Umbraco.Tests.Packaging [Test] public void Install_Files() { - var package = PackageInstallation.ReadPackage(documentTypePickerUmb); + var package = PackageInstallation.ReadPackage( + //this is where our test zip file is + new FileInfo(Path.Combine(IOHelper.MapPath("~/Packaging/packages"), DocumentTypePickerUmb))); var def = PackageDefinition.FromCompiledPackage(package); def.Id = 1; def.PackageId = Guid.NewGuid(); @@ -122,7 +128,9 @@ namespace Umbraco.Tests.Packaging [Test] public void Install_Data() { - var package = PackageInstallation.ReadPackage(documentTypePickerUmb); + var package = PackageInstallation.ReadPackage( + //this is where our test zip file is + new FileInfo(Path.Combine(IOHelper.MapPath("~/Packaging/packages"), DocumentTypePickerUmb))); var def = PackageDefinition.FromCompiledPackage(package); def.Id = 1; def.PackageId = Guid.NewGuid(); diff --git a/src/Umbraco.Tests/Scoping/ScopeFileSystemsTests.cs b/src/Umbraco.Tests/Scoping/ScopeFileSystemsTests.cs index 0ef0e9362b..0a23e4a1b9 100644 --- a/src/Umbraco.Tests/Scoping/ScopeFileSystemsTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopeFileSystemsTests.cs @@ -45,7 +45,7 @@ namespace Umbraco.Tests.Scoping { TestHelper.DeleteDirectory(IOHelper.MapPath("media")); TestHelper.DeleteDirectory(IOHelper.MapPath("FileSysTests")); - TestHelper.DeleteDirectory(IOHelper.MapPath("App_Data/TEMP/ShadowFs")); + TestHelper.DeleteDirectory(IOHelper.MapPath(SystemDirectories.TempData.EnsureEndsWith('/') + "ShadowFs")); } [TestCase(true)] diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects.cs b/src/Umbraco.Tests/TestHelpers/TestObjects.cs index 412a492376..684da2599e 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects.cs @@ -185,7 +185,8 @@ namespace Umbraco.Tests.TestHelpers new PackageDataInstallation(logger, fileService.Value, macroService.Value, localizationService.Value, dataTypeService.Value, entityService.Value, contentTypeService.Value, contentService.Value, propertyEditorCollection), new PackageFileInstallation(compiledPackageXmlParser, new ProfilingLogger(logger, new TestProfiler())), compiledPackageXmlParser, Mock.Of(), - "", null, null)); + new DirectoryInfo(IOHelper.GetRootDirectorySafe()), + new DirectoryInfo(IOHelper.GetRootDirectorySafe()))); }); var relationService = GetLazyService(factory, c => new RelationService(scopeProvider, logger, eventMessagesFactory, entityService.Value, GetRepo(c), GetRepo(c))); var treeService = GetLazyService(factory, c => new ApplicationTreeService(logger, cache, typeLoader)); diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js index 057f1160c2..4afe62786e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js @@ -144,6 +144,8 @@ vm.package = updatedPackage; vm.buttonState = "success"; + formHelper.resetForm({ scope: $scope }); + if (create) { //if we are creating, then redirect to the correct url and reload $location.path("packages/packages/edit/" + vm.package.id).search("subview", "created").search("create", null); diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html index 955676b806..a66eb94746 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html @@ -138,7 +138,7 @@ {{doctype.name}} diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/views/install-local.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/views/install-local.controller.js index 8be7d1b17a..9c6c2bb7c5 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/views/install-local.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/views/install-local.controller.js @@ -10,7 +10,7 @@ vm.installPackage = installPackage; vm.installState = { status: "", - progress:0 + progress: 0 }; vm.installCompleted = false; vm.zipFile = { @@ -27,6 +27,23 @@ } }; + var labels = {}; + var labelKeys = [ + "packager_installStateImporting", + "packager_installStateInstalling", + "packager_installStateRestarting", + "packager_installStateComplete", + "packager_installStateCompleted" + ]; + + localizationService.localizeMany(labelKeys).then(function (values) { + labels.installStateImporting = values[0]; + labels.installStateInstalling = values[1]; + labels.installStateRestarting = values[2]; + labels.installStateComplete = values[3]; + labels.installStateCompleted = values[4]; + }); + function upload(file) { Upload.upload({ @@ -34,10 +51,10 @@ fields: {}, file: file }).progress(function (evt) { - + // hack: in some browsers the progress event is called after success // this prevents the UI from going back to a uploading state - if(vm.zipFile.uploadStatus !== "done" && vm.zipFile.uploadStatus !== "error") { + if (vm.zipFile.uploadStatus !== "done" && vm.zipFile.uploadStatus !== "error") { // set view state to uploading vm.state = 'uploading'; @@ -110,83 +127,85 @@ } function installPackage() { - vm.installState.status = localizationService.localize("packager_installStateImporting"); + + vm.installState.status = labels.installStateImporting; vm.installState.progress = "0"; packageResource - .import(vm.localPackage) - .then(function(pack) { - vm.installState.progress = "25"; - vm.installState.status = localizationService.localize("packager_installStateInstalling"); - return packageResource.installFiles(pack); - }, + .import(vm.localPackage) + .then(function (pack) { + vm.installState.progress = "25"; + vm.installState.status = labels.installStateInstalling; + return packageResource.installFiles(pack); + }, installError) - .then(function(pack) { - vm.installState.status = localizationService.localize("packager_installStateRestarting"); - vm.installState.progress = "50"; - var deferred = $q.defer(); + .then(function (pack) { + vm.installState.status = labels.installStateRestarting; + vm.installState.progress = "50"; + var deferred = $q.defer(); - //check if the app domain is restarted ever 2 seconds - var count = 0; - function checkRestart() { - $timeout(function () { + //check if the app domain is restarted ever 2 seconds + var count = 0; + + function checkRestart() { + $timeout(function () { packageResource.checkRestart(pack).then(function (d) { count++; //if there is an id it means it's not restarted yet but we'll limit it to only check 10 times if (d.isRestarting && count < 10) { - checkRestart(); + checkRestart(); } else { - //it's restarted! - deferred.resolve(d); + //it's restarted! + deferred.resolve(d); } - }, - installError); - }, 2000); - } + }, + installError); + }, + 2000); + } - checkRestart(); - - return deferred.promise; - }, installError) - .then(function(pack) { - vm.installState.status = localizationService.localize("packager_installStateRestarting"); - vm.installState.progress = "75"; - return packageResource.installData(pack); - }, + checkRestart(); + + return deferred.promise; + }, installError) - .then(function(pack) { - vm.installState.status = localizationService.localize("packager_installStateComplete"); - vm.installState.progress = "100"; - return packageResource.cleanUp(pack); - }, + .then(function (pack) { + vm.installState.status = labels.installStateRestarting; + vm.installState.progress = "75"; + return packageResource.installData(pack); + }, installError) - .then(function(result) { + .then(function (pack) { + vm.installState.status = labels.installStateComplete; + vm.installState.progress = "100"; + return packageResource.cleanUp(pack); + }, + installError) + .then(function (result) { - if (result.postInstallationPath) { - //Put the redirect Uri in a cookie so we can use after reloading - localStorageService.set("packageInstallUri", result.postInstallationPath); - } - else { - //set to a constant value so it knows to just go to the installed view - localStorageService.set("packageInstallUri", "installed"); - } + if (result.postInstallationPath) { + //Put the redirect Uri in a cookie so we can use after reloading + localStorageService.set("packageInstallUri", result.postInstallationPath); + } + else { + //set to a constant value so it knows to just go to the installed view + localStorageService.set("packageInstallUri", "installed"); + } - vm.installState.status = localizationService.localize("packager_installStateCompleted"); - vm.installCompleted = true; - - + vm.installState.status = labels.installStateCompleted; + vm.installCompleted = true; - }, - installError); + + }, installError); } - + function installError() { //This will return a rejection meaning that the promise change above will stop return $q.reject(); } - vm.reloadPage = function() { + vm.reloadPage = function () { //reload on next digest (after cookie) $timeout(function () { $window.location.reload(true); diff --git a/src/Umbraco.Web/Editors/Binders/ContentModelBinderHelper.cs b/src/Umbraco.Web/Editors/Binders/ContentModelBinderHelper.cs index 8c3edd915d..dd6d22a967 100644 --- a/src/Umbraco.Web/Editors/Binders/ContentModelBinderHelper.cs +++ b/src/Umbraco.Web/Editors/Binders/ContentModelBinderHelper.cs @@ -3,6 +3,7 @@ using System.Net.Http; using System.Web.Http; using System.Web.Http.Controllers; using Umbraco.Core; +using Umbraco.Core.IO; using Umbraco.Core.Models; using Umbraco.Core.Models.Editors; using Umbraco.Web.Models.ContentEditing; @@ -19,7 +20,7 @@ namespace Umbraco.Web.Editors.Binders public TModelSave BindModelFromMultipartRequest(HttpActionContext actionContext, ModelBindingContext bindingContext) where TModelSave : IHaveUploadedFiles { - var result = actionContext.ReadAsMultipart("~/App_Data/TEMP/FileUploads"); + var result = actionContext.ReadAsMultipart(SystemDirectories.TempFileUploads); var model = actionContext.GetModelFromMultipartRequest(result, "contentItem"); diff --git a/src/Umbraco.Web/Editors/ContentTypeController.cs b/src/Umbraco.Web/Editors/ContentTypeController.cs index 97f7ff3589..670d37e7a7 100644 --- a/src/Umbraco.Web/Editors/ContentTypeController.cs +++ b/src/Umbraco.Web/Editors/ContentTypeController.cs @@ -17,6 +17,7 @@ using Umbraco.Core.Dictionary; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models; +using Umbraco.Core.Models.Editors; using Umbraco.Core.Packaging; using Umbraco.Core.Persistence; using Umbraco.Core.PropertyEditors; @@ -532,7 +533,7 @@ namespace Umbraco.Web.Editors throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType); } - var root = IOHelper.MapPath("~/App_Data/TEMP/FileUploads"); + var root = IOHelper.MapPath(SystemDirectories.TempData.EnsureEndsWith('/') + "FileUploads"); //ensure it exists Directory.CreateDirectory(root); var provider = new MultipartFormDataStreamProvider(root); @@ -545,26 +546,24 @@ namespace Umbraco.Web.Editors } var model = new ContentTypeImportModel(); + var file = result.FileData[0]; var fileName = file.Headers.ContentDisposition.FileName.Trim('\"'); var ext = fileName.Substring(fileName.LastIndexOf('.') + 1).ToLower(); if (ext.InvariantEquals("udt")) { - //TODO: Currently it has to be here, it's not ideal but that's the way it is right now - var tempDir = IOHelper.MapPath(SystemDirectories.Data); + model.TempFileName = Path.Combine(root, model.TempFileName); - //ensure it's there - Directory.CreateDirectory(tempDir); - - model.TempFileName = "justDelete_" + Guid.NewGuid() + ".udt"; - var tempFileLocation = Path.Combine(tempDir, model.TempFileName); - System.IO.File.Copy(file.LocalFileName, tempFileLocation, true); + model.UploadedFiles.Add(new ContentPropertyFile + { + TempFilePath = model.TempFileName + }); var xd = new XmlDocument { XmlResolver = null }; - xd.Load(tempFileLocation); + xd.Load(model.TempFileName); model.Alias = xd.DocumentElement?.SelectSingleNode("//DocumentType/Info/Alias")?.FirstChild.Value; model.Name = xd.DocumentElement?.SelectSingleNode("//DocumentType/Info/Name")?.FirstChild.Value; diff --git a/src/Umbraco.Web/Editors/MediaController.cs b/src/Umbraco.Web/Editors/MediaController.cs index 2c6ba06dc2..ce088e0caa 100644 --- a/src/Umbraco.Web/Editors/MediaController.cs +++ b/src/Umbraco.Web/Editors/MediaController.cs @@ -626,7 +626,7 @@ namespace Umbraco.Web.Editors throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType); } - var root = IOHelper.MapPath("~/App_Data/TEMP/FileUploads"); + var root = IOHelper.MapPath(SystemDirectories.TempFileUploads); //ensure it exists Directory.CreateDirectory(root); var provider = new MultipartFormDataStreamProvider(root); diff --git a/src/Umbraco.Web/Editors/PackageController.cs b/src/Umbraco.Web/Editors/PackageController.cs index 4b452ac6a6..063dcf483e 100644 --- a/src/Umbraco.Web/Editors/PackageController.cs +++ b/src/Umbraco.Web/Editors/PackageController.cs @@ -13,7 +13,7 @@ using Umbraco.Web.WebApi.Filters; namespace Umbraco.Web.Editors { /// - /// A controller used for installing packages and managing all of the data in the packages section in the back office + /// A controller used for managing packages in the back office /// [PluginController("UmbracoApi")] [SerializeVersion] diff --git a/src/Umbraco.Web/Editors/PackageInstallController.cs b/src/Umbraco.Web/Editors/PackageInstallController.cs index bfaec3f82c..38b75a27f8 100644 --- a/src/Umbraco.Web/Editors/PackageInstallController.cs +++ b/src/Umbraco.Web/Editors/PackageInstallController.cs @@ -16,6 +16,7 @@ using Umbraco.Core.Events; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models; +using Umbraco.Core.Models.Editors; using Umbraco.Core.Models.Packaging; using Umbraco.Core.Packaging; using Umbraco.Core.Persistence; @@ -42,14 +43,11 @@ namespace Umbraco.Web.Editors [UmbracoApplicationAuthorize(Core.Constants.Applications.Packages)] public class PackageInstallController : UmbracoAuthorizedJsonController { - private readonly IPackageActionRunner _packageActionRunner; - public PackageInstallController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, - IProfilingLogger logger, IRuntimeState runtimeState, IPackageActionRunner packageActionRunner) + IProfilingLogger logger, IRuntimeState runtimeState) : base(globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) { - _packageActionRunner = packageActionRunner; } /// @@ -75,7 +73,7 @@ namespace Umbraco.Web.Editors var package = Services.PackagingService.GetInstalledPackageById(packageId); if (package == null) return NotFound(); - PerformUninstall(package); + var summary = Services.PackagingService.UninstallPackage(package); //now get all other packages by this name since we'll uninstall all versions foreach (var installed in Services.PackagingService.GetAllInstalledPackages() @@ -94,176 +92,6 @@ namespace Umbraco.Web.Editors return Ok(); } - /// - /// SORRY :( I didn't have time to put this in a service somewhere - the old packager did this all manually too - /// - /// - protected void PerformUninstall(PackageDefinition package) - { - if (package == null) throw new ArgumentNullException("package"); - - var removedTemplates = new List(); - var removedMacros = new List(); - var removedContentTypes = new List(); - var removedDictionaryItems = new List(); - var removedDataTypes = new List(); - var removedFiles = new List(); - - //Uninstall templates - foreach (var item in package.Templates.ToArray()) - { - int nId; - if (int.TryParse(item, out nId) == false) continue; - var found = Services.FileService.GetTemplate(nId); - if (found != null) - { - removedTemplates.Add(found); - Services.FileService.DeleteTemplate(found.Alias, Security.GetUserId().ResultOr(0)); - } - package.Templates.Remove(nId.ToString()); - } - - //Uninstall macros - foreach (var item in package.Macros.ToArray()) - { - int nId; - if (int.TryParse(item, out nId) == false) continue; - var macro = Services.MacroService.GetById(nId); - if (macro != null) - { - removedMacros.Add(macro); - Services.MacroService.Delete(macro); - } - package.Macros.Remove(nId.ToString()); - } - - //Remove Document Types - var contentTypes = new List(); - var contentTypeService = Services.ContentTypeService; - foreach (var item in package.DocumentTypes.ToArray()) - { - int nId; - if (int.TryParse(item, out nId) == false) continue; - var contentType = contentTypeService.Get(nId); - if (contentType == null) continue; - contentTypes.Add(contentType); - package.DocumentTypes.Remove(nId.ToString(CultureInfo.InvariantCulture)); - } - - //Order the DocumentTypes before removing them - if (contentTypes.Any()) - { - //TODO: I don't think this ordering is necessary - var orderedTypes = from contentType in contentTypes - orderby contentType.ParentId descending, contentType.Id descending - select contentType; - removedContentTypes.AddRange(orderedTypes); - contentTypeService.Delete(orderedTypes); - } - - //Remove Dictionary items - foreach (var item in package.DictionaryItems.ToArray()) - { - int nId; - if (int.TryParse(item, out nId) == false) continue; - var di = Services.LocalizationService.GetDictionaryItemById(nId); - if (di != null) - { - removedDictionaryItems.Add(di); - Services.LocalizationService.Delete(di); - } - package.DictionaryItems.Remove(nId.ToString()); - } - - //Remove Data types - foreach (var item in package.DataTypes.ToArray()) - { - int nId; - if (int.TryParse(item, out nId) == false) continue; - var dtd = Services.DataTypeService.GetDataType(nId); - if (dtd != null) - { - removedDataTypes.Add(dtd); - Services.DataTypeService.Delete(dtd); - } - package.DataTypes.Remove(nId.ToString()); - } - - Services.PackagingService.SaveInstalledPackage(package); - - // uninstall actions - //TODO: We should probably report errors to the UI!! - // This never happened before though, but we should do something now - if (package.Actions.IsNullOrWhiteSpace() == false) - { - try - { - var actionsXml = XDocument.Parse("" + package.Actions + ""); - - Logger.Debug("Executing undo actions: {UndoActionsXml}", actionsXml.ToString(SaveOptions.DisableFormatting)); - - foreach (var n in actionsXml.Root.Elements("Action")) - { - try - { - _packageActionRunner.UndoPackageAction(package.Name, n.AttributeValue("alias"), n); - } - catch (Exception ex) - { - Logger.Error(ex, "An error occurred running undo actions"); - } - } - } - catch (Exception ex) - { - Logger.Error(ex, "An error occurred running undo actions"); - } - } - - //moved remove of files here so custom package actions can still undo - //Remove files - foreach (var item in package.Files.ToArray()) - { - removedFiles.Add(item.GetRelativePath()); - - //here we need to try to find the file in question as most packages does not support the tilde char - var file = IOHelper.FindFile(item); - if (file != null) - { - if (file.StartsWith("/") == false) - file = string.Format("/{0}", file); - var filePath = IOHelper.MapPath(file); - - if (File.Exists(filePath)) - File.Delete(filePath); - - } - package.Files.Remove(file); - } - - Services.PackagingService.SaveInstalledPackage(package); - - Services.PackagingService.DeleteInstalledPackage(package.Id, Security.GetUserId().ResultOr(0)); - - // create a summary of what was actually removed, for PackagingService.UninstalledPackage - var summary = new UninstallationSummary - { - MetaData = package, - TemplatesUninstalled = removedTemplates, - MacrosUninstalled = removedMacros, - ContentTypesUninstalled = removedContentTypes, - DictionaryItemsUninstalled = removedDictionaryItems, - DataTypesUninstalled = removedDataTypes, - FilesUninstalled = removedFiles, - PackageUninstalled = true - }; - - // trigger the UninstalledPackage event - // fixme: This all needs to be part of the service! - PackagingService.OnUninstalledPackage(new UninstallPackageEventArgs(summary, package, false)); - - } - /// /// Returns all installed packages - only shows their latest versions /// @@ -302,7 +130,9 @@ namespace Umbraco.Web.Editors private void PopulateFromPackageData(LocalPackageInstallModel model) { - var ins = Services.PackagingService.GetCompiledPackageInfo(model.ZipFilePath); + var zipFile = new FileInfo(Path.Combine(IOHelper.MapPath(SystemDirectories.Packages), model.ZipFileName)); + + var ins = Services.PackagingService.GetCompiledPackageInfo(zipFile); model.Name = ins.Name; model.Author = ins.Author; @@ -365,11 +195,9 @@ namespace Umbraco.Web.Editors public async Task UploadLocalPackage() { if (Request.Content.IsMimeMultipartContent() == false) - { throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType); - } - var root = IOHelper.MapPath("~/App_Data/TEMP/FileUploads"); + var root = IOHelper.MapPath(SystemDirectories.TempFileUploads); //ensure it exists Directory.CreateDirectory(root); var provider = new MultipartFormDataStreamProvider(root); @@ -378,38 +206,36 @@ namespace Umbraco.Web.Editors //must have a file if (result.FileData.Count == 0) - { throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound)); - } - //TODO: App/Tree Permissions? var model = new LocalPackageInstallModel { + //Generate a new package Id for this, we'll use this later for tracking, when persisting, saving the file, etc... PackageGuid = Guid.NewGuid() }; //get the files foreach (var file in result.FileData) { - var fileName = file.Headers.ContentDisposition.FileName.Trim(new[] { '\"' }); + var fileName = file.Headers.ContentDisposition.FileName.Trim('\"'); var ext = fileName.Substring(fileName.LastIndexOf('.') + 1).ToLower(); - //TODO: Only allow .zip if (ext.InvariantEquals("zip") || ext.InvariantEquals("umb")) { - //TODO: Currently it has to be here, it's not ideal but that's the way it is right now - var packageTempDir = IOHelper.MapPath(SystemDirectories.Data); + //we always save package files to /App_Data/packages/package-guid.umb for processing as a standard so lets copy. + + var packagesFolder = IOHelper.MapPath(SystemDirectories.Packages); + Directory.CreateDirectory(packagesFolder); + var packageFile = Path.Combine(packagesFolder, model.PackageGuid + ".umb"); + File.Copy(file.LocalFileName, packageFile); - //ensure it's there - Directory.CreateDirectory(packageTempDir); + model.ZipFileName = Path.GetFileName(packageFile); - //copy it - must always be '.umb' for the installer thing to work - //the file name must be a GUID - this is what the packager expects (strange yes) - //because essentially this is creating a temporary package Id that will be used - //for unpacking/installing/etc... - model.ZipFilePath = model.PackageGuid + ".umb"; - var packageTempFileLocation = Path.Combine(packageTempDir, model.ZipFilePath); - File.Copy(file.LocalFileName, packageTempFileLocation, true); + //add to the outgoing model so that all temp files are cleaned up + model.UploadedFiles.Add(new ContentPropertyFile + { + TempFilePath = file.LocalFileName + }); //Populate the model from the metadata in the package file (zip file) PopulateFromPackageData(model); @@ -447,17 +273,22 @@ namespace Umbraco.Web.Editors public async Task Fetch(string packageGuid) { //Default path - string path = Path.Combine("packages", packageGuid + ".umb"); - if (File.Exists(IOHelper.MapPath(Path.Combine(SystemDirectories.Data, path))) == false) + string fileName = packageGuid + ".umb"; + if (File.Exists(Path.Combine(IOHelper.MapPath(SystemDirectories.Packages), fileName)) == false) { - path = await Services.PackagingService.FetchPackageFileAsync(Guid.Parse(packageGuid), UmbracoVersion.Current, Security.GetUserId().ResultOr(0)); + var packageFile = await Services.PackagingService.FetchPackageFileAsync( + Guid.Parse(packageGuid), + UmbracoVersion.Current, + Security.GetUserId().ResultOr(0)); + + fileName = packageFile.Name; } var model = new LocalPackageInstallModel { PackageGuid = Guid.Parse(packageGuid), - RepositoryGuid = Guid.Parse("65194810-1f85-11dd-bd0b-0800200c9a66"), - ZipFilePath = path + //RepositoryGuid = Guid.Parse("65194810-1f85-11dd-bd0b-0800200c9a66"), + ZipFileName = fileName }; //Populate the model from the metadata in the package file (zip file) @@ -483,7 +314,9 @@ namespace Umbraco.Web.Editors [HttpPost] public PackageInstallModel Import(PackageInstallModel model) { - var packageInfo = Services.PackagingService.GetCompiledPackageInfo(model.ZipFilePath); + var zipFile = new FileInfo(Path.Combine(IOHelper.MapPath(SystemDirectories.Packages), model.ZipFileName)); + + var packageInfo = Services.PackagingService.GetCompiledPackageInfo(zipFile); //now we need to check for version comparison if (packageInfo.UmbracoVersionRequirementsType == RequirementsType.Strict) @@ -497,9 +330,10 @@ namespace Umbraco.Web.Editors } var packageDefinition = PackageDefinition.FromCompiledPackage(packageInfo); + packageDefinition.PackageId = model.PackageGuid; //We must re-map the original package GUID that was generated + packageDefinition.PackagePath = zipFile.FullName; //save to the installedPackages.config - packageDefinition.PackageId = model.PackageGuid; //fixme: why are we doing this? Services.PackagingService.SaveInstalledPackage(packageDefinition); model.Id = packageDefinition.Id; @@ -518,7 +352,9 @@ namespace Umbraco.Web.Editors var definition = Services.PackagingService.GetInstalledPackageById(model.Id); if (definition == null) throw new InvalidOperationException("Not package definition found with id " + model.Id); - Services.PackagingService.InstallCompiledPackageFiles(definition, model.ZipFilePath, Security.GetUserId().ResultOr(0)); + var zipFile = new FileInfo(definition.PackagePath); + + var installedFiles = Services.PackagingService.InstallCompiledPackageFiles(definition, zipFile, Security.GetUserId().ResultOr(0)); //set a restarting marker and reset the app pool Current.RestartAppPool(Request.TryGetHttpContext().Result); @@ -553,7 +389,10 @@ namespace Umbraco.Web.Editors var definition = Services.PackagingService.GetInstalledPackageById(model.Id); if (definition == null) throw new InvalidOperationException("Not package definition found with id " + model.Id); - Services.PackagingService.InstallCompiledPackageData(definition, model.ZipFilePath, Security.GetUserId().ResultOr(0)); + var zipFile = new FileInfo(definition.PackagePath); + + var installSummary = Services.PackagingService.InstallCompiledPackageData(definition, zipFile, Security.GetUserId().ResultOr(0)); + return model; } @@ -565,7 +404,12 @@ namespace Umbraco.Web.Editors [HttpPost] public PackageInstallResult CleanUp(PackageInstallModel model) { - var packageInfo = Services.PackagingService.GetCompiledPackageInfo(model.ZipFilePath); + var definition = Services.PackagingService.GetInstalledPackageById(model.Id); + if (definition == null) throw new InvalidOperationException("Not package definition found with id " + model.Id); + + var zipFile = new FileInfo(definition.PackagePath); + + var packageInfo = Services.PackagingService.GetCompiledPackageInfo(zipFile); var clientDependencyConfig = new ClientDependencyConfiguration(Logger); var clientDependencyUpdated = clientDependencyConfig.UpdateVersionNumber( @@ -585,9 +429,9 @@ namespace Umbraco.Web.Editors return new PackageInstallResult { Id = model.Id, - ZipFilePath = model.ZipFilePath, + ZipFileName = model.ZipFileName, PackageGuid = model.PackageGuid, - RepositoryGuid = model.RepositoryGuid, + //RepositoryGuid = model.RepositoryGuid, PostInstallationPath = redirectUrl }; diff --git a/src/Umbraco.Web/Editors/UsersController.cs b/src/Umbraco.Web/Editors/UsersController.cs index 7577624621..e46e83c6e4 100644 --- a/src/Umbraco.Web/Editors/UsersController.cs +++ b/src/Umbraco.Web/Editors/UsersController.cs @@ -70,7 +70,7 @@ namespace Umbraco.Web.Editors throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType); } - var root = IOHelper.MapPath("~/App_Data/TEMP/FileUploads"); + var root = IOHelper.MapPath(SystemDirectories.TempFileUploads); //ensure it exists Directory.CreateDirectory(root); var provider = new MultipartFormDataStreamProvider(root); diff --git a/src/Umbraco.Web/Install/Controllers/InstallPackageController.cs b/src/Umbraco.Web/Install/Controllers/InstallPackageController.cs index dd9b0a42d0..81cb1e2e39 100644 --- a/src/Umbraco.Web/Install/Controllers/InstallPackageController.cs +++ b/src/Umbraco.Web/Install/Controllers/InstallPackageController.cs @@ -1,196 +1,196 @@ -using System; -using System.Linq; -using System.Net; -using System.Net.Http; -using System.Text; -using System.Threading.Tasks; -using System.Web; -using System.Web.Http; -using Newtonsoft.Json.Linq; -using umbraco; -using Umbraco.Core; -using Umbraco.Web.Cache; -using Umbraco.Core.Configuration; -using Umbraco.Core.Models.Packaging; -using Umbraco.Core.Services; -using Umbraco.Web.Composing; -using Umbraco.Web.Install.Models; -using Umbraco.Web.WebApi; +//using System; +//using System.Linq; +//using System.Net; +//using System.Net.Http; +//using System.Text; +//using System.Threading.Tasks; +//using System.Web; +//using System.Web.Http; +//using Newtonsoft.Json.Linq; +//using umbraco; +//using Umbraco.Core; +//using Umbraco.Web.Cache; +//using Umbraco.Core.Configuration; +//using Umbraco.Core.Models.Packaging; +//using Umbraco.Core.Services; +//using Umbraco.Web.Composing; +//using Umbraco.Web.Install.Models; +//using Umbraco.Web.WebApi; -namespace Umbraco.Web.Install.Controllers -{ - /// - /// A controller for the installation process regarding packages - /// - /// - /// Currently this is used for web services however we should/could eventually migrate the whole installer to MVC as it - /// is a bit of a mess currently. - /// - [HttpInstallAuthorize] - [AngularJsonOnlyConfiguration] - [Obsolete("This is only used for the legacy way of installing starter kits in the back office")] - //fixme: Is this used anymore?? - public class InstallPackageController : ApiController - { - private readonly IPackagingService _packagingService; - private readonly UmbracoContext _umbracoContext; +//namespace Umbraco.Web.Install.Controllers +//{ +// /// +// /// A controller for the installation process regarding packages +// /// +// /// +// /// Currently this is used for web services however we should/could eventually migrate the whole installer to MVC as it +// /// is a bit of a mess currently. +// /// +// [HttpInstallAuthorize] +// [AngularJsonOnlyConfiguration] +// [Obsolete("This is only used for the legacy way of installing starter kits in the back office")] +// //fixme: Is this used anymore?? +// public class InstallPackageController : ApiController +// { +// private readonly IPackagingService _packagingService; +// private readonly UmbracoContext _umbracoContext; - public InstallPackageController(IPackagingService packagingService, UmbracoContext umbracoContext) - { - _packagingService = packagingService; - _umbracoContext = umbracoContext; - } +// public InstallPackageController(IPackagingService packagingService, UmbracoContext umbracoContext) +// { +// _packagingService = packagingService; +// _umbracoContext = umbracoContext; +// } - /// - /// Empty action, useful for retrieving the base url for this controller - /// - /// - [HttpGet] - public HttpResponseMessage Index() - { - throw new NotImplementedException(); - } +// /// +// /// Empty action, useful for retrieving the base url for this controller +// /// +// /// +// [HttpGet] +// public HttpResponseMessage Index() +// { +// throw new NotImplementedException(); +// } - /// - /// Connects to the repo, downloads the package and creates the definition - /// - /// - /// - [HttpPost] - public async Task DownloadPackageFiles(InstallPackageModel model) - { - var packageFile = await _packagingService.FetchPackageFileAsync( - model.KitGuid, - UmbracoVersion.Current, - UmbracoContext.Current.Security.CurrentUser.Id); +// /// +// /// Connects to the repo, downloads the package and creates the definition +// /// +// /// +// /// +// [HttpPost] +// public async Task DownloadPackageFiles(InstallPackageModel model) +// { +// var packageFile = await _packagingService.FetchPackageFileAsync( +// model.KitGuid, +// UmbracoVersion.Current, +// UmbracoContext.Current.Security.CurrentUser.Id); - var packageInfo = _packagingService.GetCompiledPackageInfo(packageFile); - if (packageInfo == null) throw new InvalidOperationException("Could not read package file " + packageFile); +// var packageInfo = _packagingService.GetCompiledPackageInfo(packageFile); +// if (packageInfo == null) throw new InvalidOperationException("Could not read package file " + packageFile); - //save to the installedPackages.config - var packageDefinition = PackageDefinition.FromCompiledPackage(packageInfo); - _packagingService.SaveInstalledPackage(packageDefinition); +// //save to the installedPackages.config +// var packageDefinition = PackageDefinition.FromCompiledPackage(packageInfo); +// _packagingService.SaveInstalledPackage(packageDefinition); - return Json(new - { - success = true, - packageId = packageDefinition.Id, - packageFile = packageInfo.PackageFileName, - percentage = 10, - message = "Downloading starter kit files..." - }, HttpStatusCode.OK); - } +// return Json(new +// { +// success = true, +// packageId = packageDefinition.Id, +// packageFile = packageInfo.PackageFileName, +// percentage = 10, +// message = "Downloading starter kit files..." +// }, HttpStatusCode.OK); +// } - /// - /// Installs the files in the package - /// - /// - [HttpPost] - public HttpResponseMessage InstallPackageFiles(InstallPackageModel model) - { - model.PackageFile = HttpUtility.UrlDecode(model.PackageFile); +// /// +// /// Installs the files in the package +// /// +// /// +// [HttpPost] +// public HttpResponseMessage InstallPackageFiles(InstallPackageModel model) +// { +// model.PackageFile = HttpUtility.UrlDecode(model.PackageFile); - var definition = _packagingService.GetInstalledPackageById(model.PackageId); - if (definition == null) throw new InvalidOperationException("Not package definition found with id " + model.PackageId); +// var definition = _packagingService.GetInstalledPackageById(model.PackageId); +// if (definition == null) throw new InvalidOperationException("Not package definition found with id " + model.PackageId); - _packagingService.InstallCompiledPackageFiles(definition, model.PackageFile, _umbracoContext.Security.GetUserId().ResultOr(0)); +// _packagingService.InstallCompiledPackageFiles(definition, model.PackageFile, _umbracoContext.Security.GetUserId().ResultOr(0)); - return Json(new - { - success = true, - ManifestId = model.PackageId, - model.PackageFile, - percentage = 20, - message = "Installing starter kit files" - }, HttpStatusCode.OK); - } +// return Json(new +// { +// success = true, +// ManifestId = model.PackageId, +// model.PackageFile, +// percentage = 20, +// message = "Installing starter kit files" +// }, HttpStatusCode.OK); +// } - /// - /// Ensures the app pool is restarted - /// - /// - [HttpPost] - public HttpResponseMessage RestartAppPool() - { - Current.RestartAppPool(Request.TryGetHttpContext().Result); - return Json(new - { - success = true, - percentage = 25, - message = "Installing starter kit files" - }, HttpStatusCode.OK); - } +// /// +// /// Ensures the app pool is restarted +// /// +// /// +// [HttpPost] +// public HttpResponseMessage RestartAppPool() +// { +// Current.RestartAppPool(Request.TryGetHttpContext().Result); +// return Json(new +// { +// success = true, +// percentage = 25, +// message = "Installing starter kit files" +// }, HttpStatusCode.OK); +// } - /// - /// Checks if the app pool has completed restarted - /// - /// - [HttpPost] - public HttpResponseMessage CheckAppPoolRestart() - { - if (Request.TryGetHttpContext().Result.Application.AllKeys.Contains("AppPoolRestarting")) - { - return Request.CreateResponse(HttpStatusCode.BadRequest); - } +// /// +// /// Checks if the app pool has completed restarted +// /// +// /// +// [HttpPost] +// public HttpResponseMessage CheckAppPoolRestart() +// { +// if (Request.TryGetHttpContext().Result.Application.AllKeys.Contains("AppPoolRestarting")) +// { +// return Request.CreateResponse(HttpStatusCode.BadRequest); +// } - return Json(new - { - percentage = 30, - success = true, - }, HttpStatusCode.OK); - } +// return Json(new +// { +// percentage = 30, +// success = true, +// }, HttpStatusCode.OK); +// } - /// - /// Installs the business logic portion of the package after app restart - /// - /// - [HttpPost] - public HttpResponseMessage InstallBusinessLogic(InstallPackageModel model) - { - model.PackageFile = HttpUtility.UrlDecode(model.PackageFile); +// /// +// /// Installs the business logic portion of the package after app restart +// /// +// /// +// [HttpPost] +// public HttpResponseMessage InstallBusinessLogic(InstallPackageModel model) +// { +// model.PackageFile = HttpUtility.UrlDecode(model.PackageFile); - var definition = _packagingService.GetInstalledPackageById(model.PackageId); - if (definition == null) throw new InvalidOperationException("Not package definition found with id " + model.PackageId); +// var definition = _packagingService.GetInstalledPackageById(model.PackageId); +// if (definition == null) throw new InvalidOperationException("Not package definition found with id " + model.PackageId); - _packagingService.InstallCompiledPackageData(definition, model.PackageFile, _umbracoContext.Security.GetUserId().ResultOr(0)); +// _packagingService.InstallCompiledPackageData(definition, model.PackageFile, _umbracoContext.Security.GetUserId().ResultOr(0)); - return Json(new - { - success = true, - ManifestId = model.PackageId, - model.PackageFile, - percentage = 70, - message = "Installing starter kit files" - }, HttpStatusCode.OK); - } +// return Json(new +// { +// success = true, +// ManifestId = model.PackageId, +// model.PackageFile, +// percentage = 70, +// message = "Installing starter kit files" +// }, HttpStatusCode.OK); +// } - /// - /// Cleans up the package installation - /// - /// - [HttpPost] - public HttpResponseMessage CleanupInstallation(InstallPackageModel model) - { - model.PackageFile = HttpUtility.UrlDecode(model.PackageFile); +// /// +// /// Cleans up the package installation +// /// +// /// +// [HttpPost] +// public HttpResponseMessage CleanupInstallation(InstallPackageModel model) +// { +// model.PackageFile = HttpUtility.UrlDecode(model.PackageFile); - return Json(new - { - success = true, - ManifestId = model.PackageId, - model.PackageFile, - percentage = 100, - message = "Starter kit has been installed" - }, HttpStatusCode.OK); - } +// return Json(new +// { +// success = true, +// ManifestId = model.PackageId, +// model.PackageFile, +// percentage = 100, +// message = "Starter kit has been installed" +// }, HttpStatusCode.OK); +// } - private HttpResponseMessage Json(object jsonObject, HttpStatusCode status) - { - var response = Request.CreateResponse(status); - var json = JObject.FromObject(jsonObject); - response.Content = new StringContent(json.ToString(), Encoding.UTF8, "application/json"); - return response; - } - } +// private HttpResponseMessage Json(object jsonObject, HttpStatusCode status) +// { +// var response = Request.CreateResponse(status); +// var json = JObject.FromObject(jsonObject); +// response.Content = new StringContent(json.ToString(), Encoding.UTF8, "application/json"); +// return response; +// } +// } -} +//} diff --git a/src/Umbraco.Web/Install/InstallHelper.cs b/src/Umbraco.Web/Install/InstallHelper.cs index 08a552d4d4..36fb384655 100644 --- a/src/Umbraco.Web/Install/InstallHelper.cs +++ b/src/Umbraco.Web/Install/InstallHelper.cs @@ -41,31 +41,6 @@ namespace Umbraco.Web.Install return _installationType ?? (_installationType = IsBrandNewInstall ? InstallationType.NewInstall : InstallationType.Upgrade).Value; } - internal static void DeleteLegacyInstaller() - { - if (Directory.Exists(IOHelper.MapPath(SystemDirectories.Install))) - { - if (Directory.Exists(IOHelper.MapPath("~/app_data/temp/install_backup"))) - { - //this means the backup already exists with files but there's no files in it, so we'll delete the backup and re-run it - if (Directory.GetFiles(IOHelper.MapPath("~/app_data/temp/install_backup")).Any() == false) - { - Directory.Delete(IOHelper.MapPath("~/app_data/temp/install_backup"), true); - Directory.Move(IOHelper.MapPath(SystemDirectories.Install), IOHelper.MapPath("~/app_data/temp/install_backup")); - } - } - else - { - Directory.Move(IOHelper.MapPath(SystemDirectories.Install), IOHelper.MapPath("~/app_data/temp/install_backup")); - } - } - - if (Directory.Exists(IOHelper.MapPath("~/Areas/UmbracoInstall"))) - { - Directory.Delete(IOHelper.MapPath("~/Areas/UmbracoInstall"), true); - } - } - internal void InstallStatus(bool isCompleted, string errorMsg) { try diff --git a/src/Umbraco.Web/Install/InstallStatusTracker.cs b/src/Umbraco.Web/Install/InstallStatusTracker.cs index 7944100648..d93eb9a06c 100644 --- a/src/Umbraco.Web/Install/InstallStatusTracker.cs +++ b/src/Umbraco.Web/Install/InstallStatusTracker.cs @@ -24,7 +24,7 @@ namespace Umbraco.Web.Install private static string GetFile(Guid installId) { - var file = IOHelper.MapPath("~/App_Data/TEMP/Install/" + var file = IOHelper.MapPath(SystemDirectories.TempData.EnsureEndsWith('/') + "Install/" + "install_" + installId.ToString("N") + ".txt"); @@ -39,7 +39,7 @@ namespace Umbraco.Web.Install public static void ClearFiles() { - var dir = IOHelper.MapPath("~/App_Data/TEMP/Install/"); + var dir = IOHelper.MapPath(SystemDirectories.TempData.EnsureEndsWith('/') + "Install/"); if (Directory.Exists(dir)) { var files = Directory.GetFiles(dir); diff --git a/src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs b/src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs index 0fe1e333d3..0349bb4ec7 100644 --- a/src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Threading.Tasks; using System.Web; @@ -49,39 +50,38 @@ namespace Umbraco.Web.Install.InstallSteps return null; } - var result = await DownloadPackageFilesAsync(starterKitId.Value); + var (packageFile, packageId) = await DownloadPackageFilesAsync(starterKitId.Value); Current.RestartAppPool(); return new InstallSetupResult(new Dictionary { - {"packageId", result.Item2}, - {"packageFile", result.Item1} + {"packageId", packageId}, + {"packageFile", packageFile} }); } - private async Task> DownloadPackageFilesAsync(Guid kitGuid) + private async Task<(string packageFile, int packageId)> DownloadPackageFilesAsync(Guid kitGuid) { //Go get the package file from the package repo - var packageFileName = await _packageService.FetchPackageFileAsync(kitGuid, UmbracoVersion.Current, _umbracoContext.Security.GetUserId().ResultOr(0)); - if (packageFileName == null) throw new InvalidOperationException("Could not fetch package file " + kitGuid); + var packageFile = await _packageService.FetchPackageFileAsync(kitGuid, UmbracoVersion.Current, _umbracoContext.Security.GetUserId().ResultOr(0)); + if (packageFile == null) throw new InvalidOperationException("Could not fetch package file " + kitGuid); //add an entry to the installedPackages.config - var compiledPackage = _packageService.GetCompiledPackageInfo(packageFileName); + var compiledPackage = _packageService.GetCompiledPackageInfo(packageFile); var packageDefinition = PackageDefinition.FromCompiledPackage(compiledPackage); _packageService.SaveInstalledPackage(packageDefinition); - InstallPackageFiles(packageDefinition, compiledPackage.PackageFileName); + InstallPackageFiles(packageDefinition, compiledPackage.PackageFile); - return new Tuple(compiledPackage.PackageFileName, packageDefinition.Id); + return (compiledPackage.PackageFile.Name, packageDefinition.Id); } - private void InstallPackageFiles(PackageDefinition packageDefinition, string packageFileName) + private void InstallPackageFiles(PackageDefinition packageDefinition, FileInfo packageFile) { if (packageDefinition == null) throw new ArgumentNullException(nameof(packageDefinition)); - packageFileName = HttpUtility.UrlDecode(packageFileName); - _packageService.InstallCompiledPackageData(packageDefinition, packageFileName, _umbracoContext.Security.GetUserId().ResultOr(0)); + _packageService.InstallCompiledPackageData(packageDefinition, packageFile, _umbracoContext.Security.GetUserId().ResultOr(0)); } public override string View => _packageService.GetAllInstalledPackages().Any() ? string.Empty : base.View; diff --git a/src/Umbraco.Web/Install/InstallSteps/StarterKitInstallStep.cs b/src/Umbraco.Web/Install/InstallSteps/StarterKitInstallStep.cs index 9d3f38b061..805041391f 100644 --- a/src/Umbraco.Web/Install/InstallSteps/StarterKitInstallStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/StarterKitInstallStep.cs @@ -1,4 +1,5 @@ using System; +using System.IO; using System.Linq; using System.Threading.Tasks; using System.Web; @@ -30,22 +31,21 @@ namespace Umbraco.Web.Install.InstallSteps var installSteps = InstallStatusTracker.GetStatus().ToArray(); var previousStep = installSteps.Single(x => x.Name == "StarterKitDownload"); var packageId = Convert.ToInt32(previousStep.AdditionalData["packageId"]); - var packageFile = (string)previousStep.AdditionalData["packageFile"]; - InstallBusinessLogic(packageId, packageFile); + InstallBusinessLogic(packageId); Current.RestartAppPool(_httContext); return Task.FromResult(null); } - private void InstallBusinessLogic(int packageId, string packageFile) + private void InstallBusinessLogic(int packageId) { - packageFile = HttpUtility.UrlDecode(packageFile); - var definition = _packagingService.GetInstalledPackageById(packageId); if (definition == null) throw new InvalidOperationException("Not package definition found with id " + packageId); + var packageFile = new FileInfo(definition.PackagePath); + _packagingService.InstallCompiledPackageData(definition, packageFile, _umbracoContext.Security.GetUserId().ResultOr(0)); } diff --git a/src/Umbraco.Web/Models/ContentTypeImportModel.cs b/src/Umbraco.Web/Models/ContentTypeImportModel.cs index 961476e5f0..f6f9a5926d 100644 --- a/src/Umbraco.Web/Models/ContentTypeImportModel.cs +++ b/src/Umbraco.Web/Models/ContentTypeImportModel.cs @@ -1,17 +1,13 @@ using System.Collections.Generic; using System.Runtime.Serialization; +using Umbraco.Core.Models.Editors; using Umbraco.Web.Models.ContentEditing; namespace Umbraco.Web.Models { [DataContract(Name = "contentTypeImportModel")] - public class ContentTypeImportModel : INotificationModel + public class ContentTypeImportModel : INotificationModel, IHaveUploadedFiles { - public ContentTypeImportModel() - { - Notifications = new List(); - } - [DataMember(Name = "alias")] public string Alias { get; set; } @@ -19,9 +15,11 @@ namespace Umbraco.Web.Models public string Name { get; set; } [DataMember(Name = "notifications")] - public List Notifications { get; } + public List Notifications { get; } = new List(); [DataMember(Name = "tempFileName")] public string TempFileName { get; set; } + + public List UploadedFiles => new List(); } } diff --git a/src/Umbraco.Web/Models/LocalPackageInstallModel.cs b/src/Umbraco.Web/Models/LocalPackageInstallModel.cs index d1d51e1fcc..8adc9acf30 100644 --- a/src/Umbraco.Web/Models/LocalPackageInstallModel.cs +++ b/src/Umbraco.Web/Models/LocalPackageInstallModel.cs @@ -11,16 +11,10 @@ namespace Umbraco.Web.Models [DataContract(Name = "localPackageInstallModel")] public class LocalPackageInstallModel : PackageInstallModel, IHaveUploadedFiles, INotificationModel { - public LocalPackageInstallModel() - { - UploadedFiles = new List(); - Notifications = new List(); - } - - public List UploadedFiles { get; } + public List UploadedFiles { get; } = new List(); [DataMember(Name = "notifications")] - public List Notifications { get; } + public List Notifications { get; } = new List(); /// /// A flag to determine if this package is compatible to be installed diff --git a/src/Umbraco.Web/Models/PackageInstallModel.cs b/src/Umbraco.Web/Models/PackageInstallModel.cs index 1cf4a483ae..2decaeb098 100644 --- a/src/Umbraco.Web/Models/PackageInstallModel.cs +++ b/src/Umbraco.Web/Models/PackageInstallModel.cs @@ -15,13 +15,13 @@ namespace Umbraco.Web.Models [DataMember(Name = "packageGuid")] public Guid PackageGuid { get; set; } - //TODO: Do we need this? - [DataMember(Name = "repositoryGuid")] - public Guid RepositoryGuid { get; set; } + ////TODO: Do we need this? + //[DataMember(Name = "repositoryGuid")] + //public Guid RepositoryGuid { get; set; } - [DataMember(Name = "zipFilePath")] - public string ZipFilePath { get; set; } + [DataMember(Name = "zipFileName")] + public string ZipFileName { get; set; } /// /// During installation this can be used to track any pending appdomain restarts diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs index 0199a34579..422b502f80 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs @@ -17,6 +17,7 @@ using Umbraco.Core.Components; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; +using Umbraco.Core.IO; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Profiling; using Umbraco.Core.Services; @@ -77,8 +78,6 @@ namespace Umbraco.Web.Runtime // Disable the X-AspNetMvc-Version HTTP Header MvcHandler.DisableMvcResponseHeader = true; - InstallHelper.DeleteLegacyInstaller(); - // wrap view engines in the profiling engine WrapViewEngines(ViewEngines.Engines); @@ -245,7 +244,7 @@ namespace Umbraco.Web.Runtime private static void ConfigureClientDependency(IGlobalSettings globalSettings) { // Backwards compatibility - set the path and URL type for ClientDependency 1.5.1 [LK] - XmlFileMapper.FileMapDefaultFolder = "~/App_Data/TEMP/ClientDependency"; + XmlFileMapper.FileMapDefaultFolder = SystemDirectories.TempData.EnsureEndsWith('/') + "ClientDependency"; BaseCompositeFileProcessingProvider.UrlTypeDefault = CompositeUrlType.Base64QueryStrings; // Now we need to detect if we are running umbracoLocalTempStorage as EnvironmentTemp and in that case we want to change the CDF file diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 89260e59f6..36550f9b54 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -1132,7 +1132,6 @@ - diff --git a/src/Umbraco.Web/WebApi/Filters/FileUploadCleanupFilterAttribute.cs b/src/Umbraco.Web/WebApi/Filters/FileUploadCleanupFilterAttribute.cs index b60545e3cb..233ce39e52 100644 --- a/src/Umbraco.Web/WebApi/Filters/FileUploadCleanupFilterAttribute.cs +++ b/src/Umbraco.Web/WebApi/Filters/FileUploadCleanupFilterAttribute.cs @@ -14,7 +14,7 @@ using File = System.IO.File; namespace Umbraco.Web.WebApi.Filters { /// - /// Checks if the parameter is ContentItemSave and then deletes any temporary saved files from file uploads associated with the request + /// Checks if the parameter is IHaveUploadedFiles and then deletes any temporary saved files from file uploads associated with the request /// internal sealed class FileUploadCleanupFilterAttribute : ActionFilterAttribute { @@ -29,14 +29,6 @@ namespace Umbraco.Web.WebApi.Filters _incomingModel = incomingModel; } - /// - /// Returns true so that other filters can execute along with this one - /// - public override bool AllowMultiple - { - get { return true; } - } - public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) { base.OnActionExecuted(actionExecutedContext); @@ -47,8 +39,7 @@ namespace Umbraco.Web.WebApi.Filters { if (actionExecutedContext.ActionContext.ActionArguments.Any()) { - var contentItem = actionExecutedContext.ActionContext.ActionArguments.First().Value as IHaveUploadedFiles; - if (contentItem != null) + if (actionExecutedContext.ActionContext.ActionArguments.First().Value is IHaveUploadedFiles contentItem) { //cleanup any files associated foreach (var f in contentItem.UploadedFiles) @@ -104,8 +95,7 @@ namespace Umbraco.Web.WebApi.Filters if (objectContent != null) { - var uploadedFiles = objectContent.Value as IHaveUploadedFiles; - if (uploadedFiles != null) + if (objectContent.Value is IHaveUploadedFiles uploadedFiles) { if (uploadedFiles.UploadedFiles != null) { diff --git a/src/Umbraco.Web/_Legacy/PackageActions/addApplication.cs b/src/Umbraco.Web/_Legacy/PackageActions/addApplication.cs index 75614f68aa..26116820e6 100644 --- a/src/Umbraco.Web/_Legacy/PackageActions/addApplication.cs +++ b/src/Umbraco.Web/_Legacy/PackageActions/addApplication.cs @@ -11,7 +11,7 @@ namespace Umbraco.Web._Legacy.PackageActions /// This class implements the IPackageAction Interface, used to execute code when packages are installed. /// All IPackageActions only takes a PackageName and a XmlNode as input, and executes based on the data in the xmlnode. /// - public class addApplication : IPackageAction + public class AddApplication : IPackageAction { #region IPackageAction Members diff --git a/src/Umbraco.Web/_Legacy/PackageActions/addDashboardSection.cs b/src/Umbraco.Web/_Legacy/PackageActions/addDashboardSection.cs deleted file mode 100644 index 1e2e396d2c..0000000000 --- a/src/Umbraco.Web/_Legacy/PackageActions/addDashboardSection.cs +++ /dev/null @@ -1,98 +0,0 @@ -using System; -using System.Linq; -using System.Xml; -using System.Xml.Linq; -using System.Xml.XPath; -using Umbraco.Core; -using Umbraco.Core.IO; -using Umbraco.Core.Xml; -using Umbraco.Core._Legacy.PackageActions; - -namespace Umbraco.Web._Legacy.PackageActions -{ - /// - /// - /// - public class addDashboardSection : IPackageAction - { - #region IPackageAction Members - - /// - /// Installs a dashboard section. This action reuses the action XML, so it has to be valid dashboard markup. - /// - /// Name of the package. - /// The XML data. - /// true if successfull - /// - /// - /// - ///
    - /// - /// default - /// content - /// - /// - /// /usercontrols/dashboard/latestEdits.ascx - /// /usercontrols/umbracoBlog/dashboardBlogPostCreate.ascx - /// - /// - /// /usercontrols/umbracoBlog/dashboardBlogPostCreate.ascx - /// - ///
    - ///
    - ///
    - ///
    - public bool Execute(string packageName, XElement xmlData) - { - //this will need a complete section node to work... - - if (xmlData.HasElements) - { - string sectionAlias = xmlData.AttributeValue("dashboardAlias"); - string dbConfig = SystemFiles.DashboardConfig; - - var section = xmlData.Element("section"); - var dashboardFile = XDocument.Load(IOHelper.MapPath(dbConfig)); - - //don't continue if it already exists - var found = dashboardFile.XPathSelectElements("//section[@alias='" + sectionAlias + "']"); - if (!found.Any()) - { - dashboardFile.Root.Add(section); - dashboardFile.Save(IOHelper.MapPath(dbConfig)); - } - - return true; - } - - return false; - } - - - public string Alias() - { - return "addDashboardSection"; - } - - public bool Undo(string packageName, XElement xmlData) - { - - string sectionAlias = xmlData.AttributeValue("dashboardAlias"); - string dbConfig = SystemFiles.DashboardConfig; - var dashboardFile = XDocument.Load(IOHelper.MapPath(dbConfig)); - - var section = dashboardFile.XPathSelectElement("//section [@alias = '" + sectionAlias + "']"); - - if (section != null) - { - section.Remove(); - dashboardFile.Save(IOHelper.MapPath(dbConfig)); - } - - return true; - } - - #endregion - - } -} diff --git a/src/Umbraco.Web/_Legacy/PackageActions/addProxyFeedHost.cs b/src/Umbraco.Web/_Legacy/PackageActions/addProxyFeedHost.cs index bcd7d7c52f..f53adb3be0 100644 --- a/src/Umbraco.Web/_Legacy/PackageActions/addProxyFeedHost.cs +++ b/src/Umbraco.Web/_Legacy/PackageActions/addProxyFeedHost.cs @@ -7,7 +7,7 @@ using Umbraco.Core._Legacy.PackageActions; namespace Umbraco.Web._Legacy.PackageActions { - public class addProxyFeedHost : IPackageAction + public class AddProxyFeedHost : IPackageAction { #region IPackageAction Members diff --git a/src/Umbraco.Web/_Legacy/PackageActions/allowDoctype.cs b/src/Umbraco.Web/_Legacy/PackageActions/allowDoctype.cs index 2ed16e3842..f4b206a9ad 100644 --- a/src/Umbraco.Web/_Legacy/PackageActions/allowDoctype.cs +++ b/src/Umbraco.Web/_Legacy/PackageActions/allowDoctype.cs @@ -14,7 +14,7 @@ namespace Umbraco.Web._Legacy.PackageActions /// This class implements the IPackageAction Interface, used to execute code when packages are installed. /// All IPackageActions only takes a PackageName and a XmlNode as input, and executes based on the data in the xmlnode. ///
    - public class allowDoctype : IPackageAction + public class AllowDoctype : IPackageAction { #region IPackageAction Members @@ -68,7 +68,6 @@ namespace Umbraco.Web._Legacy.PackageActions return false; } - //this has no undo. /// /// This action has no undo. /// diff --git a/src/Umbraco.Web/_Legacy/PackageActions/publishRootDocument.cs b/src/Umbraco.Web/_Legacy/PackageActions/publishRootDocument.cs index f4fe17e999..f4bd7dd4fc 100644 --- a/src/Umbraco.Web/_Legacy/PackageActions/publishRootDocument.cs +++ b/src/Umbraco.Web/_Legacy/PackageActions/publishRootDocument.cs @@ -11,7 +11,7 @@ namespace Umbraco.Web._Legacy.PackageActions /// This class implements the IPackageAction Interface, used to execute code when packages are installed. /// All IPackageActions only takes a PackageName and a XmlNode as input, and executes based on the data in the xmlnode. ///
    - public class publishRootDocument : IPackageAction + public class PublishRootDocument : IPackageAction { #region IPackageAction Members @@ -29,7 +29,6 @@ namespace Umbraco.Web._Legacy.PackageActions string documentName = xmlData.AttributeValue("documentName"); - //global::umbraco.cms.businesslogic.web.Document[] rootDocs = global::umbraco.cms.businesslogic.web.Document.GetRootDocuments(); var rootDocs = Current.Services.ContentService.GetRootContent(); foreach (var rootDoc in rootDocs) @@ -44,7 +43,6 @@ namespace Umbraco.Web._Legacy.PackageActions return true; } - //this has no undo. /// /// This action has no undo. /// From 5b1ca92184fa9962a7306f0db09ac36c37d5f777 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Tue, 15 Jan 2019 12:12:35 +0100 Subject: [PATCH 350/469] Fixes for tag validation and build --- .../components/tags/umbtagseditor.directive.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/tags/umbtagseditor.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/tags/umbtagseditor.directive.js index 92c9d57ee8..3d784c999f 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/tags/umbtagseditor.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/tags/umbtagseditor.directive.js @@ -181,7 +181,7 @@ else { vm.onValueChanged({ value: [] }); } - + reValidate(); } @@ -190,7 +190,7 @@ */ function validateMandatory() { return { - isValid: !vm.validation.mandatory || (vm.viewModel != null && vm.viewModel.length > 0), + isValid: !vm.validation.mandatory || (vm.viewModel != null && vm.viewModel.length > 0)|| (vm.value != null && vm.value.length > 0), errorMsg: "Value cannot be empty", errorKey: "required" }; @@ -271,12 +271,12 @@ return ($.inArray(suggestion.value, vm.viewModel) === -1); }); } - + function reValidate() { //this is required to re-validate vm.tagEditorForm.tagCount.$setViewValue(vm.viewModel.length); - { - + } + } })(); From a5efc25c8152db9a4d38b138a0e3f46c9cc5ea93 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Tue, 15 Jan 2019 12:23:14 +0100 Subject: [PATCH 351/469] Revert "Support IContentType.IsElement" This reverts commit ba38b67b --- .../services/umbdataformatter.service.js | 18 +++++++-------- .../permissions/permissions.controller.js | 22 ++++++++++++------- .../views/permissions/permissions.html | 20 ++--------------- src/Umbraco.Web.UI/Umbraco/config/lang/en.xml | 2 -- .../Umbraco/config/lang/en_us.xml | 2 -- .../ContentTypeCompositionDisplay.cs | 4 ---- .../Models/ContentEditing/ContentTypeSave.cs | 3 --- 7 files changed, 25 insertions(+), 46 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/umbdataformatter.service.js b/src/Umbraco.Web.UI.Client/src/common/services/umbdataformatter.service.js index 1e6fc5d643..e31742e660 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/umbdataformatter.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/umbdataformatter.service.js @@ -64,7 +64,7 @@ var saveModel = _.pick(displayModel, 'compositeContentTypes', 'isContainer', 'allowAsRoot', 'allowedTemplates', 'allowedContentTypes', 'alias', 'description', 'thumbnail', 'name', 'id', 'icon', 'trashed', - 'key', 'parentId', 'alias', 'path', 'allowCultureVariant', 'isElement'); + 'key', 'parentId', 'alias', 'path', 'allowCultureVariant'); //TODO: Map these saveModel.allowedTemplates = _.map(displayModel.allowedTemplates, function (t) { return t.alias; }); @@ -262,7 +262,7 @@ saveModel[props[m]] = startId.id; } - saveModel.parentId = -1; + saveModel.parentId = -1; return saveModel; }, @@ -293,7 +293,7 @@ }); saveModel.email = propEmail.value.trim(); saveModel.username = propLogin.value.trim(); - + saveModel.password = this.formatChangePasswordModel(propPass.value); var selectedGroups = []; @@ -336,7 +336,7 @@ /** formats the display model used to display the media to the model used to save the media */ formatMediaPostData: function (displayModel, action) { - //NOTE: the display model inherits from the save model so we can in theory just post up the display model but + //NOTE: the display model inherits from the save model so we can in theory just post up the display model but // we don't want to post all of the data as it is unecessary. var saveModel = { id: displayModel.id, @@ -354,7 +354,7 @@ /** formats the display model used to display the content to the model used to save the content */ formatContentPostData: function (displayModel, action) { - //NOTE: the display model inherits from the save model so we can in theory just post up the display model but + //NOTE: the display model inherits from the save model so we can in theory just post up the display model but // we don't want to post all of the data as it is unecessary. var saveModel = { id: displayModel.id, @@ -379,7 +379,7 @@ var propExpireDate = displayModel.removeDate; var propReleaseDate = displayModel.releaseDate; var propTemplate = displayModel.template; - + saveModel.expireDate = propExpireDate ? propExpireDate : null; saveModel.releaseDate = propReleaseDate ? propReleaseDate : null; saveModel.templateAlias = propTemplate ? propTemplate : null; @@ -389,8 +389,8 @@ /** * This formats the server GET response for a content display item - * @param {} displayModel - * @returns {} + * @param {} displayModel + * @returns {} */ formatContentGetData: function(displayModel) { @@ -418,7 +418,7 @@ } }); }); - + //now assign this same invariant property instance to the same index of the other variants property array for (var j = 1; j < displayModel.variants.length; j++) { diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.controller.js b/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.controller.js index 317fe094ae..4a7a870618 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.controller.js @@ -25,7 +25,6 @@ vm.removeChild = removeChild; vm.toggleAllowAsRoot = toggleAllowAsRoot; vm.toggleAllowCultureVariants = toggleAllowCultureVariants; - vm.toggleIsElement = toggleIsElement; /* ---------- INIT ---------- */ @@ -85,18 +84,25 @@ $scope.model.allowedContentTypes.splice(selectedChildIndex, 1); } - // note: "safe toggling" here ie handling cases where the value is undefined, etc + /** + * Toggle the $scope.model.allowAsRoot value to either true or false + */ + function toggleAllowAsRoot(){ + if($scope.model.allowAsRoot){ + $scope.model.allowAsRoot = false; + return; + } - function toggleAllowAsRoot() { - $scope.model.allowAsRoot = $scope.model.allowAsRoot ? false : true; + $scope.model.allowAsRoot = true; } function toggleAllowCultureVariants() { - $scope.model.allowCultureVariant = $scope.model.allowCultureVariant ? false : true; - } + if ($scope.model.allowCultureVariant) { + $scope.model.allowCultureVariant = false; + return; + } - function toggleIsElement() { - $scope.model.isElement = $scope.model.isElement ? false : true; + $scope.model.allowCultureVariant = true; } } diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.html b/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.html index 0d74c655d7..ec1e528f8c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.html +++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.html @@ -53,25 +53,9 @@ hotkey="alt+shift+v"> - + -
    - -
    -
    - -
    - -
    - - -
    - -
    - - + diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml index 987203442a..386d3af518 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml @@ -1518,8 +1518,6 @@ To manage your website, simply open the Umbraco back office and start adding con Allow varying by culture Allow editors to create content of this type in different languages Allow varying by culture - Is an Element type - An Element type is meant to be used for instance in Nested Content, and not in the tree Building models diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml index 1860d3afc9..5de373f571 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml @@ -1559,8 +1559,6 @@ To manage your website, simply open the Umbraco back office and start adding con Allow varying by culture Allow editors to create content of this type in different languages Allow varying by culture - Is an Element type - An Element type is meant to be used for instance in Nested Content, and not in the tree Add language diff --git a/src/Umbraco.Web/Models/ContentEditing/ContentTypeCompositionDisplay.cs b/src/Umbraco.Web/Models/ContentEditing/ContentTypeCompositionDisplay.cs index e5e74c2749..7211ddbf61 100644 --- a/src/Umbraco.Web/Models/ContentEditing/ContentTypeCompositionDisplay.cs +++ b/src/Umbraco.Web/Models/ContentEditing/ContentTypeCompositionDisplay.cs @@ -26,10 +26,6 @@ namespace Umbraco.Web.Models.ContentEditing [DataMember(Name = "isContainer")] public bool IsContainer { get; set; } - //Element - [DataMember(Name = "isElement")] - public bool IsElement { get; set; } - [DataMember(Name = "listViewEditorName")] [ReadOnly(true)] public string ListViewEditorName { get; set; } diff --git a/src/Umbraco.Web/Models/ContentEditing/ContentTypeSave.cs b/src/Umbraco.Web/Models/ContentEditing/ContentTypeSave.cs index b1d24c5fd2..c2ec70d3dc 100644 --- a/src/Umbraco.Web/Models/ContentEditing/ContentTypeSave.cs +++ b/src/Umbraco.Web/Models/ContentEditing/ContentTypeSave.cs @@ -25,9 +25,6 @@ namespace Umbraco.Web.Models.ContentEditing [DataMember(Name = "isContainer")] public bool IsContainer { get; set; } - [DataMember(Name = "isElement")] - public bool IsElement { get; set; } - [DataMember(Name = "allowAsRoot")] public bool AllowAsRoot { get; set; } From ff6a9ba97f17bddd64edb1da5cc0a8858fb336f9 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Tue, 15 Jan 2019 12:23:45 +0100 Subject: [PATCH 352/469] Revert "Identify element types" This reverts commit 4ad2505b --- .../Migrations/Upgrade/UmbracoPlan.cs | 1 - .../V_8_0_0/AddContentTypeIsElementColumn.cs | 15 ---------- src/Umbraco.Core/Models/ContentTypeBase.cs | 10 ------- .../Models/ContentTypeBaseExtensions.cs | 3 +- src/Umbraco.Core/Models/IContentTypeBase.cs | 12 +------- .../PublishedContent/PublishedItemType.cs | 7 +---- .../Persistence/Dtos/ContentTypeDto.cs | 4 --- .../Factories/ContentTypeFactory.cs | 2 -- .../Persistence/Mappers/ContentTypeMapper.cs | 1 - .../Persistence/Mappers/MediaTypeMapper.cs | 1 - .../Persistence/Mappers/MemberTypeMapper.cs | 1 - .../Implement/ContentTypeRepositoryBase.cs | 6 ++-- .../Services/EntityXmlSerializer.cs | 3 +- .../Services/Implement/PackagingService.cs | 4 --- src/Umbraco.Core/Umbraco.Core.csproj | 1 - .../PublishedContent/PublishedContentTests.cs | 1 + .../Services/ContentTypeServiceTests.cs | 30 ------------------- .../ContentEditing/ContentItemDisplay.cs | 8 +---- .../Models/Mapping/ContentMapperProfile.cs | 5 ++-- 19 files changed, 10 insertions(+), 105 deletions(-) delete mode 100644 src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/AddContentTypeIsElementColumn.cs diff --git a/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs b/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs index 9ec970f1fe..b469c02a3c 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs @@ -121,7 +121,6 @@ namespace Umbraco.Core.Migrations.Upgrade To("{648A2D5F-7467-48F8-B309-E99CEEE00E2A}"); // fixed version To("{C39BF2A7-1454-4047-BBFE-89E40F66ED63}"); To("{64EBCE53-E1F0-463A-B40B-E98EFCCA8AE2}"); - To("{0009109C-A0B8-4F3F-8FEB-C137BBDDA268}"); //FINAL diff --git a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/AddContentTypeIsElementColumn.cs b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/AddContentTypeIsElementColumn.cs deleted file mode 100644 index 1df11a3e99..0000000000 --- a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/AddContentTypeIsElementColumn.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Umbraco.Core.Persistence.Dtos; - -namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0 -{ - public class AddContentTypeIsElementColumn : MigrationBase - { - public AddContentTypeIsElementColumn(IMigrationContext context) : base(context) - { } - - public override void Migrate() - { - AddColumn("isElement"); - } - } -} diff --git a/src/Umbraco.Core/Models/ContentTypeBase.cs b/src/Umbraco.Core/Models/ContentTypeBase.cs index b6ea9f50a0..88b1179f6d 100644 --- a/src/Umbraco.Core/Models/ContentTypeBase.cs +++ b/src/Umbraco.Core/Models/ContentTypeBase.cs @@ -26,7 +26,6 @@ namespace Umbraco.Core.Models private string _thumbnail = "folder.png"; private bool _allowedAsRoot; // note: only one that's not 'pure element type' private bool _isContainer; - private bool _isElement; private PropertyGroupCollection _propertyGroups; private PropertyTypeCollection _noGroupPropertyTypes; private IEnumerable _allowedContentTypes; @@ -91,7 +90,6 @@ namespace Umbraco.Core.Models public readonly PropertyInfo IconSelector = ExpressionHelper.GetPropertyInfo(x => x.Icon); public readonly PropertyInfo ThumbnailSelector = ExpressionHelper.GetPropertyInfo(x => x.Thumbnail); public readonly PropertyInfo AllowedAsRootSelector = ExpressionHelper.GetPropertyInfo(x => x.AllowedAsRoot); - public readonly PropertyInfo IsElementSelector = ExpressionHelper.GetPropertyInfo(x => x.IsElement); public readonly PropertyInfo IsContainerSelector = ExpressionHelper.GetPropertyInfo(x => x.IsContainer); public readonly PropertyInfo AllowedContentTypesSelector = ExpressionHelper.GetPropertyInfo>(x => x.AllowedContentTypes); public readonly PropertyInfo PropertyGroupsSelector = ExpressionHelper.GetPropertyInfo(x => x.PropertyGroups); @@ -182,14 +180,6 @@ namespace Umbraco.Core.Models set => SetPropertyValueAndDetectChanges(value, ref _isContainer, Ps.Value.IsContainerSelector); } - /// - [DataMember] - public bool IsElement - { - get => _isElement; - set => SetPropertyValueAndDetectChanges(value, ref _isElement, Ps.Value.IsElementSelector); - } - /// /// Gets or sets a list of integer Ids for allowed ContentTypes /// diff --git a/src/Umbraco.Core/Models/ContentTypeBaseExtensions.cs b/src/Umbraco.Core/Models/ContentTypeBaseExtensions.cs index adbc3de54f..8af48bb881 100644 --- a/src/Umbraco.Core/Models/ContentTypeBaseExtensions.cs +++ b/src/Umbraco.Core/Models/ContentTypeBaseExtensions.cs @@ -15,8 +15,7 @@ namespace Umbraco.Core.Models { var type = contentType.GetType(); var itemType = PublishedItemType.Unknown; - if (contentType.IsElement) itemType = PublishedItemType.Element; - else if (typeof(IContentType).IsAssignableFrom(type)) itemType = PublishedItemType.Content; + if (typeof(IContentType).IsAssignableFrom(type)) itemType = PublishedItemType.Content; else if (typeof(IMediaType).IsAssignableFrom(type)) itemType = PublishedItemType.Media; else if (typeof(IMemberType).IsAssignableFrom(type)) itemType = PublishedItemType.Member; return itemType; diff --git a/src/Umbraco.Core/Models/IContentTypeBase.cs b/src/Umbraco.Core/Models/IContentTypeBase.cs index 787e347b37..a1d4aee02f 100644 --- a/src/Umbraco.Core/Models/IContentTypeBase.cs +++ b/src/Umbraco.Core/Models/IContentTypeBase.cs @@ -25,7 +25,7 @@ namespace Umbraco.Core.Models /// the icon (eg. icon-home) along with an optional CSS class name representing the /// color (eg. icon-blue). Put together, the value for this scenario would be /// icon-home color-blue. - /// + /// /// If a class name for the color isn't specified, the icon color will default to black. ///
    string Icon { get; set; } @@ -48,16 +48,6 @@ namespace Umbraco.Core.Models /// bool IsContainer { get; set; } - /// - /// Gets or sets a value indicating whether this content type is for an element. - /// - /// - /// By default a content type is for a true media, member or document, but - /// it can also be for an element, ie a subset that can for instance be used in - /// nested content. - /// - bool IsElement { get; set; } - /// /// Gets or sets the content variation of the content type. /// diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedItemType.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedItemType.cs index 42e9c9538d..e55fe66945 100644 --- a/src/Umbraco.Core/Models/PublishedContent/PublishedItemType.cs +++ b/src/Umbraco.Core/Models/PublishedContent/PublishedItemType.cs @@ -4,18 +4,13 @@ /// The type of published element. ///
    /// Can be a simple element, or a document, a media, a member. - public enum PublishedItemType + public enum PublishedItemType // fixme - need to rename to PublishedElementType but then conflicts? { /// /// Unknown. /// Unknown = 0, - /// - /// An element. - /// - Element, - /// /// A document. /// diff --git a/src/Umbraco.Core/Persistence/Dtos/ContentTypeDto.cs b/src/Umbraco.Core/Persistence/Dtos/ContentTypeDto.cs index 4f3a67aa91..d930abc54c 100644 --- a/src/Umbraco.Core/Persistence/Dtos/ContentTypeDto.cs +++ b/src/Umbraco.Core/Persistence/Dtos/ContentTypeDto.cs @@ -41,10 +41,6 @@ namespace Umbraco.Core.Persistence.Dtos [Constraint(Default = "0")] public bool IsContainer { get; set; } - [Column("isElement")] - [Constraint(Default = "0")] - public bool IsElement { get; set; } - [Column("allowAtRoot")] [Constraint(Default = "0")] public bool AllowAtRoot { get; set; } diff --git a/src/Umbraco.Core/Persistence/Factories/ContentTypeFactory.cs b/src/Umbraco.Core/Persistence/Factories/ContentTypeFactory.cs index 7a04a6d0d9..38a1aa2aab 100644 --- a/src/Umbraco.Core/Persistence/Factories/ContentTypeFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/ContentTypeFactory.cs @@ -107,7 +107,6 @@ namespace Umbraco.Core.Persistence.Factories entity.CreatorId = dto.NodeDto.UserId ?? Constants.Security.UnknownUserId; entity.AllowedAsRoot = dto.AllowAtRoot; entity.IsContainer = dto.IsContainer; - entity.IsElement = dto.IsElement; entity.Trashed = dto.NodeDto.Trashed; entity.Variations = (ContentVariation) dto.Variations; } @@ -133,7 +132,6 @@ namespace Umbraco.Core.Persistence.Factories NodeId = entity.Id, AllowAtRoot = entity.AllowedAsRoot, IsContainer = entity.IsContainer, - IsElement = entity.IsElement, Variations = (byte) entity.Variations, NodeDto = BuildNodeDto(entity, nodeObjectType) }; diff --git a/src/Umbraco.Core/Persistence/Mappers/ContentTypeMapper.cs b/src/Umbraco.Core/Persistence/Mappers/ContentTypeMapper.cs index a24963bace..c692a75474 100644 --- a/src/Umbraco.Core/Persistence/Mappers/ContentTypeMapper.cs +++ b/src/Umbraco.Core/Persistence/Mappers/ContentTypeMapper.cs @@ -35,7 +35,6 @@ namespace Umbraco.Core.Persistence.Mappers CacheMap(src => src.Description, dto => dto.Description); CacheMap(src => src.Icon, dto => dto.Icon); CacheMap(src => src.IsContainer, dto => dto.IsContainer); - CacheMap(src => src.IsElement, dto => dto.IsElement); CacheMap(src => src.Thumbnail, dto => dto.Thumbnail); } } diff --git a/src/Umbraco.Core/Persistence/Mappers/MediaTypeMapper.cs b/src/Umbraco.Core/Persistence/Mappers/MediaTypeMapper.cs index 6cf83bc7aa..3f5a6e24bc 100644 --- a/src/Umbraco.Core/Persistence/Mappers/MediaTypeMapper.cs +++ b/src/Umbraco.Core/Persistence/Mappers/MediaTypeMapper.cs @@ -35,7 +35,6 @@ namespace Umbraco.Core.Persistence.Mappers CacheMap(src => src.Description, dto => dto.Description); CacheMap(src => src.Icon, dto => dto.Icon); CacheMap(src => src.IsContainer, dto => dto.IsContainer); - CacheMap(src => src.IsElement, dto => dto.IsElement); CacheMap(src => src.Thumbnail, dto => dto.Thumbnail); } } diff --git a/src/Umbraco.Core/Persistence/Mappers/MemberTypeMapper.cs b/src/Umbraco.Core/Persistence/Mappers/MemberTypeMapper.cs index 9a4e4ec040..28dc19171f 100644 --- a/src/Umbraco.Core/Persistence/Mappers/MemberTypeMapper.cs +++ b/src/Umbraco.Core/Persistence/Mappers/MemberTypeMapper.cs @@ -35,7 +35,6 @@ namespace Umbraco.Core.Persistence.Mappers CacheMap(src => src.Description, dto => dto.Description); CacheMap(src => src.Icon, dto => dto.Icon); CacheMap(src => src.IsContainer, dto => dto.IsContainer); - CacheMap(src => src.IsElement, dto => dto.IsElement); CacheMap(src => src.Thumbnail, dto => dto.Thumbnail); } } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs index 683df047f8..662254d1ee 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs @@ -1283,7 +1283,7 @@ AND umbracoNode.id <> @id", if (db == null) throw new ArgumentNullException(nameof(db)); var sql = @"SELECT cmsContentType.pk as ctPk, cmsContentType.alias as ctAlias, cmsContentType.allowAtRoot as ctAllowAtRoot, cmsContentType.description as ctDesc, cmsContentType.variations as ctVariations, - cmsContentType.icon as ctIcon, cmsContentType.isContainer as ctIsContainer, cmsContentType.IsElement as ctIsElement, cmsContentType.nodeId as ctId, cmsContentType.thumbnail as ctThumb, + cmsContentType.icon as ctIcon, cmsContentType.isContainer as ctIsContainer, cmsContentType.nodeId as ctId, cmsContentType.thumbnail as ctThumb, AllowedTypes.AllowedId as ctaAllowedId, AllowedTypes.SortOrder as ctaSortOrder, AllowedTypes.alias as ctaAlias, ParentTypes.parentContentTypeId as chtParentId, ParentTypes.parentContentTypeKey as chtParentKey, umbracoNode.createDate as nCreateDate, umbracoNode." + sqlSyntax.GetQuotedColumnName("level") + @" as nLevel, umbracoNode.nodeObjectType as nObjectType, umbracoNode.nodeUser as nUser, @@ -1384,7 +1384,6 @@ AND umbracoNode.id <> @id", Description = currCt.ctDesc, Icon = currCt.ctIcon, IsContainer = currCt.ctIsContainer, - IsElement = currCt.ctIsElement, NodeId = currCt.ctId, PrimaryKey = currCt.ctPk, Thumbnail = currCt.ctThumb, @@ -1423,7 +1422,7 @@ AND umbracoNode.id <> @id", var sql = @"SELECT cmsDocumentType.IsDefault as dtIsDefault, cmsDocumentType.templateNodeId as dtTemplateId, cmsContentType.pk as ctPk, cmsContentType.alias as ctAlias, cmsContentType.allowAtRoot as ctAllowAtRoot, cmsContentType.description as ctDesc, cmsContentType.variations as ctVariations, - cmsContentType.icon as ctIcon, cmsContentType.isContainer as ctIsContainer, cmsContentType.IsElement as ctIsElement, cmsContentType.nodeId as ctId, cmsContentType.thumbnail as ctThumb, + cmsContentType.icon as ctIcon, cmsContentType.isContainer as ctIsContainer, cmsContentType.nodeId as ctId, cmsContentType.thumbnail as ctThumb, AllowedTypes.AllowedId as ctaAllowedId, AllowedTypes.SortOrder as ctaSortOrder, AllowedTypes.alias as ctaAlias, ParentTypes.parentContentTypeId as chtParentId,ParentTypes.parentContentTypeKey as chtParentKey, umbracoNode.createDate as nCreateDate, umbracoNode." + sqlSyntax.GetQuotedColumnName("level") + @" as nLevel, umbracoNode.nodeObjectType as nObjectType, umbracoNode.nodeUser as nUser, @@ -1560,7 +1559,6 @@ AND umbracoNode.id <> @id", Description = currCt.ctDesc, Icon = currCt.ctIcon, IsContainer = currCt.ctIsContainer, - IsElement = currCt.ctIsElement, NodeId = currCt.ctId, PrimaryKey = currCt.ctPk, Thumbnail = currCt.ctThumb, diff --git a/src/Umbraco.Core/Services/EntityXmlSerializer.cs b/src/Umbraco.Core/Services/EntityXmlSerializer.cs index 38d5471bb7..d938e032a8 100644 --- a/src/Umbraco.Core/Services/EntityXmlSerializer.cs +++ b/src/Umbraco.Core/Services/EntityXmlSerializer.cs @@ -337,8 +337,7 @@ namespace Umbraco.Core.Services new XElement("Thumbnail", contentType.Thumbnail), new XElement("Description", contentType.Description), new XElement("AllowAtRoot", contentType.AllowedAsRoot.ToString()), - new XElement("IsListView", contentType.IsContainer.ToString()), - new XElement("IsElement", contentType.IsElement.ToString())); + new XElement("IsListView", contentType.IsContainer.ToString())); var masterContentType = contentType.ContentTypeComposition.FirstOrDefault(x => x.Id == contentType.ParentId); if(masterContentType != null) diff --git a/src/Umbraco.Core/Services/Implement/PackagingService.cs b/src/Umbraco.Core/Services/Implement/PackagingService.cs index 8f6c287cf1..106d2b9f12 100644 --- a/src/Umbraco.Core/Services/Implement/PackagingService.cs +++ b/src/Umbraco.Core/Services/Implement/PackagingService.cs @@ -578,10 +578,6 @@ namespace Umbraco.Core.Services.Implement if (isListView != null) contentType.IsContainer = isListView.Value.InvariantEquals("true"); - var isElement = infoElement.Element("IsElement"); - if (isListView != null) - contentType.IsElement = isElement.Value.InvariantEquals("true"); - //Name of the master corresponds to the parent and we need to ensure that the Parent Id is set var masterElement = infoElement.Element("Master"); if (masterElement != null) diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 7d65a46f49..609befd233 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -377,7 +377,6 @@ - diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs index ab65ac82b1..914956dce1 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs @@ -233,6 +233,7 @@ namespace Umbraco.Tests.PublishedContent } [Test] + [Ignore("Fails as long as PublishedContentModel is internal.")] // fixme public void Is_Last_From_Where_Filter2() { var doc = GetNode(1173); diff --git a/src/Umbraco.Tests/Services/ContentTypeServiceTests.cs b/src/Umbraco.Tests/Services/ContentTypeServiceTests.cs index 8dc8a2b45c..b1a8fa26a8 100644 --- a/src/Umbraco.Tests/Services/ContentTypeServiceTests.cs +++ b/src/Umbraco.Tests/Services/ContentTypeServiceTests.cs @@ -22,36 +22,6 @@ namespace Umbraco.Tests.Services [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest, PublishedRepositoryEvents = true)] public class ContentTypeServiceTests : TestWithSomeContentBase { - [Test] - public void CanSaveAndGetIsElement() - { - //create content type with a property type that varies by culture - IContentType contentType = MockedContentTypes.CreateBasicContentType(); - contentType.Variations = ContentVariation.Nothing; - var contentCollection = new PropertyTypeCollection(true); - contentCollection.Add(new PropertyType("test", ValueStorageType.Ntext) - { - Alias = "title", - Name = "Title", - Description = "", - Mandatory = false, - SortOrder = 1, - DataTypeId = -88, - Variations = ContentVariation.Nothing - }); - contentType.PropertyGroups.Add(new PropertyGroup(contentCollection) { Name = "Content", SortOrder = 1 }); - ServiceContext.ContentTypeService.Save(contentType); - - contentType = ServiceContext.ContentTypeService.Get(contentType.Id); - Assert.IsFalse(contentType.IsElement); - - contentType.IsElement = true; - ServiceContext.ContentTypeService.Save(contentType); - - contentType = ServiceContext.ContentTypeService.Get(contentType.Id); - Assert.IsTrue(contentType.IsElement); - } - [Test] public void Change_Content_Type_Variation_Clears_Redirects() { diff --git a/src/Umbraco.Web/Models/ContentEditing/ContentItemDisplay.cs b/src/Umbraco.Web/Models/ContentEditing/ContentItemDisplay.cs index 80358bfc7a..4908025351 100644 --- a/src/Umbraco.Web/Models/ContentEditing/ContentItemDisplay.cs +++ b/src/Umbraco.Web/Models/ContentEditing/ContentItemDisplay.cs @@ -86,12 +86,6 @@ namespace Umbraco.Web.Models.ContentEditing [DataMember(Name = "isContainer")] public bool IsContainer { get; set; } - /// - /// Indicates if the content is configured as an element - /// - [DataMember(Name = "isElement")] - public bool IsElement { get; set; } - /// /// Property indicating if this item is part of a list view parent /// @@ -123,7 +117,7 @@ namespace Umbraco.Web.Models.ContentEditing /// [DataMember(Name = "updateDate")] public DateTime UpdateDate { get; set; } - + [DataMember(Name = "template")] public string TemplateAlias { get; set; } diff --git a/src/Umbraco.Web/Models/Mapping/ContentMapperProfile.cs b/src/Umbraco.Web/Models/Mapping/ContentMapperProfile.cs index 1caf81a1eb..6de3bdc02c 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentMapperProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentMapperProfile.cs @@ -46,7 +46,6 @@ namespace Umbraco.Web.Models.Mapping .ForMember(dest => dest.ContentTypeAlias, opt => opt.MapFrom(src => src.ContentType.Alias)) .ForMember(dest => dest.ContentTypeName, opt => opt.MapFrom(src => src.ContentType.Name)) .ForMember(dest => dest.IsContainer, opt => opt.MapFrom(src => src.ContentType.IsContainer)) - .ForMember(dest => dest.IsElement, opt => opt.MapFrom(src => src.ContentType.IsElement)) .ForMember(dest => dest.IsBlueprint, opt => opt.MapFrom(src => src.Blueprint)) .ForMember(dest => dest.IsChildOfListView, opt => opt.ResolveUsing(childOfListViewResolver)) .ForMember(dest => dest.Trashed, opt => opt.MapFrom(src => src.Trashed)) @@ -60,7 +59,7 @@ namespace Umbraco.Web.Models.Mapping .ForMember(dest => dest.AllowedTemplates, opt => opt.MapFrom(content => content.ContentType.AllowedTemplates .Where(t => t.Alias.IsNullOrWhiteSpace() == false && t.Name.IsNullOrWhiteSpace() == false) - .ToDictionary(t => t.Alias, t => t.Name))) + .ToDictionary(t => t.Alias, t => t.Name))) .ForMember(dest => dest.AllowedActions, opt => opt.ResolveUsing(src => actionButtonsResolver.Resolve(src))) .ForMember(dest => dest.AdditionalData, opt => opt.Ignore()); @@ -141,5 +140,5 @@ namespace Umbraco.Web.Models.Mapping return source.CultureInfos.TryGetValue(culture, out var name) && !name.Name.IsNullOrWhiteSpace() ? name.Name : $"(({source.Name}))"; } } - } + } } From a5ff29ccc7457ecb7ea82744e405daf58cdc2d57 Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 15 Jan 2019 22:59:13 +1100 Subject: [PATCH 353/469] Gets package uninstall working, fixes other UI issues with packages --- .../Packaging/CompiledPackageXmlParser.cs | 37 ++-- .../Packaging/PackageDefinitionXmlParser.cs | 2 + .../Packaging/PackageInstallation.cs | 1 + .../src/views/packages/overview.controller.js | 15 +- .../src/views/packages/overview.html | 34 ++- .../views/install-local.controller.js | 2 +- .../packages/views/installed.controller.js | 16 +- .../Controllers/InstallPackageController.cs | 196 ------------------ src/Umbraco.Web/Install/UmbracoInstallArea.cs | 8 - 9 files changed, 67 insertions(+), 244 deletions(-) delete mode 100644 src/Umbraco.Web/Install/Controllers/InstallPackageController.cs diff --git a/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs b/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs index eb9cf46008..be9c69667a 100644 --- a/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs +++ b/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs @@ -149,37 +149,50 @@ namespace Umbraco.Core.Packaging return path; } + /// + /// Parses the package actions stored in the package definition + /// + /// + /// + /// public IEnumerable GetPackageActions(XElement actionsElement, string packageName) { - if (actionsElement == null) { return new PackageAction[0]; } + if (actionsElement == null) return Enumerable.Empty(); - if (string.Equals("Actions", actionsElement.Name.LocalName) == false) - throw new ArgumentException($"Must be \"Actions\" as root", nameof(actionsElement)); + //invariant check ... because people can realy enter anything :/ + if (!string.Equals("actions", actionsElement.Name.LocalName, StringComparison.InvariantCultureIgnoreCase)) + throw new FormatException("Must be \"\" as root"); - return actionsElement.Elements("Action") - .Select(elemet => + if (!actionsElement.HasElements) return Enumerable.Empty(); + + var actionElementName = actionsElement.Elements().First().Name.LocalName; + + //invariant check ... because people can realy enter anything :/ + if (!string.Equals("action", actionElementName, StringComparison.InvariantCultureIgnoreCase)) + throw new FormatException("Must be \" { - var aliasAttr = elemet.Attribute("Alias"); + var aliasAttr = e.Attribute("alias") ?? e.Attribute("Alias"); //allow both ... because people can really enter anything :/ if (aliasAttr == null) - throw new ArgumentException("missing \"Alias\" atribute in alias element", nameof(actionsElement)); + throw new ArgumentException("missing \"alias\" atribute in alias element", nameof(actionsElement)); var packageAction = new PackageAction { - XmlData = elemet, + XmlData = e, Alias = aliasAttr.Value, PackageName = packageName, }; - - var attr = elemet.Attribute("runat"); + var attr = e.Attribute("runat") ?? e.Attribute("Runat"); //allow both ... because people can really enter anything :/ if (attr != null && Enum.TryParse(attr.Value, true, out ActionRunAt runAt)) { packageAction.RunAt = runAt; } - attr = elemet.Attribute("undo"); + attr = e.Attribute("undo") ?? e.Attribute("Undo"); //allow both ... because people can really enter anything :/ if (attr != null && bool.TryParse(attr.Value, out var undo)) { packageAction.Undo = undo; } - return packageAction; }).ToArray(); } diff --git a/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs b/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs index 0d7adf8ece..45e6fd9845 100644 --- a/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs +++ b/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs @@ -105,5 +105,7 @@ namespace Umbraco.Core.Packaging return packageXml; } + + } } diff --git a/src/Umbraco.Core/Packaging/PackageInstallation.cs b/src/Umbraco.Core/Packaging/PackageInstallation.cs index 4563d31560..7abf96b266 100644 --- a/src/Umbraco.Core/Packaging/PackageInstallation.cs +++ b/src/Umbraco.Core/Packaging/PackageInstallation.cs @@ -76,6 +76,7 @@ namespace Umbraco.Core.Packaging { //running this will update the PackageDefinition with the items being removed var summary = _packageDataInstallation.UninstallPackageData(package, userId); + summary.Actions = _parser.GetPackageActions(XElement.Parse(package.Actions), package.Name); //run actions before files are removed diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/overview.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/overview.controller.js index 4ca0015aa5..ccd86c6f6c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/overview.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/overview.controller.js @@ -1,7 +1,7 @@ (function () { "use strict"; - function PackagesOverviewController($scope, $route, $location, navigationService, $timeout, localStorageService) { + function PackagesOverviewController($scope, $location, localStorageService) { //Hack! // if there is a cookie value for packageInstallUri then we need to redirect there, @@ -9,12 +9,13 @@ // because it will double load it. // we will refresh and then navigate there. - var installPackageUri = localStorageService.get("packageInstallUri"); - const packageUri = $location.search().subview; + let installPackageUri = localStorageService.get("packageInstallUri"); + let packageUri = $location.search().subview; if (installPackageUri) { localStorageService.remove("packageInstallUri"); } + if (installPackageUri && installPackageUri !== "installed") { //navigate to the custom installer screen, if it is just "installed", then we'll //show the installed view @@ -23,6 +24,8 @@ else { var vm = this; + packageUri = installPackageUri ? installPackageUri : packageUri; //use the path stored in storage over the one in the current path + vm.page = {}; vm.page.name = "Packages"; vm.page.navigation = [ @@ -30,7 +33,7 @@ "name": "Packages", "icon": "icon-cloud", "view": "views/packages/views/repo.html", - "active": !packageUri || installPackageUri === "navigation" || packageUri === "navigation", + "active": !packageUri || packageUri === "navigation", "alias": "umbPackages", "action": function() { $location.search("subview", "navigation"); @@ -40,7 +43,7 @@ "name": "Installed", "icon": "icon-box", "view": "views/packages/views/installed.html", - "active": installPackageUri === "installed" || packageUri === "installed", + "active": packageUri === "installed", "alias": "umbInstalled", "action": function() { $location.search("subview", "installed"); @@ -50,7 +53,7 @@ "name": "Install local", "icon": "icon-add", "view": "views/packages/views/install-local.html", - "active": installPackageUri === "local" || packageUri === "local", + "active": packageUri === "local", "alias": "umbInstallLocal", "action": function() { $location.search("subview", "local"); diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/overview.html b/src/Umbraco.Web.UI.Client/src/views/packages/overview.html index 250dc889d6..84f594b48d 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/overview.html +++ b/src/Umbraco.Web.UI.Client/src/views/packages/overview.html @@ -1,28 +1,24 @@
    -
    + - + + - - + - + + - - + - - - - - +
    diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/views/install-local.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/views/install-local.controller.js index 9c6c2bb7c5..6753fad942 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/views/install-local.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/views/install-local.controller.js @@ -1,7 +1,7 @@ (function () { "use strict"; - function PackagesInstallLocalController($scope, $route, $location, Upload, umbRequestHelper, packageResource, localStorageService, $timeout, $window, localizationService, $q) { + function PackagesInstallLocalController($scope, Upload, umbRequestHelper, packageResource, localStorageService, $timeout, $window, localizationService, $q) { var vm = this; vm.state = "upload"; diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/views/installed.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/views/installed.controller.js index ce1d2cca0f..6e0e162e86 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/views/installed.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/views/installed.controller.js @@ -13,6 +13,8 @@ }; vm.package = {}; + var labels = {}; + function init() { packageResource.getInstalled() .then(function (packs) { @@ -20,6 +22,16 @@ }); vm.installState.status = ""; vm.state = "list"; + + var labelKeys = [ + "packager_installStateUninstalling", + "packager_installStateComplete", + ]; + + localizationService.localizeMany(labelKeys).then(function (values) { + labels.installStateUninstalling = values[0]; + labels.installStateComplete = values[1]; + }); } function confirmUninstall(pck) { @@ -28,14 +40,14 @@ } function uninstallPackage(installedPackage) { - vm.installState.status = localizationService.localize("packager_installStateUninstalling"); + vm.installState.status = labels.installStateUninstalling; vm.installState.progress = "0"; packageResource.uninstall(installedPackage.id) .then(function () { if (installedPackage.files.length > 0) { - vm.installState.status = localizationService.localize("packager_installStateComplete"); + vm.installState.status = labels.installStateComplete; vm.installState.progress = "100"; //set this flag so that on refresh it shows the installed packages list diff --git a/src/Umbraco.Web/Install/Controllers/InstallPackageController.cs b/src/Umbraco.Web/Install/Controllers/InstallPackageController.cs deleted file mode 100644 index 81cb1e2e39..0000000000 --- a/src/Umbraco.Web/Install/Controllers/InstallPackageController.cs +++ /dev/null @@ -1,196 +0,0 @@ -//using System; -//using System.Linq; -//using System.Net; -//using System.Net.Http; -//using System.Text; -//using System.Threading.Tasks; -//using System.Web; -//using System.Web.Http; -//using Newtonsoft.Json.Linq; -//using umbraco; -//using Umbraco.Core; -//using Umbraco.Web.Cache; -//using Umbraco.Core.Configuration; -//using Umbraco.Core.Models.Packaging; -//using Umbraco.Core.Services; -//using Umbraco.Web.Composing; -//using Umbraco.Web.Install.Models; -//using Umbraco.Web.WebApi; - -//namespace Umbraco.Web.Install.Controllers -//{ -// /// -// /// A controller for the installation process regarding packages -// /// -// /// -// /// Currently this is used for web services however we should/could eventually migrate the whole installer to MVC as it -// /// is a bit of a mess currently. -// /// -// [HttpInstallAuthorize] -// [AngularJsonOnlyConfiguration] -// [Obsolete("This is only used for the legacy way of installing starter kits in the back office")] -// //fixme: Is this used anymore?? -// public class InstallPackageController : ApiController -// { -// private readonly IPackagingService _packagingService; -// private readonly UmbracoContext _umbracoContext; - -// public InstallPackageController(IPackagingService packagingService, UmbracoContext umbracoContext) -// { -// _packagingService = packagingService; -// _umbracoContext = umbracoContext; -// } - -// /// -// /// Empty action, useful for retrieving the base url for this controller -// /// -// /// -// [HttpGet] -// public HttpResponseMessage Index() -// { -// throw new NotImplementedException(); -// } - -// /// -// /// Connects to the repo, downloads the package and creates the definition -// /// -// /// -// /// -// [HttpPost] -// public async Task DownloadPackageFiles(InstallPackageModel model) -// { -// var packageFile = await _packagingService.FetchPackageFileAsync( -// model.KitGuid, -// UmbracoVersion.Current, -// UmbracoContext.Current.Security.CurrentUser.Id); - - -// var packageInfo = _packagingService.GetCompiledPackageInfo(packageFile); -// if (packageInfo == null) throw new InvalidOperationException("Could not read package file " + packageFile); - -// //save to the installedPackages.config -// var packageDefinition = PackageDefinition.FromCompiledPackage(packageInfo); -// _packagingService.SaveInstalledPackage(packageDefinition); - -// return Json(new -// { -// success = true, -// packageId = packageDefinition.Id, -// packageFile = packageInfo.PackageFileName, -// percentage = 10, -// message = "Downloading starter kit files..." -// }, HttpStatusCode.OK); -// } - -// /// -// /// Installs the files in the package -// /// -// /// -// [HttpPost] -// public HttpResponseMessage InstallPackageFiles(InstallPackageModel model) -// { -// model.PackageFile = HttpUtility.UrlDecode(model.PackageFile); - -// var definition = _packagingService.GetInstalledPackageById(model.PackageId); -// if (definition == null) throw new InvalidOperationException("Not package definition found with id " + model.PackageId); - -// _packagingService.InstallCompiledPackageFiles(definition, model.PackageFile, _umbracoContext.Security.GetUserId().ResultOr(0)); - -// return Json(new -// { -// success = true, -// ManifestId = model.PackageId, -// model.PackageFile, -// percentage = 20, -// message = "Installing starter kit files" -// }, HttpStatusCode.OK); -// } - -// /// -// /// Ensures the app pool is restarted -// /// -// /// -// [HttpPost] -// public HttpResponseMessage RestartAppPool() -// { -// Current.RestartAppPool(Request.TryGetHttpContext().Result); -// return Json(new -// { -// success = true, -// percentage = 25, -// message = "Installing starter kit files" -// }, HttpStatusCode.OK); -// } - -// /// -// /// Checks if the app pool has completed restarted -// /// -// /// -// [HttpPost] -// public HttpResponseMessage CheckAppPoolRestart() -// { -// if (Request.TryGetHttpContext().Result.Application.AllKeys.Contains("AppPoolRestarting")) -// { -// return Request.CreateResponse(HttpStatusCode.BadRequest); -// } - -// return Json(new -// { -// percentage = 30, -// success = true, -// }, HttpStatusCode.OK); -// } - -// /// -// /// Installs the business logic portion of the package after app restart -// /// -// /// -// [HttpPost] -// public HttpResponseMessage InstallBusinessLogic(InstallPackageModel model) -// { -// model.PackageFile = HttpUtility.UrlDecode(model.PackageFile); - -// var definition = _packagingService.GetInstalledPackageById(model.PackageId); -// if (definition == null) throw new InvalidOperationException("Not package definition found with id " + model.PackageId); - -// _packagingService.InstallCompiledPackageData(definition, model.PackageFile, _umbracoContext.Security.GetUserId().ResultOr(0)); - -// return Json(new -// { -// success = true, -// ManifestId = model.PackageId, -// model.PackageFile, -// percentage = 70, -// message = "Installing starter kit files" -// }, HttpStatusCode.OK); -// } - -// /// -// /// Cleans up the package installation -// /// -// /// -// [HttpPost] -// public HttpResponseMessage CleanupInstallation(InstallPackageModel model) -// { -// model.PackageFile = HttpUtility.UrlDecode(model.PackageFile); - -// return Json(new -// { -// success = true, -// ManifestId = model.PackageId, -// model.PackageFile, -// percentage = 100, -// message = "Starter kit has been installed" -// }, HttpStatusCode.OK); -// } - -// private HttpResponseMessage Json(object jsonObject, HttpStatusCode status) -// { -// var response = Request.CreateResponse(status); -// var json = JObject.FromObject(jsonObject); -// response.Content = new StringContent(json.ToString(), Encoding.UTF8, "application/json"); -// return response; -// } -// } - -//} diff --git a/src/Umbraco.Web/Install/UmbracoInstallArea.cs b/src/Umbraco.Web/Install/UmbracoInstallArea.cs index 2b44abd4ab..398ed7b245 100644 --- a/src/Umbraco.Web/Install/UmbracoInstallArea.cs +++ b/src/Umbraco.Web/Install/UmbracoInstallArea.cs @@ -32,14 +32,6 @@ namespace Umbraco.Web.Install new { controller = "Install", action = "Index", id = UrlParameter.Optional }, new[] { typeof(InstallController).Namespace }); - //TODO: We can remove this when we re-build the back office package installer - //Create the install routes - context.MapHttpRoute( - "Umbraco_install_packages", - "Install/PackageInstaller/{action}/{id}", - new { controller = "InstallPackage", action = "Index", id = UrlParameter.Optional }, - new[] { typeof(InstallPackageController).Namespace }); - context.MapHttpRoute( "umbraco-install-api", "install/api/{action}/{id}", From 8c7d29bd020a62a2d87c2a34763ab4b865a01080 Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 15 Jan 2019 23:03:23 +1100 Subject: [PATCH 354/469] file update missing --- src/Umbraco.Web/Umbraco.Web.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index f8f33ca0fa..b0142771d2 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -730,7 +730,6 @@ - From 56ab88983a9c95d0803c348e989c23b0c2fc9124 Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 15 Jan 2019 23:10:08 +1100 Subject: [PATCH 355/469] updates a test --- .../Packaging/PackageInstallation.cs | 6 +++++- .../Services/Implement/PackagingService.cs | 3 +-- .../Packaging/PackageInstallationTest.cs | 21 ++++--------------- 3 files changed, 10 insertions(+), 20 deletions(-) diff --git a/src/Umbraco.Core/Packaging/PackageInstallation.cs b/src/Umbraco.Core/Packaging/PackageInstallation.cs index 7abf96b266..ae9b8173f5 100644 --- a/src/Umbraco.Core/Packaging/PackageInstallation.cs +++ b/src/Umbraco.Core/Packaging/PackageInstallation.cs @@ -69,7 +69,11 @@ namespace Umbraco.Core.Packaging var packageZipFile = compiledPackage.PackageFile; - return _packageFileInstallation.InstallFiles(compiledPackage, packageZipFile, _packageExtractionFolder.FullName); + var files = _packageFileInstallation.InstallFiles(compiledPackage, packageZipFile, _packageExtractionFolder.FullName).ToList(); + + packageDefinition.Files = files; + + return files; } public UninstallationSummary UninstallPackage(PackageDefinition package, int userId) diff --git a/src/Umbraco.Core/Services/Implement/PackagingService.cs b/src/Umbraco.Core/Services/Implement/PackagingService.cs index 362b1fc67b..a5c279fa21 100644 --- a/src/Umbraco.Core/Services/Implement/PackagingService.cs +++ b/src/Umbraco.Core/Services/Implement/PackagingService.cs @@ -109,8 +109,7 @@ namespace Umbraco.Core.Services.Implement if (compiledPackage == null) throw new InvalidOperationException("Could not read the package file " + packageFile); var files = _packageInstallation.InstallPackageFiles(packageDefinition, compiledPackage, userId).ToList(); - packageDefinition.Files = files; - + SaveInstalledPackage(packageDefinition); _auditService.Add(AuditType.PackagerInstall, userId, -1, "Package", $"Package files installed for package '{compiledPackage.Name}'."); diff --git a/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs b/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs index 7514eea00b..62feb64c10 100644 --- a/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs +++ b/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs @@ -1,16 +1,14 @@ using System; +using System.Collections.Generic; using System.IO; using System.Linq; using Moq; using NUnit.Framework; -using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Core.IO; using Umbraco.Core.Models.Packaging; using Umbraco.Core.Packaging; using Umbraco.Core.PropertyEditors; -using Umbraco.Core.Services; -using Umbraco.Core.Services.Implement; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; @@ -55,19 +53,6 @@ namespace Umbraco.Tests.Packaging private const string DocumentTypePickerUmb = "Document_Type_Picker_1.1.umb"; - //[Test] - //public void PackagingService_Can_ImportPackage() - //{ - // const string documentTypePickerUmb = "Document_Type_Picker_1.1.umb"; - - // string testPackagePath = GetTestPackagePath(documentTypePickerUmb); - - // InstallationSummary installationSummary = packagingService.InstallPackage(testPackagePath); - - // Assert.IsNotNull(installationSummary); - //} - - [Test] public void Can_Read_Compiled_Package() { @@ -111,9 +96,11 @@ namespace Umbraco.Tests.Packaging var package = PackageInstallation.ReadPackage( //this is where our test zip file is new FileInfo(Path.Combine(IOHelper.MapPath("~/Packaging/packages"), DocumentTypePickerUmb))); + var def = PackageDefinition.FromCompiledPackage(package); def.Id = 1; def.PackageId = Guid.NewGuid(); + def.Files = new List(); //clear out the files of the def for testing, this should be populated by the install var result = PackageInstallation.InstallPackageFiles(def, package, -1).ToList(); @@ -122,7 +109,7 @@ namespace Umbraco.Tests.Packaging Assert.IsTrue(File.Exists(Path.Combine(IOHelper.MapPath("~/" + _testBaseFolder), result[0]))); //make sure the def is updated too - Assert.AreEqual(result.Count(), def.Files.Count); + Assert.AreEqual(result.Count, def.Files.Count); } [Test] From 93ba694106d2f435126a495b8111df01ed3e43b8 Mon Sep 17 00:00:00 2001 From: Stephan Date: Tue, 15 Jan 2019 13:36:30 +0100 Subject: [PATCH 356/469] Upgrade ModelsBuilder (bugfix) --- build/NuSpecs/UmbracoCms.nuspec | 2 +- src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build/NuSpecs/UmbracoCms.nuspec b/build/NuSpecs/UmbracoCms.nuspec index 565d693979..1b7a1c5ae1 100644 --- a/build/NuSpecs/UmbracoCms.nuspec +++ b/build/NuSpecs/UmbracoCms.nuspec @@ -22,7 +22,7 @@ not want this to happen as the alpha of the next major is, really, the next major already. --> - + diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index 7a59b15eb3..ca4acd9d66 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -107,7 +107,7 @@ - 8.0.0-alpha.31 + 8.0.0-alpha.32 From 62fcbd8e84c8e6c09e1f4a7cef70d469ac6f43d3 Mon Sep 17 00:00:00 2001 From: Stephan Date: Tue, 15 Jan 2019 13:43:56 +0100 Subject: [PATCH 357/469] Handle max runtime level for components --- src/Umbraco.Core/Components/Composers.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Core/Components/Composers.cs b/src/Umbraco.Core/Components/Composers.cs index 1c836e9e5c..89deed934e 100644 --- a/src/Umbraco.Core/Components/Composers.cs +++ b/src/Umbraco.Core/Components/Composers.cs @@ -76,11 +76,13 @@ namespace Umbraco.Core.Components var composerTypeList = _composerTypes .Where(x => { - // use the min level specified by the attribute if any - // otherwise, user composers have Run min level, anything else is Unknown (always run) + // use the min/max levels specified by the attribute if any + // otherwise, min: user composers are Run, anything else is Unknown (always run) + // max: everything is Run (always run) var attr = x.GetCustomAttribute(); var minLevel = attr?.MinLevel ?? (x.Implements() ? RuntimeLevel.Run : RuntimeLevel.Unknown); - return _composition.RuntimeState.Level >= minLevel; + var maxLevel = attr?.MaxLevel ?? RuntimeLevel.Run; + return _composition.RuntimeState.Level >= minLevel && _composition.RuntimeState.Level <= maxLevel; }) .ToList(); From f6fdc9ae2d33b38d41d4c6a6626d11a6b5f83849 Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 15 Jan 2019 23:46:58 +1100 Subject: [PATCH 358/469] Updates test, fixes some other issues during testing --- .../Models/Packaging/PreInstallWarnings.cs | 2 ++ .../Packaging/ConflictingPackageData.cs | 2 +- .../Packaging/PackageInstallationTest.cs | 13 +++++++++++-- .../views/packages/views/installed.controller.js | 2 +- src/Umbraco.Web/Search/ExamineComponent.cs | 2 +- 5 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Core/Models/Packaging/PreInstallWarnings.cs b/src/Umbraco.Core/Models/Packaging/PreInstallWarnings.cs index 18b63ced88..f0acb2a46b 100644 --- a/src/Umbraco.Core/Models/Packaging/PreInstallWarnings.cs +++ b/src/Umbraco.Core/Models/Packaging/PreInstallWarnings.cs @@ -9,6 +9,8 @@ namespace Umbraco.Core.Models.Packaging { public IEnumerable UnsecureFiles { get; set; } = Enumerable.Empty(); public IEnumerable FilesReplaced { get; set; } = Enumerable.Empty(); + + //TODO: Shouldn't we detect other conflicting entities too ? public IEnumerable ConflictingMacros { get; set; } = Enumerable.Empty(); public IEnumerable ConflictingTemplates { get; set; } = Enumerable.Empty(); public IEnumerable ConflictingStylesheets { get; set; } = Enumerable.Empty(); diff --git a/src/Umbraco.Core/Packaging/ConflictingPackageData.cs b/src/Umbraco.Core/Packaging/ConflictingPackageData.cs index a37195806e..82693677fb 100644 --- a/src/Umbraco.Core/Packaging/ConflictingPackageData.cs +++ b/src/Umbraco.Core/Packaging/ConflictingPackageData.cs @@ -23,7 +23,7 @@ namespace Umbraco.Core.Packaging return stylesheetNodes .Select(n => { - var xElement = n.Element("Name"); + var xElement = n.Element("Name") ?? n.Element("name"); ; if (xElement == null) throw new FormatException("Missing \"Name\" element"); diff --git a/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs b/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs index 62feb64c10..8fcacbeff7 100644 --- a/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs +++ b/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs @@ -6,11 +6,13 @@ using Moq; using NUnit.Framework; using Umbraco.Core.Composing; using Umbraco.Core.IO; +using Umbraco.Core.Models; using Umbraco.Core.Models.Packaging; using Umbraco.Core.Packaging; using Umbraco.Core.PropertyEditors; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; +using File = System.IO.File; namespace Umbraco.Tests.Packaging { @@ -79,7 +81,11 @@ namespace Umbraco.Tests.Packaging [Test] public void Can_Read_Compiled_Package_Warnings() { - + //copy a file to the same path that the package will install so we can detect file conflicts + var path = IOHelper.MapPath("~/" + _testBaseFolder); + var filePath = Path.Combine(path, "bin", "Auros.DocumentTypePicker.dll"); + Directory.CreateDirectory(Path.GetDirectoryName(filePath)); + File.WriteAllText(filePath, "test"); var preInstallWarnings = PackageInstallation.ReadPackage( //this is where our test zip file is @@ -87,7 +93,10 @@ namespace Umbraco.Tests.Packaging .Warnings; Assert.IsNotNull(preInstallWarnings); - //TODO: Assert! + Assert.AreEqual(preInstallWarnings.FilesReplaced.Count(), 1); + Assert.AreEqual(preInstallWarnings.FilesReplaced.First(), "bin\\Auros.DocumentTypePicker.dll"); + + //TODO: More Asserts } [Test] diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/views/installed.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/views/installed.controller.js index 6e0e162e86..5265897708 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/views/installed.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/views/installed.controller.js @@ -25,7 +25,7 @@ var labelKeys = [ "packager_installStateUninstalling", - "packager_installStateComplete", + "packager_installStateComplete" ]; localizationService.localizeMany(labelKeys).then(function (values) { diff --git a/src/Umbraco.Web/Search/ExamineComponent.cs b/src/Umbraco.Web/Search/ExamineComponent.cs index 09d0c555da..336fcc7aec 100644 --- a/src/Umbraco.Web/Search/ExamineComponent.cs +++ b/src/Umbraco.Web/Search/ExamineComponent.cs @@ -446,7 +446,7 @@ namespace Umbraco.Web.Search while (page * pageSize < total) { //paging with examine, see https://shazwazza.com/post/paging-with-examine/ - var results = searcher.CreateQuery().Field("nodeType", id).Execute(maxResults: pageSize * (page + 1)); + var results = searcher.CreateQuery().Field("nodeType", id.ToInvariantString()).Execute(maxResults: pageSize * (page + 1)); total = results.TotalItemCount; var paged = results.Skip(page * pageSize); From 709df804e5ac3069e768eba7b153fc82f3889890 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 16 Jan 2019 00:13:40 +1100 Subject: [PATCH 359/469] Updates tests and better type support for importing content --- .../Models/Packaging/CompiledPackage.cs | 12 +- .../Packaging/CompiledPackageDocument.cs | 26 +++++ .../Models/Packaging/CompiledPackageFile.cs | 25 +++++ .../Packaging/CompiledPackageXmlParser.cs | 10 +- .../Packaging/PackageDataInstallation.cs | 59 +++++----- .../Packaging/PackageInstallation.cs | 1 - src/Umbraco.Core/Umbraco.Core.csproj | 2 + .../PackageDataInstallationTests.cs} | 105 +++++++++--------- .../Packaging/PackageInstallationTest.cs | 39 ++++++- .../Packaging/Packages/Hello_1.0.0.zip | Bin 0 -> 1529 bytes src/Umbraco.Tests/Umbraco.Tests.csproj | 2 +- 11 files changed, 172 insertions(+), 109 deletions(-) create mode 100644 src/Umbraco.Core/Models/Packaging/CompiledPackageDocument.cs create mode 100644 src/Umbraco.Core/Models/Packaging/CompiledPackageFile.cs rename src/Umbraco.Tests/{Services/Importing/PackageImportTests.cs => Packaging/PackageDataInstallationTests.cs} (84%) create mode 100644 src/Umbraco.Tests/Packaging/Packages/Hello_1.0.0.zip diff --git a/src/Umbraco.Core/Models/Packaging/CompiledPackage.cs b/src/Umbraco.Core/Models/Packaging/CompiledPackage.cs index d458337bf9..a852fcc997 100644 --- a/src/Umbraco.Core/Models/Packaging/CompiledPackage.cs +++ b/src/Umbraco.Core/Models/Packaging/CompiledPackage.cs @@ -39,16 +39,6 @@ namespace Umbraco.Core.Models.Packaging public IEnumerable Languages { get; set; } //fixme: make strongly typed public IEnumerable DictionaryItems { get; set; } //fixme: make strongly typed public IEnumerable DocumentTypes { get; set; } //fixme: make strongly typed - public IEnumerable Documents { get; set; } //fixme: make strongly typed + public IEnumerable Documents { get; set; } } - - public class CompiledPackageFile - { - public string OriginalPath { get; set; } - public string UniqueFileName { get; set; } - public string OriginalName { get; set; } - - } - - } diff --git a/src/Umbraco.Core/Models/Packaging/CompiledPackageDocument.cs b/src/Umbraco.Core/Models/Packaging/CompiledPackageDocument.cs new file mode 100644 index 0000000000..c41966dfe1 --- /dev/null +++ b/src/Umbraco.Core/Models/Packaging/CompiledPackageDocument.cs @@ -0,0 +1,26 @@ +using System; +using System.Xml.Linq; + +namespace Umbraco.Core.Models.Packaging +{ + public class CompiledPackageDocument + { + public static CompiledPackageDocument Create(XElement xml) + { + if (xml.Name.LocalName != "DocumentSet") + throw new ArgumentException("The xml isn't formatted correctly, a document element is defined by ", nameof(xml)); + return new CompiledPackageDocument + { + XmlData = xml, + ImportMode = xml.AttributeValue("importMode") + }; + } + + public string ImportMode { get; set; } //this is never used + + /// + /// The serialized version of the content + /// + public XElement XmlData { get; set; } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Packaging/CompiledPackageFile.cs b/src/Umbraco.Core/Models/Packaging/CompiledPackageFile.cs new file mode 100644 index 0000000000..2cb989b42b --- /dev/null +++ b/src/Umbraco.Core/Models/Packaging/CompiledPackageFile.cs @@ -0,0 +1,25 @@ +using System; +using System.Xml.Linq; + +namespace Umbraco.Core.Models.Packaging +{ + public class CompiledPackageFile + { + public static CompiledPackageFile Create(XElement xml) + { + if (xml.Name.LocalName != "file") + throw new ArgumentException("The xml isn't formatted correctly, a file element is defined by ", nameof(xml)); + return new CompiledPackageFile + { + UniqueFileName = xml.Element("guid")?.Value, + OriginalName = xml.Element("orgName")?.Value, + OriginalPath = xml.Element("orgPath")?.Value + }; + } + + public string OriginalPath { get; set; } + public string UniqueFileName { get; set; } + public string OriginalName { get; set; } + + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs b/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs index be9c69667a..4695ccb673 100644 --- a/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs +++ b/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs @@ -53,13 +53,7 @@ namespace Umbraco.Core.Packaging UmbracoVersionRequirementsType = requirements.AttributeValue("type").IsNullOrWhiteSpace() ? RequirementsType.Legacy : Enum.Parse(requirements.AttributeValue("type")), Control = package.Element("control")?.Value, Actions = xml.Root.Element("Actions")?.ToString(SaveOptions.None) ?? "", //take the entire outer xml value - Files = xml.Root.Element("files")?.Elements("file")?.Select(x => new CompiledPackageFile - { - UniqueFileName = x.Element("guid")?.Value, - OriginalName = x.Element("orgName")?.Value, - OriginalPath = x.Element("orgPath")?.Value - }).ToList() ?? new List(), - + Files = xml.Root.Element("files")?.Elements("file")?.Select(CompiledPackageFile.Create).ToList() ?? new List(), Macros = xml.Root.Element("Macros")?.Elements("macro") ?? Enumerable.Empty(), Templates = xml.Root.Element("Templates")?.Elements("Template") ?? Enumerable.Empty(), Stylesheets = xml.Root.Element("Stylesheets")?.Elements("styleSheet") ?? Enumerable.Empty(), @@ -67,7 +61,7 @@ namespace Umbraco.Core.Packaging Languages = xml.Root.Element("Languages")?.Elements("Language") ?? Enumerable.Empty(), DictionaryItems = xml.Root.Element("DictionaryItems")?.Elements("DictionaryItem") ?? Enumerable.Empty(), DocumentTypes = xml.Root.Element("DocumentTypes")?.Elements("DocumentType") ?? Enumerable.Empty(), - Documents = xml.Root.Element("Documents")?.Elements("DocumentSet") ?? Enumerable.Empty(), + Documents = xml.Root.Element("Documents")?.Elements("DocumentSet")?.Select(CompiledPackageDocument.Create) ?? Enumerable.Empty(), }; def.Warnings = GetPreInstallWarnings(def, applicationRootFolder); diff --git a/src/Umbraco.Core/Packaging/PackageDataInstallation.cs b/src/Umbraco.Core/Packaging/PackageDataInstallation.cs index 1743bb0041..2212a8957d 100644 --- a/src/Umbraco.Core/Packaging/PackageDataInstallation.cs +++ b/src/Umbraco.Core/Packaging/PackageDataInstallation.cs @@ -170,51 +170,48 @@ namespace Umbraco.Core.Packaging #region Content - public IEnumerable ImportContent(IEnumerable element, IDictionary importedDocumentTypes, int userId) + public IEnumerable ImportContent(IEnumerable docs, IDictionary importedDocumentTypes, int userId) { - return element.Elements("DocumentSet").SelectMany(x => ImportContent(x, -1, importedDocumentTypes, userId)); + return docs.SelectMany(x => ImportContent(x, -1, importedDocumentTypes, userId)); } /// /// Imports and saves package xml as /// - /// Xml to import + /// Xml to import /// Optional parent Id for the content being imported /// A dictionary of already imported document types (basically used as a cache) /// Optional Id of the user performing the import /// An enumrable list of generated content - public IEnumerable ImportContent(XElement element, int parentId, IDictionary importedDocumentTypes, int userId) + public IEnumerable ImportContent(CompiledPackageDocument packageDocument, int parentId, IDictionary importedDocumentTypes, int userId) { - var name = element.Name.LocalName; - if (name.Equals("DocumentSet")) - { - //This is a regular deep-structured import - var roots = from doc in element.Elements() - where (string)doc.Attribute("isDoc") == "" - select doc; + var element = packageDocument.XmlData; - var contents = ParseDocumentRootXml(roots, parentId, importedDocumentTypes).ToList(); - if (contents.Any()) - _contentService.Save(contents, userId); - - return contents; - } + var roots = from doc in element.Elements() + where (string)doc.Attribute("isDoc") == "" + select doc; - var attribute = element.Attribute("isDoc"); - if (attribute != null) - { - //This is a single doc import - var elements = new List { element }; - var contents = ParseDocumentRootXml(elements, parentId, importedDocumentTypes).ToList(); - if (contents.Any()) - _contentService.Save(contents, userId); - - return contents; - } + var contents = ParseDocumentRootXml(roots, parentId, importedDocumentTypes).ToList(); + if (contents.Any()) + _contentService.Save(contents, userId); - throw new ArgumentException( - "The passed in XElement is not valid! It does not contain a root element called " + - "'DocumentSet' (for structured imports) nor is the first element a Document (for single document import)."); + return contents; + + //var attribute = element.Attribute("isDoc"); + //if (attribute != null) + //{ + // //This is a single doc import + // var elements = new List { element }; + // var contents = ParseDocumentRootXml(elements, parentId, importedDocumentTypes).ToList(); + // if (contents.Any()) + // _contentService.Save(contents, userId); + + // return contents; + //} + + //throw new ArgumentException( + // "The passed in XElement is not valid! It does not contain a root element called " + + // "'DocumentSet' (for structured imports) nor is the first element a Document (for single document import)."); } private IEnumerable ParseDocumentRootXml(IEnumerable roots, int parentId, IDictionary importedContentTypes) diff --git a/src/Umbraco.Core/Packaging/PackageInstallation.cs b/src/Umbraco.Core/Packaging/PackageInstallation.cs index ae9b8173f5..d7bb72836e 100644 --- a/src/Umbraco.Core/Packaging/PackageInstallation.cs +++ b/src/Umbraco.Core/Packaging/PackageInstallation.cs @@ -111,7 +111,6 @@ namespace Umbraco.Core.Packaging installationSummary.ContentInstalled = _packageDataInstallation.ImportContent(compiledPackage.Documents, importedDocTypes, userId); installationSummary.Actions = _parser.GetPackageActions(XElement.Parse(compiledPackage.Actions), compiledPackage.Name); installationSummary.MetaData = compiledPackage; - //fixme: Verify that this will work! installationSummary.FilesInstalled = packageDefinition.Files; //make sure the definition is up to date with everything diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 6b334b234b..cd974613eb 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -432,6 +432,8 @@ + + diff --git a/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs b/src/Umbraco.Tests/Packaging/PackageDataInstallationTests.cs similarity index 84% rename from src/Umbraco.Tests/Services/Importing/PackageImportTests.cs rename to src/Umbraco.Tests/Packaging/PackageDataInstallationTests.cs index f29a43c504..aecef34f4f 100644 --- a/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs +++ b/src/Umbraco.Tests/Packaging/PackageDataInstallationTests.cs @@ -3,24 +3,27 @@ using System.Linq; using System.Threading; using System.Xml.Linq; using NUnit.Framework; -using Umbraco.Core.Models; using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Core.Composing.Composers; using Umbraco.Core.Logging; +using Umbraco.Core.Models; +using Umbraco.Core.Models.Packaging; using Umbraco.Core.Packaging; using Umbraco.Core.Persistence.Dtos; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Services; +using Umbraco.Tests.Services; +using Umbraco.Tests.Services.Importing; using Umbraco.Tests.Testing; -namespace Umbraco.Tests.Services.Importing +namespace Umbraco.Tests.Packaging { [TestFixture] [Category("Slow")] [Apartment(ApartmentState.STA)] [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)] - public class PackageImportTests : TestWithSomeContentBase + public class PackageDataInstallationTests : TestWithSomeContentBase { [HideFromTypeFinder] public class Editor1 : DataEditor @@ -66,7 +69,7 @@ namespace Umbraco.Tests.Services.Importing Composition.ComposeFileSystems(); } - private PackageDataInstallation PackagingService => Factory.GetInstance(); + private PackageDataInstallation PackageDataInstallation => Factory.GetInstance(); [Test] public void PackagingService_Can_Import_uBlogsy_ContentTypes_And_Verify_Structure() @@ -79,9 +82,9 @@ namespace Umbraco.Tests.Services.Importing var docTypeElement = xml.Descendants("DocumentTypes").First(); // Act - var dataTypes = PackagingService.ImportDataTypes(dataTypeElement.Elements("DataType").ToList(), 0); - var templates = PackagingService.ImportTemplates(templateElement.Elements("Template").ToList(), 0); - var contentTypes = PackagingService.ImportDocumentTypes(docTypeElement.Elements("DocumentType"), 0); + var dataTypes = PackageDataInstallation.ImportDataTypes(dataTypeElement.Elements("DataType").ToList(), 0); + var templates = PackageDataInstallation.ImportTemplates(templateElement.Elements("Template").ToList(), 0); + var contentTypes = PackageDataInstallation.ImportDocumentTypes(docTypeElement.Elements("DocumentType"), 0); var numberOfTemplates = (from doc in templateElement.Elements("Template") select doc).Count(); var numberOfDocTypes = (from doc in docTypeElement.Elements("DocumentType") select doc).Count(); @@ -126,9 +129,9 @@ namespace Umbraco.Tests.Services.Importing var docTypeElement = xml.Descendants("DocumentTypes").First(); // Act - var dataTypes = PackagingService.ImportDataTypes(dataTypeElement.Elements("DataType").ToList(), 0); - var templates = PackagingService.ImportTemplates(templateElement.Elements("Template").ToList(), 0); - var contentTypes = PackagingService.ImportDocumentTypes(docTypeElement.Elements("DocumentType"), 0); + var dataTypes = PackageDataInstallation.ImportDataTypes(dataTypeElement.Elements("DataType").ToList(), 0); + var templates = PackageDataInstallation.ImportTemplates(templateElement.Elements("Template").ToList(), 0); + var contentTypes = PackageDataInstallation.ImportDocumentTypes(docTypeElement.Elements("DocumentType"), 0); // Assert var mRBasePage = contentTypes.First(x => x.Alias == "MRBasePage"); @@ -151,9 +154,9 @@ namespace Umbraco.Tests.Services.Importing var docTypeElement = xml.Descendants("DocumentTypes").First(); // Act - var dataTypes = PackagingService.ImportDataTypes(dataTypeElement.Elements("DataType").ToList(), 0); - var templates = PackagingService.ImportTemplates(templateElement.Elements("Template").ToList(), 0); - var contentTypes = PackagingService.ImportDocumentTypes(docTypeElement.Elements("DocumentType"), 0); + var dataTypes = PackageDataInstallation.ImportDataTypes(dataTypeElement.Elements("DataType").ToList(), 0); + var templates = PackageDataInstallation.ImportTemplates(templateElement.Elements("Template").ToList(), 0); + var contentTypes = PackageDataInstallation.ImportDocumentTypes(docTypeElement.Elements("DocumentType"), 0); var numberOfDocTypes = (from doc in docTypeElement.Elements("DocumentType") select doc).Count(); @@ -190,7 +193,7 @@ namespace Umbraco.Tests.Services.Importing var init = ServiceContext.FileService.GetTemplates().Count(); // Act - var templates = PackagingService.ImportTemplates(element.Elements("Template").ToList(), 0); + var templates = PackageDataInstallation.ImportTemplates(element.Elements("Template").ToList(), 0); var numberOfTemplates = (from doc in element.Elements("Template") select doc).Count(); var allTemplates = ServiceContext.FileService.GetTemplates(); @@ -213,7 +216,7 @@ namespace Umbraco.Tests.Services.Importing // Act - var templates = PackagingService.ImportTemplate(element.Elements("Template").First(), 0); + var templates = PackageDataInstallation.ImportTemplate(element.Elements("Template").First(), 0); // Assert Assert.That(templates, Is.Not.Null); @@ -233,9 +236,9 @@ namespace Umbraco.Tests.Services.Importing // Act - var dataTypeDefinitions = PackagingService.ImportDataTypes(dataTypeElement.Elements("DataType").ToList(), 0); - var templates = PackagingService.ImportTemplates(templateElement.Elements("Template").ToList(), 0); - var contentTypes = PackagingService.ImportDocumentTypes(docTypeElement.Elements("DocumentType"), 0); + var dataTypeDefinitions = PackageDataInstallation.ImportDataTypes(dataTypeElement.Elements("DataType").ToList(), 0); + var templates = PackageDataInstallation.ImportTemplates(templateElement.Elements("Template").ToList(), 0); + var contentTypes = PackageDataInstallation.ImportDocumentTypes(docTypeElement.Elements("DocumentType"), 0); var numberOfDocTypes = (from doc in docTypeElement.Elements("DocumentType") select doc).Count(); // Assert @@ -268,13 +271,13 @@ namespace Umbraco.Tests.Services.Importing var docTypeElement = xml.Descendants("DocumentTypes").First(); // Act - var dataTypeDefinitions = PackagingService.ImportDataTypes(dataTypeElement.Elements("DataType").ToList(), 0); - var templates = PackagingService.ImportTemplates(templateElement.Elements("Template").ToList(), 0); - var contentTypes = PackagingService.ImportDocumentTypes(docTypeElement.Elements("DocumentType"), 0); + var dataTypeDefinitions = PackageDataInstallation.ImportDataTypes(dataTypeElement.Elements("DataType").ToList(), 0); + var templates = PackageDataInstallation.ImportTemplates(templateElement.Elements("Template").ToList(), 0); + var contentTypes = PackageDataInstallation.ImportDocumentTypes(docTypeElement.Elements("DocumentType"), 0); var numberOfDocTypes = (from doc in docTypeElement.Elements("DocumentType") select doc).Count(); //Assert - Re-Import contenttypes doesn't throw - Assert.DoesNotThrow(() => PackagingService.ImportDocumentTypes(docTypeElement.Elements("DocumentType"), 0)); + Assert.DoesNotThrow(() => PackageDataInstallation.ImportDocumentTypes(docTypeElement.Elements("DocumentType"), 0)); Assert.That(contentTypes.Count(), Is.EqualTo(numberOfDocTypes)); Assert.That(dataTypeDefinitions, Is.Not.Null); Assert.That(dataTypeDefinitions.Any(), Is.True); @@ -292,13 +295,13 @@ namespace Umbraco.Tests.Services.Importing var docTypeElement = xml.Descendants("DocumentTypes").First(); // Act - var dataTypeDefinitions = PackagingService.ImportDataTypes(dataTypeElement.Elements("DataType").ToList(), 0); - var templates = PackagingService.ImportTemplates(templateElement.Elements("Template").ToList(), 0); - var contentTypes = PackagingService.ImportDocumentTypes(docTypeElement.Elements("DocumentType"), 0); + var dataTypeDefinitions = PackageDataInstallation.ImportDataTypes(dataTypeElement.Elements("DataType").ToList(), 0); + var templates = PackageDataInstallation.ImportTemplates(templateElement.Elements("Template").ToList(), 0); + var contentTypes = PackageDataInstallation.ImportDocumentTypes(docTypeElement.Elements("DocumentType"), 0); var numberOfDocTypes = (from doc in docTypeElement.Elements("DocumentType") select doc).Count(); //Assert - Re-Import contenttypes doesn't throw - Assert.DoesNotThrow(() => PackagingService.ImportDocumentTypes(docTypeElement.Elements("DocumentType"), 0)); + Assert.DoesNotThrow(() => PackageDataInstallation.ImportDocumentTypes(docTypeElement.Elements("DocumentType"), 0)); Assert.That(contentTypes.Count(), Is.EqualTo(numberOfDocTypes)); Assert.That(dataTypeDefinitions, Is.Not.Null); Assert.That(dataTypeDefinitions.Any(), Is.True); @@ -314,13 +317,13 @@ namespace Umbraco.Tests.Services.Importing var dataTypeElement = xml.Descendants("DataTypes").First(); var docTypesElement = xml.Descendants("DocumentTypes").First(); var element = xml.Descendants("DocumentSet").First(); - + var packageDocument = CompiledPackageDocument.Create(element); // Act - var dataTypeDefinitions = PackagingService.ImportDataTypes(dataTypeElement.Elements("DataType").ToList(), 0); - var contentTypes = PackagingService.ImportDocumentTypes(docTypesElement.Elements("DocumentType"), 0); + var dataTypeDefinitions = PackageDataInstallation.ImportDataTypes(dataTypeElement.Elements("DataType").ToList(), 0); + var contentTypes = PackageDataInstallation.ImportDocumentTypes(docTypesElement.Elements("DocumentType"), 0); var importedContentTypes = contentTypes.ToDictionary(x => x.Alias, x => x); - var contents = PackagingService.ImportContent(element, -1, importedContentTypes, 0); + var contents = PackageDataInstallation.ImportContent(packageDocument, -1, importedContentTypes, 0); var numberOfDocs = (from doc in element.Descendants() where (string) doc.Attribute("isDoc") == "" select doc).Count(); @@ -348,13 +351,13 @@ namespace Umbraco.Tests.Services.Importing var dataTypeElement = xml.Descendants("DataTypes").First(); var docTypesElement = xml.Descendants("DocumentTypes").First(); var element = xml.Descendants("DocumentSet").First(); - + var packageDocument = CompiledPackageDocument.Create(element); // Act - var dataTypeDefinitions = PackagingService.ImportDataTypes(dataTypeElement.Elements("DataType").ToList(), 0); - var contentTypes = PackagingService.ImportDocumentTypes(docTypesElement.Elements("DocumentType"), 0); + var dataTypeDefinitions = PackageDataInstallation.ImportDataTypes(dataTypeElement.Elements("DataType").ToList(), 0); + var contentTypes = PackageDataInstallation.ImportDocumentTypes(docTypesElement.Elements("DocumentType"), 0); var importedContentTypes = contentTypes.ToDictionary(x => x.Alias, x => x); - var contents = PackagingService.ImportContent(element, -1, importedContentTypes, 0); + var contents = PackageDataInstallation.ImportContent(packageDocument, -1, importedContentTypes, 0); var numberOfDocs = (from doc in element.Descendants() where (string)doc.Attribute("isDoc") == "" select doc).Count(); @@ -387,7 +390,7 @@ namespace Umbraco.Tests.Services.Importing // Act - var templates = PackagingService.ImportTemplates(templateElement.Elements("Template").ToList(), 0); + var templates = PackageDataInstallation.ImportTemplates(templateElement.Elements("Template").ToList(), 0); var numberOfTemplates = (from doc in templateElement.Elements("Template") select doc).Count(); // Assert @@ -404,7 +407,7 @@ namespace Umbraco.Tests.Services.Importing // Act - var contentTypes = PackagingService.ImportDocumentType(docTypeElement, 0); + var contentTypes = PackageDataInstallation.ImportDocumentType(docTypeElement, 0); // Assert Assert.That(contentTypes.Any(), Is.True); @@ -422,7 +425,7 @@ namespace Umbraco.Tests.Services.Importing var serializer = Factory.GetInstance(); // Act - var contentTypes = PackagingService.ImportDocumentType(docTypeElement, 0); + var contentTypes = PackageDataInstallation.ImportDocumentType(docTypeElement, 0); var contentType = contentTypes.FirstOrDefault(); var element = serializer.Serialize(contentType); @@ -444,8 +447,8 @@ namespace Umbraco.Tests.Services.Importing var docTypeElement = XElement.Parse(strXml); // Act - var contentTypes = PackagingService.ImportDocumentType(docTypeElement, 0); - var contentTypesUpdated = PackagingService.ImportDocumentType(docTypeElement, 0); + var contentTypes = PackageDataInstallation.ImportDocumentType(docTypeElement, 0); + var contentTypesUpdated = PackageDataInstallation.ImportDocumentType(docTypeElement, 0); // Assert Assert.That(contentTypes.Any(), Is.True); @@ -475,8 +478,8 @@ namespace Umbraco.Tests.Services.Importing // Act var numberOfTemplates = (from doc in templateElement.Elements("Template") select doc).Count(); - var templates = PackagingService.ImportTemplates(templateElement.Elements("Template").ToList(), 0); - var templatesAfterUpdate = PackagingService.ImportTemplates(templateElementUpdated.Elements("Template").ToList(), 0); + var templates = PackageDataInstallation.ImportTemplates(templateElement.Elements("Template").ToList(), 0); + var templatesAfterUpdate = PackageDataInstallation.ImportTemplates(templateElementUpdated.Elements("Template").ToList(), 0); var allTemplates = fileService.GetTemplates(); // Assert @@ -502,7 +505,7 @@ namespace Umbraco.Tests.Services.Importing AddLanguages(); // Act - PackagingService.ImportDictionaryItems(dictionaryItemsElement.Elements("DictionaryItem"), 0); + PackageDataInstallation.ImportDictionaryItems(dictionaryItemsElement.Elements("DictionaryItem"), 0); // Assert AssertDictionaryItem("Parent", expectedEnglishParentValue, "en-GB"); @@ -524,7 +527,7 @@ namespace Umbraco.Tests.Services.Importing AddLanguages(); // Act - var dictionaryItems = PackagingService.ImportDictionaryItems(dictionaryItemsElement.Elements("DictionaryItem"), 0); + var dictionaryItems = PackageDataInstallation.ImportDictionaryItems(dictionaryItemsElement.Elements("DictionaryItem"), 0); // Assert Assert.That(ServiceContext.LocalizationService.DictionaryItemExists(parentKey), "DictionaryItem parentKey does not exist"); @@ -553,7 +556,7 @@ namespace Umbraco.Tests.Services.Importing AddExistingEnglishAndNorwegianParentDictionaryItem(expectedEnglishParentValue, expectedNorwegianParentValue); // Act - PackagingService.ImportDictionaryItems(dictionaryItemsElement.Elements("DictionaryItem"), 0); + PackageDataInstallation.ImportDictionaryItems(dictionaryItemsElement.Elements("DictionaryItem"), 0); // Assert AssertDictionaryItem("Parent", expectedEnglishParentValue, "en-GB"); @@ -578,7 +581,7 @@ namespace Umbraco.Tests.Services.Importing AddExistingEnglishParentDictionaryItem(expectedEnglishParentValue); // Act - PackagingService.ImportDictionaryItems(dictionaryItemsElement.Elements("DictionaryItem"), 0); + PackageDataInstallation.ImportDictionaryItems(dictionaryItemsElement.Elements("DictionaryItem"), 0); // Assert AssertDictionaryItem("Parent", expectedEnglishParentValue, "en-GB"); @@ -595,7 +598,7 @@ namespace Umbraco.Tests.Services.Importing var LanguageItemsElement = newPackageXml.Elements("Languages").First(); // Act - var languages = PackagingService.ImportLanguages(LanguageItemsElement.Elements("Language"), 0); + var languages = PackageDataInstallation.ImportLanguages(LanguageItemsElement.Elements("Language"), 0); var allLanguages = ServiceContext.LocalizationService.GetAllLanguages(); // Assert @@ -616,7 +619,7 @@ namespace Umbraco.Tests.Services.Importing // Act - var macros = PackagingService.ImportMacros(macrosElement.Elements("macro"), 0).ToList(); + var macros = PackageDataInstallation.ImportMacros(macrosElement.Elements("macro"), 0).ToList(); // Assert Assert.That(macros.Any(), Is.True); @@ -638,7 +641,7 @@ namespace Umbraco.Tests.Services.Importing // Act - var macros = PackagingService.ImportMacros(macrosElement.Elements("macro"), 0).ToList(); + var macros = PackageDataInstallation.ImportMacros(macrosElement.Elements("macro"), 0).ToList(); // Assert Assert.That(macros.Any(), Is.True); @@ -662,8 +665,8 @@ namespace Umbraco.Tests.Services.Importing // Act - var templates = PackagingService.ImportTemplates(templateElement.Elements("Template").ToList(), 0); - var contentTypes = PackagingService.ImportDocumentTypes(docTypeElement.Elements("DocumentType"), 0); + var templates = PackageDataInstallation.ImportTemplates(templateElement.Elements("Template").ToList(), 0); + var contentTypes = PackageDataInstallation.ImportDocumentTypes(docTypeElement.Elements("DocumentType"), 0); var numberOfDocTypes = (from doc in docTypeElement.Elements("DocumentType") select doc).Count(); // Assert @@ -690,7 +693,7 @@ namespace Umbraco.Tests.Services.Importing // Act - var contentTypes = PackagingService.ImportDocumentTypes(docTypeElement.Elements("DocumentType"), 0); + var contentTypes = PackageDataInstallation.ImportDocumentTypes(docTypeElement.Elements("DocumentType"), 0); var numberOfDocTypes = (from doc in docTypeElement.Elements("DocumentType") select doc).Count(); // Assert diff --git a/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs b/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs index 8fcacbeff7..d944b638ad 100644 --- a/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs +++ b/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs @@ -53,14 +53,15 @@ namespace Umbraco.Tests.Packaging applicationRootFolder: new DirectoryInfo(IOHelper.GetRootDirectorySafe()), packageExtractionFolder: new DirectoryInfo(IOHelper.MapPath("~/" + _testBaseFolder))); //we don't want to extract package files to the real root, so extract to a test folder - private const string DocumentTypePickerUmb = "Document_Type_Picker_1.1.umb"; + private const string DocumentTypePickerPackage = "Document_Type_Picker_1.1.umb"; + private const string HelloPackage = "Hello_1.0.0.zip"; [Test] - public void Can_Read_Compiled_Package() + public void Can_Read_Compiled_Package_1() { var package = PackageInstallation.ReadPackage( //this is where our test zip file is - new FileInfo(Path.Combine(IOHelper.MapPath("~/Packaging/packages"), DocumentTypePickerUmb))); + new FileInfo(Path.Combine(IOHelper.MapPath("~/Packaging/packages"), DocumentTypePickerPackage))); Assert.IsNotNull(package); Assert.AreEqual(1, package.Files.Count); Assert.AreEqual("095e064b-ba4d-442d-9006-3050983c13d8.dll", package.Files[0].UniqueFileName); @@ -78,6 +79,32 @@ namespace Umbraco.Tests.Packaging Assert.AreEqual(1, package.DataTypes.Count()); } + [Test] + public void Can_Read_Compiled_Package_2() + { + var package = PackageInstallation.ReadPackage( + //this is where our test zip file is + new FileInfo(Path.Combine(IOHelper.MapPath("~/Packaging/packages"), HelloPackage))); + Assert.IsNotNull(package); + Assert.AreEqual(0, package.Files.Count); + Assert.AreEqual("Hello", package.Name); + Assert.AreEqual("1.0.0", package.Version); + Assert.AreEqual("http://opensource.org/licenses/MIT", package.LicenseUrl); + Assert.AreEqual("MIT License", package.License); + Assert.AreEqual(8, package.UmbracoVersion.Major); + Assert.AreEqual(0, package.UmbracoVersion.Minor); + Assert.AreEqual(0, package.UmbracoVersion.Build); + Assert.AreEqual(RequirementsType.Strict, package.UmbracoVersionRequirementsType); + Assert.AreEqual("asdf", package.Author); + Assert.AreEqual("http://hello.com", package.AuthorUrl); + Assert.AreEqual("asdf", package.Readme); + Assert.AreEqual(1, package.Documents.Count()); + Assert.AreEqual("root", package.Documents.First().ImportMode); + Assert.AreEqual(1, package.DocumentTypes.Count()); + Assert.AreEqual(1, package.Templates.Count()); + Assert.AreEqual(1, package.DataTypes.Count()); + } + [Test] public void Can_Read_Compiled_Package_Warnings() { @@ -89,7 +116,7 @@ namespace Umbraco.Tests.Packaging var preInstallWarnings = PackageInstallation.ReadPackage( //this is where our test zip file is - new FileInfo(Path.Combine(IOHelper.MapPath("~/Packaging/packages"), DocumentTypePickerUmb))) + new FileInfo(Path.Combine(IOHelper.MapPath("~/Packaging/packages"), DocumentTypePickerPackage))) .Warnings; Assert.IsNotNull(preInstallWarnings); @@ -104,7 +131,7 @@ namespace Umbraco.Tests.Packaging { var package = PackageInstallation.ReadPackage( //this is where our test zip file is - new FileInfo(Path.Combine(IOHelper.MapPath("~/Packaging/packages"), DocumentTypePickerUmb))); + new FileInfo(Path.Combine(IOHelper.MapPath("~/Packaging/packages"), DocumentTypePickerPackage))); var def = PackageDefinition.FromCompiledPackage(package); def.Id = 1; @@ -126,7 +153,7 @@ namespace Umbraco.Tests.Packaging { var package = PackageInstallation.ReadPackage( //this is where our test zip file is - new FileInfo(Path.Combine(IOHelper.MapPath("~/Packaging/packages"), DocumentTypePickerUmb))); + new FileInfo(Path.Combine(IOHelper.MapPath("~/Packaging/packages"), DocumentTypePickerPackage))); var def = PackageDefinition.FromCompiledPackage(package); def.Id = 1; def.PackageId = Guid.NewGuid(); diff --git a/src/Umbraco.Tests/Packaging/Packages/Hello_1.0.0.zip b/src/Umbraco.Tests/Packaging/Packages/Hello_1.0.0.zip new file mode 100644 index 0000000000000000000000000000000000000000..c95cb282d14065396851362194fd37007cb632fe GIT binary patch literal 1529 zcmVeh01E&B0B~VrYhh<)E_iKh%~wlv z+cpqBH#7MUEDt@I;=|N46cg8)q?)l(kENssPYxgnN@yrT0YTfEOnzAp{Ym``U63FN z=#iw8OAofN59}_!UF?GY{PlP6@@bnH5118%=2O${Ii`X0m?k7&PtB62*2sJrK7SUJ z+vpa>AJG~EWf(z9GF%vTO^`gL)e6=-MXO@uXp6(&aF)@)uGXzYx(&f=&k5{?Y~>`T z`8$?{f!(ZHQAT2%7uYCSHZ?b#?`A^bCLYEICII&)wq zlvXw((q2rrfnBN|8U9ofhPOE9g~9hbJT;e`k(isU4rp!BpOl58z^)gngyg`0W7Z2r zvO_%H2uZzYJ=&_v23}joH$WxdDCTOkQIVvFU_auhARM1KW+Q1lXeQy@C;>ac&-d4} ztJT%Lu>IjfD59$bRRP#-1q3r1ms-RPV~M#zwmZuBf+m0-qg25z*zT7g&G0Q8&L9cY zqT>yH)A)$@Q!_#s`QtvahJNf={%GJ>k)L9#?Tqzq16hPKamlH#I%S9a*ktxuccmOqfY~kVhf~U@|r9ovW&p2A(tS=&OvN0=6rVw5O;oFE=R9X>J;i z3{rQR*_@YSFj9pNUPi+GZ5d^x*kC}Jvl43+%n8qwbXP~J@?8rQ&4jMk1Q(s|5|ssn zT4^^z^#+{Ea9?J)kE4Ek>3G&)FdmBxCl*RBJ!?2{5D)S0+_HOY4r8kLe{R?~WtFXY+&PpM8(R%p3C&USUSli5C%?>96{ zaBkdT&M;{7dmn5;0U?acns6g_u{b?rQ^sNIN0qwk?)OB4QaDMcZj0! zx-Mk!1B51BHqBJLQaVD@S)e=-O>5s&TgTA!-lL2FUqlet3ZWLvd1Su>^ch_j=P{S< z>D#E!z{89_=DpV$ej<@b)K~F$BiHZa(WNzV(gg4yMHU+MVU#(kI~=B|8@ut3D8P9V!qgnX#Y}X;HL6-zceaM{-|9=pq@ubP@zHhGS#oR~cAwz5 zt$brV$O<|?8bs43>%1F~uSmWDOyPr}sj5G4)LT5nJxPmRTv?L%h?j9z^t7?~sx07R z%+NH9sb;Yq^0o8@Z2J8C*-tlUPfHHEd6{Lv{89~Q8DxW=217?m)Rue?-+3F1dHb=q zKry2&HG?l8$R}d^IXpgE_6-cc65{Xl5J&pNmJFkQ(1=@W8gqE2oV|di(cK<+0Di}P zgB{={LWO*Ky?sC|-XM6b0h%dUmkia$KL7Hmr2NGKrVRn)Yic6i#uxRvI-F$ROKp-! zhAWjGP*yg3>mT_du8A)fhZ`@?ZajQiowMMbwQz$Xx#`0fv&n+3ry;nCyRi@7yWKbb zzfem70u%rg000080Jn)RPO_5QS%C!r02>eh01E&B0000000000000000001RVPk7y fXJsyUZER3W1qJ{B000310RTAw0062500000ehA61 literal 0 HcmV?d00001 diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index 8d3900088c..e49ba250fa 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -444,7 +444,7 @@ - + True True From db2a003444664d12935fed139d94ff0dc2cb76af Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 16 Jan 2019 00:54:25 +1100 Subject: [PATCH 360/469] change how the install status works, fixes infinite loop --- .../src/views/packages/views/install-local.controller.js | 2 +- src/Umbraco.Web/Search/ExamineComponent.cs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/views/install-local.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/views/install-local.controller.js index 6753fad942..17b417de48 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/views/install-local.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/views/install-local.controller.js @@ -171,7 +171,7 @@ }, installError) .then(function (pack) { - vm.installState.status = labels.installStateRestarting; + vm.installState.status = labels.installStateInstalling; vm.installState.progress = "75"; return packageResource.installData(pack); }, diff --git a/src/Umbraco.Web/Search/ExamineComponent.cs b/src/Umbraco.Web/Search/ExamineComponent.cs index 336fcc7aec..05a1258441 100644 --- a/src/Umbraco.Web/Search/ExamineComponent.cs +++ b/src/Umbraco.Web/Search/ExamineComponent.cs @@ -453,6 +453,7 @@ namespace Umbraco.Web.Search foreach (var item in paged) if (int.TryParse(item.Id, out var contentId)) DeleteIndexForEntity(contentId, false); + page++; } } } From 16eae7c4fc894d31b4510f6953ad9f545101d713 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Tue, 15 Jan 2019 14:54:34 +0100 Subject: [PATCH 361/469] #3305 Added optional culture parameter to Children and Descendants extension methods --- .../PublishedContentDataTableTests.cs | 496 ++--- .../PublishedContent/PublishedContentTests.cs | 1756 ++++++++--------- .../PublishedContent/PublishedMediaTests.cs | 1016 +++++----- src/Umbraco.Web/PublishedContentExtensions.cs | 115 +- 4 files changed, 1700 insertions(+), 1683 deletions(-) diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentDataTableTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentDataTableTests.cs index 3af930c4c3..4e3c17403b 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentDataTableTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentDataTableTests.cs @@ -1,248 +1,248 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; -using Moq; -using NUnit.Framework; -using Umbraco.Core; -using Umbraco.Core.Composing; -using Umbraco.Core.Logging; -using Umbraco.Core.Models; -using Umbraco.Core.Models.PublishedContent; -using Umbraco.Core.PropertyEditors; -using Umbraco.Core.Services; -using Umbraco.Tests.TestHelpers; -using Umbraco.Web; - -namespace Umbraco.Tests.PublishedContent -{ - /// - /// Unit tests for IPublishedContent and extensions - /// - [TestFixture] - public class PublishedContentDataTableTests : BaseWebTest - { - public override void SetUp() - { - base.SetUp(); - - // need to specify a different callback for testing - PublishedContentExtensions.GetPropertyAliasesAndNames = (services, alias) => - { - var userFields = new Dictionary() - { - {"property1", "Property 1"}, - {"property2", "Property 2"} - }; - if (alias == "Child") - { - userFields.Add("property4", "Property 4"); - } - else - { - userFields.Add("property3", "Property 3"); - } - - //ensure the standard fields are there - var allFields = new Dictionary() - { - {"Id", "Id"}, - {"NodeName", "NodeName"}, - {"NodeTypeAlias", "NodeTypeAlias"}, - {"CreateDate", "CreateDate"}, - {"UpdateDate", "UpdateDate"}, - {"CreatorName", "CreatorName"}, - {"WriterName", "WriterName"}, - {"Url", "Url"} - }; - foreach (var f in userFields.Where(f => !allFields.ContainsKey(f.Key))) - { - allFields.Add(f.Key, f.Value); - } - return allFields; - }; - var umbracoContext = GetUmbracoContext("/test"); - - //set the UmbracoContext.Current since the extension methods rely on it - Umbraco.Web.Composing.Current.UmbracoContextAccessor.UmbracoContext = umbracoContext; - } - - public override void TearDown() - { - base.TearDown(); - Umbraco.Web.PublishedContentExtensions.GetPropertyAliasesAndNames = null; - } - - [Test] - public void To_DataTable() - { - var doc = GetContent(true, 1); - var dt = doc.ChildrenAsTable(Current.Services); - - Assert.AreEqual(11, dt.Columns.Count); - Assert.AreEqual(3, dt.Rows.Count); - Assert.AreEqual("value4", dt.Rows[0]["Property 1"]); - Assert.AreEqual("value5", dt.Rows[0]["Property 2"]); - Assert.AreEqual("value6", dt.Rows[0]["Property 4"]); - Assert.AreEqual("value7", dt.Rows[1]["Property 1"]); - Assert.AreEqual("value8", dt.Rows[1]["Property 2"]); - Assert.AreEqual("value9", dt.Rows[1]["Property 4"]); - Assert.AreEqual("value10", dt.Rows[2]["Property 1"]); - Assert.AreEqual("value11", dt.Rows[2]["Property 2"]); - Assert.AreEqual("value12", dt.Rows[2]["Property 4"]); - } - - [Test] - public void To_DataTable_With_Filter() - { - var doc = GetContent(true, 1); - //change a doc type alias - var c = (TestPublishedContent) doc.Children.ElementAt(0); - c.ContentType = new PublishedContentType(22, "DontMatch", PublishedItemType.Content, Enumerable.Empty(), Enumerable.Empty(), ContentVariation.Nothing); - - var dt = doc.ChildrenAsTable(Current.Services, "Child"); - - Assert.AreEqual(11, dt.Columns.Count); - Assert.AreEqual(2, dt.Rows.Count); - Assert.AreEqual("value7", dt.Rows[0]["Property 1"]); - Assert.AreEqual("value8", dt.Rows[0]["Property 2"]); - Assert.AreEqual("value9", dt.Rows[0]["Property 4"]); - Assert.AreEqual("value10", dt.Rows[1]["Property 1"]); - Assert.AreEqual("value11", dt.Rows[1]["Property 2"]); - Assert.AreEqual("value12", dt.Rows[1]["Property 4"]); - } - - [Test] - public void To_DataTable_No_Rows() - { - var doc = GetContent(false, 1); - var dt = doc.ChildrenAsTable(Current.Services); - //will return an empty data table - Assert.AreEqual(0, dt.Columns.Count); - Assert.AreEqual(0, dt.Rows.Count); - } - - private IPublishedContent GetContent(bool createChildren, int indexVals) - { - var dataTypeService = new TestObjects.TestDataTypeService( - new DataType(new VoidEditor(Mock.Of())) { Id = 1 }); - - var factory = new PublishedContentTypeFactory(Mock.Of(), new PropertyValueConverterCollection(Array.Empty()), dataTypeService); - var contentTypeAlias = createChildren ? "Parent" : "Child"; - var d = new TestPublishedContent - { - CreateDate = DateTime.Now, - CreatorId = 1, - CreatorName = "Shannon", - Id = 3, - SortOrder = 4, - TemplateId = 5, - UpdateDate = DateTime.Now, - Path = "-1,3", - UrlSegment = "home-page", - Name = "Page" + Guid.NewGuid().ToString(), - Version = Guid.NewGuid(), - WriterId = 1, - WriterName = "Shannon", - Parent = null, - Level = 1, - Children = new List() - }; - d.Properties = new Collection(new List - { - new RawValueProperty(factory.CreatePropertyType("property1", 1), d, "value" + indexVals), - new RawValueProperty(factory.CreatePropertyType("property2", 1), d, "value" + (indexVals + 1)) - }); - if (createChildren) - { - d.Children = new List() - { - GetContent(false, indexVals + 3), - GetContent(false, indexVals + 6), - GetContent(false, indexVals + 9) - }; - } - - if (!createChildren) - { - //create additional columns, used to test the different columns for child nodes - ((Collection) d.Properties).Add( - new RawValueProperty(factory.CreatePropertyType("property4",1), d, "value" + (indexVals + 2))); - } - else - { - ((Collection) d.Properties).Add( - new RawValueProperty(factory.CreatePropertyType("property3", 1), d, "value" + (indexVals + 2))); - } - - d.ContentType = new PublishedContentType(22, contentTypeAlias, PublishedItemType.Content, Enumerable.Empty(), Enumerable.Empty(), ContentVariation.Nothing); - return d; - } - - // note - could probably rewrite those tests using SolidPublishedContentCache - // l8tr... - private class TestPublishedContent : IPublishedContent - { - public string Url { get; set; } - public string GetUrl(string culture = null) => throw new NotSupportedException(); - - public PublishedItemType ItemType { get; set; } - - IPublishedContent IPublishedContent.Parent - { - get { return Parent; } - } - - IEnumerable IPublishedContent.Children - { - get { return Children; } - } - - public IPublishedContent Parent { get; set; } - public int Id { get; set; } - public Guid Key { get; set; } - public int? TemplateId { get; set; } - public int SortOrder { get; set; } - public string Name { get; set; } - public PublishedCultureInfo GetCulture(string culture = null) => throw new NotSupportedException(); - public IReadOnlyDictionary Cultures => throw new NotSupportedException(); - public string UrlSegment { get; set; } - public string WriterName { get; set; } - public string CreatorName { get; set; } - public int WriterId { get; set; } - public int CreatorId { get; set; } - public string Path { get; set; } - public DateTime CreateDate { get; set; } - public DateTime UpdateDate { get; set; } - public Guid Version { get; set; } - public int Level { get; set; } - public bool IsDraft(string culture = null) => false; - - public IEnumerable Properties { get; set; } - - public IEnumerable Children { get; set; } - - public IPublishedProperty GetProperty(string alias) - { - return Properties.FirstOrDefault(x => x.Alias.InvariantEquals(alias)); - } - - public IPublishedProperty GetProperty(string alias, bool recurse) - { - var property = GetProperty(alias); - if (recurse == false) return property; - - IPublishedContent content = this; - while (content != null && (property == null || property.HasValue() == false)) - { - content = content.Parent; - property = content == null ? null : content.GetProperty(alias); - } - - return property; - } - - public PublishedContentType ContentType { get; set; } - } - } -} +//using System; +//using System.Collections.Generic; +//using System.Collections.ObjectModel; +//using System.Linq; +//using Moq; +//using NUnit.Framework; +//using Umbraco.Core; +//using Umbraco.Core.Composing; +//using Umbraco.Core.Logging; +//using Umbraco.Core.Models; +//using Umbraco.Core.Models.PublishedContent; +//using Umbraco.Core.PropertyEditors; +//using Umbraco.Core.Services; +//using Umbraco.Tests.TestHelpers; +//using Umbraco.Web; +// +//namespace Umbraco.Tests.PublishedContent +//{ +// /// +// /// Unit tests for IPublishedContent and extensions +// /// +// [TestFixture] +// public class PublishedContentDataTableTests : BaseWebTest +// { +// public override void SetUp() +// { +// base.SetUp(); +// +// // need to specify a different callback for testing +// PublishedContentExtensions.GetPropertyAliasesAndNames = (services, alias) => +// { +// var userFields = new Dictionary() +// { +// {"property1", "Property 1"}, +// {"property2", "Property 2"} +// }; +// if (alias == "Child") +// { +// userFields.Add("property4", "Property 4"); +// } +// else +// { +// userFields.Add("property3", "Property 3"); +// } +// +// //ensure the standard fields are there +// var allFields = new Dictionary() +// { +// {"Id", "Id"}, +// {"NodeName", "NodeName"}, +// {"NodeTypeAlias", "NodeTypeAlias"}, +// {"CreateDate", "CreateDate"}, +// {"UpdateDate", "UpdateDate"}, +// {"CreatorName", "CreatorName"}, +// {"WriterName", "WriterName"}, +// {"Url", "Url"} +// }; +// foreach (var f in userFields.Where(f => !allFields.ContainsKey(f.Key))) +// { +// allFields.Add(f.Key, f.Value); +// } +// return allFields; +// }; +// var umbracoContext = GetUmbracoContext("/test"); +// +// //set the UmbracoContext.Current since the extension methods rely on it +// Umbraco.Web.Composing.Current.UmbracoContextAccessor.UmbracoContext = umbracoContext; +// } +// +// public override void TearDown() +// { +// base.TearDown(); +// Umbraco.Web.PublishedContentExtensions.GetPropertyAliasesAndNames = null; +// } +// +// [Test] +// public void To_DataTable() +// { +// var doc = GetContent(true, 1); +// var dt = doc.ChildrenAsTable(Current.Services); +// +// Assert.AreEqual(11, dt.Columns.Count); +// Assert.AreEqual(3, dt.Rows.Count); +// Assert.AreEqual("value4", dt.Rows[0]["Property 1"]); +// Assert.AreEqual("value5", dt.Rows[0]["Property 2"]); +// Assert.AreEqual("value6", dt.Rows[0]["Property 4"]); +// Assert.AreEqual("value7", dt.Rows[1]["Property 1"]); +// Assert.AreEqual("value8", dt.Rows[1]["Property 2"]); +// Assert.AreEqual("value9", dt.Rows[1]["Property 4"]); +// Assert.AreEqual("value10", dt.Rows[2]["Property 1"]); +// Assert.AreEqual("value11", dt.Rows[2]["Property 2"]); +// Assert.AreEqual("value12", dt.Rows[2]["Property 4"]); +// } +// +// [Test] +// public void To_DataTable_With_Filter() +// { +// var doc = GetContent(true, 1); +// //change a doc type alias +// var c = (TestPublishedContent) doc.Children.ElementAt(0); +// c.ContentType = new PublishedContentType(22, "DontMatch", PublishedItemType.Content, Enumerable.Empty(), Enumerable.Empty(), ContentVariation.Nothing); +// +// var dt = doc.ChildrenAsTable(Current.Services, "Child"); +// +// Assert.AreEqual(11, dt.Columns.Count); +// Assert.AreEqual(2, dt.Rows.Count); +// Assert.AreEqual("value7", dt.Rows[0]["Property 1"]); +// Assert.AreEqual("value8", dt.Rows[0]["Property 2"]); +// Assert.AreEqual("value9", dt.Rows[0]["Property 4"]); +// Assert.AreEqual("value10", dt.Rows[1]["Property 1"]); +// Assert.AreEqual("value11", dt.Rows[1]["Property 2"]); +// Assert.AreEqual("value12", dt.Rows[1]["Property 4"]); +// } +// +// [Test] +// public void To_DataTable_No_Rows() +// { +// var doc = GetContent(false, 1); +// var dt = doc.ChildrenAsTable(Current.Services); +// //will return an empty data table +// Assert.AreEqual(0, dt.Columns.Count); +// Assert.AreEqual(0, dt.Rows.Count); +// } +// +// private IPublishedContent GetContent(bool createChildren, int indexVals) +// { +// var dataTypeService = new TestObjects.TestDataTypeService( +// new DataType(new VoidEditor(Mock.Of())) { Id = 1 }); +// +// var factory = new PublishedContentTypeFactory(Mock.Of(), new PropertyValueConverterCollection(Array.Empty()), dataTypeService); +// var contentTypeAlias = createChildren ? "Parent" : "Child"; +// var d = new TestPublishedContent +// { +// CreateDate = DateTime.Now, +// CreatorId = 1, +// CreatorName = "Shannon", +// Id = 3, +// SortOrder = 4, +// TemplateId = 5, +// UpdateDate = DateTime.Now, +// Path = "-1,3", +// UrlSegment = "home-page", +// Name = "Page" + Guid.NewGuid().ToString(), +// Version = Guid.NewGuid(), +// WriterId = 1, +// WriterName = "Shannon", +// Parent = null, +// Level = 1, +// Children = new List() +// }; +// d.Properties = new Collection(new List +// { +// new RawValueProperty(factory.CreatePropertyType("property1", 1), d, "value" + indexVals), +// new RawValueProperty(factory.CreatePropertyType("property2", 1), d, "value" + (indexVals + 1)) +// }); +// if (createChildren) +// { +// d.Children = new List() +// { +// GetContent(false, indexVals + 3), +// GetContent(false, indexVals + 6), +// GetContent(false, indexVals + 9) +// }; +// } +// +// if (!createChildren) +// { +// //create additional columns, used to test the different columns for child nodes +// ((Collection) d.Properties).Add( +// new RawValueProperty(factory.CreatePropertyType("property4",1), d, "value" + (indexVals + 2))); +// } +// else +// { +// ((Collection) d.Properties).Add( +// new RawValueProperty(factory.CreatePropertyType("property3", 1), d, "value" + (indexVals + 2))); +// } +// +// d.ContentType = new PublishedContentType(22, contentTypeAlias, PublishedItemType.Content, Enumerable.Empty(), Enumerable.Empty(), ContentVariation.Nothing); +// return d; +// } +// +// // note - could probably rewrite those tests using SolidPublishedContentCache +// // l8tr... +// private class TestPublishedContent : IPublishedContent +// { +// public string Url { get; set; } +// public string GetUrl(string culture = null) => throw new NotSupportedException(); +// +// public PublishedItemType ItemType { get; set; } +// +// IPublishedContent IPublishedContent.Parent +// { +// get { return Parent; } +// } +// +// IEnumerable IPublishedContent.Children +// { +// get { return Children; } +// } +// +// public IPublishedContent Parent { get; set; } +// public int Id { get; set; } +// public Guid Key { get; set; } +// public int? TemplateId { get; set; } +// public int SortOrder { get; set; } +// public string Name { get; set; } +// public PublishedCultureInfo GetCulture(string culture = null) => throw new NotSupportedException(); +// public IReadOnlyDictionary Cultures => throw new NotSupportedException(); +// public string UrlSegment { get; set; } +// public string WriterName { get; set; } +// public string CreatorName { get; set; } +// public int WriterId { get; set; } +// public int CreatorId { get; set; } +// public string Path { get; set; } +// public DateTime CreateDate { get; set; } +// public DateTime UpdateDate { get; set; } +// public Guid Version { get; set; } +// public int Level { get; set; } +// public bool IsDraft(string culture = null) => false; +// +// public IEnumerable Properties { get; set; } +// +// public IEnumerable Children { get; set; } +// +// public IPublishedProperty GetProperty(string alias) +// { +// return Properties.FirstOrDefault(x => x.Alias.InvariantEquals(alias)); +// } +// +// public IPublishedProperty GetProperty(string alias, bool recurse) +// { +// var property = GetProperty(alias); +// if (recurse == false) return property; +// +// IPublishedContent content = this; +// while (content != null && (property == null || property.HasValue() == false)) +// { +// content = content.Parent; +// property = content == null ? null : content.GetProperty(alias); +// } +// +// return property; +// } +// +// public PublishedContentType ContentType { get; set; } +// } +// } +//} diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs index 914956dce1..6e652fdc68 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs @@ -1,878 +1,878 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using NUnit.Framework; -using Umbraco.Core; -using Umbraco.Core.Models.PublishedContent; -using Umbraco.Core.PropertyEditors; -using Umbraco.Web; -using Umbraco.Web.PublishedCache; -using Umbraco.Core.Composing; -using Moq; -using Umbraco.Core.Cache; -using Umbraco.Core.Configuration; -using Umbraco.Core.Logging; -using Umbraco.Core.Models; -using Umbraco.Core.Services; -using Umbraco.Tests.TestHelpers; -using Umbraco.Tests.Testing; -using Umbraco.Web.Models.PublishedContent; -using Umbraco.Web.PropertyEditors; - -namespace Umbraco.Tests.PublishedContent -{ - /// - /// Tests the methods on IPublishedContent using the DefaultPublishedContentStore - /// - [TestFixture] - [UmbracoTest(TypeLoader = UmbracoTestOptions.TypeLoader.PerFixture)] - public class PublishedContentTests : PublishedContentTestBase - { - protected override void Compose() - { - base.Compose(); - - Composition.RegisterUnique(f => new PublishedModelFactory(f.GetInstance().GetTypes())); - Composition.RegisterUnique(); - Composition.RegisterUnique(); - - var logger = Mock.Of(); - var dataTypeService = new TestObjects.TestDataTypeService( - new DataType(new VoidEditor(logger)) { Id = 1 }, - new DataType(new TrueFalsePropertyEditor(logger)) { Id = 1001 }, - new DataType(new RichTextPropertyEditor(logger)) { Id = 1002 }, - new DataType(new IntegerPropertyEditor(logger)) { Id = 1003 }, - new DataType(new TextboxPropertyEditor(logger)) { Id = 1004 }, - new DataType(new MediaPickerPropertyEditor(logger)) { Id = 1005 }); - Composition.RegisterUnique(f => dataTypeService); - } - - protected override void Initialize() - { - base.Initialize(); - - var factory = Factory.GetInstance() as PublishedContentTypeFactory; - - // need to specify a custom callback for unit tests - // AutoPublishedContentTypes generates properties automatically - // when they are requested, but we must declare those that we - // explicitely want to be here... - - var propertyTypes = new[] - { - // AutoPublishedContentType will auto-generate other properties - factory.CreatePropertyType("umbracoNaviHide", 1001), - factory.CreatePropertyType("selectedNodes", 1), - factory.CreatePropertyType("umbracoUrlAlias", 1), - factory.CreatePropertyType("content", 1002), - factory.CreatePropertyType("testRecursive", 1), - }; - var compositionAliases = new[] { "MyCompositionAlias" }; - var type = new AutoPublishedContentType(0, "anything", compositionAliases, propertyTypes); - ContentTypesCache.GetPublishedContentTypeByAlias = alias => type; - } - - protected override TypeLoader CreateTypeLoader(IRuntimeCacheProvider runtimeCache, IGlobalSettings globalSettings, IProfilingLogger logger) - { - var pluginManager = base.CreateTypeLoader(runtimeCache, globalSettings, logger); - - // this is so the model factory looks into the test assembly - pluginManager.AssembliesToScan = pluginManager.AssembliesToScan - .Union(new[] { typeof(PublishedContentTests).Assembly }) - .ToList(); - - return pluginManager; - } - - private readonly Guid _node1173Guid = Guid.NewGuid(); - - protected override string GetXmlContent(int templateId) - { - return @" - - - - -]> - - - - - 1 - - - This is some content]]> - - - - - - - - - - - - - - - - 1 - - - - - - - - - -"; - } - - internal IPublishedContent GetNode(int id) - { - var ctx = GetUmbracoContext("/test"); - var doc = ctx.ContentCache.GetById(id); - Assert.IsNotNull(doc); - return doc; - } - - [Test] - public void GetNodeByIds() - { - var ctx = GetUmbracoContext("/test"); - var contentById = ctx.ContentCache.GetById(1173); - Assert.IsNotNull(contentById); - var contentByGuid = ctx.ContentCache.GetById(_node1173Guid); - Assert.IsNotNull(contentByGuid); - Assert.AreEqual(contentById.Id, contentByGuid.Id); - Assert.AreEqual(contentById.Key, contentByGuid.Key); - - contentById = ctx.ContentCache.GetById(666); - Assert.IsNull(contentById); - contentByGuid = ctx.ContentCache.GetById(Guid.NewGuid()); - Assert.IsNull(contentByGuid); - } - - [Test] - public void Is_Last_From_Where_Filter_Dynamic_Linq() - { - var doc = GetNode(1173); - - var items = doc.Children.Where(x => x.IsVisible()).ToIndexedArray(); - - foreach (var item in items) - { - if (item.Content.Id != 1178) - { - Assert.IsFalse(item.IsLast()); - } - else - { - Assert.IsTrue(item.IsLast()); - } - } - } - - [Test] - public void Is_Last_From_Where_Filter() - { - var doc = GetNode(1173); - - var items = doc - .Children - .Where(x => x.IsVisible()) - .ToIndexedArray(); - - Assert.AreEqual(4, items.Length); - - foreach (var d in items) - { - switch (d.Content.Id) - { - case 1174: - Assert.IsTrue(d.IsFirst()); - Assert.IsFalse(d.IsLast()); - break; - case 117: - Assert.IsFalse(d.IsFirst()); - Assert.IsFalse(d.IsLast()); - break; - case 1177: - Assert.IsFalse(d.IsFirst()); - Assert.IsFalse(d.IsLast()); - break; - case 1178: - Assert.IsFalse(d.IsFirst()); - Assert.IsTrue(d.IsLast()); - break; - default: - Assert.Fail("Invalid id."); - break; - } - } - } - - [PublishedModel("Home")] - internal class Home : PublishedContentModel - { - public Home(IPublishedContent content) - : base(content) - {} - } - - [PublishedModel("anything")] - internal class Anything : PublishedContentModel - { - public Anything(IPublishedContent content) - : base(content) - { } - } - - [Test] - [Ignore("Fails as long as PublishedContentModel is internal.")] // fixme - public void Is_Last_From_Where_Filter2() - { - var doc = GetNode(1173); - - var items = doc.Children - .Select(x => x.CreateModel()) // linq, returns IEnumerable - - // only way around this is to make sure every IEnumerable extension - // explicitely returns a PublishedContentSet, not an IEnumerable - - .OfType() // ours, return IEnumerable (actually a PublishedContentSet) - .Where(x => x.IsVisible()) // so, here it's linq again :-( - .ToIndexedArray(); // so, we need that one for the test to pass - - Assert.AreEqual(1, items.Length); - - foreach (var d in items) - { - switch (d.Content.Id) - { - case 1174: - Assert.IsTrue(d.IsFirst()); - Assert.IsTrue(d.IsLast()); - break; - default: - Assert.Fail("Invalid id."); - break; - } - } - } - - [Test] - public void Is_Last_From_Take() - { - var doc = GetNode(1173); - - var items = doc.Children.Take(4).ToIndexedArray(); - - foreach (var item in items) - { - if (item.Content.Id != 1178) - { - Assert.IsFalse(item.IsLast()); - } - else - { - Assert.IsTrue(item.IsLast()); - } - } - } - - [Test] - public void Is_Last_From_Skip() - { - var doc = GetNode(1173); - - foreach (var d in doc.Children.Skip(1).ToIndexedArray()) - { - if (d.Content.Id != 1176) - { - Assert.IsFalse(d.IsLast()); - } - else - { - Assert.IsTrue(d.IsLast()); - } - } - } - - [Test] - public void Is_Last_From_Concat() - { - var doc = GetNode(1173); - - var items = doc.Children - .Concat(new[] { GetNode(1175), GetNode(4444) }) - .ToIndexedArray(); - - foreach (var item in items) - { - if (item.Content.Id != 4444) - { - Assert.IsFalse(item.IsLast()); - } - else - { - Assert.IsTrue(item.IsLast()); - } - } - } - - [Test] - public void Descendants_Ordered_Properly() - { - var doc = GetNode(1046); - - var expected = new[] { 1046, 1173, 1174, 117, 1177, 1178, 1179, 1176, 1175, 4444, 1172 }; - var exindex = 0; - - // must respect the XPath descendants-or-self axis! - foreach (var d in doc.DescendantsOrSelf()) - Assert.AreEqual(expected[exindex++], d.Id); - } - - [Test] - public void Get_Property_Value_Recursive() - { - var doc = GetNode(1174); - var rVal = doc.Value("testRecursive", fallback: Fallback.ToAncestors); - var nullVal = doc.Value("DoNotFindThis", fallback: Fallback.ToAncestors); - Assert.AreEqual("This is the recursive val", rVal); - Assert.AreEqual(null, nullVal); - } - - [Test] - public void Get_Property_Value_Uses_Converter() - { - var doc = GetNode(1173); - - var propVal = doc.Value("content"); - Assert.IsInstanceOf(typeof(IHtmlString), propVal); - Assert.AreEqual("
    This is some content
    ", propVal.ToString()); - - var propVal2 = doc.Value("content"); - Assert.IsInstanceOf(typeof(IHtmlString), propVal2); - Assert.AreEqual("
    This is some content
    ", propVal2.ToString()); - - var propVal3 = doc.Value("Content"); - Assert.IsInstanceOf(typeof(IHtmlString), propVal3); - Assert.AreEqual("
    This is some content
    ", propVal3.ToString()); - } - - [Test] - public void Complex_Linq() - { - var doc = GetNode(1173); - - var result = doc.Ancestors().OrderBy(x => x.Level) - .Single() - .Descendants() - .FirstOrDefault(x => x.Value("selectedNodes", defaultValue: "").Split(',').Contains("1173")); - - Assert.IsNotNull(result); - } - - [Test] - public void Children_GroupBy_DocumentTypeAlias() - { - var home = new AutoPublishedContentType(22, "Home", new PublishedPropertyType[] { }); - var custom = new AutoPublishedContentType(23, "CustomDocument", new PublishedPropertyType[] { }); - var contentTypes = new Dictionary - { - { home.Alias, home }, - { custom.Alias, custom } - }; - ContentTypesCache.GetPublishedContentTypeByAlias = alias => contentTypes[alias]; - - var doc = GetNode(1046); - - var found1 = doc.Children.GroupBy(x => x.ContentType.Alias).ToArray(); - - Assert.AreEqual(2, found1.Length); - Assert.AreEqual(2, found1.Single(x => x.Key.ToString() == "Home").Count()); - Assert.AreEqual(1, found1.Single(x => x.Key.ToString() == "CustomDocument").Count()); - } - - [Test] - public void Children_Where_DocumentTypeAlias() - { - var home = new AutoPublishedContentType(22, "Home", new PublishedPropertyType[] { }); - var custom = new AutoPublishedContentType(23, "CustomDocument", new PublishedPropertyType[] { }); - var contentTypes = new Dictionary - { - { home.Alias, home }, - { custom.Alias, custom } - }; - ContentTypesCache.GetPublishedContentTypeByAlias = alias => contentTypes[alias]; - - var doc = GetNode(1046); - - var found1 = doc.Children.Where(x => x.ContentType.Alias == "CustomDocument"); - var found2 = doc.Children.Where(x => x.ContentType.Alias == "Home"); - - Assert.AreEqual(1, found1.Count()); - Assert.AreEqual(2, found2.Count()); - } - - [Test] - public void Children_Order_By_Update_Date() - { - var doc = GetNode(1173); - - var ordered = doc.Children.OrderBy(x => x.UpdateDate); - - var correctOrder = new[] { 1178, 1177, 1174, 1176 }; - for (var i = 0; i < correctOrder.Length; i++) - { - Assert.AreEqual(correctOrder[i], ordered.ElementAt(i).Id); - } - - } - - [Test] - public void FirstChild() - { - var doc = GetNode(1173); // has child nodes - Assert.IsNotNull(doc.FirstChild()); - Assert.IsNotNull(doc.FirstChild(x => true)); - Assert.IsNotNull(doc.FirstChild()); - - doc = GetNode(1175); // does not have child nodes - Assert.IsNull(doc.FirstChild()); - Assert.IsNull(doc.FirstChild(x => true)); - Assert.IsNull(doc.FirstChild()); - } - - [Test] - public void FirstChildAsT() - { - var doc = GetNode(1046); // has child nodes - - var model = doc.FirstChild(x => true); // predicate - - Assert.IsNotNull(model); - Assert.IsTrue(model.Id == 1173); - Assert.IsInstanceOf(model); - Assert.IsInstanceOf(model); - - doc = GetNode(1175); // does not have child nodes - Assert.IsNull(doc.FirstChild()); - Assert.IsNull(doc.FirstChild(x => true)); - } - - [Test] - public void IsComposedOf() - { - var doc = GetNode(1173); - - var isComposedOf = doc.IsComposedOf("MyCompositionAlias"); - - Assert.IsTrue(isComposedOf); - } - - [Test] - public void HasProperty() - { - var doc = GetNode(1173); - - var hasProp = doc.HasProperty(Constants.Conventions.Content.UrlAlias); - - Assert.IsTrue(hasProp); - } - - [Test] - public void HasValue() - { - var doc = GetNode(1173); - - var hasValue = doc.HasValue(Constants.Conventions.Content.UrlAlias); - var noValue = doc.HasValue("blahblahblah"); - - Assert.IsTrue(hasValue); - Assert.IsFalse(noValue); - } - - [Test] - public void Ancestors_Where_Visible() - { - var doc = GetNode(1174); - - var whereVisible = doc.Ancestors().Where(x => x.IsVisible()); - Assert.AreEqual(1, whereVisible.Count()); - - } - - [Test] - public void Visible() - { - var hidden = GetNode(1046); - var visible = GetNode(1173); - - Assert.IsFalse(hidden.IsVisible()); - Assert.IsTrue(visible.IsVisible()); - } - - [Test] - public void Ancestor_Or_Self() - { - var doc = GetNode(1173); - - var result = doc.AncestorOrSelf(); - - Assert.IsNotNull(result); - - // ancestor-or-self has to be self! - Assert.AreEqual(1173, result.Id); - } - - [Test] - public void U4_4559() - { - var doc = GetNode(1174); - var result = doc.AncestorOrSelf(1); - Assert.IsNotNull(result); - Assert.AreEqual(1046, result.Id); - } - - [Test] - public void Ancestors_Or_Self() - { - var doc = GetNode(1174); - - var result = doc.AncestorsOrSelf().ToArray(); - - Assert.IsNotNull(result); - - Assert.AreEqual(3, result.Length); - Assert.IsTrue(result.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1174, 1173, 1046 })); - } - - [Test] - public void Ancestors() - { - var doc = GetNode(1174); - - var result = doc.Ancestors().ToArray(); - - Assert.IsNotNull(result); - - Assert.AreEqual(2, result.Length); - Assert.IsTrue(result.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1173, 1046 })); - } - - [Test] - public void IsAncestor() - { - // Structure: - // - Root : 1046 (no parent) - // -- Home: 1173 (parent 1046) - // -- Custom Doc: 1178 (parent 1173) - // --- Custom Doc2: 1179 (parent: 1178) - // -- Custom Doc4: 117 (parent 1173) - // - Custom Doc3: 1172 (no parent) - - var home = GetNode(1173); - var root = GetNode(1046); - var customDoc = GetNode(1178); - var customDoc2 = GetNode(1179); - var customDoc3 = GetNode(1172); - var customDoc4 = GetNode(117); - - Assert.IsTrue(root.IsAncestor(customDoc4)); - Assert.IsFalse(root.IsAncestor(customDoc3)); - Assert.IsTrue(root.IsAncestor(customDoc2)); - Assert.IsTrue(root.IsAncestor(customDoc)); - Assert.IsTrue(root.IsAncestor(home)); - Assert.IsFalse(root.IsAncestor(root)); - - Assert.IsTrue(home.IsAncestor(customDoc4)); - Assert.IsFalse(home.IsAncestor(customDoc3)); - Assert.IsTrue(home.IsAncestor(customDoc2)); - Assert.IsTrue(home.IsAncestor(customDoc)); - Assert.IsFalse(home.IsAncestor(home)); - Assert.IsFalse(home.IsAncestor(root)); - - Assert.IsFalse(customDoc.IsAncestor(customDoc4)); - Assert.IsFalse(customDoc.IsAncestor(customDoc3)); - Assert.IsTrue(customDoc.IsAncestor(customDoc2)); - Assert.IsFalse(customDoc.IsAncestor(customDoc)); - Assert.IsFalse(customDoc.IsAncestor(home)); - Assert.IsFalse(customDoc.IsAncestor(root)); - - Assert.IsFalse(customDoc2.IsAncestor(customDoc4)); - Assert.IsFalse(customDoc2.IsAncestor(customDoc3)); - Assert.IsFalse(customDoc2.IsAncestor(customDoc2)); - Assert.IsFalse(customDoc2.IsAncestor(customDoc)); - Assert.IsFalse(customDoc2.IsAncestor(home)); - Assert.IsFalse(customDoc2.IsAncestor(root)); - - Assert.IsFalse(customDoc3.IsAncestor(customDoc3)); - } - - [Test] - public void IsAncestorOrSelf() - { - // Structure: - // - Root : 1046 (no parent) - // -- Home: 1173 (parent 1046) - // -- Custom Doc: 1178 (parent 1173) - // --- Custom Doc2: 1179 (parent: 1178) - // -- Custom Doc4: 117 (parent 1173) - // - Custom Doc3: 1172 (no parent) - - var home = GetNode(1173); - var root = GetNode(1046); - var customDoc = GetNode(1178); - var customDoc2 = GetNode(1179); - var customDoc3 = GetNode(1172); - var customDoc4 = GetNode(117); - - Assert.IsTrue(root.IsAncestorOrSelf(customDoc4)); - Assert.IsFalse(root.IsAncestorOrSelf(customDoc3)); - Assert.IsTrue(root.IsAncestorOrSelf(customDoc2)); - Assert.IsTrue(root.IsAncestorOrSelf(customDoc)); - Assert.IsTrue(root.IsAncestorOrSelf(home)); - Assert.IsTrue(root.IsAncestorOrSelf(root)); - - Assert.IsTrue(home.IsAncestorOrSelf(customDoc4)); - Assert.IsFalse(home.IsAncestorOrSelf(customDoc3)); - Assert.IsTrue(home.IsAncestorOrSelf(customDoc2)); - Assert.IsTrue(home.IsAncestorOrSelf(customDoc)); - Assert.IsTrue(home.IsAncestorOrSelf(home)); - Assert.IsFalse(home.IsAncestorOrSelf(root)); - - Assert.IsFalse(customDoc.IsAncestorOrSelf(customDoc4)); - Assert.IsFalse(customDoc.IsAncestorOrSelf(customDoc3)); - Assert.IsTrue(customDoc.IsAncestorOrSelf(customDoc2)); - Assert.IsTrue(customDoc.IsAncestorOrSelf(customDoc)); - Assert.IsFalse(customDoc.IsAncestorOrSelf(home)); - Assert.IsFalse(customDoc.IsAncestorOrSelf(root)); - - Assert.IsFalse(customDoc2.IsAncestorOrSelf(customDoc4)); - Assert.IsFalse(customDoc2.IsAncestorOrSelf(customDoc3)); - Assert.IsTrue(customDoc2.IsAncestorOrSelf(customDoc2)); - Assert.IsFalse(customDoc2.IsAncestorOrSelf(customDoc)); - Assert.IsFalse(customDoc2.IsAncestorOrSelf(home)); - Assert.IsFalse(customDoc2.IsAncestorOrSelf(root)); - - Assert.IsTrue(customDoc4.IsAncestorOrSelf(customDoc4)); - Assert.IsTrue(customDoc3.IsAncestorOrSelf(customDoc3)); - } - - - [Test] - public void Descendants_Or_Self() - { - var doc = GetNode(1046); - - var result = doc.DescendantsOrSelf().ToArray(); - - Assert.IsNotNull(result); - - Assert.AreEqual(10, result.Count()); - Assert.IsTrue(result.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1046, 1173, 1174, 1176, 1175 })); - } - - [Test] - public void Descendants() - { - var doc = GetNode(1046); - - var result = doc.Descendants().ToArray(); - - Assert.IsNotNull(result); - - Assert.AreEqual(9, result.Count()); - Assert.IsTrue(result.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1173, 1174, 1176, 1175, 4444 })); - } - - [Test] - public void IsDescendant() - { - // Structure: - // - Root : 1046 (no parent) - // -- Home: 1173 (parent 1046) - // -- Custom Doc: 1178 (parent 1173) - // --- Custom Doc2: 1179 (parent: 1178) - // -- Custom Doc4: 117 (parent 1173) - // - Custom Doc3: 1172 (no parent) - - var home = GetNode(1173); - var root = GetNode(1046); - var customDoc = GetNode(1178); - var customDoc2 = GetNode(1179); - var customDoc3 = GetNode(1172); - var customDoc4 = GetNode(117); - - Assert.IsFalse(root.IsDescendant(root)); - Assert.IsFalse(root.IsDescendant(home)); - Assert.IsFalse(root.IsDescendant(customDoc)); - Assert.IsFalse(root.IsDescendant(customDoc2)); - Assert.IsFalse(root.IsDescendant(customDoc3)); - Assert.IsFalse(root.IsDescendant(customDoc4)); - - Assert.IsTrue(home.IsDescendant(root)); - Assert.IsFalse(home.IsDescendant(home)); - Assert.IsFalse(home.IsDescendant(customDoc)); - Assert.IsFalse(home.IsDescendant(customDoc2)); - Assert.IsFalse(home.IsDescendant(customDoc3)); - Assert.IsFalse(home.IsDescendant(customDoc4)); - - Assert.IsTrue(customDoc.IsDescendant(root)); - Assert.IsTrue(customDoc.IsDescendant(home)); - Assert.IsFalse(customDoc.IsDescendant(customDoc)); - Assert.IsFalse(customDoc.IsDescendant(customDoc2)); - Assert.IsFalse(customDoc.IsDescendant(customDoc3)); - Assert.IsFalse(customDoc.IsDescendant(customDoc4)); - - Assert.IsTrue(customDoc2.IsDescendant(root)); - Assert.IsTrue(customDoc2.IsDescendant(home)); - Assert.IsTrue(customDoc2.IsDescendant(customDoc)); - Assert.IsFalse(customDoc2.IsDescendant(customDoc2)); - Assert.IsFalse(customDoc2.IsDescendant(customDoc3)); - Assert.IsFalse(customDoc2.IsDescendant(customDoc4)); - - Assert.IsFalse(customDoc3.IsDescendant(customDoc3)); - } - - [Test] - public void IsDescendantOrSelf() - { - // Structure: - // - Root : 1046 (no parent) - // -- Home: 1173 (parent 1046) - // -- Custom Doc: 1178 (parent 1173) - // --- Custom Doc2: 1179 (parent: 1178) - // -- Custom Doc4: 117 (parent 1173) - // - Custom Doc3: 1172 (no parent) - - var home = GetNode(1173); - var root = GetNode(1046); - var customDoc = GetNode(1178); - var customDoc2 = GetNode(1179); - var customDoc3 = GetNode(1172); - var customDoc4 = GetNode(117); - - Assert.IsTrue(root.IsDescendantOrSelf(root)); - Assert.IsFalse(root.IsDescendantOrSelf(home)); - Assert.IsFalse(root.IsDescendantOrSelf(customDoc)); - Assert.IsFalse(root.IsDescendantOrSelf(customDoc2)); - Assert.IsFalse(root.IsDescendantOrSelf(customDoc3)); - Assert.IsFalse(root.IsDescendantOrSelf(customDoc4)); - - Assert.IsTrue(home.IsDescendantOrSelf(root)); - Assert.IsTrue(home.IsDescendantOrSelf(home)); - Assert.IsFalse(home.IsDescendantOrSelf(customDoc)); - Assert.IsFalse(home.IsDescendantOrSelf(customDoc2)); - Assert.IsFalse(home.IsDescendantOrSelf(customDoc3)); - Assert.IsFalse(home.IsDescendantOrSelf(customDoc4)); - - Assert.IsTrue(customDoc.IsDescendantOrSelf(root)); - Assert.IsTrue(customDoc.IsDescendantOrSelf(home)); - Assert.IsTrue(customDoc.IsDescendantOrSelf(customDoc)); - Assert.IsFalse(customDoc.IsDescendantOrSelf(customDoc2)); - Assert.IsFalse(customDoc.IsDescendantOrSelf(customDoc3)); - Assert.IsFalse(customDoc.IsDescendantOrSelf(customDoc4)); - - Assert.IsTrue(customDoc2.IsDescendantOrSelf(root)); - Assert.IsTrue(customDoc2.IsDescendantOrSelf(home)); - Assert.IsTrue(customDoc2.IsDescendantOrSelf(customDoc)); - Assert.IsTrue(customDoc2.IsDescendantOrSelf(customDoc2)); - Assert.IsFalse(customDoc2.IsDescendantOrSelf(customDoc3)); - Assert.IsFalse(customDoc2.IsDescendantOrSelf(customDoc4)); - - Assert.IsTrue(customDoc3.IsDescendantOrSelf(customDoc3)); - } - - [Test] - public void Up() - { - var doc = GetNode(1173); - - var result = doc.Up(); - - Assert.IsNotNull(result); - - Assert.AreEqual(1046, result.Id); - } - - [Test] - public void Down() - { - var doc = GetNode(1173); - - var result = doc.Down(); - - Assert.IsNotNull(result); - - Assert.AreEqual(1174, result.Id); - } - - [Test] - public void FragmentProperty() - { - var factory = Factory.GetInstance() as PublishedContentTypeFactory; - - var pt = factory.CreatePropertyType("detached", 1003); - var ct = factory.CreateContentType(0, "alias", new[] { pt }); - var prop = new PublishedElementPropertyBase(pt, null, false, PropertyCacheLevel.None, 5548); - Assert.IsInstanceOf(prop.GetValue()); - Assert.AreEqual(5548, prop.GetValue()); - } - - public void Fragment1() - { - var type = ContentTypesCache.Get(PublishedItemType.Content, "detachedSomething"); - var values = new Dictionary(); - var f = new PublishedElement(type, Guid.NewGuid(), values, false); - } - - [Test] - public void Fragment2() - { - var factory = Factory.GetInstance() as PublishedContentTypeFactory; - - var pt1 = factory.CreatePropertyType("legend", 1004); - var pt2 = factory.CreatePropertyType("image", 1005); - var pt3 = factory.CreatePropertyType("size", 1003); - const string val1 = "boom bam"; - const int val2 = 0; - const int val3 = 666; - - var guid = Guid.NewGuid(); - - var ct = factory.CreateContentType(0, "alias", new[] { pt1, pt2, pt3 }); - - var c = new ImageWithLegendModel(ct, guid, new Dictionary - { - { "legend", val1 }, - { "image", val2 }, - { "size", val3 }, - }, false); - - Assert.AreEqual(val1, c.Legend); - Assert.AreEqual(val3, c.Size); - } - - class ImageWithLegendModel : PublishedElement - { - public ImageWithLegendModel(PublishedContentType contentType, Guid fragmentKey, Dictionary values, bool previewing) - : base(contentType, fragmentKey, values, previewing) - { } - - - public string Legend => this.Value("legend"); - - public IPublishedContent Image => this.Value("image"); - - public int Size => this.Value("size"); - } - } -} +//using System; +//using System.Collections.Generic; +//using System.Linq; +//using System.Web; +//using NUnit.Framework; +//using Umbraco.Core; +//using Umbraco.Core.Models.PublishedContent; +//using Umbraco.Core.PropertyEditors; +//using Umbraco.Web; +//using Umbraco.Web.PublishedCache; +//using Umbraco.Core.Composing; +//using Moq; +//using Umbraco.Core.Cache; +//using Umbraco.Core.Configuration; +//using Umbraco.Core.Logging; +//using Umbraco.Core.Models; +//using Umbraco.Core.Services; +//using Umbraco.Tests.TestHelpers; +//using Umbraco.Tests.Testing; +//using Umbraco.Web.Models.PublishedContent; +//using Umbraco.Web.PropertyEditors; +// +//namespace Umbraco.Tests.PublishedContent +//{ +// /// +// /// Tests the methods on IPublishedContent using the DefaultPublishedContentStore +// /// +// [TestFixture] +// [UmbracoTest(TypeLoader = UmbracoTestOptions.TypeLoader.PerFixture)] +// public class PublishedContentTests : PublishedContentTestBase +// { +// protected override void Compose() +// { +// base.Compose(); +// +// Composition.RegisterUnique(f => new PublishedModelFactory(f.GetInstance().GetTypes())); +// Composition.RegisterUnique(); +// Composition.RegisterUnique(); +// +// var logger = Mock.Of(); +// var dataTypeService = new TestObjects.TestDataTypeService( +// new DataType(new VoidEditor(logger)) { Id = 1 }, +// new DataType(new TrueFalsePropertyEditor(logger)) { Id = 1001 }, +// new DataType(new RichTextPropertyEditor(logger)) { Id = 1002 }, +// new DataType(new IntegerPropertyEditor(logger)) { Id = 1003 }, +// new DataType(new TextboxPropertyEditor(logger)) { Id = 1004 }, +// new DataType(new MediaPickerPropertyEditor(logger)) { Id = 1005 }); +// Composition.RegisterUnique(f => dataTypeService); +// } +// +// protected override void Initialize() +// { +// base.Initialize(); +// +// var factory = Factory.GetInstance() as PublishedContentTypeFactory; +// +// // need to specify a custom callback for unit tests +// // AutoPublishedContentTypes generates properties automatically +// // when they are requested, but we must declare those that we +// // explicitely want to be here... +// +// var propertyTypes = new[] +// { +// // AutoPublishedContentType will auto-generate other properties +// factory.CreatePropertyType("umbracoNaviHide", 1001), +// factory.CreatePropertyType("selectedNodes", 1), +// factory.CreatePropertyType("umbracoUrlAlias", 1), +// factory.CreatePropertyType("content", 1002), +// factory.CreatePropertyType("testRecursive", 1), +// }; +// var compositionAliases = new[] { "MyCompositionAlias" }; +// var type = new AutoPublishedContentType(0, "anything", compositionAliases, propertyTypes); +// ContentTypesCache.GetPublishedContentTypeByAlias = alias => type; +// } +// +// protected override TypeLoader CreateTypeLoader(IRuntimeCacheProvider runtimeCache, IGlobalSettings globalSettings, IProfilingLogger logger) +// { +// var pluginManager = base.CreateTypeLoader(runtimeCache, globalSettings, logger); +// +// // this is so the model factory looks into the test assembly +// pluginManager.AssembliesToScan = pluginManager.AssembliesToScan +// .Union(new[] { typeof(PublishedContentTests).Assembly }) +// .ToList(); +// +// return pluginManager; +// } +// +// private readonly Guid _node1173Guid = Guid.NewGuid(); +// +// protected override string GetXmlContent(int templateId) +// { +// return @" +// +// +// +// +//]> +// +// +// +// +// 1 +// +// +// This is some content]]> +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// 1 +// +// +// +// +// +// +// +// +// +//"; +// } +// +// internal IPublishedContent GetNode(int id) +// { +// var ctx = GetUmbracoContext("/test"); +// var doc = ctx.ContentCache.GetById(id); +// Assert.IsNotNull(doc); +// return doc; +// } +// +// [Test] +// public void GetNodeByIds() +// { +// var ctx = GetUmbracoContext("/test"); +// var contentById = ctx.ContentCache.GetById(1173); +// Assert.IsNotNull(contentById); +// var contentByGuid = ctx.ContentCache.GetById(_node1173Guid); +// Assert.IsNotNull(contentByGuid); +// Assert.AreEqual(contentById.Id, contentByGuid.Id); +// Assert.AreEqual(contentById.Key, contentByGuid.Key); +// +// contentById = ctx.ContentCache.GetById(666); +// Assert.IsNull(contentById); +// contentByGuid = ctx.ContentCache.GetById(Guid.NewGuid()); +// Assert.IsNull(contentByGuid); +// } +// +// [Test] +// public void Is_Last_From_Where_Filter_Dynamic_Linq() +// { +// var doc = GetNode(1173); +// +// var items = doc.Children.Where(x => x.IsVisible()).ToIndexedArray(); +// +// foreach (var item in items) +// { +// if (item.Content.Id != 1178) +// { +// Assert.IsFalse(item.IsLast()); +// } +// else +// { +// Assert.IsTrue(item.IsLast()); +// } +// } +// } +// +// [Test] +// public void Is_Last_From_Where_Filter() +// { +// var doc = GetNode(1173); +// +// var items = doc +// .Children +// .Where(x => x.IsVisible()) +// .ToIndexedArray(); +// +// Assert.AreEqual(4, items.Length); +// +// foreach (var d in items) +// { +// switch (d.Content.Id) +// { +// case 1174: +// Assert.IsTrue(d.IsFirst()); +// Assert.IsFalse(d.IsLast()); +// break; +// case 117: +// Assert.IsFalse(d.IsFirst()); +// Assert.IsFalse(d.IsLast()); +// break; +// case 1177: +// Assert.IsFalse(d.IsFirst()); +// Assert.IsFalse(d.IsLast()); +// break; +// case 1178: +// Assert.IsFalse(d.IsFirst()); +// Assert.IsTrue(d.IsLast()); +// break; +// default: +// Assert.Fail("Invalid id."); +// break; +// } +// } +// } +// +// [PublishedModel("Home")] +// internal class Home : PublishedContentModel +// { +// public Home(IPublishedContent content) +// : base(content) +// {} +// } +// +// [PublishedModel("anything")] +// internal class Anything : PublishedContentModel +// { +// public Anything(IPublishedContent content) +// : base(content) +// { } +// } +// +// [Test] +// [Ignore("Fails as long as PublishedContentModel is internal.")] // fixme +// public void Is_Last_From_Where_Filter2() +// { +// var doc = GetNode(1173); +// +// var items = doc.Children +// .Select(x => x.CreateModel()) // linq, returns IEnumerable +// +// // only way around this is to make sure every IEnumerable extension +// // explicitely returns a PublishedContentSet, not an IEnumerable +// +// .OfType() // ours, return IEnumerable (actually a PublishedContentSet) +// .Where(x => x.IsVisible()) // so, here it's linq again :-( +// .ToIndexedArray(); // so, we need that one for the test to pass +// +// Assert.AreEqual(1, items.Length); +// +// foreach (var d in items) +// { +// switch (d.Content.Id) +// { +// case 1174: +// Assert.IsTrue(d.IsFirst()); +// Assert.IsTrue(d.IsLast()); +// break; +// default: +// Assert.Fail("Invalid id."); +// break; +// } +// } +// } +// +// [Test] +// public void Is_Last_From_Take() +// { +// var doc = GetNode(1173); +// +// var items = doc.Children.Take(4).ToIndexedArray(); +// +// foreach (var item in items) +// { +// if (item.Content.Id != 1178) +// { +// Assert.IsFalse(item.IsLast()); +// } +// else +// { +// Assert.IsTrue(item.IsLast()); +// } +// } +// } +// +// [Test] +// public void Is_Last_From_Skip() +// { +// var doc = GetNode(1173); +// +// foreach (var d in doc.Children.Skip(1).ToIndexedArray()) +// { +// if (d.Content.Id != 1176) +// { +// Assert.IsFalse(d.IsLast()); +// } +// else +// { +// Assert.IsTrue(d.IsLast()); +// } +// } +// } +// +// [Test] +// public void Is_Last_From_Concat() +// { +// var doc = GetNode(1173); +// +// var items = doc.Children +// .Concat(new[] { GetNode(1175), GetNode(4444) }) +// .ToIndexedArray(); +// +// foreach (var item in items) +// { +// if (item.Content.Id != 4444) +// { +// Assert.IsFalse(item.IsLast()); +// } +// else +// { +// Assert.IsTrue(item.IsLast()); +// } +// } +// } +// +// [Test] +// public void Descendants_Ordered_Properly() +// { +// var doc = GetNode(1046); +// +// var expected = new[] { 1046, 1173, 1174, 117, 1177, 1178, 1179, 1176, 1175, 4444, 1172 }; +// var exindex = 0; +// +// // must respect the XPath descendants-or-self axis! +// foreach (var d in doc.DescendantsOrSelf()) +// Assert.AreEqual(expected[exindex++], d.Id); +// } +// +// [Test] +// public void Get_Property_Value_Recursive() +// { +// var doc = GetNode(1174); +// var rVal = doc.Value("testRecursive", fallback: Fallback.ToAncestors); +// var nullVal = doc.Value("DoNotFindThis", fallback: Fallback.ToAncestors); +// Assert.AreEqual("This is the recursive val", rVal); +// Assert.AreEqual(null, nullVal); +// } +// +// [Test] +// public void Get_Property_Value_Uses_Converter() +// { +// var doc = GetNode(1173); +// +// var propVal = doc.Value("content"); +// Assert.IsInstanceOf(typeof(IHtmlString), propVal); +// Assert.AreEqual("
    This is some content
    ", propVal.ToString()); +// +// var propVal2 = doc.Value("content"); +// Assert.IsInstanceOf(typeof(IHtmlString), propVal2); +// Assert.AreEqual("
    This is some content
    ", propVal2.ToString()); +// +// var propVal3 = doc.Value("Content"); +// Assert.IsInstanceOf(typeof(IHtmlString), propVal3); +// Assert.AreEqual("
    This is some content
    ", propVal3.ToString()); +// } +// +// [Test] +// public void Complex_Linq() +// { +// var doc = GetNode(1173); +// +// var result = doc.Ancestors().OrderBy(x => x.Level) +// .Single() +// .Descendants() +// .FirstOrDefault(x => x.Value("selectedNodes", defaultValue: "").Split(',').Contains("1173")); +// +// Assert.IsNotNull(result); +// } +// +// [Test] +// public void Children_GroupBy_DocumentTypeAlias() +// { +// var home = new AutoPublishedContentType(22, "Home", new PublishedPropertyType[] { }); +// var custom = new AutoPublishedContentType(23, "CustomDocument", new PublishedPropertyType[] { }); +// var contentTypes = new Dictionary +// { +// { home.Alias, home }, +// { custom.Alias, custom } +// }; +// ContentTypesCache.GetPublishedContentTypeByAlias = alias => contentTypes[alias]; +// +// var doc = GetNode(1046); +// +// var found1 = doc.Children.GroupBy(x => x.ContentType.Alias).ToArray(); +// +// Assert.AreEqual(2, found1.Length); +// Assert.AreEqual(2, found1.Single(x => x.Key.ToString() == "Home").Count()); +// Assert.AreEqual(1, found1.Single(x => x.Key.ToString() == "CustomDocument").Count()); +// } +// +// [Test] +// public void Children_Where_DocumentTypeAlias() +// { +// var home = new AutoPublishedContentType(22, "Home", new PublishedPropertyType[] { }); +// var custom = new AutoPublishedContentType(23, "CustomDocument", new PublishedPropertyType[] { }); +// var contentTypes = new Dictionary +// { +// { home.Alias, home }, +// { custom.Alias, custom } +// }; +// ContentTypesCache.GetPublishedContentTypeByAlias = alias => contentTypes[alias]; +// +// var doc = GetNode(1046); +// +// var found1 = doc.Children.Where(x => x.ContentType.Alias == "CustomDocument"); +// var found2 = doc.Children.Where(x => x.ContentType.Alias == "Home"); +// +// Assert.AreEqual(1, found1.Count()); +// Assert.AreEqual(2, found2.Count()); +// } +// +// [Test] +// public void Children_Order_By_Update_Date() +// { +// var doc = GetNode(1173); +// +// var ordered = doc.Children.OrderBy(x => x.UpdateDate); +// +// var correctOrder = new[] { 1178, 1177, 1174, 1176 }; +// for (var i = 0; i < correctOrder.Length; i++) +// { +// Assert.AreEqual(correctOrder[i], ordered.ElementAt(i).Id); +// } +// +// } +// +// [Test] +// public void FirstChild() +// { +// var doc = GetNode(1173); // has child nodes +// Assert.IsNotNull(doc.FirstChild()); +// Assert.IsNotNull(doc.FirstChild(x => true)); +// Assert.IsNotNull(doc.FirstChild()); +// +// doc = GetNode(1175); // does not have child nodes +// Assert.IsNull(doc.FirstChild()); +// Assert.IsNull(doc.FirstChild(x => true)); +// Assert.IsNull(doc.FirstChild()); +// } +// +// [Test] +// public void FirstChildAsT() +// { +// var doc = GetNode(1046); // has child nodes +// +// var model = doc.FirstChild(x => true); // predicate +// +// Assert.IsNotNull(model); +// Assert.IsTrue(model.Id == 1173); +// Assert.IsInstanceOf(model); +// Assert.IsInstanceOf(model); +// +// doc = GetNode(1175); // does not have child nodes +// Assert.IsNull(doc.FirstChild()); +// Assert.IsNull(doc.FirstChild(x => true)); +// } +// +// [Test] +// public void IsComposedOf() +// { +// var doc = GetNode(1173); +// +// var isComposedOf = doc.IsComposedOf("MyCompositionAlias"); +// +// Assert.IsTrue(isComposedOf); +// } +// +// [Test] +// public void HasProperty() +// { +// var doc = GetNode(1173); +// +// var hasProp = doc.HasProperty(Constants.Conventions.Content.UrlAlias); +// +// Assert.IsTrue(hasProp); +// } +// +// [Test] +// public void HasValue() +// { +// var doc = GetNode(1173); +// +// var hasValue = doc.HasValue(Constants.Conventions.Content.UrlAlias); +// var noValue = doc.HasValue("blahblahblah"); +// +// Assert.IsTrue(hasValue); +// Assert.IsFalse(noValue); +// } +// +// [Test] +// public void Ancestors_Where_Visible() +// { +// var doc = GetNode(1174); +// +// var whereVisible = doc.Ancestors().Where(x => x.IsVisible()); +// Assert.AreEqual(1, whereVisible.Count()); +// +// } +// +// [Test] +// public void Visible() +// { +// var hidden = GetNode(1046); +// var visible = GetNode(1173); +// +// Assert.IsFalse(hidden.IsVisible()); +// Assert.IsTrue(visible.IsVisible()); +// } +// +// [Test] +// public void Ancestor_Or_Self() +// { +// var doc = GetNode(1173); +// +// var result = doc.AncestorOrSelf(); +// +// Assert.IsNotNull(result); +// +// // ancestor-or-self has to be self! +// Assert.AreEqual(1173, result.Id); +// } +// +// [Test] +// public void U4_4559() +// { +// var doc = GetNode(1174); +// var result = doc.AncestorOrSelf(1); +// Assert.IsNotNull(result); +// Assert.AreEqual(1046, result.Id); +// } +// +// [Test] +// public void Ancestors_Or_Self() +// { +// var doc = GetNode(1174); +// +// var result = doc.AncestorsOrSelf().ToArray(); +// +// Assert.IsNotNull(result); +// +// Assert.AreEqual(3, result.Length); +// Assert.IsTrue(result.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1174, 1173, 1046 })); +// } +// +// [Test] +// public void Ancestors() +// { +// var doc = GetNode(1174); +// +// var result = doc.Ancestors().ToArray(); +// +// Assert.IsNotNull(result); +// +// Assert.AreEqual(2, result.Length); +// Assert.IsTrue(result.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1173, 1046 })); +// } +// +// [Test] +// public void IsAncestor() +// { +// // Structure: +// // - Root : 1046 (no parent) +// // -- Home: 1173 (parent 1046) +// // -- Custom Doc: 1178 (parent 1173) +// // --- Custom Doc2: 1179 (parent: 1178) +// // -- Custom Doc4: 117 (parent 1173) +// // - Custom Doc3: 1172 (no parent) +// +// var home = GetNode(1173); +// var root = GetNode(1046); +// var customDoc = GetNode(1178); +// var customDoc2 = GetNode(1179); +// var customDoc3 = GetNode(1172); +// var customDoc4 = GetNode(117); +// +// Assert.IsTrue(root.IsAncestor(customDoc4)); +// Assert.IsFalse(root.IsAncestor(customDoc3)); +// Assert.IsTrue(root.IsAncestor(customDoc2)); +// Assert.IsTrue(root.IsAncestor(customDoc)); +// Assert.IsTrue(root.IsAncestor(home)); +// Assert.IsFalse(root.IsAncestor(root)); +// +// Assert.IsTrue(home.IsAncestor(customDoc4)); +// Assert.IsFalse(home.IsAncestor(customDoc3)); +// Assert.IsTrue(home.IsAncestor(customDoc2)); +// Assert.IsTrue(home.IsAncestor(customDoc)); +// Assert.IsFalse(home.IsAncestor(home)); +// Assert.IsFalse(home.IsAncestor(root)); +// +// Assert.IsFalse(customDoc.IsAncestor(customDoc4)); +// Assert.IsFalse(customDoc.IsAncestor(customDoc3)); +// Assert.IsTrue(customDoc.IsAncestor(customDoc2)); +// Assert.IsFalse(customDoc.IsAncestor(customDoc)); +// Assert.IsFalse(customDoc.IsAncestor(home)); +// Assert.IsFalse(customDoc.IsAncestor(root)); +// +// Assert.IsFalse(customDoc2.IsAncestor(customDoc4)); +// Assert.IsFalse(customDoc2.IsAncestor(customDoc3)); +// Assert.IsFalse(customDoc2.IsAncestor(customDoc2)); +// Assert.IsFalse(customDoc2.IsAncestor(customDoc)); +// Assert.IsFalse(customDoc2.IsAncestor(home)); +// Assert.IsFalse(customDoc2.IsAncestor(root)); +// +// Assert.IsFalse(customDoc3.IsAncestor(customDoc3)); +// } +// +// [Test] +// public void IsAncestorOrSelf() +// { +// // Structure: +// // - Root : 1046 (no parent) +// // -- Home: 1173 (parent 1046) +// // -- Custom Doc: 1178 (parent 1173) +// // --- Custom Doc2: 1179 (parent: 1178) +// // -- Custom Doc4: 117 (parent 1173) +// // - Custom Doc3: 1172 (no parent) +// +// var home = GetNode(1173); +// var root = GetNode(1046); +// var customDoc = GetNode(1178); +// var customDoc2 = GetNode(1179); +// var customDoc3 = GetNode(1172); +// var customDoc4 = GetNode(117); +// +// Assert.IsTrue(root.IsAncestorOrSelf(customDoc4)); +// Assert.IsFalse(root.IsAncestorOrSelf(customDoc3)); +// Assert.IsTrue(root.IsAncestorOrSelf(customDoc2)); +// Assert.IsTrue(root.IsAncestorOrSelf(customDoc)); +// Assert.IsTrue(root.IsAncestorOrSelf(home)); +// Assert.IsTrue(root.IsAncestorOrSelf(root)); +// +// Assert.IsTrue(home.IsAncestorOrSelf(customDoc4)); +// Assert.IsFalse(home.IsAncestorOrSelf(customDoc3)); +// Assert.IsTrue(home.IsAncestorOrSelf(customDoc2)); +// Assert.IsTrue(home.IsAncestorOrSelf(customDoc)); +// Assert.IsTrue(home.IsAncestorOrSelf(home)); +// Assert.IsFalse(home.IsAncestorOrSelf(root)); +// +// Assert.IsFalse(customDoc.IsAncestorOrSelf(customDoc4)); +// Assert.IsFalse(customDoc.IsAncestorOrSelf(customDoc3)); +// Assert.IsTrue(customDoc.IsAncestorOrSelf(customDoc2)); +// Assert.IsTrue(customDoc.IsAncestorOrSelf(customDoc)); +// Assert.IsFalse(customDoc.IsAncestorOrSelf(home)); +// Assert.IsFalse(customDoc.IsAncestorOrSelf(root)); +// +// Assert.IsFalse(customDoc2.IsAncestorOrSelf(customDoc4)); +// Assert.IsFalse(customDoc2.IsAncestorOrSelf(customDoc3)); +// Assert.IsTrue(customDoc2.IsAncestorOrSelf(customDoc2)); +// Assert.IsFalse(customDoc2.IsAncestorOrSelf(customDoc)); +// Assert.IsFalse(customDoc2.IsAncestorOrSelf(home)); +// Assert.IsFalse(customDoc2.IsAncestorOrSelf(root)); +// +// Assert.IsTrue(customDoc4.IsAncestorOrSelf(customDoc4)); +// Assert.IsTrue(customDoc3.IsAncestorOrSelf(customDoc3)); +// } +// +// +// [Test] +// public void Descendants_Or_Self() +// { +// var doc = GetNode(1046); +// +// var result = doc.DescendantsOrSelf().ToArray(); +// +// Assert.IsNotNull(result); +// +// Assert.AreEqual(10, result.Count()); +// Assert.IsTrue(result.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1046, 1173, 1174, 1176, 1175 })); +// } +// +// [Test] +// public void Descendants() +// { +// var doc = GetNode(1046); +// +// var result = doc.Descendants().ToArray(); +// +// Assert.IsNotNull(result); +// +// Assert.AreEqual(9, result.Count()); +// Assert.IsTrue(result.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1173, 1174, 1176, 1175, 4444 })); +// } +// +// [Test] +// public void IsDescendant() +// { +// // Structure: +// // - Root : 1046 (no parent) +// // -- Home: 1173 (parent 1046) +// // -- Custom Doc: 1178 (parent 1173) +// // --- Custom Doc2: 1179 (parent: 1178) +// // -- Custom Doc4: 117 (parent 1173) +// // - Custom Doc3: 1172 (no parent) +// +// var home = GetNode(1173); +// var root = GetNode(1046); +// var customDoc = GetNode(1178); +// var customDoc2 = GetNode(1179); +// var customDoc3 = GetNode(1172); +// var customDoc4 = GetNode(117); +// +// Assert.IsFalse(root.IsDescendant(root)); +// Assert.IsFalse(root.IsDescendant(home)); +// Assert.IsFalse(root.IsDescendant(customDoc)); +// Assert.IsFalse(root.IsDescendant(customDoc2)); +// Assert.IsFalse(root.IsDescendant(customDoc3)); +// Assert.IsFalse(root.IsDescendant(customDoc4)); +// +// Assert.IsTrue(home.IsDescendant(root)); +// Assert.IsFalse(home.IsDescendant(home)); +// Assert.IsFalse(home.IsDescendant(customDoc)); +// Assert.IsFalse(home.IsDescendant(customDoc2)); +// Assert.IsFalse(home.IsDescendant(customDoc3)); +// Assert.IsFalse(home.IsDescendant(customDoc4)); +// +// Assert.IsTrue(customDoc.IsDescendant(root)); +// Assert.IsTrue(customDoc.IsDescendant(home)); +// Assert.IsFalse(customDoc.IsDescendant(customDoc)); +// Assert.IsFalse(customDoc.IsDescendant(customDoc2)); +// Assert.IsFalse(customDoc.IsDescendant(customDoc3)); +// Assert.IsFalse(customDoc.IsDescendant(customDoc4)); +// +// Assert.IsTrue(customDoc2.IsDescendant(root)); +// Assert.IsTrue(customDoc2.IsDescendant(home)); +// Assert.IsTrue(customDoc2.IsDescendant(customDoc)); +// Assert.IsFalse(customDoc2.IsDescendant(customDoc2)); +// Assert.IsFalse(customDoc2.IsDescendant(customDoc3)); +// Assert.IsFalse(customDoc2.IsDescendant(customDoc4)); +// +// Assert.IsFalse(customDoc3.IsDescendant(customDoc3)); +// } +// +// [Test] +// public void IsDescendantOrSelf() +// { +// // Structure: +// // - Root : 1046 (no parent) +// // -- Home: 1173 (parent 1046) +// // -- Custom Doc: 1178 (parent 1173) +// // --- Custom Doc2: 1179 (parent: 1178) +// // -- Custom Doc4: 117 (parent 1173) +// // - Custom Doc3: 1172 (no parent) +// +// var home = GetNode(1173); +// var root = GetNode(1046); +// var customDoc = GetNode(1178); +// var customDoc2 = GetNode(1179); +// var customDoc3 = GetNode(1172); +// var customDoc4 = GetNode(117); +// +// Assert.IsTrue(root.IsDescendantOrSelf(root)); +// Assert.IsFalse(root.IsDescendantOrSelf(home)); +// Assert.IsFalse(root.IsDescendantOrSelf(customDoc)); +// Assert.IsFalse(root.IsDescendantOrSelf(customDoc2)); +// Assert.IsFalse(root.IsDescendantOrSelf(customDoc3)); +// Assert.IsFalse(root.IsDescendantOrSelf(customDoc4)); +// +// Assert.IsTrue(home.IsDescendantOrSelf(root)); +// Assert.IsTrue(home.IsDescendantOrSelf(home)); +// Assert.IsFalse(home.IsDescendantOrSelf(customDoc)); +// Assert.IsFalse(home.IsDescendantOrSelf(customDoc2)); +// Assert.IsFalse(home.IsDescendantOrSelf(customDoc3)); +// Assert.IsFalse(home.IsDescendantOrSelf(customDoc4)); +// +// Assert.IsTrue(customDoc.IsDescendantOrSelf(root)); +// Assert.IsTrue(customDoc.IsDescendantOrSelf(home)); +// Assert.IsTrue(customDoc.IsDescendantOrSelf(customDoc)); +// Assert.IsFalse(customDoc.IsDescendantOrSelf(customDoc2)); +// Assert.IsFalse(customDoc.IsDescendantOrSelf(customDoc3)); +// Assert.IsFalse(customDoc.IsDescendantOrSelf(customDoc4)); +// +// Assert.IsTrue(customDoc2.IsDescendantOrSelf(root)); +// Assert.IsTrue(customDoc2.IsDescendantOrSelf(home)); +// Assert.IsTrue(customDoc2.IsDescendantOrSelf(customDoc)); +// Assert.IsTrue(customDoc2.IsDescendantOrSelf(customDoc2)); +// Assert.IsFalse(customDoc2.IsDescendantOrSelf(customDoc3)); +// Assert.IsFalse(customDoc2.IsDescendantOrSelf(customDoc4)); +// +// Assert.IsTrue(customDoc3.IsDescendantOrSelf(customDoc3)); +// } +// +// [Test] +// public void Up() +// { +// var doc = GetNode(1173); +// +// var result = doc.Up(); +// +// Assert.IsNotNull(result); +// +// Assert.AreEqual(1046, result.Id); +// } +// +// [Test] +// public void Down() +// { +// var doc = GetNode(1173); +// +// var result = doc.Down(); +// +// Assert.IsNotNull(result); +// +// Assert.AreEqual(1174, result.Id); +// } +// +// [Test] +// public void FragmentProperty() +// { +// var factory = Factory.GetInstance() as PublishedContentTypeFactory; +// +// var pt = factory.CreatePropertyType("detached", 1003); +// var ct = factory.CreateContentType(0, "alias", new[] { pt }); +// var prop = new PublishedElementPropertyBase(pt, null, false, PropertyCacheLevel.None, 5548); +// Assert.IsInstanceOf(prop.GetValue()); +// Assert.AreEqual(5548, prop.GetValue()); +// } +// +// public void Fragment1() +// { +// var type = ContentTypesCache.Get(PublishedItemType.Content, "detachedSomething"); +// var values = new Dictionary(); +// var f = new PublishedElement(type, Guid.NewGuid(), values, false); +// } +// +// [Test] +// public void Fragment2() +// { +// var factory = Factory.GetInstance() as PublishedContentTypeFactory; +// +// var pt1 = factory.CreatePropertyType("legend", 1004); +// var pt2 = factory.CreatePropertyType("image", 1005); +// var pt3 = factory.CreatePropertyType("size", 1003); +// const string val1 = "boom bam"; +// const int val2 = 0; +// const int val3 = 666; +// +// var guid = Guid.NewGuid(); +// +// var ct = factory.CreateContentType(0, "alias", new[] { pt1, pt2, pt3 }); +// +// var c = new ImageWithLegendModel(ct, guid, new Dictionary +// { +// { "legend", val1 }, +// { "image", val2 }, +// { "size", val3 }, +// }, false); +// +// Assert.AreEqual(val1, c.Legend); +// Assert.AreEqual(val3, c.Size); +// } +// +// class ImageWithLegendModel : PublishedElement +// { +// public ImageWithLegendModel(PublishedContentType contentType, Guid fragmentKey, Dictionary values, bool previewing) +// : base(contentType, fragmentKey, values, previewing) +// { } +// +// +// public string Legend => this.Value("legend"); +// +// public IPublishedContent Image => this.Value("image"); +// +// public int Size => this.Value("size"); +// } +// } +//} diff --git a/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs index 88b211d0ee..f88f37a972 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs @@ -1,508 +1,508 @@ -using System.Web; -using System.Xml.Linq; -using System.Xml.XPath; -using NUnit.Framework; -using Umbraco.Core; -using Umbraco.Core.Models; -using Umbraco.Tests.TestHelpers; -using Umbraco.Tests.TestHelpers.Entities; -using Umbraco.Tests.UmbracoExamine; -using Umbraco.Web; -using Umbraco.Web.PublishedCache.XmlPublishedCache; -using System.Linq; -using System.Threading; -using System.Xml; -using Examine; -using Umbraco.Core.Cache; -using Umbraco.Core.Models.PublishedContent; -using Umbraco.Core.Strings; -using Umbraco.Examine; -using Current = Umbraco.Web.Composing.Current; -using Umbraco.Tests.Testing; -using Umbraco.Core.Composing; -using Umbraco.Core.Models.Membership; -using Umbraco.Core.PropertyEditors; - -namespace Umbraco.Tests.PublishedContent -{ - /// - /// Tests the typed extension methods on IPublishedContent using the DefaultPublishedMediaStore - /// - [TestFixture] - [Apartment(ApartmentState.STA)] - [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest, WithApplication = true)] - public class PublishedMediaTests : PublishedContentTestBase - { - /// - /// sets up resolvers before resolution is frozen - /// - protected override void Compose() - { - base.Compose(); - - Composition.WithCollectionBuilder() - .Clear() - .Append(); - } - - private IMediaType MakeNewMediaType(IUser user, string text, int parentId = -1) - { - var mt = new MediaType(parentId) { Name = text, Alias = text, Thumbnail = "icon-folder", Icon = "icon-folder" }; - ServiceContext.MediaTypeService.Save(mt); - return mt; - } - - private IMedia MakeNewMedia(string name, IMediaType mediaType, IUser user, int parentId) - { - var m = ServiceContext.MediaService.CreateMediaWithIdentity(name, parentId, mediaType.Alias); - return m; - } - - /// - /// Shared with PublishMediaStoreTests - /// - /// - /// - /// - internal IPublishedContent GetNode(int id, UmbracoContext umbracoContext) - { - var cache = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), Current.Services.MediaService, Current.Services.UserService, new StaticCacheProvider(), ContentTypesCache); - var doc = cache.GetById(id); - Assert.IsNotNull(doc); - return doc; - } - - private IPublishedContent GetNode(int id) - { - return GetNode(id, GetUmbracoContext("/test")); - } - - [Test] - public void Get_Property_Value_Uses_Converter() - { - var mType = MockedContentTypes.CreateImageMediaType("image2"); - //lets add an RTE to this - mType.PropertyGroups.First().PropertyTypes.Add( - new PropertyType("test", ValueStorageType.Nvarchar, "content") - { - Name = "Rich Text", - DataTypeId = -87 //tiny mce - }); - ServiceContext.MediaTypeService.Save(mType); - var media = MockedMedia.CreateMediaImage(mType, -1); - media.Properties["content"].SetValue("
    This is some content
    "); - ServiceContext.MediaService.Save(media); - - var publishedMedia = GetNode(media.Id); - - var propVal = publishedMedia.Value("content"); - Assert.IsInstanceOf(propVal); - Assert.AreEqual("
    This is some content
    ", propVal.ToString()); - - var propVal2 = publishedMedia.Value("content"); - Assert.IsInstanceOf(propVal2); - Assert.AreEqual("
    This is some content
    ", propVal2.ToString()); - - var propVal3 = publishedMedia.Value("Content"); - Assert.IsInstanceOf(propVal3); - Assert.AreEqual("
    This is some content
    ", propVal3.ToString()); - } - - [Test] - public void Ensure_Children_Sorted_With_Examine() - { - var rebuilder = IndexInitializer.GetMediaIndexRebuilder(Factory.GetInstance(), IndexInitializer.GetMockMediaService()); - - using (var luceneDir = new RandomIdRamDirectory()) - using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, - validator: new ContentValueSetValidator(true))) - using (indexer.ProcessNonAsync()) - { - rebuilder.RegisterIndex(indexer.Name); - rebuilder.Populate(indexer); - - var searcher = indexer.GetSearcher(); - var ctx = GetUmbracoContext("/test"); - var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, indexer, new StaticCacheProvider(), ContentTypesCache); - - //we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace - var publishedMedia = cache.GetById(1111); - var rootChildren = publishedMedia.Children().ToArray(); - var currSort = 0; - for (var i = 0; i < rootChildren.Count(); i++) - { - Assert.GreaterOrEqual(rootChildren[i].SortOrder, currSort); - currSort = rootChildren[i].SortOrder; - } - } - } - - [Test] - public void Do_Not_Find_In_Recycle_Bin() - { - var rebuilder = IndexInitializer.GetMediaIndexRebuilder(Factory.GetInstance(), IndexInitializer.GetMockMediaService()); - - using (var luceneDir = new RandomIdRamDirectory()) - using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, - //include unpublished content since this uses the 'internal' indexer, it's up to the media cache to filter - validator: new ContentValueSetValidator(false))) - using (indexer.ProcessNonAsync()) - { - rebuilder.RegisterIndex(indexer.Name); - rebuilder.Populate(indexer); - - var searcher = indexer.GetSearcher(); - var ctx = GetUmbracoContext("/test"); - var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, indexer, new StaticCacheProvider(), ContentTypesCache); - - //ensure it is found - var publishedMedia = cache.GetById(3113); - Assert.IsNotNull(publishedMedia); - - //move item to recycle bin - var newXml = XElement.Parse(@" - - 115 - 268 - 10726 - jpg - "); - indexer.IndexItems(new[]{ newXml.ConvertToValueSet("media") }); - - - //ensure it still exists in the index (raw examine search) - var criteria = searcher.CreateQuery(); - var filter = criteria.Id(3113); - var found = filter.Execute(); - Assert.IsNotNull(found); - Assert.AreEqual(1, found.TotalItemCount); - - //ensure it does not show up in the published media store - var recycledMedia = cache.GetById(3113); - Assert.IsNull(recycledMedia); - - } - - } - - [Test] - public void Children_With_Examine() - { - var rebuilder = IndexInitializer.GetMediaIndexRebuilder(Factory.GetInstance(), IndexInitializer.GetMockMediaService()); - - using (var luceneDir = new RandomIdRamDirectory()) - using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, - validator: new ContentValueSetValidator(true))) - using (indexer.ProcessNonAsync()) - { - rebuilder.RegisterIndex(indexer.Name); - rebuilder.Populate(indexer); - - var searcher = indexer.GetSearcher(); - var ctx = GetUmbracoContext("/test"); - var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, indexer, new StaticCacheProvider(), ContentTypesCache); - - //we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace - var publishedMedia = cache.GetById(1111); - var rootChildren = publishedMedia.Children(); - Assert.IsTrue(rootChildren.Select(x => x.Id).ContainsAll(new[] { 2222, 1113, 1114, 1115, 1116 })); - - var publishedChild1 = cache.GetById(2222); - var subChildren = publishedChild1.Children(); - Assert.IsTrue(subChildren.Select(x => x.Id).ContainsAll(new[] { 2112 })); - } - } - - [Test] - public void Descendants_With_Examine() - { - var rebuilder = IndexInitializer.GetMediaIndexRebuilder(Factory.GetInstance(), IndexInitializer.GetMockMediaService()); - - using (var luceneDir = new RandomIdRamDirectory()) - using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, - validator: new ContentValueSetValidator(true))) - using (indexer.ProcessNonAsync()) - { - rebuilder.RegisterIndex(indexer.Name); - rebuilder.Populate(indexer); - - var searcher = indexer.GetSearcher(); - var ctx = GetUmbracoContext("/test"); - var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, indexer, new StaticCacheProvider(), ContentTypesCache); - - //we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace - var publishedMedia = cache.GetById(1111); - var rootDescendants = publishedMedia.Descendants(); - Assert.IsTrue(rootDescendants.Select(x => x.Id).ContainsAll(new[] { 2112, 2222, 1113, 1114, 1115, 1116 })); - - var publishedChild1 = cache.GetById(2222); - var subDescendants = publishedChild1.Descendants(); - Assert.IsTrue(subDescendants.Select(x => x.Id).ContainsAll(new[] { 2112, 3113 })); - } - } - - [Test] - public void DescendantsOrSelf_With_Examine() - { - var rebuilder = IndexInitializer.GetMediaIndexRebuilder(Factory.GetInstance(), IndexInitializer.GetMockMediaService()); - - using (var luceneDir = new RandomIdRamDirectory()) - using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, - validator: new ContentValueSetValidator(true))) - using (indexer.ProcessNonAsync()) - { - rebuilder.RegisterIndex(indexer.Name); - rebuilder.Populate(indexer); - - var searcher = indexer.GetSearcher(); - var ctx = GetUmbracoContext("/test"); - var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, indexer, new StaticCacheProvider(), ContentTypesCache); - - //we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace - var publishedMedia = cache.GetById(1111); - var rootDescendants = publishedMedia.DescendantsOrSelf(); - Assert.IsTrue(rootDescendants.Select(x => x.Id).ContainsAll(new[] { 1111, 2112, 2222, 1113, 1114, 1115, 1116 })); - - var publishedChild1 = cache.GetById(2222); - var subDescendants = publishedChild1.DescendantsOrSelf(); - Assert.IsTrue(subDescendants.Select(x => x.Id).ContainsAll(new[] { 2222, 2112, 3113 })); - } - } - - [Test] - public void Ancestors_With_Examine() - { - var rebuilder = IndexInitializer.GetMediaIndexRebuilder(Factory.GetInstance(), IndexInitializer.GetMockMediaService()); - - - using (var luceneDir = new RandomIdRamDirectory()) - using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, - validator: new ContentValueSetValidator(true))) - using (indexer.ProcessNonAsync()) - { - rebuilder.RegisterIndex(indexer.Name); - rebuilder.Populate(indexer); - - var ctx = GetUmbracoContext("/test"); - var searcher = indexer.GetSearcher(); - var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, indexer, new StaticCacheProvider(), ContentTypesCache); - - //we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace - var publishedMedia = cache.GetById(3113); - var ancestors = publishedMedia.Ancestors(); - Assert.IsTrue(ancestors.Select(x => x.Id).ContainsAll(new[] { 2112, 2222, 1111 })); - } - - } - - [Test] - public void AncestorsOrSelf_With_Examine() - { - var rebuilder = IndexInitializer.GetMediaIndexRebuilder(Factory.GetInstance(), IndexInitializer.GetMockMediaService()); - - using (var luceneDir = new RandomIdRamDirectory()) - using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, - validator: new ContentValueSetValidator(true))) - using (indexer.ProcessNonAsync()) - { - rebuilder.RegisterIndex(indexer.Name); - rebuilder.Populate(indexer); - - - var ctx = GetUmbracoContext("/test"); - var searcher = indexer.GetSearcher(); - var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, indexer, new StaticCacheProvider(), ContentTypesCache); - - //we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace - var publishedMedia = cache.GetById(3113); - var ancestors = publishedMedia.AncestorsOrSelf(); - Assert.IsTrue(ancestors.Select(x => x.Id).ContainsAll(new[] { 3113, 2112, 2222, 1111 })); - } - } - - [Test] - public void Children_Without_Examine() - { - var user = ServiceContext.UserService.GetUserById(0); - var mType = MakeNewMediaType(user, "TestMediaType"); - var mRoot = MakeNewMedia("MediaRoot", mType, user, -1); - - var mChild1 = MakeNewMedia("Child1", mType, user, mRoot.Id); - var mChild2 = MakeNewMedia("Child2", mType, user, mRoot.Id); - var mChild3 = MakeNewMedia("Child3", mType, user, mRoot.Id); - - var mSubChild1 = MakeNewMedia("SubChild1", mType, user, mChild1.Id); - var mSubChild2 = MakeNewMedia("SubChild2", mType, user, mChild1.Id); - var mSubChild3 = MakeNewMedia("SubChild3", mType, user, mChild1.Id); - - var publishedMedia = GetNode(mRoot.Id); - var rootChildren = publishedMedia.Children(); - Assert.IsTrue(rootChildren.Select(x => x.Id).ContainsAll(new[] { mChild1.Id, mChild2.Id, mChild3.Id })); - - var publishedChild1 = GetNode(mChild1.Id); - var subChildren = publishedChild1.Children(); - Assert.IsTrue(subChildren.Select(x => x.Id).ContainsAll(new[] { mSubChild1.Id, mSubChild2.Id, mSubChild3.Id })); - } - - [Test] - public void Descendants_Without_Examine() - { - var user = ServiceContext.UserService.GetUserById(0); - var mType = MakeNewMediaType(user, "TestMediaType"); - var mRoot = MakeNewMedia("MediaRoot", mType, user, -1); - - var mChild1 = MakeNewMedia("Child1", mType, user, mRoot.Id); - var mChild2 = MakeNewMedia("Child2", mType, user, mRoot.Id); - var mChild3 = MakeNewMedia("Child3", mType, user, mRoot.Id); - - var mSubChild1 = MakeNewMedia("SubChild1", mType, user, mChild1.Id); - var mSubChild2 = MakeNewMedia("SubChild2", mType, user, mChild1.Id); - var mSubChild3 = MakeNewMedia("SubChild3", mType, user, mChild1.Id); - - var publishedMedia = GetNode(mRoot.Id); - var rootDescendants = publishedMedia.Descendants(); - Assert.IsTrue(rootDescendants.Select(x => x.Id).ContainsAll(new[] { mChild1.Id, mChild2.Id, mChild3.Id, mSubChild1.Id, mSubChild2.Id, mSubChild3.Id })); - - var publishedChild1 = GetNode(mChild1.Id); - var subDescendants = publishedChild1.Descendants(); - Assert.IsTrue(subDescendants.Select(x => x.Id).ContainsAll(new[] { mSubChild1.Id, mSubChild2.Id, mSubChild3.Id })); - } - - [Test] - public void DescendantsOrSelf_Without_Examine() - { - var user = ServiceContext.UserService.GetUserById(0); - var mType = MakeNewMediaType(user, "TestMediaType"); - var mRoot = MakeNewMedia("MediaRoot", mType, user, -1); - - var mChild1 = MakeNewMedia("Child1", mType, user, mRoot.Id); - var mChild2 = MakeNewMedia("Child2", mType, user, mRoot.Id); - var mChild3 = MakeNewMedia("Child3", mType, user, mRoot.Id); - - var mSubChild1 = MakeNewMedia("SubChild1", mType, user, mChild1.Id); - var mSubChild2 = MakeNewMedia("SubChild2", mType, user, mChild1.Id); - var mSubChild3 = MakeNewMedia("SubChild3", mType, user, mChild1.Id); - - var publishedMedia = GetNode(mRoot.Id); - var rootDescendantsOrSelf = publishedMedia.DescendantsOrSelf(); - Assert.IsTrue(rootDescendantsOrSelf.Select(x => x.Id).ContainsAll( - new[] { mRoot.Id, mChild1.Id, mChild2.Id, mChild3.Id, mSubChild1.Id, mSubChild2.Id, mSubChild3.Id })); - - var publishedChild1 = GetNode(mChild1.Id); - var subDescendantsOrSelf = publishedChild1.DescendantsOrSelf(); - Assert.IsTrue(subDescendantsOrSelf.Select(x => x.Id).ContainsAll( - new[] { mChild1.Id, mSubChild1.Id, mSubChild2.Id, mSubChild3.Id })); - } - - [Test] - public void Parent_Without_Examine() - { - var user = ServiceContext.UserService.GetUserById(0); - var mType = MakeNewMediaType(user, "TestMediaType"); - var mRoot = MakeNewMedia("MediaRoot", mType, user, -1); - - var mChild1 = MakeNewMedia("Child1", mType, user, mRoot.Id); - var mChild2 = MakeNewMedia("Child2", mType, user, mRoot.Id); - var mChild3 = MakeNewMedia("Child3", mType, user, mRoot.Id); - - var mSubChild1 = MakeNewMedia("SubChild1", mType, user, mChild1.Id); - var mSubChild2 = MakeNewMedia("SubChild2", mType, user, mChild1.Id); - var mSubChild3 = MakeNewMedia("SubChild3", mType, user, mChild1.Id); - - var publishedRoot = GetNode(mRoot.Id); - Assert.AreEqual(null, publishedRoot.Parent); - - var publishedChild1 = GetNode(mChild1.Id); - Assert.AreEqual(mRoot.Id, publishedChild1.Parent.Id); - - var publishedSubChild1 = GetNode(mSubChild1.Id); - Assert.AreEqual(mChild1.Id, publishedSubChild1.Parent.Id); - } - - [Test] - public void Ancestors_Without_Examine() - { - var user = ServiceContext.UserService.GetUserById(0); - var mType = MakeNewMediaType(user, "TestMediaType"); - var mRoot = MakeNewMedia("MediaRoot", mType, user, -1); - - var mChild1 = MakeNewMedia("Child1", mType, user, mRoot.Id); - var mChild2 = MakeNewMedia("Child2", mType, user, mRoot.Id); - var mChild3 = MakeNewMedia("Child3", mType, user, mRoot.Id); - - var mSubChild1 = MakeNewMedia("SubChild1", mType, user, mChild1.Id); - var mSubChild2 = MakeNewMedia("SubChild2", mType, user, mChild1.Id); - var mSubChild3 = MakeNewMedia("SubChild3", mType, user, mChild1.Id); - - var publishedSubChild1 = GetNode(mSubChild1.Id); - Assert.IsTrue(publishedSubChild1.Ancestors().Select(x => x.Id).ContainsAll(new[] { mChild1.Id, mRoot.Id })); - } - - [Test] - public void AncestorsOrSelf_Without_Examine() - { - var user = ServiceContext.UserService.GetUserById(0); - var mType = MakeNewMediaType(user, "TestMediaType"); - var mRoot = MakeNewMedia("MediaRoot", mType, user, -1); - - var mChild1 = MakeNewMedia("Child1", mType, user, mRoot.Id); - var mChild2 = MakeNewMedia("Child2", mType, user, mRoot.Id); - var mChild3 = MakeNewMedia("Child3", mType, user, mRoot.Id); - - var mSubChild1 = MakeNewMedia("SubChild1", mType, user, mChild1.Id); - var mSubChild2 = MakeNewMedia("SubChild2", mType, user, mChild1.Id); - var mSubChild3 = MakeNewMedia("SubChild3", mType, user, mChild1.Id); - - var publishedSubChild1 = GetNode(mSubChild1.Id); - Assert.IsTrue(publishedSubChild1.AncestorsOrSelf().Select(x => x.Id).ContainsAll( - new[] { mSubChild1.Id, mChild1.Id, mRoot.Id })); - } - - [Test] - public void Convert_From_Standard_Xml() - { - var nodeId = 2112; - - var xml = XElement.Parse(@" - - 115 - 268 - 10726 - jpg - - - 115 - 268 - 10726 - jpg - - "); - var node = xml.DescendantsAndSelf("Image").Single(x => (int)x.Attribute("id") == nodeId); - - var publishedMedia = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), ServiceContext.MediaService, ServiceContext.UserService, new StaticCacheProvider(), ContentTypesCache); - - var nav = node.CreateNavigator(); - - var converted = publishedMedia.CreateFromCacheValues( - publishedMedia.ConvertFromXPathNodeIterator(nav.Select("/Image"), nodeId)); - - Assert.AreEqual(nodeId, converted.Id); - Assert.AreEqual(3, converted.Level); - Assert.AreEqual(1, converted.SortOrder); - Assert.AreEqual("Sam's Umbraco Image", converted.Name); - Assert.AreEqual("-1,1111,2222,2112", converted.Path); - } - - [Test] - public void Detects_Error_In_Xml() - { - var errorXml = new XElement("error", string.Format("No media is maching '{0}'", 1234)); - var nav = errorXml.CreateNavigator(); - - var publishedMedia = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), ServiceContext.MediaService, ServiceContext.UserService, new StaticCacheProvider(), ContentTypesCache); - var converted = publishedMedia.ConvertFromXPathNodeIterator(nav.Select("/"), 1234); - - Assert.IsNull(converted); - } - } -} +//using System.Web; +//using System.Xml.Linq; +//using System.Xml.XPath; +//using NUnit.Framework; +//using Umbraco.Core; +//using Umbraco.Core.Models; +//using Umbraco.Tests.TestHelpers; +//using Umbraco.Tests.TestHelpers.Entities; +//using Umbraco.Tests.UmbracoExamine; +//using Umbraco.Web; +//using Umbraco.Web.PublishedCache.XmlPublishedCache; +//using System.Linq; +//using System.Threading; +//using System.Xml; +//using Examine; +//using Umbraco.Core.Cache; +//using Umbraco.Core.Models.PublishedContent; +//using Umbraco.Core.Strings; +//using Umbraco.Examine; +//using Current = Umbraco.Web.Composing.Current; +//using Umbraco.Tests.Testing; +//using Umbraco.Core.Composing; +//using Umbraco.Core.Models.Membership; +//using Umbraco.Core.PropertyEditors; +// +//namespace Umbraco.Tests.PublishedContent +//{ +// /// +// /// Tests the typed extension methods on IPublishedContent using the DefaultPublishedMediaStore +// /// +// [TestFixture] +// [Apartment(ApartmentState.STA)] +// [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest, WithApplication = true)] +// public class PublishedMediaTests : PublishedContentTestBase +// { +// /// +// /// sets up resolvers before resolution is frozen +// /// +// protected override void Compose() +// { +// base.Compose(); +// +// Composition.WithCollectionBuilder() +// .Clear() +// .Append(); +// } +// +// private IMediaType MakeNewMediaType(IUser user, string text, int parentId = -1) +// { +// var mt = new MediaType(parentId) { Name = text, Alias = text, Thumbnail = "icon-folder", Icon = "icon-folder" }; +// ServiceContext.MediaTypeService.Save(mt); +// return mt; +// } +// +// private IMedia MakeNewMedia(string name, IMediaType mediaType, IUser user, int parentId) +// { +// var m = ServiceContext.MediaService.CreateMediaWithIdentity(name, parentId, mediaType.Alias); +// return m; +// } +// +// /// +// /// Shared with PublishMediaStoreTests +// /// +// /// +// /// +// /// +// internal IPublishedContent GetNode(int id, UmbracoContext umbracoContext) +// { +// var cache = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), Current.Services.MediaService, Current.Services.UserService, new StaticCacheProvider(), ContentTypesCache); +// var doc = cache.GetById(id); +// Assert.IsNotNull(doc); +// return doc; +// } +// +// private IPublishedContent GetNode(int id) +// { +// return GetNode(id, GetUmbracoContext("/test")); +// } +// +// [Test] +// public void Get_Property_Value_Uses_Converter() +// { +// var mType = MockedContentTypes.CreateImageMediaType("image2"); +// //lets add an RTE to this +// mType.PropertyGroups.First().PropertyTypes.Add( +// new PropertyType("test", ValueStorageType.Nvarchar, "content") +// { +// Name = "Rich Text", +// DataTypeId = -87 //tiny mce +// }); +// ServiceContext.MediaTypeService.Save(mType); +// var media = MockedMedia.CreateMediaImage(mType, -1); +// media.Properties["content"].SetValue("
    This is some content
    "); +// ServiceContext.MediaService.Save(media); +// +// var publishedMedia = GetNode(media.Id); +// +// var propVal = publishedMedia.Value("content"); +// Assert.IsInstanceOf(propVal); +// Assert.AreEqual("
    This is some content
    ", propVal.ToString()); +// +// var propVal2 = publishedMedia.Value("content"); +// Assert.IsInstanceOf(propVal2); +// Assert.AreEqual("
    This is some content
    ", propVal2.ToString()); +// +// var propVal3 = publishedMedia.Value("Content"); +// Assert.IsInstanceOf(propVal3); +// Assert.AreEqual("
    This is some content
    ", propVal3.ToString()); +// } +// +// [Test] +// public void Ensure_Children_Sorted_With_Examine() +// { +// var rebuilder = IndexInitializer.GetMediaIndexRebuilder(Factory.GetInstance(), IndexInitializer.GetMockMediaService()); +// +// using (var luceneDir = new RandomIdRamDirectory()) +// using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, +// validator: new ContentValueSetValidator(true))) +// using (indexer.ProcessNonAsync()) +// { +// rebuilder.RegisterIndex(indexer.Name); +// rebuilder.Populate(indexer); +// +// var searcher = indexer.GetSearcher(); +// var ctx = GetUmbracoContext("/test"); +// var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, indexer, new StaticCacheProvider(), ContentTypesCache); +// +// //we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace +// var publishedMedia = cache.GetById(1111); +// var rootChildren = publishedMedia.Children().ToArray(); +// var currSort = 0; +// for (var i = 0; i < rootChildren.Count(); i++) +// { +// Assert.GreaterOrEqual(rootChildren[i].SortOrder, currSort); +// currSort = rootChildren[i].SortOrder; +// } +// } +// } +// +// [Test] +// public void Do_Not_Find_In_Recycle_Bin() +// { +// var rebuilder = IndexInitializer.GetMediaIndexRebuilder(Factory.GetInstance(), IndexInitializer.GetMockMediaService()); +// +// using (var luceneDir = new RandomIdRamDirectory()) +// using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, +// //include unpublished content since this uses the 'internal' indexer, it's up to the media cache to filter +// validator: new ContentValueSetValidator(false))) +// using (indexer.ProcessNonAsync()) +// { +// rebuilder.RegisterIndex(indexer.Name); +// rebuilder.Populate(indexer); +// +// var searcher = indexer.GetSearcher(); +// var ctx = GetUmbracoContext("/test"); +// var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, indexer, new StaticCacheProvider(), ContentTypesCache); +// +// //ensure it is found +// var publishedMedia = cache.GetById(3113); +// Assert.IsNotNull(publishedMedia); +// +// //move item to recycle bin +// var newXml = XElement.Parse(@" +// +// 115 +// 268 +// 10726 +// jpg +// "); +// indexer.IndexItems(new[]{ newXml.ConvertToValueSet("media") }); +// +// +// //ensure it still exists in the index (raw examine search) +// var criteria = searcher.CreateQuery(); +// var filter = criteria.Id(3113); +// var found = filter.Execute(); +// Assert.IsNotNull(found); +// Assert.AreEqual(1, found.TotalItemCount); +// +// //ensure it does not show up in the published media store +// var recycledMedia = cache.GetById(3113); +// Assert.IsNull(recycledMedia); +// +// } +// +// } +// +// [Test] +// public void Children_With_Examine() +// { +// var rebuilder = IndexInitializer.GetMediaIndexRebuilder(Factory.GetInstance(), IndexInitializer.GetMockMediaService()); +// +// using (var luceneDir = new RandomIdRamDirectory()) +// using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, +// validator: new ContentValueSetValidator(true))) +// using (indexer.ProcessNonAsync()) +// { +// rebuilder.RegisterIndex(indexer.Name); +// rebuilder.Populate(indexer); +// +// var searcher = indexer.GetSearcher(); +// var ctx = GetUmbracoContext("/test"); +// var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, indexer, new StaticCacheProvider(), ContentTypesCache); +// +// //we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace +// var publishedMedia = cache.GetById(1111); +// var rootChildren = publishedMedia.Children(); +// Assert.IsTrue(rootChildren.Select(x => x.Id).ContainsAll(new[] { 2222, 1113, 1114, 1115, 1116 })); +// +// var publishedChild1 = cache.GetById(2222); +// var subChildren = publishedChild1.Children(); +// Assert.IsTrue(subChildren.Select(x => x.Id).ContainsAll(new[] { 2112 })); +// } +// } +// +// [Test] +// public void Descendants_With_Examine() +// { +// var rebuilder = IndexInitializer.GetMediaIndexRebuilder(Factory.GetInstance(), IndexInitializer.GetMockMediaService()); +// +// using (var luceneDir = new RandomIdRamDirectory()) +// using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, +// validator: new ContentValueSetValidator(true))) +// using (indexer.ProcessNonAsync()) +// { +// rebuilder.RegisterIndex(indexer.Name); +// rebuilder.Populate(indexer); +// +// var searcher = indexer.GetSearcher(); +// var ctx = GetUmbracoContext("/test"); +// var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, indexer, new StaticCacheProvider(), ContentTypesCache); +// +// //we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace +// var publishedMedia = cache.GetById(1111); +// var rootDescendants = publishedMedia.Descendants(); +// Assert.IsTrue(rootDescendants.Select(x => x.Id).ContainsAll(new[] { 2112, 2222, 1113, 1114, 1115, 1116 })); +// +// var publishedChild1 = cache.GetById(2222); +// var subDescendants = publishedChild1.Descendants(); +// Assert.IsTrue(subDescendants.Select(x => x.Id).ContainsAll(new[] { 2112, 3113 })); +// } +// } +// +// [Test] +// public void DescendantsOrSelf_With_Examine() +// { +// var rebuilder = IndexInitializer.GetMediaIndexRebuilder(Factory.GetInstance(), IndexInitializer.GetMockMediaService()); +// +// using (var luceneDir = new RandomIdRamDirectory()) +// using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, +// validator: new ContentValueSetValidator(true))) +// using (indexer.ProcessNonAsync()) +// { +// rebuilder.RegisterIndex(indexer.Name); +// rebuilder.Populate(indexer); +// +// var searcher = indexer.GetSearcher(); +// var ctx = GetUmbracoContext("/test"); +// var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, indexer, new StaticCacheProvider(), ContentTypesCache); +// +// //we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace +// var publishedMedia = cache.GetById(1111); +// var rootDescendants = publishedMedia.DescendantsOrSelf(); +// Assert.IsTrue(rootDescendants.Select(x => x.Id).ContainsAll(new[] { 1111, 2112, 2222, 1113, 1114, 1115, 1116 })); +// +// var publishedChild1 = cache.GetById(2222); +// var subDescendants = publishedChild1.DescendantsOrSelf(); +// Assert.IsTrue(subDescendants.Select(x => x.Id).ContainsAll(new[] { 2222, 2112, 3113 })); +// } +// } +// +// [Test] +// public void Ancestors_With_Examine() +// { +// var rebuilder = IndexInitializer.GetMediaIndexRebuilder(Factory.GetInstance(), IndexInitializer.GetMockMediaService()); +// +// +// using (var luceneDir = new RandomIdRamDirectory()) +// using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, +// validator: new ContentValueSetValidator(true))) +// using (indexer.ProcessNonAsync()) +// { +// rebuilder.RegisterIndex(indexer.Name); +// rebuilder.Populate(indexer); +// +// var ctx = GetUmbracoContext("/test"); +// var searcher = indexer.GetSearcher(); +// var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, indexer, new StaticCacheProvider(), ContentTypesCache); +// +// //we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace +// var publishedMedia = cache.GetById(3113); +// var ancestors = publishedMedia.Ancestors(); +// Assert.IsTrue(ancestors.Select(x => x.Id).ContainsAll(new[] { 2112, 2222, 1111 })); +// } +// +// } +// +// [Test] +// public void AncestorsOrSelf_With_Examine() +// { +// var rebuilder = IndexInitializer.GetMediaIndexRebuilder(Factory.GetInstance(), IndexInitializer.GetMockMediaService()); +// +// using (var luceneDir = new RandomIdRamDirectory()) +// using (var indexer = IndexInitializer.GetUmbracoIndexer(ProfilingLogger, luceneDir, +// validator: new ContentValueSetValidator(true))) +// using (indexer.ProcessNonAsync()) +// { +// rebuilder.RegisterIndex(indexer.Name); +// rebuilder.Populate(indexer); +// +// +// var ctx = GetUmbracoContext("/test"); +// var searcher = indexer.GetSearcher(); +// var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, indexer, new StaticCacheProvider(), ContentTypesCache); +// +// //we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace +// var publishedMedia = cache.GetById(3113); +// var ancestors = publishedMedia.AncestorsOrSelf(); +// Assert.IsTrue(ancestors.Select(x => x.Id).ContainsAll(new[] { 3113, 2112, 2222, 1111 })); +// } +// } +// +// [Test] +// public void Children_Without_Examine() +// { +// var user = ServiceContext.UserService.GetUserById(0); +// var mType = MakeNewMediaType(user, "TestMediaType"); +// var mRoot = MakeNewMedia("MediaRoot", mType, user, -1); +// +// var mChild1 = MakeNewMedia("Child1", mType, user, mRoot.Id); +// var mChild2 = MakeNewMedia("Child2", mType, user, mRoot.Id); +// var mChild3 = MakeNewMedia("Child3", mType, user, mRoot.Id); +// +// var mSubChild1 = MakeNewMedia("SubChild1", mType, user, mChild1.Id); +// var mSubChild2 = MakeNewMedia("SubChild2", mType, user, mChild1.Id); +// var mSubChild3 = MakeNewMedia("SubChild3", mType, user, mChild1.Id); +// +// var publishedMedia = GetNode(mRoot.Id); +// var rootChildren = publishedMedia.Children(); +// Assert.IsTrue(rootChildren.Select(x => x.Id).ContainsAll(new[] { mChild1.Id, mChild2.Id, mChild3.Id })); +// +// var publishedChild1 = GetNode(mChild1.Id); +// var subChildren = publishedChild1.Children(); +// Assert.IsTrue(subChildren.Select(x => x.Id).ContainsAll(new[] { mSubChild1.Id, mSubChild2.Id, mSubChild3.Id })); +// } +// +// [Test] +// public void Descendants_Without_Examine() +// { +// var user = ServiceContext.UserService.GetUserById(0); +// var mType = MakeNewMediaType(user, "TestMediaType"); +// var mRoot = MakeNewMedia("MediaRoot", mType, user, -1); +// +// var mChild1 = MakeNewMedia("Child1", mType, user, mRoot.Id); +// var mChild2 = MakeNewMedia("Child2", mType, user, mRoot.Id); +// var mChild3 = MakeNewMedia("Child3", mType, user, mRoot.Id); +// +// var mSubChild1 = MakeNewMedia("SubChild1", mType, user, mChild1.Id); +// var mSubChild2 = MakeNewMedia("SubChild2", mType, user, mChild1.Id); +// var mSubChild3 = MakeNewMedia("SubChild3", mType, user, mChild1.Id); +// +// var publishedMedia = GetNode(mRoot.Id); +// var rootDescendants = publishedMedia.Descendants(); +// Assert.IsTrue(rootDescendants.Select(x => x.Id).ContainsAll(new[] { mChild1.Id, mChild2.Id, mChild3.Id, mSubChild1.Id, mSubChild2.Id, mSubChild3.Id })); +// +// var publishedChild1 = GetNode(mChild1.Id); +// var subDescendants = publishedChild1.Descendants(); +// Assert.IsTrue(subDescendants.Select(x => x.Id).ContainsAll(new[] { mSubChild1.Id, mSubChild2.Id, mSubChild3.Id })); +// } +// +// [Test] +// public void DescendantsOrSelf_Without_Examine() +// { +// var user = ServiceContext.UserService.GetUserById(0); +// var mType = MakeNewMediaType(user, "TestMediaType"); +// var mRoot = MakeNewMedia("MediaRoot", mType, user, -1); +// +// var mChild1 = MakeNewMedia("Child1", mType, user, mRoot.Id); +// var mChild2 = MakeNewMedia("Child2", mType, user, mRoot.Id); +// var mChild3 = MakeNewMedia("Child3", mType, user, mRoot.Id); +// +// var mSubChild1 = MakeNewMedia("SubChild1", mType, user, mChild1.Id); +// var mSubChild2 = MakeNewMedia("SubChild2", mType, user, mChild1.Id); +// var mSubChild3 = MakeNewMedia("SubChild3", mType, user, mChild1.Id); +// +// var publishedMedia = GetNode(mRoot.Id); +// var rootDescendantsOrSelf = publishedMedia.DescendantsOrSelf(); +// Assert.IsTrue(rootDescendantsOrSelf.Select(x => x.Id).ContainsAll( +// new[] { mRoot.Id, mChild1.Id, mChild2.Id, mChild3.Id, mSubChild1.Id, mSubChild2.Id, mSubChild3.Id })); +// +// var publishedChild1 = GetNode(mChild1.Id); +// var subDescendantsOrSelf = publishedChild1.DescendantsOrSelf(); +// Assert.IsTrue(subDescendantsOrSelf.Select(x => x.Id).ContainsAll( +// new[] { mChild1.Id, mSubChild1.Id, mSubChild2.Id, mSubChild3.Id })); +// } +// +// [Test] +// public void Parent_Without_Examine() +// { +// var user = ServiceContext.UserService.GetUserById(0); +// var mType = MakeNewMediaType(user, "TestMediaType"); +// var mRoot = MakeNewMedia("MediaRoot", mType, user, -1); +// +// var mChild1 = MakeNewMedia("Child1", mType, user, mRoot.Id); +// var mChild2 = MakeNewMedia("Child2", mType, user, mRoot.Id); +// var mChild3 = MakeNewMedia("Child3", mType, user, mRoot.Id); +// +// var mSubChild1 = MakeNewMedia("SubChild1", mType, user, mChild1.Id); +// var mSubChild2 = MakeNewMedia("SubChild2", mType, user, mChild1.Id); +// var mSubChild3 = MakeNewMedia("SubChild3", mType, user, mChild1.Id); +// +// var publishedRoot = GetNode(mRoot.Id); +// Assert.AreEqual(null, publishedRoot.Parent); +// +// var publishedChild1 = GetNode(mChild1.Id); +// Assert.AreEqual(mRoot.Id, publishedChild1.Parent.Id); +// +// var publishedSubChild1 = GetNode(mSubChild1.Id); +// Assert.AreEqual(mChild1.Id, publishedSubChild1.Parent.Id); +// } +// +// [Test] +// public void Ancestors_Without_Examine() +// { +// var user = ServiceContext.UserService.GetUserById(0); +// var mType = MakeNewMediaType(user, "TestMediaType"); +// var mRoot = MakeNewMedia("MediaRoot", mType, user, -1); +// +// var mChild1 = MakeNewMedia("Child1", mType, user, mRoot.Id); +// var mChild2 = MakeNewMedia("Child2", mType, user, mRoot.Id); +// var mChild3 = MakeNewMedia("Child3", mType, user, mRoot.Id); +// +// var mSubChild1 = MakeNewMedia("SubChild1", mType, user, mChild1.Id); +// var mSubChild2 = MakeNewMedia("SubChild2", mType, user, mChild1.Id); +// var mSubChild3 = MakeNewMedia("SubChild3", mType, user, mChild1.Id); +// +// var publishedSubChild1 = GetNode(mSubChild1.Id); +// Assert.IsTrue(publishedSubChild1.Ancestors().Select(x => x.Id).ContainsAll(new[] { mChild1.Id, mRoot.Id })); +// } +// +// [Test] +// public void AncestorsOrSelf_Without_Examine() +// { +// var user = ServiceContext.UserService.GetUserById(0); +// var mType = MakeNewMediaType(user, "TestMediaType"); +// var mRoot = MakeNewMedia("MediaRoot", mType, user, -1); +// +// var mChild1 = MakeNewMedia("Child1", mType, user, mRoot.Id); +// var mChild2 = MakeNewMedia("Child2", mType, user, mRoot.Id); +// var mChild3 = MakeNewMedia("Child3", mType, user, mRoot.Id); +// +// var mSubChild1 = MakeNewMedia("SubChild1", mType, user, mChild1.Id); +// var mSubChild2 = MakeNewMedia("SubChild2", mType, user, mChild1.Id); +// var mSubChild3 = MakeNewMedia("SubChild3", mType, user, mChild1.Id); +// +// var publishedSubChild1 = GetNode(mSubChild1.Id); +// Assert.IsTrue(publishedSubChild1.AncestorsOrSelf().Select(x => x.Id).ContainsAll( +// new[] { mSubChild1.Id, mChild1.Id, mRoot.Id })); +// } +// +// [Test] +// public void Convert_From_Standard_Xml() +// { +// var nodeId = 2112; +// +// var xml = XElement.Parse(@" +// +// 115 +// 268 +// 10726 +// jpg +// +// +// 115 +// 268 +// 10726 +// jpg +// +// "); +// var node = xml.DescendantsAndSelf("Image").Single(x => (int)x.Attribute("id") == nodeId); +// +// var publishedMedia = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), ServiceContext.MediaService, ServiceContext.UserService, new StaticCacheProvider(), ContentTypesCache); +// +// var nav = node.CreateNavigator(); +// +// var converted = publishedMedia.CreateFromCacheValues( +// publishedMedia.ConvertFromXPathNodeIterator(nav.Select("/Image"), nodeId)); +// +// Assert.AreEqual(nodeId, converted.Id); +// Assert.AreEqual(3, converted.Level); +// Assert.AreEqual(1, converted.SortOrder); +// Assert.AreEqual("Sam's Umbraco Image", converted.Name); +// Assert.AreEqual("-1,1111,2222,2112", converted.Path); +// } +// +// [Test] +// public void Detects_Error_In_Xml() +// { +// var errorXml = new XElement("error", string.Format("No media is maching '{0}'", 1234)); +// var nav = errorXml.CreateNavigator(); +// +// var publishedMedia = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), ServiceContext.MediaService, ServiceContext.UserService, new StaticCacheProvider(), ContentTypesCache); +// var converted = publishedMedia.ConvertFromXPathNodeIterator(nav.Select("/"), 1234); +// +// Assert.IsNull(converted); +// } +// } +//} diff --git a/src/Umbraco.Web/PublishedContentExtensions.cs b/src/Umbraco.Web/PublishedContentExtensions.cs index d4494c5f91..21353049d8 100644 --- a/src/Umbraco.Web/PublishedContentExtensions.cs +++ b/src/Umbraco.Web/PublishedContentExtensions.cs @@ -864,79 +864,79 @@ namespace Umbraco.Web return content.DescendantsOrSelf(level).OfType(); } - public static IPublishedContent Descendant(this IPublishedContent content) + public static IPublishedContent Descendant(this IPublishedContent content, string culture = null) { - return content.Children.FirstOrDefault(); + return content.Children(culture).FirstOrDefault(); } - public static IPublishedContent Descendant(this IPublishedContent content, int level) + public static IPublishedContent Descendant(this IPublishedContent content, int level, string culture = null) { - return content.EnumerateDescendants(false).FirstOrDefault(x => x.Level == level); + return content.EnumerateDescendants(false, culture).FirstOrDefault(x => x.Level == level); } - public static IPublishedContent Descendant(this IPublishedContent content, string contentTypeAlias) + public static IPublishedContent Descendant(this IPublishedContent content, string contentTypeAlias, string culture = null) { - return content.EnumerateDescendants(false).FirstOrDefault(x => x.ContentType.Alias == contentTypeAlias); + return content.EnumerateDescendants(false, culture).FirstOrDefault(x => x.ContentType.Alias == contentTypeAlias); } - public static T Descendant(this IPublishedContent content) + public static T Descendant(this IPublishedContent content, string culture = null) where T : class, IPublishedContent { - return content.EnumerateDescendants(false).FirstOrDefault(x => x is T) as T; + return content.EnumerateDescendants(false, culture).FirstOrDefault(x => x is T) as T; } - public static T Descendant(this IPublishedContent content, int level) + public static T Descendant(this IPublishedContent content, int level, string culture = null) where T : class, IPublishedContent { - return content.Descendant(level) as T; + return content.Descendant(level, culture) as T; } - public static IPublishedContent DescendantOrSelf(this IPublishedContent content) + public static IPublishedContent DescendantOrSelf(this IPublishedContent content, string culture = null) { return content; } - public static IPublishedContent DescendantOrSelf(this IPublishedContent content, int level) + public static IPublishedContent DescendantOrSelf(this IPublishedContent content, int level, string culture = null) { - return content.EnumerateDescendants(true).FirstOrDefault(x => x.Level == level); + return content.EnumerateDescendants(true, culture).FirstOrDefault(x => x.Level == level); } - public static IPublishedContent DescendantOrSelf(this IPublishedContent content, string contentTypeAlias) + public static IPublishedContent DescendantOrSelf(this IPublishedContent content, string contentTypeAlias, string culture = null) { - return content.EnumerateDescendants(true).FirstOrDefault(x => x.ContentType.Alias == contentTypeAlias); + return content.EnumerateDescendants(true, culture).FirstOrDefault(x => x.ContentType.Alias == contentTypeAlias); } - public static T DescendantOrSelf(this IPublishedContent content) + public static T DescendantOrSelf(this IPublishedContent content, string culture = null) where T : class, IPublishedContent { - return content.EnumerateDescendants(true).FirstOrDefault(x => x is T) as T; + return content.EnumerateDescendants(true, culture).FirstOrDefault(x => x is T) as T; } - public static T DescendantOrSelf(this IPublishedContent content, int level) + public static T DescendantOrSelf(this IPublishedContent content, int level, string culture = null) where T : class, IPublishedContent { - return content.DescendantOrSelf(level) as T; + return content.DescendantOrSelf(level, culture) as T; } - internal static IEnumerable DescendantsOrSelf(this IPublishedContent content, bool orSelf, Func func) + internal static IEnumerable DescendantsOrSelf(this IPublishedContent content, bool orSelf, Func func, string culture = null) { - return content.EnumerateDescendants(orSelf).Where(x => func == null || func(x)); + return content.EnumerateDescendants(orSelf, culture).Where(x => func == null || func(x)); } - internal static IEnumerable EnumerateDescendants(this IPublishedContent content, bool orSelf) + internal static IEnumerable EnumerateDescendants(this IPublishedContent content, bool orSelf, string culture = null) { if (content == null) throw new ArgumentNullException(nameof(content)); if (orSelf) yield return content; - foreach (var desc in content.Children.SelectMany(x => x.EnumerateDescendants())) + foreach (var desc in content.Children(culture).SelectMany(x => x.EnumerateDescendants())) yield return desc; } - internal static IEnumerable EnumerateDescendants(this IPublishedContent content) + internal static IEnumerable EnumerateDescendants(this IPublishedContent content, string culture = null) { yield return content; - foreach (var desc in content.Children.SelectMany(x => x.EnumerateDescendants())) + foreach (var desc in content.Children(culture).SelectMany(x => x.EnumerateDescendants())) yield return desc; } @@ -1022,6 +1022,23 @@ namespace Umbraco.Web #region Axes: children + + private static IEnumerable WhereHasCulture(this IEnumerable contents, string culture = null) + { + if (contents == null) throw new ArgumentNullException(nameof(contents)); + + var actualCulture = culture ?? GetCurrentCulture(); + + return contents.Where(x=>x.HasCulture(actualCulture) ||x.HasCulture(null)); + } + + private static string GetCurrentCulture() + { + + //Review: is this the correct way to get the current culture? + return System.Threading.Thread.CurrentThread.CurrentUICulture.Name; + } + /// /// Gets the children of the content. /// @@ -1031,10 +1048,10 @@ namespace Umbraco.Web /// Children are sorted by their sortOrder. /// This method exists for consistency, it is the same as calling content.Children as a property. /// - public static IEnumerable Children(this IPublishedContent content) + public static IEnumerable Children(this IPublishedContent content, string culture = null) { if (content == null) throw new ArgumentNullException(nameof(content)); - return content.Children; + return content.Children.WhereHasCulture(culture); } /// @@ -1046,9 +1063,9 @@ namespace Umbraco.Web /// /// Children are sorted by their sortOrder. /// - public static IEnumerable Children(this IPublishedContent content, Func predicate) + public static IEnumerable Children(this IPublishedContent content, Func predicate, string culture = null) { - return content.Children().Where(predicate); + return content.Children(culture).Where(predicate); } /// @@ -1057,9 +1074,9 @@ namespace Umbraco.Web /// The content. /// One or more content type alias. /// The children of the content, of any of the specified types. - public static IEnumerable Children(this IPublishedContent content, params string[] alias) + public static IEnumerable Children(this IPublishedContent content, string culture = null, params string[] alias) { - return content.Children(x => alias.InvariantContains(x.ContentType.Alias)); + return content.Children(x => alias.InvariantContains(x.ContentType.Alias), culture); } /// @@ -1071,15 +1088,15 @@ namespace Umbraco.Web /// /// Children are sorted by their sortOrder. /// - public static IEnumerable Children(this IPublishedContent content) + public static IEnumerable Children(this IPublishedContent content, string culture = null) where T : class, IPublishedContent { - return content.Children().OfType(); + return content.Children(culture).OfType(); } - public static IPublishedContent FirstChild(this IPublishedContent content) + public static IPublishedContent FirstChild(this IPublishedContent content, string culture = null) { - return content.Children().FirstOrDefault(); + return content.Children(culture).FirstOrDefault(); } /// @@ -1088,26 +1105,26 @@ namespace Umbraco.Web /// The content. /// The content type alias. /// The first child of content, of the given content type. - public static IPublishedContent FirstChild(this IPublishedContent content, string alias) + public static IPublishedContent FirstChild(this IPublishedContent content, string alias, string culture = null) { - return content.Children(alias).FirstOrDefault(); + return content.Children(culture,alias).FirstOrDefault(); } - public static IPublishedContent FirstChild(this IPublishedContent content, Func predicate) + public static IPublishedContent FirstChild(this IPublishedContent content, Func predicate, string culture = null) { - return content.Children(predicate).FirstOrDefault(); + return content.Children(predicate, culture).FirstOrDefault(); } - public static T FirstChild(this IPublishedContent content) + public static T FirstChild(this IPublishedContent content, string culture = null) where T : class, IPublishedContent { - return content.Children().FirstOrDefault(); + return content.Children(culture).FirstOrDefault(); } - public static T FirstChild(this IPublishedContent content, Func predicate) + public static T FirstChild(this IPublishedContent content, Func predicate, string culture = null) where T : class, IPublishedContent { - return content.Children().FirstOrDefault(predicate); + return content.Children(culture).FirstOrDefault(predicate); } /// @@ -1117,9 +1134,9 @@ namespace Umbraco.Web /// A service context. /// An optional content type alias. /// The children of the content. - public static DataTable ChildrenAsTable(this IPublishedContent content, ServiceContext services, string contentTypeAliasFilter = "") + public static DataTable ChildrenAsTable(this IPublishedContent content, ServiceContext services, string contentTypeAliasFilter = "", string culture = null) { - return GenerateDataTable(content, services, contentTypeAliasFilter); + return GenerateDataTable(content, services, contentTypeAliasFilter, culture); } /// @@ -1129,13 +1146,13 @@ namespace Umbraco.Web /// A service context. /// An optional content type alias. /// The children of the content. - private static DataTable GenerateDataTable(IPublishedContent content, ServiceContext services, string contentTypeAliasFilter = "") + private static DataTable GenerateDataTable(IPublishedContent content, ServiceContext services, string contentTypeAliasFilter = "", string culture = null) { var firstNode = contentTypeAliasFilter.IsNullOrWhiteSpace() - ? content.Children.Any() - ? content.Children.ElementAt(0) + ? content.Children(culture).Any() + ? content.Children(culture).ElementAt(0) : null - : content.Children.FirstOrDefault(x => x.ContentType.Alias == contentTypeAliasFilter); + : content.Children(culture).FirstOrDefault(x => x.ContentType.Alias == contentTypeAliasFilter); if (firstNode == null) return new DataTable(); //no children found From 20d6a3b4b496dfd61ca2e10b35faa5daa46d6eb3 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 16 Jan 2019 01:02:21 +1100 Subject: [PATCH 362/469] some cleanup and ensure the package file is deleted after install --- src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs | 2 +- src/Umbraco.Web/Editors/PackageInstallController.cs | 4 +--- src/Umbraco.Web/Models/PackageInstallModel.cs | 5 ----- 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs b/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs index 4695ccb673..3dee5686ff 100644 --- a/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs +++ b/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs @@ -50,7 +50,7 @@ namespace Umbraco.Core.Packaging Url = package.Element("url")?.Value, IconUrl = package.Element("iconUrl")?.Value, UmbracoVersion = new Version((int)requirements.Element("major"), (int)requirements.Element("minor"), (int)requirements.Element("patch")), - UmbracoVersionRequirementsType = requirements.AttributeValue("type").IsNullOrWhiteSpace() ? RequirementsType.Legacy : Enum.Parse(requirements.AttributeValue("type")), + UmbracoVersionRequirementsType = requirements.AttributeValue("type").IsNullOrWhiteSpace() ? RequirementsType.Legacy : Enum.Parse(requirements.AttributeValue("type"), true), Control = package.Element("control")?.Value, Actions = xml.Root.Element("Actions")?.ToString(SaveOptions.None) ?? "", //take the entire outer xml value Files = xml.Root.Element("files")?.Elements("file")?.Select(CompiledPackageFile.Create).ToList() ?? new List(), diff --git a/src/Umbraco.Web/Editors/PackageInstallController.cs b/src/Umbraco.Web/Editors/PackageInstallController.cs index 38b75a27f8..2dfb5e12e4 100644 --- a/src/Umbraco.Web/Editors/PackageInstallController.cs +++ b/src/Umbraco.Web/Editors/PackageInstallController.cs @@ -287,7 +287,6 @@ namespace Umbraco.Web.Editors var model = new LocalPackageInstallModel { PackageGuid = Guid.Parse(packageGuid), - //RepositoryGuid = Guid.Parse("65194810-1f85-11dd-bd0b-0800200c9a66"), ZipFileName = fileName }; @@ -415,7 +414,7 @@ namespace Umbraco.Web.Editors var clientDependencyUpdated = clientDependencyConfig.UpdateVersionNumber( UmbracoVersion.SemanticVersion, DateTime.UtcNow, "yyyyMMdd"); - //fixme: when do we delete the zip file? + zipFile.Delete(); var redirectUrl = ""; if (packageInfo.Control.IsNullOrWhiteSpace() == false) @@ -431,7 +430,6 @@ namespace Umbraco.Web.Editors Id = model.Id, ZipFileName = model.ZipFileName, PackageGuid = model.PackageGuid, - //RepositoryGuid = model.RepositoryGuid, PostInstallationPath = redirectUrl }; diff --git a/src/Umbraco.Web/Models/PackageInstallModel.cs b/src/Umbraco.Web/Models/PackageInstallModel.cs index 2decaeb098..1ec7ddd434 100644 --- a/src/Umbraco.Web/Models/PackageInstallModel.cs +++ b/src/Umbraco.Web/Models/PackageInstallModel.cs @@ -15,11 +15,6 @@ namespace Umbraco.Web.Models [DataMember(Name = "packageGuid")] public Guid PackageGuid { get; set; } - ////TODO: Do we need this? - //[DataMember(Name = "repositoryGuid")] - //public Guid RepositoryGuid { get; set; } - - [DataMember(Name = "zipFileName")] public string ZipFileName { get; set; } From 5995a7ec843e5ca50d36a98eb4f7fd0de03e4cb4 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Tue, 15 Jan 2019 15:05:04 +0100 Subject: [PATCH 363/469] a small change to let Git see changes --- src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs b/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs index 9ec970f1fe..51935e6517 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs @@ -123,6 +123,7 @@ namespace Umbraco.Core.Migrations.Upgrade To("{64EBCE53-E1F0-463A-B40B-E98EFCCA8AE2}"); To("{0009109C-A0B8-4F3F-8FEB-C137BBDDA268}"); + //FINAL From 2e782a4f114c44184f5076a07fbe3c94b5104524 Mon Sep 17 00:00:00 2001 From: Robert Date: Tue, 15 Jan 2019 15:10:50 +0100 Subject: [PATCH 364/469] Mapping IsContainer into AdditionalData using IEntitySlim to EntityBasic mapper --- src/Umbraco.Web/Editors/EntityController.cs | 2 +- src/Umbraco.Web/Models/Mapping/EntityMapperProfile.cs | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web/Editors/EntityController.cs b/src/Umbraco.Web/Editors/EntityController.cs index 993489855f..500b25ab2e 100644 --- a/src/Umbraco.Web/Editors/EntityController.cs +++ b/src/Umbraco.Web/Editors/EntityController.cs @@ -769,7 +769,7 @@ namespace Umbraco.Web.Editors { throw new HttpResponseException(HttpStatusCode.NotFound); } - return Mapper.Map(found); + return Mapper.Map(found); } //now we need to convert the unknown ones switch (entityType) diff --git a/src/Umbraco.Web/Models/Mapping/EntityMapperProfile.cs b/src/Umbraco.Web/Models/Mapping/EntityMapperProfile.cs index 178027857c..ff7fcfc0b0 100644 --- a/src/Umbraco.Web/Models/Mapping/EntityMapperProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/EntityMapperProfile.cs @@ -16,7 +16,7 @@ namespace Umbraco.Web.Models.Mapping { internal class EntityMapperProfile : Profile { - private static string GetContentTypeIcon(EntitySlim entity) + private static string GetContentTypeIcon(IEntitySlim entity) => entity is ContentEntitySlim contentEntity ? contentEntity.ContentTypeIcon : null; public EntityMapperProfile() @@ -24,7 +24,7 @@ namespace Umbraco.Web.Models.Mapping // create, capture, cache var contentTypeUdiResolver = new ContentTypeUdiResolver(); - CreateMap() + CreateMap() .ForMember(dest => dest.Name, opt => opt.ResolveUsing()) .ForMember(dest => dest.Udi, opt => opt.MapFrom(src => Udi.Create(ObjectTypes.GetUdiType(src.NodeObjectType), src.Key))) .ForMember(dest => dest.Icon, opt => opt.MapFrom(src => GetContentTypeIcon(src))) @@ -36,6 +36,8 @@ namespace Umbraco.Web.Models.Mapping { dest.Icon = "icon-user"; } + + dest.AdditionalData.Add("IsContainer", src.IsContainer); }); CreateMap() @@ -186,9 +188,9 @@ namespace Umbraco.Web.Models.Mapping /// /// Resolves the name for a content item/content variant /// - private class NameResolver : IValueResolver + private class NameResolver : IValueResolver { - public string Resolve(EntitySlim source, EntityBasic destination, string destMember, ResolutionContext context) + public string Resolve(IEntitySlim source, EntityBasic destination, string destMember, ResolutionContext context) { if (!(source is DocumentEntitySlim doc)) return source.Name; From 11ffafacdf42a461b793df8a3e32fda1c88b6a4f Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Tue, 15 Jan 2019 15:12:59 +0100 Subject: [PATCH 365/469] Revert "Revert "Identify element types"" This reverts commit ff6a9ba9 --- .../Migrations/Upgrade/UmbracoPlan.cs | 1 + .../V_8_0_0/AddContentTypeIsElementColumn.cs | 15 ++++++++++ src/Umbraco.Core/Models/ContentTypeBase.cs | 10 +++++++ .../Models/ContentTypeBaseExtensions.cs | 3 +- src/Umbraco.Core/Models/IContentTypeBase.cs | 12 +++++++- .../PublishedContent/PublishedItemType.cs | 7 ++++- .../Persistence/Dtos/ContentTypeDto.cs | 4 +++ .../Factories/ContentTypeFactory.cs | 2 ++ .../Persistence/Mappers/ContentTypeMapper.cs | 1 + .../Persistence/Mappers/MediaTypeMapper.cs | 1 + .../Persistence/Mappers/MemberTypeMapper.cs | 1 + .../Implement/ContentTypeRepositoryBase.cs | 6 ++-- .../Services/EntityXmlSerializer.cs | 3 +- .../Services/Implement/PackagingService.cs | 4 +++ src/Umbraco.Core/Umbraco.Core.csproj | 1 + .../PublishedContent/PublishedContentTests.cs | 1 - .../Services/ContentTypeServiceTests.cs | 30 +++++++++++++++++++ .../ContentEditing/ContentItemDisplay.cs | 8 ++++- .../Models/Mapping/ContentMapperProfile.cs | 5 ++-- 19 files changed, 105 insertions(+), 10 deletions(-) create mode 100644 src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/AddContentTypeIsElementColumn.cs diff --git a/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs b/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs index b469c02a3c..9ec970f1fe 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs @@ -121,6 +121,7 @@ namespace Umbraco.Core.Migrations.Upgrade To("{648A2D5F-7467-48F8-B309-E99CEEE00E2A}"); // fixed version To("{C39BF2A7-1454-4047-BBFE-89E40F66ED63}"); To("{64EBCE53-E1F0-463A-B40B-E98EFCCA8AE2}"); + To("{0009109C-A0B8-4F3F-8FEB-C137BBDDA268}"); //FINAL diff --git a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/AddContentTypeIsElementColumn.cs b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/AddContentTypeIsElementColumn.cs new file mode 100644 index 0000000000..1df11a3e99 --- /dev/null +++ b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/AddContentTypeIsElementColumn.cs @@ -0,0 +1,15 @@ +using Umbraco.Core.Persistence.Dtos; + +namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0 +{ + public class AddContentTypeIsElementColumn : MigrationBase + { + public AddContentTypeIsElementColumn(IMigrationContext context) : base(context) + { } + + public override void Migrate() + { + AddColumn("isElement"); + } + } +} diff --git a/src/Umbraco.Core/Models/ContentTypeBase.cs b/src/Umbraco.Core/Models/ContentTypeBase.cs index 88b1179f6d..b6ea9f50a0 100644 --- a/src/Umbraco.Core/Models/ContentTypeBase.cs +++ b/src/Umbraco.Core/Models/ContentTypeBase.cs @@ -26,6 +26,7 @@ namespace Umbraco.Core.Models private string _thumbnail = "folder.png"; private bool _allowedAsRoot; // note: only one that's not 'pure element type' private bool _isContainer; + private bool _isElement; private PropertyGroupCollection _propertyGroups; private PropertyTypeCollection _noGroupPropertyTypes; private IEnumerable _allowedContentTypes; @@ -90,6 +91,7 @@ namespace Umbraco.Core.Models public readonly PropertyInfo IconSelector = ExpressionHelper.GetPropertyInfo(x => x.Icon); public readonly PropertyInfo ThumbnailSelector = ExpressionHelper.GetPropertyInfo(x => x.Thumbnail); public readonly PropertyInfo AllowedAsRootSelector = ExpressionHelper.GetPropertyInfo(x => x.AllowedAsRoot); + public readonly PropertyInfo IsElementSelector = ExpressionHelper.GetPropertyInfo(x => x.IsElement); public readonly PropertyInfo IsContainerSelector = ExpressionHelper.GetPropertyInfo(x => x.IsContainer); public readonly PropertyInfo AllowedContentTypesSelector = ExpressionHelper.GetPropertyInfo>(x => x.AllowedContentTypes); public readonly PropertyInfo PropertyGroupsSelector = ExpressionHelper.GetPropertyInfo(x => x.PropertyGroups); @@ -180,6 +182,14 @@ namespace Umbraco.Core.Models set => SetPropertyValueAndDetectChanges(value, ref _isContainer, Ps.Value.IsContainerSelector); } + /// + [DataMember] + public bool IsElement + { + get => _isElement; + set => SetPropertyValueAndDetectChanges(value, ref _isElement, Ps.Value.IsElementSelector); + } + /// /// Gets or sets a list of integer Ids for allowed ContentTypes /// diff --git a/src/Umbraco.Core/Models/ContentTypeBaseExtensions.cs b/src/Umbraco.Core/Models/ContentTypeBaseExtensions.cs index 8af48bb881..adbc3de54f 100644 --- a/src/Umbraco.Core/Models/ContentTypeBaseExtensions.cs +++ b/src/Umbraco.Core/Models/ContentTypeBaseExtensions.cs @@ -15,7 +15,8 @@ namespace Umbraco.Core.Models { var type = contentType.GetType(); var itemType = PublishedItemType.Unknown; - if (typeof(IContentType).IsAssignableFrom(type)) itemType = PublishedItemType.Content; + if (contentType.IsElement) itemType = PublishedItemType.Element; + else if (typeof(IContentType).IsAssignableFrom(type)) itemType = PublishedItemType.Content; else if (typeof(IMediaType).IsAssignableFrom(type)) itemType = PublishedItemType.Media; else if (typeof(IMemberType).IsAssignableFrom(type)) itemType = PublishedItemType.Member; return itemType; diff --git a/src/Umbraco.Core/Models/IContentTypeBase.cs b/src/Umbraco.Core/Models/IContentTypeBase.cs index a1d4aee02f..787e347b37 100644 --- a/src/Umbraco.Core/Models/IContentTypeBase.cs +++ b/src/Umbraco.Core/Models/IContentTypeBase.cs @@ -25,7 +25,7 @@ namespace Umbraco.Core.Models /// the icon (eg. icon-home) along with an optional CSS class name representing the /// color (eg. icon-blue). Put together, the value for this scenario would be /// icon-home color-blue. - /// + /// /// If a class name for the color isn't specified, the icon color will default to black. /// string Icon { get; set; } @@ -48,6 +48,16 @@ namespace Umbraco.Core.Models /// bool IsContainer { get; set; } + /// + /// Gets or sets a value indicating whether this content type is for an element. + /// + /// + /// By default a content type is for a true media, member or document, but + /// it can also be for an element, ie a subset that can for instance be used in + /// nested content. + /// + bool IsElement { get; set; } + /// /// Gets or sets the content variation of the content type. /// diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedItemType.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedItemType.cs index e55fe66945..42e9c9538d 100644 --- a/src/Umbraco.Core/Models/PublishedContent/PublishedItemType.cs +++ b/src/Umbraco.Core/Models/PublishedContent/PublishedItemType.cs @@ -4,13 +4,18 @@ /// The type of published element. /// /// Can be a simple element, or a document, a media, a member. - public enum PublishedItemType // fixme - need to rename to PublishedElementType but then conflicts? + public enum PublishedItemType { /// /// Unknown. /// Unknown = 0, + /// + /// An element. + /// + Element, + /// /// A document. /// diff --git a/src/Umbraco.Core/Persistence/Dtos/ContentTypeDto.cs b/src/Umbraco.Core/Persistence/Dtos/ContentTypeDto.cs index d930abc54c..4f3a67aa91 100644 --- a/src/Umbraco.Core/Persistence/Dtos/ContentTypeDto.cs +++ b/src/Umbraco.Core/Persistence/Dtos/ContentTypeDto.cs @@ -41,6 +41,10 @@ namespace Umbraco.Core.Persistence.Dtos [Constraint(Default = "0")] public bool IsContainer { get; set; } + [Column("isElement")] + [Constraint(Default = "0")] + public bool IsElement { get; set; } + [Column("allowAtRoot")] [Constraint(Default = "0")] public bool AllowAtRoot { get; set; } diff --git a/src/Umbraco.Core/Persistence/Factories/ContentTypeFactory.cs b/src/Umbraco.Core/Persistence/Factories/ContentTypeFactory.cs index 38a1aa2aab..7a04a6d0d9 100644 --- a/src/Umbraco.Core/Persistence/Factories/ContentTypeFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/ContentTypeFactory.cs @@ -107,6 +107,7 @@ namespace Umbraco.Core.Persistence.Factories entity.CreatorId = dto.NodeDto.UserId ?? Constants.Security.UnknownUserId; entity.AllowedAsRoot = dto.AllowAtRoot; entity.IsContainer = dto.IsContainer; + entity.IsElement = dto.IsElement; entity.Trashed = dto.NodeDto.Trashed; entity.Variations = (ContentVariation) dto.Variations; } @@ -132,6 +133,7 @@ namespace Umbraco.Core.Persistence.Factories NodeId = entity.Id, AllowAtRoot = entity.AllowedAsRoot, IsContainer = entity.IsContainer, + IsElement = entity.IsElement, Variations = (byte) entity.Variations, NodeDto = BuildNodeDto(entity, nodeObjectType) }; diff --git a/src/Umbraco.Core/Persistence/Mappers/ContentTypeMapper.cs b/src/Umbraco.Core/Persistence/Mappers/ContentTypeMapper.cs index c692a75474..a24963bace 100644 --- a/src/Umbraco.Core/Persistence/Mappers/ContentTypeMapper.cs +++ b/src/Umbraco.Core/Persistence/Mappers/ContentTypeMapper.cs @@ -35,6 +35,7 @@ namespace Umbraco.Core.Persistence.Mappers CacheMap(src => src.Description, dto => dto.Description); CacheMap(src => src.Icon, dto => dto.Icon); CacheMap(src => src.IsContainer, dto => dto.IsContainer); + CacheMap(src => src.IsElement, dto => dto.IsElement); CacheMap(src => src.Thumbnail, dto => dto.Thumbnail); } } diff --git a/src/Umbraco.Core/Persistence/Mappers/MediaTypeMapper.cs b/src/Umbraco.Core/Persistence/Mappers/MediaTypeMapper.cs index 3f5a6e24bc..6cf83bc7aa 100644 --- a/src/Umbraco.Core/Persistence/Mappers/MediaTypeMapper.cs +++ b/src/Umbraco.Core/Persistence/Mappers/MediaTypeMapper.cs @@ -35,6 +35,7 @@ namespace Umbraco.Core.Persistence.Mappers CacheMap(src => src.Description, dto => dto.Description); CacheMap(src => src.Icon, dto => dto.Icon); CacheMap(src => src.IsContainer, dto => dto.IsContainer); + CacheMap(src => src.IsElement, dto => dto.IsElement); CacheMap(src => src.Thumbnail, dto => dto.Thumbnail); } } diff --git a/src/Umbraco.Core/Persistence/Mappers/MemberTypeMapper.cs b/src/Umbraco.Core/Persistence/Mappers/MemberTypeMapper.cs index 28dc19171f..9a4e4ec040 100644 --- a/src/Umbraco.Core/Persistence/Mappers/MemberTypeMapper.cs +++ b/src/Umbraco.Core/Persistence/Mappers/MemberTypeMapper.cs @@ -35,6 +35,7 @@ namespace Umbraco.Core.Persistence.Mappers CacheMap(src => src.Description, dto => dto.Description); CacheMap(src => src.Icon, dto => dto.Icon); CacheMap(src => src.IsContainer, dto => dto.IsContainer); + CacheMap(src => src.IsElement, dto => dto.IsElement); CacheMap(src => src.Thumbnail, dto => dto.Thumbnail); } } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs index 662254d1ee..683df047f8 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs @@ -1283,7 +1283,7 @@ AND umbracoNode.id <> @id", if (db == null) throw new ArgumentNullException(nameof(db)); var sql = @"SELECT cmsContentType.pk as ctPk, cmsContentType.alias as ctAlias, cmsContentType.allowAtRoot as ctAllowAtRoot, cmsContentType.description as ctDesc, cmsContentType.variations as ctVariations, - cmsContentType.icon as ctIcon, cmsContentType.isContainer as ctIsContainer, cmsContentType.nodeId as ctId, cmsContentType.thumbnail as ctThumb, + cmsContentType.icon as ctIcon, cmsContentType.isContainer as ctIsContainer, cmsContentType.IsElement as ctIsElement, cmsContentType.nodeId as ctId, cmsContentType.thumbnail as ctThumb, AllowedTypes.AllowedId as ctaAllowedId, AllowedTypes.SortOrder as ctaSortOrder, AllowedTypes.alias as ctaAlias, ParentTypes.parentContentTypeId as chtParentId, ParentTypes.parentContentTypeKey as chtParentKey, umbracoNode.createDate as nCreateDate, umbracoNode." + sqlSyntax.GetQuotedColumnName("level") + @" as nLevel, umbracoNode.nodeObjectType as nObjectType, umbracoNode.nodeUser as nUser, @@ -1384,6 +1384,7 @@ AND umbracoNode.id <> @id", Description = currCt.ctDesc, Icon = currCt.ctIcon, IsContainer = currCt.ctIsContainer, + IsElement = currCt.ctIsElement, NodeId = currCt.ctId, PrimaryKey = currCt.ctPk, Thumbnail = currCt.ctThumb, @@ -1422,7 +1423,7 @@ AND umbracoNode.id <> @id", var sql = @"SELECT cmsDocumentType.IsDefault as dtIsDefault, cmsDocumentType.templateNodeId as dtTemplateId, cmsContentType.pk as ctPk, cmsContentType.alias as ctAlias, cmsContentType.allowAtRoot as ctAllowAtRoot, cmsContentType.description as ctDesc, cmsContentType.variations as ctVariations, - cmsContentType.icon as ctIcon, cmsContentType.isContainer as ctIsContainer, cmsContentType.nodeId as ctId, cmsContentType.thumbnail as ctThumb, + cmsContentType.icon as ctIcon, cmsContentType.isContainer as ctIsContainer, cmsContentType.IsElement as ctIsElement, cmsContentType.nodeId as ctId, cmsContentType.thumbnail as ctThumb, AllowedTypes.AllowedId as ctaAllowedId, AllowedTypes.SortOrder as ctaSortOrder, AllowedTypes.alias as ctaAlias, ParentTypes.parentContentTypeId as chtParentId,ParentTypes.parentContentTypeKey as chtParentKey, umbracoNode.createDate as nCreateDate, umbracoNode." + sqlSyntax.GetQuotedColumnName("level") + @" as nLevel, umbracoNode.nodeObjectType as nObjectType, umbracoNode.nodeUser as nUser, @@ -1559,6 +1560,7 @@ AND umbracoNode.id <> @id", Description = currCt.ctDesc, Icon = currCt.ctIcon, IsContainer = currCt.ctIsContainer, + IsElement = currCt.ctIsElement, NodeId = currCt.ctId, PrimaryKey = currCt.ctPk, Thumbnail = currCt.ctThumb, diff --git a/src/Umbraco.Core/Services/EntityXmlSerializer.cs b/src/Umbraco.Core/Services/EntityXmlSerializer.cs index d938e032a8..38d5471bb7 100644 --- a/src/Umbraco.Core/Services/EntityXmlSerializer.cs +++ b/src/Umbraco.Core/Services/EntityXmlSerializer.cs @@ -337,7 +337,8 @@ namespace Umbraco.Core.Services new XElement("Thumbnail", contentType.Thumbnail), new XElement("Description", contentType.Description), new XElement("AllowAtRoot", contentType.AllowedAsRoot.ToString()), - new XElement("IsListView", contentType.IsContainer.ToString())); + new XElement("IsListView", contentType.IsContainer.ToString()), + new XElement("IsElement", contentType.IsElement.ToString())); var masterContentType = contentType.ContentTypeComposition.FirstOrDefault(x => x.Id == contentType.ParentId); if(masterContentType != null) diff --git a/src/Umbraco.Core/Services/Implement/PackagingService.cs b/src/Umbraco.Core/Services/Implement/PackagingService.cs index 106d2b9f12..8f6c287cf1 100644 --- a/src/Umbraco.Core/Services/Implement/PackagingService.cs +++ b/src/Umbraco.Core/Services/Implement/PackagingService.cs @@ -578,6 +578,10 @@ namespace Umbraco.Core.Services.Implement if (isListView != null) contentType.IsContainer = isListView.Value.InvariantEquals("true"); + var isElement = infoElement.Element("IsElement"); + if (isListView != null) + contentType.IsElement = isElement.Value.InvariantEquals("true"); + //Name of the master corresponds to the parent and we need to ensure that the Parent Id is set var masterElement = infoElement.Element("Master"); if (masterElement != null) diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 609befd233..7d65a46f49 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -377,6 +377,7 @@ + diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs index 914956dce1..ab65ac82b1 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs @@ -233,7 +233,6 @@ namespace Umbraco.Tests.PublishedContent } [Test] - [Ignore("Fails as long as PublishedContentModel is internal.")] // fixme public void Is_Last_From_Where_Filter2() { var doc = GetNode(1173); diff --git a/src/Umbraco.Tests/Services/ContentTypeServiceTests.cs b/src/Umbraco.Tests/Services/ContentTypeServiceTests.cs index b1a8fa26a8..8dc8a2b45c 100644 --- a/src/Umbraco.Tests/Services/ContentTypeServiceTests.cs +++ b/src/Umbraco.Tests/Services/ContentTypeServiceTests.cs @@ -22,6 +22,36 @@ namespace Umbraco.Tests.Services [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest, PublishedRepositoryEvents = true)] public class ContentTypeServiceTests : TestWithSomeContentBase { + [Test] + public void CanSaveAndGetIsElement() + { + //create content type with a property type that varies by culture + IContentType contentType = MockedContentTypes.CreateBasicContentType(); + contentType.Variations = ContentVariation.Nothing; + var contentCollection = new PropertyTypeCollection(true); + contentCollection.Add(new PropertyType("test", ValueStorageType.Ntext) + { + Alias = "title", + Name = "Title", + Description = "", + Mandatory = false, + SortOrder = 1, + DataTypeId = -88, + Variations = ContentVariation.Nothing + }); + contentType.PropertyGroups.Add(new PropertyGroup(contentCollection) { Name = "Content", SortOrder = 1 }); + ServiceContext.ContentTypeService.Save(contentType); + + contentType = ServiceContext.ContentTypeService.Get(contentType.Id); + Assert.IsFalse(contentType.IsElement); + + contentType.IsElement = true; + ServiceContext.ContentTypeService.Save(contentType); + + contentType = ServiceContext.ContentTypeService.Get(contentType.Id); + Assert.IsTrue(contentType.IsElement); + } + [Test] public void Change_Content_Type_Variation_Clears_Redirects() { diff --git a/src/Umbraco.Web/Models/ContentEditing/ContentItemDisplay.cs b/src/Umbraco.Web/Models/ContentEditing/ContentItemDisplay.cs index 4908025351..80358bfc7a 100644 --- a/src/Umbraco.Web/Models/ContentEditing/ContentItemDisplay.cs +++ b/src/Umbraco.Web/Models/ContentEditing/ContentItemDisplay.cs @@ -86,6 +86,12 @@ namespace Umbraco.Web.Models.ContentEditing [DataMember(Name = "isContainer")] public bool IsContainer { get; set; } + /// + /// Indicates if the content is configured as an element + /// + [DataMember(Name = "isElement")] + public bool IsElement { get; set; } + /// /// Property indicating if this item is part of a list view parent /// @@ -117,7 +123,7 @@ namespace Umbraco.Web.Models.ContentEditing /// [DataMember(Name = "updateDate")] public DateTime UpdateDate { get; set; } - + [DataMember(Name = "template")] public string TemplateAlias { get; set; } diff --git a/src/Umbraco.Web/Models/Mapping/ContentMapperProfile.cs b/src/Umbraco.Web/Models/Mapping/ContentMapperProfile.cs index 6de3bdc02c..1caf81a1eb 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentMapperProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentMapperProfile.cs @@ -46,6 +46,7 @@ namespace Umbraco.Web.Models.Mapping .ForMember(dest => dest.ContentTypeAlias, opt => opt.MapFrom(src => src.ContentType.Alias)) .ForMember(dest => dest.ContentTypeName, opt => opt.MapFrom(src => src.ContentType.Name)) .ForMember(dest => dest.IsContainer, opt => opt.MapFrom(src => src.ContentType.IsContainer)) + .ForMember(dest => dest.IsElement, opt => opt.MapFrom(src => src.ContentType.IsElement)) .ForMember(dest => dest.IsBlueprint, opt => opt.MapFrom(src => src.Blueprint)) .ForMember(dest => dest.IsChildOfListView, opt => opt.ResolveUsing(childOfListViewResolver)) .ForMember(dest => dest.Trashed, opt => opt.MapFrom(src => src.Trashed)) @@ -59,7 +60,7 @@ namespace Umbraco.Web.Models.Mapping .ForMember(dest => dest.AllowedTemplates, opt => opt.MapFrom(content => content.ContentType.AllowedTemplates .Where(t => t.Alias.IsNullOrWhiteSpace() == false && t.Name.IsNullOrWhiteSpace() == false) - .ToDictionary(t => t.Alias, t => t.Name))) + .ToDictionary(t => t.Alias, t => t.Name))) .ForMember(dest => dest.AllowedActions, opt => opt.ResolveUsing(src => actionButtonsResolver.Resolve(src))) .ForMember(dest => dest.AdditionalData, opt => opt.Ignore()); @@ -140,5 +141,5 @@ namespace Umbraco.Web.Models.Mapping return source.CultureInfos.TryGetValue(culture, out var name) && !name.Name.IsNullOrWhiteSpace() ? name.Name : $"(({source.Name}))"; } } - } + } } From 0b9705ca3f44b73bb3cc7e9d2386a979abe9a5da Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Tue, 15 Jan 2019 15:13:10 +0100 Subject: [PATCH 366/469] Revert "Revert "Support IContentType.IsElement"" This reverts commit a5efc25c --- .../services/umbdataformatter.service.js | 18 +++++++-------- .../permissions/permissions.controller.js | 22 +++++++------------ .../views/permissions/permissions.html | 20 +++++++++++++++-- src/Umbraco.Web.UI/Umbraco/config/lang/en.xml | 2 ++ .../Umbraco/config/lang/en_us.xml | 2 ++ .../ContentTypeCompositionDisplay.cs | 4 ++++ .../Models/ContentEditing/ContentTypeSave.cs | 3 +++ 7 files changed, 46 insertions(+), 25 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/umbdataformatter.service.js b/src/Umbraco.Web.UI.Client/src/common/services/umbdataformatter.service.js index e31742e660..1e6fc5d643 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/umbdataformatter.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/umbdataformatter.service.js @@ -64,7 +64,7 @@ var saveModel = _.pick(displayModel, 'compositeContentTypes', 'isContainer', 'allowAsRoot', 'allowedTemplates', 'allowedContentTypes', 'alias', 'description', 'thumbnail', 'name', 'id', 'icon', 'trashed', - 'key', 'parentId', 'alias', 'path', 'allowCultureVariant'); + 'key', 'parentId', 'alias', 'path', 'allowCultureVariant', 'isElement'); //TODO: Map these saveModel.allowedTemplates = _.map(displayModel.allowedTemplates, function (t) { return t.alias; }); @@ -262,7 +262,7 @@ saveModel[props[m]] = startId.id; } - saveModel.parentId = -1; + saveModel.parentId = -1; return saveModel; }, @@ -293,7 +293,7 @@ }); saveModel.email = propEmail.value.trim(); saveModel.username = propLogin.value.trim(); - + saveModel.password = this.formatChangePasswordModel(propPass.value); var selectedGroups = []; @@ -336,7 +336,7 @@ /** formats the display model used to display the media to the model used to save the media */ formatMediaPostData: function (displayModel, action) { - //NOTE: the display model inherits from the save model so we can in theory just post up the display model but + //NOTE: the display model inherits from the save model so we can in theory just post up the display model but // we don't want to post all of the data as it is unecessary. var saveModel = { id: displayModel.id, @@ -354,7 +354,7 @@ /** formats the display model used to display the content to the model used to save the content */ formatContentPostData: function (displayModel, action) { - //NOTE: the display model inherits from the save model so we can in theory just post up the display model but + //NOTE: the display model inherits from the save model so we can in theory just post up the display model but // we don't want to post all of the data as it is unecessary. var saveModel = { id: displayModel.id, @@ -379,7 +379,7 @@ var propExpireDate = displayModel.removeDate; var propReleaseDate = displayModel.releaseDate; var propTemplate = displayModel.template; - + saveModel.expireDate = propExpireDate ? propExpireDate : null; saveModel.releaseDate = propReleaseDate ? propReleaseDate : null; saveModel.templateAlias = propTemplate ? propTemplate : null; @@ -389,8 +389,8 @@ /** * This formats the server GET response for a content display item - * @param {} displayModel - * @returns {} + * @param {} displayModel + * @returns {} */ formatContentGetData: function(displayModel) { @@ -418,7 +418,7 @@ } }); }); - + //now assign this same invariant property instance to the same index of the other variants property array for (var j = 1; j < displayModel.variants.length; j++) { diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.controller.js b/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.controller.js index 4a7a870618..317fe094ae 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.controller.js @@ -25,6 +25,7 @@ vm.removeChild = removeChild; vm.toggleAllowAsRoot = toggleAllowAsRoot; vm.toggleAllowCultureVariants = toggleAllowCultureVariants; + vm.toggleIsElement = toggleIsElement; /* ---------- INIT ---------- */ @@ -84,25 +85,18 @@ $scope.model.allowedContentTypes.splice(selectedChildIndex, 1); } - /** - * Toggle the $scope.model.allowAsRoot value to either true or false - */ - function toggleAllowAsRoot(){ - if($scope.model.allowAsRoot){ - $scope.model.allowAsRoot = false; - return; - } + // note: "safe toggling" here ie handling cases where the value is undefined, etc - $scope.model.allowAsRoot = true; + function toggleAllowAsRoot() { + $scope.model.allowAsRoot = $scope.model.allowAsRoot ? false : true; } function toggleAllowCultureVariants() { - if ($scope.model.allowCultureVariant) { - $scope.model.allowCultureVariant = false; - return; - } + $scope.model.allowCultureVariant = $scope.model.allowCultureVariant ? false : true; + } - $scope.model.allowCultureVariant = true; + function toggleIsElement() { + $scope.model.isElement = $scope.model.isElement ? false : true; } } diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.html b/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.html index ec1e528f8c..0d74c655d7 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.html +++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.html @@ -53,9 +53,25 @@ hotkey="alt+shift+v"> - + - +
    + +
    +
    + +
    + +
    + + +
    + +
    + + diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml index 386d3af518..987203442a 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml @@ -1518,6 +1518,8 @@ To manage your website, simply open the Umbraco back office and start adding con Allow varying by culture Allow editors to create content of this type in different languages Allow varying by culture + Is an Element type + An Element type is meant to be used for instance in Nested Content, and not in the tree Building models diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml index 5de373f571..1860d3afc9 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml @@ -1559,6 +1559,8 @@ To manage your website, simply open the Umbraco back office and start adding con Allow varying by culture Allow editors to create content of this type in different languages Allow varying by culture + Is an Element type + An Element type is meant to be used for instance in Nested Content, and not in the tree Add language diff --git a/src/Umbraco.Web/Models/ContentEditing/ContentTypeCompositionDisplay.cs b/src/Umbraco.Web/Models/ContentEditing/ContentTypeCompositionDisplay.cs index 7211ddbf61..e5e74c2749 100644 --- a/src/Umbraco.Web/Models/ContentEditing/ContentTypeCompositionDisplay.cs +++ b/src/Umbraco.Web/Models/ContentEditing/ContentTypeCompositionDisplay.cs @@ -26,6 +26,10 @@ namespace Umbraco.Web.Models.ContentEditing [DataMember(Name = "isContainer")] public bool IsContainer { get; set; } + //Element + [DataMember(Name = "isElement")] + public bool IsElement { get; set; } + [DataMember(Name = "listViewEditorName")] [ReadOnly(true)] public string ListViewEditorName { get; set; } diff --git a/src/Umbraco.Web/Models/ContentEditing/ContentTypeSave.cs b/src/Umbraco.Web/Models/ContentEditing/ContentTypeSave.cs index c2ec70d3dc..b1d24c5fd2 100644 --- a/src/Umbraco.Web/Models/ContentEditing/ContentTypeSave.cs +++ b/src/Umbraco.Web/Models/ContentEditing/ContentTypeSave.cs @@ -25,6 +25,9 @@ namespace Umbraco.Web.Models.ContentEditing [DataMember(Name = "isContainer")] public bool IsContainer { get; set; } + [DataMember(Name = "isElement")] + public bool IsElement { get; set; } + [DataMember(Name = "allowAsRoot")] public bool AllowAsRoot { get; set; } From f9cd22d908ddfbfb09dd8ef0b6d033b1f32f18d1 Mon Sep 17 00:00:00 2001 From: Robert Date: Tue, 15 Jan 2019 15:43:10 +0100 Subject: [PATCH 367/469] Added a comment explaining why we need the delay --- .../src/common/services/editor.service.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js b/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js index c495c4e7a1..721efe251c 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js @@ -245,7 +245,9 @@ When building a custom infinite editor view you can use the same components as a // emit event to let components know an editor has been removed eventsService.emit("appState.editors.close", args); - + + // delay required to map the properties to the correct editor due + // to another delay in the closing animation of the editor $timeout(function() { // rebind keyboard shortcuts for the new editor in focus rebindKeyboardShortcuts(); From b7c15dc393d43a40a33670b836033411ea0e0f72 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 16 Jan 2019 01:53:08 +1100 Subject: [PATCH 368/469] gets readme and our package install working --- .../src/common/resources/package.resource.js | 2 +- .../views/packages/views/repo.controller.js | 162 ++++++++++-------- src/Umbraco.Web/Editors/PackageController.cs | 41 ++++- .../Editors/PackageInstallController.cs | 36 +--- .../ContentEditing/InstalledPackageModel.cs | 3 + 5 files changed, 135 insertions(+), 109 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/package.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/package.resource.js index ce2a557390..0d74d0fdd3 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/package.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/package.resource.js @@ -19,7 +19,7 @@ function packageResource($q, $http, umbDataFormatter, umbRequestHelper) { return umbRequestHelper.resourcePromise( $http.get( umbRequestHelper.getApiUrl( - "packageInstallApiBaseUrl", + "packageApiBaseUrl", "GetInstalled")), 'Failed to get installed packages'); }, diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/views/repo.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/views/repo.controller.js index 395800d329..b77326d2fc 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/views/repo.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/views/repo.controller.js @@ -32,6 +32,8 @@ vm.search = search; vm.installCompleted = false; + var labels = {}; + var currSort = "Latest"; //used to cancel any request in progress if another one needs to take it's place var canceler = null; @@ -52,22 +54,38 @@ vm.loading = true; + var labelKeys = [ + "packager_installStateImporting", + "packager_installStateInstalling", + "packager_installStateRestarting", + "packager_installStateComplete", + "packager_installStateCompleted" + ]; + + localizationService.localizeMany(labelKeys).then(function (values) { + labels.installStateImporting = values[0]; + labels.installStateInstalling = values[1]; + labels.installStateRestarting = values[2]; + labels.installStateComplete = values[3]; + labels.installStateCompleted = values[4]; + }); + $q.all([ - ourPackageRepositoryResource.getCategories() - .then(function(cats) { + ourPackageRepositoryResource.getCategories() + .then(function (cats) { vm.categories = cats; }), - ourPackageRepositoryResource.getPopular(8) - .then(function(pack) { + ourPackageRepositoryResource.getPopular(8) + .then(function (pack) { vm.popular = pack.packages; }), - ourPackageRepositoryResource.search(vm.pagination.pageNumber - 1, vm.pagination.pageSize, currSort) - .then(function(pack) { + ourPackageRepositoryResource.search(vm.pagination.pageNumber - 1, vm.pagination.pageSize, currSort) + .then(function (pack) { vm.packages = pack.packages; vm.pagination.totalPages = Math.ceil(pack.total / vm.pagination.pageSize); }) - ]) - .then(function() { + ]) + .then(function () { vm.loading = false; }); @@ -94,18 +112,18 @@ currSort = "Latest"; $q.all([ - ourPackageRepositoryResource.getPopular(8, searchCategory) - .then(function(pack) { + ourPackageRepositoryResource.getPopular(8, searchCategory) + .then(function (pack) { vm.popular = pack.packages; }), - ourPackageRepositoryResource.search(vm.pagination.pageNumber - 1, vm.pagination.pageSize, currSort, searchCategory, vm.searchQuery) - .then(function(pack) { + ourPackageRepositoryResource.search(vm.pagination.pageNumber - 1, vm.pagination.pageSize, currSort, searchCategory, vm.searchQuery) + .then(function (pack) { vm.packages = pack.packages; vm.pagination.totalPages = Math.ceil(pack.total / vm.pagination.pageSize); vm.pagination.pageNumber = 1; }) - ]) - .then(function() { + ]) + .then(function () { vm.loading = false; selectedCategory.active = reset === false; }); @@ -115,12 +133,12 @@ ourPackageRepositoryResource.getDetails(selectedPackage.id) .then(function (pack) { packageResource.validateInstalled(pack.name, pack.latestVersion) - .then(function() { + .then(function () { //ok, can install vm.package = pack; vm.package.isValid = true; vm.packageViewState = "packageDetails"; - }, function() { + }, function () { //nope, cannot install vm.package = pack; vm.package.isValid = false; @@ -130,7 +148,7 @@ } function setPackageViewState(state) { - if(state) { + if (state) { vm.packageViewState = state; } } @@ -164,13 +182,13 @@ packageResource .fetch(selectedPackage.id) - .then(function(pack) { - vm.packageViewState = "packageInstall"; - vm.loading = false; - vm.localPackage = pack; - vm.localPackage.allowed = true; + .then(function (pack) { + vm.packageViewState = "packageInstall"; + vm.loading = false; + vm.localPackage = pack; + vm.localPackage.allowed = true; }, function (evt, status, headers, config) { - + if (status == 400) { //it's a validation error vm.installState.type = "error"; @@ -186,68 +204,68 @@ function installPackage(selectedPackage) { - vm.installState.status = localizationService.localize("packager_installStateImporting"); + vm.installState.status = labels.installStateImporting; vm.installState.progress = "0"; packageResource .import(selectedPackage) - .then(function(pack) { - vm.installState.status = localizationService.localize("packager_installStateInstalling"); - vm.installState.progress = "25"; - return packageResource.installFiles(pack); - }, + .then(function (pack) { + vm.installState.status = labels.installStateInstalling; + vm.installState.progress = "25"; + return packageResource.installFiles(pack); + }, error) - .then(function(pack) { - vm.installState.status = localizationService.localize("packager_installStateRestarting"); - vm.installState.progress = "50"; - var deferred = $q.defer(); + .then(function (pack) { + vm.installState.status = labels.installStateRestarting; + vm.installState.progress = "50"; + var deferred = $q.defer(); - //check if the app domain is restarted ever 2 seconds - var count = 0; - function checkRestart() { - $timeout(function () { + //check if the app domain is restarted ever 2 seconds + var count = 0; + function checkRestart() { + $timeout(function () { packageResource.checkRestart(pack).then(function (d) { count++; //if there is an id it means it's not restarted yet but we'll limit it to only check 10 times if (d.isRestarting && count < 10) { - checkRestart(); + checkRestart(); } else { - //it's restarted! - deferred.resolve(d); + //it's restarted! + deferred.resolve(d); } - }, - error); - }, 2000); - } + }, + error); + }, 2000); + } - checkRestart(); - - return deferred.promise; - }, error) + checkRestart(); + + return deferred.promise; + }, error) .then(function (pack) { - vm.installState.status = localizationService.localize("packager_installStateRestarting"); - vm.installState.progress = "75"; - return packageResource.installData(pack); - }, + vm.installState.status = labels.installStateInstalling; + vm.installState.progress = "75"; + return packageResource.installData(pack); + }, error) - .then(function(pack) { - vm.installState.status = localizationService.localize("packager_installStateComplete"); - vm.installState.progress = "100"; - return packageResource.cleanUp(pack); - }, + .then(function (pack) { + vm.installState.status = labels.installStateComplete; + vm.installState.progress = "100"; + return packageResource.cleanUp(pack); + }, error) - .then(function(result) { + .then(function (result) { - if (result.postInstallationPath) { - //Put the redirect Uri in a cookie so we can use after reloading - localStorageService.set("packageInstallUri", result.postInstallationPath); - } + if (result.postInstallationPath) { + //Put the redirect Uri in a cookie so we can use after reloading + localStorageService.set("packageInstallUri", result.postInstallationPath); + } - vm.installState.status = localizationService.localize("packager_installStateCompleted"); - vm.installCompleted = true; + vm.installState.status = labels.installStateCompleted; + vm.installCompleted = true; - }, + }, error); } @@ -265,7 +283,7 @@ } - var searchDebounced = _.debounce(function(e) { + var searchDebounced = _.debounce(function (e) { $scope.$apply(function () { @@ -281,12 +299,12 @@ currSort = vm.searchQuery ? "Default" : "Latest"; ourPackageRepositoryResource.search(vm.pagination.pageNumber - 1, - vm.pagination.pageSize, - currSort, - "", - vm.searchQuery, - canceler) - .then(function(pack) { + vm.pagination.pageSize, + currSort, + "", + vm.searchQuery, + canceler) + .then(function (pack) { vm.packages = pack.packages; vm.pagination.totalPages = Math.ceil(pack.total / vm.pagination.pageSize); vm.pagination.pageNumber = 1; diff --git a/src/Umbraco.Web/Editors/PackageController.cs b/src/Umbraco.Web/Editors/PackageController.cs index 063dcf483e..2d1d124a2c 100644 --- a/src/Umbraco.Web/Editors/PackageController.cs +++ b/src/Umbraco.Web/Editors/PackageController.cs @@ -1,11 +1,14 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.IO; +using System.Linq; using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Web.Http; using Umbraco.Core.IO; using Umbraco.Core.Models.Packaging; +using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Mvc; using Umbraco.Web.WebApi; using Umbraco.Web.WebApi.Filters; @@ -111,5 +114,41 @@ namespace Umbraco.Web.Editors return response; } + /// + /// Returns all installed packages - only shows their latest versions + /// + /// + public IEnumerable GetInstalled() + { + return Services.PackagingService.GetAllInstalledPackages() + .GroupBy( + //group by name + x => x.Name, + //select the package with a parsed version + pck => Version.TryParse(pck.Version, out var pckVersion) + ? new { package = pck, version = pckVersion } + : new { package = pck, version = new Version(0, 0, 0) }) + .Select(grouping => + { + //get the max version for the package + var maxVersion = grouping.Max(x => x.version); + //only return the first package with this version + return grouping.First(x => x.version == maxVersion).package; + }) + .Select(pack => new InstalledPackageModel + { + Name = pack.Name, + Id = pack.Id, + Author = pack.Author, + Version = pack.Version, + Url = pack.Url, + License = pack.License, + LicenseUrl = pack.LicenseUrl, + Files = pack.Files, + IconUrl = pack.IconUrl, + Readme = pack.Readme + }) + .ToList(); + } } } diff --git a/src/Umbraco.Web/Editors/PackageInstallController.cs b/src/Umbraco.Web/Editors/PackageInstallController.cs index 2dfb5e12e4..bc6db1b552 100644 --- a/src/Umbraco.Web/Editors/PackageInstallController.cs +++ b/src/Umbraco.Web/Editors/PackageInstallController.cs @@ -92,41 +92,7 @@ namespace Umbraco.Web.Editors return Ok(); } - /// - /// Returns all installed packages - only shows their latest versions - /// - /// - public IEnumerable GetInstalled() - { - return Services.PackagingService.GetAllInstalledPackages() - .GroupBy( - //group by name - x => x.Name, - //select the package with a parsed version - pck => Version.TryParse(pck.Version, out var pckVersion) - ? new { package = pck, version = pckVersion } - : new { package = pck, version = new Version(0, 0, 0) }) - .Select(grouping => - { - //get the max version for the package - var maxVersion = grouping.Max(x => x.version); - //only return the first package with this version - return grouping.First(x => x.version == maxVersion).package; - }) - .Select(pack => new InstalledPackageModel - { - Name = pack.Name, - Id = pack.Id, - Author = pack.Author, - Version = pack.Version, - Url = pack.Url, - License = pack.License, - LicenseUrl = pack.LicenseUrl, - Files = pack.Files, - IconUrl = pack.IconUrl - }) - .ToList(); - } + private void PopulateFromPackageData(LocalPackageInstallModel model) { diff --git a/src/Umbraco.Web/Models/ContentEditing/InstalledPackageModel.cs b/src/Umbraco.Web/Models/ContentEditing/InstalledPackageModel.cs index 9161f972bd..67bfe6fe53 100644 --- a/src/Umbraco.Web/Models/ContentEditing/InstalledPackageModel.cs +++ b/src/Umbraco.Web/Models/ContentEditing/InstalledPackageModel.cs @@ -32,5 +32,8 @@ namespace Umbraco.Web.Models.ContentEditing [DataMember(Name = "iconUrl")] public string IconUrl { get; set; } + + [DataMember(Name = "readme")] + public string Readme { get; set; } } } From d97b100bab5ff66b2bc0f99a7ceaf89a8e2c22ce Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 16 Jan 2019 02:18:02 +1100 Subject: [PATCH 369/469] fixes merge --- src/Umbraco.Core/Packaging/PackageDataInstallation.cs | 4 ++++ src/Umbraco.Core/Services/Implement/PackagingService.cs | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Core/Packaging/PackageDataInstallation.cs b/src/Umbraco.Core/Packaging/PackageDataInstallation.cs index 2212a8957d..36066b104f 100644 --- a/src/Umbraco.Core/Packaging/PackageDataInstallation.cs +++ b/src/Umbraco.Core/Packaging/PackageDataInstallation.cs @@ -556,6 +556,10 @@ namespace Umbraco.Core.Packaging if (isListView != null) contentType.IsContainer = isListView.Value.InvariantEquals("true"); + var isElement = infoElement.Element("IsElement"); + if (isElement != null) + contentType.IsElement = isElement.Value.InvariantEquals("true"); + //Name of the master corresponds to the parent and we need to ensure that the Parent Id is set var masterElement = infoElement.Element("Master"); if (masterElement != null) diff --git a/src/Umbraco.Core/Services/Implement/PackagingService.cs b/src/Umbraco.Core/Services/Implement/PackagingService.cs index 55608e605e..a5c279fa21 100644 --- a/src/Umbraco.Core/Services/Implement/PackagingService.cs +++ b/src/Umbraco.Core/Services/Implement/PackagingService.cs @@ -43,10 +43,6 @@ namespace Umbraco.Core.Services.Implement ICreatedPackagesRepository createdPackages, IInstalledPackagesRepository installedPackages, IPackageInstallation packageInstallation) - var isElement = infoElement.Element("IsElement"); - if (isListView != null) - contentType.IsElement = isElement.Value.InvariantEquals("true"); - { _auditService = auditService; _createdPackages = createdPackages; From 00e951c3949b015c06ce3d6576734fcffb9d7dde Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 16 Jan 2019 02:35:21 +1100 Subject: [PATCH 370/469] fixes installer with async --- .../Install/Controllers/InstallApiController.cs | 15 ++++++++------- .../Install/Models/InstallSetupStep.cs | 4 +--- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/Umbraco.Web/Install/Controllers/InstallApiController.cs b/src/Umbraco.Web/Install/Controllers/InstallApiController.cs index a63484fb39..c8e862abcb 100644 --- a/src/Umbraco.Web/Install/Controllers/InstallApiController.cs +++ b/src/Umbraco.Web/Install/Controllers/InstallApiController.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using System.Threading.Tasks; using System.Web.Http; using Newtonsoft.Json.Linq; using Umbraco.Core; @@ -75,7 +76,7 @@ namespace Umbraco.Web.Install.Controllers /// /// Installs. /// - public InstallProgressResultModel PostPerformInstall(InstallInstructions installModel) + public async Task PostPerformInstall(InstallInstructions installModel) { if (installModel == null) throw new ArgumentNullException(nameof(installModel)); @@ -94,8 +95,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; - installModel.Instructions.TryGetValue(item.Name, out instruction); // else null + installModel.Instructions.TryGetValue(item.Name, out var instruction); // else null // if this step doesn't require execution then continue to the next one, this is just a fail-safe check. if (StepRequiresExecution(step, instruction) == false) @@ -107,7 +107,7 @@ namespace Umbraco.Web.Install.Controllers try { - var setupData = ExecuteStep(step, instruction); + var setupData = await ExecuteStepAsync(step, instruction); // update the status InstallStatusTracker.SetComplete(installModel.InstallId, step.Name, setupData?.SavedStepData); @@ -222,7 +222,7 @@ namespace Umbraco.Web.Install.Controllers } // executes the step - internal InstallSetupResult ExecuteStep(InstallSetupStep step, JToken instruction) + internal async Task ExecuteStepAsync(InstallSetupStep step, JToken instruction) { using (_proflog.TraceDuration($"Executing installation step: '{step.Name}'.", "Step completed")) { @@ -232,8 +232,9 @@ namespace Umbraco.Web.Install.Controllers var typedStepType = genericStepType.MakeGenericType(typeArgs); try { - var method = typedStepType.GetMethods().Single(x => x.Name == "Execute"); - return (InstallSetupResult) method.Invoke(step, new[] { model }); + var method = typedStepType.GetMethods().Single(x => x.Name == "ExecuteAsync"); + var task = (Task) method.Invoke(step, new[] { model }); + return await task; } catch (Exception ex) { diff --git a/src/Umbraco.Web/Install/Models/InstallSetupStep.cs b/src/Umbraco.Web/Install/Models/InstallSetupStep.cs index 3b017368f9..fd50d7855c 100644 --- a/src/Umbraco.Web/Install/Models/InstallSetupStep.cs +++ b/src/Umbraco.Web/Install/Models/InstallSetupStep.cs @@ -82,8 +82,6 @@ namespace Umbraco.Web.Install.Models ///
    [IgnoreDataMember] public abstract Type StepType { get; } - - [IgnoreDataMember] - public bool HasUIElement => View.IsNullOrWhiteSpace() == false; + } } From 1bd5127bcf6d05b2f38a0c0121ae1e399c6ae63c Mon Sep 17 00:00:00 2001 From: Stephan Date: Tue, 15 Jan 2019 17:27:18 +0100 Subject: [PATCH 371/469] Actually run HealthCheck notifier --- src/Umbraco.Web/Scheduling/SchedulerComponent.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web/Scheduling/SchedulerComponent.cs b/src/Umbraco.Web/Scheduling/SchedulerComponent.cs index e4bc74b7f2..cd4f5ac933 100644 --- a/src/Umbraco.Web/Scheduling/SchedulerComponent.cs +++ b/src/Umbraco.Web/Scheduling/SchedulerComponent.cs @@ -149,6 +149,7 @@ namespace Umbraco.Web.Scheduling var periodInMilliseconds = healthCheckConfig.NotificationSettings.PeriodInHours * 60 * 60 * 1000; var task = new HealthCheckNotifier(_healthCheckRunner, delayInMilliseconds, periodInMilliseconds, healthChecks, notifications, _runtime, logger); + _healthCheckRunner.TryAdd(task); return task; } From 477075662163857ba32cea0a4989f1ab9438f7f4 Mon Sep 17 00:00:00 2001 From: Stephan Date: Tue, 15 Jan 2019 18:41:02 +0100 Subject: [PATCH 372/469] Bugfix ContentCacheRefresher --- src/Umbraco.Web/Cache/ContentCacheRefresher.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web/Cache/ContentCacheRefresher.cs b/src/Umbraco.Web/Cache/ContentCacheRefresher.cs index 22f1554269..b0192e9e75 100644 --- a/src/Umbraco.Web/Cache/ContentCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/ContentCacheRefresher.cs @@ -44,16 +44,14 @@ namespace Umbraco.Web.Cache public override void Refresh(JsonPayload[] payloads) { - var runtimeCache = Current.ApplicationCache.RuntimeCache; - - runtimeCache.ClearCacheObjectTypes(); + CacheHelper.RuntimeCache.ClearCacheObjectTypes(); var idsRemoved = new HashSet(); + var isolatedCache = CacheHelper.IsolatedRuntimeCache.GetOrCreateCache(); foreach (var payload in payloads) { - // remove that one - runtimeCache.ClearCacheItem(RepositoryCacheKeys.GetKey(payload.Id)); + isolatedCache.ClearCacheItem(RepositoryCacheKeys.GetKey(payload.Id)); _idkMap.ClearCache(payload.Id); @@ -61,7 +59,7 @@ namespace Umbraco.Web.Cache if (payload.ChangeTypes.HasTypesAny(TreeChangeTypes.RefreshBranch | TreeChangeTypes.Remove)) { var pathid = "," + payload.Id + ","; - runtimeCache.ClearCacheObjectTypes((k, v) => v.Path.Contains(pathid)); + isolatedCache.ClearCacheObjectTypes((k, v) => v.Path.Contains(pathid)); } //if the item is being completely removed, we need to refresh the domains cache if any domain was assigned to the content From eb3d3e129c8a96583155239a85efacd1b825199f Mon Sep 17 00:00:00 2001 From: Stephan Date: Tue, 15 Jan 2019 19:15:06 +0100 Subject: [PATCH 373/469] Bugfix package service --- src/Umbraco.Core/Services/Implement/PackagingService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Core/Services/Implement/PackagingService.cs b/src/Umbraco.Core/Services/Implement/PackagingService.cs index 8f6c287cf1..99ee7a098b 100644 --- a/src/Umbraco.Core/Services/Implement/PackagingService.cs +++ b/src/Umbraco.Core/Services/Implement/PackagingService.cs @@ -579,7 +579,7 @@ namespace Umbraco.Core.Services.Implement contentType.IsContainer = isListView.Value.InvariantEquals("true"); var isElement = infoElement.Element("IsElement"); - if (isListView != null) + if (isElement != null) contentType.IsElement = isElement.Value.InvariantEquals("true"); //Name of the master corresponds to the parent and we need to ensure that the Parent Id is set From d4edbc8e791a9d944c737e0882b973672787147a Mon Sep 17 00:00:00 2001 From: Stephan Date: Tue, 15 Jan 2019 19:38:52 +0100 Subject: [PATCH 374/469] Fix tests --- .../PublishedContent/PublishedContentTests.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs index ab65ac82b1..603464e18b 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs @@ -69,8 +69,9 @@ namespace Umbraco.Tests.PublishedContent factory.CreatePropertyType("testRecursive", 1), }; var compositionAliases = new[] { "MyCompositionAlias" }; - var type = new AutoPublishedContentType(0, "anything", compositionAliases, propertyTypes); - ContentTypesCache.GetPublishedContentTypeByAlias = alias => type; + var anythingType = new AutoPublishedContentType(0, "anything", compositionAliases, propertyTypes); + var homeType = new AutoPublishedContentType(0, "home", compositionAliases, propertyTypes); + ContentTypesCache.GetPublishedContentTypeByAlias = alias => alias.InvariantEquals("home") ? homeType : anythingType; } protected override TypeLoader CreateTypeLoader(IRuntimeCacheProvider runtimeCache, IGlobalSettings globalSettings, IProfilingLogger logger) @@ -236,6 +237,7 @@ namespace Umbraco.Tests.PublishedContent public void Is_Last_From_Where_Filter2() { var doc = GetNode(1173); + var ct = doc.ContentType; var items = doc.Children .Select(x => x.CreateModel()) // linq, returns IEnumerable @@ -454,11 +456,11 @@ namespace Umbraco.Tests.PublishedContent { var doc = GetNode(1046); // has child nodes - var model = doc.FirstChild(x => true); // predicate + var model = doc.FirstChild(x => true); // predicate Assert.IsNotNull(model); Assert.IsTrue(model.Id == 1173); - Assert.IsInstanceOf(model); + Assert.IsInstanceOf(model); Assert.IsInstanceOf(model); doc = GetNode(1175); // does not have child nodes From 90be93d94842b84ed86358e0d812fdd50e0afc66 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 16 Jan 2019 16:27:51 +1100 Subject: [PATCH 375/469] Got upgrade status showing in the ui, started implementing merging the package definitions for upgrades but have decided to have an element for each install like we currenlty have in case there are problems installing. --- .../Models/Packaging/PackageDefinition.cs | 33 ++++++++ .../Packaging/CompiledPackageXmlParser.cs | 2 +- .../Packaging/PackageInstallType.cs | 9 ++ .../Services/IPackagingService.cs | 19 +++++ .../Services/Implement/PackagingService.cs | 81 ++++++++++++++++++ src/Umbraco.Core/Umbraco.Core.csproj | 1 + .../mocks/services/localization.mocks.js | 1 - .../views/packages/views/install-local.html | 31 ++++--- src/Umbraco.Web.UI/Umbraco/config/lang/cs.xml | 1 - src/Umbraco.Web.UI/Umbraco/config/lang/da.xml | 1 - src/Umbraco.Web.UI/Umbraco/config/lang/de.xml | 1 - src/Umbraco.Web.UI/Umbraco/config/lang/en.xml | 1 - .../Umbraco/config/lang/en_us.xml | 2 +- src/Umbraco.Web.UI/Umbraco/config/lang/fr.xml | 1 - src/Umbraco.Web.UI/Umbraco/config/lang/ja.xml | 1 - src/Umbraco.Web.UI/Umbraco/config/lang/nb.xml | 1 - src/Umbraco.Web.UI/Umbraco/config/lang/nl.xml | 1 - src/Umbraco.Web.UI/Umbraco/config/lang/pl.xml | 1 - src/Umbraco.Web.UI/Umbraco/config/lang/ru.xml | 1 - src/Umbraco.Web.UI/Umbraco/config/lang/sv.xml | 1 - src/Umbraco.Web.UI/Umbraco/config/lang/tr.xml | 1 - src/Umbraco.Web.UI/Umbraco/config/lang/zh.xml | 1 - .../Umbraco/config/lang/zh_tw.xml | 1 - src/Umbraco.Web.UI/umbraco/config/lang/nb.xml | 1 - .../umbraco/config/lang/zh_tw.xml | 1 - .../Editors/PackageInstallController.cs | 82 ++++++++++--------- .../Models/LocalPackageInstallModel.cs | 6 ++ src/Umbraco.Web/Models/PackageInstallModel.cs | 1 + 28 files changed, 212 insertions(+), 72 deletions(-) create mode 100644 src/Umbraco.Core/Packaging/PackageInstallType.cs diff --git a/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs b/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs index bab52c63f6..c068c57b08 100644 --- a/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs +++ b/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs @@ -128,5 +128,38 @@ namespace Umbraco.Core.Models.Packaging [DataMember(Name = "iconUrl")] public string IconUrl { get; set; } = string.Empty; + public PackageDefinition Clone() + { + return new PackageDefinition + { + Id = Id, + PackagePath = PackagePath, + Name = Name, + Files = new List(Files), + UmbracoVersion = (Version) UmbracoVersion.Clone(), + Version = Version, + Url = Url, + Readme = Readme, + AuthorUrl = AuthorUrl, + Author = Author, + LicenseUrl = LicenseUrl, + Actions = Actions, + PackageId = PackageId, + Control = Control, + DataTypes = new List(DataTypes), + IconUrl = IconUrl, + License = License, + Templates = new List(Templates), + Languages = new List(Languages), + Macros = new List(Macros), + Stylesheets = new List(Stylesheets), + DocumentTypes = new List(DocumentTypes), + DictionaryItems = new List(DictionaryItems), + ContentNodeId = ContentNodeId, + ContentLoadChildNodes = ContentLoadChildNodes + }; + } + } + } diff --git a/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs b/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs index 3dee5686ff..0d533cfbc2 100644 --- a/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs +++ b/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs @@ -149,7 +149,7 @@ namespace Umbraco.Core.Packaging /// /// /// - public IEnumerable GetPackageActions(XElement actionsElement, string packageName) + public static IEnumerable GetPackageActions(XElement actionsElement, string packageName) { if (actionsElement == null) return Enumerable.Empty(); diff --git a/src/Umbraco.Core/Packaging/PackageInstallType.cs b/src/Umbraco.Core/Packaging/PackageInstallType.cs new file mode 100644 index 0000000000..015b994aec --- /dev/null +++ b/src/Umbraco.Core/Packaging/PackageInstallType.cs @@ -0,0 +1,9 @@ +namespace Umbraco.Core.Packaging +{ + public enum PackageInstallType + { + AlreadyInstalled, + NewInstall, + Upgrade + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Services/IPackagingService.cs b/src/Umbraco.Core/Services/IPackagingService.cs index a31fc2d6cf..7d4d70196d 100644 --- a/src/Umbraco.Core/Services/IPackagingService.cs +++ b/src/Umbraco.Core/Services/IPackagingService.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Threading.Tasks; using System.Xml.Linq; +using Semver; using Umbraco.Core.Models; using Umbraco.Core.Models.Packaging; using Umbraco.Core.Packaging; @@ -44,8 +45,26 @@ namespace Umbraco.Core.Services IEnumerable GetAllInstalledPackages(); PackageDefinition GetInstalledPackageById(int id); + PackageDefinition GetInstalledPackageByName(string name); + + /// + /// Returns a for a given package name and version + /// + /// + /// + /// If the package is an upgrade, the original/current PackageDefinition is returned + /// + PackageInstallType GetPackageInstallType(string packageName, SemVersion packageVersion, out PackageDefinition alreadyInstalled); void DeleteInstalledPackage(int packageId, int userId = 0); + /// + /// Merges the package definition information from the upgrade on to the original and returns the merged definition + /// + /// + /// + /// + PackageDefinition MergePackageDefinition(PackageDefinition original, PackageDefinition upgrade); + /// /// Persists a package definition to storage /// diff --git a/src/Umbraco.Core/Services/Implement/PackagingService.cs b/src/Umbraco.Core/Services/Implement/PackagingService.cs index a5c279fa21..1da53c5e11 100644 --- a/src/Umbraco.Core/Services/Implement/PackagingService.cs +++ b/src/Umbraco.Core/Services/Implement/PackagingService.cs @@ -7,6 +7,7 @@ using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Web; using System.Xml.Linq; +using Semver; using Umbraco.Core.Collections; using Umbraco.Core.Events; using Umbraco.Core.Exceptions; @@ -180,6 +181,86 @@ namespace Umbraco.Core.Services.Implement public PackageDefinition GetInstalledPackageById(int id) => _installedPackages.GetById(id); + public PackageDefinition GetInstalledPackageByName(string name) + { + var found = _installedPackages.GetAll().FirstOrDefault(x => x.Name.InvariantEquals(name)); + return found; + } + + public PackageInstallType GetPackageInstallType(string packageName, SemVersion packageVersion, out PackageDefinition alreadyInstalled) + { + if (packageName == null) throw new ArgumentNullException(nameof(packageName)); + if (packageVersion == null) throw new ArgumentNullException(nameof(packageVersion)); + + alreadyInstalled = GetInstalledPackageByName(packageName); + if (alreadyInstalled == null) return PackageInstallType.NewInstall; + + if (!SemVersion.TryParse(alreadyInstalled.Version, out var installedVersion)) + throw new InvalidOperationException("Could not parse the currently installed package version " + alreadyInstalled.Version); + + //compare versions + if (installedVersion >= packageVersion) return PackageInstallType.AlreadyInstalled; + + //it's an upgrade + return PackageInstallType.Upgrade; + } + + public PackageDefinition MergePackageDefinition(PackageDefinition original, PackageDefinition upgrade) + { + if (!SemVersion.TryParse(original.Version, out var originalVersion)) + throw new InvalidOperationException("Could not parse the original version"); + if(!SemVersion.TryParse(upgrade.Version, out var upgradeVersion)) + throw new InvalidOperationException("Could not parse the upgrade version"); + if (originalVersion >= upgradeVersion) + throw new InvalidOperationException("The upgrade version must be higher than the original version"); + if (!original.Name.InvariantEquals(upgrade.Name)) + throw new InvalidOperationException("Cannot merge the package definitions, the package name doesn't match"); + + var result = original.Clone(); + + result.PackagePath = upgrade.PackagePath; + result.PackageId = upgrade.PackageId; + + result.UmbracoVersion = upgrade.UmbracoVersion; + result.Version = upgrade.Version; + result.Url = upgrade.Url; + result.Readme = upgrade.Readme; + result.AuthorUrl = upgrade.AuthorUrl; + result.Author = upgrade.Author; + result.LicenseUrl = upgrade.LicenseUrl; + result.PackageId = upgrade.PackageId; + result.Control = upgrade.Control; + result.IconUrl = upgrade.IconUrl; + result.License = upgrade.License; + result.ContentNodeId = upgrade.ContentNodeId; + result.ContentLoadChildNodes = upgrade.ContentLoadChildNodes; + + result.Files = original.Files.Concat(upgrade.Files).Distinct(StringComparer.InvariantCultureIgnoreCase).ToList(); + result.DataTypes = original.DataTypes.Concat(upgrade.DataTypes).Distinct(StringComparer.InvariantCultureIgnoreCase).ToList(); + result.Templates = original.Templates.Concat(upgrade.Templates).Distinct(StringComparer.InvariantCultureIgnoreCase).ToList(); + result.Languages = original.Languages.Concat(upgrade.Languages).Distinct(StringComparer.InvariantCultureIgnoreCase).ToList(); + result.Macros = original.Macros.Concat(upgrade.Macros).Distinct(StringComparer.InvariantCultureIgnoreCase).ToList(); + result.Stylesheets = original.Stylesheets.Concat(upgrade.Stylesheets).Distinct(StringComparer.InvariantCultureIgnoreCase).ToList(); + result.DocumentTypes = original.DocumentTypes.Concat(upgrade.DocumentTypes).Distinct(StringComparer.InvariantCultureIgnoreCase).ToList(); + result.DictionaryItems = original.DictionaryItems.Concat(upgrade.DictionaryItems).Distinct(StringComparer.InvariantCultureIgnoreCase).ToList(); + + var originalActions = CompiledPackageXmlParser.GetPackageActions(XElement.Parse(result.Actions), result.Name); + var upgradeActions = CompiledPackageXmlParser.GetPackageActions(XElement.Parse(upgrade.Actions), result.Name).ToList(); + var upgradeActionsLookup = upgradeActions.ToLookup(x => x.Alias, x => x.XmlData.ToString()); + + foreach (var originalAction in originalActions) + { + var upgradeActionsWithAlias = upgradeActionsLookup[originalAction.Alias]; + + //check if the original action does not exist already in our upgrade actions + if(upgradeActionsWithAlias.All(upgradeActionXml => upgradeActionXml != originalAction.XmlData.ToString())) + upgradeActions.Add(originalAction); + } + result.Actions = new XElement("actions", upgradeActions.Select(x => x.XmlData)).ToString(); + + return result; + } + public bool SaveInstalledPackage(PackageDefinition definition) => _installedPackages.SavePackage(definition); public void DeleteInstalledPackage(int packageId, int userId = 0) diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 251ecd00c1..b385e63d0c 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -458,6 +458,7 @@ + diff --git a/src/Umbraco.Web.UI.Client/src/common/mocks/services/localization.mocks.js b/src/Umbraco.Web.UI.Client/src/common/mocks/services/localization.mocks.js index b6c87027b1..ec1175ab6c 100644 --- a/src/Umbraco.Web.UI.Client/src/common/mocks/services/localization.mocks.js +++ b/src/Umbraco.Web.UI.Client/src/common/mocks/services/localization.mocks.js @@ -473,7 +473,6 @@ angular.module('umbraco.mocks'). "packager_packageUpgradeInstructions": "Upgrade instructions", "packager_packageUpgradeText": " There's an upgrade available for this package. You can download it directly from the Umbraco package repository.", "packager_packageVersion": "Package version", - "packager_packageVersionHistory": "Package version history", "packager_viewPackageWebsite": "View package website", "paste_doNothing": "Paste with full formatting (Not recommended)", "paste_errorMessage": "The text you're trying to paste contains special characters or formatting. This could be caused by copying text from Microsoft Word. Umbraco can remove special characters or formatting automatically, so the pasted content will be more suitable for the web.", diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/views/install-local.html b/src/Umbraco.Web.UI.Client/src/views/packages/views/install-local.html index 5e3ef6ad1c..b657c42877 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/views/install-local.html +++ b/src/Umbraco.Web.UI.Client/src/views/packages/views/install-local.html @@ -118,6 +118,14 @@
    Version {{ vm.localPackage.version }} +

    + + + Upgrading from version + {{ vm.localPackage.originalVersion }} + + +

    @@ -136,21 +144,19 @@ I accept terms of use - +
    - +
    @@ -165,9 +171,8 @@
    - +
    [DataMember(Name = "isRestarting")] public bool IsRestarting { get; set; } + } } From 94da9a66816734292471f7b600ff4d348e2954eb Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 16 Jan 2019 17:25:46 +1100 Subject: [PATCH 376/469] Gets package upgrading working along with package uninstallation with multiple versions --- .../Events/UninstallPackageEventArgs.cs | 11 +- .../Packaging/IPackageInstallation.cs | 2 +- .../Packaging/PackageDataInstallation.cs | 39 +++--- .../Packaging/PackageInstallation.cs | 5 +- .../Packaging/PackagesRepository.cs | 5 - .../Services/IPackagingService.cs | 32 +++-- .../Services/Implement/PackagingService.cs | 111 +++++++----------- .../src/views/packages/edit.html | 14 +-- src/Umbraco.Web/Editors/PackageController.cs | 5 +- .../Editors/PackageInstallController.cs | 17 +-- 10 files changed, 110 insertions(+), 131 deletions(-) diff --git a/src/Umbraco.Core/Events/UninstallPackageEventArgs.cs b/src/Umbraco.Core/Events/UninstallPackageEventArgs.cs index 2618d04e17..63c5ceaba0 100644 --- a/src/Umbraco.Core/Events/UninstallPackageEventArgs.cs +++ b/src/Umbraco.Core/Events/UninstallPackageEventArgs.cs @@ -3,16 +3,13 @@ using Umbraco.Core.Models.Packaging; namespace Umbraco.Core.Events { - public class UninstallPackageEventArgs : CancellableObjectEventArgs> + public class UninstallPackageEventArgs: CancellableObjectEventArgs> { - public UninstallPackageEventArgs(TEntity eventObject, IPackageInfo packageMetaData, bool canCancel) - : base(new[] { eventObject }, canCancel) + public UninstallPackageEventArgs(IEnumerable eventObject, bool canCancel) + : base(eventObject, canCancel) { - PackageMetaData = packageMetaData; } - public IPackageInfo PackageMetaData { get; } - - public IEnumerable UninstallationSummary => EventObject; + public IEnumerable UninstallationSummary => EventObject; } } diff --git a/src/Umbraco.Core/Packaging/IPackageInstallation.cs b/src/Umbraco.Core/Packaging/IPackageInstallation.cs index 5dae76674d..c85a4ccd5f 100644 --- a/src/Umbraco.Core/Packaging/IPackageInstallation.cs +++ b/src/Umbraco.Core/Packaging/IPackageInstallation.cs @@ -8,7 +8,7 @@ namespace Umbraco.Core.Packaging public interface IPackageInstallation { /// - /// Uninstalls a package including all data, entities and files + /// This will run the uninstallation sequence for this /// /// /// diff --git a/src/Umbraco.Core/Packaging/PackageDataInstallation.cs b/src/Umbraco.Core/Packaging/PackageDataInstallation.cs index 36066b104f..2e9fee9595 100644 --- a/src/Umbraco.Core/Packaging/PackageDataInstallation.cs +++ b/src/Umbraco.Core/Packaging/PackageDataInstallation.cs @@ -228,14 +228,17 @@ namespace Umbraco.Core.Packaging } var content = CreateContentFromXml(root, importedContentTypes[contentTypeAlias], null, parentId); + if (content == null) continue; + contents.Add(content); var children = (from child in root.Elements() where (string)child.Attribute("isDoc") == "" select child) .ToList(); - if (children.Any()) - contents.AddRange(CreateContentFromXml(children, content, importedContentTypes)); + + if (children.Count > 0) + contents.AddRange(CreateContentFromXml(children, content, importedContentTypes).WhereNotNull()); } return contents; } @@ -258,7 +261,7 @@ namespace Umbraco.Core.Packaging list.Add(content); //Recursive call - XElement child1 = child; + var child1 = child; var grandChildren = (from grand in child1.Elements() where (string)grand.Attribute("isDoc") == "" select grand).ToList(); @@ -272,37 +275,43 @@ namespace Umbraco.Core.Packaging private IContent CreateContentFromXml(XElement element, IContentType contentType, IContent parent, int parentId) { + var key = Guid.Empty; + if (element.Attribute("key") != null && Guid.TryParse(element.Attribute("key").Value, out key)) + { + //if a Key is supplied, then we need to check if the content already exists and if so we ignore the installation for this item + if (_contentService.GetById(key) != null) + return null; + } + var id = element.Attribute("id").Value; var level = element.Attribute("level").Value; var sortOrder = element.Attribute("sortOrder").Value; var nodeName = element.Attribute("nodeName").Value; var path = element.Attribute("path").Value; - //TODO: Shouldn't we be using this value??? - var template = element.Attribute("template").Value; - var key = Guid.Empty; - + var templateId = element.AttributeValue("template"); + var properties = from property in element.Elements() where property.Attribute("isDoc") == null select property; + var template = templateId.HasValue ? _fileService.GetTemplate(templateId.Value) : null; + IContent content = parent == null ? new Content(nodeName, parentId, contentType) { Level = int.Parse(level), - SortOrder = int.Parse(sortOrder) + SortOrder = int.Parse(sortOrder), + TemplateId = template?.Id, + Key = key } : new Content(nodeName, parent, contentType) { Level = int.Parse(level), - SortOrder = int.Parse(sortOrder) + SortOrder = int.Parse(sortOrder), + TemplateId = template?.Id, + Key = key }; - if (element.Attribute("key") != null && Guid.TryParse(element.Attribute("key").Value, out key)) - { - // update the Guid (for UDI support) - content.Key = key; - } - foreach (var property in properties) { string propertyTypeAlias = property.Name.LocalName; diff --git a/src/Umbraco.Core/Packaging/PackageInstallation.cs b/src/Umbraco.Core/Packaging/PackageInstallation.cs index d7bb72836e..955662f3fe 100644 --- a/src/Umbraco.Core/Packaging/PackageInstallation.cs +++ b/src/Umbraco.Core/Packaging/PackageInstallation.cs @@ -76,12 +76,13 @@ namespace Umbraco.Core.Packaging return files; } + /// public UninstallationSummary UninstallPackage(PackageDefinition package, int userId) { //running this will update the PackageDefinition with the items being removed var summary = _packageDataInstallation.UninstallPackageData(package, userId); - summary.Actions = _parser.GetPackageActions(XElement.Parse(package.Actions), package.Name); + summary.Actions = CompiledPackageXmlParser.GetPackageActions(XElement.Parse(package.Actions), package.Name); //run actions before files are removed summary.ActionErrors = UndoPackageActions(package, summary.Actions).ToList(); @@ -109,7 +110,7 @@ namespace Umbraco.Core.Packaging installationSummary.StylesheetsInstalled = _packageDataInstallation.ImportStylesheets(compiledPackage.Stylesheets, userId); installationSummary.ContentInstalled = _packageDataInstallation.ImportContent(compiledPackage.Documents, importedDocTypes, userId); - installationSummary.Actions = _parser.GetPackageActions(XElement.Parse(compiledPackage.Actions), compiledPackage.Name); + installationSummary.Actions = CompiledPackageXmlParser.GetPackageActions(XElement.Parse(compiledPackage.Actions), compiledPackage.Name); installationSummary.MetaData = compiledPackage; installationSummary.FilesInstalled = packageDefinition.Files; diff --git a/src/Umbraco.Core/Packaging/PackagesRepository.cs b/src/Umbraco.Core/Packaging/PackagesRepository.cs index af5c7ffded..249d02a320 100644 --- a/src/Umbraco.Core/Packaging/PackagesRepository.cs +++ b/src/Umbraco.Core/Packaging/PackagesRepository.cs @@ -120,11 +120,6 @@ namespace Umbraco.Core.Packaging if (definition.Id == default) { - //check if the name already exists - var existsByName = packagesXml.Root.Elements("package").Any(x => x.AttributeValue("name") == definition.Name); - if (existsByName) - return false; - //need to gen an id and persist // Find max id var maxId = packagesXml.Root.Elements("package").Max(x => x.AttributeValue("id")) ?? 0; diff --git a/src/Umbraco.Core/Services/IPackagingService.cs b/src/Umbraco.Core/Services/IPackagingService.cs index 7d4d70196d..c14882fe7a 100644 --- a/src/Umbraco.Core/Services/IPackagingService.cs +++ b/src/Umbraco.Core/Services/IPackagingService.cs @@ -37,15 +37,35 @@ namespace Umbraco.Core.Services /// InstallationSummary InstallCompiledPackageData(PackageDefinition packageDefinition, FileInfo packageFile, int userId = 0); - UninstallationSummary UninstallPackage(PackageDefinition packageDefinition, int userId = 0); + /// + /// Uninstalls all versions of the package by name + /// + /// + /// + /// + UninstallationSummary UninstallPackage(string packageName, int userId = 0); #endregion #region Installed Packages IEnumerable GetAllInstalledPackages(); + + /// + /// Returns the for the installation id + /// + /// + /// PackageDefinition GetInstalledPackageById(int id); - PackageDefinition GetInstalledPackageByName(string name); + + /// + /// Returns all for the package by name + /// + /// + /// + /// A list of all package definitions installed for this package (i.e. original install and any upgrades) + /// + IEnumerable GetInstalledPackageByName(string name); /// /// Returns a for a given package name and version @@ -57,14 +77,6 @@ namespace Umbraco.Core.Services PackageInstallType GetPackageInstallType(string packageName, SemVersion packageVersion, out PackageDefinition alreadyInstalled); void DeleteInstalledPackage(int packageId, int userId = 0); - /// - /// Merges the package definition information from the upgrade on to the original and returns the merged definition - /// - /// - /// - /// - PackageDefinition MergePackageDefinition(PackageDefinition original, PackageDefinition upgrade); - /// /// Persists a package definition to storage /// diff --git a/src/Umbraco.Core/Services/Implement/PackagingService.cs b/src/Umbraco.Core/Services/Implement/PackagingService.cs index 1da53c5e11..24ef818624 100644 --- a/src/Umbraco.Core/Services/Implement/PackagingService.cs +++ b/src/Umbraco.Core/Services/Implement/PackagingService.cs @@ -44,7 +44,7 @@ namespace Umbraco.Core.Services.Implement ICreatedPackagesRepository createdPackages, IInstalledPackagesRepository installedPackages, IPackageInstallation packageInstallation) - { + { _auditService = auditService; _createdPackages = createdPackages; _installedPackages = installedPackages; @@ -110,7 +110,7 @@ namespace Umbraco.Core.Services.Implement if (compiledPackage == null) throw new InvalidOperationException("Could not read the package file " + packageFile); var files = _packageInstallation.InstallPackageFiles(packageDefinition, compiledPackage, userId).ToList(); - + SaveInstalledPackage(packageDefinition); _auditService.Add(AuditType.PackagerInstall, userId, -1, "Package", $"Package files installed for package '{compiledPackage.Name}'."); @@ -141,16 +141,44 @@ namespace Umbraco.Core.Services.Implement return summary; } - public UninstallationSummary UninstallPackage(PackageDefinition package, int userId = 0) + public UninstallationSummary UninstallPackage(string packageName, int userId = 0) { - var summary = _packageInstallation.UninstallPackage(package, userId); - - SaveInstalledPackage(package); + //this is ordered by descending version + var allPackageVersions = GetInstalledPackageByName(packageName)?.ToList(); + if (allPackageVersions == null || allPackageVersions.Count == 0) + throw new InvalidOperationException("No installed package found by name " + packageName); - DeleteInstalledPackage(package.Id, userId); + var summary = new UninstallationSummary + { + MetaData = allPackageVersions[0] + }; + + var allSummaries = new List(); + + foreach (var packageVersion in allPackageVersions) + { + var versionUninstallSummary = _packageInstallation.UninstallPackage(packageVersion, userId); + + allSummaries.Add(versionUninstallSummary); + + //merge the summary + summary.ActionErrors = summary.ActionErrors.Concat(versionUninstallSummary.ActionErrors).Distinct().ToList(); + summary.Actions = summary.Actions.Concat(versionUninstallSummary.Actions).Distinct().ToList(); + summary.DataTypesUninstalled = summary.DataTypesUninstalled.Concat(versionUninstallSummary.DataTypesUninstalled).Distinct().ToList(); + summary.DictionaryItemsUninstalled = summary.DictionaryItemsUninstalled.Concat(versionUninstallSummary.DictionaryItemsUninstalled).Distinct().ToList(); + summary.DocumentTypesUninstalled = summary.DocumentTypesUninstalled.Concat(versionUninstallSummary.DocumentTypesUninstalled).Distinct().ToList(); + summary.FilesUninstalled = summary.FilesUninstalled.Concat(versionUninstallSummary.FilesUninstalled).Distinct().ToList(); + summary.LanguagesUninstalled = summary.LanguagesUninstalled.Concat(versionUninstallSummary.LanguagesUninstalled).Distinct().ToList(); + summary.MacrosUninstalled = summary.MacrosUninstalled.Concat(versionUninstallSummary.MacrosUninstalled).Distinct().ToList(); + summary.StylesheetsUninstalled = summary.StylesheetsUninstalled.Concat(versionUninstallSummary.StylesheetsUninstalled).Distinct().ToList(); + summary.TemplatesUninstalled = summary.TemplatesUninstalled.Concat(versionUninstallSummary.TemplatesUninstalled).Distinct().ToList(); + + SaveInstalledPackage(packageVersion); + DeleteInstalledPackage(packageVersion.Id, userId); + } // trigger the UninstalledPackage event - UninstalledPackage.RaiseEvent(new UninstallPackageEventArgs(summary, package, false), this); + UninstalledPackage.RaiseEvent(new UninstallPackageEventArgs(allSummaries, false), this); return summary; } @@ -181,9 +209,9 @@ namespace Umbraco.Core.Services.Implement public PackageDefinition GetInstalledPackageById(int id) => _installedPackages.GetById(id); - public PackageDefinition GetInstalledPackageByName(string name) + public IEnumerable GetInstalledPackageByName(string name) { - var found = _installedPackages.GetAll().FirstOrDefault(x => x.Name.InvariantEquals(name)); + var found = _installedPackages.GetAll().Where(x => x.Name.InvariantEquals(name)).OrderByDescending(x => SemVersion.Parse(x.Version)); return found; } @@ -192,7 +220,8 @@ namespace Umbraco.Core.Services.Implement if (packageName == null) throw new ArgumentNullException(nameof(packageName)); if (packageVersion == null) throw new ArgumentNullException(nameof(packageVersion)); - alreadyInstalled = GetInstalledPackageByName(packageName); + //get the latest version installed + alreadyInstalled = GetInstalledPackageByName(packageName)?.OrderByDescending(x => SemVersion.Parse(x.Version)).FirstOrDefault(); if (alreadyInstalled == null) return PackageInstallType.NewInstall; if (!SemVersion.TryParse(alreadyInstalled.Version, out var installedVersion)) @@ -205,62 +234,6 @@ namespace Umbraco.Core.Services.Implement return PackageInstallType.Upgrade; } - public PackageDefinition MergePackageDefinition(PackageDefinition original, PackageDefinition upgrade) - { - if (!SemVersion.TryParse(original.Version, out var originalVersion)) - throw new InvalidOperationException("Could not parse the original version"); - if(!SemVersion.TryParse(upgrade.Version, out var upgradeVersion)) - throw new InvalidOperationException("Could not parse the upgrade version"); - if (originalVersion >= upgradeVersion) - throw new InvalidOperationException("The upgrade version must be higher than the original version"); - if (!original.Name.InvariantEquals(upgrade.Name)) - throw new InvalidOperationException("Cannot merge the package definitions, the package name doesn't match"); - - var result = original.Clone(); - - result.PackagePath = upgrade.PackagePath; - result.PackageId = upgrade.PackageId; - - result.UmbracoVersion = upgrade.UmbracoVersion; - result.Version = upgrade.Version; - result.Url = upgrade.Url; - result.Readme = upgrade.Readme; - result.AuthorUrl = upgrade.AuthorUrl; - result.Author = upgrade.Author; - result.LicenseUrl = upgrade.LicenseUrl; - result.PackageId = upgrade.PackageId; - result.Control = upgrade.Control; - result.IconUrl = upgrade.IconUrl; - result.License = upgrade.License; - result.ContentNodeId = upgrade.ContentNodeId; - result.ContentLoadChildNodes = upgrade.ContentLoadChildNodes; - - result.Files = original.Files.Concat(upgrade.Files).Distinct(StringComparer.InvariantCultureIgnoreCase).ToList(); - result.DataTypes = original.DataTypes.Concat(upgrade.DataTypes).Distinct(StringComparer.InvariantCultureIgnoreCase).ToList(); - result.Templates = original.Templates.Concat(upgrade.Templates).Distinct(StringComparer.InvariantCultureIgnoreCase).ToList(); - result.Languages = original.Languages.Concat(upgrade.Languages).Distinct(StringComparer.InvariantCultureIgnoreCase).ToList(); - result.Macros = original.Macros.Concat(upgrade.Macros).Distinct(StringComparer.InvariantCultureIgnoreCase).ToList(); - result.Stylesheets = original.Stylesheets.Concat(upgrade.Stylesheets).Distinct(StringComparer.InvariantCultureIgnoreCase).ToList(); - result.DocumentTypes = original.DocumentTypes.Concat(upgrade.DocumentTypes).Distinct(StringComparer.InvariantCultureIgnoreCase).ToList(); - result.DictionaryItems = original.DictionaryItems.Concat(upgrade.DictionaryItems).Distinct(StringComparer.InvariantCultureIgnoreCase).ToList(); - - var originalActions = CompiledPackageXmlParser.GetPackageActions(XElement.Parse(result.Actions), result.Name); - var upgradeActions = CompiledPackageXmlParser.GetPackageActions(XElement.Parse(upgrade.Actions), result.Name).ToList(); - var upgradeActionsLookup = upgradeActions.ToLookup(x => x.Alias, x => x.XmlData.ToString()); - - foreach (var originalAction in originalActions) - { - var upgradeActionsWithAlias = upgradeActionsLookup[originalAction.Alias]; - - //check if the original action does not exist already in our upgrade actions - if(upgradeActionsWithAlias.All(upgradeActionXml => upgradeActionXml != originalAction.XmlData.ToString())) - upgradeActions.Add(originalAction); - } - result.Actions = new XElement("actions", upgradeActions.Select(x => x.XmlData)).ToString(); - - return result; - } - public bool SaveInstalledPackage(PackageDefinition definition) => _installedPackages.SavePackage(definition); public void DeleteInstalledPackage(int packageId, int userId = 0) @@ -289,10 +262,10 @@ namespace Umbraco.Core.Services.Implement /// /// Occurs after a package is uninstalled /// - public static event TypedEventHandler> UninstalledPackage; + public static event TypedEventHandler UninstalledPackage; #endregion - + } } diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html index a66eb94746..8ed1a43e8a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html @@ -133,7 +133,7 @@ -
    +
    /// The content. + /// The specific culture to filter for. If null is used the current culture is used. (Default is null) /// One or more content type alias. /// The children of the content, of any of the specified types. public static IEnumerable Children(this IPublishedContent content, string culture = null, params string[] alias) @@ -1078,6 +1085,7 @@ namespace Umbraco.Web ///
    /// The content type. /// The content. + /// The specific culture to filter for. If null is used the current culture is used. (Default is null) /// The children of content, of the given content type. /// /// Children are sorted by their sortOrder. @@ -1127,6 +1135,7 @@ namespace Umbraco.Web /// The content. /// A service context. /// An optional content type alias. + /// The specific culture to filter for. If null is used the current culture is used. (Default is null) /// The children of the content. public static DataTable ChildrenAsTable(this IPublishedContent content, ServiceContext services, string contentTypeAliasFilter = "", string culture = null) { @@ -1139,6 +1148,7 @@ namespace Umbraco.Web /// The content. /// A service context. /// An optional content type alias. + /// The specific culture to filter for. If null is used the current culture is used. (Default is null) /// The children of the content. private static DataTable GenerateDataTable(IPublishedContent content, ServiceContext services, string contentTypeAliasFilter = "", string culture = null) { From 31545db91ed33ad59a4049a91792d11edbee02a6 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 16 Jan 2019 19:29:42 +1100 Subject: [PATCH 381/469] Fixes routing with the packages section --- src/Umbraco.Web.UI.Client/src/routes.js | 13 ++++++++--- .../src/views/packages/edit.controller.js | 4 ++-- .../src/views/packages/overview.controller.js | 22 +++++++++---------- .../Trees/PackagesTreeController.cs | 2 +- 4 files changed, 24 insertions(+), 17 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/routes.js b/src/Umbraco.Web.UI.Client/src/routes.js index 2d8ad46371..64bddb16e2 100644 --- a/src/Umbraco.Web.UI.Client/src/routes.js +++ b/src/Umbraco.Web.UI.Client/src/routes.js @@ -149,14 +149,21 @@ app.config(function ($routeProvider) { .when('/:section/:tree/:method?', { //This allows us to dynamically change the template for this route since you cannot inject services into the templateUrl method. template: "
    ", - //This controller will execute for this route, then we replace the template dynamnically based on the current tree. - controller: function ($scope, $route, $routeParams, treeService) { + //This controller will execute for this route, then we replace the template dynamically based on the current tree. + controller: function ($scope, $routeParams, treeService) { if (!$routeParams.method) { $scope.templateUrl = "views/common/dashboard.html"; + return; } - // Here we need to figure out if this route is for a package tree and if so then we need + //special case for the package section + if ($routeParams.section.toLowerCase() === "packages" && $routeParams.tree.toLowerCase() === "packages" && $routeParams.method !== "edit") { + $scope.templateUrl = "views/packages/overview.html"; + return; + } + + // Here we need to figure out if this route is for a user's package tree and if so then we need // to change it's convention view path to: // /App_Plugins/{mypackage}/backoffice/{treetype}/{method}.html diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js index 4afe62786e..29d871c0b1 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js @@ -130,7 +130,7 @@ } function back() { - $location.path("packages/packages/overview").search('create', null);; + $location.path("packages/packages/created").search("create", null); } function createOrUpdatePackage(editPackageForm) { @@ -148,7 +148,7 @@ if (create) { //if we are creating, then redirect to the correct url and reload - $location.path("packages/packages/edit/" + vm.package.id).search("subview", "created").search("create", null); + $location.path("packages/packages/edit/" + vm.package.id).search("create", null); //don't add a browser history for this $location.replace(); } diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/overview.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/overview.controller.js index ccd86c6f6c..59fa79dc26 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/overview.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/overview.controller.js @@ -1,7 +1,7 @@ (function () { "use strict"; - function PackagesOverviewController($scope, $location, localStorageService) { + function PackagesOverviewController($scope, $location, $routeParams, localStorageService) { //Hack! // if there is a cookie value for packageInstallUri then we need to redirect there, @@ -10,7 +10,7 @@ // we will refresh and then navigate there. let installPackageUri = localStorageService.get("packageInstallUri"); - let packageUri = $location.search().subview; + let packageUri = $routeParams.method; if (installPackageUri) { localStorageService.remove("packageInstallUri"); @@ -33,10 +33,10 @@ "name": "Packages", "icon": "icon-cloud", "view": "views/packages/views/repo.html", - "active": !packageUri || packageUri === "navigation", + "active": !packageUri || packageUri === "repo", "alias": "umbPackages", - "action": function() { - $location.search("subview", "navigation"); + "action": function () { + $location.path("/packages/packages/repo"); } }, { @@ -45,8 +45,8 @@ "view": "views/packages/views/installed.html", "active": packageUri === "installed", "alias": "umbInstalled", - "action": function() { - $location.search("subview", "installed"); + "action": function () { + $location.path("/packages/packages/installed"); } }, { @@ -55,8 +55,8 @@ "view": "views/packages/views/install-local.html", "active": packageUri === "local", "alias": "umbInstallLocal", - "action": function() { - $location.search("subview", "local"); + "action": function () { + $location.path("/packages/packages/local"); } }, { @@ -65,8 +65,8 @@ "view": "views/packages/views/created.html", "active": packageUri === "created", "alias": "umbCreatedPackages", - "action": function() { - $location.search("subview", "created"); + "action": function () { + $location.path("/packages/packages/created"); } } ]; diff --git a/src/Umbraco.Web/Trees/PackagesTreeController.cs b/src/Umbraco.Web/Trees/PackagesTreeController.cs index fdc5294aa2..68b67f9fe2 100644 --- a/src/Umbraco.Web/Trees/PackagesTreeController.cs +++ b/src/Umbraco.Web/Trees/PackagesTreeController.cs @@ -22,7 +22,7 @@ namespace Umbraco.Web.Trees var root = base.CreateRootNode(queryStrings); //this will load in a custom UI instead of the dashboard for the root node - root.RoutePath = $"{Constants.Applications.Packages}/{Constants.Trees.Packages}/overview"; + root.RoutePath = $"{Constants.Applications.Packages}/{Constants.Trees.Packages}/repo"; root.Icon = "icon-box"; root.HasChildren = false; From 572c6989ceadb4edccfad2238ca1258510be4d1e Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 16 Jan 2019 19:30:07 +1100 Subject: [PATCH 382/469] Changes control to view for the package view --- .../Models/Packaging/CompiledPackage.cs | 2 +- .../Models/Packaging/IPackageInfo.cs | 7 +++- .../Models/Packaging/PackageDefinition.cs | 41 +++---------------- .../Packaging/CompiledPackageXmlParser.cs | 2 +- .../Packaging/PackageDefinitionXmlParser.cs | 4 +- .../Packaging/PackagesRepository.cs | 6 +-- .../src/views/packages/edit.controller.js | 14 +++---- .../src/views/packages/edit.html | 6 +-- .../Editors/PackageInstallController.cs | 7 ++-- 9 files changed, 32 insertions(+), 57 deletions(-) diff --git a/src/Umbraco.Core/Models/Packaging/CompiledPackage.cs b/src/Umbraco.Core/Models/Packaging/CompiledPackage.cs index a852fcc997..f14fe47bfe 100644 --- a/src/Umbraco.Core/Models/Packaging/CompiledPackage.cs +++ b/src/Umbraco.Core/Models/Packaging/CompiledPackage.cs @@ -23,7 +23,7 @@ namespace Umbraco.Core.Models.Packaging public string Author { get; set; } public string AuthorUrl { get; set; } public string Readme { get; set; } - public string Control { get; set; } + public string PackageView { get; set; } public string IconUrl { get; set; } public string Actions { get; set; } //fixme: Should we make this strongly typed to IEnumerable ? diff --git a/src/Umbraco.Core/Models/Packaging/IPackageInfo.cs b/src/Umbraco.Core/Models/Packaging/IPackageInfo.cs index 8722ee7811..eea56549f1 100644 --- a/src/Umbraco.Core/Models/Packaging/IPackageInfo.cs +++ b/src/Umbraco.Core/Models/Packaging/IPackageInfo.cs @@ -13,7 +13,12 @@ namespace Umbraco.Core.Models.Packaging string Author { get; } string AuthorUrl { get; } string Readme { get; } - string Control { get; } //fixme - this needs to be an angular view + + /// + /// This is the angular view path that will be loaded when the package installs + /// + string PackageView { get; } + string IconUrl { get; } } } diff --git a/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs b/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs index c068c57b08..8c0ef79d0b 100644 --- a/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs +++ b/src/Umbraco.Core/Models/Packaging/PackageDefinition.cs @@ -25,7 +25,7 @@ namespace Umbraco.Core.Models.Packaging Actions = compiled.Actions, Author = compiled.Author, AuthorUrl = compiled.AuthorUrl, - Control = compiled.Control, + PackageView = compiled.PackageView, IconUrl = compiled.IconUrl, License = compiled.License, LicenseUrl = compiled.LicenseUrl, @@ -115,9 +115,9 @@ namespace Umbraco.Core.Models.Packaging [DataMember(Name = "files")] public IList Files { get; set; } = new List(); - //fixme: Change this to angular view - [DataMember(Name = "loadControl")] - public string Control { get; set; } = string.Empty; + /// + [DataMember(Name = "packageView")] + public string PackageView { get; set; } = string.Empty; [DataMember(Name = "actions")] public string Actions { get; set; } = ""; @@ -127,38 +127,7 @@ namespace Umbraco.Core.Models.Packaging [DataMember(Name = "iconUrl")] public string IconUrl { get; set; } = string.Empty; - - public PackageDefinition Clone() - { - return new PackageDefinition - { - Id = Id, - PackagePath = PackagePath, - Name = Name, - Files = new List(Files), - UmbracoVersion = (Version) UmbracoVersion.Clone(), - Version = Version, - Url = Url, - Readme = Readme, - AuthorUrl = AuthorUrl, - Author = Author, - LicenseUrl = LicenseUrl, - Actions = Actions, - PackageId = PackageId, - Control = Control, - DataTypes = new List(DataTypes), - IconUrl = IconUrl, - License = License, - Templates = new List(Templates), - Languages = new List(Languages), - Macros = new List(Macros), - Stylesheets = new List(Stylesheets), - DocumentTypes = new List(DocumentTypes), - DictionaryItems = new List(DictionaryItems), - ContentNodeId = ContentNodeId, - ContentLoadChildNodes = ContentLoadChildNodes - }; - } + } diff --git a/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs b/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs index 0d533cfbc2..7f62f4fd27 100644 --- a/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs +++ b/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs @@ -51,7 +51,7 @@ namespace Umbraco.Core.Packaging IconUrl = package.Element("iconUrl")?.Value, UmbracoVersion = new Version((int)requirements.Element("major"), (int)requirements.Element("minor"), (int)requirements.Element("patch")), UmbracoVersionRequirementsType = requirements.AttributeValue("type").IsNullOrWhiteSpace() ? RequirementsType.Legacy : Enum.Parse(requirements.AttributeValue("type"), true), - Control = package.Element("control")?.Value, + PackageView = package.Element("view")?.Value, Actions = xml.Root.Element("Actions")?.ToString(SaveOptions.None) ?? "", //take the entire outer xml value Files = xml.Root.Element("files")?.Elements("file")?.Select(CompiledPackageFile.Create).ToList() ?? new List(), Macros = xml.Root.Element("Macros")?.Elements("macro") ?? Enumerable.Empty(), diff --git a/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs b/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs index 45e6fd9845..00255fa43a 100644 --- a/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs +++ b/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs @@ -50,7 +50,7 @@ namespace Umbraco.Core.Packaging DictionaryItems = xml.Element("dictionaryitems")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(), DataTypes = xml.Element("datatypes")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(), Files = xml.Element("files")?.Elements("file").Select(x => x.Value).ToList() ?? new List(), - Control = xml.Element("loadcontrol")?.Value ?? string.Empty + PackageView = xml.Element("view")?.Value ?? string.Empty }; return retVal; @@ -101,7 +101,7 @@ namespace Umbraco.Core.Packaging new XElement("files", (def.Files ?? Array.Empty()).Where(x => !x.IsNullOrWhiteSpace()).Select(x => new XElement("file", x))), new XElement("languages", string.Join(",", def.Languages ?? Array.Empty())), new XElement("dictionaryitems", string.Join(",", def.DictionaryItems ?? Array.Empty())), - new XElement("loadcontrol", def.Control ?? string.Empty)); //fixme: no more loadcontrol, needs to be an angular view + new XElement("view", def.PackageView ?? string.Empty)); return packageXml; } diff --git a/src/Umbraco.Core/Packaging/PackagesRepository.cs b/src/Umbraco.Core/Packaging/PackagesRepository.cs index 249d02a320..5531e05705 100644 --- a/src/Umbraco.Core/Packaging/PackagesRepository.cs +++ b/src/Umbraco.Core/Packaging/PackagesRepository.cs @@ -180,10 +180,10 @@ namespace Umbraco.Core.Packaging AppendFileToManifest(fileName, temporaryPath, filesXml); //Load control on install... - if (!string.IsNullOrEmpty(definition.Control)) + if (!string.IsNullOrEmpty(definition.PackageView)) { - var control = new XElement("control", definition.Control); - AppendFileToManifest(definition.Control, temporaryPath, filesXml); + var control = new XElement("view", definition.PackageView); + AppendFileToManifest(definition.PackageView, temporaryPath, filesXml); manifestRoot.Add(control); } diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js index 29d871c0b1..ca20b33a3e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js @@ -19,8 +19,8 @@ vm.openContentPicker = openContentPicker; vm.openFilePicker = openFilePicker; vm.removeFile = removeFile; - vm.openControlPicker = openControlPicker; - vm.removeControl = removeControl; + vm.openViewPicker = openViewPicker; + vm.removePackageView = removePackageView; vm.downloadFile = downloadFile; const packageId = $routeParams.id; @@ -220,16 +220,16 @@ vm.package.files.splice(index, 1); } - function openControlPicker() { + function openViewPicker() { const controlPicker = { - title: "Select control", + title: "Select view", section: "settings", treeAlias: "files", entityType: "file", onlyInitialized: false, select: function(node) { const id = unescape(node.id); - vm.package.loadControl = id; + vm.package.packageView = id; editorService.close(); }, close: function() { @@ -239,8 +239,8 @@ editorService.treePicker(controlPicker); } - function removeControl() { - vm.package.loadControl = null; + function removePackageView() { + vm.package.packageView = null; } onInit(); diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html index 8ed1a43e8a..5163fadfb5 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html @@ -264,14 +264,14 @@ name="vm.package.loadControl" allow-edit="true" allow-remove="true" - on-edit="vm.openControlPicker()" - on-remove="vm.removeControl()"> + on-edit="vm.openViewPicker()" + on-remove="vm.removePackageView()"> Add diff --git a/src/Umbraco.Web/Editors/PackageInstallController.cs b/src/Umbraco.Web/Editors/PackageInstallController.cs index dd7c4302c5..544a871720 100644 --- a/src/Umbraco.Web/Editors/PackageInstallController.cs +++ b/src/Umbraco.Web/Editors/PackageInstallController.cs @@ -376,10 +376,11 @@ namespace Umbraco.Web.Editors zipFile.Delete(); var redirectUrl = ""; - if (packageInfo.Control.IsNullOrWhiteSpace() == false) + if (!packageInfo.PackageView.IsNullOrWhiteSpace()) { - //fixme: this needs to be replaced with an angular view the installer.aspx no longer exists. - //redirectUrl = string.Format("/developer/framed/{0}", + //fixme! + throw new NotImplementedException(); + //redirectUrl = string.Format("/packages/framed/{0}", // Uri.EscapeDataString( // string.Format("/umbraco/developer/Packages/installer.aspx?installing=custominstaller&dir={0}&pId={1}&customControl={2}&customUrl={3}", tempDir, model.Id, ins.Control, ins.Url))); } From 26b31f1fc88598bb1a201c55c4c06d269ceec438 Mon Sep 17 00:00:00 2001 From: Stephan Date: Wed, 16 Jan 2019 10:01:04 +0100 Subject: [PATCH 383/469] Fix Git repository issue with casing of some filepaths --- src/Umbraco.Web.UI/umbraco/config/lang/nb.xml | 963 ------------- .../umbraco/config/lang/zh_tw.xml | 1269 ----------------- 2 files changed, 2232 deletions(-) delete mode 100644 src/Umbraco.Web.UI/umbraco/config/lang/nb.xml delete mode 100644 src/Umbraco.Web.UI/umbraco/config/lang/zh_tw.xml diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/nb.xml b/src/Umbraco.Web.UI/umbraco/config/lang/nb.xml deleted file mode 100644 index d51d41e558..0000000000 --- a/src/Umbraco.Web.UI/umbraco/config/lang/nb.xml +++ /dev/null @@ -1,963 +0,0 @@ - - - - The Umbraco community - http://our.umbraco.org/documentation/Extending-Umbraco/Language-Files - - - Angi domene - Revisjoner - Bla gjennom - Skift dokumenttype - Kopier - Opprett - Opprett pakke - Slett - Deaktiver - Tøm papirkurv - Eksporter dokumenttype - Importer dokumenttype - Importer pakke - Rediger i Canvas - Logg av - Flytt - Varslinger - Offentlig tilgang - Publiser - Avpubliser - Oppdater noder - Republiser hele siten - Gjenopprett - Rettigheter - Reverser - Send til publisering - Send til oversetting - Sorter - Oversett - Oppdater - - - Ingen tilgang. - Legg til domene - Fjern - Ugyldig node. - Ugyldig domeneformat. - Domene er allerede tilknyttet. - Språk - Domene - Domene '%0%' er nå opprettet og tilknyttet siden - Domenet '%0%' er nå slettet - Domenet '%0%' er allerede tilknyttet - Domenet '%0%' er nå oppdatert - eller rediger eksisterende domener -
    Stier med ett nivå støttes, f.eks. "eksempel.com/no". Imidlertid bør det unngås. Bruk heller språkinnstillingen over.]]>
    - Arv - Språk - Vil også gjelde denne noden, med mindre et underordnet domene også gjelder.]]> - Domener - - - Viser for - - - Velg - Gjør noe annet - Fet - Reduser innrykk - Sett inn skjemafelt - Sett inn grafisk overskrift - Rediger HTML - Øk innrykk - Kursiv - Midtstill - Juster tekst venstre - Juster tekst høyre - Sett inn lenke - Sett inn lokal lenke (anker) - Punktmerking - Nummerering - Sett inn makro - Sett inn bilde - Rediger relasjoner - Tilbake til listen - Lagre - Lagre og publiser - Lagre og planlegge - Lagre og send til publisering - Forhåndsvis - Forhåndsvisning er deaktivert siden det ikke er angitt noen mal - Velg formattering - Vis stiler - Sett inn tabell - - - For å endre det valge innholdets dokumenttype, velger du først en ny dokumenttype som er gyldig på gjeldende plassering. - Kontroller deretter at alle egenskaper blir overført riktig til den nye dokumenttypen og klikk på Lagre. - Innholdet har blitt republisert. - Nåværende egenskap - Nåværende type - Du kan ikke endre dokumenttype, ettersom det ikke er andre gyldige dokumenttyper på denne plasseringen. - Dokumenttype endret - Overfør egenskaper - Overfør til egenskap - Ny mal - Ny type - ingen - Innhold - Velg ny dokumenttype - Dokumenttypen på det valgte innhold ble endret til [new type], og følgende egenskaper ble overført: - til - Overføringen av egenskaper kunne ikke fullføres da en eller flere egenskaper er satt til å bli overført mer enn en gang. - Kun andre dokumenttyper som er gyldige for denne plasseringen vises. - - - Publisert - Om siden - Alias - (hvordan du ville beskrevet bildet over telefon) - Alternative lenker - Klikk for å redigere denne noden - Opprettet av - Opprinnelig forfatter - Oppdatert av - Opprettet den - Tidspunkt for opprettelse - Dokumenttype - Redigerer - Utløpsdato - Denne noden er endret siden siste publisering - Denne noden er enda ikke publisert - Sist publisert - Det er ingen elementer å vise i listen. - Mediatype - Link til media - Medlemsgruppe - Rolle - Medlemstype - Ingen dato valgt - Sidetittel - Egenskaper - Dette dokumentet er publisert, men ikke synlig ettersom den overliggende siden '%0%' ikke er publisert - Intern feil: dokumentet er publisert men finnes ikke i hurtigbuffer - Publisert - Publiseringsstatus - Publiseringsdato - Dato for avpublisering - Fjern dato - Sorteringsrekkefølgen er oppdatert - Trekk og slipp nodene eller klikk på kolonneoverskriftene for å sortere. Du kan velge flere noder ved å holde shift eller control tastene mens du velger. - Statistikk - Tittel (valgfri) - Alternativ tekst (valgfri) - Type - Avpubliser - Sist endret - Tidspunkt for siste endring - Fjern fil - Lenke til dokument - Medlem av gruppe(ne) - Ikke medlem av gruppe(ne) - Undersider - Åpne i vindu - - - Klikk for å laste opp - - - Opprett et nytt medlem - Alle medlemmer - - - Hvor ønsker du å oprette den nye %0% - Opprett under - Velg en type og skriv en tittel - "dokumenttyper".]]> - "mediatyper".]]> - - - Til ditt nettsted - - Skjul - Hvis Umbraco ikke starter, kan det skyldes at pop-up vinduer ikke er tillatt - er åpnet i nytt vindu - Omstart - Besøk - Velkommen - - - Stay - Discard changes - You have unsaved changes - Are you sure you want to navigate away from this page? - you have unsaved changes - - - Done - Deleted %0% item - Deleted %0% items - Deleted %0% out of %1% item - Deleted %0% out of %1% items - Published %0% item - Published %0% items - Published %0% out of %1% item - Published %0% out of %1% items - Unpublished %0% item - Unpublished %0% items - Unpublished %0% out of %1% item - Unpublished %0% out of %1% items - Moved %0% item - Moved %0% items - Moved %0% out of %1% item - Moved %0% out of %1% items - Copied %0% item - Copied %0% items - Copied %0% out of %1% item - Copied %0% out of %1% items - - - Navn på lokal link - Rediger domener - Lukk dette vinduet - Er du sikker på at du vil slette - Er du sikker på at du vil deaktivere - Er du sikker på at du vil forlate Umbraco? - Er du sikker? - Klipp ut - Rediger ordboksnøkkel - Rediger språk - Sett inn lokal link - Sett inn spesialtegn - Sett inn grafisk overskrift - Sett inn bilde - Sett inn lenke - Sett inn makro - Sett inn tabell - Sist redigert - Lenke - Intern link: - Ved lokal link, sett inn "#" foran link - Åpne i nytt vindu? - Makroinnstillinger - Denne makroen har ingen egenskaper du kan endre - Lim inn - Endre rettigheter for - Innholdet i papirkurven blir nå slettet. Vennligst ikke lukk dette vinduet mens denne operasjonen foregår - Papirkurven er nå tom - Når elementer blir slettet fra papirkurven vil de være slettet for alltid - regexlib.com tjenesten opplever for tiden problemer som vi ikke har kontroll over. Vi beklager denne ubeleiligheten.]]> - Søk etter et regulært uttrykk for å legge inn validering til et felt. Eksempel: 'email, 'zip-code' 'url' - Fjern makro - Obligatorisk - Nettstedet er indeksert - Hurtigbufferen er blitt oppdatert. Alt publisert innhold er nå à jour. Alt upublisert innhold er fortsatt ikke publisert. - Hurtigbufferen for siden vil bli oppdatert. Alt publisert innhold vil bli oppdatert, mens upublisert innhold vil forbli upublisert. - Antall kolonner - Antall rader - Sett en plassholder-ID
    Ved å sette en ID på plassholderen kan du legge inn innhold i denne malen fra underliggende maler, ved å referere denne ID'en ved hjelp av et <asp:content /> element.]]>
    - Velg en plassholder ID fra listen under. Du kan bare velge ID'er fra den gjeldende malens overordnede mal.]]> - Klikk på bildet for å se det i full størrelse - Velg punkt - Se buffret node - - - %0%' under.
    Du kan legge til flere språk under 'språk' i menyen til venstre.]]>
    - Språk - - - Skriv inn ditt brukernavn - Skriv inn ditt passord - Navngi %0%... - Skriv inn navn... - Søk... - Filtrer... - Skriv inn nøkkelord (trykk på Enter etter hvert nøkkelord)... - - - Tillatte underordnede noder - Opprett - Slett arkfane - Beskrivelse - Ny arkfane - Arkfane - Miniatyrbilde - Opprett brukerdefinert listevisning - Fjern brukerdefinert listevisning - - - Legg til forhåndsverdi - Database datatype - Kontrollelement GUID - Kontrollelement - Knapper - Aktiver avanserte instillinger for - Aktiver kontektsmeny - Maksimum standard størrelse på innsatte bilder - Beslektede stilark - Vis etikett - Bredde og høyde - - - Dine data har blitt lagret, men før du kan publisere denne siden må du rette noen feil: - Den gjeldende Membership Provider støtter ikke endring av passord. (EnablePasswordRetrieval må være satt til sann) - %0% finnes allerede - Det var feil i dokumentet: - Det var feil i skjemaet: - Passordet bør være minst %0% tegn og inneholde minst %1% numeriske tegn - %0% må være et heltall - %0% under %1% er obligatorisk - %0% er obligatorisk - %0% under %1% er ikke i et korrekt format - %0% er ikke i et korrekt format - - - Filtypen er deaktivert av administrator - NB! Selv om CodeMirror er aktivert i konfigurasjon er det deaktivert i Internet Explorer pga. ustabilitet. - Fyll ut både alias og navn på den nye egenskapstypen! - Det er et problem med lese/skrive rettighetene til en fil eller mappe - Tittel mangler - Type mangler - Du er i ferd med å gjøre bildet større enn originalen. Det vil forringe kvaliteten på bildet, ønsker du å fortsette? - Startnode er slettet. Kontakt din administrator - Du må markere innhold før du kan endre stil - Det er ingen aktive stiler eller formateringer på denne siden - Sett markøren til venstre i de 2 cellene du ønsker å slå sammen - Du kan ikke dele en celle som allerede er delt. - - - Om - Handling - Muligheter - Legg til - Alias - Er du sikker? - Ramme - av - Avbryt - Cellemargin - Velg - Lukk - Lukk vindu - Kommentar - Bekreft - Behold proposjoner - Fortsett - Kopier - Opprett - Database - Dato - Standard - Slett - Slettet - Sletter... - Design - Dimensjoner - Ned - Last ned - Rediger - Endret - Elementer - E-post - Feil - Finn - Høyde - Hjelp - Ikon - Importer - Indre margin - Sett inn - Installer - Justering - Språk - Layout - Laster - Låst - Logg inn - Logg ut - Logg ut - Makro - Flytt - Navn - Ny - Neste - Nei - av - OK - Åpne - eller - Passord - Sti - Plassholder ID - Ett øyeblikk... - Forrige - Egenskaper - E-post som innholdet i skjemaet skal sendes til - Papirkurv - Gjenværende - Gi nytt navn - Forny - Påkrevd - Prøv igjen - Rettigheter - Søk - Server - Vis - Hvilken side skal vises etter at skjemaet er sendt - Størrelse - Sorter - Send - Type - Søk... - Opp - Oppdater - Oppgrader - Last opp - Url - Bruker - Brukernavn - Verdi - Visning - Velkommen... - Bredde - Ja - Mappe - Søkeresultater - Sorter - Avslutt sortering - Eksempel - Bytt passord - til - Listevisning - Lagrer... - nåværende - Innbygging - Hent - valgt - - - Bakgrunnsfarge - Fet - Tekstfarge - Skrifttype - Tekst - - - Side - - - Installasjonsprogrammet kan ikke koble til databasen - Kunne ikke lagre Web.Config-filen. Vennligst endre databasens tilkoblingsstreng manuelt. - Din database er funnet og identifisert som - Databasekonfigurasjon - installer-knappen for å installere Umbraco %0% databasen]]> - Neste for å fortsette.]]> - Databasen ble ikke funnet! Vennligst sjekk at informasjonen i "connection string" i "web.config"-filen er korrekt.

    For å fortsette, vennligst rediger "web.config"-filen (bruk Visual Studio eller din favoritteditor), rull ned til bunnen, og legg til tilkoblingsstrengen for din database i nøkkelen "umbracoDbDSN" og lagre filen.

    Klikk prøv på nytt når du er ferdig.
    Mer informasjon om redigering av web.config her.

    ]]>
    - Vennligst kontakt din ISP om nødvendig. Hvis du installerer på en lokal maskin eller server, må du kanskje skaffe informasjonen fra din systemadministrator.]]> - Trykk på knappen oppgrader for å oppgradere databasen din til Umbraco %0%

    Ikke vær urolig - intet innhold vil bli slettet og alt vil fortsette å virke etterpå!

    ]]>
    - Trykk Neste for å fortsette.]]> - neste for å fortsette konfigurasjonsveiviseren]]> - Passordet til standardbrukeren må endres!]]> - Standardbrukeren har blitt deaktivert eller har ingen tilgang til Umbraco!

    Ingen videre handling er nødvendig. Klikk neste for å fortsette.]]> - Passordet til standardbrukeren har blitt forandret etter installasjonen!

    Ingen videre handling er nødvendig. Klikk Neste for å fortsette.]]> - Passordet er blitt endret! - Få en god start med våre introduksjonsvideoer - Ved å klikke på Neste-knappen (eller endre UmbracoConfigurationStatus i Web.config), godtar du lisensen for denne programvaren som angitt i boksen nedenfor. Legg merke til at denne Umbraco distribusjon består av to ulike lisenser, åpen kilde MIT lisens for rammen og Umbraco frivareverktøy lisens som dekker brukergrensesnittet. - Ikke installert. - Berørte filer og mapper - Mer informasjon om å sette opp rettigheter for Umbraco her - Du må gi ASP.NET brukeren rettigheter til å endre de følgende filer og mapper - Rettighetene er nesten perfekt satt opp!

    Du kan kjøre Umbraco uten problemer, men du vil ikke være i stand til å installere de anbefalte pakkene for å utnytte Umbraco fullt ut.]]>
    - Hvordan løse problemet - Klikk her for å lese tekstversjonen - innføringsvideo om å sette opp rettigheter for Umbraco eller les tekstversjonen.]]> - Rettighetsinnstillingene kan være et problem!

    Du kan kjøre Umbraco uten problemer, men du vil ikke være i stand til å installere de anbefalte pakkene for å utnytte Umbraco fullt ut.]]>
    - Rettighetsinstillingene er ikke klargjort for Umbraco!

    For å kunne kjøre Umbraco, må du oppdatere rettighetsinnstillingene dine.]]>
    - Rettighetsinnstillingene er perfekt!

    Du er klar for å kjøre Umbraco og installere pakker!]]>
    - Løser mappeproblem - Følg denne linken for mer informasjon om problemer med ASP.NET og oppretting av mapper - Konfigurerer mappetillatelser - - Jeg ønsker å starte fra bunnen. - lær hvordan) Du kan fortsatt velge å installere Runway senere. Vennligst gå til Utvikler-seksjonen og velg Pakker.]]> - Du har akkurat satt opp en ren Umbraco plattform. Hva vil du gjøre nå? - Runway er installert - Dette er vår liste av anbefalte moduler- Kryss av de du ønsker å installere, eller se denfulle listen av moduler ]]> - Bare anbefalt for erfarne brukere - Jeg vil starte med en enkel webside - "Runway" er en enkel webside som utstyrer deg med noen grunnleggende dokumenttyper og maler. Veiviseren kan sette opp Runway for deg automatisk, men du kan enkelt endre, utvide eller slette den. Runway er ikke nødvendig, og du kan enkelt bruke Umbraco uten den. Imidlertidig tilbyr Runway et enkelt fundament basert på de beste metodene for å hjelpe deg i gang fortere enn noensinne. Hvis du velger å installere Runway, kan du også velge blant grunnleggende byggeklosser kalt Runway Moduler for å forøke dine Runway-sider.

    Sider inkludert i Runway: Hjemmeside, Komme-i-gang, Installere moduler.
    Valgfrie Moduler: Toppnavigasjon, Sidekart, Kontakt, Galleri.
    ]]>
    - Hva er Runway - Steg 1/5 Godta lisens - Steg 2/5 Database konfigurasjon - Steg 3/5: Valider filrettigheter - Steg 4/5: Skjekk Umbraco sikkerheten - Steg 5/5: Umbraco er klar for deg til å starte! - Tusen takk for at du valgte Umbraco! - Se ditt nye nettsted Du har installert Runway, hvorfor ikke se hvordan ditt nettsted ser ut.]]> - Mer hjelp og info Få hjelp fra vårt prisbelønte samfunn, bla gjennom dokumentasjonen eller se noen gratis videoer på hvordan man bygger et enkelt nettsted, hvordan bruke pakker og en rask guide til Umbraco terminologi]]> - Umbraco %0% er installert og klar til bruk - web.config filen, og oppdatere AppSetting-nøkkelen UmbracoConfigurationStatus til verdien '%0%']]> - starte øyeblikkelig ved å klikke på "Start Umbraco" knappen nedenfor.
    Hvis du er ny på Umbraco, kan du finne mange ressurser på våre komme-i-gang sider.]]>
    - Start Umbraco For å administrere din webside, åpne Umbraco og begynn å legge til innhold, oppdatere maler og stilark eller utvide funksjonaliteten]]> - Tilkobling til databasen mislyktes. - Umbraco Versjon 3 - Umbraco Versjon 4 - Se - Umbraco %0% for en ny installasjon eller oppgradering fra versjon 3.0.

    Trykk "neste" for å starte veiviseren.]]>
    - - - Språkkode - Språk - - - Du har vært inaktiv og vil logges ut automatisk om - Forny innlogging for å lagre - - - Da er det søndag! - Smil, det er mandag! - Hurra, det er tirsdag! - For en herlig onsdag! - Gledelig torsdag! - Endelig fredag! - Gledelig lørdag - Logg på nedenfor - Logg på med - Din sesjon er utløpt - © 2001 - %0%
    umbraco.com

    ]]>
    - - - Skrivebord - Seksjoner - Innhold - - - Velg side over... - %0% er nå kopiert til %1% - Kopier til - %0% er nå flyttet til %1% - Flytt til - har blitt valgt som rot til ditt nye innhold, klikk 'ok' nedenfor. - Ingen node er valgt, vennligst velg en node i listen over før du klikker 'fortsett' - Gjeldende nodes type tillates ikke under valgt node - Gjeldende node kan ikke legges under en underordnet node - Denne noden kan ikke ligge på rotnivå - Handlingen tillates ikke. Du mangler tilgang til en eller flere underordnede noder. - Relater kopierte elementer til original(e) - - - Rediger dine varsler for %0% - - Hei %0%

    - -

    Dette er en automatisk mail for å informere om at handlingen '%1%' - er blitt utført på siden '%2%' - av brukeren '%3%' -

    - -

    -

    Rettelser:

    - - %6% -
    -

    - - - -

    Ha en fin dag!

    - Vennlig hilsen Umbraco roboten -

    ]]>
    - [%0%] Varsling om %1% utført på %2% - Varslinger - - - Umbraco-pakker har vanligvis endelsen ".umb" eller ".zip".]]> - Utvikler - Demonstrasjon - Dokumentasjon - Metadata - Pakkenavn - Pakken inneholder ingen elementer -
    Du kan trygt fjerne pakken fra systemet ved å klikke "avinstaller pakke" nedenfor.]]>
    - Ingen oppdateringer tilgjengelig - Alternativer for pakke - Lesmeg for pakke - Pakkebrønn - Bekreft avinstallering - Pakken ble avinstallert - Pakken ble vellykket avinstallert - Avinstaller pakke - Advarsel: alle dokumenter, media, etc. som som er avhengig av elementene du sletter, vil slutte å virke, noe som kan føre til ustabilitet, så avinstaller med forsiktighet. Hvis du er i tvil, kontakt pakkeutvikleren.]]> - Last ned oppdatering fra pakkeregisteret - Oppgrader pakke - Oppgraderingsinstrukser - Det er en oppdatering tilgjengelig for denne pakken. Du kan laste den ned direkte fra pakkebrønnen. - Pakkeversjon - Pakkeversjonshistorie - Se pakkens nettsted - - - Lim inn med full formattering (Anbefales ikke) - Teksten du er i ferd med å lime inn, inneholder spesialtegn eller formattering. Dette kan skyldes at du kopierer fra f.eks. Microsoft Word. Umbraco kan fjerne denne spesialformatteringen automatisk slik at innholdet er mer velegnet for visning på en webside. - Lim inn som ren tekst, dvs. fjern al formattering - Lim inn og fjern uegnet formatering (anbefalt) - - - Avansert: Beskytt ved å velge hvilke brukergrupper som har tilgang til siden - ved å bruke Umbraco's medlems-grupper]]> - Du må opprette en medlemsgruppe før du kan bruke rollebasert autentikasjon. - Feilside - Brukt når personer logger på, men ikke har tilgang - Hvordan vil du beskytte siden din? - %0% er nå beskyttet - Beskyttelse fjernet fra %0% - Innloggingsside - Velg siden som har loginformularet - Fjern beskyttelse - Velg sidene som inneholder login-skjema og feilmelding ved feil innolgging. - Velg rollene som har tilgang til denne siden - Sett brukernavn og passord for denne siden - Enkelt: Beskytt ved hjelp av brukernavn og passord - Om du ønsker å bruke enkel autentisering via ett enkelt brukernavn og passord - - - %0% kunne ikke publiseres fordi den har planlagt utgivelsesdato. - %0% ble ikke publisert. Ett eller flere felter ble ikke godkjent av validering. - %0% kunne ikke publiseres fordi et tredjepartstillegg avbrøt handlingen. - %0% kan ikke publiseres fordi en overordnet side ikke er publisert. - Inkluder upubliserte undersider - Publiserer - vennligst vent... - %0% av %1% sider har blitt publisert... - %0% er nå publisert - %0% og alle undersider er nå publisert - Publiser alle undersider - ok for å publisere %0% og dermed gjøre innholdet synlig for alle.

    Du kan publisere denne siden og alle dens undersider ved å krysse av Publiser alle undersider nedenfor.]]>
    - - - Du har ikke konfigurert noen godkjente farger - - - skriv inn ekstern lenke - velg en intern side - Tittel - Lenke - Åpne i nytt vindu - Skriv inn en tekst - Skriv inn en lenke - - - Nullstill - - - Gjeldende versjon - Rød tekst vil ikke bli vist i den valgte versjonen. , grønn betyr lagt til]]> - Dokumentet er tilbakeført til en tidligere versjon - Dette viser den valgte versjonen som HTML, bruk avviksvisningen hvis du ønsker å se forksjellene mellom to versjoner samtidig. - Tilbakefør til - Velg versjon - Vis - - - Rediger scriptfilen - - - Concierge - Innhold - Courier - Utvikler - Umbraco konfigurasjonsveiviser - Mediaarkiv - Medlemmer - Nyhetsbrev - Innstillinger - Statistikk - Oversettelse - Brukere - Hjelp - Skjemaer - - - De beste Umbraco opplæringsvideoer - - - Standardmal - Ordboksnøkkel - For å importere en dokumenttype, finn ".udt" filen på datamaskinen din ved å klikke "Utforsk" knappen og klikk "Importer" (du vil bli spurt om bekreftelse i det neste skjermbildet) - Ny tittel på arkfane - Nodetype - Type - Stilark - Script - Stilark-egenskap - Arkfane - Tittel på arkfane - Arkfaner - Hovedinnholdstype aktivert - Denne dokumenttypen bruker - som hoveddokumenttype. Arkfaner fra hoveddokumenttyper vises ikke og kan kun endres på hoveddokumenttypen selv. - Ingen egenskaper definert i denne arkfanen. Klikk på "legg til ny egenskap" lenken i toppen for å opprette en ny egenskap. - - - Sort order - Creation date - Sortering ferdig. - Dra elementene opp eller ned for å arrangere dem. Du kan også klikke kolonneoverskriftene for å sortere alt på en gang. - - - - En feil oppsto - Utilstrekkelige brukertillatelser, kunne ikke fullføre operasjonen - Avbrutt - Handlingen ble avbrutt av et tredjepartstillegg - Publisering ble avbrutt av et tredjepartstillegg - Egenskaptypen finnes allerede - Egenskapstype opprettet - DataType: %1%]]> - Egenskapstype slettet - Innholdstype lagret - Du har opprettet en arkfane - Arkfane slettet - Arkfane med id: %0% slettet - Stilarket ble ikke lagret - Stilarket ble lagret - Stilark lagret uten feil - Datatype lagret - Ordbokelement lagret - Publiseringen feilet fordi den overliggende siden ikke er publisert - Innhold publisert - og er nå synlig for besøkende - Innhold lagret - Husk å publisere for å gjøre endringene synlig for besøkende - Sendt for godkjenning - Endringer har blitt sendt til godkjenning - Media lagret - Media lagret uten feil - Medlem lagret - Stilarksegenskap lagret - Stilark lagret - Mal lagret - Feil ved lagring av bruker (sjekk loggen) - Bruker lagret - Brukertypen lagret - Filen ble ikke lagret - Filen kunne ikke lagres. Vennligst sjekk filrettigheter - Filen ble lagret - Filen ble lagret uten feil - Språk lagret - Malen ble ikke lagret - Vennligst forviss deg om at du ikke har to maler med samme alias - Malen ble lagret - Malen ble lagret uten feil! - Innhold avpublisert - Delmal lagret - Delmal lagret uten feil - Delmal ble ikke lagret! - En feil oppsto ved lagring av delmal - - - Bruk CSS syntaks f.eks: h1, .redHeader, .blueText - Rediger stilark - Rediger egenskap for stilark - Navn for å identifisere stilarksegenskapen i rik-tekst editoren - Forhåndsvis - Stiler - - - Rediger mal - Sett inn innholdsområde - Sett inn plassholder for innholdsområde - Sett inn ordbokselement - Sett inn makro - Sett inn Umbraco sidefelt - Hovedmal - Hurtigguide til Umbraco sine maltagger - Mal - - - Image - Macro - Sett inn element - Velg layout - Legg til rad - Legg til innhold - Slipp innhold - Raden har tilpasset design - Innholdstypen er ikke tillatt her - Innholdstypen er tillatt her - Klikk for å bygge inn - Klikk for å sette inn et bilde - Bildetekst... - Skriv her... - Rutenettoppsett - Et oppsett er det overordnede arbeidsområdet til ditt rutenett - du vil typisk kun behøve ett eller to - Legg til rutenettoppsett - Juster oppsettet ved å konfigurere kolonnebredder og legge til ytterligere seksjoner - Radkonfigurasjoner - Rader er forhåndsdefinerte celler arrangert vannrett - Legg til radkonfigurasjon - Juster raden ved å sette cellebredder og legge til flere celler - Kolonner - Totalt antall kolonner i rutenettet - Innstillinger - Konfigurer hvilke innstillinger brukeren kan endre - Stiler - Konfigurer hvilke stiler redaktørene kan endre - Tillatt alle editorer - Tillat alle radkonfigurasjoner - Bruk som standard - Velg ekstra - Velg standard - er lagt til - - - Alternativt felt - Alternativ tekst - Store/små bokstaver - Encoding - Felt som skal settes inn - Konverter linjeskift - Erstatter et linjeskift med htmltaggen <br> - Egendefinerte felt - Ja, kun dato - Formatter som dato - HTML koding - Formater spesialtegn med tilsvarende HTML-tegn. - Denne teksten vil settes inn etter verdien av feltet - Denne teksten vil settes inn før verdien av feltet - Små bokstaver - Ingen - Sett inn etter felt - Sett inn før felt - Rekursivt - Standardfelter - Store bokstaver - URL koding - Dersom innholdet av feltene skal sendes til en URL skal spesialtegn formatteres - Denne teksten vil benyttes dersom feltene over er tomme - Dette feltet vil benyttes dersom feltet over er tomt - Ja, med klokkeslett. Dato/tid separator: - - - Oversettelses detaljer - Last ned XML DTD - Felt - Inkluder undersider - - Ingen oversettelses-bruker funnet. Vennligst opprett en oversettelses-bruker før du begynner å sende innhold til oversetting - Siden '%0%' har blitt sendt til oversetting - Send til oversetting - Antall ord - Oversett til - Oversetting fullført. - Du kan forhåndsvise sidene du nettopp har oversatt ved å klikke nedenfor. Hvis den originale siden finnes, vil du få en sammenligning av sidene. - Oversetting mislykkes, XML filen kan være korrupt - Alternativer for oversetting - Oversetter - Last opp XML med oversettelse - - - Hurtigbufferleser - Papirkurv - Opprettede pakker - Datatyper - Ordbok - Installerte pakker - Installer utseende - Installer startpakke - Språk - Installer lokal pakke - Makroer - Mediatyper - Medlemmer - Medlemsgrupper - Roller - Medlemstyper - Dokumenttyper - Pakker - Pakker - Installer fra pakkeregister - Installer Runway - Runway moduler - Skriptfiler - Skript - Stiler - Maler - Brukertillatelser - Brukertyper typer - Brukere - - - Ny oppdatering er klar - %0% er klar, klikk her for å laste ned - Ingen forbindelse til server - Kunne ikke sjekke etter ny oppdatering. Se trace for mere info. - - - Administrator - Kategorifelt - Bytt passord - Nytt passord - Bekreft nytt passord - Du kan endre passordet til Umbraco ved å fylle ut skjemaet under og klikke "Bytt passord" knappen. - Innholdskanal - Beskrivelsesfelt - Deaktiver bruker - Dokumenttype - Redaktør - Utdragsfelt - Språk - Brukernavn - Øverste nivå i Media - Moduler - Deaktiver tilgang til Umbraco - Passord - Nullstill passord - Passordet er endret - Bekreft nytt passord - Nytt passord - Nytt passord kan ikke være blankt - Gjeldende passord - Feil passord - Nytt og bekreftet passord må være like - Nytt og bekreftet passord må være like - Overskriv tillatelser på undernoder - Du redigerer for øyeblikket tillatelser for sidene: - Velg sider for å redigere deres tillatelser - Søk i alle undersider - Startnode - Navn - Brukertillatelser - Forfatter - Endre - Din profil - Din historikk - Sesjonen utløper om - -
    diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/zh_tw.xml b/src/Umbraco.Web.UI/umbraco/config/lang/zh_tw.xml deleted file mode 100644 index 0a87631329..0000000000 --- a/src/Umbraco.Web.UI/umbraco/config/lang/zh_tw.xml +++ /dev/null @@ -1,1269 +0,0 @@ - - - - The Umbraco community - http://our.umbraco.org/documentation/Extending-Umbraco/Language-Files - - - 管理主機名稱 - 跟蹤審計 - 流覽節點 - 改變文檔類型 - 複製 - 創建 - 創建擴展包 - 刪除 - 禁用 - 清空回收站 - 匯出文檔類型 - 導入文檔類型 - 導入擴展包 - 即時編輯模式 - 退出 - 移動 - 提醒 - 公眾存取權限 - 發佈 - 取消發佈 - 重新載入節點 - 重新發佈整站 - 回復 - 許可權 - 回滾 - 提交至發佈者 - 發送給翻譯 - 排序 - 提交至發佈者 - 翻譯 - 更新 - 預設值 - - - 禁止訪問 - 添加功能變數名稱 - 移除 - 錯誤的節點 - 功能變數名稱錯誤 - 功能變數名稱重複 - 語言 - 功能變數名稱 - 新功能變數名稱 '%0%' 已創建 - 功能變數名稱 '%0%' 已刪除 - 功能變數名稱 '%0%' 已使用 - 功能變數名稱 '%0%' 已更新 - 編輯當前功能變數名稱 - - 繼承 - 語言 - 或從父節點繼承文化設定。
    - 也會改變目前節點設定,除非下方網域有其他項目。]]>
    - 功能變數名稱 - - - 查看 - - - 清除選擇 - 選擇 - 做別的事情 - 粗體 - 取消段落縮進 - 插入表單字段 - 插入圖片標題 - 編輯Html - 段落縮進 - 斜體 - 居中 - 左對齊 - 右對齊 - 插入連結 - 插入本地連結(錨點) - 圓點列表 - 數字清單 - 插入巨集 - 插入圖片 - 編輯關聯 - 回到清單 - 保存 - 保存並發佈 - 保存並提交審核 - 保存清單檢視 - 預覽 - 因未設置範本無法預覽 - 選擇樣式 - 顯示樣式 - 插入表格 - - - 要更改所選節點的文檔類型,先在列表中選擇合適的文檔類型。 - 然後設置當前文檔類型到新文檔類型的各欄位間的對應映射關係並保存。 - 內容已被重新發佈 - 當前屬性 - 當前類型 - 不能改變文檔類型,因為沒有可替代的類型。 - 文檔類型已更改 - 要映射的欄位 - 映射欄位 - 新範本 - 新類型 - - 內容 - 選擇新的文檔類型 - 選中文檔的類型已被成功更改為[new type],以下欄位被映射: - - 不能完成欄位映射,因為存在一個欄位映射至多欄位的問題。 - 僅顯示可作為替代的文檔類型。 - - - 已發表 - 關於本頁 - 別名 - (圖片的替代文本) - 替代連結 - 點擊編輯 - 創建者 - 創建者 - 更新者 - 創建時間 - 此文件創建的日期時間 - 文檔類型 - 編輯 - 過期於 - 該項發佈之後有更改 - 該項沒有發佈 - 最近發佈 - 沒有可供顯示的項目 - 此列表中沒有可供顯示的項目 - 媒體類型 - 媒體連結位址 - 會員組 - 角色 - 會員類型 - 沒有選擇時間 - 頁標題 - 屬性 - 該文檔不可見,因為其上級 '%0%' 未發佈。 - 糟糕:該文檔已發佈,但是沒有更新至緩存(內部錯誤) - 糟糕:沒辦法連結到此網址(內部錯誤-請參見記錄) - 糟糕:此文件已經發表,但是網址和其他內容相衝 %0% - 發佈 - 發佈狀態 - 發佈於 - 取消發表於 - 清空時間 - 排序完成 - 拖拽項目或按一下列頭即可排序,可以按住Shift多選。 - 統計 - 標題(可選) - 其他說明文字(可選) - 類型 - 取消發佈 - 最近編輯 - 本文件修改時間 - 移除文件 - 連結到文檔 - 會員組成員 - 非會員組成員 - 子項目 - 目標 - 預計發表的時間(伺服器端) - 這是什麼意思?]]> - - - 點選以便上傳 - 或按這裡選擇檔案 - 檔案大小上限為 - - - 新增一位會員 - 所有會員 - - - 您想在哪裡創建 %0% - 創建在 - 選擇類型和標題 - "文檔類型"處變更。]]> - "媒體類型"處變更。]]> - 文檔類型沒有相關範本 - 沒有資料夾 - 新資料類別 - - - 流覽您的網站 - - 隱藏 - 如果Umbraco沒有打開,您可能需要允許彈出式視窗。 - 已經在新視窗中打開 - 重啟 - 訪問 - 歡迎 - - - 留下 - 放棄變更 - 您有未存檔的變更 - 您確定要離開本頁? - 您有未存檔的變更 - - - 完成 - 刪除 %0% 個項目 - 刪除 %0% 個項目 - 刪除 %1% 個中的 %0% 個項目 - 刪除 %1% 個中的 %0% 個項目 - 已發佈 %0% 個項目 - 已發佈 %0% 個項目 - 已發佈 %1% 個中的 %0% 個項目 - 已發佈 %1% 個中的 %0% 個項目 - 取消發佈 %0% 個項目 - 取消發佈 %0% 個項目 - 取消發佈 %1 個中的 %0% 個項目 - 取消發佈 %1 個中的 %0% 個項目 - 移動 %0% 個項目 - 移動 %0% 個項目 - 移動 %1 個中的 %0% 個項目 - 移動 %1 個中的 %0% 個項目 - 複製 %0% 個項目 - 複製 %0% 個項目 - 複製 %1 個中的 %0% 個項目 - 複製 %1 個中的 %0% 個項目 - - - 錨點名稱 - 管理主機名稱 - 關閉窗口 - 您確定要刪除嗎 - 您確定要禁用嗎 - 您確定嗎? - 您確定嗎? - 剪切 - 編輯字典項 - 編輯語言 - 插入本地連結 - 插入字元 - 插入圖片標題 - 插入圖片 - 插入連結 - 插入巨集 - 插入表格 - 最近編輯 - 連結 - 內部連結: - 本地連結請用“#”號開頭 - 在新視窗中打開? - 巨集設置 - 本巨集沒有包含您可以編輯的屬性 - 粘貼 - 編輯許可權 - 正在清空回收站,請不要關閉窗口。 - 回收站已清空 - 從回收站刪除的項目將不可恢復 - regexlib.com的網站服務目前出現些狀況,而我們無能為力。我們對此不便感到十分抱歉。]]> - 查找規則運算式來驗證輸入,如: 'email、'zip-code'、'url'。 - 移除巨集 - 必填項目 - 網站已重建索引 - 網站緩存已刷新,所有已發佈的內容更新生效。 - 網站緩存將會刷新,所有已發佈的內容將會更新。 - 表格列數 - 表格行數 - 設定預留位置代碼 以便您要在子範本中插入內容到本範本時,填入此代碼到 <asp:content /> 裡面。]]> - 選擇預留位置代碼 於此清單中。您只能選擇目前父範本中的代碼。]]> - 點擊圖片查看完整大小 - 拾取項 - 查看緩存項 - 與原本相關 - 最友善的社群 - 頁面連結 - 打開此連結文檔至新視窗或標籤頁 - 媒體連結 - 選擇媒體 - 選擇圖示 - 選擇項目 - 選擇連結 - 選擇巨集 - 選擇內容 - 選擇會員 - 選擇會員群組 - 沒有找到任何圖示 - 本巨集沒有需要參數 - 外部登入提供者 - 例外細節 - 詳細記錄 - 內部例外 - 連結您的 - 取消連結您的 - 帳戶 - 選擇編輯器 - - - %0%' 編輯不同語言版本,
    您可以在左方選單「語言」中增添新的語言 - ]]>
    - 語言名稱 - - - 輸入您的使用者名稱 - 輸入您的密碼 - 確認您的密碼 - 命名此 %0%... - 輸入一個名稱 - 標籤... - 輸入一段描述... - 搜尋請輸入... - 過濾請輸入... - 增加標籤(每個標籤後請按輸入鍵)... - 輸入您的電子郵件 - - - 允許子項節點類型 - 創建 - 刪除選項卡 - 描述 - 新建選項卡 - 選項卡 - 縮略圖 - 新增自訂清單檢視 - 移除自訂清單檢視 - - - 添加預設值 - 資料庫資料類型 - 資料類型唯一標識 - 渲染控制項 - 按鈕 - 允許高級設置 - 允許快顯功能表 - 插入圖片預設最大 - 關聯的樣式表 - 顯示標籤 - 寬和高 - - - 資料已保存,但是發佈前您需要修正一些錯誤: - 當前成員提供程式不支援修改密碼(EnablePasswordRetrieval的值應該為true) - %0% 已存在 - 發現錯誤: - 發現錯誤: - 密碼最少%0%位元,且至少包含%1%位元非字母數位記號 - %0% 必須是整數 - %1% 中的 %0% 欄位是必填項 - %0% 是必填項 - %1% 中的 %0% 格式不正確 - %0% 格式不正確 - - - 收到伺服器傳來的錯誤 - 該檔案類型已被管理員禁用 - 注意,儘管配置中允許CodeMirror,但是它在IE上不夠穩定,所以無法在IE運行。 - 請為新的屬性類型填寫名稱和別名! - 許可權有問題,訪問指定文檔或資料夾失敗! - 讀取片段視圖腳本錯誤(檔案:%0%) - 讀取使用者控制項 %0% 錯誤 - 請輸入標題 - 請選擇類型 - 圖片尺寸大於原始尺寸不會提高圖片品質,您確定要把圖片尺寸變大嗎? - 預設打開頁面不存在,請聯繫管理員 - 請先選擇內容,再設置樣式。 - 沒有可用的樣式 - 請把游標放在您要合併的兩個儲存格中的左邊儲存格 - 非合併儲存格不能分離。 - - - 關於 - 操作 - 操作 - 添加 - 別名 - 所有 - 您確定嗎? - 回去 - 邊框 - - 取消 - 儲存格邊距 - 選擇 - 關閉 - 關閉窗口 - 備註 - 確認 - 強制屬性 - 繼續 - 複製 - 創建 - 資料庫 - 時間 - 默認 - 刪除 - 已刪除 - 正在刪除… - 設計 - 規格 - - 下載 - 編輯 - 已編輯 - 元素 - 郵箱 - 錯誤 - 查找文檔 - - 幫助 - 圖示 - 導入 - 內邊距 - 插入 - 安裝 - 不合格 - 對齊 - 語言 - 佈局 - 載入中 - 鎖定 - 登入 - 退出 - 登出 - 巨集 - 必要 - 移動 - 名稱 - 新的 - 下一步 - - 屬於 - 確定 - 打開 - - 密碼 - 路徑 - 預留位置代碼 - 請稍候… - 上一步 - 屬性 - 接收資料郵箱 - 回收站 - 保持狀態中 - 重命名 - 更新 - 必要 - 重試 - 許可權 - 搜索 - 伺服器 - 顯示 - 在發送時預覽 - 大小 - 排序 - 送出 - 類型 - 輸入內容開始搜尋… - - 更新 - 更新 - 上傳 - 連結位址 - 用戶 - 用戶名 - - 查看 - 歡迎… - - - 資料夾 - 搜尋結果 - 重新排列 - 我已經完成排列 - 預覽 - 更改密碼 - - 清單檢視 - 存檔中... - 目前 - 內嵌 - 選取的 - - - - - - 增加標籤頁 - 增加屬性 - 增加編輯器 - 增加範本 - 增加子節點 - 增加子項目 - 編輯資料類別 - 瀏覽區塊 - 捷徑 - 顯示捷徑 - 開關清單檢視 - 開關是否允許為根項目 - - - 背景色 - 粗體 - 前景色 - 字體 - 文本 - - - 頁面 - - - 無法連接到資料庫。 - 無法保存web.config檔,請手工修改。 - 發現資料庫 - 資料庫配置 - 安裝 按鈕來安裝Umbraco資料庫 %0% - ]]> - 下一步繼續。]]> - 沒有找到資料庫!請確認檔案"web.config"中的字串"connection string"是否正確。

    -

    請編輯檔案"web.config" (例如使用Visual Studio或您喜歡的編輯器),移動到檔案底部,並在名稱為"UmbracoDbDSN"的字串中設定資料庫連結資訊,並存檔。

    -

    - 點選重試按鈕當上述步驟完成。
    - - 在此查詢更多編輯web.config的資訊。

    ]]>
    - - 若需要時,請聯繫您的網路公司。如果您在本地機器或伺服器安裝的話,您也許需要聯絡系統管理者。]]> - - 點選升級按鈕來升級Umbraco資料庫 %0%

    -

    - 請別擔心 - 不會刪除任何資料而且馬上就會繼續運作! -

    - ]]>
    - 點選下一步繼續。]]> - 下一步繼續設定精靈。]]> - 預設使用者的密碼必須更改!]]> - 預設使用者已經被暫停或沒有Umbraco的使用權!

    不需更多的操作步驟。點選下一步繼續。]]> - 安裝後預設使用者的密碼已經成功修改!

    不需更多的操作步驟。點選下一步繼續。]]> - 密碼已更改 - 作為入門者,從視頻教程開始吧! - 點擊下一步 (或在Web.config中自行修改UmbracoConfigurationStatus),意味著您接受上述授權合約。 - 安裝失敗。 - 受影響的檔和資料夾 - 此處查看更多資訊 - 您需要對以下檔和資料夾授於ASP.NET用戶修改許可權 - 您的權限設定幾近完美!

    - 您可以正常執行Umbraco沒有任何問題,只差您將沒有辦法安裝那些建議需要全部許可權的插件。]]>
    - 如何解決 - 點擊閱讀文字版 - 影片教學來瞭解如何設定Umbraco的資料夾權限或閱讀文字版本。]]> - 您的權限可能有點小問題! -

    - 您可以正常執行Umbraco沒有任何問題,然而您將無法新增資料夾或安裝那些可以讓Umbraco發揮全力的插件。]]>
    - 您的權限設定尚未未完成! -

    - 您需要更新權限設定才能執行Umbraco。]]>
    - 您的權限設定完美無瑕!

    - 您已經準備好執行Umbraco和安裝插件!]]>
    - 解決資料夾問題 - 點此查看ASP.NET和創建資料夾的問題解決方案 - 設置資料夾許可權 - - 我要從頭開始 - 學習該怎麼做) - 您晚點仍可以選擇安裝Runway,請至開發者區域選擇安裝。 - ]]> - 您剛剛安裝了一個乾淨的系統,要繼續嗎? - “Runway”已安裝 - - 這是我們的模組推薦清單,選取您想要安裝的項目,或者至 查詢完整清單。 - ]]> - 僅推薦高級用戶使用 - 給我一個簡單的網站 - - "Runway"是一個提供基本檔案類別和範本的簡單網站。安裝程式會自動幫您設定Runway, - 但你仍可輕易編輯,擴充或移除它。它並非必要項目而且您可以在沒它的情況下完美執行Umbraco。然而, - Runway提供一個輕鬆簡便但基於寶貴經驗的平台讓您可以更快開始。 - 如果您安裝Runway,您還可以選擇名為「Runway模組」的基本區塊來加強Runway頁面。 -

    - - 內含於Runway: 首頁,準備開始頁面,模組安裝頁面。
    - 可選模組: 上方瀏覽列,網站地圖,聯絡,藝廊。 -
    - ]]>
    - “Runway”是什麼? - 步驟 1/5:接受授權合約 - 步驟 2/5:資料庫配置 - 步驟 3/5:文件許可權驗證 - 步驟 4/5:系統安全性 - 步驟 5/5:一切就緒,可以開始使用系統。 - 感謝選擇我們的產品 - 參觀您的新網站 -您剛安裝好Runway,何不瞧瞧它的模樣。]]> - 更多的幫忙與資訊 -從我們獲獎的社群得到幫助,瀏覽文件,或觀看免費影片來瞭解如何輕鬆架設網站,如何使用插件,和瞭解Umbraco項目名稱的快速上手指引。]]> - 系統 %0% 安裝完畢 - /web.config 檔案並且更新AppSetting中的字串UmbracoConfigurationStatus 內容為 '%0%'。]]> - 快速開始指引。
    如果您是Umbraco的新成員, -您可以在其中找到相當多的資源。]]>
    - 啟動Umbraco -想要管理您的網站時,只需開啟Umbraco後台便可增加內容,更新範本和樣式表,或增添新功能。]]> - 無法連接到資料庫。 - 系統版本 3 - 系統版本 4 - 觀看 -
    - 點選"下一步"來啟動精靈。]]>
    - - - 語言代碼 - 語言名稱 - - - 使用者在空閒狀態下將會自動登出 - 已更新,繼續工作。 - - - 超級星期天快樂 - 瘋狂星期一快樂 - 熱鬧星期二快樂 - 美妙星期三快樂 - 悅耳星期四快樂 - 時髦星期五快樂 - 喵喵星期六快樂 - 下方登入 - 登入使用 - 連線時間過了 - © 2001 - %0%
    Umbraco.com

    ]]>
    - 忘記密碼? - 一封內有重設密碼連結的電子郵件已經寄出給您 - 一封內有重設密碼連結的電子郵件已經寄到此信箱 - 回到登入畫面 - 請輸入新密碼 - 您的密碼已經更新 - 您點選的連結是無效或過期的 - Umbraco:重設密碼 - 您登入到後台的使用者名稱是:%0%

    點選這裡來重設您的密碼或將此連結複製/貼上到您的瀏覽器:

    %1%

    ]]>
    - - - 儀錶板 - 區域 - 內容 - - - 選擇上面的頁面… - %0% 被複製到 %1% - 將 %0% 複製到 - %0% 已被移動到 %1% - 將 %0% 移動到 - 作為內容的根結點,點“確定”。 - 尚未選擇節點,請選擇一個節點點擊“確定”。 - 類型不符不允許選擇 - 該項不能移到其子項 - 當前節點不能建在根節點下 - 您在子項的許可權不夠,不允許該操作。 - 複本和原本建立關聯 - - - 為 %0% 編寫通知 - - 哈嘍 %0%

    - -

    這是一封自動產生的信件來通知您 %1% 工作 - 已經在頁面 %2% 上由使用者 %3% 執行完成 -

    - -

    -

    更新摘要:

    - - %6% -
    -

    - - - -

    祝您有美好的一天!

    - Umbraco機器人 謹上 -

    ]]>
    - 在 %2%,[%0%] 關於 %1% 的通告已執行。 - 通知 - - - - 按鈕並點選該檔案。Umbraco擴展包通常有「.zip」的副檔名。 - ]]> - 作者 - 演示 - 文檔 - 中繼資料 - 名稱 - 擴展包不含任何項 -
    - 您可以點選下方「移除擴展包」來安全地移除此項目。]]>
    - 無可用更新 - 選項 - 說明 - 程式庫 - 確認卸載 - 已卸載 - 擴展包卸載成功 - 卸載 - - 注意: 任何文檔,媒體或需要這些項目才能運作的物件將會停止運作,並可能使得系統不穩定, - 請小心移除。若有疑慮,請聯絡擴展包作者。]]> - 從程式庫下載更新 - 更新擴展包 - 更新說明 - 擴展包有可用的更新,您可以從程式庫網站更新。 - 版本 - 版本歷史 - 訪問擴展包網站 - 擴展包已安裝 - 這個擴展包無法安裝,它需要Umbraco至少是版本 %0% - 移除中... - 下載中... - 匯入中... - 安裝中... - 重新啟動中,請稍後... - 都好了,您的瀏覽器將重新整理,請稍待... - - - 帶格式粘貼(不推薦) - 您所粘貼的文本含有特殊字元或格式,Umbraco將清除以適應網頁。 - 無格式粘貼 - 粘貼並移除格式(推薦) - - - 基於角色的保護 - 請使用Umbraco的會員群組。]]> - 使用基於角色的授權需要首先建立會員組。 - 錯誤頁 - 當用戶登錄後訪問沒有許可權的頁時顯示該頁 - 選擇限制訪問此頁的方式 - %0% 現在處於受保護狀態 - %0% 的保護被取消 - 登錄頁 - 選擇公開的登錄入口 - 取消保護 - 選擇一個包含登錄表單和提示資訊的頁 - 選擇訪問該頁的角色類型 - 為此頁設置帳號和密碼 - 單用戶保護 - 如果您只希望提供一個用戶名和密碼就能訪問 - - - - - - - - 包含未發佈的子項 - 正在發佈,請稍候… - %0% 中的 %1% 頁面已發佈… - %0% 已發佈 - %0% 及其子項已發佈 - 發佈 %0% 及其子項 - 發佈按鈕來將%0%的內容設定為公開。

    - 您可以同時發佈本頁以及其子項目若您點選下面的包含子頁。 - ]]>
    - - - 您尚未設定任何許可顏色 - - - 輸入外部連結 - 選擇內部連結 - 標題 - 連結 - 新視窗 - 輸入新標題 - 輸入連結 - - - 重設 - - - 當前版本 - 紅色 文字將不會顯示於所選版本,而綠色表示增加部分。]]> - 文檔已回滾 - 這顯示所選版本的HTML格式,如果您想要比較兩版本的差異,請使用比較檢視 - 回滾至 - 選擇版本 - 查看 - - - 編輯腳本 - - - Concierge - 內容 - Courier - 開發 - 設定精靈 - 媒體 - 會員 - 消息 - 設置 - 統計 - 翻譯 - 用戶 - 說明 - 表單 - - - 最好的Umbraco影片教學 - - - 預設範本 - 字典鍵 - 要導入文檔類型,請點擊“流覽”按鈕,再點擊“導入”,然後在您電腦上查找 ".udt"檔導入(下一頁中需要您再次確認) - 新建選項卡標題 - 節點類型 - 類型 - 樣式表 - 腳本 - 樣式表屬性 - 選項卡 - 選項卡標題 - 選項卡 - 主控文件類型啟動 - 該文檔類型使用 - 作為主控文件類型. 主控文件類型的標籤只能在主控文件類型裡修改。 - 沒有欄位設置在該標籤頁 - 增加圖示 - - - 排列順序 - 增添時間 - 排序完成。 - 上下拖拽項目或按一下列頭進行排序 - - - - 驗證 - 驗證錯誤一定要修正才能儲存項目 - 失敗 - 使用者權限不足,無法完成操作 - 已取消 - 操作被協力廠商外掛程式取消 - 發佈被協力廠商外掛程式取消 - 屬性類型已存在 - 屬性類型已創建 - 資料類別:%1%]]> - 屬性類型已刪除 - 內容類別型已保存 - 選項卡已創建 - 選項卡已刪除 - id為%0%的選項卡已刪除 - 樣式表未保存 - 樣式表已保存 - 樣式表保存,無錯誤。 - 資料類型已保存 - 字典項已保存 - 因為上級頁面未發佈導致發佈失敗! - 內容已發佈 - 公眾可見 - 內容已保存 - 請發佈以使更改生效 - 提交審核 - 更改已提交審核 - 媒體已保存 - 媒體已保存 - 會員已保存 - 樣式表屬性已保存 - 樣式表已保存 - 範本已保存 - 保存使用者出錯(請查看日誌) - 用戶已保存 - 用戶類型已保存 - 檔未保存 - 檔無法保存,請檢查許可權。 - 檔保存 - 檔保存,無錯誤。 - 語言已保存 - 媒體類別已儲存 - 會員類別已儲存 - 範本未保存 - 範本別名相同 - 範本已保存 - 範本保存,無錯誤。 - 內容已取消發佈 - 片段視圖已保存 - 片段視圖保存,無錯誤。 - 片段視圖未保存 - 片段視圖因為錯誤未能保存 - - - 使用CSS語法,如:h1、.redHeader、.blueTex。 - 編輯樣式表 - 編輯樣式屬性 - 編輯器中的樣式屬性名 - 預覽 - 樣式 - - - 編輯範本 - 插入內容區 - 插入內容預留位置 - 插入字典項 - 插入巨集 - 插入頁欄位 - 母版 - 範本標籤快速指南 - 範本 - - - Image - Macro - 選擇內容類別 - 選擇排列方式 - 新增一行 - 新增內容 - 放棄內容 - 設定已儲存 - 此處不允許有內容 - 此處允許有內容 - 點選來內嵌 - 點選來插入圖片 - 圖片標題... - 在此填寫... - 網格排列方式 - 排列是指網格編輯器的整體工作區域,通常您只需要一種或兩種排列方式 - 增加網格排列方式 - 藉由設定列寬以及增加新的區域來調整排列方式 - 行設定 - 行是預先水平排列的格子 - 增加行設定 - 藉由設定小格寬度和增添小格來調整此行 - - 網格排列方式的列總數 - 設定 - 調整設定編輯器可以改變的項目 - 樣式 - 調整樣式編輯器可以改變的項目 - 允許所有編輯器 - 允許所有行設定 - 定為預設 - 選擇額外 - 選擇預設 - 已增加 - - - 組合 - 您沒有增加任何選項卡 - 繼承的表格 - 增加屬性 - 必要標籤 - 允許清單檢視 - 允許內容項目顯示成可以排列及搜尋的清單,子項目不會被顯示 - 允許的範本 - 選擇哪些範本編輯器可以使用於此類別的內容 - 允許為根項目 - 允許編輯器新增此類別的內容為根項目 - 允許子節點種類 - 允許某些特定種類能夠成為此種類內容的子項目 - 選擇子節點 - 從已存在的文檔類別中繼承選項卡以及屬性。新選項卡將被新增至目前文檔種類或合併至已存在同名的選項卡中。 - 此內容種類已經用於集合中,因此不能重複添加本身。 - 沒有可用於集合的內容種類。 - 可用的編輯器 - 重複使用 - 編輯器設定 - 設定 - 是,刪除 - 已移至下層 - 已複製至下層 - 選擇要移動的資料夾 - 選擇要複製的資料夾 - 至下方樹狀結構 - 所有文檔種類 - 所有文檔 - 所有媒體項目 - 使用此文檔種類的將被永久刪除,請確認您也想要將它們刪除。 - 使用此媒體種類的將被永久刪除,請確認您也想要將它們刪除。 - 使用此會員種類的將被永久刪除,請確認您也想要將它們刪除。 - 以及所有使用此種類的文件項目 - 以及所有使用此種類的媒體項目 - 以及所有使用此種類的會員項目 - 會員可以編輯 - 顯示於會員資料 - - - 替代欄位 - 替代文本 - 大小寫 - 編碼 - 選取欄位 - 轉換分行符號 - 將換行符號取代成為HTML標籤 &lt;br&gt; - 自訂欄位 - 是,僅日期 - 格式化時間 - HTML編碼 - 將替換HTML中的特殊字元 - 將在欄位值後插入 - 將在欄位值前插入 - 小寫 - - 欄位後插入 - 欄位前插入 - 遞迴 - 標準欄位 - 大寫 - URL編碼 - 將格式化URL中的特殊字元 - 當上面欄位值為空時使用 - 該欄位僅在主欄位為空時使用 - 是,含時間,分隔符號為: - - - 翻譯詳情 - 下載 XML DTD - 欄位 - 包含子頁 - - 沒有翻譯員,請創建翻譯員角色的用戶。 - 頁面'%0%'已經發送給翻譯 - 發送頁面'%0%'以便翻譯 - 總字數 - 翻譯到 - 翻譯完成。 - 您可以流覽剛翻譯的頁面,如果原始頁存在,您將得到兩者的比較。 - 翻譯失敗,XML可能損壞了。 - 翻譯選項 - 翻譯員 - 上傳翻譯的xml - - - 緩存流覽 - 回收站 - 創建擴展包 - 資料類型 - 字典 - 已安裝的擴展包 - 安裝皮膚 - 安裝新手套件 - 語言 - 安裝本地擴展包 - 巨集 - 媒體類型 - 會員 - 會員組 - 角色 - 會員類型 - 文檔類型 - 相關類型 - 擴展包 - 擴展包 - 從線上程式庫安裝 - 安裝Runway - Runway模組 - Scripting文件 - 腳本 - 樣式表 - 範本 - - - 有可用更新 - %0%已就緒,點擊這裡下載 - 無到伺服器的連接 - 檢查更新失敗 - - - 管理員 - 分類欄位 - 更改密碼 - 更改密碼 - 確認新密碼 - 要改變密碼,請在框中輸入新密碼,然後按一下“更改密碼”。 - 內容頻道 - 描述欄位 - 禁用用戶 - 文檔類型 - 編輯 - 排除欄位 - 語言 - 登錄 - 默認打開媒體項 - 區域 - 禁用後臺管理介面 - 舊的密碼 - 密碼 - 重設密碼 - 您的密碼已更改! - 重輸密碼 - 輸入新密碼 - 新密碼不能為空! - 當前密碼 - 密碼錯誤 - 新密碼和重輸入的密碼不一致,請重試! - 重輸的密碼和原密碼不一致! - 替換子項許可權設置 - 您正在修改存取權限的頁面: - 選擇要修改許可權的頁 - 搜索子物件 - 預設打開內容項 - 用戶名 - 用戶許可權 - 撰稿人 - 改變 - 您的個人檔案 - 您的歷程記錄 - 連線到期於 - - - 驗證 - 以電子郵件驗證 - 以數字驗證 - 以網址驗證 - ...或輸入自訂驗證 - 必要欄位 - - - - 數值已設為推薦值:%0% - 在設定檔 %3% 中XPath %2% 的數值設為 %1% 。 - 在設定檔 %3% 中XPath %2% 的預期值設為 %1% ,但卻是 %0%。 - 在設定檔 %3% 中XPath %2% 的值為非預期值 %0%。 - - 自訂錯誤設定為 %0% - 自訂錯誤設定為 %0。建議在上線前改為 %1%。 - 自訂錯誤成功設定為 %0% - 巨集錯誤設為 %0% - 巨集錯誤設為 %0%,如此一來,當巨集有任何錯誤時會阻止某些或全部頁面正常載入。改正會將此設定 %1%。 - 巨集錯誤已設為 %0% - - 嘗試略過IIS自訂錯誤目前設為 %0%,而且您使用的IIS版本為 %1%。 - 嘗試略過IIS自訂錯誤目前設為 %0%,然而在您使用的IIS版本為 %2% 時,建議設定是 %1%。 - 嘗試略過IIS自訂錯誤已成功設為 %0%。 - - 檔案不存在:%0%。 - '%1%'中無法找到'%0%'。]]> - 有錯誤產生,請參閱下列錯誤的紀錄:%0%。 - 憑證驗證錯誤:%0% - 網址探查錯誤:%0% - '%1%' - 您目前使用HTTPS瀏覽本站:%0% - 在您的web.config檔案中,appSetting的umbracoUseSSL是設為false。當您開始使用HTTPS時,應將其改為 true。 - 在您的web.config檔案中,appSetting的umbracoUseSSL是設為 %0%,您的cookies %0% 標成安全。 - 無法在您的web.config檔案中,更新appSetting的umbracoUseSSL設定,錯誤訊息:%0% - - 開啟HTTPS - 在web.config檔案中,將appSetting的umbracoUseSSL設true。 - 在您的web.config檔案中,appSetting的umbracoUseSSL已設為 true,您的cookies 將被標成安全。 - 修正 - 無法修正比較種類檢查為'ShouldNotEqual'。 - 用提供的數值無法修正比較種類檢查為'ShouldEqual'。 - 沒有提供要修正檢查的數值。 - 偵錯編輯模式關閉。 - 偵錯編輯模式目前已開啟。上線前建議將其關閉。 - 偵錯編輯模式已成功關閉。 - 詳細記錄模式已關閉。 - 詳細記錄模式目前已開啟。上線前建議將其關閉。 - 詳細記錄模式已成功關閉。 - 所有資料夾已有正確權限設定。 - - %0%。]]> - %0%。如果無須寫入,不需採取行動。]]> - 所有檔案已有正確權限設定。 - - %0%。]]> - %0%。如果無須寫入,不需採取行動。]]> - X-Frame-Options 設定能控制網站是否可以被其他人IFRAMEd已找到。]]> - X-Frame-Options 設定能控制網站是否可以被其他人IFRAMEd沒有找到。]]> - 調整設定的標頭 - 在 web.config 的 httpProtocol/customHeaders 區域增加設定來防止本站被別的網站IFRAMEd。 - 在 web.config 的 httpProtocol/customHeaders 區域已經增加設定來防止本站被別的網站IFRAMEd。 - 無法更新web.config檔案,錯誤:%0% - - %0%。]]> - 在標頭中沒有找到揭露網站技術的資訊。 - 在 Web.config 檔案中,找不到 system.net/mailsettings。 - 在 Web.config 檔案中的 system.net/mailsettings,沒有設定 host 。 - SMTP設定正確,而且服務正常運作。 - SMTP伺服器 %0% : %1% 無法連接。請確認在Web.config 檔案中 system.net/mailsettings 設定正確。 - %0%。]]> - %0%。]]> - - - 停止網址追蹤器 - 啟動網址追蹤器 - 原本網址 - 轉址成 - 沒有任何轉址 - 當發佈後的頁面改名或移動時,會自動轉址至新網頁。 - 移除 - 您確定要移除從 %0% 到 %1% 的轉址嗎? - 轉址已移除。 - 移除轉址錯誤。 - - 您確定要停止轉址追蹤器? - 轉址追蹤器已停止。 - 停止轉址追蹤器錯誤,更多資訊請參閱您的紀錄檔。 - 轉址追蹤器已開啟。 - 啟動轉址追蹤器錯誤,更多資訊請參閱您的紀錄檔。 - -
    From d0016d6a7e86b42969757ba38839d538f9c3fc1f Mon Sep 17 00:00:00 2001 From: Stephan Date: Wed, 16 Jan 2019 10:40:04 +0100 Subject: [PATCH 384/469] Upgrade to MB -alpha.33 supporting elements --- build/NuSpecs/UmbracoCms.nuspec | 2 +- src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build/NuSpecs/UmbracoCms.nuspec b/build/NuSpecs/UmbracoCms.nuspec index 1b7a1c5ae1..3cb3d0d875 100644 --- a/build/NuSpecs/UmbracoCms.nuspec +++ b/build/NuSpecs/UmbracoCms.nuspec @@ -22,7 +22,7 @@ not want this to happen as the alpha of the next major is, really, the next major already. --> - + diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index ca4acd9d66..6967ac74c2 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -107,7 +107,7 @@ - 8.0.0-alpha.32 + 8.0.0-alpha.33 From c4418185ec2e83d48c335d1ca6860b27f427dba5 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 16 Jan 2019 21:27:14 +1100 Subject: [PATCH 385/469] Gets the angular view loading and allows navigating back to the view, cleans up non used lang keys --- .../Packaging/CompiledPackageXmlParser.cs | 2 +- .../Packaging/PackageDefinitionXmlParser.cs | 8 +- .../Packaging/PackagesRepository.cs | 86 +++++++++---------- .../mocks/services/localization.mocks.js | 7 -- .../src/common/resources/package.resource.js | 12 ++- src/Umbraco.Web.UI.Client/src/routes.js | 3 +- .../src/views/packages/edit.html | 10 +-- .../src/views/packages/options.controller.js | 43 ++++++++++ .../src/views/packages/options.html | 40 +++++++++ .../src/views/packages/overview.controller.js | 3 +- .../packages/views/installed.controller.js | 5 ++ .../src/views/packages/views/installed.html | 19 ++-- src/Umbraco.Web.UI/Umbraco/config/lang/cs.xml | 7 -- src/Umbraco.Web.UI/Umbraco/config/lang/da.xml | 7 -- src/Umbraco.Web.UI/Umbraco/config/lang/de.xml | 7 -- src/Umbraco.Web.UI/Umbraco/config/lang/en.xml | 7 -- .../Umbraco/config/lang/en_us.xml | 7 -- src/Umbraco.Web.UI/Umbraco/config/lang/es.xml | 8 -- src/Umbraco.Web.UI/Umbraco/config/lang/fr.xml | 7 -- src/Umbraco.Web.UI/Umbraco/config/lang/he.xml | 7 -- src/Umbraco.Web.UI/Umbraco/config/lang/it.xml | 7 -- src/Umbraco.Web.UI/Umbraco/config/lang/ja.xml | 7 -- src/Umbraco.Web.UI/Umbraco/config/lang/ko.xml | 7 -- src/Umbraco.Web.UI/Umbraco/config/lang/nb.xml | 7 -- src/Umbraco.Web.UI/Umbraco/config/lang/nl.xml | 7 -- src/Umbraco.Web.UI/Umbraco/config/lang/pl.xml | 7 -- src/Umbraco.Web.UI/Umbraco/config/lang/pt.xml | 7 -- src/Umbraco.Web.UI/Umbraco/config/lang/ru.xml | 7 -- src/Umbraco.Web.UI/Umbraco/config/lang/sv.xml | 7 -- src/Umbraco.Web.UI/Umbraco/config/lang/tr.xml | 7 -- src/Umbraco.Web.UI/Umbraco/config/lang/zh.xml | 7 -- .../Umbraco/config/lang/zh_tw.xml | 7 -- src/Umbraco.Web.UI/umbraco/config/lang/nb.xml | 7 -- .../umbraco/config/lang/zh_tw.xml | 7 -- src/Umbraco.Web/Editors/PackageController.cs | 22 ++--- .../Editors/PackageInstallController.cs | 11 +-- .../ContentEditing/InstalledPackageModel.cs | 39 --------- src/Umbraco.Web/Umbraco.Web.csproj | 1 - 38 files changed, 180 insertions(+), 286 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/views/packages/options.controller.js create mode 100644 src/Umbraco.Web.UI.Client/src/views/packages/options.html delete mode 100644 src/Umbraco.Web/Models/ContentEditing/InstalledPackageModel.cs diff --git a/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs b/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs index 7f62f4fd27..9e6339178e 100644 --- a/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs +++ b/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs @@ -51,7 +51,7 @@ namespace Umbraco.Core.Packaging IconUrl = package.Element("iconUrl")?.Value, UmbracoVersion = new Version((int)requirements.Element("major"), (int)requirements.Element("minor"), (int)requirements.Element("patch")), UmbracoVersionRequirementsType = requirements.AttributeValue("type").IsNullOrWhiteSpace() ? RequirementsType.Legacy : Enum.Parse(requirements.AttributeValue("type"), true), - PackageView = package.Element("view")?.Value, + PackageView = xml.Root.Element("view")?.Value, Actions = xml.Root.Element("Actions")?.ToString(SaveOptions.None) ?? "", //take the entire outer xml value Files = xml.Root.Element("files")?.Elements("file")?.Select(CompiledPackageFile.Create).ToList() ?? new List(), Macros = xml.Root.Element("Macros")?.Elements("macro") ?? Enumerable.Empty(), diff --git a/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs b/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs index 00255fa43a..b66cdb095c 100644 --- a/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs +++ b/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs @@ -34,6 +34,7 @@ namespace Umbraco.Core.Packaging PackageId = xml.AttributeValue("packageGuid"), IconUrl = xml.AttributeValue("iconUrl") ?? string.Empty, UmbracoVersion = xml.AttributeValue("umbVersion"), + PackageView = xml.AttributeValue("view") ?? string.Empty, License = xml.Element("license")?.Value ?? string.Empty, LicenseUrl = xml.Element("license")?.AttributeValue("url") ?? string.Empty, Author = xml.Element("author")?.Value ?? string.Empty, @@ -49,8 +50,7 @@ namespace Umbraco.Core.Packaging Languages = xml.Element("languages")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(), DictionaryItems = xml.Element("dictionaryitems")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(), DataTypes = xml.Element("datatypes")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List(), - Files = xml.Element("files")?.Elements("file").Select(x => x.Value).ToList() ?? new List(), - PackageView = xml.Element("view")?.Value ?? string.Empty + Files = xml.Element("files")?.Elements("file").Select(x => x.Value).ToList() ?? new List() }; return retVal; @@ -77,6 +77,7 @@ namespace Umbraco.Core.Packaging new XAttribute("iconUrl", def.IconUrl ?? string.Empty), new XAttribute("umbVersion", def.UmbracoVersion), new XAttribute("packageGuid", def.PackageId), + new XAttribute("view", def.PackageView ?? string.Empty), new XElement("license", new XCData(def.License ?? string.Empty), @@ -100,8 +101,7 @@ namespace Umbraco.Core.Packaging new XElement("macros", string.Join(",", def.Macros ?? Array.Empty())), new XElement("files", (def.Files ?? Array.Empty()).Where(x => !x.IsNullOrWhiteSpace()).Select(x => new XElement("file", x))), new XElement("languages", string.Join(",", def.Languages ?? Array.Empty())), - new XElement("dictionaryitems", string.Join(",", def.DictionaryItems ?? Array.Empty())), - new XElement("view", def.PackageView ?? string.Empty)); + new XElement("dictionaryitems", string.Join(",", def.DictionaryItems ?? Array.Empty()))); return packageXml; } diff --git a/src/Umbraco.Core/Packaging/PackagesRepository.cs b/src/Umbraco.Core/Packaging/PackagesRepository.cs index 5531e05705..1df232f62d 100644 --- a/src/Umbraco.Core/Packaging/PackagesRepository.cs +++ b/src/Umbraco.Core/Packaging/PackagesRepository.cs @@ -161,30 +161,30 @@ namespace Umbraco.Core.Packaging try { //Init package file - var packageManifest = CreatePackageManifest(out var manifestRoot, out var filesXml); + var compiledPackageXml = CreateCompiledPackageXml(out var root, out var filesXml); //Info section - manifestRoot.Add(GetPackageInfoXml(definition)); + root.Add(GetPackageInfoXml(definition)); - PackageDocumentsAndTags(definition, manifestRoot); - PackageDocumentTypes(definition, manifestRoot); - PackageTemplates(definition, manifestRoot); - PackageStylesheets(definition, manifestRoot); - PackageMacros(definition, manifestRoot, filesXml, temporaryPath); - PackageDictionaryItems(definition, manifestRoot); - PackageLanguages(definition, manifestRoot); - PackageDataTypes(definition, manifestRoot); + PackageDocumentsAndTags(definition, root); + PackageDocumentTypes(definition, root); + PackageTemplates(definition, root); + PackageStylesheets(definition, root); + PackageMacros(definition, root, filesXml, temporaryPath); + PackageDictionaryItems(definition, root); + PackageLanguages(definition, root); + PackageDataTypes(definition, root); //Files foreach (var fileName in definition.Files) - AppendFileToManifest(fileName, temporaryPath, filesXml); + AppendFileToPackage(fileName, temporaryPath, filesXml); - //Load control on install... + //Load view on install... if (!string.IsNullOrEmpty(definition.PackageView)) { var control = new XElement("view", definition.PackageView); - AppendFileToManifest(definition.PackageView, temporaryPath, filesXml); - manifestRoot.Add(control); + AppendFileToPackage(definition.PackageView, temporaryPath, filesXml); + root.Add(control); } //Actions @@ -196,20 +196,20 @@ namespace Umbraco.Core.Packaging //this will be formatted like a full xml block like ... and we want the child nodes var parsed = XElement.Parse(definition.Actions); actionsXml.Add(parsed.Elements()); - manifestRoot.Add(actionsXml); + root.Add(actionsXml); } catch (Exception e) { - _logger.Warn(e, "Could not add package actions to the package manifest, the xml did not parse"); + _logger.Warn(e, "Could not add package actions to the package, the xml did not parse"); } } - var manifestFileName = temporaryPath + "/package.xml"; + var packageXmlFileName = temporaryPath + "/package.xml"; - if (File.Exists(manifestFileName)) - File.Delete(manifestFileName); + if (File.Exists(packageXmlFileName)) + File.Delete(packageXmlFileName); - packageManifest.Save(manifestFileName); + compiledPackageXml.Save(packageXmlFileName); // check if there's a packages directory below media @@ -242,7 +242,7 @@ namespace Umbraco.Core.Packaging throw new InvalidOperationException("Validation failed, there is invalid data on the model: " + string.Join(", ", results.Select(x => x.ErrorMessage))); } - private void PackageDataTypes(PackageDefinition definition, XContainer manifestRoot) + private void PackageDataTypes(PackageDefinition definition, XContainer root) { var dataTypes = new XElement("DataTypes"); foreach (var dtId in definition.DataTypes) @@ -252,10 +252,10 @@ namespace Umbraco.Core.Packaging if (dataType == null) continue; dataTypes.Add(_serializer.Serialize(dataType)); } - manifestRoot.Add(dataTypes); + root.Add(dataTypes); } - private void PackageLanguages(PackageDefinition definition, XContainer manifestRoot) + private void PackageLanguages(PackageDefinition definition, XContainer root) { var languages = new XElement("Languages"); foreach (var langId in definition.Languages) @@ -265,10 +265,10 @@ namespace Umbraco.Core.Packaging if (lang == null) continue; languages.Add(_serializer.Serialize(lang)); } - manifestRoot.Add(languages); + root.Add(languages); } - private void PackageDictionaryItems(PackageDefinition definition, XContainer manifestRoot) + private void PackageDictionaryItems(PackageDefinition definition, XContainer root) { var dictionaryItems = new XElement("DictionaryItems"); foreach (var dictionaryId in definition.DictionaryItems) @@ -278,10 +278,10 @@ namespace Umbraco.Core.Packaging if (di == null) continue; dictionaryItems.Add(_serializer.Serialize(di, false)); } - manifestRoot.Add(dictionaryItems); + root.Add(dictionaryItems); } - private void PackageMacros(PackageDefinition definition, XContainer manifestRoot, XContainer filesXml, string temporaryPath) + private void PackageMacros(PackageDefinition definition, XContainer root, XContainer filesXml, string temporaryPath) { var macros = new XElement("Macros"); foreach (var macroId in definition.Macros) @@ -291,14 +291,14 @@ namespace Umbraco.Core.Packaging var macroXml = GetMacroXml(outInt, out var macro); if (macroXml == null) continue; macros.Add(macroXml); - //if the macro has a file copy it to the manifest + //if the macro has a file copy it to the xml if (!string.IsNullOrEmpty(macro.MacroSource)) - AppendFileToManifest(macro.MacroSource, temporaryPath, filesXml); + AppendFileToPackage(macro.MacroSource, temporaryPath, filesXml); } - manifestRoot.Add(macros); + root.Add(macros); } - private void PackageStylesheets(PackageDefinition definition, XContainer manifestRoot) + private void PackageStylesheets(PackageDefinition definition, XContainer root) { var stylesheetsXml = new XElement("Stylesheets"); foreach (var stylesheetName in definition.Stylesheets) @@ -308,10 +308,10 @@ namespace Umbraco.Core.Packaging if (xml != null) stylesheetsXml.Add(xml); } - manifestRoot.Add(stylesheetsXml); + root.Add(stylesheetsXml); } - private void PackageTemplates(PackageDefinition definition, XContainer manifestRoot) + private void PackageTemplates(PackageDefinition definition, XContainer root) { var templatesXml = new XElement("Templates"); foreach (var templateId in definition.Templates) @@ -321,10 +321,10 @@ namespace Umbraco.Core.Packaging if (template == null) continue; templatesXml.Add(_serializer.Serialize(template)); } - manifestRoot.Add(templatesXml); + root.Add(templatesXml); } - private void PackageDocumentTypes(PackageDefinition definition, XContainer manifestRoot) + private void PackageDocumentTypes(PackageDefinition definition, XContainer root) { var contentTypes = new HashSet(); var docTypesXml = new XElement("DocumentTypes"); @@ -338,10 +338,10 @@ namespace Umbraco.Core.Packaging foreach (var contentType in contentTypes) docTypesXml.Add(_serializer.Serialize(contentType)); - manifestRoot.Add(docTypesXml); + root.Add(docTypesXml); } - private void PackageDocumentsAndTags(PackageDefinition definition, XContainer manifestRoot) + private void PackageDocumentsAndTags(PackageDefinition definition, XContainer root) { //Documents and tags if (string.IsNullOrEmpty(definition.ContentNodeId) == false && int.TryParse(definition.ContentNodeId, out var contentNodeId)) @@ -356,7 +356,7 @@ namespace Umbraco.Core.Packaging //Create the Documents/DocumentSet node - manifestRoot.Add( + root.Add( new XElement("Documents", new XElement("DocumentSet", new XAttribute("importMode", "root"), @@ -438,12 +438,12 @@ namespace Umbraco.Core.Packaging } /// - /// Appends a file to package manifest and copies the file to the correct folder. + /// Appends a file to package and copies the file to the correct folder. /// /// The path. /// The package directory. /// The files xml node - private static void AppendFileToManifest(string path, string packageDirectory, XContainer filesXml) + private static void AppendFileToPackage(string path, string packageDirectory, XContainer filesXml) { if (!path.StartsWith("~/") && !path.StartsWith("/")) path = "~/" + path; @@ -584,12 +584,12 @@ namespace Umbraco.Core.Packaging return info; } - private static XDocument CreatePackageManifest(out XElement root, out XElement files) + private static XDocument CreateCompiledPackageXml(out XElement root, out XElement files) { files = new XElement("files"); root = new XElement("umbPackage", files); - var packageManifest = new XDocument(root); - return packageManifest; + var compiledPackageXml = new XDocument(root); + return compiledPackageXml; } private XDocument EnsureStorage(out string packagesFile) diff --git a/src/Umbraco.Web.UI.Client/src/common/mocks/services/localization.mocks.js b/src/Umbraco.Web.UI.Client/src/common/mocks/services/localization.mocks.js index ec1175ab6c..87955739fb 100644 --- a/src/Umbraco.Web.UI.Client/src/common/mocks/services/localization.mocks.js +++ b/src/Umbraco.Web.UI.Client/src/common/mocks/services/localization.mocks.js @@ -453,13 +453,11 @@ angular.module('umbraco.mocks'). "notifications_notifications": "Notifications", "packager_chooseLocalPackageText": " Choose Package from your machine, by clicking the Browse
    button and locating the package. Umbraco packages usually have a '.umb' or '.zip' extension. ", "packager_packageAuthor": "Author", - "packager_packageDemonstration": "Demonstration", "packager_packageDocumentation": "Documentation", "packager_packageMetaData": "Package meta data", "packager_packageName": "Package name", "packager_packageNoItemsHeader": "Package doesn't contain any items", "packager_packageNoItemsText": "This package file doesn't contain any items to uninstall.

    You can safely remove this from the system by clicking 'uninstall package' below.", - "packager_packageNoUpgrades": "No upgrades available", "packager_packageOptions": "Package options", "packager_packageReadme": "Package readme", "packager_packageRepository": "Package repository", @@ -468,12 +466,7 @@ angular.module('umbraco.mocks'). "packager_packageUninstalledText": "The package was successfully uninstalled", "packager_packageUninstallHeader": "Uninstall package", "packager_packageUninstallText": "You can unselect items you do not wish to remove, at this time, below. When you click 'confirm uninstall' all checked-off items will be removed.
    Notice: any documents, media etc depending on the items you remove, will stop working, and could lead to system instability, so uninstall with caution. If in doubt, contact the package author.", - "packager_packageUpgradeDownload": "Download update from the repository", - "packager_packageUpgradeHeader": "Upgrade package", - "packager_packageUpgradeInstructions": "Upgrade instructions", - "packager_packageUpgradeText": " There's an upgrade available for this package. You can download it directly from the Umbraco package repository.", "packager_packageVersion": "Package version", - "packager_viewPackageWebsite": "View package website", "paste_doNothing": "Paste with full formatting (Not recommended)", "paste_errorMessage": "The text you're trying to paste contains special characters or formatting. This could be caused by copying text from Microsoft Word. Umbraco can remove special characters or formatting automatically, so the pasted content will be more suitable for the web.", "paste_removeAll": "Paste as raw text without any formatting at all", diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/package.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/package.resource.js index 0d74d0fdd3..7519341327 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/package.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/package.resource.js @@ -175,7 +175,17 @@ function packageResource($q, $http, umbDataFormatter, umbRequestHelper) { umbRequestHelper.getApiUrl( "packageApiBaseUrl", "GetCreatedPackageById", - [{ id: id }])), + { id: id })), + 'Failed to get package'); + }, + + getInstalledById: function (id) { + return umbRequestHelper.resourcePromise( + $http.get( + umbRequestHelper.getApiUrl( + "packageApiBaseUrl", + "GetInstalledPackageById", + { id: id })), 'Failed to get package'); }, diff --git a/src/Umbraco.Web.UI.Client/src/routes.js b/src/Umbraco.Web.UI.Client/src/routes.js index 64bddb16e2..c2d3ea2df8 100644 --- a/src/Umbraco.Web.UI.Client/src/routes.js +++ b/src/Umbraco.Web.UI.Client/src/routes.js @@ -158,7 +158,8 @@ app.config(function ($routeProvider) { } //special case for the package section - if ($routeParams.section.toLowerCase() === "packages" && $routeParams.tree.toLowerCase() === "packages" && $routeParams.method !== "edit") { + var packagePages = ["edit", "options"]; + if ($routeParams.section.toLowerCase() === "packages" && $routeParams.tree.toLowerCase() === "packages" && packagePages.indexOf($routeParams.method.toLowerCase()) === -1) { $scope.templateUrl = "views/packages/overview.html"; return; } diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html index 5163fadfb5..5ad5ac2522 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html @@ -255,13 +255,13 @@ + label="Package options view" + description="Load this view after installation (ex: App_Plugins/MyApp/MyPackageOptions.html). It can be used to configure your package at any time by clicking Options on the installed package listing"> diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/options.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/options.controller.js new file mode 100644 index 0000000000..8ffd282e0d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/packages/options.controller.js @@ -0,0 +1,43 @@ +(function () { + "use strict"; + + function OptionsController($scope, $location, $routeParams, packageResource, umbRequestHelper) { + + const vm = this; + + vm.showBackButton = true; + vm.loading = true; + vm.back = back; + + const packageId = $routeParams.id; + + function onInit() { + + packageResource.getInstalledById(packageId).then(pck => { + vm.package = pck; + vm.loading = false; + + //make sure the packageView is formatted as a virtual path + pck.packageView = pck.packageView.startsWith("/~") + ? pck.packageView + : pck.packageView.startsWith("/") + ? "~" + pck.packageView + : "~/" + pck.packageView; + + pck.packageView = umbRequestHelper.convertVirtualToAbsolutePath(pck.packageView); + + }); + } + + function back() { + $location.path("packages/packages/installed"); + } + + + onInit(); + + } + + angular.module("umbraco").controller("Umbraco.Editors.Packages.OptionsController", OptionsController); + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/options.html b/src/Umbraco.Web.UI.Client/src/views/packages/options.html new file mode 100644 index 0000000000..d75604d094 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/packages/options.html @@ -0,0 +1,40 @@ +
    + +
    + + + + + + + + + + +

    + This package has no configuration view +

    + +
    + +
    + + + + +
    + +
    + +
    diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/overview.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/overview.controller.js index 59fa79dc26..f4c1ab9de4 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/overview.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/overview.controller.js @@ -17,8 +17,7 @@ } if (installPackageUri && installPackageUri !== "installed") { - //navigate to the custom installer screen, if it is just "installed", then we'll - //show the installed view + //navigate to the custom installer screen, if it is just "installed" it means there is no custom installer screen $location.path(installPackageUri).search(""); } else { diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/views/installed.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/views/installed.controller.js index 5265897708..3b6422ace4 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/views/installed.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/views/installed.controller.js @@ -7,6 +7,7 @@ vm.confirmUninstall = confirmUninstall; vm.uninstallPackage = uninstallPackage; + vm.packageOptions = packageOptions; vm.state = "list"; vm.installState = { status: "" @@ -34,6 +35,10 @@ }); } + function packageOptions(pck) { + $location.path("packages/packages/options/" + pck.id); + } + function confirmUninstall(pck) { vm.state = "packageDetails"; vm.package = pck; diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/views/installed.html b/src/Umbraco.Web.UI.Client/src/views/packages/views/installed.html index 3c443e0bac..888bf02c4e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/views/installed.html +++ b/src/Umbraco.Web.UI.Client/src/views/packages/views/installed.html @@ -23,12 +23,19 @@ - + + + + diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/cs.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/cs.xml index f3b16def54..db780bb358 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/cs.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/cs.xml @@ -617,14 +617,12 @@ a výběrem balíčku. Balíčky umbraco mají obvykle přípony ".umb" nebo ".zip". ]]> Autor - Ukázka Dokumentace Meta data balíčku Název balíčku Balíček neobsahuje žádné položky
    Můžete jej ze systému bezpečně odstranit kliknutím na "odebrat balíček" níže.]]>
    - Žádné aktualizace nejsou dostupné Možnosti balíčku Čti mě balíčku Úložiště balíčku @@ -635,12 +633,7 @@ Upozornění: všechny dokumenty, media atd. závislé na položkách, které odstraníte, přestanou pracovat a mohou vést k nestabilitě systému, takže odinstalovávejte opatrně. Jste-li na pochybách, kontaktujte autora balíčku.]]> - Stáhnout aktualizaci z úložiště - Balíček s aktualizací - Pokyny pro aktualizaci - Pro tento balíček je dostupná aktualizace. Můžete si ji stáhnout přímo z úložiště balíčků umbraco. Verze balíčku - Zobrazit web balíčku Vložit s úplným formatováním (nedoporučeno) diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/da.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/da.xml index 523531947a..39e1341f37 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/da.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/da.xml @@ -840,13 +840,11 @@ Mange hilsner fra Umbraco robotten Denne pakke er kompatibel med de følgende versioner af Umbraco, som rapporteret af community-medlemmer. Fuld kompatibilitet kan ikke garanteres for versioner rapporteret nedenfor 100% Eksterne kilder Forfatter - Demonstration Dokumentation Pakke meta data Pakkenavn Pakken indeholder ingen elementer
    Du kan roligt fjerne denne fra systemet ved at klikke på "Fjern pakke" nedenfor.]]>
    - Ingen opdateringer tilgængelige Pakkevalg Pakke læs mig Pakke opbevaringsbase @@ -856,12 +854,7 @@ Mange hilsner fra Umbraco robotten Afinstallér pakke Bemærk: at dokumenter og medier som afhænger af denne pakke vil muligvis holde op med at virke, så vær forsigtig. Hvis i tvivl, kontakt personen som har udviklet pakken.]]> - Download opdatering fra opbevaringsbasen - Opdatér pakke - Opdateringsinstrukser - Der er en tilgængelig opdatering til denne pakke. Du kan downloade den direkte fra Umbracos pakke opbevaringsbase. Pakke version - Se pakkeudviklerens website Pakke allerede installeret Denne pakke kan ikke installeres, den kræver en minimum Umbraco version af Afinstallerer... diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/de.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/de.xml index 915b25208e..1be81fb10f 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/de.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/de.xml @@ -610,13 +610,11 @@ Wenn Sie sich für Runway entscheiden, können Sie optional Blöcke nutzen, die Wählen Sie ein Paket auf Ihrem lokalen Computer über "Datei auswählen" aus. <br />Umbraco-Pakete besitzen üblicherweise die Dateiendungen ".umb" oder ".zip". Autor - Demonstration Dokumentation Paket-Meta-Daten Name des Pakets Paket enthält keine Elemente Die Paket-Datei enthält keine Elemente die deinstalliert werden können.<br/><br/>Sie können das Paket ohne Gefahr deinstallieren indem Sie "Paket deinstallieren" anklicken. - Keine Updates für das Paket verfügbar Paket-Optionen Informationen zum Paket Paket-Repository @@ -625,12 +623,7 @@ Wenn Sie sich für Runway entscheiden, können Sie optional Blöcke nutzen, die Das Paket wurde erfolgreich deinstalliert Paket deinstallieren Sie können einzelne Elemente, die Sie nicht deinstallieren möchten, unten abwählen. Wenn Sie "Deinstallation bestätigen" klicken, werden alle markierten Elemente entfernt.<br /><span style="color: Red; font-weight: bold;">Achtung:</span> alle Dokumente, Medien, etc, die von den zu entfernenden Elementen abhängen, werden nicht mehr funktionieren und im Zweifelsfall kann dass gesamte CMS instabil werden. Bitte deinstallieren Sie also mit Vorsicht. Falls Sie unsicher sind, kontaktieren Sie den Autor des Pakets. - Update vom Paket-Repository herunterladen - Paket-Update - Hinweise für die Durchführung des Updates - Es ist ein Update für dieses Paket verfügbar. Sie können es direkt vom Umbraco-Paket-Repository herunterladen. Version des Pakets - Paket-Webseite aufrufen Einfügen mit Formatierung (Nicht empfohlen) diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml index dad27d99fe..d50cac4ac4 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml @@ -1090,14 +1090,12 @@ To manage your website, simply open the Umbraco back office and start adding con This package is compatible with the following versions of Umbraco, as reported by community members. Full compatability cannot be gauranteed for versions reported below 100% External sources Author - Demonstration Documentation Package meta data Package name Package doesn't contain any items
    You can safely remove this from the system by clicking "uninstall package" below.]]>
    - No upgrades available Package options Package readme Package repository @@ -1108,12 +1106,7 @@ To manage your website, simply open the Umbraco back office and start adding con Notice: any documents, media etc depending on the items you remove, will stop working, and could lead to system instability, so uninstall with caution. If in doubt, contact the package author.]]> - Download update from the repository - Upgrade package - Upgrade instructions - There's an upgrade available for this package. You can download it directly from the Umbraco package repository. Package version - View package website Package already installed This package cannot be installed, it requires a minimum Umbraco version of Uninstalling... diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml index ab37cf8025..23efe8047e 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml @@ -1117,14 +1117,12 @@ To manage your website, simply open the Umbraco back office and start adding con This package is compatible with the following versions of Umbraco, as reported by community members. Full compatability cannot be gauranteed for versions reported below 100% External sources Author - Demonstration Documentation Package meta data Package name Package doesn't contain any items
    You can safely remove this from the system by clicking "uninstall package" below.]]>
    - No upgrades available Package options Package readme Package repository @@ -1135,13 +1133,8 @@ To manage your website, simply open the Umbraco back office and start adding con Notice: any documents, media etc depending on the items you remove, will stop working, and could lead to system instability, so uninstall with caution. If in doubt, contact the package author.]]> - Download update from the repository - Upgrade package - Upgrade instructions - There's an upgrade available for this package. You can download it directly from the Umbraco package repository. Package version Upgrading from version - View package website Package already installed This package cannot be installed, it requires a minimum Umbraco version of Uninstalling... diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/es.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/es.xml index 7f35e90083..090ecc875e 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/es.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/es.xml @@ -863,14 +863,11 @@ Este paquete es compatible con las siguientes versiones de Umbraco, declaradas según miembros de la comunidad. No se puede garantizar compatibilidad completa para versiones declaradas debajo del 100% Fuentes externas Autor - Documentación Meta datos del paquete Nombre del paquete El paquete no contiene ningún elemento
    Puedes eliminarlo del sistema de forma segura seleccionando la opción "desinstalar paquete" de abajo.]]>
    - No hay actualizaciones disponibles Opciones del paquete Léeme del paquete Repositorio de paquetes @@ -879,12 +876,7 @@ El paquete se ha desinstalado correctamente Desinstalar paquete Nota: cualquier documento, archivo etc dependiente de los elementos eliminados, dejará de funcionar, y puede conllevar inestabilidad en el sistema, por lo que lleva cuidado al desinstalar elementos. En caso de duda, contacta con el autor del paquete.]]> - Descargar actualización del repositorio - Actualizar paquete - Instrucciones de actualización - Hay una actualización disponible para este paquete. Puedes descargarla directamente del repositorio de paquetes de Umbraco. Versión del paquete - Ver página web del paquete Paquete ya instalado Este paquete no se puede instalar, requiere un versión mínima de Umbraco de Desinstalando... diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/fr.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/fr.xml index 04b2cea4df..b6c23d7b63 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/fr.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/fr.xml @@ -1025,14 +1025,12 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Ce package est compatible avec les versions suivantes de Umbraco, selon les rapports des membres de la communauté. Une compatibilité complète ne peut pas être garantie pour les versions rapportées sous 100% Sources externes Auteur - Démo Documentation Meta data du package Nom du package Le package ne contient aucun élément
    Vous pouvez supprimer tranquillement ce package de votre installation en cliquant sur "Désinstaller le package" ci-dessous.]]>
    - Aucune mise à jour disponible Options du package Package readme Repository des packages @@ -1043,12 +1041,7 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Remarque : tous les documents, media etc. dépendant des éléments que vous supprimez vont cesser de fonctionner, ce qui peut provoquer une instabilité du système, désinstallez donc avec prudence. En cas de doute, contactez l'auteur du package.]]> - Télécharger la mise à jour depuis le repository - Mettre à jour le package - Instructions de mise à jour - Il y a une mise à jour disponible pour ce package. Vous pouvez la télécharger directement depuis le repository des packages Umbraco. Version du package - Voir le site internet du package Package déjà installé Ce package ne peut pas être installé, il nécessite au minimum la version Umbraco %0% Désinstallation... diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/he.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/he.xml index 011745ac0f..8d3822943a 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/he.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/he.xml @@ -548,14 +548,12 @@ To manage your website, simply open the Umbraco back office and start adding con ויש לבחור את החבילה הרצויה. לחבילות Umbraco יש בד"כ יש סיומות בשם ".umb" או ".zip". ]]> יוצר החבילה - הדגמה תיעוד מטה דטה עבור החבילה שם החבילה החבילה לא מכילה אף פריט
    ניתן למחוק בבטיחות רבה את החבילה מהמערכת על ידי לחיצה על "הסר חבילה".]]>
    - אין עידכונים זמינים אפשרויות חבילה תיאור החבילה מאגר חבילות @@ -566,12 +564,7 @@ To manage your website, simply open the Umbraco back office and start adding con הערה:כל מסמך, מדיה וכו' התלוים בפריטים שהסרת יפסיקו לעבוד, ויכולים להביא למצב של אי יציבות למערכת, יש למחוק קבצים עם זהירות יתרה, אם יש ספק יש לפנות ליוצר החבילה.]]> - הורד עידכון מהמאגר - שידרוג חבילה - הורדות שידרוג - קיים עידכון זמין עבור חבילה זו. ניתן להוריד אותו ישירות ממאגר החבילות של אומברקו. גירסת החבילה - צפה באתר החבילה שמור עיצוב בהדבקה (לא מומלץ) diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/it.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/it.xml index a55c626625..6796fdfc3c 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/it.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/it.xml @@ -524,14 +524,12 @@ Per gestire il tuo sito web, è sufficiente aprire il back office di Umbraco e i e selezionando il pacchetto. I pacchetti Umbraco generalmente hanno l'estensione ".umb" o ".zip". ]]> Autore - Dimostrazione Documentazione Meta dati pacchetto Nome del pacchetto Il pacchetto non contiene tutti gli elementi
    E' possibile rimuovere questo pacchetto dal sistema cliccando "rimuovi pacchetto" in basso.]]>
    - Non ci sono aggiornamenti disponibili Opzioni pacchetto Pacchetto leggimi Pacchetto repository @@ -542,12 +540,7 @@ Per gestire il tuo sito web, è sufficiente aprire il back office di Umbraco e i Avviso: tutti i documenti, i media, etc a seconda degli elementi che rimuoverai, smetteranno di funzionare, e potrebbero portare a un'instabilità del sistema, perciò disinstalla con cautela. In caso di dubbio contattare l'autore del pacchetto.]]> - - Aggiorna pacchetto - - Versione del pacchetto - Vedi sito web pacchetto diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/ja.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/ja.xml index 993a99ceec..ae30fde3c4 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/ja.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/ja.xml @@ -692,14 +692,12 @@ Runwayをインストールして作られた新しいウェブサイトがど パッケージを選択できます。Umbracoのパッケージは概ね".zip"ないしは".umb"といった拡張子です。 ]]> 作成者 - デモ ヘルプ パッケージのメタデータ パッケージ名 パッケージには何も含まれません
    "パッケージのアンインストール"をクリックしてシステムから安全に削除できます。]]>
    - 更新はありません パッケージのオプション パッケージの取扱説明書 パッケージリポジトリ @@ -710,12 +708,7 @@ Runwayをインストールして作られた新しいウェブサイトがど 注意: 全ての、文書やメディアなどに依存したアイテムを削除する場合はそれらの作業を一端止めてからアンインストールしなければシステムが不安定になる恐れがあります。 疑問点などあればパッケージの作者へ連絡してください。]]> - リポジトリからアップデートをダウンロード - パッケージのアップグレード - 更新の手順 - このパッケージの更新があります。Umbracoのパッケージリポジトリから直接ダウンロードできます。 パッケージのバージョン - パッケージのウェブサイトを見る 完全な書式を含んだまま貼り付け (非推奨) diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/ko.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/ko.xml index 7a46ea81c8..7507ca07e8 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/ko.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/ko.xml @@ -532,14 +532,12 @@ Umbraco 패키지는 보통 ".umb" 나 ".zip" 확장자를 가집니다. ]]> 저자 - 데모 문서화 패키지 메타데이터 패키지 이름 패키지가 포함한 아이템이 없습니다.
    아래 "패키지 삭제"를 클릭하시면 안전하게 시스템에서 삭제하실 수 있습니다.]]>
    - 업그레이드할 패키지가 없습니다. 패키지 옵션 패키지 정보 패키지 저장소 @@ -550,12 +548,7 @@ 알림: 문서, 미디어등 삭제항목에 관련된 모든 항목이 삭제됩니다, 작업을 중단하면 시스템이 불안정적으로 동작할 수 있습니다. 삭제는 매우 주의를 요하기 때문에 의심스러운항목은 패키지 제작자에게 문의하시기 바랍니다.]]> - 저장소에서 업데이트 다운로드 - 업그레이드 패키지 - 업그레이드 지시사항 - 업그레이드할 패키지가 없습니다. Umbraco패키지 저장소에서 직접다운로드하실 수 있습니다. 패키지 버전 - 패키지 웹사이트 보기 포맷을 포함여하 붙여넣기(권장하지 않음) diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/nb.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/nb.xml index a3c8abb946..39f4dd9560 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/nb.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/nb.xml @@ -589,13 +589,11 @@ Vennlig hilsen Umbraco roboten Umbraco-pakker har vanligvis endelsen ".umb" eller ".zip".]]> Utvikler - Demonstrasjon Dokumentasjon Metadata Pakkenavn Pakken inneholder ingen elementer
    Du kan trygt fjerne pakken fra systemet ved å klikke "avinstaller pakke" nedenfor.]]>
    - Ingen oppdateringer tilgjengelig Alternativer for pakke Lesmeg for pakke Pakkebrønn @@ -604,12 +602,7 @@ Vennlig hilsen Umbraco roboten Pakken ble vellykket avinstallert Avinstaller pakke Advarsel: alle dokumenter, media, etc. som som er avhengig av elementene du sletter, vil slutte å virke, noe som kan føre til ustabilitet, så avinstaller med forsiktighet. Hvis du er i tvil, kontakt pakkeutvikleren.]]> - Last ned oppdatering fra pakkeregisteret - Oppgrader pakke - Oppgraderingsinstrukser - Det er en oppdatering tilgjengelig for denne pakken. Du kan laste den ned direkte fra pakkebrønnen. Pakkeversjon - Se pakkens nettsted Lim inn med full formattering (Anbefales ikke) diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/nl.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/nl.xml index 8189be9429..4722abb557 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/nl.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/nl.xml @@ -698,7 +698,6 @@ Echter, Runway biedt een gemakkelijke basis om je snel op weg te helpen. Als je Kies een package op je computer door op "Bladeren" te klikken en de package te selecteren. Umbraco packages hebben meestal ".umb" of ".zip" als extensie. Auteur - Demonstratie Documentatie Package meta data Package naam @@ -706,7 +705,6 @@ Echter, Runway biedt een gemakkelijke basis om je snel op weg te helpen. Als je
    Je kunt deze package veilig verwijderen door op 'verwijder package' te klikken. ]]>
    - Geen upgrades beschikbaar Package opties Package lees mij Package repository @@ -718,12 +716,7 @@ Echter, Runway biedt een gemakkelijke basis om je snel op weg te helpen. Als je Waarschuwing: alle documenten, media etc, die afhankelijk zijn van de items die je verwijderd, zullen niet meer werken en kan leiden tot een instabiele installatie, wees dus voorzichtig met verwijderen. Als je het niet zeker weet, neem dan contact op met de auteur van de package. ]]> - Download update uit de repository - Upgrade package - Upgrade instructies - Er is een upgrade beschikbaar voor deze package. Je kunt het direct downloaden uit de Umbraco package repository. Package versie - Bekijk de package website Package reeds geinstalleerd Deze package kan niet worden geinstalleerd omdat minimaal Umbraco versie %0% benodigd is. Aan het deinstalleren... diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/pl.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/pl.xml index 1f64a5ab21..788afd3c1a 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/pl.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/pl.xml @@ -859,14 +859,12 @@ Naciśnij przycisk instaluj, aby zainstalować bazę danych Umb Według raportów członków społeczności, ten pakiet jest zgodny z następującymi wersjami Umbraco. Pełna zgodność nie może być zagwarantowana dla wersji zaraportowanych poniżej 100% Zewnętrzne źródła Autor - Demonstracja Dokumentacja Metadane pakietu Nazwa pakietu Pakiet nie zawiera żadnych elementów
    Możesz bezpiecznie go usunąć z systemu poprzez kliknięcie na przycisku "odinstaluj pakiet"]]>
    - Nie ma dostępnych aktualizacji Opcje pakietu Opis pakietu Repozytorium pakietu @@ -877,12 +875,7 @@ Naciśnij przycisk instaluj, aby zainstalować bazę danych Umb Uwaga: wszystkie elementy, media, itp. w zależności od elementów, które usuwasz, przestaną działać i mogą spowodować niestabilność systemu, więc odinstalowuj z uwagą. W przypadku problemów skontaktuj się z autorem pakietu.]]> - Pobierz aktualizację z repozytorium - Aktualizuj pakiet - Instrukcja aktualizacji - Jest dostępna aktualizacja dla tego pakietu. Możesz ją pobrać wprost z repozytorium pakietów Umbraco. Wersja pakietu - Odwiedź stronę pakietu Pakiet jest już zainstalowany Ten pakiet nie może być zainstalowany, ponieważ wymaga Umbraco w wersji przynajmniej %0% Odinstalowywanie... diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/pt.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/pt.xml index cff6009bb4..56297d23df 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/pt.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/pt.xml @@ -522,14 +522,12 @@ Vá até http://%4%/#/content/content/edit/%5% para editar. e localizando o pacote. Pacotes Umbraco tem extensão ".umb" ou ".zip".]]> Autor - Demonstração Documentação Dado meta do pacote Nome do pacote Pacote não contém nenhum item
    Você pode remover com segurança do seu sistema clicando em "desinstalar pacote" abaixo.]]>
    - Nenhuma atualização disponível Oções do pacote Leia-me do pacote Repositório do pacote @@ -539,12 +537,7 @@ Você pode remover com segurança do seu sistema clicando em "desinstalar pacote Desinstalar pacote Aviso: quaisquer documentos, mídia, etc dependentes dos itens que forem removidos vão parar de funcionar e podem levar à instabilidade do sistema. Então desinstale com cuidado. Se tiver dúvidas, contate o autor do pacote]]> - Baixar atualização pelo repositório - Atualizar pacote - Instruções de atualização - Há uma atualizaçào disponível para este pacote. Você pode baixá-lo diretamente do repositório de pacotes do Umbraco. Versão do pacote - Ver website do pacote Colar com formatação completa (Não recomendado) diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/ru.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/ru.xml index 61c42d9d6d..1744d19581 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/ru.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/ru.xml @@ -1182,14 +1182,12 @@ Этот пакет совместим со следующими версиями Umbraco, по сообщениям участников сообщества. Полная совместимость не гарантируется для версий со значением ниже 100% Внешние источники Автор - Демонстрация Документация (описание) Мета-данные пакета Название пакета Пакет ничего не содержит
    Вы можете безопасно удалить данный пакет из системы, нажав на кнопку "Деинсталлировать пакет".]]>
    - Нет доступных обновлений Опции пакета Краткий обзор пакета Репозиторий пакета @@ -1200,12 +1198,7 @@ Обратите внимание: все документы, медиа-файлы и другой контент, зависящий от этого пакета, перестанет нормально работать, что может привести к нестабильному поведению системы, поэтому удаляйте пакеты очень осторожно. При наличии сомнений, свяжитесь с автором пакета.]]> - Скачать обновление из репозитория - Обновление пакета - Руководство по обновлению - Для данного пакета доступно обновление. Вы можете загрузить это обновление непосредственно из центрального репозитория пакетов Umbraco. Версия пакета - Перейти на веб-сайт пакета Этот пакет уже установлен в системе Этот пакет не может быть установлен, он требует наличия Umbraco версии как минимум Удаление... diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/sv.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/sv.xml index 05c6dc927d..625caa0432 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/sv.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/sv.xml @@ -544,13 +544,11 @@ och leta upp paketet. Umbracos installationspaket har oftast filändelsen ".umb" eller ".zip".]]> Utvecklare - Demonstration Dokumentation Paket metadata Paketnamn Paketet innehåller inga poster
    Det är säkert att ta bort den ur systemet genom att klicka på "avinstallera paket" nedan.]]>
    - Inga uppdateringar tillgängliga Paketalternativ Paket läsmig Paketvalv @@ -559,12 +557,7 @@ Paketet har avinstallerats utan problem Avinstallera paket OBS! dokument, media osv som använder de borttagna posterna kommer sluta fungera vilket kan leda till att systemet blir instabilt. Avinstallera därför med försiktighet. Om du är osäker, kontakta personen som skapat paketet.]]> - Hämta uppdatering från paketvalvet - Uppdatera paket - Uppdateringsinstruktioner - Det finns an uppdaterad version av paketet. Du kan hämta den direkt från Umbracos paketvalv. Paketversion - Besök paketets webbplats Klistra in med helt bibehållen formatering (rekommenderas ej) diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/tr.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/tr.xml index 4ff9d22c86..053430d68d 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/tr.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/tr.xml @@ -609,14 +609,12 @@ To manage your website, simply open the Umbraco back office and start adding con button and locating the package. Umbraco packages usually have a ".umb" or ".zip" extension. ]]> Author - Demonstration Documentation Package meta data Package name Package doesn't contain any items
    You can safely remove this from the system by clicking "uninstall package" below.]]>
    - No upgrades available Package options Package readme Package repository @@ -627,12 +625,7 @@ To manage your website, simply open the Umbraco back office and start adding con Notice: any documents, media etc depending on the items you remove, will stop working, and could lead to system instability, so uninstall with caution. If in doubt, contact the package author.]]> - Download update from the repository - Upgrade package - Upgrade instructions - There's an upgrade available for this package. You can download it directly from the Umbraco package repository. Package version - View package website Paste with full formatting (Not recommended) diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/zh.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/zh.xml index 7286c3f914..227e40cf94 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/zh.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/zh.xml @@ -728,14 +728,12 @@ 选择 ".umb" 或者 ".zip" 文件 ]]> 作者 - 演示 文档 元数据 名称 扩展包不含任何项
    点击下面的“卸载”,您可以安全的删除。]]>
    - 无可用更新 选项 说明 程序库 @@ -746,12 +744,7 @@ 注意: 卸载包将导致所有依赖该包的东西失效,请确认。 ]]> - 从程序库下载更新 - 更新扩展包 - 更新说明 - 此软件包有一个可用的升级。您可以直接从 Umbraco 软件包存储库下载。 版本 - 访问扩展包网站 已安装软件包 此软件包无法安装, 它需要一个最小的 Umbraco 版本的%0% 卸载中... diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/zh_tw.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/zh_tw.xml index b61e1154b8..23da0c817c 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/zh_tw.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/zh_tw.xml @@ -714,14 +714,12 @@ 按鈕並點選該檔案。Umbraco擴展包通常有「.zip」的副檔名。 ]]> 作者 - 演示 文檔 中繼資料 名稱 擴展包不含任何項
    您可以點選下方「移除擴展包」來安全地移除此項目。]]>
    - 無可用更新 選項 說明 程式庫 @@ -732,12 +730,7 @@ 注意: 任何文檔,媒體或需要這些項目才能運作的物件將會停止運作,並可能使得系統不穩定, 請小心移除。若有疑慮,請聯絡擴展包作者。]]> - 從程式庫下載更新 - 更新擴展包 - 更新說明 - 擴展包有可用的更新,您可以從程式庫網站更新。 版本 - 訪問擴展包網站 擴展包已安裝 這個擴展包無法安裝,它需要Umbraco至少是版本 %0% 移除中... diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/nb.xml b/src/Umbraco.Web.UI/umbraco/config/lang/nb.xml index a3c8abb946..39f4dd9560 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/nb.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/nb.xml @@ -589,13 +589,11 @@ Vennlig hilsen Umbraco roboten Umbraco-pakker har vanligvis endelsen ".umb" eller ".zip".]]> Utvikler - Demonstrasjon Dokumentasjon Metadata Pakkenavn Pakken inneholder ingen elementer
    Du kan trygt fjerne pakken fra systemet ved å klikke "avinstaller pakke" nedenfor.]]>
    - Ingen oppdateringer tilgjengelig Alternativer for pakke Lesmeg for pakke Pakkebrønn @@ -604,12 +602,7 @@ Vennlig hilsen Umbraco roboten Pakken ble vellykket avinstallert Avinstaller pakke Advarsel: alle dokumenter, media, etc. som som er avhengig av elementene du sletter, vil slutte å virke, noe som kan føre til ustabilitet, så avinstaller med forsiktighet. Hvis du er i tvil, kontakt pakkeutvikleren.]]> - Last ned oppdatering fra pakkeregisteret - Oppgrader pakke - Oppgraderingsinstrukser - Det er en oppdatering tilgjengelig for denne pakken. Du kan laste den ned direkte fra pakkebrønnen. Pakkeversjon - Se pakkens nettsted Lim inn med full formattering (Anbefales ikke) diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/zh_tw.xml b/src/Umbraco.Web.UI/umbraco/config/lang/zh_tw.xml index b61e1154b8..23da0c817c 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/zh_tw.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/zh_tw.xml @@ -714,14 +714,12 @@ 按鈕並點選該檔案。Umbraco擴展包通常有「.zip」的副檔名。 ]]> 作者 - 演示 文檔 中繼資料 名稱 擴展包不含任何項
    您可以點選下方「移除擴展包」來安全地移除此項目。]]>
    - 無可用更新 選項 說明 程式庫 @@ -732,12 +730,7 @@ 注意: 任何文檔,媒體或需要這些項目才能運作的物件將會停止運作,並可能使得系統不穩定, 請小心移除。若有疑慮,請聯絡擴展包作者。]]> - 從程式庫下載更新 - 更新擴展包 - 更新說明 - 擴展包有可用的更新,您可以從程式庫網站更新。 版本 - 訪問擴展包網站 擴展包已安裝 這個擴展包無法安裝,它需要Umbraco至少是版本 %0% 移除中... diff --git a/src/Umbraco.Web/Editors/PackageController.cs b/src/Umbraco.Web/Editors/PackageController.cs index 4814a8000a..c60d035562 100644 --- a/src/Umbraco.Web/Editors/PackageController.cs +++ b/src/Umbraco.Web/Editors/PackageController.cs @@ -115,11 +115,18 @@ namespace Umbraco.Web.Editors return response; } + public PackageDefinition GetInstalledPackageById(int id) + { + var pack = Services.PackagingService.GetInstalledPackageById(id); + if (pack == null) throw new HttpResponseException(HttpStatusCode.NotFound); + return pack; + } + /// /// Returns all installed packages - only shows their latest versions /// /// - public IEnumerable GetInstalled() + public IEnumerable GetInstalled() { return Services.PackagingService.GetAllInstalledPackages() .GroupBy( @@ -136,19 +143,6 @@ namespace Umbraco.Web.Editors //only return the first package with this version return grouping.First(x => x.version == maxVersion).package; }) - .Select(pack => new InstalledPackageModel - { - Name = pack.Name, - Id = pack.Id, - Author = pack.Author, - Version = pack.Version, - Url = pack.Url, - License = pack.License, - LicenseUrl = pack.LicenseUrl, - Files = pack.Files, - IconUrl = pack.IconUrl, - Readme = pack.Readme - }) .ToList(); } } diff --git a/src/Umbraco.Web/Editors/PackageInstallController.cs b/src/Umbraco.Web/Editors/PackageInstallController.cs index 544a871720..f87f323df8 100644 --- a/src/Umbraco.Web/Editors/PackageInstallController.cs +++ b/src/Umbraco.Web/Editors/PackageInstallController.cs @@ -369,20 +369,17 @@ namespace Umbraco.Web.Editors var packageInfo = Services.PackagingService.GetCompiledPackageInfo(zipFile); + zipFile.Delete(); + + //bump cdf to be safe var clientDependencyConfig = new ClientDependencyConfiguration(Logger); var clientDependencyUpdated = clientDependencyConfig.UpdateVersionNumber( UmbracoVersion.SemanticVersion, DateTime.UtcNow, "yyyyMMdd"); - zipFile.Delete(); - var redirectUrl = ""; if (!packageInfo.PackageView.IsNullOrWhiteSpace()) { - //fixme! - throw new NotImplementedException(); - //redirectUrl = string.Format("/packages/framed/{0}", - // Uri.EscapeDataString( - // string.Format("/umbraco/developer/Packages/installer.aspx?installing=custominstaller&dir={0}&pId={1}&customControl={2}&customUrl={3}", tempDir, model.Id, ins.Control, ins.Url))); + redirectUrl = $"/packages/packages/options/{model.Id}"; } return new PackageInstallResult diff --git a/src/Umbraco.Web/Models/ContentEditing/InstalledPackageModel.cs b/src/Umbraco.Web/Models/ContentEditing/InstalledPackageModel.cs deleted file mode 100644 index 67bfe6fe53..0000000000 --- a/src/Umbraco.Web/Models/ContentEditing/InstalledPackageModel.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace Umbraco.Web.Models.ContentEditing -{ - [DataContract] - public class InstalledPackageModel - { - [DataMember(Name = "id")] - public int Id { get; set; } - - [DataMember(Name = "name")] - public string Name { get; set; } - - [DataMember(Name = "author")] - public string Author { get; set; } - - [DataMember(Name = "files")] - public IEnumerable Files { get; set; } - - [DataMember(Name = "version")] - public string Version { get; set; } - - [DataMember(Name = "url")] - public string Url { get; set; } - - [DataMember(Name = "license")] - public string License { get; set; } - - [DataMember(Name = "licenseUrl")] - public string LicenseUrl { get; set; } - - [DataMember(Name = "iconUrl")] - public string IconUrl { get; set; } - - [DataMember(Name = "readme")] - public string Readme { get; set; } - } -} diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index b0142771d2..62a7d6175c 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -596,7 +596,6 @@ - From b4f2d514be5b2c14bbb5c4b2729daf407bd70176 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Wed, 16 Jan 2019 11:44:27 +0100 Subject: [PATCH 386/469] #3305 - changed new method to be internal --- src/Umbraco.Web/PublishedContentExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web/PublishedContentExtensions.cs b/src/Umbraco.Web/PublishedContentExtensions.cs index 0e1f75684a..d30414b3d3 100644 --- a/src/Umbraco.Web/PublishedContentExtensions.cs +++ b/src/Umbraco.Web/PublishedContentExtensions.cs @@ -272,7 +272,7 @@ namespace Umbraco.Web /// The content. /// The specific culture to filter for. If null is used the current culture is used. (Default is null) /// These of the inputs that has the specified culture or are invariant. - public static IEnumerable WhereHasCultureOrInvariant(this IEnumerable contents, string culture = null) + internal static IEnumerable WhereHasCultureOrInvariant(this IEnumerable contents, string culture = null) { if (contents == null) throw new ArgumentNullException(nameof(contents)); From 8347fd79a3c00d40c63c46832c3f60a07c401ae2 Mon Sep 17 00:00:00 2001 From: Stephan Date: Wed, 16 Jan 2019 11:37:20 +0100 Subject: [PATCH 387/469] Reviewing packages PR, various fixes --- .../Services/Implement/EntityXmlSerializer.cs | 4 +- src/Umbraco.Examine/ContentValueSetBuilder.cs | 4 +- src/Umbraco.Examine/MediaValueSetBuilder.cs | 2 +- .../UmbracoExamine/IndexInitializer.cs | 2 +- src/Umbraco.Web/Composing/Current.cs | 35 --------------- .../Editors/PackageInstallController.cs | 2 +- .../InstallSteps/StarterKitDownloadStep.cs | 2 +- .../InstallSteps/StarterKitInstallStep.cs | 2 +- src/Umbraco.Web/Mvc/ContentModelBinder.cs | 2 +- .../NuCache/PublishedSnapshotService.cs | 3 ++ src/Umbraco.Web/Search/ExamineComposer.cs | 4 +- src/Umbraco.Web/UmbracoApplication.cs | 45 ++++++++++++++++++- 12 files changed, 59 insertions(+), 48 deletions(-) diff --git a/src/Umbraco.Core/Services/Implement/EntityXmlSerializer.cs b/src/Umbraco.Core/Services/Implement/EntityXmlSerializer.cs index 1a1d2e5ab2..fd1067b3e5 100644 --- a/src/Umbraco.Core/Services/Implement/EntityXmlSerializer.cs +++ b/src/Umbraco.Core/Services/Implement/EntityXmlSerializer.cs @@ -22,7 +22,7 @@ namespace Umbraco.Core.Services.Implement private readonly IDataTypeService _dataTypeService; private readonly IUserService _userService; private readonly ILocalizationService _localizationService; - private readonly IEnumerable _urlSegmentProviders; + private readonly UrlSegmentProviderCollection _urlSegmentProviders; public EntityXmlSerializer( IContentService contentService, @@ -31,7 +31,7 @@ namespace Umbraco.Core.Services.Implement IUserService userService, ILocalizationService localizationService, IContentTypeService contentTypeService, - IEnumerable urlSegmentProviders) + UrlSegmentProviderCollection urlSegmentProviders) { _contentTypeService = contentTypeService; _mediaService = mediaService; diff --git a/src/Umbraco.Examine/ContentValueSetBuilder.cs b/src/Umbraco.Examine/ContentValueSetBuilder.cs index d8e698cdad..a6262c53fc 100644 --- a/src/Umbraco.Examine/ContentValueSetBuilder.cs +++ b/src/Umbraco.Examine/ContentValueSetBuilder.cs @@ -13,11 +13,11 @@ namespace Umbraco.Examine ///
    public class ContentValueSetBuilder : BaseValueSetBuilder, IContentValueSetBuilder, IPublishedContentValueSetBuilder { - private readonly IEnumerable _urlSegmentProviders; + private readonly UrlSegmentProviderCollection _urlSegmentProviders; private readonly IUserService _userService; public ContentValueSetBuilder(PropertyEditorCollection propertyEditors, - IEnumerable urlSegmentProviders, + UrlSegmentProviderCollection urlSegmentProviders, IUserService userService, bool publishedValuesOnly) : base(propertyEditors, publishedValuesOnly) diff --git a/src/Umbraco.Examine/MediaValueSetBuilder.cs b/src/Umbraco.Examine/MediaValueSetBuilder.cs index 2676093eeb..23d0414d5d 100644 --- a/src/Umbraco.Examine/MediaValueSetBuilder.cs +++ b/src/Umbraco.Examine/MediaValueSetBuilder.cs @@ -10,7 +10,7 @@ namespace Umbraco.Examine { public class MediaValueSetBuilder : BaseValueSetBuilder { - private readonly IEnumerable _urlSegmentProviders; + private readonly UrlSegmentProviderCollection _urlSegmentProviders; private readonly IUserService _userService; public MediaValueSetBuilder(PropertyEditorCollection propertyEditors, diff --git a/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs b/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs index 0b36398dd6..3019138809 100644 --- a/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs +++ b/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs @@ -31,7 +31,7 @@ namespace Umbraco.Tests.UmbracoExamine { public static ContentValueSetBuilder GetContentValueSetBuilder(PropertyEditorCollection propertyEditors, bool publishedValuesOnly) { - var contentValueSetBuilder = new ContentValueSetBuilder(propertyEditors, new[] { new DefaultUrlSegmentProvider() }, GetMockUserService(), publishedValuesOnly); + var contentValueSetBuilder = new ContentValueSetBuilder(propertyEditors, new UrlSegmentProviderCollection(new[] { new DefaultUrlSegmentProvider() }), GetMockUserService(), publishedValuesOnly); return contentValueSetBuilder; } diff --git a/src/Umbraco.Web/Composing/Current.cs b/src/Umbraco.Web/Composing/Current.cs index 860d3ec88e..1e8f3d17f7 100644 --- a/src/Umbraco.Web/Composing/Current.cs +++ b/src/Umbraco.Web/Composing/Current.cs @@ -159,41 +159,6 @@ namespace Umbraco.Web.Composing #endregion - #region Web Actions - - internal static void RestartAppPool() - { - // see notes in overload - - var httpContext = HttpContext.Current; - if (httpContext != null) - { - httpContext.Application.Add("AppPoolRestarting", true); - httpContext.User = null; - } - Thread.CurrentPrincipal = null; - HttpRuntime.UnloadAppDomain(); - } - - internal static void RestartAppPool(HttpContextBase httpContext) - { - // we're going to put an application wide flag to show that the application is about to restart. - // we're doing this because if there is a script checking if the app pool is fully restarted, then - // it can check if this flag exists... if it does it means the app pool isn't restarted yet. - httpContext.Application.Add("AppPoolRestarting", true); - - // unload app domain - we must null out all identities otherwise we get serialization errors - // http://www.zpqrtbnk.net/posts/custom-iidentity-serialization-issue - httpContext.User = null; - if (HttpContext.Current != null) - HttpContext.Current.User = null; - Thread.CurrentPrincipal = null; - - HttpRuntime.UnloadAppDomain(); - } - - #endregion - #region Core Getters // proxy Core for convenience diff --git a/src/Umbraco.Web/Editors/PackageInstallController.cs b/src/Umbraco.Web/Editors/PackageInstallController.cs index dd7c4302c5..05d1e2a7a3 100644 --- a/src/Umbraco.Web/Editors/PackageInstallController.cs +++ b/src/Umbraco.Web/Editors/PackageInstallController.cs @@ -315,7 +315,7 @@ namespace Umbraco.Web.Editors var installedFiles = Services.PackagingService.InstallCompiledPackageFiles(definition, zipFile, Security.GetUserId().ResultOr(0)); //set a restarting marker and reset the app pool - Current.RestartAppPool(Request.TryGetHttpContext().Result); + UmbracoApplication.Restart(Request.TryGetHttpContext().Result); model.IsRestarting = true; diff --git a/src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs b/src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs index 0349bb4ec7..641146fb4a 100644 --- a/src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs @@ -52,7 +52,7 @@ namespace Umbraco.Web.Install.InstallSteps var (packageFile, packageId) = await DownloadPackageFilesAsync(starterKitId.Value); - Current.RestartAppPool(); + UmbracoApplication.Restart(); return new InstallSetupResult(new Dictionary { diff --git a/src/Umbraco.Web/Install/InstallSteps/StarterKitInstallStep.cs b/src/Umbraco.Web/Install/InstallSteps/StarterKitInstallStep.cs index 805041391f..8bd699f293 100644 --- a/src/Umbraco.Web/Install/InstallSteps/StarterKitInstallStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/StarterKitInstallStep.cs @@ -34,7 +34,7 @@ namespace Umbraco.Web.Install.InstallSteps InstallBusinessLogic(packageId); - Current.RestartAppPool(_httContext); + UmbracoApplication.Restart(_httContext); return Task.FromResult(null); } diff --git a/src/Umbraco.Web/Mvc/ContentModelBinder.cs b/src/Umbraco.Web/Mvc/ContentModelBinder.cs index b68d5a36f7..c6df52e007 100644 --- a/src/Umbraco.Web/Mvc/ContentModelBinder.cs +++ b/src/Umbraco.Web/Mvc/ContentModelBinder.cs @@ -150,7 +150,7 @@ namespace Umbraco.Web.Mvc if (context == null) AppDomain.Unload(AppDomain.CurrentDomain); else - Current.RestartAppPool(new HttpContextWrapper(context)); + UmbracoApplication.Restart(new HttpContextWrapper(context)); } throw new ModelBindingException(msg.ToString()); diff --git a/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs b/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs index dc8fcf8c0e..36f3472c31 100755 --- a/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs @@ -101,6 +101,9 @@ namespace Umbraco.Web.PublishedCache.NuCache _defaultCultureAccessor = defaultCultureAccessor; _globalSettings = globalSettings; _siteDomainHelper = siteDomainHelper; + + // we need an Xml serializer here so that the member cache can support XPath, + // for members this is done by navigating the serialized-to-xml member _entitySerializer = entitySerializer; // we always want to handle repository events, configured or not diff --git a/src/Umbraco.Web/Search/ExamineComposer.cs b/src/Umbraco.Web/Search/ExamineComposer.cs index 8ee2caedee..7aab3cfd8f 100644 --- a/src/Umbraco.Web/Search/ExamineComposer.cs +++ b/src/Umbraco.Web/Search/ExamineComposer.cs @@ -33,13 +33,13 @@ namespace Umbraco.Web.Search composition.RegisterUnique(factory => new ContentValueSetBuilder( factory.GetInstance(), - factory.GetInstance>(), + factory.GetInstance(), factory.GetInstance(), true)); composition.RegisterUnique(factory => new ContentValueSetBuilder( factory.GetInstance(), - factory.GetInstance>(), + factory.GetInstance(), factory.GetInstance(), false)); composition.RegisterUnique, MediaValueSetBuilder>(); diff --git a/src/Umbraco.Web/UmbracoApplication.cs b/src/Umbraco.Web/UmbracoApplication.cs index 136f09f83d..191fb9dcd6 100644 --- a/src/Umbraco.Web/UmbracoApplication.cs +++ b/src/Umbraco.Web/UmbracoApplication.cs @@ -1,4 +1,6 @@ -using Umbraco.Core; +using System.Threading; +using System.Web; +using Umbraco.Core; using Umbraco.Web.Runtime; namespace Umbraco.Web @@ -12,5 +14,46 @@ namespace Umbraco.Web { return new WebRuntime(this); } + + /// + /// Restarts the Umbraco application. + /// + public static void Restart() + { + // see notes in overload + + var httpContext = HttpContext.Current; + if (httpContext != null) + { + httpContext.Application.Add("AppPoolRestarting", true); + httpContext.User = null; + } + Thread.CurrentPrincipal = null; + HttpRuntime.UnloadAppDomain(); + } + + /// + /// Restarts the Umbraco application. + /// + public static void Restart(HttpContextBase httpContext) + { + if (httpContext != null) + { + // we're going to put an application wide flag to show that the application is about to restart. + // we're doing this because if there is a script checking if the app pool is fully restarted, then + // it can check if this flag exists... if it does it means the app pool isn't restarted yet. + httpContext.Application.Add("AppPoolRestarting", true); + + // unload app domain - we must null out all identities otherwise we get serialization errors + // http://www.zpqrtbnk.net/posts/custom-iidentity-serialization-issue + httpContext.User = null; + } + + if (HttpContext.Current != null) + HttpContext.Current.User = null; + + Thread.CurrentPrincipal = null; + HttpRuntime.UnloadAppDomain(); + } } } From 35650536c8f9956a86cb87284744e7d1283be202 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Wed, 16 Jan 2019 13:23:19 +0100 Subject: [PATCH 388/469] 3305 - Use the `VariationContext` instead of thread directly --- src/Umbraco.Web/PublishedContentExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web/PublishedContentExtensions.cs b/src/Umbraco.Web/PublishedContentExtensions.cs index d30414b3d3..4efe6bc82b 100644 --- a/src/Umbraco.Web/PublishedContentExtensions.cs +++ b/src/Umbraco.Web/PublishedContentExtensions.cs @@ -276,7 +276,7 @@ namespace Umbraco.Web { if (contents == null) throw new ArgumentNullException(nameof(contents)); - var actualCulture = culture ?? System.Threading.Thread.CurrentThread.CurrentUICulture.Name; + var actualCulture = culture ?? Current.VariationContextAccessor.VariationContext.Culture; return contents.Where(x=>x.HasCulture(actualCulture) || !x.Cultures.Any()); } From a60bdf5c01f02693dbcf2a76504bf50ad8f22b6c Mon Sep 17 00:00:00 2001 From: Stephan Date: Wed, 16 Jan 2019 13:26:13 +0100 Subject: [PATCH 389/469] HttpContext VariationContextAccessor fails nicely --- .../PublishedContent/HttpContextVariationContextAccessor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web/Models/PublishedContent/HttpContextVariationContextAccessor.cs b/src/Umbraco.Web/Models/PublishedContent/HttpContextVariationContextAccessor.cs index 70672e3796..0007b346c5 100644 --- a/src/Umbraco.Web/Models/PublishedContent/HttpContextVariationContextAccessor.cs +++ b/src/Umbraco.Web/Models/PublishedContent/HttpContextVariationContextAccessor.cs @@ -21,7 +21,7 @@ namespace Umbraco.Web.Models.PublishedContent /// public VariationContext VariationContext { - get => (VariationContext) HttpContextAccessor.HttpContext.Items[ContextKey]; + get => (VariationContext) HttpContextAccessor.HttpContext?.Items[ContextKey]; set => HttpContextAccessor.HttpContext.Items[ContextKey] = value; } } From b5bda0b6375ee0134467596589f56ee4e3490b2c Mon Sep 17 00:00:00 2001 From: Stephan Date: Wed, 16 Jan 2019 13:26:30 +0100 Subject: [PATCH 390/469] Some things have to be public for service events --- .../Persistence/Repositories/IDataTypeContainerRepository.cs | 2 +- .../Repositories/IDocumentTypeContainerRepository.cs | 2 +- .../Persistence/Repositories/IEntityContainerRepository.cs | 2 +- src/Umbraco.Core/Persistence/Repositories/IMacroRepository.cs | 2 +- .../Persistence/Repositories/IMediaTypeContainerRepository.cs | 2 +- src/Umbraco.Core/Services/Changes/ContentTypeChange.cs | 2 +- src/Umbraco.Core/Services/Implement/ContentTypeService.cs | 2 +- src/Umbraco.Core/Services/Implement/ContentTypeServiceBase.cs | 2 +- .../Services/Implement/ContentTypeServiceBaseOfTItemTService.cs | 2 +- .../ContentTypeServiceBaseOfTRepositoryTItemTService.cs | 2 +- src/Umbraco.Core/Services/Implement/DataTypeService.cs | 2 +- src/Umbraco.Core/Services/Implement/MacroService.cs | 2 +- src/Umbraco.Core/Services/Implement/MediaTypeService.cs | 2 +- src/Umbraco.Core/Services/Implement/MemberTypeService.cs | 2 +- 14 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Umbraco.Core/Persistence/Repositories/IDataTypeContainerRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IDataTypeContainerRepository.cs index 460bed71d3..57d3871e5a 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IDataTypeContainerRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IDataTypeContainerRepository.cs @@ -1,5 +1,5 @@ namespace Umbraco.Core.Persistence.Repositories { - interface IDataTypeContainerRepository : IEntityContainerRepository + public interface IDataTypeContainerRepository : IEntityContainerRepository { } } diff --git a/src/Umbraco.Core/Persistence/Repositories/IDocumentTypeContainerRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IDocumentTypeContainerRepository.cs index ccf8df268d..ec8dfb9110 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IDocumentTypeContainerRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IDocumentTypeContainerRepository.cs @@ -1,5 +1,5 @@ namespace Umbraco.Core.Persistence.Repositories { - interface IDocumentTypeContainerRepository : IEntityContainerRepository + public interface IDocumentTypeContainerRepository : IEntityContainerRepository { } } diff --git a/src/Umbraco.Core/Persistence/Repositories/IEntityContainerRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IEntityContainerRepository.cs index 47f0cee52b..f1c8353a0d 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IEntityContainerRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IEntityContainerRepository.cs @@ -2,6 +2,6 @@ namespace Umbraco.Core.Persistence.Repositories { - interface IEntityContainerRepository : IReadRepository, IWriteRepository + public interface IEntityContainerRepository : IReadRepository, IWriteRepository { } } diff --git a/src/Umbraco.Core/Persistence/Repositories/IMacroRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IMacroRepository.cs index eefb48933e..1ed08352ed 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IMacroRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IMacroRepository.cs @@ -3,7 +3,7 @@ using Umbraco.Core.Models; namespace Umbraco.Core.Persistence.Repositories { - internal interface IMacroRepository : IReadWriteQueryRepository, IReadRepository + public interface IMacroRepository : IReadWriteQueryRepository, IReadRepository { //IEnumerable GetAll(params string[] aliases); diff --git a/src/Umbraco.Core/Persistence/Repositories/IMediaTypeContainerRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IMediaTypeContainerRepository.cs index a1872df0cd..6a133c053a 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IMediaTypeContainerRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IMediaTypeContainerRepository.cs @@ -1,5 +1,5 @@ namespace Umbraco.Core.Persistence.Repositories { - interface IMediaTypeContainerRepository : IEntityContainerRepository + public interface IMediaTypeContainerRepository : IEntityContainerRepository { } } diff --git a/src/Umbraco.Core/Services/Changes/ContentTypeChange.cs b/src/Umbraco.Core/Services/Changes/ContentTypeChange.cs index d67f8f9200..57e1d288e4 100644 --- a/src/Umbraco.Core/Services/Changes/ContentTypeChange.cs +++ b/src/Umbraco.Core/Services/Changes/ContentTypeChange.cs @@ -4,7 +4,7 @@ using Umbraco.Core.Models; namespace Umbraco.Core.Services.Changes { - internal class ContentTypeChange + public class ContentTypeChange where TItem : class, IContentTypeComposition { public ContentTypeChange(TItem item, ContentTypeChangeTypes changeTypes) diff --git a/src/Umbraco.Core/Services/Implement/ContentTypeService.cs b/src/Umbraco.Core/Services/Implement/ContentTypeService.cs index f6498770ec..fa818496ff 100644 --- a/src/Umbraco.Core/Services/Implement/ContentTypeService.cs +++ b/src/Umbraco.Core/Services/Implement/ContentTypeService.cs @@ -12,7 +12,7 @@ namespace Umbraco.Core.Services.Implement /// /// Represents the ContentType Service, which is an easy access to operations involving /// - internal class ContentTypeService : ContentTypeServiceBase, IContentTypeService + public class ContentTypeService : ContentTypeServiceBase, IContentTypeService { public ContentTypeService(IScopeProvider provider, ILogger logger, IEventMessagesFactory eventMessagesFactory, IContentService contentService, IContentTypeRepository repository, IAuditRepository auditRepository, IDocumentTypeContainerRepository entityContainerRepository, IEntityRepository entityRepository) diff --git a/src/Umbraco.Core/Services/Implement/ContentTypeServiceBase.cs b/src/Umbraco.Core/Services/Implement/ContentTypeServiceBase.cs index d5cdd36318..26298f171c 100644 --- a/src/Umbraco.Core/Services/Implement/ContentTypeServiceBase.cs +++ b/src/Umbraco.Core/Services/Implement/ContentTypeServiceBase.cs @@ -4,7 +4,7 @@ using Umbraco.Core.Scoping; namespace Umbraco.Core.Services.Implement { - internal abstract class ContentTypeServiceBase : ScopeRepositoryService + public abstract class ContentTypeServiceBase : ScopeRepositoryService { protected ContentTypeServiceBase(IScopeProvider provider, ILogger logger, IEventMessagesFactory eventMessagesFactory) : base(provider, logger, eventMessagesFactory) diff --git a/src/Umbraco.Core/Services/Implement/ContentTypeServiceBaseOfTItemTService.cs b/src/Umbraco.Core/Services/Implement/ContentTypeServiceBaseOfTItemTService.cs index 33fb9a0894..f4457e0991 100644 --- a/src/Umbraco.Core/Services/Implement/ContentTypeServiceBaseOfTItemTService.cs +++ b/src/Umbraco.Core/Services/Implement/ContentTypeServiceBaseOfTItemTService.cs @@ -6,7 +6,7 @@ using Umbraco.Core.Services.Changes; namespace Umbraco.Core.Services.Implement { - internal abstract class ContentTypeServiceBase : ContentTypeServiceBase + public abstract class ContentTypeServiceBase : ContentTypeServiceBase where TItem : class, IContentTypeComposition where TService : class, IContentTypeServiceBase { diff --git a/src/Umbraco.Core/Services/Implement/ContentTypeServiceBaseOfTRepositoryTItemTService.cs b/src/Umbraco.Core/Services/Implement/ContentTypeServiceBaseOfTRepositoryTItemTService.cs index be4f719bb1..8189c6524e 100644 --- a/src/Umbraco.Core/Services/Implement/ContentTypeServiceBaseOfTRepositoryTItemTService.cs +++ b/src/Umbraco.Core/Services/Implement/ContentTypeServiceBaseOfTRepositoryTItemTService.cs @@ -13,7 +13,7 @@ using Umbraco.Core.Services.Changes; namespace Umbraco.Core.Services.Implement { - internal abstract class ContentTypeServiceBase : ContentTypeServiceBase, IContentTypeServiceBase + public abstract class ContentTypeServiceBase : ContentTypeServiceBase, IContentTypeServiceBase where TRepository : IContentTypeRepositoryBase where TItem : class, IContentTypeComposition where TService : class, IContentTypeServiceBase diff --git a/src/Umbraco.Core/Services/Implement/DataTypeService.cs b/src/Umbraco.Core/Services/Implement/DataTypeService.cs index 79ca851de9..84d44649da 100644 --- a/src/Umbraco.Core/Services/Implement/DataTypeService.cs +++ b/src/Umbraco.Core/Services/Implement/DataTypeService.cs @@ -16,7 +16,7 @@ namespace Umbraco.Core.Services.Implement /// /// Represents the DataType Service, which is an easy access to operations involving /// - internal class DataTypeService : ScopeRepositoryService, IDataTypeService + public class DataTypeService : ScopeRepositoryService, IDataTypeService { private readonly IDataTypeRepository _dataTypeRepository; private readonly IDataTypeContainerRepository _dataTypeContainerRepository; diff --git a/src/Umbraco.Core/Services/Implement/MacroService.cs b/src/Umbraco.Core/Services/Implement/MacroService.cs index 5176e2eb22..d4f2d95bbb 100644 --- a/src/Umbraco.Core/Services/Implement/MacroService.cs +++ b/src/Umbraco.Core/Services/Implement/MacroService.cs @@ -12,7 +12,7 @@ namespace Umbraco.Core.Services.Implement /// /// Represents the Macro Service, which is an easy access to operations involving /// - internal class MacroService : ScopeRepositoryService, IMacroService + public class MacroService : ScopeRepositoryService, IMacroService { private readonly IMacroRepository _macroRepository; private readonly IAuditRepository _auditRepository; diff --git a/src/Umbraco.Core/Services/Implement/MediaTypeService.cs b/src/Umbraco.Core/Services/Implement/MediaTypeService.cs index fe8c78e137..8cb69a655d 100644 --- a/src/Umbraco.Core/Services/Implement/MediaTypeService.cs +++ b/src/Umbraco.Core/Services/Implement/MediaTypeService.cs @@ -8,7 +8,7 @@ using Umbraco.Core.Scoping; namespace Umbraco.Core.Services.Implement { - internal class MediaTypeService : ContentTypeServiceBase, IMediaTypeService + public class MediaTypeService : ContentTypeServiceBase, IMediaTypeService { public MediaTypeService(IScopeProvider provider, ILogger logger, IEventMessagesFactory eventMessagesFactory, IMediaService mediaService, IMediaTypeRepository mediaTypeRepository, IAuditRepository auditRepository, IMediaTypeContainerRepository entityContainerRepository, diff --git a/src/Umbraco.Core/Services/Implement/MemberTypeService.cs b/src/Umbraco.Core/Services/Implement/MemberTypeService.cs index 6cc7d03cfb..05f32dc99c 100644 --- a/src/Umbraco.Core/Services/Implement/MemberTypeService.cs +++ b/src/Umbraco.Core/Services/Implement/MemberTypeService.cs @@ -8,7 +8,7 @@ using Umbraco.Core.Scoping; namespace Umbraco.Core.Services.Implement { - internal class MemberTypeService : ContentTypeServiceBase, IMemberTypeService + public class MemberTypeService : ContentTypeServiceBase, IMemberTypeService { private readonly IMemberTypeRepository _memberTypeRepository; From 9f41457f45f37011d08175af7ca223ff34534150 Mon Sep 17 00:00:00 2001 From: Stephan Date: Wed, 16 Jan 2019 13:44:19 +0100 Subject: [PATCH 391/469] Public composition.UrlProviders --- src/Umbraco.Web/CompositionExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web/CompositionExtensions.cs b/src/Umbraco.Web/CompositionExtensions.cs index f72c876a61..d33b1addf5 100644 --- a/src/Umbraco.Web/CompositionExtensions.cs +++ b/src/Umbraco.Web/CompositionExtensions.cs @@ -81,7 +81,7 @@ namespace Umbraco.Core.Components /// Gets the url providers collection builder. /// /// The composition. - internal static UrlProviderCollectionBuilder UrlProviders(this Composition composition) + public static UrlProviderCollectionBuilder UrlProviders(this Composition composition) => composition.WithCollectionBuilder(); #endregion From 7bb358888980bdcd8d605214b611ba7bd22c0712 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 16 Jan 2019 23:53:10 +1100 Subject: [PATCH 392/469] Adds the whole package definition to the scope model for devs to use, adds a custom query string parameter when redirecting to the angular view after install (so devs know its a new install) --- .../src/views/packages/edit.controller.js | 2 +- .../src/views/packages/options.controller.js | 6 +++++- .../src/views/packages/overview.controller.js | 14 +++++++------- .../packages/views/install-local.controller.js | 10 ++-------- .../views/packages/views/installed.controller.js | 5 +++-- .../src/views/packages/views/repo.controller.js | 6 ++---- 6 files changed, 20 insertions(+), 23 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js index ca20b33a3e..bed3341c6b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js @@ -130,7 +130,7 @@ } function back() { - $location.path("packages/packages/created").search("create", null); + $location.path("packages/packages/created").search("create", null).search("packageId", null); } function createOrUpdatePackage(editPackageForm) { diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/options.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/options.controller.js index 8ffd282e0d..4fdf6488a0 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/options.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/options.controller.js @@ -15,6 +15,10 @@ packageResource.getInstalledById(packageId).then(pck => { vm.package = pck; + + //set the $scope too, packages can then access this if they wanted from their own scope or parent scope + $scope.package = pck; + vm.loading = false; //make sure the packageView is formatted as a virtual path @@ -30,7 +34,7 @@ } function back() { - $location.path("packages/packages/installed"); + $location.path("packages/packages/installed").search("packageId", null); } diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/overview.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/overview.controller.js index f4c1ab9de4..e48271aa23 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/overview.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/overview.controller.js @@ -4,26 +4,26 @@ function PackagesOverviewController($scope, $location, $routeParams, localStorageService) { //Hack! - // if there is a cookie value for packageInstallUri then we need to redirect there, + // if there is a local storage value for packageInstallData then we need to redirect there, // the issue is that we still have webforms and we cannot go to a hash location and then window.reload // because it will double load it. // we will refresh and then navigate there. - let installPackageUri = localStorageService.get("packageInstallUri"); + let packageInstallData = localStorageService.get("packageInstallData"); let packageUri = $routeParams.method; - if (installPackageUri) { - localStorageService.remove("packageInstallUri"); + if (packageInstallData) { + localStorageService.remove("packageInstallData"); } - if (installPackageUri && installPackageUri !== "installed") { + if (packageInstallData && packageInstallData !== "installed" && packageInstallData.postInstallationPath) { //navigate to the custom installer screen, if it is just "installed" it means there is no custom installer screen - $location.path(installPackageUri).search(""); + $location.path(packageInstallData.postInstallationPath).search("packageId", packageInstallData.id); } else { var vm = this; - packageUri = installPackageUri ? installPackageUri : packageUri; //use the path stored in storage over the one in the current path + packageUri = packageInstallData ? packageInstallData : packageUri; //use the path stored in storage over the one in the current path vm.page = {}; vm.page.name = "Packages"; diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/views/install-local.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/views/install-local.controller.js index 17b417de48..0d9341243b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/views/install-local.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/views/install-local.controller.js @@ -184,14 +184,8 @@ installError) .then(function (result) { - if (result.postInstallationPath) { - //Put the redirect Uri in a cookie so we can use after reloading - localStorageService.set("packageInstallUri", result.postInstallationPath); - } - else { - //set to a constant value so it knows to just go to the installed view - localStorageService.set("packageInstallUri", "installed"); - } + //Put the package data in local storage so we can use after reloading + localStorageService.set("packageInstallData", result); vm.installState.status = labels.installStateCompleted; vm.installCompleted = true; diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/views/installed.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/views/installed.controller.js index 3b6422ace4..ddfee19ac1 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/views/installed.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/views/installed.controller.js @@ -36,7 +36,8 @@ } function packageOptions(pck) { - $location.path("packages/packages/options/" + pck.id); + $location.path("packages/packages/options/" + pck.id) + .search("packageId", null); //ensure the installId flag is gone, it's only available on first install } function confirmUninstall(pck) { @@ -56,7 +57,7 @@ vm.installState.progress = "100"; //set this flag so that on refresh it shows the installed packages list - localStorageService.set("packageInstallUri", "installed"); + localStorageService.set("packageInstallData", "installed"); //reload on next digest (after cookie) $timeout(function () { diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/views/repo.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/views/repo.controller.js index b77326d2fc..dc3e67db15 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/views/repo.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/views/repo.controller.js @@ -257,10 +257,8 @@ error) .then(function (result) { - if (result.postInstallationPath) { - //Put the redirect Uri in a cookie so we can use after reloading - localStorageService.set("packageInstallUri", result.postInstallationPath); - } + //Put the package data in local storage so we can use after reloading + localStorageService.set("packageInstallData", result); vm.installState.status = labels.installStateCompleted; vm.installCompleted = true; From ddcead26582daa2d87b7eeaa74f5b5e475a57eb1 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 17 Jan 2019 00:29:43 +1100 Subject: [PATCH 393/469] Updates EntityController to support stylesheets, languages and dictionary items GetAll so we can use it for the packager without worrying about security access to sections --- .../src/views/packages/edit.controller.js | 8 +-- .../Editors/DictionaryController.cs | 4 +- src/Umbraco.Web/Editors/EntityController.cs | 57 +++++++++++++++++-- .../ContentEditing/UmbracoEntityTypes.cs | 7 ++- .../Models/Mapping/CodeFileMapperProfile.cs | 12 ++++ .../Models/Mapping/DictionaryMapperProfile.cs | 12 ++++ .../Models/Mapping/LanguageMapperProfile.cs | 12 ++++ 7 files changed, 99 insertions(+), 13 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js index bed3341c6b..0a44192041 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js @@ -1,7 +1,7 @@ (function () { "use strict"; - function EditController($scope, $location, $routeParams, umbRequestHelper, entityResource, stylesheetResource, languageResource, packageResource, dictionaryResource, editorService, formHelper) { + function EditController($scope, $location, $routeParams, umbRequestHelper, entityResource, packageResource, editorService, formHelper) { const vm = this; @@ -73,7 +73,7 @@ }); // get all stylesheets - stylesheetResource.getAll().then(stylesheets => { + entityResource.getAll("Stylesheet").then(stylesheets => { vm.stylesheets = stylesheets; }); @@ -87,7 +87,7 @@ }); // get all languages - languageResource.getAll().then(languages => { + entityResource.getAll("Language").then(languages => { // a package stores the id as a string so we // need to convert all ids to string for comparison languages.forEach(language => { @@ -97,7 +97,7 @@ }); // get all dictionary items - dictionaryResource.getList().then(dictionaryItems => { + entityResource.getAll("DictionaryItem").then(dictionaryItems => { // a package stores the id as a string so we // need to convert all ids to string for comparison dictionaryItems.forEach(dictionaryItem => { diff --git a/src/Umbraco.Web/Editors/DictionaryController.cs b/src/Umbraco.Web/Editors/DictionaryController.cs index cd3141c7b9..9d01cc9d64 100644 --- a/src/Umbraco.Web/Editors/DictionaryController.cs +++ b/src/Umbraco.Web/Editors/DictionaryController.cs @@ -219,7 +219,7 @@ namespace Umbraco.Web.Editors /// /// The list. /// - private void GetChildItemsForList(IDictionaryItem dictionaryItem, int level, List list) + private void GetChildItemsForList(IDictionaryItem dictionaryItem, int level, ICollection list) { foreach (var childItem in Services.LocalizationService.GetDictionaryItemChildren(dictionaryItem.Key).OrderBy(ItemSort())) { @@ -231,6 +231,6 @@ namespace Umbraco.Web.Editors } } - private Func ItemSort() => item => item.ItemKey; + private static Func ItemSort() => item => item.ItemKey; } } diff --git a/src/Umbraco.Web/Editors/EntityController.cs b/src/Umbraco.Web/Editors/EntityController.cs index 993489855f..396615a339 100644 --- a/src/Umbraco.Web/Editors/EntityController.cs +++ b/src/Umbraco.Web/Editors/EntityController.cs @@ -839,8 +839,6 @@ namespace Umbraco.Web.Editors return UmbracoObjectTypes.MediaType; case UmbracoEntityTypes.DocumentType: return UmbracoObjectTypes.DocumentType; - case UmbracoEntityTypes.Stylesheet: - return UmbracoObjectTypes.Stylesheet; case UmbracoEntityTypes.Member: return UmbracoObjectTypes.Member; case UmbracoEntityTypes.DataType: @@ -912,13 +910,31 @@ namespace Umbraco.Web.Editors case UmbracoEntityTypes.User: - long total; - var users = Services.UserService.GetAll(0, int.MaxValue, out total); + var users = Services.UserService.GetAll(0, int.MaxValue, out _); var filteredUsers = ExecutePostFilter(users, postFilter, postFilterParams); return Mapper.Map, IEnumerable>(filteredUsers); - case UmbracoEntityTypes.Domain: + case UmbracoEntityTypes.Stylesheet: + + if (!postFilter.IsNullOrWhiteSpace() || (postFilterParams != null && postFilterParams.Count > 0)) + throw new NotSupportedException("Filtering on stylesheets is not currently supported"); + + return Services.FileService.GetStylesheets().Select(Mapper.Map); + case UmbracoEntityTypes.Language: + + if (!postFilter.IsNullOrWhiteSpace() || (postFilterParams != null && postFilterParams.Count > 0)) + throw new NotSupportedException("Filtering on languages is not currently supported"); + + return Services.LocalizationService.GetAllLanguages().Select(Mapper.Map); + case UmbracoEntityTypes.DictionaryItem: + + if (!postFilter.IsNullOrWhiteSpace() || (postFilterParams != null && postFilterParams.Count > 0)) + throw new NotSupportedException("Filtering on languages is not currently supported"); + + return GetAllDictionaryItems(); + + case UmbracoEntityTypes.Domain: default: throw new NotSupportedException("The " + typeof(EntityController) + " does not currently support data for the type " + entityType); } @@ -937,5 +953,36 @@ namespace Umbraco.Web.Editors } return entities; } + + + #region Methods to get all dictionary items + private IEnumerable GetAllDictionaryItems() + { + var list = new List(); + + foreach (var dictionaryItem in Services.LocalizationService.GetRootDictionaryItems().OrderBy(DictionaryItemSort())) + { + var item = Mapper.Map(dictionaryItem); + list.Add(item); + GetChildItemsForList(dictionaryItem, list); + } + + return list; + } + + private static Func DictionaryItemSort() => item => item.ItemKey; + + private void GetChildItemsForList(IDictionaryItem dictionaryItem, ICollection list) + { + foreach (var childItem in Services.LocalizationService.GetDictionaryItemChildren(dictionaryItem.Key).OrderBy(DictionaryItemSort())) + { + var item = Mapper.Map(childItem); + list.Add(item); + + GetChildItemsForList(childItem, list); + } + } + #endregion + } } diff --git a/src/Umbraco.Web/Models/ContentEditing/UmbracoEntityTypes.cs b/src/Umbraco.Web/Models/ContentEditing/UmbracoEntityTypes.cs index 04d06845d9..fcf7271673 100644 --- a/src/Umbraco.Web/Models/ContentEditing/UmbracoEntityTypes.cs +++ b/src/Umbraco.Web/Models/ContentEditing/UmbracoEntityTypes.cs @@ -86,8 +86,11 @@ namespace Umbraco.Web.Models.ContentEditing /// /// Property Group /// - PropertyGroup + PropertyGroup, - //TODO: Dictionary? + /// + /// Dictionary Item + /// + DictionaryItem } } diff --git a/src/Umbraco.Web/Models/Mapping/CodeFileMapperProfile.cs b/src/Umbraco.Web/Models/Mapping/CodeFileMapperProfile.cs index 94c43f8f11..b3f5f0374c 100644 --- a/src/Umbraco.Web/Models/Mapping/CodeFileMapperProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/CodeFileMapperProfile.cs @@ -9,6 +9,18 @@ namespace Umbraco.Web.Models.Mapping { public CodeFileMapperProfile() { + CreateMap() + .ForMember(dest => dest.Id, opt => opt.MapFrom(sheet => sheet.Id)) + .ForMember(dest => dest.Alias, opt => opt.MapFrom(sheet => sheet.Alias)) + .ForMember(dest => dest.Key, opt => opt.MapFrom(sheet => sheet.Key)) + .ForMember(dest => dest.Name, opt => opt.MapFrom(sheet => sheet.Name)) + .ForMember(dest => dest.ParentId, opt => opt.UseValue(-1)) + .ForMember(dest => dest.Path, opt => opt.MapFrom(sheet => sheet.Path)) + .ForMember(dest => dest.Trashed, opt => opt.Ignore()) + .ForMember(dest => dest.AdditionalData, opt => opt.Ignore()) + .ForMember(dest => dest.Udi, opt => opt.Ignore()) + .ForMember(dest => dest.Icon, opt => opt.Ignore()); + CreateMap() .ForMember(dest => dest.FileType, opt => opt.Ignore()) .ForMember(dest => dest.Notifications, opt => opt.Ignore()) diff --git a/src/Umbraco.Web/Models/Mapping/DictionaryMapperProfile.cs b/src/Umbraco.Web/Models/Mapping/DictionaryMapperProfile.cs index ebd675f572..b3af04603c 100644 --- a/src/Umbraco.Web/Models/Mapping/DictionaryMapperProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/DictionaryMapperProfile.cs @@ -17,6 +17,18 @@ namespace Umbraco.Web.Models.Mapping { public DictionaryMapperProfile(ILocalizationService localizationService) { + CreateMap() + .ForMember(dest => dest.Id, opt => opt.MapFrom(sheet => sheet.Id)) + .ForMember(dest => dest.Alias, opt => opt.MapFrom(sheet => sheet.ItemKey)) + .ForMember(dest => dest.Key, opt => opt.MapFrom(sheet => sheet.Key)) + .ForMember(dest => dest.Name, opt => opt.MapFrom(sheet => sheet.ItemKey)) + .ForMember(dest => dest.ParentId, opt => opt.Ignore()) + .ForMember(dest => dest.Path, opt => opt.Ignore()) + .ForMember(dest => dest.Trashed, opt => opt.Ignore()) + .ForMember(dest => dest.AdditionalData, opt => opt.Ignore()) + .ForMember(dest => dest.Udi, opt => opt.Ignore()) + .ForMember(dest => dest.Icon, opt => opt.Ignore()); + CreateMap() .ForMember(x => x.Translations, expression => expression.Ignore()) .ForMember(x => x.Notifications, expression => expression.Ignore()) diff --git a/src/Umbraco.Web/Models/Mapping/LanguageMapperProfile.cs b/src/Umbraco.Web/Models/Mapping/LanguageMapperProfile.cs index f820d5ae54..ea29b671a6 100644 --- a/src/Umbraco.Web/Models/Mapping/LanguageMapperProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/LanguageMapperProfile.cs @@ -12,6 +12,18 @@ namespace Umbraco.Web.Models.Mapping { public LanguageMapperProfile() { + CreateMap() + .ForMember(dest => dest.Id, opt => opt.MapFrom(x => x.Id)) + .ForMember(dest => dest.Name, opt => opt.MapFrom(x => x.CultureName)) + .ForMember(dest => dest.Key, opt => opt.MapFrom(x => x.Key)) + .ForMember(dest => dest.Alias, opt => opt.MapFrom(x => x.IsoCode)) + .ForMember(dest => dest.ParentId, opt => opt.UseValue(-1)) + .ForMember(dest => dest.Path, opt => opt.Ignore()) + .ForMember(dest => dest.Trashed, opt => opt.Ignore()) + .ForMember(dest => dest.AdditionalData, opt => opt.Ignore()) + .ForMember(dest => dest.Udi, opt => opt.Ignore()) + .ForMember(dest => dest.Icon, opt => opt.Ignore()); + CreateMap() .ForMember(l => l.Name, expression => expression.MapFrom(x => x.CultureInfo.DisplayName)); From 3ed1b44710d21b8a5f3b9c6321020541689dafb3 Mon Sep 17 00:00:00 2001 From: Stephan Date: Wed, 16 Jan 2019 15:21:10 +0100 Subject: [PATCH 394/469] Try to bugfix a failing test --- .../Packaging/PackageInstallationTest.cs | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs b/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs index d944b638ad..5e33538f17 100644 --- a/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs +++ b/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs @@ -60,7 +60,7 @@ namespace Umbraco.Tests.Packaging public void Can_Read_Compiled_Package_1() { var package = PackageInstallation.ReadPackage( - //this is where our test zip file is + //this is where our test zip file is new FileInfo(Path.Combine(IOHelper.MapPath("~/Packaging/packages"), DocumentTypePickerPackage))); Assert.IsNotNull(package); Assert.AreEqual(1, package.Files.Count); @@ -83,7 +83,7 @@ namespace Umbraco.Tests.Packaging public void Can_Read_Compiled_Package_2() { var package = PackageInstallation.ReadPackage( - //this is where our test zip file is + //this is where our test zip file is new FileInfo(Path.Combine(IOHelper.MapPath("~/Packaging/packages"), HelloPackage))); Assert.IsNotNull(package); Assert.AreEqual(0, package.Files.Count); @@ -110,18 +110,22 @@ namespace Umbraco.Tests.Packaging { //copy a file to the same path that the package will install so we can detect file conflicts var path = IOHelper.MapPath("~/" + _testBaseFolder); + Console.WriteLine(path); + var filePath = Path.Combine(path, "bin", "Auros.DocumentTypePicker.dll"); Directory.CreateDirectory(Path.GetDirectoryName(filePath)); File.WriteAllText(filePath, "test"); - var preInstallWarnings = PackageInstallation.ReadPackage( - //this is where our test zip file is - new FileInfo(Path.Combine(IOHelper.MapPath("~/Packaging/packages"), DocumentTypePickerPackage))) - .Warnings; + //this is where our test zip file is + var packageFile = Path.Combine(IOHelper.MapPath("~/Packaging/packages"), DocumentTypePickerPackage); + Console.WriteLine(packageFile); + + var package = PackageInstallation.ReadPackage(new FileInfo(packageFile)); + var preInstallWarnings = package.Warnings; Assert.IsNotNull(preInstallWarnings); - Assert.AreEqual(preInstallWarnings.FilesReplaced.Count(), 1); - Assert.AreEqual(preInstallWarnings.FilesReplaced.First(), "bin\\Auros.DocumentTypePicker.dll"); + Assert.AreEqual(1, preInstallWarnings.FilesReplaced.Count()); + Assert.AreEqual("bin\\Auros.DocumentTypePicker.dll", preInstallWarnings.FilesReplaced.First()); //TODO: More Asserts } @@ -130,7 +134,7 @@ namespace Umbraco.Tests.Packaging public void Install_Files() { var package = PackageInstallation.ReadPackage( - //this is where our test zip file is + //this is where our test zip file is new FileInfo(Path.Combine(IOHelper.MapPath("~/Packaging/packages"), DocumentTypePickerPackage))); var def = PackageDefinition.FromCompiledPackage(package); @@ -152,7 +156,7 @@ namespace Umbraco.Tests.Packaging public void Install_Data() { var package = PackageInstallation.ReadPackage( - //this is where our test zip file is + //this is where our test zip file is new FileInfo(Path.Combine(IOHelper.MapPath("~/Packaging/packages"), DocumentTypePickerPackage))); var def = PackageDefinition.FromCompiledPackage(package); def.Id = 1; @@ -161,7 +165,7 @@ namespace Umbraco.Tests.Packaging var summary = PackageInstallation.InstallPackageData(def, package, -1); Assert.AreEqual(1, summary.DataTypesInstalled.Count()); - + //make sure the def is updated too Assert.AreEqual(summary.DataTypesInstalled.Count(), def.DataTypes.Count); From 664a892fd5073a37a9d10bb4a5ea57c0e29df948 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Wed, 16 Jan 2019 15:25:42 +0100 Subject: [PATCH 395/469] 3305 - fixed tests --- .../Testing/Objects/Accessors/TestVariationContextAccessor.cs | 2 +- .../PublishedCache/XmlPublishedCache/XmlPublishedContent.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Tests/Testing/Objects/Accessors/TestVariationContextAccessor.cs b/src/Umbraco.Tests/Testing/Objects/Accessors/TestVariationContextAccessor.cs index 3c7377f2cc..4b56799fa4 100644 --- a/src/Umbraco.Tests/Testing/Objects/Accessors/TestVariationContextAccessor.cs +++ b/src/Umbraco.Tests/Testing/Objects/Accessors/TestVariationContextAccessor.cs @@ -12,6 +12,6 @@ namespace Umbraco.Tests.Testing.Objects.Accessors { get; set; - } + } = new VariationContext(); } } diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlPublishedContent.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlPublishedContent.cs index efd4535bd4..d8436c05b5 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlPublishedContent.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlPublishedContent.cs @@ -138,7 +138,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache public override PublishedCultureInfo GetCulture(string culture = null) => throw new NotSupportedException(); - public override IReadOnlyDictionary Cultures => throw new NotSupportedException(); + public override IReadOnlyDictionary Cultures => new Dictionary(); public override string WriterName { From 899bb812aac24d52ff1f014e2d1b2fd54a257dd9 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 17 Jan 2019 01:42:56 +1100 Subject: [PATCH 396/469] Creates RuntimeStateOptions and pre-loads the error page on the installer --- src/Umbraco.Core/RuntimeState.cs | 12 ++---- src/Umbraco.Core/RuntimeStateOptions.cs | 40 +++++++++++++++++++ src/Umbraco.Core/Umbraco.Core.csproj | 1 + .../src/installer/installer.service.js | 33 +++++++++------ 4 files changed, 64 insertions(+), 22 deletions(-) create mode 100644 src/Umbraco.Core/RuntimeStateOptions.cs diff --git a/src/Umbraco.Core/RuntimeState.cs b/src/Umbraco.Core/RuntimeState.cs index e344a67920..85e8c7370d 100644 --- a/src/Umbraco.Core/RuntimeState.cs +++ b/src/Umbraco.Core/RuntimeState.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Configuration; using System.Threading; using System.Web; using Semver; @@ -133,11 +132,6 @@ namespace Umbraco.Core /// public BootFailedException BootFailedException { get; internal set; } - // currently configured via app settings - private static bool BoolSetting(string key, bool missing) => ConfigurationManager.AppSettings[key]?.InvariantEquals("true") ?? missing; - private bool InstallMissingDatabase { get; } = BoolSetting("Umbraco.Core.RuntimeState.InstallMissingDatabase", false); - private bool InstallEmptyDatabase { get; } = BoolSetting("Umbraco.Core.RuntimeState.InstallEmptyDatabase", false); - /// /// Determines the runtime level. /// @@ -185,7 +179,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 = InstallMissingDatabase ? 2 : 5; + var tries = RuntimeStateOptions.InstallMissingDatabase ? 2 : 5; for (var i = 0;;) { connect = databaseFactory.CanConnect; @@ -199,7 +193,7 @@ namespace Umbraco.Core // cannot connect to configured database, this is bad, fail logger.Debug("Could not connect to database."); - if (InstallMissingDatabase) + if (RuntimeStateOptions.InstallMissingDatabase) { // ok to install on a configured but missing database Level = RuntimeLevel.Install; @@ -228,7 +222,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 (InstallEmptyDatabase) + if (RuntimeStateOptions.InstallEmptyDatabase) { // ok to install on an empty database Level = RuntimeLevel.Install; diff --git a/src/Umbraco.Core/RuntimeStateOptions.cs b/src/Umbraco.Core/RuntimeStateOptions.cs new file mode 100644 index 0000000000..9262a8a990 --- /dev/null +++ b/src/Umbraco.Core/RuntimeStateOptions.cs @@ -0,0 +1,40 @@ +using System.Configuration; + +namespace Umbraco.Core +{ + /// + /// Allows configuration of the in PreApplicationStart or in appSettings + /// + public static class RuntimeStateOptions + { + // configured statically or via app settings + private static bool BoolSetting(string key, bool missing) => ConfigurationManager.AppSettings[key]?.InvariantEquals("true") ?? missing; + + /// + /// If true the RuntimeState will continue the installation sequence when a database is missing + /// + /// + /// In this case it will be up to the implementor that is setting this value to true to take over the bootup/installation sequence + /// + public static bool InstallMissingDatabase + { + get => _installEmptyDatabase ?? BoolSetting("Umbraco.Core.RuntimeState.InstallMissingDatabase", false); + set => _installEmptyDatabase = value; + } + + /// + /// If true the RuntimeState will continue the installation sequence when a database is available but is empty + /// + /// + /// In this case it will be up to the implementor that is setting this value to true to take over the bootup/installation sequence + /// + public static bool InstallEmptyDatabase + { + get => _installMissingDatabase ?? BoolSetting("Umbraco.Core.RuntimeState.InstallEmptyDatabase", false); + set => _installMissingDatabase = value; + } + + private static bool? _installMissingDatabase; + private static bool? _installEmptyDatabase; + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 50cc36d7b9..2236854351 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -512,6 +512,7 @@ + diff --git a/src/Umbraco.Web.UI.Client/src/installer/installer.service.js b/src/Umbraco.Web.UI.Client/src/installer/installer.service.js index a8e0530417..cc92935b4d 100644 --- a/src/Umbraco.Web.UI.Client/src/installer/installer.service.js +++ b/src/Umbraco.Web.UI.Client/src/installer/installer.service.js @@ -1,4 +1,4 @@ -angular.module("umbraco.install").factory('installerService', function($rootScope, $q, $timeout, $http, $location, $log){ +angular.module("umbraco.install").factory('installerService', function ($rootScope, $q, $timeout, $http, $templateRequest){ var _status = { index: 0, @@ -106,19 +106,26 @@ angular.module("umbraco.install").factory('installerService', function($rootScop //loads the needed steps and sets the intial state init : function(){ service.status.loading = true; - if(!_status.all){ - service.getSteps().then(function(response){ - service.status.steps = response.data.steps; - service.status.index = 0; - _installerModel.installId = response.data.installId; - service.findNextStep(); + if (!_status.all) { + //pre-load the error page, if an error occurs, the page might not be able to load + // so we want to make sure it's available in the templatecache first + $templateRequest("views/install/error.html").then(x => { + service.getSteps().then(response => { + service.status.steps = response.data.steps; + service.status.index = 0; + _installerModel.installId = response.data.installId; + service.findNextStep(); - $timeout(function(){ - service.status.loading = false; - service.status.configuring = true; - }, 2000); - }); - } + $timeout(function() { + service.status.loading = false; + service.status.configuring = true; + }, + 2000); + }); + }); + + + } }, //loads available packages from our.umbraco.com From 5f7bf3a211d920c8e2efca17955ecc457c1d9151 Mon Sep 17 00:00:00 2001 From: Stephan Date: Wed, 16 Jan 2019 17:03:36 +0100 Subject: [PATCH 397/469] Ignore failing test --- src/Umbraco.Tests/Packaging/PackageInstallationTest.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs b/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs index 5e33538f17..2b9e50e9e5 100644 --- a/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs +++ b/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs @@ -106,6 +106,7 @@ namespace Umbraco.Tests.Packaging } [Test] + [Explicit("Will fail on CI?")] public void Can_Read_Compiled_Package_Warnings() { //copy a file to the same path that the package will install so we can detect file conflicts From 67c571fb289bf7cbf2efa4f739f94a6221b8e958 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 17 Jan 2019 10:56:24 +1100 Subject: [PATCH 398/469] Fixes tests --- src/Umbraco.Core/Composing/Composers/ServicesComposer.cs | 3 +-- src/Umbraco.Core/Packaging/PackageInstallation.cs | 9 ++------- src/Umbraco.Tests/Packaging/PackageInstallationTest.cs | 4 +--- src/Umbraco.Tests/TestHelpers/TestObjects.cs | 1 - 4 files changed, 4 insertions(+), 13 deletions(-) diff --git a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs index bd07123fb2..8c9ccd1088 100644 --- a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs @@ -67,12 +67,11 @@ namespace Umbraco.Core.Composing.Composers composition.RegisterUnique(factory => CreatePackageRepository(factory, "installedPackages.config")); composition.RegisterUnique(); composition.RegisterUnique(); - var appRoot = new DirectoryInfo(IOHelper.GetRootDirectorySafe()); composition.RegisterUnique(factory => //factory required because we need to pass in a string path new PackageInstallation( factory.GetInstance(), factory.GetInstance(), factory.GetInstance(), factory.GetInstance(), - appRoot, appRoot)); + new DirectoryInfo(IOHelper.GetRootDirectorySafe()))); //TODO: These are replaced in the web project - we need to declare them so that // something is wired up, just not sure this is very nice but will work for now. diff --git a/src/Umbraco.Core/Packaging/PackageInstallation.cs b/src/Umbraco.Core/Packaging/PackageInstallation.cs index 955662f3fe..d791295b38 100644 --- a/src/Umbraco.Core/Packaging/PackageInstallation.cs +++ b/src/Umbraco.Core/Packaging/PackageInstallation.cs @@ -18,7 +18,6 @@ namespace Umbraco.Core.Packaging private readonly PackageFileInstallation _packageFileInstallation; private readonly CompiledPackageXmlParser _parser; private readonly IPackageActionRunner _packageActionRunner; - private readonly DirectoryInfo _packageExtractionFolder; private readonly DirectoryInfo _applicationRootFolder; /// @@ -31,11 +30,8 @@ namespace Umbraco.Core.Packaging /// /// The root folder of the application /// - /// - /// The destination root folder to extract the package files (generally the same as applicationRoot) but can be modified for testing - /// public PackageInstallation(PackageDataInstallation packageDataInstallation, PackageFileInstallation packageFileInstallation, CompiledPackageXmlParser parser, IPackageActionRunner packageActionRunner, - DirectoryInfo applicationRootFolder, DirectoryInfo packageExtractionFolder) + DirectoryInfo applicationRootFolder) { _packageExtraction = new PackageExtraction(); _packageFileInstallation = packageFileInstallation ?? throw new ArgumentNullException(nameof(packageFileInstallation)); @@ -43,7 +39,6 @@ namespace Umbraco.Core.Packaging _parser = parser ?? throw new ArgumentNullException(nameof(parser)); _packageActionRunner = packageActionRunner ?? throw new ArgumentNullException(nameof(packageActionRunner)); _applicationRootFolder = applicationRootFolder ?? throw new ArgumentNullException(nameof(applicationRootFolder)); - _packageExtractionFolder = packageExtractionFolder ?? throw new ArgumentNullException(nameof(packageExtractionFolder)); } public CompiledPackage ReadPackage(FileInfo packageFile) @@ -69,7 +64,7 @@ namespace Umbraco.Core.Packaging var packageZipFile = compiledPackage.PackageFile; - var files = _packageFileInstallation.InstallFiles(compiledPackage, packageZipFile, _packageExtractionFolder.FullName).ToList(); + var files = _packageFileInstallation.InstallFiles(compiledPackage, packageZipFile, _applicationRootFolder.FullName).ToList(); packageDefinition.Files = files; diff --git a/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs b/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs index 2b9e50e9e5..4256a66a2d 100644 --- a/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs +++ b/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs @@ -50,8 +50,7 @@ namespace Umbraco.Tests.Packaging PackageDataInstallation, new PackageFileInstallation(Parser, ProfilingLogger), Parser, Mock.Of(), - applicationRootFolder: new DirectoryInfo(IOHelper.GetRootDirectorySafe()), - packageExtractionFolder: new DirectoryInfo(IOHelper.MapPath("~/" + _testBaseFolder))); //we don't want to extract package files to the real root, so extract to a test folder + applicationRootFolder: new DirectoryInfo(IOHelper.MapPath("~/" + _testBaseFolder))); //we don't want to extract package files to the real root, so extract to a test folder private const string DocumentTypePickerPackage = "Document_Type_Picker_1.1.umb"; private const string HelloPackage = "Hello_1.0.0.zip"; @@ -106,7 +105,6 @@ namespace Umbraco.Tests.Packaging } [Test] - [Explicit("Will fail on CI?")] public void Can_Read_Compiled_Package_Warnings() { //copy a file to the same path that the package will install so we can detect file conflicts diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects.cs b/src/Umbraco.Tests/TestHelpers/TestObjects.cs index 684da2599e..14ffeb743f 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects.cs @@ -185,7 +185,6 @@ namespace Umbraco.Tests.TestHelpers new PackageDataInstallation(logger, fileService.Value, macroService.Value, localizationService.Value, dataTypeService.Value, entityService.Value, contentTypeService.Value, contentService.Value, propertyEditorCollection), new PackageFileInstallation(compiledPackageXmlParser, new ProfilingLogger(logger, new TestProfiler())), compiledPackageXmlParser, Mock.Of(), - new DirectoryInfo(IOHelper.GetRootDirectorySafe()), new DirectoryInfo(IOHelper.GetRootDirectorySafe()))); }); var relationService = GetLazyService(factory, c => new RelationService(scopeProvider, logger, eventMessagesFactory, entityService.Value, GetRepo(c), GetRepo(c))); From 355ac09d90f435f96a217c32ce9dbe93852a85bb Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 17 Jan 2019 13:20:19 +1100 Subject: [PATCH 399/469] WIP - moved out the tree and section service from Core, these are web only things, removes their xml parsing, fixes base controller ctor params with UmbracoContext, need to implement tree/section collections taking into account controllers and not scanning so much --- .../Composing/Composers/ServicesComposer.cs | 4 - src/Umbraco.Core/Models/ApplicationTree.cs | 170 ---- src/Umbraco.Core/Models/Section.cs | 22 - src/Umbraco.Core/Services/ISectionService.cs | 114 --- src/Umbraco.Core/Services/ServiceContext.cs | 20 +- src/Umbraco.Core/Umbraco.Core.csproj | 4 - .../Cache/DistributedCacheBinderTests.cs | 7 - .../Packages/Document_Type_Picker_1.1.zip | Bin 0 -> 6147 bytes .../Services/SectionServiceTests.cs | 17 +- .../TestControllerActivatorBase.cs | 3 +- .../TestHelpers/TestObjects-Mocks.cs | 2 - src/Umbraco.Tests/TestHelpers/TestObjects.cs | 6 +- .../TreesAndSections/ApplicationTreeTest.cs | 724 ++++++++--------- .../TreesAndSections/SectionTests.cs | 454 +++++------ .../Cache/ApplicationTreeCacheRefresher.cs | 68 +- .../Cache/DistributedCacheBinder_Handlers.cs | 72 +- .../Cache/DistributedCacheExtensions.cs | 24 +- .../{ => Controllers}/TagsController.cs | 6 +- .../Editors/AuthenticationController.cs | 4 +- .../Editors/BackOfficeServerVariables.cs | 4 +- .../Editors/ContentTypeController.cs | 4 +- .../Editors/ContentTypeControllerBase.cs | 3 +- .../Editors/DashboardController.cs | 4 +- src/Umbraco.Web/Editors/DashboardSecurity.cs | 1 + src/Umbraco.Web/Editors/Dashboards.cs | 1 + src/Umbraco.Web/Editors/EntityController.cs | 16 +- .../Editors/MediaTypeController.cs | 3 +- .../Editors/MemberTypeController.cs | 3 +- .../Editors/PackageInstallController.cs | 4 +- src/Umbraco.Web/Editors/SectionController.cs | 30 +- .../UmbracoAuthorizedJsonController.cs | 4 +- .../Models/ContentEditing/ApplicationTree.cs | 177 +++++ .../ContentEditing/IBackOfficeSection.cs | 15 + .../Models/Mapping/SectionMapperProfile.cs | 3 +- .../Models/Mapping/UserMapperProfile.cs | 1 + .../Models/Trees/ApplicationAttribute.cs | 30 - .../Models/Trees/ApplicationDefinitions.cs | 90 ++- src/Umbraco.Web/Models/Trees/IApplication.cs | 10 - .../Mvc/SurfaceControllerTypeCollection.cs | 2 + .../Runtime/WebRuntimeComponent.cs | 2 + src/Umbraco.Web/Runtime/WebRuntimeComposer.cs | 11 + .../Search/SearchableTreeCollection.cs | 1 + .../Services/ApplicationTreeService.cs | 747 +++++++++--------- .../Services/IApplicationTreeService.cs | 121 +-- src/Umbraco.Web/Services/ISectionService.cs | 116 +++ src/Umbraco.Web/Services/SectionService.cs | 443 +++++------ .../Trees/ApplicationTreeController.cs | 33 +- .../Trees/BackOfficeSectionCollection.cs | 21 + src/Umbraco.Web/Trees/TreeCollection.cs | 27 + src/Umbraco.Web/Trees/TreeController.cs | 34 +- src/Umbraco.Web/Trees/TreeControllerBase.cs | 98 +-- ...xtensions.cs => TreeControllerResolver.cs} | 106 ++- .../UI/Pages/UmbracoEnsuredPage.cs | 14 +- src/Umbraco.Web/Umbraco.Web.csproj | 13 +- src/Umbraco.Web/UrlHelperExtensions.cs | 1 - .../Filters/LegacyTreeAuthorizeAttribute.cs | 29 - .../Filters/UmbracoTreeAuthorizeAttribute.cs | 23 +- .../WebApi/UmbracoApiController.cs | 4 +- .../WebApi/UmbracoApiControllerBase.cs | 11 +- .../UmbracoApiControllerTypeCollection.cs | 2 + .../WebApi/UmbracoAuthorizedApiController.cs | 4 +- .../_Legacy/PackageActions/addApplication.cs | 106 +-- 62 files changed, 2043 insertions(+), 2050 deletions(-) delete mode 100644 src/Umbraco.Core/Models/ApplicationTree.cs delete mode 100644 src/Umbraco.Core/Models/Section.cs delete mode 100644 src/Umbraco.Core/Services/ISectionService.cs create mode 100644 src/Umbraco.Tests/Packaging/Packages/Document_Type_Picker_1.1.zip rename src/Umbraco.Web/{ => Controllers}/TagsController.cs (89%) create mode 100644 src/Umbraco.Web/Models/ContentEditing/ApplicationTree.cs create mode 100644 src/Umbraco.Web/Models/ContentEditing/IBackOfficeSection.cs delete mode 100644 src/Umbraco.Web/Models/Trees/ApplicationAttribute.cs delete mode 100644 src/Umbraco.Web/Models/Trees/IApplication.cs rename src/{Umbraco.Core => Umbraco.Web}/Services/IApplicationTreeService.cs (52%) create mode 100644 src/Umbraco.Web/Services/ISectionService.cs create mode 100644 src/Umbraco.Web/Trees/BackOfficeSectionCollection.cs create mode 100644 src/Umbraco.Web/Trees/TreeCollection.cs rename src/Umbraco.Web/Trees/{ApplicationTreeExtensions.cs => TreeControllerResolver.cs} (56%) delete mode 100644 src/Umbraco.Web/WebApi/Filters/LegacyTreeAuthorizeAttribute.cs diff --git a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs index 8c9ccd1088..0b83373d99 100644 --- a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs @@ -73,10 +73,6 @@ namespace Umbraco.Core.Composing.Composers factory.GetInstance(), factory.GetInstance(), new DirectoryInfo(IOHelper.GetRootDirectorySafe()))); - //TODO: These are replaced in the web project - we need to declare them so that - // something is wired up, just not sure this is very nice but will work for now. - composition.RegisterUnique(); - composition.RegisterUnique(); return composition; } diff --git a/src/Umbraco.Core/Models/ApplicationTree.cs b/src/Umbraco.Core/Models/ApplicationTree.cs deleted file mode 100644 index ccdebea724..0000000000 --- a/src/Umbraco.Core/Models/ApplicationTree.cs +++ /dev/null @@ -1,170 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Diagnostics; -using Umbraco.Core.Services; - -namespace Umbraco.Core.Models -{ - [DebuggerDisplay("Tree - {Title} ({ApplicationAlias})")] - public class ApplicationTree - { - private static readonly ConcurrentDictionary ResolvedTypes = new ConcurrentDictionary(); - - /// - /// Initializes a new instance of the class. - /// - public ApplicationTree() { } - - /// - /// Initializes a new instance of the class. - /// - /// if set to true [initialize]. - /// The sort order. - /// The application alias. - /// The tree alias. - /// The tree title. - /// The icon closed. - /// The icon opened. - /// The tree type. - public ApplicationTree(bool initialize, int sortOrder, string applicationAlias, string alias, string title, string iconClosed, string iconOpened, string type) - { - Initialize = initialize; - SortOrder = sortOrder; - ApplicationAlias = applicationAlias; - Alias = alias; - Title = title; - IconClosed = iconClosed; - IconOpened = iconOpened; - Type = type; - - } - - /// - /// Gets or sets a value indicating whether this should initialize. - /// - /// true if initialize; otherwise, false. - public bool Initialize { get; set; } - - /// - /// Gets or sets the sort order. - /// - /// The sort order. - public int SortOrder { get; set; } - - /// - /// Gets the application alias. - /// - /// The application alias. - public string ApplicationAlias { get; } - - /// - /// Gets the tree alias. - /// - /// The alias. - public string Alias { get; } - - /// - /// Gets or sets the tree title. - /// - /// The title. - public string Title { get; set; } - - /// - /// Gets or sets the icon closed. - /// - /// The icon closed. - public string IconClosed { get; set; } - - /// - /// Gets or sets the icon opened. - /// - /// The icon opened. - public string IconOpened { get; set; } - - /// - /// Gets or sets the tree type assembly name. - /// - /// The type. - public string Type { get; set; } - - /// - /// Returns the localized root node display name - /// - /// - /// - public string GetRootNodeDisplayName(ILocalizedTextService textService) - { - var label = $"[{Alias}]"; - - // try to look up a the localized tree header matching the tree alias - var localizedLabel = textService.Localize("treeHeaders/" + Alias); - - // if the localizedLabel returns [alias] then return the title attribute from the trees.config file, if it's defined - if (localizedLabel != null && localizedLabel.Equals(label, StringComparison.InvariantCultureIgnoreCase)) - { - if (string.IsNullOrEmpty(Title) == false) - label = Title; - } - else - { - // the localizedLabel translated into something that's not just [alias], so use the translation - label = localizedLabel; - } - - return label; - } - - private Type _runtimeType; - - /// - /// Returns the CLR type based on it's assembly name stored in the config - /// - /// - public Type GetRuntimeType() - { - return _runtimeType ?? (_runtimeType = System.Type.GetType(Type)); - } - - /// - /// Used to try to get and cache the tree type - /// - /// - /// - internal static Type TryGetType(string type) - { - try - { - return ResolvedTypes.GetOrAdd(type, s => - { - var result = System.Type.GetType(type); - if (result != null) - { - return result; - } - - //we need to implement a bit of a hack here due to some trees being renamed and backwards compat - var parts = type.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); - if (parts.Length != 2) - throw new InvalidOperationException("Could not resolve type"); - if (parts[1].Trim() != "Umbraco.Web" || parts[0].StartsWith("Umbraco.Web.Trees") == false || parts[0].EndsWith("Controller")) - throw new InvalidOperationException("Could not resolve type"); - - //if it's one of our controllers but it's not suffixed with "Controller" then add it and try again - var tempType = parts[0] + "Controller, Umbraco.Web"; - - result = System.Type.GetType(tempType); - if (result != null) - return result; - - throw new InvalidOperationException("Could not resolve type"); - }); - } - catch (InvalidOperationException) - { - //swallow, this is our own exception, couldn't find the type - // fixme bad use of exceptions here! - return null; - } - } - } -} diff --git a/src/Umbraco.Core/Models/Section.cs b/src/Umbraco.Core/Models/Section.cs deleted file mode 100644 index 4b7f8309dd..0000000000 --- a/src/Umbraco.Core/Models/Section.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace Umbraco.Core.Models -{ - /// - /// Represents a section defined in the app.config file. - /// - public class Section - { - public Section(string name, string @alias, int sortOrder) - { - Name = name; - Alias = alias; - SortOrder = sortOrder; - } - - public Section() - { } - - public string Name { get; set; } - public string Alias { get; set; } - public int SortOrder { get; set; } - } -} diff --git a/src/Umbraco.Core/Services/ISectionService.cs b/src/Umbraco.Core/Services/ISectionService.cs deleted file mode 100644 index 899ae78245..0000000000 --- a/src/Umbraco.Core/Services/ISectionService.cs +++ /dev/null @@ -1,114 +0,0 @@ -using System.Collections.Generic; -using Umbraco.Core.Models; - -namespace Umbraco.Core.Services -{ - public interface ISectionService - { - /// - /// The cache storage for all applications - /// - IEnumerable
    GetSections(); - - /// - /// Get the user group's allowed sections - /// - /// - /// - IEnumerable
    GetAllowedSections(int userId); - - /// - /// Gets the application by its alias. - /// - /// The application alias. - /// - Section GetByAlias(string appAlias); - - /// - /// Creates a new applcation if no application with the specified alias is found. - /// - /// The application name. - /// The application alias. - /// The application icon, which has to be located in umbraco/images/tray folder. - void MakeNew(string name, string alias, string icon); - - /// - /// Makes the new. - /// - /// The name. - /// The alias. - /// The icon. - /// The sort order. - void MakeNew(string name, string alias, string icon, int sortOrder); - - /// - /// Deletes the section - /// - void DeleteSection(Section section); - } - - /// - /// Purely used to allow a service context to create the default services - /// - internal class EmptySectionService : ISectionService - { - /// - /// The cache storage for all applications - /// - public IEnumerable
    GetSections() - { - throw new System.NotImplementedException(); - } - - /// - /// Get the user's allowed sections - /// - /// - /// - public IEnumerable
    GetAllowedSections(int userId) - { - throw new System.NotImplementedException(); - } - - /// - /// Gets the application by its alias. - /// - /// The application alias. - /// - public Section GetByAlias(string appAlias) - { - throw new System.NotImplementedException(); - } - - /// - /// Creates a new applcation if no application with the specified alias is found. - /// - /// The application name. - /// The application alias. - /// The application icon, which has to be located in umbraco/images/tray folder. - public void MakeNew(string name, string alias, string icon) - { - throw new System.NotImplementedException(); - } - - /// - /// Makes the new. - /// - /// The name. - /// The alias. - /// The icon. - /// The sort order. - public void MakeNew(string name, string alias, string icon, int sortOrder) - { - throw new System.NotImplementedException(); - } - - /// - /// Deletes the section - /// - public void DeleteSection(Section section) - { - throw new System.NotImplementedException(); - } - } -} diff --git a/src/Umbraco.Core/Services/ServiceContext.cs b/src/Umbraco.Core/Services/ServiceContext.cs index 731d3a58c6..6d7ac8a5e7 100644 --- a/src/Umbraco.Core/Services/ServiceContext.cs +++ b/src/Umbraco.Core/Services/ServiceContext.cs @@ -25,8 +25,6 @@ namespace Umbraco.Core.Services private readonly Lazy _serverRegistrationService; private readonly Lazy _entityService; private readonly Lazy _relationService; - private readonly Lazy _treeService; - private readonly Lazy _sectionService; private readonly Lazy _macroService; private readonly Lazy _memberTypeService; private readonly Lazy _memberGroupService; @@ -38,7 +36,7 @@ namespace Umbraco.Core.Services /// /// Initializes a new instance of the class with lazy services. /// - public ServiceContext(Lazy publicAccessService, Lazy domainService, Lazy auditService, Lazy localizedTextService, Lazy tagService, Lazy contentService, Lazy userService, Lazy memberService, Lazy mediaService, Lazy contentTypeService, Lazy mediaTypeService, Lazy dataTypeService, Lazy fileService, Lazy localizationService, Lazy packagingService, Lazy serverRegistrationService, Lazy entityService, Lazy relationService, Lazy treeService, Lazy sectionService, Lazy macroService, Lazy memberTypeService, Lazy memberGroupService, Lazy notificationService, Lazy externalLoginService, Lazy redirectUrlService, Lazy consentService) + public ServiceContext(Lazy publicAccessService, Lazy domainService, Lazy auditService, Lazy localizedTextService, Lazy tagService, Lazy contentService, Lazy userService, Lazy memberService, Lazy mediaService, Lazy contentTypeService, Lazy mediaTypeService, Lazy dataTypeService, Lazy fileService, Lazy localizationService, Lazy packagingService, Lazy serverRegistrationService, Lazy entityService, Lazy relationService, Lazy macroService, Lazy memberTypeService, Lazy memberGroupService, Lazy notificationService, Lazy externalLoginService, Lazy redirectUrlService, Lazy consentService) { _publicAccessService = publicAccessService; _domainService = domainService; @@ -58,8 +56,6 @@ namespace Umbraco.Core.Services _serverRegistrationService = serverRegistrationService; _entityService = entityService; _relationService = relationService; - _treeService = treeService; - _sectionService = sectionService; _macroService = macroService; _memberTypeService = memberTypeService; _memberGroupService = memberGroupService; @@ -90,8 +86,6 @@ namespace Umbraco.Core.Services IMemberTypeService memberTypeService = null, IMemberService memberService = null, IUserService userService = null, - ISectionService sectionService = null, - IApplicationTreeService treeService = null, ITagService tagService = null, INotificationService notificationService = null, ILocalizedTextService localizedTextService = null, @@ -125,8 +119,6 @@ namespace Umbraco.Core.Services Lazy(serverRegistrationService), Lazy(entityService), Lazy(relationService), - Lazy(treeService), - Lazy(sectionService), Lazy(macroService), Lazy(memberTypeService), Lazy(memberGroupService), @@ -236,16 +228,6 @@ namespace Umbraco.Core.Services ///
    public IMemberService MemberService => _memberService.Value; - /// - /// Gets the - /// - public ISectionService SectionService => _sectionService.Value; - - /// - /// Gets the - /// - public IApplicationTreeService ApplicationTreeService => _treeService.Value; - /// /// Gets the MemberTypeService /// diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 2236854351..8395dd9cb8 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -678,7 +678,6 @@ - @@ -875,7 +874,6 @@ - @@ -1390,7 +1388,6 @@ - @@ -1420,7 +1417,6 @@ - diff --git a/src/Umbraco.Tests/Cache/DistributedCacheBinderTests.cs b/src/Umbraco.Tests/Cache/DistributedCacheBinderTests.cs index 50b27da89f..3532a11c63 100644 --- a/src/Umbraco.Tests/Cache/DistributedCacheBinderTests.cs +++ b/src/Umbraco.Tests/Cache/DistributedCacheBinderTests.cs @@ -47,13 +47,6 @@ namespace Umbraco.Tests.Cache //Permission.Deleted += PermissionDeleted; //PermissionRepository.AssignedPermissions += CacheRefresherEventHandler_AssignedPermissions; - new EventDefinition(null, serviceContext.ApplicationTreeService, new EventArgs(), "Deleted"), - new EventDefinition(null, serviceContext.ApplicationTreeService, new EventArgs(), "Updated"), - new EventDefinition(null, serviceContext.ApplicationTreeService, new EventArgs(), "New"), - - new EventDefinition(null, serviceContext.SectionService, new EventArgs(), "Deleted"), - new EventDefinition(null, serviceContext.SectionService, new EventArgs(), "New"), - new EventDefinition>(null, serviceContext.UserService, new SaveEventArgs(Enumerable.Empty())), new EventDefinition>(null, serviceContext.UserService, new DeleteEventArgs(Enumerable.Empty())), new EventDefinition>(null, serviceContext.UserService, new SaveEventArgs(Enumerable.Empty())), diff --git a/src/Umbraco.Tests/Packaging/Packages/Document_Type_Picker_1.1.zip b/src/Umbraco.Tests/Packaging/Packages/Document_Type_Picker_1.1.zip new file mode 100644 index 0000000000000000000000000000000000000000..18449bd3735870c98e711525a7ea9883941e321f GIT binary patch literal 6147 zcma)=RZJWVl!bAp6qn)@DHL~ich`a9GDv|U9o*dqXP~$j8>HwIcc+6CcZxg3_Ww7V z%_f^o_TGmt_vYr@m-BSARFP4L5D*YB5dOwu%SOrHjmG{vav>nF{0m`zTP^`UD|RbO zJ{xvEJ{}u(VJ6 z>RqIdc64-an*}K5AZ-UAemx4uIqk2~WIP~j*f$8$!If+UInR2e$q(g!=FuH-F4L-4 z9dYM91Y;{#CsPV><>WPb+O>B}bWg&$d6f8SWagJ$DRHjNnOwXeRSe4r{pSursKP2+ z5*!Csj==m?xdmqNt(gZb?I}|u@T-17dXyRCfw)Zm+V*Ay#4LOW7g^5bn$2t^_RxbI zb~nFqnEJIPe82VAW1vgLGN5?NciA2C@u8*RO#64`l1El`KGb^eq{hBl4d;)_RN9|h z;2vSvnrG6N7_BRX3JZ;r19(S{2)`5E;kr~#Mr_~Kl~nJtaO8z|tn0FriIPLEk-0X6 zvkrodN)M#{Ib62%^qF1q_<~==kbKIOK6YgSp`>(Lk|N2qo8u_hSPg*eGz2WtsELJg z&i!U|fb7dz**KzB*2#Yx-xvl~W{KI5olssKlTbSoK4HwQbkz%LRT0Zs&^mDvdZM^f zaJ6-Hs!Z$PJ3v>ei2UT60fWv}du)Y_hI){-2L5Ct%oxT=k6UZvoJj>&I^!)jbKH&Z zn`AY%?Dat5!Xs-{1DBUi;|eN+y0ooBU9<+W zXtE^aR5vrFAIN4;N9Ijz8F;tVH*fW17b6FKG25!*j&7OkS`7Kf{_6PgnqvHT(@?hk zLv`$3uPtrWhuOD|xBV3K-Z=x^L*J84#xI&3h8UoEF81qz>!y#mJLY5D1@>wIkH3r( zKD4hMlFtyiV)%T#VfSo7!H3Sox<$um(_bE!wiwmw%hWWmIl0OA#aZY==|=ILqn824 zdZOgHV!5W3XWn)GHS;s9Br+0=)89}`$X;b0zt|G{kaO!YVoO;^U|9U?4*?C z!%|*r>zZj^}+;2PT53CIGVe$h&mj**Cis2A- z`8%{XPB83WbizI%%r;n-d1*hl?rK}yc6^H~msEv1`WhYfE;4vHO~yK60KQbPy+H~& z`rp(kJ4~kAZ*nz~nKy2r#MMU^21S{qW`tix;>?ZXUT`dLZ6bRY-q$g#o^Br|Ldz)_ zDg*O{d2CY7!@cjB=Op+FYx~N>fq<(Ap`nroe+W26+&nUTGK}0iDtO^=(%MYj)iRO# z?oT?0ZWTHZ_P``(^9-`JtTQyLdIA#NI|)c0!3Dc?);nWKZ{Cszq-_5F9y*io>5Hs_ zAnWq_~2s-hqXHNdHM>xV6h`*qRK!=$MrB=hXz+vHdBI$$LU=ggLL z^jO=a$aVtKjpt#M5lUhlQ9Qx@QXkS}vB$}6U~xu4-=rlJC}joEaE7=&(6 z-FR1gL)Z7leecjH^`_wsAd@Ib5u$uuuP82a*C4daRl_d$88oY z?qOz0+t3y^;Qp(6uXXmoj0;jop*I%skt<_q-YP(blUACHztsDilz|0Jd@ULU$sc+RLK@h*@r?;B}v z5IR{Rml=D#;)V+nRmdHtzuv~~FmDRVv)(rn+fk1Yzhcp14yw3Di#tW^85Hq1ZQVh1EGVb^Pax`C0-tS*wo!YH)*C?b4l>Vd)h$bQvM zNSz2P#E`kRXV;MRxn)F7ARMWiXcSQ(iu@Eq6X`bGc#i~zADH>Am4e1_OzOkKBI!m< z5joA{8()ep_|OZrSOWD$LqRZUQF*|}qFR(&V0a?+IQvVvdeiP8IhwTVglv`-h2`=uZ zwI0SrzXM<)cRy#(T3;a9U#glApBlWuG3yBb(Dk~5p$5_3H;wnI@2XOw=YrfS{!*7u z!a)pbk#MBP%1@F8K3KPxe-~fzp(YrDTIB`9&np ztMlJ}{Q*|$yDUgbRY&CGkDxUh_5?3`NWEGwS7;n+Y6(spup!c*h{@AP*SUfef@0ej zlCCAABKL2mkX~}vCOp`U((16TP~2 zxKU*Dd2$2VNmPQMwt~1_3Aj|k8m7@uWe7mq1%nXTy!oGrE^CkEty^Pbnro5D>Aspl ziUt=k7gWZqNu}1Qa&_*oo?Z2$e^eRLTjSg3$omYe6;Z8!i9pU+Of8oM{Iqvl_}wkRr_ix0&v0i6~@8!2pJC z0?yO1Lt}PzprseZS^620EvXAmX#;6|$gCV5aw66pHHh;7pohN53HJUgym11h0jGT- znJ#Tb$S;1B9Xh0Q7{kcJ_icsw*?<*Go{dAqDRdLD{m}#B1gZm$H28~O^a20@7UFd; z^36^G%h6?Y1+qrj_`+%8r5B+Oov?kBJsBZ})OR8HZny>6jN6V{zL7h7RpcaO z5gO`zz>0is7z+KjO(6iDFK#}CfU5I7l!)6=*Ub>G`aIq+tQvmPydGtaCD@oHL7j90pUrRf%j^&T{Jpd~)}G*FsWLG6xG|$2-QLDh zs_|#`jtveNrTh3?w*S(#Uy?=#qbF-XKV_X`86NIM@j3^XQuIuxS==-_^47lWv$vJq zAS-P47_7Qm>CT+iJm*k8G{$l8J-3y)##sctTD3kLG_*=!qr&g1_QQB(#59Eb%crLV zyB0Zy2en_nt@k~(T!~f6Jdu38;wfg|vSD{Jz{iU_vPH+URQobavCM`S`ojBP9;v#WL= z>Z>yLbwtLvJL$L%%hHAtZ)_WxxdjDH?IaWh#|7-DgT4f|^*0Mk?5N0h@9(^Ql#GIQ zIPZo_?1=li8lhhfl>D5VUi_o>5u6|BkcdlML!dv$Kug0CZ>N#VXU~Vj14NKiemoKL z8^EUPT9E^p7+)OUXJn4d@ETz@+s$N&yHVJsIlvm?kZ-d?&o2WH?C?`O%u(#MA9=o$ zFRG_EyMLUP8e&~#83rVlo?X{NHswSt)xi)PQDuT0WK_FkPNI*INOd%XY!yZvU(ZCP zliy@uGXh7|XauM@$j8aYgvj>o&U@JHj=HIZDP;bHTs~l z#J%r#h;A3H8V{i4hs=?{$rrsAJ!&sZf`nK1fw!_E1@2Ahg8SUhmgqI(azDLQ4M@iN zC^^OE24Bns*a5 zYX13M#}>VKWJ{)NbfNLRWwol7POHxS-zz(`+@#DH?~BEaN{`5>vKM7uzs4yEHtZ6? z%b<$VnhJ`OpC?)Tqq&=9t&ST?%NVFxmMrV7#gut+RWr>z947bo(U#Wsuepn;P z2CFR7mLNf@aY{4MQuz%Ey_;>92&Gazd0)1pkuV>KwP$FYH0)fzzAyzRb18KS!#fP| zDm)@sn%t?!zS76PA{H;7zsbm`LvQ< zujr5-h3qLt)ms{ZJ(|eq>yHUna6T$~q`<+!`i{I(0_}hdrjfw{)sLA>FU8Y#MTJzp z*e50C?c_m#FH~OBZ=h(72(>P=r?NoiPd(G^7sqAn!C@OdA#19pGdl0kztLc)mT@T{ z7Be~GoNdd0Ql|LXVMXGm$s{cIE-K^)y>^vSo|GH9rXpxxY-9~l>K#GNBhG=cQF4E7 zPQ)#W|4u#$G>eS?!x}d`c5DPSs!rJR`EPK;qm=L;;3B%{6}`SczsYyVAJc^r&E~K3qG|;RjqSU&+G3p*#4?VcqDZL6ezyGN!?Y&PAwMCGXttI%{xhL8yTaq?Eq< z!Dq0=I+ttmY;wh-`*-ieub$qXlxxTIW~q$@is3z}pp}|?M^7ZTK{O0Ozv+k!XItJ+ ztD2PAu@d&U|2j?_Wf89v($Jg`iub|tXMYh$t*YDIY6l0NCw1QrW4HSAJsemBZ5|$j zc=CN$8#*Yuse0CY|4tT1nYIGD4da+(W(J81-!t|qml8NsXvJnZY`DH*u52LwX6eOO zS=lmpgRjK@9j`nq4@p?zC}%LCs(}HYF7g11dgq<8GP&Ae+?Lx6RC8wWoWnR|#or^n z#*ni+O-L?dB$%ySp}o{={FHmXPRfKTAdMzNu`Kd!M#z({447Y!hR=?#UPT;3TsRPy zp4Ci{VaAufHd_@(ddu4eCH3r1WMq6r})JmSFPFdJrM`@a{?6axWC`G}A^DqGoIlg>9x%ssmFHAc zA;yh4FL&ObY{WN%1-N@ZkQEL$$G;3WwzQ5C?2izkG6-CG9J)TO|IP@-u!NrV(IF!O z^B$y&*w-qd>0l#76lq7<_+~i>wK9}j-kQ0>a__4_Y*flT4t|0TMxo|Gdl@&YMrW|_ zyf>Rk#+sy%!PnQtW14igo!1F%z6^)&_4m-!DYYxrb*s~~n$M{#zt~jJ>Kv8V(9+i4 z*g{(07N zU#$Pmp^gUD6>_j~06U-(Tzh@KF1lDf`}$<|G`?Nw)~I&+x44+O+%wT@SuA!g(T~rN zmHKA#w_@Giy|&*|g5qw%ZWaBZm22Khof#gU!Ab#UAiM>3)4w63*ZCrZ{O}|}InXr) zDEm-=^Z;@c|HA%q!+sU`IP!MD@9;zfov$>&X%zS7{fYQ{R}k>5k%iHQbAPk6 zv>`9*-r5WeOnzihj!z!MY(Xwx=F_No(zlR6)h*&N*Y?j*K;h+iW6?!6m(t{sdS4>4 zTY#&rxiRB(jqCp|IZW2TpJOt1#LY=mIgpIsnu_FWt6e;Mw;{xXkgAk8nI`qZsD(Bv zyvkm`XZB0;m2<6&qi_R=jZU%pn;+RV=FBo@`K9B9KhnO?%gL_4Nh)<;z>P1{#oja~ zP5Tq~;tO(M&{(VFdC$4z)(}~%)j} zHaDuLH34?Tfy}eJl|Mlb3)|1$JHVBocd@TYa85+6|IRZ*9m?fCGU0)xkq{6-Cf*ZaN#F@~PP8t@EI#8X^FN|lf;z-*2tigPkH zbrg##Zrs60*X2O={)MXU%7Jr7nG#W4#aq<9*%R6EOj#p%)rC#(AeEk5y&=)qjcZUYRKJY3dvzFX0C%hZGvfmP~T#f zQE#0|`ZS;WNqe8?#T>YB${6@t4y*v{!=MN#$xTUjBy>z@K=aez!CKP*$1RsptqQGc zk|dGUV%496zS~E$+R}9%)*?sIBLm?z(d9%m`4Vn|Q4@2fa3w3t2p9ictT=2AdNUk? zLMN+KIpxkKthpLGVjEiap8)2v_dljd3GU)?Wp^bc@nX?%6L_7;3XYi#EDg^QzNTP` zBCVgG%9kK`2UACUoY-(lhqhT1bsm4*L4MLduukZszN-JxqW4DwVYV}pKLAJ%KHlO7 zpyewOysjBD1=o3I%T2PT-pko?rE%RcxC@rsV8_gkw$Oz4V4M&15?no@=0_tjhZ+fC z8$IL`v60`W-u5o)k=v(nZlh|cA|eqX{NLI6KX&^c_5V%M|5cUzFV+9;;P?NfNc#_` z|9SmC{EUV0?-Bt45rGV0H$DE%j^h-f<+aM~_CI_MRr*hAsiLC&dxP{(H~m8q(toG_ E0K6^9ApigX literal 0 HcmV?d00001 diff --git a/src/Umbraco.Tests/Services/SectionServiceTests.cs b/src/Umbraco.Tests/Services/SectionServiceTests.cs index ca5d755220..206c99ffbf 100644 --- a/src/Umbraco.Tests/Services/SectionServiceTests.cs +++ b/src/Umbraco.Tests/Services/SectionServiceTests.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Threading; using Umbraco.Core.Models.Membership; using Umbraco.Tests.Testing; +using Umbraco.Web.Services; namespace Umbraco.Tests.Services { @@ -14,24 +15,20 @@ namespace Umbraco.Tests.Services [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest, WithApplication = true)] public class SectionServiceTests : TestWithSomeContentBase { - public override void CreateTestData() - { - base.CreateTestData(); - - ServiceContext.SectionService.MakeNew("Content", "content", "icon-content"); - ServiceContext.SectionService.MakeNew("Media", "media", "icon-media"); - ServiceContext.SectionService.MakeNew("Settings", "settings", "icon-settings"); - ServiceContext.SectionService.MakeNew("Developer", "developer", "icon-developer"); - } + //fixme + private ISectionService SectionService => new SectionService(ServiceContext.UserService, null, null); + [Test] public void SectionService_Can_Get_Allowed_Sections_For_User() { + //fixme - need to mock + // Arrange var user = CreateTestUser(); // Act - var result = ServiceContext.SectionService.GetAllowedSections(user.Id).ToList(); + var result = SectionService.GetAllowedSections(user.Id).ToList(); // Assert Assert.AreEqual(3, result.Count); diff --git a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs index 9e2a2156ee..31ee34843d 100644 --- a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs +++ b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs @@ -60,8 +60,7 @@ namespace Umbraco.Tests.TestHelpers.ControllerTesting memberTypeService: mockedMemberTypeService, dataTypeService: mockedDataTypeService, contentTypeService: mockedContentTypeService, - localizedTextService:Mock.Of(), - sectionService:Mock.Of()); + localizedTextService:Mock.Of()); var globalSettings = SettingsForTests.GenerateMockGlobalSettings(); diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs b/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs index 8c230f98d0..4dfaa9e674 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs @@ -73,8 +73,6 @@ namespace Umbraco.Tests.TestHelpers MockService(container), MockService(container), MockService(container), - MockService(container), - MockService(container), MockService(container), MockService(container), MockService(container), diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects.cs b/src/Umbraco.Tests/TestHelpers/TestObjects.cs index 14ffeb743f..f7f0d26c0e 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects.cs @@ -188,9 +188,7 @@ namespace Umbraco.Tests.TestHelpers new DirectoryInfo(IOHelper.GetRootDirectorySafe()))); }); var relationService = GetLazyService(factory, c => new RelationService(scopeProvider, logger, eventMessagesFactory, entityService.Value, GetRepo(c), GetRepo(c))); - var treeService = GetLazyService(factory, c => new ApplicationTreeService(logger, cache, typeLoader)); - var tagService = GetLazyService(factory, c => new TagService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); - var sectionService = GetLazyService(factory, c => new SectionService(userService.Value, treeService.Value, scopeProvider, cache)); + var tagService = GetLazyService(factory, c => new TagService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); var redirectUrlService = GetLazyService(factory, c => new RedirectUrlService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); var consentService = GetLazyService(factory, c => new ConsentService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); @@ -213,8 +211,6 @@ namespace Umbraco.Tests.TestHelpers serverRegistrationService, entityService, relationService, - treeService, - sectionService, macroService, memberTypeService, memberGroupService, diff --git a/src/Umbraco.Tests/TreesAndSections/ApplicationTreeTest.cs b/src/Umbraco.Tests/TreesAndSections/ApplicationTreeTest.cs index 951246c535..95d90f1463 100644 --- a/src/Umbraco.Tests/TreesAndSections/ApplicationTreeTest.cs +++ b/src/Umbraco.Tests/TreesAndSections/ApplicationTreeTest.cs @@ -1,397 +1,397 @@ -using System.IO; -using NUnit.Framework; -using Umbraco.Core.Services; -using Umbraco.Tests.TestHelpers; -using System; -using System.Linq; -using System.Threading; -using Umbraco.Tests.Testing; -using Umbraco.Web.Services; -using Current = Umbraco.Web.Composing.Current; +//using System.IO; +//using NUnit.Framework; +//using Umbraco.Core.Services; +//using Umbraco.Tests.TestHelpers; +//using System; +//using System.Linq; +//using System.Threading; +//using Umbraco.Tests.Testing; +//using Umbraco.Web.Services; +//using Current = Umbraco.Web.Composing.Current; -namespace Umbraco.Tests.TreesAndSections -{ +//namespace Umbraco.Tests.TreesAndSections +//{ - /// - ///This is a test class for ApplicationTreeTest and is intended - ///to contain all ApplicationTreeTest Unit Tests - /// - [TestFixture] - [Apartment(ApartmentState.STA)] - [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)] - public class ApplicationTreeTest : TestWithDatabaseBase - { - public override void SetUp() - { - base.SetUp(); +// /// +// ///This is a test class for ApplicationTreeTest and is intended +// ///to contain all ApplicationTreeTest Unit Tests +// /// +// [TestFixture] +// [Apartment(ApartmentState.STA)] +// [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)] +// public class ApplicationTreeTest : TestWithDatabaseBase +// { +// public override void SetUp() +// { +// base.SetUp(); - var treesConfig = TestHelper.MapPathForTest("~/TEMP/TreesAndSections/trees.config"); - var appConfig = TestHelper.MapPathForTest("~/TEMP/TreesAndSections/applications.config"); - Directory.CreateDirectory(TestHelper.MapPathForTest("~/TEMP/TreesAndSections")); - using (var writer = File.CreateText(treesConfig)) - { - writer.Write(ResourceFiles.trees); - } - using (var writer = File.CreateText(appConfig)) - { - writer.Write(ResourceFiles.applications); - } +// var treesConfig = TestHelper.MapPathForTest("~/TEMP/TreesAndSections/trees.config"); +// var appConfig = TestHelper.MapPathForTest("~/TEMP/TreesAndSections/applications.config"); +// Directory.CreateDirectory(TestHelper.MapPathForTest("~/TEMP/TreesAndSections")); +// using (var writer = File.CreateText(treesConfig)) +// { +// writer.Write(ResourceFiles.trees); +// } +// using (var writer = File.CreateText(appConfig)) +// { +// writer.Write(ResourceFiles.applications); +// } - ApplicationTreeService.TreeConfigFilePath = treesConfig; - SectionService.AppConfigFilePath = appConfig; - } +// //ApplicationTreeService.TreeConfigFilePath = treesConfig; +// SectionService.AppConfigFilePath = appConfig; +// } - public override void TearDown() - { - base.TearDown(); +// public override void TearDown() +// { +// base.TearDown(); - if (Directory.Exists(TestHelper.MapPathForTest("~/TEMP/TreesAndSections"))) - { - Directory.Delete(TestHelper.MapPathForTest("~/TEMP/TreesAndSections"), true); - } - ApplicationTreeService.TreeConfigFilePath = null; - SectionService.AppConfigFilePath = null; - } +// if (Directory.Exists(TestHelper.MapPathForTest("~/TEMP/TreesAndSections"))) +// { +// Directory.Delete(TestHelper.MapPathForTest("~/TEMP/TreesAndSections"), true); +// } +// //ApplicationTreeService.TreeConfigFilePath = null; +// SectionService.AppConfigFilePath = null; +// } - /// - /// Creates a new app tree linked to an application, then delete the application and make sure the tree is gone as well - /// - [Test()] - public void ApplicationTree_Make_New_Then_Delete_App() - { - //create new app - var appName = Guid.NewGuid().ToString("N"); - var treeName = Guid.NewGuid().ToString("N"); - Current.Services.SectionService.MakeNew(appName, appName, "icon.jpg"); +// ///// +// ///// Creates a new app tree linked to an application, then delete the application and make sure the tree is gone as well +// ///// +// //[Test()] +// //public void ApplicationTree_Make_New_Then_Delete_App() +// //{ +// // //create new app +// // var appName = Guid.NewGuid().ToString("N"); +// // var treeName = Guid.NewGuid().ToString("N"); +// // Current.Services.SectionService.MakeNew(appName, appName, "icon.jpg"); - //check if it exists - var app = Current.Services.SectionService.GetByAlias(appName); - Assert.IsNotNull(app); +// // //check if it exists +// // var app = Current.Services.SectionService.GetByAlias(appName); +// // Assert.IsNotNull(app); - //create the new app tree assigned to the new app - Current.Services.ApplicationTreeService.MakeNew(false, 0, app.Alias, treeName, treeName, "icon.jpg", "icon.jpg", "Umbraco.Web.Trees.ContentTreeController, Umbraco.Web"); - var tree = Current.Services.ApplicationTreeService.GetByAlias(treeName); - Assert.IsNotNull(tree); +// // //create the new app tree assigned to the new app +// // Current.Services.ApplicationTreeService.MakeNew(false, 0, app.Alias, treeName, treeName, "icon.jpg", "icon.jpg", "Umbraco.Web.Trees.ContentTreeController, Umbraco.Web"); +// // var tree = Current.Services.ApplicationTreeService.GetByAlias(treeName); +// // Assert.IsNotNull(tree); - //now delete the app - Current.Services.SectionService.DeleteSection(app); +// // //now delete the app +// // Current.Services.SectionService.DeleteSection(app); - //check that the tree is gone - Assert.AreEqual(0, Current.Services.ApplicationTreeService.GetApplicationTrees(treeName).Count()); - } +// // //check that the tree is gone +// // Assert.AreEqual(0, Current.Services.ApplicationTreeService.GetApplicationTrees(treeName).Count()); +// //} - #region Tests to write - ///// - /////A test for ApplicationTree Constructor - ///// - //[TestMethod()] - //public void ApplicationTreeConstructorTest() - //{ - // bool silent = false; // TODO: Initialize to an appropriate value - // bool initialize = false; // TODO: Initialize to an appropriate value - // byte sortOrder = 0; // TODO: Initialize to an appropriate value - // string applicationAlias = string.Empty; // TODO: Initialize to an appropriate value - // string alias = string.Empty; // TODO: Initialize to an appropriate value - // string title = string.Empty; // TODO: Initialize to an appropriate value - // string iconClosed = string.Empty; // TODO: Initialize to an appropriate value - // string iconOpened = string.Empty; // TODO: Initialize to an appropriate value - // string assemblyName = string.Empty; // TODO: Initialize to an appropriate value - // string type = string.Empty; // TODO: Initialize to an appropriate value - // string action = string.Empty; // TODO: Initialize to an appropriate value - // ApplicationTree target = new ApplicationTree(silent, initialize, sortOrder, applicationAlias, alias, title, iconClosed, iconOpened, assemblyName, type, action); - // Assert.Inconclusive("TODO: Implement code to verify target"); - //} +// #region Tests to write +// ///// +// /////A test for ApplicationTree Constructor +// ///// +// //[TestMethod()] +// //public void ApplicationTreeConstructorTest() +// //{ +// // bool silent = false; // TODO: Initialize to an appropriate value +// // bool initialize = false; // TODO: Initialize to an appropriate value +// // byte sortOrder = 0; // TODO: Initialize to an appropriate value +// // string applicationAlias = string.Empty; // TODO: Initialize to an appropriate value +// // string alias = string.Empty; // TODO: Initialize to an appropriate value +// // string title = string.Empty; // TODO: Initialize to an appropriate value +// // string iconClosed = string.Empty; // TODO: Initialize to an appropriate value +// // string iconOpened = string.Empty; // TODO: Initialize to an appropriate value +// // string assemblyName = string.Empty; // TODO: Initialize to an appropriate value +// // string type = string.Empty; // TODO: Initialize to an appropriate value +// // string action = string.Empty; // TODO: Initialize to an appropriate value +// // ApplicationTree target = new ApplicationTree(silent, initialize, sortOrder, applicationAlias, alias, title, iconClosed, iconOpened, assemblyName, type, action); +// // Assert.Inconclusive("TODO: Implement code to verify target"); +// //} - ///// - /////A test for ApplicationTree Constructor - ///// - //[TestMethod()] - //public void ApplicationTreeConstructorTest1() - //{ - // ApplicationTree target = new ApplicationTree(); - // Assert.Inconclusive("TODO: Implement code to verify target"); - //} +// ///// +// /////A test for ApplicationTree Constructor +// ///// +// //[TestMethod()] +// //public void ApplicationTreeConstructorTest1() +// //{ +// // ApplicationTree target = new ApplicationTree(); +// // Assert.Inconclusive("TODO: Implement code to verify target"); +// //} - ///// - /////A test for Delete - ///// - //[TestMethod()] - //public void DeleteTest() - //{ - // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value - // target.Delete(); - // Assert.Inconclusive("A method that does not return a value cannot be verified."); - //} +// ///// +// /////A test for Delete +// ///// +// //[TestMethod()] +// //public void DeleteTest() +// //{ +// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value +// // target.Delete(); +// // Assert.Inconclusive("A method that does not return a value cannot be verified."); +// //} - ///// - /////A test for Save - ///// - //[TestMethod()] - //public void SaveTest() - //{ - // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value - // target.Save(); - // Assert.Inconclusive("A method that does not return a value cannot be verified."); - //} +// ///// +// /////A test for Save +// ///// +// //[TestMethod()] +// //public void SaveTest() +// //{ +// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value +// // target.Save(); +// // Assert.Inconclusive("A method that does not return a value cannot be verified."); +// //} - ///// - /////A test for getAll - ///// - //[TestMethod()] - //public void getAllTest() - //{ - // ApplicationTree[] expected = null; // TODO: Initialize to an appropriate value - // ApplicationTree[] actual; - // actual = ApplicationTree.getAll(); - // Assert.AreEqual(expected, actual); - // Assert.Inconclusive("Verify the correctness of this test method."); - //} +// ///// +// /////A test for getAll +// ///// +// //[TestMethod()] +// //public void getAllTest() +// //{ +// // ApplicationTree[] expected = null; // TODO: Initialize to an appropriate value +// // ApplicationTree[] actual; +// // actual = ApplicationTree.getAll(); +// // Assert.AreEqual(expected, actual); +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} - ///// - /////A test for getApplicationTree - ///// - //[TestMethod()] - //public void getApplicationTreeTest() - //{ - // string applicationAlias = string.Empty; // TODO: Initialize to an appropriate value - // ApplicationTree[] expected = null; // TODO: Initialize to an appropriate value - // ApplicationTree[] actual; - // actual = ApplicationTree.getApplicationTree(applicationAlias); - // Assert.AreEqual(expected, actual); - // Assert.Inconclusive("Verify the correctness of this test method."); - //} +// ///// +// /////A test for getApplicationTree +// ///// +// //[TestMethod()] +// //public void getApplicationTreeTest() +// //{ +// // string applicationAlias = string.Empty; // TODO: Initialize to an appropriate value +// // ApplicationTree[] expected = null; // TODO: Initialize to an appropriate value +// // ApplicationTree[] actual; +// // actual = ApplicationTree.getApplicationTree(applicationAlias); +// // Assert.AreEqual(expected, actual); +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} - ///// - /////A test for getApplicationTree - ///// - //[TestMethod()] - //public void getApplicationTreeTest1() - //{ - // string applicationAlias = string.Empty; // TODO: Initialize to an appropriate value - // bool onlyInitializedApplications = false; // TODO: Initialize to an appropriate value - // ApplicationTree[] expected = null; // TODO: Initialize to an appropriate value - // ApplicationTree[] actual; - // actual = ApplicationTree.getApplicationTree(applicationAlias, onlyInitializedApplications); - // Assert.AreEqual(expected, actual); - // Assert.Inconclusive("Verify the correctness of this test method."); - //} +// ///// +// /////A test for getApplicationTree +// ///// +// //[TestMethod()] +// //public void getApplicationTreeTest1() +// //{ +// // string applicationAlias = string.Empty; // TODO: Initialize to an appropriate value +// // bool onlyInitializedApplications = false; // TODO: Initialize to an appropriate value +// // ApplicationTree[] expected = null; // TODO: Initialize to an appropriate value +// // ApplicationTree[] actual; +// // actual = ApplicationTree.getApplicationTree(applicationAlias, onlyInitializedApplications); +// // Assert.AreEqual(expected, actual); +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} - ///// - /////A test for getByAlias - ///// - //[TestMethod()] - //public void getByAliasTest() - //{ - // string treeAlias = string.Empty; // TODO: Initialize to an appropriate value - // ApplicationTree expected = null; // TODO: Initialize to an appropriate value - // ApplicationTree actual; - // actual = ApplicationTree.getByAlias(treeAlias); - // Assert.AreEqual(expected, actual); - // Assert.Inconclusive("Verify the correctness of this test method."); - //} +// ///// +// /////A test for getByAlias +// ///// +// //[TestMethod()] +// //public void getByAliasTest() +// //{ +// // string treeAlias = string.Empty; // TODO: Initialize to an appropriate value +// // ApplicationTree expected = null; // TODO: Initialize to an appropriate value +// // ApplicationTree actual; +// // actual = ApplicationTree.getByAlias(treeAlias); +// // Assert.AreEqual(expected, actual); +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} - ///// - /////A test for Action - ///// - //[TestMethod()] - //public void ActionTest() - //{ - // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value - // string expected = string.Empty; // TODO: Initialize to an appropriate value - // string actual; - // target.Action = expected; - // actual = target.Action; - // Assert.AreEqual(expected, actual); - // Assert.Inconclusive("Verify the correctness of this test method."); - //} +// ///// +// /////A test for Action +// ///// +// //[TestMethod()] +// //public void ActionTest() +// //{ +// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value +// // string expected = string.Empty; // TODO: Initialize to an appropriate value +// // string actual; +// // target.Action = expected; +// // actual = target.Action; +// // Assert.AreEqual(expected, actual); +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} - ///// - /////A test for Alias - ///// - //[TestMethod()] - //public void AliasTest() - //{ - // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value - // string actual; - // actual = target.Alias; - // Assert.Inconclusive("Verify the correctness of this test method."); - //} +// ///// +// /////A test for Alias +// ///// +// //[TestMethod()] +// //public void AliasTest() +// //{ +// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value +// // string actual; +// // actual = target.Alias; +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} - ///// - /////A test for ApplicationAlias - ///// - //[TestMethod()] - //public void ApplicationAliasTest() - //{ - // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value - // string actual; - // actual = target.ApplicationAlias; - // Assert.Inconclusive("Verify the correctness of this test method."); - //} +// ///// +// /////A test for ApplicationAlias +// ///// +// //[TestMethod()] +// //public void ApplicationAliasTest() +// //{ +// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value +// // string actual; +// // actual = target.ApplicationAlias; +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} - ///// - /////A test for AssemblyName - ///// - //[TestMethod()] - //public void AssemblyNameTest() - //{ - // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value - // string expected = string.Empty; // TODO: Initialize to an appropriate value - // string actual; - // target.AssemblyName = expected; - // actual = target.AssemblyName; - // Assert.AreEqual(expected, actual); - // Assert.Inconclusive("Verify the correctness of this test method."); - //} +// ///// +// /////A test for AssemblyName +// ///// +// //[TestMethod()] +// //public void AssemblyNameTest() +// //{ +// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value +// // string expected = string.Empty; // TODO: Initialize to an appropriate value +// // string actual; +// // target.AssemblyName = expected; +// // actual = target.AssemblyName; +// // Assert.AreEqual(expected, actual); +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} - ///// - /////A test for IconClosed - ///// - //[TestMethod()] - //public void IconClosedTest() - //{ - // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value - // string expected = string.Empty; // TODO: Initialize to an appropriate value - // string actual; - // target.IconClosed = expected; - // actual = target.IconClosed; - // Assert.AreEqual(expected, actual); - // Assert.Inconclusive("Verify the correctness of this test method."); - //} +// ///// +// /////A test for IconClosed +// ///// +// //[TestMethod()] +// //public void IconClosedTest() +// //{ +// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value +// // string expected = string.Empty; // TODO: Initialize to an appropriate value +// // string actual; +// // target.IconClosed = expected; +// // actual = target.IconClosed; +// // Assert.AreEqual(expected, actual); +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} - ///// - /////A test for IconOpened - ///// - //[TestMethod()] - //public void IconOpenedTest() - //{ - // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value - // string expected = string.Empty; // TODO: Initialize to an appropriate value - // string actual; - // target.IconOpened = expected; - // actual = target.IconOpened; - // Assert.AreEqual(expected, actual); - // Assert.Inconclusive("Verify the correctness of this test method."); - //} +// ///// +// /////A test for IconOpened +// ///// +// //[TestMethod()] +// //public void IconOpenedTest() +// //{ +// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value +// // string expected = string.Empty; // TODO: Initialize to an appropriate value +// // string actual; +// // target.IconOpened = expected; +// // actual = target.IconOpened; +// // Assert.AreEqual(expected, actual); +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} - ///// - /////A test for Initialize - ///// - //[TestMethod()] - //public void InitializeTest() - //{ - // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value - // bool expected = false; // TODO: Initialize to an appropriate value - // bool actual; - // target.Initialize = expected; - // actual = target.Initialize; - // Assert.AreEqual(expected, actual); - // Assert.Inconclusive("Verify the correctness of this test method."); - //} +// ///// +// /////A test for Initialize +// ///// +// //[TestMethod()] +// //public void InitializeTest() +// //{ +// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value +// // bool expected = false; // TODO: Initialize to an appropriate value +// // bool actual; +// // target.Initialize = expected; +// // actual = target.Initialize; +// // Assert.AreEqual(expected, actual); +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} - ///// - /////A test for Silent - ///// - //[TestMethod()] - //public void SilentTest() - //{ - // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value - // bool expected = false; // TODO: Initialize to an appropriate value - // bool actual; - // target.Silent = expected; - // actual = target.Silent; - // Assert.AreEqual(expected, actual); - // Assert.Inconclusive("Verify the correctness of this test method."); - //} +// ///// +// /////A test for Silent +// ///// +// //[TestMethod()] +// //public void SilentTest() +// //{ +// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value +// // bool expected = false; // TODO: Initialize to an appropriate value +// // bool actual; +// // target.Silent = expected; +// // actual = target.Silent; +// // Assert.AreEqual(expected, actual); +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} - ///// - /////A test for SortOrder - ///// - //[TestMethod()] - //public void SortOrderTest() - //{ - // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value - // byte expected = 0; // TODO: Initialize to an appropriate value - // byte actual; - // target.SortOrder = expected; - // actual = target.SortOrder; - // Assert.AreEqual(expected, actual); - // Assert.Inconclusive("Verify the correctness of this test method."); - //} +// ///// +// /////A test for SortOrder +// ///// +// //[TestMethod()] +// //public void SortOrderTest() +// //{ +// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value +// // byte expected = 0; // TODO: Initialize to an appropriate value +// // byte actual; +// // target.SortOrder = expected; +// // actual = target.SortOrder; +// // Assert.AreEqual(expected, actual); +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} - ///// - /////A test for SqlHelper - ///// - //[TestMethod()] - //public void SqlHelperTest() - //{ - // ISqlHelper actual; - // actual = ApplicationTree.SqlHelper; - // Assert.Inconclusive("Verify the correctness of this test method."); - //} +// ///// +// /////A test for SqlHelper +// ///// +// //[TestMethod()] +// //public void SqlHelperTest() +// //{ +// // ISqlHelper actual; +// // actual = ApplicationTree.SqlHelper; +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} - ///// - /////A test for Title - ///// - //[TestMethod()] - //public void TitleTest() - //{ - // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value - // string expected = string.Empty; // TODO: Initialize to an appropriate value - // string actual; - // target.Title = expected; - // actual = target.Title; - // Assert.AreEqual(expected, actual); - // Assert.Inconclusive("Verify the correctness of this test method."); - //} +// ///// +// /////A test for Title +// ///// +// //[TestMethod()] +// //public void TitleTest() +// //{ +// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value +// // string expected = string.Empty; // TODO: Initialize to an appropriate value +// // string actual; +// // target.Title = expected; +// // actual = target.Title; +// // Assert.AreEqual(expected, actual); +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} - ///// - /////A test for Type - ///// - //[TestMethod()] - //public void TypeTest() - //{ - // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value - // string expected = string.Empty; // TODO: Initialize to an appropriate value - // string actual; - // target.Type = expected; - // actual = target.Type; - // Assert.AreEqual(expected, actual); - // Assert.Inconclusive("Verify the correctness of this test method."); - //} - #endregion +// ///// +// /////A test for Type +// ///// +// //[TestMethod()] +// //public void TypeTest() +// //{ +// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value +// // string expected = string.Empty; // TODO: Initialize to an appropriate value +// // string actual; +// // target.Type = expected; +// // actual = target.Type; +// // Assert.AreEqual(expected, actual); +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} +// #endregion - #region Additional test attributes - // - //You can use the following additional attributes as you write your tests: - // - //Use ClassInitialize to run code before running the first test in the class - //[ClassInitialize()] - //public static void MyClassInitialize(TestContext testContext) - //{ - //} - // - //Use ClassCleanup to run code after all tests in a class have run - //[ClassCleanup()] - //public static void MyClassCleanup() - //{ - //} - // - //Use TestInitialize to run code before running each test - //[TestInitialize()] - //public void MyTestInitialize() - //{ - //} - // - //Use TestCleanup to run code after each test has run - //[TestCleanup()] - //public void MyTestCleanup() - //{ - //} - // - #endregion - } -} +// #region Additional test attributes +// // +// //You can use the following additional attributes as you write your tests: +// // +// //Use ClassInitialize to run code before running the first test in the class +// //[ClassInitialize()] +// //public static void MyClassInitialize(TestContext testContext) +// //{ +// //} +// // +// //Use ClassCleanup to run code after all tests in a class have run +// //[ClassCleanup()] +// //public static void MyClassCleanup() +// //{ +// //} +// // +// //Use TestInitialize to run code before running each test +// //[TestInitialize()] +// //public void MyTestInitialize() +// //{ +// //} +// // +// //Use TestCleanup to run code after each test has run +// //[TestCleanup()] +// //public void MyTestCleanup() +// //{ +// //} +// // +// #endregion +// } +//} diff --git a/src/Umbraco.Tests/TreesAndSections/SectionTests.cs b/src/Umbraco.Tests/TreesAndSections/SectionTests.cs index 1f4a01fd3d..83de6c4479 100644 --- a/src/Umbraco.Tests/TreesAndSections/SectionTests.cs +++ b/src/Umbraco.Tests/TreesAndSections/SectionTests.cs @@ -1,252 +1,252 @@ -using System.IO; -using NUnit.Framework; -using Umbraco.Core.Services; -using Umbraco.Tests.TestHelpers; -using System; -using Umbraco.Core.Composing; -using Umbraco.Tests.Testing; -using Umbraco.Web.Services; +//using System.IO; +//using NUnit.Framework; +//using Umbraco.Core.Services; +//using Umbraco.Tests.TestHelpers; +//using System; +//using Umbraco.Core.Composing; +//using Umbraco.Tests.Testing; +//using Umbraco.Web.Services; -namespace Umbraco.Tests.TreesAndSections -{ - /// - ///This is a test class for ApplicationTest and is intended - ///to contain all ApplicationTest Unit Tests - /// - [TestFixture] - [UmbracoTest(AutoMapper = true, Database = UmbracoTestOptions.Database.NewSchemaPerTest)] - public class SectionTests : TestWithDatabaseBase - { - protected override void Compose() - { - base.Compose(); - Composition.RegisterUnique(); - } +//namespace Umbraco.Tests.TreesAndSections +//{ +// /// +// ///This is a test class for ApplicationTest and is intended +// ///to contain all ApplicationTest Unit Tests +// /// +// [TestFixture] +// [UmbracoTest(AutoMapper = true, Database = UmbracoTestOptions.Database.NewSchemaPerTest)] +// public class SectionTests : TestWithDatabaseBase +// { +// protected override void Compose() +// { +// base.Compose(); +// Composition.RegisterUnique(); +// } - public override void SetUp() - { - base.SetUp(); +// public override void SetUp() +// { +// base.SetUp(); - var treesConfig = TestHelper.MapPathForTest("~/TEMP/TreesAndSections/trees.config"); - var appConfig = TestHelper.MapPathForTest("~/TEMP/TreesAndSections/applications.config"); - Directory.CreateDirectory(TestHelper.MapPathForTest("~/TEMP/TreesAndSections")); - using (var writer = File.CreateText(treesConfig)) - { - writer.Write(ResourceFiles.trees); - } - using (var writer = File.CreateText(appConfig)) - { - writer.Write(ResourceFiles.applications); - } +// var treesConfig = TestHelper.MapPathForTest("~/TEMP/TreesAndSections/trees.config"); +// var appConfig = TestHelper.MapPathForTest("~/TEMP/TreesAndSections/applications.config"); +// Directory.CreateDirectory(TestHelper.MapPathForTest("~/TEMP/TreesAndSections")); +// using (var writer = File.CreateText(treesConfig)) +// { +// writer.Write(ResourceFiles.trees); +// } +// using (var writer = File.CreateText(appConfig)) +// { +// writer.Write(ResourceFiles.applications); +// } - ApplicationTreeService.TreeConfigFilePath = treesConfig; - SectionService.AppConfigFilePath = appConfig; - } +// ApplicationTreeService.TreeConfigFilePath = treesConfig; +// SectionService.AppConfigFilePath = appConfig; +// } - public override void TearDown() - { - base.TearDown(); +// public override void TearDown() +// { +// base.TearDown(); - if (Directory.Exists(TestHelper.MapPathForTest("~/TEMP/TreesAndSections"))) - { - Directory.Delete(TestHelper.MapPathForTest("~/TEMP/TreesAndSections"), true); - } - ApplicationTreeService.TreeConfigFilePath = null; - SectionService.AppConfigFilePath = null; - } +// if (Directory.Exists(TestHelper.MapPathForTest("~/TEMP/TreesAndSections"))) +// { +// Directory.Delete(TestHelper.MapPathForTest("~/TEMP/TreesAndSections"), true); +// } +// ApplicationTreeService.TreeConfigFilePath = null; +// SectionService.AppConfigFilePath = null; +// } - /// - /// Create a new application and delete it - /// - [Test()] - public void Application_Make_New() - { - var name = Guid.NewGuid().ToString("N"); - ServiceContext.SectionService.MakeNew(name, name, "icon.jpg"); +// ///// +// ///// Create a new application and delete it +// ///// +// //[Test()] +// //public void Application_Make_New() +// //{ +// // var name = Guid.NewGuid().ToString("N"); +// // ServiceContext.SectionService.MakeNew(name, name, "icon.jpg"); - //check if it exists - var app = ServiceContext.SectionService.GetByAlias(name); - Assert.IsNotNull(app); +// // //check if it exists +// // var app = ServiceContext.SectionService.GetByAlias(name); +// // Assert.IsNotNull(app); - //now remove it - ServiceContext.SectionService.DeleteSection(app); - Assert.IsNull(ServiceContext.SectionService.GetByAlias(name)); - } +// // //now remove it +// // ServiceContext.SectionService.DeleteSection(app); +// // Assert.IsNull(ServiceContext.SectionService.GetByAlias(name)); +// //} - #region Tests to write +// #region Tests to write - ///// - /////A test for Application Constructor - ///// - //[TestMethod()] - //public void ApplicationConstructorTest() - //{ - // string name = string.Empty; // TODO: Initialize to an appropriate value - // string alias = string.Empty; // TODO: Initialize to an appropriate value - // string icon = string.Empty; // TODO: Initialize to an appropriate value - // Application target = new Application(name, alias, icon); - // Assert.Inconclusive("TODO: Implement code to verify target"); - //} +// ///// +// /////A test for Application Constructor +// ///// +// //[TestMethod()] +// //public void ApplicationConstructorTest() +// //{ +// // string name = string.Empty; // TODO: Initialize to an appropriate value +// // string alias = string.Empty; // TODO: Initialize to an appropriate value +// // string icon = string.Empty; // TODO: Initialize to an appropriate value +// // Application target = new Application(name, alias, icon); +// // Assert.Inconclusive("TODO: Implement code to verify target"); +// //} - ///// - /////A test for Application Constructor - ///// - //[TestMethod()] - //public void ApplicationConstructorTest1() - //{ - // Application target = new Application(); - // Assert.Inconclusive("TODO: Implement code to verify target"); - //} +// ///// +// /////A test for Application Constructor +// ///// +// //[TestMethod()] +// //public void ApplicationConstructorTest1() +// //{ +// // Application target = new Application(); +// // Assert.Inconclusive("TODO: Implement code to verify target"); +// //} - ///// - /////A test for Delete - ///// - //[TestMethod()] - //public void DeleteTest() - //{ - // Application target = new Application(); // TODO: Initialize to an appropriate value - // target.Delete(); - // Assert.Inconclusive("A method that does not return a value cannot be verified."); - //} +// ///// +// /////A test for Delete +// ///// +// //[TestMethod()] +// //public void DeleteTest() +// //{ +// // Application target = new Application(); // TODO: Initialize to an appropriate value +// // target.Delete(); +// // Assert.Inconclusive("A method that does not return a value cannot be verified."); +// //} - ///// - /////A test for MakeNew - ///// - //[TestMethod()] - //public void MakeNewTest1() - //{ - // string name = string.Empty; // TODO: Initialize to an appropriate value - // string alias = string.Empty; // TODO: Initialize to an appropriate value - // string icon = string.Empty; // TODO: Initialize to an appropriate value - // Application.MakeNew(name, alias, icon); - // Assert.Inconclusive("A method that does not return a value cannot be verified."); - //} +// ///// +// /////A test for MakeNew +// ///// +// //[TestMethod()] +// //public void MakeNewTest1() +// //{ +// // string name = string.Empty; // TODO: Initialize to an appropriate value +// // string alias = string.Empty; // TODO: Initialize to an appropriate value +// // string icon = string.Empty; // TODO: Initialize to an appropriate value +// // Application.MakeNew(name, alias, icon); +// // Assert.Inconclusive("A method that does not return a value cannot be verified."); +// //} - ///// - /////A test for RegisterIApplications - ///// - //[TestMethod()] - //public void RegisterIApplicationsTest() - //{ - // Application.RegisterIApplications(); - // Assert.Inconclusive("A method that does not return a value cannot be verified."); - //} +// ///// +// /////A test for RegisterIApplications +// ///// +// //[TestMethod()] +// //public void RegisterIApplicationsTest() +// //{ +// // Application.RegisterIApplications(); +// // Assert.Inconclusive("A method that does not return a value cannot be verified."); +// //} - ///// - /////A test for getAll - ///// - //[TestMethod()] - //public void getAllTest() - //{ - // List expected = null; // TODO: Initialize to an appropriate value - // List actual; - // actual = Application.getAll(); - // Assert.AreEqual(expected, actual); - // Assert.Inconclusive("Verify the correctness of this test method."); - //} +// ///// +// /////A test for getAll +// ///// +// //[TestMethod()] +// //public void getAllTest() +// //{ +// // List expected = null; // TODO: Initialize to an appropriate value +// // List actual; +// // actual = Application.getAll(); +// // Assert.AreEqual(expected, actual); +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} - ///// - /////A test for getByAlias - ///// - //[TestMethod()] - //public void getByAliasTest() - //{ - // string appAlias = string.Empty; // TODO: Initialize to an appropriate value - // Application expected = null; // TODO: Initialize to an appropriate value - // Application actual; - // actual = Application.getByAlias(appAlias); - // Assert.AreEqual(expected, actual); - // Assert.Inconclusive("Verify the correctness of this test method."); - //} +// ///// +// /////A test for getByAlias +// ///// +// //[TestMethod()] +// //public void getByAliasTest() +// //{ +// // string appAlias = string.Empty; // TODO: Initialize to an appropriate value +// // Application expected = null; // TODO: Initialize to an appropriate value +// // Application actual; +// // actual = Application.getByAlias(appAlias); +// // Assert.AreEqual(expected, actual); +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} - ///// - /////A test for SqlHelper - ///// - //[TestMethod()] - //public void SqlHelperTest() - //{ - // ISqlHelper actual; - // actual = Application.SqlHelper; - // Assert.Inconclusive("Verify the correctness of this test method."); - //} +// ///// +// /////A test for SqlHelper +// ///// +// //[TestMethod()] +// //public void SqlHelperTest() +// //{ +// // ISqlHelper actual; +// // actual = Application.SqlHelper; +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} - ///// - /////A test for alias - ///// - //[TestMethod()] - //public void aliasTest() - //{ - // Application target = new Application(); // TODO: Initialize to an appropriate value - // string expected = string.Empty; // TODO: Initialize to an appropriate value - // string actual; - // target.alias = expected; - // actual = target.alias; - // Assert.AreEqual(expected, actual); - // Assert.Inconclusive("Verify the correctness of this test method."); - //} +// ///// +// /////A test for alias +// ///// +// //[TestMethod()] +// //public void aliasTest() +// //{ +// // Application target = new Application(); // TODO: Initialize to an appropriate value +// // string expected = string.Empty; // TODO: Initialize to an appropriate value +// // string actual; +// // target.alias = expected; +// // actual = target.alias; +// // Assert.AreEqual(expected, actual); +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} - ///// - /////A test for icon - ///// - //[TestMethod()] - //public void iconTest() - //{ - // Application target = new Application(); // TODO: Initialize to an appropriate value - // string expected = string.Empty; // TODO: Initialize to an appropriate value - // string actual; - // target.icon = expected; - // actual = target.icon; - // Assert.AreEqual(expected, actual); - // Assert.Inconclusive("Verify the correctness of this test method."); - //} +// ///// +// /////A test for icon +// ///// +// //[TestMethod()] +// //public void iconTest() +// //{ +// // Application target = new Application(); // TODO: Initialize to an appropriate value +// // string expected = string.Empty; // TODO: Initialize to an appropriate value +// // string actual; +// // target.icon = expected; +// // actual = target.icon; +// // Assert.AreEqual(expected, actual); +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} - ///// - /////A test for name - ///// - //[TestMethod()] - //public void nameTest() - //{ - // Application target = new Application(); // TODO: Initialize to an appropriate value - // string expected = string.Empty; // TODO: Initialize to an appropriate value - // string actual; - // target.name = expected; - // actual = target.name; - // Assert.AreEqual(expected, actual); - // Assert.Inconclusive("Verify the correctness of this test method."); - //} - #endregion +// ///// +// /////A test for name +// ///// +// //[TestMethod()] +// //public void nameTest() +// //{ +// // Application target = new Application(); // TODO: Initialize to an appropriate value +// // string expected = string.Empty; // TODO: Initialize to an appropriate value +// // string actual; +// // target.name = expected; +// // actual = target.name; +// // Assert.AreEqual(expected, actual); +// // Assert.Inconclusive("Verify the correctness of this test method."); +// //} +// #endregion - #region Additional test attributes - // - //You can use the following additional attributes as you write your tests: - // - //Use ClassInitialize to run code before running the first test in the class - //[ClassInitialize()] - //public static void MyClassInitialize(TestContext testContext) - //{ - //} - // - //Use ClassCleanup to run code after all tests in a class have run - //[ClassCleanup()] - //public static void MyClassCleanup() - //{ - //} - // - //Use TestInitialize to run code before running each test - //[TestInitialize()] - //public void MyTestInitialize() - //{ - //} - // - //Use TestCleanup to run code after each test has run - //[TestCleanup()] - //public void MyTestCleanup() - //{ - //} - // - #endregion - } -} +// #region Additional test attributes +// // +// //You can use the following additional attributes as you write your tests: +// // +// //Use ClassInitialize to run code before running the first test in the class +// //[ClassInitialize()] +// //public static void MyClassInitialize(TestContext testContext) +// //{ +// //} +// // +// //Use ClassCleanup to run code after all tests in a class have run +// //[ClassCleanup()] +// //public static void MyClassCleanup() +// //{ +// //} +// // +// //Use TestInitialize to run code before running each test +// //[TestInitialize()] +// //public void MyTestInitialize() +// //{ +// //} +// // +// //Use TestCleanup to run code after each test has run +// //[TestCleanup()] +// //public void MyTestCleanup() +// //{ +// //} +// // +// #endregion +// } +//} diff --git a/src/Umbraco.Web/Cache/ApplicationTreeCacheRefresher.cs b/src/Umbraco.Web/Cache/ApplicationTreeCacheRefresher.cs index 247c33c361..4d6740a0b1 100644 --- a/src/Umbraco.Web/Cache/ApplicationTreeCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/ApplicationTreeCacheRefresher.cs @@ -1,46 +1,46 @@ -using System; -using Umbraco.Core.Cache; +//using System; +//using Umbraco.Core.Cache; -namespace Umbraco.Web.Cache -{ - public sealed class ApplicationTreeCacheRefresher : CacheRefresherBase - { - public ApplicationTreeCacheRefresher(CacheHelper cacheHelper) - : base(cacheHelper) - { } +//namespace Umbraco.Web.Cache +//{ +// public sealed class ApplicationTreeCacheRefresher : CacheRefresherBase +// { +// public ApplicationTreeCacheRefresher(CacheHelper cacheHelper) +// : base(cacheHelper) +// { } - #region Define +// #region Define - protected override ApplicationTreeCacheRefresher This => this; +// protected override ApplicationTreeCacheRefresher This => this; - public static readonly Guid UniqueId = Guid.Parse("0AC6C028-9860-4EA4-958D-14D39F45886E"); +// public static readonly Guid UniqueId = Guid.Parse("0AC6C028-9860-4EA4-958D-14D39F45886E"); - public override Guid RefresherUniqueId => UniqueId; +// public override Guid RefresherUniqueId => UniqueId; - public override string Name => "Application Tree Cache Refresher"; +// public override string Name => "Application Tree Cache Refresher"; - #endregion +// #endregion - #region Refresher +// #region Refresher - public override void RefreshAll() - { - CacheHelper.RuntimeCache.ClearCacheItem(CacheKeys.ApplicationTreeCacheKey); - base.RefreshAll(); - } +// public override void RefreshAll() +// { +// CacheHelper.RuntimeCache.ClearCacheItem(CacheKeys.ApplicationTreeCacheKey); +// base.RefreshAll(); +// } - public override void Refresh(int id) - { - Remove(id); - base.Refresh(id); - } +// public override void Refresh(int id) +// { +// Remove(id); +// base.Refresh(id); +// } - public override void Remove(int id) - { - CacheHelper.RuntimeCache.ClearCacheItem(CacheKeys.ApplicationTreeCacheKey); - base.Remove(id); - } +// public override void Remove(int id) +// { +// CacheHelper.RuntimeCache.ClearCacheItem(CacheKeys.ApplicationTreeCacheKey); +// base.Remove(id); +// } - #endregion - } -} +// #endregion +// } +//} diff --git a/src/Umbraco.Web/Cache/DistributedCacheBinder_Handlers.cs b/src/Umbraco.Web/Cache/DistributedCacheBinder_Handlers.cs index d522e54de6..421eb546a4 100644 --- a/src/Umbraco.Web/Cache/DistributedCacheBinder_Handlers.cs +++ b/src/Umbraco.Web/Cache/DistributedCacheBinder_Handlers.cs @@ -46,19 +46,19 @@ namespace Umbraco.Web.Cache _logger.Info("Initializing Umbraco internal event handlers for cache refreshing."); - // bind to application tree events - Bind(() => ApplicationTreeService.Deleted += ApplicationTreeService_Deleted, - () => ApplicationTreeService.Deleted -= ApplicationTreeService_Deleted); - Bind(() => ApplicationTreeService.Updated += ApplicationTreeService_Updated, - () => ApplicationTreeService.Updated -= ApplicationTreeService_Updated); - Bind(() => ApplicationTreeService.New += ApplicationTreeService_New, - () => ApplicationTreeService.New -= ApplicationTreeService_New); + //// bind to application tree events + //Bind(() => ApplicationTreeService.Deleted += ApplicationTreeService_Deleted, + // () => ApplicationTreeService.Deleted -= ApplicationTreeService_Deleted); + //Bind(() => ApplicationTreeService.Updated += ApplicationTreeService_Updated, + // () => ApplicationTreeService.Updated -= ApplicationTreeService_Updated); + //Bind(() => ApplicationTreeService.New += ApplicationTreeService_New, + // () => ApplicationTreeService.New -= ApplicationTreeService_New); - // bind to application events - Bind(() => SectionService.Deleted += SectionService_Deleted, - () => SectionService.Deleted -= SectionService_Deleted); - Bind(() => SectionService.New += SectionService_New, - () => SectionService.New -= SectionService_New); + //// bind to application events + //Bind(() => SectionService.Deleted += SectionService_Deleted, + // () => SectionService.Deleted -= SectionService_Deleted); + //Bind(() => SectionService.New += SectionService_New, + // () => SectionService.New -= SectionService_New); // bind to user and user group events Bind(() => UserService.SavedUserGroup += UserService_SavedUserGroup, @@ -231,38 +231,38 @@ namespace Umbraco.Web.Cache #endregion - #region ApplicationTreeService + //#region ApplicationTreeService - private void ApplicationTreeService_New(ApplicationTree sender, EventArgs e) - { - _distributedCache.RefreshAllApplicationTreeCache(); - } + //private void ApplicationTreeService_New(ApplicationTree sender, EventArgs e) + //{ + // _distributedCache.RefreshAllApplicationTreeCache(); + //} - private void ApplicationTreeService_Updated(ApplicationTree sender, EventArgs e) - { - _distributedCache.RefreshAllApplicationTreeCache(); - } + //private void ApplicationTreeService_Updated(ApplicationTree sender, EventArgs e) + //{ + // _distributedCache.RefreshAllApplicationTreeCache(); + //} - private void ApplicationTreeService_Deleted(ApplicationTree sender, EventArgs e) - { - _distributedCache.RefreshAllApplicationTreeCache(); - } + //private void ApplicationTreeService_Deleted(ApplicationTree sender, EventArgs e) + //{ + // _distributedCache.RefreshAllApplicationTreeCache(); + //} - #endregion + //#endregion - #region Application event handlers + //#region Application event handlers - private void SectionService_New(ISectionService sender, EventArgs e) - { - _distributedCache.RefreshAllApplicationCache(); - } + //private void SectionService_New(ISectionService sender, EventArgs e) + //{ + // _distributedCache.RefreshAllApplicationCache(); + //} - private void SectionService_Deleted(ISectionService sender, EventArgs e) - { - _distributedCache.RefreshAllApplicationCache(); - } + //private void SectionService_Deleted(ISectionService sender, EventArgs e) + //{ + // _distributedCache.RefreshAllApplicationCache(); + //} - #endregion + //#endregion #region LocalizationService / Dictionary diff --git a/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs b/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs index 68ac339a46..aab0f9b157 100644 --- a/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs +++ b/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs @@ -18,23 +18,23 @@ namespace Umbraco.Web.Cache #endregion - #region ApplicationTreeCache + //#region ApplicationTreeCache - public static void RefreshAllApplicationTreeCache(this DistributedCache dc) - { - dc.RefreshAll(ApplicationTreeCacheRefresher.UniqueId); - } + //public static void RefreshAllApplicationTreeCache(this DistributedCache dc) + //{ + // dc.RefreshAll(ApplicationTreeCacheRefresher.UniqueId); + //} - #endregion + //#endregion - #region ApplicationCache + //#region ApplicationCache - public static void RefreshAllApplicationCache(this DistributedCache dc) - { - dc.RefreshAll(ApplicationCacheRefresher.UniqueId); - } + //public static void RefreshAllApplicationCache(this DistributedCache dc) + //{ + // dc.RefreshAll(ApplicationCacheRefresher.UniqueId); + //} - #endregion + //#endregion #region User cache diff --git a/src/Umbraco.Web/TagsController.cs b/src/Umbraco.Web/Controllers/TagsController.cs similarity index 89% rename from src/Umbraco.Web/TagsController.cs rename to src/Umbraco.Web/Controllers/TagsController.cs index 181b9f7da2..cb6a28be47 100644 --- a/src/Umbraco.Web/TagsController.cs +++ b/src/Umbraco.Web/Controllers/TagsController.cs @@ -8,7 +8,7 @@ using Umbraco.Core.Services; using Umbraco.Web.Models; using Umbraco.Web.WebApi; -namespace Umbraco.Web.WebServices +namespace Umbraco.Web.Controllers { /// /// A public web service for querying tags @@ -29,8 +29,8 @@ namespace Umbraco.Web.WebServices /// /// Initializes a new instance of the with all its dependencies. /// - public TagsController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) - : base(globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) + public TagsController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) + : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, runtimeState) { } /// diff --git a/src/Umbraco.Web/Editors/AuthenticationController.cs b/src/Umbraco.Web/Editors/AuthenticationController.cs index 231ec9ba67..7ffc6e1207 100644 --- a/src/Umbraco.Web/Editors/AuthenticationController.cs +++ b/src/Umbraco.Web/Editors/AuthenticationController.cs @@ -52,8 +52,8 @@ namespace Umbraco.Web.Editors /// /// Initializes a new instance of the class with all its dependencies. /// - public AuthenticationController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) - : base(globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) + public AuthenticationController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) + : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, runtimeState) { } protected BackOfficeUserManager UserManager => _userManager diff --git a/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs b/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs index ee973a4b58..65ab27d76a 100644 --- a/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs +++ b/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs @@ -14,13 +14,13 @@ using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; +using Umbraco.Web.Controllers; using Umbraco.Web.Features; using Umbraco.Web.HealthCheck; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Mvc; using Umbraco.Web.PropertyEditors; using Umbraco.Web.Trees; -using Umbraco.Web.WebServices; using Constants = Umbraco.Core.Constants; namespace Umbraco.Web.Editors @@ -158,7 +158,7 @@ namespace Umbraco.Web.Editors }, { "treeApplicationApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl( - controller => controller.GetApplicationTrees(null, null, null, true)) + controller => controller.GetApplicationTrees(null, null, null)) }, { "contentTypeApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl( diff --git a/src/Umbraco.Web/Editors/ContentTypeController.cs b/src/Umbraco.Web/Editors/ContentTypeController.cs index 670d37e7a7..00a0cb90bc 100644 --- a/src/Umbraco.Web/Editors/ContentTypeController.cs +++ b/src/Umbraco.Web/Editors/ContentTypeController.cs @@ -54,11 +54,11 @@ namespace Umbraco.Web.Editors public ContentTypeController(IEntityXmlSerializer serializer, ICultureDictionaryFactory cultureDictionaryFactory, IGlobalSettings globalSettings, - IUmbracoContextAccessor umbracoContextAccessor, + UmbracoContext umbracoContext, ISqlContext sqlContext, PropertyEditorCollection propertyEditors, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) - : base(cultureDictionaryFactory, globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) + : base(cultureDictionaryFactory, globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, runtimeState) { _serializer = serializer; _propertyEditors = propertyEditors; diff --git a/src/Umbraco.Web/Editors/ContentTypeControllerBase.cs b/src/Umbraco.Web/Editors/ContentTypeControllerBase.cs index 898208319a..a11fcaa869 100644 --- a/src/Umbraco.Web/Editors/ContentTypeControllerBase.cs +++ b/src/Umbraco.Web/Editors/ContentTypeControllerBase.cs @@ -33,7 +33,8 @@ namespace Umbraco.Web.Editors private readonly ICultureDictionaryFactory _cultureDictionaryFactory; private ICultureDictionary _cultureDictionary; - protected ContentTypeControllerBase(ICultureDictionaryFactory cultureDictionaryFactory, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) : base(globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) + protected ContentTypeControllerBase(ICultureDictionaryFactory cultureDictionaryFactory, IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) + : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, runtimeState) { _cultureDictionaryFactory = cultureDictionaryFactory; } diff --git a/src/Umbraco.Web/Editors/DashboardController.cs b/src/Umbraco.Web/Editors/DashboardController.cs index 8960f110c3..0340926ce4 100644 --- a/src/Umbraco.Web/Editors/DashboardController.cs +++ b/src/Umbraco.Web/Editors/DashboardController.cs @@ -38,8 +38,8 @@ namespace Umbraco.Web.Editors /// /// Initializes a new instance of the with all its dependencies. /// - public DashboardController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState, Dashboards dashboards) - : base(globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) + public DashboardController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState, Dashboards dashboards) + : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, runtimeState) { _dashboards = dashboards; } diff --git a/src/Umbraco.Web/Editors/DashboardSecurity.cs b/src/Umbraco.Web/Editors/DashboardSecurity.cs index 1481606c7e..fdbf5af7d9 100644 --- a/src/Umbraco.Web/Editors/DashboardSecurity.cs +++ b/src/Umbraco.Web/Editors/DashboardSecurity.cs @@ -6,6 +6,7 @@ using Umbraco.Core; using Umbraco.Core.Configuration.Dashboard; using Umbraco.Core.Models.Membership; using Umbraco.Core.Services; +using Umbraco.Web.Services; namespace Umbraco.Web.Editors { diff --git a/src/Umbraco.Web/Editors/Dashboards.cs b/src/Umbraco.Web/Editors/Dashboards.cs index 4bf2d81045..c837cbbf33 100644 --- a/src/Umbraco.Web/Editors/Dashboards.cs +++ b/src/Umbraco.Web/Editors/Dashboards.cs @@ -8,6 +8,7 @@ using Umbraco.Core.Manifest; using Umbraco.Core.Models.Membership; using Umbraco.Core.Services; using Umbraco.Web.Models.ContentEditing; +using Umbraco.Web.Services; namespace Umbraco.Web.Editors { diff --git a/src/Umbraco.Web/Editors/EntityController.cs b/src/Umbraco.Web/Editors/EntityController.cs index 993489855f..c8368d11b0 100644 --- a/src/Umbraco.Web/Editors/EntityController.cs +++ b/src/Umbraco.Web/Editors/EntityController.cs @@ -16,11 +16,16 @@ using Constants = Umbraco.Core.Constants; using Umbraco.Core.Persistence.DatabaseModelDefinitions; using System.Web.Http.Controllers; using Examine; +using Umbraco.Core.Cache; +using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; using Umbraco.Core.Models.Entities; +using Umbraco.Core.Persistence; using Umbraco.Core.Services; using Umbraco.Core.Xml; using Umbraco.Web.Models.Mapping; using Umbraco.Web.Search; +using Umbraco.Web.Services; using Umbraco.Web.Trees; using Umbraco.Web.WebApi; using Umbraco.Web.WebApi.Filters; @@ -37,6 +42,15 @@ namespace Umbraco.Web.Editors [PluginController("UmbracoApi")] public class EntityController : UmbracoAuthorizedJsonController { + private readonly IApplicationTreeService _treeService; + + public EntityController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState, + IApplicationTreeService treeService) + : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, runtimeState) + { + _treeService = treeService; + } + /// /// Configures this controller with a custom action selector /// @@ -129,7 +143,7 @@ namespace Umbraco.Web.Editors { if (allowedSections.Contains(searchableTree.Value.AppAlias)) { - var tree = Services.ApplicationTreeService.GetByAlias(searchableTree.Key); + var tree = _treeService.GetByAlias(searchableTree.Key); if (tree == null) continue; //shouldn't occur var searchableTreeAttribute = searchableTree.Value.SearchableTree.GetType().GetCustomAttribute(false); diff --git a/src/Umbraco.Web/Editors/MediaTypeController.cs b/src/Umbraco.Web/Editors/MediaTypeController.cs index f2b8fd3dda..e2fbe8c428 100644 --- a/src/Umbraco.Web/Editors/MediaTypeController.cs +++ b/src/Umbraco.Web/Editors/MediaTypeController.cs @@ -37,7 +37,8 @@ namespace Umbraco.Web.Editors [MediaTypeControllerControllerConfiguration] public class MediaTypeController : ContentTypeControllerBase { - public MediaTypeController(ICultureDictionaryFactory cultureDictionaryFactory, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) : base(cultureDictionaryFactory, globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) + public MediaTypeController(ICultureDictionaryFactory cultureDictionaryFactory, IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) + : base(cultureDictionaryFactory, globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, runtimeState) { } diff --git a/src/Umbraco.Web/Editors/MemberTypeController.cs b/src/Umbraco.Web/Editors/MemberTypeController.cs index 3abc0035d3..c59bf6d332 100644 --- a/src/Umbraco.Web/Editors/MemberTypeController.cs +++ b/src/Umbraco.Web/Editors/MemberTypeController.cs @@ -30,7 +30,8 @@ namespace Umbraco.Web.Editors [UmbracoTreeAuthorize(new string[] { Constants.Trees.MemberTypes, Constants.Trees.Members})] public class MemberTypeController : ContentTypeControllerBase { - public MemberTypeController(ICultureDictionaryFactory cultureDictionaryFactory, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) : base(cultureDictionaryFactory, globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) + public MemberTypeController(ICultureDictionaryFactory cultureDictionaryFactory, IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) + : base(cultureDictionaryFactory, globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, runtimeState) { } diff --git a/src/Umbraco.Web/Editors/PackageInstallController.cs b/src/Umbraco.Web/Editors/PackageInstallController.cs index 05d1e2a7a3..ec81b794a1 100644 --- a/src/Umbraco.Web/Editors/PackageInstallController.cs +++ b/src/Umbraco.Web/Editors/PackageInstallController.cs @@ -44,10 +44,10 @@ namespace Umbraco.Web.Editors [UmbracoApplicationAuthorize(Core.Constants.Applications.Packages)] public class PackageInstallController : UmbracoAuthorizedJsonController { - public PackageInstallController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, + public PackageInstallController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) - : base(globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) + : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, runtimeState) { } diff --git a/src/Umbraco.Web/Editors/SectionController.cs b/src/Umbraco.Web/Editors/SectionController.cs index f650c18fb3..7b484b09b1 100644 --- a/src/Umbraco.Web/Editors/SectionController.cs +++ b/src/Umbraco.Web/Editors/SectionController.cs @@ -2,10 +2,17 @@ using AutoMapper; using Umbraco.Web.Mvc; using System.Linq; +using Umbraco.Core; +using Umbraco.Core.Cache; +using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; using Umbraco.Core.Models; +using Umbraco.Core.Persistence; +using Umbraco.Core.Services; using Umbraco.Web.Trees; using Section = Umbraco.Web.Models.ContentEditing.Section; using Umbraco.Web.Models.Trees; +using Umbraco.Web.Services; namespace Umbraco.Web.Editors { @@ -16,21 +23,32 @@ namespace Umbraco.Web.Editors public class SectionController : UmbracoAuthorizedJsonController { private readonly Dashboards _dashboards; + private readonly ISectionService _sectionService; + private readonly TreeControllerResolver _treeControllerResolver; + private readonly IApplicationTreeService _treeService; - public SectionController(Dashboards dashboards) + public SectionController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState, + Dashboards dashboards, ISectionService sectionService, TreeControllerResolver treeControllerResolver, IApplicationTreeService treeService) + : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, runtimeState) { _dashboards = dashboards; + _sectionService = sectionService; + _treeControllerResolver = treeControllerResolver; + _treeService = treeService; } public IEnumerable
    GetSections() { - var sections = Services.SectionService.GetAllowedSections(Security.GetUserId().ResultOr(0)); + var sections = _sectionService.GetAllowedSections(Security.GetUserId().ResultOr(0)); - var sectionModels = sections.Select(Mapper.Map).ToArray(); + var sectionModels = sections.Select(Mapper.Map
    ).ToArray(); // this is a bit nasty since we'll be proxying via the app tree controller but we sort of have to do that // since tree's by nature are controllers and require request contextual data - var appTreeController = new ApplicationTreeController { ControllerContext = ControllerContext }; + var appTreeController = new ApplicationTreeController(GlobalSettings, UmbracoContext, SqlContext, Services, ApplicationCache, Logger, RuntimeState, _treeControllerResolver, _treeService) + { + ControllerContext = ControllerContext + }; var dashboards = _dashboards.GetDashboards(Security.CurrentUser); @@ -76,8 +94,8 @@ namespace Umbraco.Web.Editors /// public IEnumerable
    GetAllSections() { - var sections = Services.SectionService.GetSections(); - var mapped = sections.Select(Mapper.Map); + var sections = _sectionService.GetSections(); + var mapped = sections.Select(Mapper.Map
    ); if (Security.CurrentUser.IsAdmin()) return mapped; diff --git a/src/Umbraco.Web/Editors/UmbracoAuthorizedJsonController.cs b/src/Umbraco.Web/Editors/UmbracoAuthorizedJsonController.cs index 3baa5e85ff..4e430b833c 100644 --- a/src/Umbraco.Web/Editors/UmbracoAuthorizedJsonController.cs +++ b/src/Umbraco.Web/Editors/UmbracoAuthorizedJsonController.cs @@ -31,13 +31,13 @@ namespace Umbraco.Web.Editors /// Initializes a new instance of the class with all its dependencies. ///
    /// - /// + /// /// /// /// /// /// - protected UmbracoAuthorizedJsonController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) : base(globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) + protected UmbracoAuthorizedJsonController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, runtimeState) { } } diff --git a/src/Umbraco.Web/Models/ContentEditing/ApplicationTree.cs b/src/Umbraco.Web/Models/ContentEditing/ApplicationTree.cs new file mode 100644 index 0000000000..e9befb0e27 --- /dev/null +++ b/src/Umbraco.Web/Models/ContentEditing/ApplicationTree.cs @@ -0,0 +1,177 @@ +using System; +using System.Diagnostics; +using Umbraco.Core.Services; + +namespace Umbraco.Web.Models.ContentEditing +{ + [DebuggerDisplay("Tree - {Alias} ({ApplicationAlias})")] + public class ApplicationTree + { + //private static readonly ConcurrentDictionary ResolvedTypes = new ConcurrentDictionary(); + + ///// + ///// Initializes a new instance of the class. + ///// + //public ApplicationTree() { } + + ///// + ///// Initializes a new instance of the class. + ///// + ///// if set to true [initialize]. + ///// The sort order. + ///// The application alias. + ///// The tree alias. + ///// The tree title. + ///// The icon closed. + ///// The icon opened. + ///// The tree type. + //public ApplicationTree(bool initialize, int sortOrder, string applicationAlias, string alias, string title, string iconClosed, string iconOpened, string type) + //{ + // //Initialize = initialize; + // SortOrder = sortOrder; + // ApplicationAlias = applicationAlias; + // Alias = alias; + // Title = title; + // IconClosed = iconClosed; + // IconOpened = iconOpened; + // Type = type; + + //} + + public ApplicationTree(int sortOrder, string applicationAlias, string alias, string title) + { + SortOrder = sortOrder; + ApplicationAlias = applicationAlias; + Alias = alias; + Title = title; + } + + ///// + ///// Gets or sets a value indicating whether this should initialize. + ///// + ///// true if initialize; otherwise, false. + //public bool Initialize { get; set; } + + /// + /// Gets or sets the sort order. + /// + /// The sort order. + public int SortOrder { get; set; } + + /// + /// Gets the application alias. + /// + /// The application alias. + public string ApplicationAlias { get; } + + /// + /// Gets the tree alias. + /// + /// The alias. + public string Alias { get; } + + /// + /// Gets or sets the tree title (fallback if the tree alias isn't localized) + /// + /// The title. + public string Title { get; set; } + + ///// + ///// Gets or sets the icon closed. + ///// + ///// The icon closed. + //public string IconClosed { get; set; } + + ///// + ///// Gets or sets the icon opened. + ///// + ///// The icon opened. + //public string IconOpened { get; set; } + + ///// + ///// Gets or sets the tree type assembly name. + ///// + ///// The type. + //public string Type { get; set; } + + /// + /// Returns the localized root node display name + /// + /// + /// + public string GetRootNodeDisplayName(ILocalizedTextService textService) + { + var label = $"[{Alias}]"; + + // try to look up a the localized tree header matching the tree alias + var localizedLabel = textService.Localize("treeHeaders/" + Alias); + + // if the localizedLabel returns [alias] then return the title if it's defined + if (localizedLabel != null && localizedLabel.Equals(label, StringComparison.InvariantCultureIgnoreCase)) + { + if (string.IsNullOrEmpty(Title) == false) + label = Title; + } + else + { + // the localizedLabel translated into something that's not just [alias], so use the translation + label = localizedLabel; + } + + return label; + } + + //private Type _runtimeType; + + ///// + ///// Returns the CLR type based on it's assembly name stored in the config + ///// + ///// + //public Type GetRuntimeType() + //{ + // return _runtimeType ?? (_runtimeType = System.Type.GetType(Type)); + //} + + ///// + ///// Used to try to get and cache the tree type + ///// + ///// + ///// + //internal static Type TryGetType(string type) + //{ + // try + // { + // return ResolvedTypes.GetOrAdd(type, s => + // { + // var result = System.Type.GetType(type); + // if (result != null) + // { + // return result; + // } + + // //we need to implement a bit of a hack here due to some trees being renamed and backwards compat + // var parts = type.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + // if (parts.Length != 2) + // throw new InvalidOperationException("Could not resolve type"); + // if (parts[1].Trim() != "Umbraco.Web" || parts[0].StartsWith("Umbraco.Web.Trees") == false || parts[0].EndsWith("Controller")) + // throw new InvalidOperationException("Could not resolve type"); + + // //if it's one of our controllers but it's not suffixed with "Controller" then add it and try again + // var tempType = parts[0] + "Controller, Umbraco.Web"; + + // result = System.Type.GetType(tempType); + // if (result != null) + // return result; + + // throw new InvalidOperationException("Could not resolve type"); + // }); + // } + // catch (InvalidOperationException) + // { + // //swallow, this is our own exception, couldn't find the type + // // fixme bad use of exceptions here! + // return null; + // } + //} + } +} diff --git a/src/Umbraco.Web/Models/ContentEditing/IBackOfficeSection.cs b/src/Umbraco.Web/Models/ContentEditing/IBackOfficeSection.cs new file mode 100644 index 0000000000..f27941035a --- /dev/null +++ b/src/Umbraco.Web/Models/ContentEditing/IBackOfficeSection.cs @@ -0,0 +1,15 @@ +using Umbraco.Core.Composing; + +namespace Umbraco.Web.Models.ContentEditing +{ + + /// + /// Defines a back office section + /// + public interface IBackOfficeSection : IDiscoverable + { + string Alias { get; } + string Name { get; } + int SortOrder { get; } + } +} diff --git a/src/Umbraco.Web/Models/Mapping/SectionMapperProfile.cs b/src/Umbraco.Web/Models/Mapping/SectionMapperProfile.cs index ba7ff3c38d..683fce36e8 100644 --- a/src/Umbraco.Web/Models/Mapping/SectionMapperProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/SectionMapperProfile.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using AutoMapper; +using Umbraco.Core.Models.ContentEditing; using Umbraco.Core.Services; using Umbraco.Web.Models.ContentEditing; @@ -9,7 +10,7 @@ namespace Umbraco.Web.Models.Mapping { public SectionMapperProfile(ILocalizedTextService textService) { - CreateMap() + CreateMap() .ForMember(dest => dest.RoutePath, opt => opt.Ignore()) .ForMember(dest => dest.Icon, opt => opt.Ignore()) .ForMember(dest => dest.Name, opt => opt.MapFrom(src => textService.Localize("sections/" + src.Alias, (IDictionary)null))) diff --git a/src/Umbraco.Web/Models/Mapping/UserMapperProfile.cs b/src/Umbraco.Web/Models/Mapping/UserMapperProfile.cs index 8261dda0d4..c975f3a106 100644 --- a/src/Umbraco.Web/Models/Mapping/UserMapperProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/UserMapperProfile.cs @@ -12,6 +12,7 @@ using Umbraco.Core.Models.Entities; using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Web.Actions; +using Umbraco.Web.Services; namespace Umbraco.Web.Models.Mapping diff --git a/src/Umbraco.Web/Models/Trees/ApplicationAttribute.cs b/src/Umbraco.Web/Models/Trees/ApplicationAttribute.cs deleted file mode 100644 index 65fc4ed6f3..0000000000 --- a/src/Umbraco.Web/Models/Trees/ApplicationAttribute.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; - -namespace Umbraco.Web.Models.Trees -{ - /// - /// Identifies an application tree - /// - [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] - public class ApplicationAttribute : Attribute - { - /// - /// Initializes a new instance of the class. - /// - /// The alias. - /// The name. - /// The sort order. - public ApplicationAttribute(string alias, - string name, - int sortOrder = 0) - { - Alias = alias; - Name = name; - SortOrder = sortOrder; - } - - public string Alias { get; private set; } - public string Name { get; private set; } - public int SortOrder { get; private set; } - } -} diff --git a/src/Umbraco.Web/Models/Trees/ApplicationDefinitions.cs b/src/Umbraco.Web/Models/Trees/ApplicationDefinitions.cs index aa8e0cfda6..ba48c9e240 100644 --- a/src/Umbraco.Web/Models/Trees/ApplicationDefinitions.cs +++ b/src/Umbraco.Web/Models/Trees/ApplicationDefinitions.cs @@ -1,37 +1,77 @@ using Umbraco.Core; using Umbraco.Core.Models; +using Umbraco.Core.Models.ContentEditing; +using Umbraco.Web.Models.ContentEditing; namespace Umbraco.Web.Models.Trees { - // The application definitions are intended as a means to auto populate - // the application.config. On app startup, Umbraco will look for any - // unregistered classes with an ApplicationAttribute and add them to the cache + /// + /// Defines the back office content section + /// + public class ContentBackOfficeSectionDefinition : IBackOfficeSection + { + public string Alias => Constants.Applications.Content; + public string Name => "Content"; + public int SortOrder => 0; + } - [Application(Constants.Applications.Content, "Content")] - public class ContentApplicationDefinition : IApplication - { } + /// + /// Defines the back office media section + /// + public class MediaBackOfficeSectionDefinition : IBackOfficeSection + { + public string Alias => Constants.Applications.Media; + public string Name => "Media"; + public int SortOrder => 1; + } - [Application(Constants.Applications.Media, "Media", sortOrder: 1)] - public class MediaApplicationDefinition : IApplication - { } + /// + /// Defines the back office settings section + /// + public class SettingsBackOfficeSectionDefinition : IBackOfficeSection + { + public string Alias => Constants.Applications.Settings; + public string Name => "Settings"; + public int SortOrder => 2; + } - [Application(Constants.Applications.Settings, "Settings", sortOrder: 2)] - public class SettingsApplicationDefinition : IApplication - { } + /// + /// Defines the back office packages section + /// + public class PackagesBackOfficeSectionDefinition : IBackOfficeSection + { + public string Alias => Constants.Applications.Packages; + public string Name => "Packages"; + public int SortOrder => 3; + } - [Application(Constants.Applications.Packages, "Packages", sortOrder: 3)] - public class PackagesApplicationDefinition : IApplication - { } + /// + /// Defines the back office users section + /// + public class UsersBackOfficeSectionDefinition : IBackOfficeSection + { + public string Alias => Constants.Applications.Users; + public string Name => "Users"; + public int SortOrder => 4; + } - [Application(Constants.Applications.Users, "Users", sortOrder: 4)] - public class UsersApplicationDefinition : IApplication - { } + /// + /// Defines the back office members section + /// + public class MembersBackOfficeSectionDefinition : IBackOfficeSection + { + public string Alias => Constants.Applications.Members; + public string Name => "Members"; + public int SortOrder => 5; + } - [Application(Constants.Applications.Members, "Members", sortOrder: 5)] - public class MembersApplicationDefinition : IApplication - { } - - [Application(Constants.Applications.Translation, "Translation", sortOrder: 6)] - public class TranslationApplicationDefinition : IApplication - { } + /// + /// Defines the back office translation section + /// + public class TranslationBackOfficeSectionDefinition : IBackOfficeSection + { + public string Alias => Constants.Applications.Translation; + public string Name => "Translation"; + public int SortOrder => 6; + } } diff --git a/src/Umbraco.Web/Models/Trees/IApplication.cs b/src/Umbraco.Web/Models/Trees/IApplication.cs deleted file mode 100644 index 4e9cae43fd..0000000000 --- a/src/Umbraco.Web/Models/Trees/IApplication.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Umbraco.Core.Composing; - -namespace Umbraco.Web.Models.Trees -{ - /// - /// Marker interface for created applications in the umbraco backoffice - /// - public interface IApplication : IDiscoverable - { } -} diff --git a/src/Umbraco.Web/Mvc/SurfaceControllerTypeCollection.cs b/src/Umbraco.Web/Mvc/SurfaceControllerTypeCollection.cs index 30c21fce96..eef6ab1ca2 100644 --- a/src/Umbraco.Web/Mvc/SurfaceControllerTypeCollection.cs +++ b/src/Umbraco.Web/Mvc/SurfaceControllerTypeCollection.cs @@ -8,6 +8,8 @@ namespace Umbraco.Web.Mvc // which we are not doing at the moment // we can inherit from BuilderCollectionBase and just be enumerable + //fixme: this should be LazyCollectionBuilderBase ? + public class SurfaceControllerTypeCollection : BuilderCollectionBase { public SurfaceControllerTypeCollection(IEnumerable items) diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs index 422b502f80..b7f4e13432 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs @@ -22,10 +22,12 @@ using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Profiling; using Umbraco.Core.Services; using Umbraco.Web.Install; +using Umbraco.Web.Models.Trees; using Umbraco.Web.Mvc; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; using Umbraco.Web.Security; +using Umbraco.Web.Trees; using Umbraco.Web.UI.JavaScript; using Umbraco.Web.WebApi; diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs b/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs index 51e4fbd008..0ef9adddb7 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs @@ -8,6 +8,8 @@ using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Dictionary; using Umbraco.Core.Events; +using Umbraco.Core.Models; +using Umbraco.Core.Models.ContentEditing; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.PropertyEditors; using Umbraco.Core.PropertyEditors.ValueConverters; @@ -21,6 +23,7 @@ using Umbraco.Web.Dictionary; using Umbraco.Web.Editors; using Umbraco.Web.Features; using Umbraco.Web.HealthCheck; +using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Models.PublishedContent; using Umbraco.Web.Mvc; using Umbraco.Web.PublishedCache; @@ -189,6 +192,14 @@ namespace Umbraco.Web.Runtime .Append() .Append() .Append(); + + // register back office sections + composition.WithCollectionBuilder() + .Add(() => composition.TypeLoader.GetTypes()); + + // register back office trees + composition.WithCollectionBuilder() + .Add(() => composition.TypeLoader.GetTypes()); } } } diff --git a/src/Umbraco.Web/Search/SearchableTreeCollection.cs b/src/Umbraco.Web/Search/SearchableTreeCollection.cs index 38c329cafa..2b1baa5194 100644 --- a/src/Umbraco.Web/Search/SearchableTreeCollection.cs +++ b/src/Umbraco.Web/Search/SearchableTreeCollection.cs @@ -5,6 +5,7 @@ using System.Linq; using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Core.Services; +using Umbraco.Web.Services; using Umbraco.Web.Trees; namespace Umbraco.Web.Search diff --git a/src/Umbraco.Web/Services/ApplicationTreeService.cs b/src/Umbraco.Web/Services/ApplicationTreeService.cs index 86bfc5d0bb..72b26e26d3 100644 --- a/src/Umbraco.Web/Services/ApplicationTreeService.cs +++ b/src/Umbraco.Web/Services/ApplicationTreeService.cs @@ -11,7 +11,9 @@ using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Composing; +using Umbraco.Core.Models.ContentEditing; using Umbraco.Core.Services; +using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Trees; namespace Umbraco.Web.Services @@ -19,276 +21,251 @@ namespace Umbraco.Web.Services internal class ApplicationTreeService : IApplicationTreeService { private readonly ILogger _logger; - private readonly CacheHelper _cache; - private readonly TypeLoader _typeLoader; - private Lazy> _allAvailableTrees; - internal const string TreeConfigFileName = "trees.config"; - private static string _treeConfig; + private readonly TreeCollection _treeCollection; private static readonly object Locker = new object(); private readonly Lazy>> _groupedTrees; - public ApplicationTreeService(ILogger logger, CacheHelper cache, TypeLoader typeLoader) + public ApplicationTreeService(ILogger logger, TreeCollection treeCollection) { _logger = logger; - _cache = cache; - _typeLoader = typeLoader; - _groupedTrees = new Lazy>>(InitGroupedTrees); + _treeCollection = treeCollection; + //_groupedTrees = new Lazy>>(InitGroupedTrees); } - /// - /// gets/sets the trees.config file path - /// - /// - /// The setter is generally only going to be used in unit tests, otherwise it will attempt to resolve it using the IOHelper.MapPath - /// - internal static string TreeConfigFilePath - { - get - { - if (string.IsNullOrWhiteSpace(_treeConfig)) - { - _treeConfig = IOHelper.MapPath(SystemDirectories.Config + "/" + TreeConfigFileName); - } - return _treeConfig; - } - set { _treeConfig = value; } - } + ///// + ///// gets/sets the trees.config file path + ///// + ///// + ///// The setter is generally only going to be used in unit tests, otherwise it will attempt to resolve it using the IOHelper.MapPath + ///// + //internal static string TreeConfigFilePath + //{ + // get + // { + // if (string.IsNullOrWhiteSpace(_treeConfig)) + // { + // _treeConfig = IOHelper.MapPath(SystemDirectories.Config + "/" + TreeConfigFileName); + // } + // return _treeConfig; + // } + // set { _treeConfig = value; } + //} - /// - /// The main entry point to get application trees - /// - /// - /// This lazily on first access will scan for plugin trees and ensure the trees.config is up-to-date with the plugins. If plugins - /// haven't changed on disk then the file will not be saved. The trees are all then loaded from this config file into cache and returned. - /// - private List GetAppTrees() - { - return _cache.RuntimeCache.GetCacheItem>( - CacheKeys.ApplicationTreeCacheKey, - () => - { - var list = ReadFromXmlAndSort(); + ///// + ///// The main entry point to get application trees + ///// + ///// + ///// This lazily on first access will scan for plugin trees and ensure the trees.config is up-to-date with the plugins. If plugins + ///// haven't changed on disk then the file will not be saved. The trees are all then loaded from this config file into cache and returned. + ///// + //private List GetAppTrees() + //{ + // return _cache.RuntimeCache.GetCacheItem>( + // CacheKeys.ApplicationTreeCacheKey, + // () => + // { + // var list = ReadFromXmlAndSort(); - //now we can check the non-volatile flag - if (_allAvailableTrees != null) - { - var hasChanges = false; + // //now we can check the non-volatile flag + // if (_allAvailableTrees != null) + // { + // var hasChanges = false; - LoadXml(doc => - { - //Now, load in the xml structure and update it with anything that is not declared there and save the file. + // LoadXml(doc => + // { + // //Now, load in the xml structure and update it with anything that is not declared there and save the file. - //NOTE: On the first iteration here, it will lazily scan all trees, etc... this is because this ienumerable is lazy - // based on the ApplicationTreeRegistrar - and as noted there this is not an ideal way to do things but were stuck like this - // currently because of the legacy assemblies and types not in the Core. + // //NOTE: On the first iteration here, it will lazily scan all trees, etc... this is because this ienumerable is lazy + // // based on the ApplicationTreeRegistrar - and as noted there this is not an ideal way to do things but were stuck like this + // // currently because of the legacy assemblies and types not in the Core. - //Get all the trees not registered in the config (those not matching by alias casing will be detected as "unregistered") - var unregistered = _allAvailableTrees.Value - .Where(x => list.Any(l => l.Alias == x.Alias) == false) - .ToArray(); + // //Get all the trees not registered in the config (those not matching by alias casing will be detected as "unregistered") + // var unregistered = _allAvailableTrees.Value + // .Where(x => list.Any(l => l.Alias == x.Alias) == false) + // .ToArray(); - hasChanges = unregistered.Any(); + // hasChanges = unregistered.Any(); - if (hasChanges == false) return false; + // if (hasChanges == false) return false; - //add or edit the unregistered ones and re-save the file if any changes were found - var count = 0; - foreach (var tree in unregistered) - { - var existingElement = doc.Root.Elements("add").SingleOrDefault(x => - string.Equals(x.Attribute("alias").Value, tree.Alias, - StringComparison.InvariantCultureIgnoreCase) && - string.Equals(x.Attribute("application").Value, tree.ApplicationAlias, - StringComparison.InvariantCultureIgnoreCase)); - if (existingElement != null) - { - existingElement.SetAttributeValue("alias", tree.Alias); - } - else - { - if (tree.Title.IsNullOrWhiteSpace()) - { - doc.Root.Add(new XElement("add", - new XAttribute("initialize", tree.Initialize), - new XAttribute("sortOrder", tree.SortOrder), - new XAttribute("alias", tree.Alias), - new XAttribute("application", tree.ApplicationAlias), - new XAttribute("iconClosed", tree.IconClosed), - new XAttribute("iconOpen", tree.IconOpened), - new XAttribute("type", tree.Type))); - } - else - { - doc.Root.Add(new XElement("add", - new XAttribute("initialize", tree.Initialize), - new XAttribute("sortOrder", tree.SortOrder), - new XAttribute("alias", tree.Alias), - new XAttribute("application", tree.ApplicationAlias), - new XAttribute("title", tree.Title), - new XAttribute("iconClosed", tree.IconClosed), - new XAttribute("iconOpen", tree.IconOpened), - new XAttribute("type", tree.Type))); - } + // //add or edit the unregistered ones and re-save the file if any changes were found + // var count = 0; + // foreach (var tree in unregistered) + // { + // var existingElement = doc.Root.Elements("add").SingleOrDefault(x => + // string.Equals(x.Attribute("alias").Value, tree.Alias, + // StringComparison.InvariantCultureIgnoreCase) && + // string.Equals(x.Attribute("application").Value, tree.ApplicationAlias, + // StringComparison.InvariantCultureIgnoreCase)); + // if (existingElement != null) + // { + // existingElement.SetAttributeValue("alias", tree.Alias); + // } + // else + // { + // if (tree.Title.IsNullOrWhiteSpace()) + // { + // doc.Root.Add(new XElement("add", + // new XAttribute("initialize", tree.Initialize), + // new XAttribute("sortOrder", tree.SortOrder), + // new XAttribute("alias", tree.Alias), + // new XAttribute("application", tree.ApplicationAlias), + // new XAttribute("iconClosed", tree.IconClosed), + // new XAttribute("iconOpen", tree.IconOpened), + // new XAttribute("type", tree.Type))); + // } + // else + // { + // doc.Root.Add(new XElement("add", + // new XAttribute("initialize", tree.Initialize), + // new XAttribute("sortOrder", tree.SortOrder), + // new XAttribute("alias", tree.Alias), + // new XAttribute("application", tree.ApplicationAlias), + // new XAttribute("title", tree.Title), + // new XAttribute("iconClosed", tree.IconClosed), + // new XAttribute("iconOpen", tree.IconOpened), + // new XAttribute("type", tree.Type))); + // } - } - count++; - } + // } + // count++; + // } - //don't save if there's no changes - return count > 0; - }, true); + // //don't save if there's no changes + // return count > 0; + // }, true); - if (hasChanges) - { - //If there were changes, we need to re-read the structures from the XML - list = ReadFromXmlAndSort(); - } - } + // if (hasChanges) + // { + // //If there were changes, we need to re-read the structures from the XML + // list = ReadFromXmlAndSort(); + // } + // } - return list; - }, new TimeSpan(0, 10, 0)); - } + // return list; + // }, new TimeSpan(0, 10, 0)); + //} - /// - /// Creates a new application tree. - /// - /// if set to true [initialize]. - /// The sort order. - /// The application alias. - /// The alias. - /// The title. - /// The icon closed. - /// The icon opened. - /// The type. - public void MakeNew(bool initialize, int sortOrder, string applicationAlias, string alias, string title, string iconClosed, string iconOpened, string type) - { - LoadXml(doc => - { - var el = doc.Root.Elements("add").SingleOrDefault(x => x.Attribute("alias").Value == alias && x.Attribute("application").Value == applicationAlias); + ///// + ///// Creates a new application tree. + ///// + ///// if set to true [initialize]. + ///// The sort order. + ///// The application alias. + ///// The alias. + ///// The title. + ///// The icon closed. + ///// The icon opened. + ///// The type. + //public void MakeNew(bool initialize, int sortOrder, string applicationAlias, string alias, string title, string iconClosed, string iconOpened, string type) + //{ + // LoadXml(doc => + // { + // var el = doc.Root.Elements("add").SingleOrDefault(x => x.Attribute("alias").Value == alias && x.Attribute("application").Value == applicationAlias); - if (el == null) - { - doc.Root.Add(new XElement("add", - new XAttribute("initialize", initialize), - new XAttribute("sortOrder", sortOrder), - new XAttribute("alias", alias), - new XAttribute("application", applicationAlias), - new XAttribute("title", title), - new XAttribute("iconClosed", iconClosed), - new XAttribute("iconOpen", iconOpened), - new XAttribute("type", type))); - } + // if (el == null) + // { + // doc.Root.Add(new XElement("add", + // new XAttribute("initialize", initialize), + // new XAttribute("sortOrder", sortOrder), + // new XAttribute("alias", alias), + // new XAttribute("application", applicationAlias), + // new XAttribute("title", title), + // new XAttribute("iconClosed", iconClosed), + // new XAttribute("iconOpen", iconOpened), + // new XAttribute("type", type))); + // } - return true; + // return true; - }, true); + // }, true); - OnNew(new ApplicationTree(initialize, sortOrder, applicationAlias, alias, title, iconClosed, iconOpened, type), new EventArgs()); - } + // OnNew(new ApplicationTree(initialize, sortOrder, applicationAlias, alias, title, iconClosed, iconOpened, type), new EventArgs()); + //} - /// - /// Saves this instance. - /// - public void SaveTree(ApplicationTree tree) - { - LoadXml(doc => - { - var el = doc.Root.Elements("add").SingleOrDefault(x => x.Attribute("alias").Value == tree.Alias && x.Attribute("application").Value == tree.ApplicationAlias); + ///// + ///// Saves this instance. + ///// + //public void SaveTree(ApplicationTree tree) + //{ + // LoadXml(doc => + // { + // var el = doc.Root.Elements("add").SingleOrDefault(x => x.Attribute("alias").Value == tree.Alias && x.Attribute("application").Value == tree.ApplicationAlias); - if (el != null) - { - el.RemoveAttributes(); + // if (el != null) + // { + // el.RemoveAttributes(); - el.Add(new XAttribute("initialize", tree.Initialize)); - el.Add(new XAttribute("sortOrder", tree.SortOrder)); - el.Add(new XAttribute("alias", tree.Alias)); - el.Add(new XAttribute("application", tree.ApplicationAlias)); - el.Add(new XAttribute("title", tree.Title)); - el.Add(new XAttribute("iconClosed", tree.IconClosed)); - el.Add(new XAttribute("iconOpen", tree.IconOpened)); - el.Add(new XAttribute("type", tree.Type)); - } + // el.Add(new XAttribute("initialize", tree.Initialize)); + // el.Add(new XAttribute("sortOrder", tree.SortOrder)); + // el.Add(new XAttribute("alias", tree.Alias)); + // el.Add(new XAttribute("application", tree.ApplicationAlias)); + // el.Add(new XAttribute("title", tree.Title)); + // el.Add(new XAttribute("iconClosed", tree.IconClosed)); + // el.Add(new XAttribute("iconOpen", tree.IconOpened)); + // el.Add(new XAttribute("type", tree.Type)); + // } - return true; + // return true; - }, true); + // }, true); - OnUpdated(tree, new EventArgs()); - } + // OnUpdated(tree, new EventArgs()); + //} - /// - /// Deletes this instance. - /// - public void DeleteTree(ApplicationTree tree) - { - LoadXml(doc => - { - doc.Root.Elements("add") - .Where(x => x.Attribute("application") != null - && x.Attribute("application").Value == tree.ApplicationAlias - && x.Attribute("alias") != null && x.Attribute("alias").Value == tree.Alias).Remove(); + ///// + ///// Deletes this instance. + ///// + //public void DeleteTree(ApplicationTree tree) + //{ + // LoadXml(doc => + // { + // doc.Root.Elements("add") + // .Where(x => x.Attribute("application") != null + // && x.Attribute("application").Value == tree.ApplicationAlias + // && x.Attribute("alias") != null && x.Attribute("alias").Value == tree.Alias).Remove(); - return true; + // return true; - }, true); + // }, true); - OnDeleted(tree, new EventArgs()); - } + // OnDeleted(tree, new EventArgs()); + //} - /// - /// Gets an ApplicationTree by it's tree alias. - /// - /// The tree alias. - /// An ApplicationTree instance - public ApplicationTree GetByAlias(string treeAlias) - { - return GetAppTrees().Find(t => (t.Alias == treeAlias)); + /// + public ApplicationTree GetByAlias(string treeAlias) => _treeCollection.FirstOrDefault(t => t.Alias == treeAlias); - } + /// + public IEnumerable GetAll() => _treeCollection; - /// - /// Gets all applicationTrees registered in umbraco from the umbracoAppTree table.. - /// - /// Returns a ApplicationTree Array - public IEnumerable GetAll() - { - return GetAppTrees().OrderBy(x => x.SortOrder); - } - - /// - /// Gets the application tree for the applcation with the specified alias - /// - /// The application alias. - /// Returns a ApplicationTree Array + /// public IEnumerable GetApplicationTrees(string applicationAlias) - { - return GetApplicationTrees(applicationAlias, false); - } + => GetAll().Where(x => x.ApplicationAlias.InvariantEquals(applicationAlias)).OrderBy(x => x.SortOrder).ToList(); - /// - /// Gets the application tree for the applcation with the specified alias - /// - /// The application alias. - /// - /// Returns a ApplicationTree Array - public IEnumerable GetApplicationTrees(string applicationAlias, bool onlyInitialized) - { - var list = GetAppTrees().FindAll( - t => - { - if (onlyInitialized) - return (t.ApplicationAlias == applicationAlias && t.Initialize); - return (t.ApplicationAlias == applicationAlias); - } - ); + ///// + ///// Gets the application tree for the applcation with the specified alias + ///// + ///// The application alias. + ///// + ///// Returns a ApplicationTree Array + //public IEnumerable GetApplicationTrees(string applicationAlias, bool onlyInitialized) + //{ + // var list = GetAppTrees().FindAll( + // t => + // { + // if (onlyInitialized) + // return (t.ApplicationAlias == applicationAlias && t.Initialize); + // return (t.ApplicationAlias == applicationAlias); + // } + // ); - return list.OrderBy(x => x.SortOrder).ToArray(); - } + // return list.OrderBy(x => x.SortOrder).ToArray(); + //} - public IDictionary> GetGroupedApplicationTrees(string applicationAlias, bool onlyInitialized) + public IDictionary> GetGroupedApplicationTrees(string applicationAlias) { var result = new Dictionary>(); - var foundTrees = GetApplicationTrees(applicationAlias, onlyInitialized); + var foundTrees = GetApplicationTrees(applicationAlias).ToList(); foreach(var treeGroup in _groupedTrees.Value) { List resultGroup = null; @@ -309,185 +286,185 @@ namespace Umbraco.Web.Services return result; } - /// - /// Creates a group of all tree groups and their tree aliases - /// - /// - /// - /// Used to initialize the field - /// - private IReadOnlyCollection> InitGroupedTrees() - { - var result = GetAll() - .Select(x => (treeAlias: x.Alias, treeGroup: x.GetRuntimeType().GetCustomAttribute(false)?.TreeGroup)) - .GroupBy(x => x.treeGroup, x => x.treeAlias) - .ToList(); - return result; - } - - /// - /// Loads in the xml structure from disk if one is found, otherwise loads in an empty xml structure, calls the - /// callback with the xml document and saves the structure back to disk if saveAfterCallback is true. - /// - /// - /// - internal void LoadXml(Func callback, bool saveAfterCallbackIfChanges) - { - lock (Locker) - { - var doc = System.IO.File.Exists(TreeConfigFilePath) - ? XDocument.Load(TreeConfigFilePath) - : XDocument.Parse(""); + ///// + ///// Creates a group of all tree groups and their tree aliases + ///// + ///// + ///// + ///// Used to initialize the field + ///// + //private IReadOnlyCollection> InitGroupedTrees() + //{ + // var result = GetAll() + // .Select(x => (treeAlias: x.Alias, treeGroup: x.GetRuntimeType().GetCustomAttribute(false)?.TreeGroup)) + // .GroupBy(x => x.treeGroup, x => x.treeAlias) + // .ToList(); + // return result; + //} - if (doc.Root != null) - { - var hasChanges = callback.Invoke(doc); + ///// + ///// Loads in the xml structure from disk if one is found, otherwise loads in an empty xml structure, calls the + ///// callback with the xml document and saves the structure back to disk if saveAfterCallback is true. + ///// + ///// + ///// + //internal void LoadXml(Func callback, bool saveAfterCallbackIfChanges) + //{ + // lock (Locker) + // { + // var doc = System.IO.File.Exists(TreeConfigFilePath) + // ? XDocument.Load(TreeConfigFilePath) + // : XDocument.Parse(""); - if (saveAfterCallbackIfChanges && hasChanges - //Don't save it if it is empty, in some very rare cases if the app domain get's killed in the middle of this process - // in some insane way the file saved will be empty. I'm pretty sure it's not actually anything to do with the xml doc and - // more about the IO trying to save the XML doc, but it doesn't hurt to check. - && doc.Root != null && doc.Root.Elements().Any()) - { - //ensures the folder exists - Directory.CreateDirectory(Path.GetDirectoryName(TreeConfigFilePath)); + // if (doc.Root != null) + // { + // var hasChanges = callback.Invoke(doc); - //saves it - doc.Save(TreeConfigFilePath); + // if (saveAfterCallbackIfChanges && hasChanges + // //Don't save it if it is empty, in some very rare cases if the app domain get's killed in the middle of this process + // // in some insane way the file saved will be empty. I'm pretty sure it's not actually anything to do with the xml doc and + // // more about the IO trying to save the XML doc, but it doesn't hurt to check. + // && doc.Root != null && doc.Root.Elements().Any()) + // { + // //ensures the folder exists + // Directory.CreateDirectory(Path.GetDirectoryName(TreeConfigFilePath)); - //remove the cache now that it has changed SD: I'm leaving this here even though it - // is taken care of by events as well, I think unit tests may rely on it being cleared here. - _cache.RuntimeCache.ClearCacheItem(CacheKeys.ApplicationTreeCacheKey); - } - } - } - } + // //saves it + // doc.Save(TreeConfigFilePath); - private List ReadFromXmlAndSort() - { - var list = new List(); + // //remove the cache now that it has changed SD: I'm leaving this here even though it + // // is taken care of by events as well, I think unit tests may rely on it being cleared here. + // _cache.RuntimeCache.ClearCacheItem(CacheKeys.ApplicationTreeCacheKey); + // } + // } + // } + //} - //read in the xml file containing trees and convert them all to ApplicationTree instances - LoadXml(doc => - { - foreach (var addElement in doc.Root.Elements("add").OrderBy(x => - { - var sortOrderAttr = x.Attribute("sortOrder"); - return sortOrderAttr != null ? Convert.ToInt32(sortOrderAttr.Value) : 0; - })) - { - var applicationAlias = (string)addElement.Attribute("application"); - var type = (string)addElement.Attribute("type"); - var assembly = (string)addElement.Attribute("assembly"); + //private List ReadFromXmlAndSort() + //{ + // var list = new List(); - var clrType = Type.GetType(type); - if (clrType == null) - { - _logger.Warn("The tree definition: {AddElement} could not be resolved to a .Net object type", addElement); - continue; - } + // //read in the xml file containing trees and convert them all to ApplicationTree instances + // LoadXml(doc => + // { + // foreach (var addElement in doc.Root.Elements("add").OrderBy(x => + // { + // var sortOrderAttr = x.Attribute("sortOrder"); + // return sortOrderAttr != null ? Convert.ToInt32(sortOrderAttr.Value) : 0; + // })) + // { + // var applicationAlias = (string)addElement.Attribute("application"); + // var type = (string)addElement.Attribute("type"); + // var assembly = (string)addElement.Attribute("assembly"); - //check if the tree definition (applicationAlias + type + assembly) is already in the list + // var clrType = Type.GetType(type); + // if (clrType == null) + // { + // _logger.Warn("The tree definition: {AddElement} could not be resolved to a .Net object type", addElement); + // continue; + // } - if (list.Any(tree => tree.ApplicationAlias.InvariantEquals(applicationAlias) && tree.GetRuntimeType() == clrType) == false) - { - list.Add(new ApplicationTree( - addElement.Attribute("initialize") == null || Convert.ToBoolean(addElement.Attribute("initialize").Value), - addElement.Attribute("sortOrder") != null - ? Convert.ToByte(addElement.Attribute("sortOrder").Value) - : (byte)0, - (string)addElement.Attribute("application"), - (string)addElement.Attribute("alias"), - (string)addElement.Attribute("title"), - (string)addElement.Attribute("iconClosed"), - (string)addElement.Attribute("iconOpen"), - (string)addElement.Attribute("type"))); - } - } + // //check if the tree definition (applicationAlias + type + assembly) is already in the list - return false; + // if (list.Any(tree => tree.ApplicationAlias.InvariantEquals(applicationAlias) && tree.GetRuntimeType() == clrType) == false) + // { + // list.Add(new ApplicationTree( + // addElement.Attribute("initialize") == null || Convert.ToBoolean(addElement.Attribute("initialize").Value), + // addElement.Attribute("sortOrder") != null + // ? Convert.ToByte(addElement.Attribute("sortOrder").Value) + // : (byte)0, + // (string)addElement.Attribute("application"), + // (string)addElement.Attribute("alias"), + // (string)addElement.Attribute("title"), + // (string)addElement.Attribute("iconClosed"), + // (string)addElement.Attribute("iconOpen"), + // (string)addElement.Attribute("type"))); + // } + // } - }, false); + // return false; - return list; - } + // }, false); + + // return list; + //} - internal static event TypedEventHandler Deleted; - private static void OnDeleted(ApplicationTree app, EventArgs args) - { - if (Deleted != null) - { - Deleted(app, args); - } - } + //internal static event TypedEventHandler Deleted; + //private static void OnDeleted(ApplicationTree app, EventArgs args) + //{ + // if (Deleted != null) + // { + // Deleted(app, args); + // } + //} - internal static event TypedEventHandler New; - private static void OnNew(ApplicationTree app, EventArgs args) - { - if (New != null) - { - New(app, args); - } - } + //internal static event TypedEventHandler New; + //private static void OnNew(ApplicationTree app, EventArgs args) + //{ + // if (New != null) + // { + // New(app, args); + // } + //} - internal static event TypedEventHandler Updated; - private static void OnUpdated(ApplicationTree app, EventArgs args) - { - if (Updated != null) - { - Updated(app, args); - } - } + //internal static event TypedEventHandler Updated; + //private static void OnUpdated(ApplicationTree app, EventArgs args) + //{ + // if (Updated != null) + // { + // Updated(app, args); + // } + //} - /// - /// This class is here so that we can provide lazy access to tree scanning for when it is needed - /// - private class LazyEnumerableTrees : IEnumerable - { - public LazyEnumerableTrees(TypeLoader typeLoader) - { - _lazyTrees = new Lazy>(() => - { - var added = new List(); + ///// + ///// This class is here so that we can provide lazy access to tree scanning for when it is needed + ///// + //private class LazyEnumerableTrees : IEnumerable + //{ + // public LazyEnumerableTrees(TypeLoader typeLoader) + // { + // _lazyTrees = new Lazy>(() => + // { + // var added = new List(); - // Load all Controller Trees by attribute - var types = typeLoader.GetTypesWithAttribute(); // fixme inject - //convert them to ApplicationTree instances - var items = types - .Select(x => (tree: x, treeAttribute: x.GetCustomAttributes(false).Single())) - .Select(x => new ApplicationTree(x.treeAttribute.Initialize, x.treeAttribute.SortOrder, x.treeAttribute.ApplicationAlias, x.treeAttribute.Alias, x.treeAttribute.Title, x.treeAttribute.IconClosed, x.treeAttribute.IconOpen, x.tree.GetFullNameWithAssembly())) - .ToArray(); + // // Load all Controller Trees by attribute + // var types = typeLoader.GetTypesWithAttribute(); // fixme inject + // //convert them to ApplicationTree instances + // var items = types + // .Select(x => (tree: x, treeAttribute: x.GetCustomAttributes(false).Single())) + // .Select(x => new ApplicationTree(x.treeAttribute.Initialize, x.treeAttribute.SortOrder, x.treeAttribute.ApplicationAlias, x.treeAttribute.Alias, x.treeAttribute.Title, x.treeAttribute.IconClosed, x.treeAttribute.IconOpen, x.tree.GetFullNameWithAssembly())) + // .ToArray(); - added.AddRange(items.Select(x => x.Alias)); + // added.AddRange(items.Select(x => x.Alias)); - return items.ToArray(); - }); - } + // return items.ToArray(); + // }); + // } - private readonly Lazy> _lazyTrees; - - /// - /// Returns an enumerator that iterates through the collection. - /// - /// - /// A that can be used to iterate through the collection. - /// - public IEnumerator GetEnumerator() - { - return _lazyTrees.Value.GetEnumerator(); - } + // private readonly Lazy> _lazyTrees; - /// - /// Returns an enumerator that iterates through a collection. - /// - /// - /// An object that can be used to iterate through the collection. - /// - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - } + // /// + // /// Returns an enumerator that iterates through the collection. + // /// + // /// + // /// A that can be used to iterate through the collection. + // /// + // public IEnumerator GetEnumerator() + // { + // return _lazyTrees.Value.GetEnumerator(); + // } + + // /// + // /// Returns an enumerator that iterates through a collection. + // /// + // /// + // /// An object that can be used to iterate through the collection. + // /// + // IEnumerator IEnumerable.GetEnumerator() + // { + // return GetEnumerator(); + // } + //} } } diff --git a/src/Umbraco.Core/Services/IApplicationTreeService.cs b/src/Umbraco.Web/Services/IApplicationTreeService.cs similarity index 52% rename from src/Umbraco.Core/Services/IApplicationTreeService.cs rename to src/Umbraco.Web/Services/IApplicationTreeService.cs index 691a3a0b63..1fd7bc939a 100644 --- a/src/Umbraco.Core/Services/IApplicationTreeService.cs +++ b/src/Umbraco.Web/Services/IApplicationTreeService.cs @@ -2,33 +2,35 @@ using System.Collections.Generic; using System.Linq; using Umbraco.Core.Models; +using Umbraco.Core.Models.ContentEditing; +using Umbraco.Web.Models.ContentEditing; -namespace Umbraco.Core.Services +namespace Umbraco.Web.Services { public interface IApplicationTreeService { - /// - /// Creates a new application tree. - /// - /// if set to true [initialize]. - /// The sort order. - /// The application alias. - /// The alias. - /// The title. - /// The icon closed. - /// The icon opened. - /// The type. - void MakeNew(bool initialize, int sortOrder, string applicationAlias, string alias, string title, string iconClosed, string iconOpened, string type); + ///// + ///// Creates a new application tree. + ///// + ///// if set to true [initialize]. + ///// The sort order. + ///// The application alias. + ///// The alias. + ///// The title. + ///// The icon closed. + ///// The icon opened. + ///// The type. + //void MakeNew(bool initialize, int sortOrder, string applicationAlias, string alias, string title, string iconClosed, string iconOpened, string type); - /// - /// Saves this instance. - /// - void SaveTree(ApplicationTree tree); + ///// + ///// Saves this instance. + ///// + //void SaveTree(ApplicationTree tree); - /// - /// Deletes this instance. - /// - void DeleteTree(ApplicationTree tree); + ///// + ///// Deletes this instance. + ///// + //void DeleteTree(ApplicationTree tree); /// /// Gets an ApplicationTree by it's tree alias. @@ -50,21 +52,20 @@ namespace Umbraco.Core.Services /// Returns a ApplicationTree Array IEnumerable GetApplicationTrees(string applicationAlias); - /// - /// Gets the application tree for the applcation with the specified alias - /// - /// The application alias. - /// - /// Returns a ApplicationTree Array - IEnumerable GetApplicationTrees(string applicationAlias, bool onlyInitialized); + ///// + ///// Gets the application tree for the applcation with the specified alias + ///// + ///// The application alias. + ///// + ///// Returns a ApplicationTree Array + //IEnumerable GetApplicationTrees(string applicationAlias, bool onlyInitialized); /// /// Gets the grouped application trees for the application with the specified alias /// /// - /// /// - IDictionary> GetGroupedApplicationTrees(string applicationAlias, bool onlyInitialized); + IDictionary> GetGroupedApplicationTrees(string applicationAlias); } /// @@ -72,37 +73,37 @@ namespace Umbraco.Core.Services /// internal class EmptyApplicationTreeService : IApplicationTreeService { - /// - /// Creates a new application tree. - /// - /// if set to true [initialize]. - /// The sort order. - /// The application alias. - /// The alias. - /// The title. - /// The icon closed. - /// The icon opened. - /// The type. - public void MakeNew(bool initialize, int sortOrder, string applicationAlias, string alias, string title, string iconClosed, string iconOpened, string type) - { - throw new System.NotImplementedException(); - } + ///// + ///// Creates a new application tree. + ///// + ///// if set to true [initialize]. + ///// The sort order. + ///// The application alias. + ///// The alias. + ///// The title. + ///// The icon closed. + ///// The icon opened. + ///// The type. + //public void MakeNew(bool initialize, int sortOrder, string applicationAlias, string alias, string title, string iconClosed, string iconOpened, string type) + //{ + // throw new System.NotImplementedException(); + //} - /// - /// Saves this instance. - /// - public void SaveTree(ApplicationTree tree) - { - throw new System.NotImplementedException(); - } + ///// + ///// Saves this instance. + ///// + //public void SaveTree(ApplicationTree tree) + //{ + // throw new System.NotImplementedException(); + //} - /// - /// Deletes this instance. - /// - public void DeleteTree(ApplicationTree tree) - { - throw new System.NotImplementedException(); - } + ///// + ///// Deletes this instance. + ///// + //public void DeleteTree(ApplicationTree tree) + //{ + // throw new System.NotImplementedException(); + //} /// /// Gets an ApplicationTree by it's tree alias. @@ -123,7 +124,7 @@ namespace Umbraco.Core.Services throw new System.NotImplementedException(); } - public IDictionary> GetGroupedApplicationTrees(string applicationAlias, bool onlyInitialized) + public IDictionary> GetGroupedApplicationTrees(string applicationAlias) { throw new System.NotImplementedException(); } diff --git a/src/Umbraco.Web/Services/ISectionService.cs b/src/Umbraco.Web/Services/ISectionService.cs new file mode 100644 index 0000000000..560805634f --- /dev/null +++ b/src/Umbraco.Web/Services/ISectionService.cs @@ -0,0 +1,116 @@ +using System.Collections.Generic; +using Umbraco.Core.Models; +using Umbraco.Core.Models.ContentEditing; +using Umbraco.Web.Models.ContentEditing; + +namespace Umbraco.Web.Services +{ + public interface ISectionService + { + /// + /// The cache storage for all applications + /// + IEnumerable GetSections(); + + /// + /// Get the user group's allowed sections + /// + /// + /// + IEnumerable GetAllowedSections(int userId); + + /// + /// Gets the application by its alias. + /// + /// The application alias. + /// + IBackOfficeSection GetByAlias(string appAlias); + + ///// + ///// Creates a new applcation if no application with the specified alias is found. + ///// + ///// The application name. + ///// The application alias. + ///// The application icon, which has to be located in umbraco/images/tray folder. + //void MakeNew(string name, string alias, string icon); + + ///// + ///// Makes the new. + ///// + ///// The name. + ///// The alias. + ///// The icon. + ///// The sort order. + //void MakeNew(string name, string alias, string icon, int sortOrder); + + ///// + ///// Deletes the section + ///// + //void DeleteSection(Section section); + } + + /// + /// Purely used to allow a service context to create the default services + /// + internal class EmptySectionService : ISectionService + { + /// + /// The cache storage for all applications + /// + public IEnumerable GetSections() + { + throw new System.NotImplementedException(); + } + + /// + /// Get the user's allowed sections + /// + /// + /// + public IEnumerable GetAllowedSections(int userId) + { + throw new System.NotImplementedException(); + } + + /// + /// Gets the application by its alias. + /// + /// The application alias. + /// + public IBackOfficeSection GetByAlias(string appAlias) + { + throw new System.NotImplementedException(); + } + + ///// + ///// Creates a new applcation if no application with the specified alias is found. + ///// + ///// The application name. + ///// The application alias. + ///// The application icon, which has to be located in umbraco/images/tray folder. + //public void MakeNew(string name, string alias, string icon) + //{ + // throw new System.NotImplementedException(); + //} + + ///// + ///// Makes the new. + ///// + ///// The name. + ///// The alias. + ///// The icon. + ///// The sort order. + //public void MakeNew(string name, string alias, string icon, int sortOrder) + //{ + // throw new System.NotImplementedException(); + //} + + ///// + ///// Deletes the section + ///// + //public void DeleteSection(IBackOfficeSection section) + //{ + // throw new System.NotImplementedException(); + //} + } +} diff --git a/src/Umbraco.Web/Services/SectionService.cs b/src/Umbraco.Web/Services/SectionService.cs index 6337db67f9..bb154976f0 100644 --- a/src/Umbraco.Web/Services/SectionService.cs +++ b/src/Umbraco.Web/Services/SectionService.cs @@ -10,9 +10,12 @@ using Umbraco.Core.Events; using Umbraco.Core.IO; using Umbraco.Core.Models; using Umbraco.Core.Composing; +using Umbraco.Core.Models.ContentEditing; using Umbraco.Core.Scoping; using Umbraco.Core.Services; +using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Models.Trees; +using Umbraco.Web.Trees; using File = System.IO.File; namespace Umbraco.Web.Services @@ -20,130 +23,90 @@ namespace Umbraco.Web.Services internal class SectionService : ISectionService { private readonly IUserService _userService; - private readonly Lazy> _allAvailableSections; - private readonly IApplicationTreeService _applicationTreeService; - private readonly IScopeProvider _scopeProvider; + private readonly BackOfficeSectionCollection _sectionCollection; + + private readonly Lazy> _allAvailableSections; + //private readonly IApplicationTreeService _applicationTreeService; + //private readonly IScopeProvider _scopeProvider; private readonly CacheHelper _cache; - internal const string AppConfigFileName = "applications.config"; - private static string _appConfig; - private static readonly object Locker = new object(); + //internal const string AppConfigFileName = "applications.config"; + //private static string _appConfig; + //private static readonly object Locker = new object(); public SectionService( IUserService userService, - IApplicationTreeService applicationTreeService, - IScopeProvider scopeProvider, + BackOfficeSectionCollection sectionCollection, CacheHelper cache) { - _applicationTreeService = applicationTreeService ?? throw new ArgumentNullException(nameof(applicationTreeService)); + //_applicationTreeService = applicationTreeService ?? throw new ArgumentNullException(nameof(applicationTreeService)); _cache = cache ?? throw new ArgumentNullException(nameof(cache)); _userService = userService; - _scopeProvider = scopeProvider; - _allAvailableSections = new Lazy>(() => new LazyEnumerableSections()); + _sectionCollection = sectionCollection; + //_scopeProvider = scopeProvider; + //_allAvailableSections = new Lazy>(() => new LazyEnumerableSections()); } - /// - /// gets/sets the application.config file path - /// - /// - /// The setter is generally only going to be used in unit tests, otherwise it will attempt to resolve it using the IOHelper.MapPath - /// - internal static string AppConfigFilePath - { - get - { - if (string.IsNullOrWhiteSpace(_appConfig)) - { - _appConfig = IOHelper.MapPath(SystemDirectories.Config + "/" + AppConfigFileName); - } - return _appConfig; - } - set => _appConfig = value; - } + ///// + ///// gets/sets the application.config file path + ///// + ///// + ///// The setter is generally only going to be used in unit tests, otherwise it will attempt to resolve it using the IOHelper.MapPath + ///// + //internal static string AppConfigFilePath + //{ + // get + // { + // if (string.IsNullOrWhiteSpace(_appConfig)) + // { + // _appConfig = IOHelper.MapPath(SystemDirectories.Config + "/" + AppConfigFileName); + // } + // return _appConfig; + // } + // set => _appConfig = value; + //} /// /// The cache storage for all applications /// - public IEnumerable
    GetSections() + public IEnumerable GetSections() { - return _cache.RuntimeCache.GetCacheItem>( - CacheKeys.ApplicationsCacheKey, - () => - { - var list = ReadFromXmlAndSort(); - var hasChanges = false; - var localCopyList = list; - - LoadXml(doc => - { - //Now, load in the xml structure and update it with anything that is not declared there and save the file. - //NOTE: On the first iteration here, it will lazily scan all apps, etc... this is because this ienumerable is lazy - //Get all the trees not registered in the config - - var unregistered = _allAvailableSections.Value - .Where(x => localCopyList.Any(l => l.Alias == x.Alias) == false) - .ToArray(); - - hasChanges = unregistered.Any(); - - var count = 0; - foreach (var attr in unregistered) - { - doc.Root.Add(new XElement("add", - new XAttribute("alias", attr.Alias), - new XAttribute("name", attr.Name), - new XAttribute("sortOrder", attr.SortOrder))); - count++; - } - - //don't save if there's no changes - return count > 0; - }, true); - - if (hasChanges) - { - //If there were changes, we need to re-read the structures from the XML - list = ReadFromXmlAndSort(); - } - - return list; - - }, new TimeSpan(0, 10, 0)); + return _sectionCollection; } - internal void LoadXml(Func callback, bool saveAfterCallbackIfChanged) - { - lock (Locker) - { - var doc = File.Exists(AppConfigFilePath) - ? XDocument.Load(AppConfigFilePath) - : XDocument.Parse(""); + //internal void LoadXml(Func callback, bool saveAfterCallbackIfChanged) + //{ + // lock (Locker) + // { + // var doc = File.Exists(AppConfigFilePath) + // ? XDocument.Load(AppConfigFilePath) + // : XDocument.Parse(""); - if (doc.Root != null) - { - var changed = callback.Invoke(doc); + // if (doc.Root != null) + // { + // var changed = callback.Invoke(doc); - if (saveAfterCallbackIfChanged && changed) - { - //ensure the folder is created! - Directory.CreateDirectory(Path.GetDirectoryName(AppConfigFilePath)); + // if (saveAfterCallbackIfChanged && changed) + // { + // //ensure the folder is created! + // Directory.CreateDirectory(Path.GetDirectoryName(AppConfigFilePath)); - doc.Save(AppConfigFilePath); + // doc.Save(AppConfigFilePath); - //remove the cache so it gets re-read ... SD: I'm leaving this here even though it - // is taken care of by events as well, I think unit tests may rely on it being cleared here. - _cache.RuntimeCache.ClearCacheItem(CacheKeys.ApplicationsCacheKey); - } - } - } - } + // //remove the cache so it gets re-read ... SD: I'm leaving this here even though it + // // is taken care of by events as well, I think unit tests may rely on it being cleared here. + // _cache.RuntimeCache.ClearCacheItem(CacheKeys.ApplicationsCacheKey); + // } + // } + // } + //} /// /// Get the user's allowed sections /// /// /// - public IEnumerable
    GetAllowedSections(int userId) + public IEnumerable GetAllowedSections(int userId) { var user = _userService.GetUserById(userId); @@ -160,172 +123,172 @@ namespace Umbraco.Web.Services ///
    /// The application alias. /// - public Section GetByAlias(string appAlias) + public IBackOfficeSection GetByAlias(string appAlias) { return GetSections().FirstOrDefault(t => t.Alias == appAlias); } - /// - /// Creates a new applcation if no application with the specified alias is found. - /// - /// The application name. - /// The application alias. - /// The application icon, which has to be located in umbraco/images/tray folder. - public void MakeNew(string name, string alias, string icon) - { - var sections = GetSections(); - var nextSortOrder = sections.Any() ? sections.Max(x => x.SortOrder) + 1 : 1; - MakeNew(name, alias, icon, nextSortOrder); - } + ///// + ///// Creates a new applcation if no application with the specified alias is found. + ///// + ///// The application name. + ///// The application alias. + ///// The application icon, which has to be located in umbraco/images/tray folder. + //public void MakeNew(string name, string alias, string icon) + //{ + // var sections = GetSections(); + // var nextSortOrder = sections.Any() ? sections.Max(x => x.SortOrder) + 1 : 1; + // MakeNew(name, alias, icon, nextSortOrder); + //} - /// - /// Makes the new. - /// - /// The name. - /// The alias. - /// The icon. - /// The sort order. - public void MakeNew(string name, string alias, string icon, int sortOrder) - { - if (GetSections().All(x => x.Alias != alias)) - { - LoadXml(doc => - { - doc.Root.Add(new XElement("add", - new XAttribute("alias", alias), - new XAttribute("name", name), - new XAttribute("icon", icon), - new XAttribute("sortOrder", sortOrder))); - return true; - }, true); + ///// + ///// Makes the new. + ///// + ///// The name. + ///// The alias. + ///// The icon. + ///// The sort order. + //public void MakeNew(string name, string alias, string icon, int sortOrder) + //{ + // if (GetSections().All(x => x.Alias != alias)) + // { + // LoadXml(doc => + // { + // doc.Root.Add(new XElement("add", + // new XAttribute("alias", alias), + // new XAttribute("name", name), + // new XAttribute("icon", icon), + // new XAttribute("sortOrder", sortOrder))); + // return true; + // }, true); - //raise event - OnNew(this /*new Section(name, alias, sortOrder)*/, new EventArgs()); - } - } + // //raise event + // OnNew(this /*new Section(name, alias, sortOrder)*/, new EventArgs()); + // } + //} - /// - /// Deletes the section - /// - public void DeleteSection(Section section) - { - lock (Locker) - { - //delete the assigned applications - using (var scope = _scopeProvider.CreateScope()) - { - scope.Database.Execute("delete from umbracoUserGroup2App where app = @appAlias", - new { appAlias = section.Alias }); - scope.Complete(); - } + ///// + ///// Deletes the section + ///// + //public void DeleteSection(Section section) + //{ + // lock (Locker) + // { + // //delete the assigned applications + // using (var scope = _scopeProvider.CreateScope()) + // { + // scope.Database.Execute("delete from umbracoUserGroup2App where app = @appAlias", + // new { appAlias = section.Alias }); + // scope.Complete(); + // } - //delete the assigned trees - var trees = _applicationTreeService.GetApplicationTrees(section.Alias); - foreach (var t in trees) - { - _applicationTreeService.DeleteTree(t); - } + // //delete the assigned trees + // var trees = _applicationTreeService.GetApplicationTrees(section.Alias); + // foreach (var t in trees) + // { + // _applicationTreeService.DeleteTree(t); + // } - LoadXml(doc => - { - doc.Root.Elements("add").Where(x => x.Attribute("alias") != null && x.Attribute("alias").Value == section.Alias) - .Remove(); + // LoadXml(doc => + // { + // doc.Root.Elements("add").Where(x => x.Attribute("alias") != null && x.Attribute("alias").Value == section.Alias) + // .Remove(); - return true; - }, true); + // return true; + // }, true); - //raise event - OnDeleted(this, new EventArgs()); - } - } + // //raise event + // OnDeleted(this, new EventArgs()); + // } + //} - private List
    ReadFromXmlAndSort() - { - var tmp = new List
    (); + //private List
    ReadFromXmlAndSort() + //{ + // var tmp = new List
    (); - LoadXml(doc => - { - foreach (var addElement in doc.Root.Elements("add").OrderBy(x => - { - var sortOrderAttr = x.Attribute("sortOrder"); - return sortOrderAttr != null ? Convert.ToInt32(sortOrderAttr.Value) : 0; - })) - { - var sortOrderAttr = addElement.Attribute("sortOrder"); - tmp.Add(new Section(addElement.Attribute("name").Value, - addElement.Attribute("alias").Value, - sortOrderAttr != null ? Convert.ToInt32(sortOrderAttr.Value) : 0)); - } - return false; - }, false); + // LoadXml(doc => + // { + // foreach (var addElement in doc.Root.Elements("add").OrderBy(x => + // { + // var sortOrderAttr = x.Attribute("sortOrder"); + // return sortOrderAttr != null ? Convert.ToInt32(sortOrderAttr.Value) : 0; + // })) + // { + // var sortOrderAttr = addElement.Attribute("sortOrder"); + // tmp.Add(new Section(addElement.Attribute("name").Value, + // addElement.Attribute("alias").Value, + // sortOrderAttr != null ? Convert.ToInt32(sortOrderAttr.Value) : 0)); + // } + // return false; + // }, false); - return tmp; - } + // return tmp; + //} - internal static event TypedEventHandler Deleted; - private static void OnDeleted(ISectionService app, EventArgs args) - { - if (Deleted != null) - { - Deleted(app, args); - } - } + //internal static event TypedEventHandler Deleted; + //private static void OnDeleted(ISectionService app, EventArgs args) + //{ + // if (Deleted != null) + // { + // Deleted(app, args); + // } + //} - internal static event TypedEventHandler New; - private static void OnNew(ISectionService app, EventArgs args) - { - if (New != null) - { - New(app, args); - } - } + //internal static event TypedEventHandler New; + //private static void OnNew(ISectionService app, EventArgs args) + //{ + // if (New != null) + // { + // New(app, args); + // } + //} - /// - /// This class is here so that we can provide lazy access to tree scanning for when it is needed - /// - private class LazyEnumerableSections : IEnumerable
    - { - public LazyEnumerableSections() - { - _lazySections = new Lazy>(() => - { - // Load all Applications by attribute and add them to the XML config + ///// + ///// This class is here so that we can provide lazy access to tree scanning for when it is needed + ///// + //private class LazyEnumerableSections : IEnumerable
    + //{ + // public LazyEnumerableSections() + // { + // _lazySections = new Lazy>(() => + // { + // // Load all Applications by attribute and add them to the XML config - //don't cache the result of this because it is only used once during app startup, caching will just add a bit more mem overhead for no reason - var types = Current.TypeLoader.GetTypesWithAttribute(cache: false); // fixme - inject + // //don't cache the result of this because it is only used once during app startup, caching will just add a bit more mem overhead for no reason + // var types = Current.TypeLoader.GetTypesWithAttribute(cache: false); // fixme - inject - //since applications don't populate their metadata from the attribute and because it is an interface, - //we need to interrogate the attributes for the data. Would be better to have a base class that contains - //metadata populated by the attribute. Oh well i guess. - var attrs = types.Select(x => x.GetCustomAttributes(false).Single()); - return attrs.Select(x => new Section(x.Name, x.Alias, x.SortOrder)).ToArray(); - }); - } + // //since applications don't populate their metadata from the attribute and because it is an interface, + // //we need to interrogate the attributes for the data. Would be better to have a base class that contains + // //metadata populated by the attribute. Oh well i guess. + // var attrs = types.Select(x => x.GetCustomAttributes(false).Single()); + // return attrs.Select(x => new Section(x.Name, x.Alias, x.SortOrder)).ToArray(); + // }); + // } - private readonly Lazy> _lazySections; + // private readonly Lazy> _lazySections; - /// - /// Returns an enumerator that iterates through the collection. - /// - /// - /// A that can be used to iterate through the collection. - /// - public IEnumerator
    GetEnumerator() - { - return _lazySections.Value.GetEnumerator(); - } + // /// + // /// Returns an enumerator that iterates through the collection. + // /// + // /// + // /// A that can be used to iterate through the collection. + // /// + // public IEnumerator
    GetEnumerator() + // { + // return _lazySections.Value.GetEnumerator(); + // } - /// - /// Returns an enumerator that iterates through a collection. - /// - /// - /// An object that can be used to iterate through the collection. - /// - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - } + // /// + // /// Returns an enumerator that iterates through a collection. + // /// + // /// + // /// An object that can be used to iterate through the collection. + // /// + // IEnumerator IEnumerable.GetEnumerator() + // { + // return GetEnumerator(); + // } + //} } } diff --git a/src/Umbraco.Web/Trees/ApplicationTreeController.cs b/src/Umbraco.Web/Trees/ApplicationTreeController.cs index 0454155772..7e7c77d607 100644 --- a/src/Umbraco.Web/Trees/ApplicationTreeController.cs +++ b/src/Umbraco.Web/Trees/ApplicationTreeController.cs @@ -7,10 +7,17 @@ using System.Net.Http.Formatting; using System.Threading.Tasks; using System.Web.Http; using Umbraco.Core; +using Umbraco.Core.Cache; +using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; using Umbraco.Core.Models; +using Umbraco.Core.Models.ContentEditing; +using Umbraco.Core.Persistence; using Umbraco.Core.Services; +using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Models.Trees; using Umbraco.Web.Mvc; +using Umbraco.Web.Services; using Umbraco.Web.WebApi; using Umbraco.Web.WebApi.Filters; using Constants = Umbraco.Core.Constants; @@ -20,7 +27,19 @@ namespace Umbraco.Web.Trees [AngularJsonOnlyConfiguration] [PluginController("UmbracoTrees")] public class ApplicationTreeController : UmbracoAuthorizedApiController - { + { + private readonly TreeControllerResolver _treeControllerResolver; + private readonly IApplicationTreeService _treeService; + + public ApplicationTreeController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, + ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, + IRuntimeState runtimeState, TreeControllerResolver treeControllerResolver, IApplicationTreeService treeService) + : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, runtimeState) + { + _treeControllerResolver = treeControllerResolver; + _treeService = treeService; + } + /// /// Returns the tree nodes for an application /// @@ -30,14 +49,14 @@ namespace Umbraco.Web.Trees /// An optional bool (defaults to true), if set to false it will also load uninitialized trees /// [HttpQueryStringFilter("queryStrings")] - public async Task GetApplicationTrees(string application, string tree, FormDataCollection queryStrings, bool onlyInitialized = true) + public async Task GetApplicationTrees(string application, string tree, FormDataCollection queryStrings/*, bool onlyInitialized = true*/) { application = application.CleanForXss(); if (string.IsNullOrEmpty(application)) throw new HttpResponseException(HttpStatusCode.NotFound); //find all tree definitions that have the current application alias - var groupedTrees = Services.ApplicationTreeService.GetGroupedApplicationTrees(application, onlyInitialized); + var groupedTrees = _treeService.GetGroupedApplicationTrees(application); var allTrees = groupedTrees.Values.SelectMany(x => x).ToList(); if (string.IsNullOrEmpty(tree) == false || allTrees.Count == 1) @@ -142,7 +161,7 @@ namespace Umbraco.Web.Trees if (configTree == null) throw new ArgumentNullException(nameof(configTree)); try { - var byControllerAttempt = await configTree.TryGetRootNodeFromControllerTree(queryStrings, ControllerContext); + var byControllerAttempt = await _treeControllerResolver.TryGetRootNodeFromControllerTree(configTree, queryStrings, ControllerContext); if (byControllerAttempt.Success) { return byControllerAttempt.Result; @@ -170,17 +189,17 @@ namespace Umbraco.Web.Trees { var rootId = Constants.System.Root.ToString(CultureInfo.InvariantCulture); if (configTree == null) throw new ArgumentNullException(nameof(configTree)); - var byControllerAttempt = configTree.TryLoadFromControllerTree(id, queryStrings, ControllerContext); + var byControllerAttempt = _treeControllerResolver.TryLoadFromControllerTree(configTree, id, queryStrings, ControllerContext); if (byControllerAttempt.Success) { - var rootNode = await configTree.TryGetRootNodeFromControllerTree(queryStrings, ControllerContext); + var rootNode = await _treeControllerResolver.TryGetRootNodeFromControllerTree(configTree, queryStrings, ControllerContext); if (rootNode.Success == false) { //This should really never happen if we've successfully got the children above. throw new InvalidOperationException("Could not create root node for tree " + configTree.Alias); } - var treeAttribute = configTree.GetTreeAttribute(); + var treeAttribute = _treeControllerResolver.GetTreeAttribute(configTree); var sectionRoot = TreeRootNode.CreateSingleTreeRoot( rootId, diff --git a/src/Umbraco.Web/Trees/BackOfficeSectionCollection.cs b/src/Umbraco.Web/Trees/BackOfficeSectionCollection.cs new file mode 100644 index 0000000000..2b5a78d758 --- /dev/null +++ b/src/Umbraco.Web/Trees/BackOfficeSectionCollection.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; +using Umbraco.Core.Composing; +using Umbraco.Core.Models.ContentEditing; +using Umbraco.Web.Models.ContentEditing; + +namespace Umbraco.Web.Trees +{ + public class BackOfficeSectionCollection : BuilderCollectionBase + { + public BackOfficeSectionCollection(IEnumerable items) + : base(items) + { } + } + + public class BackOfficeSectionCollectionBuilder : LazyCollectionBuilderBase + { + protected override BackOfficeSectionCollectionBuilder This => this; + + //TODO: can we allow for re-ordering OOTB without exposing other methods? + } +} diff --git a/src/Umbraco.Web/Trees/TreeCollection.cs b/src/Umbraco.Web/Trees/TreeCollection.cs new file mode 100644 index 0000000000..8f913fb2d7 --- /dev/null +++ b/src/Umbraco.Web/Trees/TreeCollection.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Umbraco.Core.Composing; +using Umbraco.Core.Models; +using Umbraco.Core.Models.ContentEditing; +using Umbraco.Web.Models.ContentEditing; + +namespace Umbraco.Web.Trees +{ + public class TreeCollection : BuilderCollectionBase + { + public TreeCollection(IEnumerable items) + : base(items) + { } + } + + public class TreeCollectionBuilder : LazyCollectionBuilderBase + { + protected override TreeCollectionBuilder This => this; + + //TODO: can we allow for re-ordering OOTB without exposing other methods? + } + +} diff --git a/src/Umbraco.Web/Trees/TreeController.cs b/src/Umbraco.Web/Trees/TreeController.cs index 1c37307db5..102671ec29 100644 --- a/src/Umbraco.Web/Trees/TreeController.cs +++ b/src/Umbraco.Web/Trees/TreeController.cs @@ -1,4 +1,12 @@ -namespace Umbraco.Web.Trees +using System; +using Umbraco.Core; +using Umbraco.Core.Cache; +using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; +using Umbraco.Core.Persistence; +using Umbraco.Core.Services; + +namespace Umbraco.Web.Trees { /// /// The base controller for all tree requests @@ -8,6 +16,10 @@ private TreeAttribute _attribute; private string _rootNodeDisplayName; + protected TreeController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, runtimeState) + { + } + protected TreeController() { Initialize(); @@ -17,21 +29,25 @@ /// The name to display on the root node /// public override string RootNodeDisplayName - => _rootNodeDisplayName - ?? (_rootNodeDisplayName = Services.ApplicationTreeService.GetByAlias(_attribute.Alias) - ?.GetRootNodeDisplayName(Services.TextService)); + { + get + { + throw new NotImplementedException(); + //return _rootNodeDisplayName + // ?? (_rootNodeDisplayName = Services.ApplicationTreeService.GetByAlias(_attribute.Alias) + // ?.GetRootNodeDisplayName(Services.TextService)); + } + } /// /// Gets the current tree alias from the attribute assigned to it. /// - public override string TreeAlias - { - get { return _attribute.Alias; } - } + public override string TreeAlias => _attribute.Alias; private void Initialize() { - _attribute = GetType().GetTreeAttribute(); + throw new NotImplementedException(); + //_attribute = GetType().GetTreeAttribute(); } } } diff --git a/src/Umbraco.Web/Trees/TreeControllerBase.cs b/src/Umbraco.Web/Trees/TreeControllerBase.cs index ffdcac4479..c00d6053c8 100644 --- a/src/Umbraco.Web/Trees/TreeControllerBase.cs +++ b/src/Umbraco.Web/Trees/TreeControllerBase.cs @@ -4,9 +4,14 @@ using System.Linq; using System.Net.Http.Formatting; using System.Web.Http.Routing; using Umbraco.Core; +using Umbraco.Core.Cache; +using Umbraco.Core.Configuration; using Umbraco.Core.Events; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Entities; +using Umbraco.Core.Persistence; +using Umbraco.Core.Services; using Umbraco.Web.Models.Trees; using Umbraco.Web.WebApi; using Umbraco.Web.WebApi.Filters; @@ -14,12 +19,23 @@ using Umbraco.Web.WebApi.Filters; namespace Umbraco.Web.Trees { /// - /// A base controller reference for non-attributed trees (un-registered). Developers should inherit from - /// TreeController. + /// A base controller reference for non-attributed trees (un-registered). /// + /// + /// Developers should generally inherit from TreeController. + /// [AngularJsonOnlyConfiguration] public abstract class TreeControllerBase : UmbracoAuthorizedApiController { + protected TreeControllerBase() + { + } + + protected TreeControllerBase(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, runtimeState) + { + } + + /// /// The method called to render the contents of the tree structure /// @@ -351,7 +367,7 @@ namespace Umbraco.Web.Trees private static void OnTreeNodesRendering(TreeControllerBase instance, TreeNodesRenderingEventArgs e) { var handler = TreeNodesRendering; - if (handler != null) handler(instance, e); + handler?.Invoke(instance, e); } /// @@ -363,7 +379,7 @@ namespace Umbraco.Web.Trees internal static void OnRootNodeRendering(TreeControllerBase instance, TreeNodeRenderingEventArgs e) { var handler = RootNodeRendering; - if (handler != null) handler(instance, e); + handler?.Invoke(instance, e); } /// @@ -377,80 +393,8 @@ namespace Umbraco.Web.Trees private static void OnMenuRendering(TreeControllerBase instance, MenuRenderingEventArgs e) { var handler = MenuRendering; - if (handler != null) handler(instance, e); + handler?.Invoke(instance, e); } } - internal class TreeControllerBaseStuffForLegacy - { - private readonly string _treeAlias; - private readonly string _rootNodeDisplayName; - private readonly UrlHelper _url; - - public TreeControllerBaseStuffForLegacy(string treeAlias, string rootNodeDisplayName, UrlHelper url) - { - _treeAlias = treeAlias; - _rootNodeDisplayName = rootNodeDisplayName; - _url = url; - } - - public TreeNode GetRootNode(FormDataCollection queryStrings) - { - if (queryStrings == null) queryStrings = new FormDataCollection(""); - var node = CreateRootNode(queryStrings); - - //add the tree alias to the root - node.AdditionalData["treeAlias"] = _treeAlias; - - AddQueryStringsToAdditionalData(node, queryStrings); - - //check if the tree is searchable and add that to the meta data as well - if (this is ISearchableTree) - { - node.AdditionalData.Add("searchable", "true"); - } - - //now update all data based on some of the query strings, like if we are running in dialog mode - if (IsDialog(queryStrings)) - { - node.RoutePath = "#"; - } - - TreeControllerBase.OnRootNodeRendering(null, new TreeNodeRenderingEventArgs(node, queryStrings)); - - return node; - } - - protected virtual TreeNode CreateRootNode(FormDataCollection queryStrings) - { - var rootNodeAsString = Constants.System.Root.ToString(CultureInfo.InvariantCulture); - var currApp = queryStrings.GetValue(TreeQueryStringParameters.Application); - - var node = new TreeNode( - rootNodeAsString, - null, //this is a root node, there is no parent - _url.GetTreeUrl(GetType(), rootNodeAsString, queryStrings), - _url.GetMenuUrl(GetType(), rootNodeAsString, queryStrings)) - { - HasChildren = true, - RoutePath = currApp, - Name = _rootNodeDisplayName - }; - - return node; - } - - protected void AddQueryStringsToAdditionalData(TreeNode node, FormDataCollection queryStrings) - { - foreach (var q in queryStrings.Where(x => node.AdditionalData.ContainsKey(x.Key) == false)) - { - node.AdditionalData.Add(q.Key, q.Value); - } - } - - protected bool IsDialog(FormDataCollection queryStrings) - { - return queryStrings.GetValue(TreeQueryStringParameters.IsDialog); - } - } } diff --git a/src/Umbraco.Web/Trees/ApplicationTreeExtensions.cs b/src/Umbraco.Web/Trees/TreeControllerResolver.cs similarity index 56% rename from src/Umbraco.Web/Trees/ApplicationTreeExtensions.cs rename to src/Umbraco.Web/Trees/TreeControllerResolver.cs index 2c43cbd5dc..62cafbb5dd 100644 --- a/src/Umbraco.Web/Trees/ApplicationTreeExtensions.cs +++ b/src/Umbraco.Web/Trees/TreeControllerResolver.cs @@ -14,16 +14,25 @@ using Umbraco.Web.Models.Trees; using Umbraco.Web.Mvc; using Umbraco.Web.WebApi; using Umbraco.Core.Composing; -using Current = Umbraco.Web.Composing.Current; -using ApplicationTree = Umbraco.Core.Models.ApplicationTree; +using ApplicationTree = Umbraco.Web.Models.ContentEditing.ApplicationTree; namespace Umbraco.Web.Trees { - internal static class ApplicationTreeExtensions + public class TreeControllerResolver { - private static readonly ConcurrentDictionary TreeAttributeCache = new ConcurrentDictionary(); + private readonly TreeCollection _trees; + private readonly UmbracoApiControllerTypeCollection _apiControllers; - internal static TreeAttribute GetTreeAttribute(this Type treeControllerType) + public TreeControllerResolver(TreeCollection trees, UmbracoApiControllerTypeCollection apiControllers) + { + _trees = trees; + _apiControllers = apiControllers; + } + + private static readonly ConcurrentDictionary TreeAttributeCache = new ConcurrentDictionary(); + private static readonly ConcurrentDictionary ResolvedControllerTypes = new ConcurrentDictionary(); + + private TreeAttribute GetTreeAttribute(Type treeControllerType) { return TreeAttributeCache.GetOrAdd(treeControllerType, type => { @@ -42,25 +51,41 @@ namespace Umbraco.Web.Trees }); } - internal static TreeAttribute GetTreeAttribute(this ApplicationTree tree) + internal TreeAttribute GetTreeAttribute(ApplicationTree tree) { - return tree.GetRuntimeType().GetTreeAttribute(); + throw new NotImplementedException(); + //return ResolvedControllerTypes.GetOrAdd(tree.Alias, s => + //{ + // var controllerType = _apiControllers + // .OfType() + // .FirstOrDefault(x => x.) + //}); + + //return GetTreeAttribute(tree.GetRuntimeType()); } - internal static Attempt TryGetControllerTree(this ApplicationTree appTree) + private Type GetControllerType(ApplicationTree tree) { - //get reference to all TreeApiControllers - var controllerTrees = Current.UmbracoApiControllerTypes - .Where(TypeHelper.IsTypeAssignableFrom) - .ToArray(); + throw new NotImplementedException(); + } + - //find the one we're looking for - var foundControllerTree = controllerTrees.FirstOrDefault(x => x == appTree.GetRuntimeType()); - if (foundControllerTree == null) - { - return Attempt.Fail(new InstanceNotFoundException("Could not find tree of type " + appTree.Type + " in any loaded DLLs")); - } - return Attempt.Succeed(foundControllerTree); + internal Attempt TryGetControllerTree(ApplicationTree appTree) + { + throw new NotImplementedException(); + + ////get reference to all TreeApiControllers + //var controllerTrees = _apiControllers + // .Where(TypeHelper.IsTypeAssignableFrom) + // .ToArray(); + + ////find the one we're looking for + //var foundControllerTree = controllerTrees.FirstOrDefault(x => x == appTree.GetRuntimeType()); + //if (foundControllerTree == null) + //{ + // return Attempt.Fail(new InstanceNotFoundException("Could not find tree of type " + appTree.Type + " in any loaded DLLs")); + //} + //return Attempt.Succeed(foundControllerTree); } /// @@ -73,9 +98,9 @@ namespace Umbraco.Web.Trees /// /// This ensures that authorization filters are applied to the sub request /// - internal static async Task> TryGetRootNodeFromControllerTree(this ApplicationTree appTree, FormDataCollection formCollection, HttpControllerContext controllerContext) + internal async Task> TryGetRootNodeFromControllerTree(ApplicationTree appTree, FormDataCollection formCollection, HttpControllerContext controllerContext) { - var foundControllerTreeAttempt = appTree.TryGetControllerTree(); + var foundControllerTreeAttempt = TryGetControllerTree(appTree); if (foundControllerTreeAttempt.Success == false) { return Attempt.Fail(foundControllerTreeAttempt.Exception); @@ -110,12 +135,15 @@ namespace Umbraco.Web.Trees if (WebApiVersionCheck.WebApiVersion >= Version.Parse("5.0.0")) { - //In WebApi2, this is required to be set: - // proxiedControllerContext.RequestContext = controllerContext.RequestContext - // but we need to do this with reflection because of codebase changes between version 4/5 - //NOTE: Use TypeHelper here since the reflection is cached - var controllerContextRequestContext = TypeHelper.GetProperty(controllerContext.GetType(), "RequestContext").GetValue(controllerContext); - TypeHelper.GetProperty(proxiedControllerContext.GetType(), "RequestContext").SetValue(proxiedControllerContext, controllerContextRequestContext); + //fixme - will this 'just' work now? + proxiedControllerContext.RequestContext = controllerContext.RequestContext; + + ////In WebApi2, this is required to be set: + //// proxiedControllerContext.RequestContext = controllerContext.RequestContext + //// but we need to do this with reflection because of codebase changes between version 4/5 + ////NOTE: Use TypeHelper here since the reflection is cached + //var controllerContextRequestContext = TypeHelper.GetProperty(controllerContext.GetType(), "RequestContext").GetValue(controllerContext); + //TypeHelper.GetProperty(proxiedControllerContext.GetType(), "RequestContext").SetValue(proxiedControllerContext, controllerContextRequestContext); } instance.ControllerContext = proxiedControllerContext; @@ -123,13 +151,17 @@ namespace Umbraco.Web.Trees if (WebApiVersionCheck.WebApiVersion >= Version.Parse("5.0.0")) { - //now we can change the request context's route data to be the proxied route data - NOTE: we cannot do this directly above - // because it will detect that the request context is different throw an exception. This is a change in webapi2 and we need to set - // this with reflection due to codebase changes between version 4/5 - // instance.RequestContext.RouteData = proxiedRouteData; - //NOTE: Use TypeHelper here since the reflection is cached - var instanceRequestContext = TypeHelper.GetProperty(typeof(ApiController), "RequestContext").GetValue(instance); - TypeHelper.GetProperty(instanceRequestContext.GetType(), "RouteData").SetValue(instanceRequestContext, proxiedRouteData); + + //fixme - will this 'just' work now? + instance.RequestContext.RouteData = proxiedRouteData; + + ////now we can change the request context's route data to be the proxied route data - NOTE: we cannot do this directly above + //// because it will detect that the request context is different throw an exception. This is a change in webapi2 and we need to set + //// this with reflection due to codebase changes between version 4/5 + //// instance.RequestContext.RouteData = proxiedRouteData; + ////NOTE: Use TypeHelper here since the reflection is cached + //var instanceRequestContext = TypeHelper.GetProperty(typeof(ApiController), "RequestContext").GetValue(instance); + //TypeHelper.GetProperty(instanceRequestContext.GetType(), "RouteData").SetValue(instanceRequestContext, proxiedRouteData); } //invoke auth filters for this sub request @@ -143,13 +175,13 @@ namespace Umbraco.Web.Trees //return the root var node = instance.GetRootNode(formCollection); return node == null - ? Attempt.Fail(new InvalidOperationException("Could not return a root node for tree " + appTree.Type)) + ? Attempt.Fail(new InvalidOperationException("Could not return a root node for tree " + appTree.Alias)) : Attempt.Succeed(node); } - internal static Attempt TryLoadFromControllerTree(this ApplicationTree appTree, string id, FormDataCollection formCollection, HttpControllerContext controllerContext) + internal Attempt TryLoadFromControllerTree(ApplicationTree appTree, string id, FormDataCollection formCollection, HttpControllerContext controllerContext) { - var foundControllerTreeAttempt = appTree.TryGetControllerTree(); + var foundControllerTreeAttempt = TryGetControllerTree(appTree); if (foundControllerTreeAttempt.Success == false) return Attempt.Fail(foundControllerTreeAttempt.Exception); diff --git a/src/Umbraco.Web/UI/Pages/UmbracoEnsuredPage.cs b/src/Umbraco.Web/UI/Pages/UmbracoEnsuredPage.cs index bb9ce3c421..9e632eabc9 100644 --- a/src/Umbraco.Web/UI/Pages/UmbracoEnsuredPage.cs +++ b/src/Umbraco.Web/UI/Pages/UmbracoEnsuredPage.cs @@ -29,12 +29,14 @@ namespace Umbraco.Web.UI.Pages var treeAuth = this.GetType().GetCustomAttribute(true); if (treeAuth != null) { - var treeByAlias = Current.Services.ApplicationTreeService - .GetByAlias(treeAuth.TreeAlias); - if (treeByAlias != null) - { - CurrentApp = treeByAlias.ApplicationAlias; - } + throw new NotImplementedException(); + + //var treeByAlias = Current.Services.ApplicationTreeService + // .GetByAlias(treeAuth.TreeAlias); + //if (treeByAlias != null) + //{ + // CurrentApp = treeByAlias.ApplicationAlias; + //} } } diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index b0142771d2..f1d15e9ea6 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -166,6 +166,8 @@ + + @@ -181,6 +183,9 @@ + + + @@ -217,6 +222,7 @@ + @@ -585,9 +591,7 @@ - - @@ -890,7 +894,6 @@ - @@ -969,7 +972,7 @@ - + @@ -1236,7 +1239,7 @@ True Reference.map - + diff --git a/src/Umbraco.Web/UrlHelperExtensions.cs b/src/Umbraco.Web/UrlHelperExtensions.cs index 9b1c282aab..0a04539967 100644 --- a/src/Umbraco.Web/UrlHelperExtensions.cs +++ b/src/Umbraco.Web/UrlHelperExtensions.cs @@ -13,7 +13,6 @@ using Umbraco.Web.Composing; using Umbraco.Web.Editors; using Umbraco.Web.Mvc; using Umbraco.Web.WebApi; -using Umbraco.Web.WebServices; namespace Umbraco.Web { diff --git a/src/Umbraco.Web/WebApi/Filters/LegacyTreeAuthorizeAttribute.cs b/src/Umbraco.Web/WebApi/Filters/LegacyTreeAuthorizeAttribute.cs deleted file mode 100644 index 5d1b90a09d..0000000000 --- a/src/Umbraco.Web/WebApi/Filters/LegacyTreeAuthorizeAttribute.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Web.Http; -using System.Web.Http.Controllers; -using Umbraco.Core; -using Umbraco.Web.Composing; - -namespace Umbraco.Web.WebApi.Filters -{ - internal class LegacyTreeAuthorizeAttribute : AuthorizeAttribute - { - protected override bool IsAuthorized(HttpActionContext actionContext) - { - var httpContext = actionContext.Request.TryGetHttpContext(); - if (httpContext) - { - var treeRequest = httpContext.Result.Request.QueryString["treeType"]; - if (treeRequest.IsNullOrWhiteSpace()) return false; - - var tree = Current.Services.ApplicationTreeService.GetByAlias(treeRequest); - if (tree == null) return false; - - return UmbracoContext.Current.Security.CurrentUser != null - && UmbracoContext.Current.Security.UserHasSectionAccess(tree.ApplicationAlias, UmbracoContext.Current.Security.CurrentUser); - } - return false; - - - } - } -} diff --git a/src/Umbraco.Web/WebApi/Filters/UmbracoTreeAuthorizeAttribute.cs b/src/Umbraco.Web/WebApi/Filters/UmbracoTreeAuthorizeAttribute.cs index 7318c9d9b8..cc483db416 100644 --- a/src/Umbraco.Web/WebApi/Filters/UmbracoTreeAuthorizeAttribute.cs +++ b/src/Umbraco.Web/WebApi/Filters/UmbracoTreeAuthorizeAttribute.cs @@ -1,4 +1,5 @@ -using System.Linq; +using System; +using System.Linq; using System.Web.Http.Controllers; using System.Web.Http.Filters; using Umbraco.Core; @@ -40,16 +41,18 @@ namespace Umbraco.Web.WebApi.Filters return true; } - var apps = _treeAliases.Select(x => Current.Services.ApplicationTreeService - .GetByAlias(x)) - .WhereNotNull() - .Select(x => x.ApplicationAlias) - .Distinct() - .ToArray(); + throw new NotImplementedException(); - return Current.UmbracoContext.Security.CurrentUser != null - && apps.Any(app => Current.UmbracoContext.Security.UserHasSectionAccess( - app, Current.UmbracoContext.Security.CurrentUser)); + //var apps = _treeAliases.Select(x => Current.Services.ApplicationTreeService + // .GetByAlias(x)) + // .WhereNotNull() + // .Select(x => x.ApplicationAlias) + // .Distinct() + // .ToArray(); + + //return Current.UmbracoContext.Security.CurrentUser != null + // && apps.Any(app => Current.UmbracoContext.Security.UserHasSectionAccess( + // app, Current.UmbracoContext.Security.CurrentUser)); } } } diff --git a/src/Umbraco.Web/WebApi/UmbracoApiController.cs b/src/Umbraco.Web/WebApi/UmbracoApiController.cs index 3db3610cc2..586160cfa0 100644 --- a/src/Umbraco.Web/WebApi/UmbracoApiController.cs +++ b/src/Umbraco.Web/WebApi/UmbracoApiController.cs @@ -23,8 +23,8 @@ namespace Umbraco.Web.WebApi /// /// Initialize a new instance of the with all its dependencies. /// - protected UmbracoApiController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) - : base(globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) + protected UmbracoApiController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) + : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, runtimeState) { } } } diff --git a/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs b/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs index 21b88cc919..106ef60e0b 100644 --- a/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs +++ b/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs @@ -21,7 +21,6 @@ namespace Umbraco.Web.WebApi [FeatureAuthorize] public abstract class UmbracoApiControllerBase : ApiController { - private readonly IUmbracoContextAccessor _umbracoContextAccessor; private UmbracoHelper _umbracoHelper; // note: all Umbraco controllers have two constructors: one with all dependencies, which should be used, @@ -36,7 +35,7 @@ namespace Umbraco.Web.WebApi protected UmbracoApiControllerBase() : this( Current.Factory.GetInstance(), - Current.Factory.GetInstance(), + Current.Factory.GetInstance().UmbracoContext, Current.Factory.GetInstance(), Current.Factory.GetInstance(), Current.Factory.GetInstance(), @@ -48,15 +47,15 @@ namespace Umbraco.Web.WebApi /// /// Initializes a new instance of the class with all its dependencies. /// - protected UmbracoApiControllerBase(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) + protected UmbracoApiControllerBase(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) { GlobalSettings = globalSettings; - _umbracoContextAccessor = umbracoContextAccessor; SqlContext = sqlContext; Services = services; ApplicationCache = applicationCache; Logger = logger; RuntimeState = runtimeState; + UmbracoContext = umbracoContext; } /// @@ -73,8 +72,8 @@ namespace Umbraco.Web.WebApi /// /// Gets the Umbraco context. /// - public virtual UmbracoContext UmbracoContext => _umbracoContextAccessor.UmbracoContext; - + public virtual UmbracoContext UmbracoContext { get; } + /// /// Gets the sql context. /// diff --git a/src/Umbraco.Web/WebApi/UmbracoApiControllerTypeCollection.cs b/src/Umbraco.Web/WebApi/UmbracoApiControllerTypeCollection.cs index cdb1aa2f51..d84ab3fe4a 100644 --- a/src/Umbraco.Web/WebApi/UmbracoApiControllerTypeCollection.cs +++ b/src/Umbraco.Web/WebApi/UmbracoApiControllerTypeCollection.cs @@ -8,6 +8,8 @@ namespace Umbraco.Web.WebApi // which we are not doing at the moment // we can inherit from BuilderCollectionBase and just be enumerable + //fixme: this should be LazyCollectionBuilderBase ? + public class UmbracoApiControllerTypeCollection : BuilderCollectionBase { public UmbracoApiControllerTypeCollection(IEnumerable items) diff --git a/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs b/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs index 4ae9c00a47..e8c0a3c674 100644 --- a/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs +++ b/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs @@ -40,8 +40,8 @@ namespace Umbraco.Web.WebApi /// /// Initializes a new instance of the class with all its dependencies. /// - protected UmbracoAuthorizedApiController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) - : base(globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) + protected UmbracoAuthorizedApiController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) + : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, runtimeState) { } /// diff --git a/src/Umbraco.Web/_Legacy/PackageActions/addApplication.cs b/src/Umbraco.Web/_Legacy/PackageActions/addApplication.cs index 26116820e6..c6d5ba30d9 100644 --- a/src/Umbraco.Web/_Legacy/PackageActions/addApplication.cs +++ b/src/Umbraco.Web/_Legacy/PackageActions/addApplication.cs @@ -1,61 +1,61 @@ -using System; -using System.Xml; -using System.Xml.Linq; -using Umbraco.Core; -using Umbraco.Core._Legacy.PackageActions; -using Umbraco.Web.Composing; +//using System; +//using System.Xml; +//using System.Xml.Linq; +//using Umbraco.Core; +//using Umbraco.Core._Legacy.PackageActions; +//using Umbraco.Web.Composing; -namespace Umbraco.Web._Legacy.PackageActions -{ - /// - /// This class implements the IPackageAction Interface, used to execute code when packages are installed. - /// All IPackageActions only takes a PackageName and a XmlNode as input, and executes based on the data in the xmlnode. - /// - public class AddApplication : IPackageAction - { +//namespace Umbraco.Web._Legacy.PackageActions +//{ +// /// +// /// This class implements the IPackageAction Interface, used to execute code when packages are installed. +// /// All IPackageActions only takes a PackageName and a XmlNode as input, and executes based on the data in the xmlnode. +// /// +// public class AddApplication : IPackageAction +// { - #region IPackageAction Members +// #region IPackageAction Members - /// - /// Installs a new application in umbraco. - /// - /// Name of the package. - /// The XML data. - /// - /// - /// - /// true if successfull - public bool Execute(string packageName, XElement xmlData) - { - string name = xmlData.AttributeValue("appName"); - string alias = xmlData.AttributeValue("appAlias"); - string icon = xmlData.AttributeValue("appIcon"); +// /// +// /// Installs a new application in umbraco. +// /// +// /// Name of the package. +// /// The XML data. +// /// +// /// +// /// +// /// true if successfull +// public bool Execute(string packageName, XElement xmlData) +// { +// string name = xmlData.AttributeValue("appName"); +// string alias = xmlData.AttributeValue("appAlias"); +// string icon = xmlData.AttributeValue("appIcon"); - Current.Services.SectionService.MakeNew(name, alias, icon); +// Current.Services.SectionService.MakeNew(name, alias, icon); - return true; - } +// return true; +// } - public bool Undo(string packageName, XElement xmlData) - { - string alias = xmlData.AttributeValue("appAlias"); - var section = Current.Services.SectionService.GetByAlias(alias); - if (section != null) - { - Current.Services.SectionService.DeleteSection(section); - } - return true; - } - /// - /// Action alias. - /// - /// - public string Alias() - { - return "addApplication"; - } +// public bool Undo(string packageName, XElement xmlData) +// { +// string alias = xmlData.AttributeValue("appAlias"); +// var section = Current.Services.SectionService.GetByAlias(alias); +// if (section != null) +// { +// Current.Services.SectionService.DeleteSection(section); +// } +// return true; +// } +// /// +// /// Action alias. +// /// +// /// +// public string Alias() +// { +// return "addApplication"; +// } - #endregion +// #endregion - } -} +// } +//} From cfe1b17eecc5a06b56530610d9e04158033e66a4 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 17 Jan 2019 16:40:11 +1100 Subject: [PATCH 400/469] Gets trees and sections loading now in a much more simplified way without any xml, now to cleanup --- src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 2 +- src/Umbraco.Web/Composing/Current.cs | 7 + .../Editors/BackOfficeServerVariables.cs | 2 +- src/Umbraco.Web/Editors/EntityController.cs | 6 +- src/Umbraco.Web/Editors/SectionController.cs | 8 +- .../Models/ContentEditing/ApplicationTree.cs | 177 --------------- .../Mvc/SurfaceControllerTypeCollection.cs | 4 +- src/Umbraco.Web/Runtime/WebRuntimeComposer.cs | 13 +- .../Search/SearchableTreeCollection.cs | 8 +- .../Services/IApplicationTreeService.cs | 153 ------------- src/Umbraco.Web/Services/ISectionService.cs | 89 +------- src/Umbraco.Web/Services/ITreeService.cs | 49 +++++ ...plicationTreeService.cs => TreeService.cs} | 40 ++-- src/Umbraco.Web/Trees/ApplicationTree.cs | 69 ++++++ .../Trees/ApplicationTreeController.cs | 173 +++++++++++---- src/Umbraco.Web/Trees/ITree.cs | 31 +++ src/Umbraco.Web/Trees/TreeAttribute.cs | 35 +-- src/Umbraco.Web/Trees/TreeCollection.cs | 21 +- src/Umbraco.Web/Trees/TreeController.cs | 55 +++-- src/Umbraco.Web/Trees/TreeControllerBase.cs | 14 +- .../Trees/TreeControllerResolver.cs | 203 ------------------ .../Trees/UserPermissionsTreeController.cs | 52 ----- src/Umbraco.Web/Umbraco.Web.csproj | 10 +- .../Filters/UmbracoTreeAuthorizeAttribute.cs | 20 +- src/Umbraco.Web/WebApi/MvcVersionCheck.cs | 10 - .../UmbracoApiControllerTypeCollection.cs | 2 - 26 files changed, 425 insertions(+), 828 deletions(-) delete mode 100644 src/Umbraco.Web/Models/ContentEditing/ApplicationTree.cs delete mode 100644 src/Umbraco.Web/Services/IApplicationTreeService.cs create mode 100644 src/Umbraco.Web/Services/ITreeService.cs rename src/Umbraco.Web/Services/{ApplicationTreeService.cs => TreeService.cs} (95%) create mode 100644 src/Umbraco.Web/Trees/ApplicationTree.cs create mode 100644 src/Umbraco.Web/Trees/ITree.cs delete mode 100644 src/Umbraco.Web/Trees/TreeControllerResolver.cs delete mode 100644 src/Umbraco.Web/Trees/UserPermissionsTreeController.cs delete mode 100644 src/Umbraco.Web/WebApi/MvcVersionCheck.cs diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index a79531af74..0a0999f2dc 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -342,7 +342,7 @@ namespace Umbraco.Tests.Testing Composition.ComposeServices(); // composition root is doing weird things, fix - Composition.RegisterUnique(); + Composition.RegisterUnique(); Composition.RegisterUnique(); // somehow property editor ends up wanting this diff --git a/src/Umbraco.Web/Composing/Current.cs b/src/Umbraco.Web/Composing/Current.cs index 1e8f3d17f7..d887720063 100644 --- a/src/Umbraco.Web/Composing/Current.cs +++ b/src/Umbraco.Web/Composing/Current.cs @@ -25,6 +25,7 @@ using Umbraco.Web.HealthCheck; using Umbraco.Web.Mvc; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; +using Umbraco.Web.Services; using Umbraco.Web.WebApi; using CoreCurrent = Umbraco.Core.Composing.Current; @@ -135,6 +136,12 @@ namespace Umbraco.Web.Composing internal static IPublishedSnapshotService PublishedSnapshotService => Factory.GetInstance(); + public static ITreeService TreeService + => Factory.GetInstance(); + + public static ISectionService SectionService + => Factory.GetInstance(); + #endregion #region Web Constants diff --git a/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs b/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs index 65ab27d76a..1525dd5808 100644 --- a/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs +++ b/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs @@ -408,7 +408,7 @@ namespace Umbraco.Web.Editors let pluginAttr = p.attributes.OfType().Single() select new Dictionary { - {"alias", treeAttr.Alias}, {"packageFolder", pluginAttr.AreaName} + {"alias", treeAttr.TreeAlias}, {"packageFolder", pluginAttr.AreaName} }).ToArray(); } diff --git a/src/Umbraco.Web/Editors/EntityController.cs b/src/Umbraco.Web/Editors/EntityController.cs index c8368d11b0..ca1a6a12bb 100644 --- a/src/Umbraco.Web/Editors/EntityController.cs +++ b/src/Umbraco.Web/Editors/EntityController.cs @@ -42,10 +42,10 @@ namespace Umbraco.Web.Editors [PluginController("UmbracoApi")] public class EntityController : UmbracoAuthorizedJsonController { - private readonly IApplicationTreeService _treeService; + private readonly ITreeService _treeService; public EntityController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState, - IApplicationTreeService treeService) + ITreeService treeService) : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, runtimeState) { _treeService = treeService; @@ -148,7 +148,7 @@ namespace Umbraco.Web.Editors var searchableTreeAttribute = searchableTree.Value.SearchableTree.GetType().GetCustomAttribute(false); - result[tree.GetRootNodeDisplayName(Services.TextService)] = new TreeSearchResult + result[ApplicationTree.GetRootNodeDisplayName(tree, Services.TextService)] = new TreeSearchResult { Results = searchableTree.Value.SearchableTree.Search(query, 200, 0, out var total), TreeAlias = searchableTree.Key, diff --git a/src/Umbraco.Web/Editors/SectionController.cs b/src/Umbraco.Web/Editors/SectionController.cs index 7b484b09b1..d68f062f61 100644 --- a/src/Umbraco.Web/Editors/SectionController.cs +++ b/src/Umbraco.Web/Editors/SectionController.cs @@ -24,16 +24,14 @@ namespace Umbraco.Web.Editors { private readonly Dashboards _dashboards; private readonly ISectionService _sectionService; - private readonly TreeControllerResolver _treeControllerResolver; - private readonly IApplicationTreeService _treeService; + private readonly ITreeService _treeService; public SectionController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState, - Dashboards dashboards, ISectionService sectionService, TreeControllerResolver treeControllerResolver, IApplicationTreeService treeService) + Dashboards dashboards, ISectionService sectionService, ITreeService treeService) : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, runtimeState) { _dashboards = dashboards; _sectionService = sectionService; - _treeControllerResolver = treeControllerResolver; _treeService = treeService; } @@ -45,7 +43,7 @@ namespace Umbraco.Web.Editors // this is a bit nasty since we'll be proxying via the app tree controller but we sort of have to do that // since tree's by nature are controllers and require request contextual data - var appTreeController = new ApplicationTreeController(GlobalSettings, UmbracoContext, SqlContext, Services, ApplicationCache, Logger, RuntimeState, _treeControllerResolver, _treeService) + var appTreeController = new ApplicationTreeController(GlobalSettings, UmbracoContext, SqlContext, Services, ApplicationCache, Logger, RuntimeState, _treeService) { ControllerContext = ControllerContext }; diff --git a/src/Umbraco.Web/Models/ContentEditing/ApplicationTree.cs b/src/Umbraco.Web/Models/ContentEditing/ApplicationTree.cs deleted file mode 100644 index e9befb0e27..0000000000 --- a/src/Umbraco.Web/Models/ContentEditing/ApplicationTree.cs +++ /dev/null @@ -1,177 +0,0 @@ -using System; -using System.Diagnostics; -using Umbraco.Core.Services; - -namespace Umbraco.Web.Models.ContentEditing -{ - [DebuggerDisplay("Tree - {Alias} ({ApplicationAlias})")] - public class ApplicationTree - { - //private static readonly ConcurrentDictionary ResolvedTypes = new ConcurrentDictionary(); - - ///// - ///// Initializes a new instance of the class. - ///// - //public ApplicationTree() { } - - ///// - ///// Initializes a new instance of the class. - ///// - ///// if set to true [initialize]. - ///// The sort order. - ///// The application alias. - ///// The tree alias. - ///// The tree title. - ///// The icon closed. - ///// The icon opened. - ///// The tree type. - //public ApplicationTree(bool initialize, int sortOrder, string applicationAlias, string alias, string title, string iconClosed, string iconOpened, string type) - //{ - // //Initialize = initialize; - // SortOrder = sortOrder; - // ApplicationAlias = applicationAlias; - // Alias = alias; - // Title = title; - // IconClosed = iconClosed; - // IconOpened = iconOpened; - // Type = type; - - //} - - public ApplicationTree(int sortOrder, string applicationAlias, string alias, string title) - { - SortOrder = sortOrder; - ApplicationAlias = applicationAlias; - Alias = alias; - Title = title; - } - - ///// - ///// Gets or sets a value indicating whether this should initialize. - ///// - ///// true if initialize; otherwise, false. - //public bool Initialize { get; set; } - - /// - /// Gets or sets the sort order. - /// - /// The sort order. - public int SortOrder { get; set; } - - /// - /// Gets the application alias. - /// - /// The application alias. - public string ApplicationAlias { get; } - - /// - /// Gets the tree alias. - /// - /// The alias. - public string Alias { get; } - - /// - /// Gets or sets the tree title (fallback if the tree alias isn't localized) - /// - /// The title. - public string Title { get; set; } - - ///// - ///// Gets or sets the icon closed. - ///// - ///// The icon closed. - //public string IconClosed { get; set; } - - ///// - ///// Gets or sets the icon opened. - ///// - ///// The icon opened. - //public string IconOpened { get; set; } - - ///// - ///// Gets or sets the tree type assembly name. - ///// - ///// The type. - //public string Type { get; set; } - - /// - /// Returns the localized root node display name - /// - /// - /// - public string GetRootNodeDisplayName(ILocalizedTextService textService) - { - var label = $"[{Alias}]"; - - // try to look up a the localized tree header matching the tree alias - var localizedLabel = textService.Localize("treeHeaders/" + Alias); - - // if the localizedLabel returns [alias] then return the title if it's defined - if (localizedLabel != null && localizedLabel.Equals(label, StringComparison.InvariantCultureIgnoreCase)) - { - if (string.IsNullOrEmpty(Title) == false) - label = Title; - } - else - { - // the localizedLabel translated into something that's not just [alias], so use the translation - label = localizedLabel; - } - - return label; - } - - //private Type _runtimeType; - - ///// - ///// Returns the CLR type based on it's assembly name stored in the config - ///// - ///// - //public Type GetRuntimeType() - //{ - // return _runtimeType ?? (_runtimeType = System.Type.GetType(Type)); - //} - - ///// - ///// Used to try to get and cache the tree type - ///// - ///// - ///// - //internal static Type TryGetType(string type) - //{ - // try - // { - // return ResolvedTypes.GetOrAdd(type, s => - // { - // var result = System.Type.GetType(type); - // if (result != null) - // { - // return result; - // } - - // //we need to implement a bit of a hack here due to some trees being renamed and backwards compat - // var parts = type.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); - // if (parts.Length != 2) - // throw new InvalidOperationException("Could not resolve type"); - // if (parts[1].Trim() != "Umbraco.Web" || parts[0].StartsWith("Umbraco.Web.Trees") == false || parts[0].EndsWith("Controller")) - // throw new InvalidOperationException("Could not resolve type"); - - // //if it's one of our controllers but it's not suffixed with "Controller" then add it and try again - // var tempType = parts[0] + "Controller, Umbraco.Web"; - - // result = System.Type.GetType(tempType); - // if (result != null) - // return result; - - // throw new InvalidOperationException("Could not resolve type"); - // }); - // } - // catch (InvalidOperationException) - // { - // //swallow, this is our own exception, couldn't find the type - // // fixme bad use of exceptions here! - // return null; - // } - //} - } -} diff --git a/src/Umbraco.Web/Mvc/SurfaceControllerTypeCollection.cs b/src/Umbraco.Web/Mvc/SurfaceControllerTypeCollection.cs index eef6ab1ca2..d9577417cc 100644 --- a/src/Umbraco.Web/Mvc/SurfaceControllerTypeCollection.cs +++ b/src/Umbraco.Web/Mvc/SurfaceControllerTypeCollection.cs @@ -7,9 +7,7 @@ namespace Umbraco.Web.Mvc // unless we want to modify the content of the collection // which we are not doing at the moment // we can inherit from BuilderCollectionBase and just be enumerable - - //fixme: this should be LazyCollectionBuilderBase ? - + public class SurfaceControllerTypeCollection : BuilderCollectionBase { public SurfaceControllerTypeCollection(IEnumerable items) diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs b/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs index 0ef9adddb7..047d080a88 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs @@ -95,7 +95,7 @@ namespace Umbraco.Web.Runtime // replace some services composition.RegisterUnique(); composition.RegisterUnique(); - composition.RegisterUnique(); + composition.RegisterUnique(); composition.RegisterUnique(); composition.RegisterUnique(factory => ExamineManager.Instance); @@ -125,9 +125,11 @@ namespace Umbraco.Web.Runtime composition.WithCollectionBuilder() .Add(() => composition.TypeLoader.GetTypes()); + //we need to eagerly scan controller types since they will need to be routed var surfaceControllerTypes = new SurfaceControllerTypeCollection(composition.TypeLoader.GetSurfaceControllers()); composition.RegisterUnique(surfaceControllerTypes); + //we need to eagerly scan controller types since they will need to be routed var umbracoApiControllerTypes = new UmbracoApiControllerTypeCollection(composition.TypeLoader.GetUmbracoApiControllers()); composition.RegisterUnique(umbracoApiControllerTypes); @@ -198,8 +200,13 @@ namespace Umbraco.Web.Runtime .Add(() => composition.TypeLoader.GetTypes()); // register back office trees - composition.WithCollectionBuilder() - .Add(() => composition.TypeLoader.GetTypes()); + foreach (var treeControllerType in umbracoApiControllerTypes) + { + var attribute = treeControllerType.GetCustomAttribute(false); + if (attribute == null) continue; + var tree = new ApplicationTree(attribute.SortOrder, attribute.ApplicationAlias, attribute.TreeAlias, attribute.TreeTitle, treeControllerType, attribute.IsSingleNodeTree); + composition.WithCollectionBuilder().AddTree(tree); + } } } } diff --git a/src/Umbraco.Web/Search/SearchableTreeCollection.cs b/src/Umbraco.Web/Search/SearchableTreeCollection.cs index 2b1baa5194..032782b466 100644 --- a/src/Umbraco.Web/Search/SearchableTreeCollection.cs +++ b/src/Umbraco.Web/Search/SearchableTreeCollection.cs @@ -14,13 +14,13 @@ namespace Umbraco.Web.Search { private readonly Dictionary _dictionary; - public SearchableTreeCollection(IEnumerable items, IApplicationTreeService treeService) + public SearchableTreeCollection(IEnumerable items, ITreeService treeService) : base(items) { _dictionary = CreateDictionary(treeService); } - private Dictionary CreateDictionary(IApplicationTreeService treeService) + private Dictionary CreateDictionary(ITreeService treeService) { var appTrees = treeService.GetAll() .OrderBy(x => x.SortOrder) @@ -29,10 +29,10 @@ namespace Umbraco.Web.Search var searchableTrees = this.ToArray(); foreach (var appTree in appTrees) { - var found = searchableTrees.FirstOrDefault(x => x.TreeAlias.InvariantEquals(appTree.Alias)); + var found = searchableTrees.FirstOrDefault(x => x.TreeAlias.InvariantEquals(appTree.TreeAlias)); if (found != null) { - dictionary[found.TreeAlias] = new SearchableApplicationTree(appTree.ApplicationAlias, appTree.Alias, found); + dictionary[found.TreeAlias] = new SearchableApplicationTree(appTree.ApplicationAlias, appTree.TreeAlias, found); } } return dictionary; diff --git a/src/Umbraco.Web/Services/IApplicationTreeService.cs b/src/Umbraco.Web/Services/IApplicationTreeService.cs deleted file mode 100644 index 1fd7bc939a..0000000000 --- a/src/Umbraco.Web/Services/IApplicationTreeService.cs +++ /dev/null @@ -1,153 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Umbraco.Core.Models; -using Umbraco.Core.Models.ContentEditing; -using Umbraco.Web.Models.ContentEditing; - -namespace Umbraco.Web.Services -{ - public interface IApplicationTreeService - { - ///// - ///// Creates a new application tree. - ///// - ///// if set to true [initialize]. - ///// The sort order. - ///// The application alias. - ///// The alias. - ///// The title. - ///// The icon closed. - ///// The icon opened. - ///// The type. - //void MakeNew(bool initialize, int sortOrder, string applicationAlias, string alias, string title, string iconClosed, string iconOpened, string type); - - ///// - ///// Saves this instance. - ///// - //void SaveTree(ApplicationTree tree); - - ///// - ///// Deletes this instance. - ///// - //void DeleteTree(ApplicationTree tree); - - /// - /// Gets an ApplicationTree by it's tree alias. - /// - /// The tree alias. - /// An ApplicationTree instance - ApplicationTree GetByAlias(string treeAlias); - - /// - /// Gets all applicationTrees registered in umbraco from the umbracoAppTree table.. - /// - /// Returns a ApplicationTree Array - IEnumerable GetAll(); - - /// - /// Gets the application tree for the applcation with the specified alias - /// - /// The application alias. - /// Returns a ApplicationTree Array - IEnumerable GetApplicationTrees(string applicationAlias); - - ///// - ///// Gets the application tree for the applcation with the specified alias - ///// - ///// The application alias. - ///// - ///// Returns a ApplicationTree Array - //IEnumerable GetApplicationTrees(string applicationAlias, bool onlyInitialized); - - /// - /// Gets the grouped application trees for the application with the specified alias - /// - /// - /// - IDictionary> GetGroupedApplicationTrees(string applicationAlias); - } - - /// - /// Purely used to allow a service context to create the default services - /// - internal class EmptyApplicationTreeService : IApplicationTreeService - { - ///// - ///// Creates a new application tree. - ///// - ///// if set to true [initialize]. - ///// The sort order. - ///// The application alias. - ///// The alias. - ///// The title. - ///// The icon closed. - ///// The icon opened. - ///// The type. - //public void MakeNew(bool initialize, int sortOrder, string applicationAlias, string alias, string title, string iconClosed, string iconOpened, string type) - //{ - // throw new System.NotImplementedException(); - //} - - ///// - ///// Saves this instance. - ///// - //public void SaveTree(ApplicationTree tree) - //{ - // throw new System.NotImplementedException(); - //} - - ///// - ///// Deletes this instance. - ///// - //public void DeleteTree(ApplicationTree tree) - //{ - // throw new System.NotImplementedException(); - //} - - /// - /// Gets an ApplicationTree by it's tree alias. - /// - /// The tree alias. - /// An ApplicationTree instance - public ApplicationTree GetByAlias(string treeAlias) - { - throw new System.NotImplementedException(); - } - - /// - /// Gets all applicationTrees registered in umbraco from the umbracoAppTree table.. - /// - /// Returns a ApplicationTree Array - public IEnumerable GetAll() - { - throw new System.NotImplementedException(); - } - - public IDictionary> GetGroupedApplicationTrees(string applicationAlias) - { - throw new System.NotImplementedException(); - } - - /// - /// Gets the application tree for the applcation with the specified alias - /// - /// The application alias. - /// Returns a ApplicationTree Array - public IEnumerable GetApplicationTrees(string applicationAlias) - { - throw new System.NotImplementedException(); - } - - /// - /// Gets the application tree for the applcation with the specified alias - /// - /// The application alias. - /// - /// Returns a ApplicationTree Array - public IEnumerable GetApplicationTrees(string applicationAlias, bool onlyInitialized) - { - throw new System.NotImplementedException(); - } - } -} diff --git a/src/Umbraco.Web/Services/ISectionService.cs b/src/Umbraco.Web/Services/ISectionService.cs index 560805634f..c325020cf1 100644 --- a/src/Umbraco.Web/Services/ISectionService.cs +++ b/src/Umbraco.Web/Services/ISectionService.cs @@ -25,92 +25,7 @@ namespace Umbraco.Web.Services /// The application alias. /// IBackOfficeSection GetByAlias(string appAlias); - - ///// - ///// Creates a new applcation if no application with the specified alias is found. - ///// - ///// The application name. - ///// The application alias. - ///// The application icon, which has to be located in umbraco/images/tray folder. - //void MakeNew(string name, string alias, string icon); - - ///// - ///// Makes the new. - ///// - ///// The name. - ///// The alias. - ///// The icon. - ///// The sort order. - //void MakeNew(string name, string alias, string icon, int sortOrder); - - ///// - ///// Deletes the section - ///// - //void DeleteSection(Section section); - } - - /// - /// Purely used to allow a service context to create the default services - /// - internal class EmptySectionService : ISectionService - { - /// - /// The cache storage for all applications - /// - public IEnumerable GetSections() - { - throw new System.NotImplementedException(); - } - - /// - /// Get the user's allowed sections - /// - /// - /// - public IEnumerable GetAllowedSections(int userId) - { - throw new System.NotImplementedException(); - } - - /// - /// Gets the application by its alias. - /// - /// The application alias. - /// - public IBackOfficeSection GetByAlias(string appAlias) - { - throw new System.NotImplementedException(); - } - - ///// - ///// Creates a new applcation if no application with the specified alias is found. - ///// - ///// The application name. - ///// The application alias. - ///// The application icon, which has to be located in umbraco/images/tray folder. - //public void MakeNew(string name, string alias, string icon) - //{ - // throw new System.NotImplementedException(); - //} - - ///// - ///// Makes the new. - ///// - ///// The name. - ///// The alias. - ///// The icon. - ///// The sort order. - //public void MakeNew(string name, string alias, string icon, int sortOrder) - //{ - // throw new System.NotImplementedException(); - //} - - ///// - ///// Deletes the section - ///// - //public void DeleteSection(IBackOfficeSection section) - //{ - // throw new System.NotImplementedException(); - //} + } + } diff --git a/src/Umbraco.Web/Services/ITreeService.cs b/src/Umbraco.Web/Services/ITreeService.cs new file mode 100644 index 0000000000..ce734cc5e4 --- /dev/null +++ b/src/Umbraco.Web/Services/ITreeService.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Umbraco.Core.Models; +using Umbraco.Core.Models.ContentEditing; +using Umbraco.Web.Models.ContentEditing; +using Umbraco.Web.Trees; + +namespace Umbraco.Web.Services +{ + public interface ITreeService + { + /// + /// Gets an ApplicationTree by it's tree alias. + /// + /// The tree alias. + /// An ApplicationTree instance + ApplicationTree GetByAlias(string treeAlias); + + /// + /// Gets all applicationTrees registered in umbraco from the umbracoAppTree table.. + /// + /// Returns a ApplicationTree Array + IEnumerable GetAll(); + + /// + /// Gets the application tree for the applcation with the specified alias + /// + /// The application alias. + /// Returns a ApplicationTree Array + IEnumerable GetApplicationTrees(string applicationAlias); + + ///// + ///// Gets the application tree for the applcation with the specified alias + ///// + ///// The application alias. + ///// + ///// Returns a ApplicationTree Array + //IEnumerable GetApplicationTrees(string applicationAlias, bool onlyInitialized); + + /// + /// Gets the grouped application trees for the application with the specified alias + /// + /// + /// + IDictionary> GetGroupedApplicationTrees(string applicationAlias); + } + +} diff --git a/src/Umbraco.Web/Services/ApplicationTreeService.cs b/src/Umbraco.Web/Services/TreeService.cs similarity index 95% rename from src/Umbraco.Web/Services/ApplicationTreeService.cs rename to src/Umbraco.Web/Services/TreeService.cs index 72b26e26d3..cf010f1480 100644 --- a/src/Umbraco.Web/Services/ApplicationTreeService.cs +++ b/src/Umbraco.Web/Services/TreeService.cs @@ -18,18 +18,18 @@ using Umbraco.Web.Trees; namespace Umbraco.Web.Services { - internal class ApplicationTreeService : IApplicationTreeService + internal class TreeService : ITreeService { private readonly ILogger _logger; private readonly TreeCollection _treeCollection; private static readonly object Locker = new object(); private readonly Lazy>> _groupedTrees; - public ApplicationTreeService(ILogger logger, TreeCollection treeCollection) + public TreeService(ILogger logger, TreeCollection treeCollection) { _logger = logger; _treeCollection = treeCollection; - //_groupedTrees = new Lazy>>(InitGroupedTrees); + _groupedTrees = new Lazy>>(InitGroupedTrees); } ///// @@ -233,7 +233,7 @@ namespace Umbraco.Web.Services //} /// - public ApplicationTree GetByAlias(string treeAlias) => _treeCollection.FirstOrDefault(t => t.Alias == treeAlias); + public ApplicationTree GetByAlias(string treeAlias) => _treeCollection.FirstOrDefault(t => t.TreeAlias == treeAlias); /// public IEnumerable GetAll() => _treeCollection; @@ -273,7 +273,7 @@ namespace Umbraco.Web.Services { foreach(var treeAliasInGroup in treeGroup) { - if (tree.Alias == treeAliasInGroup) + if (tree.TreeAlias == treeAliasInGroup) { if (resultGroup == null) resultGroup = new List(); resultGroup.Add(tree); @@ -286,21 +286,21 @@ namespace Umbraco.Web.Services return result; } - ///// - ///// Creates a group of all tree groups and their tree aliases - ///// - ///// - ///// - ///// Used to initialize the field - ///// - //private IReadOnlyCollection> InitGroupedTrees() - //{ - // var result = GetAll() - // .Select(x => (treeAlias: x.Alias, treeGroup: x.GetRuntimeType().GetCustomAttribute(false)?.TreeGroup)) - // .GroupBy(x => x.treeGroup, x => x.treeAlias) - // .ToList(); - // return result; - //} + /// + /// Creates a group of all tree groups and their tree aliases + /// + /// + /// + /// Used to initialize the field + /// + private IReadOnlyCollection> InitGroupedTrees() + { + var result = GetAll() + .Select(x => (treeAlias: x.TreeAlias, treeGroup: x.TreeControllerType.GetCustomAttribute(false)?.TreeGroup)) + .GroupBy(x => x.treeGroup, x => x.treeAlias) + .ToList(); + return result; + } ///// ///// Loads in the xml structure from disk if one is found, otherwise loads in an empty xml structure, calls the diff --git a/src/Umbraco.Web/Trees/ApplicationTree.cs b/src/Umbraco.Web/Trees/ApplicationTree.cs new file mode 100644 index 0000000000..5ed9847be3 --- /dev/null +++ b/src/Umbraco.Web/Trees/ApplicationTree.cs @@ -0,0 +1,69 @@ +using System; +using System.Diagnostics; +using Umbraco.Core.Services; +using Umbraco.Web.Models.Trees; + +namespace Umbraco.Web.Trees +{ + [DebuggerDisplay("Tree - {TreeAlias} ({ApplicationAlias})")] + public class ApplicationTree : ITree + { + public ApplicationTree(int sortOrder, string applicationAlias, string alias, string title, Type treeControllerType, bool isSingleNodeTree) + { + SortOrder = sortOrder; + ApplicationAlias = applicationAlias; + TreeAlias = alias; + TreeTitle = title; + TreeControllerType = treeControllerType; + IsSingleNodeTree = isSingleNodeTree; + } + + /// + /// + /// Gets or sets the sort order. + /// + public int SortOrder { get; set; } + + /// + /// Gets the application alias. + /// + public string ApplicationAlias { get; set; } + + /// + public string TreeAlias { get; } + + /// + /// + /// Gets or sets the tree title (fallback if the tree alias isn't localized) + /// + /// The title. + public string TreeTitle { get; set; } + + public bool IsSingleNodeTree { get; } + + public Type TreeControllerType { get; } + + public static string GetRootNodeDisplayName(ITree tree, ILocalizedTextService textService) + { + var label = $"[{tree.TreeAlias}]"; + + // try to look up a the localized tree header matching the tree alias + var localizedLabel = textService.Localize("treeHeaders/" + tree.TreeAlias); + + // if the localizedLabel returns [alias] then return the title if it's defined + if (localizedLabel != null && localizedLabel.Equals(label, StringComparison.InvariantCultureIgnoreCase)) + { + if (string.IsNullOrEmpty(tree.TreeTitle) == false) + label = tree.TreeTitle; + } + else + { + // the localizedLabel translated into something that's not just [alias], so use the translation + label = localizedLabel; + } + + return label; + } + + } +} diff --git a/src/Umbraco.Web/Trees/ApplicationTreeController.cs b/src/Umbraco.Web/Trees/ApplicationTreeController.cs index 7e7c77d607..0e405ca3f3 100644 --- a/src/Umbraco.Web/Trees/ApplicationTreeController.cs +++ b/src/Umbraco.Web/Trees/ApplicationTreeController.cs @@ -3,9 +3,13 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Net; +using System.Net.Http; using System.Net.Http.Formatting; using System.Threading.Tasks; using System.Web.Http; +using System.Web.Http.Controllers; +using System.Web.Http.Routing; +using System.Web.Mvc; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; @@ -24,19 +28,20 @@ using Constants = Umbraco.Core.Constants; namespace Umbraco.Web.Trees { + /// + /// Used to return tree root nodes + /// [AngularJsonOnlyConfiguration] [PluginController("UmbracoTrees")] public class ApplicationTreeController : UmbracoAuthorizedApiController { - private readonly TreeControllerResolver _treeControllerResolver; - private readonly IApplicationTreeService _treeService; + private readonly ITreeService _treeService; public ApplicationTreeController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, - IRuntimeState runtimeState, TreeControllerResolver treeControllerResolver, IApplicationTreeService treeService) + IRuntimeState runtimeState, ITreeService treeService) : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, runtimeState) { - _treeControllerResolver = treeControllerResolver; _treeService = treeService; } @@ -46,10 +51,9 @@ namespace Umbraco.Web.Trees /// The application to load tree for /// An optional single tree alias, if specified will only load the single tree for the request app /// - /// An optional bool (defaults to true), if set to false it will also load uninitialized trees /// [HttpQueryStringFilter("queryStrings")] - public async Task GetApplicationTrees(string application, string tree, FormDataCollection queryStrings/*, bool onlyInitialized = true*/) + public async Task GetApplicationTrees(string application, string tree, FormDataCollection queryStrings) { application = application.CleanForXss(); @@ -62,7 +66,7 @@ namespace Umbraco.Web.Trees if (string.IsNullOrEmpty(tree) == false || allTrees.Count == 1) { var apptree = !tree.IsNullOrWhiteSpace() - ? allTrees.FirstOrDefault(x => x.Alias == tree) + ? allTrees.FirstOrDefault(x => x.TreeAlias == tree) : allTrees.FirstOrDefault(); if (apptree == null) throw new HttpResponseException(HttpStatusCode.NotFound); @@ -153,15 +157,15 @@ namespace Umbraco.Web.Trees /// /// Get the root node for an application with multiple trees /// - /// + /// /// /// - private async Task GetRootForMultipleAppTree(ApplicationTree configTree, FormDataCollection queryStrings) + private async Task GetRootForMultipleAppTree(ApplicationTree tree, FormDataCollection queryStrings) { - if (configTree == null) throw new ArgumentNullException(nameof(configTree)); + if (tree == null) throw new ArgumentNullException(nameof(tree)); try { - var byControllerAttempt = await _treeControllerResolver.TryGetRootNodeFromControllerTree(configTree, queryStrings, ControllerContext); + var byControllerAttempt = await TryGetRootNodeFromControllerTree(tree, queryStrings, ControllerContext); if (byControllerAttempt.Success) { return byControllerAttempt.Result; @@ -174,54 +178,133 @@ namespace Umbraco.Web.Trees return null; } - throw new ApplicationException("Could not get root node for tree type " + configTree.Alias); + throw new ApplicationException("Could not get root node for tree type " + tree.TreeAlias); } /// /// Get the root node for an application with one tree /// - /// + /// /// /// /// /// - private async Task GetRootForSingleAppTree(ApplicationTree configTree, string id, FormDataCollection queryStrings, string application) + private async Task GetRootForSingleAppTree(ApplicationTree tree, string id, FormDataCollection queryStrings, string application) { var rootId = Constants.System.Root.ToString(CultureInfo.InvariantCulture); - if (configTree == null) throw new ArgumentNullException(nameof(configTree)); - var byControllerAttempt = _treeControllerResolver.TryLoadFromControllerTree(configTree, id, queryStrings, ControllerContext); - if (byControllerAttempt.Success) + if (tree == null) throw new ArgumentNullException(nameof(tree)); + var byControllerAttempt = TryLoadFromControllerTree(tree, id, queryStrings, ControllerContext); + if (!byControllerAttempt.Success) + throw new ApplicationException("Could not render a tree for type " + tree.TreeAlias); + + var rootNode = await TryGetRootNodeFromControllerTree(tree, queryStrings, ControllerContext); + if (rootNode.Success == false) { - var rootNode = await _treeControllerResolver.TryGetRootNodeFromControllerTree(configTree, queryStrings, ControllerContext); - if (rootNode.Success == false) - { - //This should really never happen if we've successfully got the children above. - throw new InvalidOperationException("Could not create root node for tree " + configTree.Alias); - } - - var treeAttribute = _treeControllerResolver.GetTreeAttribute(configTree); - - var sectionRoot = TreeRootNode.CreateSingleTreeRoot( - rootId, - rootNode.Result.ChildNodesUrl, - rootNode.Result.MenuUrl, - rootNode.Result.Name, - byControllerAttempt.Result, - treeAttribute.IsSingleNodeTree); - - //assign the route path based on the root node, this means it will route there when the section is navigated to - //and no dashboards will be available for this section - sectionRoot.RoutePath = rootNode.Result.RoutePath; - - foreach (var d in rootNode.Result.AdditionalData) - { - sectionRoot.AdditionalData[d.Key] = d.Value; - } - return sectionRoot; - + //This should really never happen if we've successfully got the children above. + throw new InvalidOperationException("Could not create root node for tree " + tree.TreeAlias); } - throw new ApplicationException("Could not render a tree for type " + configTree.Alias); + var sectionRoot = TreeRootNode.CreateSingleTreeRoot( + rootId, + rootNode.Result.ChildNodesUrl, + rootNode.Result.MenuUrl, + rootNode.Result.Name, + byControllerAttempt.Result, + tree.IsSingleNodeTree); + + //assign the route path based on the root node, this means it will route there when the section is navigated to + //and no dashboards will be available for this section + sectionRoot.RoutePath = rootNode.Result.RoutePath; + + foreach (var d in rootNode.Result.AdditionalData) + { + sectionRoot.AdditionalData[d.Key] = d.Value; + } + return sectionRoot; + } + + /// + /// Proxies a request to the destination tree controller to get it's root tree node + /// + /// + /// + /// + /// + /// + /// This ensures that authorization filters are applied to the sub request + /// + private async Task> TryGetRootNodeFromControllerTree(ApplicationTree appTree, FormDataCollection formCollection, HttpControllerContext controllerContext) + { + //instantiate it, since we are proxying, we need to setup the instance with our current context + var instance = (TreeController)DependencyResolver.Current.GetService(appTree.TreeControllerType); + + //NOTE: This is all required in order to execute the auth-filters for the sub request, we + // need to "trick" web-api into thinking that it is actually executing the proxied controller. + + var urlHelper = controllerContext.Request.GetUrlHelper(); + //create the proxied URL for the controller action + var proxiedUrl = controllerContext.Request.RequestUri.GetLeftPart(UriPartial.Authority) + + urlHelper.GetUmbracoApiService("GetRootNode", instance.GetType()); + //add the query strings to it + proxiedUrl += "?" + formCollection.ToQueryString(); + //create proxy route data specifying the action / controller to execute + var proxiedRouteData = new HttpRouteData( + controllerContext.RouteData.Route, + new HttpRouteValueDictionary(new { action = "GetRootNode", controller = ControllerExtensions.GetControllerName(instance.GetType()) })); + + //create a proxied controller context + var proxiedControllerContext = new HttpControllerContext( + controllerContext.Configuration, + proxiedRouteData, + new HttpRequestMessage(HttpMethod.Get, proxiedUrl)) + { + ControllerDescriptor = new HttpControllerDescriptor(controllerContext.ControllerDescriptor.Configuration, ControllerExtensions.GetControllerName(instance.GetType()), instance.GetType()), + RequestContext = controllerContext.RequestContext + }; + + instance.ControllerContext = proxiedControllerContext; + instance.Request = controllerContext.Request; + instance.RequestContext.RouteData = proxiedRouteData; + + //invoke auth filters for this sub request + var result = await instance.ControllerContext.InvokeAuthorizationFiltersForRequest(); + //if a result is returned it means they are unauthorized, just throw the response. + if (result != null) + { + throw new HttpResponseException(result); + } + + //return the root + var node = instance.GetRootNode(formCollection); + return node == null + ? Attempt.Fail(new InvalidOperationException("Could not return a root node for tree " + appTree.TreeAlias)) + : Attempt.Succeed(node); + } + + /// + /// Proxies a request to the destination tree controller to get it's tree node collection + /// + /// + /// + /// + /// + /// + private Attempt TryLoadFromControllerTree(ApplicationTree appTree, string id, FormDataCollection formCollection, HttpControllerContext controllerContext) + { + // instantiate it, since we are proxying, we need to setup the instance with our current context + var instance = (TreeController)DependencyResolver.Current.GetService(appTree.TreeControllerType); + if (instance == null) + throw new Exception("Failed to create tree " + appTree.TreeControllerType + "."); + + //TODO: Shouldn't we be applying the same proxying logic as above so that filters work? seems like an oversight + + instance.ControllerContext = controllerContext; + instance.Request = controllerContext.Request; + + // return its data + return Attempt.Succeed(instance.GetNodes(id, formCollection)); + } + } } diff --git a/src/Umbraco.Web/Trees/ITree.cs b/src/Umbraco.Web/Trees/ITree.cs new file mode 100644 index 0000000000..40be7338b0 --- /dev/null +++ b/src/Umbraco.Web/Trees/ITree.cs @@ -0,0 +1,31 @@ +namespace Umbraco.Web.Trees +{ + public interface ITree + { + /// + /// Gets or sets the sort order. + /// + /// The sort order. + int SortOrder { get; } + + /// + /// Gets the section alias. + /// + string ApplicationAlias { get; } + + /// + /// Gets the tree alias. + /// + string TreeAlias { get; } + + /// + /// Gets or sets the tree title (fallback if the tree alias isn't localized) + /// + string TreeTitle { get; } + + /// + /// Flag to define if this tree is a single node tree (will never contain child nodes, full screen app) + /// + bool IsSingleNodeTree { get; } + } +} diff --git a/src/Umbraco.Web/Trees/TreeAttribute.cs b/src/Umbraco.Web/Trees/TreeAttribute.cs index 1cf23c549f..dd63f8c172 100644 --- a/src/Umbraco.Web/Trees/TreeAttribute.cs +++ b/src/Umbraco.Web/Trees/TreeAttribute.cs @@ -1,4 +1,5 @@ using System; +using Umbraco.Web.Models.Trees; namespace Umbraco.Web.Trees { @@ -6,15 +7,15 @@ namespace Umbraco.Web.Trees /// Identifies an application tree /// [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] - public class TreeAttribute : Attribute + public class TreeAttribute : Attribute, ITree { /// /// Initializes a new instance of the class. /// /// The app alias. - /// The alias. + /// public TreeAttribute(string appAlias, - string alias) : this(appAlias, alias, null) + string treeAlias) : this(appAlias, treeAlias, null) { } @@ -22,16 +23,16 @@ namespace Umbraco.Web.Trees /// Initializes a new instance of the class. /// /// The app alias. - /// The alias. - /// The title. + /// + /// /// The icon closed. /// The icon open. /// if set to true [initialize]. /// The sort order. /// Flag to define if this tree is a single node tree (will never contain child nodes, full screen app) public TreeAttribute(string appAlias, - string alias, - string title, + string treeAlias, + string treeTitle, string iconClosed = "icon-folder", string iconOpen = "icon-folder-open", bool initialize = true, @@ -39,8 +40,8 @@ namespace Umbraco.Web.Trees bool isSingleNodeTree = false) { ApplicationAlias = appAlias; - Alias = alias; - Title = title; + TreeAlias = treeAlias; + TreeTitle = treeTitle; IconClosed = iconClosed; IconOpen = iconOpen; Initialize = initialize; @@ -48,17 +49,17 @@ namespace Umbraco.Web.Trees IsSingleNodeTree = isSingleNodeTree; } - public string ApplicationAlias { get; private set; } - public string Alias { get; private set; } - public string Title { get; private set; } - public string IconClosed { get; private set; } - public string IconOpen { get; private set; } - public bool Initialize { get; private set; } - public int SortOrder { get; private set; } + public string ApplicationAlias { get; } + public string TreeAlias { get; } + public string TreeTitle { get; } + public string IconClosed { get; } + public string IconOpen { get; } + public bool Initialize { get; } + public int SortOrder { get; } /// /// Flag to define if this tree is a single node tree (will never contain child nodes, full screen app) /// - public bool IsSingleNodeTree { get; private set; } + public bool IsSingleNodeTree { get; } } } diff --git a/src/Umbraco.Web/Trees/TreeCollection.cs b/src/Umbraco.Web/Trees/TreeCollection.cs index 8f913fb2d7..c7b60dea16 100644 --- a/src/Umbraco.Web/Trees/TreeCollection.cs +++ b/src/Umbraco.Web/Trees/TreeCollection.cs @@ -21,7 +21,26 @@ namespace Umbraco.Web.Trees { protected override TreeCollectionBuilder This => this; - //TODO: can we allow for re-ordering OOTB without exposing other methods? + private readonly List _instances = new List(); + + public void AddTree(ApplicationTree tree) + { + _instances.Add(tree); + } + + protected override IEnumerable CreateItems(IFactory factory) + { + return _instances; + + //var items = base.CreateItems(factory).ToList(); + //throw new NotImplementedException(); + ////validate the items, no actions should exist that do not either expose notifications or permissions + //var invalidItems = items.Where(x => !x.CanBePermissionAssigned && !x.ShowInNotifier).ToList(); + //if (invalidItems.Count == 0) return items; + + //var invalidActions = string.Join(", ", invalidItems.Select(x => "'" + x.Alias + "'")); + //throw new InvalidOperationException($"Invalid actions {invalidActions}'. All {typeof(IAction)} implementations must be true for either {nameof(IAction.CanBePermissionAssigned)} or {nameof(IAction.ShowInNotifier)}."); + } } } diff --git a/src/Umbraco.Web/Trees/TreeController.cs b/src/Umbraco.Web/Trees/TreeController.cs index 102671ec29..63e8f5aad5 100644 --- a/src/Umbraco.Web/Trees/TreeController.cs +++ b/src/Umbraco.Web/Trees/TreeController.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Concurrent; +using System.Linq; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; @@ -14,10 +16,10 @@ namespace Umbraco.Web.Trees public abstract class TreeController : TreeControllerBase { private TreeAttribute _attribute; - private string _rootNodeDisplayName; protected TreeController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) : base(globalSettings, umbracoContext, sqlContext, services, applicationCache, logger, runtimeState) { + Initialize(); } protected TreeController() @@ -25,29 +27,42 @@ namespace Umbraco.Web.Trees Initialize(); } - /// - /// The name to display on the root node - /// - public override string RootNodeDisplayName - { - get - { - throw new NotImplementedException(); - //return _rootNodeDisplayName - // ?? (_rootNodeDisplayName = Services.ApplicationTreeService.GetByAlias(_attribute.Alias) - // ?.GetRootNodeDisplayName(Services.TextService)); - } - } + /// + public override string RootNodeDisplayName => ApplicationTree.GetRootNodeDisplayName(this, Services.TextService); - /// - /// Gets the current tree alias from the attribute assigned to it. - /// - public override string TreeAlias => _attribute.Alias; + /// + public override string TreeAlias => _attribute.TreeAlias; + /// + public override string TreeTitle => _attribute.TreeTitle; + /// + public override string ApplicationAlias => _attribute.ApplicationAlias; + /// + public override int SortOrder => _attribute.SortOrder; + /// + public override bool IsSingleNodeTree => _attribute.IsSingleNodeTree; private void Initialize() { - throw new NotImplementedException(); - //_attribute = GetType().GetTreeAttribute(); + _attribute = GetTreeAttribute(); + } + + private static readonly ConcurrentDictionary TreeAttributeCache = new ConcurrentDictionary(); + + private TreeAttribute GetTreeAttribute() + { + return TreeAttributeCache.GetOrAdd(GetType(), type => + { + //Locate the tree attribute + var treeAttributes = type + .GetCustomAttributes(false) + .ToArray(); + + if (treeAttributes.Length == 0) + throw new InvalidOperationException("The Tree controller is missing the " + typeof(TreeAttribute).FullName + " attribute"); + + //assign the properties of this object to those of the metadata attribute + return treeAttributes[0]; + }); } } } diff --git a/src/Umbraco.Web/Trees/TreeControllerBase.cs b/src/Umbraco.Web/Trees/TreeControllerBase.cs index c00d6053c8..7a027033fc 100644 --- a/src/Umbraco.Web/Trees/TreeControllerBase.cs +++ b/src/Umbraco.Web/Trees/TreeControllerBase.cs @@ -25,7 +25,7 @@ namespace Umbraco.Web.Trees /// Developers should generally inherit from TreeController. /// [AngularJsonOnlyConfiguration] - public abstract class TreeControllerBase : UmbracoAuthorizedApiController + public abstract class TreeControllerBase : UmbracoAuthorizedApiController, ITree { protected TreeControllerBase() { @@ -62,10 +62,16 @@ namespace Umbraco.Web.Trees /// public abstract string RootNodeDisplayName { get; } - /// - /// Gets the current tree alias from the attribute assigned to it. - /// + /// public abstract string TreeAlias { get; } + /// + public abstract string TreeTitle { get; } + /// + public abstract string ApplicationAlias { get; } + /// + public abstract int SortOrder { get; } + /// + public abstract bool IsSingleNodeTree { get; } /// /// Returns the root node for the tree diff --git a/src/Umbraco.Web/Trees/TreeControllerResolver.cs b/src/Umbraco.Web/Trees/TreeControllerResolver.cs deleted file mode 100644 index 62cafbb5dd..0000000000 --- a/src/Umbraco.Web/Trees/TreeControllerResolver.cs +++ /dev/null @@ -1,203 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Linq; -using System.Management.Instrumentation; -using System.Net.Http; -using System.Net.Http.Formatting; -using System.Threading.Tasks; -using System.Web.Http; -using System.Web.Http.Controllers; -using System.Web.Http.Routing; -using System.Web.Mvc; -using Umbraco.Core; -using Umbraco.Web.Models.Trees; -using Umbraco.Web.Mvc; -using Umbraco.Web.WebApi; -using Umbraco.Core.Composing; -using ApplicationTree = Umbraco.Web.Models.ContentEditing.ApplicationTree; - -namespace Umbraco.Web.Trees -{ - public class TreeControllerResolver - { - private readonly TreeCollection _trees; - private readonly UmbracoApiControllerTypeCollection _apiControllers; - - public TreeControllerResolver(TreeCollection trees, UmbracoApiControllerTypeCollection apiControllers) - { - _trees = trees; - _apiControllers = apiControllers; - } - - private static readonly ConcurrentDictionary TreeAttributeCache = new ConcurrentDictionary(); - private static readonly ConcurrentDictionary ResolvedControllerTypes = new ConcurrentDictionary(); - - private TreeAttribute GetTreeAttribute(Type treeControllerType) - { - return TreeAttributeCache.GetOrAdd(treeControllerType, type => - { - //Locate the tree attribute - var treeAttributes = type - .GetCustomAttributes(false) - .ToArray(); - - if (treeAttributes.Length == 0) - { - throw new InvalidOperationException("The Tree controller is missing the " + typeof(TreeAttribute).FullName + " attribute"); - } - - //assign the properties of this object to those of the metadata attribute - return treeAttributes[0]; - }); - } - - internal TreeAttribute GetTreeAttribute(ApplicationTree tree) - { - throw new NotImplementedException(); - //return ResolvedControllerTypes.GetOrAdd(tree.Alias, s => - //{ - // var controllerType = _apiControllers - // .OfType() - // .FirstOrDefault(x => x.) - //}); - - //return GetTreeAttribute(tree.GetRuntimeType()); - } - - private Type GetControllerType(ApplicationTree tree) - { - throw new NotImplementedException(); - } - - - internal Attempt TryGetControllerTree(ApplicationTree appTree) - { - throw new NotImplementedException(); - - ////get reference to all TreeApiControllers - //var controllerTrees = _apiControllers - // .Where(TypeHelper.IsTypeAssignableFrom) - // .ToArray(); - - ////find the one we're looking for - //var foundControllerTree = controllerTrees.FirstOrDefault(x => x == appTree.GetRuntimeType()); - //if (foundControllerTree == null) - //{ - // return Attempt.Fail(new InstanceNotFoundException("Could not find tree of type " + appTree.Type + " in any loaded DLLs")); - //} - //return Attempt.Succeed(foundControllerTree); - } - - /// - /// This will go and get the root node from a controller tree by executing the tree's GetRootNode method - /// - /// - /// - /// - /// - /// - /// This ensures that authorization filters are applied to the sub request - /// - internal async Task> TryGetRootNodeFromControllerTree(ApplicationTree appTree, FormDataCollection formCollection, HttpControllerContext controllerContext) - { - var foundControllerTreeAttempt = TryGetControllerTree(appTree); - if (foundControllerTreeAttempt.Success == false) - { - return Attempt.Fail(foundControllerTreeAttempt.Exception); - } - - var foundControllerTree = foundControllerTreeAttempt.Result; - //instantiate it, since we are proxying, we need to setup the instance with our current context - var instance = (TreeController)DependencyResolver.Current.GetService(foundControllerTree); - - //NOTE: This is all required in order to execute the auth-filters for the sub request, we - // need to "trick" web-api into thinking that it is actually executing the proxied controller. - - var urlHelper = controllerContext.Request.GetUrlHelper(); - //create the proxied URL for the controller action - var proxiedUrl = controllerContext.Request.RequestUri.GetLeftPart(UriPartial.Authority) + - urlHelper.GetUmbracoApiService("GetRootNode", instance.GetType()); - //add the query strings to it - proxiedUrl += "?" + formCollection.ToQueryString(); - //create proxy route data specifying the action / controller to execute - var proxiedRouteData = new HttpRouteData( - controllerContext.RouteData.Route, - new HttpRouteValueDictionary(new {action = "GetRootNode", controller = ControllerExtensions.GetControllerName(instance.GetType())})); - - //create a proxied controller context - var proxiedControllerContext = new HttpControllerContext( - controllerContext.Configuration, - proxiedRouteData, - new HttpRequestMessage(HttpMethod.Get, proxiedUrl)) - { - ControllerDescriptor = new HttpControllerDescriptor(controllerContext.ControllerDescriptor.Configuration, ControllerExtensions.GetControllerName(instance.GetType()), instance.GetType()) - }; - - if (WebApiVersionCheck.WebApiVersion >= Version.Parse("5.0.0")) - { - //fixme - will this 'just' work now? - proxiedControllerContext.RequestContext = controllerContext.RequestContext; - - ////In WebApi2, this is required to be set: - //// proxiedControllerContext.RequestContext = controllerContext.RequestContext - //// but we need to do this with reflection because of codebase changes between version 4/5 - ////NOTE: Use TypeHelper here since the reflection is cached - //var controllerContextRequestContext = TypeHelper.GetProperty(controllerContext.GetType(), "RequestContext").GetValue(controllerContext); - //TypeHelper.GetProperty(proxiedControllerContext.GetType(), "RequestContext").SetValue(proxiedControllerContext, controllerContextRequestContext); - } - - instance.ControllerContext = proxiedControllerContext; - instance.Request = controllerContext.Request; - - if (WebApiVersionCheck.WebApiVersion >= Version.Parse("5.0.0")) - { - - //fixme - will this 'just' work now? - instance.RequestContext.RouteData = proxiedRouteData; - - ////now we can change the request context's route data to be the proxied route data - NOTE: we cannot do this directly above - //// because it will detect that the request context is different throw an exception. This is a change in webapi2 and we need to set - //// this with reflection due to codebase changes between version 4/5 - //// instance.RequestContext.RouteData = proxiedRouteData; - ////NOTE: Use TypeHelper here since the reflection is cached - //var instanceRequestContext = TypeHelper.GetProperty(typeof(ApiController), "RequestContext").GetValue(instance); - //TypeHelper.GetProperty(instanceRequestContext.GetType(), "RouteData").SetValue(instanceRequestContext, proxiedRouteData); - } - - //invoke auth filters for this sub request - var result = await instance.ControllerContext.InvokeAuthorizationFiltersForRequest(); - //if a result is returned it means they are unauthorized, just throw the response. - if (result != null) - { - throw new HttpResponseException(result); - } - - //return the root - var node = instance.GetRootNode(formCollection); - return node == null - ? Attempt.Fail(new InvalidOperationException("Could not return a root node for tree " + appTree.Alias)) - : Attempt.Succeed(node); - } - - internal Attempt TryLoadFromControllerTree(ApplicationTree appTree, string id, FormDataCollection formCollection, HttpControllerContext controllerContext) - { - var foundControllerTreeAttempt = TryGetControllerTree(appTree); - if (foundControllerTreeAttempt.Success == false) - return Attempt.Fail(foundControllerTreeAttempt.Exception); - - // instantiate it, since we are proxying, we need to setup the instance with our current context - var foundControllerTree = foundControllerTreeAttempt.Result; - var instance = (TreeController) DependencyResolver.Current.GetService(foundControllerTree); - if (instance == null) - throw new Exception("Failed to get tree " + foundControllerTree.FullName + "."); - - instance.ControllerContext = controllerContext; - instance.Request = controllerContext.Request; - - // return its data - return Attempt.Succeed(instance.GetNodes(id, formCollection)); - } - - } - -} diff --git a/src/Umbraco.Web/Trees/UserPermissionsTreeController.cs b/src/Umbraco.Web/Trees/UserPermissionsTreeController.cs deleted file mode 100644 index 5473fee7bb..0000000000 --- a/src/Umbraco.Web/Trees/UserPermissionsTreeController.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System; -using System.Linq; -using System.Net.Http.Formatting; -using Umbraco.Core; -using Umbraco.Web.Models.Trees; -using Umbraco.Web.Mvc; -using Umbraco.Web.WebApi.Filters; - -using Constants = Umbraco.Core.Constants; - -namespace Umbraco.Web.Trees -{ - [UmbracoTreeAuthorize(Constants.Trees.UserPermissions)] - [Tree(Constants.Applications.Users, Constants.Trees.UserPermissions, null, sortOrder: 2)] - [PluginController("UmbracoTrees")] - [CoreTree] - public class UserPermissionsTreeController : TreeController - { - protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) - { - var nodes = new TreeNodeCollection(); - long totalUsers; - nodes.AddRange( - Services.UserService.GetAll(0, int.MaxValue, out totalUsers) - .Where(x => x.Id != Constants.Security.SuperUserId && x.IsApproved) - .Select(x => CreateTreeNode(x.Id.ToString(), - id, - queryStrings, - x.Name, - "icon-user", - false, - "/" + queryStrings.GetValue("application") + "/framed/" - + Uri.EscapeDataString("users/PermissionEditor.aspx?id=" + x.Id)))); - - return nodes; - } - - protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) - { - var menu = new MenuItemCollection(); - - if (id == Constants.System.Root.ToInvariantString()) - { - // root actions - menu.Items.Add(new RefreshNode(Services.TextService, true)); - return menu; - } - - return menu; - } - } -} diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index f1d15e9ea6..0b1603c9e3 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -166,8 +166,9 @@ - + + @@ -183,7 +184,7 @@ - + @@ -551,7 +552,6 @@ - @@ -649,7 +649,7 @@ - + @@ -972,7 +972,6 @@ - @@ -1056,7 +1055,6 @@ - diff --git a/src/Umbraco.Web/WebApi/Filters/UmbracoTreeAuthorizeAttribute.cs b/src/Umbraco.Web/WebApi/Filters/UmbracoTreeAuthorizeAttribute.cs index cc483db416..5ad3da7f4d 100644 --- a/src/Umbraco.Web/WebApi/Filters/UmbracoTreeAuthorizeAttribute.cs +++ b/src/Umbraco.Web/WebApi/Filters/UmbracoTreeAuthorizeAttribute.cs @@ -41,18 +41,16 @@ namespace Umbraco.Web.WebApi.Filters return true; } - throw new NotImplementedException(); + var apps = _treeAliases.Select(x => Current.TreeService + .GetByAlias(x)) + .WhereNotNull() + .Select(x => x.ApplicationAlias) + .Distinct() + .ToArray(); - //var apps = _treeAliases.Select(x => Current.Services.ApplicationTreeService - // .GetByAlias(x)) - // .WhereNotNull() - // .Select(x => x.ApplicationAlias) - // .Distinct() - // .ToArray(); - - //return Current.UmbracoContext.Security.CurrentUser != null - // && apps.Any(app => Current.UmbracoContext.Security.UserHasSectionAccess( - // app, Current.UmbracoContext.Security.CurrentUser)); + return Current.UmbracoContext.Security.CurrentUser != null + && apps.Any(app => Current.UmbracoContext.Security.UserHasSectionAccess( + app, Current.UmbracoContext.Security.CurrentUser)); } } } diff --git a/src/Umbraco.Web/WebApi/MvcVersionCheck.cs b/src/Umbraco.Web/WebApi/MvcVersionCheck.cs deleted file mode 100644 index 3c84fa91ce..0000000000 --- a/src/Umbraco.Web/WebApi/MvcVersionCheck.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Umbraco.Web.WebApi -{ - internal class WebApiVersionCheck - { - public static System.Version WebApiVersion - { - get { return typeof(System.Web.Http.ApiController).Assembly.GetName().Version; } - } - } -} diff --git a/src/Umbraco.Web/WebApi/UmbracoApiControllerTypeCollection.cs b/src/Umbraco.Web/WebApi/UmbracoApiControllerTypeCollection.cs index d84ab3fe4a..cdb1aa2f51 100644 --- a/src/Umbraco.Web/WebApi/UmbracoApiControllerTypeCollection.cs +++ b/src/Umbraco.Web/WebApi/UmbracoApiControllerTypeCollection.cs @@ -8,8 +8,6 @@ namespace Umbraco.Web.WebApi // which we are not doing at the moment // we can inherit from BuilderCollectionBase and just be enumerable - //fixme: this should be LazyCollectionBuilderBase ? - public class UmbracoApiControllerTypeCollection : BuilderCollectionBase { public UmbracoApiControllerTypeCollection(IEnumerable items) From 0160f141f4104c1048cf96f498b2dc1cc4a20e06 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 17 Jan 2019 17:04:53 +1100 Subject: [PATCH 401/469] cleanup and explicitly registering sections --- .../Services/SectionServiceTests.cs | 2 +- .../TreesAndSections/ApplicationTreeTest.cs | 397 ----------------- .../ResourceFiles.Designer.cs | 91 ---- .../TreesAndSections/ResourceFiles.resx | 127 ------ .../TreesAndSections/SectionTests.cs | 252 ----------- .../TreesAndSections/applications.config | 16 - .../TreesAndSections/trees.config | 8 - src/Umbraco.Tests/Umbraco.Tests.csproj | 13 - .../Cache/ApplicationTreeCacheRefresher.cs | 46 -- .../Cache/DistributedCacheBinder_Handlers.cs | 47 -- .../Cache/DistributedCacheExtensions.cs | 19 - .../ContentEditing/IBackOfficeSection.cs | 15 - .../Models/Mapping/SectionMapperProfile.cs | 1 + .../Models/Trees/ApplicationDefinitions.cs | 77 ---- .../Models/Trees/IBackOfficeSection.cs | 12 + .../{SectionRootNode.cs => TreeRootNode.cs} | 0 src/Umbraco.Web/Runtime/WebRuntimeComposer.cs | 11 +- src/Umbraco.Web/Services/ISectionService.cs | 1 + src/Umbraco.Web/Services/ITreeService.cs | 10 +- src/Umbraco.Web/Services/SectionService.cs | 253 +---------- src/Umbraco.Web/Services/TreeService.cs | 410 +----------------- .../Trees/BackOfficeSectionCollection.cs | 8 +- .../BackOfficeSectionCollectionBuilder.cs | 10 + .../Trees/ContentBackOfficeSection.cs | 15 + src/Umbraco.Web/Trees/ITree.cs | 1 + .../Trees/MediaBackOfficeSection.cs | 15 + .../Trees/MembersBackOfficeSection.cs | 15 + .../Trees/PackagesBackOfficeSection.cs | 15 + .../Trees/SettingsBackOfficeSection.cs | 15 + .../Trees/TranslationBackOfficeSection.cs | 15 + src/Umbraco.Web/Trees/TreeCollection.cs | 27 -- .../Trees/TreeCollectionBuilder.cs | 18 + .../Trees/UsersBackOfficeSection.cs | 15 + src/Umbraco.Web/Umbraco.Web.csproj | 15 +- 34 files changed, 183 insertions(+), 1809 deletions(-) delete mode 100644 src/Umbraco.Tests/TreesAndSections/ApplicationTreeTest.cs delete mode 100644 src/Umbraco.Tests/TreesAndSections/ResourceFiles.Designer.cs delete mode 100644 src/Umbraco.Tests/TreesAndSections/ResourceFiles.resx delete mode 100644 src/Umbraco.Tests/TreesAndSections/SectionTests.cs delete mode 100644 src/Umbraco.Tests/TreesAndSections/applications.config delete mode 100644 src/Umbraco.Tests/TreesAndSections/trees.config delete mode 100644 src/Umbraco.Web/Cache/ApplicationTreeCacheRefresher.cs delete mode 100644 src/Umbraco.Web/Models/ContentEditing/IBackOfficeSection.cs delete mode 100644 src/Umbraco.Web/Models/Trees/ApplicationDefinitions.cs create mode 100644 src/Umbraco.Web/Models/Trees/IBackOfficeSection.cs rename src/Umbraco.Web/Models/Trees/{SectionRootNode.cs => TreeRootNode.cs} (100%) create mode 100644 src/Umbraco.Web/Trees/BackOfficeSectionCollectionBuilder.cs create mode 100644 src/Umbraco.Web/Trees/ContentBackOfficeSection.cs create mode 100644 src/Umbraco.Web/Trees/MediaBackOfficeSection.cs create mode 100644 src/Umbraco.Web/Trees/MembersBackOfficeSection.cs create mode 100644 src/Umbraco.Web/Trees/PackagesBackOfficeSection.cs create mode 100644 src/Umbraco.Web/Trees/SettingsBackOfficeSection.cs create mode 100644 src/Umbraco.Web/Trees/TranslationBackOfficeSection.cs create mode 100644 src/Umbraco.Web/Trees/TreeCollectionBuilder.cs create mode 100644 src/Umbraco.Web/Trees/UsersBackOfficeSection.cs diff --git a/src/Umbraco.Tests/Services/SectionServiceTests.cs b/src/Umbraco.Tests/Services/SectionServiceTests.cs index 206c99ffbf..9211755251 100644 --- a/src/Umbraco.Tests/Services/SectionServiceTests.cs +++ b/src/Umbraco.Tests/Services/SectionServiceTests.cs @@ -16,7 +16,7 @@ namespace Umbraco.Tests.Services public class SectionServiceTests : TestWithSomeContentBase { //fixme - private ISectionService SectionService => new SectionService(ServiceContext.UserService, null, null); + private ISectionService SectionService => new SectionService(ServiceContext.UserService, null); [Test] diff --git a/src/Umbraco.Tests/TreesAndSections/ApplicationTreeTest.cs b/src/Umbraco.Tests/TreesAndSections/ApplicationTreeTest.cs deleted file mode 100644 index 95d90f1463..0000000000 --- a/src/Umbraco.Tests/TreesAndSections/ApplicationTreeTest.cs +++ /dev/null @@ -1,397 +0,0 @@ -//using System.IO; -//using NUnit.Framework; -//using Umbraco.Core.Services; -//using Umbraco.Tests.TestHelpers; -//using System; -//using System.Linq; -//using System.Threading; -//using Umbraco.Tests.Testing; -//using Umbraco.Web.Services; -//using Current = Umbraco.Web.Composing.Current; - -//namespace Umbraco.Tests.TreesAndSections -//{ - - -// /// -// ///This is a test class for ApplicationTreeTest and is intended -// ///to contain all ApplicationTreeTest Unit Tests -// /// -// [TestFixture] -// [Apartment(ApartmentState.STA)] -// [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)] -// public class ApplicationTreeTest : TestWithDatabaseBase -// { -// public override void SetUp() -// { -// base.SetUp(); - -// var treesConfig = TestHelper.MapPathForTest("~/TEMP/TreesAndSections/trees.config"); -// var appConfig = TestHelper.MapPathForTest("~/TEMP/TreesAndSections/applications.config"); -// Directory.CreateDirectory(TestHelper.MapPathForTest("~/TEMP/TreesAndSections")); -// using (var writer = File.CreateText(treesConfig)) -// { -// writer.Write(ResourceFiles.trees); -// } -// using (var writer = File.CreateText(appConfig)) -// { -// writer.Write(ResourceFiles.applications); -// } - -// //ApplicationTreeService.TreeConfigFilePath = treesConfig; -// SectionService.AppConfigFilePath = appConfig; -// } - -// public override void TearDown() -// { -// base.TearDown(); - -// if (Directory.Exists(TestHelper.MapPathForTest("~/TEMP/TreesAndSections"))) -// { -// Directory.Delete(TestHelper.MapPathForTest("~/TEMP/TreesAndSections"), true); -// } -// //ApplicationTreeService.TreeConfigFilePath = null; -// SectionService.AppConfigFilePath = null; -// } - -// ///// -// ///// Creates a new app tree linked to an application, then delete the application and make sure the tree is gone as well -// ///// -// //[Test()] -// //public void ApplicationTree_Make_New_Then_Delete_App() -// //{ -// // //create new app -// // var appName = Guid.NewGuid().ToString("N"); -// // var treeName = Guid.NewGuid().ToString("N"); -// // Current.Services.SectionService.MakeNew(appName, appName, "icon.jpg"); - -// // //check if it exists -// // var app = Current.Services.SectionService.GetByAlias(appName); -// // Assert.IsNotNull(app); - -// // //create the new app tree assigned to the new app -// // Current.Services.ApplicationTreeService.MakeNew(false, 0, app.Alias, treeName, treeName, "icon.jpg", "icon.jpg", "Umbraco.Web.Trees.ContentTreeController, Umbraco.Web"); -// // var tree = Current.Services.ApplicationTreeService.GetByAlias(treeName); -// // Assert.IsNotNull(tree); - -// // //now delete the app -// // Current.Services.SectionService.DeleteSection(app); - -// // //check that the tree is gone -// // Assert.AreEqual(0, Current.Services.ApplicationTreeService.GetApplicationTrees(treeName).Count()); -// //} - - -// #region Tests to write -// ///// -// /////A test for ApplicationTree Constructor -// ///// -// //[TestMethod()] -// //public void ApplicationTreeConstructorTest() -// //{ -// // bool silent = false; // TODO: Initialize to an appropriate value -// // bool initialize = false; // TODO: Initialize to an appropriate value -// // byte sortOrder = 0; // TODO: Initialize to an appropriate value -// // string applicationAlias = string.Empty; // TODO: Initialize to an appropriate value -// // string alias = string.Empty; // TODO: Initialize to an appropriate value -// // string title = string.Empty; // TODO: Initialize to an appropriate value -// // string iconClosed = string.Empty; // TODO: Initialize to an appropriate value -// // string iconOpened = string.Empty; // TODO: Initialize to an appropriate value -// // string assemblyName = string.Empty; // TODO: Initialize to an appropriate value -// // string type = string.Empty; // TODO: Initialize to an appropriate value -// // string action = string.Empty; // TODO: Initialize to an appropriate value -// // ApplicationTree target = new ApplicationTree(silent, initialize, sortOrder, applicationAlias, alias, title, iconClosed, iconOpened, assemblyName, type, action); -// // Assert.Inconclusive("TODO: Implement code to verify target"); -// //} - -// ///// -// /////A test for ApplicationTree Constructor -// ///// -// //[TestMethod()] -// //public void ApplicationTreeConstructorTest1() -// //{ -// // ApplicationTree target = new ApplicationTree(); -// // Assert.Inconclusive("TODO: Implement code to verify target"); -// //} - -// ///// -// /////A test for Delete -// ///// -// //[TestMethod()] -// //public void DeleteTest() -// //{ -// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value -// // target.Delete(); -// // Assert.Inconclusive("A method that does not return a value cannot be verified."); -// //} - - -// ///// -// /////A test for Save -// ///// -// //[TestMethod()] -// //public void SaveTest() -// //{ -// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value -// // target.Save(); -// // Assert.Inconclusive("A method that does not return a value cannot be verified."); -// //} - -// ///// -// /////A test for getAll -// ///// -// //[TestMethod()] -// //public void getAllTest() -// //{ -// // ApplicationTree[] expected = null; // TODO: Initialize to an appropriate value -// // ApplicationTree[] actual; -// // actual = ApplicationTree.getAll(); -// // Assert.AreEqual(expected, actual); -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} - -// ///// -// /////A test for getApplicationTree -// ///// -// //[TestMethod()] -// //public void getApplicationTreeTest() -// //{ -// // string applicationAlias = string.Empty; // TODO: Initialize to an appropriate value -// // ApplicationTree[] expected = null; // TODO: Initialize to an appropriate value -// // ApplicationTree[] actual; -// // actual = ApplicationTree.getApplicationTree(applicationAlias); -// // Assert.AreEqual(expected, actual); -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} - -// ///// -// /////A test for getApplicationTree -// ///// -// //[TestMethod()] -// //public void getApplicationTreeTest1() -// //{ -// // string applicationAlias = string.Empty; // TODO: Initialize to an appropriate value -// // bool onlyInitializedApplications = false; // TODO: Initialize to an appropriate value -// // ApplicationTree[] expected = null; // TODO: Initialize to an appropriate value -// // ApplicationTree[] actual; -// // actual = ApplicationTree.getApplicationTree(applicationAlias, onlyInitializedApplications); -// // Assert.AreEqual(expected, actual); -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} - -// ///// -// /////A test for getByAlias -// ///// -// //[TestMethod()] -// //public void getByAliasTest() -// //{ -// // string treeAlias = string.Empty; // TODO: Initialize to an appropriate value -// // ApplicationTree expected = null; // TODO: Initialize to an appropriate value -// // ApplicationTree actual; -// // actual = ApplicationTree.getByAlias(treeAlias); -// // Assert.AreEqual(expected, actual); -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} - -// ///// -// /////A test for Action -// ///// -// //[TestMethod()] -// //public void ActionTest() -// //{ -// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value -// // string expected = string.Empty; // TODO: Initialize to an appropriate value -// // string actual; -// // target.Action = expected; -// // actual = target.Action; -// // Assert.AreEqual(expected, actual); -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} - -// ///// -// /////A test for Alias -// ///// -// //[TestMethod()] -// //public void AliasTest() -// //{ -// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value -// // string actual; -// // actual = target.Alias; -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} - -// ///// -// /////A test for ApplicationAlias -// ///// -// //[TestMethod()] -// //public void ApplicationAliasTest() -// //{ -// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value -// // string actual; -// // actual = target.ApplicationAlias; -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} - -// ///// -// /////A test for AssemblyName -// ///// -// //[TestMethod()] -// //public void AssemblyNameTest() -// //{ -// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value -// // string expected = string.Empty; // TODO: Initialize to an appropriate value -// // string actual; -// // target.AssemblyName = expected; -// // actual = target.AssemblyName; -// // Assert.AreEqual(expected, actual); -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} - -// ///// -// /////A test for IconClosed -// ///// -// //[TestMethod()] -// //public void IconClosedTest() -// //{ -// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value -// // string expected = string.Empty; // TODO: Initialize to an appropriate value -// // string actual; -// // target.IconClosed = expected; -// // actual = target.IconClosed; -// // Assert.AreEqual(expected, actual); -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} - -// ///// -// /////A test for IconOpened -// ///// -// //[TestMethod()] -// //public void IconOpenedTest() -// //{ -// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value -// // string expected = string.Empty; // TODO: Initialize to an appropriate value -// // string actual; -// // target.IconOpened = expected; -// // actual = target.IconOpened; -// // Assert.AreEqual(expected, actual); -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} - -// ///// -// /////A test for Initialize -// ///// -// //[TestMethod()] -// //public void InitializeTest() -// //{ -// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value -// // bool expected = false; // TODO: Initialize to an appropriate value -// // bool actual; -// // target.Initialize = expected; -// // actual = target.Initialize; -// // Assert.AreEqual(expected, actual); -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} - -// ///// -// /////A test for Silent -// ///// -// //[TestMethod()] -// //public void SilentTest() -// //{ -// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value -// // bool expected = false; // TODO: Initialize to an appropriate value -// // bool actual; -// // target.Silent = expected; -// // actual = target.Silent; -// // Assert.AreEqual(expected, actual); -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} - -// ///// -// /////A test for SortOrder -// ///// -// //[TestMethod()] -// //public void SortOrderTest() -// //{ -// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value -// // byte expected = 0; // TODO: Initialize to an appropriate value -// // byte actual; -// // target.SortOrder = expected; -// // actual = target.SortOrder; -// // Assert.AreEqual(expected, actual); -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} - -// ///// -// /////A test for SqlHelper -// ///// -// //[TestMethod()] -// //public void SqlHelperTest() -// //{ -// // ISqlHelper actual; -// // actual = ApplicationTree.SqlHelper; -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} - -// ///// -// /////A test for Title -// ///// -// //[TestMethod()] -// //public void TitleTest() -// //{ -// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value -// // string expected = string.Empty; // TODO: Initialize to an appropriate value -// // string actual; -// // target.Title = expected; -// // actual = target.Title; -// // Assert.AreEqual(expected, actual); -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} - -// ///// -// /////A test for Type -// ///// -// //[TestMethod()] -// //public void TypeTest() -// //{ -// // ApplicationTree target = new ApplicationTree(); // TODO: Initialize to an appropriate value -// // string expected = string.Empty; // TODO: Initialize to an appropriate value -// // string actual; -// // target.Type = expected; -// // actual = target.Type; -// // Assert.AreEqual(expected, actual); -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} -// #endregion - -// #region Additional test attributes -// // -// //You can use the following additional attributes as you write your tests: -// // -// //Use ClassInitialize to run code before running the first test in the class -// //[ClassInitialize()] -// //public static void MyClassInitialize(TestContext testContext) -// //{ -// //} -// // -// //Use ClassCleanup to run code after all tests in a class have run -// //[ClassCleanup()] -// //public static void MyClassCleanup() -// //{ -// //} -// // -// //Use TestInitialize to run code before running each test -// //[TestInitialize()] -// //public void MyTestInitialize() -// //{ -// //} -// // -// //Use TestCleanup to run code after each test has run -// //[TestCleanup()] -// //public void MyTestCleanup() -// //{ -// //} -// // -// #endregion -// } -//} diff --git a/src/Umbraco.Tests/TreesAndSections/ResourceFiles.Designer.cs b/src/Umbraco.Tests/TreesAndSections/ResourceFiles.Designer.cs deleted file mode 100644 index 02bc84649e..0000000000 --- a/src/Umbraco.Tests/TreesAndSections/ResourceFiles.Designer.cs +++ /dev/null @@ -1,91 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Umbraco.Tests.TreesAndSections { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class ResourceFiles { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal ResourceFiles() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Umbraco.Tests.TreesAndSections.ResourceFiles", typeof(ResourceFiles).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to <?xml version="1.0" encoding="utf-8"?> - ///<applications> - /// <add alias="content" name="content" icon="file" sortOrder="0" /> - /// <add alias="0b486ac9c0f1456996192c6ed1f03e57" name="0b486ac9c0f1456996192c6ed1f03e57" icon="icon.jpg" sortOrder="1" /> - /// <add alias="1ffbc301744c4e75ae3054d741954c7b" name="1ffbc301744c4e75ae3054d741954c7b" icon="icon.jpg" sortOrder="2" /> - /// <add alias="1838c3e1591f4008bbafe59a06a00a31" name="1838c3e1591f4008bbafe59a06a00a31" icon="icon.jpg" sortOrder="3" /> - /// <add alias="e5badae2 [rest of string was truncated]";. - /// - internal static string applications { - get { - return ResourceManager.GetString("applications", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to <?xml version="1.0" encoding="utf-8"?> - ///<trees> - /// <add initialize="false" sortOrder="0" alias="1838c3e1591f4008bbafe59a06a00a31" application="1838c3e1591f4008bbafe59a06a00a31" title="1838c3e1591f4008bbafe59a06a00a31" iconClosed="icon.jpg" iconOpen="icon.jpg" type="nulltype" /> - /// <add initialize="false" sortOrder="0" alias="e5badae2fc5e4cd7acb3700320e33b8b" application="e5badae2fc5e4cd7acb3700320e33b8b" title="e5badae2fc5e4cd7acb3700320e33b8b" iconClosed="icon.jpg" iconOpen="icon.jpg" type="nulltype" /> - /// [rest of string was truncated]";. - /// - internal static string trees { - get { - return ResourceManager.GetString("trees", resourceCulture); - } - } - } -} diff --git a/src/Umbraco.Tests/TreesAndSections/ResourceFiles.resx b/src/Umbraco.Tests/TreesAndSections/ResourceFiles.resx deleted file mode 100644 index fac58dc842..0000000000 --- a/src/Umbraco.Tests/TreesAndSections/ResourceFiles.resx +++ /dev/null @@ -1,127 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - - applications.config;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 - - - trees.config;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 - - \ No newline at end of file diff --git a/src/Umbraco.Tests/TreesAndSections/SectionTests.cs b/src/Umbraco.Tests/TreesAndSections/SectionTests.cs deleted file mode 100644 index 83de6c4479..0000000000 --- a/src/Umbraco.Tests/TreesAndSections/SectionTests.cs +++ /dev/null @@ -1,252 +0,0 @@ -//using System.IO; -//using NUnit.Framework; -//using Umbraco.Core.Services; -//using Umbraco.Tests.TestHelpers; -//using System; -//using Umbraco.Core.Composing; -//using Umbraco.Tests.Testing; -//using Umbraco.Web.Services; - -//namespace Umbraco.Tests.TreesAndSections -//{ -// /// -// ///This is a test class for ApplicationTest and is intended -// ///to contain all ApplicationTest Unit Tests -// /// -// [TestFixture] -// [UmbracoTest(AutoMapper = true, Database = UmbracoTestOptions.Database.NewSchemaPerTest)] -// public class SectionTests : TestWithDatabaseBase -// { -// protected override void Compose() -// { -// base.Compose(); -// Composition.RegisterUnique(); -// } - -// public override void SetUp() -// { -// base.SetUp(); - -// var treesConfig = TestHelper.MapPathForTest("~/TEMP/TreesAndSections/trees.config"); -// var appConfig = TestHelper.MapPathForTest("~/TEMP/TreesAndSections/applications.config"); -// Directory.CreateDirectory(TestHelper.MapPathForTest("~/TEMP/TreesAndSections")); -// using (var writer = File.CreateText(treesConfig)) -// { -// writer.Write(ResourceFiles.trees); -// } -// using (var writer = File.CreateText(appConfig)) -// { -// writer.Write(ResourceFiles.applications); -// } - -// ApplicationTreeService.TreeConfigFilePath = treesConfig; -// SectionService.AppConfigFilePath = appConfig; -// } - -// public override void TearDown() -// { -// base.TearDown(); - -// if (Directory.Exists(TestHelper.MapPathForTest("~/TEMP/TreesAndSections"))) -// { -// Directory.Delete(TestHelper.MapPathForTest("~/TEMP/TreesAndSections"), true); -// } -// ApplicationTreeService.TreeConfigFilePath = null; -// SectionService.AppConfigFilePath = null; -// } - -// ///// -// ///// Create a new application and delete it -// ///// -// //[Test()] -// //public void Application_Make_New() -// //{ -// // var name = Guid.NewGuid().ToString("N"); -// // ServiceContext.SectionService.MakeNew(name, name, "icon.jpg"); - -// // //check if it exists -// // var app = ServiceContext.SectionService.GetByAlias(name); -// // Assert.IsNotNull(app); - -// // //now remove it -// // ServiceContext.SectionService.DeleteSection(app); -// // Assert.IsNull(ServiceContext.SectionService.GetByAlias(name)); -// //} - -// #region Tests to write - - -// ///// -// /////A test for Application Constructor -// ///// -// //[TestMethod()] -// //public void ApplicationConstructorTest() -// //{ -// // string name = string.Empty; // TODO: Initialize to an appropriate value -// // string alias = string.Empty; // TODO: Initialize to an appropriate value -// // string icon = string.Empty; // TODO: Initialize to an appropriate value -// // Application target = new Application(name, alias, icon); -// // Assert.Inconclusive("TODO: Implement code to verify target"); -// //} - -// ///// -// /////A test for Application Constructor -// ///// -// //[TestMethod()] -// //public void ApplicationConstructorTest1() -// //{ -// // Application target = new Application(); -// // Assert.Inconclusive("TODO: Implement code to verify target"); -// //} - -// ///// -// /////A test for Delete -// ///// -// //[TestMethod()] -// //public void DeleteTest() -// //{ -// // Application target = new Application(); // TODO: Initialize to an appropriate value -// // target.Delete(); -// // Assert.Inconclusive("A method that does not return a value cannot be verified."); -// //} - - - -// ///// -// /////A test for MakeNew -// ///// -// //[TestMethod()] -// //public void MakeNewTest1() -// //{ -// // string name = string.Empty; // TODO: Initialize to an appropriate value -// // string alias = string.Empty; // TODO: Initialize to an appropriate value -// // string icon = string.Empty; // TODO: Initialize to an appropriate value -// // Application.MakeNew(name, alias, icon); -// // Assert.Inconclusive("A method that does not return a value cannot be verified."); -// //} - -// ///// -// /////A test for RegisterIApplications -// ///// -// //[TestMethod()] -// //public void RegisterIApplicationsTest() -// //{ -// // Application.RegisterIApplications(); -// // Assert.Inconclusive("A method that does not return a value cannot be verified."); -// //} - -// ///// -// /////A test for getAll -// ///// -// //[TestMethod()] -// //public void getAllTest() -// //{ -// // List expected = null; // TODO: Initialize to an appropriate value -// // List actual; -// // actual = Application.getAll(); -// // Assert.AreEqual(expected, actual); -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} - -// ///// -// /////A test for getByAlias -// ///// -// //[TestMethod()] -// //public void getByAliasTest() -// //{ -// // string appAlias = string.Empty; // TODO: Initialize to an appropriate value -// // Application expected = null; // TODO: Initialize to an appropriate value -// // Application actual; -// // actual = Application.getByAlias(appAlias); -// // Assert.AreEqual(expected, actual); -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} - -// ///// -// /////A test for SqlHelper -// ///// -// //[TestMethod()] -// //public void SqlHelperTest() -// //{ -// // ISqlHelper actual; -// // actual = Application.SqlHelper; -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} - -// ///// -// /////A test for alias -// ///// -// //[TestMethod()] -// //public void aliasTest() -// //{ -// // Application target = new Application(); // TODO: Initialize to an appropriate value -// // string expected = string.Empty; // TODO: Initialize to an appropriate value -// // string actual; -// // target.alias = expected; -// // actual = target.alias; -// // Assert.AreEqual(expected, actual); -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} - -// ///// -// /////A test for icon -// ///// -// //[TestMethod()] -// //public void iconTest() -// //{ -// // Application target = new Application(); // TODO: Initialize to an appropriate value -// // string expected = string.Empty; // TODO: Initialize to an appropriate value -// // string actual; -// // target.icon = expected; -// // actual = target.icon; -// // Assert.AreEqual(expected, actual); -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} - -// ///// -// /////A test for name -// ///// -// //[TestMethod()] -// //public void nameTest() -// //{ -// // Application target = new Application(); // TODO: Initialize to an appropriate value -// // string expected = string.Empty; // TODO: Initialize to an appropriate value -// // string actual; -// // target.name = expected; -// // actual = target.name; -// // Assert.AreEqual(expected, actual); -// // Assert.Inconclusive("Verify the correctness of this test method."); -// //} -// #endregion - -// #region Additional test attributes -// // -// //You can use the following additional attributes as you write your tests: -// // -// //Use ClassInitialize to run code before running the first test in the class -// //[ClassInitialize()] -// //public static void MyClassInitialize(TestContext testContext) -// //{ -// //} -// // -// //Use ClassCleanup to run code after all tests in a class have run -// //[ClassCleanup()] -// //public static void MyClassCleanup() -// //{ -// //} -// // -// //Use TestInitialize to run code before running each test -// //[TestInitialize()] -// //public void MyTestInitialize() -// //{ -// //} -// // -// //Use TestCleanup to run code after each test has run -// //[TestCleanup()] -// //public void MyTestCleanup() -// //{ -// //} -// // -// #endregion -// } -//} diff --git a/src/Umbraco.Tests/TreesAndSections/applications.config b/src/Umbraco.Tests/TreesAndSections/applications.config deleted file mode 100644 index aadd1c5407..0000000000 --- a/src/Umbraco.Tests/TreesAndSections/applications.config +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Umbraco.Tests/TreesAndSections/trees.config b/src/Umbraco.Tests/TreesAndSections/trees.config deleted file mode 100644 index d21fea28a9..0000000000 --- a/src/Umbraco.Tests/TreesAndSections/trees.config +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index e49ba250fa..408b0f96ca 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -423,13 +423,6 @@ - - True - True - ResourceFiles.resx - - - @@ -525,8 +518,6 @@ Designer Always - - Designer @@ -561,10 +552,6 @@ ImportResources.Designer.cs Designer - - ResXFileCodeGenerator - ResourceFiles.Designer.cs - ResXFileCodeGenerator TestFiles.Designer.cs diff --git a/src/Umbraco.Web/Cache/ApplicationTreeCacheRefresher.cs b/src/Umbraco.Web/Cache/ApplicationTreeCacheRefresher.cs deleted file mode 100644 index 4d6740a0b1..0000000000 --- a/src/Umbraco.Web/Cache/ApplicationTreeCacheRefresher.cs +++ /dev/null @@ -1,46 +0,0 @@ -//using System; -//using Umbraco.Core.Cache; - -//namespace Umbraco.Web.Cache -//{ -// public sealed class ApplicationTreeCacheRefresher : CacheRefresherBase -// { -// public ApplicationTreeCacheRefresher(CacheHelper cacheHelper) -// : base(cacheHelper) -// { } - -// #region Define - -// protected override ApplicationTreeCacheRefresher This => this; - -// public static readonly Guid UniqueId = Guid.Parse("0AC6C028-9860-4EA4-958D-14D39F45886E"); - -// public override Guid RefresherUniqueId => UniqueId; - -// public override string Name => "Application Tree Cache Refresher"; - -// #endregion - -// #region Refresher - -// public override void RefreshAll() -// { -// CacheHelper.RuntimeCache.ClearCacheItem(CacheKeys.ApplicationTreeCacheKey); -// base.RefreshAll(); -// } - -// public override void Refresh(int id) -// { -// Remove(id); -// base.Refresh(id); -// } - -// public override void Remove(int id) -// { -// CacheHelper.RuntimeCache.ClearCacheItem(CacheKeys.ApplicationTreeCacheKey); -// base.Remove(id); -// } - -// #endregion -// } -//} diff --git a/src/Umbraco.Web/Cache/DistributedCacheBinder_Handlers.cs b/src/Umbraco.Web/Cache/DistributedCacheBinder_Handlers.cs index 421eb546a4..3a3eb1b8fb 100644 --- a/src/Umbraco.Web/Cache/DistributedCacheBinder_Handlers.cs +++ b/src/Umbraco.Web/Cache/DistributedCacheBinder_Handlers.cs @@ -46,20 +46,6 @@ namespace Umbraco.Web.Cache _logger.Info("Initializing Umbraco internal event handlers for cache refreshing."); - //// bind to application tree events - //Bind(() => ApplicationTreeService.Deleted += ApplicationTreeService_Deleted, - // () => ApplicationTreeService.Deleted -= ApplicationTreeService_Deleted); - //Bind(() => ApplicationTreeService.Updated += ApplicationTreeService_Updated, - // () => ApplicationTreeService.Updated -= ApplicationTreeService_Updated); - //Bind(() => ApplicationTreeService.New += ApplicationTreeService_New, - // () => ApplicationTreeService.New -= ApplicationTreeService_New); - - //// bind to application events - //Bind(() => SectionService.Deleted += SectionService_Deleted, - // () => SectionService.Deleted -= SectionService_Deleted); - //Bind(() => SectionService.New += SectionService_New, - // () => SectionService.New -= SectionService_New); - // bind to user and user group events Bind(() => UserService.SavedUserGroup += UserService_SavedUserGroup, () => UserService.SavedUserGroup -= UserService_SavedUserGroup); @@ -231,39 +217,6 @@ namespace Umbraco.Web.Cache #endregion - //#region ApplicationTreeService - - //private void ApplicationTreeService_New(ApplicationTree sender, EventArgs e) - //{ - // _distributedCache.RefreshAllApplicationTreeCache(); - //} - - //private void ApplicationTreeService_Updated(ApplicationTree sender, EventArgs e) - //{ - // _distributedCache.RefreshAllApplicationTreeCache(); - //} - - //private void ApplicationTreeService_Deleted(ApplicationTree sender, EventArgs e) - //{ - // _distributedCache.RefreshAllApplicationTreeCache(); - //} - - //#endregion - - //#region Application event handlers - - //private void SectionService_New(ISectionService sender, EventArgs e) - //{ - // _distributedCache.RefreshAllApplicationCache(); - //} - - //private void SectionService_Deleted(ISectionService sender, EventArgs e) - //{ - // _distributedCache.RefreshAllApplicationCache(); - //} - - //#endregion - #region LocalizationService / Dictionary private void LocalizationService_SavedDictionaryItem(ILocalizationService sender, SaveEventArgs e) diff --git a/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs b/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs index aab0f9b157..80c49e279c 100644 --- a/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs +++ b/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs @@ -18,24 +18,6 @@ namespace Umbraco.Web.Cache #endregion - //#region ApplicationTreeCache - - //public static void RefreshAllApplicationTreeCache(this DistributedCache dc) - //{ - // dc.RefreshAll(ApplicationTreeCacheRefresher.UniqueId); - //} - - //#endregion - - //#region ApplicationCache - - //public static void RefreshAllApplicationCache(this DistributedCache dc) - //{ - // dc.RefreshAll(ApplicationCacheRefresher.UniqueId); - //} - - //#endregion - #region User cache public static void RemoveUserCache(this DistributedCache dc, int userId) @@ -74,7 +56,6 @@ namespace Umbraco.Web.Cache #endregion - #region TemplateCache public static void RefreshTemplateCache(this DistributedCache dc, int templateId) diff --git a/src/Umbraco.Web/Models/ContentEditing/IBackOfficeSection.cs b/src/Umbraco.Web/Models/ContentEditing/IBackOfficeSection.cs deleted file mode 100644 index f27941035a..0000000000 --- a/src/Umbraco.Web/Models/ContentEditing/IBackOfficeSection.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Umbraco.Core.Composing; - -namespace Umbraco.Web.Models.ContentEditing -{ - - /// - /// Defines a back office section - /// - public interface IBackOfficeSection : IDiscoverable - { - string Alias { get; } - string Name { get; } - int SortOrder { get; } - } -} diff --git a/src/Umbraco.Web/Models/Mapping/SectionMapperProfile.cs b/src/Umbraco.Web/Models/Mapping/SectionMapperProfile.cs index 683fce36e8..5aa99e4652 100644 --- a/src/Umbraco.Web/Models/Mapping/SectionMapperProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/SectionMapperProfile.cs @@ -3,6 +3,7 @@ using AutoMapper; using Umbraco.Core.Models.ContentEditing; using Umbraco.Core.Services; using Umbraco.Web.Models.ContentEditing; +using Umbraco.Web.Models.Trees; namespace Umbraco.Web.Models.Mapping { diff --git a/src/Umbraco.Web/Models/Trees/ApplicationDefinitions.cs b/src/Umbraco.Web/Models/Trees/ApplicationDefinitions.cs deleted file mode 100644 index ba48c9e240..0000000000 --- a/src/Umbraco.Web/Models/Trees/ApplicationDefinitions.cs +++ /dev/null @@ -1,77 +0,0 @@ -using Umbraco.Core; -using Umbraco.Core.Models; -using Umbraco.Core.Models.ContentEditing; -using Umbraco.Web.Models.ContentEditing; - -namespace Umbraco.Web.Models.Trees -{ - /// - /// Defines the back office content section - /// - public class ContentBackOfficeSectionDefinition : IBackOfficeSection - { - public string Alias => Constants.Applications.Content; - public string Name => "Content"; - public int SortOrder => 0; - } - - /// - /// Defines the back office media section - /// - public class MediaBackOfficeSectionDefinition : IBackOfficeSection - { - public string Alias => Constants.Applications.Media; - public string Name => "Media"; - public int SortOrder => 1; - } - - /// - /// Defines the back office settings section - /// - public class SettingsBackOfficeSectionDefinition : IBackOfficeSection - { - public string Alias => Constants.Applications.Settings; - public string Name => "Settings"; - public int SortOrder => 2; - } - - /// - /// Defines the back office packages section - /// - public class PackagesBackOfficeSectionDefinition : IBackOfficeSection - { - public string Alias => Constants.Applications.Packages; - public string Name => "Packages"; - public int SortOrder => 3; - } - - /// - /// Defines the back office users section - /// - public class UsersBackOfficeSectionDefinition : IBackOfficeSection - { - public string Alias => Constants.Applications.Users; - public string Name => "Users"; - public int SortOrder => 4; - } - - /// - /// Defines the back office members section - /// - public class MembersBackOfficeSectionDefinition : IBackOfficeSection - { - public string Alias => Constants.Applications.Members; - public string Name => "Members"; - public int SortOrder => 5; - } - - /// - /// Defines the back office translation section - /// - public class TranslationBackOfficeSectionDefinition : IBackOfficeSection - { - public string Alias => Constants.Applications.Translation; - public string Name => "Translation"; - public int SortOrder => 6; - } -} diff --git a/src/Umbraco.Web/Models/Trees/IBackOfficeSection.cs b/src/Umbraco.Web/Models/Trees/IBackOfficeSection.cs new file mode 100644 index 0000000000..0cc505fb19 --- /dev/null +++ b/src/Umbraco.Web/Models/Trees/IBackOfficeSection.cs @@ -0,0 +1,12 @@ +namespace Umbraco.Web.Models.Trees +{ + + /// + /// Defines a back office section + /// + public interface IBackOfficeSection + { + string Alias { get; } + string Name { get; } + } +} diff --git a/src/Umbraco.Web/Models/Trees/SectionRootNode.cs b/src/Umbraco.Web/Models/Trees/TreeRootNode.cs similarity index 100% rename from src/Umbraco.Web/Models/Trees/SectionRootNode.cs rename to src/Umbraco.Web/Models/Trees/TreeRootNode.cs diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs b/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs index 047d080a88..134ed7b1d0 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs @@ -25,6 +25,7 @@ using Umbraco.Web.Features; using Umbraco.Web.HealthCheck; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Models.PublishedContent; +using Umbraco.Web.Models.Trees; using Umbraco.Web.Mvc; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; @@ -195,9 +196,15 @@ namespace Umbraco.Web.Runtime .Append() .Append(); - // register back office sections + // register back office sections in the order we want them rendered composition.WithCollectionBuilder() - .Add(() => composition.TypeLoader.GetTypes()); + .Append() + .Append() + .Append() + .Append() + .Append() + .Append() + .Append(); // register back office trees foreach (var treeControllerType in umbracoApiControllerTypes) diff --git a/src/Umbraco.Web/Services/ISectionService.cs b/src/Umbraco.Web/Services/ISectionService.cs index c325020cf1..f0a16dc965 100644 --- a/src/Umbraco.Web/Services/ISectionService.cs +++ b/src/Umbraco.Web/Services/ISectionService.cs @@ -2,6 +2,7 @@ using Umbraco.Core.Models; using Umbraco.Core.Models.ContentEditing; using Umbraco.Web.Models.ContentEditing; +using Umbraco.Web.Models.Trees; namespace Umbraco.Web.Services { diff --git a/src/Umbraco.Web/Services/ITreeService.cs b/src/Umbraco.Web/Services/ITreeService.cs index ce734cc5e4..17998ae1a7 100644 --- a/src/Umbraco.Web/Services/ITreeService.cs +++ b/src/Umbraco.Web/Services/ITreeService.cs @@ -29,15 +29,7 @@ namespace Umbraco.Web.Services /// The application alias. /// Returns a ApplicationTree Array IEnumerable GetApplicationTrees(string applicationAlias); - - ///// - ///// Gets the application tree for the applcation with the specified alias - ///// - ///// The application alias. - ///// - ///// Returns a ApplicationTree Array - //IEnumerable GetApplicationTrees(string applicationAlias, bool onlyInitialized); - + /// /// Gets the grouped application trees for the application with the specified alias /// diff --git a/src/Umbraco.Web/Services/SectionService.cs b/src/Umbraco.Web/Services/SectionService.cs index bb154976f0..e6af27534c 100644 --- a/src/Umbraco.Web/Services/SectionService.cs +++ b/src/Umbraco.Web/Services/SectionService.cs @@ -25,270 +25,31 @@ namespace Umbraco.Web.Services private readonly IUserService _userService; private readonly BackOfficeSectionCollection _sectionCollection; - private readonly Lazy> _allAvailableSections; - //private readonly IApplicationTreeService _applicationTreeService; - //private readonly IScopeProvider _scopeProvider; - private readonly CacheHelper _cache; - //internal const string AppConfigFileName = "applications.config"; - //private static string _appConfig; - //private static readonly object Locker = new object(); - public SectionService( IUserService userService, - BackOfficeSectionCollection sectionCollection, - CacheHelper cache) + BackOfficeSectionCollection sectionCollection) { - //_applicationTreeService = applicationTreeService ?? throw new ArgumentNullException(nameof(applicationTreeService)); - _cache = cache ?? throw new ArgumentNullException(nameof(cache)); _userService = userService; _sectionCollection = sectionCollection; - //_scopeProvider = scopeProvider; - //_allAvailableSections = new Lazy>(() => new LazyEnumerableSections()); } - - - ///// - ///// gets/sets the application.config file path - ///// - ///// - ///// The setter is generally only going to be used in unit tests, otherwise it will attempt to resolve it using the IOHelper.MapPath - ///// - //internal static string AppConfigFilePath - //{ - // get - // { - // if (string.IsNullOrWhiteSpace(_appConfig)) - // { - // _appConfig = IOHelper.MapPath(SystemDirectories.Config + "/" + AppConfigFileName); - // } - // return _appConfig; - // } - // set => _appConfig = value; - //} - + /// /// The cache storage for all applications /// - public IEnumerable GetSections() - { - return _sectionCollection; - } + public IEnumerable GetSections() => _sectionCollection; - //internal void LoadXml(Func callback, bool saveAfterCallbackIfChanged) - //{ - // lock (Locker) - // { - // var doc = File.Exists(AppConfigFilePath) - // ? XDocument.Load(AppConfigFilePath) - // : XDocument.Parse(""); - - // if (doc.Root != null) - // { - // var changed = callback.Invoke(doc); - - // if (saveAfterCallbackIfChanged && changed) - // { - // //ensure the folder is created! - // Directory.CreateDirectory(Path.GetDirectoryName(AppConfigFilePath)); - - // doc.Save(AppConfigFilePath); - - // //remove the cache so it gets re-read ... SD: I'm leaving this here even though it - // // is taken care of by events as well, I think unit tests may rely on it being cleared here. - // _cache.RuntimeCache.ClearCacheItem(CacheKeys.ApplicationsCacheKey); - // } - // } - // } - //} - - /// - /// Get the user's allowed sections - /// - /// - /// + /// public IEnumerable GetAllowedSections(int userId) { - var user = _userService.GetUserById(userId); if (user == null) - { throw new InvalidOperationException("No user found with id " + userId); - } return GetSections().Where(x => user.AllowedSections.Contains(x.Alias)); } - /// - /// Gets the application by its alias. - /// - /// The application alias. - /// - public IBackOfficeSection GetByAlias(string appAlias) - { - return GetSections().FirstOrDefault(t => t.Alias == appAlias); - } - - ///// - ///// Creates a new applcation if no application with the specified alias is found. - ///// - ///// The application name. - ///// The application alias. - ///// The application icon, which has to be located in umbraco/images/tray folder. - //public void MakeNew(string name, string alias, string icon) - //{ - // var sections = GetSections(); - // var nextSortOrder = sections.Any() ? sections.Max(x => x.SortOrder) + 1 : 1; - // MakeNew(name, alias, icon, nextSortOrder); - //} - - ///// - ///// Makes the new. - ///// - ///// The name. - ///// The alias. - ///// The icon. - ///// The sort order. - //public void MakeNew(string name, string alias, string icon, int sortOrder) - //{ - // if (GetSections().All(x => x.Alias != alias)) - // { - // LoadXml(doc => - // { - // doc.Root.Add(new XElement("add", - // new XAttribute("alias", alias), - // new XAttribute("name", name), - // new XAttribute("icon", icon), - // new XAttribute("sortOrder", sortOrder))); - // return true; - // }, true); - - // //raise event - // OnNew(this /*new Section(name, alias, sortOrder)*/, new EventArgs()); - // } - //} - - ///// - ///// Deletes the section - ///// - //public void DeleteSection(Section section) - //{ - // lock (Locker) - // { - // //delete the assigned applications - // using (var scope = _scopeProvider.CreateScope()) - // { - // scope.Database.Execute("delete from umbracoUserGroup2App where app = @appAlias", - // new { appAlias = section.Alias }); - // scope.Complete(); - // } - - // //delete the assigned trees - // var trees = _applicationTreeService.GetApplicationTrees(section.Alias); - // foreach (var t in trees) - // { - // _applicationTreeService.DeleteTree(t); - // } - - // LoadXml(doc => - // { - // doc.Root.Elements("add").Where(x => x.Attribute("alias") != null && x.Attribute("alias").Value == section.Alias) - // .Remove(); - - // return true; - // }, true); - - // //raise event - // OnDeleted(this, new EventArgs()); - // } - //} - - //private List
    ReadFromXmlAndSort() - //{ - // var tmp = new List
    (); - - // LoadXml(doc => - // { - // foreach (var addElement in doc.Root.Elements("add").OrderBy(x => - // { - // var sortOrderAttr = x.Attribute("sortOrder"); - // return sortOrderAttr != null ? Convert.ToInt32(sortOrderAttr.Value) : 0; - // })) - // { - // var sortOrderAttr = addElement.Attribute("sortOrder"); - // tmp.Add(new Section(addElement.Attribute("name").Value, - // addElement.Attribute("alias").Value, - // sortOrderAttr != null ? Convert.ToInt32(sortOrderAttr.Value) : 0)); - // } - // return false; - // }, false); - - // return tmp; - //} - - //internal static event TypedEventHandler Deleted; - //private static void OnDeleted(ISectionService app, EventArgs args) - //{ - // if (Deleted != null) - // { - // Deleted(app, args); - // } - //} - - //internal static event TypedEventHandler New; - //private static void OnNew(ISectionService app, EventArgs args) - //{ - // if (New != null) - // { - // New(app, args); - // } - //} - - ///// - ///// This class is here so that we can provide lazy access to tree scanning for when it is needed - ///// - //private class LazyEnumerableSections : IEnumerable
    - //{ - // public LazyEnumerableSections() - // { - // _lazySections = new Lazy>(() => - // { - // // Load all Applications by attribute and add them to the XML config - - // //don't cache the result of this because it is only used once during app startup, caching will just add a bit more mem overhead for no reason - // var types = Current.TypeLoader.GetTypesWithAttribute(cache: false); // fixme - inject - - // //since applications don't populate their metadata from the attribute and because it is an interface, - // //we need to interrogate the attributes for the data. Would be better to have a base class that contains - // //metadata populated by the attribute. Oh well i guess. - // var attrs = types.Select(x => x.GetCustomAttributes(false).Single()); - // return attrs.Select(x => new Section(x.Name, x.Alias, x.SortOrder)).ToArray(); - // }); - // } - - // private readonly Lazy> _lazySections; - - // /// - // /// Returns an enumerator that iterates through the collection. - // /// - // /// - // /// A that can be used to iterate through the collection. - // /// - // public IEnumerator
    GetEnumerator() - // { - // return _lazySections.Value.GetEnumerator(); - // } - - // /// - // /// Returns an enumerator that iterates through a collection. - // /// - // /// - // /// An object that can be used to iterate through the collection. - // /// - // IEnumerator IEnumerable.GetEnumerator() - // { - // return GetEnumerator(); - // } - //} - + /// + public IBackOfficeSection GetByAlias(string appAlias) => GetSections().FirstOrDefault(t => t.Alias == appAlias); + } } diff --git a/src/Umbraco.Web/Services/TreeService.cs b/src/Umbraco.Web/Services/TreeService.cs index cf010f1480..670f57ce49 100644 --- a/src/Umbraco.Web/Services/TreeService.cs +++ b/src/Umbraco.Web/Services/TreeService.cs @@ -1,237 +1,22 @@ using System; -using System.Collections; using System.Collections.Generic; -using System.IO; using System.Linq; -using System.Xml.Linq; using Umbraco.Core; -using Umbraco.Core.Cache; -using Umbraco.Core.Events; -using Umbraco.Core.IO; -using Umbraco.Core.Logging; -using Umbraco.Core.Models; -using Umbraco.Core.Composing; -using Umbraco.Core.Models.ContentEditing; -using Umbraco.Core.Services; -using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Trees; namespace Umbraco.Web.Services { internal class TreeService : ITreeService { - private readonly ILogger _logger; private readonly TreeCollection _treeCollection; - private static readonly object Locker = new object(); private readonly Lazy>> _groupedTrees; - public TreeService(ILogger logger, TreeCollection treeCollection) + public TreeService(TreeCollection treeCollection) { - _logger = logger; _treeCollection = treeCollection; _groupedTrees = new Lazy>>(InitGroupedTrees); } - ///// - ///// gets/sets the trees.config file path - ///// - ///// - ///// The setter is generally only going to be used in unit tests, otherwise it will attempt to resolve it using the IOHelper.MapPath - ///// - //internal static string TreeConfigFilePath - //{ - // get - // { - // if (string.IsNullOrWhiteSpace(_treeConfig)) - // { - // _treeConfig = IOHelper.MapPath(SystemDirectories.Config + "/" + TreeConfigFileName); - // } - // return _treeConfig; - // } - // set { _treeConfig = value; } - //} - - ///// - ///// The main entry point to get application trees - ///// - ///// - ///// This lazily on first access will scan for plugin trees and ensure the trees.config is up-to-date with the plugins. If plugins - ///// haven't changed on disk then the file will not be saved. The trees are all then loaded from this config file into cache and returned. - ///// - //private List GetAppTrees() - //{ - // return _cache.RuntimeCache.GetCacheItem>( - // CacheKeys.ApplicationTreeCacheKey, - // () => - // { - // var list = ReadFromXmlAndSort(); - - // //now we can check the non-volatile flag - // if (_allAvailableTrees != null) - // { - // var hasChanges = false; - - // LoadXml(doc => - // { - // //Now, load in the xml structure and update it with anything that is not declared there and save the file. - - // //NOTE: On the first iteration here, it will lazily scan all trees, etc... this is because this ienumerable is lazy - // // based on the ApplicationTreeRegistrar - and as noted there this is not an ideal way to do things but were stuck like this - // // currently because of the legacy assemblies and types not in the Core. - - // //Get all the trees not registered in the config (those not matching by alias casing will be detected as "unregistered") - // var unregistered = _allAvailableTrees.Value - // .Where(x => list.Any(l => l.Alias == x.Alias) == false) - // .ToArray(); - - // hasChanges = unregistered.Any(); - - // if (hasChanges == false) return false; - - // //add or edit the unregistered ones and re-save the file if any changes were found - // var count = 0; - // foreach (var tree in unregistered) - // { - // var existingElement = doc.Root.Elements("add").SingleOrDefault(x => - // string.Equals(x.Attribute("alias").Value, tree.Alias, - // StringComparison.InvariantCultureIgnoreCase) && - // string.Equals(x.Attribute("application").Value, tree.ApplicationAlias, - // StringComparison.InvariantCultureIgnoreCase)); - // if (existingElement != null) - // { - // existingElement.SetAttributeValue("alias", tree.Alias); - // } - // else - // { - // if (tree.Title.IsNullOrWhiteSpace()) - // { - // doc.Root.Add(new XElement("add", - // new XAttribute("initialize", tree.Initialize), - // new XAttribute("sortOrder", tree.SortOrder), - // new XAttribute("alias", tree.Alias), - // new XAttribute("application", tree.ApplicationAlias), - // new XAttribute("iconClosed", tree.IconClosed), - // new XAttribute("iconOpen", tree.IconOpened), - // new XAttribute("type", tree.Type))); - // } - // else - // { - // doc.Root.Add(new XElement("add", - // new XAttribute("initialize", tree.Initialize), - // new XAttribute("sortOrder", tree.SortOrder), - // new XAttribute("alias", tree.Alias), - // new XAttribute("application", tree.ApplicationAlias), - // new XAttribute("title", tree.Title), - // new XAttribute("iconClosed", tree.IconClosed), - // new XAttribute("iconOpen", tree.IconOpened), - // new XAttribute("type", tree.Type))); - // } - - // } - // count++; - // } - - // //don't save if there's no changes - // return count > 0; - // }, true); - - // if (hasChanges) - // { - // //If there were changes, we need to re-read the structures from the XML - // list = ReadFromXmlAndSort(); - // } - // } - - // return list; - // }, new TimeSpan(0, 10, 0)); - //} - - ///// - ///// Creates a new application tree. - ///// - ///// if set to true [initialize]. - ///// The sort order. - ///// The application alias. - ///// The alias. - ///// The title. - ///// The icon closed. - ///// The icon opened. - ///// The type. - //public void MakeNew(bool initialize, int sortOrder, string applicationAlias, string alias, string title, string iconClosed, string iconOpened, string type) - //{ - // LoadXml(doc => - // { - // var el = doc.Root.Elements("add").SingleOrDefault(x => x.Attribute("alias").Value == alias && x.Attribute("application").Value == applicationAlias); - - // if (el == null) - // { - // doc.Root.Add(new XElement("add", - // new XAttribute("initialize", initialize), - // new XAttribute("sortOrder", sortOrder), - // new XAttribute("alias", alias), - // new XAttribute("application", applicationAlias), - // new XAttribute("title", title), - // new XAttribute("iconClosed", iconClosed), - // new XAttribute("iconOpen", iconOpened), - // new XAttribute("type", type))); - // } - - // return true; - - // }, true); - - // OnNew(new ApplicationTree(initialize, sortOrder, applicationAlias, alias, title, iconClosed, iconOpened, type), new EventArgs()); - //} - - ///// - ///// Saves this instance. - ///// - //public void SaveTree(ApplicationTree tree) - //{ - // LoadXml(doc => - // { - // var el = doc.Root.Elements("add").SingleOrDefault(x => x.Attribute("alias").Value == tree.Alias && x.Attribute("application").Value == tree.ApplicationAlias); - - // if (el != null) - // { - // el.RemoveAttributes(); - - // el.Add(new XAttribute("initialize", tree.Initialize)); - // el.Add(new XAttribute("sortOrder", tree.SortOrder)); - // el.Add(new XAttribute("alias", tree.Alias)); - // el.Add(new XAttribute("application", tree.ApplicationAlias)); - // el.Add(new XAttribute("title", tree.Title)); - // el.Add(new XAttribute("iconClosed", tree.IconClosed)); - // el.Add(new XAttribute("iconOpen", tree.IconOpened)); - // el.Add(new XAttribute("type", tree.Type)); - // } - - // return true; - - // }, true); - - // OnUpdated(tree, new EventArgs()); - //} - - ///// - ///// Deletes this instance. - ///// - //public void DeleteTree(ApplicationTree tree) - //{ - // LoadXml(doc => - // { - // doc.Root.Elements("add") - // .Where(x => x.Attribute("application") != null - // && x.Attribute("application").Value == tree.ApplicationAlias - // && x.Attribute("alias") != null && x.Attribute("alias").Value == tree.Alias).Remove(); - - // return true; - - // }, true); - - // OnDeleted(tree, new EventArgs()); - //} - /// public ApplicationTree GetByAlias(string treeAlias) => _treeCollection.FirstOrDefault(t => t.TreeAlias == treeAlias); @@ -242,26 +27,6 @@ namespace Umbraco.Web.Services public IEnumerable GetApplicationTrees(string applicationAlias) => GetAll().Where(x => x.ApplicationAlias.InvariantEquals(applicationAlias)).OrderBy(x => x.SortOrder).ToList(); - ///// - ///// Gets the application tree for the applcation with the specified alias - ///// - ///// The application alias. - ///// - ///// Returns a ApplicationTree Array - //public IEnumerable GetApplicationTrees(string applicationAlias, bool onlyInitialized) - //{ - // var list = GetAppTrees().FindAll( - // t => - // { - // if (onlyInitialized) - // return (t.ApplicationAlias == applicationAlias && t.Initialize); - // return (t.ApplicationAlias == applicationAlias); - // } - // ); - - // return list.OrderBy(x => x.SortOrder).ToArray(); - //} - public IDictionary> GetGroupedApplicationTrees(string applicationAlias) { var result = new Dictionary>(); @@ -273,11 +38,10 @@ namespace Umbraco.Web.Services { foreach(var treeAliasInGroup in treeGroup) { - if (tree.TreeAlias == treeAliasInGroup) - { - if (resultGroup == null) resultGroup = new List(); - resultGroup.Add(tree); - } + if (tree.TreeAlias != treeAliasInGroup) continue; + + if (resultGroup == null) resultGroup = new List(); + resultGroup.Add(tree); } } if (resultGroup != null) @@ -302,169 +66,5 @@ namespace Umbraco.Web.Services return result; } - ///// - ///// Loads in the xml structure from disk if one is found, otherwise loads in an empty xml structure, calls the - ///// callback with the xml document and saves the structure back to disk if saveAfterCallback is true. - ///// - ///// - ///// - //internal void LoadXml(Func callback, bool saveAfterCallbackIfChanges) - //{ - // lock (Locker) - // { - // var doc = System.IO.File.Exists(TreeConfigFilePath) - // ? XDocument.Load(TreeConfigFilePath) - // : XDocument.Parse(""); - - // if (doc.Root != null) - // { - // var hasChanges = callback.Invoke(doc); - - // if (saveAfterCallbackIfChanges && hasChanges - // //Don't save it if it is empty, in some very rare cases if the app domain get's killed in the middle of this process - // // in some insane way the file saved will be empty. I'm pretty sure it's not actually anything to do with the xml doc and - // // more about the IO trying to save the XML doc, but it doesn't hurt to check. - // && doc.Root != null && doc.Root.Elements().Any()) - // { - // //ensures the folder exists - // Directory.CreateDirectory(Path.GetDirectoryName(TreeConfigFilePath)); - - // //saves it - // doc.Save(TreeConfigFilePath); - - // //remove the cache now that it has changed SD: I'm leaving this here even though it - // // is taken care of by events as well, I think unit tests may rely on it being cleared here. - // _cache.RuntimeCache.ClearCacheItem(CacheKeys.ApplicationTreeCacheKey); - // } - // } - // } - //} - - //private List ReadFromXmlAndSort() - //{ - // var list = new List(); - - // //read in the xml file containing trees and convert them all to ApplicationTree instances - // LoadXml(doc => - // { - // foreach (var addElement in doc.Root.Elements("add").OrderBy(x => - // { - // var sortOrderAttr = x.Attribute("sortOrder"); - // return sortOrderAttr != null ? Convert.ToInt32(sortOrderAttr.Value) : 0; - // })) - // { - // var applicationAlias = (string)addElement.Attribute("application"); - // var type = (string)addElement.Attribute("type"); - // var assembly = (string)addElement.Attribute("assembly"); - - // var clrType = Type.GetType(type); - // if (clrType == null) - // { - // _logger.Warn("The tree definition: {AddElement} could not be resolved to a .Net object type", addElement); - // continue; - // } - - // //check if the tree definition (applicationAlias + type + assembly) is already in the list - - // if (list.Any(tree => tree.ApplicationAlias.InvariantEquals(applicationAlias) && tree.GetRuntimeType() == clrType) == false) - // { - // list.Add(new ApplicationTree( - // addElement.Attribute("initialize") == null || Convert.ToBoolean(addElement.Attribute("initialize").Value), - // addElement.Attribute("sortOrder") != null - // ? Convert.ToByte(addElement.Attribute("sortOrder").Value) - // : (byte)0, - // (string)addElement.Attribute("application"), - // (string)addElement.Attribute("alias"), - // (string)addElement.Attribute("title"), - // (string)addElement.Attribute("iconClosed"), - // (string)addElement.Attribute("iconOpen"), - // (string)addElement.Attribute("type"))); - // } - // } - - // return false; - - // }, false); - - // return list; - //} - - - //internal static event TypedEventHandler Deleted; - //private static void OnDeleted(ApplicationTree app, EventArgs args) - //{ - // if (Deleted != null) - // { - // Deleted(app, args); - // } - //} - - //internal static event TypedEventHandler New; - //private static void OnNew(ApplicationTree app, EventArgs args) - //{ - // if (New != null) - // { - // New(app, args); - // } - //} - - //internal static event TypedEventHandler Updated; - //private static void OnUpdated(ApplicationTree app, EventArgs args) - //{ - // if (Updated != null) - // { - // Updated(app, args); - // } - //} - - ///// - ///// This class is here so that we can provide lazy access to tree scanning for when it is needed - ///// - //private class LazyEnumerableTrees : IEnumerable - //{ - // public LazyEnumerableTrees(TypeLoader typeLoader) - // { - // _lazyTrees = new Lazy>(() => - // { - // var added = new List(); - - // // Load all Controller Trees by attribute - // var types = typeLoader.GetTypesWithAttribute(); // fixme inject - // //convert them to ApplicationTree instances - // var items = types - // .Select(x => (tree: x, treeAttribute: x.GetCustomAttributes(false).Single())) - // .Select(x => new ApplicationTree(x.treeAttribute.Initialize, x.treeAttribute.SortOrder, x.treeAttribute.ApplicationAlias, x.treeAttribute.Alias, x.treeAttribute.Title, x.treeAttribute.IconClosed, x.treeAttribute.IconOpen, x.tree.GetFullNameWithAssembly())) - // .ToArray(); - - // added.AddRange(items.Select(x => x.Alias)); - - // return items.ToArray(); - // }); - // } - - // private readonly Lazy> _lazyTrees; - - // /// - // /// Returns an enumerator that iterates through the collection. - // /// - // /// - // /// A that can be used to iterate through the collection. - // /// - // public IEnumerator GetEnumerator() - // { - // return _lazyTrees.Value.GetEnumerator(); - // } - - // /// - // /// Returns an enumerator that iterates through a collection. - // /// - // /// - // /// An object that can be used to iterate through the collection. - // /// - // IEnumerator IEnumerable.GetEnumerator() - // { - // return GetEnumerator(); - // } - //} } } diff --git a/src/Umbraco.Web/Trees/BackOfficeSectionCollection.cs b/src/Umbraco.Web/Trees/BackOfficeSectionCollection.cs index 2b5a78d758..54762e73d8 100644 --- a/src/Umbraco.Web/Trees/BackOfficeSectionCollection.cs +++ b/src/Umbraco.Web/Trees/BackOfficeSectionCollection.cs @@ -2,6 +2,7 @@ using Umbraco.Core.Composing; using Umbraco.Core.Models.ContentEditing; using Umbraco.Web.Models.ContentEditing; +using Umbraco.Web.Models.Trees; namespace Umbraco.Web.Trees { @@ -11,11 +12,4 @@ namespace Umbraco.Web.Trees : base(items) { } } - - public class BackOfficeSectionCollectionBuilder : LazyCollectionBuilderBase - { - protected override BackOfficeSectionCollectionBuilder This => this; - - //TODO: can we allow for re-ordering OOTB without exposing other methods? - } } diff --git a/src/Umbraco.Web/Trees/BackOfficeSectionCollectionBuilder.cs b/src/Umbraco.Web/Trees/BackOfficeSectionCollectionBuilder.cs new file mode 100644 index 0000000000..62d61a4090 --- /dev/null +++ b/src/Umbraco.Web/Trees/BackOfficeSectionCollectionBuilder.cs @@ -0,0 +1,10 @@ +using Umbraco.Core.Composing; +using Umbraco.Web.Models.Trees; + +namespace Umbraco.Web.Trees +{ + public class BackOfficeSectionCollectionBuilder : OrderedCollectionBuilderBase + { + protected override BackOfficeSectionCollectionBuilder This => this; + } +} diff --git a/src/Umbraco.Web/Trees/ContentBackOfficeSection.cs b/src/Umbraco.Web/Trees/ContentBackOfficeSection.cs new file mode 100644 index 0000000000..0109a6916d --- /dev/null +++ b/src/Umbraco.Web/Trees/ContentBackOfficeSection.cs @@ -0,0 +1,15 @@ +using Umbraco.Core; +using Umbraco.Web.Models.ContentEditing; +using Umbraco.Web.Models.Trees; + +namespace Umbraco.Web.Trees +{ + /// + /// Defines the back office content section + /// + public class ContentBackOfficeSection : IBackOfficeSection + { + public string Alias => Constants.Applications.Content; + public string Name => "Content"; + } +} diff --git a/src/Umbraco.Web/Trees/ITree.cs b/src/Umbraco.Web/Trees/ITree.cs index 40be7338b0..f408ce5e60 100644 --- a/src/Umbraco.Web/Trees/ITree.cs +++ b/src/Umbraco.Web/Trees/ITree.cs @@ -1,5 +1,6 @@ namespace Umbraco.Web.Trees { + //fixme - we don't really use this, it is nice to have the treecontroller, attribute and ApplicationTree streamlined to implement this but it's not used public interface ITree { /// diff --git a/src/Umbraco.Web/Trees/MediaBackOfficeSection.cs b/src/Umbraco.Web/Trees/MediaBackOfficeSection.cs new file mode 100644 index 0000000000..aac4fd036f --- /dev/null +++ b/src/Umbraco.Web/Trees/MediaBackOfficeSection.cs @@ -0,0 +1,15 @@ +using Umbraco.Core; +using Umbraco.Web.Models.ContentEditing; +using Umbraco.Web.Models.Trees; + +namespace Umbraco.Web.Trees +{ + /// + /// Defines the back office media section + /// + public class MediaBackOfficeSection : IBackOfficeSection + { + public string Alias => Constants.Applications.Media; + public string Name => "Media"; + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Trees/MembersBackOfficeSection.cs b/src/Umbraco.Web/Trees/MembersBackOfficeSection.cs new file mode 100644 index 0000000000..bfaead33d5 --- /dev/null +++ b/src/Umbraco.Web/Trees/MembersBackOfficeSection.cs @@ -0,0 +1,15 @@ +using Umbraco.Core; +using Umbraco.Web.Models.ContentEditing; +using Umbraco.Web.Models.Trees; + +namespace Umbraco.Web.Trees +{ + /// + /// Defines the back office members section + /// + public class MembersBackOfficeSection : IBackOfficeSection + { + public string Alias => Constants.Applications.Members; + public string Name => "Members"; + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Trees/PackagesBackOfficeSection.cs b/src/Umbraco.Web/Trees/PackagesBackOfficeSection.cs new file mode 100644 index 0000000000..41f049c092 --- /dev/null +++ b/src/Umbraco.Web/Trees/PackagesBackOfficeSection.cs @@ -0,0 +1,15 @@ +using Umbraco.Core; +using Umbraco.Web.Models.ContentEditing; +using Umbraco.Web.Models.Trees; + +namespace Umbraco.Web.Trees +{ + /// + /// Defines the back office packages section + /// + public class PackagesBackOfficeSection : IBackOfficeSection + { + public string Alias => Constants.Applications.Packages; + public string Name => "Packages"; + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Trees/SettingsBackOfficeSection.cs b/src/Umbraco.Web/Trees/SettingsBackOfficeSection.cs new file mode 100644 index 0000000000..623f593c30 --- /dev/null +++ b/src/Umbraco.Web/Trees/SettingsBackOfficeSection.cs @@ -0,0 +1,15 @@ +using Umbraco.Core; +using Umbraco.Web.Models.ContentEditing; +using Umbraco.Web.Models.Trees; + +namespace Umbraco.Web.Trees +{ + /// + /// Defines the back office settings section + /// + public class SettingsBackOfficeSection : IBackOfficeSection + { + public string Alias => Constants.Applications.Settings; + public string Name => "Settings"; + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Trees/TranslationBackOfficeSection.cs b/src/Umbraco.Web/Trees/TranslationBackOfficeSection.cs new file mode 100644 index 0000000000..41254b3179 --- /dev/null +++ b/src/Umbraco.Web/Trees/TranslationBackOfficeSection.cs @@ -0,0 +1,15 @@ +using Umbraco.Core; +using Umbraco.Web.Models.ContentEditing; +using Umbraco.Web.Models.Trees; + +namespace Umbraco.Web.Trees +{ + /// + /// Defines the back office translation section + /// + public class TranslationBackOfficeSection : IBackOfficeSection + { + public string Alias => Constants.Applications.Translation; + public string Name => "Translation"; + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Trees/TreeCollection.cs b/src/Umbraco.Web/Trees/TreeCollection.cs index c7b60dea16..51b79ce67b 100644 --- a/src/Umbraco.Web/Trees/TreeCollection.cs +++ b/src/Umbraco.Web/Trees/TreeCollection.cs @@ -16,31 +16,4 @@ namespace Umbraco.Web.Trees : base(items) { } } - - public class TreeCollectionBuilder : LazyCollectionBuilderBase - { - protected override TreeCollectionBuilder This => this; - - private readonly List _instances = new List(); - - public void AddTree(ApplicationTree tree) - { - _instances.Add(tree); - } - - protected override IEnumerable CreateItems(IFactory factory) - { - return _instances; - - //var items = base.CreateItems(factory).ToList(); - //throw new NotImplementedException(); - ////validate the items, no actions should exist that do not either expose notifications or permissions - //var invalidItems = items.Where(x => !x.CanBePermissionAssigned && !x.ShowInNotifier).ToList(); - //if (invalidItems.Count == 0) return items; - - //var invalidActions = string.Join(", ", invalidItems.Select(x => "'" + x.Alias + "'")); - //throw new InvalidOperationException($"Invalid actions {invalidActions}'. All {typeof(IAction)} implementations must be true for either {nameof(IAction.CanBePermissionAssigned)} or {nameof(IAction.ShowInNotifier)}."); - } - } - } diff --git a/src/Umbraco.Web/Trees/TreeCollectionBuilder.cs b/src/Umbraco.Web/Trees/TreeCollectionBuilder.cs new file mode 100644 index 0000000000..2f92e72419 --- /dev/null +++ b/src/Umbraco.Web/Trees/TreeCollectionBuilder.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using Umbraco.Core.Composing; + +namespace Umbraco.Web.Trees +{ + //fixme - how will we allow users to modify these items? they will need to be able to change the ApplicationTree's registered (i.e. sort order, section) + public class TreeCollectionBuilder : CollectionBuilderBase + { + private readonly List _instances = new List(); + + public void AddTree(ApplicationTree tree) + { + _instances.Add(tree); + } + + protected override IEnumerable CreateItems(IFactory factory) => _instances; + } +} diff --git a/src/Umbraco.Web/Trees/UsersBackOfficeSection.cs b/src/Umbraco.Web/Trees/UsersBackOfficeSection.cs new file mode 100644 index 0000000000..90a65cb508 --- /dev/null +++ b/src/Umbraco.Web/Trees/UsersBackOfficeSection.cs @@ -0,0 +1,15 @@ +using Umbraco.Core; +using Umbraco.Web.Models.ContentEditing; +using Umbraco.Web.Models.Trees; + +namespace Umbraco.Web.Trees +{ + /// + /// Defines the back office users section + /// + public class UsersBackOfficeSection : IBackOfficeSection + { + public string Alias => Constants.Applications.Users; + public string Name => "Users"; + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 0b1603c9e3..161f6c6689 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -166,8 +166,16 @@ + + + + + + + + - + @@ -591,7 +599,7 @@ - + @@ -673,7 +681,6 @@ - @@ -970,7 +977,7 @@ - + From 77dd816c514e13c487ce6b258af0dbdde4d932cb Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 17 Jan 2019 17:06:22 +1100 Subject: [PATCH 402/469] more cleanup --- .../UI/Pages/UmbracoEnsuredPage.cs | 14 ++--- src/Umbraco.Web/Umbraco.Web.csproj | 1 - .../_Legacy/PackageActions/addApplication.cs | 61 ------------------- 3 files changed, 6 insertions(+), 70 deletions(-) delete mode 100644 src/Umbraco.Web/_Legacy/PackageActions/addApplication.cs diff --git a/src/Umbraco.Web/UI/Pages/UmbracoEnsuredPage.cs b/src/Umbraco.Web/UI/Pages/UmbracoEnsuredPage.cs index 9e632eabc9..cafdfb0e04 100644 --- a/src/Umbraco.Web/UI/Pages/UmbracoEnsuredPage.cs +++ b/src/Umbraco.Web/UI/Pages/UmbracoEnsuredPage.cs @@ -29,14 +29,12 @@ namespace Umbraco.Web.UI.Pages var treeAuth = this.GetType().GetCustomAttribute(true); if (treeAuth != null) { - throw new NotImplementedException(); - - //var treeByAlias = Current.Services.ApplicationTreeService - // .GetByAlias(treeAuth.TreeAlias); - //if (treeByAlias != null) - //{ - // CurrentApp = treeByAlias.ApplicationAlias; - //} + var treeByAlias = Current.TreeService + .GetByAlias(treeAuth.TreeAlias); + if (treeByAlias != null) + { + CurrentApp = treeByAlias.ApplicationAlias; + } } } diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 161f6c6689..8c1a0639c4 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -1138,7 +1138,6 @@ - diff --git a/src/Umbraco.Web/_Legacy/PackageActions/addApplication.cs b/src/Umbraco.Web/_Legacy/PackageActions/addApplication.cs deleted file mode 100644 index c6d5ba30d9..0000000000 --- a/src/Umbraco.Web/_Legacy/PackageActions/addApplication.cs +++ /dev/null @@ -1,61 +0,0 @@ -//using System; -//using System.Xml; -//using System.Xml.Linq; -//using Umbraco.Core; -//using Umbraco.Core._Legacy.PackageActions; -//using Umbraco.Web.Composing; - -//namespace Umbraco.Web._Legacy.PackageActions -//{ -// /// -// /// This class implements the IPackageAction Interface, used to execute code when packages are installed. -// /// All IPackageActions only takes a PackageName and a XmlNode as input, and executes based on the data in the xmlnode. -// /// -// public class AddApplication : IPackageAction -// { - -// #region IPackageAction Members - -// /// -// /// Installs a new application in umbraco. -// /// -// /// Name of the package. -// /// The XML data. -// /// -// /// -// /// -// /// true if successfull -// public bool Execute(string packageName, XElement xmlData) -// { -// string name = xmlData.AttributeValue("appName"); -// string alias = xmlData.AttributeValue("appAlias"); -// string icon = xmlData.AttributeValue("appIcon"); - -// Current.Services.SectionService.MakeNew(name, alias, icon); - -// return true; -// } - -// public bool Undo(string packageName, XElement xmlData) -// { -// string alias = xmlData.AttributeValue("appAlias"); -// var section = Current.Services.SectionService.GetByAlias(alias); -// if (section != null) -// { -// Current.Services.SectionService.DeleteSection(section); -// } -// return true; -// } -// /// -// /// Action alias. -// /// -// /// -// public string Alias() -// { -// return "addApplication"; -// } - -// #endregion - -// } -//} From 9df1773b78d38a3ff59c65193702ef7e3ba73cfe Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 17 Jan 2019 17:08:58 +1100 Subject: [PATCH 403/469] more cleanup --- build/NuSpecs/UmbracoCms.nuspec | 2 -- src/Umbraco.Core/Composing/TypeLoader.cs | 4 +-- src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 11 ------ .../config/applications.Release.config | 11 ------ src/Umbraco.Web.UI/config/applications.config | 11 ------ .../config/trees.Release.config | 34 ------------------ src/Umbraco.Web.UI/config/trees.config | 36 ------------------- 7 files changed, 1 insertion(+), 108 deletions(-) delete mode 100644 src/Umbraco.Web.UI/config/applications.Release.config delete mode 100644 src/Umbraco.Web.UI/config/applications.config delete mode 100644 src/Umbraco.Web.UI/config/trees.Release.config delete mode 100644 src/Umbraco.Web.UI/config/trees.config diff --git a/build/NuSpecs/UmbracoCms.nuspec b/build/NuSpecs/UmbracoCms.nuspec index 3cb3d0d875..a188377c19 100644 --- a/build/NuSpecs/UmbracoCms.nuspec +++ b/build/NuSpecs/UmbracoCms.nuspec @@ -52,10 +52,8 @@ - - diff --git a/src/Umbraco.Core/Composing/TypeLoader.cs b/src/Umbraco.Core/Composing/TypeLoader.cs index acb12ab575..4c4139848d 100644 --- a/src/Umbraco.Core/Composing/TypeLoader.cs +++ b/src/Umbraco.Core/Composing/TypeLoader.cs @@ -185,9 +185,7 @@ namespace Umbraco.Core.Composing // the app code folder and everything in it new Tuple(new DirectoryInfo(IOHelper.MapPath("~/App_Code")), false), // global.asax (the app domain also monitors this, if it changes will do a full restart) - new Tuple(new FileInfo(IOHelper.MapPath("~/global.asax")), false), - // trees.config - use the contents to create the hash since this gets resaved on every app startup! - new Tuple(new FileInfo(IOHelper.MapPath(SystemDirectories.Config + "/trees.config")), true) + new Tuple(new FileInfo(IOHelper.MapPath("~/global.asax")), false) }, _logger); return _currentAssembliesHash; diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index c21bf7fef6..778ab188cd 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -241,9 +241,6 @@ umbracoSettings.config Designer - - trees.config - tinyMceConfig.config Designer @@ -301,14 +298,6 @@ - - - Designer - - - applications.config - Designer - diff --git a/src/Umbraco.Web.UI/config/applications.Release.config b/src/Umbraco.Web.UI/config/applications.Release.config deleted file mode 100644 index 5c8dee3b8a..0000000000 --- a/src/Umbraco.Web.UI/config/applications.Release.config +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/src/Umbraco.Web.UI/config/applications.config b/src/Umbraco.Web.UI/config/applications.config deleted file mode 100644 index 5c8dee3b8a..0000000000 --- a/src/Umbraco.Web.UI/config/applications.config +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/src/Umbraco.Web.UI/config/trees.Release.config b/src/Umbraco.Web.UI/config/trees.Release.config deleted file mode 100644 index bd75e97c38..0000000000 --- a/src/Umbraco.Web.UI/config/trees.Release.config +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Umbraco.Web.UI/config/trees.config b/src/Umbraco.Web.UI/config/trees.config deleted file mode 100644 index 5892545682..0000000000 --- a/src/Umbraco.Web.UI/config/trees.config +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 1a734141f18a6e25493e1b6fef7ab0188b5ec3d6 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 17 Jan 2019 17:31:29 +1100 Subject: [PATCH 404/469] Allows package manifest to declare a section --- src/Umbraco.Core/Manifest/ManifestParser.cs | 7 +++- src/Umbraco.Core/Manifest/PackageManifest.cs | 7 ++++ .../Manifest/ManifestParserTests.cs | 18 ++++++++++ src/Umbraco.Web/Services/SectionService.cs | 13 ------- .../Trees/BackOfficeSectionCollection.cs | 1 + .../BackOfficeSectionCollectionBuilder.cs | 35 ++++++++++++++++++- 6 files changed, 66 insertions(+), 15 deletions(-) diff --git a/src/Umbraco.Core/Manifest/ManifestParser.cs b/src/Umbraco.Core/Manifest/ManifestParser.cs index 59753df66a..28493fe20f 100644 --- a/src/Umbraco.Core/Manifest/ManifestParser.cs +++ b/src/Umbraco.Core/Manifest/ManifestParser.cs @@ -101,6 +101,7 @@ namespace Umbraco.Core.Manifest var gridEditors = new List(); var contentApps = new List(); var dashboards = new List(); + var sections = new Dictionary(); foreach (var manifest in manifests) { @@ -111,6 +112,9 @@ namespace Umbraco.Core.Manifest if (manifest.GridEditors != null) gridEditors.AddRange(manifest.GridEditors); if (manifest.ContentApps != null) contentApps.AddRange(manifest.ContentApps); if (manifest.Dashboards != null) dashboards.AddRange(manifest.Dashboards); + if (manifest.Sections != null) + foreach (var (key, value) in manifest.Sections) + sections[key] = value; } return new PackageManifest @@ -121,7 +125,8 @@ namespace Umbraco.Core.Manifest ParameterEditors = parameterEditors.ToArray(), GridEditors = gridEditors.ToArray(), ContentApps = contentApps.ToArray(), - Dashboards = dashboards.ToArray() + Dashboards = dashboards.ToArray(), + Sections = sections }; } diff --git a/src/Umbraco.Core/Manifest/PackageManifest.cs b/src/Umbraco.Core/Manifest/PackageManifest.cs index cd806ac847..a0546f3629 100644 --- a/src/Umbraco.Core/Manifest/PackageManifest.cs +++ b/src/Umbraco.Core/Manifest/PackageManifest.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using Newtonsoft.Json; using Umbraco.Core.Models.ContentEditing; using Umbraco.Core.PropertyEditors; @@ -30,5 +31,11 @@ namespace Umbraco.Core.Manifest [JsonProperty("dashboards")] public ManifestDashboardDefinition[] Dashboards { get; set; } = Array.Empty(); + + /// + /// Declares the back office sections that this package installs + /// + [JsonProperty("sections")] + public IReadOnlyDictionary Sections { get; set; } = new Dictionary(); } } diff --git a/src/Umbraco.Tests/Manifest/ManifestParserTests.cs b/src/Umbraco.Tests/Manifest/ManifestParserTests.cs index ce3d1d705c..9970d5f6b0 100644 --- a/src/Umbraco.Tests/Manifest/ManifestParserTests.cs +++ b/src/Umbraco.Tests/Manifest/ManifestParserTests.cs @@ -429,5 +429,23 @@ javascript: ['~/test.js',/*** some note about stuff asd09823-4**09234*/ '~/test2 Assert.AreEqual(1, db1.Sections.Length); Assert.AreEqual("forms", db1.Sections[0]); } + + [Test] + public void CanParseManifest_Sections() + { + const string json = @"{'sections': { + 'content': 'Content', + 'hello': 'World' + } +}"; + + var manifest = _parser.ParseManifest(json); + Assert.AreEqual(2, manifest.Sections.Count); + Assert.AreEqual("content", manifest.Sections.Keys.ElementAt(0)); + Assert.AreEqual("hello", manifest.Sections.Keys.ElementAt(1)); + Assert.AreEqual("Content", manifest.Sections["content"]); + Assert.AreEqual("World", manifest.Sections["hello"]); + + } } } diff --git a/src/Umbraco.Web/Services/SectionService.cs b/src/Umbraco.Web/Services/SectionService.cs index e6af27534c..b17b9f965a 100644 --- a/src/Umbraco.Web/Services/SectionService.cs +++ b/src/Umbraco.Web/Services/SectionService.cs @@ -1,22 +1,9 @@ using System; -using System.Collections; using System.Collections.Generic; -using System.IO; using System.Linq; -using System.Xml.Linq; -using Umbraco.Core; -using Umbraco.Core.Cache; -using Umbraco.Core.Events; -using Umbraco.Core.IO; -using Umbraco.Core.Models; -using Umbraco.Core.Composing; -using Umbraco.Core.Models.ContentEditing; -using Umbraco.Core.Scoping; using Umbraco.Core.Services; -using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Models.Trees; using Umbraco.Web.Trees; -using File = System.IO.File; namespace Umbraco.Web.Services { diff --git a/src/Umbraco.Web/Trees/BackOfficeSectionCollection.cs b/src/Umbraco.Web/Trees/BackOfficeSectionCollection.cs index 54762e73d8..fdeb812363 100644 --- a/src/Umbraco.Web/Trees/BackOfficeSectionCollection.cs +++ b/src/Umbraco.Web/Trees/BackOfficeSectionCollection.cs @@ -11,5 +11,6 @@ namespace Umbraco.Web.Trees public BackOfficeSectionCollection(IEnumerable items) : base(items) { } + } } diff --git a/src/Umbraco.Web/Trees/BackOfficeSectionCollectionBuilder.cs b/src/Umbraco.Web/Trees/BackOfficeSectionCollectionBuilder.cs index 62d61a4090..ec5833f79c 100644 --- a/src/Umbraco.Web/Trees/BackOfficeSectionCollectionBuilder.cs +++ b/src/Umbraco.Web/Trees/BackOfficeSectionCollectionBuilder.cs @@ -1,10 +1,43 @@ -using Umbraco.Core.Composing; +using System.Collections.Generic; +using System.Linq; +using Umbraco.Core.Composing; +using Umbraco.Core.Manifest; +using Umbraco.Core.Models.ContentEditing; using Umbraco.Web.Models.Trees; namespace Umbraco.Web.Trees { + //fixme: how can a developer re-sort the items in this collection ? public class BackOfficeSectionCollectionBuilder : OrderedCollectionBuilderBase { protected override BackOfficeSectionCollectionBuilder This => this; + + // need to inject dependencies in the collection, so override creation + public override BackOfficeSectionCollection CreateCollection(IFactory factory) + { + return new BackOfficeSectionCollection(CreateItems(factory)); + } + + protected override IEnumerable CreateItems(IFactory factory) + { + // 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(); + + return base.CreateItems(factory).Concat(manifestParser.Manifest.Sections.Select(x => new ManifestBackOfficeSection(x.Key, x.Value))); + } + + private class ManifestBackOfficeSection : IBackOfficeSection + { + public ManifestBackOfficeSection(string @alias, string name) + { + Alias = alias; + Name = name; + } + + public string Alias { get; } + public string Name { get; } + } } } From 356209e013f93cf9b7b890a3c7067ce6830dac42 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 17 Jan 2019 17:33:38 +1100 Subject: [PATCH 405/469] renames ApplicationTree to just Tree --- src/Umbraco.Web/Editors/EntityController.cs | 2 +- src/Umbraco.Web/Runtime/WebRuntimeComposer.cs | 2 +- src/Umbraco.Web/Services/ITreeService.cs | 8 ++++---- src/Umbraco.Web/Services/TreeService.cs | 14 +++++++------- src/Umbraco.Web/Trees/ApplicationTreeController.cs | 8 ++++---- .../Trees/{ApplicationTree.cs => Tree.cs} | 4 ++-- src/Umbraco.Web/Trees/TreeCollection.cs | 4 ++-- src/Umbraco.Web/Trees/TreeCollectionBuilder.cs | 8 ++++---- src/Umbraco.Web/Trees/TreeController.cs | 2 +- src/Umbraco.Web/Umbraco.Web.csproj | 2 +- 10 files changed, 27 insertions(+), 27 deletions(-) rename src/Umbraco.Web/Trees/{ApplicationTree.cs => Tree.cs} (91%) diff --git a/src/Umbraco.Web/Editors/EntityController.cs b/src/Umbraco.Web/Editors/EntityController.cs index ca1a6a12bb..e376f9ad5b 100644 --- a/src/Umbraco.Web/Editors/EntityController.cs +++ b/src/Umbraco.Web/Editors/EntityController.cs @@ -148,7 +148,7 @@ namespace Umbraco.Web.Editors var searchableTreeAttribute = searchableTree.Value.SearchableTree.GetType().GetCustomAttribute(false); - result[ApplicationTree.GetRootNodeDisplayName(tree, Services.TextService)] = new TreeSearchResult + result[Tree.GetRootNodeDisplayName(tree, Services.TextService)] = new TreeSearchResult { Results = searchableTree.Value.SearchableTree.Search(query, 200, 0, out var total), TreeAlias = searchableTree.Key, diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs b/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs index 134ed7b1d0..f21c040a37 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs @@ -211,7 +211,7 @@ namespace Umbraco.Web.Runtime { var attribute = treeControllerType.GetCustomAttribute(false); if (attribute == null) continue; - var tree = new ApplicationTree(attribute.SortOrder, attribute.ApplicationAlias, attribute.TreeAlias, attribute.TreeTitle, treeControllerType, attribute.IsSingleNodeTree); + var tree = new Tree(attribute.SortOrder, attribute.ApplicationAlias, attribute.TreeAlias, attribute.TreeTitle, treeControllerType, attribute.IsSingleNodeTree); composition.WithCollectionBuilder().AddTree(tree); } } diff --git a/src/Umbraco.Web/Services/ITreeService.cs b/src/Umbraco.Web/Services/ITreeService.cs index 17998ae1a7..5172e4b7b7 100644 --- a/src/Umbraco.Web/Services/ITreeService.cs +++ b/src/Umbraco.Web/Services/ITreeService.cs @@ -15,27 +15,27 @@ namespace Umbraco.Web.Services /// /// The tree alias. /// An ApplicationTree instance - ApplicationTree GetByAlias(string treeAlias); + Tree GetByAlias(string treeAlias); /// /// Gets all applicationTrees registered in umbraco from the umbracoAppTree table.. /// /// Returns a ApplicationTree Array - IEnumerable GetAll(); + IEnumerable GetAll(); /// /// Gets the application tree for the applcation with the specified alias /// /// The application alias. /// Returns a ApplicationTree Array - IEnumerable GetApplicationTrees(string applicationAlias); + IEnumerable GetApplicationTrees(string applicationAlias); /// /// Gets the grouped application trees for the application with the specified alias /// /// /// - IDictionary> GetGroupedApplicationTrees(string applicationAlias); + IDictionary> GetGroupedApplicationTrees(string applicationAlias); } } diff --git a/src/Umbraco.Web/Services/TreeService.cs b/src/Umbraco.Web/Services/TreeService.cs index 670f57ce49..8389c27a19 100644 --- a/src/Umbraco.Web/Services/TreeService.cs +++ b/src/Umbraco.Web/Services/TreeService.cs @@ -18,29 +18,29 @@ namespace Umbraco.Web.Services } /// - public ApplicationTree GetByAlias(string treeAlias) => _treeCollection.FirstOrDefault(t => t.TreeAlias == treeAlias); + public Tree GetByAlias(string treeAlias) => _treeCollection.FirstOrDefault(t => t.TreeAlias == treeAlias); /// - public IEnumerable GetAll() => _treeCollection; + public IEnumerable GetAll() => _treeCollection; /// - public IEnumerable GetApplicationTrees(string applicationAlias) + public IEnumerable GetApplicationTrees(string applicationAlias) => GetAll().Where(x => x.ApplicationAlias.InvariantEquals(applicationAlias)).OrderBy(x => x.SortOrder).ToList(); - public IDictionary> GetGroupedApplicationTrees(string applicationAlias) + public IDictionary> GetGroupedApplicationTrees(string applicationAlias) { - var result = new Dictionary>(); + var result = new Dictionary>(); var foundTrees = GetApplicationTrees(applicationAlias).ToList(); foreach(var treeGroup in _groupedTrees.Value) { - List resultGroup = null; + List resultGroup = null; foreach(var tree in foundTrees) { foreach(var treeAliasInGroup in treeGroup) { if (tree.TreeAlias != treeAliasInGroup) continue; - if (resultGroup == null) resultGroup = new List(); + if (resultGroup == null) resultGroup = new List(); resultGroup.Add(tree); } } diff --git a/src/Umbraco.Web/Trees/ApplicationTreeController.cs b/src/Umbraco.Web/Trees/ApplicationTreeController.cs index 0e405ca3f3..5a0f72c8dc 100644 --- a/src/Umbraco.Web/Trees/ApplicationTreeController.cs +++ b/src/Umbraco.Web/Trees/ApplicationTreeController.cs @@ -160,7 +160,7 @@ namespace Umbraco.Web.Trees /// /// /// - private async Task GetRootForMultipleAppTree(ApplicationTree tree, FormDataCollection queryStrings) + private async Task GetRootForMultipleAppTree(Tree tree, FormDataCollection queryStrings) { if (tree == null) throw new ArgumentNullException(nameof(tree)); try @@ -189,7 +189,7 @@ namespace Umbraco.Web.Trees /// /// /// - private async Task GetRootForSingleAppTree(ApplicationTree tree, string id, FormDataCollection queryStrings, string application) + private async Task GetRootForSingleAppTree(Tree tree, string id, FormDataCollection queryStrings, string application) { var rootId = Constants.System.Root.ToString(CultureInfo.InvariantCulture); if (tree == null) throw new ArgumentNullException(nameof(tree)); @@ -234,7 +234,7 @@ namespace Umbraco.Web.Trees /// /// This ensures that authorization filters are applied to the sub request /// - private async Task> TryGetRootNodeFromControllerTree(ApplicationTree appTree, FormDataCollection formCollection, HttpControllerContext controllerContext) + private async Task> TryGetRootNodeFromControllerTree(Tree appTree, FormDataCollection formCollection, HttpControllerContext controllerContext) { //instantiate it, since we are proxying, we need to setup the instance with our current context var instance = (TreeController)DependencyResolver.Current.GetService(appTree.TreeControllerType); @@ -290,7 +290,7 @@ namespace Umbraco.Web.Trees /// /// /// - private Attempt TryLoadFromControllerTree(ApplicationTree appTree, string id, FormDataCollection formCollection, HttpControllerContext controllerContext) + private Attempt TryLoadFromControllerTree(Tree appTree, string id, FormDataCollection formCollection, HttpControllerContext controllerContext) { // instantiate it, since we are proxying, we need to setup the instance with our current context var instance = (TreeController)DependencyResolver.Current.GetService(appTree.TreeControllerType); diff --git a/src/Umbraco.Web/Trees/ApplicationTree.cs b/src/Umbraco.Web/Trees/Tree.cs similarity index 91% rename from src/Umbraco.Web/Trees/ApplicationTree.cs rename to src/Umbraco.Web/Trees/Tree.cs index 5ed9847be3..3bac5bae58 100644 --- a/src/Umbraco.Web/Trees/ApplicationTree.cs +++ b/src/Umbraco.Web/Trees/Tree.cs @@ -6,9 +6,9 @@ using Umbraco.Web.Models.Trees; namespace Umbraco.Web.Trees { [DebuggerDisplay("Tree - {TreeAlias} ({ApplicationAlias})")] - public class ApplicationTree : ITree + public class Tree : ITree { - public ApplicationTree(int sortOrder, string applicationAlias, string alias, string title, Type treeControllerType, bool isSingleNodeTree) + public Tree(int sortOrder, string applicationAlias, string alias, string title, Type treeControllerType, bool isSingleNodeTree) { SortOrder = sortOrder; ApplicationAlias = applicationAlias; diff --git a/src/Umbraco.Web/Trees/TreeCollection.cs b/src/Umbraco.Web/Trees/TreeCollection.cs index 51b79ce67b..a7bfe52295 100644 --- a/src/Umbraco.Web/Trees/TreeCollection.cs +++ b/src/Umbraco.Web/Trees/TreeCollection.cs @@ -10,9 +10,9 @@ using Umbraco.Web.Models.ContentEditing; namespace Umbraco.Web.Trees { - public class TreeCollection : BuilderCollectionBase + public class TreeCollection : BuilderCollectionBase { - public TreeCollection(IEnumerable items) + public TreeCollection(IEnumerable items) : base(items) { } } diff --git a/src/Umbraco.Web/Trees/TreeCollectionBuilder.cs b/src/Umbraco.Web/Trees/TreeCollectionBuilder.cs index 2f92e72419..143b8e308b 100644 --- a/src/Umbraco.Web/Trees/TreeCollectionBuilder.cs +++ b/src/Umbraco.Web/Trees/TreeCollectionBuilder.cs @@ -4,15 +4,15 @@ using Umbraco.Core.Composing; namespace Umbraco.Web.Trees { //fixme - how will we allow users to modify these items? they will need to be able to change the ApplicationTree's registered (i.e. sort order, section) - public class TreeCollectionBuilder : CollectionBuilderBase + public class TreeCollectionBuilder : CollectionBuilderBase { - private readonly List _instances = new List(); + private readonly List _instances = new List(); - public void AddTree(ApplicationTree tree) + public void AddTree(Tree tree) { _instances.Add(tree); } - protected override IEnumerable CreateItems(IFactory factory) => _instances; + protected override IEnumerable CreateItems(IFactory factory) => _instances; } } diff --git a/src/Umbraco.Web/Trees/TreeController.cs b/src/Umbraco.Web/Trees/TreeController.cs index 63e8f5aad5..553cda255e 100644 --- a/src/Umbraco.Web/Trees/TreeController.cs +++ b/src/Umbraco.Web/Trees/TreeController.cs @@ -28,7 +28,7 @@ namespace Umbraco.Web.Trees } /// - public override string RootNodeDisplayName => ApplicationTree.GetRootNodeDisplayName(this, Services.TextService); + public override string RootNodeDisplayName => Tree.GetRootNodeDisplayName(this, Services.TextService); /// public override string TreeAlias => _attribute.TreeAlias; diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 8c1a0639c4..23cbb7a416 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -174,7 +174,7 @@ - + From 6b9ba3c53c806b2943f531bb71e0fc247ee243e3 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 17 Jan 2019 17:50:59 +1100 Subject: [PATCH 406/469] Fixing tests --- src/Umbraco.Tests/Services/SectionServiceTests.cs | 9 +++------ src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 11 +++++++++++ src/Umbraco.Web/Services/SectionService.cs | 4 ++-- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Tests/Services/SectionServiceTests.cs b/src/Umbraco.Tests/Services/SectionServiceTests.cs index 9211755251..87fcde34ad 100644 --- a/src/Umbraco.Tests/Services/SectionServiceTests.cs +++ b/src/Umbraco.Tests/Services/SectionServiceTests.cs @@ -1,6 +1,7 @@ using NUnit.Framework; using System.Linq; using System.Threading; +using Umbraco.Core.Composing; using Umbraco.Core.Models.Membership; using Umbraco.Tests.Testing; using Umbraco.Web.Services; @@ -15,15 +16,11 @@ namespace Umbraco.Tests.Services [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest, WithApplication = true)] public class SectionServiceTests : TestWithSomeContentBase { - //fixme - private ISectionService SectionService => new SectionService(ServiceContext.UserService, null); - + private ISectionService SectionService => Factory.GetInstance(); [Test] public void SectionService_Can_Get_Allowed_Sections_For_User() { - //fixme - need to mock - // Arrange var user = CreateTestUser(); @@ -60,7 +57,7 @@ namespace Umbraco.Tests.Services Name = "Group B" }; userGroupB.AddAllowedSection("settings"); - userGroupB.AddAllowedSection("developer"); + userGroupB.AddAllowedSection("member"); ServiceContext.UserService.Save(userGroupB, new[] { user.Id }, false); return ServiceContext.UserService.GetUserById(user.Id); diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index 0a0999f2dc..ace50917ba 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -40,6 +40,7 @@ using Umbraco.Web.Composing.Composers; using Umbraco.Web.ContentApps; using Current = Umbraco.Core.Composing.Current; using Umbraco.Web.Routing; +using Umbraco.Web.Trees; namespace Umbraco.Tests.Testing { @@ -216,6 +217,16 @@ namespace Umbraco.Tests.Testing Composition.WithCollectionBuilder(); Composition.RegisterUnique(); Composition.RegisterUnique(); + + // register back office sections in the order we want them rendered + Composition.WithCollectionBuilder().Append() + .Append() + .Append() + .Append() + .Append() + .Append() + .Append(); + Composition.RegisterUnique(); } protected virtual void ComposeWtf() diff --git a/src/Umbraco.Web/Services/SectionService.cs b/src/Umbraco.Web/Services/SectionService.cs index b17b9f965a..089bdc5bd3 100644 --- a/src/Umbraco.Web/Services/SectionService.cs +++ b/src/Umbraco.Web/Services/SectionService.cs @@ -16,8 +16,8 @@ namespace Umbraco.Web.Services IUserService userService, BackOfficeSectionCollection sectionCollection) { - _userService = userService; - _sectionCollection = sectionCollection; + _userService = userService ?? throw new ArgumentNullException(nameof(userService)); + _sectionCollection = sectionCollection ?? throw new ArgumentNullException(nameof(sectionCollection)); } /// From 3f89558ddbc3d37081eb50ce5360f476839499ed Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 17 Jan 2019 17:51:38 +1100 Subject: [PATCH 407/469] Fixing tests --- src/Umbraco.Tests/Composing/TypeFinderTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Tests/Composing/TypeFinderTests.cs b/src/Umbraco.Tests/Composing/TypeFinderTests.cs index 49c807b19f..2b9474310b 100644 --- a/src/Umbraco.Tests/Composing/TypeFinderTests.cs +++ b/src/Umbraco.Tests/Composing/TypeFinderTests.cs @@ -90,7 +90,7 @@ namespace Umbraco.Tests.Composing Assert.AreEqual(0, typesFound.Count()); // 0 classes in _assemblies are marked with [Tree] typesFound = TypeFinder.FindClassesWithAttribute(new[] { typeof (UmbracoContext).Assembly }); - Assert.AreEqual(22, typesFound.Count()); // + classes in Umbraco.Web are marked with [Tree] + Assert.AreEqual(21, typesFound.Count()); // + classes in Umbraco.Web are marked with [Tree] } private static IProfilingLogger GetTestProfilingLogger() From 67e47038217be35969e982195974c5441a518e65 Mon Sep 17 00:00:00 2001 From: Stephan Date: Thu, 17 Jan 2019 08:34:29 +0100 Subject: [PATCH 408/469] CacheHelper becomes AppCaches --- .../Cache/{CacheHelper.cs => AppCaches.cs} | 12 +++--- src/Umbraco.Core/Cache/CacheRefresherBase.cs | 10 ++--- .../Cache/JsonCacheRefresherBase.cs | 4 +- .../Cache/PayloadCacheRefresherBase.cs | 4 +- .../Cache/TypedCacheRefresherBase.cs | 6 +-- .../Composing/Composers/ServicesComposer.cs | 2 +- .../Composing/CompositionExtensions.cs | 4 +- src/Umbraco.Core/Composing/Current.cs | 4 +- .../Implement/AuditEntryRepository.cs | 2 +- .../Repositories/Implement/AuditRepository.cs | 2 +- .../Implement/ConsentRepository.cs | 2 +- .../Implement/ContentRepositoryBase.cs | 2 +- .../Implement/ContentTypeRepository.cs | 2 +- .../Implement/ContentTypeRepositoryBase.cs | 2 +- .../Implement/DataTypeContainerRepository.cs | 2 +- .../Implement/DataTypeRepository.cs | 2 +- .../Implement/DictionaryRepository.cs | 6 +-- .../Implement/DocumentBlueprintRepository.cs | 4 +- .../Implement/DocumentRepository.cs | 14 +++---- .../DocumentTypeContainerRepository.cs | 2 +- .../Implement/DomainRepository.cs | 2 +- .../Implement/EntityContainerRepository.cs | 2 +- .../Implement/ExternalLoginRepository.cs | 2 +- .../Implement/LanguageRepository.cs | 2 +- .../Repositories/Implement/MacroRepository.cs | 2 +- .../Repositories/Implement/MediaRepository.cs | 4 +- .../Implement/MediaTypeContainerRepository.cs | 2 +- .../Implement/MediaTypeRepository.cs | 2 +- .../Implement/MemberGroupRepository.cs | 2 +- .../Implement/MemberRepository.cs | 2 +- .../Implement/MemberTypeRepository.cs | 2 +- .../Implement/NPocoRepositoryBase.cs | 2 +- .../Implement/PermissionRepository.cs | 2 +- .../Implement/PublicAccessRepository.cs | 2 +- .../Implement/RedirectUrlRepository.cs | 2 +- .../Implement/RelationRepository.cs | 2 +- .../Implement/RelationTypeRepository.cs | 2 +- .../Implement/RepositoryBaseOfTIdTEntity.cs | 6 +-- .../Implement/ServerRegistrationRepository.cs | 2 +- .../Implement/SimpleGetRepository.cs | 2 +- .../Repositories/Implement/TagRepository.cs | 2 +- .../Implement/TemplateRepository.cs | 2 +- .../Implement/UserGroupRepository.cs | 10 ++--- .../Repositories/Implement/UserRepository.cs | 10 ++--- src/Umbraco.Core/Runtime/CoreRuntime.cs | 4 +- src/Umbraco.Core/Umbraco.Core.csproj | 2 +- src/Umbraco.Tests/Macros/MacroTests.cs | 2 +- .../Models/Mapping/AutoMapperTests.cs | 2 +- .../Repositories/ContentTypeRepositoryTest.cs | 12 +++--- .../DataTypeDefinitionRepositoryTest.cs | 2 +- .../Repositories/DocumentRepositoryTest.cs | 28 ++++++------- .../Repositories/DomainRepositoryTest.cs | 12 +++--- .../Repositories/LanguageRepositoryTest.cs | 2 +- .../Repositories/MacroRepositoryTest.cs | 36 ++++++++--------- .../Repositories/MediaRepositoryTest.cs | 14 +++---- .../Repositories/MediaTypeRepositoryTest.cs | 4 +- .../Repositories/MemberRepositoryTest.cs | 8 ++-- .../Repositories/MemberTypeRepositoryTest.cs | 2 +- .../PublicAccessRepositoryTest.cs | 24 +++++------ .../RedirectUrlRepositoryTests.cs | 2 +- .../Repositories/RelationRepositoryTest.cs | 4 +- .../RelationTypeRepositoryTest.cs | 4 +- .../ServerRegistrationRepositoryTest.cs | 4 +- .../Repositories/TagRepositoryTest.cs | 18 ++++----- .../Repositories/TemplateRepositoryTest.cs | 10 ++--- .../Repositories/UserGroupRepositoryTest.cs | 4 +- .../Repositories/UserRepositoryTest.cs | 22 +++++----- .../Routing/RenderRouteHandlerTests.cs | 2 +- src/Umbraco.Tests/Runtimes/StandaloneTests.cs | 4 +- .../Scoping/ScopedRepositoryTests.cs | 4 +- .../Services/ContentServicePerformanceTest.cs | 40 +++++++++---------- .../Services/ContentServiceTests.cs | 10 ++--- .../Services/MacroServiceTests.cs | 2 +- .../Templates/TemplateRepositoryTests.cs | 2 +- .../TestControllerActivatorBase.cs | 2 +- src/Umbraco.Tests/TestHelpers/TestObjects.cs | 2 +- .../Testing/TestingTests/MockTests.cs | 4 +- src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 6 +-- .../Web/Mvc/SurfaceControllerTests.cs | 4 +- .../Cache/ApplicationCacheRefresher.cs | 8 ++-- .../Cache/ApplicationTreeCacheRefresher.cs | 8 ++-- .../Cache/ContentCacheRefresher.cs | 20 +++++----- .../Cache/ContentTypeCacheRefresher.cs | 10 ++--- .../Cache/DataTypeCacheRefresher.cs | 6 +-- .../Cache/DictionaryCacheRefresher.cs | 4 +- src/Umbraco.Web/Cache/DomainCacheRefresher.cs | 4 +- .../Cache/LanguageCacheRefresher.cs | 4 +- src/Umbraco.Web/Cache/MacroCacheRefresher.cs | 16 ++++---- src/Umbraco.Web/Cache/MediaCacheRefresher.cs | 10 ++--- src/Umbraco.Web/Cache/MemberCacheRefresher.cs | 12 +++--- .../Cache/MemberGroupCacheRefresher.cs | 6 +-- .../Cache/PublicAccessCacheRefresher.cs | 4 +- .../Cache/RelationTypeCacheRefresher.cs | 8 ++-- .../Cache/TemplateCacheRefresher.cs | 6 +-- src/Umbraco.Web/Cache/UserCacheRefresher.cs | 6 +-- .../Cache/UserGroupCacheRefresher.cs | 8 ++-- .../UserGroupPermissionsCacheRefresher.cs | 4 +- src/Umbraco.Web/CacheHelperExtensions.cs | 12 +++--- src/Umbraco.Web/Composing/Current.cs | 2 +- .../Controllers/UmbLoginController.cs | 2 +- .../Controllers/UmbLoginStatusController.cs | 2 +- .../Controllers/UmbProfileController.cs | 2 +- .../Controllers/UmbRegisterController.cs | 2 +- .../Editors/AuthenticationController.cs | 2 +- .../Editors/BackOfficeController.cs | 2 +- .../Editors/ContentTypeController.cs | 2 +- .../Editors/ContentTypeControllerBase.cs | 2 +- .../Editors/DashboardController.cs | 2 +- .../Editors/MediaTypeController.cs | 2 +- .../Editors/MemberTypeController.cs | 2 +- .../Editors/PackageInstallController.cs | 2 +- .../UmbracoAuthorizedJsonController.cs | 2 +- src/Umbraco.Web/Mvc/PluginController.cs | 6 +-- src/Umbraco.Web/Mvc/RenderMvcController.cs | 2 +- src/Umbraco.Web/Mvc/SurfaceController.cs | 2 +- .../Mvc/UmbracoAuthorizedController.cs | 2 +- src/Umbraco.Web/Mvc/UmbracoController.cs | 6 +-- .../Mvc/UmbracoViewPageOfTModel.cs | 6 +-- src/Umbraco.Web/Runtime/WebRuntime.cs | 2 +- src/Umbraco.Web/Security/MembershipHelper.cs | 4 +- .../Services/ApplicationTreeService.cs | 4 +- src/Umbraco.Web/Services/SectionService.cs | 4 +- src/Umbraco.Web/TagsController.cs | 2 +- .../WebApi/UmbracoApiController.cs | 2 +- .../WebApi/UmbracoApiControllerBase.cs | 6 +-- .../WebApi/UmbracoAuthorizedApiController.cs | 2 +- 126 files changed, 348 insertions(+), 348 deletions(-) rename src/Umbraco.Core/Cache/{CacheHelper.cs => AppCaches.cs} (83%) diff --git a/src/Umbraco.Core/Cache/CacheHelper.cs b/src/Umbraco.Core/Cache/AppCaches.cs similarity index 83% rename from src/Umbraco.Core/Cache/CacheHelper.cs rename to src/Umbraco.Core/Cache/AppCaches.cs index cd2225ae9d..7dd95624ef 100644 --- a/src/Umbraco.Core/Cache/CacheHelper.cs +++ b/src/Umbraco.Core/Cache/AppCaches.cs @@ -6,12 +6,12 @@ namespace Umbraco.Core.Cache /// /// Represents the application-wide caches. /// - public class CacheHelper + public class AppCaches { /// /// Initializes a new instance for use in the web /// - public CacheHelper() + public AppCaches() : this( new HttpRuntimeCacheProvider(HttpRuntime.Cache), new StaticCacheProvider(), @@ -23,7 +23,7 @@ namespace Umbraco.Core.Cache /// /// Initializes a new instance for use in the web /// - public CacheHelper(System.Web.Caching.Cache cache) + public AppCaches(System.Web.Caching.Cache cache) : this( new HttpRuntimeCacheProvider(cache), new StaticCacheProvider(), @@ -35,7 +35,7 @@ namespace Umbraco.Core.Cache /// /// Initializes a new instance based on the provided providers /// - public CacheHelper( + public AppCaches( IRuntimeCacheProvider httpCacheProvider, ICacheProvider staticCacheProvider, ICacheProvider requestCacheProvider, @@ -54,7 +54,7 @@ namespace Umbraco.Core.Cache /// When used by repositories, all cache policies apply, but the underlying caches do not cache anything. /// Used by tests. /// - public static CacheHelper Disabled { get; } = new CacheHelper(NullCacheProvider.Instance, NullCacheProvider.Instance, NullCacheProvider.Instance, new IsolatedRuntimeCache(_ => NullCacheProvider.Instance)); + public static AppCaches Disabled { get; } = new AppCaches(NullCacheProvider.Instance, NullCacheProvider.Instance, NullCacheProvider.Instance, new IsolatedRuntimeCache(_ => NullCacheProvider.Instance)); /// /// Gets the special no-cache instance. @@ -63,7 +63,7 @@ namespace Umbraco.Core.Cache /// When used by repositories, all cache policies are bypassed. /// Used by repositories that do no cache. /// - public static CacheHelper NoCache { get; } = new CacheHelper(NullCacheProvider.Instance, NullCacheProvider.Instance, NullCacheProvider.Instance, new IsolatedRuntimeCache(_ => NullCacheProvider.Instance)); + public static AppCaches NoCache { get; } = new AppCaches(NullCacheProvider.Instance, NullCacheProvider.Instance, NullCacheProvider.Instance, new IsolatedRuntimeCache(_ => NullCacheProvider.Instance)); /// /// Returns the current Request cache diff --git a/src/Umbraco.Core/Cache/CacheRefresherBase.cs b/src/Umbraco.Core/Cache/CacheRefresherBase.cs index 7242ab225e..5e6ec593af 100644 --- a/src/Umbraco.Core/Cache/CacheRefresherBase.cs +++ b/src/Umbraco.Core/Cache/CacheRefresherBase.cs @@ -16,10 +16,10 @@ namespace Umbraco.Core.Cache /// /// Initializes a new instance of the . /// - /// A cache helper. - protected CacheRefresherBase(CacheHelper cacheHelper) + /// A cache helper. + protected CacheRefresherBase(AppCaches appCaches) { - CacheHelper = cacheHelper; + AppCaches = appCaches; } /// @@ -93,7 +93,7 @@ namespace Umbraco.Core.Cache /// /// Gets the cache helper. /// - protected CacheHelper CacheHelper { get; } + protected AppCaches AppCaches { get; } /// /// Clears the cache for all repository entities of a specified type. @@ -102,7 +102,7 @@ namespace Umbraco.Core.Cache protected void ClearAllIsolatedCacheByEntityType() where TEntity : class, IEntity { - CacheHelper.IsolatedRuntimeCache.ClearCache(); + AppCaches.IsolatedRuntimeCache.ClearCache(); } /// diff --git a/src/Umbraco.Core/Cache/JsonCacheRefresherBase.cs b/src/Umbraco.Core/Cache/JsonCacheRefresherBase.cs index 27302f0786..d9d9644a36 100644 --- a/src/Umbraco.Core/Cache/JsonCacheRefresherBase.cs +++ b/src/Umbraco.Core/Cache/JsonCacheRefresherBase.cs @@ -13,8 +13,8 @@ namespace Umbraco.Core.Cache /// /// Initializes a new instance of the . /// - /// A cache helper. - protected JsonCacheRefresherBase(CacheHelper cacheHelper) : base(cacheHelper) + /// A cache helper. + protected JsonCacheRefresherBase(AppCaches appCaches) : base(appCaches) { } /// diff --git a/src/Umbraco.Core/Cache/PayloadCacheRefresherBase.cs b/src/Umbraco.Core/Cache/PayloadCacheRefresherBase.cs index 22bc46e020..4a3a03a0d6 100644 --- a/src/Umbraco.Core/Cache/PayloadCacheRefresherBase.cs +++ b/src/Umbraco.Core/Cache/PayloadCacheRefresherBase.cs @@ -15,8 +15,8 @@ namespace Umbraco.Core.Cache /// /// Initializes a new instance of the . /// - /// A cache helper. - protected PayloadCacheRefresherBase(CacheHelper cacheHelper) : base(cacheHelper) + /// A cache helper. + protected PayloadCacheRefresherBase(AppCaches appCaches) : base(appCaches) { } #region Json diff --git a/src/Umbraco.Core/Cache/TypedCacheRefresherBase.cs b/src/Umbraco.Core/Cache/TypedCacheRefresherBase.cs index 4defc15482..0b5a04b571 100644 --- a/src/Umbraco.Core/Cache/TypedCacheRefresherBase.cs +++ b/src/Umbraco.Core/Cache/TypedCacheRefresherBase.cs @@ -14,9 +14,9 @@ namespace Umbraco.Core.Cache /// /// Initializes a new instance of the . /// - /// A cache helper. - protected TypedCacheRefresherBase(CacheHelper cacheHelper) - : base(cacheHelper) + /// A cache helper. + protected TypedCacheRefresherBase(AppCaches appCaches) + : base(appCaches) { } #region Refresher diff --git a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs index 8c9ccd1088..9ed4a7265c 100644 --- a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs @@ -116,7 +116,7 @@ namespace Umbraco.Core.Composing.Composers return new LocalizedTextServiceFileSources( container.GetInstance(), - container.GetInstance().RuntimeCache, + container.GetInstance().RuntimeCache, mainLangFolder, pluginLangFolders.Concat(userLangFolders)); } diff --git a/src/Umbraco.Core/Composing/CompositionExtensions.cs b/src/Umbraco.Core/Composing/CompositionExtensions.cs index 2307d757c9..910062688c 100644 --- a/src/Umbraco.Core/Composing/CompositionExtensions.cs +++ b/src/Umbraco.Core/Composing/CompositionExtensions.cs @@ -18,7 +18,7 @@ namespace Umbraco.Core.Composing public static void RegisterEssentials(this Composition composition, ILogger logger, IProfiler profiler, IProfilingLogger profilingLogger, IMainDom mainDom, - CacheHelper appCaches, + AppCaches appCaches, IUmbracoDatabaseFactory databaseFactory, TypeLoader typeLoader, IRuntimeState state) @@ -28,7 +28,7 @@ namespace Umbraco.Core.Composing composition.RegisterUnique(profilingLogger); composition.RegisterUnique(mainDom); composition.RegisterUnique(appCaches); - composition.RegisterUnique(factory => factory.GetInstance().RuntimeCache); + composition.RegisterUnique(factory => factory.GetInstance().RuntimeCache); composition.RegisterUnique(databaseFactory); composition.RegisterUnique(factory => factory.GetInstance().SqlContext); composition.RegisterUnique(typeLoader); diff --git a/src/Umbraco.Core/Composing/Current.cs b/src/Umbraco.Core/Composing/Current.cs index 5c8351924f..bfc5cfd51c 100644 --- a/src/Umbraco.Core/Composing/Current.cs +++ b/src/Umbraco.Core/Composing/Current.cs @@ -180,8 +180,8 @@ namespace Umbraco.Core.Composing public static ICultureDictionaryFactory CultureDictionaryFactory => Factory.GetInstance(); - public static CacheHelper ApplicationCache - => Factory.GetInstance(); + public static AppCaches ApplicationCache + => Factory.GetInstance(); public static ServiceContext Services => Factory.GetInstance(); diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/AuditEntryRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/AuditEntryRepository.cs index 77759ea2da..1486935e2a 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/AuditEntryRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/AuditEntryRepository.cs @@ -21,7 +21,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement /// /// Initializes a new instance of the class. /// - public AuditEntryRepository(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger) + public AuditEntryRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger) : base(scopeAccessor, cache, logger) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/AuditRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/AuditRepository.cs index 45f083bc6b..cda89fd89a 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/AuditRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/AuditRepository.cs @@ -15,7 +15,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement internal class AuditRepository : NPocoRepositoryBase, IAuditRepository { public AuditRepository(IScopeAccessor scopeAccessor, ILogger logger) - : base(scopeAccessor, CacheHelper.NoCache, logger) + : base(scopeAccessor, AppCaches.NoCache, logger) { } protected override void PersistNewItem(IAuditItem entity) diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/ConsentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/ConsentRepository.cs index 3794bf183a..bd55654809 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/ConsentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/ConsentRepository.cs @@ -20,7 +20,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement /// /// Initializes a new instance of the class. /// - public ConsentRepository(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger) + public ConsentRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger) : base(scopeAccessor, cache, logger) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentRepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentRepositoryBase.cs index bd7943ff1d..ba56c17087 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentRepositoryBase.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentRepositoryBase.cs @@ -33,7 +33,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement where TEntity : class, IUmbracoEntity where TRepository : class, IRepository { - protected ContentRepositoryBase(IScopeAccessor scopeAccessor, CacheHelper cache, ILanguageRepository languageRepository, ILogger logger) + protected ContentRepositoryBase(IScopeAccessor scopeAccessor, AppCaches cache, ILanguageRepository languageRepository, ILogger logger) : base(scopeAccessor, cache, logger) { LanguageRepository = languageRepository; diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepository.cs index 4bec3160a7..f608e2968d 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepository.cs @@ -19,7 +19,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { private readonly ITemplateRepository _templateRepository; - public ContentTypeRepository(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger, ITemplateRepository templateRepository) + public ContentTypeRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger, ITemplateRepository templateRepository) : base(scopeAccessor, cache, logger) { _templateRepository = templateRepository; diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs index 683df047f8..6404880a2e 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs @@ -28,7 +28,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement internal abstract class ContentTypeRepositoryBase : NPocoRepositoryBase, IReadRepository where TEntity : class, IContentTypeComposition { - protected ContentTypeRepositoryBase(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger) + protected ContentTypeRepositoryBase(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger) : base(scopeAccessor, cache, logger) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/DataTypeContainerRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/DataTypeContainerRepository.cs index f23b6df5e2..752b641bc3 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/DataTypeContainerRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/DataTypeContainerRepository.cs @@ -6,7 +6,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { class DataTypeContainerRepository : EntityContainerRepository, IDataTypeContainerRepository { - public DataTypeContainerRepository(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger) + public DataTypeContainerRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger) : base(scopeAccessor, cache, logger, Constants.ObjectTypes.DataTypeContainer) { } } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/DataTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/DataTypeRepository.cs index 4556c78fe6..28d4262763 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/DataTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/DataTypeRepository.cs @@ -27,7 +27,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement private readonly Lazy _editors; // fixme temp fixing circular dependencies with LAZY but is this the right place? - public DataTypeRepository(IScopeAccessor scopeAccessor, CacheHelper cache, Lazy editors, ILogger logger) + public DataTypeRepository(IScopeAccessor scopeAccessor, AppCaches cache, Lazy editors, ILogger logger) : base(scopeAccessor, cache, logger) { _editors = editors; diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/DictionaryRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/DictionaryRepository.cs index 8f5ad70c32..3517fb3545 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/DictionaryRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/DictionaryRepository.cs @@ -18,7 +18,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement /// internal class DictionaryRepository : NPocoRepositoryBase, IDictionaryRepository { - public DictionaryRepository(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger) + public DictionaryRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger) : base(scopeAccessor, cache, logger) { } @@ -290,7 +290,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { private readonly DictionaryRepository _dictionaryRepository; - public DictionaryByUniqueIdRepository(DictionaryRepository dictionaryRepository, IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger) + public DictionaryByUniqueIdRepository(DictionaryRepository dictionaryRepository, IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger) : base(scopeAccessor, cache, logger) { _dictionaryRepository = dictionaryRepository; @@ -343,7 +343,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { private readonly DictionaryRepository _dictionaryRepository; - public DictionaryByKeyRepository(DictionaryRepository dictionaryRepository, IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger) + public DictionaryByKeyRepository(DictionaryRepository dictionaryRepository, IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger) : base(scopeAccessor, cache, logger) { _dictionaryRepository = dictionaryRepository; diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentBlueprintRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentBlueprintRepository.cs index 1d24cfd2dc..09fa420f26 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentBlueprintRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentBlueprintRepository.cs @@ -17,8 +17,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement /// internal class DocumentBlueprintRepository : DocumentRepository, IDocumentBlueprintRepository { - public DocumentBlueprintRepository(IScopeAccessor scopeAccessor, CacheHelper cacheHelper, ILogger logger, IContentTypeRepository contentTypeRepository, ITemplateRepository templateRepository, ITagRepository tagRepository, ILanguageRepository languageRepository, IContentSection settings) - : base(scopeAccessor, cacheHelper, logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, settings) + public DocumentBlueprintRepository(IScopeAccessor scopeAccessor, AppCaches appCaches, ILogger logger, IContentTypeRepository contentTypeRepository, ITemplateRepository templateRepository, ITagRepository tagRepository, ILanguageRepository languageRepository, IContentSection settings) + : base(scopeAccessor, appCaches, logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, settings) { EnsureUniqueNaming = false; // duplicates are allowed } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs index 054ab8cb4b..31c08f9124 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs @@ -25,20 +25,20 @@ namespace Umbraco.Core.Persistence.Repositories.Implement private readonly IContentTypeRepository _contentTypeRepository; private readonly ITemplateRepository _templateRepository; private readonly ITagRepository _tagRepository; - private readonly CacheHelper _cacheHelper; + private readonly AppCaches _appCaches; private PermissionRepository _permissionRepository; private readonly ContentByGuidReadRepository _contentByGuidReadRepository; private readonly IScopeAccessor _scopeAccessor; - public DocumentRepository(IScopeAccessor scopeAccessor, CacheHelper cacheHelper, ILogger logger, IContentTypeRepository contentTypeRepository, ITemplateRepository templateRepository, ITagRepository tagRepository, ILanguageRepository languageRepository, IContentSection settings) - : base(scopeAccessor, cacheHelper, languageRepository, logger) + public DocumentRepository(IScopeAccessor scopeAccessor, AppCaches appCaches, ILogger logger, IContentTypeRepository contentTypeRepository, ITemplateRepository templateRepository, ITagRepository tagRepository, ILanguageRepository languageRepository, IContentSection settings) + : base(scopeAccessor, appCaches, languageRepository, logger) { _contentTypeRepository = contentTypeRepository ?? throw new ArgumentNullException(nameof(contentTypeRepository)); _templateRepository = templateRepository ?? throw new ArgumentNullException(nameof(templateRepository)); _tagRepository = tagRepository ?? throw new ArgumentNullException(nameof(tagRepository)); - _cacheHelper = cacheHelper; + _appCaches = appCaches; _scopeAccessor = scopeAccessor; - _contentByGuidReadRepository = new ContentByGuidReadRepository(this, scopeAccessor, cacheHelper, logger); + _contentByGuidReadRepository = new ContentByGuidReadRepository(this, scopeAccessor, appCaches, logger); EnsureUniqueNaming = settings.EnsureUniqueNaming; } @@ -48,7 +48,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement // note: is ok to 'new' the repo here as it's a sub-repo really private PermissionRepository PermissionRepository => _permissionRepository - ?? (_permissionRepository = new PermissionRepository(_scopeAccessor, _cacheHelper, Logger)); + ?? (_permissionRepository = new PermissionRepository(_scopeAccessor, _appCaches, Logger)); #region Repository Base @@ -847,7 +847,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { private readonly DocumentRepository _outerRepo; - public ContentByGuidReadRepository(DocumentRepository outerRepo, IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger) + public ContentByGuidReadRepository(DocumentRepository outerRepo, IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger) : base(scopeAccessor, cache, logger) { _outerRepo = outerRepo; diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentTypeContainerRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentTypeContainerRepository.cs index de8042cfcf..d50981e036 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentTypeContainerRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentTypeContainerRepository.cs @@ -6,7 +6,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { class DocumentTypeContainerRepository : EntityContainerRepository, IDocumentTypeContainerRepository { - public DocumentTypeContainerRepository(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger) + public DocumentTypeContainerRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger) : base(scopeAccessor, cache, logger, Constants.ObjectTypes.DocumentTypeContainer) { } } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/DomainRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/DomainRepository.cs index f75d82bd4e..fa06216f9b 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/DomainRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/DomainRepository.cs @@ -16,7 +16,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement internal class DomainRepository : NPocoRepositoryBase, IDomainRepository { - public DomainRepository(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger) + public DomainRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger) : base(scopeAccessor, cache, logger) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/EntityContainerRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/EntityContainerRepository.cs index fae7ae2ebc..09fe949df1 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/EntityContainerRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/EntityContainerRepository.cs @@ -19,7 +19,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { private readonly Guid _containerObjectType; - public EntityContainerRepository(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger, Guid containerObjectType) + public EntityContainerRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger, Guid containerObjectType) : base(scopeAccessor, cache, logger) { var allowedContainers = new[] { Constants.ObjectTypes.DocumentTypeContainer, Constants.ObjectTypes.MediaTypeContainer, Constants.ObjectTypes.DataTypeContainer }; diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/ExternalLoginRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/ExternalLoginRepository.cs index ce9a44f595..7cb78f4c9f 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/ExternalLoginRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/ExternalLoginRepository.cs @@ -16,7 +16,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { internal class ExternalLoginRepository : NPocoRepositoryBase, IExternalLoginRepository { - public ExternalLoginRepository(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger) + public ExternalLoginRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger) : base(scopeAccessor, cache, logger) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/LanguageRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/LanguageRepository.cs index e236670e74..b3f2ff4af0 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/LanguageRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/LanguageRepository.cs @@ -21,7 +21,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement private readonly Dictionary _codeIdMap = new Dictionary(StringComparer.OrdinalIgnoreCase); private readonly Dictionary _idCodeMap = new Dictionary(); - public LanguageRepository(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger) + public LanguageRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger) : base(scopeAccessor, cache, logger) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/MacroRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/MacroRepository.cs index 594f26fa72..565917e078 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/MacroRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/MacroRepository.cs @@ -15,7 +15,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { internal class MacroRepository : NPocoRepositoryBase, IMacroRepository { - public MacroRepository(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger) + public MacroRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger) : base(scopeAccessor, cache, logger) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/MediaRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/MediaRepository.cs index 3e665e321f..f2c7e35395 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/MediaRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/MediaRepository.cs @@ -26,7 +26,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement private readonly ITagRepository _tagRepository; private readonly MediaByGuidReadRepository _mediaByGuidReadRepository; - public MediaRepository(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger, IMediaTypeRepository mediaTypeRepository, ITagRepository tagRepository, IContentSection contentSection, ILanguageRepository languageRepository) + public MediaRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger, IMediaTypeRepository mediaTypeRepository, ITagRepository tagRepository, IContentSection contentSection, ILanguageRepository languageRepository) : base(scopeAccessor, cache, languageRepository, logger) { _mediaTypeRepository = mediaTypeRepository ?? throw new ArgumentNullException(nameof(mediaTypeRepository)); @@ -395,7 +395,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { private readonly MediaRepository _outerRepo; - public MediaByGuidReadRepository(MediaRepository outerRepo, IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger) + public MediaByGuidReadRepository(MediaRepository outerRepo, IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger) : base(scopeAccessor, cache, logger) { _outerRepo = outerRepo; diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/MediaTypeContainerRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/MediaTypeContainerRepository.cs index 318d3a9c5a..68b33e989d 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/MediaTypeContainerRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/MediaTypeContainerRepository.cs @@ -6,7 +6,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { class MediaTypeContainerRepository : EntityContainerRepository, IMediaTypeContainerRepository { - public MediaTypeContainerRepository(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger) + public MediaTypeContainerRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger) : base(scopeAccessor, cache, logger, Constants.ObjectTypes.MediaTypeContainer) { } } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/MediaTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/MediaTypeRepository.cs index 7dc1c29396..4639871a4a 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/MediaTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/MediaTypeRepository.cs @@ -16,7 +16,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement /// internal class MediaTypeRepository : ContentTypeRepositoryBase, IMediaTypeRepository { - public MediaTypeRepository(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger) + public MediaTypeRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger) : base(scopeAccessor, cache, logger) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/MemberGroupRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/MemberGroupRepository.cs index e80faaa44a..11166ce777 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/MemberGroupRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/MemberGroupRepository.cs @@ -15,7 +15,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { internal class MemberGroupRepository : NPocoRepositoryBase, IMemberGroupRepository { - public MemberGroupRepository(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger) + public MemberGroupRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger) : base(scopeAccessor, cache, logger) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/MemberRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/MemberRepository.cs index bfadebd61b..2daa4abeca 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/MemberRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/MemberRepository.cs @@ -24,7 +24,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement private readonly ITagRepository _tagRepository; private readonly IMemberGroupRepository _memberGroupRepository; - public MemberRepository(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger, IMemberTypeRepository memberTypeRepository, IMemberGroupRepository memberGroupRepository, ITagRepository tagRepository, ILanguageRepository languageRepository) + public MemberRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger, IMemberTypeRepository memberTypeRepository, IMemberGroupRepository memberGroupRepository, ITagRepository tagRepository, ILanguageRepository languageRepository) : base(scopeAccessor, cache, languageRepository, logger) { _memberTypeRepository = memberTypeRepository ?? throw new ArgumentNullException(nameof(memberTypeRepository)); diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/MemberTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/MemberTypeRepository.cs index 023e308ad3..b81ce4010b 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/MemberTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/MemberTypeRepository.cs @@ -17,7 +17,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement /// internal class MemberTypeRepository : ContentTypeRepositoryBase, IMemberTypeRepository { - public MemberTypeRepository(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger) + public MemberTypeRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger) : base(scopeAccessor, cache, logger) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/NPocoRepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/NPocoRepositoryBase.cs index df7517469c..234693602f 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/NPocoRepositoryBase.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/NPocoRepositoryBase.cs @@ -21,7 +21,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement /// /// Initializes a new instance of the class. /// - protected NPocoRepositoryBase(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger) + protected NPocoRepositoryBase(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger) : base(scopeAccessor, cache, logger) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/PermissionRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/PermissionRepository.cs index 8261ed2ea3..b4fd86c567 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/PermissionRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/PermissionRepository.cs @@ -25,7 +25,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement internal class PermissionRepository : NPocoRepositoryBase where TEntity : class, IEntity { - public PermissionRepository(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger) + public PermissionRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger) : base(scopeAccessor, cache, logger) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/PublicAccessRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/PublicAccessRepository.cs index f49905573d..bd2580b38f 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/PublicAccessRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/PublicAccessRepository.cs @@ -14,7 +14,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { internal class PublicAccessRepository : NPocoRepositoryBase, IPublicAccessRepository { - public PublicAccessRepository(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger) + public PublicAccessRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger) : base(scopeAccessor, cache, logger) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/RedirectUrlRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/RedirectUrlRepository.cs index 3ca937ffcd..baac02b6bf 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/RedirectUrlRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/RedirectUrlRepository.cs @@ -13,7 +13,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { internal class RedirectUrlRepository : NPocoRepositoryBase, IRedirectUrlRepository { - public RedirectUrlRepository(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger) + public RedirectUrlRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger) : base(scopeAccessor, cache, logger) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/RelationRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/RelationRepository.cs index fb5ba00ea0..c5ba24f385 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/RelationRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/RelationRepository.cs @@ -21,7 +21,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement private readonly IRelationTypeRepository _relationTypeRepository; public RelationRepository(IScopeAccessor scopeAccessor, ILogger logger, IRelationTypeRepository relationTypeRepository) - : base(scopeAccessor, CacheHelper.NoCache, logger) + : base(scopeAccessor, AppCaches.NoCache, logger) { _relationTypeRepository = relationTypeRepository; } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/RelationTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/RelationTypeRepository.cs index e4d8396e71..4faf78bd0a 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/RelationTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/RelationTypeRepository.cs @@ -18,7 +18,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement /// internal class RelationTypeRepository : NPocoRepositoryBase, IRelationTypeRepository { - public RelationTypeRepository(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger) + public RelationTypeRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger) : base(scopeAccessor, cache, logger) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/RepositoryBaseOfTIdTEntity.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/RepositoryBaseOfTIdTEntity.cs index 84c76dbb53..2626f60123 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/RepositoryBaseOfTIdTEntity.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/RepositoryBaseOfTIdTEntity.cs @@ -19,7 +19,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { private IRepositoryCachePolicy _cachePolicy; - protected RepositoryBase(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger) + protected RepositoryBase(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger) { ScopeAccessor = scopeAccessor ?? throw new ArgumentNullException(nameof(scopeAccessor)); Logger = logger ?? throw new ArgumentNullException(nameof(logger)); @@ -28,7 +28,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement protected ILogger Logger { get; } - protected CacheHelper GlobalCache { get; } + protected AppCaches GlobalCache { get; } protected IRuntimeCacheProvider GlobalIsolatedCache => GlobalCache.IsolatedRuntimeCache.GetOrCreateCache(); @@ -127,7 +127,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { get { - if (GlobalCache == CacheHelper.NoCache) + if (GlobalCache == AppCaches.NoCache) return NoCacheRepositoryCachePolicy.Instance; // create the cache policy using IsolatedCache which is either global diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/ServerRegistrationRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/ServerRegistrationRepository.cs index 2679f8f92f..ead7c066be 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/ServerRegistrationRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/ServerRegistrationRepository.cs @@ -15,7 +15,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement internal class ServerRegistrationRepository : NPocoRepositoryBase, IServerRegistrationRepository { public ServerRegistrationRepository(IScopeAccessor scopeAccessor, ILogger logger) - : base(scopeAccessor, CacheHelper.NoCache, logger) + : base(scopeAccessor, AppCaches.NoCache, logger) { } protected override IRepositoryCachePolicy CreateCachePolicy() diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/SimpleGetRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/SimpleGetRepository.cs index 7a3bfdb757..43233d0f31 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/SimpleGetRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/SimpleGetRepository.cs @@ -18,7 +18,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement where TEntity : class, IEntity where TDto: class { - protected SimpleGetRepository(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger) + protected SimpleGetRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger) : base(scopeAccessor, cache, logger) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/TagRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/TagRepository.cs index 77e474be08..7dd3f03407 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/TagRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/TagRepository.cs @@ -17,7 +17,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { internal class TagRepository : NPocoRepositoryBase, ITagRepository { - public TagRepository(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger) + public TagRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger) : base(scopeAccessor, cache, logger) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/TemplateRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/TemplateRepository.cs index 19ef303ebe..bef71b1a51 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/TemplateRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/TemplateRepository.cs @@ -29,7 +29,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement private readonly ViewHelper _viewHelper; private readonly MasterPageHelper _masterPageHelper; - public TemplateRepository(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger, ITemplatesSection templateConfig, IFileSystems fileSystems) + public TemplateRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger, ITemplatesSection templateConfig, IFileSystems fileSystems) : base(scopeAccessor, cache, logger) { _masterpagesFileSystem = fileSystems.MasterPagesFileSystem; diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/UserGroupRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/UserGroupRepository.cs index 91466a0d09..c76a5de0d0 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/UserGroupRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/UserGroupRepository.cs @@ -23,11 +23,11 @@ namespace Umbraco.Core.Persistence.Repositories.Implement private readonly UserGroupWithUsersRepository _userGroupWithUsersRepository; private readonly PermissionRepository _permissionRepository; - public UserGroupRepository(IScopeAccessor scopeAccessor, CacheHelper cacheHelper, ILogger logger) - : base(scopeAccessor, cacheHelper, logger) + public UserGroupRepository(IScopeAccessor scopeAccessor, AppCaches appCaches, ILogger logger) + : base(scopeAccessor, appCaches, logger) { - _userGroupWithUsersRepository = new UserGroupWithUsersRepository(this, scopeAccessor, cacheHelper, logger); - _permissionRepository = new PermissionRepository(scopeAccessor, cacheHelper, logger); + _userGroupWithUsersRepository = new UserGroupWithUsersRepository(this, scopeAccessor, appCaches, logger); + _permissionRepository = new PermissionRepository(scopeAccessor, appCaches, logger); } public const string GetByAliasCacheKeyPrefix = "UserGroupRepository_GetByAlias_"; @@ -360,7 +360,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { private readonly UserGroupRepository _userGroupRepo; - public UserGroupWithUsersRepository(UserGroupRepository userGroupRepo, IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger) + public UserGroupWithUsersRepository(UserGroupRepository userGroupRepo, IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger) : base(scopeAccessor, cache, logger) { _userGroupRepo = userGroupRepo; diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/UserRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/UserRepository.cs index 17fe79a55b..918cc66cb0 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/UserRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/UserRepository.cs @@ -35,22 +35,22 @@ namespace Umbraco.Core.Persistence.Repositories.Implement /// Constructor /// /// - /// + /// /// /// /// A dictionary specifying the configuration for user passwords. If this is null then no password configuration will be persisted or read. /// /// - public UserRepository(IScopeAccessor scopeAccessor, CacheHelper cacheHelper, ILogger logger, IMapperCollection mapperCollection, IGlobalSettings globalSettings) - : base(scopeAccessor, cacheHelper, logger) + public UserRepository(IScopeAccessor scopeAccessor, AppCaches appCaches, ILogger logger, IMapperCollection mapperCollection, IGlobalSettings globalSettings) + : base(scopeAccessor, appCaches, logger) { _mapperCollection = mapperCollection; _globalSettings = globalSettings; } // for tests - internal UserRepository(IScopeAccessor scopeAccessor, CacheHelper cacheHelper, ILogger logger, IMapperCollection mapperCollection, IDictionary passwordConfig, IGlobalSettings globalSettings) - : base(scopeAccessor, cacheHelper, logger) + internal UserRepository(IScopeAccessor scopeAccessor, AppCaches appCaches, ILogger logger, IMapperCollection mapperCollection, IDictionary passwordConfig, IGlobalSettings globalSettings) + : base(scopeAccessor, appCaches, logger) { _mapperCollection = mapperCollection; _globalSettings = globalSettings; diff --git a/src/Umbraco.Core/Runtime/CoreRuntime.cs b/src/Umbraco.Core/Runtime/CoreRuntime.cs index 729e960896..f29109b9d2 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntime.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntime.cs @@ -325,13 +325,13 @@ namespace Umbraco.Core.Runtime /// /// Gets the application caches. /// - protected virtual CacheHelper GetAppCaches() + protected virtual AppCaches GetAppCaches() { // need the deep clone runtime cache provider to ensure entities are cached properly, ie // are cloned in and cloned out - no request-based cache here since no web-based context, // is overriden by the web runtime - return new CacheHelper( + return new AppCaches( new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()), new StaticCacheProvider(), NullCacheProvider.Instance, diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 2236854351..79162c06ad 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -111,7 +111,7 @@ - + diff --git a/src/Umbraco.Tests/Macros/MacroTests.cs b/src/Umbraco.Tests/Macros/MacroTests.cs index 984fb94fab..23e198b778 100644 --- a/src/Umbraco.Tests/Macros/MacroTests.cs +++ b/src/Umbraco.Tests/Macros/MacroTests.cs @@ -21,7 +21,7 @@ namespace Umbraco.Tests.Macros public void Setup() { //we DO want cache enabled for these tests - var cacheHelper = new CacheHelper( + var cacheHelper = new AppCaches( new ObjectCacheRuntimeCacheProvider(), new StaticCacheProvider(), NullCacheProvider.Instance, diff --git a/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs b/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs index 1f7c5624bf..f48abc1233 100644 --- a/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs +++ b/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs @@ -20,7 +20,7 @@ namespace Umbraco.Tests.Models.Mapping base.Compose(); var manifestBuilder = new ManifestParser( - CacheHelper.Disabled.RuntimeCache, + AppCaches.Disabled.RuntimeCache, new ManifestValueValidatorCollection(Enumerable.Empty()), Composition.Logger) { diff --git a/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs index aeaf76967f..34699826ad 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs @@ -35,7 +35,7 @@ namespace Umbraco.Tests.Persistence.Repositories private DocumentRepository CreateRepository(IScopeAccessor scopeAccessor, out ContentTypeRepository contentTypeRepository) { - var cacheHelper = CacheHelper.Disabled; + var cacheHelper = AppCaches.Disabled; var templateRepository = new TemplateRepository(scopeAccessor, cacheHelper, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); var tagRepository = new TagRepository(scopeAccessor, cacheHelper, Logger); contentTypeRepository = new ContentTypeRepository(scopeAccessor, cacheHelper, Logger, templateRepository); @@ -46,20 +46,20 @@ namespace Umbraco.Tests.Persistence.Repositories private ContentTypeRepository CreateRepository(IScopeAccessor scopeAccessor) { - var templateRepository = new TemplateRepository(scopeAccessor, CacheHelper.Disabled, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); - var contentTypeRepository = new ContentTypeRepository(scopeAccessor, CacheHelper.Disabled, Logger, templateRepository); + var templateRepository = new TemplateRepository(scopeAccessor, AppCaches.Disabled, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); + var contentTypeRepository = new ContentTypeRepository(scopeAccessor, AppCaches.Disabled, Logger, templateRepository); return contentTypeRepository; } private MediaTypeRepository CreateMediaTypeRepository(IScopeAccessor scopeAccessor) { - var contentTypeRepository = new MediaTypeRepository(scopeAccessor, CacheHelper.Disabled, Logger); + var contentTypeRepository = new MediaTypeRepository(scopeAccessor, AppCaches.Disabled, Logger); return contentTypeRepository; } private EntityContainerRepository CreateContainerRepository(IScopeAccessor scopeAccessor, Guid containerEntityType) { - return new EntityContainerRepository(scopeAccessor, CacheHelper.Disabled, Logger, containerEntityType); + return new EntityContainerRepository(scopeAccessor, AppCaches.Disabled, Logger, containerEntityType); } //TODO Add test to verify SetDefaultTemplates updates both AllowedTemplates and DefaultTemplate(id). @@ -71,7 +71,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var templateRepo = new TemplateRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); + var templateRepo = new TemplateRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); var repository = CreateRepository((IScopeAccessor) provider); var templates = new[] { diff --git a/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs index ce871d0d0a..b9724b0770 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs @@ -25,7 +25,7 @@ namespace Umbraco.Tests.Persistence.Repositories private EntityContainerRepository CreateContainerRepository(IScopeAccessor scopeAccessor) { - return new EntityContainerRepository(scopeAccessor, CacheHelper.Disabled, Logger, Constants.ObjectTypes.DataTypeContainer); + return new EntityContainerRepository(scopeAccessor, AppCaches.Disabled, Logger, Constants.ObjectTypes.DataTypeContainer); } [Test] diff --git a/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs index c1fa5381ff..772147f5ad 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs @@ -43,39 +43,39 @@ namespace Umbraco.Tests.Persistence.Repositories base.TearDown(); } - private DocumentRepository CreateRepository(IScopeAccessor scopeAccessor, out ContentTypeRepository contentTypeRepository, out DataTypeRepository dtdRepository, CacheHelper cacheHelper = null) + private DocumentRepository CreateRepository(IScopeAccessor scopeAccessor, out ContentTypeRepository contentTypeRepository, out DataTypeRepository dtdRepository, AppCaches appCaches = null) { - cacheHelper = cacheHelper ?? CacheHelper; + appCaches = appCaches ?? AppCaches; TemplateRepository tr; var ctRepository = CreateRepository(scopeAccessor, out contentTypeRepository, out tr); var editors = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty())); - dtdRepository = new DataTypeRepository(scopeAccessor, cacheHelper, new Lazy(() => editors), Logger); + dtdRepository = new DataTypeRepository(scopeAccessor, appCaches, new Lazy(() => editors), Logger); return ctRepository; } - private DocumentRepository CreateRepository(IScopeAccessor scopeAccessor, out ContentTypeRepository contentTypeRepository, CacheHelper cacheHelper = null) + private DocumentRepository CreateRepository(IScopeAccessor scopeAccessor, out ContentTypeRepository contentTypeRepository, AppCaches appCaches = null) { TemplateRepository tr; - return CreateRepository(scopeAccessor, out contentTypeRepository, out tr, cacheHelper); + return CreateRepository(scopeAccessor, out contentTypeRepository, out tr, appCaches); } - private DocumentRepository CreateRepository(IScopeAccessor scopeAccessor, out ContentTypeRepository contentTypeRepository, out TemplateRepository templateRepository, CacheHelper cacheHelper = null) + private DocumentRepository CreateRepository(IScopeAccessor scopeAccessor, out ContentTypeRepository contentTypeRepository, out TemplateRepository templateRepository, AppCaches appCaches = null) { - cacheHelper = cacheHelper ?? CacheHelper; + appCaches = appCaches ?? AppCaches; - templateRepository = new TemplateRepository(scopeAccessor, cacheHelper, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); - var tagRepository = new TagRepository(scopeAccessor, cacheHelper, Logger); - contentTypeRepository = new ContentTypeRepository(scopeAccessor, cacheHelper, Logger, templateRepository); - var languageRepository = new LanguageRepository(scopeAccessor, cacheHelper, Logger); - var repository = new DocumentRepository(scopeAccessor, cacheHelper, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, Mock.Of()); + templateRepository = new TemplateRepository(scopeAccessor, appCaches, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); + var tagRepository = new TagRepository(scopeAccessor, appCaches, Logger); + contentTypeRepository = new ContentTypeRepository(scopeAccessor, appCaches, Logger, templateRepository); + var languageRepository = new LanguageRepository(scopeAccessor, appCaches, Logger); + var repository = new DocumentRepository(scopeAccessor, appCaches, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, Mock.Of()); return repository; } [Test] public void CacheActiveForIntsAndGuids() { - var realCache = new CacheHelper( + var realCache = new AppCaches( new ObjectCacheRuntimeCacheProvider(), new StaticCacheProvider(), new StaticCacheProvider(), @@ -84,7 +84,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = CreateRepository((IScopeAccessor)provider, out var contentTypeRepository, cacheHelper: realCache); + var repository = CreateRepository((IScopeAccessor)provider, out var contentTypeRepository, appCaches: realCache); var udb = (UmbracoDatabase)scope.Database; diff --git a/src/Umbraco.Tests/Persistence/Repositories/DomainRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DomainRepositoryTest.cs index a5402f964e..a64a65047b 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DomainRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DomainRepositoryTest.cs @@ -22,12 +22,12 @@ namespace Umbraco.Tests.Persistence.Repositories private DomainRepository CreateRepository(IScopeProvider provider, out ContentTypeRepository contentTypeRepository, out DocumentRepository documentRepository, out LanguageRepository languageRepository) { var accessor = (IScopeAccessor) provider; - var templateRepository = new TemplateRepository(accessor, Core.Cache.CacheHelper.Disabled, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); - var tagRepository = new TagRepository(accessor, Core.Cache.CacheHelper.Disabled, Logger); - contentTypeRepository = new ContentTypeRepository(accessor, Core.Cache.CacheHelper.Disabled, Logger, templateRepository); - languageRepository = new LanguageRepository(accessor, Core.Cache.CacheHelper.Disabled, Logger); - documentRepository = new DocumentRepository(accessor, Core.Cache.CacheHelper.Disabled, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, Mock.Of()); - var domainRepository = new DomainRepository(accessor, Core.Cache.CacheHelper.Disabled, Logger); + var templateRepository = new TemplateRepository(accessor, Core.Cache.AppCaches.Disabled, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); + var tagRepository = new TagRepository(accessor, Core.Cache.AppCaches.Disabled, Logger); + contentTypeRepository = new ContentTypeRepository(accessor, Core.Cache.AppCaches.Disabled, Logger, templateRepository); + languageRepository = new LanguageRepository(accessor, Core.Cache.AppCaches.Disabled, Logger); + documentRepository = new DocumentRepository(accessor, Core.Cache.AppCaches.Disabled, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, Mock.Of()); + var domainRepository = new DomainRepository(accessor, Core.Cache.AppCaches.Disabled, Logger); return domainRepository; } diff --git a/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs index 2f91c602af..5823537f7a 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs @@ -26,7 +26,7 @@ namespace Umbraco.Tests.Persistence.Repositories private LanguageRepository CreateRepository(IScopeProvider provider) { - return new LanguageRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); + return new LanguageRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of()); } [Test] diff --git a/src/Umbraco.Tests/Persistence/Repositories/MacroRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MacroRepositoryTest.cs index e21debfdfd..6f215f4a35 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MacroRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MacroRepositoryTest.cs @@ -35,7 +35,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); + var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of()); var macro = new Macro("test1", "Test", "~/views/macropartials/test.cshtml", MacroTypes.PartialView); ; @@ -52,7 +52,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); + var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of()); var macro = repository.Get(1); macro.Alias = "test2"; @@ -69,7 +69,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); + var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of()); // Assert Assert.That(repository, Is.Not.Null); @@ -83,7 +83,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); + var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of()); // Act var macro = repository.Get(1); @@ -111,7 +111,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); + var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of()); // Act var macros = repository.GetMany(); @@ -129,7 +129,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); + var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of()); // Act var query = scope.SqlContext.Query().Where(x => x.Alias.ToUpper() == "TEST1"); @@ -147,7 +147,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); + var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of()); // Act var query = scope.SqlContext.Query().Where(x => x.Name.StartsWith("Test")); @@ -165,7 +165,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); + var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of()); // Act var macro = new Macro("test", "Test", "~/views/macropartials/test.cshtml", MacroTypes.PartialView); @@ -186,7 +186,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); + var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of()); // Act var macro = repository.Get(2); @@ -221,7 +221,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); + var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of()); // Act var macro = repository.Get(3); @@ -242,7 +242,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); + var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of()); // Act var exists = repository.Exists(3); @@ -261,7 +261,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); + var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of()); var macro = repository.Get(1); macro.Properties.Add(new MacroProperty("new1", "New1", 3, "test")); @@ -287,7 +287,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); + var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of()); var macro = new Macro("newmacro", "A new macro", "~/views/macropartials/test1.cshtml", MacroTypes.PartialView); macro.Properties.Add(new MacroProperty("blah1", "New1", 4, "test.editor")); @@ -312,7 +312,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); + var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of()); var macro = new Macro("newmacro", "A new macro", "~/views/macropartials/test1.cshtml", MacroTypes.PartialView); macro.Properties.Add(new MacroProperty("blah1", "New1", 4, "test.editor")); @@ -336,7 +336,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); + var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of()); var macro = new Macro("newmacro", "A new macro", "~/views/macropartials/test1.cshtml", MacroTypes.PartialView); var prop1 = new MacroProperty("blah1", "New1", 4, "test.editor"); @@ -367,7 +367,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); + var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of()); var macro = repository.Get(1); macro.Properties.Add(new MacroProperty("new1", "New1", 3, "test")); @@ -394,7 +394,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); + var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of()); var macro = repository.Get(1); macro.Properties.Add(new MacroProperty("new1", "New1", 3, "test")); @@ -422,7 +422,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); + var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of()); repository.Save(new Macro("test1", "Test1", "~/views/macropartials/test1.cshtml", MacroTypes.PartialView)); repository.Save(new Macro("test2", "Test2", "~/views/macropartials/test2.cshtml", MacroTypes.PartialView)); diff --git a/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs index d1e7f96ff3..5e1900b29e 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs @@ -30,14 +30,14 @@ namespace Umbraco.Tests.Persistence.Repositories CreateTestData(); } - private MediaRepository CreateRepository(IScopeProvider provider, out MediaTypeRepository mediaTypeRepository, CacheHelper cacheHelper = null) + private MediaRepository CreateRepository(IScopeProvider provider, out MediaTypeRepository mediaTypeRepository, AppCaches appCaches = null) { - cacheHelper = cacheHelper ?? CacheHelper; + appCaches = appCaches ?? AppCaches; var scopeAccessor = (IScopeAccessor) provider; - mediaTypeRepository = new MediaTypeRepository(scopeAccessor, cacheHelper, Logger); - var tagRepository = new TagRepository(scopeAccessor, cacheHelper, Logger); - var repository = new MediaRepository(scopeAccessor, cacheHelper, Logger, mediaTypeRepository, tagRepository, Mock.Of(), Mock.Of()); + mediaTypeRepository = new MediaTypeRepository(scopeAccessor, appCaches, Logger); + var tagRepository = new TagRepository(scopeAccessor, appCaches, Logger); + var repository = new MediaRepository(scopeAccessor, appCaches, Logger, mediaTypeRepository, tagRepository, Mock.Of(), Mock.Of()); return repository; } @@ -46,7 +46,7 @@ namespace Umbraco.Tests.Persistence.Repositories { MediaTypeRepository mediaTypeRepository; - var realCache = new CacheHelper( + var realCache = new AppCaches( new ObjectCacheRuntimeCacheProvider(), new StaticCacheProvider(), new StaticCacheProvider(), @@ -55,7 +55,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = CreateRepository(provider, out mediaTypeRepository, cacheHelper: realCache); + var repository = CreateRepository(provider, out mediaTypeRepository, appCaches: realCache); var udb = (UmbracoDatabase)scope.Database; diff --git a/src/Umbraco.Tests/Persistence/Repositories/MediaTypeRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MediaTypeRepositoryTest.cs index ae4308db55..49bb93f2a7 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MediaTypeRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MediaTypeRepositoryTest.cs @@ -21,12 +21,12 @@ namespace Umbraco.Tests.Persistence.Repositories { private MediaTypeRepository CreateRepository(IScopeProvider provider) { - return new MediaTypeRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger); + return new MediaTypeRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger); } private EntityContainerRepository CreateContainerRepository(IScopeProvider provider) { - return new EntityContainerRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, Constants.ObjectTypes.MediaTypeContainer); + return new EntityContainerRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, Constants.ObjectTypes.MediaTypeContainer); } diff --git a/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs index 18bfc4fcea..dea15cd4ad 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs @@ -29,10 +29,10 @@ namespace Umbraco.Tests.Persistence.Repositories private MemberRepository CreateRepository(IScopeProvider provider, out MemberTypeRepository memberTypeRepository, out MemberGroupRepository memberGroupRepository) { var accessor = (IScopeAccessor) provider; - memberTypeRepository = new MemberTypeRepository(accessor, CacheHelper.Disabled, Logger); - memberGroupRepository = new MemberGroupRepository(accessor, CacheHelper.Disabled, Logger); - var tagRepo = new TagRepository(accessor, CacheHelper.Disabled, Logger); - var repository = new MemberRepository(accessor, CacheHelper.Disabled, Logger, memberTypeRepository, memberGroupRepository, tagRepo, Mock.Of()); + memberTypeRepository = new MemberTypeRepository(accessor, AppCaches.Disabled, Logger); + memberGroupRepository = new MemberGroupRepository(accessor, AppCaches.Disabled, Logger); + var tagRepo = new TagRepository(accessor, AppCaches.Disabled, Logger); + var repository = new MemberRepository(accessor, AppCaches.Disabled, Logger, memberTypeRepository, memberGroupRepository, tagRepo, Mock.Of()); return repository; } diff --git a/src/Umbraco.Tests/Persistence/Repositories/MemberTypeRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MemberTypeRepositoryTest.cs index 87d146f9f4..0c2314fd47 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MemberTypeRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MemberTypeRepositoryTest.cs @@ -22,7 +22,7 @@ namespace Umbraco.Tests.Persistence.Repositories { private MemberTypeRepository CreateRepository(IScopeProvider provider) { - return new MemberTypeRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); + return new MemberTypeRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of()); } [Test] diff --git a/src/Umbraco.Tests/Persistence/Repositories/PublicAccessRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/PublicAccessRepositoryTest.cs index e76d794e69..d28a002e31 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/PublicAccessRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/PublicAccessRepositoryTest.cs @@ -29,7 +29,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repo = new PublicAccessRepository((IScopeAccessor) provider, CacheHelper, Logger); + var repo = new PublicAccessRepository((IScopeAccessor) provider, AppCaches, Logger); var entry = new PublicAccessEntry(content[0], content[1], content[2], new[] { @@ -59,7 +59,7 @@ namespace Umbraco.Tests.Persistence.Repositories using (var scope = provider.CreateScope()) { scope.Database.AsUmbracoDatabase().EnableSqlTrace = true; - var repo = new PublicAccessRepository((IScopeAccessor) provider, CacheHelper, Logger); + var repo = new PublicAccessRepository((IScopeAccessor) provider, AppCaches, Logger); var entry = new PublicAccessEntry(content[0], content[1], content[2], new[] { @@ -99,7 +99,7 @@ namespace Umbraco.Tests.Persistence.Repositories using (var scope = provider.CreateScope()) { scope.Database.AsUmbracoDatabase().EnableSqlTrace = true; - var repo = new PublicAccessRepository((IScopeAccessor) provider, CacheHelper, Logger); + var repo = new PublicAccessRepository((IScopeAccessor) provider, AppCaches, Logger); var entry = new PublicAccessEntry(content[0], content[1], content[2], new[] { @@ -144,7 +144,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repo = new PublicAccessRepository((IScopeAccessor) provider, CacheHelper, Logger); + var repo = new PublicAccessRepository((IScopeAccessor) provider, AppCaches, Logger); var entry = new PublicAccessEntry(content[0], content[1], content[2], new[] { @@ -182,7 +182,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repo = new PublicAccessRepository((IScopeAccessor) provider, CacheHelper, Logger); + var repo = new PublicAccessRepository((IScopeAccessor) provider, AppCaches, Logger); var entry = new PublicAccessEntry(content[0], content[1], content[2], new[] { @@ -210,7 +210,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repo = new PublicAccessRepository((IScopeAccessor) provider, CacheHelper, Logger); + var repo = new PublicAccessRepository((IScopeAccessor) provider, AppCaches, Logger); var allEntries = new List(); for (int i = 0; i < 10; i++) @@ -274,7 +274,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repo = new PublicAccessRepository((IScopeAccessor) provider, CacheHelper, Logger); + var repo = new PublicAccessRepository((IScopeAccessor) provider, AppCaches, Logger); var entry1 = new PublicAccessEntry(content[0], content[1], content[2], new[] { @@ -307,11 +307,11 @@ namespace Umbraco.Tests.Persistence.Repositories private DocumentRepository CreateRepository(IScopeProvider provider, out ContentTypeRepository contentTypeRepository) { var accessor = (IScopeAccessor) provider; - var templateRepository = new TemplateRepository(accessor, CacheHelper, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); - var tagRepository = new TagRepository(accessor, CacheHelper, Logger); - contentTypeRepository = new ContentTypeRepository(accessor, CacheHelper, Logger, templateRepository); - var languageRepository = new LanguageRepository(accessor, CacheHelper, Logger); - var repository = new DocumentRepository(accessor, CacheHelper, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, Mock.Of()); + var templateRepository = new TemplateRepository(accessor, AppCaches, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); + var tagRepository = new TagRepository(accessor, AppCaches, Logger); + contentTypeRepository = new ContentTypeRepository(accessor, AppCaches, Logger, templateRepository); + var languageRepository = new LanguageRepository(accessor, AppCaches, Logger); + var repository = new DocumentRepository(accessor, AppCaches, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, Mock.Of()); return repository; } diff --git a/src/Umbraco.Tests/Persistence/Repositories/RedirectUrlRepositoryTests.cs b/src/Umbraco.Tests/Persistence/Repositories/RedirectUrlRepositoryTests.cs index ca2c713a27..66f6655c77 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/RedirectUrlRepositoryTests.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/RedirectUrlRepositoryTests.cs @@ -188,7 +188,7 @@ namespace Umbraco.Tests.Persistence.Repositories private IRedirectUrlRepository CreateRepository(IScopeProvider provider) { - return new RedirectUrlRepository((IScopeAccessor) provider, CacheHelper, Logger); + return new RedirectUrlRepository((IScopeAccessor) provider, AppCaches, Logger); } private IContent _textpage, _subpage, _otherpage, _trashed; diff --git a/src/Umbraco.Tests/Persistence/Repositories/RelationRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/RelationRepositoryTest.cs index 697951d021..cea7f44b71 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/RelationRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/RelationRepositoryTest.cs @@ -30,7 +30,7 @@ namespace Umbraco.Tests.Persistence.Repositories private RelationRepository CreateRepository(IScopeProvider provider, out RelationTypeRepository relationTypeRepository) { var accessor = (IScopeAccessor) provider; - relationTypeRepository = new RelationTypeRepository(accessor, CacheHelper.Disabled, Mock.Of()); + relationTypeRepository = new RelationTypeRepository(accessor, AppCaches.Disabled, Mock.Of()); var repository = new RelationRepository(accessor, Mock.Of(), relationTypeRepository); return repository; } @@ -266,7 +266,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var relationTypeRepository = new RelationTypeRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); + var relationTypeRepository = new RelationTypeRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of()); var relationRepository = new RelationRepository((IScopeAccessor) provider, Mock.Of(), relationTypeRepository); relationTypeRepository.Save(relateContent); diff --git a/src/Umbraco.Tests/Persistence/Repositories/RelationTypeRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/RelationTypeRepositoryTest.cs index 26b2fe48c2..e52e2dfcdf 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/RelationTypeRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/RelationTypeRepositoryTest.cs @@ -28,7 +28,7 @@ namespace Umbraco.Tests.Persistence.Repositories private RelationTypeRepository CreateRepository(IScopeProvider provider) { - return new RelationTypeRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); + return new RelationTypeRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of()); } @@ -232,7 +232,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = ScopeProvider.CreateScope()) { - var repository = new RelationTypeRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); + var repository = new RelationTypeRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of()); repository.Save(relateContent);//Id 2 repository.Save(relateContentType);//Id 3 diff --git a/src/Umbraco.Tests/Persistence/Repositories/ServerRegistrationRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ServerRegistrationRepositoryTest.cs index 08c34f453c..e2fc4b4705 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ServerRegistrationRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ServerRegistrationRepositoryTest.cs @@ -16,13 +16,13 @@ namespace Umbraco.Tests.Persistence.Repositories [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)] public class ServerRegistrationRepositoryTest : TestWithDatabaseBase { - private CacheHelper _cacheHelper; + private AppCaches _appCaches; public override void SetUp() { base.SetUp(); - _cacheHelper = new CacheHelper(); + _appCaches = new AppCaches(); CreateTestData(); } diff --git a/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs index 78eb736007..4812131a61 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs @@ -947,26 +947,26 @@ namespace Umbraco.Tests.Persistence.Repositories private TagRepository CreateRepository(IScopeProvider provider) { - return new TagRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger); + return new TagRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger); } private DocumentRepository CreateContentRepository(IScopeProvider provider, out ContentTypeRepository contentTypeRepository) { var accessor = (IScopeAccessor) provider; - var templateRepository = new TemplateRepository(accessor, CacheHelper.Disabled, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); - var tagRepository = new TagRepository(accessor, CacheHelper.Disabled, Logger); - contentTypeRepository = new ContentTypeRepository(accessor, CacheHelper.Disabled, Logger, templateRepository); - var languageRepository = new LanguageRepository(accessor, CacheHelper.Disabled, Logger); - var repository = new DocumentRepository(accessor, CacheHelper.Disabled, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, Mock.Of()); + var templateRepository = new TemplateRepository(accessor, AppCaches.Disabled, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); + var tagRepository = new TagRepository(accessor, AppCaches.Disabled, Logger); + contentTypeRepository = new ContentTypeRepository(accessor, AppCaches.Disabled, Logger, templateRepository); + var languageRepository = new LanguageRepository(accessor, AppCaches.Disabled, Logger); + var repository = new DocumentRepository(accessor, AppCaches.Disabled, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, Mock.Of()); return repository; } private MediaRepository CreateMediaRepository(IScopeProvider provider, out MediaTypeRepository mediaTypeRepository) { var accessor = (IScopeAccessor) provider; - var tagRepository = new TagRepository(accessor, CacheHelper.Disabled, Logger); - mediaTypeRepository = new MediaTypeRepository(accessor, CacheHelper.Disabled, Logger); - var repository = new MediaRepository(accessor, CacheHelper.Disabled, Logger, mediaTypeRepository, tagRepository, Mock.Of(), Mock.Of()); + var tagRepository = new TagRepository(accessor, AppCaches.Disabled, Logger); + mediaTypeRepository = new MediaTypeRepository(accessor, AppCaches.Disabled, Logger); + var repository = new MediaRepository(accessor, AppCaches.Disabled, Logger, mediaTypeRepository, tagRepository, Mock.Of(), Mock.Of()); return repository; } } diff --git a/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs index f4bed68315..94471aed7e 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs @@ -27,7 +27,7 @@ namespace Umbraco.Tests.Persistence.Repositories private ITemplateRepository CreateRepository(IScopeProvider provider, ITemplatesSection templatesSection = null) { - return new TemplateRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, + return new TemplateRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, templatesSection ?? Mock.Of(t => t.DefaultRenderingEngine == RenderingEngine.Mvc), _fileSystems); } @@ -363,10 +363,10 @@ namespace Umbraco.Tests.Persistence.Repositories { var templateRepository = CreateRepository(ScopeProvider); - var tagRepository = new TagRepository((IScopeAccessor) ScopeProvider, CacheHelper.Disabled, Logger); - var contentTypeRepository = new ContentTypeRepository((IScopeAccessor) ScopeProvider, CacheHelper.Disabled, Logger, templateRepository); - var languageRepository = new LanguageRepository((IScopeAccessor) ScopeProvider, CacheHelper.Disabled, Logger); - var contentRepo = new DocumentRepository((IScopeAccessor) ScopeProvider, CacheHelper.Disabled, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, Mock.Of()); + var tagRepository = new TagRepository((IScopeAccessor) ScopeProvider, AppCaches.Disabled, Logger); + var contentTypeRepository = new ContentTypeRepository((IScopeAccessor) ScopeProvider, AppCaches.Disabled, Logger, templateRepository); + var languageRepository = new LanguageRepository((IScopeAccessor) ScopeProvider, AppCaches.Disabled, Logger); + var contentRepo = new DocumentRepository((IScopeAccessor) ScopeProvider, AppCaches.Disabled, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, Mock.Of()); var contentType = MockedContentTypes.CreateSimpleContentType("umbTextpage2", "Textpage"); ServiceContext.FileService.SaveTemplate(contentType.DefaultTemplate); // else, FK violation on contentType! diff --git a/src/Umbraco.Tests/Persistence/Repositories/UserGroupRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/UserGroupRepositoryTest.cs index f0fb8cff88..311372ef10 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/UserGroupRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/UserGroupRepositoryTest.cs @@ -19,7 +19,7 @@ namespace Umbraco.Tests.Persistence.Repositories { private UserGroupRepository CreateRepository(IScopeProvider provider) { - return new UserGroupRepository((IScopeAccessor) provider, Core.Cache.CacheHelper.Disabled, Mock.Of()); + return new UserGroupRepository((IScopeAccessor) provider, Core.Cache.AppCaches.Disabled, Mock.Of()); } [Test] @@ -131,7 +131,7 @@ namespace Umbraco.Tests.Persistence.Repositories var id = userGroup.Id; - var repository2 = new UserGroupRepository((IScopeAccessor) provider, Core.Cache.CacheHelper.Disabled, Logger); + var repository2 = new UserGroupRepository((IScopeAccessor) provider, Core.Cache.AppCaches.Disabled, Logger); repository2.Delete(userGroup); scope.Complete(); diff --git a/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs index 847972cc50..7934544d8f 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs @@ -26,9 +26,9 @@ namespace Umbraco.Tests.Persistence.Repositories private MediaRepository CreateMediaRepository(IScopeProvider provider, out IMediaTypeRepository mediaTypeRepository) { var accessor = (IScopeAccessor) provider; - mediaTypeRepository = new MediaTypeRepository(accessor, CacheHelper, Mock.Of()); - var tagRepository = new TagRepository(accessor, CacheHelper, Mock.Of()); - var repository = new MediaRepository(accessor, CacheHelper, Mock.Of(), mediaTypeRepository, tagRepository, Mock.Of(), Mock.Of()); + mediaTypeRepository = new MediaTypeRepository(accessor, AppCaches, Mock.Of()); + var tagRepository = new TagRepository(accessor, AppCaches, Mock.Of()); + var repository = new MediaRepository(accessor, AppCaches, Mock.Of(), mediaTypeRepository, tagRepository, Mock.Of(), Mock.Of()); return repository; } @@ -41,25 +41,25 @@ namespace Umbraco.Tests.Persistence.Repositories private DocumentRepository CreateContentRepository(IScopeProvider provider, out IContentTypeRepository contentTypeRepository, out ITemplateRepository templateRepository) { var accessor = (IScopeAccessor) provider; - templateRepository = new TemplateRepository(accessor, CacheHelper, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); - var tagRepository = new TagRepository(accessor, CacheHelper, Logger); - contentTypeRepository = new ContentTypeRepository(accessor, CacheHelper, Logger, templateRepository); - var languageRepository = new LanguageRepository(accessor, CacheHelper, Logger); - var repository = new DocumentRepository(accessor, CacheHelper, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, Mock.Of()); + templateRepository = new TemplateRepository(accessor, AppCaches, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); + var tagRepository = new TagRepository(accessor, AppCaches, Logger); + contentTypeRepository = new ContentTypeRepository(accessor, AppCaches, Logger, templateRepository); + var languageRepository = new LanguageRepository(accessor, AppCaches, Logger); + var repository = new DocumentRepository(accessor, AppCaches, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, Mock.Of()); return repository; } private UserRepository CreateRepository(IScopeProvider provider) { var accessor = (IScopeAccessor) provider; - var repository = new UserRepository(accessor, CacheHelper.Disabled, Logger, Mappers, TestObjects.GetGlobalSettings()); + var repository = new UserRepository(accessor, AppCaches.Disabled, Logger, Mappers, TestObjects.GetGlobalSettings()); return repository; } private UserGroupRepository CreateUserGroupRepository(IScopeProvider provider) { var accessor = (IScopeAccessor) provider; - return new UserGroupRepository(accessor, CacheHelper.Disabled, Logger); + return new UserGroupRepository(accessor, AppCaches.Disabled, Logger); } [Test] @@ -207,7 +207,7 @@ namespace Umbraco.Tests.Persistence.Repositories var id = user.Id; - var repository2 = new UserRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, Mock.Of(),TestObjects.GetGlobalSettings()); + var repository2 = new UserRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, Mock.Of(),TestObjects.GetGlobalSettings()); repository2.Delete(user); diff --git a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs index 84f4f5dbd7..fe2cbdc145 100644 --- a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs +++ b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs @@ -173,7 +173,7 @@ namespace Umbraco.Tests.Routing /// public class CustomDocumentController : RenderMvcController { - public CustomDocumentController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, IProfilingLogger profilingLogger) + public CustomDocumentController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ServiceContext services, AppCaches applicationCache, ILogger logger, IProfilingLogger profilingLogger) : base(globalSettings, umbracoContext, services, applicationCache, logger, profilingLogger) { } diff --git a/src/Umbraco.Tests/Runtimes/StandaloneTests.cs b/src/Umbraco.Tests/Runtimes/StandaloneTests.cs index ccb7427907..3a52eea17c 100644 --- a/src/Umbraco.Tests/Runtimes/StandaloneTests.cs +++ b/src/Umbraco.Tests/Runtimes/StandaloneTests.cs @@ -59,7 +59,7 @@ namespace Umbraco.Tests.Runtimes var logger = new ConsoleLogger(); var profiler = new LogProfiler(logger); var profilingLogger = new ProfilingLogger(logger, profiler); - var appCaches = new CacheHelper(); // fixme has HttpRuntime stuff? + var appCaches = new AppCaches(); // fixme has HttpRuntime stuff? var databaseFactory = new UmbracoDatabaseFactory(logger, new Lazy(() => factory.GetInstance())); var typeLoader = new TypeLoader(appCaches.RuntimeCache, LocalTempStorage.Default, profilingLogger); var mainDom = new SimpleMainDom(); @@ -239,7 +239,7 @@ namespace Umbraco.Tests.Runtimes var logger = new ConsoleLogger(); var profiler = Mock.Of(); var profilingLogger = new ProfilingLogger(logger, profiler); - var appCaches = CacheHelper.Disabled; + var appCaches = AppCaches.Disabled; var databaseFactory = Mock.Of(); var typeLoader = new TypeLoader(appCaches.RuntimeCache, LocalTempStorage.Default, profilingLogger); var runtimeState = Mock.Of(); diff --git a/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs b/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs index 3a0cb00ea9..5d4fa4f182 100644 --- a/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs @@ -37,10 +37,10 @@ namespace Umbraco.Tests.Scoping .Add(() => Composition.TypeLoader.GetCacheRefreshers()); } - protected override CacheHelper GetCacheHelper() + protected override AppCaches GetCacheHelper() { // this is what's created core web runtime - return new CacheHelper( + return new AppCaches( new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()), new StaticCacheProvider(), NullCacheProvider.Instance, diff --git a/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs b/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs index 3aefa88a50..c56f66fc94 100644 --- a/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs +++ b/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs @@ -163,11 +163,11 @@ namespace Umbraco.Tests.Services var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var tRepository = new TemplateRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); - var tagRepo = new TagRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger); - var ctRepository = new ContentTypeRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, tRepository); - var languageRepository = new LanguageRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger); - var repository = new DocumentRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, ctRepository, tRepository, tagRepo, languageRepository, Mock.Of()); + var tRepository = new TemplateRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); + var tagRepo = new TagRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger); + var ctRepository = new ContentTypeRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, tRepository); + var languageRepository = new LanguageRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger); + var repository = new DocumentRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, ctRepository, tRepository, tagRepo, languageRepository, Mock.Of()); // Act Stopwatch watch = Stopwatch.StartNew(); @@ -196,11 +196,11 @@ namespace Umbraco.Tests.Services var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var tRepository = new TemplateRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); - var tagRepo = new TagRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger); - var ctRepository = new ContentTypeRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, tRepository); - var languageRepository = new LanguageRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger); - var repository = new DocumentRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, ctRepository, tRepository, tagRepo, languageRepository, Mock.Of()); + var tRepository = new TemplateRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); + var tagRepo = new TagRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger); + var ctRepository = new ContentTypeRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, tRepository); + var languageRepository = new LanguageRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger); + var repository = new DocumentRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, ctRepository, tRepository, tagRepo, languageRepository, Mock.Of()); // Act Stopwatch watch = Stopwatch.StartNew(); @@ -227,11 +227,11 @@ namespace Umbraco.Tests.Services var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var tRepository = new TemplateRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); - var tagRepo = new TagRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger); - var ctRepository = new ContentTypeRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, tRepository); - var languageRepository = new LanguageRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger); - var repository = new DocumentRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, ctRepository, tRepository, tagRepo, languageRepository, Mock.Of()); + var tRepository = new TemplateRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); + var tagRepo = new TagRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger); + var ctRepository = new ContentTypeRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, tRepository); + var languageRepository = new LanguageRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger); + var repository = new DocumentRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, ctRepository, tRepository, tagRepo, languageRepository, Mock.Of()); // Act var contents = repository.GetMany(); @@ -261,11 +261,11 @@ namespace Umbraco.Tests.Services var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var tRepository = new TemplateRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); - var tagRepo = new TagRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger); - var ctRepository = new ContentTypeRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, tRepository); - var languageRepository = new LanguageRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger); - var repository = new DocumentRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, ctRepository, tRepository, tagRepo, languageRepository, Mock.Of()); + var tRepository = new TemplateRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); + var tagRepo = new TagRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger); + var ctRepository = new ContentTypeRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, tRepository); + var languageRepository = new LanguageRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger); + var repository = new DocumentRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, ctRepository, tRepository, tagRepo, languageRepository, Mock.Of()); // Act var contents = repository.GetMany(); diff --git a/src/Umbraco.Tests/Services/ContentServiceTests.cs b/src/Umbraco.Tests/Services/ContentServiceTests.cs index 0f48a9c99a..799ce6a47c 100644 --- a/src/Umbraco.Tests/Services/ContentServiceTests.cs +++ b/src/Umbraco.Tests/Services/ContentServiceTests.cs @@ -3037,11 +3037,11 @@ namespace Umbraco.Tests.Services private DocumentRepository CreateRepository(IScopeProvider provider, out ContentTypeRepository contentTypeRepository) { var accessor = (IScopeAccessor) provider; - var templateRepository = new TemplateRepository(accessor, CacheHelper.Disabled, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); - var tagRepository = new TagRepository(accessor, CacheHelper.Disabled, Logger); - contentTypeRepository = new ContentTypeRepository(accessor, CacheHelper.Disabled, Logger, templateRepository); - var languageRepository = new LanguageRepository(accessor, CacheHelper.Disabled, Logger); - var repository = new DocumentRepository(accessor, CacheHelper.Disabled, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, Mock.Of()); + var templateRepository = new TemplateRepository(accessor, AppCaches.Disabled, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); + var tagRepository = new TagRepository(accessor, AppCaches.Disabled, Logger); + contentTypeRepository = new ContentTypeRepository(accessor, AppCaches.Disabled, Logger, templateRepository); + var languageRepository = new LanguageRepository(accessor, AppCaches.Disabled, Logger); + var repository = new DocumentRepository(accessor, AppCaches.Disabled, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, Mock.Of()); return repository; } } diff --git a/src/Umbraco.Tests/Services/MacroServiceTests.cs b/src/Umbraco.Tests/Services/MacroServiceTests.cs index 52cc8ab0d1..69e816585e 100644 --- a/src/Umbraco.Tests/Services/MacroServiceTests.cs +++ b/src/Umbraco.Tests/Services/MacroServiceTests.cs @@ -26,7 +26,7 @@ namespace Umbraco.Tests.Services var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.Disabled, Mock.Of()); + var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of()); repository.Save(new Macro("test1", "Test1", "~/views/macropartials/test1.cshtml", MacroTypes.PartialView)); repository.Save(new Macro("test2", "Test2", "~/views/macropartials/test2.cshtml", MacroTypes.PartialView)); diff --git a/src/Umbraco.Tests/Templates/TemplateRepositoryTests.cs b/src/Umbraco.Tests/Templates/TemplateRepositoryTests.cs index 795d79ced1..ececf46a18 100644 --- a/src/Umbraco.Tests/Templates/TemplateRepositoryTests.cs +++ b/src/Umbraco.Tests/Templates/TemplateRepositoryTests.cs @@ -15,7 +15,7 @@ namespace Umbraco.Tests.Templates [TestFixture] public class TemplateRepositoryTests { - private readonly Mock _cacheMock = new Mock(); + private readonly Mock _cacheMock = new Mock(); private readonly Mock _templateConfigMock = new Mock(); private readonly IFileSystems _fileSystems = Mock.Of(); private TemplateRepository _templateRepository; diff --git a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs index 9e2a2156ee..94e38d6872 100644 --- a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs +++ b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs @@ -151,7 +151,7 @@ namespace Umbraco.Tests.TestHelpers.ControllerTesting urlHelper.Setup(provider => provider.GetUrl(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Returns(UrlInfo.Url("/hello/world/1234")); - var membershipHelper = new MembershipHelper(new TestUmbracoContextAccessor(umbCtx), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), null, Mock.Of(), Mock.Of()); + var membershipHelper = new MembershipHelper(new TestUmbracoContextAccessor(umbCtx), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), null, Mock.Of(), Mock.Of()); var umbHelper = new UmbracoHelper(umbCtx, Mock.Of(), diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects.cs b/src/Umbraco.Tests/TestHelpers/TestObjects.cs index 14ffeb743f..29eb649c48 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects.cs @@ -90,7 +90,7 @@ namespace Umbraco.Tests.TestHelpers /// just mock the services to be passed to the ctor of the ServiceContext. public ServiceContext GetServiceContext( IScopeProvider scopeProvider, IScopeAccessor scopeAccessor, - CacheHelper cache, + AppCaches cache, ILogger logger, IGlobalSettings globalSettings, IUmbracoSettingsSection umbracoSettings, diff --git a/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs b/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs index c413cb0e94..575f14e818 100644 --- a/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs +++ b/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs @@ -56,7 +56,7 @@ namespace Umbraco.Tests.Testing.TestingTests Composition.Register(_ => Mock.Of()); Composition.Register(_ => Mock.Of()); Composition.Register(_ => Mock.Of()); - Composition.Register(_ => CacheHelper.Disabled); + Composition.Register(_ => AppCaches.Disabled); Composition.Register(); // ReSharper disable once UnusedVariable @@ -65,7 +65,7 @@ namespace Umbraco.Tests.Testing.TestingTests Mock.Of(), Mock.Of(), Mock.Of(), - new MembershipHelper(new TestUmbracoContextAccessor(umbracoContext), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), null, Mock.Of(), Mock.Of()), + new MembershipHelper(new TestUmbracoContextAccessor(umbracoContext), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), null, Mock.Of(), Mock.Of()), ServiceContext.CreatePartial()); Assert.Pass(); } diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index a79531af74..c980f9c1ee 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -101,7 +101,7 @@ namespace Umbraco.Tests.Testing protected virtual IProfilingLogger ProfilingLogger => Factory.GetInstance(); - protected CacheHelper CacheHelper => Factory.GetInstance(); + protected AppCaches AppCaches => Factory.GetInstance(); protected virtual ISqlSyntaxProvider SqlSyntax => Factory.GetInstance(); @@ -199,9 +199,9 @@ namespace Umbraco.Tests.Testing return (logger, profiler); } - protected virtual CacheHelper GetCacheHelper() + protected virtual AppCaches GetCacheHelper() { - return CacheHelper.Disabled; + return AppCaches.Disabled; } protected virtual void ComposeWeb() diff --git a/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs b/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs index 35e8f0a937..03844b5d72 100644 --- a/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs +++ b/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs @@ -132,7 +132,7 @@ namespace Umbraco.Tests.Web.Mvc Mock.Of(), Mock.Of(), Mock.Of(), - new MembershipHelper(new TestUmbracoContextAccessor(umbracoContext), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), null, Mock.Of(), Mock.Of()), + new MembershipHelper(new TestUmbracoContextAccessor(umbracoContext), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), null, Mock.Of(), Mock.Of()), ServiceContext.CreatePartial()); var ctrl = new TestSurfaceController(umbracoContext, helper); @@ -185,7 +185,7 @@ namespace Umbraco.Tests.Web.Mvc public class TestSurfaceController : SurfaceController { public TestSurfaceController(UmbracoContext ctx, UmbracoHelper helper = null) - : base(ctx, null, ServiceContext.CreatePartial(), Mock.Of(), null, null) + : base(ctx, null, ServiceContext.CreatePartial(), Mock.Of(), null, null) { if (helper != null) { diff --git a/src/Umbraco.Web/Cache/ApplicationCacheRefresher.cs b/src/Umbraco.Web/Cache/ApplicationCacheRefresher.cs index c1ab217642..cf93b44215 100644 --- a/src/Umbraco.Web/Cache/ApplicationCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/ApplicationCacheRefresher.cs @@ -5,8 +5,8 @@ namespace Umbraco.Web.Cache { public sealed class ApplicationCacheRefresher : CacheRefresherBase { - public ApplicationCacheRefresher(CacheHelper cacheHelper) - : base(cacheHelper) + public ApplicationCacheRefresher(AppCaches appCaches) + : base(appCaches) { } #region Define @@ -25,7 +25,7 @@ namespace Umbraco.Web.Cache public override void RefreshAll() { - CacheHelper.RuntimeCache.ClearCacheItem(CacheKeys.ApplicationsCacheKey); + AppCaches.RuntimeCache.ClearCacheItem(CacheKeys.ApplicationsCacheKey); base.RefreshAll(); } @@ -37,7 +37,7 @@ namespace Umbraco.Web.Cache public override void Remove(int id) { - CacheHelper.RuntimeCache.ClearCacheItem(CacheKeys.ApplicationsCacheKey); + AppCaches.RuntimeCache.ClearCacheItem(CacheKeys.ApplicationsCacheKey); base.Remove(id); } diff --git a/src/Umbraco.Web/Cache/ApplicationTreeCacheRefresher.cs b/src/Umbraco.Web/Cache/ApplicationTreeCacheRefresher.cs index 247c33c361..72fceec631 100644 --- a/src/Umbraco.Web/Cache/ApplicationTreeCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/ApplicationTreeCacheRefresher.cs @@ -5,8 +5,8 @@ namespace Umbraco.Web.Cache { public sealed class ApplicationTreeCacheRefresher : CacheRefresherBase { - public ApplicationTreeCacheRefresher(CacheHelper cacheHelper) - : base(cacheHelper) + public ApplicationTreeCacheRefresher(AppCaches appCaches) + : base(appCaches) { } #region Define @@ -25,7 +25,7 @@ namespace Umbraco.Web.Cache public override void RefreshAll() { - CacheHelper.RuntimeCache.ClearCacheItem(CacheKeys.ApplicationTreeCacheKey); + AppCaches.RuntimeCache.ClearCacheItem(CacheKeys.ApplicationTreeCacheKey); base.RefreshAll(); } @@ -37,7 +37,7 @@ namespace Umbraco.Web.Cache public override void Remove(int id) { - CacheHelper.RuntimeCache.ClearCacheItem(CacheKeys.ApplicationTreeCacheKey); + AppCaches.RuntimeCache.ClearCacheItem(CacheKeys.ApplicationTreeCacheKey); base.Remove(id); } diff --git a/src/Umbraco.Web/Cache/ContentCacheRefresher.cs b/src/Umbraco.Web/Cache/ContentCacheRefresher.cs index b0192e9e75..3ae2f8e3dd 100644 --- a/src/Umbraco.Web/Cache/ContentCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/ContentCacheRefresher.cs @@ -20,8 +20,8 @@ namespace Umbraco.Web.Cache private readonly IdkMap _idkMap; private readonly IDomainService _domainService; - public ContentCacheRefresher(CacheHelper cacheHelper, IPublishedSnapshotService publishedSnapshotService, IdkMap idkMap, IDomainService domainService) - : base(cacheHelper) + public ContentCacheRefresher(AppCaches appCaches, IPublishedSnapshotService publishedSnapshotService, IdkMap idkMap, IDomainService domainService) + : base(appCaches) { _publishedSnapshotService = publishedSnapshotService; _idkMap = idkMap; @@ -44,10 +44,10 @@ namespace Umbraco.Web.Cache public override void Refresh(JsonPayload[] payloads) { - CacheHelper.RuntimeCache.ClearCacheObjectTypes(); + AppCaches.RuntimeCache.ClearCacheObjectTypes(); var idsRemoved = new HashSet(); - var isolatedCache = CacheHelper.IsolatedRuntimeCache.GetOrCreateCache(); + var isolatedCache = AppCaches.IsolatedRuntimeCache.GetOrCreateCache(); foreach (var payload in payloads) { @@ -103,7 +103,7 @@ namespace Umbraco.Web.Cache { // when a public version changes Current.ApplicationCache.ClearPartialViewCache(); - MacroCacheRefresher.ClearMacroContentCache(CacheHelper); // just the content + MacroCacheRefresher.ClearMacroContentCache(AppCaches); // just the content } base.Refresh(payloads); @@ -153,17 +153,17 @@ namespace Umbraco.Web.Cache #region Indirect - public static void RefreshContentTypes(CacheHelper cacheHelper) + public static void RefreshContentTypes(AppCaches appCaches) { // we could try to have a mechanism to notify the PublishedCachesService // and figure out whether published items were modified or not... keep it // simple for now, just clear the whole thing - cacheHelper.ClearPartialViewCache(); - MacroCacheRefresher.ClearMacroContentCache(cacheHelper); // just the content + appCaches.ClearPartialViewCache(); + MacroCacheRefresher.ClearMacroContentCache(appCaches); // just the content - cacheHelper.IsolatedRuntimeCache.ClearCache(); - cacheHelper.IsolatedRuntimeCache.ClearCache(); + appCaches.IsolatedRuntimeCache.ClearCache(); + appCaches.IsolatedRuntimeCache.ClearCache(); } #endregion diff --git a/src/Umbraco.Web/Cache/ContentTypeCacheRefresher.cs b/src/Umbraco.Web/Cache/ContentTypeCacheRefresher.cs index c1b99d25ec..90b6e79ae1 100644 --- a/src/Umbraco.Web/Cache/ContentTypeCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/ContentTypeCacheRefresher.cs @@ -13,8 +13,8 @@ namespace Umbraco.Web.Cache private readonly IPublishedSnapshotService _publishedSnapshotService; private readonly IdkMap _idkMap; - public ContentTypeCacheRefresher(CacheHelper cacheHelper, IPublishedSnapshotService publishedSnapshotService, IdkMap idkMap) - : base(cacheHelper) + public ContentTypeCacheRefresher(AppCaches appCaches, IPublishedSnapshotService publishedSnapshotService, IdkMap idkMap) + : base(appCaches) { _publishedSnapshotService = publishedSnapshotService; _idkMap = idkMap; @@ -65,15 +65,15 @@ namespace Umbraco.Web.Cache if (payloads.Any(x => x.ItemType == typeof(IContentType).Name)) // don't try to be clever - refresh all - ContentCacheRefresher.RefreshContentTypes(CacheHelper); + ContentCacheRefresher.RefreshContentTypes(AppCaches); if (payloads.Any(x => x.ItemType == typeof(IMediaType).Name)) // don't try to be clever - refresh all - MediaCacheRefresher.RefreshMediaTypes(CacheHelper); + MediaCacheRefresher.RefreshMediaTypes(AppCaches); if (payloads.Any(x => x.ItemType == typeof(IMemberType).Name)) // don't try to be clever - refresh all - MemberCacheRefresher.RefreshMemberTypes(CacheHelper); + MemberCacheRefresher.RefreshMemberTypes(AppCaches); // notify _publishedSnapshotService.Notify(payloads); diff --git a/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs b/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs index be17c28067..e1a8f05e39 100644 --- a/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs @@ -15,8 +15,8 @@ namespace Umbraco.Web.Cache private readonly IPublishedSnapshotService _publishedSnapshotService; private readonly IdkMap _idkMap; - public DataTypeCacheRefresher(CacheHelper cacheHelper, IPublishedSnapshotService publishedSnapshotService, IdkMap idkMap) - : base(cacheHelper) + public DataTypeCacheRefresher(AppCaches appCaches, IPublishedSnapshotService publishedSnapshotService, IdkMap idkMap) + : base(appCaches) { _publishedSnapshotService = publishedSnapshotService; _idkMap = idkMap; @@ -49,7 +49,7 @@ namespace Umbraco.Web.Cache ClearAllIsolatedCacheByEntityType(); ClearAllIsolatedCacheByEntityType(); - var dataTypeCache = CacheHelper.IsolatedRuntimeCache.GetCache(); + var dataTypeCache = AppCaches.IsolatedRuntimeCache.GetCache(); foreach (var payload in payloads) { diff --git a/src/Umbraco.Web/Cache/DictionaryCacheRefresher.cs b/src/Umbraco.Web/Cache/DictionaryCacheRefresher.cs index 7dadee87b1..525b4d2157 100644 --- a/src/Umbraco.Web/Cache/DictionaryCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/DictionaryCacheRefresher.cs @@ -6,8 +6,8 @@ namespace Umbraco.Web.Cache { public sealed class DictionaryCacheRefresher : CacheRefresherBase { - public DictionaryCacheRefresher(CacheHelper cacheHelper) - : base(cacheHelper) + public DictionaryCacheRefresher(AppCaches appCaches) + : base(appCaches) { } #region Define diff --git a/src/Umbraco.Web/Cache/DomainCacheRefresher.cs b/src/Umbraco.Web/Cache/DomainCacheRefresher.cs index 6907a654ff..37b0a483a6 100644 --- a/src/Umbraco.Web/Cache/DomainCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/DomainCacheRefresher.cs @@ -10,8 +10,8 @@ namespace Umbraco.Web.Cache { private readonly IPublishedSnapshotService _publishedSnapshotService; - public DomainCacheRefresher(CacheHelper cacheHelper, IPublishedSnapshotService publishedSnapshotService) - : base(cacheHelper) + public DomainCacheRefresher(AppCaches appCaches, IPublishedSnapshotService publishedSnapshotService) + : base(appCaches) { _publishedSnapshotService = publishedSnapshotService; } diff --git a/src/Umbraco.Web/Cache/LanguageCacheRefresher.cs b/src/Umbraco.Web/Cache/LanguageCacheRefresher.cs index bee12020cb..f5fe5075eb 100644 --- a/src/Umbraco.Web/Cache/LanguageCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/LanguageCacheRefresher.cs @@ -10,8 +10,8 @@ namespace Umbraco.Web.Cache { public sealed class LanguageCacheRefresher : CacheRefresherBase { - public LanguageCacheRefresher(CacheHelper cacheHelper, IPublishedSnapshotService publishedSnapshotService, IDomainService domainService) - : base(cacheHelper) + public LanguageCacheRefresher(AppCaches appCaches, IPublishedSnapshotService publishedSnapshotService, IDomainService domainService) + : base(appCaches) { _publishedSnapshotService = publishedSnapshotService; _domainService = domainService; diff --git a/src/Umbraco.Web/Cache/MacroCacheRefresher.cs b/src/Umbraco.Web/Cache/MacroCacheRefresher.cs index a4af601379..cdeb2ffdd0 100644 --- a/src/Umbraco.Web/Cache/MacroCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/MacroCacheRefresher.cs @@ -12,8 +12,8 @@ namespace Umbraco.Web.Cache { public sealed class MacroCacheRefresher : JsonCacheRefresherBase { - public MacroCacheRefresher(CacheHelper cacheHelper) - : base(cacheHelper) + public MacroCacheRefresher(AppCaches appCaches) + : base(appCaches) { } #region Define @@ -33,11 +33,11 @@ namespace Umbraco.Web.Cache public override void RefreshAll() { foreach (var prefix in GetAllMacroCacheKeys()) - CacheHelper.RuntimeCache.ClearCacheByKeySearch(prefix); + AppCaches.RuntimeCache.ClearCacheByKeySearch(prefix); ClearAllIsolatedCacheByEntityType(); - CacheHelper.RuntimeCache.ClearCacheObjectTypes(); + AppCaches.RuntimeCache.ClearCacheObjectTypes(); base.RefreshAll(); } @@ -49,9 +49,9 @@ namespace Umbraco.Web.Cache foreach (var payload in payloads) { foreach (var alias in GetCacheKeysForAlias(payload.Alias)) - CacheHelper.RuntimeCache.ClearCacheByKeySearch(alias); + AppCaches.RuntimeCache.ClearCacheByKeySearch(alias); - var macroRepoCache = CacheHelper.IsolatedRuntimeCache.GetCache(); + var macroRepoCache = AppCaches.IsolatedRuntimeCache.GetCache(); if (macroRepoCache) { macroRepoCache.Result.ClearCacheItem(RepositoryCacheKeys.GetKey(payload.Id)); @@ -110,9 +110,9 @@ namespace Umbraco.Web.Cache return GetAllMacroCacheKeys().Select(x => x + alias).ToArray(); } - public static void ClearMacroContentCache(CacheHelper cacheHelper) + public static void ClearMacroContentCache(AppCaches appCaches) { - cacheHelper.RuntimeCache.ClearCacheObjectTypes(); + appCaches.RuntimeCache.ClearCacheObjectTypes(); } #endregion diff --git a/src/Umbraco.Web/Cache/MediaCacheRefresher.cs b/src/Umbraco.Web/Cache/MediaCacheRefresher.cs index 4abf7d8787..a6ccd7e005 100644 --- a/src/Umbraco.Web/Cache/MediaCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/MediaCacheRefresher.cs @@ -18,8 +18,8 @@ namespace Umbraco.Web.Cache private readonly IPublishedSnapshotService _publishedSnapshotService; private readonly IdkMap _idkMap; - public MediaCacheRefresher(CacheHelper cacheHelper, IPublishedSnapshotService publishedSnapshotService, IdkMap idkMap) - : base(cacheHelper) + public MediaCacheRefresher(AppCaches appCaches, IPublishedSnapshotService publishedSnapshotService, IdkMap idkMap) + : base(appCaches) { _publishedSnapshotService = publishedSnapshotService; _idkMap = idkMap; @@ -49,7 +49,7 @@ namespace Umbraco.Web.Cache { Current.ApplicationCache.ClearPartialViewCache(); - var mediaCache = CacheHelper.IsolatedRuntimeCache.GetCache(); + var mediaCache = AppCaches.IsolatedRuntimeCache.GetCache(); foreach (var payload in payloads) { @@ -119,9 +119,9 @@ namespace Umbraco.Web.Cache #region Indirect - public static void RefreshMediaTypes(CacheHelper cacheHelper) + public static void RefreshMediaTypes(AppCaches appCaches) { - cacheHelper.IsolatedRuntimeCache.ClearCache(); + appCaches.IsolatedRuntimeCache.ClearCache(); } #endregion diff --git a/src/Umbraco.Web/Cache/MemberCacheRefresher.cs b/src/Umbraco.Web/Cache/MemberCacheRefresher.cs index 237daa39b4..29c102e7a2 100644 --- a/src/Umbraco.Web/Cache/MemberCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/MemberCacheRefresher.cs @@ -11,8 +11,8 @@ namespace Umbraco.Web.Cache { private readonly IdkMap _idkMap; - public MemberCacheRefresher(CacheHelper cacheHelper, IdkMap idkMap) - : base(cacheHelper) + public MemberCacheRefresher(AppCaches appCaches, IdkMap idkMap) + : base(appCaches) { _idkMap = idkMap; } @@ -58,9 +58,9 @@ namespace Umbraco.Web.Cache private void ClearCache(int id) { _idkMap.ClearCache(id); - CacheHelper.ClearPartialViewCache(); + AppCaches.ClearPartialViewCache(); - var memberCache = CacheHelper.IsolatedRuntimeCache.GetCache(); + var memberCache = AppCaches.IsolatedRuntimeCache.GetCache(); if (memberCache) memberCache.Result.ClearCacheItem(RepositoryCacheKeys.GetKey(id)); } @@ -69,9 +69,9 @@ namespace Umbraco.Web.Cache #region Indirect - public static void RefreshMemberTypes(CacheHelper cacheHelper) + public static void RefreshMemberTypes(AppCaches appCaches) { - cacheHelper.IsolatedRuntimeCache.ClearCache(); + appCaches.IsolatedRuntimeCache.ClearCache(); } #endregion diff --git a/src/Umbraco.Web/Cache/MemberGroupCacheRefresher.cs b/src/Umbraco.Web/Cache/MemberGroupCacheRefresher.cs index 4540f0b495..9368b0f9f4 100644 --- a/src/Umbraco.Web/Cache/MemberGroupCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/MemberGroupCacheRefresher.cs @@ -8,8 +8,8 @@ namespace Umbraco.Web.Cache { public sealed class MemberGroupCacheRefresher : JsonCacheRefresherBase { - public MemberGroupCacheRefresher(CacheHelper cacheHelper) - : base(cacheHelper) + public MemberGroupCacheRefresher(AppCaches appCaches) + : base(appCaches) { } #region Define @@ -49,7 +49,7 @@ namespace Umbraco.Web.Cache // Since we cache by group name, it could be problematic when renaming to // previously existing names - see http://issues.umbraco.org/issue/U4-10846. // To work around this, just clear all the cache items - CacheHelper.IsolatedRuntimeCache.ClearCache(); + AppCaches.IsolatedRuntimeCache.ClearCache(); } #endregion diff --git a/src/Umbraco.Web/Cache/PublicAccessCacheRefresher.cs b/src/Umbraco.Web/Cache/PublicAccessCacheRefresher.cs index 7c3af1129f..59c8231ed2 100644 --- a/src/Umbraco.Web/Cache/PublicAccessCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/PublicAccessCacheRefresher.cs @@ -6,8 +6,8 @@ namespace Umbraco.Web.Cache { public sealed class PublicAccessCacheRefresher : CacheRefresherBase { - public PublicAccessCacheRefresher(CacheHelper cacheHelper) - : base(cacheHelper) + public PublicAccessCacheRefresher(AppCaches appCaches) + : base(appCaches) { } #region Define diff --git a/src/Umbraco.Web/Cache/RelationTypeCacheRefresher.cs b/src/Umbraco.Web/Cache/RelationTypeCacheRefresher.cs index 4dd7282f98..8b1c8581cd 100644 --- a/src/Umbraco.Web/Cache/RelationTypeCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/RelationTypeCacheRefresher.cs @@ -8,8 +8,8 @@ namespace Umbraco.Web.Cache { public sealed class RelationTypeCacheRefresher : CacheRefresherBase { - public RelationTypeCacheRefresher(CacheHelper cacheHelper) - : base(cacheHelper) + public RelationTypeCacheRefresher(AppCaches appCaches) + : base(appCaches) { } #region Define @@ -34,7 +34,7 @@ namespace Umbraco.Web.Cache public override void Refresh(int id) { - var cache = CacheHelper.IsolatedRuntimeCache.GetCache(); + var cache = AppCaches.IsolatedRuntimeCache.GetCache(); if (cache) cache.Result.ClearCacheItem(RepositoryCacheKeys.GetKey(id)); base.Refresh(id); } @@ -47,7 +47,7 @@ namespace Umbraco.Web.Cache public override void Remove(int id) { - var cache = CacheHelper.IsolatedRuntimeCache.GetCache(); + var cache = AppCaches.IsolatedRuntimeCache.GetCache(); if (cache) cache.Result.ClearCacheItem(RepositoryCacheKeys.GetKey(id)); base.Remove(id); } diff --git a/src/Umbraco.Web/Cache/TemplateCacheRefresher.cs b/src/Umbraco.Web/Cache/TemplateCacheRefresher.cs index 6f76d148cc..7ff7c6fdb6 100644 --- a/src/Umbraco.Web/Cache/TemplateCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/TemplateCacheRefresher.cs @@ -9,8 +9,8 @@ namespace Umbraco.Web.Cache { private readonly IdkMap _idkMap; - public TemplateCacheRefresher(CacheHelper cacheHelper, IdkMap idkMap) - : base(cacheHelper) + public TemplateCacheRefresher(AppCaches appCaches, IdkMap idkMap) + : base(appCaches) { _idkMap = idkMap; } @@ -52,7 +52,7 @@ namespace Umbraco.Web.Cache private void RemoveFromCache(int id) { _idkMap.ClearCache(id); - CacheHelper.RuntimeCache.ClearCacheItem($"{CacheKeys.TemplateFrontEndCacheKey}{id}"); + AppCaches.RuntimeCache.ClearCacheItem($"{CacheKeys.TemplateFrontEndCacheKey}{id}"); //need to clear the runtime cache for templates ClearAllIsolatedCacheByEntityType(); diff --git a/src/Umbraco.Web/Cache/UserCacheRefresher.cs b/src/Umbraco.Web/Cache/UserCacheRefresher.cs index ae57fc902a..a502a7554f 100644 --- a/src/Umbraco.Web/Cache/UserCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/UserCacheRefresher.cs @@ -8,8 +8,8 @@ namespace Umbraco.Web.Cache { public sealed class UserCacheRefresher : CacheRefresherBase { - public UserCacheRefresher(CacheHelper cacheHelper) - : base(cacheHelper) + public UserCacheRefresher(AppCaches appCaches) + : base(appCaches) { } #region Define @@ -40,7 +40,7 @@ namespace Umbraco.Web.Cache public override void Remove(int id) { - var userCache = CacheHelper.IsolatedRuntimeCache.GetCache(); + var userCache = AppCaches.IsolatedRuntimeCache.GetCache(); if (userCache) userCache.Result.ClearCacheItem(RepositoryCacheKeys.GetKey(id)); diff --git a/src/Umbraco.Web/Cache/UserGroupCacheRefresher.cs b/src/Umbraco.Web/Cache/UserGroupCacheRefresher.cs index deb49ad624..4dea595c85 100644 --- a/src/Umbraco.Web/Cache/UserGroupCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/UserGroupCacheRefresher.cs @@ -14,8 +14,8 @@ namespace Umbraco.Web.Cache /// public sealed class UserGroupCacheRefresher : CacheRefresherBase { - public UserGroupCacheRefresher(CacheHelper cacheHelper) - : base(cacheHelper) + public UserGroupCacheRefresher(AppCaches appCaches) + : base(appCaches) { } #region Define @@ -35,7 +35,7 @@ namespace Umbraco.Web.Cache public override void RefreshAll() { ClearAllIsolatedCacheByEntityType(); - var userGroupCache = CacheHelper.IsolatedRuntimeCache.GetCache(); + var userGroupCache = AppCaches.IsolatedRuntimeCache.GetCache(); if (userGroupCache) { userGroupCache.Result.ClearCacheByKeySearch(UserGroupRepository.GetByAliasCacheKeyPrefix); @@ -55,7 +55,7 @@ namespace Umbraco.Web.Cache public override void Remove(int id) { - var userGroupCache = CacheHelper.IsolatedRuntimeCache.GetCache(); + var userGroupCache = AppCaches.IsolatedRuntimeCache.GetCache(); if (userGroupCache) { userGroupCache.Result.ClearCacheItem(RepositoryCacheKeys.GetKey(id)); diff --git a/src/Umbraco.Web/Cache/UserGroupPermissionsCacheRefresher.cs b/src/Umbraco.Web/Cache/UserGroupPermissionsCacheRefresher.cs index bd2ad50ef5..37e02a0149 100644 --- a/src/Umbraco.Web/Cache/UserGroupPermissionsCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/UserGroupPermissionsCacheRefresher.cs @@ -8,8 +8,8 @@ namespace Umbraco.Web.Cache [EditorBrowsable(EditorBrowsableState.Never)] public sealed class UserGroupPermissionsCacheRefresher : CacheRefresherBase { - public UserGroupPermissionsCacheRefresher(CacheHelper cacheHelper) - : base(cacheHelper) + public UserGroupPermissionsCacheRefresher(AppCaches appCaches) + : base(appCaches) { } #region Define diff --git a/src/Umbraco.Web/CacheHelperExtensions.cs b/src/Umbraco.Web/CacheHelperExtensions.cs index d7aa838a09..3c5ea1930d 100644 --- a/src/Umbraco.Web/CacheHelperExtensions.cs +++ b/src/Umbraco.Web/CacheHelperExtensions.cs @@ -19,7 +19,7 @@ namespace Umbraco.Web /// /// Outputs and caches a partial view in MVC /// - /// + /// /// /// /// @@ -28,7 +28,7 @@ namespace Umbraco.Web /// /// public static IHtmlString CachedPartialView( - this CacheHelper cacheHelper, + this AppCaches appCaches, HtmlHelper htmlHelper, string partialViewName, object model, @@ -43,7 +43,7 @@ namespace Umbraco.Web return htmlHelper.Partial(partialViewName, model, viewData); } - return cacheHelper.RuntimeCache.GetCacheItem( + return appCaches.RuntimeCache.GetCacheItem( PartialViewCacheKey + cacheKey, () => htmlHelper.Partial(partialViewName, model, viewData), priority: CacheItemPriority.NotRemovable, //not removable, the same as macros (apparently issue #27610) @@ -53,10 +53,10 @@ namespace Umbraco.Web /// /// Clears the cache for partial views /// - /// - public static void ClearPartialViewCache(this CacheHelper cacheHelper) + /// + public static void ClearPartialViewCache(this AppCaches appCaches) { - cacheHelper.RuntimeCache.ClearCacheByKeySearch(PartialViewCacheKey); + appCaches.RuntimeCache.ClearCacheByKeySearch(PartialViewCacheKey); } } } diff --git a/src/Umbraco.Web/Composing/Current.cs b/src/Umbraco.Web/Composing/Current.cs index 1e8f3d17f7..ed1853c351 100644 --- a/src/Umbraco.Web/Composing/Current.cs +++ b/src/Umbraco.Web/Composing/Current.cs @@ -203,7 +203,7 @@ namespace Umbraco.Web.Composing public static IProfilingLogger ProfilingLogger => CoreCurrent.ProfilingLogger; - public static CacheHelper ApplicationCache => CoreCurrent.ApplicationCache; + public static AppCaches ApplicationCache => CoreCurrent.ApplicationCache; public static ServiceContext Services => CoreCurrent.Services; diff --git a/src/Umbraco.Web/Controllers/UmbLoginController.cs b/src/Umbraco.Web/Controllers/UmbLoginController.cs index fc6613200c..684925c3e3 100644 --- a/src/Umbraco.Web/Controllers/UmbLoginController.cs +++ b/src/Umbraco.Web/Controllers/UmbLoginController.cs @@ -16,7 +16,7 @@ namespace Umbraco.Web.Controllers { } - public UmbLoginController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, CacheHelper applicationCache, ILogger logger, IProfilingLogger profilingLogger) + public UmbLoginController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, AppCaches applicationCache, ILogger logger, IProfilingLogger profilingLogger) : base(umbracoContext, databaseFactory, services, applicationCache, logger, profilingLogger) { } diff --git a/src/Umbraco.Web/Controllers/UmbLoginStatusController.cs b/src/Umbraco.Web/Controllers/UmbLoginStatusController.cs index 83f4ae04a1..3f394824f6 100644 --- a/src/Umbraco.Web/Controllers/UmbLoginStatusController.cs +++ b/src/Umbraco.Web/Controllers/UmbLoginStatusController.cs @@ -18,7 +18,7 @@ namespace Umbraco.Web.Controllers { } - public UmbLoginStatusController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, CacheHelper applicationCache, ILogger logger, IProfilingLogger profilingLogger) : base(umbracoContext, databaseFactory, services, applicationCache, logger, profilingLogger) + public UmbLoginStatusController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, AppCaches applicationCache, ILogger logger, IProfilingLogger profilingLogger) : base(umbracoContext, databaseFactory, services, applicationCache, logger, profilingLogger) { } diff --git a/src/Umbraco.Web/Controllers/UmbProfileController.cs b/src/Umbraco.Web/Controllers/UmbProfileController.cs index 7ee8385edc..459d1b1829 100644 --- a/src/Umbraco.Web/Controllers/UmbProfileController.cs +++ b/src/Umbraco.Web/Controllers/UmbProfileController.cs @@ -19,7 +19,7 @@ namespace Umbraco.Web.Controllers { } - public UmbProfileController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, CacheHelper applicationCache, ILogger logger, IProfilingLogger profilingLogger) : base(umbracoContext, databaseFactory, services, applicationCache, logger, profilingLogger) + public UmbProfileController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, AppCaches applicationCache, ILogger logger, IProfilingLogger profilingLogger) : base(umbracoContext, databaseFactory, services, applicationCache, logger, profilingLogger) { } diff --git a/src/Umbraco.Web/Controllers/UmbRegisterController.cs b/src/Umbraco.Web/Controllers/UmbRegisterController.cs index 5a5024dad9..0288995b1f 100644 --- a/src/Umbraco.Web/Controllers/UmbRegisterController.cs +++ b/src/Umbraco.Web/Controllers/UmbRegisterController.cs @@ -18,7 +18,7 @@ namespace Umbraco.Web.Controllers { } - public UmbRegisterController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, CacheHelper applicationCache, ILogger logger, IProfilingLogger profilingLogger) : base(umbracoContext, databaseFactory, services, applicationCache, logger, profilingLogger) + public UmbRegisterController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, AppCaches applicationCache, ILogger logger, IProfilingLogger profilingLogger) : base(umbracoContext, databaseFactory, services, applicationCache, logger, profilingLogger) { } diff --git a/src/Umbraco.Web/Editors/AuthenticationController.cs b/src/Umbraco.Web/Editors/AuthenticationController.cs index 231ec9ba67..d1c9ec48bb 100644 --- a/src/Umbraco.Web/Editors/AuthenticationController.cs +++ b/src/Umbraco.Web/Editors/AuthenticationController.cs @@ -52,7 +52,7 @@ namespace Umbraco.Web.Editors /// /// Initializes a new instance of the class with all its dependencies. /// - public AuthenticationController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) + public AuthenticationController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) : base(globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) { } diff --git a/src/Umbraco.Web/Editors/BackOfficeController.cs b/src/Umbraco.Web/Editors/BackOfficeController.cs index 6294a0377f..414c248041 100644 --- a/src/Umbraco.Web/Editors/BackOfficeController.cs +++ b/src/Umbraco.Web/Editors/BackOfficeController.cs @@ -49,7 +49,7 @@ namespace Umbraco.Web.Editors private const string TokenPasswordResetCode = "PasswordResetCode"; private static readonly string[] TempDataTokenNames = { TokenExternalSignInError, TokenPasswordResetCode }; - public BackOfficeController(ManifestParser manifestParser, UmbracoFeatures features, IGlobalSettings globalSettings, UmbracoContext umbracoContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, IProfilingLogger profilingLogger, IRuntimeState runtimeState) + public BackOfficeController(ManifestParser manifestParser, UmbracoFeatures features, IGlobalSettings globalSettings, UmbracoContext umbracoContext, ServiceContext services, AppCaches applicationCache, ILogger logger, IProfilingLogger profilingLogger, IRuntimeState runtimeState) : base(globalSettings, umbracoContext, services, applicationCache, logger, profilingLogger) { _manifestParser = manifestParser; diff --git a/src/Umbraco.Web/Editors/ContentTypeController.cs b/src/Umbraco.Web/Editors/ContentTypeController.cs index 670d37e7a7..84ce177eef 100644 --- a/src/Umbraco.Web/Editors/ContentTypeController.cs +++ b/src/Umbraco.Web/Editors/ContentTypeController.cs @@ -56,7 +56,7 @@ namespace Umbraco.Web.Editors IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, PropertyEditorCollection propertyEditors, - ServiceContext services, CacheHelper applicationCache, + ServiceContext services, AppCaches applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) : base(cultureDictionaryFactory, globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) { diff --git a/src/Umbraco.Web/Editors/ContentTypeControllerBase.cs b/src/Umbraco.Web/Editors/ContentTypeControllerBase.cs index 898208319a..8d23a34c5e 100644 --- a/src/Umbraco.Web/Editors/ContentTypeControllerBase.cs +++ b/src/Umbraco.Web/Editors/ContentTypeControllerBase.cs @@ -33,7 +33,7 @@ namespace Umbraco.Web.Editors private readonly ICultureDictionaryFactory _cultureDictionaryFactory; private ICultureDictionary _cultureDictionary; - protected ContentTypeControllerBase(ICultureDictionaryFactory cultureDictionaryFactory, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) : base(globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) + protected ContentTypeControllerBase(ICultureDictionaryFactory cultureDictionaryFactory, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) : base(globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) { _cultureDictionaryFactory = cultureDictionaryFactory; } diff --git a/src/Umbraco.Web/Editors/DashboardController.cs b/src/Umbraco.Web/Editors/DashboardController.cs index 8960f110c3..3fdf1b78c8 100644 --- a/src/Umbraco.Web/Editors/DashboardController.cs +++ b/src/Umbraco.Web/Editors/DashboardController.cs @@ -38,7 +38,7 @@ namespace Umbraco.Web.Editors /// /// Initializes a new instance of the with all its dependencies. /// - public DashboardController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState, Dashboards dashboards) + public DashboardController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches applicationCache, IProfilingLogger logger, IRuntimeState runtimeState, Dashboards dashboards) : base(globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) { _dashboards = dashboards; diff --git a/src/Umbraco.Web/Editors/MediaTypeController.cs b/src/Umbraco.Web/Editors/MediaTypeController.cs index f2b8fd3dda..b8617e6f94 100644 --- a/src/Umbraco.Web/Editors/MediaTypeController.cs +++ b/src/Umbraco.Web/Editors/MediaTypeController.cs @@ -37,7 +37,7 @@ namespace Umbraco.Web.Editors [MediaTypeControllerControllerConfiguration] public class MediaTypeController : ContentTypeControllerBase { - public MediaTypeController(ICultureDictionaryFactory cultureDictionaryFactory, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) : base(cultureDictionaryFactory, globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) + public MediaTypeController(ICultureDictionaryFactory cultureDictionaryFactory, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) : base(cultureDictionaryFactory, globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) { } diff --git a/src/Umbraco.Web/Editors/MemberTypeController.cs b/src/Umbraco.Web/Editors/MemberTypeController.cs index 3abc0035d3..4ba5204e4d 100644 --- a/src/Umbraco.Web/Editors/MemberTypeController.cs +++ b/src/Umbraco.Web/Editors/MemberTypeController.cs @@ -30,7 +30,7 @@ namespace Umbraco.Web.Editors [UmbracoTreeAuthorize(new string[] { Constants.Trees.MemberTypes, Constants.Trees.Members})] public class MemberTypeController : ContentTypeControllerBase { - public MemberTypeController(ICultureDictionaryFactory cultureDictionaryFactory, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) : base(cultureDictionaryFactory, globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) + public MemberTypeController(ICultureDictionaryFactory cultureDictionaryFactory, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) : base(cultureDictionaryFactory, globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) { } diff --git a/src/Umbraco.Web/Editors/PackageInstallController.cs b/src/Umbraco.Web/Editors/PackageInstallController.cs index 05d1e2a7a3..f59fd360ed 100644 --- a/src/Umbraco.Web/Editors/PackageInstallController.cs +++ b/src/Umbraco.Web/Editors/PackageInstallController.cs @@ -45,7 +45,7 @@ namespace Umbraco.Web.Editors public class PackageInstallController : UmbracoAuthorizedJsonController { public PackageInstallController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, - ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, + ISqlContext sqlContext, ServiceContext services, AppCaches applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) : base(globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) { diff --git a/src/Umbraco.Web/Editors/UmbracoAuthorizedJsonController.cs b/src/Umbraco.Web/Editors/UmbracoAuthorizedJsonController.cs index 3baa5e85ff..8cb9408044 100644 --- a/src/Umbraco.Web/Editors/UmbracoAuthorizedJsonController.cs +++ b/src/Umbraco.Web/Editors/UmbracoAuthorizedJsonController.cs @@ -37,7 +37,7 @@ namespace Umbraco.Web.Editors /// /// /// - protected UmbracoAuthorizedJsonController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) : base(globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) + protected UmbracoAuthorizedJsonController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) : base(globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) { } } diff --git a/src/Umbraco.Web/Mvc/PluginController.cs b/src/Umbraco.Web/Mvc/PluginController.cs index a8d73fe575..a8e7f1f0d1 100644 --- a/src/Umbraco.Web/Mvc/PluginController.cs +++ b/src/Umbraco.Web/Mvc/PluginController.cs @@ -50,7 +50,7 @@ namespace Umbraco.Web.Mvc /// /// Gets or sets the application cache. /// - public CacheHelper ApplicationCache { get; } + public AppCaches ApplicationCache { get; } /// /// Gets or sets the logger. @@ -93,14 +93,14 @@ namespace Umbraco.Web.Mvc Current.Factory.GetInstance(), Current.Factory.GetInstance(), Current.Factory.GetInstance(), - Current.Factory.GetInstance(), + Current.Factory.GetInstance(), Current.Factory.GetInstance(), Current.Factory.GetInstance() ) { } - protected PluginController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, CacheHelper applicationCache, ILogger logger, IProfilingLogger profilingLogger) + protected PluginController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, AppCaches applicationCache, ILogger logger, IProfilingLogger profilingLogger) { UmbracoContext = umbracoContext; DatabaseFactory = databaseFactory; diff --git a/src/Umbraco.Web/Mvc/RenderMvcController.cs b/src/Umbraco.Web/Mvc/RenderMvcController.cs index 44a6a9346d..dc775450bf 100644 --- a/src/Umbraco.Web/Mvc/RenderMvcController.cs +++ b/src/Umbraco.Web/Mvc/RenderMvcController.cs @@ -24,7 +24,7 @@ namespace Umbraco.Web.Mvc ActionInvoker = new RenderActionInvoker(); } - public RenderMvcController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, IProfilingLogger profilingLogger) + public RenderMvcController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ServiceContext services, AppCaches applicationCache, ILogger logger, IProfilingLogger profilingLogger) : base(globalSettings, umbracoContext, services, applicationCache, logger, profilingLogger) { ActionInvoker = new RenderActionInvoker(); diff --git a/src/Umbraco.Web/Mvc/SurfaceController.cs b/src/Umbraco.Web/Mvc/SurfaceController.cs index b3e67e4b2b..1035d43739 100644 --- a/src/Umbraco.Web/Mvc/SurfaceController.cs +++ b/src/Umbraco.Web/Mvc/SurfaceController.cs @@ -21,7 +21,7 @@ namespace Umbraco.Web.Mvc { } - protected SurfaceController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, CacheHelper applicationCache, ILogger logger, IProfilingLogger profilingLogger) + protected SurfaceController(UmbracoContext umbracoContext, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, AppCaches applicationCache, ILogger logger, IProfilingLogger profilingLogger) : base(umbracoContext, databaseFactory, services, applicationCache, logger, profilingLogger) { } diff --git a/src/Umbraco.Web/Mvc/UmbracoAuthorizedController.cs b/src/Umbraco.Web/Mvc/UmbracoAuthorizedController.cs index 2f8f7a6e76..7084b79271 100644 --- a/src/Umbraco.Web/Mvc/UmbracoAuthorizedController.cs +++ b/src/Umbraco.Web/Mvc/UmbracoAuthorizedController.cs @@ -20,7 +20,7 @@ namespace Umbraco.Web.Mvc protected UmbracoAuthorizedController() { } - protected UmbracoAuthorizedController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, IProfilingLogger profilingLogger) + protected UmbracoAuthorizedController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ServiceContext services, AppCaches applicationCache, ILogger logger, IProfilingLogger profilingLogger) : base(globalSettings, umbracoContext, services, applicationCache, logger, profilingLogger) { } } diff --git a/src/Umbraco.Web/Mvc/UmbracoController.cs b/src/Umbraco.Web/Mvc/UmbracoController.cs index 36f688b714..7d451321bc 100644 --- a/src/Umbraco.Web/Mvc/UmbracoController.cs +++ b/src/Umbraco.Web/Mvc/UmbracoController.cs @@ -48,7 +48,7 @@ namespace Umbraco.Web.Mvc /// /// Gets or sets the application cache. /// - public CacheHelper ApplicationCache { get; set; } + public AppCaches ApplicationCache { get; set; } /// /// Gets or sets the logger. @@ -83,14 +83,14 @@ namespace Umbraco.Web.Mvc Current.Factory.GetInstance(), Current.Factory.GetInstance(), Current.Factory.GetInstance(), - Current.Factory.GetInstance(), + Current.Factory.GetInstance(), Current.Factory.GetInstance(), Current.Factory.GetInstance() ) { } - protected UmbracoController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ServiceContext services, CacheHelper applicationCache, ILogger logger, IProfilingLogger profilingLogger) + protected UmbracoController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ServiceContext services, AppCaches applicationCache, ILogger logger, IProfilingLogger profilingLogger) { GlobalSettings = globalSettings; UmbracoContext = umbracoContext; diff --git a/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs b/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs index 394aa39dd9..2c5c0395a4 100644 --- a/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs +++ b/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs @@ -39,7 +39,7 @@ namespace Umbraco.Web.Mvc /// /// Gets or sets the application cache. /// - public CacheHelper ApplicationCache { get; set; } + public AppCaches ApplicationCache { get; set; } // fixme // previously, Services and ApplicationCache would derive from UmbracoContext.Application, which @@ -110,12 +110,12 @@ namespace Umbraco.Web.Mvc protected UmbracoViewPage() : this( Current.Factory.GetInstance(), - Current.Factory.GetInstance() + Current.Factory.GetInstance() ) { } - protected UmbracoViewPage(ServiceContext services, CacheHelper applicationCache) + protected UmbracoViewPage(ServiceContext services, AppCaches applicationCache) { Services = services; ApplicationCache = applicationCache; diff --git a/src/Umbraco.Web/Runtime/WebRuntime.cs b/src/Umbraco.Web/Runtime/WebRuntime.cs index ad1a4851f0..c69a3bec8b 100644 --- a/src/Umbraco.Web/Runtime/WebRuntime.cs +++ b/src/Umbraco.Web/Runtime/WebRuntime.cs @@ -59,7 +59,7 @@ namespace Umbraco.Web.Runtime protected override IProfiler GetProfiler() => _webProfiler; - protected override CacheHelper GetAppCaches() => new CacheHelper( + protected override AppCaches GetAppCaches() => new AppCaches( // we need to have the dep clone runtime cache provider to ensure // all entities are cached properly (cloned in and cloned out) new DeepCloneRuntimeCacheProvider(new HttpRuntimeCacheProvider(HttpRuntime.Cache)), diff --git a/src/Umbraco.Web/Security/MembershipHelper.cs b/src/Umbraco.Web/Security/MembershipHelper.cs index eb4c24aabc..6ae8ff8c96 100644 --- a/src/Umbraco.Web/Security/MembershipHelper.cs +++ b/src/Umbraco.Web/Security/MembershipHelper.cs @@ -32,7 +32,7 @@ namespace Umbraco.Web.Security private readonly IUserService _userService; private readonly IPublicAccessService _publicAccessService; private readonly PublishedRouter _publishedRouter; - private readonly CacheHelper _appCaches; + private readonly AppCaches _appCaches; private readonly ILogger _logger; #region Constructors @@ -47,7 +47,7 @@ namespace Umbraco.Web.Security IUserService userService, IPublicAccessService publicAccessService, PublishedRouter publishedRouter, - CacheHelper appCaches, + AppCaches appCaches, ILogger logger ) { diff --git a/src/Umbraco.Web/Services/ApplicationTreeService.cs b/src/Umbraco.Web/Services/ApplicationTreeService.cs index 86bfc5d0bb..2ddec054c7 100644 --- a/src/Umbraco.Web/Services/ApplicationTreeService.cs +++ b/src/Umbraco.Web/Services/ApplicationTreeService.cs @@ -19,7 +19,7 @@ namespace Umbraco.Web.Services internal class ApplicationTreeService : IApplicationTreeService { private readonly ILogger _logger; - private readonly CacheHelper _cache; + private readonly AppCaches _cache; private readonly TypeLoader _typeLoader; private Lazy> _allAvailableTrees; internal const string TreeConfigFileName = "trees.config"; @@ -27,7 +27,7 @@ namespace Umbraco.Web.Services private static readonly object Locker = new object(); private readonly Lazy>> _groupedTrees; - public ApplicationTreeService(ILogger logger, CacheHelper cache, TypeLoader typeLoader) + public ApplicationTreeService(ILogger logger, AppCaches cache, TypeLoader typeLoader) { _logger = logger; _cache = cache; diff --git a/src/Umbraco.Web/Services/SectionService.cs b/src/Umbraco.Web/Services/SectionService.cs index 6337db67f9..2d06141292 100644 --- a/src/Umbraco.Web/Services/SectionService.cs +++ b/src/Umbraco.Web/Services/SectionService.cs @@ -23,7 +23,7 @@ namespace Umbraco.Web.Services private readonly Lazy> _allAvailableSections; private readonly IApplicationTreeService _applicationTreeService; private readonly IScopeProvider _scopeProvider; - private readonly CacheHelper _cache; + private readonly AppCaches _cache; internal const string AppConfigFileName = "applications.config"; private static string _appConfig; private static readonly object Locker = new object(); @@ -32,7 +32,7 @@ namespace Umbraco.Web.Services IUserService userService, IApplicationTreeService applicationTreeService, IScopeProvider scopeProvider, - CacheHelper cache) + AppCaches cache) { _applicationTreeService = applicationTreeService ?? throw new ArgumentNullException(nameof(applicationTreeService)); _cache = cache ?? throw new ArgumentNullException(nameof(cache)); diff --git a/src/Umbraco.Web/TagsController.cs b/src/Umbraco.Web/TagsController.cs index 181b9f7da2..784f1d9883 100644 --- a/src/Umbraco.Web/TagsController.cs +++ b/src/Umbraco.Web/TagsController.cs @@ -29,7 +29,7 @@ namespace Umbraco.Web.WebServices /// /// Initializes a new instance of the with all its dependencies. /// - public TagsController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) + public TagsController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) : base(globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) { } diff --git a/src/Umbraco.Web/WebApi/UmbracoApiController.cs b/src/Umbraco.Web/WebApi/UmbracoApiController.cs index 3db3610cc2..a779632def 100644 --- a/src/Umbraco.Web/WebApi/UmbracoApiController.cs +++ b/src/Umbraco.Web/WebApi/UmbracoApiController.cs @@ -23,7 +23,7 @@ namespace Umbraco.Web.WebApi /// /// Initialize a new instance of the with all its dependencies. /// - protected UmbracoApiController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) + protected UmbracoApiController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) : base(globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) { } } diff --git a/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs b/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs index 21b88cc919..44457fbef1 100644 --- a/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs +++ b/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs @@ -39,7 +39,7 @@ namespace Umbraco.Web.WebApi Current.Factory.GetInstance(), Current.Factory.GetInstance(), Current.Factory.GetInstance(), - Current.Factory.GetInstance(), + Current.Factory.GetInstance(), Current.Factory.GetInstance(), Current.Factory.GetInstance() ) @@ -48,7 +48,7 @@ namespace Umbraco.Web.WebApi /// /// Initializes a new instance of the class with all its dependencies. /// - protected UmbracoApiControllerBase(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) + protected UmbracoApiControllerBase(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) { GlobalSettings = globalSettings; _umbracoContextAccessor = umbracoContextAccessor; @@ -88,7 +88,7 @@ namespace Umbraco.Web.WebApi /// /// Gets the application cache. /// - public CacheHelper ApplicationCache { get; } + public AppCaches ApplicationCache { get; } /// /// Gets the logger. diff --git a/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs b/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs index 4ae9c00a47..1d20857efd 100644 --- a/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs +++ b/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs @@ -40,7 +40,7 @@ namespace Umbraco.Web.WebApi /// /// Initializes a new instance of the class with all its dependencies. /// - protected UmbracoAuthorizedApiController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, CacheHelper applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) + protected UmbracoAuthorizedApiController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches applicationCache, IProfilingLogger logger, IRuntimeState runtimeState) : base(globalSettings, umbracoContextAccessor, sqlContext, services, applicationCache, logger, runtimeState) { } From 1667e914cd4354f9edcb45cedeaf0d4b3108faad Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 17 Jan 2019 18:38:55 +1100 Subject: [PATCH 409/469] Allows the tree collection to be manipulated by devs on startup, renames some things --- src/Umbraco.Web/Runtime/WebRuntimeComposer.cs | 13 +++++-------- src/Umbraco.Web/Services/ITreeService.cs | 8 ++++---- src/Umbraco.Web/Services/TreeService.cs | 8 ++++---- .../Trees/ApplicationTreeController.cs | 2 +- .../Trees/BackOfficeSectionCollectionBuilder.cs | 9 ++------- src/Umbraco.Web/Trees/ITree.cs | 3 ++- src/Umbraco.Web/Trees/Tree.cs | 2 +- src/Umbraco.Web/Trees/TreeCollectionBuilder.cs | 15 +++++++-------- 8 files changed, 26 insertions(+), 34 deletions(-) diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs b/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs index f21c040a37..1a0bf8d1b0 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs @@ -1,15 +1,13 @@ -using System.Web; +using System.Linq; +using System.Web; using System.Web.Security; using Examine; using Microsoft.AspNet.SignalR; using Umbraco.Core; using Umbraco.Core.Components; using Umbraco.Core.Composing; -using Umbraco.Core.Configuration; using Umbraco.Core.Dictionary; using Umbraco.Core.Events; -using Umbraco.Core.Models; -using Umbraco.Core.Models.ContentEditing; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.PropertyEditors; using Umbraco.Core.PropertyEditors.ValueConverters; @@ -23,9 +21,7 @@ using Umbraco.Web.Dictionary; using Umbraco.Web.Editors; using Umbraco.Web.Features; using Umbraco.Web.HealthCheck; -using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Models.PublishedContent; -using Umbraco.Web.Models.Trees; using Umbraco.Web.Mvc; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; @@ -207,12 +203,13 @@ namespace Umbraco.Web.Runtime .Append(); // register back office trees - foreach (var treeControllerType in umbracoApiControllerTypes) + foreach (var treeControllerType in umbracoApiControllerTypes + .Where(x => typeof(TreeControllerBase).IsAssignableFrom(x))) { var attribute = treeControllerType.GetCustomAttribute(false); if (attribute == null) continue; var tree = new Tree(attribute.SortOrder, attribute.ApplicationAlias, attribute.TreeAlias, attribute.TreeTitle, treeControllerType, attribute.IsSingleNodeTree); - composition.WithCollectionBuilder().AddTree(tree); + composition.WithCollectionBuilder().Trees.Add(tree); } } } diff --git a/src/Umbraco.Web/Services/ITreeService.cs b/src/Umbraco.Web/Services/ITreeService.cs index 5172e4b7b7..96787086c6 100644 --- a/src/Umbraco.Web/Services/ITreeService.cs +++ b/src/Umbraco.Web/Services/ITreeService.cs @@ -26,16 +26,16 @@ namespace Umbraco.Web.Services /// /// Gets the application tree for the applcation with the specified alias /// - /// The application alias. + /// The application alias. /// Returns a ApplicationTree Array - IEnumerable GetApplicationTrees(string applicationAlias); + IEnumerable GetTrees(string sectionAlias); /// /// Gets the grouped application trees for the application with the specified alias /// - /// + /// /// - IDictionary> GetGroupedApplicationTrees(string applicationAlias); + IDictionary> GetGroupedTrees(string sectionAlias); } } diff --git a/src/Umbraco.Web/Services/TreeService.cs b/src/Umbraco.Web/Services/TreeService.cs index 8389c27a19..f58dce59bc 100644 --- a/src/Umbraco.Web/Services/TreeService.cs +++ b/src/Umbraco.Web/Services/TreeService.cs @@ -24,13 +24,13 @@ namespace Umbraco.Web.Services public IEnumerable GetAll() => _treeCollection; /// - public IEnumerable GetApplicationTrees(string applicationAlias) - => GetAll().Where(x => x.ApplicationAlias.InvariantEquals(applicationAlias)).OrderBy(x => x.SortOrder).ToList(); + public IEnumerable GetTrees(string sectionAlias) + => GetAll().Where(x => x.ApplicationAlias.InvariantEquals(sectionAlias)).OrderBy(x => x.SortOrder).ToList(); - public IDictionary> GetGroupedApplicationTrees(string applicationAlias) + public IDictionary> GetGroupedTrees(string sectionAlias) { var result = new Dictionary>(); - var foundTrees = GetApplicationTrees(applicationAlias).ToList(); + var foundTrees = GetTrees(sectionAlias).ToList(); foreach(var treeGroup in _groupedTrees.Value) { List resultGroup = null; diff --git a/src/Umbraco.Web/Trees/ApplicationTreeController.cs b/src/Umbraco.Web/Trees/ApplicationTreeController.cs index 5a0f72c8dc..5433f3c157 100644 --- a/src/Umbraco.Web/Trees/ApplicationTreeController.cs +++ b/src/Umbraco.Web/Trees/ApplicationTreeController.cs @@ -60,7 +60,7 @@ namespace Umbraco.Web.Trees if (string.IsNullOrEmpty(application)) throw new HttpResponseException(HttpStatusCode.NotFound); //find all tree definitions that have the current application alias - var groupedTrees = _treeService.GetGroupedApplicationTrees(application); + var groupedTrees = _treeService.GetGroupedTrees(application); var allTrees = groupedTrees.Values.SelectMany(x => x).ToList(); if (string.IsNullOrEmpty(tree) == false || allTrees.Count == 1) diff --git a/src/Umbraco.Web/Trees/BackOfficeSectionCollectionBuilder.cs b/src/Umbraco.Web/Trees/BackOfficeSectionCollectionBuilder.cs index ec5833f79c..3228cd309f 100644 --- a/src/Umbraco.Web/Trees/BackOfficeSectionCollectionBuilder.cs +++ b/src/Umbraco.Web/Trees/BackOfficeSectionCollectionBuilder.cs @@ -12,12 +12,6 @@ namespace Umbraco.Web.Trees { protected override BackOfficeSectionCollectionBuilder This => this; - // need to inject dependencies in the collection, so override creation - public override BackOfficeSectionCollection CreateCollection(IFactory factory) - { - return new BackOfficeSectionCollection(CreateItems(factory)); - } - protected override IEnumerable CreateItems(IFactory factory) { // get the manifest parser just-in-time - injecting it in the ctor would mean that @@ -25,7 +19,8 @@ namespace Umbraco.Web.Trees // its dependencies too, and that can create cycles or other oddities var manifestParser = factory.GetInstance(); - return base.CreateItems(factory).Concat(manifestParser.Manifest.Sections.Select(x => new ManifestBackOfficeSection(x.Key, x.Value))); + return base.CreateItems(factory) + .Concat(manifestParser.Manifest.Sections.Select(x => new ManifestBackOfficeSection(x.Key, x.Value))); } private class ManifestBackOfficeSection : IBackOfficeSection diff --git a/src/Umbraco.Web/Trees/ITree.cs b/src/Umbraco.Web/Trees/ITree.cs index f408ce5e60..867beda20e 100644 --- a/src/Umbraco.Web/Trees/ITree.cs +++ b/src/Umbraco.Web/Trees/ITree.cs @@ -1,7 +1,8 @@ namespace Umbraco.Web.Trees { //fixme - we don't really use this, it is nice to have the treecontroller, attribute and ApplicationTree streamlined to implement this but it's not used - public interface ITree + //leave as internal for now, maybe we'll use in the future, means we could pass around ITree + internal interface ITree { /// /// Gets or sets the sort order. diff --git a/src/Umbraco.Web/Trees/Tree.cs b/src/Umbraco.Web/Trees/Tree.cs index 3bac5bae58..39f5cec1eb 100644 --- a/src/Umbraco.Web/Trees/Tree.cs +++ b/src/Umbraco.Web/Trees/Tree.cs @@ -43,7 +43,7 @@ namespace Umbraco.Web.Trees public Type TreeControllerType { get; } - public static string GetRootNodeDisplayName(ITree tree, ILocalizedTextService textService) + internal static string GetRootNodeDisplayName(ITree tree, ILocalizedTextService textService) { var label = $"[{tree.TreeAlias}]"; diff --git a/src/Umbraco.Web/Trees/TreeCollectionBuilder.cs b/src/Umbraco.Web/Trees/TreeCollectionBuilder.cs index 143b8e308b..ae2675bac9 100644 --- a/src/Umbraco.Web/Trees/TreeCollectionBuilder.cs +++ b/src/Umbraco.Web/Trees/TreeCollectionBuilder.cs @@ -3,16 +3,15 @@ using Umbraco.Core.Composing; namespace Umbraco.Web.Trees { - //fixme - how will we allow users to modify these items? they will need to be able to change the ApplicationTree's registered (i.e. sort order, section) - public class TreeCollectionBuilder : CollectionBuilderBase + public class TreeCollectionBuilder : ICollectionBuilder { - private readonly List _instances = new List(); + /// + /// expose the list of trees which developers can manipulate before the collection is created + /// + public List Trees { get; } = new List(); - public void AddTree(Tree tree) - { - _instances.Add(tree); - } + public TreeCollection CreateCollection(IFactory factory) => new TreeCollection(Trees); - protected override IEnumerable CreateItems(IFactory factory) => _instances; + public void RegisterWith(IRegister register) => register.Register(CreateCollection, Lifetime.Singleton); } } From 0bee01e0eeea61ba2861a9e3b16f3594ea9a9396 Mon Sep 17 00:00:00 2001 From: Stephan Date: Thu, 17 Jan 2019 11:01:23 +0100 Subject: [PATCH 410/469] Great AppCaches renaming --- src/Umbraco.Core/Cache/AppCaches.cs | 75 +++-- .../Cache/AppPolicedCacheDictionary.cs | 74 +++++ .../Cache/CacheProviderExtensions.cs | 24 +- src/Umbraco.Core/Cache/CacheRefresherBase.cs | 2 +- src/Umbraco.Core/Cache/DeepCloneAppCache.cs | 157 ++++++++++ .../Cache/DeepCloneRuntimeCacheProvider.cs | 155 ---------- .../Cache/DefaultRepositoryCachePolicy.cs | 30 +- .../Cache/DictionaryCacheProvider.cs | 178 ++++------- ...rBase.cs => FastDictionaryAppCacheBase.cs} | 242 ++++++++------- .../Cache/FastDictionaryCacheProvider.cs | 162 ++++++++++ .../Cache/FullDataSetRepositoryCachePolicy.cs | 8 +- ...acheProvider.cs => HttpRequestAppCache.cs} | 157 +++++----- src/Umbraco.Core/Cache/IAppCache.cs | 94 ++++++ src/Umbraco.Core/Cache/IAppPolicedCache.cs | 54 ++++ src/Umbraco.Core/Cache/ICacheProvider.cs | 68 ----- .../Cache/IRuntimeCacheProvider.cs | 35 --- src/Umbraco.Core/Cache/IsolatedCaches.cs | 41 +++ .../Cache/IsolatedRuntimeCache.cs | 91 ------ src/Umbraco.Core/Cache/NoAppCache.cs | 82 +++++ .../Cache/NoCacheRepositoryCachePolicy.cs | 2 +- src/Umbraco.Core/Cache/NullCacheProvider.cs | 66 ---- ...acheProvider.cs => ObjectCacheAppCache.cs} | 283 +++++++++--------- .../Cache/RepositoryCachePolicyBase.cs | 10 +- .../SingleItemsOnlyRepositoryCachePolicy.cs | 2 +- src/Umbraco.Core/Cache/StaticCacheProvider.cs | 79 ----- ...CacheProvider.cs => WebCachingAppCache.cs} | 118 +++----- src/Umbraco.Core/Composing/TypeLoader.cs | 8 +- src/Umbraco.Core/ConfigsExtensions.cs | 2 +- .../Configuration/Grid/GridConfig.cs | 2 +- .../Configuration/Grid/GridEditorsConfig.cs | 4 +- src/Umbraco.Core/Manifest/ManifestParser.cs | 6 +- src/Umbraco.Core/Models/UserExtensions.cs | 2 +- .../Implement/ConsentRepository.cs | 2 +- .../Implement/DictionaryRepository.cs | 12 +- .../Implement/RepositoryBaseOfTIdTEntity.cs | 12 +- src/Umbraco.Core/Runtime/CoreRuntime.cs | 8 +- src/Umbraco.Core/Scoping/IScope.cs | 2 +- src/Umbraco.Core/Scoping/Scope.cs | 10 +- .../LocalizedTextServiceFileSources.cs | 6 +- src/Umbraco.Core/Umbraco.Core.csproj | 23 +- src/Umbraco.Tests/Cache/CacheProviderTests.cs | 94 +++--- .../DeepCloneRuntimeCacheProviderTests.cs | 16 +- .../Cache/DefaultCachePolicyTests.cs | 26 +- .../Cache/FullDataSetCachePolicyTests.cs | 32 +- .../Cache/HttpRequestCacheProviderTests.cs | 14 +- .../Cache/HttpRuntimeCacheProviderTests.cs | 16 +- .../Cache/ObjectCacheProviderTests.cs | 8 +- .../PublishedContentCacheTests.cs | 2 +- .../PublishedMediaCacheTests.cs | 8 +- .../Cache/RuntimeCacheProviderTests.cs | 4 +- .../Cache/SingleItemsOnlyCachePolicyTests.cs | 10 +- .../Composing/ComposingTestBase.cs | 2 +- .../Composing/TypeLoaderTests.cs | 2 +- src/Umbraco.Tests/CoreThings/UdiTests.cs | 2 +- .../FrontEnd/UmbracoHelperTests.cs | 2 +- src/Umbraco.Tests/Macros/MacroTests.cs | 8 +- .../Manifest/ManifestParserTests.cs | 2 +- src/Umbraco.Tests/Models/ContentTests.cs | 6 +- .../Repositories/DocumentRepositoryTest.cs | 8 +- .../Repositories/MediaRepositoryTest.cs | 8 +- .../Published/PropertyCacheLevelTests.cs | 4 +- .../PublishedContentSnapshotTestBase.cs | 2 +- .../PublishedContent/PublishedContentTests.cs | 2 +- .../PublishedContent/PublishedMediaTests.cs | 20 +- .../SolidPublishedSnapshot.cs | 4 +- .../Scoping/ScopedRepositoryTests.cs | 54 ++-- .../TestHelpers/BaseUsingSqlCeSyntax.cs | 2 +- .../TestHelpers/TestWithDatabaseBase.cs | 2 +- src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 6 +- .../Web/Mvc/UmbracoViewPageTests.cs | 2 +- .../Web/TemplateUtilitiesTests.cs | 2 +- .../Cache/ApplicationCacheRefresher.cs | 4 +- .../Cache/ApplicationTreeCacheRefresher.cs | 4 +- .../Cache/ContentCacheRefresher.cs | 12 +- .../Cache/DataTypeCacheRefresher.cs | 2 +- src/Umbraco.Web/Cache/MacroCacheRefresher.cs | 12 +- src/Umbraco.Web/Cache/MediaCacheRefresher.cs | 8 +- src/Umbraco.Web/Cache/MemberCacheRefresher.cs | 6 +- .../Cache/MemberGroupCacheRefresher.cs | 2 +- .../Cache/RelationTypeCacheRefresher.cs | 8 +- .../Cache/TemplateCacheRefresher.cs | 2 +- src/Umbraco.Web/Cache/UserCacheRefresher.cs | 4 +- .../Cache/UserGroupCacheRefresher.cs | 10 +- src/Umbraco.Web/CacheHelperExtensions.cs | 2 +- .../Dictionary/UmbracoCultureDictionary.cs | 6 +- .../Editors/ExamineManagementController.cs | 10 +- src/Umbraco.Web/Editors/UsersController.cs | 2 +- src/Umbraco.Web/Macros/MacroRenderer.cs | 2 +- .../Models/Mapping/UserMapperProfile.cs | 2 +- .../PublishedCache/IPublishedSnapshot.cs | 4 +- .../PublishedCache/NuCache/ContentCache.cs | 8 +- .../PublishedCache/NuCache/MediaCache.cs | 8 +- .../PublishedCache/NuCache/MemberCache.cs | 4 +- .../PublishedCache/NuCache/Property.cs | 6 +- .../NuCache/PublishedContent.cs | 10 +- .../NuCache/PublishedSnapshot.cs | 8 +- .../NuCache/PublishedSnapshotService.cs | 8 +- .../PublishedElementPropertyBase.cs | 6 +- .../DictionaryPublishedContent.cs | 4 +- .../PublishedContentCache.cs | 6 +- .../XmlPublishedCache/PublishedMediaCache.cs | 12 +- .../XmlPublishedCache/PublishedMemberCache.cs | 4 +- .../XmlPublishedCache/PublishedSnapshot.cs | 4 +- .../PublishedSnapshotService.cs | 6 +- .../XmlPublishedCache/XmlPublishedContent.cs | 10 +- src/Umbraco.Web/Runtime/WebRuntime.cs | 10 +- .../Services/ApplicationTreeService.cs | 2 +- src/Umbraco.Web/Services/SectionService.cs | 2 +- 108 files changed, 1538 insertions(+), 1440 deletions(-) create mode 100644 src/Umbraco.Core/Cache/AppPolicedCacheDictionary.cs create mode 100644 src/Umbraco.Core/Cache/DeepCloneAppCache.cs delete mode 100644 src/Umbraco.Core/Cache/DeepCloneRuntimeCacheProvider.cs rename src/Umbraco.Core/Cache/{DictionaryCacheProviderBase.cs => FastDictionaryAppCacheBase.cs} (81%) create mode 100644 src/Umbraco.Core/Cache/FastDictionaryCacheProvider.cs rename src/Umbraco.Core/Cache/{HttpRequestCacheProvider.cs => HttpRequestAppCache.cs} (53%) create mode 100644 src/Umbraco.Core/Cache/IAppCache.cs create mode 100644 src/Umbraco.Core/Cache/IAppPolicedCache.cs delete mode 100644 src/Umbraco.Core/Cache/ICacheProvider.cs delete mode 100644 src/Umbraco.Core/Cache/IRuntimeCacheProvider.cs create mode 100644 src/Umbraco.Core/Cache/IsolatedCaches.cs delete mode 100644 src/Umbraco.Core/Cache/IsolatedRuntimeCache.cs create mode 100644 src/Umbraco.Core/Cache/NoAppCache.cs delete mode 100644 src/Umbraco.Core/Cache/NullCacheProvider.cs rename src/Umbraco.Core/Cache/{ObjectCacheRuntimeCacheProvider.cs => ObjectCacheAppCache.cs} (73%) delete mode 100644 src/Umbraco.Core/Cache/StaticCacheProvider.cs rename src/Umbraco.Core/Cache/{HttpRuntimeCacheProvider.cs => WebCachingAppCache.cs} (68%) diff --git a/src/Umbraco.Core/Cache/AppCaches.cs b/src/Umbraco.Core/Cache/AppCaches.cs index 7dd95624ef..6372bccbab 100644 --- a/src/Umbraco.Core/Cache/AppCaches.cs +++ b/src/Umbraco.Core/Cache/AppCaches.cs @@ -4,47 +4,41 @@ using System.Web; namespace Umbraco.Core.Cache { /// - /// Represents the application-wide caches. + /// Represents the application caches. /// public class AppCaches { /// - /// Initializes a new instance for use in the web + /// Initializes a new instance of the for use in a web application. /// public AppCaches() - : this( - new HttpRuntimeCacheProvider(HttpRuntime.Cache), - new StaticCacheProvider(), - new HttpRequestCacheProvider(), - new IsolatedRuntimeCache(t => new ObjectCacheRuntimeCacheProvider())) - { - } + : this(HttpRuntime.Cache) + { } /// - /// Initializes a new instance for use in the web + /// Initializes a new instance of the for use in a web application. /// public AppCaches(System.Web.Caching.Cache cache) : this( - new HttpRuntimeCacheProvider(cache), - new StaticCacheProvider(), - new HttpRequestCacheProvider(), - new IsolatedRuntimeCache(t => new ObjectCacheRuntimeCacheProvider())) - { - } + new WebCachingAppCache(cache), + new DictionaryCacheProvider(), + new HttpRequestAppCache(), + new IsolatedCaches(t => new ObjectCacheAppCache())) + { } /// - /// Initializes a new instance based on the provided providers + /// Initializes a new instance of the with cache providers. /// public AppCaches( - IRuntimeCacheProvider httpCacheProvider, - ICacheProvider staticCacheProvider, - ICacheProvider requestCacheProvider, - IsolatedRuntimeCache isolatedCacheManager) + IAppPolicedCache runtimeCache, + IAppCache staticCacheProvider, + IAppCache requestCache, + IsolatedCaches isolatedCaches) { - RuntimeCache = httpCacheProvider ?? throw new ArgumentNullException(nameof(httpCacheProvider)); + RuntimeCache = runtimeCache ?? throw new ArgumentNullException(nameof(runtimeCache)); StaticCache = staticCacheProvider ?? throw new ArgumentNullException(nameof(staticCacheProvider)); - RequestCache = requestCacheProvider ?? throw new ArgumentNullException(nameof(requestCacheProvider)); - IsolatedRuntimeCache = isolatedCacheManager ?? throw new ArgumentNullException(nameof(isolatedCacheManager)); + RequestCache = requestCache ?? throw new ArgumentNullException(nameof(requestCache)); + IsolatedCaches = isolatedCaches ?? throw new ArgumentNullException(nameof(isolatedCaches)); } /// @@ -54,7 +48,7 @@ namespace Umbraco.Core.Cache /// When used by repositories, all cache policies apply, but the underlying caches do not cache anything. /// Used by tests. /// - public static AppCaches Disabled { get; } = new AppCaches(NullCacheProvider.Instance, NullCacheProvider.Instance, NullCacheProvider.Instance, new IsolatedRuntimeCache(_ => NullCacheProvider.Instance)); + public static AppCaches Disabled { get; } = new AppCaches(NoAppCache.Instance, NoAppCache.Instance, NoAppCache.Instance, new IsolatedCaches(_ => NoAppCache.Instance)); /// /// Gets the special no-cache instance. @@ -63,27 +57,42 @@ namespace Umbraco.Core.Cache /// When used by repositories, all cache policies are bypassed. /// Used by repositories that do no cache. /// - public static AppCaches NoCache { get; } = new AppCaches(NullCacheProvider.Instance, NullCacheProvider.Instance, NullCacheProvider.Instance, new IsolatedRuntimeCache(_ => NullCacheProvider.Instance)); + public static AppCaches NoCache { get; } = new AppCaches(NoAppCache.Instance, NoAppCache.Instance, NoAppCache.Instance, new IsolatedCaches(_ => NoAppCache.Instance)); /// - /// Returns the current Request cache + /// Gets the per-request cache. /// - public ICacheProvider RequestCache { get; internal set; } + /// + /// The per-request caches works on top of the current HttpContext items. + /// fixme - what about non-web applications? + /// + public IAppCache RequestCache { get; } /// /// Returns the current Runtime cache /// - public ICacheProvider StaticCache { get; internal set; } + /// + /// fixme - what is this? why not use RuntimeCache? + /// + public IAppCache StaticCache { get; } /// - /// Returns the current Runtime cache + /// Gets the runtime cache. /// - public IRuntimeCacheProvider RuntimeCache { get; internal set; } + /// + /// The runtime cache is the main application cache. + /// + public IAppPolicedCache RuntimeCache { get; } /// - /// Returns the current Isolated Runtime cache manager + /// Gets the isolated caches. /// - public IsolatedRuntimeCache IsolatedRuntimeCache { get; internal set; } + /// + /// Isolated caches are used by e.g. repositories, to ensure that each cached entity + /// type has its own cache, so that lookups are fast and the repository does not need to + /// search through all keys on a global scale. + /// + public IsolatedCaches IsolatedCaches { get; } } diff --git a/src/Umbraco.Core/Cache/AppPolicedCacheDictionary.cs b/src/Umbraco.Core/Cache/AppPolicedCacheDictionary.cs new file mode 100644 index 0000000000..51cc3c4c53 --- /dev/null +++ b/src/Umbraco.Core/Cache/AppPolicedCacheDictionary.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Concurrent; + +namespace Umbraco.Core.Cache +{ + /// + /// Provides a base class for implementing a dictionary of . + /// + /// The type of the dictionary key. + public abstract class AppPolicedCacheDictionary + { + private readonly ConcurrentDictionary _caches = new ConcurrentDictionary(); + + /// + /// Initializes a new instance of the class. + /// + /// + protected AppPolicedCacheDictionary(Func cacheFactory) + { + CacheFactory = cacheFactory; + } + + /// + /// Gets the internal cache factory, for tests only! + /// + internal readonly Func CacheFactory; + + /// + /// Gets or creates a cache. + /// + public IAppPolicedCache GetOrCreate(TKey key) + => _caches.GetOrAdd(key, k => CacheFactory(k)); + + /// + /// Tries to get a cache. + /// + public Attempt Get(TKey key) + => _caches.TryGetValue(key, out var cache) ? Attempt.Succeed(cache) : Attempt.Fail(); + + /// + /// Removes a cache. + /// + public void Remove(TKey key) + { + _caches.TryRemove(key, out _); + } + + /// + /// Removes all caches. + /// + public void RemoveAll() + { + _caches.Clear(); + } + + /// + /// Clears a cache. + /// + public void ClearCache(TKey key) + { + if (_caches.TryGetValue(key, out var cache)) + cache.Clear(); + } + + /// + /// Clears all caches. + /// + public void ClearAllCaches() + { + foreach (var cache in _caches.Values) + cache.Clear(); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Cache/CacheProviderExtensions.cs b/src/Umbraco.Core/Cache/CacheProviderExtensions.cs index e42cb4d9ad..0e41b981fb 100644 --- a/src/Umbraco.Core/Cache/CacheProviderExtensions.cs +++ b/src/Umbraco.Core/Cache/CacheProviderExtensions.cs @@ -10,7 +10,7 @@ namespace Umbraco.Core.Cache /// public static class CacheProviderExtensions { - public static T GetCacheItem(this IRuntimeCacheProvider provider, + public static T GetCacheItem(this IAppPolicedCache provider, string cacheKey, Func getCacheItem, TimeSpan? timeout, @@ -19,11 +19,11 @@ namespace Umbraco.Core.Cache CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null) { - var result = provider.GetCacheItem(cacheKey, () => getCacheItem(), timeout, isSliding, priority, removedCallback, dependentFiles); + var result = provider.Get(cacheKey, () => getCacheItem(), timeout, isSliding, priority, removedCallback, dependentFiles); return result == null ? default(T) : result.TryConvertTo().Result; } - public static void InsertCacheItem(this IRuntimeCacheProvider provider, + public static void InsertCacheItem(this IAppPolicedCache provider, string cacheKey, Func getCacheItem, TimeSpan? timeout = null, @@ -32,24 +32,24 @@ namespace Umbraco.Core.Cache CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null) { - provider.InsertCacheItem(cacheKey, () => getCacheItem(), timeout, isSliding, priority, removedCallback, dependentFiles); + provider.Insert(cacheKey, () => getCacheItem(), timeout, isSliding, priority, removedCallback, dependentFiles); } - public static IEnumerable GetCacheItemsByKeySearch(this ICacheProvider provider, string keyStartsWith) + public static IEnumerable GetCacheItemsByKeySearch(this IAppCache provider, string keyStartsWith) { - var result = provider.GetCacheItemsByKeySearch(keyStartsWith); + var result = provider.SearchByKey(keyStartsWith); return result.Select(x => x.TryConvertTo().Result); } - public static IEnumerable GetCacheItemsByKeyExpression(this ICacheProvider provider, string regexString) + public static IEnumerable GetCacheItemsByKeyExpression(this IAppCache provider, string regexString) { - var result = provider.GetCacheItemsByKeyExpression(regexString); + var result = provider.SearchByRegex(regexString); return result.Select(x => x.TryConvertTo().Result); } - public static T GetCacheItem(this ICacheProvider provider, string cacheKey) + public static T GetCacheItem(this IAppCache provider, string cacheKey) { - var result = provider.GetCacheItem(cacheKey); + var result = provider.Get(cacheKey); if (result == null) { return default(T); @@ -57,9 +57,9 @@ namespace Umbraco.Core.Cache return result.TryConvertTo().Result; } - public static T GetCacheItem(this ICacheProvider provider, string cacheKey, Func getCacheItem) + public static T GetCacheItem(this IAppCache provider, string cacheKey, Func getCacheItem) { - var result = provider.GetCacheItem(cacheKey, () => getCacheItem()); + var result = provider.Get(cacheKey, () => getCacheItem()); if (result == null) { return default(T); diff --git a/src/Umbraco.Core/Cache/CacheRefresherBase.cs b/src/Umbraco.Core/Cache/CacheRefresherBase.cs index 5e6ec593af..bfa16ff3fa 100644 --- a/src/Umbraco.Core/Cache/CacheRefresherBase.cs +++ b/src/Umbraco.Core/Cache/CacheRefresherBase.cs @@ -102,7 +102,7 @@ namespace Umbraco.Core.Cache protected void ClearAllIsolatedCacheByEntityType() where TEntity : class, IEntity { - AppCaches.IsolatedRuntimeCache.ClearCache(); + AppCaches.IsolatedCaches.ClearCache(); } /// diff --git a/src/Umbraco.Core/Cache/DeepCloneAppCache.cs b/src/Umbraco.Core/Cache/DeepCloneAppCache.cs new file mode 100644 index 0000000000..cdc66f1db7 --- /dev/null +++ b/src/Umbraco.Core/Cache/DeepCloneAppCache.cs @@ -0,0 +1,157 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web.Caching; +using Umbraco.Core.Models; +using Umbraco.Core.Models.Entities; + +namespace Umbraco.Core.Cache +{ + /// + /// Implements by wrapping an inner other + /// instance, and ensuring that all inserts and returns are deep cloned copies of the cache item, + /// when the item is deep-cloneable. + /// + internal class DeepCloneAppCache : IAppPolicedCache + { + /// + /// Initializes a new instance of the class. + /// + public DeepCloneAppCache(IAppPolicedCache innerCache) + { + var type = typeof (DeepCloneAppCache); + + if (innerCache.GetType() == type) + throw new InvalidOperationException($"A {type} cannot wrap another instance of itself."); + + InnerCache = innerCache; + } + + /// + /// Gets the inner cache. + /// + public IAppPolicedCache InnerCache { get; } + + /// + public object Get(string key) + { + var item = InnerCache.Get(key); + return CheckCloneableAndTracksChanges(item); + } + + /// + public object Get(string key, Func factory) + { + var cached = InnerCache.Get(key, () => + { + var result = FastDictionaryAppCacheBase.GetSafeLazy(factory); + var value = result.Value; // force evaluation now - this may throw if cacheItem throws, and then nothing goes into cache + // do not store null values (backward compat), clone / reset to go into the cache + return value == null ? null : CheckCloneableAndTracksChanges(value); + }); + return CheckCloneableAndTracksChanges(cached); + } + + /// + public IEnumerable SearchByKey(string keyStartsWith) + { + return InnerCache.SearchByKey(keyStartsWith) + .Select(CheckCloneableAndTracksChanges); + } + + /// + public IEnumerable SearchByRegex(string regex) + { + return InnerCache.SearchByRegex(regex) + .Select(CheckCloneableAndTracksChanges); + } + + /// + public object Get(string key, Func factory, TimeSpan? timeout, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null) + { + var cached = InnerCache.Get(key, () => + { + var result = FastDictionaryAppCacheBase.GetSafeLazy(factory); + var value = result.Value; // force evaluation now - this may throw if cacheItem throws, and then nothing goes into cache + // do not store null values (backward compat), clone / reset to go into the cache + return value == null ? null : CheckCloneableAndTracksChanges(value); + + // clone / reset to go into the cache + }, timeout, isSliding, priority, removedCallback, dependentFiles); + + // clone / reset to go into the cache + return CheckCloneableAndTracksChanges(cached); + } + + /// + public void Insert(string key, Func factory, TimeSpan? timeout = null, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null) + { + InnerCache.Insert(key, () => + { + var result = FastDictionaryAppCacheBase.GetSafeLazy(factory); + var value = result.Value; // force evaluation now - this may throw if cacheItem throws, and then nothing goes into cache + // do not store null values (backward compat), clone / reset to go into the cache + return value == null ? null : CheckCloneableAndTracksChanges(value); + }, timeout, isSliding, priority, removedCallback, dependentFiles); + } + + /// + public void Clear() + { + InnerCache.Clear(); + } + + /// + public void Clear(string key) + { + InnerCache.Clear(key); + } + + /// + public void ClearOfType(string typeName) + { + InnerCache.ClearOfType(typeName); + } + + /// + public void ClearOfType() + { + InnerCache.ClearOfType(); + } + + /// + public void ClearOfType(Func predicate) + { + InnerCache.ClearOfType(predicate); + } + + /// + public void ClearByKey(string keyStartsWith) + { + InnerCache.ClearByKey(keyStartsWith); + } + + /// + public void ClearByRegex(string regex) + { + InnerCache.ClearByRegex(regex); + } + + private static object CheckCloneableAndTracksChanges(object input) + { + if (input is IDeepCloneable cloneable) + { + input = cloneable.DeepClone(); + } + + // reset dirty initial properties + if (input is IRememberBeingDirty tracksChanges) + { + tracksChanges.ResetDirtyProperties(false); + input = tracksChanges; + } + + return input; + } + } +} diff --git a/src/Umbraco.Core/Cache/DeepCloneRuntimeCacheProvider.cs b/src/Umbraco.Core/Cache/DeepCloneRuntimeCacheProvider.cs deleted file mode 100644 index 255d7b526d..0000000000 --- a/src/Umbraco.Core/Cache/DeepCloneRuntimeCacheProvider.cs +++ /dev/null @@ -1,155 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web.Caching; -using Umbraco.Core.Models; -using Umbraco.Core.Models.Entities; - -namespace Umbraco.Core.Cache -{ - /// - /// Interface describing this cache provider as a wrapper for another - /// - internal interface IRuntimeCacheProviderWrapper - { - IRuntimeCacheProvider InnerProvider { get; } - } - - /// - /// A wrapper for any IRuntimeCacheProvider that ensures that all inserts and returns - /// are a deep cloned copy of the item when the item is IDeepCloneable and that tracks changes are - /// reset if the object is TracksChangesEntityBase - /// - internal class DeepCloneRuntimeCacheProvider : IRuntimeCacheProvider, IRuntimeCacheProviderWrapper - { - public IRuntimeCacheProvider InnerProvider { get; } - - public DeepCloneRuntimeCacheProvider(IRuntimeCacheProvider innerProvider) - { - var type = typeof (DeepCloneRuntimeCacheProvider); - - if (innerProvider.GetType() == type) - throw new InvalidOperationException($"A {type} cannot wrap another instance of {type}."); - - InnerProvider = innerProvider; - } - - #region Clear - doesn't require any changes - - public void ClearAllCache() - { - InnerProvider.ClearAllCache(); - } - - public void ClearCacheItem(string key) - { - InnerProvider.ClearCacheItem(key); - } - - public void ClearCacheObjectTypes(string typeName) - { - InnerProvider.ClearCacheObjectTypes(typeName); - } - - public void ClearCacheObjectTypes() - { - InnerProvider.ClearCacheObjectTypes(); - } - - public void ClearCacheObjectTypes(Func predicate) - { - InnerProvider.ClearCacheObjectTypes(predicate); - } - - public void ClearCacheByKeySearch(string keyStartsWith) - { - InnerProvider.ClearCacheByKeySearch(keyStartsWith); - } - - public void ClearCacheByKeyExpression(string regexString) - { - InnerProvider.ClearCacheByKeyExpression(regexString); - } - - #endregion - - public IEnumerable GetCacheItemsByKeySearch(string keyStartsWith) - { - return InnerProvider.GetCacheItemsByKeySearch(keyStartsWith) - .Select(CheckCloneableAndTracksChanges); - } - - public IEnumerable GetCacheItemsByKeyExpression(string regexString) - { - return InnerProvider.GetCacheItemsByKeyExpression(regexString) - .Select(CheckCloneableAndTracksChanges); - } - - public object GetCacheItem(string cacheKey) - { - var item = InnerProvider.GetCacheItem(cacheKey); - return CheckCloneableAndTracksChanges(item); - } - - public object GetCacheItem(string cacheKey, Func getCacheItem) - { - var cached = InnerProvider.GetCacheItem(cacheKey, () => - { - var result = DictionaryCacheProviderBase.GetSafeLazy(getCacheItem); - var value = result.Value; // force evaluation now - this may throw if cacheItem throws, and then nothing goes into cache - if (value == null) return null; // do not store null values (backward compat) - - return CheckCloneableAndTracksChanges(value); - }); - return CheckCloneableAndTracksChanges(cached); - } - - public object GetCacheItem(string cacheKey, Func getCacheItem, TimeSpan? timeout, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null) - { - var cached = InnerProvider.GetCacheItem(cacheKey, () => - { - var result = DictionaryCacheProviderBase.GetSafeLazy(getCacheItem); - var value = result.Value; // force evaluation now - this may throw if cacheItem throws, and then nothing goes into cache - if (value == null) return null; // do not store null values (backward compat) - - // clone / reset to go into the cache - return CheckCloneableAndTracksChanges(value); - }, timeout, isSliding, priority, removedCallback, dependentFiles); - - // clone / reset to go into the cache - return CheckCloneableAndTracksChanges(cached); - } - - public void InsertCacheItem(string cacheKey, Func getCacheItem, TimeSpan? timeout = null, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null) - { - InnerProvider.InsertCacheItem(cacheKey, () => - { - var result = DictionaryCacheProviderBase.GetSafeLazy(getCacheItem); - var value = result.Value; // force evaluation now - this may throw if cacheItem throws, and then nothing goes into cache - if (value == null) return null; // do not store null values (backward compat) - - // clone / reset to go into the cache - return CheckCloneableAndTracksChanges(value); - }, timeout, isSliding, priority, removedCallback, dependentFiles); - } - - private static object CheckCloneableAndTracksChanges(object input) - { - var cloneable = input as IDeepCloneable; - if (cloneable != null) - { - input = cloneable.DeepClone(); - } - - // reset dirty initial properties (U4-1946) - var tracksChanges = input as IRememberBeingDirty; - if (tracksChanges != null) - { - tracksChanges.ResetDirtyProperties(false); - input = tracksChanges; - } - - return input; - } - } -} diff --git a/src/Umbraco.Core/Cache/DefaultRepositoryCachePolicy.cs b/src/Umbraco.Core/Cache/DefaultRepositoryCachePolicy.cs index 8387f547d3..6f160cd552 100644 --- a/src/Umbraco.Core/Cache/DefaultRepositoryCachePolicy.cs +++ b/src/Umbraco.Core/Cache/DefaultRepositoryCachePolicy.cs @@ -23,7 +23,7 @@ namespace Umbraco.Core.Cache private static readonly TEntity[] EmptyEntities = new TEntity[0]; // const private readonly RepositoryCachePolicyOptions _options; - public DefaultRepositoryCachePolicy(IRuntimeCacheProvider cache, IScopeAccessor scopeAccessor, RepositoryCachePolicyOptions options) + public DefaultRepositoryCachePolicy(IAppPolicedCache cache, IScopeAccessor scopeAccessor, RepositoryCachePolicyOptions options) : base(cache, scopeAccessor) { _options = options ?? throw new ArgumentNullException(nameof(options)); @@ -42,7 +42,7 @@ namespace Umbraco.Core.Cache protected virtual void InsertEntity(string cacheKey, TEntity entity) { - Cache.InsertCacheItem(cacheKey, () => entity, TimeSpan.FromMinutes(5), true); + Cache.Insert(cacheKey, () => entity, TimeSpan.FromMinutes(5), true); } protected virtual void InsertEntities(TId[] ids, TEntity[] entities) @@ -52,7 +52,7 @@ namespace Umbraco.Core.Cache // getting all of them, and finding nothing. // if we can cache a zero count, cache an empty array, // for as long as the cache is not cleared (no expiration) - Cache.InsertCacheItem(GetEntityTypeCacheKey(), () => EmptyEntities); + Cache.Insert(GetEntityTypeCacheKey(), () => EmptyEntities); } else { @@ -60,7 +60,7 @@ namespace Umbraco.Core.Cache foreach (var entity in entities) { var capture = entity; - Cache.InsertCacheItem(GetEntityCacheKey(entity.Id), () => capture, TimeSpan.FromMinutes(5), true); + Cache.Insert(GetEntityCacheKey(entity.Id), () => capture, TimeSpan.FromMinutes(5), true); } } } @@ -77,21 +77,21 @@ namespace Umbraco.Core.Cache // just to be safe, we cannot cache an item without an identity if (entity.HasIdentity) { - Cache.InsertCacheItem(GetEntityCacheKey(entity.Id), () => entity, TimeSpan.FromMinutes(5), true); + Cache.Insert(GetEntityCacheKey(entity.Id), () => entity, TimeSpan.FromMinutes(5), true); } // if there's a GetAllCacheAllowZeroCount cache, ensure it is cleared - Cache.ClearCacheItem(GetEntityTypeCacheKey()); + Cache.Clear(GetEntityTypeCacheKey()); } catch { // if an exception is thrown we need to remove the entry from cache, // this is ONLY a work around because of the way // that we cache entities: http://issues.umbraco.org/issue/U4-4259 - Cache.ClearCacheItem(GetEntityCacheKey(entity.Id)); + Cache.Clear(GetEntityCacheKey(entity.Id)); // if there's a GetAllCacheAllowZeroCount cache, ensure it is cleared - Cache.ClearCacheItem(GetEntityTypeCacheKey()); + Cache.Clear(GetEntityTypeCacheKey()); throw; } @@ -109,21 +109,21 @@ namespace Umbraco.Core.Cache // just to be safe, we cannot cache an item without an identity if (entity.HasIdentity) { - Cache.InsertCacheItem(GetEntityCacheKey(entity.Id), () => entity, TimeSpan.FromMinutes(5), true); + Cache.Insert(GetEntityCacheKey(entity.Id), () => entity, TimeSpan.FromMinutes(5), true); } // if there's a GetAllCacheAllowZeroCount cache, ensure it is cleared - Cache.ClearCacheItem(GetEntityTypeCacheKey()); + Cache.Clear(GetEntityTypeCacheKey()); } catch { // if an exception is thrown we need to remove the entry from cache, // this is ONLY a work around because of the way // that we cache entities: http://issues.umbraco.org/issue/U4-4259 - Cache.ClearCacheItem(GetEntityCacheKey(entity.Id)); + Cache.Clear(GetEntityCacheKey(entity.Id)); // if there's a GetAllCacheAllowZeroCount cache, ensure it is cleared - Cache.ClearCacheItem(GetEntityTypeCacheKey()); + Cache.Clear(GetEntityTypeCacheKey()); throw; } @@ -142,9 +142,9 @@ namespace Umbraco.Core.Cache { // whatever happens, clear the cache var cacheKey = GetEntityCacheKey(entity.Id); - Cache.ClearCacheItem(cacheKey); + Cache.Clear(cacheKey); // if there's a GetAllCacheAllowZeroCount cache, ensure it is cleared - Cache.ClearCacheItem(GetEntityTypeCacheKey()); + Cache.Clear(GetEntityTypeCacheKey()); } } @@ -238,7 +238,7 @@ namespace Umbraco.Core.Cache /// public override void ClearAll() { - Cache.ClearCacheByKeySearch(GetEntityTypeCacheKey()); + Cache.ClearByKey(GetEntityTypeCacheKey()); } } } diff --git a/src/Umbraco.Core/Cache/DictionaryCacheProvider.cs b/src/Umbraco.Core/Cache/DictionaryCacheProvider.cs index 98dceb80b0..2ff5f6ea83 100644 --- a/src/Umbraco.Core/Cache/DictionaryCacheProvider.cs +++ b/src/Umbraco.Core/Cache/DictionaryCacheProvider.cs @@ -1,147 +1,97 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; -using System.Linq; using System.Text.RegularExpressions; -using Umbraco.Core.Composing; namespace Umbraco.Core.Cache { - internal class DictionaryCacheProvider : ICacheProvider + /// + /// Implements on top of a concurrent dictionary. + /// + public class DictionaryCacheProvider : IAppCache { - private readonly ConcurrentDictionary> _items - = new ConcurrentDictionary>(); + /// + /// Gets the internal items dictionary, for tests only! + /// + internal readonly ConcurrentDictionary Items = new ConcurrentDictionary(); - // for tests - internal ConcurrentDictionary> Items => _items; - - public void ClearAllCache() + /// + public virtual object Get(string key) { - _items.Clear(); + // fixme throws if non-existing, shouldn't it return null? + return Items[key]; } - public void ClearCacheItem(string key) + /// + public virtual object Get(string key, Func factory) { - _items.TryRemove(key, out _); + return Items.GetOrAdd(key, _ => factory()); } - public void ClearCacheObjectTypes(string typeName) + /// + public virtual IEnumerable SearchByKey(string keyStartsWith) { - var type = TypeFinder.GetTypeByName(typeName); - if (type == null) return; - var isInterface = type.IsInterface; - - foreach (var kvp in _items - .Where(x => - { - // entry.Value is Lazy and not null, its value may be null - // remove null values as well, does not hurt - // get non-created as NonCreatedValue & exceptions as null - var value = DictionaryCacheProviderBase.GetSafeLazyValue(x.Value, true); - - // if T is an interface remove anything that implements that interface - // otherwise remove exact types (not inherited types) - return value == null || (isInterface ? (type.IsInstanceOfType(value)) : (value.GetType() == type)); - })) - _items.TryRemove(kvp.Key, out _); + var items = new List(); + foreach (var (key, value) in Items) + if (key.InvariantStartsWith(keyStartsWith)) + items.Add(value); + return items; } - public void ClearCacheObjectTypes() + /// + public IEnumerable SearchByRegex(string regex) + { + var compiled = new Regex(regex, RegexOptions.Compiled); + var items = new List(); + foreach (var (key, value) in Items) + if (compiled.IsMatch(key)) + items.Add(value); + return items; + } + + /// + public virtual void Clear() + { + Items.Clear(); + } + + /// + public virtual void Clear(string key) + { + Items.TryRemove(key, out _); + } + + /// + public virtual void ClearOfType(string typeName) + { + Items.RemoveAll(kvp => kvp.Value != null && kvp.Value.GetType().ToString().InvariantEquals(typeName)); + } + + /// + public virtual void ClearOfType() { var typeOfT = typeof(T); - var isInterface = typeOfT.IsInterface; - - foreach (var kvp in _items - .Where(x => - { - // entry.Value is Lazy and not null, its value may be null - // remove null values as well, does not hurt - // compare on exact type, don't use "is" - // get non-created as NonCreatedValue & exceptions as null - var value = DictionaryCacheProviderBase.GetSafeLazyValue(x.Value, true); - - // if T is an interface remove anything that implements that interface - // otherwise remove exact types (not inherited types) - return value == null || (isInterface ? (value is T) : (value.GetType() == typeOfT)); - })) - _items.TryRemove(kvp.Key, out _); + Items.RemoveAll(kvp => kvp.Value != null && kvp.Value.GetType() == typeOfT); } - public void ClearCacheObjectTypes(Func predicate) + /// + public virtual void ClearOfType(Func predicate) { var typeOfT = typeof(T); - var isInterface = typeOfT.IsInterface; - - foreach (var kvp in _items - .Where(x => - { - // entry.Value is Lazy and not null, its value may be null - // remove null values as well, does not hurt - // compare on exact type, don't use "is" - // get non-created as NonCreatedValue & exceptions as null - var value = DictionaryCacheProviderBase.GetSafeLazyValue(x.Value, true); - if (value == null) return true; - - // if T is an interface remove anything that implements that interface - // otherwise remove exact types (not inherited types) - return (isInterface ? (value is T) : (value.GetType() == typeOfT)) - // run predicate on the 'public key' part only, ie without prefix - && predicate(x.Key, (T)value); - })) - _items.TryRemove(kvp.Key, out _); + Items.RemoveAll(kvp => kvp.Value != null && kvp.Value.GetType() == typeOfT && predicate(kvp.Key, (T)kvp.Value)); } - public void ClearCacheByKeySearch(string keyStartsWith) + /// + public virtual void ClearByKey(string keyStartsWith) { - foreach (var ikvp in _items - .Where(kvp => kvp.Key.InvariantStartsWith(keyStartsWith))) - _items.TryRemove(ikvp.Key, out _); + Items.RemoveAll(kvp => kvp.Key.InvariantStartsWith(keyStartsWith)); } - public void ClearCacheByKeyExpression(string regexString) + /// + public virtual void ClearByRegex(string regex) { - foreach (var ikvp in _items - .Where(kvp => Regex.IsMatch(kvp.Key, regexString))) - _items.TryRemove(ikvp.Key, out _); - } - - public IEnumerable GetCacheItemsByKeySearch(string keyStartsWith) - { - return _items - .Where(kvp => kvp.Key.InvariantStartsWith(keyStartsWith)) - .Select(kvp => DictionaryCacheProviderBase.GetSafeLazyValue(kvp.Value)) - .Where(x => x != null); - } - - public IEnumerable GetCacheItemsByKeyExpression(string regexString) - { - return _items - .Where(kvp => Regex.IsMatch(kvp.Key, regexString)) - .Select(kvp => DictionaryCacheProviderBase.GetSafeLazyValue(kvp.Value)) - .Where(x => x != null); - } - - public object GetCacheItem(string cacheKey) - { - _items.TryGetValue(cacheKey, out var result); // else null - return result == null ? null : DictionaryCacheProviderBase.GetSafeLazyValue(result); // return exceptions as null - } - - public object GetCacheItem(string cacheKey, Func getCacheItem) - { - var result = _items.GetOrAdd(cacheKey, k => DictionaryCacheProviderBase.GetSafeLazy(getCacheItem)); - - var value = result.Value; // will not throw (safe lazy) - if (!(value is DictionaryCacheProviderBase.ExceptionHolder eh)) - return value; - - // and... it's in the cache anyway - so contrary to other cache providers, - // which would trick with GetSafeLazyValue, we need to remove by ourselves, - // in order NOT to cache exceptions - - _items.TryRemove(cacheKey, out result); - eh.Exception.Throw(); // throw once! - return null; // never reached + var compiled = new Regex(regex, RegexOptions.Compiled); + Items.RemoveAll(kvp => compiled.IsMatch(kvp.Key)); } } } diff --git a/src/Umbraco.Core/Cache/DictionaryCacheProviderBase.cs b/src/Umbraco.Core/Cache/FastDictionaryAppCacheBase.cs similarity index 81% rename from src/Umbraco.Core/Cache/DictionaryCacheProviderBase.cs rename to src/Umbraco.Core/Cache/FastDictionaryAppCacheBase.cs index f556d47a8e..371ab90a57 100644 --- a/src/Umbraco.Core/Cache/DictionaryCacheProviderBase.cs +++ b/src/Umbraco.Core/Cache/FastDictionaryAppCacheBase.cs @@ -8,7 +8,10 @@ using Umbraco.Core.Composing; namespace Umbraco.Core.Cache { - internal abstract class DictionaryCacheProviderBase : ICacheProvider + /// + /// Provides a base class to fast, dictionary-based implementations. + /// + internal abstract class FastDictionaryAppCacheBase : IAppCache { // prefix cache keys so we know which one are ours protected const string CacheItemPrefix = "umbrtmche"; @@ -16,82 +19,75 @@ namespace Umbraco.Core.Cache // an object that represent a value that has not been created yet protected internal static readonly object ValueNotCreated = new object(); - // manupulate the underlying cache entries - // these *must* be called from within the appropriate locks - // and use the full prefixed cache keys - protected abstract IEnumerable GetDictionaryEntries(); - protected abstract void RemoveEntry(string key); - protected abstract object GetEntry(string key); + #region IAppCache - // read-write lock the underlying cache - //protected abstract IDisposable ReadLock { get; } - //protected abstract IDisposable WriteLock { get; } - - protected abstract void EnterReadLock(); - protected abstract void ExitReadLock(); - protected abstract void EnterWriteLock(); - protected abstract void ExitWriteLock(); - - protected string GetCacheKey(string key) + /// + public virtual object Get(string key) { - return string.Format("{0}-{1}", CacheItemPrefix, key); - } - - protected internal static Lazy GetSafeLazy(Func getCacheItem) - { - // try to generate the value and if it fails, - // wrap in an ExceptionHolder - would be much simpler - // to just use lazy.IsValueFaulted alas that field is - // internal - return new Lazy(() => - { - try - { - return getCacheItem(); - } - catch (Exception e) - { - return new ExceptionHolder(ExceptionDispatchInfo.Capture(e)); - } - }); - } - - protected internal static object GetSafeLazyValue(Lazy lazy, bool onlyIfValueIsCreated = false) - { - // if onlyIfValueIsCreated, do not trigger value creation - // must return something, though, to differenciate from null values - if (onlyIfValueIsCreated && lazy.IsValueCreated == false) return ValueNotCreated; - - // if execution has thrown then lazy.IsValueCreated is false - // and lazy.IsValueFaulted is true (but internal) so we use our - // own exception holder (see Lazy source code) to return null - if (lazy.Value is ExceptionHolder) return null; - - // we have a value and execution has not thrown so returning - // here does not throw - unless we're re-entering, take care of it + key = GetCacheKey(key); + Lazy result; try { - return lazy.Value; + EnterReadLock(); + result = GetEntry(key) as Lazy; // null if key not found } - catch (InvalidOperationException e) + finally { - throw new InvalidOperationException("The method that computes a value for the cache has tried to read that value from the cache.", e); + ExitReadLock(); } + return result == null ? null : GetSafeLazyValue(result); // return exceptions as null } - internal class ExceptionHolder + /// + public abstract object Get(string key, Func factory); + + /// + public virtual IEnumerable SearchByKey(string keyStartsWith) { - public ExceptionHolder(ExceptionDispatchInfo e) + var plen = CacheItemPrefix.Length + 1; + IEnumerable entries; + try { - Exception = e; + EnterReadLock(); + entries = GetDictionaryEntries() + .Where(x => ((string)x.Key).Substring(plen).InvariantStartsWith(keyStartsWith)) + .ToArray(); // evaluate while locked + } + finally + { + ExitReadLock(); } - public ExceptionDispatchInfo Exception { get; } + return entries + .Select(x => GetSafeLazyValue((Lazy)x.Value)) // return exceptions as null + .Where(x => x != null); // backward compat, don't store null values in the cache } - #region Clear + /// + public virtual IEnumerable SearchByRegex(string regex) + { + const string prefix = CacheItemPrefix + "-"; + var compiled = new Regex(regex, RegexOptions.Compiled); + var plen = prefix.Length; + IEnumerable entries; + try + { + EnterReadLock(); + entries = GetDictionaryEntries() + .Where(x => compiled.IsMatch(((string)x.Key).Substring(plen))) + .ToArray(); // evaluate while locked + } + finally + { + ExitReadLock(); + } + return entries + .Select(x => GetSafeLazyValue((Lazy)x.Value)) // return exceptions as null + .Where(x => x != null); // backward compat, don't store null values in the cache + } - public virtual void ClearAllCache() + /// + public virtual void Clear() { try { @@ -106,7 +102,8 @@ namespace Umbraco.Core.Cache } } - public virtual void ClearCacheItem(string key) + /// + public virtual void Clear(string key) { var cacheKey = GetCacheKey(key); try @@ -120,7 +117,8 @@ namespace Umbraco.Core.Cache } } - public virtual void ClearCacheObjectTypes(string typeName) + /// + public virtual void ClearOfType(string typeName) { var type = TypeFinder.GetTypeByName(typeName); if (type == null) return; @@ -149,7 +147,8 @@ namespace Umbraco.Core.Cache } } - public virtual void ClearCacheObjectTypes() + /// + public virtual void ClearOfType() { var typeOfT = typeof(T); var isInterface = typeOfT.IsInterface; @@ -178,7 +177,8 @@ namespace Umbraco.Core.Cache } } - public virtual void ClearCacheObjectTypes(Func predicate) + /// + public virtual void ClearOfType(Func predicate) { var typeOfT = typeof(T); var isInterface = typeOfT.IsInterface; @@ -210,7 +210,8 @@ namespace Umbraco.Core.Cache } } - public virtual void ClearCacheByKeySearch(string keyStartsWith) + /// + public virtual void ClearByKey(string keyStartsWith) { var plen = CacheItemPrefix.Length + 1; try @@ -227,14 +228,16 @@ namespace Umbraco.Core.Cache } } - public virtual void ClearCacheByKeyExpression(string regexString) + /// + public virtual void ClearByRegex(string regex) { + var compiled = new Regex(regex, RegexOptions.Compiled); var plen = CacheItemPrefix.Length + 1; try { EnterWriteLock(); foreach (var entry in GetDictionaryEntries() - .Where(x => Regex.IsMatch(((string)x.Key).Substring(plen), regexString)) + .Where(x => compiled.IsMatch(((string)x.Key).Substring(plen))) .ToArray()) RemoveEntry((string) entry.Key); } @@ -246,67 +249,80 @@ namespace Umbraco.Core.Cache #endregion - #region Get + #region Dictionary - public virtual IEnumerable GetCacheItemsByKeySearch(string keyStartsWith) + // manipulate the underlying cache entries + // these *must* be called from within the appropriate locks + // and use the full prefixed cache keys + protected abstract IEnumerable GetDictionaryEntries(); + protected abstract void RemoveEntry(string key); + protected abstract object GetEntry(string key); + + // read-write lock the underlying cache + //protected abstract IDisposable ReadLock { get; } + //protected abstract IDisposable WriteLock { get; } + + protected abstract void EnterReadLock(); + protected abstract void ExitReadLock(); + protected abstract void EnterWriteLock(); + protected abstract void ExitWriteLock(); + + protected string GetCacheKey(string key) { - var plen = CacheItemPrefix.Length + 1; - IEnumerable entries; - try - { - EnterReadLock(); - entries = GetDictionaryEntries() - .Where(x => ((string)x.Key).Substring(plen).InvariantStartsWith(keyStartsWith)) - .ToArray(); // evaluate while locked - } - finally - { - ExitReadLock(); - } - - return entries - .Select(x => GetSafeLazyValue((Lazy)x.Value)) // return exceptions as null - .Where(x => x != null); // backward compat, don't store null values in the cache + return $"{CacheItemPrefix}-{key}"; } - public virtual IEnumerable GetCacheItemsByKeyExpression(string regexString) + protected internal static Lazy GetSafeLazy(Func getCacheItem) { - const string prefix = CacheItemPrefix + "-"; - var plen = prefix.Length; - IEnumerable entries; - try + // try to generate the value and if it fails, + // wrap in an ExceptionHolder - would be much simpler + // to just use lazy.IsValueFaulted alas that field is + // internal + return new Lazy(() => { - EnterReadLock(); - entries = GetDictionaryEntries() - .Where(x => Regex.IsMatch(((string)x.Key).Substring(plen), regexString)) - .ToArray(); // evaluate while locked - } - finally - { - ExitReadLock(); - } - return entries - .Select(x => GetSafeLazyValue((Lazy)x.Value)) // return exceptions as null - .Where(x => x != null); // backward compat, don't store null values in the cache + try + { + return getCacheItem(); + } + catch (Exception e) + { + return new ExceptionHolder(ExceptionDispatchInfo.Capture(e)); + } + }); } - public virtual object GetCacheItem(string cacheKey) + protected internal static object GetSafeLazyValue(Lazy lazy, bool onlyIfValueIsCreated = false) { - cacheKey = GetCacheKey(cacheKey); - Lazy result; + // if onlyIfValueIsCreated, do not trigger value creation + // must return something, though, to differentiate from null values + if (onlyIfValueIsCreated && lazy.IsValueCreated == false) return ValueNotCreated; + + // if execution has thrown then lazy.IsValueCreated is false + // and lazy.IsValueFaulted is true (but internal) so we use our + // own exception holder (see Lazy source code) to return null + if (lazy.Value is ExceptionHolder) return null; + + // we have a value and execution has not thrown so returning + // here does not throw - unless we're re-entering, take care of it try { - EnterReadLock(); - result = GetEntry(cacheKey) as Lazy; // null if key not found + return lazy.Value; } - finally + catch (InvalidOperationException e) { - ExitReadLock(); + throw new InvalidOperationException("The method that computes a value for the cache has tried to read that value from the cache.", e); } - return result == null ? null : GetSafeLazyValue(result); // return exceptions as null } - public abstract object GetCacheItem(string cacheKey, Func getCacheItem); + internal class ExceptionHolder + { + public ExceptionHolder(ExceptionDispatchInfo e) + { + Exception = e; + } + + public ExceptionDispatchInfo Exception { get; } + } #endregion } diff --git a/src/Umbraco.Core/Cache/FastDictionaryCacheProvider.cs b/src/Umbraco.Core/Cache/FastDictionaryCacheProvider.cs new file mode 100644 index 0000000000..a3863dac52 --- /dev/null +++ b/src/Umbraco.Core/Cache/FastDictionaryCacheProvider.cs @@ -0,0 +1,162 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using Umbraco.Core.Composing; + +namespace Umbraco.Core.Cache +{ + /// + /// Implements a fast on top of a concurrent dictionary. + /// + internal class FastDictionaryCacheProvider : IAppCache + { + /// + /// Gets the internal items dictionary, for tests only! + /// + internal readonly ConcurrentDictionary> Items = new ConcurrentDictionary>(); + + /// + public object Get(string cacheKey) + { + Items.TryGetValue(cacheKey, out var result); // else null + return result == null ? null : FastDictionaryAppCacheBase.GetSafeLazyValue(result); // return exceptions as null + } + + /// + public object Get(string cacheKey, Func getCacheItem) + { + var result = Items.GetOrAdd(cacheKey, k => FastDictionaryAppCacheBase.GetSafeLazy(getCacheItem)); + + var value = result.Value; // will not throw (safe lazy) + if (!(value is FastDictionaryAppCacheBase.ExceptionHolder eh)) + return value; + + // and... it's in the cache anyway - so contrary to other cache providers, + // which would trick with GetSafeLazyValue, we need to remove by ourselves, + // in order NOT to cache exceptions + + Items.TryRemove(cacheKey, out result); + eh.Exception.Throw(); // throw once! + return null; // never reached + } + + /// + public IEnumerable SearchByKey(string keyStartsWith) + { + return Items + .Where(kvp => kvp.Key.InvariantStartsWith(keyStartsWith)) + .Select(kvp => FastDictionaryAppCacheBase.GetSafeLazyValue(kvp.Value)) + .Where(x => x != null); + } + + /// + public IEnumerable SearchByRegex(string regex) + { + var compiled = new Regex(regex, RegexOptions.Compiled); + return Items + .Where(kvp => compiled.IsMatch(kvp.Key)) + .Select(kvp => FastDictionaryAppCacheBase.GetSafeLazyValue(kvp.Value)) + .Where(x => x != null); + } + + /// + public void Clear() + { + Items.Clear(); + } + + /// + public void Clear(string key) + { + Items.TryRemove(key, out _); + } + + /// + public void ClearOfType(string typeName) + { + var type = TypeFinder.GetTypeByName(typeName); + if (type == null) return; + var isInterface = type.IsInterface; + + foreach (var kvp in Items + .Where(x => + { + // entry.Value is Lazy and not null, its value may be null + // remove null values as well, does not hurt + // get non-created as NonCreatedValue & exceptions as null + var value = FastDictionaryAppCacheBase.GetSafeLazyValue(x.Value, true); + + // if T is an interface remove anything that implements that interface + // otherwise remove exact types (not inherited types) + return value == null || (isInterface ? (type.IsInstanceOfType(value)) : (value.GetType() == type)); + })) + Items.TryRemove(kvp.Key, out _); + } + + /// + public void ClearOfType() + { + var typeOfT = typeof(T); + var isInterface = typeOfT.IsInterface; + + foreach (var kvp in Items + .Where(x => + { + // entry.Value is Lazy and not null, its value may be null + // remove null values as well, does not hurt + // compare on exact type, don't use "is" + // get non-created as NonCreatedValue & exceptions as null + var value = FastDictionaryAppCacheBase.GetSafeLazyValue(x.Value, true); + + // if T is an interface remove anything that implements that interface + // otherwise remove exact types (not inherited types) + return value == null || (isInterface ? (value is T) : (value.GetType() == typeOfT)); + })) + Items.TryRemove(kvp.Key, out _); + } + + /// + public void ClearOfType(Func predicate) + { + var typeOfT = typeof(T); + var isInterface = typeOfT.IsInterface; + + foreach (var kvp in Items + .Where(x => + { + // entry.Value is Lazy and not null, its value may be null + // remove null values as well, does not hurt + // compare on exact type, don't use "is" + // get non-created as NonCreatedValue & exceptions as null + var value = FastDictionaryAppCacheBase.GetSafeLazyValue(x.Value, true); + if (value == null) return true; + + // if T is an interface remove anything that implements that interface + // otherwise remove exact types (not inherited types) + return (isInterface ? (value is T) : (value.GetType() == typeOfT)) + // run predicate on the 'public key' part only, ie without prefix + && predicate(x.Key, (T)value); + })) + Items.TryRemove(kvp.Key, out _); + } + + /// + public void ClearByKey(string keyStartsWith) + { + foreach (var ikvp in Items + .Where(kvp => kvp.Key.InvariantStartsWith(keyStartsWith))) + Items.TryRemove(ikvp.Key, out _); + } + + /// + public void ClearByRegex(string regex) + { + var compiled = new Regex(regex, RegexOptions.Compiled); + foreach (var ikvp in Items + .Where(kvp => compiled.IsMatch(kvp.Key))) + Items.TryRemove(ikvp.Key, out _); + } + } +} diff --git a/src/Umbraco.Core/Cache/FullDataSetRepositoryCachePolicy.cs b/src/Umbraco.Core/Cache/FullDataSetRepositoryCachePolicy.cs index 319d84d41f..3bc4c9d059 100644 --- a/src/Umbraco.Core/Cache/FullDataSetRepositoryCachePolicy.cs +++ b/src/Umbraco.Core/Cache/FullDataSetRepositoryCachePolicy.cs @@ -24,7 +24,7 @@ namespace Umbraco.Core.Cache private readonly Func _entityGetId; private readonly bool _expires; - public FullDataSetRepositoryCachePolicy(IRuntimeCacheProvider cache, IScopeAccessor scopeAccessor, Func entityGetId, bool expires) + public FullDataSetRepositoryCachePolicy(IAppPolicedCache cache, IScopeAccessor scopeAccessor, Func entityGetId, bool expires) : base(cache, scopeAccessor) { _entityGetId = entityGetId; @@ -55,11 +55,11 @@ namespace Umbraco.Core.Cache if (_expires) { - Cache.InsertCacheItem(key, () => new DeepCloneableList(entities), TimeSpan.FromMinutes(5), true); + Cache.Insert(key, () => new DeepCloneableList(entities), TimeSpan.FromMinutes(5), true); } else { - Cache.InsertCacheItem(key, () => new DeepCloneableList(entities)); + Cache.Insert(key, () => new DeepCloneableList(entities)); } } @@ -171,7 +171,7 @@ namespace Umbraco.Core.Cache /// public override void ClearAll() { - Cache.ClearCacheItem(GetEntityTypeCacheKey()); + Cache.Clear(GetEntityTypeCacheKey()); } } } diff --git a/src/Umbraco.Core/Cache/HttpRequestCacheProvider.cs b/src/Umbraco.Core/Cache/HttpRequestAppCache.cs similarity index 53% rename from src/Umbraco.Core/Cache/HttpRequestCacheProvider.cs rename to src/Umbraco.Core/Cache/HttpRequestAppCache.cs index 52c230ff71..dcb2621d75 100644 --- a/src/Umbraco.Core/Cache/HttpRequestCacheProvider.cs +++ b/src/Umbraco.Core/Cache/HttpRequestAppCache.cs @@ -7,54 +7,83 @@ using System.Web; namespace Umbraco.Core.Cache { /// - /// A cache provider that caches items in the HttpContext.Items + /// Implements a fast on top of HttpContext.Items. /// /// - /// If the Items collection is null, then this provider has no effect + /// If no current HttpContext items can be found (no current HttpContext, + /// or no Items...) then this cache acts as a pass-through and does not cache + /// anything. /// - internal class HttpRequestCacheProvider : DictionaryCacheProviderBase + internal class HttpRequestAppCache : FastDictionaryAppCacheBase { - // context provider - // the idea is that there is only one, application-wide HttpRequestCacheProvider instance, - // that is initialized with a method that returns the "current" context. - // NOTE - // but then it is initialized with () => new HttpContextWrapper(HttpContent.Current) - // which is higly inefficient because it creates a new wrapper each time we refer to _context() - // so replace it with _context1 and _context2 below + a way to get context.Items. - //private readonly Func _context; - - // NOTE - // and then in almost 100% cases _context2 will be () => HttpContext.Current - // so why not bring that logic in here and fallback on to HttpContext.Current when - // _context1 is null? - //private readonly HttpContextBase _context1; - //private readonly Func _context2; private readonly HttpContextBase _context; - private IDictionary ContextItems - { - //get { return _context1 != null ? _context1.Items : _context2().Items; } - get { return _context != null ? _context.Items : HttpContext.Current.Items; } - } - - private bool HasContextItems - { - get { return (_context != null && _context.Items != null) || HttpContext.Current != null; } - } - - // for unit tests - public HttpRequestCacheProvider(HttpContextBase context) + /// + /// Initializes a new instance of the class with a context, for unit tests! + /// + public HttpRequestAppCache(HttpContextBase context) { _context = context; } - // main constructor - // will use HttpContext.Current - public HttpRequestCacheProvider(/*Func context*/) + /// + /// Initializes a new instance of the class. + /// + /// + /// Will use HttpContext.Current. + /// fixme - should use IHttpContextAccessor + /// + public HttpRequestAppCache() + { } + + private IDictionary ContextItems => _context?.Items ?? HttpContext.Current?.Items; + + private bool HasContextItems => _context?.Items != null || HttpContext.Current != null; + + /// + public override object Get(string key, Func factory) { - //_context2 = context; + //no place to cache so just return the callback result + if (HasContextItems == false) return factory(); + + key = GetCacheKey(key); + + Lazy result; + + try + { + EnterWriteLock(); + result = ContextItems[key] as Lazy; // null if key not found + + // cannot create value within the lock, so if result.IsValueCreated is false, just + // do nothing here - means that if creation throws, a race condition could cause + // more than one thread to reach the return statement below and throw - accepted. + + if (result == null || GetSafeLazyValue(result, true) == null) // get non-created as NonCreatedValue & exceptions as null + { + result = GetSafeLazy(factory); + ContextItems[key] = result; + } + } + finally + { + ExitWriteLock(); + } + + // using GetSafeLazy and GetSafeLazyValue ensures that we don't cache + // exceptions (but try again and again) and silently eat them - however at + // some point we have to report them - so need to re-throw here + + // this does not throw anymore + //return result.Value; + + var value = result.Value; // will not throw (safe lazy) + if (value is ExceptionHolder eh) eh.Exception.Throw(); // throw once! + return value; } + #region Entries + protected override IEnumerable GetDictionaryEntries() { const string prefix = CacheItemPrefix + "-"; @@ -62,7 +91,7 @@ namespace Umbraco.Core.Cache if (HasContextItems == false) return Enumerable.Empty(); return ContextItems.Cast() - .Where(x => x.Key is string && ((string)x.Key).StartsWith(prefix)); + .Where(x => x.Key is string s && s.StartsWith(prefix)); } protected override void RemoveEntry(string key) @@ -77,6 +106,8 @@ namespace Umbraco.Core.Cache return HasContextItems ? ContextItems[key] : null; } + #endregion + #region Lock private bool _entered; @@ -103,59 +134,5 @@ namespace Umbraco.Core.Cache } #endregion - - #region Get - - public override object GetCacheItem(string cacheKey, Func getCacheItem) - { - //no place to cache so just return the callback result - if (HasContextItems == false) return getCacheItem(); - - cacheKey = GetCacheKey(cacheKey); - - Lazy result; - - try - { - EnterWriteLock(); - result = ContextItems[cacheKey] as Lazy; // null if key not found - - // cannot create value within the lock, so if result.IsValueCreated is false, just - // do nothing here - means that if creation throws, a race condition could cause - // more than one thread to reach the return statement below and throw - accepted. - - if (result == null || GetSafeLazyValue(result, true) == null) // get non-created as NonCreatedValue & exceptions as null - { - result = GetSafeLazy(getCacheItem); - ContextItems[cacheKey] = result; - } - } - finally - { - ExitWriteLock(); - } - - // using GetSafeLazy and GetSafeLazyValue ensures that we don't cache - // exceptions (but try again and again) and silently eat them - however at - // some point we have to report them - so need to re-throw here - - // this does not throw anymore - //return result.Value; - - var value = result.Value; // will not throw (safe lazy) - if (value is ExceptionHolder eh) eh.Exception.Throw(); // throw once! - return value; - } - - #endregion - - #region Insert - #endregion - - private class NoopLocker : DisposableObjectSlim - { - protected override void DisposeResources() - { } - } } } diff --git a/src/Umbraco.Core/Cache/IAppCache.cs b/src/Umbraco.Core/Cache/IAppCache.cs new file mode 100644 index 0000000000..674781f6d6 --- /dev/null +++ b/src/Umbraco.Core/Cache/IAppCache.cs @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; + +namespace Umbraco.Core.Cache +{ + /// + /// Defines an application cache. + /// + public interface IAppCache + { + /// + /// Gets an item identified by its key. + /// + /// The key of the item. + /// The item, or null if the item was not found. + object Get(string key); + + /// + /// Gets or creates an item identified by its key. + /// + /// The key of the item. + /// A factory function that can create the item. + /// The item. + object Get(string key, Func factory); + + /// + /// Gets items with a key starting with the specified value. + /// + /// The StartsWith value to use in the search. + /// Items matching the search. + IEnumerable SearchByKey(string keyStartsWith); + + /// + /// Gets items with a key matching a regular expression. + /// + /// The regular expression. + /// Items matching the search. + IEnumerable SearchByRegex(string regex); + + /// + /// Removes all items from the cache. + /// + void Clear(); + + /// + /// Removes an item identified by its key from the cache. + /// + /// The key of the item. + void Clear(string key); + + /// + /// Removes items of a specified type from the cache. + /// + /// The name of the type to remove. + /// + /// If the type is an interface, then all items of a type implementing that interface are + /// removed. Otherwise, only items of that exact type are removed (items of type inheriting from + /// the specified type are not removed). + /// Performs a case-sensitive search. + /// + void ClearOfType(string typeName); + + /// + /// Removes items of a specified type from the cache. + /// + /// The type of the items to remove. + /// If the type is an interface, then all items of a type implementing that interface are + /// removed. Otherwise, only items of that exact type are removed (items of type inheriting from + /// the specified type are not removed). + void ClearOfType(); + + /// + /// Removes items of a specified type from the cache. + /// + /// The type of the items to remove. + /// The predicate to satisfy. + /// If the type is an interface, then all items of a type implementing that interface are + /// removed. Otherwise, only items of that exact type are removed (items of type inheriting from + /// the specified type are not removed). + void ClearOfType(Func predicate); + + /// + /// Clears items with a key starting with the specified value. + /// + /// The StartsWith value to use in the search. + void ClearByKey(string keyStartsWith); + + /// + /// Clears items with a key matching a regular expression. + /// + /// The regular expression. + void ClearByRegex(string regex); + } +} diff --git a/src/Umbraco.Core/Cache/IAppPolicedCache.cs b/src/Umbraco.Core/Cache/IAppPolicedCache.cs new file mode 100644 index 0000000000..0aee7584df --- /dev/null +++ b/src/Umbraco.Core/Cache/IAppPolicedCache.cs @@ -0,0 +1,54 @@ +using System; +using System.Web.Caching; + +// fixme should this be/support non-web? + +namespace Umbraco.Core.Cache +{ + /// + /// Defines an application cache that support cache policies. + /// + /// A cache policy can be used to cache with timeouts, + /// or depending on files, and with a remove callback, etc. + public interface IAppPolicedCache : IAppCache + { + /// + /// Gets an item identified by its key. + /// + /// The key of the item. + /// A factory function that can create the item. + /// An optional cache timeout. + /// An optional value indicating whether the cache timeout is sliding (default is false). + /// An optional cache priority (default is Normal). + /// An optional callback to handle removals. + /// Files the cache entry depends on. + /// The item. + object Get( + string key, + Func factory, + TimeSpan? timeout, + bool isSliding = false, + CacheItemPriority priority = CacheItemPriority.Normal, + CacheItemRemovedCallback removedCallback = null, + string[] dependentFiles = null); + + /// + /// Inserts an item. + /// + /// The key of the item. + /// A factory function that can create the item. + /// An optional cache timeout. + /// An optional value indicating whether the cache timeout is sliding (default is false). + /// An optional cache priority (default is Normal). + /// An optional callback to handle removals. + /// Files the cache entry depends on. + void Insert( + string key, + Func factory, + TimeSpan? timeout = null, + bool isSliding = false, + CacheItemPriority priority = CacheItemPriority.Normal, + CacheItemRemovedCallback removedCallback = null, + string[] dependentFiles = null); + } +} diff --git a/src/Umbraco.Core/Cache/ICacheProvider.cs b/src/Umbraco.Core/Cache/ICacheProvider.cs deleted file mode 100644 index 177f7570c2..0000000000 --- a/src/Umbraco.Core/Cache/ICacheProvider.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace Umbraco.Core.Cache -{ - /// - /// An interface for implementing a basic cache provider - /// - public interface ICacheProvider - { - /// - /// Removes all items from the cache. - /// - void ClearAllCache(); - - /// - /// Removes an item from the cache, identified by its key. - /// - /// The key of the item. - void ClearCacheItem(string key); - - /// - /// Removes items from the cache, of a specified type. - /// - /// The name of the type to remove. - /// - /// If the type is an interface, then all items of a type implementing that interface are - /// removed. Otherwise, only items of that exact type are removed (items of type inheriting from - /// the specified type are not removed). - /// Performs a case-sensitive search. - /// - void ClearCacheObjectTypes(string typeName); - - /// - /// Removes items from the cache, of a specified type. - /// - /// The type of the items to remove. - /// If the type is an interface, then all items of a type implementing that interface are - /// removed. Otherwise, only items of that exact type are removed (items of type inheriting from - /// the specified type are not removed). - void ClearCacheObjectTypes(); - - /// - /// Removes items from the cache, of a specified type, satisfying a predicate. - /// - /// The type of the items to remove. - /// The predicate to satisfy. - /// If the type is an interface, then all items of a type implementing that interface are - /// removed. Otherwise, only items of that exact type are removed (items of type inheriting from - /// the specified type are not removed). - void ClearCacheObjectTypes(Func predicate); - - void ClearCacheByKeySearch(string keyStartsWith); - void ClearCacheByKeyExpression(string regexString); - - IEnumerable GetCacheItemsByKeySearch(string keyStartsWith); - IEnumerable GetCacheItemsByKeyExpression(string regexString); - - /// - /// Returns an item with a given key - /// - /// - /// - object GetCacheItem(string cacheKey); - - object GetCacheItem(string cacheKey, Func getCacheItem); - } -} diff --git a/src/Umbraco.Core/Cache/IRuntimeCacheProvider.cs b/src/Umbraco.Core/Cache/IRuntimeCacheProvider.cs deleted file mode 100644 index 9f3d687e1d..0000000000 --- a/src/Umbraco.Core/Cache/IRuntimeCacheProvider.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using System.Runtime.Caching; -using System.Text; -using System.Web.Caching; -using CacheItemPriority = System.Web.Caching.CacheItemPriority; - -namespace Umbraco.Core.Cache -{ - /// - /// An abstract class for implementing a runtime cache provider - /// - /// - /// - public interface IRuntimeCacheProvider : ICacheProvider - { - object GetCacheItem( - string cacheKey, - Func getCacheItem, - TimeSpan? timeout, - bool isSliding = false, - CacheItemPriority priority = CacheItemPriority.Normal, - CacheItemRemovedCallback removedCallback = null, - string[] dependentFiles = null); - - void InsertCacheItem( - string cacheKey, - Func getCacheItem, - TimeSpan? timeout = null, - bool isSliding = false, - CacheItemPriority priority = CacheItemPriority.Normal, - CacheItemRemovedCallback removedCallback = null, - string[] dependentFiles = null); - - } -} diff --git a/src/Umbraco.Core/Cache/IsolatedCaches.cs b/src/Umbraco.Core/Cache/IsolatedCaches.cs new file mode 100644 index 0000000000..bc624be20d --- /dev/null +++ b/src/Umbraco.Core/Cache/IsolatedCaches.cs @@ -0,0 +1,41 @@ +using System; + +namespace Umbraco.Core.Cache +{ + /// + /// Represents a dictionary of for types. + /// + /// + /// Isolated caches are used by e.g. repositories, to ensure that each cached entity + /// type has its own cache, so that lookups are fast and the repository does not need to + /// search through all keys on a global scale. + /// + public class IsolatedCaches : AppPolicedCacheDictionary + { + /// + /// Initializes a new instance of the class. + /// + /// + public IsolatedCaches(Func cacheFactory) + : base(cacheFactory) + { } + + /// + /// Gets a cache. + /// + public IAppPolicedCache GetOrCreate() + => GetOrCreate(typeof(T)); + + /// + /// Tries to get a cache. + /// + public Attempt Get() + => Get(typeof(T)); + + /// + /// Clears a cache. + /// + public void ClearCache() + => ClearCache(typeof(T)); + } +} diff --git a/src/Umbraco.Core/Cache/IsolatedRuntimeCache.cs b/src/Umbraco.Core/Cache/IsolatedRuntimeCache.cs deleted file mode 100644 index ee73a17532..0000000000 --- a/src/Umbraco.Core/Cache/IsolatedRuntimeCache.cs +++ /dev/null @@ -1,91 +0,0 @@ -using System; -using System.Collections.Concurrent; - -namespace Umbraco.Core.Cache -{ - /// - /// Used to get/create/manipulate isolated runtime cache - /// - /// - /// This is useful for repository level caches to ensure that cache lookups by key are fast so - /// that the repository doesn't need to search through all keys on a global scale. - /// - public class IsolatedRuntimeCache - { - internal Func CacheFactory { get; set; } - - /// - /// Constructor that allows specifying a factory for the type of runtime isolated cache to create - /// - /// - public IsolatedRuntimeCache(Func cacheFactory) - { - CacheFactory = cacheFactory; - } - - private readonly ConcurrentDictionary _isolatedCache = new ConcurrentDictionary(); - - /// - /// Returns an isolated runtime cache for a given type - /// - /// - /// - public IRuntimeCacheProvider GetOrCreateCache() - { - return _isolatedCache.GetOrAdd(typeof(T), type => CacheFactory(type)); - } - - /// - /// Returns an isolated runtime cache for a given type - /// - /// - public IRuntimeCacheProvider GetOrCreateCache(Type type) - { - return _isolatedCache.GetOrAdd(type, t => CacheFactory(t)); - } - - /// - /// Tries to get a cache by the type specified - /// - /// - /// - public Attempt GetCache() - { - IRuntimeCacheProvider cache; - if (_isolatedCache.TryGetValue(typeof(T), out cache)) - { - return Attempt.Succeed(cache); - } - return Attempt.Fail(); - } - - /// - /// Clears all values inside this isolated runtime cache - /// - /// - /// - public void ClearCache() - { - IRuntimeCacheProvider cache; - if (_isolatedCache.TryGetValue(typeof(T), out cache)) - { - cache.ClearAllCache(); - } - } - - /// - /// Clears all of the isolated caches - /// - public void ClearAllCaches() - { - foreach (var key in _isolatedCache.Keys) - { - IRuntimeCacheProvider cache; - if (_isolatedCache.TryRemove(key, out cache)) - { - cache.ClearAllCache(); - } - } - } - } -} diff --git a/src/Umbraco.Core/Cache/NoAppCache.cs b/src/Umbraco.Core/Cache/NoAppCache.cs new file mode 100644 index 0000000000..8a7e15cb29 --- /dev/null +++ b/src/Umbraco.Core/Cache/NoAppCache.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web.Caching; + +namespace Umbraco.Core.Cache +{ + /// + /// Implements and do not cache. + /// + public class NoAppCache : IAppPolicedCache + { + private NoAppCache() { } + + /// + /// Gets the singleton instance. + /// + public static NoAppCache Instance { get; } = new NoAppCache(); + + /// + public virtual object Get(string cacheKey) + { + return null; + } + + /// + public virtual object Get(string cacheKey, Func factory) + { + return factory(); + } + + /// + public virtual IEnumerable SearchByKey(string keyStartsWith) + { + return Enumerable.Empty(); + } + + /// + public IEnumerable SearchByRegex(string regex) + { + return Enumerable.Empty(); + } + + /// + public object Get(string key, Func factory, TimeSpan? timeout, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null) + { + return factory(); + } + + /// + public void Insert(string key, Func factory, TimeSpan? timeout = null, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null) + { } + + /// + public virtual void Clear() + { } + + /// + public virtual void Clear(string key) + { } + + /// + public virtual void ClearOfType(string typeName) + { } + + /// + public virtual void ClearOfType() + { } + + /// + public virtual void ClearOfType(Func predicate) + { } + + /// + public virtual void ClearByKey(string keyStartsWith) + { } + + /// + public virtual void ClearByRegex(string regex) + { } + } +} diff --git a/src/Umbraco.Core/Cache/NoCacheRepositoryCachePolicy.cs b/src/Umbraco.Core/Cache/NoCacheRepositoryCachePolicy.cs index a3e7335d7f..acc67be679 100644 --- a/src/Umbraco.Core/Cache/NoCacheRepositoryCachePolicy.cs +++ b/src/Umbraco.Core/Cache/NoCacheRepositoryCachePolicy.cs @@ -13,7 +13,7 @@ namespace Umbraco.Core.Cache public static NoCacheRepositoryCachePolicy Instance { get; } = new NoCacheRepositoryCachePolicy(); - public IRepositoryCachePolicy Scoped(IRuntimeCacheProvider runtimeCache, IScope scope) + public IRepositoryCachePolicy Scoped(IAppPolicedCache runtimeCache, IScope scope) { throw new NotImplementedException(); } diff --git a/src/Umbraco.Core/Cache/NullCacheProvider.cs b/src/Umbraco.Core/Cache/NullCacheProvider.cs deleted file mode 100644 index 78286f75e2..0000000000 --- a/src/Umbraco.Core/Cache/NullCacheProvider.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web.Caching; - -namespace Umbraco.Core.Cache -{ - /// - /// Represents a cache provider that does not cache anything. - /// - public class NullCacheProvider : IRuntimeCacheProvider - { - private NullCacheProvider() { } - - public static NullCacheProvider Instance { get; } = new NullCacheProvider(); - - public virtual void ClearAllCache() - { } - - public virtual void ClearCacheItem(string key) - { } - - public virtual void ClearCacheObjectTypes(string typeName) - { } - - public virtual void ClearCacheObjectTypes() - { } - - public virtual void ClearCacheObjectTypes(Func predicate) - { } - - public virtual void ClearCacheByKeySearch(string keyStartsWith) - { } - - public virtual void ClearCacheByKeyExpression(string regexString) - { } - - public virtual IEnumerable GetCacheItemsByKeySearch(string keyStartsWith) - { - return Enumerable.Empty(); - } - - public IEnumerable GetCacheItemsByKeyExpression(string regexString) - { - return Enumerable.Empty(); - } - - public virtual object GetCacheItem(string cacheKey) - { - return default(object); - } - - public virtual object GetCacheItem(string cacheKey, Func getCacheItem) - { - return getCacheItem(); - } - - public object GetCacheItem(string cacheKey, Func getCacheItem, TimeSpan? timeout, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null) - { - return getCacheItem(); - } - - public void InsertCacheItem(string cacheKey, Func getCacheItem, TimeSpan? timeout = null, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null) - { } - } -} diff --git a/src/Umbraco.Core/Cache/ObjectCacheRuntimeCacheProvider.cs b/src/Umbraco.Core/Cache/ObjectCacheAppCache.cs similarity index 73% rename from src/Umbraco.Core/Cache/ObjectCacheRuntimeCacheProvider.cs rename to src/Umbraco.Core/Cache/ObjectCacheAppCache.cs index 8a844bbc9b..9c5917a53c 100644 --- a/src/Umbraco.Core/Cache/ObjectCacheRuntimeCacheProvider.cs +++ b/src/Umbraco.Core/Cache/ObjectCacheAppCache.cs @@ -11,31 +11,142 @@ using CacheItemPriority = System.Web.Caching.CacheItemPriority; namespace Umbraco.Core.Cache { /// - /// Represents a cache provider that caches item in a . - /// A cache provider that wraps the logic of a System.Runtime.Caching.ObjectCache + /// Implements on top of a . /// - /// The is created with name "in-memory". That name is - /// used to retrieve configuration options. It does not identify the memory cache, i.e. - /// each instance of this class has its own, independent, memory cache. - public class ObjectCacheRuntimeCacheProvider : IRuntimeCacheProvider + public class ObjectCacheAppCache : IAppPolicedCache { private readonly ReaderWriterLockSlim _locker = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); - internal ObjectCache MemoryCache; /// - /// Used for debugging + /// Initializes a new instance of the . /// - internal Guid InstanceId { get; private set; } - - public ObjectCacheRuntimeCacheProvider() + public ObjectCacheAppCache() { + // the MemoryCache is created with name "in-memory". That name is + // used to retrieve configuration options. It does not identify the memory cache, i.e. + // each instance of this class has its own, independent, memory cache. MemoryCache = new MemoryCache("in-memory"); - InstanceId = Guid.NewGuid(); } - #region Clear + /// + /// Gets the internal memory cache, for tests only! + /// + internal readonly ObjectCache MemoryCache; - public virtual void ClearAllCache() + /// + public object Get(string key) + { + Lazy result; + try + { + _locker.EnterReadLock(); + result = MemoryCache.Get(key) as Lazy; // null if key not found + } + finally + { + if (_locker.IsReadLockHeld) + _locker.ExitReadLock(); + } + return result == null ? null : FastDictionaryAppCacheBase.GetSafeLazyValue(result); // return exceptions as null + } + + /// + public object Get(string key, Func factory) + { + return Get(key, factory, null); + } + + /// + public IEnumerable SearchByKey(string keyStartsWith) + { + KeyValuePair[] entries; + try + { + _locker.EnterReadLock(); + entries = MemoryCache + .Where(x => x.Key.InvariantStartsWith(keyStartsWith)) + .ToArray(); // evaluate while locked + } + finally + { + if (_locker.IsReadLockHeld) + _locker.ExitReadLock(); + } + return entries + .Select(x => FastDictionaryAppCacheBase.GetSafeLazyValue((Lazy)x.Value)) // return exceptions as null + .Where(x => x != null) // backward compat, don't store null values in the cache + .ToList(); + } + + /// + public IEnumerable SearchByRegex(string regex) + { + var compiled = new Regex(regex, RegexOptions.Compiled); + + KeyValuePair[] entries; + try + { + _locker.EnterReadLock(); + entries = MemoryCache + .Where(x => compiled.IsMatch(x.Key)) + .ToArray(); // evaluate while locked + } + finally + { + if (_locker.IsReadLockHeld) + _locker.ExitReadLock(); + } + return entries + .Select(x => FastDictionaryAppCacheBase.GetSafeLazyValue((Lazy)x.Value)) // return exceptions as null + .Where(x => x != null) // backward compat, don't store null values in the cache + .ToList(); + } + + /// + public object Get(string key, Func factory, TimeSpan? timeout, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null) + { + // see notes in HttpRuntimeCacheProvider + + Lazy result; + + using (var lck = new UpgradeableReadLock(_locker)) + { + result = MemoryCache.Get(key) as Lazy; + if (result == null || FastDictionaryAppCacheBase.GetSafeLazyValue(result, true) == null) // get non-created as NonCreatedValue & exceptions as null + { + result = FastDictionaryAppCacheBase.GetSafeLazy(factory); + var policy = GetPolicy(timeout, isSliding, removedCallback, dependentFiles); + + lck.UpgradeToWriteLock(); + //NOTE: This does an add or update + MemoryCache.Set(key, result, policy); + } + } + + //return result.Value; + + var value = result.Value; // will not throw (safe lazy) + if (value is FastDictionaryAppCacheBase.ExceptionHolder eh) eh.Exception.Throw(); // throw once! + return value; + } + + /// + public void Insert(string key, Func factory, TimeSpan? timeout = null, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null) + { + // NOTE - here also we must insert a Lazy but we can evaluate it right now + // and make sure we don't store a null value. + + var result = FastDictionaryAppCacheBase.GetSafeLazy(factory); + var value = result.Value; // force evaluation now + if (value == null) return; // do not store null values (backward compat) + + var policy = GetPolicy(timeout, isSliding, removedCallback, dependentFiles); + //NOTE: This does an add or update + MemoryCache.Set(key, result, policy); + } + + /// + public virtual void Clear() { try { @@ -50,7 +161,8 @@ namespace Umbraco.Core.Cache } } - public virtual void ClearCacheItem(string key) + /// + public virtual void Clear(string key) { try { @@ -65,7 +177,8 @@ namespace Umbraco.Core.Cache } } - public virtual void ClearCacheObjectTypes(string typeName) + /// + public virtual void ClearOfType(string typeName) { var type = TypeFinder.GetTypeByName(typeName); if (type == null) return; @@ -79,7 +192,7 @@ namespace Umbraco.Core.Cache // x.Value is Lazy and not null, its value may be null // remove null values as well, does not hurt // get non-created as NonCreatedValue & exceptions as null - var value = DictionaryCacheProviderBase.GetSafeLazyValue((Lazy)x.Value, true); + var value = FastDictionaryAppCacheBase.GetSafeLazyValue((Lazy)x.Value, true); // if T is an interface remove anything that implements that interface // otherwise remove exact types (not inherited types) @@ -96,12 +209,13 @@ namespace Umbraco.Core.Cache } } - public virtual void ClearCacheObjectTypes() + /// + public virtual void ClearOfType() { try { _locker.EnterWriteLock(); - var typeOfT = typeof (T); + var typeOfT = typeof(T); var isInterface = typeOfT.IsInterface; foreach (var key in MemoryCache .Where(x => @@ -109,7 +223,7 @@ namespace Umbraco.Core.Cache // x.Value is Lazy and not null, its value may be null // remove null values as well, does not hurt // get non-created as NonCreatedValue & exceptions as null - var value = DictionaryCacheProviderBase.GetSafeLazyValue((Lazy)x.Value, true); + var value = FastDictionaryAppCacheBase.GetSafeLazyValue((Lazy)x.Value, true); // if T is an interface remove anything that implements that interface // otherwise remove exact types (not inherited types) @@ -127,7 +241,8 @@ namespace Umbraco.Core.Cache } } - public virtual void ClearCacheObjectTypes(Func predicate) + /// + public virtual void ClearOfType(Func predicate) { try { @@ -140,7 +255,7 @@ namespace Umbraco.Core.Cache // x.Value is Lazy and not null, its value may be null // remove null values as well, does not hurt // get non-created as NonCreatedValue & exceptions as null - var value = DictionaryCacheProviderBase.GetSafeLazyValue((Lazy)x.Value, true); + var value = FastDictionaryAppCacheBase.GetSafeLazyValue((Lazy)x.Value, true); if (value == null) return true; // if T is an interface remove anything that implements that interface @@ -159,7 +274,8 @@ namespace Umbraco.Core.Cache } } - public virtual void ClearCacheByKeySearch(string keyStartsWith) + /// + public virtual void ClearByKey(string keyStartsWith) { try { @@ -177,13 +293,16 @@ namespace Umbraco.Core.Cache } } - public virtual void ClearCacheByKeyExpression(string regexString) + /// + public virtual void ClearByRegex(string regex) { + var compiled = new Regex(regex, RegexOptions.Compiled); + try { _locker.EnterWriteLock(); foreach (var key in MemoryCache - .Where(x => Regex.IsMatch(x.Key, regexString)) + .Where(x => compiled.IsMatch(x.Key)) .Select(x => x.Key) .ToArray()) // ToArray required to remove MemoryCache.Remove(key); @@ -195,120 +314,6 @@ namespace Umbraco.Core.Cache } } - #endregion - - #region Get - - public IEnumerable GetCacheItemsByKeySearch(string keyStartsWith) - { - KeyValuePair[] entries; - try - { - _locker.EnterReadLock(); - entries = MemoryCache - .Where(x => x.Key.InvariantStartsWith(keyStartsWith)) - .ToArray(); // evaluate while locked - } - finally - { - if (_locker.IsReadLockHeld) - _locker.ExitReadLock(); - } - return entries - .Select(x => DictionaryCacheProviderBase.GetSafeLazyValue((Lazy)x.Value)) // return exceptions as null - .Where(x => x != null) // backward compat, don't store null values in the cache - .ToList(); - } - - public IEnumerable GetCacheItemsByKeyExpression(string regexString) - { - KeyValuePair[] entries; - try - { - _locker.EnterReadLock(); - entries = MemoryCache - .Where(x => Regex.IsMatch(x.Key, regexString)) - .ToArray(); // evaluate while locked - } - finally - { - if (_locker.IsReadLockHeld) - _locker.ExitReadLock(); - } - return entries - .Select(x => DictionaryCacheProviderBase.GetSafeLazyValue((Lazy)x.Value)) // return exceptions as null - .Where(x => x != null) // backward compat, don't store null values in the cache - .ToList(); - } - - public object GetCacheItem(string cacheKey) - { - Lazy result; - try - { - _locker.EnterReadLock(); - result = MemoryCache.Get(cacheKey) as Lazy; // null if key not found - } - finally - { - if (_locker.IsReadLockHeld) - _locker.ExitReadLock(); - } - return result == null ? null : DictionaryCacheProviderBase.GetSafeLazyValue(result); // return exceptions as null - } - - public object GetCacheItem(string cacheKey, Func getCacheItem) - { - return GetCacheItem(cacheKey, getCacheItem, null); - } - - public object GetCacheItem(string cacheKey, Func getCacheItem, TimeSpan? timeout, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null) - { - // see notes in HttpRuntimeCacheProvider - - Lazy result; - - using (var lck = new UpgradeableReadLock(_locker)) - { - result = MemoryCache.Get(cacheKey) as Lazy; - if (result == null || DictionaryCacheProviderBase.GetSafeLazyValue(result, true) == null) // get non-created as NonCreatedValue & exceptions as null - { - result = DictionaryCacheProviderBase.GetSafeLazy(getCacheItem); - var policy = GetPolicy(timeout, isSliding, removedCallback, dependentFiles); - - lck.UpgradeToWriteLock(); - //NOTE: This does an add or update - MemoryCache.Set(cacheKey, result, policy); - } - } - - //return result.Value; - - var value = result.Value; // will not throw (safe lazy) - if (value is DictionaryCacheProviderBase.ExceptionHolder eh) eh.Exception.Throw(); // throw once! - return value; - } - - #endregion - - #region Insert - - public void InsertCacheItem(string cacheKey, Func getCacheItem, TimeSpan? timeout = null, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null) - { - // NOTE - here also we must insert a Lazy but we can evaluate it right now - // and make sure we don't store a null value. - - var result = DictionaryCacheProviderBase.GetSafeLazy(getCacheItem); - var value = result.Value; // force evaluation now - if (value == null) return; // do not store null values (backward compat) - - var policy = GetPolicy(timeout, isSliding, removedCallback, dependentFiles); - //NOTE: This does an add or update - MemoryCache.Set(cacheKey, result, policy); - } - - #endregion - private static CacheItemPolicy GetPolicy(TimeSpan? timeout = null, bool isSliding = false, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null) { var absolute = isSliding ? ObjectCache.InfiniteAbsoluteExpiration : (timeout == null ? ObjectCache.InfiniteAbsoluteExpiration : DateTime.Now.Add(timeout.Value)); diff --git a/src/Umbraco.Core/Cache/RepositoryCachePolicyBase.cs b/src/Umbraco.Core/Cache/RepositoryCachePolicyBase.cs index 2d21d410a7..f8bba4b033 100644 --- a/src/Umbraco.Core/Cache/RepositoryCachePolicyBase.cs +++ b/src/Umbraco.Core/Cache/RepositoryCachePolicyBase.cs @@ -13,16 +13,16 @@ namespace Umbraco.Core.Cache internal abstract class RepositoryCachePolicyBase : IRepositoryCachePolicy where TEntity : class, IEntity { - private readonly IRuntimeCacheProvider _globalCache; + private readonly IAppPolicedCache _globalCache; private readonly IScopeAccessor _scopeAccessor; - protected RepositoryCachePolicyBase(IRuntimeCacheProvider globalCache, IScopeAccessor scopeAccessor) + protected RepositoryCachePolicyBase(IAppPolicedCache globalCache, IScopeAccessor scopeAccessor) { _globalCache = globalCache ?? throw new ArgumentNullException(nameof(globalCache)); _scopeAccessor = scopeAccessor ?? throw new ArgumentNullException(nameof(scopeAccessor)); } - protected IRuntimeCacheProvider Cache + protected IAppPolicedCache Cache { get { @@ -32,9 +32,9 @@ namespace Umbraco.Core.Cache case RepositoryCacheMode.Default: return _globalCache; case RepositoryCacheMode.Scoped: - return ambientScope.IsolatedRuntimeCache.GetOrCreateCache(); + return ambientScope.IsolatedCaches.GetOrCreate(); case RepositoryCacheMode.None: - return NullCacheProvider.Instance; + return NoAppCache.Instance; default: throw new NotSupportedException($"Repository cache mode {ambientScope.RepositoryCacheMode} is not supported."); } diff --git a/src/Umbraco.Core/Cache/SingleItemsOnlyRepositoryCachePolicy.cs b/src/Umbraco.Core/Cache/SingleItemsOnlyRepositoryCachePolicy.cs index d89524d4f9..714798a47c 100644 --- a/src/Umbraco.Core/Cache/SingleItemsOnlyRepositoryCachePolicy.cs +++ b/src/Umbraco.Core/Cache/SingleItemsOnlyRepositoryCachePolicy.cs @@ -16,7 +16,7 @@ namespace Umbraco.Core.Cache internal class SingleItemsOnlyRepositoryCachePolicy : DefaultRepositoryCachePolicy where TEntity : class, IEntity { - public SingleItemsOnlyRepositoryCachePolicy(IRuntimeCacheProvider cache, IScopeAccessor scopeAccessor, RepositoryCachePolicyOptions options) + public SingleItemsOnlyRepositoryCachePolicy(IAppPolicedCache cache, IScopeAccessor scopeAccessor, RepositoryCachePolicyOptions options) : base(cache, scopeAccessor, options) { } diff --git a/src/Umbraco.Core/Cache/StaticCacheProvider.cs b/src/Umbraco.Core/Cache/StaticCacheProvider.cs deleted file mode 100644 index 1604add4d7..0000000000 --- a/src/Umbraco.Core/Cache/StaticCacheProvider.cs +++ /dev/null @@ -1,79 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; -using System.Text.RegularExpressions; - -namespace Umbraco.Core.Cache -{ - /// - /// Represents a cache provider that statically caches item in a concurrent dictionary. - /// - public class StaticCacheProvider : ICacheProvider - { - internal readonly ConcurrentDictionary StaticCache = new ConcurrentDictionary(); - - public virtual void ClearAllCache() - { - StaticCache.Clear(); - } - - public virtual void ClearCacheItem(string key) - { - object val; - StaticCache.TryRemove(key, out val); - } - - public virtual void ClearCacheObjectTypes(string typeName) - { - StaticCache.RemoveAll(kvp => kvp.Value != null && kvp.Value.GetType().ToString().InvariantEquals(typeName)); - } - - public virtual void ClearCacheObjectTypes() - { - var typeOfT = typeof(T); - StaticCache.RemoveAll(kvp => kvp.Value != null && kvp.Value.GetType() == typeOfT); - } - - public virtual void ClearCacheObjectTypes(Func predicate) - { - var typeOfT = typeof(T); - StaticCache.RemoveAll(kvp => kvp.Value != null && kvp.Value.GetType() == typeOfT && predicate(kvp.Key, (T)kvp.Value)); - } - - public virtual void ClearCacheByKeySearch(string keyStartsWith) - { - StaticCache.RemoveAll(kvp => kvp.Key.InvariantStartsWith(keyStartsWith)); - } - - public virtual void ClearCacheByKeyExpression(string regexString) - { - StaticCache.RemoveAll(kvp => Regex.IsMatch(kvp.Key, regexString)); - } - - public virtual IEnumerable GetCacheItemsByKeySearch(string keyStartsWith) - { - return (from KeyValuePair c in StaticCache - where c.Key.InvariantStartsWith(keyStartsWith) - select c.Value).ToList(); - } - - public IEnumerable GetCacheItemsByKeyExpression(string regexString) - { - return (from KeyValuePair c in StaticCache - where Regex.IsMatch(c.Key, regexString) - select c.Value).ToList(); - } - - public virtual object GetCacheItem(string cacheKey) - { - var result = StaticCache[cacheKey]; - return result; - } - - public virtual object GetCacheItem(string cacheKey, Func getCacheItem) - { - return StaticCache.GetOrAdd(cacheKey, key => getCacheItem()); - } - } -} diff --git a/src/Umbraco.Core/Cache/HttpRuntimeCacheProvider.cs b/src/Umbraco.Core/Cache/WebCachingAppCache.cs similarity index 68% rename from src/Umbraco.Core/Cache/HttpRuntimeCacheProvider.cs rename to src/Umbraco.Core/Cache/WebCachingAppCache.cs index 835c5d1ee6..b762fcda07 100644 --- a/src/Umbraco.Core/Cache/HttpRuntimeCacheProvider.cs +++ b/src/Umbraco.Core/Cache/WebCachingAppCache.cs @@ -4,14 +4,15 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Web.Caching; -using CacheItemPriority = System.Web.Caching.CacheItemPriority; namespace Umbraco.Core.Cache { /// + /// Implements on top of a . /// A CacheProvider that wraps the logic of the HttpRuntime.Cache /// - internal class HttpRuntimeCacheProvider : DictionaryCacheProviderBase, IRuntimeCacheProvider + /// The underlying cache is expected to be HttpRuntime.Cache. + internal class WebCachingAppCache : FastDictionaryAppCacheBase, IAppPolicedCache { // locker object that supports upgradeable read locking // does not need to support recursion if we implement the cache correctly and ensure @@ -21,16 +22,43 @@ namespace Umbraco.Core.Cache private readonly System.Web.Caching.Cache _cache; /// - /// Used for debugging + /// Initializes a new instance of the class. /// - internal Guid InstanceId { get; private set; } - - public HttpRuntimeCacheProvider(System.Web.Caching.Cache cache) + public WebCachingAppCache(System.Web.Caching.Cache cache) { _cache = cache; - InstanceId = Guid.NewGuid(); } + /// + public override object Get(string key, Func factory) + { + return Get(key, factory, null, dependentFiles: null); + } + + /// + public object Get(string key, Func factory, TimeSpan? timeout, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null) + { + CacheDependency dependency = null; + if (dependentFiles != null && dependentFiles.Any()) + { + dependency = new CacheDependency(dependentFiles); + } + return Get(key, factory, timeout, isSliding, priority, removedCallback, dependency); + } + + /// + public void Insert(string key, Func factory, TimeSpan? timeout = null, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null) + { + CacheDependency dependency = null; + if (dependentFiles != null && dependentFiles.Any()) + { + dependency = new CacheDependency(dependentFiles); + } + Insert(key, factory, timeout, isSliding, priority, removedCallback, dependency); + } + + #region Dictionary + protected override IEnumerable GetDictionaryEntries() { const string prefix = CacheItemPrefix + "-"; @@ -48,6 +76,8 @@ namespace Umbraco.Core.Cache return _cache.Get(key); } + #endregion + #region Lock protected override void EnterReadLock() @@ -74,33 +104,9 @@ namespace Umbraco.Core.Cache #endregion - #region Get - - /// - /// Gets (and adds if necessary) an item from the cache with all of the default parameters - /// - /// - /// - /// - public override object GetCacheItem(string cacheKey, Func getCacheItem) + private object Get(string key, Func factory, TimeSpan? timeout, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, CacheDependency dependency = null) { - return GetCacheItem(cacheKey, getCacheItem, null, dependentFiles: null); - } - - /// - /// This overload is here for legacy purposes - /// - /// - /// - /// - /// - /// - /// - /// - /// - internal object GetCacheItem(string cacheKey, Func getCacheItem, TimeSpan? timeout, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, CacheDependency dependency = null) - { - cacheKey = GetCacheKey(cacheKey); + key = GetCacheKey(key); // NOTE - because we don't know what getCacheItem does, how long it will take and whether it will hang, // getCacheItem should run OUTSIDE of the global application lock else we run into lock contention and @@ -133,7 +139,7 @@ namespace Umbraco.Core.Cache try { _locker.EnterReadLock(); - result = _cache.Get(cacheKey) as Lazy; // null if key not found + result = _cache.Get(key) as Lazy; // null if key not found } finally { @@ -145,7 +151,7 @@ namespace Umbraco.Core.Cache using (var lck = new UpgradeableReadLock(_locker)) { - result = _cache.Get(cacheKey) as Lazy; // null if key not found + result = _cache.Get(key) as Lazy; // null if key not found // cannot create value within the lock, so if result.IsValueCreated is false, just // do nothing here - means that if creation throws, a race condition could cause @@ -153,13 +159,13 @@ namespace Umbraco.Core.Cache if (result == null || GetSafeLazyValue(result, true) == null) // get non-created as NonCreatedValue & exceptions as null { - result = GetSafeLazy(getCacheItem); + result = GetSafeLazy(factory); var absolute = isSliding ? System.Web.Caching.Cache.NoAbsoluteExpiration : (timeout == null ? System.Web.Caching.Cache.NoAbsoluteExpiration : DateTime.Now.Add(timeout.Value)); var sliding = isSliding == false ? System.Web.Caching.Cache.NoSlidingExpiration : (timeout ?? System.Web.Caching.Cache.NoSlidingExpiration); lck.UpgradeToWriteLock(); //NOTE: 'Insert' on System.Web.Caching.Cache actually does an add or update! - _cache.Insert(cacheKey, result, dependency, absolute, sliding, priority, removedCallback); + _cache.Insert(key, result, dependency, absolute, sliding, priority, removedCallback); } } @@ -175,31 +181,7 @@ namespace Umbraco.Core.Cache return value; } - public object GetCacheItem(string cacheKey, Func getCacheItem, TimeSpan? timeout, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null) - { - CacheDependency dependency = null; - if (dependentFiles != null && dependentFiles.Any()) - { - dependency = new CacheDependency(dependentFiles); - } - return GetCacheItem(cacheKey, getCacheItem, timeout, isSliding, priority, removedCallback, dependency); - } - - #endregion - - #region Insert - - /// - /// This overload is here for legacy purposes - /// - /// - /// - /// - /// - /// - /// - /// - internal void InsertCacheItem(string cacheKey, Func getCacheItem, TimeSpan? timeout = null, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, CacheDependency dependency = null) + private void Insert(string cacheKey, Func getCacheItem, TimeSpan? timeout = null, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, CacheDependency dependency = null) { // NOTE - here also we must insert a Lazy but we can evaluate it right now // and make sure we don't store a null value. @@ -225,17 +207,5 @@ namespace Umbraco.Core.Cache _locker.ExitWriteLock(); } } - - public void InsertCacheItem(string cacheKey, Func getCacheItem, TimeSpan? timeout = null, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null) - { - CacheDependency dependency = null; - if (dependentFiles != null && dependentFiles.Any()) - { - dependency = new CacheDependency(dependentFiles); - } - InsertCacheItem(cacheKey, getCacheItem, timeout, isSliding, priority, removedCallback, dependency); - } - - #endregion } } diff --git a/src/Umbraco.Core/Composing/TypeLoader.cs b/src/Umbraco.Core/Composing/TypeLoader.cs index acb12ab575..fe277676d7 100644 --- a/src/Umbraco.Core/Composing/TypeLoader.cs +++ b/src/Umbraco.Core/Composing/TypeLoader.cs @@ -29,7 +29,7 @@ namespace Umbraco.Core.Composing { private const string CacheKey = "umbraco-types.list"; - private readonly IRuntimeCacheProvider _runtimeCache; + private readonly IAppPolicedCache _runtimeCache; private readonly IProfilingLogger _logger; private readonly Dictionary _types = new Dictionary(); @@ -51,7 +51,7 @@ namespace Umbraco.Core.Composing /// The application runtime cache. /// Files storage mode. /// A profiling logger. - public TypeLoader(IRuntimeCacheProvider runtimeCache, LocalTempStorage localTempStorage, IProfilingLogger logger) + public TypeLoader(IAppPolicedCache runtimeCache, LocalTempStorage localTempStorage, IProfilingLogger logger) : this(runtimeCache, localTempStorage, logger, true) { } @@ -62,7 +62,7 @@ namespace Umbraco.Core.Composing /// Files storage mode. /// A profiling logger. /// Whether to detect changes using hashes. - internal TypeLoader(IRuntimeCacheProvider runtimeCache, LocalTempStorage localTempStorage, IProfilingLogger logger, bool detectChanges) + internal TypeLoader(IAppPolicedCache runtimeCache, LocalTempStorage localTempStorage, IProfilingLogger logger, bool detectChanges) { _runtimeCache = runtimeCache ?? throw new ArgumentNullException(nameof(runtimeCache)); _localTempStorage = localTempStorage == LocalTempStorage.Unknown ? LocalTempStorage.Default : localTempStorage; @@ -478,7 +478,7 @@ namespace Umbraco.Core.Composing var typesHashFilePath = GetTypesHashFilePath(); DeleteFile(typesHashFilePath, FileDeleteTimeout); - _runtimeCache.ClearCacheItem(CacheKey); + _runtimeCache.Clear(CacheKey); } private Stream GetFileStream(string path, FileMode fileMode, FileAccess fileAccess, FileShare fileShare, int timeoutMilliseconds) diff --git a/src/Umbraco.Core/ConfigsExtensions.cs b/src/Umbraco.Core/ConfigsExtensions.cs index 1414dbc852..9b2abda53c 100644 --- a/src/Umbraco.Core/ConfigsExtensions.cs +++ b/src/Umbraco.Core/ConfigsExtensions.cs @@ -46,7 +46,7 @@ namespace Umbraco.Core 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().Debug)); + configs.Add(factory => new GridConfig(factory.GetInstance(), factory.GetInstance(), configDir, factory.GetInstance().Debug)); } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Configuration/Grid/GridConfig.cs b/src/Umbraco.Core/Configuration/Grid/GridConfig.cs index 6c16a5e7ef..979eccb839 100644 --- a/src/Umbraco.Core/Configuration/Grid/GridConfig.cs +++ b/src/Umbraco.Core/Configuration/Grid/GridConfig.cs @@ -6,7 +6,7 @@ namespace Umbraco.Core.Configuration.Grid { class GridConfig : IGridConfig { - public GridConfig(ILogger logger, IRuntimeCacheProvider runtimeCache, DirectoryInfo configFolder, bool isDebug) + public GridConfig(ILogger logger, IAppPolicedCache runtimeCache, DirectoryInfo configFolder, bool isDebug) { EditorsConfig = new GridEditorsConfig(logger, runtimeCache, configFolder, isDebug); } diff --git a/src/Umbraco.Core/Configuration/Grid/GridEditorsConfig.cs b/src/Umbraco.Core/Configuration/Grid/GridEditorsConfig.cs index 94249aa135..121b74194c 100644 --- a/src/Umbraco.Core/Configuration/Grid/GridEditorsConfig.cs +++ b/src/Umbraco.Core/Configuration/Grid/GridEditorsConfig.cs @@ -13,11 +13,11 @@ namespace Umbraco.Core.Configuration.Grid internal class GridEditorsConfig : IGridEditorsConfig { private readonly ILogger _logger; - private readonly IRuntimeCacheProvider _runtimeCache; + private readonly IAppPolicedCache _runtimeCache; private readonly DirectoryInfo _configFolder; private readonly bool _isDebug; - public GridEditorsConfig(ILogger logger, IRuntimeCacheProvider runtimeCache, DirectoryInfo configFolder, bool isDebug) + public GridEditorsConfig(ILogger logger, IAppPolicedCache runtimeCache, DirectoryInfo configFolder, bool isDebug) { _logger = logger; _runtimeCache = runtimeCache; diff --git a/src/Umbraco.Core/Manifest/ManifestParser.cs b/src/Umbraco.Core/Manifest/ManifestParser.cs index 59753df66a..fd344674af 100644 --- a/src/Umbraco.Core/Manifest/ManifestParser.cs +++ b/src/Umbraco.Core/Manifest/ManifestParser.cs @@ -20,7 +20,7 @@ namespace Umbraco.Core.Manifest { private static readonly string Utf8Preamble = Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble()); - private readonly IRuntimeCacheProvider _cache; + private readonly IAppPolicedCache _cache; private readonly ILogger _logger; private readonly ManifestValueValidatorCollection _validators; @@ -29,14 +29,14 @@ namespace Umbraco.Core.Manifest /// /// Initializes a new instance of the class. /// - public ManifestParser(IRuntimeCacheProvider cache, ManifestValueValidatorCollection validators, ILogger logger) + public ManifestParser(IAppPolicedCache cache, ManifestValueValidatorCollection validators, ILogger logger) : this(cache, validators, "~/App_Plugins", logger) { } /// /// Initializes a new instance of the class. /// - private ManifestParser(IRuntimeCacheProvider cache, ManifestValueValidatorCollection validators, string path, ILogger logger) + private ManifestParser(IAppPolicedCache cache, ManifestValueValidatorCollection validators, string path, ILogger logger) { _cache = cache ?? throw new ArgumentNullException(nameof(cache)); _validators = validators ?? throw new ArgumentNullException(nameof(validators)); diff --git a/src/Umbraco.Core/Models/UserExtensions.cs b/src/Umbraco.Core/Models/UserExtensions.cs index ba4d8cf590..7db3e3adbe 100644 --- a/src/Umbraco.Core/Models/UserExtensions.cs +++ b/src/Umbraco.Core/Models/UserExtensions.cs @@ -54,7 +54,7 @@ namespace Umbraco.Core.Models /// /// A list of 5 different sized avatar URLs /// - internal static string[] GetUserAvatarUrls(this IUser user, ICacheProvider staticCache) + internal static string[] GetUserAvatarUrls(this IUser user, IAppCache staticCache) { // If FIPS is required, never check the Gravatar service as it only supports MD5 hashing. // Unfortunately, if the FIPS setting is enabled on Windows, using MD5 will throw an exception diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/ConsentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/ConsentRepository.cs index bd55654809..8df9bf686d 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/ConsentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/ConsentRepository.cs @@ -86,7 +86,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement Database.Update(dto); entity.ResetDirtyProperties(); - IsolatedCache.ClearCacheItem(RepositoryCacheKeys.GetKey(entity.Id)); + IsolatedCache.Clear(RepositoryCacheKeys.GetKey(entity.Id)); } /// diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/DictionaryRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/DictionaryRepository.cs index 3517fb3545..9b191d830c 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/DictionaryRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/DictionaryRepository.cs @@ -174,8 +174,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement entity.ResetDirtyProperties(); //Clear the cache entries that exist by uniqueid/item key - IsolatedCache.ClearCacheItem(RepositoryCacheKeys.GetKey(entity.ItemKey)); - IsolatedCache.ClearCacheItem(RepositoryCacheKeys.GetKey(entity.Key)); + IsolatedCache.Clear(RepositoryCacheKeys.GetKey(entity.ItemKey)); + IsolatedCache.Clear(RepositoryCacheKeys.GetKey(entity.Key)); } protected override void PersistDeletedItem(IDictionaryItem entity) @@ -186,8 +186,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement Database.Delete("WHERE id = @Id", new { Id = entity.Key }); //Clear the cache entries that exist by uniqueid/item key - IsolatedCache.ClearCacheItem(RepositoryCacheKeys.GetKey(entity.ItemKey)); - IsolatedCache.ClearCacheItem(RepositoryCacheKeys.GetKey(entity.Key)); + IsolatedCache.Clear(RepositoryCacheKeys.GetKey(entity.ItemKey)); + IsolatedCache.Clear(RepositoryCacheKeys.GetKey(entity.Key)); entity.DeleteDate = DateTime.Now; } @@ -203,8 +203,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement Database.Delete("WHERE id = @Id", new { Id = dto.UniqueId }); //Clear the cache entries that exist by uniqueid/item key - IsolatedCache.ClearCacheItem(RepositoryCacheKeys.GetKey(dto.Key)); - IsolatedCache.ClearCacheItem(RepositoryCacheKeys.GetKey(dto.UniqueId)); + IsolatedCache.Clear(RepositoryCacheKeys.GetKey(dto.Key)); + IsolatedCache.Clear(RepositoryCacheKeys.GetKey(dto.UniqueId)); } } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/RepositoryBaseOfTIdTEntity.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/RepositoryBaseOfTIdTEntity.cs index 2626f60123..f106949c77 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/RepositoryBaseOfTIdTEntity.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/RepositoryBaseOfTIdTEntity.cs @@ -30,7 +30,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement protected AppCaches GlobalCache { get; } - protected IRuntimeCacheProvider GlobalIsolatedCache => GlobalCache.IsolatedRuntimeCache.GetOrCreateCache(); + protected IAppPolicedCache GlobalIsolatedCache => GlobalCache.IsolatedCaches.GetOrCreate(); protected IScopeAccessor ScopeAccessor { get; } @@ -60,18 +60,18 @@ namespace Umbraco.Core.Persistence.Repositories.Implement /// Gets the isolated cache. /// /// Depends on the ambient scope cache mode. - protected IRuntimeCacheProvider IsolatedCache + protected IAppPolicedCache IsolatedCache { get { switch (AmbientScope.RepositoryCacheMode) { case RepositoryCacheMode.Default: - return GlobalCache.IsolatedRuntimeCache.GetOrCreateCache(); + return GlobalCache.IsolatedCaches.GetOrCreate(); case RepositoryCacheMode.Scoped: - return AmbientScope.IsolatedRuntimeCache.GetOrCreateCache(); + return AmbientScope.IsolatedCaches.GetOrCreate(); case RepositoryCacheMode.None: - return NullCacheProvider.Instance; + return NoAppCache.Instance; default: throw new Exception("oops: cache mode."); } @@ -157,7 +157,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement /// /// Adds or Updates an entity of type TEntity /// - /// This method is backed by an cache + /// This method is backed by an cache /// public void Save(TEntity entity) { diff --git a/src/Umbraco.Core/Runtime/CoreRuntime.cs b/src/Umbraco.Core/Runtime/CoreRuntime.cs index f29109b9d2..e37b5e254e 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntime.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntime.cs @@ -332,10 +332,10 @@ namespace Umbraco.Core.Runtime // is overriden by the web runtime return new AppCaches( - new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()), - new StaticCacheProvider(), - NullCacheProvider.Instance, - new IsolatedRuntimeCache(type => new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()))); + new DeepCloneAppCache(new ObjectCacheAppCache()), + new DictionaryCacheProvider(), + NoAppCache.Instance, + new IsolatedCaches(type => new DeepCloneAppCache(new ObjectCacheAppCache()))); } // by default, returns null, meaning that Umbraco should auto-detect the application root path. diff --git a/src/Umbraco.Core/Scoping/IScope.cs b/src/Umbraco.Core/Scoping/IScope.cs index eefc964965..de4eef0a08 100644 --- a/src/Umbraco.Core/Scoping/IScope.cs +++ b/src/Umbraco.Core/Scoping/IScope.cs @@ -38,7 +38,7 @@ namespace Umbraco.Core.Scoping /// /// Gets the scope isolated cache. /// - IsolatedRuntimeCache IsolatedRuntimeCache { get; } + IsolatedCaches IsolatedCaches { get; } /// /// Completes the scope. diff --git a/src/Umbraco.Core/Scoping/Scope.cs b/src/Umbraco.Core/Scoping/Scope.cs index b8d4d7b430..aa08016d3c 100644 --- a/src/Umbraco.Core/Scoping/Scope.cs +++ b/src/Umbraco.Core/Scoping/Scope.cs @@ -34,7 +34,7 @@ namespace Umbraco.Core.Scoping private bool _disposed; private bool? _completed; - private IsolatedRuntimeCache _isolatedRuntimeCache; + private IsolatedCaches _isolatedCaches; private IUmbracoDatabase _database; private EventMessages _messages; private ICompletable _fscope; @@ -177,14 +177,14 @@ namespace Umbraco.Core.Scoping } /// - public IsolatedRuntimeCache IsolatedRuntimeCache + public IsolatedCaches IsolatedCaches { get { - if (ParentScope != null) return ParentScope.IsolatedRuntimeCache; + if (ParentScope != null) return ParentScope.IsolatedCaches; - return _isolatedRuntimeCache ?? (_isolatedRuntimeCache - = new IsolatedRuntimeCache(type => new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()))); + return _isolatedCaches ?? (_isolatedCaches + = new IsolatedCaches(type => new DeepCloneAppCache(new ObjectCacheAppCache()))); } } diff --git a/src/Umbraco.Core/Services/Implement/LocalizedTextServiceFileSources.cs b/src/Umbraco.Core/Services/Implement/LocalizedTextServiceFileSources.cs index 3b3f90a412..5577508adb 100644 --- a/src/Umbraco.Core/Services/Implement/LocalizedTextServiceFileSources.cs +++ b/src/Umbraco.Core/Services/Implement/LocalizedTextServiceFileSources.cs @@ -17,7 +17,7 @@ namespace Umbraco.Core.Services.Implement public class LocalizedTextServiceFileSources { private readonly ILogger _logger; - private readonly IRuntimeCacheProvider _cache; + private readonly IAppPolicedCache _cache; private readonly IEnumerable _supplementFileSources; private readonly DirectoryInfo _fileSourceFolder; @@ -37,7 +37,7 @@ namespace Umbraco.Core.Services.Implement /// public LocalizedTextServiceFileSources( ILogger logger, - IRuntimeCacheProvider cache, + IAppPolicedCache cache, DirectoryInfo fileSourceFolder, IEnumerable supplementFileSources) { @@ -140,7 +140,7 @@ namespace Umbraco.Core.Services.Implement /// /// /// - public LocalizedTextServiceFileSources(ILogger logger, IRuntimeCacheProvider cache, DirectoryInfo fileSourceFolder) + public LocalizedTextServiceFileSources(ILogger logger, IAppPolicedCache cache, DirectoryInfo fileSourceFolder) : this(logger, cache, fileSourceFolder, Enumerable.Empty()) { diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 79162c06ad..41f2bc4951 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -109,6 +109,7 @@ + @@ -118,29 +119,29 @@ - + - - + + - - - + + + - - + + - - + + - + diff --git a/src/Umbraco.Tests/Cache/CacheProviderTests.cs b/src/Umbraco.Tests/Cache/CacheProviderTests.cs index d060df3c56..f2288cbaf2 100644 --- a/src/Umbraco.Tests/Cache/CacheProviderTests.cs +++ b/src/Umbraco.Tests/Cache/CacheProviderTests.cs @@ -9,7 +9,7 @@ namespace Umbraco.Tests.Cache { public abstract class CacheProviderTests { - internal abstract ICacheProvider Provider { get; } + internal abstract IAppCache Provider { get; } protected abstract int GetTotalItemCount { get; } [SetUp] @@ -21,7 +21,7 @@ namespace Umbraco.Tests.Cache [TearDown] public virtual void TearDown() { - Provider.ClearAllCache(); + Provider.Clear(); } [Test] @@ -32,11 +32,11 @@ namespace Umbraco.Tests.Cache Assert.Ignore("Do not run for StaticCacheProvider."); Exception exception = null; - var result = Provider.GetCacheItem("blah", () => + var result = Provider.Get("blah", () => { try { - var result2 = Provider.GetCacheItem("blah"); + var result2 = Provider.Get("blah"); } catch (Exception e) { @@ -56,7 +56,7 @@ namespace Umbraco.Tests.Cache object result; try { - result = Provider.GetCacheItem("Blah", () => + result = Provider.Get("Blah", () => { counter++; throw new Exception("Do not cache this"); @@ -66,7 +66,7 @@ namespace Umbraco.Tests.Cache try { - result = Provider.GetCacheItem("Blah", () => + result = Provider.Get("Blah", () => { counter++; throw new Exception("Do not cache this"); @@ -85,13 +85,13 @@ namespace Umbraco.Tests.Cache object result; - result = Provider.GetCacheItem("Blah", () => + result = Provider.Get("Blah", () => { counter++; return ""; }); - result = Provider.GetCacheItem("Blah", () => + result = Provider.Get("Blah", () => { counter++; return ""; @@ -108,14 +108,14 @@ namespace Umbraco.Tests.Cache var cacheContent2 = new MacroCacheContent(new LiteralControl(), "Test2"); var cacheContent3 = new MacroCacheContent(new LiteralControl(), "Test3"); var cacheContent4 = new LiteralControl(); - Provider.GetCacheItem("Test1", () => cacheContent1); - Provider.GetCacheItem("Tester2", () => cacheContent2); - Provider.GetCacheItem("Tes3", () => cacheContent3); - Provider.GetCacheItem("different4", () => cacheContent4); + Provider.Get("Test1", () => cacheContent1); + Provider.Get("Tester2", () => cacheContent2); + Provider.Get("Tes3", () => cacheContent3); + Provider.Get("different4", () => cacheContent4); Assert.AreEqual(4, GetTotalItemCount); - var result = Provider.GetCacheItemsByKeySearch("Tes"); + var result = Provider.SearchByKey("Tes"); Assert.AreEqual(3, result.Count()); } @@ -127,14 +127,14 @@ namespace Umbraco.Tests.Cache var cacheContent2 = new MacroCacheContent(new LiteralControl(), "Test2"); var cacheContent3 = new MacroCacheContent(new LiteralControl(), "Test3"); var cacheContent4 = new LiteralControl(); - Provider.GetCacheItem("TTes1t", () => cacheContent1); - Provider.GetCacheItem("Tester2", () => cacheContent2); - Provider.GetCacheItem("Tes3", () => cacheContent3); - Provider.GetCacheItem("different4", () => cacheContent4); + Provider.Get("TTes1t", () => cacheContent1); + Provider.Get("Tester2", () => cacheContent2); + Provider.Get("Tes3", () => cacheContent3); + Provider.Get("different4", () => cacheContent4); Assert.AreEqual(4, GetTotalItemCount); - Provider.ClearCacheByKeyExpression("^\\w+es\\d.*"); + Provider.ClearByRegex("^\\w+es\\d.*"); Assert.AreEqual(2, GetTotalItemCount); } @@ -146,14 +146,14 @@ namespace Umbraco.Tests.Cache var cacheContent2 = new MacroCacheContent(new LiteralControl(), "Test2"); var cacheContent3 = new MacroCacheContent(new LiteralControl(), "Test3"); var cacheContent4 = new LiteralControl(); - Provider.GetCacheItem("Test1", () => cacheContent1); - Provider.GetCacheItem("Tester2", () => cacheContent2); - Provider.GetCacheItem("Tes3", () => cacheContent3); - Provider.GetCacheItem("different4", () => cacheContent4); + Provider.Get("Test1", () => cacheContent1); + Provider.Get("Tester2", () => cacheContent2); + Provider.Get("Tes3", () => cacheContent3); + Provider.Get("different4", () => cacheContent4); Assert.AreEqual(4, GetTotalItemCount); - Provider.ClearCacheByKeySearch("Test"); + Provider.ClearByKey("Test"); Assert.AreEqual(2, GetTotalItemCount); } @@ -165,15 +165,15 @@ namespace Umbraco.Tests.Cache var cacheContent2 = new MacroCacheContent(new LiteralControl(), "Test2"); var cacheContent3 = new MacroCacheContent(new LiteralControl(), "Test3"); var cacheContent4 = new LiteralControl(); - Provider.GetCacheItem("Test1", () => cacheContent1); - Provider.GetCacheItem("Test2", () => cacheContent2); - Provider.GetCacheItem("Test3", () => cacheContent3); - Provider.GetCacheItem("Test4", () => cacheContent4); + Provider.Get("Test1", () => cacheContent1); + Provider.Get("Test2", () => cacheContent2); + Provider.Get("Test3", () => cacheContent3); + Provider.Get("Test4", () => cacheContent4); Assert.AreEqual(4, GetTotalItemCount); - Provider.ClearCacheItem("Test1"); - Provider.ClearCacheItem("Test2"); + Provider.Clear("Test1"); + Provider.Clear("Test2"); Assert.AreEqual(2, GetTotalItemCount); } @@ -185,14 +185,14 @@ namespace Umbraco.Tests.Cache var cacheContent2 = new MacroCacheContent(new LiteralControl(), "Test2"); var cacheContent3 = new MacroCacheContent(new LiteralControl(), "Test3"); var cacheContent4 = new LiteralControl(); - Provider.GetCacheItem("Test1", () => cacheContent1); - Provider.GetCacheItem("Test2", () => cacheContent2); - Provider.GetCacheItem("Test3", () => cacheContent3); - Provider.GetCacheItem("Test4", () => cacheContent4); + Provider.Get("Test1", () => cacheContent1); + Provider.Get("Test2", () => cacheContent2); + Provider.Get("Test3", () => cacheContent3); + Provider.Get("Test4", () => cacheContent4); Assert.AreEqual(4, GetTotalItemCount); - Provider.ClearAllCache(); + Provider.Clear(); Assert.AreEqual(0, GetTotalItemCount); } @@ -201,7 +201,7 @@ namespace Umbraco.Tests.Cache public void Can_Add_When_Not_Available() { var cacheContent1 = new MacroCacheContent(new LiteralControl(), "Test1"); - Provider.GetCacheItem("Test1", () => cacheContent1); + Provider.Get("Test1", () => cacheContent1); Assert.AreEqual(1, GetTotalItemCount); } @@ -209,8 +209,8 @@ namespace Umbraco.Tests.Cache public void Can_Get_When_Available() { var cacheContent1 = new MacroCacheContent(new LiteralControl(), "Test1"); - var result = Provider.GetCacheItem("Test1", () => cacheContent1); - var result2 = Provider.GetCacheItem("Test1", () => cacheContent1); + var result = Provider.Get("Test1", () => cacheContent1); + var result2 = Provider.Get("Test1", () => cacheContent1); Assert.AreEqual(1, GetTotalItemCount); Assert.AreEqual(result, result2); } @@ -222,15 +222,15 @@ namespace Umbraco.Tests.Cache var cacheContent2 = new MacroCacheContent(new LiteralControl(), "Test2"); var cacheContent3 = new MacroCacheContent(new LiteralControl(), "Test3"); var cacheContent4 = new LiteralControl(); - Provider.GetCacheItem("Test1", () => cacheContent1); - Provider.GetCacheItem("Test2", () => cacheContent2); - Provider.GetCacheItem("Test3", () => cacheContent3); - Provider.GetCacheItem("Test4", () => cacheContent4); + Provider.Get("Test1", () => cacheContent1); + Provider.Get("Test2", () => cacheContent2); + Provider.Get("Test3", () => cacheContent3); + Provider.Get("Test4", () => cacheContent4); Assert.AreEqual(4, GetTotalItemCount); //Provider.ClearCacheObjectTypes("umbraco.MacroCacheContent"); - Provider.ClearCacheObjectTypes(typeof(MacroCacheContent).ToString()); + Provider.ClearOfType(typeof(MacroCacheContent).ToString()); Assert.AreEqual(1, GetTotalItemCount); } @@ -242,14 +242,14 @@ namespace Umbraco.Tests.Cache var cacheContent2 = new MacroCacheContent(new LiteralControl(), "Test2"); var cacheContent3 = new MacroCacheContent(new LiteralControl(), "Test3"); var cacheContent4 = new LiteralControl(); - Provider.GetCacheItem("Test1", () => cacheContent1); - Provider.GetCacheItem("Test2", () => cacheContent2); - Provider.GetCacheItem("Test3", () => cacheContent3); - Provider.GetCacheItem("Test4", () => cacheContent4); + Provider.Get("Test1", () => cacheContent1); + Provider.Get("Test2", () => cacheContent2); + Provider.Get("Test3", () => cacheContent3); + Provider.Get("Test4", () => cacheContent4); Assert.AreEqual(4, GetTotalItemCount); - Provider.ClearCacheObjectTypes(); + Provider.ClearOfType(); Assert.AreEqual(1, GetTotalItemCount); } diff --git a/src/Umbraco.Tests/Cache/DeepCloneRuntimeCacheProviderTests.cs b/src/Umbraco.Tests/Cache/DeepCloneRuntimeCacheProviderTests.cs index 169100153e..5158989a8b 100644 --- a/src/Umbraco.Tests/Cache/DeepCloneRuntimeCacheProviderTests.cs +++ b/src/Umbraco.Tests/Cache/DeepCloneRuntimeCacheProviderTests.cs @@ -16,7 +16,7 @@ namespace Umbraco.Tests.Cache [TestFixture] public class DeepCloneRuntimeCacheProviderTests : RuntimeCacheProviderTests { - private DeepCloneRuntimeCacheProvider _provider; + private DeepCloneAppCache _provider; protected override int GetTotalItemCount { @@ -26,15 +26,15 @@ namespace Umbraco.Tests.Cache public override void Setup() { base.Setup(); - _provider = new DeepCloneRuntimeCacheProvider(new HttpRuntimeCacheProvider(HttpRuntime.Cache)); + _provider = new DeepCloneAppCache(new WebCachingAppCache(HttpRuntime.Cache)); } - internal override ICacheProvider Provider + internal override IAppCache Provider { get { return _provider; } } - internal override IRuntimeCacheProvider RuntimeProvider + internal override IAppPolicedCache RuntimeProvider { get { return _provider; } } @@ -75,15 +75,15 @@ namespace Umbraco.Tests.Cache public void DoesNotCacheExceptions() { string value; - Assert.Throws(() => { value = (string)_provider.GetCacheItem("key", () => GetValue(1)); }); - Assert.Throws(() => { value = (string)_provider.GetCacheItem("key", () => GetValue(2)); }); + Assert.Throws(() => { value = (string)_provider.Get("key", () => GetValue(1)); }); + Assert.Throws(() => { value = (string)_provider.Get("key", () => GetValue(2)); }); // does not throw - value = (string)_provider.GetCacheItem("key", () => GetValue(3)); + value = (string)_provider.Get("key", () => GetValue(3)); Assert.AreEqual("succ3", value); // cache - value = (string)_provider.GetCacheItem("key", () => GetValue(4)); + value = (string)_provider.Get("key", () => GetValue(4)); Assert.AreEqual("succ3", value); } diff --git a/src/Umbraco.Tests/Cache/DefaultCachePolicyTests.cs b/src/Umbraco.Tests/Cache/DefaultCachePolicyTests.cs index 37488600c7..0f649328fe 100644 --- a/src/Umbraco.Tests/Cache/DefaultCachePolicyTests.cs +++ b/src/Umbraco.Tests/Cache/DefaultCachePolicyTests.cs @@ -28,8 +28,8 @@ namespace Umbraco.Tests.Cache public void Caches_Single() { var isCached = false; - var cache = new Mock(); - cache.Setup(x => x.InsertCacheItem(It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny(), + var cache = new Mock(); + cache.Setup(x => x.Insert(It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Callback(() => { @@ -45,8 +45,8 @@ namespace Umbraco.Tests.Cache [Test] public void Get_Single_From_Cache() { - var cache = new Mock(); - cache.Setup(x => x.GetCacheItem(It.IsAny())).Returns(new AuditItem(1, AuditType.Copy, 123, "test", "blah")); + var cache = new Mock(); + cache.Setup(x => x.Get(It.IsAny())).Returns(new AuditItem(1, AuditType.Copy, 123, "test", "blah")); var defaultPolicy = new DefaultRepositoryCachePolicy(cache.Object, DefaultAccessor, new RepositoryCachePolicyOptions()); @@ -58,14 +58,14 @@ namespace Umbraco.Tests.Cache public void Caches_Per_Id_For_Get_All() { var cached = new List(); - var cache = new Mock(); - cache.Setup(x => x.InsertCacheItem(It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny(), + var cache = new Mock(); + cache.Setup(x => x.Insert(It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Callback((string cacheKey, Func o, TimeSpan? t, bool b, CacheItemPriority cip, CacheItemRemovedCallback circ, string[] s) => { cached.Add(cacheKey); }); - cache.Setup(x => x.GetCacheItemsByKeySearch(It.IsAny())).Returns(new AuditItem[] {}); + cache.Setup(x => x.SearchByKey(It.IsAny())).Returns(new AuditItem[] {}); var defaultPolicy = new DefaultRepositoryCachePolicy(cache.Object, DefaultAccessor, new RepositoryCachePolicyOptions()); @@ -81,8 +81,8 @@ namespace Umbraco.Tests.Cache [Test] public void Get_All_Without_Ids_From_Cache() { - var cache = new Mock(); - cache.Setup(x => x.GetCacheItemsByKeySearch(It.IsAny())).Returns(new[] + var cache = new Mock(); + cache.Setup(x => x.SearchByKey(It.IsAny())).Returns(new[] { new AuditItem(1, AuditType.Copy, 123, "test", "blah"), new AuditItem(2, AuditType.Copy, 123, "test", "blah2") @@ -98,8 +98,8 @@ namespace Umbraco.Tests.Cache public void If_CreateOrUpdate_Throws_Cache_Is_Removed() { var cacheCleared = false; - var cache = new Mock(); - cache.Setup(x => x.ClearCacheItem(It.IsAny())) + var cache = new Mock(); + cache.Setup(x => x.Clear(It.IsAny())) .Callback(() => { cacheCleared = true; @@ -124,8 +124,8 @@ namespace Umbraco.Tests.Cache public void If_Removes_Throws_Cache_Is_Removed() { var cacheCleared = false; - var cache = new Mock(); - cache.Setup(x => x.ClearCacheItem(It.IsAny())) + var cache = new Mock(); + cache.Setup(x => x.Clear(It.IsAny())) .Callback(() => { cacheCleared = true; diff --git a/src/Umbraco.Tests/Cache/FullDataSetCachePolicyTests.cs b/src/Umbraco.Tests/Cache/FullDataSetCachePolicyTests.cs index 404587bcfa..7c5a1524d2 100644 --- a/src/Umbraco.Tests/Cache/FullDataSetCachePolicyTests.cs +++ b/src/Umbraco.Tests/Cache/FullDataSetCachePolicyTests.cs @@ -37,8 +37,8 @@ namespace Umbraco.Tests.Cache }; var isCached = false; - var cache = new Mock(); - cache.Setup(x => x.InsertCacheItem(It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny(), + var cache = new Mock(); + cache.Setup(x => x.Insert(It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Callback(() => { @@ -60,8 +60,8 @@ namespace Umbraco.Tests.Cache new AuditItem(2, AuditType.Copy, 123, "test", "blah2") }; - var cache = new Mock(); - cache.Setup(x => x.GetCacheItem(It.IsAny())).Returns(new AuditItem(1, AuditType.Copy, 123, "test", "blah")); + var cache = new Mock(); + cache.Setup(x => x.Get(It.IsAny())).Returns(new AuditItem(1, AuditType.Copy, 123, "test", "blah")); var defaultPolicy = new FullDataSetRepositoryCachePolicy(cache.Object, DefaultAccessor, item => item.Id, false); @@ -78,8 +78,8 @@ namespace Umbraco.Tests.Cache IList list = null; - var cache = new Mock(); - cache.Setup(x => x.InsertCacheItem(It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny(), + var cache = new Mock(); + cache.Setup(x => x.Insert(It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Callback((string cacheKey, Func o, TimeSpan? t, bool b, CacheItemPriority cip, CacheItemRemovedCallback circ, string[] s) => { @@ -87,7 +87,7 @@ namespace Umbraco.Tests.Cache list = o() as IList; }); - cache.Setup(x => x.GetCacheItem(It.IsAny())).Returns(() => + cache.Setup(x => x.Get(It.IsAny())).Returns(() => { //return null if this is the first pass return cached.Any() ? new DeepCloneableList(ListCloneBehavior.CloneOnce) : null; @@ -121,8 +121,8 @@ namespace Umbraco.Tests.Cache var cached = new List(); IList list = null; - var cache = new Mock(); - cache.Setup(x => x.InsertCacheItem(It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny(), + var cache = new Mock(); + cache.Setup(x => x.Insert(It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Callback((string cacheKey, Func o, TimeSpan? t, bool b, CacheItemPriority cip, CacheItemRemovedCallback circ, string[] s) => { @@ -130,7 +130,7 @@ namespace Umbraco.Tests.Cache list = o() as IList; }); - cache.Setup(x => x.GetCacheItem(It.IsAny())).Returns(new AuditItem[] { }); + cache.Setup(x => x.Get(It.IsAny())).Returns(new AuditItem[] { }); var defaultPolicy = new FullDataSetRepositoryCachePolicy(cache.Object, DefaultAccessor, item => item.Id, false); @@ -145,9 +145,9 @@ namespace Umbraco.Tests.Cache { var getAll = new[] { (AuditItem)null }; - var cache = new Mock(); + var cache = new Mock(); - cache.Setup(x => x.GetCacheItem(It.IsAny())).Returns(() => new DeepCloneableList(ListCloneBehavior.CloneOnce) + cache.Setup(x => x.Get(It.IsAny())).Returns(() => new DeepCloneableList(ListCloneBehavior.CloneOnce) { new AuditItem(1, AuditType.Copy, 123, "test", "blah"), new AuditItem(2, AuditType.Copy, 123, "test", "blah2") @@ -169,8 +169,8 @@ namespace Umbraco.Tests.Cache }; var cacheCleared = false; - var cache = new Mock(); - cache.Setup(x => x.ClearCacheItem(It.IsAny())) + var cache = new Mock(); + cache.Setup(x => x.Clear(It.IsAny())) .Callback(() => { cacheCleared = true; @@ -201,8 +201,8 @@ namespace Umbraco.Tests.Cache }; var cacheCleared = false; - var cache = new Mock(); - cache.Setup(x => x.ClearCacheItem(It.IsAny())) + var cache = new Mock(); + cache.Setup(x => x.Clear(It.IsAny())) .Callback(() => { cacheCleared = true; diff --git a/src/Umbraco.Tests/Cache/HttpRequestCacheProviderTests.cs b/src/Umbraco.Tests/Cache/HttpRequestCacheProviderTests.cs index cbb8d4e49d..f442319d7f 100644 --- a/src/Umbraco.Tests/Cache/HttpRequestCacheProviderTests.cs +++ b/src/Umbraco.Tests/Cache/HttpRequestCacheProviderTests.cs @@ -7,17 +7,17 @@ namespace Umbraco.Tests.Cache [TestFixture] public class HttpRequestCacheProviderTests : CacheProviderTests { - private HttpRequestCacheProvider _provider; + private HttpRequestAppCache _provider; private FakeHttpContextFactory _ctx; public override void Setup() { base.Setup(); _ctx = new FakeHttpContextFactory("http://localhost/test"); - _provider = new HttpRequestCacheProvider(_ctx.HttpContext); + _provider = new HttpRequestAppCache(_ctx.HttpContext); } - internal override ICacheProvider Provider + internal override IAppCache Provider { get { return _provider; } } @@ -31,22 +31,22 @@ namespace Umbraco.Tests.Cache [TestFixture] public class StaticCacheProviderTests : CacheProviderTests { - private StaticCacheProvider _provider; + private DictionaryCacheProvider _provider; public override void Setup() { base.Setup(); - _provider = new StaticCacheProvider(); + _provider = new DictionaryCacheProvider(); } - internal override ICacheProvider Provider + internal override IAppCache Provider { get { return _provider; } } protected override int GetTotalItemCount { - get { return _provider.StaticCache.Count; } + get { return _provider.Items.Count; } } } } diff --git a/src/Umbraco.Tests/Cache/HttpRuntimeCacheProviderTests.cs b/src/Umbraco.Tests/Cache/HttpRuntimeCacheProviderTests.cs index 679b8c5125..56f3303e9c 100644 --- a/src/Umbraco.Tests/Cache/HttpRuntimeCacheProviderTests.cs +++ b/src/Umbraco.Tests/Cache/HttpRuntimeCacheProviderTests.cs @@ -9,7 +9,7 @@ namespace Umbraco.Tests.Cache [TestFixture] public class HttpRuntimeCacheProviderTests : RuntimeCacheProviderTests { - private HttpRuntimeCacheProvider _provider; + private WebCachingAppCache _provider; protected override int GetTotalItemCount { @@ -19,15 +19,15 @@ namespace Umbraco.Tests.Cache public override void Setup() { base.Setup(); - _provider = new HttpRuntimeCacheProvider(HttpRuntime.Cache); + _provider = new WebCachingAppCache(HttpRuntime.Cache); } - internal override ICacheProvider Provider + internal override IAppCache Provider { get { return _provider; } } - internal override IRuntimeCacheProvider RuntimeProvider + internal override IAppPolicedCache RuntimeProvider { get { return _provider; } } @@ -36,15 +36,15 @@ namespace Umbraco.Tests.Cache public void DoesNotCacheExceptions() { string value; - Assert.Throws(() => { value = (string)_provider.GetCacheItem("key", () => GetValue(1)); }); - Assert.Throws(() => { value = (string)_provider.GetCacheItem("key", () => GetValue(2)); }); + Assert.Throws(() => { value = (string)_provider.Get("key", () => GetValue(1)); }); + Assert.Throws(() => { value = (string)_provider.Get("key", () => GetValue(2)); }); // does not throw - value = (string)_provider.GetCacheItem("key", () => GetValue(3)); + value = (string)_provider.Get("key", () => GetValue(3)); Assert.AreEqual("succ3", value); // cache - value = (string)_provider.GetCacheItem("key", () => GetValue(4)); + value = (string)_provider.Get("key", () => GetValue(4)); Assert.AreEqual("succ3", value); } diff --git a/src/Umbraco.Tests/Cache/ObjectCacheProviderTests.cs b/src/Umbraco.Tests/Cache/ObjectCacheProviderTests.cs index e373fdda4d..6ed7f590e0 100644 --- a/src/Umbraco.Tests/Cache/ObjectCacheProviderTests.cs +++ b/src/Umbraco.Tests/Cache/ObjectCacheProviderTests.cs @@ -10,7 +10,7 @@ namespace Umbraco.Tests.Cache [TestFixture] public class ObjectCacheProviderTests : RuntimeCacheProviderTests { - private ObjectCacheRuntimeCacheProvider _provider; + private ObjectCacheAppCache _provider; protected override int GetTotalItemCount { @@ -20,15 +20,15 @@ namespace Umbraco.Tests.Cache public override void Setup() { base.Setup(); - _provider = new ObjectCacheRuntimeCacheProvider(); + _provider = new ObjectCacheAppCache(); } - internal override ICacheProvider Provider + internal override IAppCache Provider { get { return _provider; } } - internal override IRuntimeCacheProvider RuntimeProvider + internal override IAppPolicedCache RuntimeProvider { get { return _provider; } } diff --git a/src/Umbraco.Tests/Cache/PublishedCache/PublishedContentCacheTests.cs b/src/Umbraco.Tests/Cache/PublishedCache/PublishedContentCacheTests.cs index 12ea87087d..79d0dfb9da 100644 --- a/src/Umbraco.Tests/Cache/PublishedCache/PublishedContentCacheTests.cs +++ b/src/Umbraco.Tests/Cache/PublishedCache/PublishedContentCacheTests.cs @@ -63,7 +63,7 @@ namespace Umbraco.Tests.Cache.PublishedCache _xml = new XmlDocument(); _xml.LoadXml(GetXml()); var xmlStore = new XmlStore(() => _xml, null, null, null); - var cacheProvider = new StaticCacheProvider(); + var cacheProvider = new DictionaryCacheProvider(); var domainCache = new DomainCache(ServiceContext.DomainService, DefaultCultureAccessor); var publishedShapshot = new Umbraco.Web.PublishedCache.XmlPublishedCache.PublishedSnapshot( new PublishedContentCache(xmlStore, domainCache, cacheProvider, globalSettings, new SiteDomainHelper(), ContentTypesCache, null, null), diff --git a/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs b/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs index 6add88009d..ee16a1dede 100644 --- a/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs +++ b/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs @@ -75,7 +75,7 @@ namespace Umbraco.Tests.Cache.PublishedCache var mChild2 = MakeNewMedia("Child2", mType, user, mRoot2.Id); var ctx = GetUmbracoContext("/test"); - var cache = new PublishedMediaCache(new XmlStore((XmlDocument) null, null, null, null), ServiceContext.MediaService, ServiceContext.UserService, new StaticCacheProvider(), ContentTypesCache, Factory.GetInstance()); + var cache = new PublishedMediaCache(new XmlStore((XmlDocument) null, null, null, null), ServiceContext.MediaService, ServiceContext.UserService, new DictionaryCacheProvider(), ContentTypesCache, Factory.GetInstance()); var roots = cache.GetAtRoot(); Assert.AreEqual(2, roots.Count()); Assert.IsTrue(roots.Select(x => x.Id).ContainsAll(new[] {mRoot1.Id, mRoot2.Id})); @@ -93,7 +93,7 @@ namespace Umbraco.Tests.Cache.PublishedCache //var publishedMedia = PublishedMediaTests.GetNode(mRoot.Id, GetUmbracoContext("/test", 1234)); var umbracoContext = GetUmbracoContext("/test"); - var cache = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), Current.Services.MediaService, Current.Services.UserService, new StaticCacheProvider(), ContentTypesCache, Factory.GetInstance()); + var cache = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), Current.Services.MediaService, Current.Services.UserService, new DictionaryCacheProvider(), ContentTypesCache, Factory.GetInstance()); var publishedMedia = cache.GetById(mRoot.Id); Assert.IsNotNull(publishedMedia); @@ -204,7 +204,7 @@ namespace Umbraco.Tests.Cache.PublishedCache var result = new SearchResult("1234", 1, () => fields.ToDictionary(x => x.Key, x => new List { x.Value })); - var store = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), ServiceContext.MediaService, ServiceContext.UserService, new StaticCacheProvider(), ContentTypesCache, Factory.GetInstance()); + var store = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), ServiceContext.MediaService, ServiceContext.UserService, new DictionaryCacheProvider(), ContentTypesCache, Factory.GetInstance()); var doc = store.CreateFromCacheValues(store.ConvertFromSearchResult(result)); DoAssert(doc, 1234, key, templateIdVal: null, 0, "/media/test.jpg", "Image", 23, "Shannon", "Shannon", 0, 0, "-1,1234", DateTime.Parse("2012-07-17T10:34:09"), DateTime.Parse("2012-07-16T10:34:09"), 2); @@ -220,7 +220,7 @@ namespace Umbraco.Tests.Cache.PublishedCache var xmlDoc = GetMediaXml(); ((XmlElement)xmlDoc.DocumentElement.FirstChild).SetAttribute("key", key.ToString()); var navigator = xmlDoc.SelectSingleNode("/root/Image").CreateNavigator(); - var cache = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), ServiceContext.MediaService, ServiceContext.UserService, new StaticCacheProvider(), ContentTypesCache, Factory.GetInstance()); + var cache = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), ServiceContext.MediaService, ServiceContext.UserService, new DictionaryCacheProvider(), ContentTypesCache, Factory.GetInstance()); var doc = cache.CreateFromCacheValues(cache.ConvertFromXPathNavigator(navigator, true)); DoAssert(doc, 2000, key, templateIdVal: null, 2, "image1", "Image", 23, "Shannon", "Shannon", 33, 33, "-1,2000", DateTime.Parse("2012-06-12T14:13:17"), DateTime.Parse("2012-07-20T18:50:43"), 1); diff --git a/src/Umbraco.Tests/Cache/RuntimeCacheProviderTests.cs b/src/Umbraco.Tests/Cache/RuntimeCacheProviderTests.cs index e45dfd4250..08eb5e9a60 100644 --- a/src/Umbraco.Tests/Cache/RuntimeCacheProviderTests.cs +++ b/src/Umbraco.Tests/Cache/RuntimeCacheProviderTests.cs @@ -8,7 +8,7 @@ namespace Umbraco.Tests.Cache public abstract class RuntimeCacheProviderTests : CacheProviderTests { - internal abstract IRuntimeCacheProvider RuntimeProvider { get; } + internal abstract IAppPolicedCache RuntimeProvider { get; } [Test] @@ -16,7 +16,7 @@ namespace Umbraco.Tests.Cache public void Can_Add_And_Expire_Struct_Strongly_Typed_With_Null() { var now = DateTime.Now; - RuntimeProvider.InsertCacheItem("DateTimeTest", () => now, new TimeSpan(0, 0, 0, 0, 200)); + RuntimeProvider.Insert("DateTimeTest", () => now, new TimeSpan(0, 0, 0, 0, 200)); Assert.AreEqual(now, Provider.GetCacheItem("DateTimeTest")); Assert.AreEqual(now, Provider.GetCacheItem("DateTimeTest")); diff --git a/src/Umbraco.Tests/Cache/SingleItemsOnlyCachePolicyTests.cs b/src/Umbraco.Tests/Cache/SingleItemsOnlyCachePolicyTests.cs index 1c2227f79b..2b37d85801 100644 --- a/src/Umbraco.Tests/Cache/SingleItemsOnlyCachePolicyTests.cs +++ b/src/Umbraco.Tests/Cache/SingleItemsOnlyCachePolicyTests.cs @@ -28,14 +28,14 @@ namespace Umbraco.Tests.Cache public void Get_All_Doesnt_Cache() { var cached = new List(); - var cache = new Mock(); - cache.Setup(x => x.InsertCacheItem(It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny(), + var cache = new Mock(); + cache.Setup(x => x.Insert(It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Callback((string cacheKey, Func o, TimeSpan? t, bool b, CacheItemPriority cip, CacheItemRemovedCallback circ, string[] s) => { cached.Add(cacheKey); }); - cache.Setup(x => x.GetCacheItemsByKeySearch(It.IsAny())).Returns(new AuditItem[] { }); + cache.Setup(x => x.SearchByKey(It.IsAny())).Returns(new AuditItem[] { }); var defaultPolicy = new SingleItemsOnlyRepositoryCachePolicy(cache.Object, DefaultAccessor, new RepositoryCachePolicyOptions()); @@ -52,8 +52,8 @@ namespace Umbraco.Tests.Cache public void Caches_Single() { var isCached = false; - var cache = new Mock(); - cache.Setup(x => x.InsertCacheItem(It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny(), + var cache = new Mock(); + cache.Setup(x => x.Insert(It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Callback(() => { diff --git a/src/Umbraco.Tests/Composing/ComposingTestBase.cs b/src/Umbraco.Tests/Composing/ComposingTestBase.cs index 48850afd97..407d953509 100644 --- a/src/Umbraco.Tests/Composing/ComposingTestBase.cs +++ b/src/Umbraco.Tests/Composing/ComposingTestBase.cs @@ -21,7 +21,7 @@ namespace Umbraco.Tests.Composing { ProfilingLogger = new ProfilingLogger(Mock.Of(), Mock.Of()); - TypeLoader = new TypeLoader(NullCacheProvider.Instance, LocalTempStorage.Default, ProfilingLogger, detectChanges: false) + TypeLoader = new TypeLoader(NoAppCache.Instance, LocalTempStorage.Default, ProfilingLogger, detectChanges: false) { AssembliesToScan = AssembliesToScan }; diff --git a/src/Umbraco.Tests/Composing/TypeLoaderTests.cs b/src/Umbraco.Tests/Composing/TypeLoaderTests.cs index 1649f3675d..add3424599 100644 --- a/src/Umbraco.Tests/Composing/TypeLoaderTests.cs +++ b/src/Umbraco.Tests/Composing/TypeLoaderTests.cs @@ -28,7 +28,7 @@ namespace Umbraco.Tests.Composing public void Initialize() { // this ensures it's reset - _typeLoader = new TypeLoader(NullCacheProvider.Instance, LocalTempStorage.Default, new ProfilingLogger(Mock.Of(), Mock.Of())); + _typeLoader = new TypeLoader(NoAppCache.Instance, LocalTempStorage.Default, new ProfilingLogger(Mock.Of(), Mock.Of())); foreach (var file in Directory.GetFiles(IOHelper.MapPath(SystemDirectories.TempData.EnsureEndsWith('/') + "TypesCache"))) File.Delete(file); diff --git a/src/Umbraco.Tests/CoreThings/UdiTests.cs b/src/Umbraco.Tests/CoreThings/UdiTests.cs index 2b4ace8810..35080e8c24 100644 --- a/src/Umbraco.Tests/CoreThings/UdiTests.cs +++ b/src/Umbraco.Tests/CoreThings/UdiTests.cs @@ -26,7 +26,7 @@ namespace Umbraco.Tests.CoreThings var container = new Mock(); var globalSettings = SettingsForTests.GenerateMockGlobalSettings(); container.Setup(x => x.GetInstance(typeof(TypeLoader))).Returns( - new TypeLoader(NullCacheProvider.Instance, LocalTempStorage.Default, new ProfilingLogger(Mock.Of(), Mock.Of()))); + new TypeLoader(NoAppCache.Instance, LocalTempStorage.Default, new ProfilingLogger(Mock.Of(), Mock.Of()))); Current.Factory = container.Object; Udi.ResetUdiTypes(); diff --git a/src/Umbraco.Tests/FrontEnd/UmbracoHelperTests.cs b/src/Umbraco.Tests/FrontEnd/UmbracoHelperTests.cs index 7508395c64..088ef6b54b 100644 --- a/src/Umbraco.Tests/FrontEnd/UmbracoHelperTests.cs +++ b/src/Umbraco.Tests/FrontEnd/UmbracoHelperTests.cs @@ -413,7 +413,7 @@ namespace Umbraco.Tests.FrontEnd container .Setup(x => x.GetInstance(typeof(TypeLoader))) .Returns(new TypeLoader( - NullCacheProvider.Instance, + NoAppCache.Instance, LocalTempStorage.Default, new ProfilingLogger(Mock.Of(), Mock.Of()) ) diff --git a/src/Umbraco.Tests/Macros/MacroTests.cs b/src/Umbraco.Tests/Macros/MacroTests.cs index 23e198b778..225bd17618 100644 --- a/src/Umbraco.Tests/Macros/MacroTests.cs +++ b/src/Umbraco.Tests/Macros/MacroTests.cs @@ -22,10 +22,10 @@ namespace Umbraco.Tests.Macros { //we DO want cache enabled for these tests var cacheHelper = new AppCaches( - new ObjectCacheRuntimeCacheProvider(), - new StaticCacheProvider(), - NullCacheProvider.Instance, - new IsolatedRuntimeCache(type => new ObjectCacheRuntimeCacheProvider())); + new ObjectCacheAppCache(), + new DictionaryCacheProvider(), + NoAppCache.Instance, + new IsolatedCaches(type => new ObjectCacheAppCache())); //Current.ApplicationContext = new ApplicationContext(cacheHelper, new ProfilingLogger(Mock.Of(), Mock.Of())); Current.Reset(); diff --git a/src/Umbraco.Tests/Manifest/ManifestParserTests.cs b/src/Umbraco.Tests/Manifest/ManifestParserTests.cs index ce3d1d705c..74f9fd7157 100644 --- a/src/Umbraco.Tests/Manifest/ManifestParserTests.cs +++ b/src/Umbraco.Tests/Manifest/ManifestParserTests.cs @@ -44,7 +44,7 @@ namespace Umbraco.Tests.Manifest new RequiredValidator(Mock.Of()), new RegexValidator(Mock.Of(), null) }; - _parser = new ManifestParser(NullCacheProvider.Instance, new ManifestValueValidatorCollection(validators), Mock.Of()); + _parser = new ManifestParser(NoAppCache.Instance, new ManifestValueValidatorCollection(validators), Mock.Of()); } [Test] diff --git a/src/Umbraco.Tests/Models/ContentTests.cs b/src/Umbraco.Tests/Models/ContentTests.cs index ea5614fb85..14f766fba1 100644 --- a/src/Umbraco.Tests/Models/ContentTests.cs +++ b/src/Umbraco.Tests/Models/ContentTests.cs @@ -232,8 +232,8 @@ namespace Umbraco.Tests.Models content.UpdateDate = DateTime.Now; content.WriterId = 23; - var runtimeCache = new ObjectCacheRuntimeCacheProvider(); - runtimeCache.InsertCacheItem(content.Id.ToString(CultureInfo.InvariantCulture), () => content); + var runtimeCache = new ObjectCacheAppCache(); + runtimeCache.Insert(content.Id.ToString(CultureInfo.InvariantCulture), () => content); var proflog = GetTestProfilingLogger(); @@ -241,7 +241,7 @@ namespace Umbraco.Tests.Models { for (int j = 0; j < 1000; j++) { - var clone = runtimeCache.GetCacheItem(content.Id.ToString(CultureInfo.InvariantCulture)); + var clone = runtimeCache.Get(content.Id.ToString(CultureInfo.InvariantCulture)); } } diff --git a/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs index 772147f5ad..1641631f43 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs @@ -76,10 +76,10 @@ namespace Umbraco.Tests.Persistence.Repositories public void CacheActiveForIntsAndGuids() { var realCache = new AppCaches( - new ObjectCacheRuntimeCacheProvider(), - new StaticCacheProvider(), - new StaticCacheProvider(), - new IsolatedRuntimeCache(t => new ObjectCacheRuntimeCacheProvider())); + new ObjectCacheAppCache(), + new DictionaryCacheProvider(), + new DictionaryCacheProvider(), + new IsolatedCaches(t => new ObjectCacheAppCache())); var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) diff --git a/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs index 5e1900b29e..33c8524bb4 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs @@ -47,10 +47,10 @@ namespace Umbraco.Tests.Persistence.Repositories MediaTypeRepository mediaTypeRepository; var realCache = new AppCaches( - new ObjectCacheRuntimeCacheProvider(), - new StaticCacheProvider(), - new StaticCacheProvider(), - new IsolatedRuntimeCache(t => new ObjectCacheRuntimeCacheProvider())); + new ObjectCacheAppCache(), + new DictionaryCacheProvider(), + new DictionaryCacheProvider(), + new IsolatedCaches(t => new ObjectCacheAppCache())); var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) diff --git a/src/Umbraco.Tests/Published/PropertyCacheLevelTests.cs b/src/Umbraco.Tests/Published/PropertyCacheLevelTests.cs index 33a595626e..04444855fb 100644 --- a/src/Umbraco.Tests/Published/PropertyCacheLevelTests.cs +++ b/src/Umbraco.Tests/Published/PropertyCacheLevelTests.cs @@ -118,8 +118,8 @@ namespace Umbraco.Tests.Published publishedContentTypeFactory.CreatePropertyType("prop1", 1), }); - var elementsCache = new DictionaryCacheProvider(); - var snapshotCache = new DictionaryCacheProvider(); + var elementsCache = new FastDictionaryCacheProvider(); + var snapshotCache = new FastDictionaryCacheProvider(); var publishedSnapshot = new Mock(); publishedSnapshot.Setup(x => x.SnapshotCache).Returns(snapshotCache); diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs index 6b280832da..5b1dcde728 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs @@ -40,7 +40,7 @@ namespace Umbraco.Tests.PublishedContent Composition.RegisterUnique(f => new PublishedModelFactory(f.GetInstance().GetTypes())); } - protected override TypeLoader CreateTypeLoader(IRuntimeCacheProvider runtimeCache, IGlobalSettings globalSettings, IProfilingLogger logger) + protected override TypeLoader CreateTypeLoader(IAppPolicedCache runtimeCache, IGlobalSettings globalSettings, IProfilingLogger logger) { var pluginManager = base.CreateTypeLoader(runtimeCache, globalSettings, logger); diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs index 603464e18b..e798be82c4 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs @@ -74,7 +74,7 @@ namespace Umbraco.Tests.PublishedContent ContentTypesCache.GetPublishedContentTypeByAlias = alias => alias.InvariantEquals("home") ? homeType : anythingType; } - protected override TypeLoader CreateTypeLoader(IRuntimeCacheProvider runtimeCache, IGlobalSettings globalSettings, IProfilingLogger logger) + protected override TypeLoader CreateTypeLoader(IAppPolicedCache runtimeCache, IGlobalSettings globalSettings, IProfilingLogger logger) { var pluginManager = base.CreateTypeLoader(runtimeCache, globalSettings, logger); diff --git a/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs index 4f55b4fd71..4257e3dabb 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs @@ -68,7 +68,7 @@ namespace Umbraco.Tests.PublishedContent internal IPublishedContent GetNode(int id, UmbracoContext umbracoContext) { var cache = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), - ServiceContext.MediaService, ServiceContext.UserService, new StaticCacheProvider(), ContentTypesCache, + ServiceContext.MediaService, ServiceContext.UserService, new DictionaryCacheProvider(), ContentTypesCache, Factory.GetInstance()); var doc = cache.GetById(id); Assert.IsNotNull(doc); @@ -126,7 +126,7 @@ namespace Umbraco.Tests.PublishedContent var searcher = indexer.GetSearcher(); var ctx = GetUmbracoContext("/test"); - var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new StaticCacheProvider(), ContentTypesCache, Factory.GetInstance()); + var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryCacheProvider(), ContentTypesCache, Factory.GetInstance()); //we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace var publishedMedia = cache.GetById(1111); @@ -156,7 +156,7 @@ namespace Umbraco.Tests.PublishedContent var searcher = indexer.GetSearcher(); var ctx = GetUmbracoContext("/test"); - var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new StaticCacheProvider(), ContentTypesCache, Factory.GetInstance()); + var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryCacheProvider(), ContentTypesCache, Factory.GetInstance()); //ensure it is found var publishedMedia = cache.GetById(3113); @@ -203,7 +203,7 @@ namespace Umbraco.Tests.PublishedContent var searcher = indexer.GetSearcher(); var ctx = GetUmbracoContext("/test"); - var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new StaticCacheProvider(), ContentTypesCache, Factory.GetInstance()); + var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryCacheProvider(), ContentTypesCache, Factory.GetInstance()); //we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace var publishedMedia = cache.GetById(1111); @@ -231,7 +231,7 @@ namespace Umbraco.Tests.PublishedContent var searcher = indexer.GetSearcher(); var ctx = GetUmbracoContext("/test"); - var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new StaticCacheProvider(), ContentTypesCache, Factory.GetInstance()); + var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryCacheProvider(), ContentTypesCache, Factory.GetInstance()); //we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace var publishedMedia = cache.GetById(1111); @@ -259,7 +259,7 @@ namespace Umbraco.Tests.PublishedContent var searcher = indexer.GetSearcher(); var ctx = GetUmbracoContext("/test"); - var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new StaticCacheProvider(), ContentTypesCache, Factory.GetInstance()); + var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryCacheProvider(), ContentTypesCache, Factory.GetInstance()); //we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace var publishedMedia = cache.GetById(1111); @@ -288,7 +288,7 @@ namespace Umbraco.Tests.PublishedContent var ctx = GetUmbracoContext("/test"); var searcher = indexer.GetSearcher(); - var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new StaticCacheProvider(), ContentTypesCache, Factory.GetInstance()); + var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryCacheProvider(), ContentTypesCache, Factory.GetInstance()); //we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace var publishedMedia = cache.GetById(3113); @@ -314,7 +314,7 @@ namespace Umbraco.Tests.PublishedContent var ctx = GetUmbracoContext("/test"); var searcher = indexer.GetSearcher(); - var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new StaticCacheProvider(), ContentTypesCache, Factory.GetInstance()); + var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryCacheProvider(), ContentTypesCache, Factory.GetInstance()); //we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace var publishedMedia = cache.GetById(3113); @@ -482,7 +482,7 @@ namespace Umbraco.Tests.PublishedContent "); var node = xml.DescendantsAndSelf("Image").Single(x => (int)x.Attribute("id") == nodeId); - var publishedMedia = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), ServiceContext.MediaService, ServiceContext.UserService, new StaticCacheProvider(), ContentTypesCache, Factory.GetInstance()); + var publishedMedia = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), ServiceContext.MediaService, ServiceContext.UserService, new DictionaryCacheProvider(), ContentTypesCache, Factory.GetInstance()); var nav = node.CreateNavigator(); @@ -502,7 +502,7 @@ namespace Umbraco.Tests.PublishedContent var errorXml = new XElement("error", string.Format("No media is maching '{0}'", 1234)); var nav = errorXml.CreateNavigator(); - var publishedMedia = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), ServiceContext.MediaService, ServiceContext.UserService, new StaticCacheProvider(), ContentTypesCache, Factory.GetInstance()); + var publishedMedia = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), ServiceContext.MediaService, ServiceContext.UserService, new DictionaryCacheProvider(), ContentTypesCache, Factory.GetInstance()); var converted = publishedMedia.ConvertFromXPathNodeIterator(nav.Select("/"), 1234); Assert.IsNull(converted); diff --git a/src/Umbraco.Tests/PublishedContent/SolidPublishedSnapshot.cs b/src/Umbraco.Tests/PublishedContent/SolidPublishedSnapshot.cs index deaecf821e..f7077ecb3a 100644 --- a/src/Umbraco.Tests/PublishedContent/SolidPublishedSnapshot.cs +++ b/src/Umbraco.Tests/PublishedContent/SolidPublishedSnapshot.cs @@ -36,9 +36,9 @@ namespace Umbraco.Tests.PublishedContent public void Resync() { } - public ICacheProvider SnapshotCache => null; + public IAppCache SnapshotCache => null; - public ICacheProvider ElementsCache => null; + public IAppCache ElementsCache => null; } class SolidPublishedContentCache : PublishedCacheBase, IPublishedContentCache, IPublishedMediaCache diff --git a/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs b/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs index 5d4fa4f182..6e01de1670 100644 --- a/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs @@ -41,10 +41,10 @@ namespace Umbraco.Tests.Scoping { // this is what's created core web runtime return new AppCaches( - new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()), - new StaticCacheProvider(), - NullCacheProvider.Instance, - new IsolatedRuntimeCache(type => new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()))); + new DeepCloneAppCache(new ObjectCacheAppCache()), + new DictionaryCacheProvider(), + NoAppCache.Instance, + new IsolatedCaches(type => new DeepCloneAppCache(new ObjectCacheAppCache()))); } [TearDown] @@ -60,13 +60,13 @@ namespace Umbraco.Tests.Scoping { var scopeProvider = ScopeProvider; var service = Current.Services.UserService; - var globalCache = Current.ApplicationCache.IsolatedRuntimeCache.GetOrCreateCache(typeof(IUser)); + var globalCache = Current.ApplicationCache.IsolatedCaches.GetOrCreate(typeof(IUser)); var user = (IUser)new User("name", "email", "username", "rawPassword"); service.Save(user); // global cache contains the entity - var globalCached = (IUser) globalCache.GetCacheItem(GetCacheIdKey(user.Id), () => null); + var globalCached = (IUser) globalCache.Get(GetCacheIdKey(user.Id), () => null); Assert.IsNotNull(globalCached); Assert.AreEqual(user.Id, globalCached.Id); Assert.AreEqual("name", globalCached.Name); @@ -85,20 +85,20 @@ namespace Umbraco.Tests.Scoping Assert.AreSame(scope, scopeProvider.AmbientScope); // scope has its own isolated cache - var scopedCache = scope.IsolatedRuntimeCache.GetOrCreateCache(typeof (IUser)); + var scopedCache = scope.IsolatedCaches.GetOrCreate(typeof (IUser)); Assert.AreNotSame(globalCache, scopedCache); user.Name = "changed"; service.Save(user); // scoped cache contains the "new" entity - var scopeCached = (IUser) scopedCache.GetCacheItem(GetCacheIdKey(user.Id), () => null); + var scopeCached = (IUser) scopedCache.Get(GetCacheIdKey(user.Id), () => null); Assert.IsNotNull(scopeCached); Assert.AreEqual(user.Id, scopeCached.Id); Assert.AreEqual("changed", scopeCached.Name); // global cache is unchanged - globalCached = (IUser) globalCache.GetCacheItem(GetCacheIdKey(user.Id), () => null); + globalCached = (IUser) globalCache.Get(GetCacheIdKey(user.Id), () => null); Assert.IsNotNull(globalCached); Assert.AreEqual(user.Id, globalCached.Id); Assert.AreEqual("name", globalCached.Name); @@ -108,7 +108,7 @@ namespace Umbraco.Tests.Scoping } Assert.IsNull(scopeProvider.AmbientScope); - globalCached = (IUser) globalCache.GetCacheItem(GetCacheIdKey(user.Id), () => null); + globalCached = (IUser) globalCache.Get(GetCacheIdKey(user.Id), () => null); if (complete) { // global cache has been cleared @@ -125,7 +125,7 @@ namespace Umbraco.Tests.Scoping Assert.AreEqual(complete ? "changed" : "name", user.Name); // global cache contains the entity again - globalCached = (IUser) globalCache.GetCacheItem(GetCacheIdKey(user.Id), () => null); + globalCached = (IUser) globalCache.Get(GetCacheIdKey(user.Id), () => null); Assert.IsNotNull(globalCached); Assert.AreEqual(user.Id, globalCached.Id); Assert.AreEqual(complete ? "changed" : "name", globalCached.Name); @@ -137,18 +137,18 @@ namespace Umbraco.Tests.Scoping { var scopeProvider = ScopeProvider; var service = Current.Services.LocalizationService; - var globalCache = Current.ApplicationCache.IsolatedRuntimeCache.GetOrCreateCache(typeof (ILanguage)); + var globalCache = Current.ApplicationCache.IsolatedCaches.GetOrCreate(typeof (ILanguage)); var lang = (ILanguage) new Language("fr-FR"); service.Save(lang); // global cache has been flushed, reload - var globalFullCached = (IEnumerable) globalCache.GetCacheItem(GetCacheTypeKey(), () => null); + var globalFullCached = (IEnumerable) globalCache.Get(GetCacheTypeKey(), () => null); Assert.IsNull(globalFullCached); var reload = service.GetLanguageById(lang.Id); // global cache contains the entity - globalFullCached = (IEnumerable) globalCache.GetCacheItem(GetCacheTypeKey(), () => null); + globalFullCached = (IEnumerable) globalCache.Get(GetCacheTypeKey(), () => null); Assert.IsNotNull(globalFullCached); var globalCached = globalFullCached.First(x => x.Id == lang.Id); Assert.IsNotNull(globalCached); @@ -166,19 +166,19 @@ namespace Umbraco.Tests.Scoping Assert.AreSame(scope, scopeProvider.AmbientScope); // scope has its own isolated cache - var scopedCache = scope.IsolatedRuntimeCache.GetOrCreateCache(typeof (ILanguage)); + var scopedCache = scope.IsolatedCaches.GetOrCreate(typeof (ILanguage)); Assert.AreNotSame(globalCache, scopedCache); lang.IsoCode = "de-DE"; service.Save(lang); // scoped cache has been flushed, reload - var scopeFullCached = (IEnumerable) scopedCache.GetCacheItem(GetCacheTypeKey(), () => null); + var scopeFullCached = (IEnumerable) scopedCache.Get(GetCacheTypeKey(), () => null); Assert.IsNull(scopeFullCached); reload = service.GetLanguageById(lang.Id); // scoped cache contains the "new" entity - scopeFullCached = (IEnumerable) scopedCache.GetCacheItem(GetCacheTypeKey(), () => null); + scopeFullCached = (IEnumerable) scopedCache.Get(GetCacheTypeKey(), () => null); Assert.IsNotNull(scopeFullCached); var scopeCached = scopeFullCached.First(x => x.Id == lang.Id); Assert.IsNotNull(scopeCached); @@ -186,7 +186,7 @@ namespace Umbraco.Tests.Scoping Assert.AreEqual("de-DE", scopeCached.IsoCode); // global cache is unchanged - globalFullCached = (IEnumerable) globalCache.GetCacheItem(GetCacheTypeKey(), () => null); + globalFullCached = (IEnumerable) globalCache.Get(GetCacheTypeKey(), () => null); Assert.IsNotNull(globalFullCached); globalCached = globalFullCached.First(x => x.Id == lang.Id); Assert.IsNotNull(globalCached); @@ -198,7 +198,7 @@ namespace Umbraco.Tests.Scoping } Assert.IsNull(scopeProvider.AmbientScope); - globalFullCached = (IEnumerable) globalCache.GetCacheItem(GetCacheTypeKey(), () => null); + globalFullCached = (IEnumerable) globalCache.Get(GetCacheTypeKey(), () => null); if (complete) { // global cache has been cleared @@ -215,7 +215,7 @@ namespace Umbraco.Tests.Scoping Assert.AreEqual(complete ? "de-DE" : "fr-FR", lang.IsoCode); // global cache contains the entity again - globalFullCached = (IEnumerable) globalCache.GetCacheItem(GetCacheTypeKey(), () => null); + globalFullCached = (IEnumerable) globalCache.Get(GetCacheTypeKey(), () => null); Assert.IsNotNull(globalFullCached); globalCached = globalFullCached.First(x => x.Id == lang.Id); Assert.IsNotNull(globalCached); @@ -229,7 +229,7 @@ namespace Umbraco.Tests.Scoping { var scopeProvider = ScopeProvider; var service = Current.Services.LocalizationService; - var globalCache = Current.ApplicationCache.IsolatedRuntimeCache.GetOrCreateCache(typeof (IDictionaryItem)); + var globalCache = Current.ApplicationCache.IsolatedCaches.GetOrCreate(typeof (IDictionaryItem)); var lang = (ILanguage)new Language("fr-FR"); service.Save(lang); @@ -242,7 +242,7 @@ namespace Umbraco.Tests.Scoping service.Save(item); // global cache contains the entity - var globalCached = (IDictionaryItem) globalCache.GetCacheItem(GetCacheIdKey(item.Id), () => null); + var globalCached = (IDictionaryItem) globalCache.Get(GetCacheIdKey(item.Id), () => null); Assert.IsNotNull(globalCached); Assert.AreEqual(item.Id, globalCached.Id); Assert.AreEqual("item-key", globalCached.ItemKey); @@ -258,20 +258,20 @@ namespace Umbraco.Tests.Scoping Assert.AreSame(scope, scopeProvider.AmbientScope); // scope has its own isolated cache - var scopedCache = scope.IsolatedRuntimeCache.GetOrCreateCache(typeof (IDictionaryItem)); + var scopedCache = scope.IsolatedCaches.GetOrCreate(typeof (IDictionaryItem)); Assert.AreNotSame(globalCache, scopedCache); item.ItemKey = "item-changed"; service.Save(item); // scoped cache contains the "new" entity - var scopeCached = (IDictionaryItem) scopedCache.GetCacheItem(GetCacheIdKey(item.Id), () => null); + var scopeCached = (IDictionaryItem) scopedCache.Get(GetCacheIdKey(item.Id), () => null); Assert.IsNotNull(scopeCached); Assert.AreEqual(item.Id, scopeCached.Id); Assert.AreEqual("item-changed", scopeCached.ItemKey); // global cache is unchanged - globalCached = (IDictionaryItem) globalCache.GetCacheItem(GetCacheIdKey(item.Id), () => null); + globalCached = (IDictionaryItem) globalCache.Get(GetCacheIdKey(item.Id), () => null); Assert.IsNotNull(globalCached); Assert.AreEqual(item.Id, globalCached.Id); Assert.AreEqual("item-key", globalCached.ItemKey); @@ -281,7 +281,7 @@ namespace Umbraco.Tests.Scoping } Assert.IsNull(scopeProvider.AmbientScope); - globalCached = (IDictionaryItem) globalCache.GetCacheItem(GetCacheIdKey(item.Id), () => null); + globalCached = (IDictionaryItem) globalCache.Get(GetCacheIdKey(item.Id), () => null); if (complete) { // global cache has been cleared @@ -298,7 +298,7 @@ namespace Umbraco.Tests.Scoping Assert.AreEqual(complete ? "item-changed" : "item-key", item.ItemKey); // global cache contains the entity again - globalCached = (IDictionaryItem) globalCache.GetCacheItem(GetCacheIdKey(item.Id), () => null); + globalCached = (IDictionaryItem) globalCache.Get(GetCacheIdKey(item.Id), () => null); Assert.IsNotNull(globalCached); Assert.AreEqual(item.Id, globalCached.Id); Assert.AreEqual(complete ? "item-changed" : "item-key", globalCached.ItemKey); diff --git a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs index 7fd2f0f18b..35fcc853d4 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs @@ -38,7 +38,7 @@ namespace Umbraco.Tests.TestHelpers var container = RegisterFactory.Create(); var logger = new ProfilingLogger(Mock.Of(), Mock.Of()); - var typeLoader = new TypeLoader(NullCacheProvider.Instance, + var typeLoader = new TypeLoader(NoAppCache.Instance, LocalTempStorage.Default, logger, false); diff --git a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs index 0729aa0b6e..2deb30bbdd 100644 --- a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs +++ b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs @@ -246,7 +246,7 @@ namespace Umbraco.Tests.TestHelpers protected virtual IPublishedSnapshotService CreatePublishedSnapshotService() { - var cache = NullCacheProvider.Instance; + var cache = NoAppCache.Instance; ContentTypesCache = new PublishedContentTypeCache( Factory.GetInstance(), diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index c980f9c1ee..2d6e01b6bb 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -245,7 +245,7 @@ namespace Umbraco.Tests.Testing .ComposeWebMappingProfiles(); } - protected virtual TypeLoader GetTypeLoader(IRuntimeCacheProvider runtimeCache, IGlobalSettings globalSettings, IProfilingLogger logger, UmbracoTestOptions.TypeLoader option) + protected virtual TypeLoader GetTypeLoader(IAppPolicedCache runtimeCache, IGlobalSettings globalSettings, IProfilingLogger logger, UmbracoTestOptions.TypeLoader option) { switch (option) { @@ -260,13 +260,13 @@ namespace Umbraco.Tests.Testing } } - protected virtual TypeLoader CreateTypeLoader(IRuntimeCacheProvider runtimeCache, IGlobalSettings globalSettings, IProfilingLogger logger) + protected virtual TypeLoader CreateTypeLoader(IAppPolicedCache runtimeCache, IGlobalSettings globalSettings, IProfilingLogger logger) { return CreateCommonTypeLoader(runtimeCache, globalSettings, logger); } // common to all tests = cannot be overriden - private static TypeLoader CreateCommonTypeLoader(IRuntimeCacheProvider runtimeCache, IGlobalSettings globalSettings, IProfilingLogger logger) + private static TypeLoader CreateCommonTypeLoader(IAppPolicedCache runtimeCache, IGlobalSettings globalSettings, IProfilingLogger logger) { return new TypeLoader(runtimeCache, globalSettings.LocalTempStorageLocation, logger, false) { diff --git a/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs b/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs index 192b0975d1..133cbb2ee7 100644 --- a/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs +++ b/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs @@ -415,7 +415,7 @@ namespace Umbraco.Tests.Web.Mvc // CacheHelper.CreateDisabledCacheHelper(), // new ProfilingLogger(logger, Mock.Of())) { /*IsReady = true*/ }; - var cache = NullCacheProvider.Instance; + var cache = NoAppCache.Instance; //var provider = new ScopeUnitOfWorkProvider(databaseFactory, new RepositoryFactory(Mock.Of())); var scopeProvider = TestObjects.GetScopeProvider(Mock.Of()); var factory = Mock.Of(); diff --git a/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs b/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs index 047d0b0b8f..e95ae7b785 100644 --- a/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs +++ b/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs @@ -39,7 +39,7 @@ namespace Umbraco.Tests.Web // fixme - bad in a unit test - but Udi has a static ctor that wants it?! var factory = new Mock(); factory.Setup(x => x.GetInstance(typeof(TypeLoader))).Returns( - new TypeLoader(NullCacheProvider.Instance, LocalTempStorage.Default, new ProfilingLogger(Mock.Of(), Mock.Of()))); + new TypeLoader(NoAppCache.Instance, LocalTempStorage.Default, new ProfilingLogger(Mock.Of(), Mock.Of()))); factory.Setup(x => x.GetInstance(typeof (ServiceContext))).Returns(serviceContext); var settings = SettingsForTests.GetDefaultUmbracoSettings(); diff --git a/src/Umbraco.Web/Cache/ApplicationCacheRefresher.cs b/src/Umbraco.Web/Cache/ApplicationCacheRefresher.cs index cf93b44215..751b2194b7 100644 --- a/src/Umbraco.Web/Cache/ApplicationCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/ApplicationCacheRefresher.cs @@ -25,7 +25,7 @@ namespace Umbraco.Web.Cache public override void RefreshAll() { - AppCaches.RuntimeCache.ClearCacheItem(CacheKeys.ApplicationsCacheKey); + AppCaches.RuntimeCache.Clear(CacheKeys.ApplicationsCacheKey); base.RefreshAll(); } @@ -37,7 +37,7 @@ namespace Umbraco.Web.Cache public override void Remove(int id) { - AppCaches.RuntimeCache.ClearCacheItem(CacheKeys.ApplicationsCacheKey); + AppCaches.RuntimeCache.Clear(CacheKeys.ApplicationsCacheKey); base.Remove(id); } diff --git a/src/Umbraco.Web/Cache/ApplicationTreeCacheRefresher.cs b/src/Umbraco.Web/Cache/ApplicationTreeCacheRefresher.cs index 72fceec631..4d2dcd8efb 100644 --- a/src/Umbraco.Web/Cache/ApplicationTreeCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/ApplicationTreeCacheRefresher.cs @@ -25,7 +25,7 @@ namespace Umbraco.Web.Cache public override void RefreshAll() { - AppCaches.RuntimeCache.ClearCacheItem(CacheKeys.ApplicationTreeCacheKey); + AppCaches.RuntimeCache.Clear(CacheKeys.ApplicationTreeCacheKey); base.RefreshAll(); } @@ -37,7 +37,7 @@ namespace Umbraco.Web.Cache public override void Remove(int id) { - AppCaches.RuntimeCache.ClearCacheItem(CacheKeys.ApplicationTreeCacheKey); + AppCaches.RuntimeCache.Clear(CacheKeys.ApplicationTreeCacheKey); base.Remove(id); } diff --git a/src/Umbraco.Web/Cache/ContentCacheRefresher.cs b/src/Umbraco.Web/Cache/ContentCacheRefresher.cs index 3ae2f8e3dd..36397540b6 100644 --- a/src/Umbraco.Web/Cache/ContentCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/ContentCacheRefresher.cs @@ -44,14 +44,14 @@ namespace Umbraco.Web.Cache public override void Refresh(JsonPayload[] payloads) { - AppCaches.RuntimeCache.ClearCacheObjectTypes(); + AppCaches.RuntimeCache.ClearOfType(); var idsRemoved = new HashSet(); - var isolatedCache = AppCaches.IsolatedRuntimeCache.GetOrCreateCache(); + var isolatedCache = AppCaches.IsolatedCaches.GetOrCreate(); foreach (var payload in payloads) { - isolatedCache.ClearCacheItem(RepositoryCacheKeys.GetKey(payload.Id)); + isolatedCache.Clear(RepositoryCacheKeys.GetKey(payload.Id)); _idkMap.ClearCache(payload.Id); @@ -59,7 +59,7 @@ namespace Umbraco.Web.Cache if (payload.ChangeTypes.HasTypesAny(TreeChangeTypes.RefreshBranch | TreeChangeTypes.Remove)) { var pathid = "," + payload.Id + ","; - isolatedCache.ClearCacheObjectTypes((k, v) => v.Path.Contains(pathid)); + isolatedCache.ClearOfType((k, v) => v.Path.Contains(pathid)); } //if the item is being completely removed, we need to refresh the domains cache if any domain was assigned to the content @@ -162,8 +162,8 @@ namespace Umbraco.Web.Cache appCaches.ClearPartialViewCache(); MacroCacheRefresher.ClearMacroContentCache(appCaches); // just the content - appCaches.IsolatedRuntimeCache.ClearCache(); - appCaches.IsolatedRuntimeCache.ClearCache(); + appCaches.IsolatedCaches.ClearCache(); + appCaches.IsolatedCaches.ClearCache(); } #endregion diff --git a/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs b/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs index e1a8f05e39..f3d1337403 100644 --- a/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs @@ -49,7 +49,7 @@ namespace Umbraco.Web.Cache ClearAllIsolatedCacheByEntityType(); ClearAllIsolatedCacheByEntityType(); - var dataTypeCache = AppCaches.IsolatedRuntimeCache.GetCache(); + var dataTypeCache = AppCaches.IsolatedCaches.Get(); foreach (var payload in payloads) { diff --git a/src/Umbraco.Web/Cache/MacroCacheRefresher.cs b/src/Umbraco.Web/Cache/MacroCacheRefresher.cs index cdeb2ffdd0..6b739b4f49 100644 --- a/src/Umbraco.Web/Cache/MacroCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/MacroCacheRefresher.cs @@ -33,11 +33,11 @@ namespace Umbraco.Web.Cache public override void RefreshAll() { foreach (var prefix in GetAllMacroCacheKeys()) - AppCaches.RuntimeCache.ClearCacheByKeySearch(prefix); + AppCaches.RuntimeCache.ClearByKey(prefix); ClearAllIsolatedCacheByEntityType(); - AppCaches.RuntimeCache.ClearCacheObjectTypes(); + AppCaches.RuntimeCache.ClearOfType(); base.RefreshAll(); } @@ -49,12 +49,12 @@ namespace Umbraco.Web.Cache foreach (var payload in payloads) { foreach (var alias in GetCacheKeysForAlias(payload.Alias)) - AppCaches.RuntimeCache.ClearCacheByKeySearch(alias); + AppCaches.RuntimeCache.ClearByKey(alias); - var macroRepoCache = AppCaches.IsolatedRuntimeCache.GetCache(); + var macroRepoCache = AppCaches.IsolatedCaches.Get(); if (macroRepoCache) { - macroRepoCache.Result.ClearCacheItem(RepositoryCacheKeys.GetKey(payload.Id)); + macroRepoCache.Result.Clear(RepositoryCacheKeys.GetKey(payload.Id)); } }; @@ -112,7 +112,7 @@ namespace Umbraco.Web.Cache public static void ClearMacroContentCache(AppCaches appCaches) { - appCaches.RuntimeCache.ClearCacheObjectTypes(); + appCaches.RuntimeCache.ClearOfType(); } #endregion diff --git a/src/Umbraco.Web/Cache/MediaCacheRefresher.cs b/src/Umbraco.Web/Cache/MediaCacheRefresher.cs index a6ccd7e005..cdaf43dac3 100644 --- a/src/Umbraco.Web/Cache/MediaCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/MediaCacheRefresher.cs @@ -49,7 +49,7 @@ namespace Umbraco.Web.Cache { Current.ApplicationCache.ClearPartialViewCache(); - var mediaCache = AppCaches.IsolatedRuntimeCache.GetCache(); + var mediaCache = AppCaches.IsolatedCaches.Get(); foreach (var payload in payloads) { @@ -61,13 +61,13 @@ namespace Umbraco.Web.Cache // repository cache // it *was* done for each pathId but really that does not make sense // only need to do it for the current media - mediaCache.Result.ClearCacheItem(RepositoryCacheKeys.GetKey(payload.Id)); + mediaCache.Result.Clear(RepositoryCacheKeys.GetKey(payload.Id)); // remove those that are in the branch if (payload.ChangeTypes.HasTypesAny(TreeChangeTypes.RefreshBranch | TreeChangeTypes.Remove)) { var pathid = "," + payload.Id + ","; - mediaCache.Result.ClearCacheObjectTypes((_, v) => v.Path.Contains(pathid)); + mediaCache.Result.ClearOfType((_, v) => v.Path.Contains(pathid)); } } } @@ -121,7 +121,7 @@ namespace Umbraco.Web.Cache public static void RefreshMediaTypes(AppCaches appCaches) { - appCaches.IsolatedRuntimeCache.ClearCache(); + appCaches.IsolatedCaches.ClearCache(); } #endregion diff --git a/src/Umbraco.Web/Cache/MemberCacheRefresher.cs b/src/Umbraco.Web/Cache/MemberCacheRefresher.cs index 29c102e7a2..1565b1c849 100644 --- a/src/Umbraco.Web/Cache/MemberCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/MemberCacheRefresher.cs @@ -60,9 +60,9 @@ namespace Umbraco.Web.Cache _idkMap.ClearCache(id); AppCaches.ClearPartialViewCache(); - var memberCache = AppCaches.IsolatedRuntimeCache.GetCache(); + var memberCache = AppCaches.IsolatedCaches.Get(); if (memberCache) - memberCache.Result.ClearCacheItem(RepositoryCacheKeys.GetKey(id)); + memberCache.Result.Clear(RepositoryCacheKeys.GetKey(id)); } #endregion @@ -71,7 +71,7 @@ namespace Umbraco.Web.Cache public static void RefreshMemberTypes(AppCaches appCaches) { - appCaches.IsolatedRuntimeCache.ClearCache(); + appCaches.IsolatedCaches.ClearCache(); } #endregion diff --git a/src/Umbraco.Web/Cache/MemberGroupCacheRefresher.cs b/src/Umbraco.Web/Cache/MemberGroupCacheRefresher.cs index 9368b0f9f4..3e195cec5e 100644 --- a/src/Umbraco.Web/Cache/MemberGroupCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/MemberGroupCacheRefresher.cs @@ -49,7 +49,7 @@ namespace Umbraco.Web.Cache // Since we cache by group name, it could be problematic when renaming to // previously existing names - see http://issues.umbraco.org/issue/U4-10846. // To work around this, just clear all the cache items - AppCaches.IsolatedRuntimeCache.ClearCache(); + AppCaches.IsolatedCaches.ClearCache(); } #endregion diff --git a/src/Umbraco.Web/Cache/RelationTypeCacheRefresher.cs b/src/Umbraco.Web/Cache/RelationTypeCacheRefresher.cs index 8b1c8581cd..c9c8b47bbf 100644 --- a/src/Umbraco.Web/Cache/RelationTypeCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/RelationTypeCacheRefresher.cs @@ -34,8 +34,8 @@ namespace Umbraco.Web.Cache public override void Refresh(int id) { - var cache = AppCaches.IsolatedRuntimeCache.GetCache(); - if (cache) cache.Result.ClearCacheItem(RepositoryCacheKeys.GetKey(id)); + var cache = AppCaches.IsolatedCaches.Get(); + if (cache) cache.Result.Clear(RepositoryCacheKeys.GetKey(id)); base.Refresh(id); } @@ -47,8 +47,8 @@ namespace Umbraco.Web.Cache public override void Remove(int id) { - var cache = AppCaches.IsolatedRuntimeCache.GetCache(); - if (cache) cache.Result.ClearCacheItem(RepositoryCacheKeys.GetKey(id)); + var cache = AppCaches.IsolatedCaches.Get(); + if (cache) cache.Result.Clear(RepositoryCacheKeys.GetKey(id)); base.Remove(id); } diff --git a/src/Umbraco.Web/Cache/TemplateCacheRefresher.cs b/src/Umbraco.Web/Cache/TemplateCacheRefresher.cs index 7ff7c6fdb6..eda3b6eef4 100644 --- a/src/Umbraco.Web/Cache/TemplateCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/TemplateCacheRefresher.cs @@ -52,7 +52,7 @@ namespace Umbraco.Web.Cache private void RemoveFromCache(int id) { _idkMap.ClearCache(id); - AppCaches.RuntimeCache.ClearCacheItem($"{CacheKeys.TemplateFrontEndCacheKey}{id}"); + AppCaches.RuntimeCache.Clear($"{CacheKeys.TemplateFrontEndCacheKey}{id}"); //need to clear the runtime cache for templates ClearAllIsolatedCacheByEntityType(); diff --git a/src/Umbraco.Web/Cache/UserCacheRefresher.cs b/src/Umbraco.Web/Cache/UserCacheRefresher.cs index a502a7554f..922a9df385 100644 --- a/src/Umbraco.Web/Cache/UserCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/UserCacheRefresher.cs @@ -40,9 +40,9 @@ namespace Umbraco.Web.Cache public override void Remove(int id) { - var userCache = AppCaches.IsolatedRuntimeCache.GetCache(); + var userCache = AppCaches.IsolatedCaches.Get(); if (userCache) - userCache.Result.ClearCacheItem(RepositoryCacheKeys.GetKey(id)); + userCache.Result.Clear(RepositoryCacheKeys.GetKey(id)); base.Remove(id); } diff --git a/src/Umbraco.Web/Cache/UserGroupCacheRefresher.cs b/src/Umbraco.Web/Cache/UserGroupCacheRefresher.cs index 4dea595c85..cfdf8f3669 100644 --- a/src/Umbraco.Web/Cache/UserGroupCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/UserGroupCacheRefresher.cs @@ -35,10 +35,10 @@ namespace Umbraco.Web.Cache public override void RefreshAll() { ClearAllIsolatedCacheByEntityType(); - var userGroupCache = AppCaches.IsolatedRuntimeCache.GetCache(); + var userGroupCache = AppCaches.IsolatedCaches.Get(); if (userGroupCache) { - userGroupCache.Result.ClearCacheByKeySearch(UserGroupRepository.GetByAliasCacheKeyPrefix); + userGroupCache.Result.ClearByKey(UserGroupRepository.GetByAliasCacheKeyPrefix); } //We'll need to clear all user cache too @@ -55,11 +55,11 @@ namespace Umbraco.Web.Cache public override void Remove(int id) { - var userGroupCache = AppCaches.IsolatedRuntimeCache.GetCache(); + var userGroupCache = AppCaches.IsolatedCaches.Get(); if (userGroupCache) { - userGroupCache.Result.ClearCacheItem(RepositoryCacheKeys.GetKey(id)); - userGroupCache.Result.ClearCacheByKeySearch(UserGroupRepository.GetByAliasCacheKeyPrefix); + userGroupCache.Result.Clear(RepositoryCacheKeys.GetKey(id)); + userGroupCache.Result.ClearByKey(UserGroupRepository.GetByAliasCacheKeyPrefix); } //we don't know what user's belong to this group without doing a look up so we'll need to just clear them all diff --git a/src/Umbraco.Web/CacheHelperExtensions.cs b/src/Umbraco.Web/CacheHelperExtensions.cs index 3c5ea1930d..ae8df63415 100644 --- a/src/Umbraco.Web/CacheHelperExtensions.cs +++ b/src/Umbraco.Web/CacheHelperExtensions.cs @@ -56,7 +56,7 @@ namespace Umbraco.Web /// public static void ClearPartialViewCache(this AppCaches appCaches) { - appCaches.RuntimeCache.ClearCacheByKeySearch(PartialViewCacheKey); + appCaches.RuntimeCache.ClearByKey(PartialViewCacheKey); } } } diff --git a/src/Umbraco.Web/Dictionary/UmbracoCultureDictionary.cs b/src/Umbraco.Web/Dictionary/UmbracoCultureDictionary.cs index f30f8e9745..5234bf9fa7 100644 --- a/src/Umbraco.Web/Dictionary/UmbracoCultureDictionary.cs +++ b/src/Umbraco.Web/Dictionary/UmbracoCultureDictionary.cs @@ -21,7 +21,7 @@ namespace Umbraco.Web.Dictionary public class DefaultCultureDictionary : Core.Dictionary.ICultureDictionary { private readonly ILocalizationService _localizationService; - private readonly ICacheProvider _requestCacheProvider; + private readonly IAppCache _requestCacheProvider; private readonly CultureInfo _specificCulture; public DefaultCultureDictionary() @@ -30,7 +30,7 @@ namespace Umbraco.Web.Dictionary } - public DefaultCultureDictionary(ILocalizationService localizationService, ICacheProvider requestCacheProvider) + public DefaultCultureDictionary(ILocalizationService localizationService, IAppCache requestCacheProvider) { _localizationService = localizationService ?? throw new ArgumentNullException(nameof(localizationService)); _requestCacheProvider = requestCacheProvider ?? throw new ArgumentNullException(nameof(requestCacheProvider)); @@ -42,7 +42,7 @@ namespace Umbraco.Web.Dictionary _specificCulture = specificCulture ?? throw new ArgumentNullException(nameof(specificCulture)); } - public DefaultCultureDictionary(CultureInfo specificCulture, ILocalizationService localizationService, ICacheProvider requestCacheProvider) + public DefaultCultureDictionary(CultureInfo specificCulture, ILocalizationService localizationService, IAppCache requestCacheProvider) { _localizationService = localizationService ?? throw new ArgumentNullException(nameof(localizationService)); _requestCacheProvider = requestCacheProvider ?? throw new ArgumentNullException(nameof(requestCacheProvider)); diff --git a/src/Umbraco.Web/Editors/ExamineManagementController.cs b/src/Umbraco.Web/Editors/ExamineManagementController.cs index b583babee3..db9de424a9 100644 --- a/src/Umbraco.Web/Editors/ExamineManagementController.cs +++ b/src/Umbraco.Web/Editors/ExamineManagementController.cs @@ -29,12 +29,12 @@ namespace Umbraco.Web.Editors { private readonly IExamineManager _examineManager; private readonly ILogger _logger; - private readonly IRuntimeCacheProvider _runtimeCacheProvider; + private readonly IAppPolicedCache _runtimeCacheProvider; private readonly IndexRebuilder _indexRebuilder; public ExamineManagementController(IExamineManager examineManager, ILogger logger, - IRuntimeCacheProvider runtimeCacheProvider, + IAppPolicedCache runtimeCacheProvider, IndexRebuilder indexRebuilder) { _examineManager = examineManager; @@ -114,7 +114,7 @@ namespace Umbraco.Web.Editors throw new HttpResponseException(validate); var cacheKey = "temp_indexing_op_" + indexName; - var found = ApplicationCache.RuntimeCache.GetCacheItem(cacheKey); + var found = ApplicationCache.RuntimeCache.Get(cacheKey); //if its still there then it's not done return found != null @@ -153,7 +153,7 @@ namespace Umbraco.Web.Editors var cacheKey = "temp_indexing_op_" + index.Name; //put temp val in cache which is used as a rudimentary way to know when the indexing is done - ApplicationCache.RuntimeCache.InsertCacheItem(cacheKey, () => "tempValue", TimeSpan.FromMinutes(5)); + ApplicationCache.RuntimeCache.Insert(cacheKey, () => "tempValue", TimeSpan.FromMinutes(5)); _indexRebuilder.RebuildIndex(indexName); @@ -269,7 +269,7 @@ namespace Umbraco.Web.Editors >($"Rebuilding index '{indexer.Name}' done, {indexer.CommitCount} items committed (can differ from the number of items in the index)"); var cacheKey = "temp_indexing_op_" + indexer.Name; - _runtimeCacheProvider.ClearCacheItem(cacheKey); + _runtimeCacheProvider.Clear(cacheKey); } } } diff --git a/src/Umbraco.Web/Editors/UsersController.cs b/src/Umbraco.Web/Editors/UsersController.cs index e46e83c6e4..15cfda9ffd 100644 --- a/src/Umbraco.Web/Editors/UsersController.cs +++ b/src/Umbraco.Web/Editors/UsersController.cs @@ -63,7 +63,7 @@ namespace Umbraco.Web.Editors return await PostSetAvatarInternal(Request, Services.UserService, ApplicationCache.StaticCache, id); } - internal static async Task PostSetAvatarInternal(HttpRequestMessage request, IUserService userService, ICacheProvider staticCache, int id) + internal static async Task PostSetAvatarInternal(HttpRequestMessage request, IUserService userService, IAppCache staticCache, int id) { if (request.Content.IsMimeMultipartContent() == false) { diff --git a/src/Umbraco.Web/Macros/MacroRenderer.cs b/src/Umbraco.Web/Macros/MacroRenderer.cs index e0a0fd65c8..0bcdb3225b 100755 --- a/src/Umbraco.Web/Macros/MacroRenderer.cs +++ b/src/Umbraco.Web/Macros/MacroRenderer.cs @@ -152,7 +152,7 @@ namespace Umbraco.Web.Macros macroContent.Date = DateTime.Now; var cache = Current.ApplicationCache.RuntimeCache; - cache.InsertCacheItem( + cache.Insert( CacheKeys.MacroContentCacheKey + model.CacheIdentifier, () => macroContent, new TimeSpan(0, 0, model.CacheDuration), diff --git a/src/Umbraco.Web/Models/Mapping/UserMapperProfile.cs b/src/Umbraco.Web/Models/Mapping/UserMapperProfile.cs index 8261dda0d4..4b27af3120 100644 --- a/src/Umbraco.Web/Models/Mapping/UserMapperProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/UserMapperProfile.cs @@ -22,7 +22,7 @@ namespace Umbraco.Web.Models.Mapping => entity is ContentEntitySlim contentEntity ? contentEntity.ContentTypeIcon : null; public UserMapperProfile(ILocalizedTextService textService, IUserService userService, IEntityService entityService, ISectionService sectionService, - IRuntimeCacheProvider runtimeCache, ActionCollection actions, IGlobalSettings globalSettings) + IAppPolicedCache runtimeCache, ActionCollection actions, IGlobalSettings globalSettings) { var userGroupDefaultPermissionsResolver = new UserGroupDefaultPermissionsResolver(textService, actions); diff --git a/src/Umbraco.Web/PublishedCache/IPublishedSnapshot.cs b/src/Umbraco.Web/PublishedCache/IPublishedSnapshot.cs index 0636eb808c..0865e61f08 100644 --- a/src/Umbraco.Web/PublishedCache/IPublishedSnapshot.cs +++ b/src/Umbraco.Web/PublishedCache/IPublishedSnapshot.cs @@ -36,7 +36,7 @@ namespace Umbraco.Web.PublishedCache /// /// The snapshot-level cache belongs to this snapshot only. /// - ICacheProvider SnapshotCache { get; } + IAppCache SnapshotCache { get; } /// /// Gets the elements-level cache. @@ -45,7 +45,7 @@ namespace Umbraco.Web.PublishedCache /// The elements-level cache is shared by all snapshots relying on the same elements, /// ie all snapshots built on top of unchanging content / media / etc. /// - ICacheProvider ElementsCache { get; } + IAppCache ElementsCache { get; } /// /// Forces the preview mode. diff --git a/src/Umbraco.Web/PublishedCache/NuCache/ContentCache.cs b/src/Umbraco.Web/PublishedCache/NuCache/ContentCache.cs index 817c363fa5..566ab240c1 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/ContentCache.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/ContentCache.cs @@ -21,8 +21,8 @@ namespace Umbraco.Web.PublishedCache.NuCache internal class ContentCache : PublishedCacheBase, IPublishedContentCache, INavigableData, IDisposable { private readonly ContentStore.Snapshot _snapshot; - private readonly ICacheProvider _snapshotCache; - private readonly ICacheProvider _elementsCache; + private readonly IAppCache _snapshotCache; + private readonly IAppCache _elementsCache; private readonly DomainHelper _domainHelper; private readonly IGlobalSettings _globalSettings; private readonly ILocalizationService _localizationService; @@ -34,7 +34,7 @@ namespace Umbraco.Web.PublishedCache.NuCache // it's too late for UmbracoContext which has captured previewDefault and stuff into these ctor vars // but, no, UmbracoContext returns snapshot.Content which comes from elements SO a resync should create a new cache - public ContentCache(bool previewDefault, ContentStore.Snapshot snapshot, ICacheProvider snapshotCache, ICacheProvider elementsCache, DomainHelper domainHelper, IGlobalSettings globalSettings, ILocalizationService localizationService) + public ContentCache(bool previewDefault, ContentStore.Snapshot snapshot, IAppCache snapshotCache, IAppCache elementsCache, DomainHelper domainHelper, IGlobalSettings globalSettings, ILocalizationService localizationService) : base(previewDefault) { _snapshot = snapshot; @@ -259,7 +259,7 @@ namespace Umbraco.Web.PublishedCache.NuCache return GetAtRootNoCache(preview); // note: ToArray is important here, we want to cache the result, not the function! - return (IEnumerable)cache.GetCacheItem( + return (IEnumerable)cache.Get( CacheKeys.ContentCacheRoots(preview), () => GetAtRootNoCache(preview).ToArray()); } diff --git a/src/Umbraco.Web/PublishedCache/NuCache/MediaCache.cs b/src/Umbraco.Web/PublishedCache/NuCache/MediaCache.cs index f107b52a40..28c7c38c36 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/MediaCache.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/MediaCache.cs @@ -13,12 +13,12 @@ namespace Umbraco.Web.PublishedCache.NuCache internal class MediaCache : PublishedCacheBase, IPublishedMediaCache, INavigableData, IDisposable { private readonly ContentStore.Snapshot _snapshot; - private readonly ICacheProvider _snapshotCache; - private readonly ICacheProvider _elementsCache; + private readonly IAppCache _snapshotCache; + private readonly IAppCache _elementsCache; #region Constructors - public MediaCache(bool previewDefault, ContentStore.Snapshot snapshot, ICacheProvider snapshotCache, ICacheProvider elementsCache) + public MediaCache(bool previewDefault, ContentStore.Snapshot snapshot, IAppCache snapshotCache, IAppCache elementsCache) : base(previewDefault) { _snapshot = snapshot; @@ -63,7 +63,7 @@ namespace Umbraco.Web.PublishedCache.NuCache return GetAtRootNoCache(); // note: ToArray is important here, we want to cache the result, not the function! - return (IEnumerable)cache.GetCacheItem( + return (IEnumerable)cache.Get( CacheKeys.MediaCacheRoots(false), // ignore preview, only 1 key! () => GetAtRootNoCache().ToArray()); } diff --git a/src/Umbraco.Web/PublishedCache/NuCache/MemberCache.cs b/src/Umbraco.Web/PublishedCache/NuCache/MemberCache.cs index f2392c9c3d..ecf099f90b 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/MemberCache.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/MemberCache.cs @@ -19,12 +19,12 @@ namespace Umbraco.Web.PublishedCache.NuCache private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor; public readonly IVariationContextAccessor VariationContextAccessor; private readonly IEntityXmlSerializer _entitySerializer; - private readonly ICacheProvider _snapshotCache; + private readonly IAppCache _snapshotCache; private readonly IMemberService _memberService; private readonly PublishedContentTypeCache _contentTypeCache; private readonly bool _previewDefault; - public MemberCache(bool previewDefault, ICacheProvider snapshotCache, IMemberService memberService, PublishedContentTypeCache contentTypeCache, IPublishedSnapshotAccessor publishedSnapshotAccessor, IVariationContextAccessor variationContextAccessor, IEntityXmlSerializer entitySerializer) + public MemberCache(bool previewDefault, IAppCache snapshotCache, IMemberService memberService, PublishedContentTypeCache contentTypeCache, IPublishedSnapshotAccessor publishedSnapshotAccessor, IVariationContextAccessor variationContextAccessor, IEntityXmlSerializer entitySerializer) { _snapshotCache = snapshotCache; _publishedSnapshotAccessor = publishedSnapshotAccessor; diff --git a/src/Umbraco.Web/PublishedCache/NuCache/Property.cs b/src/Umbraco.Web/PublishedCache/NuCache/Property.cs index 132c4b6d59..2c8bc94d90 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/Property.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/Property.cs @@ -125,7 +125,7 @@ namespace Umbraco.Web.PublishedCache.NuCache { CacheValues cacheValues; PublishedSnapshot publishedSnapshot; - ICacheProvider cache; + IAppCache cache; switch (cacheLevel) { case PropertyCacheLevel.None: @@ -161,11 +161,11 @@ namespace Umbraco.Web.PublishedCache.NuCache return cacheValues; } - private CacheValues GetCacheValues(ICacheProvider cache) + private CacheValues GetCacheValues(IAppCache cache) { if (cache == null) // no cache, don't cache return new CacheValues(); - return (CacheValues) cache.GetCacheItem(ValuesCacheKey, () => new CacheValues()); + return (CacheValues) cache.Get(ValuesCacheKey, () => new CacheValues()); } // this is always invoked from within a lock, so does not require its own lock diff --git a/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs b/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs index 25e5244d32..65b7a1560a 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs @@ -48,7 +48,7 @@ namespace Umbraco.Web.PublishedCache.NuCache var cache = GetCurrentSnapshotCache(); return cache == null ? GetProfileNameByIdNoCache(id) - : (string)cache.GetCacheItem(CacheKeys.ProfileName(id), () => GetProfileNameByIdNoCache(id)); + : (string)cache.Get(CacheKeys.ProfileName(id), () => GetProfileNameByIdNoCache(id)); } private static string GetProfileNameByIdNoCache(int id) @@ -328,7 +328,7 @@ namespace Umbraco.Web.PublishedCache.NuCache return GetChildren(); // note: ToArray is important here, we want to cache the result, not the function! - return (IEnumerable)cache.GetCacheItem(ChildrenCacheKey, () => GetChildren().ToArray()); + return (IEnumerable)cache.Get(ChildrenCacheKey, () => GetChildren().ToArray()); } } @@ -383,7 +383,7 @@ namespace Umbraco.Web.PublishedCache.NuCache #region Caching // beware what you use that one for - you don't want to cache its result - private ICacheProvider GetAppropriateCache() + private IAppCache GetAppropriateCache() { var publishedSnapshot = (PublishedSnapshot)_publishedSnapshotAccessor.PublishedSnapshot; var cache = publishedSnapshot == null @@ -394,7 +394,7 @@ namespace Umbraco.Web.PublishedCache.NuCache return cache; } - private ICacheProvider GetCurrentSnapshotCache() + private IAppCache GetCurrentSnapshotCache() { var publishedSnapshot = (PublishedSnapshot)_publishedSnapshotAccessor.PublishedSnapshot; return publishedSnapshot?.SnapshotCache; @@ -436,7 +436,7 @@ namespace Umbraco.Web.PublishedCache.NuCache var cache = GetAppropriateCache(); if (cache == null) return new PublishedContent(this).CreateModel(); - return (IPublishedContent)cache.GetCacheItem(AsPreviewingCacheKey, () => new PublishedContent(this).CreateModel()); + return (IPublishedContent)cache.Get(AsPreviewingCacheKey, () => new PublishedContent(this).CreateModel()); } // used by Navigable.Source,... diff --git a/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshot.cs b/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshot.cs index 9b8982c69c..2ceced75eb 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshot.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshot.cs @@ -25,8 +25,8 @@ namespace Umbraco.Web.PublishedCache.NuCache public MediaCache MediaCache; public MemberCache MemberCache; public DomainCache DomainCache; - public ICacheProvider SnapshotCache; - public ICacheProvider ElementsCache; + public IAppCache SnapshotCache; + public IAppCache ElementsCache; public void Dispose() { @@ -48,9 +48,9 @@ namespace Umbraco.Web.PublishedCache.NuCache #region Caches - public ICacheProvider SnapshotCache => Elements.SnapshotCache; + public IAppCache SnapshotCache => Elements.SnapshotCache; - public ICacheProvider ElementsCache => Elements.ElementsCache; + public IAppCache ElementsCache => Elements.ElementsCache; #endregion diff --git a/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs b/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs index 36f3472c31..bcb1c6ede3 100755 --- a/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs @@ -932,7 +932,7 @@ namespace Umbraco.Web.PublishedCache.NuCache #region Create, Get Published Snapshot private long _contentGen, _mediaGen, _domainGen; - private ICacheProvider _elementsCache; + private IAppCache _elementsCache; public override IPublishedSnapshot CreatePublishedSnapshot(string previewToken) { @@ -960,7 +960,7 @@ namespace Umbraco.Web.PublishedCache.NuCache ContentStore.Snapshot contentSnap, mediaSnap; SnapDictionary.Snapshot domainSnap; - ICacheProvider elementsCache; + IAppCache elementsCache; lock (_storesLock) { var scopeContext = _scopeProvider.Context; @@ -998,11 +998,11 @@ namespace Umbraco.Web.PublishedCache.NuCache _contentGen = contentSnap.Gen; _mediaGen = mediaSnap.Gen; _domainGen = domainSnap.Gen; - elementsCache = _elementsCache = new DictionaryCacheProvider(); + elementsCache = _elementsCache = new FastDictionaryCacheProvider(); } } - var snapshotCache = new StaticCacheProvider(); + var snapshotCache = new DictionaryCacheProvider(); var memberTypeCache = new PublishedContentTypeCache(null, null, _serviceContext.MemberTypeService, _publishedContentTypeFactory, _logger); diff --git a/src/Umbraco.Web/PublishedCache/PublishedElementPropertyBase.cs b/src/Umbraco.Web/PublishedCache/PublishedElementPropertyBase.cs index cff1e40b69..6d69b96e0c 100644 --- a/src/Umbraco.Web/PublishedCache/PublishedElementPropertyBase.cs +++ b/src/Umbraco.Web/PublishedCache/PublishedElementPropertyBase.cs @@ -106,7 +106,7 @@ namespace Umbraco.Web.PublishedCache } } - private ICacheProvider GetSnapshotCache() + private IAppCache GetSnapshotCache() { // cache within the snapshot cache, unless previewing, then use the snapshot or // elements cache (if we don't want to pollute the elements cache with short-lived @@ -135,12 +135,12 @@ namespace Umbraco.Web.PublishedCache case PropertyCacheLevel.Elements: // cache within the elements cache, depending... var snapshotCache = GetSnapshotCache(); - cacheValues = (CacheValues) snapshotCache?.GetCacheItem(ValuesCacheKey, () => new CacheValues()) ?? new CacheValues(); + cacheValues = (CacheValues) snapshotCache?.Get(ValuesCacheKey, () => new CacheValues()) ?? new CacheValues(); break; case PropertyCacheLevel.Snapshot: // cache within the snapshot cache var facadeCache = _publishedSnapshotAccessor?.PublishedSnapshot?.SnapshotCache; - cacheValues = (CacheValues) facadeCache?.GetCacheItem(ValuesCacheKey, () => new CacheValues()) ?? new CacheValues(); + cacheValues = (CacheValues) facadeCache?.Get(ValuesCacheKey, () => new CacheValues()) ?? new CacheValues(); break; default: throw new InvalidOperationException("Invalid cache level."); diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/DictionaryPublishedContent.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/DictionaryPublishedContent.cs index 6f6a39144a..ea38af314f 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/DictionaryPublishedContent.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/DictionaryPublishedContent.cs @@ -35,7 +35,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache Func getParent, Func> getChildren, Func getProperty, - ICacheProvider cacheProvider, + IAppCache cacheProvider, PublishedContentTypeCache contentTypeCache, XPathNavigator nav, bool fromExamine) @@ -133,7 +133,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache //private readonly Func> _getChildren; private readonly Lazy> _getChildren; private readonly Func _getProperty; - private readonly ICacheProvider _cacheProvider; + private readonly IAppCache _cacheProvider; /// /// Returns 'Media' as the item type diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedContentCache.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedContentCache.cs index e022e36fc0..67813ce9f6 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedContentCache.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedContentCache.cs @@ -15,7 +15,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache { internal class PublishedContentCache : PublishedCacheBase, IPublishedContentCache { - private readonly ICacheProvider _cacheProvider; + private readonly IAppCache _cacheProvider; private readonly IGlobalSettings _globalSettings; private readonly RoutesCache _routesCache; private readonly IDomainCache _domainCache; @@ -30,7 +30,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache public PublishedContentCache( XmlStore xmlStore, // an XmlStore containing the master xml IDomainCache domainCache, // an IDomainCache implementation - ICacheProvider cacheProvider, // an ICacheProvider that should be at request-level + IAppCache cacheProvider, // an ICacheProvider that should be at request-level IGlobalSettings globalSettings, ISiteDomainHelper siteDomainHelper, PublishedContentTypeCache contentTypeCache, // a PublishedContentType cache @@ -517,7 +517,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache // clear recursive properties cached by XmlPublishedContent.GetProperty // assume that nothing else is going to cache IPublishedProperty items (else would need to do ByKeySearch) // NOTE also clears all the media cache properties, which is OK (see media cache) - _cacheProvider.ClearCacheObjectTypes(); + _cacheProvider.ClearOfType(); //_cacheProvider.ClearCacheByKeySearch("XmlPublishedCache.PublishedContentCache:RecursiveProperty-"); } diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs index 09b76b5c2e..3ead5a5166 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs @@ -43,9 +43,9 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache private readonly IEntityXmlSerializer _entitySerializer; // must be specified by the ctor - private readonly ICacheProvider _cacheProvider; + private readonly IAppCache _cacheProvider; - public PublishedMediaCache(XmlStore xmlStore, IMediaService mediaService, IUserService userService, ICacheProvider cacheProvider, PublishedContentTypeCache contentTypeCache, IEntityXmlSerializer entitySerializer) + public PublishedMediaCache(XmlStore xmlStore, IMediaService mediaService, IUserService userService, IAppCache cacheProvider, PublishedContentTypeCache contentTypeCache, IEntityXmlSerializer entitySerializer) : base(false) { _mediaService = mediaService ?? throw new ArgumentNullException(nameof(mediaService)); @@ -66,7 +66,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache /// /// /// - internal PublishedMediaCache(IMediaService mediaService, IUserService userService, ISearcher searchProvider, ICacheProvider cacheProvider, PublishedContentTypeCache contentTypeCache, IEntityXmlSerializer entitySerializer) + internal PublishedMediaCache(IMediaService mediaService, IUserService userService, ISearcher searchProvider, IAppCache cacheProvider, PublishedContentTypeCache contentTypeCache, IEntityXmlSerializer entitySerializer) : base(false) { _mediaService = mediaService ?? throw new ArgumentNullException(nameof(mediaService)); @@ -678,7 +678,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache var cache = Current.ApplicationCache.RuntimeCache; var key = PublishedMediaCacheKey + id; - return (CacheValues)cache.GetCacheItem(key, () => func(id), _publishedMediaCacheTimespan); + return (CacheValues)cache.Get(key, () => func(id), _publishedMediaCacheTimespan); } internal static void ClearCache(int id) @@ -696,11 +696,11 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache // cache.ClearCacheItem(PublishedMediaCacheKey + GetValuesValue(exist.Values, "parentID")); // clear the item - cache.ClearCacheItem(key); + cache.Clear(key); // clear all children - in case we moved and their path has changed var fid = "/" + sid + "/"; - cache.ClearCacheObjectTypes((k, v) => + cache.ClearOfType((k, v) => GetValuesValue(v.Values, "path", "__Path").Contains(fid)); } diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMemberCache.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMemberCache.cs index 2328a1cefd..a622a4934c 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMemberCache.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMemberCache.cs @@ -13,11 +13,11 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache class PublishedMemberCache : IPublishedMemberCache { private readonly IMemberService _memberService; - private readonly ICacheProvider _requestCache; + private readonly IAppCache _requestCache; private readonly XmlStore _xmlStore; private readonly PublishedContentTypeCache _contentTypeCache; - public PublishedMemberCache(XmlStore xmlStore, ICacheProvider requestCacheProvider, IMemberService memberService, PublishedContentTypeCache contentTypeCache) + public PublishedMemberCache(XmlStore xmlStore, IAppCache requestCacheProvider, IMemberService memberService, PublishedContentTypeCache contentTypeCache) { _requestCache = requestCacheProvider; _memberService = memberService; diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedSnapshot.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedSnapshot.cs index 61ea7d2534..b9243309a2 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedSnapshot.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedSnapshot.cs @@ -38,10 +38,10 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache public IDomainCache Domains { get; } /// - public ICacheProvider SnapshotCache => null; + public IAppCache SnapshotCache => null; /// - public ICacheProvider ElementsCache => null; + public IAppCache ElementsCache => null; /// public IDisposable ForcedPreview(bool preview, Action callback = null) diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedSnapshotService.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedSnapshotService.cs index e286e9d95c..c4ce05c9a9 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedSnapshotService.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedSnapshotService.cs @@ -30,7 +30,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache private readonly IMemberService _memberService; private readonly IMediaService _mediaService; private readonly IUserService _userService; - private readonly ICacheProvider _requestCache; + private readonly IAppCache _requestCache; private readonly IGlobalSettings _globalSettings; private readonly IDefaultCultureAccessor _defaultCultureAccessor; private readonly ISiteDomainHelper _siteDomainHelper; @@ -42,7 +42,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache public PublishedSnapshotService(ServiceContext serviceContext, IPublishedContentTypeFactory publishedContentTypeFactory, IScopeProvider scopeProvider, - ICacheProvider requestCache, + IAppCache requestCache, IPublishedSnapshotAccessor publishedSnapshotAccessor, IVariationContextAccessor variationContextAccessor, IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository, IDefaultCultureAccessor defaultCultureAccessor, @@ -63,7 +63,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache internal PublishedSnapshotService(ServiceContext serviceContext, IPublishedContentTypeFactory publishedContentTypeFactory, IScopeProvider scopeProvider, - ICacheProvider requestCache, + IAppCache requestCache, IPublishedSnapshotAccessor publishedSnapshotAccessor, IVariationContextAccessor variationContextAccessor, IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository, IDefaultCultureAccessor defaultCultureAccessor, diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlPublishedContent.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlPublishedContent.cs index efd4535bd4..a1fda17df1 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlPublishedContent.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlPublishedContent.cs @@ -20,7 +20,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache [XmlType(Namespace = "http://umbraco.org/webservices/")] internal class XmlPublishedContent : PublishedContentBase { - private XmlPublishedContent(XmlNode xmlNode, bool isPreviewing, ICacheProvider cacheProvider, PublishedContentTypeCache contentTypeCache) + private XmlPublishedContent(XmlNode xmlNode, bool isPreviewing, IAppCache cacheProvider, PublishedContentTypeCache contentTypeCache) { _xmlNode = xmlNode; _isPreviewing = isPreviewing; @@ -31,7 +31,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache private readonly XmlNode _xmlNode; private readonly bool _isPreviewing; - private readonly ICacheProvider _cacheProvider; // at snapshot/request level (see PublishedContentCache) + private readonly IAppCache _cacheProvider; // at snapshot/request level (see PublishedContentCache) private readonly PublishedContentTypeCache _contentTypeCache; private readonly object _initializeLock = new object(); @@ -426,7 +426,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache /// Maintains a per-request cache of IPublishedContent items in order to make /// sure that we create only one instance of each for the duration of a request. The /// returned IPublishedContent is a model, if models are enabled. - public static IPublishedContent Get(XmlNode node, bool isPreviewing, ICacheProvider cacheProvider, PublishedContentTypeCache contentTypeCache) + public static IPublishedContent Get(XmlNode node, bool isPreviewing, IAppCache cacheProvider, PublishedContentTypeCache contentTypeCache) { // only 1 per request @@ -434,12 +434,12 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache var id = attrs?.GetNamedItem("id").Value; if (id.IsNullOrWhiteSpace()) throw new InvalidOperationException("Node has no ID attribute."); var key = CacheKeyPrefix + id; // dont bother with preview, wont change during request in Xml cache - return (IPublishedContent) cacheProvider.GetCacheItem(key, () => (new XmlPublishedContent(node, isPreviewing, cacheProvider, contentTypeCache)).CreateModel()); + return (IPublishedContent) cacheProvider.Get(key, () => (new XmlPublishedContent(node, isPreviewing, cacheProvider, contentTypeCache)).CreateModel()); } public static void ClearRequest() { - Current.ApplicationCache.RequestCache.ClearCacheByKeySearch(CacheKeyPrefix); + Current.ApplicationCache.RequestCache.ClearByKey(CacheKeyPrefix); } private const string CacheKeyPrefix = "CONTENTCACHE_XMLPUBLISHEDCONTENT_"; diff --git a/src/Umbraco.Web/Runtime/WebRuntime.cs b/src/Umbraco.Web/Runtime/WebRuntime.cs index c69a3bec8b..e9d27a2a1c 100644 --- a/src/Umbraco.Web/Runtime/WebRuntime.cs +++ b/src/Umbraco.Web/Runtime/WebRuntime.cs @@ -62,14 +62,14 @@ namespace Umbraco.Web.Runtime protected override AppCaches GetAppCaches() => new AppCaches( // we need to have the dep clone runtime cache provider to ensure // all entities are cached properly (cloned in and cloned out) - new DeepCloneRuntimeCacheProvider(new HttpRuntimeCacheProvider(HttpRuntime.Cache)), - new StaticCacheProvider(), + new DeepCloneAppCache(new WebCachingAppCache(HttpRuntime.Cache)), + new DictionaryCacheProvider(), // we need request based cache when running in web-based context - new HttpRequestCacheProvider(), - new IsolatedRuntimeCache(type => + new HttpRequestAppCache(), + new IsolatedCaches(type => // we need to have the dep clone runtime cache provider to ensure // all entities are cached properly (cloned in and cloned out) - new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()))); + new DeepCloneAppCache(new ObjectCacheAppCache()))); #endregion } diff --git a/src/Umbraco.Web/Services/ApplicationTreeService.cs b/src/Umbraco.Web/Services/ApplicationTreeService.cs index 2ddec054c7..30d50e136c 100644 --- a/src/Umbraco.Web/Services/ApplicationTreeService.cs +++ b/src/Umbraco.Web/Services/ApplicationTreeService.cs @@ -357,7 +357,7 @@ namespace Umbraco.Web.Services //remove the cache now that it has changed SD: I'm leaving this here even though it // is taken care of by events as well, I think unit tests may rely on it being cleared here. - _cache.RuntimeCache.ClearCacheItem(CacheKeys.ApplicationTreeCacheKey); + _cache.RuntimeCache.Clear(CacheKeys.ApplicationTreeCacheKey); } } } diff --git a/src/Umbraco.Web/Services/SectionService.cs b/src/Umbraco.Web/Services/SectionService.cs index 2d06141292..09972a6dca 100644 --- a/src/Umbraco.Web/Services/SectionService.cs +++ b/src/Umbraco.Web/Services/SectionService.cs @@ -132,7 +132,7 @@ namespace Umbraco.Web.Services //remove the cache so it gets re-read ... SD: I'm leaving this here even though it // is taken care of by events as well, I think unit tests may rely on it being cleared here. - _cache.RuntimeCache.ClearCacheItem(CacheKeys.ApplicationsCacheKey); + _cache.RuntimeCache.Clear(CacheKeys.ApplicationsCacheKey); } } } From d4c714eccd0a6097865998ca9d01ba39e4898517 Mon Sep 17 00:00:00 2001 From: Stephan Date: Thu, 17 Jan 2019 11:19:06 +0100 Subject: [PATCH 411/469] Stop injecting the runtime cache, use AppCaches --- src/Umbraco.Core/Cache/ObjectCacheAppCache.cs | 2 +- .../Composing/Composers/ServicesComposer.cs | 2 +- .../Composing/CompositionExtensions.cs | 1 - src/Umbraco.Core/ConfigsExtensions.cs | 4 ++-- .../Configuration/Grid/GridConfig.cs | 4 ++-- .../Configuration/Grid/GridEditorsConfig.cs | 10 +++++----- src/Umbraco.Core/Manifest/ManifestParser.cs | 9 +++++---- .../Implement/DictionaryRepository.cs | 4 ++-- .../Implement/RepositoryBaseOfTIdTEntity.cs | 12 ++++++------ .../Implement/ServerRegistrationRepository.cs | 2 +- src/Umbraco.Core/Runtime/CoreRuntime.cs | 3 +-- .../LocalizedTextServiceFileSources.cs | 17 ++++++----------- .../Manifest/ManifestParserTests.cs | 2 +- .../Models/Mapping/AutoMapperTests.cs | 2 +- .../Scoping/ScopedRepositoryTests.cs | 2 +- src/Umbraco.Tests/TestHelpers/TestObjects.cs | 2 +- src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 9 ++++----- .../Editors/ExamineManagementController.cs | 15 ++++----------- .../Models/Mapping/UserMapperProfile.cs | 8 ++++---- 19 files changed, 48 insertions(+), 62 deletions(-) diff --git a/src/Umbraco.Core/Cache/ObjectCacheAppCache.cs b/src/Umbraco.Core/Cache/ObjectCacheAppCache.cs index 9c5917a53c..954622fc4b 100644 --- a/src/Umbraco.Core/Cache/ObjectCacheAppCache.cs +++ b/src/Umbraco.Core/Cache/ObjectCacheAppCache.cs @@ -31,7 +31,7 @@ namespace Umbraco.Core.Cache /// /// Gets the internal memory cache, for tests only! /// - internal readonly ObjectCache MemoryCache; + internal ObjectCache MemoryCache { get; private set; } /// public object Get(string key) diff --git a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs index 9ed4a7265c..2af7c5a011 100644 --- a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs @@ -116,7 +116,7 @@ namespace Umbraco.Core.Composing.Composers return new LocalizedTextServiceFileSources( container.GetInstance(), - container.GetInstance().RuntimeCache, + container.GetInstance(), mainLangFolder, pluginLangFolders.Concat(userLangFolders)); } diff --git a/src/Umbraco.Core/Composing/CompositionExtensions.cs b/src/Umbraco.Core/Composing/CompositionExtensions.cs index 910062688c..c312259b82 100644 --- a/src/Umbraco.Core/Composing/CompositionExtensions.cs +++ b/src/Umbraco.Core/Composing/CompositionExtensions.cs @@ -28,7 +28,6 @@ namespace Umbraco.Core.Composing composition.RegisterUnique(profilingLogger); composition.RegisterUnique(mainDom); composition.RegisterUnique(appCaches); - composition.RegisterUnique(factory => factory.GetInstance().RuntimeCache); composition.RegisterUnique(databaseFactory); composition.RegisterUnique(factory => factory.GetInstance().SqlContext); composition.RegisterUnique(typeLoader); diff --git a/src/Umbraco.Core/ConfigsExtensions.cs b/src/Umbraco.Core/ConfigsExtensions.cs index 9b2abda53c..0fcea5f430 100644 --- a/src/Umbraco.Core/ConfigsExtensions.cs +++ b/src/Umbraco.Core/ConfigsExtensions.cs @@ -46,7 +46,7 @@ namespace Umbraco.Core 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().Debug)); + configs.Add(factory => new GridConfig(factory.GetInstance(), factory.GetInstance(), configDir, factory.GetInstance().Debug)); } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Core/Configuration/Grid/GridConfig.cs b/src/Umbraco.Core/Configuration/Grid/GridConfig.cs index 979eccb839..b2dae09fc9 100644 --- a/src/Umbraco.Core/Configuration/Grid/GridConfig.cs +++ b/src/Umbraco.Core/Configuration/Grid/GridConfig.cs @@ -6,9 +6,9 @@ namespace Umbraco.Core.Configuration.Grid { class GridConfig : IGridConfig { - public GridConfig(ILogger logger, IAppPolicedCache runtimeCache, DirectoryInfo configFolder, bool isDebug) + public GridConfig(ILogger logger, AppCaches appCaches, DirectoryInfo configFolder, bool isDebug) { - EditorsConfig = new GridEditorsConfig(logger, runtimeCache, configFolder, isDebug); + EditorsConfig = new GridEditorsConfig(logger, appCaches, configFolder, isDebug); } public IGridEditorsConfig EditorsConfig { get; } diff --git a/src/Umbraco.Core/Configuration/Grid/GridEditorsConfig.cs b/src/Umbraco.Core/Configuration/Grid/GridEditorsConfig.cs index 121b74194c..e2f99a753b 100644 --- a/src/Umbraco.Core/Configuration/Grid/GridEditorsConfig.cs +++ b/src/Umbraco.Core/Configuration/Grid/GridEditorsConfig.cs @@ -13,14 +13,14 @@ namespace Umbraco.Core.Configuration.Grid internal class GridEditorsConfig : IGridEditorsConfig { private readonly ILogger _logger; - private readonly IAppPolicedCache _runtimeCache; + private readonly AppCaches _appCaches; private readonly DirectoryInfo _configFolder; private readonly bool _isDebug; - public GridEditorsConfig(ILogger logger, IAppPolicedCache runtimeCache, DirectoryInfo configFolder, bool isDebug) + public GridEditorsConfig(ILogger logger, AppCaches appCaches, DirectoryInfo configFolder, bool isDebug) { _logger = logger; - _runtimeCache = runtimeCache; + _appCaches = appCaches; _configFolder = configFolder; _isDebug = isDebug; } @@ -32,7 +32,7 @@ namespace Umbraco.Core.Configuration.Grid List GetResult() { // fixme - should use the common one somehow! + ignoring _appPlugins here! - var parser = new ManifestParser(_runtimeCache, Current.ManifestValidators, _logger); + var parser = new ManifestParser(_appCaches, Current.ManifestValidators, _logger); var editors = new List(); var gridConfig = Path.Combine(_configFolder.FullName, "grid.editors.config.js"); @@ -62,7 +62,7 @@ namespace Umbraco.Core.Configuration.Grid //cache the result if debugging is disabled var result = _isDebug ? GetResult() - : _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/Manifest/ManifestParser.cs b/src/Umbraco.Core/Manifest/ManifestParser.cs index fd344674af..40e99bb079 100644 --- a/src/Umbraco.Core/Manifest/ManifestParser.cs +++ b/src/Umbraco.Core/Manifest/ManifestParser.cs @@ -29,16 +29,17 @@ namespace Umbraco.Core.Manifest /// /// Initializes a new instance of the class. /// - public ManifestParser(IAppPolicedCache cache, ManifestValueValidatorCollection validators, ILogger logger) - : this(cache, validators, "~/App_Plugins", logger) + public ManifestParser(AppCaches appCaches, ManifestValueValidatorCollection validators, ILogger logger) + : this(appCaches, validators, "~/App_Plugins", logger) { } /// /// Initializes a new instance of the class. /// - private ManifestParser(IAppPolicedCache cache, ManifestValueValidatorCollection validators, string path, ILogger logger) + private ManifestParser(AppCaches appCaches, ManifestValueValidatorCollection validators, string path, ILogger logger) { - _cache = cache ?? throw new ArgumentNullException(nameof(cache)); + if (appCaches == null) throw new ArgumentNullException(nameof(appCaches)); + _cache = appCaches.RuntimeCache; _validators = validators ?? throw new ArgumentNullException(nameof(validators)); if (string.IsNullOrWhiteSpace(path)) throw new ArgumentNullOrEmptyException(nameof(path)); Path = path; diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/DictionaryRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/DictionaryRepository.cs index 9b191d830c..be1e28fcc1 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/DictionaryRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/DictionaryRepository.cs @@ -224,13 +224,13 @@ namespace Umbraco.Core.Persistence.Repositories.Implement public IDictionaryItem Get(Guid uniqueId) { - var uniqueIdRepo = new DictionaryByUniqueIdRepository(this, ScopeAccessor, GlobalCache, Logger); + var uniqueIdRepo = new DictionaryByUniqueIdRepository(this, ScopeAccessor, AppCaches, Logger); return uniqueIdRepo.Get(uniqueId); } public IDictionaryItem Get(string key) { - var keyRepo = new DictionaryByKeyRepository(this, ScopeAccessor, GlobalCache, Logger); + var keyRepo = new DictionaryByKeyRepository(this, ScopeAccessor, AppCaches, Logger); return keyRepo.Get(key); } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/RepositoryBaseOfTIdTEntity.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/RepositoryBaseOfTIdTEntity.cs index f106949c77..6862173786 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/RepositoryBaseOfTIdTEntity.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/RepositoryBaseOfTIdTEntity.cs @@ -19,18 +19,18 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { private IRepositoryCachePolicy _cachePolicy; - protected RepositoryBase(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger) + protected RepositoryBase(IScopeAccessor scopeAccessor, AppCaches appCaches, ILogger logger) { ScopeAccessor = scopeAccessor ?? throw new ArgumentNullException(nameof(scopeAccessor)); Logger = logger ?? throw new ArgumentNullException(nameof(logger)); - GlobalCache = cache ?? throw new ArgumentNullException(nameof(cache)); + AppCaches = appCaches ?? throw new ArgumentNullException(nameof(appCaches)); } protected ILogger Logger { get; } - protected AppCaches GlobalCache { get; } + protected AppCaches AppCaches { get; } - protected IAppPolicedCache GlobalIsolatedCache => GlobalCache.IsolatedCaches.GetOrCreate(); + protected IAppPolicedCache GlobalIsolatedCache => AppCaches.IsolatedCaches.GetOrCreate(); protected IScopeAccessor ScopeAccessor { get; } @@ -67,7 +67,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement switch (AmbientScope.RepositoryCacheMode) { case RepositoryCacheMode.Default: - return GlobalCache.IsolatedCaches.GetOrCreate(); + return AppCaches.IsolatedCaches.GetOrCreate(); case RepositoryCacheMode.Scoped: return AmbientScope.IsolatedCaches.GetOrCreate(); case RepositoryCacheMode.None: @@ -127,7 +127,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { get { - if (GlobalCache == AppCaches.NoCache) + if (AppCaches == AppCaches.NoCache) return NoCacheRepositoryCachePolicy.Instance; // create the cache policy using IsolatedCache which is either global diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/ServerRegistrationRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/ServerRegistrationRepository.cs index ead7c066be..298e503736 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/ServerRegistrationRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/ServerRegistrationRepository.cs @@ -28,7 +28,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement // and this is because the repository is special and should not participate in scopes // (cleanup in v8) // - return new FullDataSetRepositoryCachePolicy(GlobalCache.RuntimeCache, ScopeAccessor, GetEntityId, /*expires:*/ false); + return new FullDataSetRepositoryCachePolicy(AppCaches.RuntimeCache, ScopeAccessor, GetEntityId, /*expires:*/ false); } public void ClearCache() diff --git a/src/Umbraco.Core/Runtime/CoreRuntime.cs b/src/Umbraco.Core/Runtime/CoreRuntime.cs index e37b5e254e..6bfe9cdb55 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntime.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntime.cs @@ -102,7 +102,6 @@ namespace Umbraco.Core.Runtime // application caches var appCaches = GetAppCaches(); - var runtimeCache = appCaches.RuntimeCache; // database factory var databaseFactory = GetDatabaseFactory(); @@ -112,7 +111,7 @@ namespace Umbraco.Core.Runtime // type loader var localTempStorage = configs.Global().LocalTempStorageLocation; - var typeLoader = new TypeLoader(runtimeCache, localTempStorage, ProfilingLogger); + var typeLoader = new TypeLoader(appCaches.RuntimeCache, localTempStorage, ProfilingLogger); // runtime state // beware! must use '() => _factory.GetInstance()' and NOT '_factory.GetInstance' diff --git a/src/Umbraco.Core/Services/Implement/LocalizedTextServiceFileSources.cs b/src/Umbraco.Core/Services/Implement/LocalizedTextServiceFileSources.cs index 5577508adb..8c2d277348 100644 --- a/src/Umbraco.Core/Services/Implement/LocalizedTextServiceFileSources.cs +++ b/src/Umbraco.Core/Services/Implement/LocalizedTextServiceFileSources.cs @@ -37,16 +37,16 @@ namespace Umbraco.Core.Services.Implement /// public LocalizedTextServiceFileSources( ILogger logger, - IAppPolicedCache cache, + AppCaches appCaches, DirectoryInfo fileSourceFolder, IEnumerable supplementFileSources) { if (logger == null) throw new ArgumentNullException("logger"); - if (cache == null) throw new ArgumentNullException("cache"); + if (appCaches == null) throw new ArgumentNullException("cache"); if (fileSourceFolder == null) throw new ArgumentNullException("fileSourceFolder"); _logger = logger; - _cache = cache; + _cache = appCaches.RuntimeCache; //Create the lazy source for the _xmlSources _xmlSources = new Lazy>>(() => @@ -137,14 +137,9 @@ namespace Umbraco.Core.Services.Implement /// /// Constructor /// - /// - /// - /// - public LocalizedTextServiceFileSources(ILogger logger, IAppPolicedCache cache, DirectoryInfo fileSourceFolder) - : this(logger, cache, fileSourceFolder, Enumerable.Empty()) - { - - } + public LocalizedTextServiceFileSources(ILogger logger, AppCaches appCaches, DirectoryInfo fileSourceFolder) + : this(logger, appCaches, fileSourceFolder, Enumerable.Empty()) + { } /// /// returns all xml sources for all culture files found in the folder diff --git a/src/Umbraco.Tests/Manifest/ManifestParserTests.cs b/src/Umbraco.Tests/Manifest/ManifestParserTests.cs index 74f9fd7157..3f1e668dc0 100644 --- a/src/Umbraco.Tests/Manifest/ManifestParserTests.cs +++ b/src/Umbraco.Tests/Manifest/ManifestParserTests.cs @@ -44,7 +44,7 @@ namespace Umbraco.Tests.Manifest new RequiredValidator(Mock.Of()), new RegexValidator(Mock.Of(), null) }; - _parser = new ManifestParser(NoAppCache.Instance, new ManifestValueValidatorCollection(validators), Mock.Of()); + _parser = new ManifestParser(AppCaches.Disabled, new ManifestValueValidatorCollection(validators), Mock.Of()); } [Test] diff --git a/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs b/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs index f48abc1233..57d38e342e 100644 --- a/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs +++ b/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs @@ -20,7 +20,7 @@ namespace Umbraco.Tests.Models.Mapping base.Compose(); var manifestBuilder = new ManifestParser( - AppCaches.Disabled.RuntimeCache, + AppCaches.Disabled, new ManifestValueValidatorCollection(Enumerable.Empty()), Composition.Logger) { diff --git a/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs b/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs index 6e01de1670..12cd02d2e9 100644 --- a/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs @@ -37,7 +37,7 @@ namespace Umbraco.Tests.Scoping .Add(() => Composition.TypeLoader.GetCacheRefreshers()); } - protected override AppCaches GetCacheHelper() + protected override AppCaches GetAppCaches() { // this is what's created core web runtime return new AppCaches( diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects.cs b/src/Umbraco.Tests/TestHelpers/TestObjects.cs index 29eb649c48..34c97fcea2 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects.cs @@ -140,7 +140,7 @@ namespace Umbraco.Tests.TestHelpers return new LocalizedTextServiceFileSources( logger, - cache.RuntimeCache, + cache, mainLangFolder, pluginLangFolders.Concat(userLangFolders)); diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index 2d6e01b6bb..fd617b5a21 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -125,9 +125,9 @@ namespace Umbraco.Tests.Testing var (logger, profiler) = GetLoggers(Options.Logger); var proflogger = new ProfilingLogger(logger, profiler); - var cacheHelper = GetCacheHelper(); + var appCaches = GetAppCaches(); var globalSettings = SettingsForTests.GetDefaultGlobalSettings(); - var typeLoader = GetTypeLoader(cacheHelper.RuntimeCache, globalSettings, proflogger, Options.TypeLoader); + var typeLoader = GetTypeLoader(appCaches.RuntimeCache, globalSettings, proflogger, Options.TypeLoader); var register = RegisterFactory.Create(); @@ -137,8 +137,7 @@ namespace Umbraco.Tests.Testing Composition.RegisterUnique(logger); Composition.RegisterUnique(profiler); Composition.RegisterUnique(proflogger); - Composition.RegisterUnique(cacheHelper); - Composition.RegisterUnique(cacheHelper.RuntimeCache); + Composition.RegisterUnique(appCaches); TestObjects = new TestObjects(register); Compose(); @@ -199,7 +198,7 @@ namespace Umbraco.Tests.Testing return (logger, profiler); } - protected virtual AppCaches GetCacheHelper() + protected virtual AppCaches GetAppCaches() { return AppCaches.Disabled; } diff --git a/src/Umbraco.Web/Editors/ExamineManagementController.cs b/src/Umbraco.Web/Editors/ExamineManagementController.cs index db9de424a9..8d930b8ed7 100644 --- a/src/Umbraco.Web/Editors/ExamineManagementController.cs +++ b/src/Umbraco.Web/Editors/ExamineManagementController.cs @@ -1,26 +1,19 @@ using System; using System.Collections.Generic; -using System.ComponentModel; using System.Linq; using System.Net; using System.Net.Http; -using System.Reflection; using System.Web.Http; using Examine; -using Examine.LuceneEngine; using Examine.LuceneEngine.Providers; -using Lucene.Net.Analysis; -using Lucene.Net.QueryParsers; using Umbraco.Core; using Umbraco.Core.Cache; -using Umbraco.Core.Composing; using Umbraco.Core.Logging; using Umbraco.Examine; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Mvc; using Umbraco.Web.Search; using SearchResult = Umbraco.Web.Models.ContentEditing.SearchResult; -using Version = Lucene.Net.Util.Version; namespace Umbraco.Web.Editors { @@ -29,17 +22,17 @@ namespace Umbraco.Web.Editors { private readonly IExamineManager _examineManager; private readonly ILogger _logger; - private readonly IAppPolicedCache _runtimeCacheProvider; + private readonly IAppPolicedCache _runtimeCache; private readonly IndexRebuilder _indexRebuilder; public ExamineManagementController(IExamineManager examineManager, ILogger logger, - IAppPolicedCache runtimeCacheProvider, + AppCaches appCaches, IndexRebuilder indexRebuilder) { _examineManager = examineManager; _logger = logger; - _runtimeCacheProvider = runtimeCacheProvider; + _runtimeCache = appCaches.RuntimeCache; _indexRebuilder = indexRebuilder; } @@ -269,7 +262,7 @@ namespace Umbraco.Web.Editors >($"Rebuilding index '{indexer.Name}' done, {indexer.CommitCount} items committed (can differ from the number of items in the index)"); var cacheKey = "temp_indexing_op_" + indexer.Name; - _runtimeCacheProvider.Clear(cacheKey); + _runtimeCache.Clear(cacheKey); } } } diff --git a/src/Umbraco.Web/Models/Mapping/UserMapperProfile.cs b/src/Umbraco.Web/Models/Mapping/UserMapperProfile.cs index 4b27af3120..b6fc94eb3c 100644 --- a/src/Umbraco.Web/Models/Mapping/UserMapperProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/UserMapperProfile.cs @@ -22,7 +22,7 @@ namespace Umbraco.Web.Models.Mapping => entity is ContentEntitySlim contentEntity ? contentEntity.ContentTypeIcon : null; public UserMapperProfile(ILocalizedTextService textService, IUserService userService, IEntityService entityService, ISectionService sectionService, - IAppPolicedCache runtimeCache, ActionCollection actions, IGlobalSettings globalSettings) + AppCaches appCaches, ActionCollection actions, IGlobalSettings globalSettings) { var userGroupDefaultPermissionsResolver = new UserGroupDefaultPermissionsResolver(textService, actions); @@ -243,7 +243,7 @@ namespace Umbraco.Web.Models.Mapping //Important! Currently we are never mapping to multiple UserDisplay objects but if we start doing that // this will cause an N+1 and we'll need to change how this works. CreateMap() - .ForMember(dest => dest.Avatars, opt => opt.MapFrom(user => user.GetUserAvatarUrls(runtimeCache))) + .ForMember(dest => dest.Avatars, opt => opt.MapFrom(user => user.GetUserAvatarUrls(appCaches.RuntimeCache))) .ForMember(dest => dest.Username, opt => opt.MapFrom(user => user.Username)) .ForMember(dest => dest.LastLoginDate, opt => opt.MapFrom(user => user.LastLoginDate == default(DateTime) ? null : (DateTime?)user.LastLoginDate)) .ForMember(dest => dest.UserGroups, opt => opt.MapFrom(user => user.Groups)) @@ -293,7 +293,7 @@ namespace Umbraco.Web.Models.Mapping //like the load time is waiting. .ForMember(detail => detail.Avatars, - opt => opt.MapFrom(user => user.GetUserAvatarUrls(runtimeCache))) + opt => opt.MapFrom(user => user.GetUserAvatarUrls(appCaches.RuntimeCache))) .ForMember(dest => dest.Username, opt => opt.MapFrom(user => user.Username)) .ForMember(dest => dest.UserGroups, opt => opt.MapFrom(user => user.Groups)) .ForMember(dest => dest.LastLoginDate, opt => opt.MapFrom(user => user.LastLoginDate == default(DateTime) ? null : (DateTime?)user.LastLoginDate)) @@ -313,7 +313,7 @@ namespace Umbraco.Web.Models.Mapping .ForMember(dest => dest.AdditionalData, opt => opt.Ignore()); CreateMap() - .ForMember(dest => dest.Avatars, opt => opt.MapFrom(user => user.GetUserAvatarUrls(runtimeCache))) + .ForMember(dest => dest.Avatars, opt => opt.MapFrom(user => user.GetUserAvatarUrls(appCaches.RuntimeCache))) .ForMember(dest => dest.UserId, opt => opt.MapFrom(user => GetIntId(user.Id))) .ForMember(dest => dest.StartContentIds, opt => opt.MapFrom(user => user.CalculateContentStartNodeIds(entityService))) .ForMember(dest => dest.StartMediaIds, opt => opt.MapFrom(user => user.CalculateMediaStartNodeIds(entityService))) From 0d0179cb476450b4c580efb95f5c6b785270e3e1 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Thu, 17 Jan 2019 12:14:17 +0100 Subject: [PATCH 412/469] Use constants in upgrade migration --- .../UpdateMemberGroupPickerData.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFourteenZero/UpdateMemberGroupPickerData.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFourteenZero/UpdateMemberGroupPickerData.cs index 2dbc69e58a..62cbeacc78 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFourteenZero/UpdateMemberGroupPickerData.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFourteenZero/UpdateMemberGroupPickerData.cs @@ -16,17 +16,17 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenFourtee public override void Up() { // move the data for all member group properties from the NVarchar to the NText column and clear the NVarchar column - Execute.Sql(@"UPDATE cmsPropertyData SET dataNtext = dataNvarchar, dataNvarchar = NULL + Execute.Sql($@"UPDATE cmsPropertyData SET dataNtext = dataNvarchar, dataNvarchar = NULL WHERE dataNtext IS NULL AND id IN ( SELECT id FROM cmsPropertyData WHERE propertyTypeId in ( SELECT id from cmsPropertyType where dataTypeID IN ( - SELECT nodeId FROM cmsDataType WHERE propertyEditorAlias = 'Umbraco.MemberGroupPicker' + SELECT nodeId FROM cmsDataType WHERE propertyEditorAlias = '{Constants.PropertyEditors.MemberGroupPickerAlias}' ) ) )"); // ensure that all exising member group properties are defined as NText - Execute.Sql("UPDATE cmsDataType SET dbType = 'Ntext' WHERE propertyEditorAlias = 'Umbraco.MemberGroupPicker'"); + Execute.Sql($"UPDATE cmsDataType SET dbType = 'Ntext' WHERE propertyEditorAlias = '{Constants.PropertyEditors.MemberGroupPickerAlias}'"); } public override void Down() From 77cf071e046dc54adb92194537d9b221d28eda5f Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Thu, 17 Jan 2019 12:20:13 +0100 Subject: [PATCH 413/469] Add "Move" option for deleted items in the media tree (#3914) --- .../views/media/media.restore.controller.js | 135 +++++++++++++----- .../src/views/media/restore.html | 97 +++++++++++-- 2 files changed, 187 insertions(+), 45 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/media/media.restore.controller.js b/src/Umbraco.Web.UI.Client/src/views/media/media.restore.controller.js index 6ef9232c37..bc02217660 100644 --- a/src/Umbraco.Web.UI.Client/src/views/media/media.restore.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/media/media.restore.controller.js @@ -1,63 +1,134 @@ angular.module("umbraco").controller("Umbraco.Editors.Media.RestoreController", - function ($scope, relationResource, mediaResource, navigationService, appState, treeService, localizationService) { + function ($scope, relationResource, mediaResource, navigationService, appState, treeService, userService) { var dialogOptions = $scope.dialogOptions; - var node = dialogOptions.currentNode; + $scope.source = _.clone(dialogOptions.currentNode); - $scope.error = null; - $scope.success = false; + $scope.error = null; + $scope.loading = true; + $scope.moving = false; + $scope.success = false; - relationResource.getByChildId(node.id, "relateParentDocumentOnDelete").then(function (data) { + $scope.dialogTreeEventHandler = $({}); + $scope.searchInfo = { + showSearch: false, + results: [], + selectedSearchResults: [] + } + $scope.treeModel = { + hideHeader: false + } + userService.getCurrentUser().then(function (userData) { + $scope.treeModel.hideHeader = userData.startContentIds.length > 0 && userData.startContentIds.indexOf(-1) == -1; + }); - if (data.length == 0) { - $scope.success = false; - $scope.error = { - errorMsg: localizationService.localize('recycleBin_itemCannotBeRestored'), - data: { - Message: localizationService.localize('recycleBin_noRestoreRelation') - } - } - return; + function nodeSelectHandler(ev, args) { + + if (args && args.event) { + args.event.preventDefault(); + args.event.stopPropagation(); } + if ($scope.target) { + //un-select if there's a current one selected + $scope.target.selected = false; + } + + $scope.target = args.node; + $scope.target.selected = true; + + } + + function nodeExpandedHandler(ev, args) { + // open mini list view for list views + if (args.node.metaData.isContainer) { + openMiniListView(args.node); + } + } + + $scope.hideSearch = function () { + $scope.searchInfo.showSearch = false; + $scope.searchInfo.results = []; + } + + // method to select a search result + $scope.selectResult = function (evt, result) { + result.selected = result.selected === true ? false : true; + nodeSelectHandler(evt, { event: evt, node: result }); + }; + + //callback when there are search results + $scope.onSearchResults = function (results) { + $scope.searchInfo.results = results; + $scope.searchInfo.showSearch = true; + }; + + $scope.dialogTreeEventHandler.bind("treeNodeSelect", nodeSelectHandler); + $scope.dialogTreeEventHandler.bind("treeNodeExpanded", nodeExpandedHandler); + + $scope.$on('$destroy', function () { + $scope.dialogTreeEventHandler.unbind("treeNodeSelect", nodeSelectHandler); + $scope.dialogTreeEventHandler.unbind("treeNodeExpanded", nodeExpandedHandler); + }); + + // Mini list view + $scope.selectListViewNode = function (node) { + node.selected = node.selected === true ? false : true; + nodeSelectHandler({}, { node: node }); + }; + + $scope.closeMiniListView = function () { + $scope.miniListView = undefined; + }; + + function openMiniListView(node) { + $scope.miniListView = node; + } + + relationResource.getByChildId($scope.source.id, "relateParentDocumentOnDelete").then(function (data) { + $scope.loading = false; + + if (!data.length) { + $scope.moving = true; + return; + } + $scope.relation = data[0]; if ($scope.relation.parentId == -1) { $scope.target = { id: -1, name: "Root" }; } else { + $scope.loading = true; + mediaResource.getById($scope.relation.parentId).then(function (data) { + $scope.loading = false; $scope.target = data; - // make sure the target item isn't in the recycle bin - if ($scope.target.path.indexOf("-20") !== -1) { - $scope.error = { - errorMsg: localizationService.localize('recycleBin_itemCannotBeRestored'), - data: { - Message: localizationService.localize('recycleBin_restoreUnderRecycled').then(function (value) { - value.replace('%0%', $scope.target.name); - }) - } - }; - $scope.success = false; + // make sure the target item isn't in the recycle bin + if ($scope.target.path.indexOf("-21") !== -1) { + $scope.moving = true; + $scope.target = null; } - }, function (err) { - $scope.success = false; + $scope.loading = false; $scope.error = err; }); } }, function (err) { - $scope.success = false; - $scope.error = err; + $scope.loading = false; + $scope.error = err; }); - $scope.restore = function () { + $scope.restore = function () { + $scope.loading = true; + // this code was copied from `content.move.controller.js` - mediaResource.move({ parentId: $scope.target.id, id: node.id }) + mediaResource.move({ parentId: $scope.target.id, id: $scope.source.id }) .then(function (path) { + $scope.loading = false; $scope.success = true; //first we need to remove the node that launched the dialog @@ -78,7 +149,7 @@ angular.module("umbraco").controller("Umbraco.Editors.Media.RestoreController", }); }, function (err) { - $scope.success = false; + $scope.loading = false; $scope.error = err; }); }; diff --git a/src/Umbraco.Web.UI.Client/src/views/media/restore.html b/src/Umbraco.Web.UI.Client/src/views/media/restore.html index 17fff154d1..a24700afe7 100644 --- a/src/Umbraco.Web.UI.Client/src/views/media/restore.html +++ b/src/Umbraco.Web.UI.Client/src/views/media/restore.html @@ -1,25 +1,96 @@
    -
    +
    + + -

    - Restore {{currentNode.name}} under {{target.name}}? -

    +
    +
    +
    {{error.errorMsg}}
    +
    {{error.data.Message}}
    +
    +
    -
    -
    {{error.errorMsg}}
    -
    {{error.data.Message}}
    -
    +
    +
    + {{source.name}} + was restored under + was moved underneath + {{target.name}} +
    + +
    -
    -

    {{currentNode.name}} was moved underneath {{target.name}}

    - -
    +
    + +

    + Restore {{source.name}} under {{target.name}}? +

    + +
    + +
    +
    +
    +
    Cannot automatically restore this item
    +
    There is no location where this item can be automatically restored. You can move the item manually using the tree below.
    +
    +
    + +
    + + + +
    + + + + +
    + + +
    +
    + + + + +
    -
    -
    Required alias
    -
    Invalid alias
    -
    {{lockedFieldForm.lockedField.errorMsg}}
    +
    + Required alias +
    +
    + Invalid alias +
    +
    {{lockedFieldForm.lockedField.errorMsg}} +
    From adc9957504dce78296f70c86557fc47f69af377c Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Wed, 16 Jan 2019 22:27:58 +0100 Subject: [PATCH 432/469] Show the media link in the info app --- .../views/components/media/umb-media-node-info.html | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/components/media/umb-media-node-info.html b/src/Umbraco.Web.UI.Client/src/views/components/media/umb-media-node-info.html index 2e09fbfa3b..4004c2b958 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/media/umb-media-node-info.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/media/umb-media-node-info.html @@ -5,16 +5,16 @@ -
    /// The content property value. + /// The value property type /// The content dependencies. /// The deploy property value. - string ToArtifact(object value, ICollection dependencies); + string ToArtifact(object value, PropertyType propertyType, ICollection dependencies); /// /// Gets the content property value corresponding to a deploy property value. From e42995cf101347d82ac3069ccb293711fde33f57 Mon Sep 17 00:00:00 2001 From: Stephan Date: Thu, 17 Jan 2019 18:03:07 +0100 Subject: [PATCH 441/469] Fixes for the IPublishedContent Linq/Culture PR --- .../PublishedContentDataTableTests.cs | 74 ++++----- .../PublishedContent/PublishedContentTests.cs | 156 +++++++++--------- .../Accessors/TestVariationContextAccessor.cs | 6 +- .../DictionaryPublishedContent.cs | 5 +- .../XmlPublishedCache/XmlPublishedContent.cs | 5 +- src/Umbraco.Web/PublishedContentExtensions.cs | 27 ++- 6 files changed, 140 insertions(+), 133 deletions(-) diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentDataTableTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentDataTableTests.cs index fa60b050cc..73f3cd1537 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentDataTableTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentDataTableTests.cs @@ -73,44 +73,44 @@ namespace Umbraco.Tests.PublishedContent Umbraco.Web.PublishedContentExtensions.GetPropertyAliasesAndNames = null; } -// [Test] -// public void To_DataTable() -// { -// var doc = GetContent(true, 1); -// var dt = doc.ChildrenAsTable(Current.Services); -// -// Assert.AreEqual(11, dt.Columns.Count); -// Assert.AreEqual(3, dt.Rows.Count); -// Assert.AreEqual("value4", dt.Rows[0]["Property 1"]); -// Assert.AreEqual("value5", dt.Rows[0]["Property 2"]); -// Assert.AreEqual("value6", dt.Rows[0]["Property 4"]); -// Assert.AreEqual("value7", dt.Rows[1]["Property 1"]); -// Assert.AreEqual("value8", dt.Rows[1]["Property 2"]); -// Assert.AreEqual("value9", dt.Rows[1]["Property 4"]); -// Assert.AreEqual("value10", dt.Rows[2]["Property 1"]); -// Assert.AreEqual("value11", dt.Rows[2]["Property 2"]); -// Assert.AreEqual("value12", dt.Rows[2]["Property 4"]); -// } + [Test] + public void To_DataTable() + { + var doc = GetContent(true, 1); + var dt = doc.ChildrenAsTable(Current.Services); -// [Test] -// public void To_DataTable_With_Filter() -// { -// var doc = GetContent(true, 1); -// //change a doc type alias -// var c = (TestPublishedContent) doc.Children.ElementAt(0); -// c.ContentType = new PublishedContentType(22, "DontMatch", PublishedItemType.Content, Enumerable.Empty(), Enumerable.Empty(), ContentVariation.Nothing); -// -// var dt = doc.ChildrenAsTable(Current.Services, "Child"); -// -// Assert.AreEqual(11, dt.Columns.Count); -// Assert.AreEqual(2, dt.Rows.Count); -// Assert.AreEqual("value7", dt.Rows[0]["Property 1"]); -// Assert.AreEqual("value8", dt.Rows[0]["Property 2"]); -// Assert.AreEqual("value9", dt.Rows[0]["Property 4"]); -// Assert.AreEqual("value10", dt.Rows[1]["Property 1"]); -// Assert.AreEqual("value11", dt.Rows[1]["Property 2"]); -// Assert.AreEqual("value12", dt.Rows[1]["Property 4"]); -// } + Assert.AreEqual(11, dt.Columns.Count); + Assert.AreEqual(3, dt.Rows.Count); + Assert.AreEqual("value4", dt.Rows[0]["Property 1"]); + Assert.AreEqual("value5", dt.Rows[0]["Property 2"]); + Assert.AreEqual("value6", dt.Rows[0]["Property 4"]); + Assert.AreEqual("value7", dt.Rows[1]["Property 1"]); + Assert.AreEqual("value8", dt.Rows[1]["Property 2"]); + Assert.AreEqual("value9", dt.Rows[1]["Property 4"]); + Assert.AreEqual("value10", dt.Rows[2]["Property 1"]); + Assert.AreEqual("value11", dt.Rows[2]["Property 2"]); + Assert.AreEqual("value12", dt.Rows[2]["Property 4"]); + } + + [Test] + public void To_DataTable_With_Filter() + { + var doc = GetContent(true, 1); + //change a doc type alias + var c = (TestPublishedContent)doc.Children.ElementAt(0); + c.ContentType = new PublishedContentType(22, "DontMatch", PublishedItemType.Content, Enumerable.Empty(), Enumerable.Empty(), ContentVariation.Nothing); + + var dt = doc.ChildrenAsTable(Current.Services, "Child"); + + Assert.AreEqual(11, dt.Columns.Count); + Assert.AreEqual(2, dt.Rows.Count); + Assert.AreEqual("value7", dt.Rows[0]["Property 1"]); + Assert.AreEqual("value8", dt.Rows[0]["Property 2"]); + Assert.AreEqual("value9", dt.Rows[0]["Property 4"]); + Assert.AreEqual("value10", dt.Rows[1]["Property 1"]); + Assert.AreEqual("value11", dt.Rows[1]["Property 2"]); + Assert.AreEqual("value12", dt.Rows[1]["Property 4"]); + } [Test] public void To_DataTable_No_Rows() diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs index 855d864cc4..603464e18b 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs @@ -326,18 +326,18 @@ namespace Umbraco.Tests.PublishedContent } } -// [Test] -// public void Descendants_Ordered_Properly() -// { -// var doc = GetNode(1046); -// -// var expected = new[] { 1046, 1173, 1174, 117, 1177, 1178, 1179, 1176, 1175, 4444, 1172 }; -// var exindex = 0; -// -// // must respect the XPath descendants-or-self axis! -// foreach (var d in doc.DescendantsOrSelf()) -// Assert.AreEqual(expected[exindex++], d.Id); -// } + [Test] + public void Descendants_Ordered_Properly() + { + var doc = GetNode(1046); + + var expected = new[] { 1046, 1173, 1174, 117, 1177, 1178, 1179, 1176, 1175, 4444, 1172 }; + var exindex = 0; + + // must respect the XPath descendants-or-self axis! + foreach (var d in doc.DescendantsOrSelf()) + Assert.AreEqual(expected[exindex++], d.Id); + } [Test] public void Get_Property_Value_Recursive() @@ -367,18 +367,18 @@ namespace Umbraco.Tests.PublishedContent Assert.AreEqual("
    This is some content
    ", propVal3.ToString()); } -// [Test] -// public void Complex_Linq() -// { -// var doc = GetNode(1173); -// -// var result = doc.Ancestors().OrderBy(x => x.Level) -// .Single() -// .Descendants() -// .FirstOrDefault(x => x.Value("selectedNodes", defaultValue: "").Split(',').Contains("1173")); -// -// Assert.IsNotNull(result); -// } + [Test] + public void Complex_Linq() + { + var doc = GetNode(1173); + + var result = doc.Ancestors().OrderBy(x => x.Level) + .Single() + .Descendants() + .FirstOrDefault(x => x.Value("selectedNodes", defaultValue: "").Split(',').Contains("1173")); + + Assert.IsNotNull(result); + } [Test] public void Children_GroupBy_DocumentTypeAlias() @@ -437,36 +437,36 @@ namespace Umbraco.Tests.PublishedContent } -// [Test] -// public void FirstChild() -// { -// var doc = GetNode(1173); // has child nodes -// Assert.IsNotNull(doc.FirstChild()); -// Assert.IsNotNull(doc.FirstChild(x => true)); -// Assert.IsNotNull(doc.FirstChild()); -// -// doc = GetNode(1175); // does not have child nodes -// Assert.IsNull(doc.FirstChild()); -// Assert.IsNull(doc.FirstChild(x => true)); -// Assert.IsNull(doc.FirstChild()); -// } + [Test] + public void FirstChild() + { + var doc = GetNode(1173); // has child nodes + Assert.IsNotNull(doc.FirstChild()); + Assert.IsNotNull(doc.FirstChild(x => true)); + Assert.IsNotNull(doc.FirstChild()); -// [Test] -// public void FirstChildAsT() -// { -// var doc = GetNode(1046); // has child nodes -// -// var model = doc.FirstChild(x => true); // predicate -// -// Assert.IsNotNull(model); -// Assert.IsTrue(model.Id == 1173); -// Assert.IsInstanceOf(model); -// Assert.IsInstanceOf(model); -// -// doc = GetNode(1175); // does not have child nodes -// Assert.IsNull(doc.FirstChild()); -// Assert.IsNull(doc.FirstChild(x => true)); -// } + doc = GetNode(1175); // does not have child nodes + Assert.IsNull(doc.FirstChild()); + Assert.IsNull(doc.FirstChild(x => true)); + Assert.IsNull(doc.FirstChild()); + } + + [Test] + public void FirstChildAsT() + { + var doc = GetNode(1046); // has child nodes + + var model = doc.FirstChild(x => true); // predicate + + Assert.IsNotNull(model); + Assert.IsTrue(model.Id == 1173); + Assert.IsInstanceOf(model); + Assert.IsInstanceOf(model); + + doc = GetNode(1175); // does not have child nodes + Assert.IsNull(doc.FirstChild()); + Assert.IsNull(doc.FirstChild(x => true)); + } [Test] public void IsComposedOf() @@ -668,31 +668,31 @@ namespace Umbraco.Tests.PublishedContent } -// [Test] -// public void Descendants_Or_Self() -// { -// var doc = GetNode(1046); -// -// var result = doc.DescendantsOrSelf().ToArray(); -// -// Assert.IsNotNull(result); -// -// Assert.AreEqual(10, result.Count()); -// Assert.IsTrue(result.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1046, 1173, 1174, 1176, 1175 })); -// } -// -// [Test] -// public void Descendants() -// { -// var doc = GetNode(1046); -// -// var result = doc.Descendants().ToArray(); -// -// Assert.IsNotNull(result); -// -// Assert.AreEqual(9, result.Count()); -// Assert.IsTrue(result.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1173, 1174, 1176, 1175, 4444 })); -// } + [Test] + public void Descendants_Or_Self() + { + var doc = GetNode(1046); + + var result = doc.DescendantsOrSelf().ToArray(); + + Assert.IsNotNull(result); + + Assert.AreEqual(10, result.Count()); + Assert.IsTrue(result.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1046, 1173, 1174, 1176, 1175 })); + } + + [Test] + public void Descendants() + { + var doc = GetNode(1046); + + var result = doc.Descendants().ToArray(); + + Assert.IsNotNull(result); + + Assert.AreEqual(9, result.Count()); + Assert.IsTrue(result.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1173, 1174, 1176, 1175, 4444 })); + } [Test] public void IsDescendant() diff --git a/src/Umbraco.Tests/Testing/Objects/Accessors/TestVariationContextAccessor.cs b/src/Umbraco.Tests/Testing/Objects/Accessors/TestVariationContextAccessor.cs index 4b56799fa4..134b709447 100644 --- a/src/Umbraco.Tests/Testing/Objects/Accessors/TestVariationContextAccessor.cs +++ b/src/Umbraco.Tests/Testing/Objects/Accessors/TestVariationContextAccessor.cs @@ -8,10 +8,6 @@ namespace Umbraco.Tests.Testing.Objects.Accessors public class TestVariationContextAccessor : IVariationContextAccessor { /// - public VariationContext VariationContext - { - get; - set; - } = new VariationContext(); + public VariationContext VariationContext { get; set; } } } diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/DictionaryPublishedContent.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/DictionaryPublishedContent.cs index 6f6a39144a..c418b7a525 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/DictionaryPublishedContent.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/DictionaryPublishedContent.cs @@ -154,9 +154,10 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache public override string Name => _name; - public override PublishedCultureInfo GetCulture(string culture = null) => throw new NotSupportedException(); + public override PublishedCultureInfo GetCulture(string culture = null) => null; - public override IReadOnlyDictionary Cultures => throw new NotSupportedException(); + private static readonly Lazy> NoCultures = new Lazy>(() => new Dictionary()); + public override IReadOnlyDictionary Cultures => NoCultures.Value; public override string UrlSegment => _urlName; diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlPublishedContent.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlPublishedContent.cs index d8436c05b5..65c7dc7229 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlPublishedContent.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlPublishedContent.cs @@ -136,9 +136,10 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache } } - public override PublishedCultureInfo GetCulture(string culture = null) => throw new NotSupportedException(); + public override PublishedCultureInfo GetCulture(string culture = null) => null; - public override IReadOnlyDictionary Cultures => new Dictionary(); + private static readonly Lazy> NoCultures = new Lazy>(() => new Dictionary()); + public override IReadOnlyDictionary Cultures => NoCultures.Value; public override string WriterName { diff --git a/src/Umbraco.Web/PublishedContentExtensions.cs b/src/Umbraco.Web/PublishedContentExtensions.cs index 4efe6bc82b..0ada3d8c5b 100644 --- a/src/Umbraco.Web/PublishedContentExtensions.cs +++ b/src/Umbraco.Web/PublishedContentExtensions.cs @@ -267,19 +267,20 @@ namespace Umbraco.Web => content.Cultures.ContainsKey(culture); /// - /// Filter by the specific culture or invariant. If null is provided, the method uses the current culture instead. + /// Filters a sequence of to return invariant items, and items that are published for the specified culture. /// - /// The content. - /// The specific culture to filter for. If null is used the current culture is used. (Default is null) - /// These of the inputs that has the specified culture or are invariant. - internal static IEnumerable WhereHasCultureOrInvariant(this IEnumerable contents, string culture = null) + /// The content items. + /// The specific culture to filter for. If null is used the current culture is used. (Default is null). + internal static IEnumerable WhereIsInvariantOrHasCulture(this IEnumerable contents, string culture = null) { if (contents == null) throw new ArgumentNullException(nameof(contents)); - var actualCulture = culture ?? Current.VariationContextAccessor.VariationContext.Culture; + culture = culture ?? Current.VariationContextAccessor.VariationContext?.Culture ?? ""; - return contents.Where(x=>x.HasCulture(actualCulture) || !x.Cultures.Any()); + // either does not vary by culture, or has the specified culture + return contents.Where(x => !x.ContentType.VariesByCulture() || x.HasCulture(culture)); } + #endregion #region Search @@ -1036,7 +1037,6 @@ namespace Umbraco.Web #region Axes: children - /// /// Gets the children of the content. /// @@ -1050,7 +1050,16 @@ namespace Umbraco.Web public static IEnumerable Children(this IPublishedContent content, string culture = null) { if (content == null) throw new ArgumentNullException(nameof(content)); - return content.Children.WhereHasCultureOrInvariant(culture); + + // + return content.Children.Where(x => + { + if (!x.ContentType.VariesByCulture()) return true; // invariant = always ok + return x.HasCulture(culture); + return false; + }); + + return content.Children.WhereIsInvariantOrHasCulture(culture); } /// From 537b7e5ce9845f64a42dfc57479140ab1b0c438c Mon Sep 17 00:00:00 2001 From: mclausen Date: Thu, 17 Jan 2019 18:52:08 +0100 Subject: [PATCH 442/469] - Added PropertyType parameter to IValueConnector.FromArtifact --- src/Umbraco.Core/Deploy/IValueConnector.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Core/Deploy/IValueConnector.cs b/src/Umbraco.Core/Deploy/IValueConnector.cs index 81df59f1f1..7d9f43b5fe 100644 --- a/src/Umbraco.Core/Deploy/IValueConnector.cs +++ b/src/Umbraco.Core/Deploy/IValueConnector.cs @@ -29,8 +29,9 @@ namespace Umbraco.Core.Deploy /// Gets the content property value corresponding to a deploy property value. /// /// The deploy property value. + /// The value property type< /// The current content property value. /// The content property value. - object FromArtifact(string value, object currentValue); + object FromArtifact(string value, PropertyType propertyType, object currentValue); } } From 1ceab77aefebbb005257bbaa94c47e127a187335 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Wed, 16 Jan 2019 08:48:47 +0100 Subject: [PATCH 443/469] Fix start node configuration for tree pickers --- src/Umbraco.Web/PropertyEditors/ContentPickerConfiguration.cs | 4 ++-- src/Umbraco.Web/PropertyEditors/MediaPickerConfiguration.cs | 4 ++-- .../PropertyEditors/MultiNodePickerConfigurationTreeSource.cs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web/PropertyEditors/ContentPickerConfiguration.cs b/src/Umbraco.Web/PropertyEditors/ContentPickerConfiguration.cs index fe6ab6a054..307e41b836 100644 --- a/src/Umbraco.Web/PropertyEditors/ContentPickerConfiguration.cs +++ b/src/Umbraco.Web/PropertyEditors/ContentPickerConfiguration.cs @@ -8,6 +8,6 @@ namespace Umbraco.Web.PropertyEditors public bool ShowOpenButton { get; set; } [ConfigurationField("startNodeId", "Start node", "treepicker")] // + config in configuration editor ctor - public int StartNodeId { get; set; } = -1; // default value is -1 + public string StartNodeId { get; set; } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Web/PropertyEditors/MediaPickerConfiguration.cs b/src/Umbraco.Web/PropertyEditors/MediaPickerConfiguration.cs index 382db7e414..633fd65598 100644 --- a/src/Umbraco.Web/PropertyEditors/MediaPickerConfiguration.cs +++ b/src/Umbraco.Web/PropertyEditors/MediaPickerConfiguration.cs @@ -17,6 +17,6 @@ namespace Umbraco.Web.PropertyEditors public bool DisableFolderSelect { get; set; } [ConfigurationField("startNodeId", "Start node", "mediapicker")] - public int StartNodeId { get; set; } + public string StartNodeId { get; set; } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Web/PropertyEditors/MultiNodePickerConfigurationTreeSource.cs b/src/Umbraco.Web/PropertyEditors/MultiNodePickerConfigurationTreeSource.cs index ffedf6c7dc..65115afc63 100644 --- a/src/Umbraco.Web/PropertyEditors/MultiNodePickerConfigurationTreeSource.cs +++ b/src/Umbraco.Web/PropertyEditors/MultiNodePickerConfigurationTreeSource.cs @@ -15,6 +15,6 @@ namespace Umbraco.Web.PropertyEditors public string StartNodeQuery {get;set;} [JsonProperty("id")] - public int? StartNodeId {get;set;} + public string StartNodeId {get;set;} } } From f394bed017f2a5079f815ae11b4bf33d75bbfaea Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Thu, 17 Jan 2019 19:31:35 +0100 Subject: [PATCH 444/469] Change StartNodeId from string to Udi --- .../PropertyEditors/ContentPickerConfiguration.cs | 5 +++-- src/Umbraco.Web/PropertyEditors/MediaPickerConfiguration.cs | 5 +++-- .../MultiNodePickerConfigurationTreeSource.cs | 3 ++- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web/PropertyEditors/ContentPickerConfiguration.cs b/src/Umbraco.Web/PropertyEditors/ContentPickerConfiguration.cs index 307e41b836..7879e2b42b 100644 --- a/src/Umbraco.Web/PropertyEditors/ContentPickerConfiguration.cs +++ b/src/Umbraco.Web/PropertyEditors/ContentPickerConfiguration.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.PropertyEditors; +using Umbraco.Core; +using Umbraco.Core.PropertyEditors; namespace Umbraco.Web.PropertyEditors { @@ -8,6 +9,6 @@ namespace Umbraco.Web.PropertyEditors public bool ShowOpenButton { get; set; } [ConfigurationField("startNodeId", "Start node", "treepicker")] // + config in configuration editor ctor - public string StartNodeId { get; set; } + public Udi StartNodeId { get; set; } } } diff --git a/src/Umbraco.Web/PropertyEditors/MediaPickerConfiguration.cs b/src/Umbraco.Web/PropertyEditors/MediaPickerConfiguration.cs index 633fd65598..4844e2f822 100644 --- a/src/Umbraco.Web/PropertyEditors/MediaPickerConfiguration.cs +++ b/src/Umbraco.Web/PropertyEditors/MediaPickerConfiguration.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.PropertyEditors; +using Umbraco.Core; +using Umbraco.Core.PropertyEditors; namespace Umbraco.Web.PropertyEditors { @@ -17,6 +18,6 @@ namespace Umbraco.Web.PropertyEditors public bool DisableFolderSelect { get; set; } [ConfigurationField("startNodeId", "Start node", "mediapicker")] - public string StartNodeId { get; set; } + public Udi StartNodeId { get; set; } } } diff --git a/src/Umbraco.Web/PropertyEditors/MultiNodePickerConfigurationTreeSource.cs b/src/Umbraco.Web/PropertyEditors/MultiNodePickerConfigurationTreeSource.cs index 65115afc63..2942271acc 100644 --- a/src/Umbraco.Web/PropertyEditors/MultiNodePickerConfigurationTreeSource.cs +++ b/src/Umbraco.Web/PropertyEditors/MultiNodePickerConfigurationTreeSource.cs @@ -1,4 +1,5 @@ using Newtonsoft.Json; +using Umbraco.Core; namespace Umbraco.Web.PropertyEditors { @@ -15,6 +16,6 @@ namespace Umbraco.Web.PropertyEditors public string StartNodeQuery {get;set;} [JsonProperty("id")] - public string StartNodeId {get;set;} + public Udi StartNodeId {get;set;} } } From 27a1e51f80f38e24a29de02105128f5e7126549f Mon Sep 17 00:00:00 2001 From: Kenneth Jakobsen Date: Thu, 17 Jan 2019 21:12:10 +0100 Subject: [PATCH 445/469] Removed Property parameter from IGridCellValueVConnector --- src/Umbraco.Core/Deploy/IGridCellValueConnector.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Core/Deploy/IGridCellValueConnector.cs b/src/Umbraco.Core/Deploy/IGridCellValueConnector.cs index 827a902b89..5492a3effe 100644 --- a/src/Umbraco.Core/Deploy/IGridCellValueConnector.cs +++ b/src/Umbraco.Core/Deploy/IGridCellValueConnector.cs @@ -22,20 +22,17 @@ namespace Umbraco.Core.Deploy /// Gets the value to be deployed from the control value as a string. ///
    /// The control containing the value. - /// The property where the control is located. Do not modify - only used for context /// The dependencies of the property. /// The grid cell value to be deployed. /// Note that - string GetValue(GridValue.GridControl gridControl, Property property, ICollection dependencies); + string ToArtifact(GridValue.GridControl gridControl, ICollection dependencies); /// /// Allows you to modify the value of a control being deployed. /// /// The control being deployed. - /// The property where the is located. Do not modify - only used for context. /// Follows the pattern of the property value connectors (). The SetValue method is used to modify the value of the . - /// Note that only the value should be modified - not the . - /// The should only be used to assist with context data relevant when setting the value. - void SetValue(GridValue.GridControl gridControl, Property property); + + void FromArtifact(GridValue.GridControl gridControl); } } From 9fed610902f99a51d97f8447d5b4c4296f8e33f6 Mon Sep 17 00:00:00 2001 From: Kenneth Jakobsen Date: Thu, 17 Jan 2019 21:32:08 +0100 Subject: [PATCH 446/469] Redecided on renaming --- src/Umbraco.Core/Deploy/IGridCellValueConnector.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Core/Deploy/IGridCellValueConnector.cs b/src/Umbraco.Core/Deploy/IGridCellValueConnector.cs index 5492a3effe..15ed404d31 100644 --- a/src/Umbraco.Core/Deploy/IGridCellValueConnector.cs +++ b/src/Umbraco.Core/Deploy/IGridCellValueConnector.cs @@ -25,7 +25,7 @@ namespace Umbraco.Core.Deploy /// The dependencies of the property. /// The grid cell value to be deployed. /// Note that - string ToArtifact(GridValue.GridControl gridControl, ICollection dependencies); + string GetValue(GridValue.GridControl gridControl, ICollection dependencies); /// /// Allows you to modify the value of a control being deployed. @@ -33,6 +33,6 @@ namespace Umbraco.Core.Deploy /// The control being deployed. /// Follows the pattern of the property value connectors (). The SetValue method is used to modify the value of the . - void FromArtifact(GridValue.GridControl gridControl); + void SetValue(GridValue.GridControl gridControl); } } From 5aba1a6bd29c25101485f0b10e8321a3d2f81855 Mon Sep 17 00:00:00 2001 From: Stephan Date: Fri, 18 Jan 2019 07:56:38 +0100 Subject: [PATCH 447/469] IAppPolicedCache is IAppPolicyCache --- src/Umbraco.Core/Cache/AppCaches.cs | 4 ++-- .../Cache/AppPolicedCacheDictionary.cs | 14 +++++++------- src/Umbraco.Core/Cache/CacheProviderExtensions.cs | 4 ++-- src/Umbraco.Core/Cache/DeepCloneAppCache.cs | 8 ++++---- .../Cache/DefaultRepositoryCachePolicy.cs | 2 +- .../Cache/FullDataSetRepositoryCachePolicy.cs | 2 +- .../{IAppPolicedCache.cs => IAppPolicyCache.cs} | 2 +- src/Umbraco.Core/Cache/IsolatedCaches.cs | 8 ++++---- src/Umbraco.Core/Cache/NoAppCache.cs | 4 ++-- .../Cache/NoCacheRepositoryCachePolicy.cs | 2 +- src/Umbraco.Core/Cache/ObjectCacheAppCache.cs | 4 ++-- .../Cache/RepositoryCachePolicyBase.cs | 6 +++--- .../Cache/SingleItemsOnlyRepositoryCachePolicy.cs | 2 +- src/Umbraco.Core/Cache/WebCachingAppCache.cs | 4 ++-- src/Umbraco.Core/Composing/TypeLoader.cs | 6 +++--- src/Umbraco.Core/Manifest/ManifestParser.cs | 2 +- .../Implement/RepositoryBaseOfTIdTEntity.cs | 6 +++--- .../Implement/LocalizedTextServiceFileSources.cs | 2 +- src/Umbraco.Core/Umbraco.Core.csproj | 2 +- .../Cache/DeepCloneRuntimeCacheProviderTests.cs | 2 +- src/Umbraco.Tests/Cache/DefaultCachePolicyTests.cs | 12 ++++++------ .../Cache/FullDataSetCachePolicyTests.cs | 14 +++++++------- .../Cache/HttpRuntimeCacheProviderTests.cs | 2 +- .../Cache/ObjectCacheProviderTests.cs | 2 +- .../Cache/RuntimeCacheProviderTests.cs | 2 +- .../Cache/SingleItemsOnlyCachePolicyTests.cs | 4 ++-- .../PublishedContentSnapshotTestBase.cs | 2 +- .../PublishedContent/PublishedContentTests.cs | 2 +- src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 6 +++--- .../Editors/ExamineManagementController.cs | 2 +- 30 files changed, 67 insertions(+), 67 deletions(-) rename src/Umbraco.Core/Cache/{IAppPolicedCache.cs => IAppPolicyCache.cs} (97%) diff --git a/src/Umbraco.Core/Cache/AppCaches.cs b/src/Umbraco.Core/Cache/AppCaches.cs index 6372bccbab..7e5fa43682 100644 --- a/src/Umbraco.Core/Cache/AppCaches.cs +++ b/src/Umbraco.Core/Cache/AppCaches.cs @@ -30,7 +30,7 @@ namespace Umbraco.Core.Cache /// Initializes a new instance of the with cache providers. /// public AppCaches( - IAppPolicedCache runtimeCache, + IAppPolicyCache runtimeCache, IAppCache staticCacheProvider, IAppCache requestCache, IsolatedCaches isolatedCaches) @@ -82,7 +82,7 @@ namespace Umbraco.Core.Cache /// /// The runtime cache is the main application cache. /// - public IAppPolicedCache RuntimeCache { get; } + public IAppPolicyCache RuntimeCache { get; } /// /// Gets the isolated caches. diff --git a/src/Umbraco.Core/Cache/AppPolicedCacheDictionary.cs b/src/Umbraco.Core/Cache/AppPolicedCacheDictionary.cs index 51cc3c4c53..5c60dededa 100644 --- a/src/Umbraco.Core/Cache/AppPolicedCacheDictionary.cs +++ b/src/Umbraco.Core/Cache/AppPolicedCacheDictionary.cs @@ -4,18 +4,18 @@ using System.Collections.Concurrent; namespace Umbraco.Core.Cache { /// - /// Provides a base class for implementing a dictionary of . + /// Provides a base class for implementing a dictionary of . /// /// The type of the dictionary key. public abstract class AppPolicedCacheDictionary { - private readonly ConcurrentDictionary _caches = new ConcurrentDictionary(); + private readonly ConcurrentDictionary _caches = new ConcurrentDictionary(); /// /// Initializes a new instance of the class. /// /// - protected AppPolicedCacheDictionary(Func cacheFactory) + protected AppPolicedCacheDictionary(Func cacheFactory) { CacheFactory = cacheFactory; } @@ -23,19 +23,19 @@ namespace Umbraco.Core.Cache /// /// Gets the internal cache factory, for tests only! /// - internal readonly Func CacheFactory; + internal readonly Func CacheFactory; /// /// Gets or creates a cache. /// - public IAppPolicedCache GetOrCreate(TKey key) + public IAppPolicyCache GetOrCreate(TKey key) => _caches.GetOrAdd(key, k => CacheFactory(k)); /// /// Tries to get a cache. /// - public Attempt Get(TKey key) - => _caches.TryGetValue(key, out var cache) ? Attempt.Succeed(cache) : Attempt.Fail(); + public Attempt Get(TKey key) + => _caches.TryGetValue(key, out var cache) ? Attempt.Succeed(cache) : Attempt.Fail(); /// /// Removes a cache. diff --git a/src/Umbraco.Core/Cache/CacheProviderExtensions.cs b/src/Umbraco.Core/Cache/CacheProviderExtensions.cs index 0e41b981fb..d943d19edb 100644 --- a/src/Umbraco.Core/Cache/CacheProviderExtensions.cs +++ b/src/Umbraco.Core/Cache/CacheProviderExtensions.cs @@ -10,7 +10,7 @@ namespace Umbraco.Core.Cache /// public static class CacheProviderExtensions { - public static T GetCacheItem(this IAppPolicedCache provider, + public static T GetCacheItem(this IAppPolicyCache provider, string cacheKey, Func getCacheItem, TimeSpan? timeout, @@ -23,7 +23,7 @@ namespace Umbraco.Core.Cache return result == null ? default(T) : result.TryConvertTo().Result; } - public static void InsertCacheItem(this IAppPolicedCache provider, + public static void InsertCacheItem(this IAppPolicyCache provider, string cacheKey, Func getCacheItem, TimeSpan? timeout = null, diff --git a/src/Umbraco.Core/Cache/DeepCloneAppCache.cs b/src/Umbraco.Core/Cache/DeepCloneAppCache.cs index cdc66f1db7..eff06e2aad 100644 --- a/src/Umbraco.Core/Cache/DeepCloneAppCache.cs +++ b/src/Umbraco.Core/Cache/DeepCloneAppCache.cs @@ -8,16 +8,16 @@ using Umbraco.Core.Models.Entities; namespace Umbraco.Core.Cache { /// - /// Implements by wrapping an inner other + /// Implements by wrapping an inner other /// instance, and ensuring that all inserts and returns are deep cloned copies of the cache item, /// when the item is deep-cloneable. /// - internal class DeepCloneAppCache : IAppPolicedCache + internal class DeepCloneAppCache : IAppPolicyCache { /// /// Initializes a new instance of the class. /// - public DeepCloneAppCache(IAppPolicedCache innerCache) + public DeepCloneAppCache(IAppPolicyCache innerCache) { var type = typeof (DeepCloneAppCache); @@ -30,7 +30,7 @@ namespace Umbraco.Core.Cache /// /// Gets the inner cache. /// - public IAppPolicedCache InnerCache { get; } + public IAppPolicyCache InnerCache { get; } /// public object Get(string key) diff --git a/src/Umbraco.Core/Cache/DefaultRepositoryCachePolicy.cs b/src/Umbraco.Core/Cache/DefaultRepositoryCachePolicy.cs index 6f160cd552..c11309c827 100644 --- a/src/Umbraco.Core/Cache/DefaultRepositoryCachePolicy.cs +++ b/src/Umbraco.Core/Cache/DefaultRepositoryCachePolicy.cs @@ -23,7 +23,7 @@ namespace Umbraco.Core.Cache private static readonly TEntity[] EmptyEntities = new TEntity[0]; // const private readonly RepositoryCachePolicyOptions _options; - public DefaultRepositoryCachePolicy(IAppPolicedCache cache, IScopeAccessor scopeAccessor, RepositoryCachePolicyOptions options) + public DefaultRepositoryCachePolicy(IAppPolicyCache cache, IScopeAccessor scopeAccessor, RepositoryCachePolicyOptions options) : base(cache, scopeAccessor) { _options = options ?? throw new ArgumentNullException(nameof(options)); diff --git a/src/Umbraco.Core/Cache/FullDataSetRepositoryCachePolicy.cs b/src/Umbraco.Core/Cache/FullDataSetRepositoryCachePolicy.cs index 3bc4c9d059..c3b69d9a6d 100644 --- a/src/Umbraco.Core/Cache/FullDataSetRepositoryCachePolicy.cs +++ b/src/Umbraco.Core/Cache/FullDataSetRepositoryCachePolicy.cs @@ -24,7 +24,7 @@ namespace Umbraco.Core.Cache private readonly Func _entityGetId; private readonly bool _expires; - public FullDataSetRepositoryCachePolicy(IAppPolicedCache cache, IScopeAccessor scopeAccessor, Func entityGetId, bool expires) + public FullDataSetRepositoryCachePolicy(IAppPolicyCache cache, IScopeAccessor scopeAccessor, Func entityGetId, bool expires) : base(cache, scopeAccessor) { _entityGetId = entityGetId; diff --git a/src/Umbraco.Core/Cache/IAppPolicedCache.cs b/src/Umbraco.Core/Cache/IAppPolicyCache.cs similarity index 97% rename from src/Umbraco.Core/Cache/IAppPolicedCache.cs rename to src/Umbraco.Core/Cache/IAppPolicyCache.cs index 0aee7584df..90b0ccb9fd 100644 --- a/src/Umbraco.Core/Cache/IAppPolicedCache.cs +++ b/src/Umbraco.Core/Cache/IAppPolicyCache.cs @@ -10,7 +10,7 @@ namespace Umbraco.Core.Cache /// /// A cache policy can be used to cache with timeouts, /// or depending on files, and with a remove callback, etc. - public interface IAppPolicedCache : IAppCache + public interface IAppPolicyCache : IAppCache { /// /// Gets an item identified by its key. diff --git a/src/Umbraco.Core/Cache/IsolatedCaches.cs b/src/Umbraco.Core/Cache/IsolatedCaches.cs index bc624be20d..f070fe8b55 100644 --- a/src/Umbraco.Core/Cache/IsolatedCaches.cs +++ b/src/Umbraco.Core/Cache/IsolatedCaches.cs @@ -3,7 +3,7 @@ namespace Umbraco.Core.Cache { /// - /// Represents a dictionary of for types. + /// Represents a dictionary of for types. /// /// /// Isolated caches are used by e.g. repositories, to ensure that each cached entity @@ -16,20 +16,20 @@ namespace Umbraco.Core.Cache /// Initializes a new instance of the class. /// /// - public IsolatedCaches(Func cacheFactory) + public IsolatedCaches(Func cacheFactory) : base(cacheFactory) { } /// /// Gets a cache. /// - public IAppPolicedCache GetOrCreate() + public IAppPolicyCache GetOrCreate() => GetOrCreate(typeof(T)); /// /// Tries to get a cache. /// - public Attempt Get() + public Attempt Get() => Get(typeof(T)); /// diff --git a/src/Umbraco.Core/Cache/NoAppCache.cs b/src/Umbraco.Core/Cache/NoAppCache.cs index 8a7e15cb29..d3359a30ba 100644 --- a/src/Umbraco.Core/Cache/NoAppCache.cs +++ b/src/Umbraco.Core/Cache/NoAppCache.cs @@ -6,9 +6,9 @@ using System.Web.Caching; namespace Umbraco.Core.Cache { /// - /// Implements and do not cache. + /// Implements and do not cache. /// - public class NoAppCache : IAppPolicedCache + public class NoAppCache : IAppPolicyCache { private NoAppCache() { } diff --git a/src/Umbraco.Core/Cache/NoCacheRepositoryCachePolicy.cs b/src/Umbraco.Core/Cache/NoCacheRepositoryCachePolicy.cs index acc67be679..b1a12ec411 100644 --- a/src/Umbraco.Core/Cache/NoCacheRepositoryCachePolicy.cs +++ b/src/Umbraco.Core/Cache/NoCacheRepositoryCachePolicy.cs @@ -13,7 +13,7 @@ namespace Umbraco.Core.Cache public static NoCacheRepositoryCachePolicy Instance { get; } = new NoCacheRepositoryCachePolicy(); - public IRepositoryCachePolicy Scoped(IAppPolicedCache runtimeCache, IScope scope) + public IRepositoryCachePolicy Scoped(IAppPolicyCache runtimeCache, IScope scope) { throw new NotImplementedException(); } diff --git a/src/Umbraco.Core/Cache/ObjectCacheAppCache.cs b/src/Umbraco.Core/Cache/ObjectCacheAppCache.cs index 954622fc4b..449eb5d643 100644 --- a/src/Umbraco.Core/Cache/ObjectCacheAppCache.cs +++ b/src/Umbraco.Core/Cache/ObjectCacheAppCache.cs @@ -11,9 +11,9 @@ using CacheItemPriority = System.Web.Caching.CacheItemPriority; namespace Umbraco.Core.Cache { /// - /// Implements on top of a . + /// Implements on top of a . /// - public class ObjectCacheAppCache : IAppPolicedCache + public class ObjectCacheAppCache : IAppPolicyCache { private readonly ReaderWriterLockSlim _locker = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); diff --git a/src/Umbraco.Core/Cache/RepositoryCachePolicyBase.cs b/src/Umbraco.Core/Cache/RepositoryCachePolicyBase.cs index f8bba4b033..27fe4e3035 100644 --- a/src/Umbraco.Core/Cache/RepositoryCachePolicyBase.cs +++ b/src/Umbraco.Core/Cache/RepositoryCachePolicyBase.cs @@ -13,16 +13,16 @@ namespace Umbraco.Core.Cache internal abstract class RepositoryCachePolicyBase : IRepositoryCachePolicy where TEntity : class, IEntity { - private readonly IAppPolicedCache _globalCache; + private readonly IAppPolicyCache _globalCache; private readonly IScopeAccessor _scopeAccessor; - protected RepositoryCachePolicyBase(IAppPolicedCache globalCache, IScopeAccessor scopeAccessor) + protected RepositoryCachePolicyBase(IAppPolicyCache globalCache, IScopeAccessor scopeAccessor) { _globalCache = globalCache ?? throw new ArgumentNullException(nameof(globalCache)); _scopeAccessor = scopeAccessor ?? throw new ArgumentNullException(nameof(scopeAccessor)); } - protected IAppPolicedCache Cache + protected IAppPolicyCache Cache { get { diff --git a/src/Umbraco.Core/Cache/SingleItemsOnlyRepositoryCachePolicy.cs b/src/Umbraco.Core/Cache/SingleItemsOnlyRepositoryCachePolicy.cs index 714798a47c..9de7519edb 100644 --- a/src/Umbraco.Core/Cache/SingleItemsOnlyRepositoryCachePolicy.cs +++ b/src/Umbraco.Core/Cache/SingleItemsOnlyRepositoryCachePolicy.cs @@ -16,7 +16,7 @@ namespace Umbraco.Core.Cache internal class SingleItemsOnlyRepositoryCachePolicy : DefaultRepositoryCachePolicy where TEntity : class, IEntity { - public SingleItemsOnlyRepositoryCachePolicy(IAppPolicedCache cache, IScopeAccessor scopeAccessor, RepositoryCachePolicyOptions options) + public SingleItemsOnlyRepositoryCachePolicy(IAppPolicyCache cache, IScopeAccessor scopeAccessor, RepositoryCachePolicyOptions options) : base(cache, scopeAccessor, options) { } diff --git a/src/Umbraco.Core/Cache/WebCachingAppCache.cs b/src/Umbraco.Core/Cache/WebCachingAppCache.cs index b762fcda07..7fbdebf9ab 100644 --- a/src/Umbraco.Core/Cache/WebCachingAppCache.cs +++ b/src/Umbraco.Core/Cache/WebCachingAppCache.cs @@ -8,11 +8,11 @@ using System.Web.Caching; namespace Umbraco.Core.Cache { /// - /// Implements on top of a . + /// Implements on top of a . /// A CacheProvider that wraps the logic of the HttpRuntime.Cache /// /// The underlying cache is expected to be HttpRuntime.Cache. - internal class WebCachingAppCache : FastDictionaryAppCacheBase, IAppPolicedCache + internal class WebCachingAppCache : FastDictionaryAppCacheBase, IAppPolicyCache { // locker object that supports upgradeable read locking // does not need to support recursion if we implement the cache correctly and ensure diff --git a/src/Umbraco.Core/Composing/TypeLoader.cs b/src/Umbraco.Core/Composing/TypeLoader.cs index fe277676d7..3950cf86e9 100644 --- a/src/Umbraco.Core/Composing/TypeLoader.cs +++ b/src/Umbraco.Core/Composing/TypeLoader.cs @@ -29,7 +29,7 @@ namespace Umbraco.Core.Composing { private const string CacheKey = "umbraco-types.list"; - private readonly IAppPolicedCache _runtimeCache; + private readonly IAppPolicyCache _runtimeCache; private readonly IProfilingLogger _logger; private readonly Dictionary _types = new Dictionary(); @@ -51,7 +51,7 @@ namespace Umbraco.Core.Composing /// The application runtime cache. /// Files storage mode. /// A profiling logger. - public TypeLoader(IAppPolicedCache runtimeCache, LocalTempStorage localTempStorage, IProfilingLogger logger) + public TypeLoader(IAppPolicyCache runtimeCache, LocalTempStorage localTempStorage, IProfilingLogger logger) : this(runtimeCache, localTempStorage, logger, true) { } @@ -62,7 +62,7 @@ namespace Umbraco.Core.Composing /// Files storage mode. /// A profiling logger. /// Whether to detect changes using hashes. - internal TypeLoader(IAppPolicedCache runtimeCache, LocalTempStorage localTempStorage, IProfilingLogger logger, bool detectChanges) + internal TypeLoader(IAppPolicyCache runtimeCache, LocalTempStorage localTempStorage, IProfilingLogger logger, bool detectChanges) { _runtimeCache = runtimeCache ?? throw new ArgumentNullException(nameof(runtimeCache)); _localTempStorage = localTempStorage == LocalTempStorage.Unknown ? LocalTempStorage.Default : localTempStorage; diff --git a/src/Umbraco.Core/Manifest/ManifestParser.cs b/src/Umbraco.Core/Manifest/ManifestParser.cs index 40e99bb079..a80cd98466 100644 --- a/src/Umbraco.Core/Manifest/ManifestParser.cs +++ b/src/Umbraco.Core/Manifest/ManifestParser.cs @@ -20,7 +20,7 @@ namespace Umbraco.Core.Manifest { private static readonly string Utf8Preamble = Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble()); - private readonly IAppPolicedCache _cache; + private readonly IAppPolicyCache _cache; private readonly ILogger _logger; private readonly ManifestValueValidatorCollection _validators; diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/RepositoryBaseOfTIdTEntity.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/RepositoryBaseOfTIdTEntity.cs index 6862173786..c8329d1f32 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/RepositoryBaseOfTIdTEntity.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/RepositoryBaseOfTIdTEntity.cs @@ -30,7 +30,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement protected AppCaches AppCaches { get; } - protected IAppPolicedCache GlobalIsolatedCache => AppCaches.IsolatedCaches.GetOrCreate(); + protected IAppPolicyCache GlobalIsolatedCache => AppCaches.IsolatedCaches.GetOrCreate(); protected IScopeAccessor ScopeAccessor { get; } @@ -60,7 +60,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement /// Gets the isolated cache. /// /// Depends on the ambient scope cache mode. - protected IAppPolicedCache IsolatedCache + protected IAppPolicyCache IsolatedCache { get { @@ -157,7 +157,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement /// /// Adds or Updates an entity of type TEntity /// - /// This method is backed by an cache + /// This method is backed by an cache /// public void Save(TEntity entity) { diff --git a/src/Umbraco.Core/Services/Implement/LocalizedTextServiceFileSources.cs b/src/Umbraco.Core/Services/Implement/LocalizedTextServiceFileSources.cs index 8c2d277348..430c2b3d3c 100644 --- a/src/Umbraco.Core/Services/Implement/LocalizedTextServiceFileSources.cs +++ b/src/Umbraco.Core/Services/Implement/LocalizedTextServiceFileSources.cs @@ -17,7 +17,7 @@ namespace Umbraco.Core.Services.Implement public class LocalizedTextServiceFileSources { private readonly ILogger _logger; - private readonly IAppPolicedCache _cache; + private readonly IAppPolicyCache _cache; private readonly IEnumerable _supplementFileSources; private readonly DirectoryInfo _fileSourceFolder; diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index d72c0e5014..b94c718242 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -131,7 +131,7 @@ - + diff --git a/src/Umbraco.Tests/Cache/DeepCloneRuntimeCacheProviderTests.cs b/src/Umbraco.Tests/Cache/DeepCloneRuntimeCacheProviderTests.cs index 5158989a8b..7483df1c44 100644 --- a/src/Umbraco.Tests/Cache/DeepCloneRuntimeCacheProviderTests.cs +++ b/src/Umbraco.Tests/Cache/DeepCloneRuntimeCacheProviderTests.cs @@ -34,7 +34,7 @@ namespace Umbraco.Tests.Cache get { return _provider; } } - internal override IAppPolicedCache RuntimeProvider + internal override IAppPolicyCache RuntimeProvider { get { return _provider; } } diff --git a/src/Umbraco.Tests/Cache/DefaultCachePolicyTests.cs b/src/Umbraco.Tests/Cache/DefaultCachePolicyTests.cs index 0f649328fe..4161f576c9 100644 --- a/src/Umbraco.Tests/Cache/DefaultCachePolicyTests.cs +++ b/src/Umbraco.Tests/Cache/DefaultCachePolicyTests.cs @@ -28,7 +28,7 @@ namespace Umbraco.Tests.Cache public void Caches_Single() { var isCached = false; - var cache = new Mock(); + var cache = new Mock(); cache.Setup(x => x.Insert(It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Callback(() => @@ -45,7 +45,7 @@ namespace Umbraco.Tests.Cache [Test] public void Get_Single_From_Cache() { - var cache = new Mock(); + var cache = new Mock(); cache.Setup(x => x.Get(It.IsAny())).Returns(new AuditItem(1, AuditType.Copy, 123, "test", "blah")); var defaultPolicy = new DefaultRepositoryCachePolicy(cache.Object, DefaultAccessor, new RepositoryCachePolicyOptions()); @@ -58,7 +58,7 @@ namespace Umbraco.Tests.Cache public void Caches_Per_Id_For_Get_All() { var cached = new List(); - var cache = new Mock(); + var cache = new Mock(); cache.Setup(x => x.Insert(It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Callback((string cacheKey, Func o, TimeSpan? t, bool b, CacheItemPriority cip, CacheItemRemovedCallback circ, string[] s) => @@ -81,7 +81,7 @@ namespace Umbraco.Tests.Cache [Test] public void Get_All_Without_Ids_From_Cache() { - var cache = new Mock(); + var cache = new Mock(); cache.Setup(x => x.SearchByKey(It.IsAny())).Returns(new[] { new AuditItem(1, AuditType.Copy, 123, "test", "blah"), @@ -98,7 +98,7 @@ namespace Umbraco.Tests.Cache public void If_CreateOrUpdate_Throws_Cache_Is_Removed() { var cacheCleared = false; - var cache = new Mock(); + var cache = new Mock(); cache.Setup(x => x.Clear(It.IsAny())) .Callback(() => { @@ -124,7 +124,7 @@ namespace Umbraco.Tests.Cache public void If_Removes_Throws_Cache_Is_Removed() { var cacheCleared = false; - var cache = new Mock(); + var cache = new Mock(); cache.Setup(x => x.Clear(It.IsAny())) .Callback(() => { diff --git a/src/Umbraco.Tests/Cache/FullDataSetCachePolicyTests.cs b/src/Umbraco.Tests/Cache/FullDataSetCachePolicyTests.cs index 7c5a1524d2..a4fbdf2224 100644 --- a/src/Umbraco.Tests/Cache/FullDataSetCachePolicyTests.cs +++ b/src/Umbraco.Tests/Cache/FullDataSetCachePolicyTests.cs @@ -37,7 +37,7 @@ namespace Umbraco.Tests.Cache }; var isCached = false; - var cache = new Mock(); + var cache = new Mock(); cache.Setup(x => x.Insert(It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Callback(() => @@ -60,7 +60,7 @@ namespace Umbraco.Tests.Cache new AuditItem(2, AuditType.Copy, 123, "test", "blah2") }; - var cache = new Mock(); + var cache = new Mock(); cache.Setup(x => x.Get(It.IsAny())).Returns(new AuditItem(1, AuditType.Copy, 123, "test", "blah")); var defaultPolicy = new FullDataSetRepositoryCachePolicy(cache.Object, DefaultAccessor, item => item.Id, false); @@ -78,7 +78,7 @@ namespace Umbraco.Tests.Cache IList list = null; - var cache = new Mock(); + var cache = new Mock(); cache.Setup(x => x.Insert(It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Callback((string cacheKey, Func o, TimeSpan? t, bool b, CacheItemPriority cip, CacheItemRemovedCallback circ, string[] s) => @@ -121,7 +121,7 @@ namespace Umbraco.Tests.Cache var cached = new List(); IList list = null; - var cache = new Mock(); + var cache = new Mock(); cache.Setup(x => x.Insert(It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Callback((string cacheKey, Func o, TimeSpan? t, bool b, CacheItemPriority cip, CacheItemRemovedCallback circ, string[] s) => @@ -145,7 +145,7 @@ namespace Umbraco.Tests.Cache { var getAll = new[] { (AuditItem)null }; - var cache = new Mock(); + var cache = new Mock(); cache.Setup(x => x.Get(It.IsAny())).Returns(() => new DeepCloneableList(ListCloneBehavior.CloneOnce) { @@ -169,7 +169,7 @@ namespace Umbraco.Tests.Cache }; var cacheCleared = false; - var cache = new Mock(); + var cache = new Mock(); cache.Setup(x => x.Clear(It.IsAny())) .Callback(() => { @@ -201,7 +201,7 @@ namespace Umbraco.Tests.Cache }; var cacheCleared = false; - var cache = new Mock(); + var cache = new Mock(); cache.Setup(x => x.Clear(It.IsAny())) .Callback(() => { diff --git a/src/Umbraco.Tests/Cache/HttpRuntimeCacheProviderTests.cs b/src/Umbraco.Tests/Cache/HttpRuntimeCacheProviderTests.cs index 56f3303e9c..6297539a1b 100644 --- a/src/Umbraco.Tests/Cache/HttpRuntimeCacheProviderTests.cs +++ b/src/Umbraco.Tests/Cache/HttpRuntimeCacheProviderTests.cs @@ -27,7 +27,7 @@ namespace Umbraco.Tests.Cache get { return _provider; } } - internal override IAppPolicedCache RuntimeProvider + internal override IAppPolicyCache RuntimeProvider { get { return _provider; } } diff --git a/src/Umbraco.Tests/Cache/ObjectCacheProviderTests.cs b/src/Umbraco.Tests/Cache/ObjectCacheProviderTests.cs index 6ed7f590e0..4d34e81eff 100644 --- a/src/Umbraco.Tests/Cache/ObjectCacheProviderTests.cs +++ b/src/Umbraco.Tests/Cache/ObjectCacheProviderTests.cs @@ -28,7 +28,7 @@ namespace Umbraco.Tests.Cache get { return _provider; } } - internal override IAppPolicedCache RuntimeProvider + internal override IAppPolicyCache RuntimeProvider { get { return _provider; } } diff --git a/src/Umbraco.Tests/Cache/RuntimeCacheProviderTests.cs b/src/Umbraco.Tests/Cache/RuntimeCacheProviderTests.cs index 08eb5e9a60..6391e4ec7a 100644 --- a/src/Umbraco.Tests/Cache/RuntimeCacheProviderTests.cs +++ b/src/Umbraco.Tests/Cache/RuntimeCacheProviderTests.cs @@ -8,7 +8,7 @@ namespace Umbraco.Tests.Cache public abstract class RuntimeCacheProviderTests : CacheProviderTests { - internal abstract IAppPolicedCache RuntimeProvider { get; } + internal abstract IAppPolicyCache RuntimeProvider { get; } [Test] diff --git a/src/Umbraco.Tests/Cache/SingleItemsOnlyCachePolicyTests.cs b/src/Umbraco.Tests/Cache/SingleItemsOnlyCachePolicyTests.cs index 2b37d85801..2525eab45b 100644 --- a/src/Umbraco.Tests/Cache/SingleItemsOnlyCachePolicyTests.cs +++ b/src/Umbraco.Tests/Cache/SingleItemsOnlyCachePolicyTests.cs @@ -28,7 +28,7 @@ namespace Umbraco.Tests.Cache public void Get_All_Doesnt_Cache() { var cached = new List(); - var cache = new Mock(); + var cache = new Mock(); cache.Setup(x => x.Insert(It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Callback((string cacheKey, Func o, TimeSpan? t, bool b, CacheItemPriority cip, CacheItemRemovedCallback circ, string[] s) => @@ -52,7 +52,7 @@ namespace Umbraco.Tests.Cache public void Caches_Single() { var isCached = false; - var cache = new Mock(); + var cache = new Mock(); cache.Setup(x => x.Insert(It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Callback(() => diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs index 5b1dcde728..e293653c37 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs @@ -40,7 +40,7 @@ namespace Umbraco.Tests.PublishedContent Composition.RegisterUnique(f => new PublishedModelFactory(f.GetInstance().GetTypes())); } - protected override TypeLoader CreateTypeLoader(IAppPolicedCache runtimeCache, IGlobalSettings globalSettings, IProfilingLogger logger) + protected override TypeLoader CreateTypeLoader(IAppPolicyCache runtimeCache, IGlobalSettings globalSettings, IProfilingLogger logger) { var pluginManager = base.CreateTypeLoader(runtimeCache, globalSettings, logger); diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs index e798be82c4..705b2fd826 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs @@ -74,7 +74,7 @@ namespace Umbraco.Tests.PublishedContent ContentTypesCache.GetPublishedContentTypeByAlias = alias => alias.InvariantEquals("home") ? homeType : anythingType; } - protected override TypeLoader CreateTypeLoader(IAppPolicedCache runtimeCache, IGlobalSettings globalSettings, IProfilingLogger logger) + protected override TypeLoader CreateTypeLoader(IAppPolicyCache runtimeCache, IGlobalSettings globalSettings, IProfilingLogger logger) { var pluginManager = base.CreateTypeLoader(runtimeCache, globalSettings, logger); diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index fd617b5a21..1b3f7f50bf 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -244,7 +244,7 @@ namespace Umbraco.Tests.Testing .ComposeWebMappingProfiles(); } - protected virtual TypeLoader GetTypeLoader(IAppPolicedCache runtimeCache, IGlobalSettings globalSettings, IProfilingLogger logger, UmbracoTestOptions.TypeLoader option) + protected virtual TypeLoader GetTypeLoader(IAppPolicyCache runtimeCache, IGlobalSettings globalSettings, IProfilingLogger logger, UmbracoTestOptions.TypeLoader option) { switch (option) { @@ -259,13 +259,13 @@ namespace Umbraco.Tests.Testing } } - protected virtual TypeLoader CreateTypeLoader(IAppPolicedCache runtimeCache, IGlobalSettings globalSettings, IProfilingLogger logger) + protected virtual TypeLoader CreateTypeLoader(IAppPolicyCache runtimeCache, IGlobalSettings globalSettings, IProfilingLogger logger) { return CreateCommonTypeLoader(runtimeCache, globalSettings, logger); } // common to all tests = cannot be overriden - private static TypeLoader CreateCommonTypeLoader(IAppPolicedCache runtimeCache, IGlobalSettings globalSettings, IProfilingLogger logger) + private static TypeLoader CreateCommonTypeLoader(IAppPolicyCache runtimeCache, IGlobalSettings globalSettings, IProfilingLogger logger) { return new TypeLoader(runtimeCache, globalSettings.LocalTempStorageLocation, logger, false) { diff --git a/src/Umbraco.Web/Editors/ExamineManagementController.cs b/src/Umbraco.Web/Editors/ExamineManagementController.cs index 8d930b8ed7..06334f86e7 100644 --- a/src/Umbraco.Web/Editors/ExamineManagementController.cs +++ b/src/Umbraco.Web/Editors/ExamineManagementController.cs @@ -22,7 +22,7 @@ namespace Umbraco.Web.Editors { private readonly IExamineManager _examineManager; private readonly ILogger _logger; - private readonly IAppPolicedCache _runtimeCache; + private readonly IAppPolicyCache _runtimeCache; private readonly IndexRebuilder _indexRebuilder; From f952fe7aeb2acbf6ada02cf4454777e7def3b5df Mon Sep 17 00:00:00 2001 From: Stephan Date: Fri, 18 Jan 2019 08:14:08 +0100 Subject: [PATCH 448/469] More renaming of caches --- ...derExtensions.cs => AppCacheExtensions.cs} | 2 +- src/Umbraco.Core/Cache/ObjectCacheAppCache.cs | 2 +- src/Umbraco.Core/Cache/WebCachingAppCache.cs | 1 - src/Umbraco.Core/Composing/Current.cs | 2 +- .../Implement/MemberGroupRepository.cs | 2 +- src/Umbraco.Core/Umbraco.Core.csproj | 2 +- ...CacheProviderTests.cs => AppCacheTests.cs} | 98 +++++++++---------- ...iderTests.cs => DeepCloneAppCacheTests.cs} | 7 +- ...erTests.cs => HttpRequestAppCacheTests.cs} | 8 +- .../Cache/HttpRuntimeCacheProviderTests.cs | 59 ----------- ...roviderTests.cs => ObjectAppCacheTests.cs} | 6 +- .../PublishedContentCacheTests.cs | 8 +- ...oviderTests.cs => RuntimeAppCacheTests.cs} | 16 ++- .../Cache/WebCachingAppCacheTests.cs | 50 ++++++++++ .../Scoping/ScopedRepositoryTests.cs | 6 +- src/Umbraco.Tests/Umbraco.Tests.csproj | 12 +-- .../Cache/ContentCacheRefresher.cs | 2 +- src/Umbraco.Web/Cache/MediaCacheRefresher.cs | 2 +- src/Umbraco.Web/Composing/Current.cs | 2 +- .../Dictionary/UmbracoCultureDictionary.cs | 20 ++-- .../Editors/CurrentUserController.cs | 2 +- src/Umbraco.Web/HtmlHelperRenderExtensions.cs | 2 +- src/Umbraco.Web/Macros/MacroRenderer.cs | 4 +- .../DictionaryPublishedContent.cs | 6 +- .../PublishedContentCache.cs | 16 +-- .../XmlPublishedCache/PublishedMediaCache.cs | 22 ++--- .../XmlPublishedCache/XmlPublishedContent.cs | 12 +-- 27 files changed, 178 insertions(+), 193 deletions(-) rename src/Umbraco.Core/Cache/{CacheProviderExtensions.cs => AppCacheExtensions.cs} (98%) rename src/Umbraco.Tests/Cache/{CacheProviderTests.cs => AppCacheTests.cs} (69%) rename src/Umbraco.Tests/Cache/{DeepCloneRuntimeCacheProviderTests.cs => DeepCloneAppCacheTests.cs} (94%) rename src/Umbraco.Tests/Cache/{HttpRequestCacheProviderTests.cs => HttpRequestAppCacheTests.cs} (82%) delete mode 100644 src/Umbraco.Tests/Cache/HttpRuntimeCacheProviderTests.cs rename src/Umbraco.Tests/Cache/{ObjectCacheProviderTests.cs => ObjectAppCacheTests.cs} (78%) rename src/Umbraco.Tests/Cache/{RuntimeCacheProviderTests.cs => RuntimeAppCacheTests.cs} (51%) create mode 100644 src/Umbraco.Tests/Cache/WebCachingAppCacheTests.cs diff --git a/src/Umbraco.Core/Cache/CacheProviderExtensions.cs b/src/Umbraco.Core/Cache/AppCacheExtensions.cs similarity index 98% rename from src/Umbraco.Core/Cache/CacheProviderExtensions.cs rename to src/Umbraco.Core/Cache/AppCacheExtensions.cs index d943d19edb..ddba8be1b2 100644 --- a/src/Umbraco.Core/Cache/CacheProviderExtensions.cs +++ b/src/Umbraco.Core/Cache/AppCacheExtensions.cs @@ -8,7 +8,7 @@ namespace Umbraco.Core.Cache /// /// Extensions for strongly typed access /// - public static class CacheProviderExtensions + public static class AppCacheExtensions { public static T GetCacheItem(this IAppPolicyCache provider, string cacheKey, diff --git a/src/Umbraco.Core/Cache/ObjectCacheAppCache.cs b/src/Umbraco.Core/Cache/ObjectCacheAppCache.cs index 449eb5d643..5c4f76f51d 100644 --- a/src/Umbraco.Core/Cache/ObjectCacheAppCache.cs +++ b/src/Umbraco.Core/Cache/ObjectCacheAppCache.cs @@ -105,7 +105,7 @@ namespace Umbraco.Core.Cache /// public object Get(string key, Func factory, TimeSpan? timeout, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null) { - // see notes in HttpRuntimeCacheProvider + // see notes in HttpRuntimeAppCache Lazy result; diff --git a/src/Umbraco.Core/Cache/WebCachingAppCache.cs b/src/Umbraco.Core/Cache/WebCachingAppCache.cs index 7fbdebf9ab..c6e104221a 100644 --- a/src/Umbraco.Core/Cache/WebCachingAppCache.cs +++ b/src/Umbraco.Core/Cache/WebCachingAppCache.cs @@ -9,7 +9,6 @@ namespace Umbraco.Core.Cache { /// /// Implements on top of a . - /// A CacheProvider that wraps the logic of the HttpRuntime.Cache /// /// The underlying cache is expected to be HttpRuntime.Cache. internal class WebCachingAppCache : FastDictionaryAppCacheBase, IAppPolicyCache diff --git a/src/Umbraco.Core/Composing/Current.cs b/src/Umbraco.Core/Composing/Current.cs index bfc5cfd51c..429fee3317 100644 --- a/src/Umbraco.Core/Composing/Current.cs +++ b/src/Umbraco.Core/Composing/Current.cs @@ -180,7 +180,7 @@ namespace Umbraco.Core.Composing public static ICultureDictionaryFactory CultureDictionaryFactory => Factory.GetInstance(); - public static AppCaches ApplicationCache + public static AppCaches AppCaches => Factory.GetInstance(); public static ServiceContext Services diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/MemberGroupRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/MemberGroupRepository.cs index 11166ce777..e6ee79470c 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/MemberGroupRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/MemberGroupRepository.cs @@ -124,7 +124,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement var result = Get(qry); return result.FirstOrDefault(); }, - //cache for 5 mins since that is the default in the RuntimeCacheProvider + //cache for 5 mins since that is the default in the Runtime app cache TimeSpan.FromMinutes(5), //sliding is true true); diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index b94c718242..5b2692359a 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -114,7 +114,7 @@ - + diff --git a/src/Umbraco.Tests/Cache/CacheProviderTests.cs b/src/Umbraco.Tests/Cache/AppCacheTests.cs similarity index 69% rename from src/Umbraco.Tests/Cache/CacheProviderTests.cs rename to src/Umbraco.Tests/Cache/AppCacheTests.cs index f2288cbaf2..f18e08d680 100644 --- a/src/Umbraco.Tests/Cache/CacheProviderTests.cs +++ b/src/Umbraco.Tests/Cache/AppCacheTests.cs @@ -7,9 +7,9 @@ using umbraco; namespace Umbraco.Tests.Cache { - public abstract class CacheProviderTests + public abstract class AppCacheTests { - internal abstract IAppCache Provider { get; } + internal abstract IAppCache AppCache { get; } protected abstract int GetTotalItemCount { get; } [SetUp] @@ -21,22 +21,22 @@ namespace Umbraco.Tests.Cache [TearDown] public virtual void TearDown() { - Provider.Clear(); + AppCache.Clear(); } [Test] public void Throws_On_Reentry() { // don't run for StaticCacheProvider - not making sense - if (GetType() == typeof (StaticCacheProviderTests)) + if (GetType() == typeof (StaticAppCacheTests)) Assert.Ignore("Do not run for StaticCacheProvider."); Exception exception = null; - var result = Provider.Get("blah", () => + var result = AppCache.Get("blah", () => { try { - var result2 = Provider.Get("blah"); + var result2 = AppCache.Get("blah"); } catch (Exception e) { @@ -56,7 +56,7 @@ namespace Umbraco.Tests.Cache object result; try { - result = Provider.Get("Blah", () => + result = AppCache.Get("Blah", () => { counter++; throw new Exception("Do not cache this"); @@ -66,7 +66,7 @@ namespace Umbraco.Tests.Cache try { - result = Provider.Get("Blah", () => + result = AppCache.Get("Blah", () => { counter++; throw new Exception("Do not cache this"); @@ -85,13 +85,13 @@ namespace Umbraco.Tests.Cache object result; - result = Provider.Get("Blah", () => + result = AppCache.Get("Blah", () => { counter++; return ""; }); - result = Provider.Get("Blah", () => + result = AppCache.Get("Blah", () => { counter++; return ""; @@ -108,14 +108,14 @@ namespace Umbraco.Tests.Cache var cacheContent2 = new MacroCacheContent(new LiteralControl(), "Test2"); var cacheContent3 = new MacroCacheContent(new LiteralControl(), "Test3"); var cacheContent4 = new LiteralControl(); - Provider.Get("Test1", () => cacheContent1); - Provider.Get("Tester2", () => cacheContent2); - Provider.Get("Tes3", () => cacheContent3); - Provider.Get("different4", () => cacheContent4); + AppCache.Get("Test1", () => cacheContent1); + AppCache.Get("Tester2", () => cacheContent2); + AppCache.Get("Tes3", () => cacheContent3); + AppCache.Get("different4", () => cacheContent4); Assert.AreEqual(4, GetTotalItemCount); - var result = Provider.SearchByKey("Tes"); + var result = AppCache.SearchByKey("Tes"); Assert.AreEqual(3, result.Count()); } @@ -127,14 +127,14 @@ namespace Umbraco.Tests.Cache var cacheContent2 = new MacroCacheContent(new LiteralControl(), "Test2"); var cacheContent3 = new MacroCacheContent(new LiteralControl(), "Test3"); var cacheContent4 = new LiteralControl(); - Provider.Get("TTes1t", () => cacheContent1); - Provider.Get("Tester2", () => cacheContent2); - Provider.Get("Tes3", () => cacheContent3); - Provider.Get("different4", () => cacheContent4); + AppCache.Get("TTes1t", () => cacheContent1); + AppCache.Get("Tester2", () => cacheContent2); + AppCache.Get("Tes3", () => cacheContent3); + AppCache.Get("different4", () => cacheContent4); Assert.AreEqual(4, GetTotalItemCount); - Provider.ClearByRegex("^\\w+es\\d.*"); + AppCache.ClearByRegex("^\\w+es\\d.*"); Assert.AreEqual(2, GetTotalItemCount); } @@ -146,14 +146,14 @@ namespace Umbraco.Tests.Cache var cacheContent2 = new MacroCacheContent(new LiteralControl(), "Test2"); var cacheContent3 = new MacroCacheContent(new LiteralControl(), "Test3"); var cacheContent4 = new LiteralControl(); - Provider.Get("Test1", () => cacheContent1); - Provider.Get("Tester2", () => cacheContent2); - Provider.Get("Tes3", () => cacheContent3); - Provider.Get("different4", () => cacheContent4); + AppCache.Get("Test1", () => cacheContent1); + AppCache.Get("Tester2", () => cacheContent2); + AppCache.Get("Tes3", () => cacheContent3); + AppCache.Get("different4", () => cacheContent4); Assert.AreEqual(4, GetTotalItemCount); - Provider.ClearByKey("Test"); + AppCache.ClearByKey("Test"); Assert.AreEqual(2, GetTotalItemCount); } @@ -165,15 +165,15 @@ namespace Umbraco.Tests.Cache var cacheContent2 = new MacroCacheContent(new LiteralControl(), "Test2"); var cacheContent3 = new MacroCacheContent(new LiteralControl(), "Test3"); var cacheContent4 = new LiteralControl(); - Provider.Get("Test1", () => cacheContent1); - Provider.Get("Test2", () => cacheContent2); - Provider.Get("Test3", () => cacheContent3); - Provider.Get("Test4", () => cacheContent4); + AppCache.Get("Test1", () => cacheContent1); + AppCache.Get("Test2", () => cacheContent2); + AppCache.Get("Test3", () => cacheContent3); + AppCache.Get("Test4", () => cacheContent4); Assert.AreEqual(4, GetTotalItemCount); - Provider.Clear("Test1"); - Provider.Clear("Test2"); + AppCache.Clear("Test1"); + AppCache.Clear("Test2"); Assert.AreEqual(2, GetTotalItemCount); } @@ -185,14 +185,14 @@ namespace Umbraco.Tests.Cache var cacheContent2 = new MacroCacheContent(new LiteralControl(), "Test2"); var cacheContent3 = new MacroCacheContent(new LiteralControl(), "Test3"); var cacheContent4 = new LiteralControl(); - Provider.Get("Test1", () => cacheContent1); - Provider.Get("Test2", () => cacheContent2); - Provider.Get("Test3", () => cacheContent3); - Provider.Get("Test4", () => cacheContent4); + AppCache.Get("Test1", () => cacheContent1); + AppCache.Get("Test2", () => cacheContent2); + AppCache.Get("Test3", () => cacheContent3); + AppCache.Get("Test4", () => cacheContent4); Assert.AreEqual(4, GetTotalItemCount); - Provider.Clear(); + AppCache.Clear(); Assert.AreEqual(0, GetTotalItemCount); } @@ -201,7 +201,7 @@ namespace Umbraco.Tests.Cache public void Can_Add_When_Not_Available() { var cacheContent1 = new MacroCacheContent(new LiteralControl(), "Test1"); - Provider.Get("Test1", () => cacheContent1); + AppCache.Get("Test1", () => cacheContent1); Assert.AreEqual(1, GetTotalItemCount); } @@ -209,8 +209,8 @@ namespace Umbraco.Tests.Cache public void Can_Get_When_Available() { var cacheContent1 = new MacroCacheContent(new LiteralControl(), "Test1"); - var result = Provider.Get("Test1", () => cacheContent1); - var result2 = Provider.Get("Test1", () => cacheContent1); + var result = AppCache.Get("Test1", () => cacheContent1); + var result2 = AppCache.Get("Test1", () => cacheContent1); Assert.AreEqual(1, GetTotalItemCount); Assert.AreEqual(result, result2); } @@ -222,15 +222,15 @@ namespace Umbraco.Tests.Cache var cacheContent2 = new MacroCacheContent(new LiteralControl(), "Test2"); var cacheContent3 = new MacroCacheContent(new LiteralControl(), "Test3"); var cacheContent4 = new LiteralControl(); - Provider.Get("Test1", () => cacheContent1); - Provider.Get("Test2", () => cacheContent2); - Provider.Get("Test3", () => cacheContent3); - Provider.Get("Test4", () => cacheContent4); + AppCache.Get("Test1", () => cacheContent1); + AppCache.Get("Test2", () => cacheContent2); + AppCache.Get("Test3", () => cacheContent3); + AppCache.Get("Test4", () => cacheContent4); Assert.AreEqual(4, GetTotalItemCount); //Provider.ClearCacheObjectTypes("umbraco.MacroCacheContent"); - Provider.ClearOfType(typeof(MacroCacheContent).ToString()); + AppCache.ClearOfType(typeof(MacroCacheContent).ToString()); Assert.AreEqual(1, GetTotalItemCount); } @@ -242,14 +242,14 @@ namespace Umbraco.Tests.Cache var cacheContent2 = new MacroCacheContent(new LiteralControl(), "Test2"); var cacheContent3 = new MacroCacheContent(new LiteralControl(), "Test3"); var cacheContent4 = new LiteralControl(); - Provider.Get("Test1", () => cacheContent1); - Provider.Get("Test2", () => cacheContent2); - Provider.Get("Test3", () => cacheContent3); - Provider.Get("Test4", () => cacheContent4); + AppCache.Get("Test1", () => cacheContent1); + AppCache.Get("Test2", () => cacheContent2); + AppCache.Get("Test3", () => cacheContent3); + AppCache.Get("Test4", () => cacheContent4); Assert.AreEqual(4, GetTotalItemCount); - Provider.ClearOfType(); + AppCache.ClearOfType(); Assert.AreEqual(1, GetTotalItemCount); } diff --git a/src/Umbraco.Tests/Cache/DeepCloneRuntimeCacheProviderTests.cs b/src/Umbraco.Tests/Cache/DeepCloneAppCacheTests.cs similarity index 94% rename from src/Umbraco.Tests/Cache/DeepCloneRuntimeCacheProviderTests.cs rename to src/Umbraco.Tests/Cache/DeepCloneAppCacheTests.cs index 7483df1c44..11e2c56873 100644 --- a/src/Umbraco.Tests/Cache/DeepCloneRuntimeCacheProviderTests.cs +++ b/src/Umbraco.Tests/Cache/DeepCloneAppCacheTests.cs @@ -8,13 +8,12 @@ using Umbraco.Core.Cache; using Umbraco.Core.Collections; using Umbraco.Core.Models; using Umbraco.Core.Models.Entities; -using Umbraco.Core.Persistence.Repositories; using Umbraco.Tests.Collections; namespace Umbraco.Tests.Cache { [TestFixture] - public class DeepCloneRuntimeCacheProviderTests : RuntimeCacheProviderTests + public class DeepCloneAppCacheTests : RuntimeAppCacheTests { private DeepCloneAppCache _provider; @@ -29,12 +28,12 @@ namespace Umbraco.Tests.Cache _provider = new DeepCloneAppCache(new WebCachingAppCache(HttpRuntime.Cache)); } - internal override IAppCache Provider + internal override IAppCache AppCache { get { return _provider; } } - internal override IAppPolicyCache RuntimeProvider + internal override IAppPolicyCache AppPolicyCache { get { return _provider; } } diff --git a/src/Umbraco.Tests/Cache/HttpRequestCacheProviderTests.cs b/src/Umbraco.Tests/Cache/HttpRequestAppCacheTests.cs similarity index 82% rename from src/Umbraco.Tests/Cache/HttpRequestCacheProviderTests.cs rename to src/Umbraco.Tests/Cache/HttpRequestAppCacheTests.cs index f442319d7f..635155f68e 100644 --- a/src/Umbraco.Tests/Cache/HttpRequestCacheProviderTests.cs +++ b/src/Umbraco.Tests/Cache/HttpRequestAppCacheTests.cs @@ -5,7 +5,7 @@ using Umbraco.Tests.TestHelpers; namespace Umbraco.Tests.Cache { [TestFixture] - public class HttpRequestCacheProviderTests : CacheProviderTests + public class HttpRequestAppCacheTests : AppCacheTests { private HttpRequestAppCache _provider; private FakeHttpContextFactory _ctx; @@ -17,7 +17,7 @@ namespace Umbraco.Tests.Cache _provider = new HttpRequestAppCache(_ctx.HttpContext); } - internal override IAppCache Provider + internal override IAppCache AppCache { get { return _provider; } } @@ -29,7 +29,7 @@ namespace Umbraco.Tests.Cache } [TestFixture] - public class StaticCacheProviderTests : CacheProviderTests + public class StaticAppCacheTests : AppCacheTests { private DictionaryCacheProvider _provider; @@ -39,7 +39,7 @@ namespace Umbraco.Tests.Cache _provider = new DictionaryCacheProvider(); } - internal override IAppCache Provider + internal override IAppCache AppCache { get { return _provider; } } diff --git a/src/Umbraco.Tests/Cache/HttpRuntimeCacheProviderTests.cs b/src/Umbraco.Tests/Cache/HttpRuntimeCacheProviderTests.cs deleted file mode 100644 index 6297539a1b..0000000000 --- a/src/Umbraco.Tests/Cache/HttpRuntimeCacheProviderTests.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; -using System.Diagnostics; -using System.Web; -using NUnit.Framework; -using Umbraco.Core.Cache; - -namespace Umbraco.Tests.Cache -{ - [TestFixture] - public class HttpRuntimeCacheProviderTests : RuntimeCacheProviderTests - { - private WebCachingAppCache _provider; - - protected override int GetTotalItemCount - { - get { return HttpRuntime.Cache.Count; } - } - - public override void Setup() - { - base.Setup(); - _provider = new WebCachingAppCache(HttpRuntime.Cache); - } - - internal override IAppCache Provider - { - get { return _provider; } - } - - internal override IAppPolicyCache RuntimeProvider - { - get { return _provider; } - } - - [Test] - public void DoesNotCacheExceptions() - { - string value; - Assert.Throws(() => { value = (string)_provider.Get("key", () => GetValue(1)); }); - Assert.Throws(() => { value = (string)_provider.Get("key", () => GetValue(2)); }); - - // does not throw - value = (string)_provider.Get("key", () => GetValue(3)); - Assert.AreEqual("succ3", value); - - // cache - value = (string)_provider.Get("key", () => GetValue(4)); - Assert.AreEqual("succ3", value); - } - - private static string GetValue(int i) - { - Debug.Print("get" + i); - if (i < 3) - throw new Exception("fail"); - return "succ" + i; - } - } -} diff --git a/src/Umbraco.Tests/Cache/ObjectCacheProviderTests.cs b/src/Umbraco.Tests/Cache/ObjectAppCacheTests.cs similarity index 78% rename from src/Umbraco.Tests/Cache/ObjectCacheProviderTests.cs rename to src/Umbraco.Tests/Cache/ObjectAppCacheTests.cs index 4d34e81eff..b9c729f891 100644 --- a/src/Umbraco.Tests/Cache/ObjectCacheProviderTests.cs +++ b/src/Umbraco.Tests/Cache/ObjectAppCacheTests.cs @@ -8,7 +8,7 @@ using Umbraco.Core.Cache; namespace Umbraco.Tests.Cache { [TestFixture] - public class ObjectCacheProviderTests : RuntimeCacheProviderTests + public class ObjectAppCacheTests : RuntimeAppCacheTests { private ObjectCacheAppCache _provider; @@ -23,12 +23,12 @@ namespace Umbraco.Tests.Cache _provider = new ObjectCacheAppCache(); } - internal override IAppCache Provider + internal override IAppCache AppCache { get { return _provider; } } - internal override IAppPolicyCache RuntimeProvider + internal override IAppPolicyCache AppPolicyCache { get { return _provider; } } diff --git a/src/Umbraco.Tests/Cache/PublishedCache/PublishedContentCacheTests.cs b/src/Umbraco.Tests/Cache/PublishedCache/PublishedContentCacheTests.cs index 79d0dfb9da..f740637602 100644 --- a/src/Umbraco.Tests/Cache/PublishedCache/PublishedContentCacheTests.cs +++ b/src/Umbraco.Tests/Cache/PublishedCache/PublishedContentCacheTests.cs @@ -63,12 +63,12 @@ namespace Umbraco.Tests.Cache.PublishedCache _xml = new XmlDocument(); _xml.LoadXml(GetXml()); var xmlStore = new XmlStore(() => _xml, null, null, null); - var cacheProvider = new DictionaryCacheProvider(); + var appCache = new DictionaryCacheProvider(); var domainCache = new DomainCache(ServiceContext.DomainService, DefaultCultureAccessor); var publishedShapshot = new Umbraco.Web.PublishedCache.XmlPublishedCache.PublishedSnapshot( - new PublishedContentCache(xmlStore, domainCache, cacheProvider, globalSettings, new SiteDomainHelper(), ContentTypesCache, null, null), - new PublishedMediaCache(xmlStore, ServiceContext.MediaService, ServiceContext.UserService, cacheProvider, ContentTypesCache, Factory.GetInstance()), - new PublishedMemberCache(null, cacheProvider, Current.Services.MemberService, ContentTypesCache), + new PublishedContentCache(xmlStore, domainCache, appCache, globalSettings, new SiteDomainHelper(), ContentTypesCache, null, null), + new PublishedMediaCache(xmlStore, ServiceContext.MediaService, ServiceContext.UserService, appCache, ContentTypesCache, Factory.GetInstance()), + new PublishedMemberCache(null, appCache, Current.Services.MemberService, ContentTypesCache), domainCache); var publishedSnapshotService = new Mock(); publishedSnapshotService.Setup(x => x.CreatePublishedSnapshot(It.IsAny())).Returns(publishedShapshot); diff --git a/src/Umbraco.Tests/Cache/RuntimeCacheProviderTests.cs b/src/Umbraco.Tests/Cache/RuntimeAppCacheTests.cs similarity index 51% rename from src/Umbraco.Tests/Cache/RuntimeCacheProviderTests.cs rename to src/Umbraco.Tests/Cache/RuntimeAppCacheTests.cs index 6391e4ec7a..1beeae74db 100644 --- a/src/Umbraco.Tests/Cache/RuntimeCacheProviderTests.cs +++ b/src/Umbraco.Tests/Cache/RuntimeAppCacheTests.cs @@ -5,25 +5,23 @@ using Umbraco.Core.Cache; namespace Umbraco.Tests.Cache { - public abstract class RuntimeCacheProviderTests : CacheProviderTests + public abstract class RuntimeAppCacheTests : AppCacheTests { - - internal abstract IAppPolicyCache RuntimeProvider { get; } - + internal abstract IAppPolicyCache AppPolicyCache { get; } [Test] [Explicit("Testing for timeouts cannot work on VSTS.")] public void Can_Add_And_Expire_Struct_Strongly_Typed_With_Null() { var now = DateTime.Now; - RuntimeProvider.Insert("DateTimeTest", () => now, new TimeSpan(0, 0, 0, 0, 200)); - Assert.AreEqual(now, Provider.GetCacheItem("DateTimeTest")); - Assert.AreEqual(now, Provider.GetCacheItem("DateTimeTest")); + AppPolicyCache.Insert("DateTimeTest", () => now, new TimeSpan(0, 0, 0, 0, 200)); + Assert.AreEqual(now, AppCache.GetCacheItem("DateTimeTest")); + Assert.AreEqual(now, AppCache.GetCacheItem("DateTimeTest")); Thread.Sleep(300); //sleep longer than the cache expiration - Assert.AreEqual(default(DateTime), Provider.GetCacheItem("DateTimeTest")); - Assert.AreEqual(null, Provider.GetCacheItem("DateTimeTest")); + Assert.AreEqual(default(DateTime), AppCache.GetCacheItem("DateTimeTest")); + Assert.AreEqual(null, AppCache.GetCacheItem("DateTimeTest")); } } } diff --git a/src/Umbraco.Tests/Cache/WebCachingAppCacheTests.cs b/src/Umbraco.Tests/Cache/WebCachingAppCacheTests.cs new file mode 100644 index 0000000000..e732ae5766 --- /dev/null +++ b/src/Umbraco.Tests/Cache/WebCachingAppCacheTests.cs @@ -0,0 +1,50 @@ +using System; +using System.Diagnostics; +using System.Web; +using NUnit.Framework; +using Umbraco.Core.Cache; + +namespace Umbraco.Tests.Cache +{ + [TestFixture] + public class WebCachingAppCacheTests : RuntimeAppCacheTests + { + private WebCachingAppCache _appCache; + + protected override int GetTotalItemCount => HttpRuntime.Cache.Count; + + public override void Setup() + { + base.Setup(); + _appCache = new WebCachingAppCache(HttpRuntime.Cache); + } + + internal override IAppCache AppCache => _appCache; + + internal override IAppPolicyCache AppPolicyCache => _appCache; + + [Test] + public void DoesNotCacheExceptions() + { + string value; + Assert.Throws(() => { value = (string)_appCache.Get("key", () => GetValue(1)); }); + Assert.Throws(() => { value = (string)_appCache.Get("key", () => GetValue(2)); }); + + // does not throw + value = (string)_appCache.Get("key", () => GetValue(3)); + Assert.AreEqual("succ3", value); + + // cache + value = (string)_appCache.Get("key", () => GetValue(4)); + Assert.AreEqual("succ3", value); + } + + private static string GetValue(int i) + { + Debug.Print("get" + i); + if (i < 3) + throw new Exception("fail"); + return "succ" + i; + } + } +} diff --git a/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs b/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs index 12cd02d2e9..c56ec57db0 100644 --- a/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs @@ -60,7 +60,7 @@ namespace Umbraco.Tests.Scoping { var scopeProvider = ScopeProvider; var service = Current.Services.UserService; - var globalCache = Current.ApplicationCache.IsolatedCaches.GetOrCreate(typeof(IUser)); + var globalCache = Current.AppCaches.IsolatedCaches.GetOrCreate(typeof(IUser)); var user = (IUser)new User("name", "email", "username", "rawPassword"); service.Save(user); @@ -137,7 +137,7 @@ namespace Umbraco.Tests.Scoping { var scopeProvider = ScopeProvider; var service = Current.Services.LocalizationService; - var globalCache = Current.ApplicationCache.IsolatedCaches.GetOrCreate(typeof (ILanguage)); + var globalCache = Current.AppCaches.IsolatedCaches.GetOrCreate(typeof (ILanguage)); var lang = (ILanguage) new Language("fr-FR"); service.Save(lang); @@ -229,7 +229,7 @@ namespace Umbraco.Tests.Scoping { var scopeProvider = ScopeProvider; var service = Current.Services.LocalizationService; - var globalCache = Current.ApplicationCache.IsolatedCaches.GetOrCreate(typeof (IDictionaryItem)); + var globalCache = Current.AppCaches.IsolatedCaches.GetOrCreate(typeof (IDictionaryItem)); var lang = (ILanguage)new Language("fr-FR"); service.Save(lang); diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index e49ba250fa..a2d33a1f31 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -225,7 +225,7 @@ - + @@ -286,11 +286,11 @@ - - - - - + + + + + diff --git a/src/Umbraco.Web/Cache/ContentCacheRefresher.cs b/src/Umbraco.Web/Cache/ContentCacheRefresher.cs index 36397540b6..3f2ef1620c 100644 --- a/src/Umbraco.Web/Cache/ContentCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/ContentCacheRefresher.cs @@ -102,7 +102,7 @@ namespace Umbraco.Web.Cache if (payloads.Any(x => x.ChangeTypes.HasType(TreeChangeTypes.RefreshAll)) || publishedChanged) { // when a public version changes - Current.ApplicationCache.ClearPartialViewCache(); + Current.AppCaches.ClearPartialViewCache(); MacroCacheRefresher.ClearMacroContentCache(AppCaches); // just the content } diff --git a/src/Umbraco.Web/Cache/MediaCacheRefresher.cs b/src/Umbraco.Web/Cache/MediaCacheRefresher.cs index cdaf43dac3..fc62d38e62 100644 --- a/src/Umbraco.Web/Cache/MediaCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/MediaCacheRefresher.cs @@ -47,7 +47,7 @@ namespace Umbraco.Web.Cache if (anythingChanged) { - Current.ApplicationCache.ClearPartialViewCache(); + Current.AppCaches.ClearPartialViewCache(); var mediaCache = AppCaches.IsolatedCaches.Get(); diff --git a/src/Umbraco.Web/Composing/Current.cs b/src/Umbraco.Web/Composing/Current.cs index ed1853c351..8759193964 100644 --- a/src/Umbraco.Web/Composing/Current.cs +++ b/src/Umbraco.Web/Composing/Current.cs @@ -203,7 +203,7 @@ namespace Umbraco.Web.Composing public static IProfilingLogger ProfilingLogger => CoreCurrent.ProfilingLogger; - public static AppCaches ApplicationCache => CoreCurrent.ApplicationCache; + public static AppCaches AppCaches => CoreCurrent.AppCaches; public static ServiceContext Services => CoreCurrent.Services; diff --git a/src/Umbraco.Web/Dictionary/UmbracoCultureDictionary.cs b/src/Umbraco.Web/Dictionary/UmbracoCultureDictionary.cs index 5234bf9fa7..6e1c35352a 100644 --- a/src/Umbraco.Web/Dictionary/UmbracoCultureDictionary.cs +++ b/src/Umbraco.Web/Dictionary/UmbracoCultureDictionary.cs @@ -21,31 +21,29 @@ namespace Umbraco.Web.Dictionary public class DefaultCultureDictionary : Core.Dictionary.ICultureDictionary { private readonly ILocalizationService _localizationService; - private readonly IAppCache _requestCacheProvider; + private readonly IAppCache _requestCache; private readonly CultureInfo _specificCulture; public DefaultCultureDictionary() - : this(Current.Services.LocalizationService, Current.ApplicationCache.RequestCache) - { + : this(Current.Services.LocalizationService, Current.AppCaches.RequestCache) + { } - } - - public DefaultCultureDictionary(ILocalizationService localizationService, IAppCache requestCacheProvider) + public DefaultCultureDictionary(ILocalizationService localizationService, IAppCache requestCache) { _localizationService = localizationService ?? throw new ArgumentNullException(nameof(localizationService)); - _requestCacheProvider = requestCacheProvider ?? throw new ArgumentNullException(nameof(requestCacheProvider)); + _requestCache = requestCache ?? throw new ArgumentNullException(nameof(requestCache)); } public DefaultCultureDictionary(CultureInfo specificCulture) - : this(Current.Services.LocalizationService, Current.ApplicationCache.RequestCache) + : this(Current.Services.LocalizationService, Current.AppCaches.RequestCache) { _specificCulture = specificCulture ?? throw new ArgumentNullException(nameof(specificCulture)); } - public DefaultCultureDictionary(CultureInfo specificCulture, ILocalizationService localizationService, IAppCache requestCacheProvider) + public DefaultCultureDictionary(CultureInfo specificCulture, ILocalizationService localizationService, IAppCache requestCache) { _localizationService = localizationService ?? throw new ArgumentNullException(nameof(localizationService)); - _requestCacheProvider = requestCacheProvider ?? throw new ArgumentNullException(nameof(requestCacheProvider)); + _requestCache = requestCache ?? throw new ArgumentNullException(nameof(requestCache)); _specificCulture = specificCulture ?? throw new ArgumentNullException(nameof(specificCulture)); } @@ -123,7 +121,7 @@ namespace Umbraco.Web.Dictionary { //ensure it's stored/retrieved from request cache //NOTE: This is no longer necessary since these are cached at the runtime level, but we can leave it here for now. - return _requestCacheProvider.GetCacheItem(typeof (DefaultCultureDictionary).Name + "Culture" + Culture.Name, + return _requestCache.GetCacheItem(typeof (DefaultCultureDictionary).Name + "Culture" + Culture.Name, () => _localizationService.GetLanguageByIsoCode(Culture.Name)); } } diff --git a/src/Umbraco.Web/Editors/CurrentUserController.cs b/src/Umbraco.Web/Editors/CurrentUserController.cs index b0f4af0f57..02470e8ea1 100644 --- a/src/Umbraco.Web/Editors/CurrentUserController.cs +++ b/src/Umbraco.Web/Editors/CurrentUserController.cs @@ -157,7 +157,7 @@ namespace Umbraco.Web.Editors public async Task PostSetAvatar() { //borrow the logic from the user controller - return await UsersController.PostSetAvatarInternal(Request, Services.UserService, Current.ApplicationCache.StaticCache, Security.GetUserId().ResultOr(0)); + return await UsersController.PostSetAvatarInternal(Request, Services.UserService, Current.AppCaches.StaticCache, Security.GetUserId().ResultOr(0)); } /// diff --git a/src/Umbraco.Web/HtmlHelperRenderExtensions.cs b/src/Umbraco.Web/HtmlHelperRenderExtensions.cs index 9c30f74ea7..626a19a369 100644 --- a/src/Umbraco.Web/HtmlHelperRenderExtensions.cs +++ b/src/Umbraco.Web/HtmlHelperRenderExtensions.cs @@ -105,7 +105,7 @@ namespace Umbraco.Web var contextualKey = contextualKeyBuilder(model, viewData); cacheKey.AppendFormat("c{0}-", contextualKey); } - return Current.ApplicationCache.CachedPartialView(htmlHelper, partialViewName, model, cachedSeconds, cacheKey.ToString(), viewData); + return Current.AppCaches.CachedPartialView(htmlHelper, partialViewName, model, cachedSeconds, cacheKey.ToString(), viewData); } public static MvcHtmlString EditorFor(this HtmlHelper htmlHelper, string templateName = "", string htmlFieldName = "", object additionalViewData = null) diff --git a/src/Umbraco.Web/Macros/MacroRenderer.cs b/src/Umbraco.Web/Macros/MacroRenderer.cs index 0bcdb3225b..b7187da743 100755 --- a/src/Umbraco.Web/Macros/MacroRenderer.cs +++ b/src/Umbraco.Web/Macros/MacroRenderer.cs @@ -94,7 +94,7 @@ namespace Umbraco.Web.Macros // only if cache is enabled if (UmbracoContext.Current.InPreviewMode || model.CacheDuration <= 0) return null; - var cache = Current.ApplicationCache.RuntimeCache; + var cache = Current.AppCaches.RuntimeCache; var macroContent = cache.GetCacheItem(CacheKeys.MacroContentCacheKey + model.CacheIdentifier); if (macroContent == null) return null; @@ -151,7 +151,7 @@ namespace Umbraco.Web.Macros // remember when we cache the content macroContent.Date = DateTime.Now; - var cache = Current.ApplicationCache.RuntimeCache; + var cache = Current.AppCaches.RuntimeCache; cache.Insert( CacheKeys.MacroContentCacheKey + model.CacheIdentifier, () => macroContent, diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/DictionaryPublishedContent.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/DictionaryPublishedContent.cs index e040e7e926..83bd84dab6 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/DictionaryPublishedContent.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/DictionaryPublishedContent.cs @@ -35,7 +35,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache Func getParent, Func> getChildren, Func getProperty, - IAppCache cacheProvider, + IAppCache appCache, PublishedContentTypeCache contentTypeCache, XPathNavigator nav, bool fromExamine) @@ -47,7 +47,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache _getParent = new Lazy(() => getParent(ParentId)); _getChildren = new Lazy>(() => getChildren(Id, nav)); _getProperty = getProperty; - _cacheProvider = cacheProvider; + _appCache = appCache; LoadedFromExamine = fromExamine; @@ -133,7 +133,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache //private readonly Func> _getChildren; private readonly Lazy> _getChildren; private readonly Func _getProperty; - private readonly IAppCache _cacheProvider; + private readonly IAppCache _appCache; /// /// Returns 'Media' as the item type diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedContentCache.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedContentCache.cs index 67813ce9f6..d8c7c41ea1 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedContentCache.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedContentCache.cs @@ -15,7 +15,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache { internal class PublishedContentCache : PublishedCacheBase, IPublishedContentCache { - private readonly IAppCache _cacheProvider; + private readonly IAppCache _appCache; private readonly IGlobalSettings _globalSettings; private readonly RoutesCache _routesCache; private readonly IDomainCache _domainCache; @@ -24,13 +24,13 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache // initialize a PublishedContentCache instance with // an XmlStore containing the master xml - // an ICacheProvider that should be at request-level + // an IAppCache that should be at request-level // a RoutesCache - need to cleanup that one // a preview token string (or null if not previewing) public PublishedContentCache( XmlStore xmlStore, // an XmlStore containing the master xml IDomainCache domainCache, // an IDomainCache implementation - IAppCache cacheProvider, // an ICacheProvider that should be at request-level + IAppCache appCache, // an IAppCache that should be at request-level IGlobalSettings globalSettings, ISiteDomainHelper siteDomainHelper, PublishedContentTypeCache contentTypeCache, // a PublishedContentType cache @@ -38,7 +38,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache string previewToken) // a preview token string (or null if not previewing) : base(previewToken.IsNullOrWhiteSpace() == false) { - _cacheProvider = cacheProvider; + _appCache = appCache; _globalSettings = globalSettings; _routesCache = routesCache; // may be null for unit-testing _contentTypeCache = contentTypeCache; @@ -315,13 +315,13 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache private IPublishedContent ConvertToDocument(XmlNode xmlNode, bool isPreviewing) { - return xmlNode == null ? null : XmlPublishedContent.Get(xmlNode, isPreviewing, _cacheProvider, _contentTypeCache); + return xmlNode == null ? null : XmlPublishedContent.Get(xmlNode, isPreviewing, _appCache, _contentTypeCache); } private IEnumerable ConvertToDocuments(XmlNodeList xmlNodes, bool isPreviewing) { return xmlNodes.Cast() - .Select(xmlNode => XmlPublishedContent.Get(xmlNode, isPreviewing, _cacheProvider, _contentTypeCache)); + .Select(xmlNode => XmlPublishedContent.Get(xmlNode, isPreviewing, _appCache, _contentTypeCache)); } #endregion @@ -517,8 +517,8 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache // clear recursive properties cached by XmlPublishedContent.GetProperty // assume that nothing else is going to cache IPublishedProperty items (else would need to do ByKeySearch) // NOTE also clears all the media cache properties, which is OK (see media cache) - _cacheProvider.ClearOfType(); - //_cacheProvider.ClearCacheByKeySearch("XmlPublishedCache.PublishedContentCache:RecursiveProperty-"); + _appCache.ClearOfType(); + //_appCache.ClearCacheByKeySearch("XmlPublishedCache.PublishedContentCache:RecursiveProperty-"); } #endregion diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs index 3ead5a5166..dadf40a33b 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs @@ -43,15 +43,15 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache private readonly IEntityXmlSerializer _entitySerializer; // must be specified by the ctor - private readonly IAppCache _cacheProvider; + private readonly IAppCache _appCache; - public PublishedMediaCache(XmlStore xmlStore, IMediaService mediaService, IUserService userService, IAppCache cacheProvider, PublishedContentTypeCache contentTypeCache, IEntityXmlSerializer entitySerializer) + public PublishedMediaCache(XmlStore xmlStore, IMediaService mediaService, IUserService userService, IAppCache appCache, PublishedContentTypeCache contentTypeCache, IEntityXmlSerializer entitySerializer) : base(false) { _mediaService = mediaService ?? throw new ArgumentNullException(nameof(mediaService)); _userService = userService ?? throw new ArgumentNullException(nameof(userService)); - _cacheProvider = cacheProvider; + _appCache = appCache; _xmlStore = xmlStore; _contentTypeCache = contentTypeCache; _entitySerializer = entitySerializer; @@ -63,16 +63,16 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache /// /// /// - /// + /// /// /// - internal PublishedMediaCache(IMediaService mediaService, IUserService userService, ISearcher searchProvider, IAppCache cacheProvider, PublishedContentTypeCache contentTypeCache, IEntityXmlSerializer entitySerializer) + internal PublishedMediaCache(IMediaService mediaService, IUserService userService, ISearcher searchProvider, IAppCache appCache, PublishedContentTypeCache contentTypeCache, IEntityXmlSerializer entitySerializer) : base(false) { _mediaService = mediaService ?? throw new ArgumentNullException(nameof(mediaService)); _userService = userService ?? throw new ArgumentNullException(nameof(userService)); _searchProvider = searchProvider ?? throw new ArgumentNullException(nameof(searchProvider)); - _cacheProvider = cacheProvider; + _appCache = appCache; _contentTypeCache = contentTypeCache; _entitySerializer = entitySerializer; } @@ -598,8 +598,8 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache // clear recursive properties cached by XmlPublishedContent.GetProperty // assume that nothing else is going to cache IPublishedProperty items (else would need to do ByKeySearch) // NOTE all properties cleared when clearing the content cache (see content cache) - //_cacheProvider.ClearCacheObjectTypes(); - //_cacheProvider.ClearCacheByKeySearch("XmlPublishedCache.PublishedMediaCache:RecursiveProperty-"); + //_appCache.ClearCacheObjectTypes(); + //_appCache.ClearCacheByKeySearch("XmlPublishedCache.PublishedMediaCache:RecursiveProperty-"); } #region Content types @@ -663,7 +663,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache parentId => parentId < 0 ? null : GetUmbracoMedia(parentId), GetChildrenMedia, GetProperty, - _cacheProvider, + _appCache, _contentTypeCache, cacheValues.XPath, // though, outside of tests, that should be null cacheValues.FromExamine @@ -676,14 +676,14 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache if (_publishedMediaCacheEnabled == false) return func(id); - var cache = Current.ApplicationCache.RuntimeCache; + var cache = Current.AppCaches.RuntimeCache; var key = PublishedMediaCacheKey + id; return (CacheValues)cache.Get(key, () => func(id), _publishedMediaCacheTimespan); } internal static void ClearCache(int id) { - var cache = Current.ApplicationCache.RuntimeCache; + var cache = Current.AppCaches.RuntimeCache; var sid = id.ToString(); var key = PublishedMediaCacheKey + sid; diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlPublishedContent.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlPublishedContent.cs index a313d6947d..eb54c85984 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlPublishedContent.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlPublishedContent.cs @@ -20,18 +20,18 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache [XmlType(Namespace = "http://umbraco.org/webservices/")] internal class XmlPublishedContent : PublishedContentBase { - private XmlPublishedContent(XmlNode xmlNode, bool isPreviewing, IAppCache cacheProvider, PublishedContentTypeCache contentTypeCache) + private XmlPublishedContent(XmlNode xmlNode, bool isPreviewing, IAppCache appCache, PublishedContentTypeCache contentTypeCache) { _xmlNode = xmlNode; _isPreviewing = isPreviewing; - _cacheProvider = cacheProvider; + _appCache = appCache; _contentTypeCache = contentTypeCache; } private readonly XmlNode _xmlNode; private readonly bool _isPreviewing; - private readonly IAppCache _cacheProvider; // at snapshot/request level (see PublishedContentCache) + private readonly IAppCache _appCache; // at snapshot/request level (see PublishedContentCache) private readonly PublishedContentTypeCache _contentTypeCache; private readonly object _initializeLock = new object(); @@ -252,7 +252,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache if (parent == null) return; if (parent.Attributes?.GetNamedItem("isDoc") != null) - _parent = Get(parent, _isPreviewing, _cacheProvider, _contentTypeCache); + _parent = Get(parent, _isPreviewing, _appCache, _contentTypeCache); _parentInitialized = true; } @@ -409,7 +409,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache var iterator = nav.Select(expr); _children = iterator.Cast() - .Select(n => Get(((IHasXmlNode) n).GetNode(), _isPreviewing, _cacheProvider, _contentTypeCache)) + .Select(n => Get(((IHasXmlNode) n).GetNode(), _isPreviewing, _appCache, _contentTypeCache)) .OrderBy(x => x.SortOrder) .ToList(); @@ -440,7 +440,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache public static void ClearRequest() { - Current.ApplicationCache.RequestCache.ClearByKey(CacheKeyPrefix); + Current.AppCaches.RequestCache.ClearByKey(CacheKeyPrefix); } private const string CacheKeyPrefix = "CONTENTCACHE_XMLPUBLISHEDCONTENT_"; From ec58532f7bf70b055703b18bc7ded1e2278bfe1c Mon Sep 17 00:00:00 2001 From: Stephan Date: Fri, 18 Jan 2019 08:29:16 +0100 Subject: [PATCH 449/469] More renaming of caches --- src/Umbraco.Core/Cache/AppCaches.cs | 6 +++--- ...CacheProvider.cs => DictionaryAppCache.cs} | 2 +- ...eProvider.cs => FastDictionaryAppCache.cs} | 2 +- src/Umbraco.Core/Runtime/CoreRuntime.cs | 2 +- src/Umbraco.Core/Umbraco.Core.csproj | 4 ++-- src/Umbraco.Tests/Cache/AppCacheTests.cs | 6 +++--- .../Cache/HttpRequestAppCacheTests.cs | 16 +++++++-------- .../PublishedContentCacheTests.cs | 2 +- .../PublishedMediaCacheTests.cs | 8 ++++---- src/Umbraco.Tests/Macros/MacroTests.cs | 2 +- .../Repositories/DocumentRepositoryTest.cs | 4 ++-- .../Repositories/MediaRepositoryTest.cs | 4 ++-- .../Published/PropertyCacheLevelTests.cs | 4 ++-- .../PublishedContent/PublishedMediaTests.cs | 20 +++++++++---------- .../Scoping/ScopedRepositoryTests.cs | 2 +- .../NuCache/PublishedSnapshotService.cs | 13 ++++++------ .../XmlPublishedCache/PublishedMemberCache.cs | 4 ++-- .../XmlPublishedCache/XmlPublishedContent.cs | 6 +++--- src/Umbraco.Web/Runtime/WebRuntime.cs | 2 +- 19 files changed, 55 insertions(+), 54 deletions(-) rename src/Umbraco.Core/Cache/{DictionaryCacheProvider.cs => DictionaryAppCache.cs} (98%) rename src/Umbraco.Core/Cache/{FastDictionaryCacheProvider.cs => FastDictionaryAppCache.cs} (99%) diff --git a/src/Umbraco.Core/Cache/AppCaches.cs b/src/Umbraco.Core/Cache/AppCaches.cs index 7e5fa43682..d81e79f7d8 100644 --- a/src/Umbraco.Core/Cache/AppCaches.cs +++ b/src/Umbraco.Core/Cache/AppCaches.cs @@ -21,7 +21,7 @@ namespace Umbraco.Core.Cache public AppCaches(System.Web.Caching.Cache cache) : this( new WebCachingAppCache(cache), - new DictionaryCacheProvider(), + new DictionaryAppCache(), new HttpRequestAppCache(), new IsolatedCaches(t => new ObjectCacheAppCache())) { } @@ -31,12 +31,12 @@ namespace Umbraco.Core.Cache /// public AppCaches( IAppPolicyCache runtimeCache, - IAppCache staticCacheProvider, + IAppCache staticCache, IAppCache requestCache, IsolatedCaches isolatedCaches) { RuntimeCache = runtimeCache ?? throw new ArgumentNullException(nameof(runtimeCache)); - StaticCache = staticCacheProvider ?? throw new ArgumentNullException(nameof(staticCacheProvider)); + StaticCache = staticCache ?? throw new ArgumentNullException(nameof(staticCache)); RequestCache = requestCache ?? throw new ArgumentNullException(nameof(requestCache)); IsolatedCaches = isolatedCaches ?? throw new ArgumentNullException(nameof(isolatedCaches)); } diff --git a/src/Umbraco.Core/Cache/DictionaryCacheProvider.cs b/src/Umbraco.Core/Cache/DictionaryAppCache.cs similarity index 98% rename from src/Umbraco.Core/Cache/DictionaryCacheProvider.cs rename to src/Umbraco.Core/Cache/DictionaryAppCache.cs index 2ff5f6ea83..4c08bd0524 100644 --- a/src/Umbraco.Core/Cache/DictionaryCacheProvider.cs +++ b/src/Umbraco.Core/Cache/DictionaryAppCache.cs @@ -8,7 +8,7 @@ namespace Umbraco.Core.Cache /// /// Implements on top of a concurrent dictionary. /// - public class DictionaryCacheProvider : IAppCache + public class DictionaryAppCache : IAppCache { /// /// Gets the internal items dictionary, for tests only! diff --git a/src/Umbraco.Core/Cache/FastDictionaryCacheProvider.cs b/src/Umbraco.Core/Cache/FastDictionaryAppCache.cs similarity index 99% rename from src/Umbraco.Core/Cache/FastDictionaryCacheProvider.cs rename to src/Umbraco.Core/Cache/FastDictionaryAppCache.cs index a3863dac52..bd545694f7 100644 --- a/src/Umbraco.Core/Cache/FastDictionaryCacheProvider.cs +++ b/src/Umbraco.Core/Cache/FastDictionaryAppCache.cs @@ -10,7 +10,7 @@ namespace Umbraco.Core.Cache /// /// Implements a fast on top of a concurrent dictionary. /// - internal class FastDictionaryCacheProvider : IAppCache + internal class FastDictionaryAppCache : IAppCache { /// /// Gets the internal items dictionary, for tests only! diff --git a/src/Umbraco.Core/Runtime/CoreRuntime.cs b/src/Umbraco.Core/Runtime/CoreRuntime.cs index 6bfe9cdb55..8f1fa54a0c 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntime.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntime.cs @@ -332,7 +332,7 @@ namespace Umbraco.Core.Runtime return new AppCaches( new DeepCloneAppCache(new ObjectCacheAppCache()), - new DictionaryCacheProvider(), + new DictionaryAppCache(), NoAppCache.Instance, new IsolatedCaches(type => new DeepCloneAppCache(new ObjectCacheAppCache()))); } diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 5b2692359a..49a1cf8d8f 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -121,7 +121,7 @@ - + @@ -141,7 +141,7 @@ - + diff --git a/src/Umbraco.Tests/Cache/AppCacheTests.cs b/src/Umbraco.Tests/Cache/AppCacheTests.cs index f18e08d680..29d61cc14a 100644 --- a/src/Umbraco.Tests/Cache/AppCacheTests.cs +++ b/src/Umbraco.Tests/Cache/AppCacheTests.cs @@ -27,9 +27,9 @@ namespace Umbraco.Tests.Cache [Test] public void Throws_On_Reentry() { - // don't run for StaticCacheProvider - not making sense - if (GetType() == typeof (StaticAppCacheTests)) - Assert.Ignore("Do not run for StaticCacheProvider."); + // don't run for DictionaryAppCache - not making sense + if (GetType() == typeof (DictionaryAppCacheTests)) + Assert.Ignore("Do not run for DictionaryAppCache."); Exception exception = null; var result = AppCache.Get("blah", () => diff --git a/src/Umbraco.Tests/Cache/HttpRequestAppCacheTests.cs b/src/Umbraco.Tests/Cache/HttpRequestAppCacheTests.cs index 635155f68e..0be38d2c55 100644 --- a/src/Umbraco.Tests/Cache/HttpRequestAppCacheTests.cs +++ b/src/Umbraco.Tests/Cache/HttpRequestAppCacheTests.cs @@ -7,19 +7,19 @@ namespace Umbraco.Tests.Cache [TestFixture] public class HttpRequestAppCacheTests : AppCacheTests { - private HttpRequestAppCache _provider; + private HttpRequestAppCache _appCache; private FakeHttpContextFactory _ctx; public override void Setup() { base.Setup(); _ctx = new FakeHttpContextFactory("http://localhost/test"); - _provider = new HttpRequestAppCache(_ctx.HttpContext); + _appCache = new HttpRequestAppCache(_ctx.HttpContext); } internal override IAppCache AppCache { - get { return _provider; } + get { return _appCache; } } protected override int GetTotalItemCount @@ -29,24 +29,24 @@ namespace Umbraco.Tests.Cache } [TestFixture] - public class StaticAppCacheTests : AppCacheTests + public class DictionaryAppCacheTests : AppCacheTests { - private DictionaryCacheProvider _provider; + private DictionaryAppCache _appCache; public override void Setup() { base.Setup(); - _provider = new DictionaryCacheProvider(); + _appCache = new DictionaryAppCache(); } internal override IAppCache AppCache { - get { return _provider; } + get { return _appCache; } } protected override int GetTotalItemCount { - get { return _provider.Items.Count; } + get { return _appCache.Items.Count; } } } } diff --git a/src/Umbraco.Tests/Cache/PublishedCache/PublishedContentCacheTests.cs b/src/Umbraco.Tests/Cache/PublishedCache/PublishedContentCacheTests.cs index f740637602..147a159d5f 100644 --- a/src/Umbraco.Tests/Cache/PublishedCache/PublishedContentCacheTests.cs +++ b/src/Umbraco.Tests/Cache/PublishedCache/PublishedContentCacheTests.cs @@ -63,7 +63,7 @@ namespace Umbraco.Tests.Cache.PublishedCache _xml = new XmlDocument(); _xml.LoadXml(GetXml()); var xmlStore = new XmlStore(() => _xml, null, null, null); - var appCache = new DictionaryCacheProvider(); + var appCache = new DictionaryAppCache(); var domainCache = new DomainCache(ServiceContext.DomainService, DefaultCultureAccessor); var publishedShapshot = new Umbraco.Web.PublishedCache.XmlPublishedCache.PublishedSnapshot( new PublishedContentCache(xmlStore, domainCache, appCache, globalSettings, new SiteDomainHelper(), ContentTypesCache, null, null), diff --git a/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs b/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs index ee16a1dede..cfc45b8f53 100644 --- a/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs +++ b/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs @@ -75,7 +75,7 @@ namespace Umbraco.Tests.Cache.PublishedCache var mChild2 = MakeNewMedia("Child2", mType, user, mRoot2.Id); var ctx = GetUmbracoContext("/test"); - var cache = new PublishedMediaCache(new XmlStore((XmlDocument) null, null, null, null), ServiceContext.MediaService, ServiceContext.UserService, new DictionaryCacheProvider(), ContentTypesCache, Factory.GetInstance()); + var cache = new PublishedMediaCache(new XmlStore((XmlDocument) null, null, null, null), ServiceContext.MediaService, ServiceContext.UserService, new DictionaryAppCache(), ContentTypesCache, Factory.GetInstance()); var roots = cache.GetAtRoot(); Assert.AreEqual(2, roots.Count()); Assert.IsTrue(roots.Select(x => x.Id).ContainsAll(new[] {mRoot1.Id, mRoot2.Id})); @@ -93,7 +93,7 @@ namespace Umbraco.Tests.Cache.PublishedCache //var publishedMedia = PublishedMediaTests.GetNode(mRoot.Id, GetUmbracoContext("/test", 1234)); var umbracoContext = GetUmbracoContext("/test"); - var cache = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), Current.Services.MediaService, Current.Services.UserService, new DictionaryCacheProvider(), ContentTypesCache, Factory.GetInstance()); + var cache = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), Current.Services.MediaService, Current.Services.UserService, new DictionaryAppCache(), ContentTypesCache, Factory.GetInstance()); var publishedMedia = cache.GetById(mRoot.Id); Assert.IsNotNull(publishedMedia); @@ -204,7 +204,7 @@ namespace Umbraco.Tests.Cache.PublishedCache var result = new SearchResult("1234", 1, () => fields.ToDictionary(x => x.Key, x => new List { x.Value })); - var store = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), ServiceContext.MediaService, ServiceContext.UserService, new DictionaryCacheProvider(), ContentTypesCache, Factory.GetInstance()); + var store = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), ServiceContext.MediaService, ServiceContext.UserService, new DictionaryAppCache(), ContentTypesCache, Factory.GetInstance()); var doc = store.CreateFromCacheValues(store.ConvertFromSearchResult(result)); DoAssert(doc, 1234, key, templateIdVal: null, 0, "/media/test.jpg", "Image", 23, "Shannon", "Shannon", 0, 0, "-1,1234", DateTime.Parse("2012-07-17T10:34:09"), DateTime.Parse("2012-07-16T10:34:09"), 2); @@ -220,7 +220,7 @@ namespace Umbraco.Tests.Cache.PublishedCache var xmlDoc = GetMediaXml(); ((XmlElement)xmlDoc.DocumentElement.FirstChild).SetAttribute("key", key.ToString()); var navigator = xmlDoc.SelectSingleNode("/root/Image").CreateNavigator(); - var cache = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), ServiceContext.MediaService, ServiceContext.UserService, new DictionaryCacheProvider(), ContentTypesCache, Factory.GetInstance()); + var cache = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), ServiceContext.MediaService, ServiceContext.UserService, new DictionaryAppCache(), ContentTypesCache, Factory.GetInstance()); var doc = cache.CreateFromCacheValues(cache.ConvertFromXPathNavigator(navigator, true)); DoAssert(doc, 2000, key, templateIdVal: null, 2, "image1", "Image", 23, "Shannon", "Shannon", 33, 33, "-1,2000", DateTime.Parse("2012-06-12T14:13:17"), DateTime.Parse("2012-07-20T18:50:43"), 1); diff --git a/src/Umbraco.Tests/Macros/MacroTests.cs b/src/Umbraco.Tests/Macros/MacroTests.cs index 225bd17618..15549d5d46 100644 --- a/src/Umbraco.Tests/Macros/MacroTests.cs +++ b/src/Umbraco.Tests/Macros/MacroTests.cs @@ -23,7 +23,7 @@ namespace Umbraco.Tests.Macros //we DO want cache enabled for these tests var cacheHelper = new AppCaches( new ObjectCacheAppCache(), - new DictionaryCacheProvider(), + new DictionaryAppCache(), NoAppCache.Instance, new IsolatedCaches(type => new ObjectCacheAppCache())); //Current.ApplicationContext = new ApplicationContext(cacheHelper, new ProfilingLogger(Mock.Of(), Mock.Of())); diff --git a/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs index 1641631f43..9b1c4defa2 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs @@ -77,8 +77,8 @@ namespace Umbraco.Tests.Persistence.Repositories { var realCache = new AppCaches( new ObjectCacheAppCache(), - new DictionaryCacheProvider(), - new DictionaryCacheProvider(), + new DictionaryAppCache(), + new DictionaryAppCache(), new IsolatedCaches(t => new ObjectCacheAppCache())); var provider = TestObjects.GetScopeProvider(Logger); diff --git a/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs index 33c8524bb4..5635def412 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs @@ -48,8 +48,8 @@ namespace Umbraco.Tests.Persistence.Repositories var realCache = new AppCaches( new ObjectCacheAppCache(), - new DictionaryCacheProvider(), - new DictionaryCacheProvider(), + new DictionaryAppCache(), + new DictionaryAppCache(), new IsolatedCaches(t => new ObjectCacheAppCache())); var provider = TestObjects.GetScopeProvider(Logger); diff --git a/src/Umbraco.Tests/Published/PropertyCacheLevelTests.cs b/src/Umbraco.Tests/Published/PropertyCacheLevelTests.cs index 04444855fb..76fdd81ec2 100644 --- a/src/Umbraco.Tests/Published/PropertyCacheLevelTests.cs +++ b/src/Umbraco.Tests/Published/PropertyCacheLevelTests.cs @@ -118,8 +118,8 @@ namespace Umbraco.Tests.Published publishedContentTypeFactory.CreatePropertyType("prop1", 1), }); - var elementsCache = new FastDictionaryCacheProvider(); - var snapshotCache = new FastDictionaryCacheProvider(); + var elementsCache = new FastDictionaryAppCache(); + var snapshotCache = new FastDictionaryAppCache(); var publishedSnapshot = new Mock(); publishedSnapshot.Setup(x => x.SnapshotCache).Returns(snapshotCache); diff --git a/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs index 4257e3dabb..dfb51e83fb 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs @@ -68,7 +68,7 @@ namespace Umbraco.Tests.PublishedContent internal IPublishedContent GetNode(int id, UmbracoContext umbracoContext) { var cache = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), - ServiceContext.MediaService, ServiceContext.UserService, new DictionaryCacheProvider(), ContentTypesCache, + ServiceContext.MediaService, ServiceContext.UserService, new DictionaryAppCache(), ContentTypesCache, Factory.GetInstance()); var doc = cache.GetById(id); Assert.IsNotNull(doc); @@ -126,7 +126,7 @@ namespace Umbraco.Tests.PublishedContent var searcher = indexer.GetSearcher(); var ctx = GetUmbracoContext("/test"); - var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryCacheProvider(), ContentTypesCache, Factory.GetInstance()); + var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryAppCache(), ContentTypesCache, Factory.GetInstance()); //we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace var publishedMedia = cache.GetById(1111); @@ -156,7 +156,7 @@ namespace Umbraco.Tests.PublishedContent var searcher = indexer.GetSearcher(); var ctx = GetUmbracoContext("/test"); - var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryCacheProvider(), ContentTypesCache, Factory.GetInstance()); + var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryAppCache(), ContentTypesCache, Factory.GetInstance()); //ensure it is found var publishedMedia = cache.GetById(3113); @@ -203,7 +203,7 @@ namespace Umbraco.Tests.PublishedContent var searcher = indexer.GetSearcher(); var ctx = GetUmbracoContext("/test"); - var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryCacheProvider(), ContentTypesCache, Factory.GetInstance()); + var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryAppCache(), ContentTypesCache, Factory.GetInstance()); //we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace var publishedMedia = cache.GetById(1111); @@ -231,7 +231,7 @@ namespace Umbraco.Tests.PublishedContent var searcher = indexer.GetSearcher(); var ctx = GetUmbracoContext("/test"); - var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryCacheProvider(), ContentTypesCache, Factory.GetInstance()); + var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryAppCache(), ContentTypesCache, Factory.GetInstance()); //we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace var publishedMedia = cache.GetById(1111); @@ -259,7 +259,7 @@ namespace Umbraco.Tests.PublishedContent var searcher = indexer.GetSearcher(); var ctx = GetUmbracoContext("/test"); - var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryCacheProvider(), ContentTypesCache, Factory.GetInstance()); + var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryAppCache(), ContentTypesCache, Factory.GetInstance()); //we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace var publishedMedia = cache.GetById(1111); @@ -288,7 +288,7 @@ namespace Umbraco.Tests.PublishedContent var ctx = GetUmbracoContext("/test"); var searcher = indexer.GetSearcher(); - var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryCacheProvider(), ContentTypesCache, Factory.GetInstance()); + var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryAppCache(), ContentTypesCache, Factory.GetInstance()); //we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace var publishedMedia = cache.GetById(3113); @@ -314,7 +314,7 @@ namespace Umbraco.Tests.PublishedContent var ctx = GetUmbracoContext("/test"); var searcher = indexer.GetSearcher(); - var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryCacheProvider(), ContentTypesCache, Factory.GetInstance()); + var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryAppCache(), ContentTypesCache, Factory.GetInstance()); //we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace var publishedMedia = cache.GetById(3113); @@ -482,7 +482,7 @@ namespace Umbraco.Tests.PublishedContent "); var node = xml.DescendantsAndSelf("Image").Single(x => (int)x.Attribute("id") == nodeId); - var publishedMedia = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), ServiceContext.MediaService, ServiceContext.UserService, new DictionaryCacheProvider(), ContentTypesCache, Factory.GetInstance()); + var publishedMedia = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), ServiceContext.MediaService, ServiceContext.UserService, new DictionaryAppCache(), ContentTypesCache, Factory.GetInstance()); var nav = node.CreateNavigator(); @@ -502,7 +502,7 @@ namespace Umbraco.Tests.PublishedContent var errorXml = new XElement("error", string.Format("No media is maching '{0}'", 1234)); var nav = errorXml.CreateNavigator(); - var publishedMedia = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), ServiceContext.MediaService, ServiceContext.UserService, new DictionaryCacheProvider(), ContentTypesCache, Factory.GetInstance()); + var publishedMedia = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null), ServiceContext.MediaService, ServiceContext.UserService, new DictionaryAppCache(), ContentTypesCache, Factory.GetInstance()); var converted = publishedMedia.ConvertFromXPathNodeIterator(nav.Select("/"), 1234); Assert.IsNull(converted); diff --git a/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs b/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs index c56ec57db0..99d2fbd222 100644 --- a/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs @@ -42,7 +42,7 @@ namespace Umbraco.Tests.Scoping // this is what's created core web runtime return new AppCaches( new DeepCloneAppCache(new ObjectCacheAppCache()), - new DictionaryCacheProvider(), + new DictionaryAppCache(), NoAppCache.Instance, new IsolatedCaches(type => new DeepCloneAppCache(new ObjectCacheAppCache()))); } diff --git a/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs b/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs index bcb1c6ede3..3cca34fe77 100755 --- a/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs @@ -949,14 +949,15 @@ namespace Umbraco.Web.PublishedCache.NuCache // even though the underlying elements may not change (store snapshots) public PublishedSnapshot.PublishedSnapshotElements GetElements(bool previewDefault) { - // note: using ObjectCacheRuntimeCacheProvider for elements and snapshot caches + // note: using ObjectCacheAppCache for elements and snapshot caches // is not recommended because it creates an inner MemoryCache which is a heavy - // thing - better use a StaticCacheProvider which "just" creates a concurrent + // thing - better use a dictionary-based cache which "just" creates a concurrent // dictionary - // for snapshot cache, StaticCacheProvider MAY be OK but it is not thread-safe, + // for snapshot cache, DictionaryAppCache MAY be OK but it is not thread-safe, // nothing like that... - // for elements cache, StaticCacheProvider is a No-No, use something better. + // for elements cache, DictionaryAppCache is a No-No, use something better. + // ie FastDictionaryAppCache (thread safe and all) ContentStore.Snapshot contentSnap, mediaSnap; SnapDictionary.Snapshot domainSnap; @@ -998,11 +999,11 @@ namespace Umbraco.Web.PublishedCache.NuCache _contentGen = contentSnap.Gen; _mediaGen = mediaSnap.Gen; _domainGen = domainSnap.Gen; - elementsCache = _elementsCache = new FastDictionaryCacheProvider(); + elementsCache = _elementsCache = new FastDictionaryAppCache(); } } - var snapshotCache = new DictionaryCacheProvider(); + var snapshotCache = new DictionaryAppCache(); var memberTypeCache = new PublishedContentTypeCache(null, null, _serviceContext.MemberTypeService, _publishedContentTypeFactory, _logger); diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMemberCache.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMemberCache.cs index a622a4934c..816eb3c545 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMemberCache.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMemberCache.cs @@ -17,9 +17,9 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache private readonly XmlStore _xmlStore; private readonly PublishedContentTypeCache _contentTypeCache; - public PublishedMemberCache(XmlStore xmlStore, IAppCache requestCacheProvider, IMemberService memberService, PublishedContentTypeCache contentTypeCache) + public PublishedMemberCache(XmlStore xmlStore, IAppCache requestCache, IMemberService memberService, PublishedContentTypeCache contentTypeCache) { - _requestCache = requestCacheProvider; + _requestCache = requestCache; _memberService = memberService; _xmlStore = xmlStore; _contentTypeCache = contentTypeCache; diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlPublishedContent.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlPublishedContent.cs index eb54c85984..2e19fc423b 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlPublishedContent.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlPublishedContent.cs @@ -421,13 +421,13 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache /// /// The Xml node. /// A value indicating whether we are previewing or not. - /// A cache provider. + /// A cache. /// A content type cache. /// The IPublishedContent corresponding to the Xml cache node. /// Maintains a per-request cache of IPublishedContent items in order to make /// sure that we create only one instance of each for the duration of a request. The /// returned IPublishedContent is a model, if models are enabled. - public static IPublishedContent Get(XmlNode node, bool isPreviewing, IAppCache cacheProvider, PublishedContentTypeCache contentTypeCache) + public static IPublishedContent Get(XmlNode node, bool isPreviewing, IAppCache appCache, PublishedContentTypeCache contentTypeCache) { // only 1 per request @@ -435,7 +435,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache var id = attrs?.GetNamedItem("id").Value; if (id.IsNullOrWhiteSpace()) throw new InvalidOperationException("Node has no ID attribute."); var key = CacheKeyPrefix + id; // dont bother with preview, wont change during request in Xml cache - return (IPublishedContent) cacheProvider.Get(key, () => (new XmlPublishedContent(node, isPreviewing, cacheProvider, contentTypeCache)).CreateModel()); + return (IPublishedContent) appCache.Get(key, () => (new XmlPublishedContent(node, isPreviewing, appCache, contentTypeCache)).CreateModel()); } public static void ClearRequest() diff --git a/src/Umbraco.Web/Runtime/WebRuntime.cs b/src/Umbraco.Web/Runtime/WebRuntime.cs index e9d27a2a1c..90da402849 100644 --- a/src/Umbraco.Web/Runtime/WebRuntime.cs +++ b/src/Umbraco.Web/Runtime/WebRuntime.cs @@ -63,7 +63,7 @@ namespace Umbraco.Web.Runtime // we need to have the dep clone runtime cache provider to ensure // all entities are cached properly (cloned in and cloned out) new DeepCloneAppCache(new WebCachingAppCache(HttpRuntime.Cache)), - new DictionaryCacheProvider(), + new DictionaryAppCache(), // we need request based cache when running in web-based context new HttpRequestAppCache(), new IsolatedCaches(type => From 6dd4d7f475b72ced50578f9a16e2e99d5c4ce7f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 18 Jan 2019 10:12:24 +0100 Subject: [PATCH 450/469] V8 FE Gulp Fastdev script --- .editorconfig | 6 +- .../gulp/tasks/fastdev.js | 13 ++ .../gulp/util/processJs.js | 24 ++- .../gulp/util/processLess.js | 21 ++- src/Umbraco.Web.UI.Client/gulpfile.js | 2 + src/Umbraco.Web.UI.Client/package-lock.json | 154 +++++++++++++++--- src/Umbraco.Web.UI.Client/package.json | 5 +- 7 files changed, 185 insertions(+), 40 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/gulp/tasks/fastdev.js diff --git a/.editorconfig b/.editorconfig index c63ef39430..2305dd4b32 100644 --- a/.editorconfig +++ b/.editorconfig @@ -34,4 +34,8 @@ dotnet_naming_style.prefix_underscore.required_prefix = _ csharp_style_var_for_built_in_types = true:suggestion csharp_style_var_when_type_is_apparent = true:suggestion csharp_style_var_elsewhere = true:suggestion -csharp_prefer_braces = false : none +csharp_prefer_braces = false : none + +[*.{js,less}] +trim_trailing_whitespace = false +insert_final_newline = false diff --git a/src/Umbraco.Web.UI.Client/gulp/tasks/fastdev.js b/src/Umbraco.Web.UI.Client/gulp/tasks/fastdev.js new file mode 100644 index 0000000000..888ed38fec --- /dev/null +++ b/src/Umbraco.Web.UI.Client/gulp/tasks/fastdev.js @@ -0,0 +1,13 @@ +'use strict'; + +var config = require('../config'); +var gulp = require('gulp'); +var runSequence = require('run-sequence'); + +// Dev - build the files ready for development and start watchers +gulp.task('fastdev', function(cb) { + + global.isProd = false; + + runSequence(["dependencies", "js", "less", "views"], "watch", cb); +}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/gulp/util/processJs.js b/src/Umbraco.Web.UI.Client/gulp/util/processJs.js index c110fa9cae..45927dc0e6 100644 --- a/src/Umbraco.Web.UI.Client/gulp/util/processJs.js +++ b/src/Umbraco.Web.UI.Client/gulp/util/processJs.js @@ -9,18 +9,24 @@ var concat = require('gulp-concat'); var wrap = require("gulp-wrap-js"); module.exports = function(files, out) { - - return gulp.src(files) + + var task = gulp.src(files); + + if (global.isProd === true) { // check for js errors - .pipe(eslint()) + task = task.pipe(eslint()); // outputs the lint results to the console - .pipe(eslint.format()) - // sort files in stream by path or any custom sort comparator - .pipe(babel()) + task = task.pipe(eslint.format()); + } + + // sort files in stream by path or any custom sort comparator + task = task.pipe(babel()) .pipe(sort()) .pipe(concat(out)) .pipe(wrap('(function(){\n%= body %\n})();')) .pipe(gulp.dest(config.root + config.targets.js)); - - console.log(out + " compiled"); -}; + + + return task; + +}; \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/gulp/util/processLess.js b/src/Umbraco.Web.UI.Client/gulp/util/processLess.js index e2bb758499..26f69865d9 100644 --- a/src/Umbraco.Web.UI.Client/gulp/util/processLess.js +++ b/src/Umbraco.Web.UI.Client/gulp/util/processLess.js @@ -10,17 +10,24 @@ var cleanCss = require("gulp-clean-css"); var rename = require('gulp-rename'); module.exports = function(files, out) { + var processors = [ autoprefixer, cssnano({zindex: false}) ]; - return gulp.src(files) - .pipe(less()) - .pipe(cleanCss()) - .pipe(postcss(processors)) + var task = gulp.src(files) + .pipe(less()); + + + if (global.isProd === true) { + task = task.pipe(cleanCss()); + } + + task = task.pipe(postcss(processors)) .pipe(rename(out)) .pipe(gulp.dest(config.root + config.targets.css)); - - console.log(out + " compiled"); -} + + return task; + +}; \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/gulpfile.js b/src/Umbraco.Web.UI.Client/gulpfile.js index f01d992013..79a9d04156 100755 --- a/src/Umbraco.Web.UI.Client/gulpfile.js +++ b/src/Umbraco.Web.UI.Client/gulpfile.js @@ -11,4 +11,6 @@ * To add a new task, simply add a new task file to gulp/tasks. */ +global.isProd = true; + require('./gulp'); diff --git a/src/Umbraco.Web.UI.Client/package-lock.json b/src/Umbraco.Web.UI.Client/package-lock.json index 02ad091f75..fe657ae470 100644 --- a/src/Umbraco.Web.UI.Client/package-lock.json +++ b/src/Umbraco.Web.UI.Client/package-lock.json @@ -5115,6 +5115,12 @@ "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", "dev": true }, + "fs": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.2.tgz", + "integrity": "sha1-4fJE7zkzwbKmS9R5kTYGDQ9ZFPg=", + "dev": true + }, "fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", @@ -5204,14 +5210,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -5226,20 +5230,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -5356,8 +5357,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -5369,7 +5369,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -5384,7 +5383,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -5392,14 +5390,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.2.4", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.1", "yallist": "^3.0.0" @@ -5418,7 +5414,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -5499,8 +5494,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -5512,7 +5506,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -5634,7 +5627,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -6133,6 +6125,12 @@ "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", "dev": true }, + "growly": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", + "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=", + "dev": true + }, "gulp": { "version": "3.9.1", "resolved": "http://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", @@ -6930,6 +6928,102 @@ } } }, + "gulp-notify": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/gulp-notify/-/gulp-notify-3.2.0.tgz", + "integrity": "sha512-qEocs1UVoDKKUjfsxJNMNwkRla0PbsyJwsqNNXpzYWsLQ29LhxRMY3wnTGZcc4hMHtalnvah/Dwlwb4NijH/0A==", + "dev": true, + "requires": { + "ansi-colors": "^1.0.1", + "fancy-log": "^1.3.2", + "lodash.template": "^4.4.0", + "node-notifier": "^5.2.1", + "node.extend": "^2.0.0", + "plugin-error": "^0.1.2", + "through2": "^2.0.3" + }, + "dependencies": { + "arr-diff": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz", + "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1", + "array-slice": "^0.2.3" + } + }, + "arr-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz", + "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=", + "dev": true + }, + "array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", + "dev": true + }, + "extend-shallow": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz", + "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", + "dev": true, + "requires": { + "kind-of": "^1.1.0" + } + }, + "kind-of": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", + "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=", + "dev": true + }, + "lodash.template": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz", + "integrity": "sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A=", + "dev": true, + "requires": { + "lodash._reinterpolate": "~3.0.0", + "lodash.templatesettings": "^4.0.0" + } + }, + "lodash.templatesettings": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz", + "integrity": "sha1-K01OlbpEDZFf8IvImeRVNmZxMxY=", + "dev": true, + "requires": { + "lodash._reinterpolate": "~3.0.0" + } + }, + "node.extend": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node.extend/-/node.extend-2.0.2.tgz", + "integrity": "sha512-pDT4Dchl94/+kkgdwyS2PauDFjZG0Hk0IcHIB+LkW27HLDtdoeMxHTxZh39DYbPP8UflWXWj9JcdDozF+YDOpQ==", + "dev": true, + "requires": { + "has": "^1.0.3", + "is": "^3.2.1" + } + }, + "plugin-error": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", + "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", + "dev": true, + "requires": { + "ansi-cyan": "^0.1.1", + "ansi-red": "^0.1.1", + "arr-diff": "^1.0.1", + "arr-union": "^2.0.1", + "extend-shallow": "^1.1.2" + } + } + } + }, "gulp-open": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/gulp-open/-/gulp-open-3.0.1.tgz", @@ -9382,6 +9476,18 @@ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, + "node-notifier": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.3.0.tgz", + "integrity": "sha512-AhENzCSGZnZJgBARsUjnQ7DnZbzyP+HxlVXuD0xqAnvL8q+OqtSX7lGg9e8nHzwXkMMXNdVeqq4E2M3EUAqX6Q==", + "dev": true, + "requires": { + "growly": "^1.3.0", + "semver": "^5.5.0", + "shellwords": "^0.1.1", + "which": "^1.3.0" + } + }, "node-releases": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.0.5.tgz", @@ -14138,6 +14244,12 @@ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, + "shellwords": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", + "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", + "dev": true + }, "sigmund": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index 6e8159a940..61bdb88f17 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -3,8 +3,9 @@ "scripts": { "test": "karma start test/config/karma.conf.js --singlerun", "build": "gulp build", - "dev": "gulp dev", - "docs": "gulp docs" + "dev": "gulp dev", + "fastdev": "gulp fastdev", + "docs": "gulp docs" }, "dependencies": { "ace-builds": "1.4.2", From cee1171d39a93de59f862a2a7107edae3a93602f Mon Sep 17 00:00:00 2001 From: Callum Whyte Date: Fri, 18 Jan 2019 20:53:38 +1100 Subject: [PATCH 451/469] Removing masterpages support from V8 (#3971) --- .../Composers/ConfigurationComposer.cs | 1 - .../UmbracoSettings/ITemplatesSection.cs | 9 - .../IUmbracoSettingsSection.cs | 4 - .../UmbracoSettings/TemplatesElement.cs | 20 - .../UmbracoSettings/UmbracoSettingsSection.cs | 18 +- src/Umbraco.Core/IO/FileSystems.cs | 14 - src/Umbraco.Core/IO/IFileSystems.cs | 5 - src/Umbraco.Core/IO/MasterPageHelper.cs | 445 ------------------ src/Umbraco.Core/IO/SystemDirectories.cs | 4 - src/Umbraco.Core/Models/ITemplate.cs | 6 +- .../Packaging/PackageDataInstallation.cs | 17 +- .../Repositories/ITemplateRepository.cs | 19 +- .../Implement/TemplateRepository.cs | 136 +----- src/Umbraco.Core/Services/IFileService.cs | 15 - .../Services/Implement/FileService.cs | 24 +- src/Umbraco.Core/Umbraco.Core.csproj | 3 - .../TemplateElementDefaultTests.cs | 13 - .../UmbracoSettings/TemplateElementTests.cs | 16 - .../UmbracoSettings/umbracoSettings.config | 4 - .../umbracoSettings.minimal.config | 5 - src/Umbraco.Tests/IO/IoHelperTests.cs | 1 - .../Repositories/ContentTypeRepositoryTest.cs | 9 +- .../Repositories/DocumentRepositoryTest.cs | 2 +- .../Repositories/DomainRepositoryTest.cs | 4 +- .../PublicAccessRepositoryTest.cs | 4 +- .../Repositories/TagRepositoryTest.cs | 2 +- .../Repositories/TemplateRepositoryTest.cs | 135 +----- .../Repositories/UserRepositoryTest.cs | 2 +- .../Services/ContentServicePerformanceTest.cs | 8 +- .../Services/ContentServiceTests.cs | 2 +- .../Templates/MasterPageHelperTests.cs | 21 - .../Templates/TemplateRepositoryTests.cs | 121 ----- .../TestHelpers/SettingsForTests.cs | 3 - src/Umbraco.Tests/TestHelpers/TestHelper.cs | 5 +- .../TestHelpers/TestObjects-Mocks.cs | 3 +- src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 1 - src/Umbraco.Tests/Umbraco.Tests.csproj | 4 - .../config/umbracoSettings.Release.config | 5 - .../config/umbracoSettings.config | 5 - .../FolderAndFilePermissionsCheck.cs | 1 - .../Install/FilePermissionHelper.cs | 3 +- src/Umbraco.Web/Routing/PublishedRouter.cs | 4 - .../Trees/TemplatesTreeController.cs | 13 +- .../umbraco.presentation/default.aspx.cs | 16 - 44 files changed, 38 insertions(+), 1114 deletions(-) delete mode 100644 src/Umbraco.Core/Configuration/UmbracoSettings/ITemplatesSection.cs delete mode 100644 src/Umbraco.Core/Configuration/UmbracoSettings/TemplatesElement.cs delete mode 100644 src/Umbraco.Core/IO/MasterPageHelper.cs delete mode 100644 src/Umbraco.Tests/Configurations/UmbracoSettings/TemplateElementDefaultTests.cs delete mode 100644 src/Umbraco.Tests/Configurations/UmbracoSettings/TemplateElementTests.cs delete mode 100644 src/Umbraco.Tests/Templates/MasterPageHelperTests.cs delete mode 100644 src/Umbraco.Tests/Templates/TemplateRepositoryTests.cs diff --git a/src/Umbraco.Core/Composing/Composers/ConfigurationComposer.cs b/src/Umbraco.Core/Composing/Composers/ConfigurationComposer.cs index ca86f623cc..7fba47a2cd 100644 --- a/src/Umbraco.Core/Composing/Composers/ConfigurationComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/ConfigurationComposer.cs @@ -15,7 +15,6 @@ namespace Umbraco.Core.Composing.Composers // register others composition.RegisterUnique(factory => factory.GetInstance().Content); - composition.RegisterUnique(factory => factory.GetInstance().Templates); composition.RegisterUnique(factory => factory.GetInstance().RequestHandler); composition.RegisterUnique(factory => factory.GetInstance().Security); diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/ITemplatesSection.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/ITemplatesSection.cs deleted file mode 100644 index 67fd58030b..0000000000 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/ITemplatesSection.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System; - -namespace Umbraco.Core.Configuration.UmbracoSettings -{ - public interface ITemplatesSection : IUmbracoConfigurationSection - { - RenderingEngine DefaultRenderingEngine { get; } - } -} diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/IUmbracoSettingsSection.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/IUmbracoSettingsSection.cs index 28da03ff2d..33416d38cc 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/IUmbracoSettingsSection.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/IUmbracoSettingsSection.cs @@ -1,5 +1,4 @@ using System; -using System.ComponentModel; namespace Umbraco.Core.Configuration.UmbracoSettings { @@ -12,8 +11,6 @@ namespace Umbraco.Core.Configuration.UmbracoSettings ISecuritySection Security { get; } IRequestHandlerSection RequestHandler { get; } - - ITemplatesSection Templates { get; } ILoggingSection Logging { get; } @@ -22,6 +19,5 @@ namespace Umbraco.Core.Configuration.UmbracoSettings IProvidersSection Providers { get; } IWebRoutingSection WebRouting { get; } - } } diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/TemplatesElement.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/TemplatesElement.cs deleted file mode 100644 index 8c929b02d8..0000000000 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/TemplatesElement.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Configuration; - -namespace Umbraco.Core.Configuration.UmbracoSettings -{ - internal class TemplatesElement : UmbracoConfigurationElement, ITemplatesSection - { - [ConfigurationProperty("defaultRenderingEngine", IsRequired = true)] - internal InnerTextConfigurationElement DefaultRenderingEngine - { - get { return GetOptionalTextElement("defaultRenderingEngine", RenderingEngine.Mvc); } - } - - RenderingEngine ITemplatesSection.DefaultRenderingEngine - { - get { return DefaultRenderingEngine; } - } - - } -} diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/UmbracoSettingsSection.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/UmbracoSettingsSection.cs index d36410f317..9ed635f6a9 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/UmbracoSettingsSection.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/UmbracoSettingsSection.cs @@ -1,11 +1,7 @@ -using System; -using System.ComponentModel; -using System.Configuration; -using System.Linq; +using System.Configuration; namespace Umbraco.Core.Configuration.UmbracoSettings { - public class UmbracoSettingsSection : ConfigurationSection, IUmbracoSettingsSection { [ConfigurationProperty("backOffice")] @@ -32,12 +28,6 @@ namespace Umbraco.Core.Configuration.UmbracoSettings get { return (RequestHandlerElement)this["requestHandler"]; } } - [ConfigurationProperty("templates")] - internal TemplatesElement Templates - { - get { return (TemplatesElement)this["templates"]; } - } - [ConfigurationProperty("logging")] internal LoggingElement Logging { @@ -77,11 +67,6 @@ namespace Umbraco.Core.Configuration.UmbracoSettings get { return RequestHandler; } } - ITemplatesSection IUmbracoSettingsSection.Templates - { - get { return Templates; } - } - IBackOfficeSection IUmbracoSettingsSection.BackOffice { get { return BackOffice; } @@ -106,6 +91,5 @@ namespace Umbraco.Core.Configuration.UmbracoSettings { get { return WebRouting; } } - } } diff --git a/src/Umbraco.Core/IO/FileSystems.cs b/src/Umbraco.Core/IO/FileSystems.cs index 7fc846319b..63a1259acb 100644 --- a/src/Umbraco.Core/IO/FileSystems.cs +++ b/src/Umbraco.Core/IO/FileSystems.cs @@ -19,7 +19,6 @@ namespace Umbraco.Core.IO private ShadowWrapper _partialViewsFileSystem; private ShadowWrapper _stylesheetsFileSystem; private ShadowWrapper _scriptsFileSystem; - private ShadowWrapper _masterPagesFileSystem; private ShadowWrapper _mvcViewsFileSystem; // well-known file systems lazy initialization @@ -102,16 +101,6 @@ namespace Umbraco.Core.IO } } - /// - public IFileSystem MasterPagesFileSystem - { - get - { - if (Volatile.Read(ref _wkfsInitialized) == false) EnsureWellKnownFileSystems(); - return _masterPagesFileSystem; - } - } - /// public IFileSystem MvcViewsFileSystem { @@ -135,14 +124,12 @@ namespace Umbraco.Core.IO var partialViewsFileSystem = new PhysicalFileSystem(SystemDirectories.PartialViews); var stylesheetsFileSystem = new PhysicalFileSystem(SystemDirectories.Css); var scriptsFileSystem = new PhysicalFileSystem(SystemDirectories.Scripts); - var masterPagesFileSystem = new PhysicalFileSystem(SystemDirectories.Masterpages); var mvcViewsFileSystem = new PhysicalFileSystem(SystemDirectories.MvcViews); _macroPartialFileSystem = new ShadowWrapper(macroPartialFileSystem, "Views/MacroPartials", IsScoped); _partialViewsFileSystem = new ShadowWrapper(partialViewsFileSystem, "Views/Partials", IsScoped); _stylesheetsFileSystem = new ShadowWrapper(stylesheetsFileSystem, "css", IsScoped); _scriptsFileSystem = new ShadowWrapper(scriptsFileSystem, "scripts", IsScoped); - _masterPagesFileSystem = new ShadowWrapper(masterPagesFileSystem, "masterpages", IsScoped); _mvcViewsFileSystem = new ShadowWrapper(mvcViewsFileSystem, "Views", IsScoped); // fixme locking? @@ -150,7 +137,6 @@ namespace Umbraco.Core.IO _shadowWrappers.Add(_partialViewsFileSystem); _shadowWrappers.Add(_stylesheetsFileSystem); _shadowWrappers.Add(_scriptsFileSystem); - _shadowWrappers.Add(_masterPagesFileSystem); _shadowWrappers.Add(_mvcViewsFileSystem); return null; diff --git a/src/Umbraco.Core/IO/IFileSystems.cs b/src/Umbraco.Core/IO/IFileSystems.cs index d74ad48145..f7d35058e3 100644 --- a/src/Umbraco.Core/IO/IFileSystems.cs +++ b/src/Umbraco.Core/IO/IFileSystems.cs @@ -25,11 +25,6 @@ /// IFileSystem ScriptsFileSystem { get; } - /// - /// Gets the masterpages filesystem. - /// - IFileSystem MasterPagesFileSystem { get; } - /// /// Gets the MVC views filesystem. /// diff --git a/src/Umbraco.Core/IO/MasterPageHelper.cs b/src/Umbraco.Core/IO/MasterPageHelper.cs deleted file mode 100644 index 049db04b9a..0000000000 --- a/src/Umbraco.Core/IO/MasterPageHelper.cs +++ /dev/null @@ -1,445 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using Umbraco.Core.Models; -using Umbraco.Core.Persistence.Repositories; -using Umbraco.Core.Services; -using Umbraco.Core.Xml; - -namespace Umbraco.Core.IO -{ - internal class MasterPageHelper - { - private readonly IFileSystem _masterPageFileSystem; - internal static readonly string DefaultMasterTemplate = SystemDirectories.Umbraco + "/masterpages/default.master"; - //private static readonly char[] NewLineChars = Environment.NewLine.ToCharArray(); - - public MasterPageHelper(IFileSystem masterPageFileSystem) - { - if (masterPageFileSystem == null) throw new ArgumentNullException("masterPageFileSystem"); - _masterPageFileSystem = masterPageFileSystem; - } - - public bool MasterPageExists(ITemplate t) - { - return _masterPageFileSystem.FileExists(GetFilePath(t)); - } - - private string GetFilePath(ITemplate t) - { - return GetFilePath(t.Alias); - } - - private string GetFilePath(string alias) - { - return alias + ".master"; - } - - public string CreateMasterPage(ITemplate t, ITemplateRepository templateRepo, bool overWrite = false) - { - string masterpageContent = ""; - - var filePath = GetFilePath(t); - if (_masterPageFileSystem.FileExists(filePath) == false || overWrite) - { - masterpageContent = t.Content.IsNullOrWhiteSpace() ? CreateDefaultMasterPageContent(t, templateRepo) : t.Content; - - var data = Encoding.UTF8.GetBytes(masterpageContent); - var withBom = Encoding.UTF8.GetPreamble().Concat(data).ToArray(); - - using (var ms = new MemoryStream(withBom)) - { - _masterPageFileSystem.AddFile(filePath, ms, true); - } - } - else - { - using (var s = _masterPageFileSystem.OpenFile(filePath)) - using (var tr = new StreamReader(s, Encoding.UTF8)) - { - masterpageContent = tr.ReadToEnd(); - tr.Close(); - } - } - - return masterpageContent; - } - - //internal string GetFileContents(ITemplate t) - //{ - // var masterpageContent = ""; - // if (_masterPageFileSystem.FileExists(GetFilePath(t))) - // { - // using (var s = _masterPageFileSystem.OpenFile(GetFilePath(t))) - // using (var tr = new StreamReader(s)) - // { - // masterpageContent = tr.ReadToEnd(); - // tr.Close(); - // } - // } - - // return masterpageContent; - //} - - public string UpdateMasterPageFile(ITemplate t, string currentAlias, ITemplateRepository templateRepo) - { - var template = UpdateMasterPageContent(t, currentAlias); - UpdateChildTemplates(t, currentAlias, templateRepo); - var filePath = GetFilePath(t); - - var data = Encoding.UTF8.GetBytes(template); - var withBom = Encoding.UTF8.GetPreamble().Concat(data).ToArray(); - - using (var ms = new MemoryStream(withBom)) - { - _masterPageFileSystem.AddFile(filePath, ms, true); - } - return template; - } - - private string CreateDefaultMasterPageContent(ITemplate template, ITemplateRepository templateRepo) - { - var design = new StringBuilder(); - design.Append(GetMasterPageHeader(template) + Environment.NewLine); - - if (template.MasterTemplateAlias.IsNullOrWhiteSpace() == false) - { - var master = templateRepo.Get(template.MasterTemplateAlias); - if (master != null) - { - foreach (var cpId in GetContentPlaceholderIds(master)) - { - design.Append("" + - Environment.NewLine + - Environment.NewLine + - "" + - Environment.NewLine + - Environment.NewLine); - } - - return design.ToString(); - } - } - - design.Append(GetMasterContentElement(template) + Environment.NewLine); - design.Append(template.Content + Environment.NewLine); - design.Append("" + Environment.NewLine); - - return design.ToString(); - } - - public static IEnumerable GetContentPlaceholderIds(ITemplate template) - { - var retVal = new List(); - - var mp = template.Content; - var path = ""; - var r = new Regex(path, RegexOptions.IgnoreCase); - var m = r.Match(mp); - - while (m.Success) - { - var cc = m.Groups[3].Captures; - retVal.AddRange(cc.Cast().Where(c => c.Value != "server").Select(c => c.Value)); - - m = m.NextMatch(); - } - - return retVal; - } - - private static string UpdateMasterPageContent(ITemplate template, string currentAlias) - { - var masterPageContent = template.Content; - - if (string.IsNullOrEmpty(currentAlias) == false && currentAlias != template.Alias) - { - var masterHeader = - masterPageContent.Substring(0, masterPageContent.IndexOf("%>", StringComparison.Ordinal) + 2).Trim( - Environment.NewLine.ToCharArray()); - - // find the masterpagefile attribute - var m = Regex.Matches(masterHeader, "(?\\S*)=\"(?[^\"]*)\"", - RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); - - foreach (Match attributeSet in m) - { - if (attributeSet.Groups["attributeName"].Value.ToLower() == "masterpagefile") - { - // validate the masterpagefile - var currentMasterPageFile = attributeSet.Groups["attributeValue"].Value; - var currentMasterTemplateFile = ParentTemplatePath(template); - - if (currentMasterPageFile != currentMasterTemplateFile) - { - masterPageContent = - masterPageContent.Replace( - attributeSet.Groups["attributeName"].Value + "=\"" + currentMasterPageFile + "\"", - attributeSet.Groups["attributeName"].Value + "=\"" + currentMasterTemplateFile + - "\""); - } - } - } - } - - return masterPageContent; - } - - private void UpdateChildTemplates(ITemplate template, string currentAlias, ITemplateRepository templateRepo) - { - //if we have a Old Alias if the alias and therefor the masterpage file name has changed... - //so before we save the new masterfile, we'll clear the old one, so we don't up with - //Unused masterpage files - if (string.IsNullOrEmpty(currentAlias) == false && currentAlias != template.Alias) - { - //Ensure that child templates have the right master masterpage file name - if (template.IsMasterTemplate) - { - var children = templateRepo.GetChildren(template.Id); - foreach (var t in children) - UpdateMasterPageFile(t, null, templateRepo); - } - } - } - - - //private void SaveDesignToFile(ITemplate t, string currentAlias, string design) - //{ - // //kill the old file.. - // if (string.IsNullOrEmpty(currentAlias) == false && currentAlias != t.Alias) - // { - // var oldFile = - // IOHelper.MapPath(SystemDirectories.Masterpages + "/" + currentAlias.Replace(" ", "") + ".master"); - // if (System.IO.File.Exists(oldFile)) - // System.IO.File.Delete(oldFile); - // } - - // // save the file in UTF-8 - // System.IO.File.WriteAllText(GetFilePath(t), design, Encoding.UTF8); - //} - - //internal static void RemoveMasterPageFile(string alias) - //{ - // if (string.IsNullOrWhiteSpace(alias) == false) - // { - // string file = IOHelper.MapPath(SystemDirectories.Masterpages + "/" + alias.Replace(" ", "") + ".master"); - // if (System.IO.File.Exists(file)) - // System.IO.File.Delete(file); - // } - //} - - //internal string SaveTemplateToFile(ITemplate template, string currentAlias, ITemplateRepository templateRepo) - //{ - // var masterPageContent = template.Content; - // if (IsMasterPageSyntax(masterPageContent) == false) - // masterPageContent = ConvertToMasterPageSyntax(template); - - // // Add header to master page if it doesn't exist - // if (masterPageContent.TrimStart().StartsWith("<%@") == false) - // { - // masterPageContent = GetMasterPageHeader(template) + Environment.NewLine + masterPageContent; - // } - // else - // { - // // verify that the masterpage attribute is the same as the masterpage - // var masterHeader = - // masterPageContent.Substring(0, masterPageContent.IndexOf("%>", StringComparison.Ordinal) + 2).Trim(NewLineChars); - - // // find the masterpagefile attribute - // var m = Regex.Matches(masterHeader, "(?\\S*)=\"(?[^\"]*)\"", - // RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); - - // foreach (Match attributeSet in m) - // { - // if (attributeSet.Groups["attributeName"].Value.ToLower() == "masterpagefile") - // { - // // validate the masterpagefile - // var currentMasterPageFile = attributeSet.Groups["attributeValue"].Value; - // var currentMasterTemplateFile = ParentTemplatePath(template); - - // if (currentMasterPageFile != currentMasterTemplateFile) - // { - // masterPageContent = - // masterPageContent.Replace( - // attributeSet.Groups["attributeName"].Value + "=\"" + currentMasterPageFile + "\"", - // attributeSet.Groups["attributeName"].Value + "=\"" + currentMasterTemplateFile + - // "\""); - - // } - // } - // } - - // } - - // //we have a Old Alias if the alias and therefor the masterpage file name has changed... - // //so before we save the new masterfile, we'll clear the old one, so we don't up with - // //Unused masterpage files - // if (string.IsNullOrEmpty(currentAlias) == false && currentAlias != template.Alias) - // { - - // //Ensure that child templates have the right master masterpage file name - // if (template.IsMasterTemplate) - // { - // var children = templateRepo.GetChildren(template.Id); - - // foreach (var t in children) - // UpdateMasterPageFile(t, null, templateRepo); - // } - - // //then kill the old file.. - // var oldFile = GetFilePath(currentAlias); - // if (_masterPageFileSystem.FileExists(oldFile)) - // _masterPageFileSystem.DeleteFile(oldFile); - // } - - // // save the file in UTF-8 - // System.IO.File.WriteAllText(GetFilePath(template), masterPageContent, Encoding.UTF8); - - // return masterPageContent; - //} - - //internal static string ConvertToMasterPageSyntax(ITemplate template) - //{ - // string masterPageContent = GetMasterContentElement(template) + Environment.NewLine; - - // masterPageContent += template.Content; - - // // Parse the design for getitems - // masterPageContent = EnsureMasterPageSyntax(template.Alias, masterPageContent); - - // // append ending asp:content element - // masterPageContent += Environment.NewLine + "" + Environment.NewLine; - - // return masterPageContent; - //} - - public static bool IsMasterPageSyntax(string code) - { - return Regex.IsMatch(code, @"<%@\s*Master", RegexOptions.IgnoreCase) || - code.InvariantContains("", ParentTemplatePath(template)) + Environment.NewLine; - } - - private static string ParentTemplatePath(ITemplate template) - { - var masterTemplate = DefaultMasterTemplate; - if (template.MasterTemplateAlias.IsNullOrWhiteSpace() == false) - masterTemplate = SystemDirectories.Masterpages + "/" + template.MasterTemplateAlias + ".master"; - - return masterTemplate; - } - - internal static string GetMasterContentElement(ITemplate template) - { - if (template.MasterTemplateAlias.IsNullOrWhiteSpace() == false) - { - string masterAlias = template.MasterTemplateAlias; - return - String.Format("", masterAlias); - } - else - return - String.Format(""); - - } - - internal static string EnsureMasterPageSyntax(string templateAlias, string masterPageContent) - { - ReplaceElement(ref masterPageContent, "?UMBRACO_GETITEM", "umbraco:Item", true); - ReplaceElement(ref masterPageContent, "?UMBRACO_GETITEM", "umbraco:Item", false); - - // Parse the design for macros - ReplaceElement(ref masterPageContent, "?UMBRACO_MACRO", "umbraco:Macro", true); - ReplaceElement(ref masterPageContent, "?UMBRACO_MACRO", "umbraco:Macro", false); - - // Parse the design for load childs - masterPageContent = masterPageContent.Replace("", CreateDefaultPlaceHolder(templateAlias)) - .Replace("", CreateDefaultPlaceHolder(templateAlias)); - // Parse the design for aspnet forms - GetAspNetMasterPageForm(ref masterPageContent, templateAlias); - masterPageContent = masterPageContent.Replace("", ""); - // Parse the design for aspnet heads - masterPageContent = masterPageContent.Replace("", String.Format("", templateAlias.Replace(" ", ""))); - masterPageContent = masterPageContent.Replace("", ""); - return masterPageContent; - } - - - private static void GetAspNetMasterPageForm(ref string design, string templateAlias) - { - var formElement = Regex.Match(design, GetElementRegExp("?ASPNET_FORM", false), RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); - - if (string.IsNullOrEmpty(formElement.Value) == false) - { - string formReplace = String.Format("
    ", templateAlias.Replace(" ", "")); - if (formElement.Groups.Count == 0) - { - formReplace += ""; - } - design = design.Replace(formElement.Value, formReplace); - } - } - - private static string CreateDefaultPlaceHolder(string templateAlias) - { - return String.Format("", templateAlias.Replace(" ", "")); - } - - private static void ReplaceElement(ref string design, string elementName, string newElementName, bool checkForQuotes) - { - var m = - Regex.Matches(design, GetElementRegExp(elementName, checkForQuotes), - RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); - - foreach (Match match in m) - { - GroupCollection groups = match.Groups; - - // generate new element (compensate for a closing trail on single elements ("/")) - string elementAttributes = groups[1].Value; - // test for macro alias - if (elementName == "?UMBRACO_MACRO") - { - var tags = XmlHelper.GetAttributesFromElement(match.Value); - if (tags["macroAlias"] != null) - elementAttributes = String.Format(" Alias=\"{0}\"", tags["macroAlias"]) + elementAttributes; - else if (tags["macroalias"] != null) - elementAttributes = String.Format(" Alias=\"{0}\"", tags["macroalias"]) + elementAttributes; - } - string newElement = "<" + newElementName + " runat=\"server\" " + elementAttributes.Trim() + ">"; - if (elementAttributes.EndsWith("/")) - { - elementAttributes = elementAttributes.Substring(0, elementAttributes.Length - 1); - } - else if (groups[0].Value.StartsWith(""; - - if (checkForQuotes) - { - // if it's inside quotes, we'll change element attribute quotes to single quotes - newElement = newElement.Replace("\"", "'"); - newElement = String.Format("\"{0}\"", newElement); - } - design = design.Replace(match.Value, newElement); - } - } - - private static string GetElementRegExp(string elementName, bool checkForQuotes) - { - if (checkForQuotes) - return String.Format("\"<[^>\\s]*\\b{0}(\\b[^>]*)>\"", elementName); - else - return String.Format("<[^>\\s]*\\b{0}(\\b[^>]*)>", elementName); - - } - - } -} diff --git a/src/Umbraco.Core/IO/SystemDirectories.cs b/src/Umbraco.Core/IO/SystemDirectories.cs index 4ea3ed64d5..8bea82ea4a 100644 --- a/src/Umbraco.Core/IO/SystemDirectories.cs +++ b/src/Umbraco.Core/IO/SystemDirectories.cs @@ -18,10 +18,6 @@ namespace Umbraco.Core.IO public static string Install => "~/install"; - //fixme: remove this - [Obsolete("Master pages are obsolete and code should be removed")] - public static string Masterpages => "~/masterpages"; - public static string AppCode => "~/App_Code"; public static string AppPlugins => "~/App_Plugins"; diff --git a/src/Umbraco.Core/Models/ITemplate.cs b/src/Umbraco.Core/Models/ITemplate.cs index 97b9324415..6548a49626 100644 --- a/src/Umbraco.Core/Models/ITemplate.cs +++ b/src/Umbraco.Core/Models/ITemplate.cs @@ -1,11 +1,9 @@ -using System; -using System.Runtime.Serialization; -using Umbraco.Core.Models.Entities; +using Umbraco.Core.Models.Entities; namespace Umbraco.Core.Models { /// - /// Defines a Template File (Masterpage or Mvc View) + /// Defines a Template File (Mvc View) /// public interface ITemplate : IFile, IRememberBeingDirty, ICanBeDirty { diff --git a/src/Umbraco.Core/Packaging/PackageDataInstallation.cs b/src/Umbraco.Core/Packaging/PackageDataInstallation.cs index 2e9fee9595..9bea527b91 100644 --- a/src/Umbraco.Core/Packaging/PackageDataInstallation.cs +++ b/src/Umbraco.Core/Packaging/PackageDataInstallation.cs @@ -1234,10 +1234,7 @@ namespace Umbraco.Core.Packaging var alias = templateElement.Element("Alias").Value; var design = templateElement.Element("Design").Value; var masterElement = templateElement.Element("Master"); - - var isMasterPage = IsMasterPageSyntax(design); - var path = isMasterPage ? MasterpagePath(alias) : ViewPath(alias); - + var existingTemplate = _fileService.GetTemplate(alias) as Template; var template = existingTemplate ?? new Template(templateName, alias); template.Content = design; @@ -1257,23 +1254,11 @@ namespace Umbraco.Core.Packaging return templates; } - - private bool IsMasterPageSyntax(string code) - { - return Regex.IsMatch(code, @"<%@\s*Master", RegexOptions.IgnoreCase) || - code.InvariantContains(" GetDescendants(int masterTemplateId); IEnumerable GetDescendants(string alias); - /// - /// This checks what the default rendering engine is set in config but then also ensures that there isn't already - /// a template that exists in the opposite rendering engine's template folder, then returns the appropriate - /// rendering engine to use. - /// - /// - /// - /// The reason this is required is because for example, if you have a master page file already existing under ~/masterpages/Blah.aspx - /// and then you go to create a template in the tree called Blah and the default rendering engine is MVC, it will create a Blah.cshtml - /// empty template in ~/Views. This means every page that is using Blah will go to MVC and render an empty page. - /// This is mostly related to installing packages since packages install file templates to the file system and then create the - /// templates in business logic. Without this, it could cause the wrong rendering engine to be used for a package. - /// - RenderingEngine DetermineTemplateRenderingEngine(ITemplate template); - /// /// Validates a /// diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/TemplateRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/TemplateRepository.cs index 19ef303ebe..ac0f4f0bed 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/TemplateRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/TemplateRepository.cs @@ -5,7 +5,6 @@ using System.Linq; using System.Text; using NPoco; using Umbraco.Core.Cache; -using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models; @@ -23,20 +22,14 @@ namespace Umbraco.Core.Persistence.Repositories.Implement ///
    internal class TemplateRepository : NPocoRepositoryBase, ITemplateRepository { - private readonly IFileSystem _masterpagesFileSystem; private readonly IFileSystem _viewsFileSystem; - private readonly ITemplatesSection _templateConfig; private readonly ViewHelper _viewHelper; - private readonly MasterPageHelper _masterPageHelper; - public TemplateRepository(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger, ITemplatesSection templateConfig, IFileSystems fileSystems) + public TemplateRepository(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger, IFileSystems fileSystems) : base(scopeAccessor, cache, logger) { - _masterpagesFileSystem = fileSystems.MasterPagesFileSystem; _viewsFileSystem = fileSystems.MvcViewsFileSystem; - _templateConfig = templateConfig; _viewHelper = new ViewHelper(_viewsFileSystem); - _masterPageHelper = new MasterPageHelper(_masterpagesFileSystem); } protected override IRepositoryCachePolicy CreateCachePolicy() @@ -255,18 +248,9 @@ namespace Umbraco.Core.Persistence.Repositories.Implement else { // else, create or write template.Content to disk - if (DetermineTemplateRenderingEngine(template) == RenderingEngine.Mvc) - { - content = originalAlias == null - ? _viewHelper.CreateView(template, true) - : _viewHelper.UpdateViewFile(template, originalAlias); - } - else - { - content = originalAlias == null - ? _masterPageHelper.CreateMasterPage(template, this, true) - : _masterPageHelper.UpdateMasterPageFile(template, originalAlias, this); - } + content = originalAlias == null + ? _viewHelper.CreateView(template, true) + : _viewHelper.UpdateViewFile(template, originalAlias); } // once content has been set, "template on disk" are not "on disk" anymore @@ -298,16 +282,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement Database.Execute(delete, new { id = GetEntityId(entity) }); } - if (DetermineTemplateRenderingEngine(entity) == RenderingEngine.Mvc) - { - var viewName = string.Concat(entity.Alias, ".cshtml"); - _viewsFileSystem.DeleteFile(viewName); - } - else - { - var masterpageName = string.Concat(entity.Alias, ".master"); - _masterpagesFileSystem.DeleteFile(masterpageName); - } + var viewName = string.Concat(entity.Alias, ".cshtml"); + _viewsFileSystem.DeleteFile(viewName); entity.DeleteDate = DateTime.Now; } @@ -388,27 +364,11 @@ namespace Umbraco.Core.Persistence.Repositories.Implement template.VirtualPath = _viewsFileSystem.GetUrl(path); return; } - path = string.Concat(template.Alias, ".master"); - if (_masterpagesFileSystem.FileExists(path)) - { - template.VirtualPath = _masterpagesFileSystem.GetUrl(path); - return; - } } else { // we know the path already - var ext = Path.GetExtension(path); - switch (ext) - { - case ".cshtml": - case ".vbhtml": - template.VirtualPath = _viewsFileSystem.GetUrl(path); - return; - case ".master": - template.VirtualPath = _masterpagesFileSystem.GetUrl(path); - return; - } + template.VirtualPath = _viewsFileSystem.GetUrl(path); } template.VirtualPath = string.Empty; // file not found... @@ -426,25 +386,15 @@ namespace Umbraco.Core.Persistence.Repositories.Implement path = string.Concat(template.Alias, ".vbhtml"); if (_viewsFileSystem.FileExists(path)) return GetFileContent(template, _viewsFileSystem, path, init); - path = string.Concat(template.Alias, ".master"); - if (_masterpagesFileSystem.FileExists(path)) - return GetFileContent(template, _masterpagesFileSystem, path, init); } else { // we know the path already - var ext = Path.GetExtension(path); - switch (ext) - { - case ".cshtml": - case ".vbhtml": - return GetFileContent(template, _viewsFileSystem, path, init); - case ".master": - return GetFileContent(template, _masterpagesFileSystem, path, init); - } + return GetFileContent(template, _viewsFileSystem, path, init); } template.VirtualPath = string.Empty; // file not found... + return string.Empty; } @@ -514,9 +464,6 @@ namespace Umbraco.Core.Persistence.Repositories.Implement case ".vbhtml": fs = _viewsFileSystem; break; - case ".master": - fs = _masterpagesFileSystem; - break; default: throw new Exception("Unsupported extension " + ext + "."); } @@ -625,56 +572,6 @@ namespace Umbraco.Core.Persistence.Repositories.Implement } } - /// - /// This checks what the default rendering engine is set in config but then also ensures that there isn't already - /// a template that exists in the opposite rendering engine's template folder, then returns the appropriate - /// rendering engine to use. - /// - /// - /// - /// The reason this is required is because for example, if you have a master page file already existing under ~/masterpages/Blah.aspx - /// and then you go to create a template in the tree called Blah and the default rendering engine is MVC, it will create a Blah.cshtml - /// empty template in ~/Views. This means every page that is using Blah will go to MVC and render an empty page. - /// This is mostly related to installing packages since packages install file templates to the file system and then create the - /// templates in business logic. Without this, it could cause the wrong rendering engine to be used for a package. - /// - public RenderingEngine DetermineTemplateRenderingEngine(ITemplate template) - { - var engine = _templateConfig.DefaultRenderingEngine; - var viewHelper = new ViewHelper(_viewsFileSystem); - if (viewHelper.ViewExists(template) == false) - { - if (template.Content.IsNullOrWhiteSpace() == false && MasterPageHelper.IsMasterPageSyntax(template.Content)) - { - //there is a design but its definitely a webforms design and we haven't got a MVC view already for it - return RenderingEngine.WebForms; - } - } - - var masterPageHelper = new MasterPageHelper(_masterpagesFileSystem); - - switch (engine) - { - case RenderingEngine.Mvc: - //check if there's a view in ~/masterpages - if (masterPageHelper.MasterPageExists(template) && viewHelper.ViewExists(template) == false) - { - //change this to webforms since there's already a file there for this template alias - engine = RenderingEngine.WebForms; - } - break; - case RenderingEngine.WebForms: - //check if there's a view in ~/views - if (viewHelper.ViewExists(template) && masterPageHelper.MasterPageExists(template) == false) - { - //change this to mvc since there's already a file there for this template alias - engine = RenderingEngine.Mvc; - } - break; - } - return engine; - } - /// /// Validates a /// @@ -689,21 +586,12 @@ namespace Umbraco.Core.Persistence.Repositories.Implement var path = template.VirtualPath; // get valid paths - var validDirs = _templateConfig.DefaultRenderingEngine == RenderingEngine.Mvc - ? new[] { SystemDirectories.Masterpages, SystemDirectories.MvcViews } - : new[] { SystemDirectories.Masterpages }; + var validDirs = new[] { SystemDirectories.MvcViews }; // get valid extensions var validExts = new List(); - if (_templateConfig.DefaultRenderingEngine == RenderingEngine.Mvc) - { - validExts.Add("cshtml"); - validExts.Add("vbhtml"); - } - else - { - validExts.Add("master"); - } + validExts.Add("cshtml"); + validExts.Add("vbhtml"); // validate path and extension var validFile = IOHelper.VerifyEditPath(path, validDirs); diff --git a/src/Umbraco.Core/Services/IFileService.cs b/src/Umbraco.Core/Services/IFileService.cs index 76e850beb2..daf5d9b80c 100644 --- a/src/Umbraco.Core/Services/IFileService.cs +++ b/src/Umbraco.Core/Services/IFileService.cs @@ -210,21 +210,6 @@ namespace Umbraco.Core.Services /// Optional id of the user void SaveTemplate(IEnumerable templates, int userId = 0); - /// - /// This checks what the default rendering engine is set in config but then also ensures that there isn't already - /// a template that exists in the opposite rendering engine's template folder, then returns the appropriate - /// rendering engine to use. - /// - /// - /// - /// The reason this is required is because for example, if you have a master page file already existing under ~/masterpages/Blah.aspx - /// and then you go to create a template in the tree called Blah and the default rendering engine is MVC, it will create a Blah.cshtml - /// empty template in ~/Views. This means every page that is using Blah will go to MVC and render an empty page. - /// This is mostly related to installing packages since packages install file templates to the file system and then create the - /// templates in business logic. Without this, it could cause the wrong rendering engine to be used for a package. - /// - RenderingEngine DetermineTemplateRenderingEngine(ITemplate template); - /// /// Gets the content of a template as a stream. /// diff --git a/src/Umbraco.Core/Services/Implement/FileService.cs b/src/Umbraco.Core/Services/Implement/FileService.cs index f15f0d7d47..0c08404ab3 100644 --- a/src/Umbraco.Core/Services/Implement/FileService.cs +++ b/src/Umbraco.Core/Services/Implement/FileService.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.ComponentModel; using System.IO; using System.Linq; using System.Text.RegularExpressions; @@ -556,27 +555,6 @@ namespace Umbraco.Core.Services.Implement } } - /// - /// This checks what the default rendering engine is set in config but then also ensures that there isn't already - /// a template that exists in the opposite rendering engine's template folder, then returns the appropriate - /// rendering engine to use. - /// - /// - /// - /// The reason this is required is because for example, if you have a master page file already existing under ~/masterpages/Blah.aspx - /// and then you go to create a template in the tree called Blah and the default rendering engine is MVC, it will create a Blah.cshtml - /// empty template in ~/Views. This means every page that is using Blah will go to MVC and render an empty page. - /// This is mostly related to installing packages since packages install file templates to the file system and then create the - /// templates in business logic. Without this, it could cause the wrong rendering engine to be used for a package. - /// - public RenderingEngine DetermineTemplateRenderingEngine(ITemplate template) - { - using (var scope = ScopeProvider.CreateScope(autoComplete: true)) - { - return _templateRepository.DetermineTemplateRenderingEngine(template); - } - } - /// /// Deletes a template by its alias /// @@ -1043,7 +1021,7 @@ namespace Umbraco.Core.Services.Implement _auditRepository.Save(new AuditItem(objectId, type, userId, entityType)); } - //TODO Method to change name and/or alias of view/masterpage template + //TODO Method to change name and/or alias of view template #region Event Handlers diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 13f1ff2025..81c5af104f 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -291,7 +291,6 @@ - @@ -304,7 +303,6 @@ - @@ -631,7 +629,6 @@ - diff --git a/src/Umbraco.Tests/Configurations/UmbracoSettings/TemplateElementDefaultTests.cs b/src/Umbraco.Tests/Configurations/UmbracoSettings/TemplateElementDefaultTests.cs deleted file mode 100644 index 4f7e8c1800..0000000000 --- a/src/Umbraco.Tests/Configurations/UmbracoSettings/TemplateElementDefaultTests.cs +++ /dev/null @@ -1,13 +0,0 @@ -using NUnit.Framework; - -namespace Umbraco.Tests.Configurations.UmbracoSettings -{ - [TestFixture] - public class TemplateElementDefaultTests : TemplateElementTests - { - protected override bool TestingDefaults - { - get { return true; } - } - } -} diff --git a/src/Umbraco.Tests/Configurations/UmbracoSettings/TemplateElementTests.cs b/src/Umbraco.Tests/Configurations/UmbracoSettings/TemplateElementTests.cs deleted file mode 100644 index a2edf94ab5..0000000000 --- a/src/Umbraco.Tests/Configurations/UmbracoSettings/TemplateElementTests.cs +++ /dev/null @@ -1,16 +0,0 @@ -using NUnit.Framework; -using Umbraco.Core; - -namespace Umbraco.Tests.Configurations.UmbracoSettings -{ - [TestFixture] - public class TemplateElementTests : UmbracoSettingsTests - { - [Test] - public void DefaultRenderingEngine() - { - Assert.IsTrue(SettingsSection.Templates.DefaultRenderingEngine == RenderingEngine.Mvc); - } - - } -} diff --git a/src/Umbraco.Tests/Configurations/UmbracoSettings/umbracoSettings.config b/src/Umbraco.Tests/Configurations/UmbracoSettings/umbracoSettings.config index 4c64485503..dd44e23328 100644 --- a/src/Umbraco.Tests/Configurations/UmbracoSettings/umbracoSettings.config +++ b/src/Umbraco.Tests/Configurations/UmbracoSettings/umbracoSettings.config @@ -145,10 +145,6 @@ - - Mvc - - false true diff --git a/src/Umbraco.Tests/Configurations/UmbracoSettings/umbracoSettings.minimal.config b/src/Umbraco.Tests/Configurations/UmbracoSettings/umbracoSettings.minimal.config index 21dfa1f19e..bee7133051 100644 --- a/src/Umbraco.Tests/Configurations/UmbracoSettings/umbracoSettings.minimal.config +++ b/src/Umbraco.Tests/Configurations/UmbracoSettings/umbracoSettings.minimal.config @@ -37,11 +37,6 @@ - - - Mvc - - diff --git a/src/Umbraco.Tests/IO/IoHelperTests.cs b/src/Umbraco.Tests/IO/IoHelperTests.cs index b2ef5e4d31..b0e59cbb55 100644 --- a/src/Umbraco.Tests/IO/IoHelperTests.cs +++ b/src/Umbraco.Tests/IO/IoHelperTests.cs @@ -37,7 +37,6 @@ namespace Umbraco.Tests.IO Assert.AreEqual(IOHelper.MapPath(SystemDirectories.Css, true), IOHelper.MapPath(SystemDirectories.Css, false)); Assert.AreEqual(IOHelper.MapPath(SystemDirectories.Data, true), IOHelper.MapPath(SystemDirectories.Data, false)); Assert.AreEqual(IOHelper.MapPath(SystemDirectories.Install, true), IOHelper.MapPath(SystemDirectories.Install, false)); - Assert.AreEqual(IOHelper.MapPath(SystemDirectories.Masterpages, true), IOHelper.MapPath(SystemDirectories.Masterpages, false)); Assert.AreEqual(IOHelper.MapPath(SystemDirectories.Media, true), IOHelper.MapPath(SystemDirectories.Media, false)); Assert.AreEqual(IOHelper.MapPath(SystemDirectories.Packages, true), IOHelper.MapPath(SystemDirectories.Packages, false)); Assert.AreEqual(IOHelper.MapPath(SystemDirectories.Preview, true), IOHelper.MapPath(SystemDirectories.Preview, false)); diff --git a/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs index aeaf76967f..f3af1cf73f 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs @@ -7,12 +7,9 @@ using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Configuration.UmbracoSettings; -using Umbraco.Core.IO; using Umbraco.Core.Models; -using Umbraco.Core.Models.Entities; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Dtos; -using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.Scoping; using Umbraco.Tests.TestHelpers; @@ -36,7 +33,7 @@ namespace Umbraco.Tests.Persistence.Repositories private DocumentRepository CreateRepository(IScopeAccessor scopeAccessor, out ContentTypeRepository contentTypeRepository) { var cacheHelper = CacheHelper.Disabled; - var templateRepository = new TemplateRepository(scopeAccessor, cacheHelper, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); + var templateRepository = new TemplateRepository(scopeAccessor, cacheHelper, Logger, TestObjects.GetFileSystemsMock()); var tagRepository = new TagRepository(scopeAccessor, cacheHelper, Logger); contentTypeRepository = new ContentTypeRepository(scopeAccessor, cacheHelper, Logger, templateRepository); var languageRepository = new LanguageRepository(scopeAccessor, cacheHelper, Logger); @@ -46,7 +43,7 @@ namespace Umbraco.Tests.Persistence.Repositories private ContentTypeRepository CreateRepository(IScopeAccessor scopeAccessor) { - var templateRepository = new TemplateRepository(scopeAccessor, CacheHelper.Disabled, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); + var templateRepository = new TemplateRepository(scopeAccessor, CacheHelper.Disabled, Logger, TestObjects.GetFileSystemsMock()); var contentTypeRepository = new ContentTypeRepository(scopeAccessor, CacheHelper.Disabled, Logger, templateRepository); return contentTypeRepository; } @@ -71,7 +68,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var templateRepo = new TemplateRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); + var templateRepo = new TemplateRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, TestObjects.GetFileSystemsMock()); var repository = CreateRepository((IScopeAccessor) provider); var templates = new[] { diff --git a/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs index c1fa5381ff..2619827705 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs @@ -64,7 +64,7 @@ namespace Umbraco.Tests.Persistence.Repositories { cacheHelper = cacheHelper ?? CacheHelper; - templateRepository = new TemplateRepository(scopeAccessor, cacheHelper, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); + templateRepository = new TemplateRepository(scopeAccessor, cacheHelper, Logger, TestObjects.GetFileSystemsMock()); var tagRepository = new TagRepository(scopeAccessor, cacheHelper, Logger); contentTypeRepository = new ContentTypeRepository(scopeAccessor, cacheHelper, Logger, templateRepository); var languageRepository = new LanguageRepository(scopeAccessor, cacheHelper, Logger); diff --git a/src/Umbraco.Tests/Persistence/Repositories/DomainRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DomainRepositoryTest.cs index a5402f964e..5511114d3e 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DomainRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DomainRepositoryTest.cs @@ -4,9 +4,7 @@ using System.Linq; using Moq; using NUnit.Framework; using Umbraco.Core.Configuration.UmbracoSettings; -using Umbraco.Core.IO; using Umbraco.Core.Models; -using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.Scoping; using Umbraco.Tests.TestHelpers; @@ -22,7 +20,7 @@ namespace Umbraco.Tests.Persistence.Repositories private DomainRepository CreateRepository(IScopeProvider provider, out ContentTypeRepository contentTypeRepository, out DocumentRepository documentRepository, out LanguageRepository languageRepository) { var accessor = (IScopeAccessor) provider; - var templateRepository = new TemplateRepository(accessor, Core.Cache.CacheHelper.Disabled, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); + var templateRepository = new TemplateRepository(accessor, Core.Cache.CacheHelper.Disabled, Logger, TestObjects.GetFileSystemsMock()); var tagRepository = new TagRepository(accessor, Core.Cache.CacheHelper.Disabled, Logger); contentTypeRepository = new ContentTypeRepository(accessor, Core.Cache.CacheHelper.Disabled, Logger, templateRepository); languageRepository = new LanguageRepository(accessor, Core.Cache.CacheHelper.Disabled, Logger); diff --git a/src/Umbraco.Tests/Persistence/Repositories/PublicAccessRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/PublicAccessRepositoryTest.cs index e76d794e69..23d95163d0 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/PublicAccessRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/PublicAccessRepositoryTest.cs @@ -4,10 +4,8 @@ using System.Linq; using Moq; using NUnit.Framework; using Umbraco.Core.Configuration.UmbracoSettings; -using Umbraco.Core.IO; using Umbraco.Core.Models; using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.Scoping; using Umbraco.Tests.TestHelpers; @@ -307,7 +305,7 @@ namespace Umbraco.Tests.Persistence.Repositories private DocumentRepository CreateRepository(IScopeProvider provider, out ContentTypeRepository contentTypeRepository) { var accessor = (IScopeAccessor) provider; - var templateRepository = new TemplateRepository(accessor, CacheHelper, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); + var templateRepository = new TemplateRepository(accessor, CacheHelper, Logger, TestObjects.GetFileSystemsMock()); var tagRepository = new TagRepository(accessor, CacheHelper, Logger); contentTypeRepository = new ContentTypeRepository(accessor, CacheHelper, Logger, templateRepository); var languageRepository = new LanguageRepository(accessor, CacheHelper, Logger); diff --git a/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs index 78eb736007..03295ea599 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs @@ -953,7 +953,7 @@ namespace Umbraco.Tests.Persistence.Repositories private DocumentRepository CreateContentRepository(IScopeProvider provider, out ContentTypeRepository contentTypeRepository) { var accessor = (IScopeAccessor) provider; - var templateRepository = new TemplateRepository(accessor, CacheHelper.Disabled, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); + var templateRepository = new TemplateRepository(accessor, CacheHelper.Disabled, Logger, TestObjects.GetFileSystemsMock()); var tagRepository = new TagRepository(accessor, CacheHelper.Disabled, Logger); contentTypeRepository = new ContentTypeRepository(accessor, CacheHelper.Disabled, Logger, templateRepository); var languageRepository = new LanguageRepository(accessor, CacheHelper.Disabled, Logger); diff --git a/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs index f4bed68315..7d4b413a11 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs @@ -25,11 +25,9 @@ namespace Umbraco.Tests.Persistence.Repositories { private IFileSystems _fileSystems; - private ITemplateRepository CreateRepository(IScopeProvider provider, ITemplatesSection templatesSection = null) + private ITemplateRepository CreateRepository(IScopeProvider provider) { - return new TemplateRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, - templatesSection ?? Mock.Of(t => t.DefaultRenderingEngine == RenderingEngine.Mvc), - _fileSystems); + return new TemplateRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, _fileSystems); } public override void SetUp() @@ -37,8 +35,6 @@ namespace Umbraco.Tests.Persistence.Repositories base.SetUp(); _fileSystems = Mock.Of(); - var masterPageFileSystem = new PhysicalFileSystem(SystemDirectories.Masterpages); - Mock.Get(_fileSystems).Setup(x => x.MasterPagesFileSystem).Returns(masterPageFileSystem); var viewsFileSystem = new PhysicalFileSystem(SystemDirectories.MvcViews); Mock.Get(_fileSystems).Setup(x => x.MvcViewsFileSystem).Returns(viewsFileSystem); } @@ -56,77 +52,6 @@ namespace Umbraco.Tests.Persistence.Repositories } } - [Test] - public void Can_Perform_Add_MasterPage_Detect_Content() - { - // Arrange - using (ScopeProvider.CreateScope()) - { - var repository = CreateRepository(ScopeProvider); - - // Act - var template = new Template("test", "test") - { - Content = @"<%@ Master Language=""C#"" %>" - }; - repository.Save(template); - - //Assert - Assert.That(repository.Get("test"), Is.Not.Null); - Assert.That(_fileSystems.MasterPagesFileSystem.FileExists("test.master"), Is.True); - } - } - - [Test] - public void Can_Perform_Add_MasterPage_With_Default_Content() - { - // Arrange - using (ScopeProvider.CreateScope()) - { - var repository = CreateRepository(ScopeProvider, Mock.Of(x => x.DefaultRenderingEngine == RenderingEngine.WebForms)); - - // Act - var template = new Template("test", "test"); - repository.Save(template); - - //Assert - Assert.That(repository.Get("test"), Is.Not.Null); - Assert.That(_fileSystems.MasterPagesFileSystem.FileExists("test.master"), Is.True); - Assert.AreEqual(@"<%@ Master Language=""C#"" MasterPageFile=""~/umbraco/masterpages/default.master"" AutoEventWireup=""true"" %> - - - - -".StripWhitespace(), template.Content.StripWhitespace()); - } - } - - [Test] - public void Can_Perform_Add_MasterPage_With_Default_Content_With_Parent() - { - // Arrange - using (ScopeProvider.CreateScope()) - { - var repository = CreateRepository(ScopeProvider, Mock.Of(x => x.DefaultRenderingEngine == RenderingEngine.WebForms)); - - //NOTE: This has to be persisted first - var template = new Template("test", "test"); - repository.Save(template); - - // Act - var template2 = new Template("test2", "test2"); - template2.SetMasterTemplate(template); - repository.Save(template2); - - //Assert - Assert.That(repository.Get("test2"), Is.Not.Null); - Assert.That(_fileSystems.MasterPagesFileSystem.FileExists("test2.master"), Is.True); - Assert.AreEqual(@"<%@ Master Language=""C#"" MasterPageFile=""~/masterpages/test.master"" AutoEventWireup=""true"" %> - -".StripWhitespace(), template2.Content.StripWhitespace()); - } - } - [Test] public void Can_Perform_Add_View() { @@ -253,32 +178,6 @@ namespace Umbraco.Tests.Persistence.Repositories } } - [Test] - public void Can_Perform_Update_MasterPage() - { - // Arrange - using (ScopeProvider.CreateScope()) - { - var repository = CreateRepository(ScopeProvider); - - // Act - var template = new Template("test", "test") - { - Content = @"<%@ Master Language=""C#"" %>" - }; - repository.Save(template); - - template.Content = @"<%@ Master Language=""VB"" %>"; - repository.Save(template); - - var updated = repository.Get("test"); - - // Assert - Assert.That(_fileSystems.MasterPagesFileSystem.FileExists("test.master"), Is.True); - Assert.That(updated.Content, Is.EqualTo(@"<%@ Master Language=""VB"" %>")); - } - } - [Test] public void Can_Perform_Update_View() { @@ -305,31 +204,6 @@ namespace Umbraco.Tests.Persistence.Repositories } } - [Test] - public void Can_Perform_Delete_MasterPage() - { - // Arrange - using (ScopeProvider.CreateScope()) - { - var repository = CreateRepository(ScopeProvider); - - var template = new Template("test", "test") - { - Content = @"<%@ Master Language=""C#"" %>" - }; - repository.Save(template); - - // Act - var templates = repository.Get("test"); - Assert.That(_fileSystems.MasterPagesFileSystem.FileExists("test.master"), Is.True); - repository.Delete(templates); - - // Assert - Assert.IsNull(repository.Get("test")); - Assert.That(_fileSystems.MasterPagesFileSystem.FileExists("test.master"), Is.False); - } - } - [Test] public void Can_Perform_Delete_View() { @@ -651,11 +525,6 @@ namespace Umbraco.Tests.Persistence.Repositories _fileSystems = null; //Delete all files - var fsMaster = new PhysicalFileSystem(SystemDirectories.Masterpages); - var masterPages = fsMaster.GetFiles("", "*.master"); - foreach (var file in masterPages) - fsMaster.DeleteFile(file); - var fsViews = new PhysicalFileSystem(SystemDirectories.MvcViews); var views = fsViews.GetFiles("", "*.cshtml"); foreach (var file in views) diff --git a/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs index 847972cc50..ba2a7de859 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs @@ -41,7 +41,7 @@ namespace Umbraco.Tests.Persistence.Repositories private DocumentRepository CreateContentRepository(IScopeProvider provider, out IContentTypeRepository contentTypeRepository, out ITemplateRepository templateRepository) { var accessor = (IScopeAccessor) provider; - templateRepository = new TemplateRepository(accessor, CacheHelper, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); + templateRepository = new TemplateRepository(accessor, CacheHelper, Logger, TestObjects.GetFileSystemsMock()); var tagRepository = new TagRepository(accessor, CacheHelper, Logger); contentTypeRepository = new ContentTypeRepository(accessor, CacheHelper, Logger, templateRepository); var languageRepository = new LanguageRepository(accessor, CacheHelper, Logger); diff --git a/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs b/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs index 3aefa88a50..fff88d7531 100644 --- a/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs +++ b/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs @@ -163,7 +163,7 @@ namespace Umbraco.Tests.Services var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var tRepository = new TemplateRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); + var tRepository = new TemplateRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, TestObjects.GetFileSystemsMock()); var tagRepo = new TagRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger); var ctRepository = new ContentTypeRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, tRepository); var languageRepository = new LanguageRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger); @@ -196,7 +196,7 @@ namespace Umbraco.Tests.Services var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var tRepository = new TemplateRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); + var tRepository = new TemplateRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, TestObjects.GetFileSystemsMock()); var tagRepo = new TagRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger); var ctRepository = new ContentTypeRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, tRepository); var languageRepository = new LanguageRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger); @@ -227,7 +227,7 @@ namespace Umbraco.Tests.Services var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var tRepository = new TemplateRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); + var tRepository = new TemplateRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, TestObjects.GetFileSystemsMock()); var tagRepo = new TagRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger); var ctRepository = new ContentTypeRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, tRepository); var languageRepository = new LanguageRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger); @@ -261,7 +261,7 @@ namespace Umbraco.Tests.Services var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { - var tRepository = new TemplateRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); + var tRepository = new TemplateRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, TestObjects.GetFileSystemsMock()); var tagRepo = new TagRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger); var ctRepository = new ContentTypeRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger, tRepository); var languageRepository = new LanguageRepository((IScopeAccessor) provider, CacheHelper.Disabled, Logger); diff --git a/src/Umbraco.Tests/Services/ContentServiceTests.cs b/src/Umbraco.Tests/Services/ContentServiceTests.cs index 0f48a9c99a..a9e48988f4 100644 --- a/src/Umbraco.Tests/Services/ContentServiceTests.cs +++ b/src/Umbraco.Tests/Services/ContentServiceTests.cs @@ -3037,7 +3037,7 @@ namespace Umbraco.Tests.Services private DocumentRepository CreateRepository(IScopeProvider provider, out ContentTypeRepository contentTypeRepository) { var accessor = (IScopeAccessor) provider; - var templateRepository = new TemplateRepository(accessor, CacheHelper.Disabled, Logger, Mock.Of(), TestObjects.GetFileSystemsMock()); + var templateRepository = new TemplateRepository(accessor, CacheHelper.Disabled, Logger, TestObjects.GetFileSystemsMock()); var tagRepository = new TagRepository(accessor, CacheHelper.Disabled, Logger); contentTypeRepository = new ContentTypeRepository(accessor, CacheHelper.Disabled, Logger, templateRepository); var languageRepository = new LanguageRepository(accessor, CacheHelper.Disabled, Logger); diff --git a/src/Umbraco.Tests/Templates/MasterPageHelperTests.cs b/src/Umbraco.Tests/Templates/MasterPageHelperTests.cs deleted file mode 100644 index a8344893c0..0000000000 --- a/src/Umbraco.Tests/Templates/MasterPageHelperTests.cs +++ /dev/null @@ -1,21 +0,0 @@ -using NUnit.Framework; -using Umbraco.Core.IO; - -namespace Umbraco.Tests.Templates -{ - [TestFixture] - public class MasterPageHelperTests - { - - [TestCase(@"<%@ master language=""C#"" masterpagefile=""~/masterpages/umbMaster.master"" autoeventwireup=""true"" %>")] - [TestCase(@"<%@ Master language=""C#"" masterpagefile=""~/masterpages/umbMaster.master"" autoeventwireup=""true"" %>")] - [TestCase(@"<%@Master language=""C#"" masterpagefile=""~/masterpages/umbMaster.master"" autoeventwireup=""true"" %>")] - [TestCase(@"<%@ Master language=""C#"" masterpagefile=""~/masterpages/umbMaster.master"" autoeventwireup=""true"" %>")] - [TestCase(@"<%@master language=""C#"" masterpagefile=""~/masterpages/umbMaster.master"" autoeventwireup=""true"" %>")] - public void IsMasterPageSyntax(string design) - { - Assert.IsTrue(MasterPageHelper.IsMasterPageSyntax(design)); - } - - } -} diff --git a/src/Umbraco.Tests/Templates/TemplateRepositoryTests.cs b/src/Umbraco.Tests/Templates/TemplateRepositoryTests.cs deleted file mode 100644 index 795d79ced1..0000000000 --- a/src/Umbraco.Tests/Templates/TemplateRepositoryTests.cs +++ /dev/null @@ -1,121 +0,0 @@ -using Moq; -using NUnit.Framework; -using Umbraco.Core; -using Umbraco.Core.Cache; -using Umbraco.Core.Configuration.UmbracoSettings; -using Umbraco.Core.IO; -using Umbraco.Core.Logging; -using Umbraco.Core.Models; -using Umbraco.Core.Persistence.Repositories.Implement; -using Umbraco.Core.Scoping; -using Umbraco.Tests.TestHelpers; - -namespace Umbraco.Tests.Templates -{ - [TestFixture] - public class TemplateRepositoryTests - { - private readonly Mock _cacheMock = new Mock(); - private readonly Mock _templateConfigMock = new Mock(); - private readonly IFileSystems _fileSystems = Mock.Of(); - private TemplateRepository _templateRepository; - - private readonly TestObjects _testObjects = new TestObjects(null); - - [SetUp] - public void Setup() - { - var logger = Mock.Of(); - - var accessorMock = new Mock(); - var scopeMock = new Mock(); - var database = _testObjects.GetUmbracoSqlCeDatabase(logger); - scopeMock.Setup(x => x.Database).Returns(database); - accessorMock.Setup(x => x.AmbientScope).Returns(scopeMock.Object); - - var mvcFs = Mock.Of(); - var masterFs = Mock.Of(); - Mock.Get(_fileSystems).Setup(x => x.MvcViewsFileSystem).Returns(mvcFs); - Mock.Get(_fileSystems).Setup(x => x.MasterPagesFileSystem).Returns(masterFs); - - _templateRepository = new TemplateRepository(accessorMock.Object, _cacheMock.Object, logger, _templateConfigMock.Object, _fileSystems); - } - - [Test] - public void DetermineTemplateRenderingEngine_Returns_MVC_When_ViewFile_Exists_And_Content_Has_Webform_Markup() - { - // Project in MVC mode - _templateConfigMock.Setup(x => x.DefaultRenderingEngine).Returns(RenderingEngine.Mvc); - - // Template has masterpage content - var templateMock = new Mock(); - templateMock.Setup(x => x.Alias).Returns("Something"); - templateMock.Setup(x => x.Content).Returns(""); - - // but MVC View already exists - Mock.Get(_fileSystems.MvcViewsFileSystem) - .Setup(x => x.FileExists(It.IsAny())).Returns(true); - - var res = _templateRepository.DetermineTemplateRenderingEngine(templateMock.Object); - Assert.AreEqual(RenderingEngine.Mvc, res); - } - - [Test] - public void DetermineTemplateRenderingEngine_Returns_WebForms_When_ViewFile_Doesnt_Exist_And_Content_Has_Webform_Markup() - { - // Project in MVC mode - _templateConfigMock.Setup(x => x.DefaultRenderingEngine).Returns(RenderingEngine.Mvc); - - // Template has masterpage content - var templateMock = new Mock(); - templateMock.Setup(x => x.Alias).Returns("Something"); - templateMock.Setup(x => x.Content).Returns(""); - - // MVC View doesn't exist - Mock.Get(_fileSystems.MvcViewsFileSystem) - .Setup(x => x.FileExists(It.IsAny())).Returns(false); - - var res = _templateRepository.DetermineTemplateRenderingEngine(templateMock.Object); - Assert.AreEqual(RenderingEngine.WebForms, res); - } - - [Test] - public void DetermineTemplateRenderingEngine_Returns_WebForms_When_MasterPage_Exists_And_In_Mvc_Mode() - { - // Project in MVC mode - _templateConfigMock.Setup(x => x.DefaultRenderingEngine).Returns(RenderingEngine.Mvc); - - var templateMock = new Mock(); - templateMock.Setup(x => x.Alias).Returns("Something"); - - // but masterpage already exists - Mock.Get(_fileSystems.MvcViewsFileSystem) - .Setup(x => x.FileExists(It.IsAny())).Returns(false); - Mock.Get(_fileSystems.MasterPagesFileSystem) - .Setup(x => x.FileExists(It.IsAny())).Returns(true); - - var res = _templateRepository.DetermineTemplateRenderingEngine(templateMock.Object); - Assert.AreEqual(RenderingEngine.WebForms, res); - } - - [Test] - public void DetermineTemplateRenderingEngine_Returns_Mvc_When_ViewPage_Exists_And_In_Webforms_Mode() - { - // Project in WebForms mode - _templateConfigMock.Setup(x => x.DefaultRenderingEngine).Returns(RenderingEngine.WebForms); - - var templateMock = new Mock(); - templateMock.Setup(x => x.Alias).Returns("Something"); - - // but MVC View already exists - Mock.Get(_fileSystems.MvcViewsFileSystem) - .Setup(x => x.FileExists(It.IsAny())).Returns(true); - Mock.Get(_fileSystems.MasterPagesFileSystem) - .Setup(x => x.FileExists(It.IsAny())).Returns(false); - - var res = _templateRepository.DetermineTemplateRenderingEngine(templateMock.Object); - Assert.AreEqual(RenderingEngine.Mvc, res); - } - - } -} diff --git a/src/Umbraco.Tests/TestHelpers/SettingsForTests.cs b/src/Umbraco.Tests/TestHelpers/SettingsForTests.cs index ea40ed9c84..cfd935cd82 100644 --- a/src/Umbraco.Tests/TestHelpers/SettingsForTests.cs +++ b/src/Umbraco.Tests/TestHelpers/SettingsForTests.cs @@ -38,7 +38,6 @@ namespace Umbraco.Tests.TestHelpers var content = new Mock(); var security = new Mock(); var requestHandler = new Mock(); - var templates = new Mock(); var logging = new Mock(); var tasks = new Mock(); var providers = new Mock(); @@ -47,7 +46,6 @@ namespace Umbraco.Tests.TestHelpers settings.Setup(x => x.Content).Returns(content.Object); settings.Setup(x => x.Security).Returns(security.Object); settings.Setup(x => x.RequestHandler).Returns(requestHandler.Object); - settings.Setup(x => x.Templates).Returns(templates.Object); settings.Setup(x => x.Logging).Returns(logging.Object); settings.Setup(x => x.ScheduledTasks).Returns(tasks.Object); settings.Setup(x => x.Providers).Returns(providers.Object); @@ -61,7 +59,6 @@ namespace Umbraco.Tests.TestHelpers settings.Setup(x => x.RequestHandler.UseDomainPrefixes).Returns(false); settings.Setup(x => x.RequestHandler.CharCollection).Returns(RequestHandlerElement.GetDefaultCharReplacements()); settings.Setup(x => x.WebRouting.UrlProviderMode).Returns("AutoLegacy"); - settings.Setup(x => x.Templates.DefaultRenderingEngine).Returns(RenderingEngine.Mvc); settings.Setup(x => x.Providers.DefaultBackOfficeUserProvider).Returns("UsersMembershipProvider"); return settings.Object; diff --git a/src/Umbraco.Tests/TestHelpers/TestHelper.cs b/src/Umbraco.Tests/TestHelpers/TestHelper.cs index 1fe814e4c6..b6f597bf46 100644 --- a/src/Umbraco.Tests/TestHelpers/TestHelper.cs +++ b/src/Umbraco.Tests/TestHelpers/TestHelper.cs @@ -55,12 +55,12 @@ namespace Umbraco.Tests.TestHelpers public static void InitializeContentDirectories() { - CreateDirectories(new[] { SystemDirectories.Masterpages, SystemDirectories.MvcViews, SystemDirectories.Media, SystemDirectories.AppPlugins }); + CreateDirectories(new[] { SystemDirectories.MvcViews, SystemDirectories.Media, SystemDirectories.AppPlugins }); } public static void CleanContentDirectories() { - CleanDirectories(new[] { SystemDirectories.Masterpages, SystemDirectories.MvcViews, SystemDirectories.Media }); + CleanDirectories(new[] { SystemDirectories.MvcViews, SystemDirectories.Media }); } public static void CreateDirectories(string[] directories) @@ -77,7 +77,6 @@ namespace Umbraco.Tests.TestHelpers { var preserves = new Dictionary { - { SystemDirectories.Masterpages, new[] {"dummy.txt"} }, { SystemDirectories.MvcViews, new[] {"dummy.txt"} } }; foreach (var directory in directories) diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs b/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs index 8c230f98d0..563d81da05 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs @@ -145,8 +145,7 @@ namespace Umbraco.Tests.TestHelpers public IFileSystems GetFileSystemsMock() { var fileSystems = Mock.Of(); - - MockFs(fileSystems, x => x.MasterPagesFileSystem); + MockFs(fileSystems, x => x.MacroPartialsFileSystem); MockFs(fileSystems, x => x.MvcViewsFileSystem); MockFs(fileSystems, x => x.PartialViewsFileSystem); diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index a79531af74..304a13f20c 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -304,7 +304,6 @@ namespace Umbraco.Tests.Testing // register basic stuff that might need to be there for some container resolvers to work Composition.RegisterUnique(factory => factory.GetInstance().Content); - Composition.RegisterUnique(factory => factory.GetInstance().Templates); Composition.RegisterUnique(factory => factory.GetInstance().WebRouting); Composition.RegisterUnique(factory => ExamineManager.Instance); diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index e49ba250fa..c22b765169 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -305,8 +305,6 @@ - - @@ -354,7 +352,6 @@ - @@ -453,7 +450,6 @@ - diff --git a/src/Umbraco.Web.UI/config/umbracoSettings.Release.config b/src/Umbraco.Web.UI/config/umbracoSettings.Release.config index fb8ff63ab0..7299a397bc 100644 --- a/src/Umbraco.Web.UI/config/umbracoSettings.Release.config +++ b/src/Umbraco.Web.UI/config/umbracoSettings.Release.config @@ -85,11 +85,6 @@ - - - Mvc - - diff --git a/src/Umbraco.Web.UI/config/umbracoSettings.config b/src/Umbraco.Web.UI/config/umbracoSettings.config index c3e146d6ce..4de0a04735 100644 --- a/src/Umbraco.Web.UI/config/umbracoSettings.config +++ b/src/Umbraco.Web.UI/config/umbracoSettings.config @@ -162,11 +162,6 @@ - - - Mvc - - + + Add between {{model.config.minNumber}} and {{model.config.maxNumber}} items + + You can only have {{model.config.maxNumber}} items selected + + + + + + Add {{model.config.minNumber - renderModel.length}} item(s) + + You can only have {{model.config.maxNumber}} items selected + + + + + + Add up to {{model.config.maxNumber}} items + + You can only have {{model.config.maxNumber}} items selected + + + + + + Add at least {{model.config.minNumber}} item(s) + + + + + + + + +
    + You need to add at least {{model.config.minNumber}} items +
    + +
    + You can only have {{model.config.maxNumber}} items selected +
    + + + + diff --git a/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs b/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs index 65d366e2ad..fe85263f3b 100644 --- a/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs @@ -117,6 +117,7 @@ namespace Umbraco.Web.Cache LegacyMediaPickerPropertyConverter.ClearCaches(); SliderValueConverter.ClearCaches(); MediaPickerPropertyConverter.ClearCaches(); + MultiUrlPickerPropertyConverter.ClearCaches(); base.Refresh(jsonPayload); diff --git a/src/Umbraco.Web/Models/ContentEditing/LinkDisplay.cs b/src/Umbraco.Web/Models/ContentEditing/LinkDisplay.cs new file mode 100644 index 0000000000..857ae2c318 --- /dev/null +++ b/src/Umbraco.Web/Models/ContentEditing/LinkDisplay.cs @@ -0,0 +1,36 @@ +using System.Runtime.Serialization; +using Umbraco.Core; + +namespace Umbraco.Web.Models.ContentEditing +{ + [DataContract(Name = "link", Namespace = "")] + internal class LinkDisplay + { + [DataMember(Name = "icon")] + public string Icon { get; set; } + + [DataMember(Name = "isMedia")] + public bool IsMedia { get; set; } + + [DataMember(Name = "name")] + public string Name { get; set; } + + [DataMember(Name = "published")] + public bool Published { get; set; } + + [DataMember(Name = "queryString")] + public string QueryString { get; set; } + + [DataMember(Name = "target")] + public string Target { get; set; } + + [DataMember(Name = "trashed")] + public bool Trashed { get; set; } + + [DataMember(Name = "udi")] + public GuidUdi Udi { get; set; } + + [DataMember(Name = "url")] + public string Url { get; set; } + } +} diff --git a/src/Umbraco.Web/Models/Link.cs b/src/Umbraco.Web/Models/Link.cs new file mode 100644 index 0000000000..74ad4ad2af --- /dev/null +++ b/src/Umbraco.Web/Models/Link.cs @@ -0,0 +1,13 @@ +using Umbraco.Core; + +namespace Umbraco.Web.Models +{ + public class Link + { + public string Name { get; set; } + public string Target { get; set; } + public LinkType Type { get; set; } + public Udi Udi { get; set; } + public string Url { get; set; } + } +} diff --git a/src/Umbraco.Web/Models/LinkType.cs b/src/Umbraco.Web/Models/LinkType.cs new file mode 100644 index 0000000000..3db3165d7f --- /dev/null +++ b/src/Umbraco.Web/Models/LinkType.cs @@ -0,0 +1,9 @@ +namespace Umbraco.Web.Models +{ + public enum LinkType + { + Content, + Media, + External + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/PropertyEditors/MultiUrlPickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/MultiUrlPickerPropertyEditor.cs new file mode 100644 index 0000000000..84523f05c4 --- /dev/null +++ b/src/Umbraco.Web/PropertyEditors/MultiUrlPickerPropertyEditor.cs @@ -0,0 +1,249 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; +using Newtonsoft.Json; +using Umbraco.Core; +using Umbraco.Core.Logging; +using Umbraco.Core.Models; +using Umbraco.Core.Models.Editors; +using Umbraco.Core.Models.EntityBase; +using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Services; +using Umbraco.Web.Models.ContentEditing; +using Umbraco.Web.Routing; + +namespace Umbraco.Web.PropertyEditors +{ + [PropertyEditor(Constants.PropertyEditors.MultiUrlPickerAlias, "Multi Url Picker", PropertyEditorValueTypes.Json, "multiurlpicker", Group = "pickers", Icon = "icon-link", IsParameterEditor = true)] + public class MultiUrlPickerPropertyEditor : PropertyEditor + { + protected override PreValueEditor CreatePreValueEditor() + { + return new MultiUrlPickerPreValueEditor(); + } + + protected override PropertyValueEditor CreateValueEditor() + { + return new MultiUrlPickerPropertyValueEditor(base.CreateValueEditor()); + } + + private class MultiUrlPickerPreValueEditor : PreValueEditor + { + public MultiUrlPickerPreValueEditor() + { + Fields.Add(new PreValueField + { + Key = "minNumber", + View = "number", + Name = "Minimum number of items" + }); + Fields.Add(new PreValueField + { + Key = "maxNumber", + View = "number", + Name = "Maximum number of items" + }); + } + } + + private class MultiUrlPickerPropertyValueEditor : PropertyValueEditorWrapper + { + public MultiUrlPickerPropertyValueEditor(PropertyValueEditor wrapped) : base(wrapped) + { + } + + public override object ConvertDbToEditor(Property property, PropertyType propertyType, IDataTypeService dataTypeService) + { + if (property.Value == null) + return Enumerable.Empty(); + + var value = property.Value.ToString(); + + if (string.IsNullOrEmpty(value)) + return Enumerable.Empty(); + + try + { + var umbHelper = new UmbracoHelper(UmbracoContext.Current); + var services = ApplicationContext.Current.Services; + var entityService = services.EntityService; + var contentTypeService = services.ContentTypeService; + string deletedLocalization = null; + string recycleBinLocalization = null; + + var dtos = JsonConvert.DeserializeObject>(value); + + var documentLinks = dtos.FindAll(link => + link.Udi != null && link.Udi.EntityType == Constants.UdiEntityType.Document + ); + + var mediaLinks = dtos.FindAll(link => + link.Udi != null && link.Udi.EntityType == Constants.UdiEntityType.Media + ); + + var entities = new List(); + if (documentLinks.Count > 0) + { + entities.AddRange( + entityService.GetAll(UmbracoObjectTypes.Document, + documentLinks.Select(link => link.Udi.Guid).ToArray()) + ); + } + + if (mediaLinks.Count > 0) + { + entities.AddRange( + entityService.GetAll(UmbracoObjectTypes.Media, + mediaLinks.Select(link => link.Udi.Guid).ToArray()) + ); + } + + var links = new List(); + foreach (var dto in dtos) + { + var link = new LinkDisplay + { + Icon = "icon-link", + IsMedia = false, + Name = dto.Name, + Published = true, + QueryString = dto.QueryString, + Target = dto.Target, + Trashed = false, + Udi = dto.Udi, + Url = dto.Url, + }; + + links.Add(link); + + if (dto.Udi == null) + continue; + + var entity = entities.Find(e => e.Key == dto.Udi.Guid); + if (entity == null) + { + if (deletedLocalization == null) + deletedLocalization = services.TextService.Localize("general/deleted"); + + link.Published = false; + link.Trashed = true; + link.Url = deletedLocalization; + } + else + { + var entityType = + Equals(entity.AdditionalData["NodeObjectTypeId"], Constants.ObjectTypes.MediaGuid) + ? Constants.UdiEntityType.Media + : Constants.UdiEntityType.Document; + + var udi = new GuidUdi(entityType, entity.Key); + + var contentTypeAlias = (string)entity.AdditionalData["ContentTypeAlias"]; + if (entity.Trashed) + { + if (recycleBinLocalization == null) + recycleBinLocalization = services.TextService.Localize("general/recycleBin"); + + link.Trashed = true; + link.Url = recycleBinLocalization; + } + + if (udi.EntityType == Constants.UdiEntityType.Document) + { + var contentType = contentTypeService.GetContentType(contentTypeAlias); + + if (contentType == null) + continue; + + link.Icon = contentType.Icon; + link.Published = Equals(entity.AdditionalData["IsPublished"], true); + + if (link.Trashed == false) + link.Url = umbHelper.Url(entity.Id, UrlProviderMode.Relative); + } + else + { + link.IsMedia = true; + + var mediaType = contentTypeService.GetMediaType(contentTypeAlias); + + if (mediaType == null) + continue; + + link.Icon = mediaType.Icon; + + if (link.Trashed) + continue; + + var media = umbHelper.TypedMedia(entity.Id); + if (media != null) + link.Url = media.Url; + } + } + } + return links; + } + catch (Exception ex) + { + ApplicationContext.Current.ProfilingLogger.Logger.Error($"Error getting links.\r\n{property.Value}", ex); + } + + return base.ConvertDbToEditor(property, propertyType, dataTypeService); + } + + public override object ConvertEditorToDb(ContentPropertyData editorValue, object currentValue) + { + if (editorValue.Value == null) + return null; + + var value = editorValue.Value.ToString(); + + if (string.IsNullOrEmpty(value)) + return null; + + try + { + return JsonConvert.SerializeObject( + from link in JsonConvert.DeserializeObject>(value) + select new LinkDto + { + Name = link.Name, + QueryString = link.QueryString, + Target = link.Target, + Udi = link.Udi, + Url = link.Udi == null ? link.Url : null, // only save the url for external links + }, + new JsonSerializerSettings + { + NullValueHandling = NullValueHandling.Ignore + }); + } + catch (Exception ex) + { + ApplicationContext.Current.ProfilingLogger.Logger.Error($"Error saving links.\r\n{editorValue.Value}", ex); + } + return base.ConvertEditorToDb(editorValue, currentValue); + } + } + + [DataContract] + internal class LinkDto + { + [DataMember(Name = "name")] + public string Name { get; set; } + + [DataMember(Name = "queryString")] + public string QueryString { get; set; } + + [DataMember(Name = "target")] + public string Target { get; set; } + + [DataMember(Name = "udi")] + public GuidUdi Udi { get; set; } + + [DataMember(Name = "url")] + public string Url { get; set; } + } + } +} diff --git a/src/Umbraco.Web/PropertyEditors/RelatedLinks2PropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/RelatedLinks2PropertyEditor.cs index 3aaf191fd2..541dccaa4e 100644 --- a/src/Umbraco.Web/PropertyEditors/RelatedLinks2PropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/RelatedLinks2PropertyEditor.cs @@ -1,10 +1,13 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using Umbraco.Core; using Umbraco.Core.PropertyEditors; namespace Umbraco.Web.PropertyEditors { - [PropertyEditor(Constants.PropertyEditors.RelatedLinks2Alias, "Related links", "relatedlinks", ValueType = PropertyEditorValueTypes.Json, Icon = "icon-thumbnail-list", Group = "pickers")] + // TODO: Remove in V8 + [Obsolete("This editor is obsolete, use MultiUrlPickerPropertyEditor instead")] + [PropertyEditor(Constants.PropertyEditors.RelatedLinks2Alias, "Related links", "relatedlinks", ValueType = PropertyEditorValueTypes.Json, Icon = "icon-thumbnail-list", Group = "pickers", IsDeprecated = true)] public class RelatedLinks2PropertyEditor : PropertyEditor { public RelatedLinks2PropertyEditor() @@ -33,4 +36,4 @@ namespace Umbraco.Web.PropertyEditors public int Maximum { get; set; } } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Web/PropertyEditors/ValueConverters/MultiUrlPickerPropertyConverter.cs b/src/Umbraco.Web/PropertyEditors/ValueConverters/MultiUrlPickerPropertyConverter.cs new file mode 100644 index 0000000000..397448983a --- /dev/null +++ b/src/Umbraco.Web/PropertyEditors/ValueConverters/MultiUrlPickerPropertyConverter.cs @@ -0,0 +1,165 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using Newtonsoft.Json.Linq; +using Umbraco.Core; +using Umbraco.Core.Logging; +using Umbraco.Core.Models.PublishedContent; +using Umbraco.Core.PropertyEditors; +using Umbraco.Core.PropertyEditors.ValueConverters; +using Umbraco.Core.Services; +using Umbraco.Web.Models; + +namespace Umbraco.Web.PropertyEditors.ValueConverters +{ + [DefaultPropertyValueConverter(typeof(JsonValueConverter))] + public class MultiUrlPickerPropertyConverter : PropertyValueConverterBase, IPropertyValueConverterMeta + { + private readonly IDataTypeService _dataTypeService; + + public MultiUrlPickerPropertyConverter(IDataTypeService dataTypeService) + { + if (dataTypeService == null) throw new ArgumentNullException("dataTypeService"); + _dataTypeService = dataTypeService; + } + + //TODO: Remove this ctor in v8 since the other one will use IoC + public MultiUrlPickerPropertyConverter() : this(ApplicationContext.Current.Services.DataTypeService) + { + } + + public override bool IsConverter(PublishedPropertyType propertyType) + { + return propertyType.PropertyEditorAlias.Equals(Constants.PropertyEditors.MultiUrlPickerAlias); + } + + public override object ConvertDataToSource(PublishedPropertyType propertyType, object source, bool preview) + { + if (source == null) + return null; + + if (source.ToString().Trim().StartsWith("[") == false) + return null; + + try + { + return JArray.Parse(source.ToString()); + } + catch (Exception ex) + { + LogHelper.Error("Error parsing JSON", ex); + } + return null; + } + + public override object ConvertSourceToObject(PublishedPropertyType propertyType, object source, bool preview) + { + var isMultiple = IsMultipleDataType(propertyType.DataTypeId, out var maxNumber); + if (source == null) + return isMultiple + ? Enumerable.Empty() + : null; + + //TODO: Inject an UmbracoHelper and create a GetUmbracoHelper method based on either injected or singleton + if (UmbracoContext.Current == null) + return source; + + var umbHelper = new UmbracoHelper(UmbracoContext.Current); + + var links = new List(); + var dtos = ((JArray) source).ToObject>(); + + foreach (var dto in dtos) + { + var type = LinkType.External; + var url = dto.Url; + if (dto.Udi != null) + { + type = dto.Udi.EntityType == Constants.UdiEntityType.Media + ? LinkType.Media + : LinkType.Content; + + if (type == LinkType.Media) + { + var media = umbHelper.TypedMedia(dto.Udi); + if (media == null) + continue; + url = media.Url; + } + else + { + var content = umbHelper.TypedContent(dto.Udi); + if (content == null) + continue; + url = content.Url; + } + } + + var link = new Link + { + Name = dto.Name, + Target = dto.Target, + Type = type, + Udi = dto.Udi, + Url = url + dto.QueryString, + }; + + links.Add(link); + } + + if (isMultiple == false) + return links.FirstOrDefault(); + if (maxNumber > 0) + return links.Take(maxNumber); + + return links; + } + + public Type GetPropertyValueType(PublishedPropertyType propertyType) + { + return IsMultipleDataType(propertyType.DataTypeId, out var maxNumber) + ? typeof(IEnumerable) + : typeof(Link); + } + + public PropertyCacheLevel GetPropertyCacheLevel(PublishedPropertyType propertyType, PropertyCacheValue cacheValue) + { + switch (cacheValue) + { + case PropertyCacheValue.Source: + return PropertyCacheLevel.Content; + case PropertyCacheValue.Object: + case PropertyCacheValue.XPath: + return PropertyCacheLevel.ContentCache; + } + + return PropertyCacheLevel.None; + } + + private bool IsMultipleDataType(int dataTypeId, out int maxNumber) + { + // GetPreValuesCollectionByDataTypeId is cached at repository level; + // still, the collection is deep-cloned so this is kinda expensive, + // better to cache here + trigger refresh in DataTypeCacheRefresher + + maxNumber = Storages.GetOrAdd(dataTypeId, id => + { + var preValues = _dataTypeService.GetPreValuesCollectionByDataTypeId(id).PreValuesAsDictionary; + + return preValues.TryGetValue("maxNumber", out var maxNumberPreValue) + ? maxNumberPreValue.Value.TryConvertTo().Result + : 0; + }); + + return maxNumber != 1; + } + + private static readonly ConcurrentDictionary Storages = new ConcurrentDictionary(); + + internal static void ClearCaches() + { + Storages.Clear(); + } + } +} diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index e021de0011..1b668b06c8 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -419,6 +419,7 @@ + @@ -444,6 +445,8 @@ + + @@ -485,6 +488,7 @@ + @@ -499,6 +503,7 @@ + From d6855d18f967092dec5583169c535dece072bab4 Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Sun, 20 Jan 2019 21:19:06 +0100 Subject: [PATCH 468/469] v8: Nicer delete language confirm (#4108) --- .../src/less/components/html/umb-alert.less | 12 +++- .../src/less/utilities/_spacing.less | 13 ++-- .../src/views/languages/overlays/delete.html | 9 +++ .../views/languages/overview.controller.js | 53 ++++++++++------ .../src/views/languages/overview.html | 61 +++++++++---------- .../listview/overlays/delete.html | 4 +- .../listview/overlays/listviewpublish.html | 5 +- .../listview/overlays/listviewunpublish.html | 5 +- src/Umbraco.Web.UI/Umbraco/config/lang/da.xml | 14 +++++ src/Umbraco.Web.UI/Umbraco/config/lang/en.xml | 4 +- .../Umbraco/config/lang/en_us.xml | 1 + 11 files changed, 116 insertions(+), 65 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/views/languages/overlays/delete.html diff --git a/src/Umbraco.Web.UI.Client/src/less/components/html/umb-alert.less b/src/Umbraco.Web.UI.Client/src/less/components/html/umb-alert.less index ef8834f767..c9aff190ce 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/html/umb-alert.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/html/umb-alert.less @@ -8,4 +8,14 @@ .umb-alert--info { background-color: @turquoise-washed; border: 1px solid @turquoise; -} \ No newline at end of file +} + +.umb-alert--warning { + background-color: @yellow-washed; + border: 1px solid @yellow; +} + +.umb-alert--danger { + background-color: @red-washed; + border: 1px solid @red; +} diff --git a/src/Umbraco.Web.UI.Client/src/less/utilities/_spacing.less b/src/Umbraco.Web.UI.Client/src/less/utilities/_spacing.less index 64d86d7b6f..69bbeef0af 100644 --- a/src/Umbraco.Web.UI.Client/src/less/utilities/_spacing.less +++ b/src/Umbraco.Web.UI.Client/src/less/utilities/_spacing.less @@ -1,7 +1,5 @@ /* - Spacing - */ @spacing-none: 0; @@ -37,13 +35,11 @@ 7 = 7th step in spacing scale */ - .m-center { margin-left: auto; margin-right: auto; } - .mt0 { margin-top: @spacing-none; } .mt1 { margin-top: @spacing-extra-small; } .mt2 { margin-top: @spacing-small; } @@ -52,3 +48,12 @@ .mt5 { margin-top: @spacing-extra-large; } .mt6 { margin-top: @spacing-extra-extra-large; } .mt7 { margin-top: @spacing-extra-extra-extra-large; } + +.mb0 { margin-bottom: @spacing-none; } +.mb1 { margin-bottom: @spacing-extra-small; } +.mb2 { margin-bottom: @spacing-small; } +.mb3 { margin-bottom: @spacing-medium; } +.mb4 { margin-bottom: @spacing-large; } +.mb5 { margin-bottom: @spacing-extra-large; } +.mb6 { margin-bottom: @spacing-extra-extra-large; } +.mb7 { margin-bottom: @spacing-extra-extra-extra-large; } diff --git a/src/Umbraco.Web.UI.Client/src/views/languages/overlays/delete.html b/src/Umbraco.Web.UI.Client/src/views/languages/overlays/delete.html new file mode 100644 index 0000000000..59221fcea8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/languages/overlays/delete.html @@ -0,0 +1,9 @@ +
    + +
    + This will delete the language {{model.language.name}} [{{model.language.culture}}]. +
    + + ? + +
    diff --git a/src/Umbraco.Web.UI.Client/src/views/languages/overview.controller.js b/src/Umbraco.Web.UI.Client/src/views/languages/overview.controller.js index a5c446dfb5..c1972ec067 100644 --- a/src/Umbraco.Web.UI.Client/src/views/languages/overview.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/languages/overview.controller.js @@ -1,7 +1,7 @@ (function () { "use strict"; - function LanguagesOverviewController($location, $timeout, navigationService, notificationsService, localizationService, languageResource, eventsService) { + function LanguagesOverviewController($location, $timeout, navigationService, localizationService, languageResource, eventsService, overlayService) { var vm = this; @@ -65,30 +65,47 @@ } function deleteLanguage(language, event) { - var confirmed = confirm("Are you sure you want to delete " + language.name + "?"); - if(confirmed) { - language.deleteButtonState = "busy"; - languageResource.deleteById(language.id).then(function () { + const dialog = { + view: "views/languages/overlays/delete.html", + language: language, + submitButtonLabelKey: "contentTypeEditor_yesDelete", + submit: function (model) { + performDelete(model.language); + overlayService.close(); + }, + close: function () { + overlayService.close(); + } + }; - // emit event - var args = { language: language }; - eventsService.emit("editors.languages.languageDeleted", args); + localizationService.localize("general_delete").then(value => { + dialog.title = value; + overlayService.open(dialog); + }); - // remove from list - var index = vm.languages.indexOf(language); - vm.languages.splice(index, 1); - - }, function (err) { - language.deleteButtonState = "error"; - - }); - - } event.preventDefault() event.stopPropagation(); } + function performDelete(language) { + language.deleteButtonState = "busy"; + + languageResource.deleteById(language.id).then(function () { + + // emit event + var args = { language: language }; + eventsService.emit("editors.languages.languageDeleted", args); + + // remove from list + var index = vm.languages.indexOf(language); + vm.languages.splice(index, 1); + + }, function (err) { + language.deleteButtonState = "error"; + }); + } + init(); } diff --git a/src/Umbraco.Web.UI.Client/src/views/languages/overview.html b/src/Umbraco.Web.UI.Client/src/views/languages/overview.html index c55ce83417..15a9c84367 100644 --- a/src/Umbraco.Web.UI.Client/src/views/languages/overview.html +++ b/src/Umbraco.Web.UI.Client/src/views/languages/overview.html @@ -2,43 +2,41 @@ - + - + - + - + - + - - + + - + diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/overlays/delete.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/overlays/delete.html index 6ae3eba521..9b10b1d8b4 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/overlays/delete.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/overlays/delete.html @@ -1,6 +1,6 @@
    -
    +
    This will delete the node and all its languages. If you only want to delete one language go and unpublish it instead. @@ -8,4 +8,4 @@ ? -
    \ No newline at end of file +
    diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/overlays/listviewpublish.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/overlays/listviewpublish.html index 0e2ced411c..8354b323fa 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/overlays/listviewpublish.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/overlays/listviewpublish.html @@ -6,7 +6,7 @@
    -
    +

    @@ -16,7 +16,7 @@
    -
    +
    - \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/overlays/listviewunpublish.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/overlays/listviewunpublish.html index 03f91b1ad6..5cc46c5ce5 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/overlays/listviewunpublish.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/overlays/listviewunpublish.html @@ -8,13 +8,13 @@
    -
    +

    -
    +
    - \ No newline at end of file diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/da.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/da.xml index b10f3d0be0..a257fb41d5 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/da.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/da.xml @@ -354,6 +354,7 @@ Indsæt link Indsæt makro Indsæt tabel + Dette vil slette sproget Sidst redigeret Link Internt link: @@ -407,6 +408,7 @@ konto Vælg editor Vælg snippet + Dette vil slette noden og alle dets sprog. Hvis du kun vil slette et sprog, så afpublicér det i stedet. Vis på medlemsprofil fane har ingen sorteringsrækkefølge + + Tilføj sprog + Påkrævet sprog + Egenskaber på dette sprog skal være udfyldt før noden kan blive udgivet. + Standard sprog + Et Umbraco site kan kun have et standard sprog. + Ved at skifte standardsprog kan resultere i standard indhold mangler. + Fallsback til + Ingen fallback sprog + For at tillade flersproget indhold til at falde tilbage på et andet sprog, hvis det ikke er tilgængelig i det anmodet sprog, vælg det her. + Fallback sprog + Alternativt felt Alternativ tekst diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml index 99a35a5e3b..42a2c4c844 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml @@ -371,6 +371,7 @@ Insert link Click to add a Macro Insert table + This will delete the language Last Edited Link Internal link: @@ -429,6 +430,7 @@ account Select editor Select snippet + This will delete the node and all its languages. If you only want to delete one language go and unpublish it instead. Hide History Icon - Id + Id Import Info Inner margin diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml index 47f293c2a9..be33ee853a 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml @@ -399,6 +399,7 @@ Insert link Click to add a Macro Insert table + This will delete the language Last Edited Link Internal link: From a502be606ba331f6e32761eae9d14a981ed1c75b Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Sun, 20 Jan 2019 21:27:32 +0100 Subject: [PATCH 469/469] v8: Fix package localization (#4159) --- .../src/views/packages/edit.controller.js | 16 ++- .../src/views/packages/edit.html | 2 - .../src/views/packages/options.html | 2 +- .../src/views/packages/overview.controller.js | 119 +++++++++++------- .../src/views/packages/views/created.html | 8 +- .../views/packages/views/install-local.html | 3 - .../src/views/users/overview.controller.js | 3 +- src/Umbraco.Web.UI/Umbraco/config/lang/da.xml | 9 +- src/Umbraco.Web.UI/Umbraco/config/lang/en.xml | 13 +- .../Umbraco/config/lang/en_us.xml | 16 ++- 10 files changed, 120 insertions(+), 71 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js index 0a44192041..282fd0472c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js @@ -1,7 +1,7 @@ (function () { "use strict"; - function EditController($scope, $location, $routeParams, umbRequestHelper, entityResource, packageResource, editorService, formHelper) { + function EditController($scope, $location, $routeParams, umbRequestHelper, entityResource, packageResource, editorService, formHelper, localizationService) { const vm = this; @@ -23,18 +23,23 @@ vm.removePackageView = removePackageView; vm.downloadFile = downloadFile; + vm.buttonLabel = ""; + const packageId = $routeParams.id; const create = $routeParams.create; function onInit() { - if(create) { + if (create) { //pre populate package with some values packageResource.getEmpty().then(scaffold => { vm.package = scaffold; vm.loading = false; }); - vm.buttonLabel = "Create"; + + localizationService.localize("general_create").then(function(value) { + vm.buttonLabel = value; + }); } else { // load package packageResource.getCreatedById(packageId).then(createdPackage => { @@ -49,7 +54,10 @@ } }); - vm.buttonLabel = "Save"; + + localizationService.localize("buttons_save").then(function (value) { + vm.buttonLabel = value; + }); } // get all doc types diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html index 5ad5ac2522..4c32e7e10c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html @@ -323,8 +323,6 @@ disabled="vm.loading"> - - diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/options.html b/src/Umbraco.Web.UI.Client/src/views/packages/options.html index d75604d094..f34ac77ac2 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/options.html +++ b/src/Umbraco.Web.UI.Client/src/views/packages/options.html @@ -19,7 +19,7 @@

    - This package has no configuration view + This package has no configuration view

    + label="Create package" + label-key="packager_createPackage"> @@ -24,7 +25,7 @@
    {{ createdPackage.name }}
    - {{ createdPackage.version }} | {{ createdPackage.url }}| {{ createdPackage.author }} + {{ createdPackage.version }} | {{ createdPackage.url }} | {{ createdPackage.author }}
    @@ -34,7 +35,6 @@ button-style="danger" size="xxs" label-key="general_delete" - add-ellipsis="true" action="vm.deleteCreatedPackage($event, $index, createdPackage)"> @@ -45,7 +45,7 @@ - No packages have been created yet + No packages have been created yet
    \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/views/install-local.html b/src/Umbraco.Web.UI.Client/src/views/packages/views/install-local.html index b657c42877..6d95bcafa7 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/views/install-local.html +++ b/src/Umbraco.Web.UI.Client/src/views/packages/views/install-local.html @@ -41,7 +41,6 @@
    -

    Upload package

    Install a local package by selecting it from your machine. Only install packages from sources you know and trust. @@ -167,8 +166,6 @@

    {{vm.installState.status}}

    - -
    diff --git a/src/Umbraco.Web.UI.Client/src/views/users/overview.controller.js b/src/Umbraco.Web.UI.Client/src/views/users/overview.controller.js index 49e8007d8c..80e2322f6b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/users/overview.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/users/overview.controller.js @@ -1,7 +1,7 @@ (function () { "use strict"; - function UsersOverviewController($scope, $location, $timeout, navigationService, localizationService) { + function UsersOverviewController($scope, $location, localizationService) { var vm = this; var usersUri = $location.search().subview; @@ -24,7 +24,6 @@ loadNavigation(); setPageName(); - } function loadNavigation() { diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/da.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/da.xml index a257fb41d5..0742541484 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/da.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/da.xml @@ -804,6 +804,8 @@ Mange hilsner fra Umbraco robotten Notificeringer + Oprettet + Opret pakke Vælg pakken fra din computer. Umbraco pakker er oftest en ".zip" fil Slip her for at uploade eller klik her for at vælge pakkefil @@ -815,8 +817,12 @@ Mange hilsner fra Umbraco robotten Jeg accepterer betingelser for anvendelse Installér pakke - Afslut + Installeret Installeret pakker + Installér lokal + Afslut + Denne pakke har ingen konfigurationsvisning + Der er ikke blevet oprettet nogle pakker endnu Du har ingen pakker installeret 'Pakker' øverst til højre på din skærm]]> Søg efter pakker @@ -953,6 +959,7 @@ Mange hilsner fra Umbraco robotten Umbraco konfigurationsguide Mediearkiv Medlemmer + Pakker Nyhedsbreve Indstillinger Statistik diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml index 42a2c4c844..a057bb060f 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml @@ -1049,6 +1049,8 @@ To manage your website, simply open the Umbraco back office and start adding con Notifications + Created + Create package button and locating the package. Umbraco packages usually have a ".umb" or ".zip" extension. @@ -1063,8 +1065,12 @@ To manage your website, simply open the Umbraco back office and start adding con I accept terms of use Install package - Finish + Installed Installed packages + Install local + Finish + This package has no configuration view + No packages have been created yet You don’t have any packages installed 'Packages' icon in the top right of your screen]]> Search for packages @@ -1212,16 +1218,17 @@ To manage your website, simply open the Umbraco back office and start adding con Content Courier Developer + Forms + Help Umbraco Configuration Wizard Media Members Newsletters + Packages Settings Statistics Translation Users - Help - Forms The best Umbraco video tutorials diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml index be33ee853a..8ce9282d71 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml @@ -606,7 +606,7 @@ Hide History Icon - Id + Id Import Info Inner margin @@ -657,7 +657,7 @@ Permissions Scheduled Publishing Search - Sorry, we can not find what you are looking for. + Sorry, we can not find what you are looking for. No items have been added Server Settings @@ -1075,6 +1075,8 @@ To manage your website, simply open the Umbraco back office and start adding con Notifications + Created + Create package button and locating the package. Umbraco packages usually have a ".umb" or ".zip" extension. @@ -1089,8 +1091,12 @@ To manage your website, simply open the Umbraco back office and start adding con I accept terms of use Install package - Finish + Installed Installed packages + Install local + Finish + This package has no configuration view + No packages have been created yet You don’t have any packages installed 'Packages' icon in the top right of your screen]]> Search for packages @@ -1239,13 +1245,13 @@ To manage your website, simply open the Umbraco back office and start adding con Content - Packages + Forms Media Members + Packages Settings Translation Users - Forms The best Umbraco video tutorials
    LanguageLanguage ISODefaultMandatoryDefaultMandatory Fallback
    {{ language.name }} @@ -47,17 +45,15 @@ {{ language.culture }} - + - + @@ -65,14 +61,13 @@ (none) - +