Merge branch 'temp8' into temp8-no-restart

This commit is contained in:
Stephan
2019-02-13 16:12:48 +01:00
41 changed files with 535 additions and 427 deletions

318
.gitignore vendored
View File

@@ -1,160 +1,162 @@
#
# Umbraco Cms Git Ignore
#
# common files
*.obj
*.pdb
*.user
*.aps
*.pch
*.vspscc
*.orig
*.suo
*.vs10x
*.ndproj
#
# Umbraco Cms Git Ignore
#
# common files
*.obj
*.pdb
*.user
*.aps
*.pch
*.vspscc
*.orig
*.suo
*.vs10x
*.ndproj
*.ignorer.*
# common directories
.DS_Store
._.DS_Store
.vs/
/local/
# build directories
[Bb]in/
[Db]ebug*/
[Rr]elease*/
obj/
# tools
_ReSharper*/
_NCrunch_*/
*.ncrunchsolution
*.ncrunchsolution.user
*.ncrunchproject
*.crunchsolution.cache
tools/NDepend/
[Tt]est[Rr]esult*
[Bb]uild[Ll]og.*
*.[Pp]ublish.xml
[sS]ource
[sS]andbox
umbraco.config
App_Data/TEMP/*
[Uu]mbraco/[Pp]resentation/[Uu]mbraco/[Pp]lugins/*
[Uu]mbraco/[Pp]resentation/[Uu]ser[Cc]ontrols/*
[Uu]mbraco/[Pp]resentation/[Ss]cripts/*
[Uu]mbraco/[Pp]resentation/[Ff]onts/*
[Uu]mbraco/[Pp]resentation/[Cc]ss/*
src/Umbraco.Web.UI/[Cc]ss/*
src/Umbraco.Web.UI/App_Code/*
src/Umbraco.Web.UI/App_Data/*
src/Umbraco.Tests/App_Data/*
src/Umbraco.Web.UI/[Mm]edia/*
src/Umbraco.Web.UI/[Mm]aster[Pp]ages/*
src/Umbraco.Web.UI/[Mm]acro[Ss]cripts/*
!src/Umbraco.Web.UI/[Mm]acro[Ss]cripts/[Ww]eb.[Cc]onfig
src/Umbraco.Web.UI/[Xx]slt/*
src/Umbraco.Web.UI/[Ii]mages/*
src/Umbraco.Web.UI/[Ss]cripts/*
src/Umbraco.Web.UI/Web.*.config.transformed
umbraco/presentation/umbraco/plugins/uComponents/uComponentsInstaller.ascx
umbraco/presentation/packages/uComponents/MultiNodePicker/CustomTreeService.asmx
src/Umbraco.Tests/config/applications.config
src/Umbraco.Tests/config/trees.config
src/Umbraco.Web.UI/web.config
src/Umbraco.Web.UI/[Cc]onfig/ClientDependency.config
src/Umbraco.Tests/config/404handlers.config
src/Umbraco.Web.UI/[Vv]iews/*.cshtml
src/Umbraco.Web.UI/[Vv]iews/*.vbhtml
src/Umbraco.Tests/[Cc]onfig/umbracoSettings.config
src/Umbraco.Web.UI/[Vv]iews/*
src/packages/
src/packages/repositories.config
src/Umbraco.Web.UI/[Ww]eb.config
*.transformed
node_modules
lib-bower
src/Umbraco.Web.UI/[Uu]mbraco/[Ll]ib/*
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/umbraco.*
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/*.loader.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/init.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/routes.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/app.dev.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/loader.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/loader.dev.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/main.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/app.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/canvasdesigner.*.js
src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/
src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/**/*.js
src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/**/*.css
src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/**/*.html
src/Umbraco.Web.UI/[Uu]mbraco/[Aa]ssets/*
src/Umbraco.Web.UI.Client/[Bb]uild/*
src/Umbraco.Web.UI.Client/[Bb]uild/[Bb]elle/
src/Umbraco.Web.UI/[Uu]ser[Cc]ontrols/
src/Umbraco.Web.UI.Client/src/[Ll]ess/*.css
src/Umbraco.Web.UI.Client/vwd.webinfo
src/Umbraco.Web.UI/App_Plugins/*
src/*.psess
src/*.vspx
NDependOut/*
QueryResult.htm
src/Umbraco.Web.UI/[Cc]onfig/appSettings.config
src/Umbraco.Web.UI/[Cc]onfig/connectionStrings.config
src/Umbraco.Web.UI/[Uu]mbraco/plugins/*
build/ApiDocs/*
build/ApiDocs/Output/*
src/Umbraco.Web.UI.Client/bower_components/*
/src/Umbraco.Web.UI/[Uu]mbraco/preview
/src/Umbraco.Web.UI/[Uu]mbraco/preview.old
# ignore rule for clearing out Belle (avoid rebuilding all the time)
preserve.belle
#Ignore Rule for output of generated documentation files from Grunt docserve
src/Umbraco.Web.UI.Client/docs/api
src/*.boltdata/
src/umbraco.sln.ide/*
src/.vs/
src/Umbraco.Web.UI/[Jj]s/*
src/Umbraco.Tests/[Mm]edia
tools/docfx/*
apidocs/_site/*
src/*/project.lock.json
src/.idea/*
apidocs/api/*
build/docs.zip
build/ui-docs.zip
build/csharp-docs.zip
src/packages/
src/PrecompiledWeb/*
# build
build.out/
build.tmp/
build/hooks/
build/temp/
# common directories
.DS_Store
._.DS_Store
.vs/
/local/
# build directories
[Bb]in/
[Db]ebug*/
[Rr]elease*/
obj/
# tools
_ReSharper*/
_NCrunch_*/
*.ncrunchsolution
*.ncrunchsolution.user
*.ncrunchproject
*.crunchsolution.cache
tools/NDepend/
[Tt]est[Rr]esult*
[Bb]uild[Ll]og.*
*.[Pp]ublish.xml
[sS]ource
[sS]andbox
umbraco.config
App_Data/TEMP/*
[Uu]mbraco/[Pp]resentation/[Uu]mbraco/[Pp]lugins/*
[Uu]mbraco/[Pp]resentation/[Uu]ser[Cc]ontrols/*
[Uu]mbraco/[Pp]resentation/[Ss]cripts/*
[Uu]mbraco/[Pp]resentation/[Ff]onts/*
[Uu]mbraco/[Pp]resentation/[Cc]ss/*
src/Umbraco.Web.UI/[Cc]ss/*
src/Umbraco.Web.UI/App_Code/*
src/Umbraco.Web.UI/App_Data/*
src/Umbraco.Tests/App_Data/*
src/Umbraco.Web.UI/[Mm]edia/*
src/Umbraco.Web.UI/[Mm]aster[Pp]ages/*
src/Umbraco.Web.UI/[Mm]acro[Ss]cripts/*
!src/Umbraco.Web.UI/[Mm]acro[Ss]cripts/[Ww]eb.[Cc]onfig
src/Umbraco.Web.UI/[Xx]slt/*
src/Umbraco.Web.UI/[Ii]mages/*
src/Umbraco.Web.UI/[Ss]cripts/*
src/Umbraco.Web.UI/Web.*.config.transformed
umbraco/presentation/umbraco/plugins/uComponents/uComponentsInstaller.ascx
umbraco/presentation/packages/uComponents/MultiNodePicker/CustomTreeService.asmx
src/Umbraco.Tests/config/applications.config
src/Umbraco.Tests/config/trees.config
src/Umbraco.Web.UI/web.config
src/Umbraco.Web.UI/[Cc]onfig/ClientDependency.config
src/Umbraco.Web.UI/[Cc]onfig/serilog.config
src/Umbraco.Web.UI/[Cc]onfig/serilog.user.config
src/Umbraco.Tests/config/404handlers.config
src/Umbraco.Web.UI/[Vv]iews/*.cshtml
src/Umbraco.Web.UI/[Vv]iews/*.vbhtml
src/Umbraco.Tests/[Cc]onfig/umbracoSettings.config
src/Umbraco.Web.UI/[Vv]iews/*
src/packages/
src/packages/repositories.config
src/Umbraco.Web.UI/[Ww]eb.config
*.transformed
node_modules
lib-bower
src/Umbraco.Web.UI/[Uu]mbraco/[Ll]ib/*
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/umbraco.*
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/*.loader.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/init.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/routes.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/app.dev.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/loader.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/loader.dev.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/main.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/app.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/canvasdesigner.*.js
src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/
src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/**/*.js
src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/**/*.css
src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/**/*.html
src/Umbraco.Web.UI/[Uu]mbraco/[Aa]ssets/*
src/Umbraco.Web.UI.Client/[Bb]uild/*
src/Umbraco.Web.UI.Client/[Bb]uild/[Bb]elle/
src/Umbraco.Web.UI/[Uu]ser[Cc]ontrols/
src/Umbraco.Web.UI.Client/src/[Ll]ess/*.css
src/Umbraco.Web.UI.Client/vwd.webinfo
src/Umbraco.Web.UI/App_Plugins/*
src/*.psess
src/*.vspx
NDependOut/*
QueryResult.htm
src/Umbraco.Web.UI/[Cc]onfig/appSettings.config
src/Umbraco.Web.UI/[Cc]onfig/connectionStrings.config
src/Umbraco.Web.UI/[Uu]mbraco/plugins/*
build/ApiDocs/*
build/ApiDocs/Output/*
src/Umbraco.Web.UI.Client/bower_components/*
/src/Umbraco.Web.UI/[Uu]mbraco/preview
/src/Umbraco.Web.UI/[Uu]mbraco/preview.old
# ignore rule for clearing out Belle (avoid rebuilding all the time)
preserve.belle
#Ignore Rule for output of generated documentation files from Grunt docserve
src/Umbraco.Web.UI.Client/docs/api
src/*.boltdata/
src/umbraco.sln.ide/*
src/.vs/
src/Umbraco.Web.UI/[Jj]s/*
src/Umbraco.Tests/[Mm]edia
tools/docfx/*
apidocs/_site/*
src/*/project.lock.json
src/.idea/*
apidocs/api/*
build/docs.zip
build/ui-docs.zip
build/csharp-docs.zip
src/packages/
src/PrecompiledWeb/*
# build
build.out/
build.tmp/
build/hooks/
build/temp/
# eof

View File

@@ -110,13 +110,6 @@ namespace Umbraco.Core.Components
internal static ManifestValueValidatorCollectionBuilder Validators(this Composition composition)
=> composition.WithCollectionBuilder<ManifestValueValidatorCollectionBuilder>();
/// <summary>
/// Gets the post-migrations collection builder.
/// </summary>
/// <param name="composition">The composition.</param>
internal static PostMigrationCollectionBuilder PostMigrations(this Composition composition)
=> composition.WithCollectionBuilder<PostMigrationCollectionBuilder>();
/// <summary>
/// Gets the components collection builder.
/// </summary>

View File

@@ -1,4 +1,6 @@
using Umbraco.Core.Logging;
using System;
using System.Collections.Generic;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence;
namespace Umbraco.Core.Migrations
@@ -32,5 +34,11 @@ namespace Umbraco.Core.Migrations
/// Gets or sets a value indicating whether an expression is being built.
/// </summary>
bool BuildingExpression { get; set; }
/// <summary>
/// Adds a post-migrations.
/// </summary>
void AddPostMigration<TMigration>()
where TMigration : IMigration;
}
}

View File

@@ -1,12 +0,0 @@
using Semver;
using Umbraco.Core.Composing;
using Umbraco.Core.Logging;
using Umbraco.Core.Scoping;
namespace Umbraco.Core.Migrations
{
public interface IPostMigration : IDiscoverable
{
void Execute(string name, IScope scope, SemVersion originVersion, SemVersion targetVersion, ILogger logger);
}
}

View File

@@ -27,7 +27,6 @@ namespace Umbraco.Core.Migrations.Install
private readonly IRuntimeState _runtime;
private readonly IMigrationBuilder _migrationBuilder;
private readonly IKeyValueService _keyValueService;
private readonly PostMigrationCollection _postMigrations;
private readonly ILogger _logger;
private DatabaseSchemaResult _databaseSchemaValidationResult;
@@ -35,7 +34,7 @@ namespace Umbraco.Core.Migrations.Install
/// <summary>
/// Initializes a new instance of the <see cref="DatabaseBuilder"/> class.
/// </summary>
public DatabaseBuilder(IScopeProvider scopeProvider, IGlobalSettings globalSettings, IUmbracoDatabaseFactory databaseFactory, IRuntimeState runtime, ILogger logger, IMigrationBuilder migrationBuilder, IKeyValueService keyValueService, PostMigrationCollection postMigrations)
public DatabaseBuilder(IScopeProvider scopeProvider, IGlobalSettings globalSettings, IUmbracoDatabaseFactory databaseFactory, IRuntimeState runtime, ILogger logger, IMigrationBuilder migrationBuilder, IKeyValueService keyValueService)
{
_scopeProvider = scopeProvider;
_globalSettings = globalSettings;
@@ -44,7 +43,6 @@ namespace Umbraco.Core.Migrations.Install
_logger = logger;
_migrationBuilder = migrationBuilder;
_keyValueService = keyValueService;
_postMigrations = postMigrations;
}
#region Status
@@ -483,7 +481,7 @@ namespace Umbraco.Core.Migrations.Install
/// configured and it is possible to connect to the database.</para>
/// <para>Runs whichever migrations need to run.</para>
/// </remarks>
public Result UpgradeSchemaAndData()
public Result UpgradeSchemaAndData(MigrationPlan plan)
{
try
{
@@ -496,8 +494,8 @@ namespace Umbraco.Core.Migrations.Install
_logger.Info<DatabaseBuilder>("Database upgrade started");
// upgrade
var upgrader = new UmbracoUpgrader();
upgrader.Execute(_scopeProvider, _migrationBuilder, _keyValueService, _logger, _postMigrations);
var upgrader = new Upgrader(plan);
upgrader.Execute(_scopeProvider, _migrationBuilder, _keyValueService, _logger);
var message = "<p>Upgrade completed!</p>";

View File

@@ -321,7 +321,7 @@ namespace Umbraco.Core.Migrations.Install
{
// on install, initialize the umbraco migration plan with the final state
var upgrader = new UmbracoUpgrader();
var upgrader = new Upgrader(new UmbracoPlan());
var stateValueKey = upgrader.StateValueKey;
var finalState = upgrader.Plan.FinalState;

View File

@@ -1,11 +1,12 @@
using System;
using System.Collections.Generic;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence;
namespace Umbraco.Core.Migrations
{
/// <summary>
/// Represents a migration context.
/// Implements <see cref="IMigrationContext"/>.
/// </summary>
internal class MigrationContext : IMigrationContext
{
@@ -32,5 +33,15 @@ namespace Umbraco.Core.Migrations
/// <inheritdoc />
public bool BuildingExpression { get; set; }
// this is only internally exposed
public List<Type> PostMigrations { get; } = new List<Type>();
/// <inheritdoc />
public void AddPostMigration<TMigration>()
where TMigration : IMigration
{
PostMigrations.Add(typeof(TMigration));
}
}
}

View File

@@ -14,6 +14,7 @@ namespace Umbraco.Core.Migrations
public class MigrationPlan
{
private readonly Dictionary<string, Transition> _transitions = new Dictionary<string, Transition>();
private readonly List<Type> _postMigrationTypes = new List<Type>();
private string _prevState;
private string _finalState;
@@ -166,6 +167,25 @@ namespace Umbraco.Core.Migrations
return this;
}
/// <summary>
/// Prepares post-migrations.
/// </summary>
/// <remarks>
/// <para>This can be overriden to filter, complement, and/or re-order post-migrations.</para>
/// </remarks>
protected virtual IEnumerable<Type> PreparePostMigrations(IEnumerable<Type> types)
=> types;
/// <summary>
/// Adds a post-migration to the plan.
/// </summary>
public virtual MigrationPlan AddPostMigration<TMigration>()
where TMigration : IMigration
{
_postMigrationTypes.Add(typeof(TMigration));
return this;
}
/// <summary>
/// Creates a random, unique state.
/// </summary>
@@ -270,6 +290,7 @@ namespace Umbraco.Core.Migrations
throw new Exception($"Unknown state \"{origState}\".");
var context = new MigrationContext(scope.Database, logger);
context.PostMigrations.AddRange(_postMigrationTypes);
while (transition != null)
{
@@ -285,6 +306,20 @@ namespace Umbraco.Core.Migrations
throw new Exception($"Unknown state \"{origState}\".");
}
// prepare and de-duplicate post-migrations, only keeping the 1st occurence
var temp = new HashSet<Type>();
var postMigrationTypes = PreparePostMigrations(context.PostMigrations)
.Where(x => !temp.Contains(x))
.Select(x => { temp.Add(x); return x; });
// run post-migrations
foreach (var postMigrationType in postMigrationTypes)
{
logger.Info<MigrationPlan>($"PostMigration: {postMigrationType.FullName}.");
var postMigration = migrationBuilder.Build(postMigrationType, context);
postMigration.Migrate();
}
logger.Info<MigrationPlan>("Done (pending scope completion).");
// safety check

View File

@@ -1,12 +0,0 @@
using System.Collections.Generic;
using Umbraco.Core.Composing;
namespace Umbraco.Core.Migrations
{
public class PostMigrationCollection : BuilderCollectionBase<IPostMigration>
{
public PostMigrationCollection(IEnumerable<IPostMigration> items)
: base(items)
{ }
}
}

View File

@@ -1,11 +0,0 @@
using Umbraco.Core.Composing;
namespace Umbraco.Core.Migrations
{
public class PostMigrationCollectionBuilder : LazyCollectionBuilderBase<PostMigrationCollectionBuilder, PostMigrationCollection, IPostMigration>
{
protected override PostMigrationCollectionBuilder This => this;
protected override Lifetime CollectionLifetime => Lifetime.Transient;
}
}

View File

@@ -0,0 +1,18 @@
namespace Umbraco.Core.Migrations.PostMigrations
{
/// <summary>
/// Rebuilds the published snapshot.
/// </summary>
/// <remarks>
/// <para>This interface exists because the entire published snapshot lives in Umbraco.Web
/// but we may want to trigger rebuilds from Umbraco.Core. These two assemblies should
/// be refactored, really.</para>
/// </remarks>
public interface IPublishedSnapshotRebuilder
{
/// <summary>
/// Rebuilds.
/// </summary>
void Rebuild();
}
}

View File

@@ -0,0 +1,12 @@
namespace Umbraco.Core.Migrations.PostMigrations
{
/// <summary>
/// Implements <see cref="IPublishedSnapshotRebuilder"/> in Umbraco.Core (doing nothing).
/// </summary>
public class PublishedSnapshotRebuilder : IPublishedSnapshotRebuilder
{
/// <inheritdoc />
public void Rebuild()
{ }
}
}

View File

@@ -0,0 +1,24 @@
namespace Umbraco.Core.Migrations.PostMigrations
{
/// <summary>
/// Rebuilds the published snapshot.
/// </summary>
public class RebuildPublishedSnapshot : IMigration
{
private readonly IPublishedSnapshotRebuilder _rebuilder;
/// <summary>
/// Initializes a new instance of the <see cref="RebuildPublishedSnapshot"/> class.
/// </summary>
public RebuildPublishedSnapshot(IPublishedSnapshotRebuilder rebuilder)
{
_rebuilder = rebuilder;
}
/// <inheritdoc />
public void Migrate()
{
_rebuilder.Rebuild();
}
}
}

View File

@@ -56,7 +56,7 @@ namespace Umbraco.Core.Migrations.Upgrade
}
}
// define the plan
// define the plan
protected void DefinePlan()
{
// MODIFYING THE PLAN
@@ -128,7 +128,7 @@ namespace Umbraco.Core.Migrations.Upgrade
To<UpdatePickerIntegerValuesToUdi>("{38C809D5-6C34-426B-9BEA-EFD39162595C}");
To<RenameUmbracoDomainsTable>("{6017F044-8E70-4E10-B2A3-336949692ADD}");
To<AddUserLoginDtoDateIndex>("{98339BEF-E4B2-48A8-B9D1-D173DC842BBE}");
Merge()
.To<DropXmlTables>("{CDBEDEE4-9496-4903-9CF2-4104E00FF960}")
.With()

View File

@@ -1,48 +0,0 @@
using System;
using System.Configuration;
using Semver;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Scoping;
using Umbraco.Core.Services;
namespace Umbraco.Core.Migrations.Upgrade
{
/// <summary>
/// Represents the Umbraco upgrader.
/// </summary>
public class UmbracoUpgrader : Upgrader
{
private PostMigrationCollection _postMigrations;
/// <summary>
/// Initializes a new instance of the <see ref="UmbracoUpgrader" /> class.
/// </summary>
public UmbracoUpgrader()
: base(new UmbracoPlan())
{ }
/// <summary>
/// Executes.
/// </summary>
public void Execute(IScopeProvider scopeProvider, IMigrationBuilder migrationBuilder, IKeyValueService keyValueService, ILogger logger, PostMigrationCollection postMigrations)
{
_postMigrations = postMigrations;
Execute(scopeProvider, migrationBuilder, keyValueService, logger);
}
/// <inheritdoc />
public override void AfterMigrations(IScope scope, ILogger logger)
{
// assume we have something in web.config that makes some sense = the origin version
if (!SemVersion.TryParse(ConfigurationManager.AppSettings[Constants.AppSettings.ConfigurationStatus], out var originVersion))
throw new InvalidOperationException($"Could not get current version from web.config {Constants.AppSettings.ConfigurationStatus} appSetting.");
// target version is the code version
var targetVersion = UmbracoVersion.SemanticVersion;
foreach (var postMigration in _postMigrations)
postMigration.Execute(Name, scope, originVersion, targetVersion, logger);
}
}
}

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Umbraco.Core.Logging;
using Umbraco.Core.Migrations.PostMigrations;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Dtos;
@@ -27,7 +28,7 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
if (refreshCache)
{
//FIXME: trigger cache rebuild. Currently the data in the database tables is wrong.
Context.AddPostMigration<RebuildPublishedSnapshot>();
}
}

View File

@@ -10,6 +10,7 @@ using Umbraco.Core.Logging;
using Umbraco.Core.Manifest;
using Umbraco.Core.Migrations;
using Umbraco.Core.Migrations.Install;
using Umbraco.Core.Migrations.PostMigrations;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.PackageActions;
using Umbraco.Core.Persistence;
@@ -113,13 +114,13 @@ namespace Umbraco.Core.Runtime
composition.WithCollectionBuilder<UrlSegmentProviderCollectionBuilder>()
.Append<DefaultUrlSegmentProvider>();
composition.WithCollectionBuilder<PostMigrationCollectionBuilder>()
.Add(() => composition.TypeLoader.GetTypes<IPostMigration>());
composition.RegisterUnique<IMigrationBuilder>(factory => new MigrationBuilder(factory));
// by default, register a noop factory
composition.RegisterUnique<IPublishedModelFactory, NoopPublishedModelFactory>();
// by default, register a noop rebuilder
composition.RegisterUnique<IPublishedSnapshotRebuilder, PublishedSnapshotRebuilder>();
}
}
}

View File

@@ -242,7 +242,7 @@ namespace Umbraco.Core
protected virtual bool EnsureUmbracoUpgradeState(IUmbracoDatabaseFactory databaseFactory, ILogger logger)
{
var upgrader = new UmbracoUpgrader();
var upgrader = new Upgrader(new UmbracoPlan());
var stateValueKey = upgrader.StateValueKey;
// no scope, no service - just directly accessing the database

View File

@@ -351,6 +351,9 @@
<Compile Include="Migrations\IncompleteMigrationExpressionException.cs" />
<Compile Include="Migrations\MergeBuilder.cs" />
<Compile Include="Migrations\MigrationBase_Extra.cs" />
<Compile Include="Migrations\PostMigrations\IPublishedSnapshotRebuilder.cs" />
<Compile Include="Migrations\PostMigrations\PublishedSnapshotRebuilder.cs" />
<Compile Include="Migrations\PostMigrations\RebuildPublishedSnapshot.cs" />
<Compile Include="Migrations\Upgrade\V_7_10_0\RenamePreviewFolder.cs" />
<Compile Include="Migrations\Upgrade\V_7_12_0\AddRelationTypeForMediaFolderOnDelete.cs" />
<Compile Include="Migrations\Upgrade\V_7_12_0\IncreaseLanguageIsoCodeColumnLength.cs" />
@@ -666,15 +669,11 @@
<Compile Include="Media\IEmbedProvider.cs" />
<Compile Include="Media\OEmbedResult.cs" />
<Compile Include="Media\OEmbedStatus.cs" />
<Compile Include="Migrations\IPostMigration.cs" />
<Compile Include="Migrations\MigrationBuilder.cs" />
<Compile Include="Migrations\MigrationPlan.cs" />
<Compile Include="Migrations\NoopMigration.cs" />
<Compile Include="Migrations\PostMigrationCollection.cs" />
<Compile Include="Migrations\PostMigrationCollectionBuilder.cs" />
<Compile Include="Migrations\Upgrade\UmbracoPlan.cs" />
<Compile Include="Migrations\Upgrade\V_8_0_0\AddLockTable.cs" />
<Compile Include="Migrations\Upgrade\UmbracoUpgrader.cs" />
<Compile Include="Migrations\Upgrade\Upgrader.cs" />
<Compile Include="Migrations\Upgrade\V_8_0_0\DropMigrationsTable.cs" />
<Compile Include="Models\AuditItem.cs" />

View File

@@ -16,32 +16,6 @@ namespace Umbraco.Tests.Migrations
[TestFixture]
public class MigrationTests
{
public class TestUpgraderWithPostMigrations : Upgrader
{
private PostMigrationCollection _postMigrations;
public TestUpgraderWithPostMigrations(MigrationPlan plan)
: base(plan)
{ }
public void Execute(IScopeProvider scopeProvider, IMigrationBuilder migrationBuilder, IKeyValueService keyValueService, ILogger logger, PostMigrationCollection postMigrations)
{
_postMigrations = postMigrations;
Execute(scopeProvider, migrationBuilder, keyValueService, logger);
}
public override void AfterMigrations(IScope scope, ILogger logger)
{
// run post-migrations
var originVersion = new SemVersion(0);
var targetVersion = new SemVersion(0);
// run post-migrations
foreach (var postMigration in _postMigrations)
postMigration.Execute(Name, scope, originVersion, targetVersion, logger);
}
}
public class TestScopeProvider : IScopeProvider
{
private readonly IScope _scope;

View File

@@ -2,10 +2,9 @@
using Moq;
using NPoco;
using NUnit.Framework;
using Semver;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.Migrations;
using Umbraco.Core.Migrations.Upgrade;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Core.Scoping;
@@ -18,15 +17,10 @@ namespace Umbraco.Tests.Migrations
public class PostMigrationTests
{
[Test]
public void Executes_For_Any_Product_Name_When_Not_Specified()
public void ExecutesPlanPostMigration()
{
var logger = Mock.Of<ILogger>();
var changed1 = new Args { CountExecuted = 0 };
var post1 = new TestPostMigration(changed1);
var posts = new PostMigrationCollection(new [] { post1 });
var builder = Mock.Of<IMigrationBuilder>();
Mock.Get(builder)
.Setup(x => x.Build(It.IsAny<Type>(), It.IsAny<IMigrationContext>()))
@@ -34,8 +28,10 @@ namespace Umbraco.Tests.Migrations
{
switch (t.Name)
{
case "NoopMigration":
case nameof(NoopMigration):
return new NoopMigration();
case nameof(TestPostMigration):
return new TestPostMigration();
default:
throw new NotSupportedException();
}
@@ -50,26 +46,23 @@ namespace Umbraco.Tests.Migrations
var sqlContext = new SqlContext(new SqlCeSyntaxProvider(), DatabaseType.SQLCe, Mock.Of<IPocoDataFactory>());
var scopeProvider = new MigrationTests.TestScopeProvider(scope) { SqlContext = sqlContext };
var u1 = new MigrationTests.TestUpgraderWithPostMigrations(
new MigrationPlan("Test").From(string.Empty).To("done"));
u1.Execute(scopeProvider, builder, Mock.Of<IKeyValueService>(), logger, posts);
var plan = new MigrationPlan("Test")
.From(string.Empty).To("done");
Assert.AreEqual(1, changed1.CountExecuted);
plan.AddPostMigration<TestPostMigration>();
TestPostMigration.MigrateCount = 0;
var upgrader = new Upgrader(plan);
upgrader.Execute(scopeProvider, builder, Mock.Of<IKeyValueService>(), logger);
Assert.AreEqual(1, TestPostMigration.MigrateCount);
}
[Test]
public void Executes_Only_For_Specified_Product_Name()
public void MigrationCanAddPostMigration()
{
var logger = Mock.Of<ILogger>();
var changed1 = new Args { CountExecuted = 0};
var post1 = new TestPostMigration("Test1", changed1);
var changed2 = new Args { CountExecuted = 0 };
var post2 = new TestPostMigration("Test2", changed2);
var posts = new PostMigrationCollection(new [] { post1, post2 });
var builder = Mock.Of<IMigrationBuilder>();
Mock.Get(builder)
.Setup(x => x.Build(It.IsAny<Type>(), It.IsAny<IMigrationContext>()))
@@ -77,8 +70,12 @@ namespace Umbraco.Tests.Migrations
{
switch (t.Name)
{
case "NoopMigration":
case nameof(NoopMigration):
return new NoopMigration();
case nameof(TestMigration):
return new TestMigration(c);
case nameof(TestPostMigration):
return new TestPostMigration();
default:
throw new NotSupportedException();
}
@@ -93,52 +90,44 @@ namespace Umbraco.Tests.Migrations
var sqlContext = new SqlContext(new SqlCeSyntaxProvider(), DatabaseType.SQLCe, Mock.Of<IPocoDataFactory>());
var scopeProvider = new MigrationTests.TestScopeProvider(scope) { SqlContext = sqlContext };
var u1 = new MigrationTests.TestUpgraderWithPostMigrations(
new MigrationPlan("Test1").From(string.Empty).To("done"));
u1.Execute(scopeProvider, builder, Mock.Of<IKeyValueService>(), logger, posts);
var plan = new MigrationPlan("Test")
.From(string.Empty).To<TestMigration>("done");
Assert.AreEqual(1, changed1.CountExecuted);
Assert.AreEqual(0, changed2.CountExecuted);
TestMigration.MigrateCount = 0;
TestPostMigration.MigrateCount = 0;
var u2 = new MigrationTests.TestUpgraderWithPostMigrations(
new MigrationPlan("Test2").From(string.Empty).To("done"));
u2.Execute(scopeProvider, builder, Mock.Of<IKeyValueService>(), logger, posts);
new MigrationContext(database, logger);
Assert.AreEqual(1, changed1.CountExecuted);
Assert.AreEqual(1, changed2.CountExecuted);
var upgrader = new Upgrader(plan);
upgrader.Execute(scopeProvider, builder, Mock.Of<IKeyValueService>(), logger);
Assert.AreEqual(1, TestMigration.MigrateCount);
Assert.AreEqual(1, TestPostMigration.MigrateCount);
}
public class Args
public class TestMigration : MigrationBase
{
public int CountExecuted { get; set; }
public TestMigration(IMigrationContext context)
: base(context)
{ }
public static int MigrateCount { get; set; }
public override void Migrate()
{
MigrateCount++;
Context.AddPostMigration<TestPostMigration>();
}
}
public class TestPostMigration : IPostMigration
public class TestPostMigration : IMigration
{
private readonly string _prodName;
private readonly Args _changed;
public static int MigrateCount { get; set; }
// need that one else it breaks IoC
public TestPostMigration()
public void Migrate()
{
_changed = new Args();
}
public TestPostMigration(Args changed)
{
_changed = changed;
}
public TestPostMigration(string prodName, Args changed)
{
_prodName = prodName;
_changed = changed;
}
public void Execute(string name, IScope scope, SemVersion originVersion, SemVersion targetVersion, ILogger logger)
{
if (_prodName.IsNullOrWhiteSpace() == false && name != _prodName) return;
_changed.CountExecuted++;
MigrateCount++;
}
}
}

View File

@@ -21,13 +21,13 @@
</NuGetPackageImportStamp>
<Use64BitIISExpress />
<TargetFrameworkProfile />
<!--
<!--
for some weird reason, and because Web.config is created only during BeforeBuild,
the web.config configuration file would not be picked, and the build system would
try to use a traditional app.config, thus missing all the binding redirects.
this ensures that the build system things that the config file is web.config.
(see FindAppConfigFile target in detailed build output)
-->
<AppConfig>Web.config</AppConfig>
@@ -188,9 +188,17 @@
<Content Include="Config\serilog.user.config">
<SubType>Designer</SubType>
</Content>
<None Include="Config\serilog.user.Release.config">
<DependentUpon>serilog.user.config</DependentUpon>
<SubType>Designer</SubType>
</None>
<Content Include="Config\serilog.config">
<SubType>Designer</SubType>
</Content>
<None Include="Config\serilog.Release.config">
<DependentUpon>serilog.config</DependentUpon>
<SubType>Designer</SubType>
</None>
<Content Include="Config\logviewer.searches.config.js" />
<None Include="Config\umbracoSettings.Release.config">
<DependentUpon>umbracoSettings.config</DependentUpon>
@@ -364,6 +372,11 @@
<!-- Create ClientDependency.config file from Template if it doesn't exist -->
<Message Text="Copy ClientDependency.$(Configuration).config to ClientDependency.config" Importance="high" Condition="!Exists('$(ProjectDir)Config\ClientDependency.config')" />
<Copy SourceFiles="$(ProjectDir)Config\ClientDependency.Release.config" DestinationFiles="$(ProjectDir)Config\ClientDependency.config" OverwriteReadOnlyFiles="true" SkipUnchangedFiles="false" Condition="!Exists('$(ProjectDir)Config\ClientDependency.config')" />
<!-- Create Serilog.config & serilog.user.config file from Templates if it doesn't exist -->
<Message Text="Copy serilog.$(Configuration).config to serilog.config" Importance="high" Condition="!Exists('$(ProjectDir)Config\serilog.config')" />
<Copy SourceFiles="$(ProjectDir)Config\serilog.Release.config" DestinationFiles="$(ProjectDir)Config\serilog.config" OverwriteReadOnlyFiles="true" SkipUnchangedFiles="false" Condition="!Exists('$(ProjectDir)Config\serilog.config')" />
<Message Text="Copy serilog.user.$(Configuration).config to serilog.user.config" Importance="high" Condition="!Exists('$(ProjectDir)Config\serilog.user.config')" />
<Copy SourceFiles="$(ProjectDir)Config\serilog.user.Release.config" DestinationFiles="$(ProjectDir)Config\serilog.user.config" OverwriteReadOnlyFiles="true" SkipUnchangedFiles="false" Condition="!Exists('$(ProjectDir)Config\serilog.user.config')" />
<!-- Build Belle, if building is Visual Studio and the build folder does not exist yet -->
<Message Text="Skip Belle because UmbracoBuild is '$(UmbracoBuild)' (this is not Visual Studio)." Importance="High" Condition="'$(UmbracoBuild)' != ''" />
<Message Text="Skip Belle because $(ProjectDir)Umbraco\lib exists." Importance="High" Condition="Exists('$(ProjectDir)Umbraco\lib')" />
@@ -413,4 +426,4 @@
<Message Text="ConfigFile: $(OriginalFileName) -&gt; $(OutputFileName)" Importance="high" Condition="Exists('$(ModifiedFileName)')" />
<Copy SourceFiles="$(ModifiedFileName)" DestinationFiles="$(OutputFileName)" OverwriteReadOnlyFiles="true" SkipUnchangedFiles="false" Condition="Exists('$(ModifiedFileName)')" />
</Target>
</Project>
</Project>

View File

@@ -20,10 +20,9 @@ namespace Umbraco.Web.Composing.Composers
composition.Register<DatabaseInstallStep>(Lifetime.Scope);
composition.Register<DatabaseUpgradeStep>(Lifetime.Scope);
// TODO: Add these back once we have a compatible starter kit
//container.Register<StarterKitDownloadStep>(Lifetime.Scope);
//container.Register<StarterKitInstallStep>(Lifetime.Scope);
//container.Register<StarterKitCleanupStep>(Lifetime.Scope);
composition.Register<StarterKitDownloadStep>(Lifetime.Scope);
composition.Register<StarterKitInstallStep>(Lifetime.Scope);
composition.Register<StarterKitCleanupStep>(Lifetime.Scope);
composition.Register<SetUmbracoVersionStep>(Lifetime.Scope);

View File

@@ -464,6 +464,16 @@ namespace Umbraco.Web.Editors
{
long totalChildren;
List<IContent> children;
// Sets the culture to the only existing culture if we only have one culture.
if (string.IsNullOrWhiteSpace(cultureName))
{
if (_allLangs.Value.Count == 1)
{
cultureName = _allLangs.Value.First().Key;
}
}
if (pageNumber > 0 && pageSize > 0)
{
IQuery<IContent> queryFilter = null;
@@ -1200,7 +1210,7 @@ namespace Umbraco.Web.Editors
if (canPublish)
{
var culturesToPublish = cultureVariants.Where(x => x.Publish).Select(x => x.Culture).ToArray();
//proceed to publish if all validation still succeeds
var publishStatus = Services.ContentService.SaveAndPublish(contentItem.PersistedContent, culturesToPublish, Security.CurrentUser.Id);
wasCancelled = publishStatus.Result == PublishResultType.FailedPublishCancelledByEvent;

View File

@@ -14,8 +14,7 @@ namespace Umbraco.Web.Editors
public NuCacheStatusController(IPublishedSnapshotService publishedSnapshotService)
{
if (publishedSnapshotService == null) throw new ArgumentNullException(nameof(publishedSnapshotService));
_publishedSnapshotService = publishedSnapshotService;
_publishedSnapshotService = publishedSnapshotService ?? throw new ArgumentNullException(nameof(publishedSnapshotService));
}
private PublishedSnapshotService PublishedSnapshotService

View File

@@ -26,10 +26,9 @@ namespace Umbraco.Web.Install
a.OfType<DatabaseInstallStep>().First(),
a.OfType<DatabaseUpgradeStep>().First(),
// TODO: Add these back once we have a compatible starter kit
//orderedInstallerSteps.OfType<StarterKitDownloadStep>().First(),
//orderedInstallerSteps.OfType<StarterKitInstallStep>().First(),
//orderedInstallerSteps.OfType<StarterKitCleanupStep>().First(),
a.OfType<StarterKitDownloadStep>().First(),
a.OfType<StarterKitInstallStep>().First(),
a.OfType<StarterKitCleanupStep>().First(),
a.OfType<SetUmbracoVersionStep>().First(),
};

View File

@@ -5,7 +5,10 @@ using System.Threading.Tasks;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.Migrations.Install;
using Umbraco.Core.Migrations.Upgrade;
using Umbraco.Web.Install.Models;
using Umbraco.Web.Migrations;
using Umbraco.Web.Migrations.PostMigrations;
namespace Umbraco.Web.Install.InstallSteps
{
@@ -34,7 +37,10 @@ namespace Umbraco.Web.Install.InstallSteps
{
_logger.Info<DatabaseUpgradeStep>("Running 'Upgrade' service");
var result = _databaseBuilder.UpgradeSchemaAndData();
var plan = new UmbracoPlan();
plan.AddPostMigration<ClearCsrfCookies>(); // needed when running installer (back-office)
var result = _databaseBuilder.UpgradeSchemaAndData(plan);
if (result.Success == false)
{

View File

@@ -46,11 +46,6 @@ namespace Umbraco.Web.Install.InstallSteps
security.PerformLogin(-1);
}
// Some upgrade scripts "may modify the database (cmsContentXml...) tables directly" - not sure
// that is still true but the idea is that after an upgrade we want to reset the local published snapshot, on
// all LB nodes of course, so we need to use the distributed cache, and refresh everything.
_distributedCache.RefreshAllPublishedSnapshot();
// Update configurationStatus
_globalSettings.ConfigurationStatus = UmbracoVersion.SemanticVersion.ToSemanticString();

View File

@@ -1,7 +1,9 @@
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using Umbraco.Core.IO;
using Umbraco.Web.Install.Models;
namespace Umbraco.Web.Install.InstallSteps
@@ -24,9 +26,10 @@ namespace Umbraco.Web.Install.InstallSteps
private void CleanupInstallation(int packageId, string packageFile)
{
packageFile = HttpUtility.UrlDecode(packageFile);
var zipFile = new FileInfo(Path.Combine(IOHelper.MapPath(SystemDirectories.Packages), HttpUtility.UrlDecode(packageFile)));
// TODO: When does the zip file get deleted?
if (zipFile.Exists)
zipFile.Delete();
}
public override bool RequiresExecution(object model)

View File

@@ -70,20 +70,18 @@ namespace Umbraco.Web.Install.InstallSteps
//add an entry to the installedPackages.config
var compiledPackage = _packageService.GetCompiledPackageInfo(packageFile);
var packageDefinition = PackageDefinition.FromCompiledPackage(compiledPackage);
packageDefinition.PackagePath = packageFile.FullName;
_packageService.SaveInstalledPackage(packageDefinition);
InstallPackageFiles(packageDefinition, compiledPackage.PackageFile);
_packageService.InstallCompiledPackageFiles(packageDefinition, packageFile, _umbracoContext.Security.GetUserId().ResultOr(-1));
return (compiledPackage.PackageFile.Name, packageDefinition.Id);
}
private void InstallPackageFiles(PackageDefinition packageDefinition, FileInfo packageFile)
{
if (packageDefinition == null) throw new ArgumentNullException(nameof(packageDefinition));
_packageService.InstallCompiledPackageData(packageDefinition, packageFile, _umbracoContext.Security.GetUserId().ResultOr(0));
}
/// <summary>
/// Don't show the view if there's already packages installed
/// </summary>
public override string View => _packageService.GetAllInstalledPackages().Any() ? string.Empty : base.View;
public override bool RequiresExecution(Guid? model)
@@ -94,6 +92,7 @@ namespace Umbraco.Web.Install.InstallSteps
return false;
}
//Don't continue if there's already packages installed
if (_packageService.GetAllInstalledPackages().Any())
return false;

View File

@@ -46,7 +46,7 @@ namespace Umbraco.Web.Install.InstallSteps
var packageFile = new FileInfo(definition.PackagePath);
_packagingService.InstallCompiledPackageData(definition, packageFile, _umbracoContext.Security.GetUserId().ResultOr(0));
_packagingService.InstallCompiledPackageData(definition, packageFile, _umbracoContext.Security.GetUserId().ResultOr(-1));
}
public override bool RequiresExecution(object model)

View File

@@ -1,21 +1,16 @@
using System.Web;
using Semver;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.Migrations;
using Umbraco.Core.Scoping;
using Umbraco.Web.WebApi.Filters;
namespace Umbraco.Web.Migrations
namespace Umbraco.Web.Migrations.PostMigrations
{
/// <summary>
/// After upgrade we clear out the csrf tokens
/// Clears Csrf tokens.
/// </summary>
public class ClearCsrfCookiesAfterUpgrade : IPostMigration
public class ClearCsrfCookies : IMigration
{
public void Execute(string name, IScope scope, SemVersion originVersion, SemVersion targetVersion, ILogger logger)
public void Migrate()
{
if (name != Constants.System.UmbracoUpgradePlanName) return;
if (HttpContext.Current == null) return;
var http = new HttpContextWrapper(HttpContext.Current);

View File

@@ -0,0 +1,31 @@
using Umbraco.Core.Migrations.PostMigrations;
using Umbraco.Web.Cache;
using Umbraco.Web.PublishedCache;
namespace Umbraco.Web.Migrations.PostMigrations
{
/// <summary>
/// Implements <see cref="IPublishedSnapshotRebuilder"/> in Umbraco.Web (rebuilding).
/// </summary>
public class PublishedSnapshotRebuilder : IPublishedSnapshotRebuilder
{
private readonly IPublishedSnapshotService _publishedSnapshotService;
private readonly DistributedCache _distributedCache;
/// <summary>
/// Initializes a new instance of the <see cref="PublishedSnapshotRebuilder"/> class.
/// </summary>
public PublishedSnapshotRebuilder(IPublishedSnapshotService publishedSnapshotService, DistributedCache distributedCache)
{
_publishedSnapshotService = publishedSnapshotService;
_distributedCache = distributedCache;
}
/// <inheritdoc />
public void Rebuild()
{
_publishedSnapshotService.Rebuild();
_distributedCache.RefreshAllPublishedSnapshot();
}
}
}

View File

@@ -198,12 +198,15 @@ namespace Umbraco.Web.Models.Mapping
foreach (var p in properties.Where(x => x.DataTypeId != 0).OrderBy(x => x.SortOrder))
{
var propertyEditor = _propertyEditors[p.PropertyEditorAlias];
var configuration = _dataTypeService.GetDataType(p.DataTypeId).Configuration;
var dataType = _dataTypeService.GetDataType(p.DataTypeId);
if (propertyEditor == null)
throw new InvalidOperationException("No property editor could be resolved with the alias: " + p.PropertyEditorAlias + ", ensure all packages are installed correctly.");
var config = dataType.Editor.GetConfigurationEditor().ToConfigurationEditor(dataType.Configuration);
mappedProperties.Add(new TPropertyType
{
Id = p.Id,
@@ -213,7 +216,7 @@ namespace Umbraco.Web.Models.Mapping
Validation = new PropertyTypeValidation {Mandatory = p.Mandatory, Pattern = p.ValidationRegExp},
Label = p.Name,
View = propertyEditor.GetValueEditor().View,
Config = propertyEditor.GetConfigurationEditor().ToConfigurationEditor(configuration),
Config = config,
//Value = "",
GroupId = groupId,
Inherited = inherited,

View File

@@ -48,6 +48,21 @@ namespace Umbraco.Web.PublishedCache
#endregion
#region Rebuild
/// <summary>
/// Rebuilds internal caches (but does not reload).
/// </summary>
/// <remarks>
/// <para>Forces the snapshot service to rebuild its internal caches. For instance, some caches
/// may rely on a database table to store pre-serialized version of documents.</para>
/// <para>This does *not* reload the caches. Caches need to be reloaded, for instance via
/// <see cref="DistributedCache" /> RefreshAllPublishedSnapshot method.</para>
/// </remarks>
void Rebuild();
#endregion
#region Preview
/* Later on we can imagine that EnterPreview would handle a "level" that would be either

View File

@@ -27,6 +27,7 @@ using Umbraco.Web.Cache;
using Umbraco.Web.Install;
using Umbraco.Web.PublishedCache.NuCache.DataSource;
using Umbraco.Web.Routing;
using File = System.IO.File;
namespace Umbraco.Web.PublishedCache.NuCache
{
@@ -142,31 +143,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
if (registered)
{
string path;
var tempLocation = globalSettings.LocalTempStorageLocation;
switch (tempLocation)
{
case LocalTempStorage.AspNetTemp:
path = Path.Combine(HttpRuntime.CodegenDir, "UmbracoData", "NuCache");
break;
case LocalTempStorage.EnvironmentTemp:
// TODO: why has this to be repeated everywhere?!
// include the appdomain hash is just a safety check, for example if a website is moved from worker A to worker B and then back
// to worker A again, in theory the %temp% folder should already be empty but we really want to make sure that its not
// utilizing an old path - assuming we cannot have SHA1 collisions on AppDomainAppId
var appDomainHash = HttpRuntime.AppDomainAppId.GenerateHash();
path = Path.Combine(Environment.ExpandEnvironmentVariables("%temp%"), "UmbracoData", appDomainHash, "NuCache");
break;
//case LocalTempStorage.Default:
//case LocalTempStorage.Unknown:
default:
path = IOHelper.MapPath("~/App_Data/TEMP/NuCache");
break;
}
if (!Directory.Exists(path))
Directory.CreateDirectory(path);
var path = GetLocalFilesPath();
var localContentDbPath = Path.Combine(path, "NuCache.Content.db");
var localMediaDbPath = Path.Combine(path, "NuCache.Media.db");
_localDbExists = System.IO.File.Exists(localContentDbPath) && System.IO.File.Exists(localMediaDbPath);
@@ -295,13 +272,69 @@ namespace Umbraco.Web.PublishedCache.NuCache
#endregion
#region Local files
private string GetLocalFilesPath()
{
string path;
var tempLocation = _globalSettings.LocalTempStorageLocation;
switch (tempLocation)
{
case LocalTempStorage.AspNetTemp:
path = Path.Combine(HttpRuntime.CodegenDir, "UmbracoData", "NuCache");
break;
case LocalTempStorage.EnvironmentTemp:
// TODO: why has this to be repeated everywhere?!
// include the appdomain hash is just a safety check, for example if a website is moved from worker A to worker B and then back
// to worker A again, in theory the %temp% folder should already be empty but we really want to make sure that its not
// utilizing an old path - assuming we cannot have SHA1 collisions on AppDomainAppId
var appDomainHash = HttpRuntime.AppDomainAppId.GenerateHash();
path = Path.Combine(Environment.ExpandEnvironmentVariables("%temp%"), "UmbracoData", appDomainHash, "NuCache");
break;
//case LocalTempStorage.Default:
//case LocalTempStorage.Unknown:
default:
path = IOHelper.MapPath("~/App_Data/TEMP/NuCache");
break;
}
if (!Directory.Exists(path))
Directory.CreateDirectory(path);
return path;
}
private void DeleteLocalFilesForContent()
{
if (_isReady && _localContentDb != null)
throw new InvalidOperationException("Cannot delete local files while the cache uses them.");
var path = GetLocalFilesPath();
var localContentDbPath = Path.Combine(path, "NuCache.Content.db");
if (File.Exists(localContentDbPath))
File.Delete(localContentDbPath);
}
private void DeleteLocalFilesForMedia()
{
if (_isReady && _localMediaDb != null)
throw new InvalidOperationException("Cannot delete local files while the cache uses them.");
var path = GetLocalFilesPath();
var localMediaDbPath = Path.Combine(path, "NuCache.Media.db");
if (File.Exists(localMediaDbPath))
File.Delete(localMediaDbPath);
}
#endregion
#region Environment
public override bool EnsureEnvironment(out IEnumerable<string> errors)
{
// must have app_data and be able to write files into it
var ok = FilePermissionHelper.TryCreateDirectory(SystemDirectories.Data);
errors = ok ? Enumerable.Empty<string>() : new[] { "NuCache local DB files." };
var ok = FilePermissionHelper.TryCreateDirectory(GetLocalFilesPath());
errors = ok ? Enumerable.Empty<string>() : new[] { "NuCache local files." };
return ok;
}
@@ -560,10 +593,11 @@ namespace Umbraco.Web.PublishedCache.NuCache
public override void Notify(ContentCacheRefresher.JsonPayload[] payloads, out bool draftChanged, out bool publishedChanged)
{
// no cache, nothing we can do
// no cache, trash everything
if (_isReady == false)
{
draftChanged = publishedChanged = false;
DeleteLocalFilesForContent();
draftChanged = publishedChanged = true;
return;
}
@@ -655,10 +689,11 @@ namespace Umbraco.Web.PublishedCache.NuCache
public override void Notify(MediaCacheRefresher.JsonPayload[] payloads, out bool anythingChanged)
{
// no cache, nothing we can do
// no cache, trash everything
if (_isReady == false)
{
anythingChanged = false;
DeleteLocalFilesForMedia();
anythingChanged = true;
return;
}
@@ -1277,6 +1312,21 @@ namespace Umbraco.Web.PublishedCache.NuCache
#region Rebuild Database PreCache
public override void Rebuild()
{
_logger.Debug<PublishedSnapshotService>("Rebuilding...");
using (var scope = _scopeProvider.CreateScope(repositoryCacheMode: RepositoryCacheMode.Scoped))
{
scope.ReadLock(Constants.Locks.ContentTree);
scope.ReadLock(Constants.Locks.MediaTree);
scope.ReadLock(Constants.Locks.MemberTree);
RebuildContentDbCacheLocked(scope, 5000, null);
RebuildMediaDbCacheLocked(scope, 5000, null);
RebuildMemberDbCacheLocked(scope, 5000, null);
scope.Complete();
}
}
public void RebuildContentDbCache(int groupSize = 5000, IEnumerable<int> contentTypeIds = null)
{
using (var scope = _scopeProvider.CreateScope(repositoryCacheMode: RepositoryCacheMode.Scoped))

View File

@@ -33,6 +33,9 @@ namespace Umbraco.Web.PublishedCache
public abstract void Notify(DataTypeCacheRefresher.JsonPayload[] payloads);
public abstract void Notify(DomainCacheRefresher.JsonPayload[] payloads);
public virtual void Rebuild()
{ }
public virtual void Dispose()
{ }
}

View File

@@ -9,6 +9,8 @@ using Umbraco.Core.Composing;
using Umbraco.Core.Dashboards;
using Umbraco.Core.Dictionary;
using Umbraco.Core.Events;
using Umbraco.Core.Migrations.PostMigrations;
using Umbraco.Web.Migrations.PostMigrations;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.PropertyEditors.ValueConverters;
@@ -249,6 +251,9 @@ namespace Umbraco.Web.Runtime
.Append<Soundcloud>()
.Append<Issuu>()
.Append<Hulu>();
// replace with web implementation
composition.RegisterUnique<IPublishedSnapshotRebuilder, Migrations.PostMigrations.PublishedSnapshotRebuilder>();
}
}
}

View File

@@ -197,6 +197,7 @@
<Compile Include="Media\TypeDetector\SvgDetector.cs" />
<Compile Include="Media\TypeDetector\TIFFDetector.cs" />
<Compile Include="Media\UploadAutoFillProperties.cs" />
<Compile Include="Migrations\PostMigrations\PublishedSnapshotRebuilder.cs" />
<Compile Include="Models\ContentEditing\LinkDisplay.cs" />
<Compile Include="Models\ContentEditing\MacroDisplay.cs" />
<Compile Include="Models\ContentEditing\MacroParameterDisplay.cs" />
@@ -886,7 +887,7 @@
<Compile Include="Security\BackOfficeCookieManager.cs" />
<Compile Include="Security\UmbracoBackOfficeCookieAuthOptions.cs" />
<Compile Include="Scheduling\TaskAndFactoryExtensions.cs" />
<Compile Include="Migrations\ClearCsrfCookiesAfterUpgrade.cs" />
<Compile Include="Migrations\PostMigrations\ClearCsrfCookies.cs" />
<Compile Include="Components\NotificationsComponent.cs" />
<Compile Include="TagQuery.cs" />
<Compile Include="Trees\CoreTreeAttribute.cs" />