The database you're trying to use does not support case insensitive queries.
We currently do not support these types of databases.
" +
- "You can fix this by changing the following setting in your my.ini file in your MySQL installation directory:
" +
- "Note: Make sure to check with your hosting provider if they support case insensitive queries as well.
" +
- "("Database upgrade started");
- var message = GetResultMessageForMySql();
+ var message = _scopeProvider.SqlContext.DatabaseType.IsMySql() ? ResultMessageForMySql : "";
// upgrade
var upgrader = new UmbracoUpgrader();
@@ -554,47 +561,14 @@ namespace Umbraco.Core.Migrations.Install
}
}
- private string GetResultMessageForMySql()
- {
- if (_databaseFactory.GetType() == typeof(MySqlSyntaxProvider))
- {
- return "
Congratulations, the database step ran successfully!
" +
- "Note: You're using MySQL and the database instance you're connecting to seems to support case insensitive queries.
" +
- "However, your hosting provider may not support this option. Umbraco does not currently support MySQL installs that do not support case insensitive queries
" +
- "Make sure to check with your hosting provider if they support case insensitive queries as well.
" +
- "They can check this by looking for the following setting in the my.ini file in their MySQL installation directory:
" +
- "lower_case_table_names=1
" +
- "For more technical information on case sensitivity in MySQL, have a look at " +
- "the documentation on the subject
";
- }
- return string.Empty;
- }
-
- /*
- private string GetResultMessageForMySql(bool? supportsCaseInsensitiveQueries)
- {
- if (supportsCaseInsensitiveQueries == null)
- {
- return "
Warning! Could not check if your database type supports case insensitive queries.
We currently do not support these databases that do not support case insensitive queries.
" +
- "You can check this by looking for the following setting in your my.ini file in your MySQL installation directory:
" +
- "lower_case_table_names=1
" +
- "Note: Make sure to check with your hosting provider if they support case insensitive queries as well.
" +
- "For more technical information on case sensitivity in MySQL, have a look at " +
- "the documentation on the subject
";
- }
- if (SqlSyntax.GetType() == typeof(MySqlSyntaxProvider))
- {
- return "
Congratulations, the database step ran successfully!
" +
- "Note: You're using MySQL and the database instance you're connecting to seems to support case insensitive queries.
" +
- "However, your hosting provider may not support this option. Umbraco does not currently support MySQL installs that do not support case insensitive queries
" +
- "Make sure to check with your hosting provider if they support case insensitive queries as well.
" +
- "They can check this by looking for the following setting in the my.ini file in their MySQL installation directory:
" +
- "lower_case_table_names=1
" +
- "For more technical information on case sensitivity in MySQL, have a look at " +
- "the documentation on the subject
";
- }
- return string.Empty;
- }*/
+ private const string ResultMessageForMySql = "
Congratulations, the database step ran successfully!
" +
+ "Note: You're using MySQL and the database instance you're connecting to seems to support case insensitive queries.
" +
+ "However, your hosting provider may not support this option. Umbraco does not currently support MySQL installs that do not support case insensitive queries
" +
+ "Make sure to check with your hosting provider if they support case insensitive queries as well.
" +
+ "They can check this by looking for the following setting in the my.ini file in their MySQL installation directory:
" +
+ "lower_case_table_names=1
" +
+ "For more technical information on case sensitivity in MySQL, have a look at " +
+ "the documentation on the subject
";
private Attempt CheckReadyForInstall()
{
@@ -630,11 +604,29 @@ namespace Umbraco.Core.Migrations.Install
};
}
- internal class Result
+ ///
+ /// Represents the result of a database creation or upgrade.
+ ///
+ public class Result
{
+ ///
+ /// Gets or sets a value indicating whether an upgrade is required.
+ ///
public bool RequiresUpgrade { get; set; }
+
+ ///
+ /// Gets or sets the message returned by the operation.
+ ///
public string Message { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the operation succeeded.
+ ///
public bool Success { get; set; }
+
+ ///
+ /// Gets or sets an install progress pseudo-percentage.
+ ///
public string Percentage { get; set; }
}
diff --git a/src/Umbraco.Core/Migrations/Install/DatabaseSchemaCreator.cs b/src/Umbraco.Core/Migrations/Install/DatabaseSchemaCreator.cs
index 64be8161f2..eba5e61390 100644
--- a/src/Umbraco.Core/Migrations/Install/DatabaseSchemaCreator.cs
+++ b/src/Umbraco.Core/Migrations/Install/DatabaseSchemaCreator.cs
@@ -138,9 +138,8 @@ namespace Umbraco.Core.Migrations.Install
{
var result = new DatabaseSchemaResult(SqlSyntax);
- //get the db index defs
- result.DbIndexDefinitions = SqlSyntax.GetDefinedIndexes(_database)
- .Select(x => new DbIndexDefinition(x)).ToArray();
+ result.IndexDefinitions.AddRange(SqlSyntax.GetDefinedIndexes(_database)
+ .Select(x => new DbIndexDefinition(x)));
result.TableDefinitions.AddRange(OrderedTables
.Select(x => DefinitionFactory.GetTableDefinition(x, SqlSyntax)));
@@ -279,7 +278,7 @@ namespace Umbraco.Core.Migrations.Install
{
//These are just column indexes NOT constraints or Keys
//var colIndexesInDatabase = result.DbIndexDefinitions.Where(x => x.IndexName.InvariantStartsWith("IX_")).Select(x => x.IndexName).ToList();
- var colIndexesInDatabase = result.DbIndexDefinitions.Select(x => x.IndexName).ToList();
+ var colIndexesInDatabase = result.IndexDefinitions.Select(x => x.IndexName).ToList();
var indexesInSchema = result.TableDefinitions.SelectMany(x => x.Indexes.Select(y => y.Name)).ToList();
//Add valid and invalid index differences to the result object
diff --git a/src/Umbraco.Core/Migrations/Install/DatabaseSchemaResult.cs b/src/Umbraco.Core/Migrations/Install/DatabaseSchemaResult.cs
index 0ec27cf0b1..4c68addebc 100644
--- a/src/Umbraco.Core/Migrations/Install/DatabaseSchemaResult.cs
+++ b/src/Umbraco.Core/Migrations/Install/DatabaseSchemaResult.cs
@@ -2,153 +2,55 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
-using Umbraco.Core.Configuration;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Migrations.Install
{
- public class DatabaseSchemaResult
+ ///
+ /// Represents ...
+ ///
+ internal class DatabaseSchemaResult
{
- private readonly ISqlSyntaxProvider _sqlSyntax;
+ private readonly bool _isMySql;
public DatabaseSchemaResult(ISqlSyntaxProvider sqlSyntax)
{
- _sqlSyntax = sqlSyntax;
+ _isMySql = sqlSyntax is MySqlSyntaxProvider;
+
Errors = new List>();
TableDefinitions = new List();
ValidTables = new List();
ValidColumns = new List();
ValidConstraints = new List();
ValidIndexes = new List();
+ IndexDefinitions = new List();
}
- public List> Errors { get; set; }
+ public List> Errors { get; }
- public List TableDefinitions { get; set; }
+ public List TableDefinitions { get; }
- public List ValidTables { get; set; }
+ // fixme TableDefinitions are those that should be there, IndexDefinitions are those that... are in DB?
+ internal List IndexDefinitions { get; }
- public List ValidColumns { get; set; }
+ public List ValidTables { get; }
- public List ValidConstraints { get; set; }
+ public List ValidColumns { get; }
- public List ValidIndexes { get; set; }
+ public List ValidConstraints { get; }
- internal IEnumerable DbIndexDefinitions { get; set; }
+ public List ValidIndexes { get; }
///
- /// Determines the version of the currently installed database by detecting the current database structure
+ /// Determines whether the database contains an installed version.
///
- ///
- /// A with Major and Minor values for
- /// non-empty database, otherwise "0.0.0" for empty databases.
- ///
- public Version DetermineInstalledVersion()
+ ///
+ /// A database contains an installed version when it contains at least one valid table.
+ ///
+ public bool DetermineHasInstalledVersion()
{
- // v8 = kill versions older than 7
-
- //If (ValidTables.Count == 0) database is empty and we return -> new Version(0, 0, 0);
- if (ValidTables.Count == 0)
- return new Version(0, 0, 0);
-
- // FIXME - but the whole detection is borked really
- return new Version(8, 0, 0);
-
- //If Errors is empty or if TableDefinitions tables + columns correspond to valid tables + columns then we're at current version
- if (Errors.Any() == false ||
- (TableDefinitions.All(x => ValidTables.Contains(x.Name))
- && TableDefinitions.SelectMany(definition => definition.Columns).All(x => ValidColumns.Contains(x.Name))))
- return UmbracoVersion.Current;
-
- //If Errors contains umbracoApp or umbracoAppTree its pre-6.0.0 -> new Version(4, 10, 0);
- if (Errors.Any(x => x.Item1.Equals("Table") && (x.Item2.InvariantEquals("umbracoApp") || x.Item2.InvariantEquals("umbracoAppTree"))))
- {
- //If Errors contains umbracoUser2app or umbracoAppTree foreignkey to umbracoApp exists its pre-4.8.0 -> new Version(4, 7, 0);
- if (Errors.Any(x =>
- x.Item1.Equals("Constraint")
- && (x.Item2.InvariantContains("umbracoUser2app_umbracoApp")
- || x.Item2.InvariantContains("umbracoAppTree_umbracoApp"))))
- {
- return new Version(4, 7, 0);
- }
-
- return new Version(4, 8, 0);
- }
-
- //if the error is for umbracoServer
- if (Errors.Any(x => x.Item1.Equals("Table") && (x.Item2.InvariantEquals("umbracoServer"))))
- {
- return new Version(6, 0, 0);
- }
-
- //if the error indicates a problem with the column cmsMacroProperty.macroPropertyType then it is not version 7
- // since these columns get removed in v7
- if (Errors.Any(x => x.Item1.Equals("Column") && (x.Item2.InvariantEquals("cmsMacroProperty,macroPropertyType"))))
- {
- //if the error is for this IX_umbracoNodeTrashed which is added in 6.2 AND in 7.1 but we do not have the above columns
- // then it must mean that we aren't on 6.2 so must be 6.1
- if (Errors.Any(x => x.Item1.Equals("Index") && (x.Item2.InvariantEquals("IX_umbracoNodeTrashed"))))
- {
- return new Version(6, 1, 0);
- }
- else
- {
- //if there are no errors for that index, then the person must have 6.2 installed
- return new Version(6, 2, 0);
- }
- }
-
- //if the error indicates a problem with the constraint FK_cms-OBSOLETE-Content_cmsContentType_nodeId then it is not version 7.2
- // since this gets added in 7.2.0 so it must be the previous version
- if (Errors.Any(x => x.Item1.Equals("Constraint") && (x.Item2.InvariantEquals("FK_cms-OBSOLETE-Content_cmsContentType_nodeId"))))
- {
- return new Version(7, 0, 0);
- }
-
- //if the error is for umbracoAccess it must be the previous version to 7.3 since that is when it is added
- if (Errors.Any(x => x.Item1.Equals("Table") && (x.Item2.InvariantEquals("umbracoAccess"))))
- {
- return new Version(7, 2, 0);
- }
-
- //if the error is for cms-OBSOLETE-PropertyData.dataDecimal it must be the previous version to 7.4 since that is when it is added
- if (Errors.Any(x => x.Item1.Equals("Column") && (x.Item2.InvariantEquals("cms-OBSOLETE-PropertyData,dataDecimal"))))
- {
- return new Version(7, 3, 0);
- }
-
- //if the error is for umbracoRedirectUrl it must be the previous version to 7.5 since that is when it is added
- if (Errors.Any(x => x.Item1.Equals("Table") && (x.Item2.InvariantEquals("umbracoRedirectUrl"))))
- {
- return new Version(7, 4, 0);
- }
-
- //if the error indicates a problem with the column cmsMacroProperty.uniquePropertyId then it is not version 7.6 since that is when it is added
- if (Errors.Any(x => x.Item1.Equals("Column") && (x.Item2.InvariantEquals("cmsMacroProperty,uniquePropertyId"))))
- {
- return new Version(7, 5, 0);
- }
-
- //if the error is for umbracoUserGroup it must be the previous version to 7.7 since that is when it is added
- if (Errors.Any(x => x.Item1.Equals("Table") && (x.Item2.InvariantEquals("umbracoUserStartNode"))))
- {
- return new Version(7, 6, 0);
- }
-
- //if the error is for cmsMedia it must be the previous version to 7.8 since that is when it is added
- if (Errors.Any(x => x.Item1.Equals("Table") && (x.Item2.InvariantEquals("umbracoMedia"))))
- {
- return new Version(7, 7, 0);
- }
-
- //if the error is for isSensitive column it must be the previous version to 7.9 since that is when it is added
- if (Errors.Any(x => x.Item1.Equals("Column") && (x.Item2.InvariantEquals("cmsMemberType,isSensitive"))))
- {
- return new Version(7, 8, 0);
- }
-
- return UmbracoVersion.Current;
+ return ValidTables.Count > 0;
}
///
@@ -200,9 +102,9 @@ namespace Umbraco.Core.Migrations.Install
sb.AppendLine(" ");
}
- if (_sqlSyntax is MySqlSyntaxProvider)
+ if (_isMySql)
{
- sb.AppendLine("Please note that the constraints could not be validated because the current dataprovider is MySql.");
+ sb.AppendLine("Please note that the constraints could not be validated because the current data provider is MySql.");
}
return sb.ToString();
diff --git a/src/Umbraco.Core/Models/PublishedContent/IPublishedContent.cs b/src/Umbraco.Core/Models/PublishedContent/IPublishedContent.cs
index 5b604eff3f..0c049e81bf 100644
--- a/src/Umbraco.Core/Models/PublishedContent/IPublishedContent.cs
+++ b/src/Umbraco.Core/Models/PublishedContent/IPublishedContent.cs
@@ -151,7 +151,7 @@ namespace Umbraco.Core.Models.PublishedContent
/// is the edited version) or false (document is published, and has not been edited, and
/// what is returned is the published version).
///
- bool IsDraft { get; }
+ bool IsDraft(string culture = null);
// fixme - consider having an IsPublished flag too
// so that when IsDraft is true, we can check whether there is a published version?
diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedContentWrapped.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedContentWrapped.cs
index 5bdeb3685d..6a69d0b9e1 100644
--- a/src/Umbraco.Core/Models/PublishedContent/PublishedContentWrapped.cs
+++ b/src/Umbraco.Core/Models/PublishedContent/PublishedContentWrapped.cs
@@ -109,7 +109,7 @@ namespace Umbraco.Core.Models.PublishedContent
public virtual PublishedItemType ItemType => _content.ItemType;
///
- public virtual bool IsDraft => _content.IsDraft;
+ public virtual bool IsDraft(string culture = null) => _content.IsDraft(culture);
#endregion
diff --git a/src/Umbraco.Core/Serialization/CaseInsensitiveDictionaryConverter.cs b/src/Umbraco.Core/Serialization/CaseInsensitiveDictionaryConverter.cs
new file mode 100644
index 0000000000..a92d562a52
--- /dev/null
+++ b/src/Umbraco.Core/Serialization/CaseInsensitiveDictionaryConverter.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using Newtonsoft.Json.Converters;
+
+namespace Umbraco.Core.Serialization
+{
+ ///
+ /// Marks dictionaries so they are deserialized as case-insensitive.
+ ///
+ ///
+ /// [JsonConverter(typeof(CaseInsensitiveDictionaryConverter{PropertyData[]}))]
+ /// public Dictionary{string, PropertyData[]} PropertyData {{ get; set; }}
+ ///
+ public class CaseInsensitiveDictionaryConverter : CustomCreationConverter
+ {
+ public override bool CanWrite => false;
+
+ public override bool CanRead => true;
+
+ public override bool CanConvert(Type objectType) => typeof(IDictionary).IsAssignableFrom(objectType);
+
+ public override IDictionary Create(Type objectType) => new Dictionary(StringComparer.OrdinalIgnoreCase);
+ }
+}
diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj
index 8593a715fe..ba0cf97bf7 100755
--- a/src/Umbraco.Core/Umbraco.Core.csproj
+++ b/src/Umbraco.Core/Umbraco.Core.csproj
@@ -1311,6 +1311,7 @@
+
diff --git a/src/Umbraco.Tests/Persistence/SchemaValidationTest.cs b/src/Umbraco.Tests/Persistence/SchemaValidationTest.cs
index b8f1fab918..2c875d6afc 100644
--- a/src/Umbraco.Tests/Persistence/SchemaValidationTest.cs
+++ b/src/Umbraco.Tests/Persistence/SchemaValidationTest.cs
@@ -26,7 +26,6 @@ namespace Umbraco.Tests.Persistence
// Assert
Assert.That(result.Errors.Count, Is.EqualTo(0));
- Assert.AreEqual(result.DetermineInstalledVersion(), UmbracoVersion.Current);
}
}
}
diff --git a/src/Umbraco.Tests/Published/NestedContentTests.cs b/src/Umbraco.Tests/Published/NestedContentTests.cs
index 920fa2acd5..cf00345b65 100644
--- a/src/Umbraco.Tests/Published/NestedContentTests.cs
+++ b/src/Umbraco.Tests/Published/NestedContentTests.cs
@@ -262,7 +262,7 @@ namespace Umbraco.Tests.Published
// ReSharper disable UnassignedGetOnlyAutoProperty
public override PublishedItemType ItemType { get; }
- public override bool IsDraft { get; }
+ public override bool IsDraft(string culture = null) => false;
public override IPublishedContent Parent { get; }
public override IEnumerable Children { get; }
public override PublishedContentType ContentType { get; }
diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentDataTableTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentDataTableTests.cs
index a640423515..aa9e7e4918 100644
--- a/src/Umbraco.Tests/PublishedContent/PublishedContentDataTableTests.cs
+++ b/src/Umbraco.Tests/PublishedContent/PublishedContentDataTableTests.cs
@@ -216,7 +216,7 @@ namespace Umbraco.Tests.PublishedContent
public DateTime UpdateDate { get; set; }
public Guid Version { get; set; }
public int Level { get; set; }
- public bool IsDraft { get; set; }
+ public bool IsDraft(string culture = null) => false;
public IEnumerable Properties { get; set; }
diff --git a/src/Umbraco.Tests/PublishedContent/SolidPublishedSnapshot.cs b/src/Umbraco.Tests/PublishedContent/SolidPublishedSnapshot.cs
index efd1c6ae8b..0c4059ca7c 100644
--- a/src/Umbraco.Tests/PublishedContent/SolidPublishedSnapshot.cs
+++ b/src/Umbraco.Tests/PublishedContent/SolidPublishedSnapshot.cs
@@ -162,7 +162,6 @@ namespace Umbraco.Tests.PublishedContent
WriterId = CreatorId = 0;
CreateDate = UpdateDate = DateTime.Now;
Version = Guid.Empty;
- IsDraft = false;
ContentType = contentType;
}
@@ -192,7 +191,7 @@ namespace Umbraco.Tests.PublishedContent
public string GetUrl(string culture = null) => throw new NotSupportedException();
public PublishedItemType ItemType { get { return PublishedItemType.Content; } }
- public bool IsDraft { get; set; }
+ public bool IsDraft(string culture = null) => false;
#endregion
diff --git a/src/Umbraco.Tests/TestHelpers/Stubs/TestPublishedContent.cs b/src/Umbraco.Tests/TestHelpers/Stubs/TestPublishedContent.cs
index 0faf1537b3..9c0bb61cb3 100644
--- a/src/Umbraco.Tests/TestHelpers/Stubs/TestPublishedContent.cs
+++ b/src/Umbraco.Tests/TestHelpers/Stubs/TestPublishedContent.cs
@@ -47,7 +47,7 @@ namespace Umbraco.Tests.TestHelpers.Stubs
public string Url { get; set; }
public string GetUrl(string culture = null) => throw new NotSupportedException();
public PublishedItemType ItemType => ContentType.ItemType;
- public bool IsDraft { get; set; }
+ public bool IsDraft(string culture = null) => false;
public IPublishedContent Parent { get; set; }
public IEnumerable Children { get; set; }
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js
index 407416f2a1..f1e2150579 100644
--- a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js
@@ -815,7 +815,7 @@
//ensure the save flag is set
selectedVariant.save = true;
- performSave({ saveMethod: contentResource.publish, action: "save" }).then(function (data) {
+ performSave({ saveMethod: $scope.saveMethod(), action: "save" }).then(function (data) {
previewWindow.location.href = redirect;
}, function (err) {
//validation issues ....
diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/insertcodesnippet/insertcodesnippet.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/insertcodesnippet/insertcodesnippet.controller.js
index 526d076048..2b40d496f5 100644
--- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/insertcodesnippet/insertcodesnippet.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/insertcodesnippet/insertcodesnippet.controller.js
@@ -77,7 +77,7 @@
var emptyStateMessage = values[2];
var dictionaryItemPicker = {
- section: "settings",
+ section: "translation",
treeAlias: "dictionary",
entityType: "dictionary",
multiPicker: false,
diff --git a/src/Umbraco.Web.UI.Client/src/views/partialviewmacros/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/partialviewmacros/edit.controller.js
index afc00bb7e2..372cecb36c 100644
--- a/src/Umbraco.Web.UI.Client/src/views/partialviewmacros/edit.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/partialviewmacros/edit.controller.js
@@ -201,7 +201,7 @@
var emptyStateMessage = values[1];
var dictionaryPicker = {
- section: "settings",
+ section: "translation",
treeAlias: "dictionary",
entityType: "dictionary",
multiPicker: false,
diff --git a/src/Umbraco.Web.UI.Client/src/views/partialviews/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/partialviews/edit.controller.js
index ff14ea0ebd..292898814d 100644
--- a/src/Umbraco.Web.UI.Client/src/views/partialviews/edit.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/partialviews/edit.controller.js
@@ -207,7 +207,7 @@
var emptyStateMessage = values[1];
var dictionaryItem = {
- section: "settings",
+ section: "translation",
treeAlias: "dictionary",
entityType: "dictionary",
multiPicker: false,
diff --git a/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js
index 8ac9dc78e8..1f6fb8863a 100644
--- a/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js
@@ -438,7 +438,7 @@
var emptyStateMessage = values[1];
var dictionaryItem = {
- section: "settings",
+ section: "translation",
treeAlias: "dictionary",
entityType: "dictionary",
multiPicker: false,
diff --git a/src/Umbraco.Web/Install/Controllers/InstallApiController.cs b/src/Umbraco.Web/Install/Controllers/InstallApiController.cs
index 387360163a..81b1aac217 100644
--- a/src/Umbraco.Web/Install/Controllers/InstallApiController.cs
+++ b/src/Umbraco.Web/Install/Controllers/InstallApiController.cs
@@ -41,7 +41,7 @@ namespace Umbraco.Web.Install.Controllers
public bool PostValidateDatabaseConnection(DatabaseModel model)
{
- var canConnect = _databaseBuilder.CheckConnection(model.DatabaseType.ToString(), model.ConnectionString, model.Server, model.DatabaseName, model.Login, model.Password, model.IntegratedAuth);
+ var canConnect = _databaseBuilder.CanConnect(model.DatabaseType.ToString(), model.ConnectionString, model.Server, model.DatabaseName, model.Login, model.Password, model.IntegratedAuth);
return canConnect;
}
diff --git a/src/Umbraco.Web/Install/InstallSteps/DatabaseConfigureStep.cs b/src/Umbraco.Web/Install/InstallSteps/DatabaseConfigureStep.cs
index a54b64733f..2fe6c0ceda 100644
--- a/src/Umbraco.Web/Install/InstallSteps/DatabaseConfigureStep.cs
+++ b/src/Umbraco.Web/Install/InstallSteps/DatabaseConfigureStep.cs
@@ -1,7 +1,6 @@
using System;
using System.Configuration;
using Umbraco.Core;
-using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Migrations.Install;
using Umbraco.Web.Install.Models;
@@ -29,7 +28,7 @@ namespace Umbraco.Web.Install.InstallSteps
database = new DatabaseModel();
}
- if (_databaseBuilder.CheckConnection(database.DatabaseType.ToString(), database.ConnectionString, database.Server, database.DatabaseName, database.Login, database.Password, database.IntegratedAuth) == false)
+ if (_databaseBuilder.CanConnect(database.DatabaseType.ToString(), database.ConnectionString, database.Server, database.DatabaseName, database.Login, database.Password, database.IntegratedAuth) == false)
{
throw new InstallException("Could not connect to the database");
}
@@ -79,8 +78,7 @@ namespace Umbraco.Web.Install.InstallSteps
try
{
//Since a connection string was present we verify the db can connect and query
- var result = _databaseBuilder.ValidateDatabaseSchema();
- result.DetermineInstalledVersion();
+ _ = _databaseBuilder.ValidateSchema();
return false;
}
catch (Exception ex)
diff --git a/src/Umbraco.Web/Install/InstallSteps/DatabaseInstallStep.cs b/src/Umbraco.Web/Install/InstallSteps/DatabaseInstallStep.cs
index c4cad38072..a9daee6e95 100644
--- a/src/Umbraco.Web/Install/InstallSteps/DatabaseInstallStep.cs
+++ b/src/Umbraco.Web/Install/InstallSteps/DatabaseInstallStep.cs
@@ -29,7 +29,7 @@ namespace Umbraco.Web.Install.InstallSteps
if (_runtime.Level == RuntimeLevel.Run)
throw new Exception("Umbraco is already configured!");
- var result = _databaseBuilder.CreateDatabaseSchemaAndData();
+ var result = _databaseBuilder.CreateSchemaAndData();
if (result.Success == false)
{
diff --git a/src/Umbraco.Web/Install/InstallSteps/DatabaseUpgradeStep.cs b/src/Umbraco.Web/Install/InstallSteps/DatabaseUpgradeStep.cs
index c078caf906..8283eb6bef 100644
--- a/src/Umbraco.Web/Install/InstallSteps/DatabaseUpgradeStep.cs
+++ b/src/Umbraco.Web/Install/InstallSteps/DatabaseUpgradeStep.cs
@@ -63,18 +63,10 @@ namespace Umbraco.Web.Install.InstallSteps
if (_databaseBuilder.IsConnectionStringConfigured(databaseSettings))
{
- //Since a connection string was present we verify whether this is an upgrade or an empty db
- var result = _databaseBuilder.ValidateDatabaseSchema();
-
- var determinedVersion = result.DetermineInstalledVersion();
- if (determinedVersion.Equals(new Version(0, 0, 0)))
- {
- //Fresh install
- return false;
- }
-
- //Upgrade
- return true;
+ // a connection string was present, determine whether this is an install/upgrade
+ // return true (upgrade) if there is an installed version, else false (install)
+ var result = _databaseBuilder.ValidateSchema();
+ return result.DetermineHasInstalledVersion();
}
//no connection string configured, probably a fresh install
diff --git a/src/Umbraco.Web/Models/PublishedContentBase.cs b/src/Umbraco.Web/Models/PublishedContentBase.cs
index 1b8128b4c0..667cf145bd 100644
--- a/src/Umbraco.Web/Models/PublishedContentBase.cs
+++ b/src/Umbraco.Web/Models/PublishedContentBase.cs
@@ -142,7 +142,7 @@ namespace Umbraco.Web.Models
public abstract PublishedItemType ItemType { get; }
///
- public abstract bool IsDraft { get; }
+ public abstract bool IsDraft(string culture = null);
#endregion
diff --git a/src/Umbraco.Web/PublishedCache/NuCache/ContentCache.cs b/src/Umbraco.Web/PublishedCache/NuCache/ContentCache.cs
index edef545d2a..0197d2d640 100644
--- a/src/Umbraco.Web/PublishedCache/NuCache/ContentCache.cs
+++ b/src/Umbraco.Web/PublishedCache/NuCache/ContentCache.cs
@@ -147,7 +147,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
var urlSegment = n.GetUrlSegment(culture);
var hasDomains = _domainHelper.NodeHasDomains(n.Id);
while (hasDomains == false && n != null) // n is null at root
- {
+ {
// no segment indicates this is not published when this is a variant
if (urlSegment.IsNullOrWhiteSpace()) return null;
@@ -173,7 +173,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
var path = "/" + string.Join("/", pathParts); // will be "/" or "/foo" or "/foo/bar" etc
//prefix the root node id containing the domain if it exists (this is a standard way of creating route paths)
//and is done so that we know the ID of the domain node for the path
- var route = (n?.Id.ToString(CultureInfo.InvariantCulture) ?? "") + path;
+ var route = (n?.Id.ToString(CultureInfo.InvariantCulture) ?? "") + path;
return route;
}
@@ -223,24 +223,14 @@ namespace Umbraco.Web.PublishedCache.NuCache
public override IPublishedContent GetById(bool preview, int contentId)
{
- var n = _snapshot.Get(contentId);
- if (n == null) return null;
-
- // both .Draft and .Published cannot be null at the same time
- return preview
- ? n.Draft ?? GetPublishedContentAsPreviewing(n.Published)
- : n.Published;
+ var node = _snapshot.Get(contentId);
+ return GetNodePublishedContent(node, preview);
}
public override IPublishedContent GetById(bool preview, Guid contentId)
{
- var n = _snapshot.Get(contentId);
- if (n == null) return null;
-
- // both .Draft and .Published cannot be null at the same time
- return preview
- ? n.Draft ?? GetPublishedContentAsPreviewing(n.Published)
- : n.Published;
+ var node = _snapshot.Get(contentId);
+ return GetNodePublishedContent(node, preview);
}
public override bool HasById(bool preview, int contentId)
@@ -274,14 +264,24 @@ namespace Umbraco.Web.PublishedCache.NuCache
var c = _snapshot.GetAtRoot();
// both .Draft and .Published cannot be null at the same time
- return c.Select(n => preview
- ? n.Draft ?? GetPublishedContentAsPreviewing(n.Published)
- : n.Published).WhereNotNull().OrderBy(x => x.SortOrder);
+ return c.Select(n => GetNodePublishedContent(n, preview)).WhereNotNull().OrderBy(x => x.SortOrder);
+ }
+
+ private static IPublishedContent GetNodePublishedContent(ContentNode node, bool preview)
+ {
+ if (node == null)
+ return null;
+
+ // both .Draft and .Published cannot be null at the same time
+
+ return preview
+ ? node.Draft ?? GetPublishedContentAsDraft(node.Published)
+ : node.Published;
}
// gets a published content as a previewing draft, if preview is true
// this is for published content when previewing
- internal static IPublishedContent GetPublishedContentAsPreviewing(IPublishedContent content /*, bool preview*/)
+ private static IPublishedContent GetPublishedContentAsDraft(IPublishedContent content /*, bool preview*/)
{
if (content == null /*|| preview == false*/) return null; //content;
@@ -290,7 +290,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
// case we need to unwrap to get to the original IPublishedContentOrMedia.
var inner = PublishedContent.UnwrapIPublishedContent(content);
- return inner.AsPreviewingModel();
+ return inner.AsDraft();
}
public override bool HasContent(bool preview)
diff --git a/src/Umbraco.Web/PublishedCache/NuCache/DataSource/ContentNestedData.cs b/src/Umbraco.Web/PublishedCache/NuCache/DataSource/ContentNestedData.cs
index be3e813275..0f120024cc 100644
--- a/src/Umbraco.Web/PublishedCache/NuCache/DataSource/ContentNestedData.cs
+++ b/src/Umbraco.Web/PublishedCache/NuCache/DataSource/ContentNestedData.cs
@@ -1,5 +1,6 @@
using Newtonsoft.Json;
using System.Collections.Generic;
+using Umbraco.Core.Serialization;
namespace Umbraco.Web.PublishedCache.NuCache.DataSource
{
@@ -9,9 +10,11 @@ namespace Umbraco.Web.PublishedCache.NuCache.DataSource
internal class ContentNestedData
{
[JsonProperty("properties")]
+ [JsonConverter(typeof(CaseInsensitiveDictionaryConverter))]
public Dictionary PropertyData { get; set; }
[JsonProperty("cultureData")]
+ [JsonConverter(typeof(CaseInsensitiveDictionaryConverter))]
public Dictionary CultureData { get; set; }
}
}
diff --git a/src/Umbraco.Web/PublishedCache/NuCache/DataSource/CultureVariation.cs b/src/Umbraco.Web/PublishedCache/NuCache/DataSource/CultureVariation.cs
index 50a2adaeb8..c6e603f5a9 100644
--- a/src/Umbraco.Web/PublishedCache/NuCache/DataSource/CultureVariation.cs
+++ b/src/Umbraco.Web/PublishedCache/NuCache/DataSource/CultureVariation.cs
@@ -13,5 +13,8 @@ namespace Umbraco.Web.PublishedCache.NuCache.DataSource
[JsonProperty("date")]
public DateTime Date { get; set; }
+
+ [JsonProperty("isDraft")]
+ public bool IsDraft { get; set; }
}
}
diff --git a/src/Umbraco.Web/PublishedCache/NuCache/DataSource/DatabaseDataSource.cs b/src/Umbraco.Web/PublishedCache/NuCache/DataSource/DatabaseDataSource.cs
index a143997fab..4531d37b2b 100644
--- a/src/Umbraco.Web/PublishedCache/NuCache/DataSource/DatabaseDataSource.cs
+++ b/src/Umbraco.Web/PublishedCache/NuCache/DataSource/DatabaseDataSource.cs
@@ -182,27 +182,30 @@ namespace Umbraco.Web.PublishedCache.NuCache.DataSource
ContentData d = null;
ContentData p = null;
- if (dto.EditData == null)
+ if (dto.Edited)
{
- if (Debugger.IsAttached)
- throw new Exception("Missing cmsContentNu edited content for node " + dto.Id + ", consider rebuilding.");
- Current.Logger.Warn("Missing cmsContentNu edited content for node {NodeId}, consider rebuilding.", dto.Id);
- }
- else
- {
- var nested = DeserializeNestedData(dto.EditData);
-
- d = new ContentData
+ if (dto.EditData == null)
{
- Name = dto.EditName,
- Published = false,
- TemplateId = dto.EditTemplateId,
- VersionId = dto.VersionId,
- VersionDate = dto.EditVersionDate,
- WriterId = dto.EditWriterId,
- Properties = nested.PropertyData,
- CultureInfos = nested.CultureData
- };
+ if (Debugger.IsAttached)
+ throw new Exception("Missing cmsContentNu edited content for node " + dto.Id + ", consider rebuilding.");
+ Current.Logger.Warn("Missing cmsContentNu edited content for node {NodeId}, consider rebuilding.", dto.Id);
+ }
+ else
+ {
+ var nested = DeserializeNestedData(dto.EditData);
+
+ d = new ContentData
+ {
+ Name = dto.EditName,
+ Published = false,
+ TemplateId = dto.EditTemplateId,
+ VersionId = dto.VersionId,
+ VersionDate = dto.EditVersionDate,
+ WriterId = dto.EditWriterId,
+ Properties = nested.PropertyData,
+ CultureInfos = nested.CultureData
+ };
+ }
}
if (dto.Published)
diff --git a/src/Umbraco.Web/PublishedCache/NuCache/Navigable/NavigableContent.cs b/src/Umbraco.Web/PublishedCache/NuCache/Navigable/NavigableContent.cs
index ae34d0cb32..51badc8b9a 100644
--- a/src/Umbraco.Web/PublishedCache/NuCache/Navigable/NavigableContent.cs
+++ b/src/Umbraco.Web/PublishedCache/NuCache/Navigable/NavigableContent.cs
@@ -29,7 +29,7 @@ namespace Umbraco.Web.PublishedCache.NuCache.Navigable
XmlString(i++, _content.WriterId),
XmlString(i++, _content.CreatorId),
XmlString(i++, _content.UrlSegment),
- XmlString(i, _content.IsDraft)
+ XmlString(i, _content.IsDraft())
};
}
diff --git a/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs b/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs
index a4610e82db..36e5698e32 100644
--- a/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs
+++ b/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs
@@ -273,8 +273,27 @@ namespace Umbraco.Web.PublishedCache.NuCache
///
public override PublishedItemType ItemType => _contentNode.ContentType.ItemType;
+ // fixme
+ // was => _contentData.Published == false;
///
- public override bool IsDraft => _contentData.Published == false;
+ public override bool IsDraft(string culture = null)
+ {
+ // if this is the 'published' published content, nothing can be draft
+ if (_contentData.Published)
+ return false;
+
+ // not the 'published' published content, and does not vary = must be draft
+ if (!ContentType.VariesByCulture())
+ return true;
+
+ // handle context culture
+ if (culture == null)
+ culture = VariationContextAccessor?.VariationContext?.Culture ?? "";
+
+ // not the 'published' published content, and varies
+ // = depends on the culture
+ return _contentData.CultureInfos.TryGetValue(culture, out var cvar) && cvar.IsDraft;
+ }
#endregion
@@ -410,7 +429,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
private string AsPreviewingCacheKey => _asPreviewingCacheKey ?? (_asPreviewingCacheKey = CacheKeys.PublishedContentAsPreviewing(Key));
// used by ContentCache
- internal IPublishedContent AsPreviewingModel()
+ internal IPublishedContent AsDraft()
{
if (IsPreviewing)
return this;
diff --git a/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs b/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs
index 100833216e..4d6115f02d 100755
--- a/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs
+++ b/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs
@@ -1206,7 +1206,8 @@ namespace Umbraco.Web.PublishedCache.NuCache
foreach (var (culture, info) in infos)
{
- cultureData[culture] = new CultureVariation { Name = info.Name, Date = content.GetUpdateDate(culture) ?? DateTime.MinValue };
+ var cultureIsDraft = !published && content is IContent d && d.IsCultureEdited(culture);
+ cultureData[culture] = new CultureVariation { Name = info.Name, Date = content.GetUpdateDate(culture) ?? DateTime.MinValue, IsDraft = cultureIsDraft };
}
}
diff --git a/src/Umbraco.Web/PublishedCache/PublishedMember.cs b/src/Umbraco.Web/PublishedCache/PublishedMember.cs
index 44ce2328b7..56c8f440d8 100644
--- a/src/Umbraco.Web/PublishedCache/PublishedMember.cs
+++ b/src/Umbraco.Web/PublishedCache/PublishedMember.cs
@@ -79,7 +79,7 @@ namespace Umbraco.Web.PublishedCache
public override PublishedItemType ItemType => PublishedItemType.Member;
- public override bool IsDraft => false;
+ public override bool IsDraft(string culture = null) => false;
public override IPublishedContent Parent => null;
diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/DictionaryPublishedContent.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/DictionaryPublishedContent.cs
index c9d3c79ff5..7c311236c0 100644
--- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/DictionaryPublishedContent.cs
+++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/DictionaryPublishedContent.cs
@@ -176,7 +176,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
public override int Level => _level;
- public override bool IsDraft => false;
+ public override bool IsDraft(string culture = null) => false;
public override IEnumerable Properties => _properties;
diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlPublishedContent.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlPublishedContent.cs
index 3c143a6066..af867cc089 100644
--- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlPublishedContent.cs
+++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlPublishedContent.cs
@@ -221,13 +221,10 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
}
}
- public override bool IsDraft
+ public override bool IsDraft(string culture = null)
{
- get
- {
- EnsureNodeInitialized();
- return _isDraft;
- }
+ EnsureNodeInitialized();
+ return _isDraft; // bah
}
public override IEnumerable Properties
diff --git a/src/Umbraco.Web/PublishedContentExtensions.cs b/src/Umbraco.Web/PublishedContentExtensions.cs
index e3291f9ad5..f82c20fc4b 100644
--- a/src/Umbraco.Web/PublishedContentExtensions.cs
+++ b/src/Umbraco.Web/PublishedContentExtensions.cs
@@ -141,50 +141,35 @@ namespace Umbraco.Web
#endregion
- // fixme - .HasValue() and .Value() refactoring - in progress - see exceptions below
-
- #region HasValue
+ #region HasValue, Value, Value
///
/// Gets a value indicating whether the content has a value for a property identified by its alias.
///
/// The content.
/// The property alias.
- /// A value indicating whether to navigate the tree upwards until a property with a value is found.
+ /// The variation language.
+ /// The variation segment.
+ /// Optional fallback strategy.
/// A value indicating whether the content has a value for the property identified by the alias.
- /// Returns true if GetProperty(alias, recurse) is not null and GetProperty(alias, recurse).HasValue is true.
- public static bool HasValue(this IPublishedContent content, string alias, bool recurse)
+ /// Returns true if HasValue is true, or a fallback strategy can provide a value.
+ public static bool HasValue(this IPublishedContent content, string alias, string culture = null, string segment = null, Fallback fallback = default)
{
- throw new NotImplementedException("WorkInProgress");
+ var property = content.GetProperty(alias);
- //var prop = content.GetProperty(alias, recurse);
- //return prop != null && prop.HasValue();
+ // if we have a property, and it has a value, return that value
+ if (property != null && property.HasValue(culture, segment))
+ return true;
+
+ // else let fallback try to get a value
+ // fixme - really?
+ if (PublishedValueFallback.TryGetValue(content, alias, culture, segment, fallback, null, out _))
+ return true;
+
+ // else... no
+ return false;
}
- ///
- /// Returns one of two strings depending on whether the content has a value for a property identified by its alias.
- ///
- /// The content.
- /// The property alias.
- /// A value indicating whether to navigate the tree upwards until a property with a value is found.
- /// The value to return if the content has a value for the property.
- /// The value to return if the content has no value for the property.
- /// Either or depending on whether the content
- /// has a value for the property identified by the alias.
- public static IHtmlString HasValue(this IPublishedContent content, string alias, bool recurse,
- string valueIfTrue, string valueIfFalse = null)
- {
- throw new NotImplementedException("WorkInProgress");
-
- //return content.HasValue(alias, recurse)
- // ? new HtmlString(valueIfTrue)
- // : new HtmlString(valueIfFalse ?? string.Empty);
- }
-
- #endregion
-
- #region Value
-
///
/// Gets the value of a content's property identified by its alias, if it exists, otherwise a default value.
///
@@ -207,15 +192,14 @@ namespace Umbraco.Web
if (PublishedValueFallback.TryGetValue(content, alias, culture, segment, fallback, defaultValue, out var value))
return value;
+ if (property == null)
+ return null;
+
// else... if we have a property, at least let the converter return its own
- // vision of 'no value' (could be an empty enumerable) - otherwise, default
- return property?.GetValue(culture, segment);
+ // vision of 'no value' (could be an empty enumerable)
+ return property.GetValue(culture, segment);
}
- #endregion
-
- #region Value
-
///
/// Gets the value of a content's property identified by its alias, converted to a specified type.
///
@@ -383,16 +367,6 @@ namespace Umbraco.Web
return recursive && content.IsComposedOf(docTypeAlias);
}
- public static bool IsNull(this IPublishedContent content, string alias, bool recurse)
- {
- return content.HasValue(alias, recurse) == false;
- }
-
- public static bool IsNull(this IPublishedContent content, string alias)
- {
- return content.HasValue(alias) == false;
- }
-
#endregion
#region IsSomething: equality
diff --git a/src/Umbraco.Web/umbraco.presentation/page.cs b/src/Umbraco.Web/umbraco.presentation/page.cs
index e8d395881c..219e2101be 100644
--- a/src/Umbraco.Web/umbraco.presentation/page.cs
+++ b/src/Umbraco.Web/umbraco.presentation/page.cs
@@ -467,9 +467,9 @@ namespace umbraco
get { return PublishedItemType.Content; }
}
- public bool IsDraft
+ public bool IsDraft(string culture = null)
{
- get { throw new NotImplementedException(); }
+ throw new NotImplementedException();
}
public IPublishedContent Parent