diff --git a/build/Build.bat b/build/Build.bat
index d7fcdf75f0..8455fddf0f 100644
--- a/build/Build.bat
+++ b/build/Build.bat
@@ -121,6 +121,7 @@ ECHO.
ECHO Restoring NuGet packages
ECHO Into %nuGetFolder%
..\src\.nuget\NuGet.exe restore ..\src\Umbraco.Core\project.json -OutputDirectory %nuGetFolder% -Verbosity quiet
+..\src\.nuget\NuGet.exe restore ..\src\Umbraco.Compat7\project.json -OutputDirectory %nuGetFolder% -Verbosity quiet
..\src\.nuget\NuGet.exe restore ..\src\umbraco.datalayer\packages.config -OutputDirectory %nuGetFolder% -Verbosity quiet
..\src\.nuget\NuGet.exe restore ..\src\Umbraco.Web\project.json -OutputDirectory %nuGetFolder% -Verbosity quiet
..\src\.nuget\NuGet.exe restore ..\src\Umbraco.Web.UI\packages.config -OutputDirectory %nuGetFolder% -Verbosity quiet
@@ -149,6 +150,7 @@ REN .\_BuildOutput\WebApp\Views\Web.config Web.config.transform
ECHO.
ECHO Packing the NuGet release files
..\src\.nuget\NuGet.exe Pack NuSpecs\UmbracoCms.Core.nuspec -Version %VERSION% -Symbols -Verbosity quiet
+..\src\.nuget\NuGet.exe Pack NuSpecs\UmbracoCms.Compat7.nuspec -Version %VERSION% -Symbols -Verbosity quiet
..\src\.nuget\NuGet.exe Pack NuSpecs\UmbracoCms.nuspec -Version %VERSION% -Verbosity quiet
IF ERRORLEVEL 1 GOTO error
diff --git a/build/Build.proj b/build/Build.proj
index 0da79322c4..dbef46abe6 100644
--- a/build/Build.proj
+++ b/build/Build.proj
@@ -264,8 +264,8 @@
-
-
+
+
diff --git a/build/NuSpecs/UmbracoCms.Compat7.nuspec b/build/NuSpecs/UmbracoCms.Compat7.nuspec
new file mode 100644
index 0000000000..c2139a9cde
--- /dev/null
+++ b/build/NuSpecs/UmbracoCms.Compat7.nuspec
@@ -0,0 +1,31 @@
+
+
+
+ UmbracoCms.Compat7
+ 8.0.0
+ Umbraco Cms Compat7
+ Umbraco HQ
+ Umbraco HQ
+ http://opensource.org/licenses/MIT
+ http://umbraco.com/
+ http://umbraco.com/media/357769/100px_transparent.png
+ false
+ Contains resources aiming at providing a better v7-to-v8 backward compatibility.
+ Umbraco v7 compatibility layer for v8.
+ en-US
+ umbraco
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Umbraco.Compat7/Compat7Component.cs b/src/Umbraco.Compat7/Compat7Component.cs
new file mode 100644
index 0000000000..013070a439
--- /dev/null
+++ b/src/Umbraco.Compat7/Compat7Component.cs
@@ -0,0 +1,66 @@
+using System;
+using System.Collections.Generic;
+using LightInject;
+using System.Linq;
+using Umbraco.Core;
+using Umbraco.Core.Components;
+using Umbraco.Core.Logging;
+using Umbraco.Core.Plugins;
+
+namespace Umbraco.Compat7
+{
+ internal class Compat7Component : UmbracoComponentBase, IUmbracoUserComponent
+ {
+ private List _handlers;
+ private UmbracoApplicationBase _app;
+
+ public static event EventHandler ApplicationStarting;
+ public static event EventHandler ApplicationStarted;
+
+ public override void Compose(ServiceContainer container)
+ {
+ _app = container.GetInstance();
+ var logger = container.GetInstance();
+
+ var pluginManager = container.GetInstance();
+ var handlerTypes = pluginManager.ResolveTypes();
+ _handlers = handlerTypes.Select(Activator.CreateInstance).Cast().ToList();
+
+ // fixme - UmbracoApplication events
+
+ foreach (var handler in _handlers)
+ handler.OnApplicationInitialized(_app, ApplicationContext.Current);
+
+ foreach (var handler in _handlers)
+ handler.OnApplicationStarting(_app, ApplicationContext.Current);
+
+ try
+ {
+ ApplicationStarting?.Invoke(_app, EventArgs.Empty);
+ }
+ catch (Exception ex)
+ {
+ logger.Error("An error occurred in an ApplicationStarting event handler", ex);
+ throw;
+ }
+ }
+
+ public void Initialize(ILogger logger)
+ {
+ // fixme - UmbracoApplication events
+
+ foreach (var handler in _handlers)
+ handler.OnApplicationStarted(_app, ApplicationContext.Current);
+
+ try
+ {
+ ApplicationStarted?.Invoke(_app, EventArgs.Empty);
+ }
+ catch (Exception ex)
+ {
+ logger.Error("An error occurred in an ApplicationStarting event handler", ex);
+ throw;
+ }
+ }
+ }
+}
diff --git a/src/Umbraco.Compat7/Core/ApplicationContext.cs b/src/Umbraco.Compat7/Core/ApplicationContext.cs
new file mode 100644
index 0000000000..cbae589bab
--- /dev/null
+++ b/src/Umbraco.Compat7/Core/ApplicationContext.cs
@@ -0,0 +1,33 @@
+using System;
+using Umbraco.Core.Cache;
+using Umbraco.Core.Logging;
+using Umbraco.Core.Services;
+
+// ReSharper disable once CheckNamespace
+namespace Umbraco.Core
+{
+ public class ApplicationContext : IDisposable
+ {
+ private ApplicationContext()
+ { }
+
+ public static ApplicationContext Current { get; } = new ApplicationContext();
+
+ public CacheHelper ApplicationCache => DependencyInjection.Current.ApplicationCache;
+
+ public ProfilingLogger ProfilingLogger => DependencyInjection.Current.ProfilingLogger;
+
+ public bool IsReady { get; } = true; // because... not accessible before we are ready
+
+ public bool IsConfigured => DependencyInjection.Current.RuntimeState.Level == RuntimeLevel.Run;
+
+ public bool IsUpgrading => DependencyInjection.Current.RuntimeState.Level == RuntimeLevel.Upgrade;
+
+ public DatabaseContext DatabaseContext => DependencyInjection.Current.DatabaseContext;
+
+ public ServiceContext Services => DependencyInjection.Current.Services;
+
+ public void Dispose()
+ { }
+ }
+}
diff --git a/src/Umbraco.Compat7/Core/ApplicationEventHandler.cs b/src/Umbraco.Compat7/Core/ApplicationEventHandler.cs
new file mode 100644
index 0000000000..9125d267f6
--- /dev/null
+++ b/src/Umbraco.Compat7/Core/ApplicationEventHandler.cs
@@ -0,0 +1,63 @@
+// ReSharper disable once CheckNamespace
+namespace Umbraco.Core
+{
+ public abstract class ApplicationEventHandler : IApplicationEventHandler
+ {
+ public void OnApplicationInitialized(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
+ {
+ if (ShouldExecute(applicationContext))
+ {
+ ApplicationInitialized(umbracoApplication, applicationContext);
+ }
+ }
+
+ public void OnApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
+ {
+ if (ShouldExecute(applicationContext))
+ {
+ ApplicationStarting(umbracoApplication, applicationContext);
+ }
+ }
+
+ public void OnApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
+ {
+ if (ShouldExecute(applicationContext))
+ {
+ ApplicationStarted(umbracoApplication, applicationContext);
+ }
+ }
+
+ protected virtual void ApplicationInitialized(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
+ { }
+
+ protected virtual void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
+ { }
+
+ protected virtual void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
+ { }
+
+ private bool ShouldExecute(ApplicationContext applicationContext)
+ {
+ if (applicationContext.IsConfigured && applicationContext.DatabaseContext.IsDatabaseConfigured)
+ {
+ return true;
+ }
+
+ if (applicationContext.IsConfigured == false && ExecuteWhenApplicationNotConfigured)
+ {
+ return true;
+ }
+
+ if (applicationContext.DatabaseContext.IsDatabaseConfigured == false && ExecuteWhenDatabaseNotConfigured)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ protected virtual bool ExecuteWhenApplicationNotConfigured => false;
+
+ protected virtual bool ExecuteWhenDatabaseNotConfigured => false;
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Compat7/Core/IApplicationEventHandler.cs b/src/Umbraco.Compat7/Core/IApplicationEventHandler.cs
new file mode 100644
index 0000000000..3e16a3dbf9
--- /dev/null
+++ b/src/Umbraco.Compat7/Core/IApplicationEventHandler.cs
@@ -0,0 +1,31 @@
+// ReSharper disable once CheckNamespace
+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, ApplicationContext applicationContext);
+
+ ///
+ /// All resolvers have been initialized but resolution is not frozen so they can be modified in this method
+ ///
+ ///
+ ///
+ void OnApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext);
+
+ ///
+ /// 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, ApplicationContext applicationContext);
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Compat7/Core/Logging/LogHelper.cs b/src/Umbraco.Compat7/Core/Logging/LogHelper.cs
new file mode 100644
index 0000000000..e5a49a1de9
--- /dev/null
+++ b/src/Umbraco.Compat7/Core/Logging/LogHelper.cs
@@ -0,0 +1,221 @@
+using System;
+using System.Linq;
+using System.Web;
+using Umbraco.Web;
+
+// ReSharper disable once CheckNamespace
+namespace Umbraco.Core.Logging
+{
+ public static class LogHelper
+ {
+ #region Error
+ ///
+ /// Adds an error log
+ ///
+ ///
+ ///
+ ///
+ public static void Error(string message, Exception exception)
+ {
+ Current.Logger.Error(typeof(T), message, exception);
+ }
+
+ public static void Error(Type callingType, string message, Exception exception)
+ {
+ Current.Logger.Error(callingType, message, exception);
+ }
+
+ #endregion
+
+ #region Warn
+
+ public static void Warn(Type callingType, string message, params Func