diff --git a/src/Umbraco.Core/ApplicationEventHandler.cs b/src/Umbraco.Core/ApplicationEventHandler.cs
deleted file mode 100644
index 47035f80dd..0000000000
--- a/src/Umbraco.Core/ApplicationEventHandler.cs
+++ /dev/null
@@ -1,159 +0,0 @@
-using System;
-using System.Linq;
-using LightInject;
-using Umbraco.Core.Components;
-using Umbraco.Core.DependencyInjection;
-using Umbraco.Core.Plugins;
-using Umbraco.Core.Services;
-
-namespace Umbraco.Core
-{
- ///
- /// A plugin type that allows developers to execute code during the Umbraco bootup process
- ///
- ///
- /// Allows you to override the methods that you would like to execute code for: ApplicationInitialized, ApplicationStarting, ApplicationStarted.
- ///
- /// By default none of these methods will execute if the Umbraco application is not configured or if the Umbraco database is not configured, however
- /// if you need these methods to execute even if either of these are not configured you can override the properties:
- /// ExecuteWhenApplicationNotConfigured and ExecuteWhenDatabaseNotConfigured
- ///
- // fixme - kill.kill.kill
- public abstract class ApplicationEventHandler : IApplicationEventHandler
- {
- public void OnApplicationInitialized(UmbracoApplicationBase umbracoApplication)
- {
- if (ShouldExecute()) ApplicationInitialized(umbracoApplication);
- }
-
- public void OnApplicationStarting(UmbracoApplicationBase umbracoApplication)
- {
- if (ShouldExecute()) ApplicationStarting(umbracoApplication);
- }
-
- public void OnApplicationStarted(UmbracoApplicationBase umbracoApplication)
- {
- if (ShouldExecute()) ApplicationStarted(umbracoApplication);
- }
-
- ///
- /// Overridable method to execute when the ApplicationContext is created and other static objects that require initialization have been setup
- ///
- ///
- protected virtual void ApplicationInitialized(UmbracoApplicationBase umbracoApplication)
- { }
-
- ///
- /// Overridable method to execute when All resolvers have been initialized but resolution is not frozen so they can be modified in this method
- ///
- ///
- protected virtual void ApplicationStarting(UmbracoApplicationBase umbracoApplication)
- { }
-
- ///
- /// Overridable method to execute when Bootup is completed, this allows you to perform any other bootup logic required for the application.
- /// Resolution is frozen so now they can be used to resolve instances.
- ///
- ///
- protected virtual void ApplicationStarted(UmbracoApplicationBase umbracoApplication)
- { }
-
- private bool ShouldExecute()
- {
- var level = Current.RuntimeState.Level;
-
- switch (Current.RuntimeState.Level)
- {
- case RuntimeLevel.Unknown:
- case RuntimeLevel.Failed:
- case RuntimeLevel.Boot:
- return false;
- case RuntimeLevel.Install:
- case RuntimeLevel.Upgrade:
- // sort-of equivalent I assume?
- //if (!applicationContext.IsConfigured && ExecuteWhenApplicationNotConfigured)
- if (ExecuteWhenApplicationNotConfigured)
- return true;
- //if (!applicationContext.DatabaseContext.IsDatabaseConfigured && ExecuteWhenDatabaseNotConfigured)
- if (level == RuntimeLevel.Install && ExecuteWhenDatabaseNotConfigured)
- return true;
- return false;
- case RuntimeLevel.Run:
- //if (applicationContext.IsConfigured && applicationContext.DatabaseContext.IsDatabaseConfigured)
- return true;
- default:
- throw new NotSupportedException($"Invalid runtime level {level}");
- }
- }
-
- ///
- /// A flag to determine if the overridable methods for this class will execute even if the
- /// Umbraco application is not configured
- ///
- ///
- /// An Umbraco Application is not configured when it requires a new install or upgrade. When the latest version in the
- /// assembly does not match the version in the config.
- ///
- protected virtual bool ExecuteWhenApplicationNotConfigured => false;
-
- ///
- /// A flag to determine if the overridable methods for this class will execute even if the
- /// Umbraco database is not configured
- ///
- ///
- /// The Umbraco database is not configured when we cannot connect to the database or when the database tables are not installed.
- ///
- protected virtual bool ExecuteWhenDatabaseNotConfigured => false;
- }
-
- // that *could* replace CoreRuntime mess almost entirely
- // but what about what's in WebRuntime?
-
- [DisableComponent] // disabled for now, breaks
- public class ApplicationEventHandlerComponent : UmbracoComponentBase, IUmbracoCoreComponent
- {
- public override void Compose(ServiceContainer container)
- {
- base.Compose(container);
-
- // assuming we don't do anything in Compose? or is this where we should create the handlers?
- }
-
- public void Initialize(PluginManager pluginManager, UmbracoApplicationBase umbracoApplication)
- {
- var startupHandlerTypes = pluginManager.ResolveApplicationStartupHandlers();
- var handlers = startupHandlerTypes.Select(x =>
- {
- try
- {
- return Activator.CreateInstance(x);
- }
- catch
- {
- // fixme - breaks here!
- // cannot unstanciate GridPropertyEditor and other oddities BUT they have been refactored in 7.6?
- // well, no, so NOW is the time... bah... first we need to figure out STATES
- throw new Exception("cannot instanciate " + x.FullName);
- }
- }).Cast().ToArray();
-
- // just a test at that point
- return;
-
- foreach (var handler in handlers)
- handler.OnApplicationInitialized(umbracoApplication);
- foreach (var handler in handlers)
- handler.OnApplicationStarting(umbracoApplication);
-
- //This is a special case for the user service, we need to tell it if it's an upgrade, if so we need to ensure that
- // exceptions are bubbled up if a user is attempted to be persisted during an upgrade (i.e. when they auth to login)
- // fixme - wtf? never going back to FALSE !
- ((UserService) Current.Services.UserService).IsUpgrading = true;
-
- foreach (var handler in handlers)
- handler.OnApplicationStarted(umbracoApplication);
-
- //applicationContext.IsReady = true;
- }
- }
-}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Components/BootLoader.cs b/src/Umbraco.Core/Components/BootLoader.cs
index f40ea424dd..0840449789 100644
--- a/src/Umbraco.Core/Components/BootLoader.cs
+++ b/src/Umbraco.Core/Components/BootLoader.cs
@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using LightInject;
-using Umbraco.Core.Configuration;
using Umbraco.Core.Exceptions;
using Umbraco.Core.Logging;
@@ -225,7 +224,7 @@ namespace Umbraco.Core.Components
{
if (_booted == false) throw new InvalidOperationException("Cannot terminate, has not booted.");
- using (_proflog.DebugDuration($"Terminating Umbraco. (log components when >{LogThresholdMilliseconds}ms)", "Terminated Umbraco."))
+ using (_proflog.DebugDuration($"Terminating. (log components when >{LogThresholdMilliseconds}ms)", "Terminated."))
{
foreach (var component in _components)
{
diff --git a/src/Umbraco.Core/CoreRuntime.cs b/src/Umbraco.Core/CoreRuntime.cs
index f5db9f8cbe..45f72e50df 100644
--- a/src/Umbraco.Core/CoreRuntime.cs
+++ b/src/Umbraco.Core/CoreRuntime.cs
@@ -1,9 +1,9 @@
using System;
using System.Collections.Generic;
using System.Configuration;
-using System.Threading.Tasks;
using System.Threading;
using LightInject;
+using Semver;
using Umbraco.Core.Cache;
using Umbraco.Core.Components;
using Umbraco.Core.Configuration;
@@ -38,16 +38,23 @@ namespace Umbraco.Core
public CoreRuntime(UmbracoApplicationBase umbracoApplication)
{
if (umbracoApplication == null) throw new ArgumentNullException(nameof(umbracoApplication));
- UmbracoApplication = umbracoApplication;
}
///
public virtual void Boot(ServiceContainer container)
{
+ // some components may want to initialize with the UmbracoApplicationBase
+ // well, they should not - let's not do this
+ //container.RegisterInstance(_app);
+
Compose(container);
// prepare essential stuff
+ var path = GetApplicationRootPath();
+ if (string.IsNullOrWhiteSpace(path) == false)
+ IOHelper.SetRootDirectory(path);
+
_state = (RuntimeState) container.GetInstance();
_state.Level = RuntimeLevel.Boot;
@@ -55,9 +62,6 @@ namespace Umbraco.Core
Profiler = container.GetInstance();
ProfilingLogger = container.GetInstance();
- // fixme - totally temp
- container.RegisterInstance(UmbracoApplication);
-
// 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.
// note that this REQUIRES that perWebRequestScope has NOT been enabled yet, else
@@ -95,13 +99,26 @@ namespace Umbraco.Core
// boot
_bootLoader = new BootLoader(container);
_bootLoader.Boot(componentTypes, _state.Level);
+
+ // this was done in Complete() right before running the Started event handlers
+ // "special case for the user service, we need to tell it if it's an upgrade, if so we need to ensure that
+ // exceptions are bubbled up if a user is attempted to be persisted during an upgrade (i.e. when they auth to login)"
+ //
+ // was *always* setting the value to true which is?! so using the runtime level
+ // and then, it is *never* resetted to false, meaning Umbraco has been running with IsUpgrading being true?
+ // fixme - this is... bad
+ ((UserService) Current.Services.UserService).IsUpgrading = _state.Level == RuntimeLevel.Upgrade;
+
}
}
///
public virtual void Terminate()
{
- _bootLoader?.Terminate();
+ using (ProfilingLogger.DebugDuration("Terminating Umbraco.", "Terminated."))
+ {
+ _bootLoader?.Terminate();
+ }
}
///
@@ -150,12 +167,15 @@ namespace Umbraco.Core
container.RegisterSingleton();
}
- private static void SetRuntimeStateLevel(RuntimeState runtimeState, IDatabaseFactory databaseFactory, ILogger logger)
+ private void SetRuntimeStateLevel(RuntimeState runtimeState, IDatabaseFactory databaseFactory, ILogger logger)
{
var localVersion = LocalVersion; // the local, files, version
var codeVersion = runtimeState.SemanticVersion; // the executing code version
var connect = false;
+ // we don't know yet
+ runtimeState.Level = RuntimeLevel.Unknown;
+
if (string.IsNullOrWhiteSpace(localVersion))
{
// there is no local version, we are not installed
@@ -177,47 +197,44 @@ namespace Umbraco.Core
runtimeState.Level = RuntimeLevel.Install;
}
+ // install? not going to test anything else
+ if (runtimeState.Level == RuntimeLevel.Install)
+ return;
+
+ // else, keep going,
// anything other than install wants a database - see if we can connect
- if (runtimeState.Level != RuntimeLevel.Install)
+ for (var i = 0; i < 5; i++)
{
- for (var i = 0; i < 5; i++)
- {
- connect = databaseFactory.CanConnect;
- if (connect) break;
- logger.Debug(i == 0
- ? "Could not immediately connect to database, trying again."
- : "Could not connect to database.");
- Thread.Sleep(1000);
- }
-
- if (connect == false)
- {
- // cannot connect to configured database, this is bad, fail
- logger.Debug("Could not connect to database.");
- runtimeState.Level = RuntimeLevel.Failed;
-
- // 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.");
- }
+ connect = databaseFactory.CanConnect;
+ if (connect) break;
+ logger.Debug(i == 0
+ ? "Could not immediately connect to database, trying again."
+ : "Could not connect to database.");
+ Thread.Sleep(1000);
}
- // if we cannot connect, cannot do more
- if (connect == false) return;
+ if (connect == false)
+ {
+ // cannot connect to configured database, this is bad, fail
+ logger.Debug("Could not connect to database.");
+ runtimeState.Level = RuntimeLevel.Failed;
+
+ // 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.");
+ }
+
+ // if we already know we want to upgrade, no need to look for migrations...
+ if (runtimeState.Level == RuntimeLevel.Upgrade)
+ return;
// 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!
// fixme - eventually move to yol-style guid-based transitions
- var database = databaseFactory.GetDatabase();
- var codeVersionString = codeVersion.ToString();
- var sql = database.Sql()
- .Select()
- .From()
- .Where(x => x.Name.InvariantEquals(GlobalSettings.UmbracoMigrationName) && x.Version == codeVersionString);
bool exists;
try
{
- exists = database.FirstOrDefault(sql) != null;
+ exists = EnsureMigration(databaseFactory, codeVersion);
}
catch
{
@@ -243,6 +260,17 @@ namespace Umbraco.Core
runtimeState.Level = RuntimeLevel.Upgrade;
}
+ protected virtual bool EnsureMigration(IDatabaseFactory databaseFactory, SemVersion codeVersion)
+ {
+ var database = databaseFactory.GetDatabase();
+ var codeVersionString = codeVersion.ToString();
+ var sql = database.Sql()
+ .Select()
+ .From()
+ .Where(x => x.Name.InvariantEquals(GlobalSettings.UmbracoMigrationName) && x.Version == codeVersionString);
+ return database.FirstOrDefault(sql) != null;
+ }
+
private static string LocalVersion
{
get
@@ -261,8 +289,6 @@ namespace Umbraco.Core
#region Locals
- // fixme - we almost certainly DONT need these!
-
protected ILogger Logger { get; private set; }
protected IProfiler Profiler { get; private set; }
@@ -277,178 +303,10 @@ namespace Umbraco.Core
protected virtual IEnumerable GetComponentTypes() => Current.PluginManager.ResolveTypes();
- //protected virtual IProfiler GetProfiler() => new LogProfiler(Logger);
-
- //protected virtual 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 ObjectCacheRuntimeCacheProvider()),
- // new StaticCacheProvider(),
- // // we have no request based cache when not running in web-based context
- // new NullCacheProvider(),
- // 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())));
+ // 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;
#endregion
-
- // fixme - kill everything below!
-
- private IServiceContainer _appStartupEvtContainer;
- private bool _isInitialized;
- private bool _isStarted;
- private bool _isComplete;
-
- protected UmbracoApplicationBase UmbracoApplication { get; }
-
- protected ServiceContainer Container => Current.Container;
-
- ///
- /// Special method to extend the use of Umbraco by enabling the consumer to overwrite
- /// the absolute path to the root of an Umbraco site/solution, which is used for stuff
- /// like Umbraco.Core.IO.IOHelper.MapPath etc.
- ///
- /// Absolute Umbraco root path.
- protected virtual void InitializeApplicationRootPath(string rootPath)
- {
- IOHelper.SetRootDirectory(rootPath);
- }
-
- public virtual IRuntime Initialize()
- {
- if (_isInitialized)
- throw new InvalidOperationException("The boot manager has already been initialized");
-
- //now we need to call the initialize methods
- //Create a 'child'container which is a copy of all of the current registrations and begin a sub scope for it
- // this child container will be used to manage the application event handler instances and the scope will be
- // completed at the end of the boot process to allow garbage collection
- // using (Container.BeginScope()) { } // fixme - throws
- _appStartupEvtContainer = Container.Clone(); // fixme - but WHY clone? because *then* it has its own scope?! bah ;-(
- _appStartupEvtContainer.BeginScope();
- _appStartupEvtContainer.RegisterCollection(factory => factory.GetInstance().ResolveApplicationStartupHandlers());
-
- // fixme - parallel? what about our dependencies?
- Parallel.ForEach(_appStartupEvtContainer.GetAllInstances(), x =>
- {
- try
- {
- using (ProfilingLogger.DebugDuration(
- $"Executing {x.GetType()} in ApplicationInitialized",
- $"Executed {x.GetType()} in ApplicationInitialized",
- //only log if more than 150ms
- 150))
- {
- x.OnApplicationInitialized(UmbracoApplication);
- }
- }
- catch (Exception ex)
- {
- ProfilingLogger.Logger.Error("An error occurred running OnApplicationInitialized for handler " + x.GetType(), ex);
- throw;
- }
- });
-
- _isInitialized = true;
-
- return this;
- }
-
-
- ///
- /// Fires after initialization and calls the callback to allow for customizations to occur &
- /// Ensure that the OnApplicationStarting methods of the IApplicationEvents are called
- ///
- ///
- ///
- public virtual IRuntime Startup(Action afterStartup)
- {
- if (_isStarted)
- throw new InvalidOperationException("The boot manager has already been initialized");
-
- //call OnApplicationStarting of each application events handler
- Parallel.ForEach(_appStartupEvtContainer.GetAllInstances(), x =>
- {
- try
- {
- using (ProfilingLogger.DebugDuration(
- $"Executing {x.GetType()} in ApplicationStarting",
- $"Executed {x.GetType()} in ApplicationStarting",
- //only log if more than 150ms
- 150))
- {
- x.OnApplicationStarting(UmbracoApplication);
- }
- }
- catch (Exception ex)
- {
- ProfilingLogger.Logger.Error("An error occurred running OnApplicationStarting for handler " + x.GetType(), ex);
- throw;
- }
- });
-
- if (afterStartup != null)
- {
- afterStartup();
- }
-
- _isStarted = true;
-
- return this;
- }
-
- ///
- /// Fires after startup and calls the callback once customizations are locked
- ///
- ///
- ///
- public virtual IRuntime Complete(Action afterComplete)
- {
- if (_isComplete)
- throw new InvalidOperationException("The boot manager has already been completed");
-
- //This is a special case for the user service, we need to tell it if it's an upgrade, if so we need to ensure that
- // exceptions are bubbled up if a user is attempted to be persisted during an upgrade (i.e. when they auth to login)
- // fixme - wtf? never going back to FALSE !
- ((UserService) Current.Services.UserService).IsUpgrading = true;
-
- //call OnApplicationStarting of each application events handler
- Parallel.ForEach(_appStartupEvtContainer.GetAllInstances(), x =>
- {
- try
- {
- using (ProfilingLogger.DebugDuration(
- $"Executing {x.GetType()} in ApplicationStarted",
- $"Executed {x.GetType()} in ApplicationStarted",
- //only log if more than 150ms
- 150))
- {
- x.OnApplicationStarted(UmbracoApplication);
- }
- }
- catch (Exception ex)
- {
- ProfilingLogger.Logger.Error("An error occurred running OnApplicationStarted for handler " + x.GetType(), ex);
- throw;
- }
- });
-
- //end the current scope which was created to intantiate all of the startup handlers,
- //this will dispose them if they're IDisposable
- _appStartupEvtContainer.EndCurrentScope();
- //NOTE: DO NOT Dispose this cloned container since it will also dispose of any instances
- // resolved from the parent container
- _appStartupEvtContainer = null;
-
- if (afterComplete != null)
- {
- afterComplete();
- }
-
- _isComplete = true;
-
- return this;
- }
}
}
diff --git a/src/Umbraco.Core/CoreRuntimeComponent.cs b/src/Umbraco.Core/CoreRuntimeComponent.cs
index 2927a6e23e..9101620356 100644
--- a/src/Umbraco.Core/CoreRuntimeComponent.cs
+++ b/src/Umbraco.Core/CoreRuntimeComponent.cs
@@ -1,11 +1,6 @@
using System;
using System.Collections.Generic;
-using System.Configuration;
using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
using AutoMapper;
using LightInject;
using Umbraco.Core.Cache;
@@ -13,7 +8,6 @@ using Umbraco.Core.Components;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.DependencyInjection;
-using Umbraco.Core.Exceptions;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Manifest;
@@ -136,6 +130,14 @@ namespace Umbraco.Core
foreach (var m in modelMapperConfigurations)
m.ConfigureMappings(configuration);
});
+
+ // 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/IApplicationEventHandler.cs b/src/Umbraco.Core/IApplicationEventHandler.cs
deleted file mode 100644
index 1421af63ea..0000000000
--- a/src/Umbraco.Core/IApplicationEventHandler.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-namespace Umbraco.Core
-{
- ///
- /// Custom IApplicationStartupHandler that auto subscribes to the applications events
- ///
- public interface IApplicationEventHandler
- {
- ///
- /// ApplicationContext is created and other static objects that require initialization have been setup
- ///
- ///
- void OnApplicationInitialized(UmbracoApplicationBase umbracoApplication);
-
- ///
- /// All resolvers have been initialized but resolution is not frozen so they can be modified in this method
- ///
- ///
- void OnApplicationStarting(UmbracoApplicationBase umbracoApplication);
-
- ///
- /// Bootup is completed, this allows you to perform any other bootup logic required for the application.
- /// Resolution is frozen so now they can be used to resolve instances.
- ///
- ///
- void OnApplicationStarted(UmbracoApplicationBase umbracoApplication);
- }
-}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Logging/WebProfiler.cs b/src/Umbraco.Core/Logging/WebProfiler.cs
index 6b5d98e46c..8f0c52a8ba 100644
--- a/src/Umbraco.Core/Logging/WebProfiler.cs
+++ b/src/Umbraco.Core/Logging/WebProfiler.cs
@@ -2,94 +2,37 @@
using System.Web;
using StackExchange.Profiling;
using StackExchange.Profiling.SqlFormatters;
-using Umbraco.Core.Configuration;
namespace Umbraco.Core.Logging
{
///
- /// A profiler used for web based activity based on the MiniProfiler framework
+ /// A profiler used for web based activity based on the MiniProfiler framework.
///
- internal class WebProfiler : ApplicationEventHandler, IProfiler
+ internal class WebProfiler : IProfiler
{
- ///
- ///Binds to application events to enable the MiniProfiler
- ///
- ///
- protected override void ApplicationInitialized(UmbracoApplicationBase umbracoApplication)
+ private readonly IRuntimeState _runtime;
+
+ public WebProfiler(IRuntimeState runtime)
{
- UmbracoApplicationBase.ApplicationInit += UmbracoApplicationApplicationInit;
+ _runtime = runtime;
}
-
- ///
- /// Handle the Init event o fthe UmbracoApplication which allows us to subscribe to the HttpApplication events
- ///
- ///
- ///
- void UmbracoApplicationApplicationInit(object sender, EventArgs e)
- {
- var app = sender as HttpApplication;
- if (app == null) return;
-
- if (SystemUtilities.GetCurrentTrustLevel() < AspNetHostingPermissionLevel.High)
- {
- //If we don't have a high enough trust level we cannot bind to the events
- LogHelper.Info("Cannot start the WebProfiler since the application is running in Medium trust");
- }
- else
- {
- app.BeginRequest += UmbracoApplicationBeginRequest;
- app.EndRequest += UmbracoApplicationEndRequest;
- }
- }
-
- ///
- /// Handle the begin request event
- ///
- ///
- ///
- void UmbracoApplicationEndRequest(object sender, EventArgs e)
+ public void UmbracoApplicationEndRequest(object sender, EventArgs e)
{
if (CanPerformProfilingAction(sender))
- {
Stop();
- }
}
- ///
- /// Handle the end request event
- ///
- ///
- ///
- void UmbracoApplicationBeginRequest(object sender, EventArgs e)
+ public void UmbracoApplicationBeginRequest(object sender, EventArgs e)
{
if (CanPerformProfilingAction(sender))
- {
Start();
- }
}
- private bool CanPerformProfilingAction(object sender)
+ private static bool CanPerformProfilingAction(object sender)
{
- if (GlobalSettings.DebugMode == false)
- return false;
-
- //will not run in medium trust
- if (SystemUtilities.GetCurrentTrustLevel() < AspNetHostingPermissionLevel.High)
- return false;
-
var request = TryGetRequest(sender);
-
- if (request.Success == false || request.Result.Url.IsClientSideRequest())
- return false;
-
- if (string.IsNullOrEmpty(request.Result.QueryString["umbDebug"]))
- return true;
-
- if (request.Result.Url.IsBackOfficeRequest(HttpRuntime.AppDomainAppVirtualPath))
- return true;
-
- return true;
+ return request.Success && request.Result.Url.IsClientSideRequest() == false;
}
///
@@ -114,7 +57,7 @@ namespace Umbraco.Core.Logging
///
public IDisposable Step(string name)
{
- return GlobalSettings.DebugMode == false ? null : MiniProfiler.Current.Step(name);
+ return _runtime.Debug ? MiniProfiler.Current.Step(name) : null;
}
///
@@ -144,7 +87,7 @@ namespace Umbraco.Core.Logging
///
/// The application object
///
- private Attempt TryGetRequest(object sender)
+ private static Attempt TryGetRequest(object sender)
{
var app = sender as HttpApplication;
if (app == null) return Attempt.Fail();
diff --git a/src/Umbraco.Core/Logging/WebProfilerComponent.cs b/src/Umbraco.Core/Logging/WebProfilerComponent.cs
new file mode 100644
index 0000000000..2f92e181c3
--- /dev/null
+++ b/src/Umbraco.Core/Logging/WebProfilerComponent.cs
@@ -0,0 +1,55 @@
+using System;
+using System.Web;
+using Umbraco.Core.Components;
+
+namespace Umbraco.Core.Logging
+{
+ internal class WebProfilerComponent : UmbracoComponentBase, IUmbracoCoreComponent
+ {
+ // the profiler is too important to be composed in a component,
+ // it is composed first thing in WebRuntime.Compose - this component
+ // only initializes it if needed.
+ //
+ //public override void Compose(ServiceContainer container)
+ //{
+ // container.RegisterSingleton();
+ //}
+
+ private WebProfiler _profiler;
+
+ public void Initialize(IProfiler profiler, IRuntimeState runtime)
+ {
+ // although registered in WebRuntime.Compose, ensure that we have
+ // not been replaced by another component, and we are still "the" profiler
+ _profiler = profiler as WebProfiler;
+ if (_profiler == null) return;
+
+ if (SystemUtilities.GetCurrentTrustLevel() < AspNetHostingPermissionLevel.High)
+ {
+ // if we don't have a high enough trust level we cannot bind to the events
+ LogHelper.Info("Cannot install when the application is running in Medium trust.");
+ }
+ else if (runtime.Debug == false)
+ {
+ // only when debugging
+ LogHelper.Info("Cannot install when the application is not running in debug mode.");
+ }
+ else
+ {
+ // bind to ApplicationInit - ie execute the application initialization for *each* application
+ // it would be a mistake to try and bind to the current application events
+ UmbracoApplicationBase.ApplicationInit += InitializeApplication;
+ }
+ }
+
+ private void InitializeApplication(object sender, EventArgs args)
+ {
+ var app = sender as HttpApplication;
+ if (app == null) return;
+
+ // for *each* application (this will run more than once)
+ app.BeginRequest += (s, a) => _profiler.UmbracoApplicationBeginRequest(s, a);
+ app.EndRequest += (s, a) => _profiler.UmbracoApplicationEndRequest(s, a);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Plugins/HideFromTypeFinderAttribute.cs b/src/Umbraco.Core/Plugins/HideFromTypeFinderAttribute.cs
index 1568bc2995..6654123d6c 100644
--- a/src/Umbraco.Core/Plugins/HideFromTypeFinderAttribute.cs
+++ b/src/Umbraco.Core/Plugins/HideFromTypeFinderAttribute.cs
@@ -3,11 +3,9 @@ using System;
namespace Umbraco.Core.Plugins
{
///
- /// Used to notify the TypeFinder to ignore any class attributed with this during it's discovery
+ /// Notifies the TypeFinder that it should ignore the class marked with this attribute.
///
[AttributeUsage(AttributeTargets.Class)]
public sealed class HideFromTypeFinderAttribute : Attribute
- {
-
- }
+ { }
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Plugins/PluginManager.cs b/src/Umbraco.Core/Plugins/PluginManager.cs
index 9d37874598..331508eeae 100644
--- a/src/Umbraco.Core/Plugins/PluginManager.cs
+++ b/src/Umbraco.Core/Plugins/PluginManager.cs
@@ -680,14 +680,6 @@ namespace Umbraco.Core.Plugins
.Except(new[] { typeof(ParameterEditor), typeof(PropertyEditor) });
}
- ///
- /// Resolves IApplicationStartupHandler objects.
- ///
- internal static IEnumerable ResolveApplicationStartupHandlers(this PluginManager mgr)
- {
- return mgr.ResolveTypes();
- }
-
///
/// Resolves ICacheRefresher objects.
///
diff --git a/src/Umbraco.Web/ManifestWatcherComponent.cs b/src/Umbraco.Core/Strategies/ManifestWatcherComponent.cs
similarity index 81%
rename from src/Umbraco.Web/ManifestWatcherComponent.cs
rename to src/Umbraco.Core/Strategies/ManifestWatcherComponent.cs
index 7bf9c27aab..40b77eb700 100644
--- a/src/Umbraco.Web/ManifestWatcherComponent.cs
+++ b/src/Umbraco.Core/Strategies/ManifestWatcherComponent.cs
@@ -1,10 +1,10 @@
using System.IO;
-using Umbraco.Core;
using Umbraco.Core.Components;
+using Umbraco.Core.DependencyInjection;
using Umbraco.Core.IO;
using Umbraco.Core.Manifest;
-namespace Umbraco.Web
+namespace Umbraco.Core.Strategies
{
public class ManifestWatcherComponent : UmbracoComponentBase, IUmbracoCoreComponent
{
@@ -14,8 +14,6 @@ namespace Umbraco.Web
public void Initialize(IRuntimeState runtime)
{
- // BUT how can we tell that runtime is "ready enough"? need to depend on some sort of UmbracoRuntimeComponent?
- // and... will this kind of dependency issue be repro everywhere?!
if (runtime.Level < RuntimeLevel.Run || runtime.Debug == false) return;
//if (ApplicationContext.Current.IsConfigured == false || GlobalSettings.DebugMode == false)
diff --git a/src/Umbraco.Core/Strategies/ManifestWatcherHandler.cs b/src/Umbraco.Core/Strategies/ManifestWatcherHandler.cs
deleted file mode 100644
index efa9138306..0000000000
--- a/src/Umbraco.Core/Strategies/ManifestWatcherHandler.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-using System;
-using System.IO;
-using Umbraco.Core.DependencyInjection;
-using Umbraco.Core.IO;
-using Umbraco.Core.Manifest;
-
-namespace Umbraco.Core.Strategies
-{
- public sealed class ManifestWatcherHandler : ApplicationEventHandler
- {
- private ManifestWatcher _mw;
-
- protected override void ApplicationInitialized(UmbracoApplicationBase umbracoApplication)
- {
- UmbracoApplicationBase.ApplicationEnd += app_ApplicationEnd;
- }
-
- void app_ApplicationEnd(object sender, EventArgs e)
- {
- if (_mw != null)
- {
- _mw.Dispose();
- }
- }
-
- protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication)
- {
- _mw = new ManifestWatcher(Current.ProfilingLogger.Logger);
- _mw.Start(Directory.GetDirectories(IOHelper.MapPath("~/App_Plugins/")));
- }
- }
-}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Strategies/RelateOnCopyHandler.cs b/src/Umbraco.Core/Strategies/RelateOnCopyComponent.cs
similarity index 90%
rename from src/Umbraco.Core/Strategies/RelateOnCopyHandler.cs
rename to src/Umbraco.Core/Strategies/RelateOnCopyComponent.cs
index b7db0fdf47..aa42131dfc 100644
--- a/src/Umbraco.Core/Strategies/RelateOnCopyHandler.cs
+++ b/src/Umbraco.Core/Strategies/RelateOnCopyComponent.cs
@@ -1,4 +1,5 @@
using System;
+using Umbraco.Core.Components;
using Umbraco.Core.DependencyInjection;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
@@ -6,9 +7,9 @@ using Umbraco.Core.Services;
namespace Umbraco.Core.Strategies
{
//TODO: This should just exist in the content service/repo!
- public sealed class RelateOnCopyHandler : ApplicationEventHandler
+ public sealed class RelateOnCopyComponent : UmbracoComponentBase, IUmbracoCoreComponent
{
- protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication)
+ public void Initialize()
{
ContentService.Copied += ContentServiceCopied;
}
diff --git a/src/Umbraco.Core/Strategies/RelateOnTrashHandler.cs b/src/Umbraco.Core/Strategies/RelateOnTrashComponent.cs
similarity index 94%
rename from src/Umbraco.Core/Strategies/RelateOnTrashHandler.cs
rename to src/Umbraco.Core/Strategies/RelateOnTrashComponent.cs
index f2cfc3ac3b..b55ff98dbb 100644
--- a/src/Umbraco.Core/Strategies/RelateOnTrashHandler.cs
+++ b/src/Umbraco.Core/Strategies/RelateOnTrashComponent.cs
@@ -1,5 +1,6 @@
using System;
using System.Linq;
+using Umbraco.Core.Components;
using Umbraco.Core.DependencyInjection;
using Umbraco.Core.Events;
using Umbraco.Core.Models;
@@ -7,9 +8,9 @@ using Umbraco.Core.Services;
namespace Umbraco.Core.Strategies
{
- public sealed class RelateOnTrashHandler : ApplicationEventHandler
+ public sealed class RelateOnTrashComponent : UmbracoComponentBase, IUmbracoCoreComponent
{
- protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication)
+ public void Initialize()
{
ContentService.Moved += ContentService_Moved;
ContentService.Trashed += ContentService_Trashed;
diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj
index 6528dc95b0..8350275e89 100644
--- a/src/Umbraco.Core/Umbraco.Core.csproj
+++ b/src/Umbraco.Core/Umbraco.Core.csproj
@@ -68,7 +68,6 @@
-
@@ -280,6 +279,7 @@
Files.resx
+
@@ -299,7 +299,6 @@
-
@@ -536,7 +535,7 @@
-
+
@@ -1227,8 +1226,8 @@
-
-
+
+
diff --git a/src/Umbraco.Core/UmbracoApplicationBase.cs b/src/Umbraco.Core/UmbracoApplicationBase.cs
index ffa623c507..3713574896 100644
--- a/src/Umbraco.Core/UmbracoApplicationBase.cs
+++ b/src/Umbraco.Core/UmbracoApplicationBase.cs
@@ -13,10 +13,6 @@ namespace Umbraco.Core
///
/// Provides an abstract base class for the Umbraco HttpApplication.
///
- ///
- /// This is exposed in Core so that we can have the IApplicationEventHandler in the core project so that
- /// IApplicationEventHandler's can fire/execute outside of the web contenxt (i.e. in console applications). fixme wtf?
- ///
public abstract class UmbracoApplicationBase : HttpApplication
{
private IRuntime _runtime;
@@ -34,16 +30,33 @@ namespace Umbraco.Core
return Logger.CreateWithDefaultLog4NetConfiguration();
}
- #region Start
+ // events - in the order they trigger
- // fixme? dont make much sense!
- public event EventHandler ApplicationStarting;
- public event EventHandler ApplicationStarted;
+ // were part of the BootManager architecture, would trigger only for the initial
+ // application, so they need not be static, and they would let ppl hook into the
+ // boot process... but I believe this can be achieved with components as well and
+ // we don't need these events.
+ //public event EventHandler ApplicationStarting;
+ //public event EventHandler ApplicationStarted;
+
+ // this event can only be static since there will be several instances of this class
+ // triggers for each application instance, ie many times per lifetime of the application
+ public static event EventHandler ApplicationInit;
+
+ // this event can only be static since there will be several instances of this class
+ // triggers once per error
+ public static event EventHandler ApplicationError;
+
+ // this event can only be static since there will be several instances of this class
+ // triggers once per lifetime of the application, before it is unloaded
+ public static event EventHandler ApplicationEnd;
+
+ #region Start
// internal for tests
internal void HandleApplicationStart(object sender, EventArgs evargs)
{
- // NOTE: THIS IS WHERE EVERYTHING BEGINS!
+ // ******** THIS IS WHERE EVERYTHING BEGINS ********
// create the container for the application, and configure.
// the boot manager is responsible for registrations
@@ -74,11 +87,6 @@ namespace Umbraco.Core
// get runtime & boot
_runtime = GetRuntime();
_runtime.Boot(container);
-
- // this is extra that should get removed
- ((CoreRuntime)_runtime).Initialize();
- ((CoreRuntime)_runtime).Startup(() => OnApplicationStarting(sender, evargs));
- ((CoreRuntime)_runtime).Complete(() => OnApplicationStarted(sender, evargs));
}
// called by ASP.NET (auto event wireup) once per app domain
@@ -94,20 +102,9 @@ namespace Umbraco.Core
#region Init
- // this event can only be static since there will be several instances of this class
- public static event EventHandler ApplicationInit;
-
private void OnApplicationInit(object sender, EventArgs evargs)
{
- try
- {
- ApplicationInit?.Invoke(sender, evargs);
- }
- catch (Exception ex)
- {
- Current.Logger.Error("Exception in an ApplicationInit event handler.", ex);
- throw;
- }
+ TryInvoke(ApplicationInit, "ApplicationInit", sender, evargs);
}
// called by ASP.NET for every HttpApplication instance after all modules have been created
@@ -126,9 +123,6 @@ namespace Umbraco.Core
#region End
- // this event can only be static since there will be several instances of this class
- public static event EventHandler ApplicationEnd;
-
protected virtual void OnApplicationEnd(object sender, EventArgs evargs)
{
ApplicationEnd?.Invoke(this, EventArgs.Empty);
@@ -187,9 +181,6 @@ namespace Umbraco.Core
#region Error
- // this event can only be static since there will be several instances of this class
- public static event EventHandler ApplicationError;
-
protected virtual void OnApplicationError(object sender, EventArgs evargs)
{
ApplicationError?.Invoke(this, EventArgs.Empty);
@@ -214,42 +205,22 @@ namespace Umbraco.Core
}
#endregion
+
+ #region Utilities
-
- ///
- /// Developers can override this method to modify objects on startup
- ///
- ///
- ///
- protected virtual void OnApplicationStarting(object sender, EventArgs evargs)
+ private static void TryInvoke(EventHandler handler, string name, object sender, EventArgs evargs)
{
try
{
- ApplicationStarting?.Invoke(sender, evargs);
+ handler?.Invoke(sender, evargs);
}
catch (Exception ex)
{
- Current.Logger.Error("An error occurred in an ApplicationStarting event handler", ex);
+ Current.Logger.Error($"Error in {name} handler.", ex);
throw;
}
}
- ///
- /// Developers can override this method to do anything they need to do once the application startup routine is completed.
- ///
- ///
- ///
- protected virtual void OnApplicationStarted(object sender, EventArgs evargs)
- {
- try
- {
- ApplicationStarted?.Invoke(sender, evargs);
- }
- catch (Exception ex)
- {
- Current.Logger.Error("An error occurred in an ApplicationStarted event handler", ex);
- throw;
- }
- }
+ #endregion
}
}
diff --git a/src/Umbraco.Tests/Integration/ContentEventsTests.cs b/src/Umbraco.Tests/Integration/ContentEventsTests.cs
index 12b397e783..ca5e789744 100644
--- a/src/Umbraco.Tests/Integration/ContentEventsTests.cs
+++ b/src/Umbraco.Tests/Integration/ContentEventsTests.cs
@@ -29,7 +29,7 @@ namespace Umbraco.Tests.Integration
{
base.Initialize();
- _h1 = new CacheRefresherEventHandler();
+ _h1 = new CacheRefresherComponent();
_h1.AddHandlers();
_events = new List();
@@ -75,7 +75,7 @@ namespace Umbraco.Tests.Integration
ContentCacheRefresher.CacheUpdated -= ContentCacheUpdated;
}
- private CacheRefresherEventHandler _h1;
+ private CacheRefresherComponent _h1;
private IList _events;
private int _msgCount;
private IContentType _contentType;
diff --git a/src/Umbraco.Tests/Migrations/Upgrades/SqlCeDataUpgradeTest.cs b/src/Umbraco.Tests/Migrations/Upgrades/SqlCeDataUpgradeTest.cs
index 406f263d62..d2271630cf 100644
--- a/src/Umbraco.Tests/Migrations/Upgrades/SqlCeDataUpgradeTest.cs
+++ b/src/Umbraco.Tests/Migrations/Upgrades/SqlCeDataUpgradeTest.cs
@@ -1,5 +1,4 @@
-using System;
-using System.Data.Common;
+using System.Data.Common;
using Moq;
using NPoco;
using NUnit.Framework;
@@ -28,6 +27,7 @@ namespace Umbraco.Tests.Migrations.Upgrades
var db = GetConfiguredDatabase();
var fix = new PublishAfterUpgradeToVersionSixth();
+ MigrationRunner.Migrated += fix.Migrated;
//Setup the MigrationRunner
var migrationContext = new MigrationContext(db, Mock.Of());
@@ -46,7 +46,7 @@ namespace Umbraco.Tests.Migrations.Upgrades
bool hasPropertyTypeGroupTable = schemaHelper.TableExist("cmsPropertyTypeGroup");
bool hasAppTreeTable = schemaHelper.TableExist("umbracoAppTree");
- fix.Unsubscribe();
+ MigrationRunner.Migrated -= fix.Migrated;
Assert.That(hasTabTable, Is.False);
Assert.That(hasPropertyTypeGroupTable, Is.True);
diff --git a/src/Umbraco.Tests/NUnitTests.cs b/src/Umbraco.Tests/NUnitTests.cs
new file mode 100644
index 0000000000..2d7b345409
--- /dev/null
+++ b/src/Umbraco.Tests/NUnitTests.cs
@@ -0,0 +1,128 @@
+using NUnit.Framework;
+
+namespace Umbraco.Tests
+{
+ // these 4 test classes validate that our test class pattern *should* be:
+ // - test base classes *not* marked as [TestFixture] but having a virtual SetUp
+ // method marked as [SetUp]
+ // - test classes inheriting from base class, marked as [TestFixture], and
+ // overriding the SetUp method *without* repeating the [SetUp] attribute
+ // - same for TearDown
+ //
+ // ie what InheritsTestClassWithoutAttribute does - and it works
+
+ [TestFixture]
+ public class InheritsTestClassWithAttribute : NUnitTestClassBase
+ {
+ public const int ConstValue = 77;
+
+ protected int Value { get; set; }
+
+ [SetUp]
+ public override void SetUp()
+ {
+ base.SetUp();
+ Value = ConstValue;
+ }
+
+ [Test]
+ public void AssertValues()
+ {
+ Assert.AreEqual(ConstBaseValue, BaseValue);
+ Assert.AreEqual(ConstValue, Value);
+ }
+ }
+
+ [TestFixture]
+ public class InheritsTestClassWithoutAttribute : NUnitTestClassBase
+ {
+ public const int ConstValue = 88;
+
+ protected int Value { get; set; }
+
+ // not needed!
+ public override void SetUp()
+ {
+ base.SetUp();
+ Value = ConstValue;
+ }
+
+ [Test]
+ public void AssertValues()
+ {
+ Assert.AreEqual(ConstBaseValue, BaseValue);
+ Assert.AreEqual(ConstValue, Value);
+ }
+ }
+
+ [TestFixture]
+ public class InheritTestFixtureWithAttribute : NUnitTestFixtureBase
+ {
+ public const int ConstValue = 99;
+
+ protected int Value { get; set; }
+
+ [SetUp]
+ public override void SetUp()
+ {
+ base.SetUp();
+ Value = ConstValue;
+ }
+
+ [Test]
+ public void AssertValues()
+ {
+ Assert.AreEqual(ConstBaseValue, BaseValue);
+ Assert.AreEqual(ConstValue, Value);
+ }
+ }
+
+ [TestFixture]
+ public class InheritTestFixtureWithoutAttribute : NUnitTestFixtureBase
+ {
+ public const int ConstValue = 66;
+
+ protected int Value { get; set; }
+
+ // not needed!
+ public override void SetUp()
+ {
+ base.SetUp();
+ Value = ConstValue;
+ }
+
+ [Test]
+ public void AssertValues()
+ {
+ Assert.AreEqual(ConstBaseValue, BaseValue);
+ Assert.AreEqual(ConstValue, Value);
+ }
+ }
+
+ public class NUnitTestClassBase
+ {
+ public const int ConstBaseValue = 33;
+
+ protected int BaseValue { get; set; }
+
+ [SetUp]
+ public virtual void SetUp()
+ {
+ BaseValue = ConstBaseValue;
+ }
+ }
+
+ [TestFixture]
+ public class NUnitTestFixtureBase
+ {
+ public const int ConstBaseValue = 42;
+
+ protected int BaseValue { get; set; }
+
+ [SetUp]
+ public virtual void SetUp()
+ {
+ BaseValue = ConstBaseValue;
+ }
+ }
+}
diff --git a/src/Umbraco.Tests/Persistence/Migrations/MigrationStartupHandlerTests.cs b/src/Umbraco.Tests/Persistence/Migrations/PostMigrationTests.cs
similarity index 77%
rename from src/Umbraco.Tests/Persistence/Migrations/MigrationStartupHandlerTests.cs
rename to src/Umbraco.Tests/Persistence/Migrations/PostMigrationTests.cs
index 240c93e696..cfe08d304f 100644
--- a/src/Umbraco.Tests/Persistence/Migrations/MigrationStartupHandlerTests.cs
+++ b/src/Umbraco.Tests/Persistence/Migrations/PostMigrationTests.cs
@@ -1,22 +1,10 @@
-using System;
-using System.Collections.Generic;
-using System.Data;
-using System.Data.Common;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Moq;
-using NPoco;
+using Moq;
using NUnit.Framework;
using Semver;
using Umbraco.Core;
-using Umbraco.Core.Cache;
using Umbraco.Core.Events;
using Umbraco.Core.Logging;
-using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Migrations;
-using Umbraco.Core.Persistence.SqlSyntax;
-using Umbraco.Core.Profiling;
using Umbraco.Core.Services;
using Umbraco.Tests.TestHelpers;
using Umbraco.Web.Strategies.Migrations;
@@ -24,7 +12,7 @@ using Umbraco.Web.Strategies.Migrations;
namespace Umbraco.Tests.Persistence.Migrations
{
[TestFixture]
- public class MigrationStartupHandlerTests
+ public class PostMigrationTests
{
[Test]
public void Executes_For_Any_Product_Name_When_Not_Specified()
@@ -33,7 +21,7 @@ namespace Umbraco.Tests.Persistence.Migrations
var changed1 = new Args { CountExecuted = 0 };
var testHandler1 = new TestMigrationHandler(changed1);
- testHandler1.OnApplicationStarting(Mock.Of());
+ MigrationRunner.Migrated += testHandler1.Migrated;
var db = TestObjects.GetUmbracoSqlCeDatabase(logger);
var migrationContext = new MigrationContext(db, logger);
@@ -50,11 +38,11 @@ namespace Umbraco.Tests.Persistence.Migrations
var changed1 = new Args { CountExecuted = 0};
var testHandler1 = new TestMigrationHandler("Test1", changed1);
- testHandler1.OnApplicationStarting(Mock.Of());
+ MigrationRunner.Migrated += testHandler1.Migrated;
var changed2 = new Args { CountExecuted = 0 };
var testHandler2 = new TestMigrationHandler("Test2", changed2);
- testHandler2.OnApplicationStarting(Mock.Of());
+ MigrationRunner.Migrated += testHandler2.Migrated;
var db = TestObjects.GetUmbracoSqlCeDatabase(logger);
var migrationContext = new MigrationContext(db, logger);
@@ -76,7 +64,7 @@ namespace Umbraco.Tests.Persistence.Migrations
public int CountExecuted { get; set; }
}
- public class TestMigrationHandler : MigrationStartupHandler
+ public class TestMigrationHandler : IPostMigration
{
private readonly string _prodName;
private readonly Args _changed;
@@ -98,15 +86,11 @@ namespace Umbraco.Tests.Persistence.Migrations
_changed = changed;
}
- protected override void AfterMigration(MigrationRunner sender, MigrationEventArgs e)
+ public void Migrated(MigrationRunner sender, MigrationEventArgs args)
{
+ if (_prodName.IsNullOrWhiteSpace() == false && args.ProductName != _prodName) return;
_changed.CountExecuted++;
}
-
- public override string[] TargetProductNames
- {
- get { return _prodName.IsNullOrWhiteSpace() ? new string[] {} : new[] {_prodName}; }
- }
}
}
}
diff --git a/src/Umbraco.Tests/Plugins/TypeFinderTests.cs b/src/Umbraco.Tests/Plugins/TypeFinderTests.cs
index d8ce512b46..b44ff14f4c 100644
--- a/src/Umbraco.Tests/Plugins/TypeFinderTests.cs
+++ b/src/Umbraco.Tests/Plugins/TypeFinderTests.cs
@@ -69,26 +69,26 @@ namespace Umbraco.Tests.Plugins
Assert.AreEqual(2, typesFound.Count());
}
- [Test]
- public void Find_Classes_Of_Type()
- {
- var typesFound = TypeFinder.FindClassesOfType(_assemblies);
- var originalTypesFound = TypeFinderOriginal.FindClassesOfType(_assemblies);
+ //[Test]
+ //public void Find_Classes_Of_Type()
+ //{
+ // var typesFound = TypeFinder.FindClassesOfType(_assemblies);
+ // var originalTypesFound = TypeFinderOriginal.FindClassesOfType(_assemblies);
- foreach (var type in typesFound)
- Console.WriteLine(type);
- Console.WriteLine();
- foreach (var type in originalTypesFound)
- Console.WriteLine(type);
+ // foreach (var type in typesFound)
+ // Console.WriteLine(type);
+ // Console.WriteLine();
+ // foreach (var type in originalTypesFound)
+ // Console.WriteLine(type);
- // 6 classes in _assemblies implement IApplicationEventHandler
- Assert.AreEqual(6, typesFound.Count());
+ // // 6 classes in _assemblies implement IApplicationEventHandler
+ // Assert.AreEqual(6, typesFound.Count());
- // however,
- // Umbraco.Core.Profiling.WebProfiler is internal and is not returned by TypeFinderOriginal,
- // that's a known issue of the legacy type finder, so we have to tweak the count here.
- Assert.AreEqual(5, originalTypesFound.Count());
- }
+ // // however,
+ // // Umbraco.Core.Profiling.WebProfiler is internal and is not returned by TypeFinderOriginal,
+ // // that's a known issue of the legacy type finder, so we have to tweak the count here.
+ // Assert.AreEqual(5, originalTypesFound.Count());
+ //}
[Test]
public void Find_Classes_With_Attribute()
diff --git a/src/Umbraco.Tests/Plugins/TypeHelperTests.cs b/src/Umbraco.Tests/Plugins/TypeHelperTests.cs
index 93889555f4..9b2b1f03db 100644
--- a/src/Umbraco.Tests/Plugins/TypeHelperTests.cs
+++ b/src/Umbraco.Tests/Plugins/TypeHelperTests.cs
@@ -76,11 +76,11 @@ namespace Umbraco.Tests.Plugins
Assert.IsTrue(t5.Success);
Assert.AreEqual(typeof(PropertyAliasDto), t5.Result);
- var t6 = TypeHelper.GetLowestBaseType(typeof (IApplicationEventHandler),
- typeof (SchedulerComponent),
- typeof(CacheRefresherEventHandler));
- Assert.IsTrue(t6.Success);
- Assert.AreEqual(typeof(IApplicationEventHandler), t6.Result);
+ //var t6 = TypeHelper.GetLowestBaseType(typeof (IApplicationEventHandler),
+ // typeof (SchedulerComponent),
+ // typeof(CacheRefresherComponent));
+ //Assert.IsTrue(t6.Success);
+ //Assert.AreEqual(typeof(IApplicationEventHandler), t6.Result);
}
diff --git a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs
index 4128b4bd71..641e577a7e 100644
--- a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs
+++ b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using LightInject;
using Moq;
using NUnit.Framework;
+using Semver;
using Umbraco.Core;
using Umbraco.Core.Components;
using Umbraco.Core.Configuration.UmbracoSettings;
@@ -18,70 +19,140 @@ namespace Umbraco.Tests.Runtimes
[TestFixture]
public class CoreRuntimeTests : BaseUmbracoConfigurationTest
{
+ public override void Initialize() // fixme SetUp!
+ {
+ base.Initialize();
+ TestComponent.Reset();
+ }
+
[TearDown] // fixme TearDown is INHERITED
public override void TearDown()
{
base.TearDown();
-
- TestApplicationEventHandler.Reset();
-
+ TestComponent.Reset();
Current.Reset();
}
+ [Test]
+ public void ComponentLifeCycle()
+ {
+ using (var app = new TestUmbracoApplication())
+ {
+ app.HandleApplicationStart(app, new EventArgs());
+
+ 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);
+
+ // note: components are NOT disposed after boot
+
+ Assert.IsFalse(TestComponent.Terminated);
+
+ app.HandleApplicationEnd();
+ Assert.IsTrue(TestComponent.Terminated);
+ }
+ }
+
// test application
public class TestUmbracoApplication : UmbracoApplicationBase
{
- private readonly ILogger _logger = Mock.Of();
-
protected override IRuntime GetRuntime()
{
- return new TestRuntime(this, new ProfilingLogger(_logger, Mock.Of()));
+ return new TestRuntime(this);
}
+ // the application's logger is created by the application
+ // through GetLogger, that custom application can override
protected override ILogger GetLogger()
{
- return _logger;
+ //return Mock.Of();
+ return new DebugDiagnosticsLogger();
}
}
- // test runtime - inheriting from core runtime
+ // test runtime
public class TestRuntime : CoreRuntime
{
- private readonly ProfilingLogger _proflog;
-
- public TestRuntime(UmbracoApplicationBase umbracoApplication, ProfilingLogger proflog)
+ public TestRuntime(UmbracoApplicationBase umbracoApplication)
: base(umbracoApplication)
+ { }
+
+ public override void Compose(ServiceContainer container)
{
- _proflog = proflog;
+ base.Compose(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()); // fixme painful, is it... singleton? or what?
+ //container.RegisterKnownService(_ => GetDatabaseFactory()); // fixme - would pick the correct LifeTime!
}
+ // must override the database factory
+ // else BootFailedException because U cannot connect to the configured db
+ private static IDatabaseFactory GetDatabaseFactory()
+ {
+ var mock = new Mock();
+ mock.Setup(x => x.Configured).Returns(true);
+ mock.Setup(x => x.CanConnect).Returns(true);
+ return mock.Object;
+ }
+
+ // pretend we have the proper migration
+ // else BootFailedException because our mock IDatabaseFactory does not provide databases
+ protected override bool EnsureMigration(IDatabaseFactory databaseFactory, SemVersion codeVersion)
+ {
+ return true;
+ }
+
+ private MainDom _mainDom;
+
public override void Boot(ServiceContainer container)
{
- // do it before anything else - this is the only place where it's possible
- container.RegisterInstance(_proflog.Logger);
- container.RegisterInstance(_proflog.Profiler);
- container.RegisterInstance(_proflog);
-
base.Boot(container);
+ _mainDom = container.GetInstance();
}
+ public override void Terminate()
+ {
+ _mainDom.Stop(false);
+ base.Terminate();
+ }
+
+ // runs with only one single component
+ // UmbracoCoreComponent will be force-added too
+ // and that's it
protected override IEnumerable GetComponentTypes()
{
return new[] { typeof(TestComponent) };
}
}
+
public class TestComponent : UmbracoComponentBase
{
- // test
+ // test flags
public static bool Ctored;
public static bool Composed;
public static bool Initialized1;
public static bool Initialized2;
public static bool Terminated;
+ public static ProfilingLogger ProfilingLogger;
+
+ public static void Reset()
+ {
+ Ctored = Composed = Initialized1 = Initialized2 = Terminated = false;
+ ProfilingLogger = null;
+ }
public TestComponent()
- : base()
{
Ctored = true;
}
@@ -90,10 +161,10 @@ namespace Umbraco.Tests.Runtimes
{
base.Compose(container);
- container.Register(factory => SettingsForTests.GetDefault());
- container.Register(factory => new DatabaseContext(
+ container.Register(factory => SettingsForTests.GetDefault());
+ container.Register(factory => new DatabaseContext(
factory.GetInstance(),
- factory.GetInstance(), Mock.Of(), Mock.Of()), new PerContainerLifetime());
+ factory.GetInstance(), factory.GetInstance(), Mock.Of()), new PerContainerLifetime());
container.RegisterSingleton();
Composed = true;
@@ -109,121 +180,16 @@ namespace Umbraco.Tests.Runtimes
Initialized2 = true;
}
+ public void Initialize(ProfilingLogger proflog)
+ {
+ ProfilingLogger = proflog;
+ }
+
public override void Terminate()
{
base.Terminate();
Terminated = true;
}
}
-
- // test all event handler
- // fixme should become test component
- public class TestApplicationEventHandler : DisposableObject, IApplicationEventHandler
- {
- public static void Reset()
- {
- Initialized = false;
- Starting = false;
- Started = false;
- HasBeenDisposed = false;
- }
-
- public static bool Initialized;
- public static bool Starting;
- public static bool Started;
- public static bool HasBeenDisposed;
-
- public void OnApplicationInitialized(UmbracoApplicationBase umbracoApplication)
- {
- Initialized = true;
- }
-
- public void OnApplicationStarting(UmbracoApplicationBase umbracoApplication)
- {
- Starting = true;
- }
-
- public void OnApplicationStarted(UmbracoApplicationBase umbracoApplication)
- {
- Started = true;
- }
-
- protected override void DisposeResources()
- {
- HasBeenDisposed = true;
- }
- }
-
- [Test]
- public void ComponentLifeCycle()
- {
- using (var app = new TestUmbracoApplication())
- {
- app.HandleApplicationStart(app, new EventArgs());
-
- Assert.IsTrue(TestComponent.Ctored);
- Assert.IsTrue(TestComponent.Composed);
- Assert.IsTrue(TestComponent.Initialized1);
- Assert.IsTrue(TestComponent.Initialized2);
-
- Assert.IsFalse(TestComponent.Terminated);
-
- app.HandleApplicationEnd();
- Assert.IsTrue(TestComponent.Terminated);
- }
- }
-
- // note: components are NOT disposed after boot
- [Test]
- public void Disposes_App_Startup_Handlers_After_Startup()
- {
- using (var app = new TestUmbracoApplication())
- {
- app.HandleApplicationStart(app, new EventArgs());
-
- Assert.IsTrue(TestApplicationEventHandler.HasBeenDisposed);
- }
- }
-
- [Test]
- public void Handle_IApplicationEventHandler_Objects_Outside_Web_Context()
- {
- using (var app = new TestUmbracoApplication())
- {
- app.HandleApplicationStart(app, new EventArgs());
-
- Assert.IsTrue(TestApplicationEventHandler.Initialized);
- Assert.IsTrue(TestApplicationEventHandler.Starting);
- Assert.IsTrue(TestApplicationEventHandler.Started);
- }
- }
-
- [Test]
- public void Raises_Starting_Events()
- {
- using (var app = new TestUmbracoApplication())
- {
- EventHandler starting = (sender, args) =>
- {
- Assert.IsTrue(TestApplicationEventHandler.Initialized);
- Assert.IsTrue(TestApplicationEventHandler.Starting);
- Assert.IsFalse(TestApplicationEventHandler.Started);
- };
- EventHandler started = (sender, args) =>
- {
- Assert.IsTrue(TestApplicationEventHandler.Initialized);
- Assert.IsTrue(TestApplicationEventHandler.Starting);
- Assert.IsTrue(TestApplicationEventHandler.Started);
- };
-
- app.ApplicationStarting += starting;
- app.ApplicationStarted += started;
-
- app.HandleApplicationStart(app, new EventArgs());
-
- app.ApplicationStarting -= starting;
- app.ApplicationStarting -= started;
- }
- }
}
}
diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj
index 3b1b4a25cb..2e1e071375 100644
--- a/src/Umbraco.Tests/Umbraco.Tests.csproj
+++ b/src/Umbraco.Tests/Umbraco.Tests.csproj
@@ -232,7 +232,8 @@
-
+
+
diff --git a/src/Umbraco.Web/Cache/CacheRefresherEventHandler.cs b/src/Umbraco.Web/Cache/CacheRefresherComponent.cs
similarity index 95%
rename from src/Umbraco.Web/Cache/CacheRefresherEventHandler.cs
rename to src/Umbraco.Web/Cache/CacheRefresherComponent.cs
index e2743a5233..3421e1946a 100644
--- a/src/Umbraco.Web/Cache/CacheRefresherEventHandler.cs
+++ b/src/Umbraco.Web/Cache/CacheRefresherComponent.cs
@@ -1,485 +1,486 @@
-using System;
-using Umbraco.Core;
-using Umbraco.Core.Events;
-using Umbraco.Core.Models;
-using Umbraco.Core.Models.Membership;
-using Umbraco.Core.Persistence.Repositories;
-using Umbraco.Core.Services;
-using System.Linq;
-using Umbraco.Core.Logging;
-using Umbraco.Core.Services.Changes;
-using Umbraco.Web.Services;
-using Content = Umbraco.Core.Models.Content;
-using ApplicationTree = Umbraco.Core.Models.ApplicationTree;
-
-namespace Umbraco.Web.Cache
-{
- ///
- /// Installs listeners on service events in order to refresh our caches.
- ///
- public class CacheRefresherEventHandler : ApplicationEventHandler
- {
- protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication)
- {
- LogHelper.Info("Initializing Umbraco internal event handlers for cache refreshing.");
- AddHandlers();
- }
-
- internal void AddHandlers()
- {
- // bind to application tree events
- ApplicationTreeService.Deleted += ApplicationTreeDeleted;
- ApplicationTreeService.Updated += ApplicationTreeUpdated;
- ApplicationTreeService.New += ApplicationTreeNew;
-
- // bind to application events
- SectionService.Deleted += ApplicationDeleted;
- SectionService.New += ApplicationNew;
-
- // bind to user / user type events
- UserService.SavedUserType += UserServiceSavedUserType;
- UserService.DeletedUserType += UserServiceDeletedUserType;
- UserService.SavedUser += UserServiceSavedUser;
- UserService.DeletedUser += UserServiceDeletedUser;
-
- // bind to dictionary events
- LocalizationService.DeletedDictionaryItem += LocalizationServiceDeletedDictionaryItem;
- LocalizationService.SavedDictionaryItem += LocalizationServiceSavedDictionaryItem;
-
- // bind to data type events
- // NOTE: we need to bind to legacy and new API events currently: http://issues.umbraco.org/issue/U4-1979
- DataTypeService.Deleted += DataTypeServiceDeleted;
- DataTypeService.Saved += DataTypeServiceSaved;
-
- // bind to stylesheet events
- //FileService.SavedStylesheet += FileServiceSavedStylesheet;
- //FileService.DeletedStylesheet += FileServiceDeletedStylesheet;
-
- // bind to domain events
- DomainService.Saved += DomainServiceSaved;
- DomainService.Deleted += DomainServiceDeleted;
-
- // bind to language events
- LocalizationService.SavedLanguage += LocalizationServiceSavedLanguage;
- LocalizationService.DeletedLanguage += LocalizationServiceDeletedLanguage;
-
- // bind to content type events
- ContentTypeService.Changed += ContentTypeServiceChanged;
- MediaTypeService.Changed += ContentTypeServiceChanged;
- MemberTypeService.Changed += ContentTypeServiceChanged;
-
- // bind to permission events
- PermissionRepository.AssignedPermissions += PermissionRepositoryAssignedPermissions;
-
- // bind to template events
- FileService.SavedTemplate += FileServiceSavedTemplate;
- FileService.DeletedTemplate += FileServiceDeletedTemplate;
-
- // bind to macro events
- MacroService.Saved += MacroServiceSaved;
- MacroService.Deleted += MacroServiceDeleted;
-
- // bind to member events
- MemberService.Saved += MemberServiceSaved;
- MemberService.Deleted += MemberServiceDeleted;
- MemberGroupService.Saved += MemberGroupServiceSaved;
- MemberGroupService.Deleted += MemberGroupServiceDeleted;
-
- // bind to media events
- MediaService.TreeChanged += MediaServiceChanged; // handles all media changes
-
- // bind to content events
- ContentService.Saved += ContentServiceSaved; // needed for permissions
- ContentService.Copied += ContentServiceCopied; // needed for permissions
- ContentService.TreeChanged += ContentServiceChanged; // handles all content changes
-
- // bind to public access events
- PublicAccessService.Saved += PublicAccessServiceSaved;
- PublicAccessService.Deleted += PublicAccessServiceDeleted;
- }
-
- internal void RemoveHandlers()
- {
- // bind to application tree events
- ApplicationTreeService.Deleted -= ApplicationTreeDeleted;
- ApplicationTreeService.Updated -= ApplicationTreeUpdated;
- ApplicationTreeService.New -= ApplicationTreeNew;
-
- // bind to application events
- SectionService.Deleted -= ApplicationDeleted;
- SectionService.New -= ApplicationNew;
-
- // bind to user / user type events
- UserService.SavedUserType -= UserServiceSavedUserType;
- UserService.DeletedUserType -= UserServiceDeletedUserType;
- UserService.SavedUser -= UserServiceSavedUser;
- UserService.DeletedUser -= UserServiceDeletedUser;
-
- // bind to dictionary events
- LocalizationService.DeletedDictionaryItem -= LocalizationServiceDeletedDictionaryItem;
- LocalizationService.SavedDictionaryItem -= LocalizationServiceSavedDictionaryItem;
-
- // bind to data type events
- // NOTE: we need to bind to legacy and new API events currently: http://issues.umbraco.org/issue/U4-1979
- DataTypeService.Deleted -= DataTypeServiceDeleted;
- DataTypeService.Saved -= DataTypeServiceSaved;
-
- // bind to stylesheet events
- //FileService.SavedStylesheet -= FileServiceSavedStylesheet;
- //FileService.DeletedStylesheet -= FileServiceDeletedStylesheet;
-
- // bind to domain events
- DomainService.Saved -= DomainServiceSaved;
- DomainService.Deleted -= DomainServiceDeleted;
-
- // bind to language events
- LocalizationService.SavedLanguage -= LocalizationServiceSavedLanguage;
- LocalizationService.DeletedLanguage -= LocalizationServiceDeletedLanguage;
-
- // bind to content type events
- ContentTypeService.Changed -= ContentTypeServiceChanged;
- MediaTypeService.Changed -= ContentTypeServiceChanged;
- MemberTypeService.Changed -= ContentTypeServiceChanged;
-
- // bind to permission events
- PermissionRepository.AssignedPermissions -= PermissionRepositoryAssignedPermissions;
-
- // bind to template events
- FileService.SavedTemplate -= FileServiceSavedTemplate;
- FileService.DeletedTemplate -= FileServiceDeletedTemplate;
-
- // bind to macro events
- MacroService.Saved -= MacroServiceSaved;
- MacroService.Deleted -= MacroServiceDeleted;
-
- // bind to member events
- MemberService.Saved -= MemberServiceSaved;
- MemberService.Deleted -= MemberServiceDeleted;
- MemberGroupService.Saved -= MemberGroupServiceSaved;
- MemberGroupService.Deleted -= MemberGroupServiceDeleted;
-
- // bind to media events
- MediaService.TreeChanged -= MediaServiceChanged; // handles all media changes
-
- // bind to content events
- ContentService.Saved -= ContentServiceSaved; // needed for permissions
- ContentService.Copied -= ContentServiceCopied; // needed for permissions
- ContentService.TreeChanged -= ContentServiceChanged; // handles all content changes
-
- // bind to public access events
- PublicAccessService.Saved -= PublicAccessServiceSaved;
- PublicAccessService.Deleted -= PublicAccessServiceDeleted;
- }
-
- #region PublicAccessService
-
- static void PublicAccessServiceSaved(IPublicAccessService sender, SaveEventArgs e)
- {
- DistributedCache.Instance.RefreshPublicAccess();
- }
-
- private void PublicAccessServiceDeleted(IPublicAccessService sender, DeleteEventArgs e)
- {
- DistributedCache.Instance.RefreshPublicAccess();
- }
-
- #endregion
-
- #region ContentService
-
- ///
- /// Handles cache refreshing for when content is copied
- ///
- ///
- ///
- ///
- /// When an entity is copied new permissions may be assigned to it based on it's parent, if that is the
- /// case then we need to clear all user permissions cache.
- ///
- static void ContentServiceCopied(IContentService sender, CopyEventArgs e)
- {
- //check if permissions have changed
- var permissionsChanged = ((Content)e.Copy).WasPropertyDirty("PermissionsChanged");
- if (permissionsChanged)
- {
- DistributedCache.Instance.RefreshAllUserPermissionsCache();
- }
- }
-
- ///
- /// Handles cache refreshing for when content is saved (not published)
- ///
- ///
- ///
- ///
- /// When an entity is saved we need to notify other servers about the change in order for the Examine indexes to
- /// stay up-to-date for unpublished content.
- ///
- /// When an entity is created new permissions may be assigned to it based on it's parent, if that is the
- /// case then we need to clear all user permissions cache.
- ///
- static void ContentServiceSaved(IContentService sender, SaveEventArgs e)
- {
- var clearUserPermissions = false;
- e.SavedEntities.ForEach(x =>
- {
- //check if it is new
- if (x.IsNewEntity())
- {
- //check if permissions have changed
- var permissionsChanged = ((Content)x).WasPropertyDirty("PermissionsChanged");
- if (permissionsChanged)
- {
- clearUserPermissions = true;
- }
- }
- });
-
- if (clearUserPermissions)
- {
- DistributedCache.Instance.RefreshAllUserPermissionsCache();
- }
- }
-
- private static void ContentServiceChanged(IContentService sender, TreeChange.EventArgs args)
- {
- DistributedCache.Instance.RefreshContentCache(args.Changes.ToArray());
- }
-
- #endregion
-
- #region ApplicationTreeService
-
- static void ApplicationTreeNew(ApplicationTree sender, EventArgs e)
- {
- DistributedCache.Instance.RefreshAllApplicationTreeCache();
- }
-
- static void ApplicationTreeUpdated(ApplicationTree sender, EventArgs e)
- {
- DistributedCache.Instance.RefreshAllApplicationTreeCache();
- }
-
- static void ApplicationTreeDeleted(ApplicationTree sender, EventArgs e)
- {
- DistributedCache.Instance.RefreshAllApplicationTreeCache();
- }
- #endregion
-
- #region Application event handlers
- static void ApplicationNew(Section sender, EventArgs e)
- {
- DistributedCache.Instance.RefreshAllApplicationCache();
- }
-
- static void ApplicationDeleted(Section sender, EventArgs e)
- {
- DistributedCache.Instance.RefreshAllApplicationCache();
- }
-
- #endregion
-
- #region UserService / UserType
-
- static void UserServiceDeletedUserType(IUserService sender, DeleteEventArgs e)
- {
- e.DeletedEntities.ForEach(x => DistributedCache.Instance.RemoveUserTypeCache(x.Id));
- }
-
- static void UserServiceSavedUserType(IUserService sender, SaveEventArgs e)
- {
- e.SavedEntities.ForEach(x => DistributedCache.Instance.RefreshUserTypeCache(x.Id));
- }
-
- #endregion
-
- #region LocalizationService / Dictionary
-
- static void LocalizationServiceSavedDictionaryItem(ILocalizationService sender, SaveEventArgs e)
- {
- e.SavedEntities.ForEach(x => DistributedCache.Instance.RefreshDictionaryCache(x.Id));
- }
-
- static void LocalizationServiceDeletedDictionaryItem(ILocalizationService sender, DeleteEventArgs e)
- {
- e.DeletedEntities.ForEach(x => DistributedCache.Instance.RemoveDictionaryCache(x.Id));
- }
-
- #endregion
-
- #region DataTypeService
- static void DataTypeServiceSaved(IDataTypeService sender, SaveEventArgs e)
- {
- e.SavedEntities.ForEach(x => DistributedCache.Instance.RefreshDataTypeCache(x));
- }
-
- static void DataTypeServiceDeleted(IDataTypeService sender, DeleteEventArgs e)
- {
- e.DeletedEntities.ForEach(x => DistributedCache.Instance.RemoveDataTypeCache(x));
- }
-
- #endregion
-
- #region DomainService
-
- static void DomainServiceSaved(IDomainService sender, SaveEventArgs e)
- {
- e.SavedEntities.ForEach(x => DistributedCache.Instance.RefreshDomainCache(x));
- }
-
- static void DomainServiceDeleted(IDomainService sender, DeleteEventArgs e)
- {
- e.DeletedEntities.ForEach(x => DistributedCache.Instance.RemoveDomainCache(x));
- }
-
- #endregion
-
- #region LocalizationService / Language
- ///
- /// Fires when a langauge is deleted
- ///
- ///
- ///
- static void LocalizationServiceDeletedLanguage(ILocalizationService sender, DeleteEventArgs e)
- {
- e.DeletedEntities.ForEach(x => DistributedCache.Instance.RemoveLanguageCache(x));
- }
-
- ///
- /// Fires when a langauge is saved
- ///
- ///
- ///
- static void LocalizationServiceSavedLanguage(ILocalizationService sender, SaveEventArgs e)
- {
- e.SavedEntities.ForEach(x => DistributedCache.Instance.RefreshLanguageCache(x));
- }
-
- #endregion
-
- #region Content|Media|MemberTypeService
-
- private void ContentTypeServiceChanged(IContentTypeService sender, ContentTypeChange.EventArgs args)
- {
- DistributedCache.Instance.RefreshContentTypeCache(args.Changes.ToArray());
- }
-
- private void ContentTypeServiceChanged(IMediaTypeService sender, ContentTypeChange.EventArgs args)
- {
- DistributedCache.Instance.RefreshContentTypeCache(args.Changes.ToArray());
- }
-
- private void ContentTypeServiceChanged(IMemberTypeService sender, ContentTypeChange.EventArgs args)
- {
- DistributedCache.Instance.RefreshContentTypeCache(args.Changes.ToArray());
- }
-
- #endregion
-
- #region UserService & PermissionRepository
-
- static void PermissionRepositoryAssignedPermissions(PermissionRepository sender, SaveEventArgs e)
- {
- var userIds = e.SavedEntities.Select(x => x.UserId).Distinct();
- userIds.ForEach(x => DistributedCache.Instance.RefreshUserPermissionsCache(x));
- }
-
- static void UserServiceSavedUser(IUserService sender, SaveEventArgs e)
- {
- e.SavedEntities.ForEach(x => DistributedCache.Instance.RefreshUserCache(x.Id));
- }
-
- static void UserServiceDeletedUser(IUserService sender, DeleteEventArgs e)
- {
- e.DeletedEntities.ForEach(x => DistributedCache.Instance.RemoveUserCache(x.Id));
- }
-
- #endregion
-
- #region FileService / Template
-
- ///
- /// Removes cache for template
- ///
- ///
- ///
- static void FileServiceDeletedTemplate(IFileService sender, DeleteEventArgs e)
- {
- e.DeletedEntities.ForEach(x => DistributedCache.Instance.RemoveTemplateCache(x.Id));
- }
-
- ///
- /// Refresh cache for template
- ///
- ///
- ///
- static void FileServiceSavedTemplate(IFileService sender, SaveEventArgs e)
- {
- e.SavedEntities.ForEach(x => DistributedCache.Instance.RefreshTemplateCache(x.Id));
- }
-
- #endregion
-
- #region MacroService
-
- void MacroServiceDeleted(IMacroService sender, DeleteEventArgs e)
- {
- foreach (var entity in e.DeletedEntities)
- {
- DistributedCache.Instance.RemoveMacroCache(entity);
- }
- }
-
- void MacroServiceSaved(IMacroService sender, SaveEventArgs e)
- {
- foreach (var entity in e.SavedEntities)
- {
- DistributedCache.Instance.RefreshMacroCache(entity);
- }
- }
-
- #endregion
-
- #region MediaService
-
- private static void MediaServiceChanged(IMediaService sender, TreeChange.EventArgs args)
- {
- DistributedCache.Instance.RefreshMediaCache(args.Changes.ToArray());
- }
-
- #endregion
-
- #region MemberService
-
- static void MemberServiceDeleted(IMemberService sender, DeleteEventArgs e)
- {
- DistributedCache.Instance.RemoveMemberCache(e.DeletedEntities.ToArray());
- }
-
- static void MemberServiceSaved(IMemberService sender, SaveEventArgs e)
- {
- DistributedCache.Instance.RefreshMemberCache(e.SavedEntities.ToArray());
- }
-
- #endregion
-
- #region MemberGroupService
-
- static void MemberGroupServiceDeleted(IMemberGroupService sender, DeleteEventArgs e)
- {
- foreach (var m in e.DeletedEntities.ToArray())
- {
- DistributedCache.Instance.RemoveMemberGroupCache(m.Id);
- }
- }
-
- static void MemberGroupServiceSaved(IMemberGroupService sender, SaveEventArgs e)
- {
- foreach (var m in e.SavedEntities.ToArray())
- {
- DistributedCache.Instance.RemoveMemberGroupCache(m.Id);
- }
- }
- #endregion
- }
+using System;
+using Umbraco.Core;
+using Umbraco.Core.Events;
+using Umbraco.Core.Models;
+using Umbraco.Core.Models.Membership;
+using Umbraco.Core.Persistence.Repositories;
+using Umbraco.Core.Services;
+using System.Linq;
+using Umbraco.Core.Components;
+using Umbraco.Core.Logging;
+using Umbraco.Core.Services.Changes;
+using Umbraco.Web.Services;
+using Content = Umbraco.Core.Models.Content;
+using ApplicationTree = Umbraco.Core.Models.ApplicationTree;
+
+namespace Umbraco.Web.Cache
+{
+ ///
+ /// Installs listeners on service events in order to refresh our caches.
+ ///
+ public class CacheRefresherComponent : UmbracoComponentBase, IUmbracoCoreComponent
+ {
+ public void Initialize()
+ {
+ LogHelper.Info("Initializing Umbraco internal event handlers for cache refreshing.");
+ AddHandlers();
+ }
+
+ internal void AddHandlers()
+ {
+ // bind to application tree events
+ ApplicationTreeService.Deleted += ApplicationTreeDeleted;
+ ApplicationTreeService.Updated += ApplicationTreeUpdated;
+ ApplicationTreeService.New += ApplicationTreeNew;
+
+ // bind to application events
+ SectionService.Deleted += ApplicationDeleted;
+ SectionService.New += ApplicationNew;
+
+ // bind to user / user type events
+ UserService.SavedUserType += UserServiceSavedUserType;
+ UserService.DeletedUserType += UserServiceDeletedUserType;
+ UserService.SavedUser += UserServiceSavedUser;
+ UserService.DeletedUser += UserServiceDeletedUser;
+
+ // bind to dictionary events
+ LocalizationService.DeletedDictionaryItem += LocalizationServiceDeletedDictionaryItem;
+ LocalizationService.SavedDictionaryItem += LocalizationServiceSavedDictionaryItem;
+
+ // bind to data type events
+ // NOTE: we need to bind to legacy and new API events currently: http://issues.umbraco.org/issue/U4-1979
+ DataTypeService.Deleted += DataTypeServiceDeleted;
+ DataTypeService.Saved += DataTypeServiceSaved;
+
+ // bind to stylesheet events
+ //FileService.SavedStylesheet += FileServiceSavedStylesheet;
+ //FileService.DeletedStylesheet += FileServiceDeletedStylesheet;
+
+ // bind to domain events
+ DomainService.Saved += DomainServiceSaved;
+ DomainService.Deleted += DomainServiceDeleted;
+
+ // bind to language events
+ LocalizationService.SavedLanguage += LocalizationServiceSavedLanguage;
+ LocalizationService.DeletedLanguage += LocalizationServiceDeletedLanguage;
+
+ // bind to content type events
+ ContentTypeService.Changed += ContentTypeServiceChanged;
+ MediaTypeService.Changed += ContentTypeServiceChanged;
+ MemberTypeService.Changed += ContentTypeServiceChanged;
+
+ // bind to permission events
+ PermissionRepository.AssignedPermissions += PermissionRepositoryAssignedPermissions;
+
+ // bind to template events
+ FileService.SavedTemplate += FileServiceSavedTemplate;
+ FileService.DeletedTemplate += FileServiceDeletedTemplate;
+
+ // bind to macro events
+ MacroService.Saved += MacroServiceSaved;
+ MacroService.Deleted += MacroServiceDeleted;
+
+ // bind to member events
+ MemberService.Saved += MemberServiceSaved;
+ MemberService.Deleted += MemberServiceDeleted;
+ MemberGroupService.Saved += MemberGroupServiceSaved;
+ MemberGroupService.Deleted += MemberGroupServiceDeleted;
+
+ // bind to media events
+ MediaService.TreeChanged += MediaServiceChanged; // handles all media changes
+
+ // bind to content events
+ ContentService.Saved += ContentServiceSaved; // needed for permissions
+ ContentService.Copied += ContentServiceCopied; // needed for permissions
+ ContentService.TreeChanged += ContentServiceChanged; // handles all content changes
+
+ // bind to public access events
+ PublicAccessService.Saved += PublicAccessServiceSaved;
+ PublicAccessService.Deleted += PublicAccessServiceDeleted;
+ }
+
+ internal void RemoveHandlers()
+ {
+ // bind to application tree events
+ ApplicationTreeService.Deleted -= ApplicationTreeDeleted;
+ ApplicationTreeService.Updated -= ApplicationTreeUpdated;
+ ApplicationTreeService.New -= ApplicationTreeNew;
+
+ // bind to application events
+ SectionService.Deleted -= ApplicationDeleted;
+ SectionService.New -= ApplicationNew;
+
+ // bind to user / user type events
+ UserService.SavedUserType -= UserServiceSavedUserType;
+ UserService.DeletedUserType -= UserServiceDeletedUserType;
+ UserService.SavedUser -= UserServiceSavedUser;
+ UserService.DeletedUser -= UserServiceDeletedUser;
+
+ // bind to dictionary events
+ LocalizationService.DeletedDictionaryItem -= LocalizationServiceDeletedDictionaryItem;
+ LocalizationService.SavedDictionaryItem -= LocalizationServiceSavedDictionaryItem;
+
+ // bind to data type events
+ // NOTE: we need to bind to legacy and new API events currently: http://issues.umbraco.org/issue/U4-1979
+ DataTypeService.Deleted -= DataTypeServiceDeleted;
+ DataTypeService.Saved -= DataTypeServiceSaved;
+
+ // bind to stylesheet events
+ //FileService.SavedStylesheet -= FileServiceSavedStylesheet;
+ //FileService.DeletedStylesheet -= FileServiceDeletedStylesheet;
+
+ // bind to domain events
+ DomainService.Saved -= DomainServiceSaved;
+ DomainService.Deleted -= DomainServiceDeleted;
+
+ // bind to language events
+ LocalizationService.SavedLanguage -= LocalizationServiceSavedLanguage;
+ LocalizationService.DeletedLanguage -= LocalizationServiceDeletedLanguage;
+
+ // bind to content type events
+ ContentTypeService.Changed -= ContentTypeServiceChanged;
+ MediaTypeService.Changed -= ContentTypeServiceChanged;
+ MemberTypeService.Changed -= ContentTypeServiceChanged;
+
+ // bind to permission events
+ PermissionRepository.AssignedPermissions -= PermissionRepositoryAssignedPermissions;
+
+ // bind to template events
+ FileService.SavedTemplate -= FileServiceSavedTemplate;
+ FileService.DeletedTemplate -= FileServiceDeletedTemplate;
+
+ // bind to macro events
+ MacroService.Saved -= MacroServiceSaved;
+ MacroService.Deleted -= MacroServiceDeleted;
+
+ // bind to member events
+ MemberService.Saved -= MemberServiceSaved;
+ MemberService.Deleted -= MemberServiceDeleted;
+ MemberGroupService.Saved -= MemberGroupServiceSaved;
+ MemberGroupService.Deleted -= MemberGroupServiceDeleted;
+
+ // bind to media events
+ MediaService.TreeChanged -= MediaServiceChanged; // handles all media changes
+
+ // bind to content events
+ ContentService.Saved -= ContentServiceSaved; // needed for permissions
+ ContentService.Copied -= ContentServiceCopied; // needed for permissions
+ ContentService.TreeChanged -= ContentServiceChanged; // handles all content changes
+
+ // bind to public access events
+ PublicAccessService.Saved -= PublicAccessServiceSaved;
+ PublicAccessService.Deleted -= PublicAccessServiceDeleted;
+ }
+
+ #region PublicAccessService
+
+ static void PublicAccessServiceSaved(IPublicAccessService sender, SaveEventArgs e)
+ {
+ DistributedCache.Instance.RefreshPublicAccess();
+ }
+
+ private void PublicAccessServiceDeleted(IPublicAccessService sender, DeleteEventArgs e)
+ {
+ DistributedCache.Instance.RefreshPublicAccess();
+ }
+
+ #endregion
+
+ #region ContentService
+
+ ///
+ /// Handles cache refreshing for when content is copied
+ ///
+ ///
+ ///
+ ///
+ /// When an entity is copied new permissions may be assigned to it based on it's parent, if that is the
+ /// case then we need to clear all user permissions cache.
+ ///
+ static void ContentServiceCopied(IContentService sender, CopyEventArgs e)
+ {
+ //check if permissions have changed
+ var permissionsChanged = ((Content)e.Copy).WasPropertyDirty("PermissionsChanged");
+ if (permissionsChanged)
+ {
+ DistributedCache.Instance.RefreshAllUserPermissionsCache();
+ }
+ }
+
+ ///
+ /// Handles cache refreshing for when content is saved (not published)
+ ///
+ ///
+ ///
+ ///
+ /// When an entity is saved we need to notify other servers about the change in order for the Examine indexes to
+ /// stay up-to-date for unpublished content.
+ ///
+ /// When an entity is created new permissions may be assigned to it based on it's parent, if that is the
+ /// case then we need to clear all user permissions cache.
+ ///
+ static void ContentServiceSaved(IContentService sender, SaveEventArgs e)
+ {
+ var clearUserPermissions = false;
+ e.SavedEntities.ForEach(x =>
+ {
+ //check if it is new
+ if (x.IsNewEntity())
+ {
+ //check if permissions have changed
+ var permissionsChanged = ((Content)x).WasPropertyDirty("PermissionsChanged");
+ if (permissionsChanged)
+ {
+ clearUserPermissions = true;
+ }
+ }
+ });
+
+ if (clearUserPermissions)
+ {
+ DistributedCache.Instance.RefreshAllUserPermissionsCache();
+ }
+ }
+
+ private static void ContentServiceChanged(IContentService sender, TreeChange.EventArgs args)
+ {
+ DistributedCache.Instance.RefreshContentCache(args.Changes.ToArray());
+ }
+
+ #endregion
+
+ #region ApplicationTreeService
+
+ static void ApplicationTreeNew(ApplicationTree sender, EventArgs e)
+ {
+ DistributedCache.Instance.RefreshAllApplicationTreeCache();
+ }
+
+ static void ApplicationTreeUpdated(ApplicationTree sender, EventArgs e)
+ {
+ DistributedCache.Instance.RefreshAllApplicationTreeCache();
+ }
+
+ static void ApplicationTreeDeleted(ApplicationTree sender, EventArgs e)
+ {
+ DistributedCache.Instance.RefreshAllApplicationTreeCache();
+ }
+ #endregion
+
+ #region Application event handlers
+ static void ApplicationNew(Section sender, EventArgs e)
+ {
+ DistributedCache.Instance.RefreshAllApplicationCache();
+ }
+
+ static void ApplicationDeleted(Section sender, EventArgs e)
+ {
+ DistributedCache.Instance.RefreshAllApplicationCache();
+ }
+
+ #endregion
+
+ #region UserService / UserType
+
+ static void UserServiceDeletedUserType(IUserService sender, DeleteEventArgs e)
+ {
+ e.DeletedEntities.ForEach(x => DistributedCache.Instance.RemoveUserTypeCache(x.Id));
+ }
+
+ static void UserServiceSavedUserType(IUserService sender, SaveEventArgs e)
+ {
+ e.SavedEntities.ForEach(x => DistributedCache.Instance.RefreshUserTypeCache(x.Id));
+ }
+
+ #endregion
+
+ #region LocalizationService / Dictionary
+
+ static void LocalizationServiceSavedDictionaryItem(ILocalizationService sender, SaveEventArgs e)
+ {
+ e.SavedEntities.ForEach(x => DistributedCache.Instance.RefreshDictionaryCache(x.Id));
+ }
+
+ static void LocalizationServiceDeletedDictionaryItem(ILocalizationService sender, DeleteEventArgs e)
+ {
+ e.DeletedEntities.ForEach(x => DistributedCache.Instance.RemoveDictionaryCache(x.Id));
+ }
+
+ #endregion
+
+ #region DataTypeService
+ static void DataTypeServiceSaved(IDataTypeService sender, SaveEventArgs e)
+ {
+ e.SavedEntities.ForEach(x => DistributedCache.Instance.RefreshDataTypeCache(x));
+ }
+
+ static void DataTypeServiceDeleted(IDataTypeService sender, DeleteEventArgs e)
+ {
+ e.DeletedEntities.ForEach(x => DistributedCache.Instance.RemoveDataTypeCache(x));
+ }
+
+ #endregion
+
+ #region DomainService
+
+ static void DomainServiceSaved(IDomainService sender, SaveEventArgs e)
+ {
+ e.SavedEntities.ForEach(x => DistributedCache.Instance.RefreshDomainCache(x));
+ }
+
+ static void DomainServiceDeleted(IDomainService sender, DeleteEventArgs e)
+ {
+ e.DeletedEntities.ForEach(x => DistributedCache.Instance.RemoveDomainCache(x));
+ }
+
+ #endregion
+
+ #region LocalizationService / Language
+ ///
+ /// Fires when a langauge is deleted
+ ///
+ ///
+ ///
+ static void LocalizationServiceDeletedLanguage(ILocalizationService sender, DeleteEventArgs e)
+ {
+ e.DeletedEntities.ForEach(x => DistributedCache.Instance.RemoveLanguageCache(x));
+ }
+
+ ///
+ /// Fires when a langauge is saved
+ ///
+ ///
+ ///
+ static void LocalizationServiceSavedLanguage(ILocalizationService sender, SaveEventArgs e)
+ {
+ e.SavedEntities.ForEach(x => DistributedCache.Instance.RefreshLanguageCache(x));
+ }
+
+ #endregion
+
+ #region Content|Media|MemberTypeService
+
+ private void ContentTypeServiceChanged(IContentTypeService sender, ContentTypeChange.EventArgs args)
+ {
+ DistributedCache.Instance.RefreshContentTypeCache(args.Changes.ToArray());
+ }
+
+ private void ContentTypeServiceChanged(IMediaTypeService sender, ContentTypeChange.EventArgs args)
+ {
+ DistributedCache.Instance.RefreshContentTypeCache(args.Changes.ToArray());
+ }
+
+ private void ContentTypeServiceChanged(IMemberTypeService sender, ContentTypeChange.EventArgs args)
+ {
+ DistributedCache.Instance.RefreshContentTypeCache(args.Changes.ToArray());
+ }
+
+ #endregion
+
+ #region UserService & PermissionRepository
+
+ static void PermissionRepositoryAssignedPermissions(PermissionRepository sender, SaveEventArgs e)
+ {
+ var userIds = e.SavedEntities.Select(x => x.UserId).Distinct();
+ userIds.ForEach(x => DistributedCache.Instance.RefreshUserPermissionsCache(x));
+ }
+
+ static void UserServiceSavedUser(IUserService sender, SaveEventArgs e)
+ {
+ e.SavedEntities.ForEach(x => DistributedCache.Instance.RefreshUserCache(x.Id));
+ }
+
+ static void UserServiceDeletedUser(IUserService sender, DeleteEventArgs e)
+ {
+ e.DeletedEntities.ForEach(x => DistributedCache.Instance.RemoveUserCache(x.Id));
+ }
+
+ #endregion
+
+ #region FileService / Template
+
+ ///
+ /// Removes cache for template
+ ///
+ ///
+ ///
+ static void FileServiceDeletedTemplate(IFileService sender, DeleteEventArgs e)
+ {
+ e.DeletedEntities.ForEach(x => DistributedCache.Instance.RemoveTemplateCache(x.Id));
+ }
+
+ ///
+ /// Refresh cache for template
+ ///
+ ///
+ ///
+ static void FileServiceSavedTemplate(IFileService sender, SaveEventArgs e)
+ {
+ e.SavedEntities.ForEach(x => DistributedCache.Instance.RefreshTemplateCache(x.Id));
+ }
+
+ #endregion
+
+ #region MacroService
+
+ void MacroServiceDeleted(IMacroService sender, DeleteEventArgs e)
+ {
+ foreach (var entity in e.DeletedEntities)
+ {
+ DistributedCache.Instance.RemoveMacroCache(entity);
+ }
+ }
+
+ void MacroServiceSaved(IMacroService sender, SaveEventArgs e)
+ {
+ foreach (var entity in e.SavedEntities)
+ {
+ DistributedCache.Instance.RefreshMacroCache(entity);
+ }
+ }
+
+ #endregion
+
+ #region MediaService
+
+ private static void MediaServiceChanged(IMediaService sender, TreeChange.EventArgs args)
+ {
+ DistributedCache.Instance.RefreshMediaCache(args.Changes.ToArray());
+ }
+
+ #endregion
+
+ #region MemberService
+
+ static void MemberServiceDeleted(IMemberService sender, DeleteEventArgs e)
+ {
+ DistributedCache.Instance.RemoveMemberCache(e.DeletedEntities.ToArray());
+ }
+
+ static void MemberServiceSaved(IMemberService sender, SaveEventArgs e)
+ {
+ DistributedCache.Instance.RefreshMemberCache(e.SavedEntities.ToArray());
+ }
+
+ #endregion
+
+ #region MemberGroupService
+
+ static void MemberGroupServiceDeleted(IMemberGroupService sender, DeleteEventArgs e)
+ {
+ foreach (var m in e.DeletedEntities.ToArray())
+ {
+ DistributedCache.Instance.RemoveMemberGroupCache(m.Id);
+ }
+ }
+
+ static void MemberGroupServiceSaved(IMemberGroupService sender, SaveEventArgs e)
+ {
+ foreach (var m in e.SavedEntities.ToArray())
+ {
+ DistributedCache.Instance.RemoveMemberGroupCache(m.Id);
+ }
+ }
+ #endregion
+ }
}
\ No newline at end of file
diff --git a/src/Umbraco.Web/HealthCheck/Checks/DataIntegrity/XmlDataIntegrityHealthCheck.cs b/src/Umbraco.Web/HealthCheck/Checks/DataIntegrity/XmlDataIntegrityHealthCheck.cs
index 0264f2b3fc..a129e0a394 100644
--- a/src/Umbraco.Web/HealthCheck/Checks/DataIntegrity/XmlDataIntegrityHealthCheck.cs
+++ b/src/Umbraco.Web/HealthCheck/Checks/DataIntegrity/XmlDataIntegrityHealthCheck.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using Umbraco.Core.Plugins;
using Umbraco.Core.Services;
using Umbraco.Web.PublishedCache;
@@ -13,6 +14,7 @@ namespace Umbraco.Web.HealthCheck.Checks.DataIntegrity
"XML Data Integrity",
Description = "Checks the integrity of the XML data in Umbraco",
Group = "Data Integrity")]
+ [HideFromTypeFinder] // only if running the Xml cache! added by XmlCacheComponent!
public class XmlDataIntegrityHealthCheck : HealthCheck
{
private readonly ILocalizedTextService _textService;
diff --git a/src/Umbraco.Web/PropertyEditors/FileUploadPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/FileUploadPropertyEditor.cs
index bcc91ad042..576ffb2887 100644
--- a/src/Umbraco.Web/PropertyEditors/FileUploadPropertyEditor.cs
+++ b/src/Umbraco.Web/PropertyEditors/FileUploadPropertyEditor.cs
@@ -1,15 +1,9 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
-using System.Drawing;
-using System.Globalization;
using System.Linq;
-using System.Text.RegularExpressions;
-using System.Xml;
-using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Umbraco.Core;
-using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
@@ -20,7 +14,7 @@ using Umbraco.Core.Services;
namespace Umbraco.Web.PropertyEditors
{
[PropertyEditor(Constants.PropertyEditors.UploadFieldAlias, "File upload", "fileupload", Icon = "icon-download-alt", Group = "media")]
- public class FileUploadPropertyEditor : PropertyEditor, IApplicationEventHandler
+ public class FileUploadPropertyEditor : PropertyEditor
{
private readonly MediaFileSystem _mediaFileSystem;
private readonly IContentSection _contentSettings;
@@ -29,14 +23,13 @@ namespace Umbraco.Web.PropertyEditors
public FileUploadPropertyEditor(ILogger logger, MediaFileSystem mediaFileSystem, IContentSection contentSettings, ILocalizedTextService textService)
: base(logger)
{
- if (mediaFileSystem == null) throw new ArgumentNullException("mediaFileSystem");
- if (contentSettings == null) throw new ArgumentNullException("contentSettings");
- if (textService == null) throw new ArgumentNullException("textService");
- _applicationStartup = new FileUploadPropertyEditorApplicationStartup(this);
+ if (mediaFileSystem == null) throw new ArgumentNullException(nameof(mediaFileSystem));
+ if (contentSettings == null) throw new ArgumentNullException(nameof(contentSettings));
+ if (textService == null) throw new ArgumentNullException(nameof(textService));
+
_mediaFileSystem = mediaFileSystem;
_contentSettings = contentSettings;
- _textService = textService;
-
+ _textService = textService;
}
///
@@ -59,7 +52,7 @@ namespace Umbraco.Web.PropertyEditors
/// Ensures any files associated are removed
///
///
- IEnumerable ServiceEmptiedRecycleBin(Dictionary> allPropertyData)
+ internal IEnumerable ServiceEmptiedRecycleBin(Dictionary> allPropertyData)
{
var list = new List();
//Get all values for any image croppers found
@@ -81,7 +74,7 @@ namespace Umbraco.Web.PropertyEditors
/// Ensures any files associated are removed
///
///
- IEnumerable ServiceDeleted(IEnumerable deletedEntities)
+ internal IEnumerable ServiceDeleted(IEnumerable deletedEntities)
{
var list = new List();
foreach (var property in deletedEntities.SelectMany(deletedEntity => deletedEntity
@@ -103,7 +96,7 @@ namespace Umbraco.Web.PropertyEditors
///
///
///
- void ContentServiceCopied(IContentService sender, Core.Events.CopyEventArgs e)
+ internal void ContentServiceCopied(IContentService sender, Core.Events.CopyEventArgs e)
{
if (e.Original.Properties.Any(x => x.PropertyType.PropertyEditorAlias == Constants.PropertyEditors.UploadFieldAlias))
{
@@ -142,12 +135,12 @@ namespace Umbraco.Web.PropertyEditors
}
}
- void MediaServiceCreating(IMediaService sender, Core.Events.NewEventArgs e)
+ internal void MediaServiceCreating(IMediaService sender, Core.Events.NewEventArgs e)
{
AutoFillProperties(e.Entity);
}
- void MediaServiceSaving(IMediaService sender, Core.Events.SaveEventArgs e)
+ internal void MediaServiceSaving(IMediaService sender, Core.Events.SaveEventArgs e)
{
foreach (var m in e.SavedEntities)
{
@@ -265,62 +258,5 @@ namespace Umbraco.Web.PropertyEditors
}
}
}
-
- #region Application event handler, used to bind to events on startup
-
- private readonly FileUploadPropertyEditorApplicationStartup _applicationStartup;
-
- ///
- /// we're using a sub -class because this has the logic to prevent it from executing if the application is not configured
- ///
- private class FileUploadPropertyEditorApplicationStartup : ApplicationEventHandler
- {
- private FileUploadPropertyEditor _fileUploadPropertyEditor;
-
- public FileUploadPropertyEditorApplicationStartup(FileUploadPropertyEditor fileUploadPropertyEditor)
- {
- this._fileUploadPropertyEditor = fileUploadPropertyEditor;
- }
-
- ///
- /// We're going to bind to the MediaService Saving event so that we can populate the umbracoFile size, type, etc... label fields
- /// if we find any attached to the current media item.
- ///
- protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication)
- {
- MediaService.Saving += _fileUploadPropertyEditor.MediaServiceSaving;
- MediaService.Created += _fileUploadPropertyEditor.MediaServiceCreating;
- ContentService.Copied += _fileUploadPropertyEditor.ContentServiceCopied;
-
- MediaService.Deleted += (sender, args) =>
- args.MediaFilesToDelete.AddRange(_fileUploadPropertyEditor.ServiceDeleted(args.DeletedEntities.Cast()));
- MediaService.EmptiedRecycleBin += (sender, args) =>
- args.Files.AddRange(_fileUploadPropertyEditor.ServiceEmptiedRecycleBin(args.AllPropertyData));
- ContentService.Deleted += (sender, args) =>
- args.MediaFilesToDelete.AddRange(_fileUploadPropertyEditor.ServiceDeleted(args.DeletedEntities.Cast()));
- ContentService.EmptiedRecycleBin += (sender, args) =>
- args.Files.AddRange(_fileUploadPropertyEditor.ServiceEmptiedRecycleBin(args.AllPropertyData));
- MemberService.Deleted += (sender, args) =>
- args.MediaFilesToDelete.AddRange(_fileUploadPropertyEditor.ServiceDeleted(args.DeletedEntities.Cast()));
- }
- }
-
- public void OnApplicationInitialized(UmbracoApplicationBase umbracoApplication)
- {
- //wrap
- _applicationStartup.OnApplicationInitialized(umbracoApplication);
- }
- public void OnApplicationStarting(UmbracoApplicationBase umbracoApplication)
- {
- //wrap
- _applicationStartup.OnApplicationStarting(umbracoApplication);
- }
- public void OnApplicationStarted(UmbracoApplicationBase umbracoApplication)
- {
- //wrap
- _applicationStartup.OnApplicationStarted(umbracoApplication);
- }
- #endregion
-
}
}
diff --git a/src/Umbraco.Web/PropertyEditors/GridPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/GridPropertyEditor.cs
index fdef4c9be4..30deedc22b 100644
--- a/src/Umbraco.Web/PropertyEditors/GridPropertyEditor.cs
+++ b/src/Umbraco.Web/PropertyEditors/GridPropertyEditor.cs
@@ -12,18 +12,14 @@ using UmbracoExamine;
namespace Umbraco.Web.PropertyEditors
{
- [PropertyEditor(Core.Constants.PropertyEditors.GridAlias, "Grid layout", "grid", HideLabel = true, IsParameterEditor = false, ValueType = PropertyEditorValueTypes.Json, Group="rich content", Icon="icon-layout")]
- public class GridPropertyEditor : PropertyEditor, IApplicationEventHandler
- {
- ///
- /// Constructor
- ///
- public GridPropertyEditor(ILogger logger, IExamineIndexCollectionAccessor indexCollection) : base(logger)
- {
- _applicationStartup = new GridPropertyEditorApplicationStartup(indexCollection);
- }
+ [PropertyEditor(Constants.PropertyEditors.GridAlias, "Grid layout", "grid", HideLabel = true, IsParameterEditor = false, ValueType = PropertyEditorValueTypes.Json, Group="rich content", Icon="icon-layout")]
+ public class GridPropertyEditor : PropertyEditor
+ {
+ public GridPropertyEditor(ILogger logger)
+ : base(logger)
+ { }
- private static void DocumentWriting(object sender, Examine.LuceneEngine.DocumentWritingEventArgs e)
+ internal void DocumentWriting(object sender, Examine.LuceneEngine.DocumentWritingEventArgs e)
{
var indexer = (BaseUmbracoIndexer)sender;
foreach (var field in indexer.IndexerData.UserFields)
@@ -128,52 +124,5 @@ namespace Umbraco.Web.PropertyEditors
[PreValueField("rte", "Rich text editor", "views/propertyeditors/rte/rte.prevalues.html", Description = "Rich text editor configuration")]
public string Rte { get; set; }
}
-
- #region Application event handler, used to bind to events on startup
-
- private readonly GridPropertyEditorApplicationStartup _applicationStartup;
-
- ///
- /// we're using a sub -class because this has the logic to prevent it from executing if the application is not configured
- ///
- private class GridPropertyEditorApplicationStartup : ApplicationEventHandler
- {
- private readonly IExamineIndexCollectionAccessor _indexCollection;
-
- public GridPropertyEditorApplicationStartup(IExamineIndexCollectionAccessor indexCollection)
- {
- this._indexCollection = indexCollection;
- }
-
- ///
- /// We're going to bind to the Examine events so we can ensure grid data is index nicely.
- ///
- protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication)
- {
- foreach (var i in _indexCollection.Indexes.Values.OfType())
- {
- i.DocumentWriting += DocumentWriting;
- }
- }
- }
-
- public void OnApplicationInitialized(UmbracoApplicationBase umbracoApplication)
- {
- //wrap
- _applicationStartup.OnApplicationInitialized(umbracoApplication);
- }
- public void OnApplicationStarting(UmbracoApplicationBase umbracoApplication)
- {
- //wrap
- _applicationStartup.OnApplicationStarting(umbracoApplication);
- }
- public void OnApplicationStarted(UmbracoApplicationBase umbracoApplication)
- {
- //wrap
- _applicationStartup.OnApplicationStarted(umbracoApplication);
- }
- #endregion
}
-
-
}
diff --git a/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyEditor.cs
index e4aa3bdecc..e15bcef307 100644
--- a/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyEditor.cs
+++ b/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyEditor.cs
@@ -3,10 +3,7 @@ using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using Umbraco.Core;
-using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
@@ -17,7 +14,7 @@ using Umbraco.Core.Services;
namespace Umbraco.Web.PropertyEditors
{
[PropertyEditor(Constants.PropertyEditors.ImageCropperAlias, "Image Cropper", "imagecropper", ValueType = PropertyEditorValueTypes.Json, HideLabel = false, Group="media", Icon="icon-crop")]
- public class ImageCropperPropertyEditor : PropertyEditor, IApplicationEventHandler
+ public class ImageCropperPropertyEditor : PropertyEditor
{
private readonly MediaFileSystem _mediaFileSystem;
private readonly IContentSection _contentSettings;
@@ -25,10 +22,8 @@ namespace Umbraco.Web.PropertyEditors
public ImageCropperPropertyEditor(ILogger logger, MediaFileSystem mediaFileSystem, IContentSection contentSettings)
: base(logger)
{
- if (mediaFileSystem == null) throw new ArgumentNullException("mediaFileSystem");
- if (contentSettings == null) throw new ArgumentNullException("contentSettings");
-
- _applicationStartup = new FileUploadPropertyEditorApplicationStartup(this);
+ if (mediaFileSystem == null) throw new ArgumentNullException(nameof(mediaFileSystem));
+ if (contentSettings == null) throw new ArgumentNullException(nameof(contentSettings));
_mediaFileSystem = mediaFileSystem;
_contentSettings = contentSettings;
@@ -60,7 +55,7 @@ namespace Umbraco.Web.PropertyEditors
/// Ensures any files associated are removed
///
///
- IEnumerable ServiceEmptiedRecycleBin(Dictionary> allPropertyData)
+ internal IEnumerable ServiceEmptiedRecycleBin(Dictionary> allPropertyData)
{
var list = new List();
//Get all values for any image croppers found
@@ -93,7 +88,7 @@ namespace Umbraco.Web.PropertyEditors
/// Ensures any files associated are removed
///
///
- IEnumerable ServiceDeleted(IEnumerable deletedEntities)
+ internal IEnumerable ServiceDeleted(IEnumerable deletedEntities)
{
var list = new List();
foreach (var property in deletedEntities.SelectMany(deletedEntity => deletedEntity
@@ -126,7 +121,7 @@ namespace Umbraco.Web.PropertyEditors
///
///
///
- void ContentServiceCopied(IContentService sender, Core.Events.CopyEventArgs e)
+ internal void ContentServiceCopied(IContentService sender, Core.Events.CopyEventArgs e)
{
if (e.Original.Properties.Any(x => x.PropertyType.PropertyEditorAlias == Constants.PropertyEditors.ImageCropperAlias))
{
@@ -145,7 +140,7 @@ namespace Umbraco.Web.PropertyEditors
}
catch (Exception ex)
{
- Logger.Error("An error occurred parsing the value stored in the image cropper value: " + property.Value.ToString(), ex);
+ Logger.Error("An error occurred parsing the value stored in the image cropper value: " + property.Value, ex);
continue;
}
@@ -170,8 +165,6 @@ namespace Umbraco.Web.PropertyEditors
isUpdated = true;
}
}
-
-
}
if (isUpdated)
@@ -182,12 +175,12 @@ namespace Umbraco.Web.PropertyEditors
}
}
- void MediaServiceCreated(IMediaService sender, Core.Events.NewEventArgs e)
+ internal void MediaServiceCreated(IMediaService sender, Core.Events.NewEventArgs e)
{
AutoFillProperties(e.Entity);
}
- void MediaServiceSaving(IMediaService sender, Core.Events.SaveEventArgs e)
+ internal void MediaServiceSaving(IMediaService sender, Core.Events.SaveEventArgs e)
{
foreach (var m in e.SavedEntities)
{
@@ -252,61 +245,5 @@ namespace Umbraco.Web.PropertyEditors
[PreValueField("crops", "Crop sizes", "views/propertyeditors/imagecropper/imagecropper.prevalues.html")]
public string Crops { get; set; }
}
-
- #region Application event handler, used to bind to events on startup
-
- private readonly FileUploadPropertyEditorApplicationStartup _applicationStartup;
-
- ///
- /// we're using a sub -class because this has the logic to prevent it from executing if the application is not configured
- ///
- private class FileUploadPropertyEditorApplicationStartup : ApplicationEventHandler
- {
- private readonly ImageCropperPropertyEditor _imageCropperPropertyEditor;
-
- public FileUploadPropertyEditorApplicationStartup(ImageCropperPropertyEditor imageCropperPropertyEditor)
- {
- _imageCropperPropertyEditor = imageCropperPropertyEditor;
- }
-
- ///
- /// We're going to bind to the MediaService Saving event so that we can populate the umbracoFile size, type, etc... label fields
- /// if we find any attached to the current media item.
- ///
- protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication)
- {
- MediaService.Saving += _imageCropperPropertyEditor.MediaServiceSaving;
- MediaService.Created += _imageCropperPropertyEditor.MediaServiceCreated;
- ContentService.Copied += _imageCropperPropertyEditor.ContentServiceCopied;
-
- MediaService.Deleted += (sender, args) =>
- args.MediaFilesToDelete.AddRange(_imageCropperPropertyEditor.ServiceDeleted(args.DeletedEntities.Cast()));
- MediaService.EmptiedRecycleBin += (sender, args) =>
- args.Files.AddRange(_imageCropperPropertyEditor.ServiceEmptiedRecycleBin(args.AllPropertyData));
- ContentService.Deleted += (sender, args) =>
- args.MediaFilesToDelete.AddRange(_imageCropperPropertyEditor.ServiceDeleted(args.DeletedEntities.Cast()));
- ContentService.EmptiedRecycleBin += (sender, args) =>
- args.Files.AddRange(_imageCropperPropertyEditor.ServiceEmptiedRecycleBin(args.AllPropertyData));
- MemberService.Deleted += (sender, args) =>
- args.MediaFilesToDelete.AddRange(_imageCropperPropertyEditor.ServiceDeleted(args.DeletedEntities.Cast()));
- }
- }
-
- public void OnApplicationInitialized(UmbracoApplicationBase umbracoApplication)
- {
- //wrap
- _applicationStartup.OnApplicationInitialized(umbracoApplication);
- }
- public void OnApplicationStarting(UmbracoApplicationBase umbracoApplication)
- {
- //wrap
- _applicationStartup.OnApplicationStarting(umbracoApplication);
- }
- public void OnApplicationStarted(UmbracoApplicationBase umbracoApplication)
- {
- //wrap
- _applicationStartup.OnApplicationStarted(umbracoApplication);
- }
- #endregion
}
}
diff --git a/src/Umbraco.Web/PropertyEditors/PropertyEditorsComponent.cs b/src/Umbraco.Web/PropertyEditors/PropertyEditorsComponent.cs
new file mode 100644
index 0000000000..86bc06f7fb
--- /dev/null
+++ b/src/Umbraco.Web/PropertyEditors/PropertyEditorsComponent.cs
@@ -0,0 +1,73 @@
+using System.Linq;
+using Umbraco.Core;
+using Umbraco.Core.Components;
+using Umbraco.Core.Models;
+using Umbraco.Core.PropertyEditors;
+using Umbraco.Core.Services;
+using UmbracoExamine;
+
+namespace Umbraco.Web.PropertyEditors
+{
+ internal class PropertyEditorsComponent : UmbracoComponentBase, IUmbracoCoreComponent
+ {
+ public void Initialize(IRuntimeState runtime, PropertyEditorCollection propertyEditors, IExamineIndexCollectionAccessor indexCollection)
+ {
+ if (runtime.Level != RuntimeLevel.Run) return;
+
+ var fileUpload = propertyEditors.OfType().FirstOrDefault();
+ if (fileUpload != null) Initialize(fileUpload);
+
+ var imageCropper = propertyEditors.OfType().FirstOrDefault();
+ if (imageCropper != null) Initialize(imageCropper);
+
+ var grid = propertyEditors.OfType().FirstOrDefault();
+ if (grid != null) Initialize(grid, indexCollection);
+ }
+
+ // as long as these methods are private+static they won't be executed by the boot loader
+
+ private static void Initialize(FileUploadPropertyEditor fileUpload)
+ {
+ MediaService.Saving += fileUpload.MediaServiceSaving;
+ MediaService.Created += fileUpload.MediaServiceCreating;
+ ContentService.Copied += fileUpload.ContentServiceCopied;
+
+ MediaService.Deleted += (sender, args)
+ => args.MediaFilesToDelete.AddRange(fileUpload.ServiceDeleted(args.DeletedEntities.Cast()));
+ MediaService.EmptiedRecycleBin += (sender, args)
+ => args.Files.AddRange(fileUpload.ServiceEmptiedRecycleBin(args.AllPropertyData));
+ ContentService.Deleted += (sender, args)
+ => args.MediaFilesToDelete.AddRange(fileUpload.ServiceDeleted(args.DeletedEntities.Cast()));
+ ContentService.EmptiedRecycleBin += (sender, args)
+ => args.Files.AddRange(fileUpload.ServiceEmptiedRecycleBin(args.AllPropertyData));
+ MemberService.Deleted += (sender, args)
+ => args.MediaFilesToDelete.AddRange(fileUpload.ServiceDeleted(args.DeletedEntities.Cast()));
+ }
+
+ private static void Initialize(ImageCropperPropertyEditor imageCropper)
+ {
+ MediaService.Saving += imageCropper.MediaServiceSaving;
+ MediaService.Created += imageCropper.MediaServiceCreated;
+ ContentService.Copied += imageCropper.ContentServiceCopied;
+
+ MediaService.Deleted += (sender, args)
+ => args.MediaFilesToDelete.AddRange(imageCropper.ServiceDeleted(args.DeletedEntities.Cast()));
+ MediaService.EmptiedRecycleBin += (sender, args)
+ => args.Files.AddRange(imageCropper.ServiceEmptiedRecycleBin(args.AllPropertyData));
+ ContentService.Deleted += (sender, args)
+ => args.MediaFilesToDelete.AddRange(imageCropper.ServiceDeleted(args.DeletedEntities.Cast()));
+ ContentService.EmptiedRecycleBin += (sender, args)
+ => args.Files.AddRange(imageCropper.ServiceEmptiedRecycleBin(args.AllPropertyData));
+ MemberService.Deleted += (sender, args)
+ => args.MediaFilesToDelete.AddRange(imageCropper.ServiceDeleted(args.DeletedEntities.Cast()));
+ }
+
+ private static void Initialize(GridPropertyEditor grid, IExamineIndexCollectionAccessor indexCollection)
+ {
+ var indexes = indexCollection.Indexes;
+ if (indexes == null) return;
+ foreach (var i in indexes.Values.OfType())
+ i.DocumentWriting += grid.DocumentWriting;
+ }
+ }
+}
diff --git a/src/Umbraco.Web/PublishedCache/NuCache/NuCacheComponent.cs b/src/Umbraco.Web/PublishedCache/NuCache/NuCacheComponent.cs
index 3e42cbed94..2d98eadd11 100644
--- a/src/Umbraco.Web/PublishedCache/NuCache/NuCacheComponent.cs
+++ b/src/Umbraco.Web/PublishedCache/NuCache/NuCacheComponent.cs
@@ -23,6 +23,11 @@ namespace Umbraco.Web.PublishedCache.NuCache
factory.GetInstance(),
factory.GetInstance(),
factory.GetInstance()));
+
+ // add the NuCache health check (hidden from type finder)
+ // todo - no NuCache health check yet
+ //var builder = container.GetInstance();
+ //builder.Add();
}
public void Initialize(IFacadeService service)
diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlCacheComponent.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlCacheComponent.cs
index 810603ea60..f823017ea2 100644
--- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlCacheComponent.cs
+++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlCacheComponent.cs
@@ -6,6 +6,8 @@ using Umbraco.Core.Persistence.UnitOfWork;
using Umbraco.Core.Services;
using Umbraco.Core.Strings;
using Umbraco.Core.DependencyInjection;
+using Umbraco.Web.HealthCheck;
+using Umbraco.Web.HealthCheck.Checks.DataIntegrity;
namespace Umbraco.Web.PublishedCache.XmlPublishedCache
{
@@ -24,6 +26,10 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
factory.GetAllInstances(),
factory.GetInstance(),
factory.GetInstance()));
+
+ // add the Xml cache health check (hidden from type finder)
+ var builder = container.GetInstance();
+ builder.Exclude();
}
public void Initialize(IFacadeService service)
diff --git a/src/Umbraco.Web/Redirects/RedirectTrackingEventHandler.cs b/src/Umbraco.Web/Redirects/RedirectTrackingComponent.cs
similarity index 97%
rename from src/Umbraco.Web/Redirects/RedirectTrackingEventHandler.cs
rename to src/Umbraco.Web/Redirects/RedirectTrackingComponent.cs
index becc9ed7d4..c23ca26f05 100644
--- a/src/Umbraco.Web/Redirects/RedirectTrackingEventHandler.cs
+++ b/src/Umbraco.Web/Redirects/RedirectTrackingComponent.cs
@@ -5,6 +5,7 @@ using Umbraco.Core.Services;
using Umbraco.Core.Events;
using System.Collections.Generic;
using Umbraco.Core.Cache;
+using Umbraco.Core.Components;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Sync;
using Umbraco.Web.Cache;
@@ -19,14 +20,13 @@ namespace Umbraco.Web.Redirects
/// not managing domains because we don't know how to do it - changing domains => must create a higher level strategy using rewriting rules probably
/// recycle bin = moving to and from does nothing: to = the node is gone, where would we redirect? from = same
///
- public class RedirectTrackingEventHandler : ApplicationEventHandler
+ public class RedirectTrackingComponent : UmbracoComponentBase, IUmbracoCoreComponent
{
private const string ContextKey1 = "Umbraco.Web.Redirects.RedirectTrackingEventHandler.1";
private const string ContextKey2 = "Umbraco.Web.Redirects.RedirectTrackingEventHandler.2";
private const string ContextKey3 = "Umbraco.Web.Redirects.RedirectTrackingEventHandler.3";
- ///
- protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication)
+ protected void Initialize()
{
// events are weird
// on 'published' we 'could' get the old or the new route depending on event handlers order
diff --git a/src/Umbraco.Web/Search/ExamineEvents.cs b/src/Umbraco.Web/Search/ExamineComponent.cs
similarity index 92%
rename from src/Umbraco.Web/Search/ExamineEvents.cs
rename to src/Umbraco.Web/Search/ExamineComponent.cs
index 835a31f46b..47eab1c9b7 100644
--- a/src/Umbraco.Web/Search/ExamineEvents.cs
+++ b/src/Umbraco.Web/Search/ExamineComponent.cs
@@ -1,345 +1,337 @@
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Linq;
-using System.Xml;
-using System.Xml.Linq;
-using Examine;
-using Examine.LuceneEngine;
-using Examine.Session;
-using Lucene.Net.Documents;
-using Umbraco.Core;
-using Umbraco.Core.Cache;
-using Umbraco.Core.Logging;
-using Umbraco.Core.Models;
-using Umbraco.Core.Services;
-using Umbraco.Core.Services.Changes;
-using Umbraco.Core.Sync;
-using Umbraco.Web.Cache;
-using UmbracoExamine;
-
-namespace Umbraco.Web.Search
-{
- ///
- /// Used to wire up events for Examine
- ///
- public sealed class ExamineEvents : ApplicationEventHandler
- {
-
- ///
- /// Once the application has started we should bind to all events and initialize the providers.
- ///
- ///
- ///
- ///
- /// We need to do this on the Started event as to guarantee that all resolvers are setup properly.
- ///
- protected override void ApplicationStarted(UmbracoApplicationBase httpApplication)
- {
- LogHelper.Info("Initializing Examine and binding to business logic events");
-
- //TODO: For now we'll make this true, it means that indexes will be near real time
- // we'll see about what implications this may have - should be great in most scenarios
- DefaultExamineSession.RequireImmediateConsistency = true;
-
- var registeredProviders = ExamineManager.Instance.IndexProviderCollection
- .OfType().Count(x => x.EnableDefaultEventHandler);
-
- LogHelper.Info("Adding examine event handlers for index providers: {0}", () => registeredProviders);
-
- // don't bind event handlers if we're not suppose to listen
- if (registeredProviders == 0)
- return;
-
- // bind to distributed cache events - this ensures that this logic occurs on ALL servers
- // that are taking part in a load balanced environment.
- ContentCacheRefresher.CacheUpdated += ContentCacheRefresherUpdated;
- MediaCacheRefresher.CacheUpdated += MediaCacheRefresherUpdated;
- MemberCacheRefresher.CacheUpdated += MemberCacheRefresherUpdated;
-
- var contentIndexer = ExamineManager.Instance.IndexProviderCollection["InternalIndexer"] as UmbracoContentIndexer;
- if (contentIndexer != null)
- {
- contentIndexer.DocumentWriting += IndexerDocumentWriting;
- }
- var memberIndexer = ExamineManager.Instance.IndexProviderCollection["InternalMemberIndexer"] as UmbracoMemberIndexer;
- if (memberIndexer != null)
- {
- memberIndexer.DocumentWriting += IndexerDocumentWriting;
- }
- }
-
- static void MemberCacheRefresherUpdated(MemberCacheRefresher sender, CacheRefresherEventArgs args)
- {
- switch (args.MessageType)
- {
- case MessageType.RefreshById:
- var c1 = Current.Services.MemberService.GetById((int)args.MessageObject);
- if (c1 != null)
- {
- ReIndexForMember(c1);
- }
- break;
- case MessageType.RemoveById:
-
- // This is triggered when the item is permanently deleted
-
- DeleteIndexForEntity((int)args.MessageObject, false);
- break;
- case MessageType.RefreshByInstance:
- var c3 = args.MessageObject as IMember;
- if (c3 != null)
- {
- ReIndexForMember(c3);
- }
- break;
- case MessageType.RemoveByInstance:
-
- // This is triggered when the item is permanently deleted
-
- var c4 = args.MessageObject as IMember;
- if (c4 != null)
- {
- DeleteIndexForEntity(c4.Id, false);
- }
- break;
- case MessageType.RefreshAll:
- case MessageType.RefreshByJson:
- default:
- //We don't support these, these message types will not fire for unpublished content
- break;
- }
- }
-
- static void MediaCacheRefresherUpdated(MediaCacheRefresher sender, CacheRefresherEventArgs args)
- {
- if (args.MessageType != MessageType.RefreshByPayload)
- throw new NotSupportedException();
-
- var mediaService = Current.Services.MediaService;
-
- foreach (var payload in (MediaCacheRefresher.JsonPayload[]) args.MessageObject)
- {
- if (payload.ChangeTypes.HasType(TreeChangeTypes.Remove))
- {
- // remove from *all* indexes
- DeleteIndexForEntity(payload.Id, false);
- }
- else if (payload.ChangeTypes.HasType(TreeChangeTypes.RefreshAll))
- {
- // ExamineEvents does not support RefreshAll
- // just ignore that payload
- // so what?!
- }
- else // RefreshNode or RefreshBranch (maybe trashed)
- {
- var media = mediaService.GetById(payload.Id);
- if (media == null || media.Trashed)
- {
- // gone fishing, remove entirely
- DeleteIndexForEntity(payload.Id, false);
- continue;
- }
-
- // just that media
- ReIndexForMedia(media, media.Trashed == false);
-
- // branch
- if (payload.ChangeTypes.HasType(TreeChangeTypes.RefreshBranch))
- {
- var descendants = mediaService.GetDescendants(media);
- foreach (var descendant in descendants)
- {
- ReIndexForMedia(descendant, descendant.Trashed == false);
- }
- }
- }
- }
- }
-
- static void ContentCacheRefresherUpdated(ContentCacheRefresher sender, CacheRefresherEventArgs args)
- {
- if (args.MessageType != MessageType.RefreshByPayload)
- throw new NotSupportedException();
-
- var contentService = Current.Services.ContentService;
-
- foreach (var payload in (ContentCacheRefresher.JsonPayload[]) args.MessageObject)
- {
- if (payload.ChangeTypes.HasType(TreeChangeTypes.Remove))
- {
- // delete content entirely (with descendants)
- // false: remove entirely from all indexes
- DeleteIndexForEntity(payload.Id, false);
- }
- else if (payload.ChangeTypes.HasType(TreeChangeTypes.RefreshAll))
- {
- // ExamineEvents does not support RefreshAll
- // just ignore that payload
- // so what?!
- }
- else // RefreshNode or RefreshBranch (maybe trashed)
- {
- // don't try to be too clever - refresh entirely
- // there has to be race conds in there ;-(
-
- var content = contentService.GetById(payload.Id);
- if (content == null || content.Trashed)
- {
- // gone fishing, remove entirely from all indexes (with descendants)
- DeleteIndexForEntity(payload.Id, false);
- continue;
- }
-
- IContent published = null;
- if (content.HasPublishedVersion && ((ContentService)contentService).IsPathPublished(content))
- {
- published = content.Published
- ? content
- : contentService.GetByVersion(content.PublishedVersionGuid);
- }
-
- // just that content
- ReIndexForContent(content, published);
-
- // branch
- if (payload.ChangeTypes.HasType(TreeChangeTypes.RefreshBranch))
- {
- var masked = published == null ? null : new List();
- var descendants = contentService.GetDescendants(content);
- foreach (var descendant in descendants)
- {
- published = null;
- if (masked != null) // else everything is masked
- {
- if (masked.Contains(descendant.ParentId) || descendant.HasPublishedVersion == false)
- {
- masked.Add(descendant.Id);
- }
- else
- {
- published = descendant.Published
- ? descendant
- : contentService.GetByVersion(descendant.PublishedVersionGuid);
- }
- }
-
- ReIndexForContent(descendant, published);
- }
- }
- }
-
- // NOTE
- //
- // DeleteIndexForEntity is handled by UmbracoContentIndexer.DeleteFromIndex() which takes
- // care of also deleting the descendants
- //
- // ReIndexForContent is NOT taking care of descendants so we have to reload everything
- // again in order to process the branch - we COULD improve that by just reloading the
- // XML from database instead of reloading content & re-serializing!
- }
- }
-
- private static void ReIndexForContent(IContent content, IContent published)
- {
- if (published != null && content.Version == published.Version)
- {
- ReIndexForContent(content); // same = both
- }
- else
- {
- if (published == null)
- {
- // remove 'published' - keep 'draft'
- DeleteIndexForEntity(content.Id, true);
- }
- else
- {
- // index 'published' - don't overwrite 'draft'
- ReIndexForContent(published, false);
- }
- ReIndexForContent(content, true); // index 'draft'
- }
- }
-
- private static void ReIndexForContent(IContent sender, bool? supportUnpublished = null)
- {
- var xml = sender.ToXml();
- //add an icon attribute to get indexed
- xml.Add(new XAttribute("icon", sender.ContentType.Icon));
-
- ExamineManager.Instance.ReIndexNode(
- xml, IndexTypes.Content,
- ExamineManager.Instance.IndexProviderCollection.OfType()
- // only for the specified indexers
- .Where(x => supportUnpublished.HasValue == false || supportUnpublished.Value == x.SupportUnpublishedContent)
- .Where(x => x.EnableDefaultEventHandler));
- }
-
- private static void ReIndexForMember(IMember member)
- {
- ExamineManager.Instance.ReIndexNode(
- member.ToXml(), IndexTypes.Member,
- ExamineManager.Instance.IndexProviderCollection.OfType()
- //ensure that only the providers are flagged to listen execute
- .Where(x => x.EnableDefaultEventHandler));
- }
-
- private static void ReIndexForMedia(IMedia sender, bool isMediaPublished)
- {
- var xml = sender.ToXml();
- //add an icon attribute to get indexed
- xml.Add(new XAttribute("icon", sender.ContentType.Icon));
-
- ExamineManager.Instance.ReIndexNode(
- xml, IndexTypes.Media,
- ExamineManager.Instance.IndexProviderCollection.OfType()
- // index this item for all indexers if the media is not trashed, otherwise if the item is trashed
- // then only index this for indexers supporting unpublished media
- .Where(x => isMediaPublished || (x.SupportUnpublishedContent))
- .Where(x => x.EnableDefaultEventHandler));
- }
-
- ///
- /// Remove items from any index that doesn't support unpublished content
- ///
- ///
- ///
- /// If true, indicates that we will only delete this item from indexes that don't support unpublished content.
- /// If false it will delete this from all indexes regardless.
- ///
- private static void DeleteIndexForEntity(int entityId, bool keepIfUnpublished)
- {
- ExamineManager.Instance.DeleteFromIndex(
- entityId.ToString(CultureInfo.InvariantCulture),
- ExamineManager.Instance.IndexProviderCollection.OfType()
- // if keepIfUnpublished == true then only delete this item from indexes not supporting unpublished content,
- // otherwise if keepIfUnpublished == false then remove from all indexes
- .Where(x => keepIfUnpublished == false || (x is UmbracoContentIndexer && ((UmbracoContentIndexer)x).SupportUnpublishedContent == false))
- .Where(x => x.EnableDefaultEventHandler));
- }
-
- ///
- /// Event handler to create a lower cased version of the node name, this is so we can support case-insensitive searching and still
- /// use the Whitespace Analyzer
- ///
- ///
- ///
-
- private static void IndexerDocumentWriting(object sender, DocumentWritingEventArgs e)
- {
- if (e.Fields.Keys.Contains("nodeName"))
- {
- //TODO: This logic should really be put into the content indexer instead of hidden here!!
-
- //add the lower cased version
- e.Document.Add(new Field("__nodeName",
- e.Fields["nodeName"].ToLower(),
- Field.Store.YES,
- Field.Index.ANALYZED,
- Field.TermVector.NO
- ));
- }
- }
- }
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Xml;
+using System.Xml.Linq;
+using Examine;
+using Examine.LuceneEngine;
+using Examine.Session;
+using Lucene.Net.Documents;
+using Umbraco.Core;
+using Umbraco.Core.Cache;
+using Umbraco.Core.Components;
+using Umbraco.Core.Logging;
+using Umbraco.Core.Models;
+using Umbraco.Core.Services;
+using Umbraco.Core.Services.Changes;
+using Umbraco.Core.Sync;
+using Umbraco.Web.Cache;
+using UmbracoExamine;
+
+namespace Umbraco.Web.Search
+{
+ ///
+ /// Used to wire up events for Examine
+ ///
+ public sealed class ExamineComponent : UmbracoComponentBase, IUmbracoCoreComponent
+ {
+ public void Initialize()
+ {
+ LogHelper.Info("Initializing Examine and binding to business logic events");
+
+ //TODO: For now we'll make this true, it means that indexes will be near real time
+ // we'll see about what implications this may have - should be great in most scenarios
+ DefaultExamineSession.RequireImmediateConsistency = true;
+
+ var registeredProviders = ExamineManager.Instance.IndexProviderCollection
+ .OfType().Count(x => x.EnableDefaultEventHandler);
+
+ LogHelper.Info("Adding examine event handlers for index providers: {0}", () => registeredProviders);
+
+ // don't bind event handlers if we're not suppose to listen
+ if (registeredProviders == 0)
+ return;
+
+ // bind to distributed cache events - this ensures that this logic occurs on ALL servers
+ // that are taking part in a load balanced environment.
+ ContentCacheRefresher.CacheUpdated += ContentCacheRefresherUpdated;
+ MediaCacheRefresher.CacheUpdated += MediaCacheRefresherUpdated;
+ MemberCacheRefresher.CacheUpdated += MemberCacheRefresherUpdated;
+
+ var contentIndexer = ExamineManager.Instance.IndexProviderCollection["InternalIndexer"] as UmbracoContentIndexer;
+ if (contentIndexer != null)
+ {
+ contentIndexer.DocumentWriting += IndexerDocumentWriting;
+ }
+ var memberIndexer = ExamineManager.Instance.IndexProviderCollection["InternalMemberIndexer"] as UmbracoMemberIndexer;
+ if (memberIndexer != null)
+ {
+ memberIndexer.DocumentWriting += IndexerDocumentWriting;
+ }
+ }
+
+ static void MemberCacheRefresherUpdated(MemberCacheRefresher sender, CacheRefresherEventArgs args)
+ {
+ switch (args.MessageType)
+ {
+ case MessageType.RefreshById:
+ var c1 = Current.Services.MemberService.GetById((int)args.MessageObject);
+ if (c1 != null)
+ {
+ ReIndexForMember(c1);
+ }
+ break;
+ case MessageType.RemoveById:
+
+ // This is triggered when the item is permanently deleted
+
+ DeleteIndexForEntity((int)args.MessageObject, false);
+ break;
+ case MessageType.RefreshByInstance:
+ var c3 = args.MessageObject as IMember;
+ if (c3 != null)
+ {
+ ReIndexForMember(c3);
+ }
+ break;
+ case MessageType.RemoveByInstance:
+
+ // This is triggered when the item is permanently deleted
+
+ var c4 = args.MessageObject as IMember;
+ if (c4 != null)
+ {
+ DeleteIndexForEntity(c4.Id, false);
+ }
+ break;
+ case MessageType.RefreshAll:
+ case MessageType.RefreshByJson:
+ default:
+ //We don't support these, these message types will not fire for unpublished content
+ break;
+ }
+ }
+
+ static void MediaCacheRefresherUpdated(MediaCacheRefresher sender, CacheRefresherEventArgs args)
+ {
+ if (args.MessageType != MessageType.RefreshByPayload)
+ throw new NotSupportedException();
+
+ var mediaService = Current.Services.MediaService;
+
+ foreach (var payload in (MediaCacheRefresher.JsonPayload[]) args.MessageObject)
+ {
+ if (payload.ChangeTypes.HasType(TreeChangeTypes.Remove))
+ {
+ // remove from *all* indexes
+ DeleteIndexForEntity(payload.Id, false);
+ }
+ else if (payload.ChangeTypes.HasType(TreeChangeTypes.RefreshAll))
+ {
+ // ExamineEvents does not support RefreshAll
+ // just ignore that payload
+ // so what?!
+ }
+ else // RefreshNode or RefreshBranch (maybe trashed)
+ {
+ var media = mediaService.GetById(payload.Id);
+ if (media == null || media.Trashed)
+ {
+ // gone fishing, remove entirely
+ DeleteIndexForEntity(payload.Id, false);
+ continue;
+ }
+
+ // just that media
+ ReIndexForMedia(media, media.Trashed == false);
+
+ // branch
+ if (payload.ChangeTypes.HasType(TreeChangeTypes.RefreshBranch))
+ {
+ var descendants = mediaService.GetDescendants(media);
+ foreach (var descendant in descendants)
+ {
+ ReIndexForMedia(descendant, descendant.Trashed == false);
+ }
+ }
+ }
+ }
+ }
+
+ static void ContentCacheRefresherUpdated(ContentCacheRefresher sender, CacheRefresherEventArgs args)
+ {
+ if (args.MessageType != MessageType.RefreshByPayload)
+ throw new NotSupportedException();
+
+ var contentService = Current.Services.ContentService;
+
+ foreach (var payload in (ContentCacheRefresher.JsonPayload[]) args.MessageObject)
+ {
+ if (payload.ChangeTypes.HasType(TreeChangeTypes.Remove))
+ {
+ // delete content entirely (with descendants)
+ // false: remove entirely from all indexes
+ DeleteIndexForEntity(payload.Id, false);
+ }
+ else if (payload.ChangeTypes.HasType(TreeChangeTypes.RefreshAll))
+ {
+ // ExamineEvents does not support RefreshAll
+ // just ignore that payload
+ // so what?!
+ }
+ else // RefreshNode or RefreshBranch (maybe trashed)
+ {
+ // don't try to be too clever - refresh entirely
+ // there has to be race conds in there ;-(
+
+ var content = contentService.GetById(payload.Id);
+ if (content == null || content.Trashed)
+ {
+ // gone fishing, remove entirely from all indexes (with descendants)
+ DeleteIndexForEntity(payload.Id, false);
+ continue;
+ }
+
+ IContent published = null;
+ if (content.HasPublishedVersion && ((ContentService)contentService).IsPathPublished(content))
+ {
+ published = content.Published
+ ? content
+ : contentService.GetByVersion(content.PublishedVersionGuid);
+ }
+
+ // just that content
+ ReIndexForContent(content, published);
+
+ // branch
+ if (payload.ChangeTypes.HasType(TreeChangeTypes.RefreshBranch))
+ {
+ var masked = published == null ? null : new List();
+ var descendants = contentService.GetDescendants(content);
+ foreach (var descendant in descendants)
+ {
+ published = null;
+ if (masked != null) // else everything is masked
+ {
+ if (masked.Contains(descendant.ParentId) || descendant.HasPublishedVersion == false)
+ {
+ masked.Add(descendant.Id);
+ }
+ else
+ {
+ published = descendant.Published
+ ? descendant
+ : contentService.GetByVersion(descendant.PublishedVersionGuid);
+ }
+ }
+
+ ReIndexForContent(descendant, published);
+ }
+ }
+ }
+
+ // NOTE
+ //
+ // DeleteIndexForEntity is handled by UmbracoContentIndexer.DeleteFromIndex() which takes
+ // care of also deleting the descendants
+ //
+ // ReIndexForContent is NOT taking care of descendants so we have to reload everything
+ // again in order to process the branch - we COULD improve that by just reloading the
+ // XML from database instead of reloading content & re-serializing!
+ }
+ }
+
+ private static void ReIndexForContent(IContent content, IContent published)
+ {
+ if (published != null && content.Version == published.Version)
+ {
+ ReIndexForContent(content); // same = both
+ }
+ else
+ {
+ if (published == null)
+ {
+ // remove 'published' - keep 'draft'
+ DeleteIndexForEntity(content.Id, true);
+ }
+ else
+ {
+ // index 'published' - don't overwrite 'draft'
+ ReIndexForContent(published, false);
+ }
+ ReIndexForContent(content, true); // index 'draft'
+ }
+ }
+
+ private static void ReIndexForContent(IContent sender, bool? supportUnpublished = null)
+ {
+ var xml = sender.ToXml();
+ //add an icon attribute to get indexed
+ xml.Add(new XAttribute("icon", sender.ContentType.Icon));
+
+ ExamineManager.Instance.ReIndexNode(
+ xml, IndexTypes.Content,
+ ExamineManager.Instance.IndexProviderCollection.OfType()
+ // only for the specified indexers
+ .Where(x => supportUnpublished.HasValue == false || supportUnpublished.Value == x.SupportUnpublishedContent)
+ .Where(x => x.EnableDefaultEventHandler));
+ }
+
+ private static void ReIndexForMember(IMember member)
+ {
+ ExamineManager.Instance.ReIndexNode(
+ member.ToXml(), IndexTypes.Member,
+ ExamineManager.Instance.IndexProviderCollection.OfType()
+ //ensure that only the providers are flagged to listen execute
+ .Where(x => x.EnableDefaultEventHandler));
+ }
+
+ private static void ReIndexForMedia(IMedia sender, bool isMediaPublished)
+ {
+ var xml = sender.ToXml();
+ //add an icon attribute to get indexed
+ xml.Add(new XAttribute("icon", sender.ContentType.Icon));
+
+ ExamineManager.Instance.ReIndexNode(
+ xml, IndexTypes.Media,
+ ExamineManager.Instance.IndexProviderCollection.OfType()
+ // index this item for all indexers if the media is not trashed, otherwise if the item is trashed
+ // then only index this for indexers supporting unpublished media
+ .Where(x => isMediaPublished || (x.SupportUnpublishedContent))
+ .Where(x => x.EnableDefaultEventHandler));
+ }
+
+ ///
+ /// Remove items from any index that doesn't support unpublished content
+ ///
+ ///
+ ///
+ /// If true, indicates that we will only delete this item from indexes that don't support unpublished content.
+ /// If false it will delete this from all indexes regardless.
+ ///
+ private static void DeleteIndexForEntity(int entityId, bool keepIfUnpublished)
+ {
+ ExamineManager.Instance.DeleteFromIndex(
+ entityId.ToString(CultureInfo.InvariantCulture),
+ ExamineManager.Instance.IndexProviderCollection.OfType()
+ // if keepIfUnpublished == true then only delete this item from indexes not supporting unpublished content,
+ // otherwise if keepIfUnpublished == false then remove from all indexes
+ .Where(x => keepIfUnpublished == false || (x is UmbracoContentIndexer && ((UmbracoContentIndexer)x).SupportUnpublishedContent == false))
+ .Where(x => x.EnableDefaultEventHandler));
+ }
+
+ ///
+ /// Event handler to create a lower cased version of the node name, this is so we can support case-insensitive searching and still
+ /// use the Whitespace Analyzer
+ ///
+ ///
+ ///
+
+ private static void IndexerDocumentWriting(object sender, DocumentWritingEventArgs e)
+ {
+ if (e.Fields.Keys.Contains("nodeName"))
+ {
+ //TODO: This logic should really be put into the content indexer instead of hidden here!!
+
+ //add the lower cased version
+ e.Document.Add(new Field("__nodeName",
+ e.Fields["nodeName"].ToLower(),
+ Field.Store.YES,
+ Field.Index.ANALYZED,
+ Field.TermVector.NO
+ ));
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Strategies/Migrations/ClearCsrfCookiesAfterUpgrade.cs b/src/Umbraco.Web/Strategies/Migrations/ClearCsrfCookiesAfterUpgrade.cs
index f40490c2d1..ecf3409a7c 100644
--- a/src/Umbraco.Web/Strategies/Migrations/ClearCsrfCookiesAfterUpgrade.cs
+++ b/src/Umbraco.Web/Strategies/Migrations/ClearCsrfCookiesAfterUpgrade.cs
@@ -1,5 +1,4 @@
-using System.Linq;
-using System.Web;
+using System.Web;
using Umbraco.Core.Events;
using Umbraco.Core.Persistence.Migrations;
using Umbraco.Web.WebApi.Filters;
@@ -10,16 +9,14 @@ namespace Umbraco.Web.Strategies.Migrations
///
/// After upgrade we clear out the csrf tokens
///
- public class ClearCsrfCookiesAfterUpgrade : MigrationStartupHandler
+ public class ClearCsrfCookiesAfterUpgrade : IPostMigration
{
- protected override void AfterMigration(MigrationRunner sender, MigrationEventArgs e)
+ public void Migrated(MigrationRunner sender, MigrationEventArgs args)
{
- if (e.ProductName != GlobalSettings.UmbracoMigrationName) return;
-
+ if (args.ProductName != GlobalSettings.UmbracoMigrationName) return;
if (HttpContext.Current == null) return;
var http = new HttpContextWrapper(HttpContext.Current);
-
http.ExpireCookie(AngularAntiForgeryHelper.AngularCookieName);
http.ExpireCookie(AngularAntiForgeryHelper.CsrfValidationCookieName);
}
diff --git a/src/Umbraco.Web/Strategies/Migrations/ClearMediaXmlCacheForDeletedItemsAfterUpgrade.cs b/src/Umbraco.Web/Strategies/Migrations/ClearMediaXmlCacheForDeletedItemsAfterUpgrade.cs
index e0e55e0405..a13396fc91 100644
--- a/src/Umbraco.Web/Strategies/Migrations/ClearMediaXmlCacheForDeletedItemsAfterUpgrade.cs
+++ b/src/Umbraco.Web/Strategies/Migrations/ClearMediaXmlCacheForDeletedItemsAfterUpgrade.cs
@@ -3,7 +3,6 @@ using Umbraco.Core;
using Umbraco.Core.Events;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.Migrations;
-using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Core.Configuration;
namespace Umbraco.Web.Strategies.Migrations
@@ -16,27 +15,27 @@ namespace Umbraco.Web.Strategies.Migrations
///
/// * If current is less than or equal to 7.0.0
///
- public class ClearMediaXmlCacheForDeletedItemsAfterUpgrade : MigrationStartupHandler
+ public class ClearMediaXmlCacheForDeletedItemsAfterUpgrade : IPostMigration
{
- protected override void AfterMigration(MigrationRunner sender, MigrationEventArgs e)
+ public void Migrated(MigrationRunner sender, MigrationEventArgs args)
{
- if (e.ProductName != GlobalSettings.UmbracoMigrationName) return;
+ if (args.ProductName != GlobalSettings.UmbracoMigrationName) return;
var target70 = new Version(7, 0, 0);
- if (e.ConfiguredVersion <= target70)
+ if (args.ConfiguredVersion <= target70)
{
//This query is structured to work with MySql, SQLCE and SqlServer:
// http://issues.umbraco.org/issue/U4-3876
- var syntax = e.MigrationContext.Database.SqlSyntax;
+ var syntax = args.MigrationContext.Database.SqlSyntax;
var sql = @"DELETE FROM cmsContentXml WHERE nodeId IN
(SELECT nodeId FROM (SELECT DISTINCT cmsContentXml.nodeId FROM cmsContentXml
INNER JOIN umbracoNode ON cmsContentXml.nodeId = umbracoNode.id
WHERE nodeObjectType = '" + Constants.ObjectTypes.Media + "' AND " + syntax.GetQuotedColumnName("path") + " LIKE '%-21%') x)";
- var count = e.MigrationContext.Database.Execute(sql);
+ var count = args.MigrationContext.Database.Execute(sql);
LogHelper.Info("Cleared " + count + " items from the media xml cache that were trashed and not meant to be there");
}
diff --git a/src/Umbraco.Web/Strategies/Migrations/EnsureListViewDataTypeIsCreated.cs b/src/Umbraco.Web/Strategies/Migrations/EnsureListViewDataTypeIsCreated.cs
index 65f8abf7a0..63353ae0cd 100644
--- a/src/Umbraco.Web/Strategies/Migrations/EnsureListViewDataTypeIsCreated.cs
+++ b/src/Umbraco.Web/Strategies/Migrations/EnsureListViewDataTypeIsCreated.cs
@@ -1,15 +1,9 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
using NPoco;
using Umbraco.Core;
using Umbraco.Core.Events;
-using Umbraco.Core.Models;
using Umbraco.Core.Models.Rdbms;
-using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Migrations;
-using Umbraco.Core.Persistence.SqlSyntax;
-using Umbraco.Core.Persistence.UnitOfWork;
using Umbraco.Core.Configuration;
namespace Umbraco.Web.Strategies.Migrations
@@ -17,17 +11,17 @@ namespace Umbraco.Web.Strategies.Migrations
///
/// Creates the built in list view data types
///
- public class EnsureDefaultListViewDataTypesCreated : MigrationStartupHandler
+ public class EnsureDefaultListViewDataTypesCreated : IPostMigration
{
- protected override void AfterMigration(MigrationRunner sender, MigrationEventArgs e)
+ public void Migrated(MigrationRunner sender, MigrationEventArgs args)
{
- if (e.ProductName != GlobalSettings.UmbracoMigrationName) return;
+ if (args.ProductName != GlobalSettings.UmbracoMigrationName) return;
var target720 = new Version(7, 2, 0);
- if (e.ConfiguredVersion <= target720)
+ if (args.ConfiguredVersion <= target720)
{
- EnsureListViewDataTypeCreated(e);
+ EnsureListViewDataTypeCreated(args);
}
}
diff --git a/src/Umbraco.Web/Strategies/Migrations/IPostMigration.cs b/src/Umbraco.Web/Strategies/Migrations/IPostMigration.cs
new file mode 100644
index 0000000000..16e3a6e22b
--- /dev/null
+++ b/src/Umbraco.Web/Strategies/Migrations/IPostMigration.cs
@@ -0,0 +1,10 @@
+using Umbraco.Core.Events;
+using Umbraco.Core.Persistence.Migrations;
+
+namespace Umbraco.Web.Strategies.Migrations
+{
+ public interface IPostMigration
+ {
+ void Migrated(MigrationRunner runner, MigrationEventArgs args);
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Strategies/Migrations/MigrationStartupHandler.cs b/src/Umbraco.Web/Strategies/Migrations/MigrationStartupHandler.cs
deleted file mode 100644
index 8bfda241ff..0000000000
--- a/src/Umbraco.Web/Strategies/Migrations/MigrationStartupHandler.cs
+++ /dev/null
@@ -1,82 +0,0 @@
-using System;
-using System.Linq;
-using Umbraco.Core;
-using Umbraco.Core.Persistence.Migrations;
-
-namespace Umbraco.Web.Strategies.Migrations
-{
- ///
- /// Base class that can be used to run code after the migration runner has executed
- ///
- public abstract class MigrationStartupHandler : ApplicationEventHandler, IDisposable
- {
- private bool _disposed;
-
- ///
- /// Ensure this is run when not configured
- ///
- protected override bool ExecuteWhenApplicationNotConfigured
- {
- get { return true; }
- }
-
- ///
- /// Ensure this is run when not configured
- ///
- protected override bool ExecuteWhenDatabaseNotConfigured
- {
- get { return true; }
- }
-
- public void Unsubscribe()
- {
- MigrationRunner.Migrated -= MigrationRunner_Migrated;
- }
-
- ///
- /// Attach to event on starting
- ///
- ///
- ///
- protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication)
- {
- MigrationRunner.Migrated += MigrationRunner_Migrated;
- }
-
- private void MigrationRunner_Migrated(MigrationRunner sender, Core.Events.MigrationEventArgs e)
- {
- if (TargetProductNames.Length == 0 || TargetProductNames.Contains(e.ProductName))
- {
- AfterMigration(sender, e);
- }
- }
-
- protected abstract void AfterMigration(MigrationRunner sender, Core.Events.MigrationEventArgs e);
-
- ///
- /// Override to specify explicit target product names
- ///
- ///
- /// Leaving empty will run for all migration products
- ///
- public virtual string[] TargetProductNames { get { return new string[] {}; } }
-
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- ~MigrationStartupHandler()
- {
- Dispose(false);
- }
-
- protected virtual void Dispose(bool disposing)
- {
- if (_disposed) return;
- _disposed = true;
- Unsubscribe();
- }
- }
-}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Strategies/Migrations/OverwriteStylesheetFilesFromTempFiles.cs b/src/Umbraco.Web/Strategies/Migrations/OverwriteStylesheetFilesFromTempFiles.cs
index d8e5ded98f..0b842f683f 100644
--- a/src/Umbraco.Web/Strategies/Migrations/OverwriteStylesheetFilesFromTempFiles.cs
+++ b/src/Umbraco.Web/Strategies/Migrations/OverwriteStylesheetFilesFromTempFiles.cs
@@ -1,9 +1,5 @@
using System;
-using System.Collections.Generic;
using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using Umbraco.Core.Events;
using Umbraco.Core;
using Umbraco.Core.Configuration;
@@ -19,15 +15,15 @@ namespace Umbraco.Web.Strategies.Migrations
/// files during the migration since other parts of the migration might fail. So once the migration is complete, we'll then copy over the temp
/// files that this migration created over top of the developer's files. We'll also create a backup of their files.
///
- public sealed class OverwriteStylesheetFilesFromTempFiles : MigrationStartupHandler
+ public sealed class OverwriteStylesheetFilesFromTempFiles : IPostMigration
{
- protected override void AfterMigration(MigrationRunner sender, MigrationEventArgs e)
+ public void Migrated(MigrationRunner sender, MigrationEventArgs args)
{
- if (e.ProductName != GlobalSettings.UmbracoMigrationName) return;
+ if (args.ProductName != GlobalSettings.UmbracoMigrationName) return;
var target73 = new Version(7, 3, 0);
- if (e.ConfiguredVersion <= target73)
+ if (args.ConfiguredVersion <= target73)
{
var tempCssFolder = IOHelper.MapPath("~/App_Data/TEMP/CssMigration/");
var cssFolder = IOHelper.MapPath("~/css");
@@ -42,7 +38,7 @@ namespace Umbraco.Web.Strategies.Migrations
{
//backup
var targetPath = Path.Combine(tempCssFolder, relativePath.EnsureEndsWith(".bak"));
- e.MigrationContext.Logger.Info("CSS file is being backed up from {0}, to {1} before being migrated to new format", () => cssFilePath, () => targetPath);
+ args.MigrationContext.Logger.Info("CSS file is being backed up from {0}, to {1} before being migrated to new format", () => cssFilePath, () => targetPath);
File.Copy(cssFilePath, targetPath, true);
}
diff --git a/src/Umbraco.Web/Strategies/Migrations/PostMigrationCollection.cs b/src/Umbraco.Web/Strategies/Migrations/PostMigrationCollection.cs
new file mode 100644
index 0000000000..58c04e44e3
--- /dev/null
+++ b/src/Umbraco.Web/Strategies/Migrations/PostMigrationCollection.cs
@@ -0,0 +1,12 @@
+using System.Collections.Generic;
+using Umbraco.Core.DependencyInjection;
+
+namespace Umbraco.Web.Strategies.Migrations
+{
+ public class PostMigrationCollection : BuilderCollectionBase
+ {
+ public PostMigrationCollection(IEnumerable items)
+ : base(items)
+ { }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Strategies/Migrations/PostMigrationCollectionBuilder.cs b/src/Umbraco.Web/Strategies/Migrations/PostMigrationCollectionBuilder.cs
new file mode 100644
index 0000000000..63683c1edb
--- /dev/null
+++ b/src/Umbraco.Web/Strategies/Migrations/PostMigrationCollectionBuilder.cs
@@ -0,0 +1,16 @@
+using LightInject;
+using Umbraco.Core.DependencyInjection;
+
+namespace Umbraco.Web.Strategies.Migrations
+{
+ public class PostMigrationCollectionBuilder : LazyCollectionBuilderBase
+ {
+ public PostMigrationCollectionBuilder(IServiceContainer container)
+ : base(container)
+ { }
+
+ protected override PostMigrationCollectionBuilder This => this;
+
+ protected override ILifetime CollectionLifetime => null; // transient
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Strategies/Migrations/PostMigrationComponent.cs b/src/Umbraco.Web/Strategies/Migrations/PostMigrationComponent.cs
new file mode 100644
index 0000000000..3d4d76a95d
--- /dev/null
+++ b/src/Umbraco.Web/Strategies/Migrations/PostMigrationComponent.cs
@@ -0,0 +1,24 @@
+using LightInject;
+using Umbraco.Core.Components;
+using Umbraco.Core.Persistence.Migrations;
+using Umbraco.Core.Plugins;
+
+namespace Umbraco.Web.Strategies.Migrations
+{
+ public class PostMigrationComponent : UmbracoComponentBase, IUmbracoCoreComponent
+ {
+ public override void Compose(ServiceContainer container)
+ {
+ PostMigrationCollectionBuilder.Register(container)
+ .AddProducer(factory => factory.GetInstance().ResolveTypes());
+ }
+
+ public void Initialize(PostMigrationCollection posts)
+ {
+ // whatever the runtime level, ie also when installing or upgrading
+
+ foreach (var post in posts)
+ MigrationRunner.Migrated += post.Migrated;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Strategies/Migrations/PublishAfterUpgradeToVersionSixth.cs b/src/Umbraco.Web/Strategies/Migrations/PublishAfterUpgradeToVersionSixth.cs
index 66a412c1ff..5a80c4458a 100644
--- a/src/Umbraco.Web/Strategies/Migrations/PublishAfterUpgradeToVersionSixth.cs
+++ b/src/Umbraco.Web/Strategies/Migrations/PublishAfterUpgradeToVersionSixth.cs
@@ -1,14 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using NPoco;
using Umbraco.Core.Events;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Migrations;
-using Umbraco.Core.Persistence.UnitOfWork;
using Umbraco.Core;
-using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Core.Configuration;
namespace Umbraco.Web.Strategies.Migrations
@@ -17,16 +14,16 @@ namespace Umbraco.Web.Strategies.Migrations
/// This event ensures that upgrades from (configured) versions lower then 6.0.0
/// have their publish state updated after the database schema has been migrated.
///
- public class PublishAfterUpgradeToVersionSixth : MigrationStartupHandler
+ public class PublishAfterUpgradeToVersionSixth : IPostMigration
{
- protected override void AfterMigration(MigrationRunner sender, MigrationEventArgs e)
+ public void Migrated(MigrationRunner sender, MigrationEventArgs args)
{
- if (e.ProductName != GlobalSettings.UmbracoMigrationName) return;
+ if (args.ProductName != GlobalSettings.UmbracoMigrationName) return;
var target = new Version(6, 0, 0);
- if (e.ConfiguredVersion < target)
+ if (args.ConfiguredVersion < target)
{
- var sql = e.MigrationContext.Database.Sql()
+ var sql = args.MigrationContext.Database.Sql()
.SelectAll()
.From()
.InnerJoin()
@@ -38,7 +35,7 @@ namespace Umbraco.Web.Strategies.Migrations
.Where(x => x.NodeObjectType == new Guid(Constants.ObjectTypes.Document))
.Where(x => x.Path.StartsWith("-1"));
- var dtos = e.MigrationContext.Database.Fetch(sql);
+ var dtos = args.MigrationContext.Database.Fetch(sql);
var toUpdate = new List();
var versionGroup = dtos.GroupBy(x => x.NodeId);
foreach (var grp in versionGroup)
@@ -62,12 +59,12 @@ namespace Umbraco.Web.Strategies.Migrations
}
//Commit the updated entries for the cmsDocument table
- using (var transaction = e.MigrationContext.Database.GetTransaction())
+ using (var transaction = args.MigrationContext.Database.GetTransaction())
{
//Loop through the toUpdate
foreach (var dto in toUpdate)
{
- e.MigrationContext.Database.Update(dto);
+ args.MigrationContext.Database.Update(dto);
}
transaction.Complete();
diff --git a/src/Umbraco.Web/Strategies/Migrations/RebuildMediaXmlCacheAfterUpgrade.cs b/src/Umbraco.Web/Strategies/Migrations/RebuildMediaXmlCacheAfterUpgrade.cs
index ca478cd1b3..ded50bf671 100644
--- a/src/Umbraco.Web/Strategies/Migrations/RebuildMediaXmlCacheAfterUpgrade.cs
+++ b/src/Umbraco.Web/Strategies/Migrations/RebuildMediaXmlCacheAfterUpgrade.cs
@@ -1,10 +1,7 @@
using System;
-using Umbraco.Core;
using Umbraco.Core.Events;
using Umbraco.Core.Persistence.Migrations;
-using Umbraco.Core.Services;
using Umbraco.Core.Configuration;
-using Umbraco.Web.PublishedCache;
using Umbraco.Web.PublishedCache.XmlPublishedCache;
namespace Umbraco.Web.Strategies.Migrations
@@ -19,15 +16,15 @@ namespace Umbraco.Web.Strategies.Migrations
///
/// * If current is less than or equal to 7.0.0
///
- public class RebuildMediaXmlCacheAfterUpgrade : MigrationStartupHandler
+ public class RebuildMediaXmlCacheAfterUpgrade : IPostMigration
{
- protected override void AfterMigration(MigrationRunner sender, MigrationEventArgs e)
+ public void Migrated(MigrationRunner sender, MigrationEventArgs args)
{
- if (e.ProductName != GlobalSettings.UmbracoMigrationName) return;
+ if (args.ProductName != GlobalSettings.UmbracoMigrationName) return;
var target70 = new Version(7, 0, 0);
- if (e.ConfiguredVersion <= target70)
+ if (args.ConfiguredVersion <= target70)
{
// maintain - for backward compatibility?
//var mediasvc = (MediaService)ApplicationContext.Current.Services.MediaService;
diff --git a/src/Umbraco.Web/Strategies/PublicAccessEventHandler.cs b/src/Umbraco.Web/Strategies/PublicAccessComponent.cs
similarity index 71%
rename from src/Umbraco.Web/Strategies/PublicAccessEventHandler.cs
rename to src/Umbraco.Web/Strategies/PublicAccessComponent.cs
index 275b00c72f..3dcb723cd9 100644
--- a/src/Umbraco.Web/Strategies/PublicAccessEventHandler.cs
+++ b/src/Umbraco.Web/Strategies/PublicAccessComponent.cs
@@ -1,10 +1,5 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using umbraco.cms.businesslogic.web;
-using Umbraco.Core;
-using Umbraco.Core.Models.EntityBase;
+using Umbraco.Core;
+using Umbraco.Core.Components;
using Umbraco.Core.Services;
namespace Umbraco.Web.Strategies
@@ -12,12 +7,10 @@ namespace Umbraco.Web.Strategies
///
/// Used to ensure that the public access data file is kept up to date properly
///
- public sealed class PublicAccessEventHandler : ApplicationEventHandler
+ public sealed class PublicAccessComponent : UmbracoComponentBase, IUmbracoCoreComponent
{
- protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication)
+ public void Initialize()
{
- base.ApplicationStarted(umbracoApplication);
-
MemberGroupService.Saved += MemberGroupService_Saved;
}
diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj
index e1f1f85129..6091433e57 100644
--- a/src/Umbraco.Web/Umbraco.Web.csproj
+++ b/src/Umbraco.Web/Umbraco.Web.csproj
@@ -208,7 +208,6 @@
-
@@ -220,6 +219,7 @@
+
@@ -277,6 +277,10 @@
+
+
+
+
@@ -377,7 +381,7 @@
-
+
@@ -431,7 +435,7 @@
-
+
@@ -652,7 +656,6 @@
-
@@ -855,7 +858,7 @@
-
+
@@ -984,7 +987,7 @@
-
+
@@ -1106,7 +1109,6 @@
-
Code
diff --git a/src/Umbraco.Web/UmbracoContext.cs b/src/Umbraco.Web/UmbracoContext.cs
index fc07c6c55f..a7b06ce656 100644
--- a/src/Umbraco.Web/UmbracoContext.cs
+++ b/src/Umbraco.Web/UmbracoContext.cs
@@ -4,7 +4,6 @@ using System.Web;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
-using Umbraco.Core.Logging;
using Umbraco.Web.PublishedCache;
using Umbraco.Web.Routing;
using Umbraco.Web.Security;
diff --git a/src/Umbraco.Web/WebRuntimeComponent.cs b/src/Umbraco.Web/WebRuntimeComponent.cs
index 0696d68f5b..6538641509 100644
--- a/src/Umbraco.Web/WebRuntimeComponent.cs
+++ b/src/Umbraco.Web/WebRuntimeComponent.cs
@@ -20,7 +20,6 @@ using Umbraco.Core.Dictionary;
using Umbraco.Core.Events;
using Umbraco.Core.Logging;
using Umbraco.Core.Macros;
-using Umbraco.Core.Persistence;
using Umbraco.Core.Plugins;
using Umbraco.Core.Profiling;
using Umbraco.Core.PropertyEditors;
@@ -33,7 +32,6 @@ using Umbraco.Web.DependencyInjection;
using Umbraco.Web.Dictionary;
using Umbraco.Web.Editors;
using Umbraco.Web.HealthCheck;
-using Umbraco.Web.HealthCheck.Checks.DataIntegrity;
using Umbraco.Web.Install;
using Umbraco.Web.Media;
using Umbraco.Web.Media.ThumbnailProviders;
@@ -67,8 +65,6 @@ namespace Umbraco.Web
// 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.
- // fixme - move that one to runtime
- //container.RegisterSingleton(); // replaces HttpContext.Current
container.RegisterSingleton();
// register the 'current' umbraco context - transient - for eg controllers
@@ -81,11 +77,6 @@ namespace Umbraco.Web
// register the facade accessor - the "current" facade is in the umbraco context
container.RegisterSingleton();
- // register the umbraco database accessor
- // have to use the hybrid thing...
- // fixme moving to runtime
- //container.RegisterSingleton();
-
// register a per-request UmbracoContext object
// no real need to be per request but assuming it is faster
container.Register(factory => factory.GetInstance().UmbracoContext, new PerRequestLifeTime());
@@ -102,9 +93,6 @@ namespace Umbraco.Web
container.RegisterSingleton();
- // fixme - still, doing it before we get the INITIALIZE scope is a BAD idea
- // fixme - also note that whatever you REGISTER in a scope, stays registered => create the scope beforehand?
- // fixme - BUT not enough, once per-request is enabled it WANTS per-request scope even though a scope already exists
// IoC setup for LightInject for MVC/WebApi
// see comments on MixedScopeManagerProvider for explainations of what we are doing here
var smp = container.ScopeManagerProvider as MixedScopeManagerProvider;
@@ -186,16 +174,15 @@ namespace Umbraco.Web
container.RegisterSingleton();
+ // register *all* checks, except those marked [HideFromTypeFinder] of course
HealthCheckCollectionBuilder.Register(container)
- .AddProducer(() => pluginManager.ResolveTypes())
- .Exclude(); // fixme must remove else NuCache dies!
- // but we should also have one for NuCache AND NuCache should be a component that does all this
+ .AddProducer(() => pluginManager.ResolveTypes());
- // fixme - will this work? others?
+ // auto-register views
container.RegisterAuto(typeof(UmbracoViewPage<>));
}
- private void ComposeLegacyMessenger(ServiceContainer container, RuntimeLevel runtimeLevel, ILogger logger)
+ private static void ComposeLegacyMessenger(IServiceRegistry container, RuntimeLevel runtimeLevel, ILogger logger)
{
//set the legacy one by default - this maintains backwards compat
container.Register(factory =>
@@ -224,7 +211,7 @@ namespace Umbraco.Web
}, new PerContainerLifetime());
}
- private void ComposeMessenger(ServiceContainer container, ILogger logger, ProfilingLogger proflog)
+ private static void ComposeMessenger(IServiceRegistry container, ILogger logger, ProfilingLogger proflog)
{
container.Register(factory =>
{
@@ -263,13 +250,10 @@ namespace Umbraco.Web
}
internal void Initialize(
- UmbracoApplicationBase umbracoApplication,
IRuntimeState runtime,
SurfaceControllerTypeCollection surfaceControllerTypes,
UmbracoApiControllerTypeCollection apiControllerTypes)
{
- // fixme - need to review & cleanup
-
// setup mvc and webapi services
SetupMvcAndWebApi();
@@ -308,7 +292,7 @@ namespace Umbraco.Web
//before we do anything, we'll ensure the umbraco context
//see: http://issues.umbraco.org/issue/U4-1717
- var httpContext = new HttpContextWrapper(umbracoApplication.Context);
+ var httpContext = new HttpContextWrapper(HttpContext.Current);
UmbracoContext.EnsureContext( // fixme - refactor! UmbracoContext & UmbracoRequestContext! + inject, accessor, etc
httpContext,
Current.FacadeService,
diff --git a/src/Umbraco.Web/umbraco.presentation/EnsureSystemPathsApplicationStartupHandler.cs b/src/Umbraco.Web/umbraco.presentation/EnsureSystemPathsApplicationStartupHandler.cs
deleted file mode 100644
index 4c06619147..0000000000
--- a/src/Umbraco.Web/umbraco.presentation/EnsureSystemPathsApplicationStartupHandler.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Web;
-using Umbraco.Core;
-using Umbraco.Core.IO;
-
-namespace umbraco.presentation
-{
- public class EnsureSystemPathsApplicationStartupHandler : ApplicationEventHandler
- {
- protected override void ApplicationInitialized(UmbracoApplicationBase umbracoApplication)
- {
- base.ApplicationInitialized(umbracoApplication);
-
- IOHelper.EnsurePathExists("~/App_Data");
- IOHelper.EnsurePathExists(SystemDirectories.Media);
- IOHelper.EnsurePathExists(SystemDirectories.MvcViews);
- IOHelper.EnsurePathExists(SystemDirectories.MvcViews + "/Partials");
- IOHelper.EnsurePathExists(SystemDirectories.MvcViews + "/MacroPartials");
- }
- }
-}
\ No newline at end of file