From d8c1e2fa987ffdbcc4f95e3521a6257d2198b080 Mon Sep 17 00:00:00 2001 From: Warren Date: Wed, 21 Mar 2018 15:53:09 +0000 Subject: [PATCH 01/14] Makes sure to set no child nodes & menu url Removes the child arrow for tree items Removes the 3 dots for the context menu item that had nothing in it --- src/Umbraco.Web/Trees/LanguageTreeController.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Umbraco.Web/Trees/LanguageTreeController.cs b/src/Umbraco.Web/Trees/LanguageTreeController.cs index 76a34385db..0e547fea6a 100644 --- a/src/Umbraco.Web/Trees/LanguageTreeController.cs +++ b/src/Umbraco.Web/Trees/LanguageTreeController.cs @@ -35,6 +35,8 @@ namespace Umbraco.Web.Trees //this will load in a custom UI instead of the dashboard for the root node root.RoutePath = string.Format("{0}/{1}/{2}", Constants.Applications.Settings, Constants.Trees.Languages, "overview"); root.Icon = "icon-flag-alt"; + root.HasChildren = false; + root.MenuUrl = null; return root; } From e2d039d9847b49b99511a6850469ac366cb3882b Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 22 Mar 2018 15:10:05 +1100 Subject: [PATCH 02/14] Changes db prefix to 'umbraco' --- src/Umbraco.Core/Persistence/Constants-DatabaseSchema.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Core/Persistence/Constants-DatabaseSchema.cs b/src/Umbraco.Core/Persistence/Constants-DatabaseSchema.cs index 43438bfcf1..c2940d9299 100644 --- a/src/Umbraco.Core/Persistence/Constants-DatabaseSchema.cs +++ b/src/Umbraco.Core/Persistence/Constants-DatabaseSchema.cs @@ -5,7 +5,7 @@ namespace Umbraco.Core { public static class DatabaseSchema { - public const string TableNamePrefix = "u"; + public const string TableNamePrefix = "umbraco"; public static class Tables { From 448d490eb754ed6d5d1ec3eb9d0f37153261aa3f Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 22 Mar 2018 16:35:16 +1100 Subject: [PATCH 03/14] Adds TODO note about GlobalSettings --- src/Umbraco.Core/Configuration/GlobalSettings.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Umbraco.Core/Configuration/GlobalSettings.cs b/src/Umbraco.Core/Configuration/GlobalSettings.cs index 1ef1b1645b..3b7fc8daad 100644 --- a/src/Umbraco.Core/Configuration/GlobalSettings.cs +++ b/src/Umbraco.Core/Configuration/GlobalSettings.cs @@ -23,6 +23,9 @@ namespace Umbraco.Core.Configuration // http://issues.umbraco.org/issue/U4-58 // http://issues.umbraco.org/issue/U4-115 + // TODO: There's a current task and branch to refactor this into interfaces and proper config: http://issues.umbraco.org/issue/U4-8861 + // PR https://github.com/umbraco/Umbraco-CMS/compare/dev-v8...temp-U4-8861?expand=1 + //TODO: Replace checking for if the app settings exist and returning an empty string, instead return the defaults! /// From 422fd8e2746477bd2a16746ebf2799a44f306cb7 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 22 Mar 2018 17:17:01 +1100 Subject: [PATCH 04/14] Fixes many hard coded SQL table names with the proposed new prefix --- .../Migrations/Upgrade/V_8_0_0/SuperZero.cs | 2 +- .../Upgrade/V_8_0_0/VariantsMigration.cs | 18 ++-- .../Implement/ContentRepositoryBase.cs | 4 +- .../Implement/ContentTypeRepositoryBase.cs | 10 +- .../Implement/DocumentRepository.cs | 8 +- .../Implement/DomainRepository.cs | 4 +- .../Implement/MemberTypeRepository.cs | 2 +- .../Persistence/Mappers/DataTypeMapperTest.cs | 5 +- .../Mappers/PropertyTypeMapperTest.cs | 5 +- .../Persistence/NPocoTests/NPocoSqlTests.cs | 21 ++-- .../ContentTypeRepositorySqlClausesTest.cs | 4 +- ...aTypeDefinitionRepositorySqlClausesTest.cs | 4 +- .../Querying/MediaRepositorySqlClausesTest.cs | 6 +- .../Repositories/ContentRepositoryTest.cs | 14 +-- .../Repositories/LanguageRepositoryTest.cs | 23 +++++ .../Repositories/MemberRepositoryTest.cs | 8 +- .../Services/ContentServiceTests.cs | 2 +- .../UmbracoExamine/IndexInitializer.cs | 2 +- .../NuCache/PublishedSnapshotService.cs | 24 ++--- .../XmlPublishedCache/XmlStore.cs | 96 ++++++++++--------- 20 files changed, 145 insertions(+), 117 deletions(-) diff --git a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/SuperZero.cs b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/SuperZero.cs index f9b1a959f8..ba29880e79 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/SuperZero.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/SuperZero.cs @@ -25,7 +25,7 @@ Database.Execute("update umbracoUser2UserGroup set userId=-1 where userId=0;"); Database.Execute("update umbracoNode set nodeUser=-1 where nodeUser=0;"); - Database.Execute("update uContentVersion set userId=-1 where userId=0;"); + Database.Execute($"update {Constants.DatabaseSchema.Tables.ContentVersion} set userId=-1 where userId=0;"); Database.Execute("delete from umbracoUser where id=0;"); } } diff --git a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/VariantsMigration.cs b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/VariantsMigration.cs index e8b06c4a31..78d6bf1085 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/VariantsMigration.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/VariantsMigration.cs @@ -29,20 +29,20 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0 MigrateContent(); MigrateVersions(); - if (Database.Fetch(@"SELECT uContentVersion.nodeId, COUNT(uContentVersion.id) -FROM uContentVersion -JOIN uDocumentVersion ON uContentVersion.id=uDocumentVersion.id -WHERE uDocumentVersion.published=1 -GROUP BY uContentVersion.nodeId -HAVING COUNT(uContentVersion.id) > 1").Any()) + if (Database.Fetch($@"SELECT {Constants.DatabaseSchema.Tables.ContentVersion}.nodeId, COUNT({Constants.DatabaseSchema.Tables.ContentVersion}.id) +FROM {Constants.DatabaseSchema.Tables.ContentVersion} +JOIN {Constants.DatabaseSchema.Tables.DocumentVersion} ON {Constants.DatabaseSchema.Tables.ContentVersion}.id={Constants.DatabaseSchema.Tables.DocumentVersion}.id +WHERE {Constants.DatabaseSchema.Tables.DocumentVersion}.published=1 +GROUP BY {Constants.DatabaseSchema.Tables.ContentVersion}.nodeId +HAVING COUNT({Constants.DatabaseSchema.Tables.ContentVersion}.id) > 1").Any()) { Debugger.Break(); throw new Exception("Migration failed: duplicate 'published' document versions."); } - if (Database.Fetch(@"SELECT v1.nodeId, v1.id, COUNT(v2.id) -FROM uContentVersion v1 -LEFT JOIN uContentVersion v2 ON v1.nodeId=v2.nodeId AND v2.[current]=1 + if (Database.Fetch($@"SELECT v1.nodeId, v1.id, COUNT(v2.id) +FROM {Constants.DatabaseSchema.Tables.ContentVersion} v1 +LEFT JOIN {Constants.DatabaseSchema.Tables.ContentVersion} v2 ON v1.nodeId=v2.nodeId AND v2.[current]=1 GROUP BY v1.nodeId, v1.id HAVING COUNT(v2.id) <> 1").Any()) { diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentRepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentRepositoryBase.cs index 95377af479..17e00b3e76 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentRepositoryBase.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentRepositoryBase.cs @@ -502,13 +502,13 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { case "VERSIONDATE": case "UPDATEDATE": - return GetDatabaseFieldNameForOrderBy("uContentVersion", "versionDate"); + return GetDatabaseFieldNameForOrderBy(Constants.DatabaseSchema.Tables.ContentVersion, "versionDate"); case "CREATEDATE": return GetDatabaseFieldNameForOrderBy("umbracoNode", "createDate"); case "NAME": return GetDatabaseFieldNameForOrderBy("umbracoNode", "text"); case "PUBLISHED": - return GetDatabaseFieldNameForOrderBy("uDocument", "published"); + return GetDatabaseFieldNameForOrderBy(Constants.DatabaseSchema.Tables.Document, "published"); case "OWNER": //TODO: This isn't going to work very nicely because it's going to order by ID, not by letter return GetDatabaseFieldNameForOrderBy("umbracoNode", "nodeUser"); diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs index 3ce03f759a..d33980ac46 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs @@ -1091,11 +1091,11 @@ ORDER BY contentTypeId, id"; pt.contentTypeId AS contentTypeId, pt.id AS id, pt.uniqueID AS " + sqlSyntax.GetQuotedColumnName("key") + @", pt.propertyTypeGroupId AS groupId, - pt.Alias AS alias, pt." + sqlSyntax.GetQuotedColumnName("Description") + @" AS " + sqlSyntax.GetQuotedColumnName("desc") + @", pt.mandatory AS mandatory, + pt.Alias AS alias, pt." + sqlSyntax.GetQuotedColumnName("Description") + @" AS " + sqlSyntax.GetQuotedColumnName("desc") + $@", pt.mandatory AS mandatory, pt.Name AS name, pt.sortOrder AS sortOrder, pt.validationRegExp AS regexp, pt.variations as variations, dt.nodeId as dataTypeId, dt.dbType as dbType, dt.propertyEditorAlias as editorAlias FROM cmsPropertyType pt -INNER JOIN uDataType as dt ON pt.dataTypeId = dt.nodeId +INNER JOIN {Constants.DatabaseSchema.Tables.DataType} as dt ON pt.dataTypeId = dt.nodeId WHERE pt.contentTypeId IN (@ids) ORDER BY contentTypeId, groupId, id"; @@ -1238,9 +1238,9 @@ WHERE cmsContentType." + aliasColumn + @" LIKE @pattern", public bool HasContainerInPath(string contentPath) { var ids = contentPath.Split(',').Select(int.Parse); - var sql = new Sql(@"SELECT COUNT(*) FROM cmsContentType -INNER JOIN uContent ON cmsContentType.nodeId=uContent.contentTypeId -WHERE uContent.nodeId IN (@ids) AND cmsContentType.isContainer=@isContainer", new { ids, isContainer = true }); + var sql = new Sql($@"SELECT COUNT(*) FROM cmsContentType +INNER JOIN {Constants.DatabaseSchema.Tables.Content} ON cmsContentType.nodeId={Constants.DatabaseSchema.Tables.Content}.contentTypeId +WHERE {Constants.DatabaseSchema.Tables.Content}.nodeId IN (@ids) AND cmsContentType.isContainer=@isContainer", new { ids, isContainer = true }); return Database.ExecuteScalar(sql) > 0; } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs index 10620ee34d..084e8b6f59 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs @@ -355,12 +355,12 @@ namespace Umbraco.Core.Persistence.Repositories.Implement entity.ResetDirtyProperties(); // troubleshooting - //if (Database.ExecuteScalar("SELECT COUNT(*) FROM uDocumentVersion JOIN uContentVersion ON uDocumentVersion.id=uContentVersion.id WHERE published=1 AND nodeId=" + content.Id) > 1) + //if (Database.ExecuteScalar($"SELECT COUNT(*) FROM {Constants.DatabaseSchema.Tables.DocumentVersion} JOIN {Constants.DatabaseSchema.Tables.ContentVersion} ON {Constants.DatabaseSchema.Tables.DocumentVersion}.id={Constants.DatabaseSchema.Tables.ContentVersion}.id WHERE published=1 AND nodeId=" + content.Id) > 1) //{ // Debugger.Break(); // throw new Exception("oops"); //} - //if (Database.ExecuteScalar("SELECT COUNT(*) FROM uDocumentVersion JOIN uContentVersion ON uDocumentVersion.id=uContentVersion.id WHERE [current]=1 AND nodeId=" + content.Id) > 1) + //if (Database.ExecuteScalar($"SELECT COUNT(*) FROM {Constants.DatabaseSchema.Tables.DocumentVersion} JOIN {Constants.DatabaseSchema.Tables.ContentVersion} ON {Constants.DatabaseSchema.Tables.DocumentVersion}.id={Constants.DatabaseSchema.Tables.ContentVersion}.id WHERE [current]=1 AND nodeId=" + content.Id) > 1) //{ // Debugger.Break(); // throw new Exception("oops"); @@ -500,12 +500,12 @@ namespace Umbraco.Core.Persistence.Repositories.Implement entity.ResetDirtyProperties(); // troubleshooting - //if (Database.ExecuteScalar("SELECT COUNT(*) FROM uDocumentVersion JOIN uContentVersion ON uDocumentVersion.id=uContentVersion.id WHERE published=1 AND nodeId=" + content.Id) > 1) + //if (Database.ExecuteScalar($"SELECT COUNT(*) FROM {Constants.DatabaseSchema.Tables.DocumentVersion} JOIN {Constants.DatabaseSchema.Tables.ContentVersion} ON {Constants.DatabaseSchema.Tables.DocumentVersion}.id={Constants.DatabaseSchema.Tables.ContentVersion}.id WHERE published=1 AND nodeId=" + content.Id) > 1) //{ // Debugger.Break(); // throw new Exception("oops"); //} - //if (Database.ExecuteScalar("SELECT COUNT(*) FROM uDocumentVersion JOIN uContentVersion ON uDocumentVersion.id=uContentVersion.id WHERE [current]=1 AND nodeId=" + content.Id) > 1) + //if (Database.ExecuteScalar($"SELECT COUNT(*) FROM {Constants.DatabaseSchema.Tables.DocumentVersion} JOIN {Constants.DatabaseSchema.Tables.ContentVersion} ON {Constants.DatabaseSchema.Tables.DocumentVersion}.id={Constants.DatabaseSchema.Tables.ContentVersion}.id WHERE [current]=1 AND nodeId=" + content.Id) > 1) //{ // Debugger.Break(); // throw new Exception("oops"); diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/DomainRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/DomainRepository.cs index 9f4785c620..f75d82bd4e 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/DomainRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/DomainRepository.cs @@ -91,7 +91,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement if (entity.RootContentId.HasValue) { - var contentExists = Database.ExecuteScalar("SELECT COUNT(*) FROM uContent WHERE nodeId = @id", new { id = entity.RootContentId.Value }); + var contentExists = Database.ExecuteScalar($"SELECT COUNT(*) FROM {Constants.DatabaseSchema.Tables.Content} WHERE nodeId = @id", new { id = entity.RootContentId.Value }); if (contentExists == 0) throw new NullReferenceException("No content exists with id " + entity.RootContentId.Value); } @@ -129,7 +129,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement if (entity.RootContentId.HasValue) { - var contentExists = Database.ExecuteScalar("SELECT COUNT(*) FROM uContent WHERE nodeId = @id", new { id = entity.RootContentId.Value }); + var contentExists = Database.ExecuteScalar($"SELECT COUNT(*) FROM {Constants.DatabaseSchema.Tables.Content} WHERE nodeId = @id", new { id = entity.RootContentId.Value }); if (contentExists == 0) throw new NullReferenceException("No content exists with id " + entity.RootContentId.Value); } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/MemberTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/MemberTypeRepository.cs index 6fef47679b..68cd81fa51 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/MemberTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/MemberTypeRepository.cs @@ -148,7 +148,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement "cmsPropertyType.Name", "cmsPropertyType.Description", "cmsPropertyType.mandatory", "cmsPropertyType.UniqueID", "cmsPropertyType.validationRegExp", "cmsPropertyType.dataTypeId", "cmsPropertyType.sortOrder AS PropertyTypeSortOrder", "cmsPropertyType.propertyTypeGroupId AS PropertyTypesGroupId", "cmsMemberType.memberCanEdit", "cmsMemberType.viewOnProfile", - "uDataType.propertyEditorAlias", "uDataType.dbType", "cmsPropertyTypeGroup.id AS PropertyTypeGroupId", + $"{Constants.DatabaseSchema.Tables.DataType}.propertyEditorAlias", $"{Constants.DatabaseSchema.Tables.DataType}.dbType", "cmsPropertyTypeGroup.id AS PropertyTypeGroupId", "cmsPropertyTypeGroup.text AS PropertyGroupName", "cmsPropertyTypeGroup.uniqueID AS PropertyGroupUniqueID", "cmsPropertyTypeGroup.sortorder AS PropertyGroupSortOrder", "cmsPropertyTypeGroup.contenttypeNodeId") .From() diff --git a/src/Umbraco.Tests/Persistence/Mappers/DataTypeMapperTest.cs b/src/Umbraco.Tests/Persistence/Mappers/DataTypeMapperTest.cs index 848a60641f..a65464a629 100644 --- a/src/Umbraco.Tests/Persistence/Mappers/DataTypeMapperTest.cs +++ b/src/Umbraco.Tests/Persistence/Mappers/DataTypeMapperTest.cs @@ -1,4 +1,5 @@ using NUnit.Framework; +using Umbraco.Core; using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Persistence.SqlSyntax; @@ -37,7 +38,7 @@ namespace Umbraco.Tests.Persistence.Mappers string column = new DataTypeMapper().Map(new SqlCeSyntaxProvider(), "DatabaseType"); // Assert - Assert.That(column, Is.EqualTo("[uDataType].[dbType]")); + Assert.That(column, Is.EqualTo($"[{Constants.DatabaseSchema.Tables.DataType}].[dbType]")); } [Test] @@ -48,7 +49,7 @@ namespace Umbraco.Tests.Persistence.Mappers string column = new DataTypeMapper().Map(new SqlCeSyntaxProvider(), "EditorAlias"); // Assert - Assert.That(column, Is.EqualTo("[uDataType].[propertyEditorAlias]")); + Assert.That(column, Is.EqualTo($"[{Constants.DatabaseSchema.Tables.DataType}].[propertyEditorAlias]")); } } } diff --git a/src/Umbraco.Tests/Persistence/Mappers/PropertyTypeMapperTest.cs b/src/Umbraco.Tests/Persistence/Mappers/PropertyTypeMapperTest.cs index 9b1baafd51..208b6e3749 100644 --- a/src/Umbraco.Tests/Persistence/Mappers/PropertyTypeMapperTest.cs +++ b/src/Umbraco.Tests/Persistence/Mappers/PropertyTypeMapperTest.cs @@ -1,4 +1,5 @@ using NUnit.Framework; +using Umbraco.Core; using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Persistence.SqlSyntax; @@ -54,7 +55,7 @@ namespace Umbraco.Tests.Persistence.Mappers string column = new PropertyTypeMapper().Map(new SqlCeSyntaxProvider(), "PropertyEditorAlias"); // Assert - Assert.That(column, Is.EqualTo("[uDataType].[propertyEditorAlias]")); + Assert.That(column, Is.EqualTo($"[{Constants.DatabaseSchema.Tables.DataType}].[propertyEditorAlias]")); } [Test] @@ -64,7 +65,7 @@ namespace Umbraco.Tests.Persistence.Mappers string column = new PropertyTypeMapper().Map(new SqlCeSyntaxProvider(), "ValueStorageType"); // Assert - Assert.That(column, Is.EqualTo("[uDataType].[dbType]")); + Assert.That(column, Is.EqualTo($"[{Constants.DatabaseSchema.Tables.DataType}].[dbType]")); } } } diff --git a/src/Umbraco.Tests/Persistence/NPocoTests/NPocoSqlTests.cs b/src/Umbraco.Tests/Persistence/NPocoTests/NPocoSqlTests.cs index 927324bfbd..a7b75cbd6d 100644 --- a/src/Umbraco.Tests/Persistence/NPocoTests/NPocoSqlTests.cs +++ b/src/Umbraco.Tests/Persistence/NPocoTests/NPocoSqlTests.cs @@ -1,5 +1,6 @@ using System.Diagnostics; using NUnit.Framework; +using Umbraco.Core; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Dtos; using Umbraco.Core.Persistence.Querying; @@ -202,7 +203,7 @@ namespace Umbraco.Tests.Persistence.NPocoTests public void Can_Select_From_With_Type() { var expected = Sql(); - expected.SelectAll().From("[uContent]"); + expected.SelectAll().From($"[{Constants.DatabaseSchema.Tables.Content}]"); var sql = Sql(); sql.SelectAll().From(); @@ -217,9 +218,9 @@ namespace Umbraco.Tests.Persistence.NPocoTests { var expected = Sql(); expected.SelectAll() - .From("[uDocumentVersion]") - .InnerJoin("[uContentVersion]") - .On("[uDocumentVersion].[id] = [uContentVersion].[id]"); + .From($"[{Constants.DatabaseSchema.Tables.DocumentVersion}]") + .InnerJoin($"[{Constants.DatabaseSchema.Tables.ContentVersion}]") + .On($"[{Constants.DatabaseSchema.Tables.DocumentVersion}].[id] = [{Constants.DatabaseSchema.Tables.ContentVersion}].[id]"); var sql = Sql(); sql.SelectAll().From() @@ -235,7 +236,7 @@ namespace Umbraco.Tests.Persistence.NPocoTests public void Can_OrderBy_With_Type() { var expected = Sql(); - expected.SelectAll().From("[uContent]").OrderBy("([uContent].[contentTypeId])"); + expected.SelectAll().From($"[{Constants.DatabaseSchema.Tables.Content}]").OrderBy($"([{Constants.DatabaseSchema.Tables.Content}].[contentTypeId])"); var sql = Sql(); sql.SelectAll().From().OrderBy(x => x.ContentTypeId); @@ -249,7 +250,7 @@ namespace Umbraco.Tests.Persistence.NPocoTests public void Can_GroupBy_With_Type() { var expected = Sql(); - expected.SelectAll().From("[uContent]").GroupBy("[uContent].[contentTypeId]"); + expected.SelectAll().From($"[{Constants.DatabaseSchema.Tables.Content}]").GroupBy($"[{Constants.DatabaseSchema.Tables.Content}].[contentTypeId]"); var sql = Sql(); sql.SelectAll().From().GroupBy(x => x.ContentTypeId); @@ -263,7 +264,7 @@ namespace Umbraco.Tests.Persistence.NPocoTests public void Can_Use_Where_Predicate() { var expected = Sql(); - expected.SelectAll().From("[uContent]").Where("([uContent].[nodeId] = @0)", 1045); + expected.SelectAll().From($"[{Constants.DatabaseSchema.Tables.Content}]").Where($"([{Constants.DatabaseSchema.Tables.Content}].[nodeId] = @0)", 1045); var sql = Sql(); sql.SelectAll().From().Where(x => x.NodeId == 1045); @@ -278,9 +279,9 @@ namespace Umbraco.Tests.Persistence.NPocoTests { var expected = Sql(); expected.SelectAll() - .From("[uContent]") - .Where("([uContent].[nodeId] = @0)", 1045) - .Where("([uContent].[contentTypeId] = @0)", 1050); + .From($"[{Constants.DatabaseSchema.Tables.Content}]") + .Where($"([{Constants.DatabaseSchema.Tables.Content}].[nodeId] = @0)", 1045) + .Where($"([{Constants.DatabaseSchema.Tables.Content}].[contentTypeId] = @0)", 1050); var sql = Sql(); sql.SelectAll() diff --git a/src/Umbraco.Tests/Persistence/Querying/ContentTypeRepositorySqlClausesTest.cs b/src/Umbraco.Tests/Persistence/Querying/ContentTypeRepositorySqlClausesTest.cs index ba8155dc0a..4c10c4da41 100644 --- a/src/Umbraco.Tests/Persistence/Querying/ContentTypeRepositorySqlClausesTest.cs +++ b/src/Umbraco.Tests/Persistence/Querying/ContentTypeRepositorySqlClausesTest.cs @@ -94,7 +94,7 @@ namespace Umbraco.Tests.Persistence.Querying expected.SelectAll() .From("[cmsPropertyTypeGroup]") .RightJoin("[cmsPropertyType]").On("[cmsPropertyTypeGroup].[id] = [cmsPropertyType].[propertyTypeGroupId]") - .InnerJoin("[uDataType]").On("[cmsPropertyType].[dataTypeId] = [uDataType].[nodeId]"); + .InnerJoin($"[{Constants.DatabaseSchema.Tables.DataType}]").On($"[cmsPropertyType].[dataTypeId] = [{Constants.DatabaseSchema.Tables.DataType}].[nodeId]"); var sql = Sql(); sql.SelectAll() @@ -140,7 +140,7 @@ namespace Umbraco.Tests.Persistence.Querying expected.SelectAll() .From("[cmsPropertyTypeGroup]") .RightJoin("[cmsPropertyType]").On("[cmsPropertyTypeGroup].[id] = [cmsPropertyType].[propertyTypeGroupId]") - .InnerJoin("[uDataType]").On("[cmsPropertyType].[dataTypeId] = [uDataType].[nodeId]") + .InnerJoin($"[{Constants.DatabaseSchema.Tables.DataType}]").On($"[cmsPropertyType].[dataTypeId] = [{Constants.DatabaseSchema.Tables.DataType}].[nodeId]") .Where("([cmsPropertyType].[contentTypeId] = @0)", 1050); var sql = Sql(); diff --git a/src/Umbraco.Tests/Persistence/Querying/DataTypeDefinitionRepositorySqlClausesTest.cs b/src/Umbraco.Tests/Persistence/Querying/DataTypeDefinitionRepositorySqlClausesTest.cs index 2b3611cb02..e52da368c7 100644 --- a/src/Umbraco.Tests/Persistence/Querying/DataTypeDefinitionRepositorySqlClausesTest.cs +++ b/src/Umbraco.Tests/Persistence/Querying/DataTypeDefinitionRepositorySqlClausesTest.cs @@ -19,8 +19,8 @@ namespace Umbraco.Tests.Persistence.Querying var expected = new Sql(); expected.Select("*") - .From("[uDataType]") - .InnerJoin("[umbracoNode]").On("[uDataType].[nodeId] = [umbracoNode].[id]") + .From($"[{Constants.DatabaseSchema.Tables.DataType}]") + .InnerJoin("[umbracoNode]").On($"[{Constants.DatabaseSchema.Tables.DataType}].[nodeId] = [umbracoNode].[id]") .Where("([umbracoNode].[nodeObjectType] = @0)", new Guid("30a2a501-1978-4ddb-a57b-f7efed43ba3c")); var sql = Sql(); diff --git a/src/Umbraco.Tests/Persistence/Querying/MediaRepositorySqlClausesTest.cs b/src/Umbraco.Tests/Persistence/Querying/MediaRepositorySqlClausesTest.cs index 4def2621fd..246379bed3 100644 --- a/src/Umbraco.Tests/Persistence/Querying/MediaRepositorySqlClausesTest.cs +++ b/src/Umbraco.Tests/Persistence/Querying/MediaRepositorySqlClausesTest.cs @@ -19,9 +19,9 @@ namespace Umbraco.Tests.Persistence.Querying var expected = new Sql(); expected.Select("*") - .From("[uContentVersion]") - .InnerJoin("[uContent]").On("[uContentVersion].[nodeId] = [uContent].[nodeId]") - .InnerJoin("[umbracoNode]").On("[uContent].[nodeId] = [umbracoNode].[id]") + .From($"[{Constants.DatabaseSchema.Tables.ContentVersion}]") + .InnerJoin($"[{Constants.DatabaseSchema.Tables.Content}]").On($"[{Constants.DatabaseSchema.Tables.ContentVersion}].[nodeId] = [{Constants.DatabaseSchema.Tables.Content}].[nodeId]") + .InnerJoin("[umbracoNode]").On($"[{Constants.DatabaseSchema.Tables.Content}].[nodeId] = [umbracoNode].[id]") .Where("([umbracoNode].[nodeObjectType] = @0)", new Guid("b796f64c-1f99-4ffb-b886-4bf4bc011a9c")); var sql = Sql(); diff --git a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs index 65a32942df..f6f7048315 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs @@ -152,7 +152,7 @@ namespace Umbraco.Tests.Persistence.Repositories Assert.AreEqual(versions[versions.Count - 1], repository.Get(content1.Id).VersionId); // misc checks - Assert.AreEqual(true, scope.Database.ExecuteScalar("SELECT published FROM uDocument WHERE nodeId=@id", new { id = content1.Id })); + Assert.AreEqual(true, scope.Database.ExecuteScalar($"SELECT published FROM {Constants.DatabaseSchema.Tables.Document} WHERE nodeId=@id", new { id = content1.Id })); // change something // save = update the current (draft) version @@ -168,7 +168,7 @@ namespace Umbraco.Tests.Persistence.Repositories Assert.AreEqual(versions[versions.Count - 1], repository.Get(content1.Id).VersionId); // misc checks - Assert.AreEqual(true, scope.Database.ExecuteScalar("SELECT published FROM uDocument WHERE nodeId=@id", new { id = content1.Id })); + Assert.AreEqual(true, scope.Database.ExecuteScalar($"SELECT published FROM {Constants.DatabaseSchema.Tables.Document} WHERE nodeId=@id", new { id = content1.Id })); // unpublish = no impact on versions ((Content) content1).PublishedState = PublishedState.Unpublishing; @@ -183,7 +183,7 @@ namespace Umbraco.Tests.Persistence.Repositories Assert.AreEqual(versions[versions.Count - 1], repository.Get(content1.Id).VersionId); // misc checks - Assert.AreEqual(false, scope.Database.ExecuteScalar("SELECT published FROM uDocument WHERE nodeId=@id", new { id = content1.Id })); + Assert.AreEqual(false, scope.Database.ExecuteScalar($"SELECT published FROM {Constants.DatabaseSchema.Tables.Document} WHERE nodeId=@id", new { id = content1.Id })); // change something // save = update the current (draft) version @@ -198,7 +198,7 @@ namespace Umbraco.Tests.Persistence.Repositories Assert.AreEqual(versions[versions.Count - 1], repository.Get(content1.Id).VersionId); // misc checks - Assert.AreEqual(false, scope.Database.ExecuteScalar("SELECT published FROM uDocument WHERE nodeId=@id", new { id = content1.Id })); + Assert.AreEqual(false, scope.Database.ExecuteScalar($"SELECT published FROM {Constants.DatabaseSchema.Tables.Document} WHERE nodeId=@id", new { id = content1.Id })); // publish = version ((Content) content1).PublishValues(); @@ -214,7 +214,7 @@ namespace Umbraco.Tests.Persistence.Repositories Assert.AreEqual(versions[versions.Count - 1], repository.Get(content1.Id).VersionId); // misc checks - Assert.AreEqual(true, scope.Database.ExecuteScalar("SELECT published FROM uDocument WHERE nodeId=@id", new { id = content1.Id })); + Assert.AreEqual(true, scope.Database.ExecuteScalar($"SELECT published FROM {Constants.DatabaseSchema.Tables.Document} WHERE nodeId=@id", new { id = content1.Id })); // change something // save = update the current (draft) version @@ -232,7 +232,7 @@ namespace Umbraco.Tests.Persistence.Repositories Assert.AreEqual(versions[versions.Count - 1], repository.Get(content1.Id).VersionId); // misc checks - Assert.AreEqual(true, scope.Database.ExecuteScalar("SELECT published FROM uDocument WHERE nodeId=@id", new { id = content1.Id })); + Assert.AreEqual(true, scope.Database.ExecuteScalar($"SELECT published FROM {Constants.DatabaseSchema.Tables.Document} WHERE nodeId=@id", new { id = content1.Id })); // publish = new version content1.Name = "name-4"; @@ -250,7 +250,7 @@ namespace Umbraco.Tests.Persistence.Repositories Assert.AreEqual(versions[versions.Count - 1], repository.Get(content1.Id).VersionId); // misc checks - Assert.AreEqual(true, scope.Database.ExecuteScalar("SELECT published FROM uDocument WHERE nodeId=@id", new { id = content1.Id })); + Assert.AreEqual(true, scope.Database.ExecuteScalar($"SELECT published FROM {Constants.DatabaseSchema.Tables.Document} WHERE nodeId=@id", new { id = content1.Id })); // all versions var allVersions = repository.GetAllVersions(content1.Id).ToArray(); diff --git a/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs index 3d0b484a50..d56936df9e 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs @@ -219,6 +219,29 @@ namespace Umbraco.Tests.Persistence.Repositories // Assert Assert.That(languageBR.HasIdentity, Is.True); Assert.That(languageBR.Id, Is.EqualTo(6)); //With 5 existing entries the Id should be 6 + Assert.IsFalse(languageBR.IsDefaultVariantLanguage); + Assert.IsFalse(languageBR.Mandatory); + } + } + + [Test] + public void Can_Perform_Add_On_LanguageRepository_With_Boolean_Properties() + { + // Arrange + var provider = TestObjects.GetScopeProvider(Logger); + using (var scope = provider.CreateScope()) + { + var repository = CreateRepository(provider); + + // Act + var languageBR = new Language("pt-BR") { CultureName = "pt-BR", IsDefaultVariantLanguage = true, Mandatory = true }; + repository.Save(languageBR); + + // Assert + Assert.That(languageBR.HasIdentity, Is.True); + Assert.That(languageBR.Id, Is.EqualTo(6)); //With 5 existing entries the Id should be 6 + Assert.IsTrue(languageBR.IsDefaultVariantLanguage); + Assert.IsTrue(languageBR.Mandatory); } } diff --git a/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs index a625cc14d1..4f901935dc 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs @@ -323,8 +323,8 @@ namespace Umbraco.Tests.Persistence.Repositories } var sql = provider.SqlContext.Sql(); - sql.Select("umbracoNode.*", "uContent.contentTypeId", "cmsContentType.alias AS ContentTypeAlias", "uContentVersion.versionId", - "uContentVersion.versionDate", "cmsMember.Email", + sql.Select("umbracoNode.*", $"{Constants.DatabaseSchema.Tables.Content}.contentTypeId", "cmsContentType.alias AS ContentTypeAlias", $"{Constants.DatabaseSchema.Tables.ContentVersion}.versionId", + $"{Constants.DatabaseSchema.Tables.ContentVersion}.versionDate", "cmsMember.Email", "cmsMember.LoginName", "cmsMember.Password", Constants.DatabaseSchema.Tables.PropertyData + ".id AS PropertyDataId", Constants.DatabaseSchema.Tables.PropertyData + ".propertytypeid", Constants.DatabaseSchema.Tables.PropertyData + ".dateValue", Constants.DatabaseSchema.Tables.PropertyData + ".intValue", @@ -341,7 +341,7 @@ namespace Umbraco.Tests.Persistence.Repositories .LeftJoin().On(left => left.ContentTypeId, right => right.ContentTypeId) .LeftJoin().On(left => left.NodeId, right => right.DataTypeId) .LeftJoin().On(left => left.PropertyTypeId, right => right.Id) - .Append("AND " + Constants.DatabaseSchema.Tables.PropertyData + ".versionId = uContentVersion.id") + .Append("AND " + Constants.DatabaseSchema.Tables.PropertyData + $".versionId = {Constants.DatabaseSchema.Tables.ContentVersion}.id") .Where(x => x.NodeObjectType == NodeObjectTypeId); return sql; } @@ -359,7 +359,7 @@ namespace Umbraco.Tests.Persistence.Repositories .LeftJoin().On(left => left.ContentTypeId, right => right.ContentTypeId) .LeftJoin().On(left => left.NodeId, right => right.DataTypeId) .LeftJoin().On(left => left.PropertyTypeId, right => right.Id) - .Append("AND " + Constants.DatabaseSchema.Tables.PropertyData + ".versionId = uContentVersion.id") + .Append("AND " + Constants.DatabaseSchema.Tables.PropertyData + $".versionId = {Constants.DatabaseSchema.Tables.ContentVersion}.id") .Where(x => x.NodeObjectType == NodeObjectTypeId); return sql; } diff --git a/src/Umbraco.Tests/Services/ContentServiceTests.cs b/src/Umbraco.Tests/Services/ContentServiceTests.cs index 5dd11b2812..a67d71d081 100644 --- a/src/Umbraco.Tests/Services/ContentServiceTests.cs +++ b/src/Umbraco.Tests/Services/ContentServiceTests.cs @@ -36,7 +36,7 @@ namespace Umbraco.Tests.Services [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest, PublishedRepositoryEvents = true, WithApplication = true)] public class ContentServiceTests : TestWithSomeContentBase { - //TODO Add test to verify there is only ONE newest document/content in uDocument table after updating. + //TODO Add test to verify there is only ONE newest document/content in {Constants.DatabaseSchema.Tables.Document} table after updating. //TODO Add test to delete specific version (with and without deleting prior versions) and versions by date. public override void SetUp() diff --git a/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs b/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs index c5b161f44a..6e82f7d21e 100644 --- a/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs +++ b/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs @@ -168,7 +168,7 @@ namespace Umbraco.Tests.UmbracoExamine //var query = new Mock>(); //query // .Setup(x => x.GetWhereClauses()) - // .Returns(new List> { new Tuple("uDocument.published", new object[] { 1 }) }); + // .Returns(new List> { new Tuple($"{Constants.DatabaseSchema.Tables.Document}.published", new object[] { 1 }) }); var scopeProvider = new Mock(); //scopeProvider // .Setup(x => x.Query()) diff --git a/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs b/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs index bf1fd2473b..df264ac51c 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs @@ -1251,12 +1251,12 @@ WHERE cmsContentNu.nodeId IN ( { // assume number of ctypes won't blow IN(...) // must support SQL-CE - db.Execute(@"DELETE FROM cmsContentNu + db.Execute($@"DELETE FROM cmsContentNu WHERE cmsContentNu.nodeId IN ( SELECT id FROM umbracoNode - JOIN uContent ON uContent.nodeId=umbracoNode.id + JOIN {Constants.DatabaseSchema.Tables.Content} ON {Constants.DatabaseSchema.Tables.Content}.nodeId=umbracoNode.id WHERE umbracoNode.nodeObjectType=@objType - AND uContent.contentTypeId IN (@ctypes) + AND {Constants.DatabaseSchema.Tables.Content}.contentTypeId IN (@ctypes) )", new { objType = contentObjectType, ctypes = contentTypeIdsA }); } @@ -1318,12 +1318,12 @@ WHERE cmsContentNu.nodeId IN ( { // assume number of ctypes won't blow IN(...) // must support SQL-CE - db.Execute(@"DELETE FROM cmsContentNu + db.Execute($@"DELETE FROM cmsContentNu WHERE cmsContentNu.nodeId IN ( SELECT id FROM umbracoNode - JOIN uContent ON uContent.nodeId=umbracoNode.id + JOIN {Constants.DatabaseSchema.Tables.Content} ON {Constants.DatabaseSchema.Tables.Content}.nodeId=umbracoNode.id WHERE umbracoNode.nodeObjectType=@objType - AND uContent.contentTypeId IN (@ctypes) + AND {Constants.DatabaseSchema.Tables.Content}.contentTypeId IN (@ctypes) )", new { objType = mediaObjectType, ctypes = contentTypeIdsA }); } @@ -1376,12 +1376,12 @@ WHERE cmsContentNu.nodeId IN ( { // assume number of ctypes won't blow IN(...) // must support SQL-CE - db.Execute(@"DELETE FROM cmsContentNu + db.Execute($@"DELETE FROM cmsContentNu WHERE cmsContentNu.nodeId IN ( SELECT id FROM umbracoNode - JOIN uContent ON uContent.nodeId=umbracoNode.id + JOIN {Constants.DatabaseSchema.Tables.Content} ON {Constants.DatabaseSchema.Tables.Content}.nodeId=umbracoNode.id WHERE umbracoNode.nodeObjectType=@objType - AND uContent.contentTypeId IN (@ctypes) + AND {Constants.DatabaseSchema.Tables.Content}.contentTypeId IN (@ctypes) )", new { objType = memberObjectType, ctypes = contentTypeIdsA }); } @@ -1423,13 +1423,13 @@ WHERE cmsContentNu.nodeId IN ( var contentObjectType = Constants.ObjectTypes.Document; var db = scope.Database; - var count = db.ExecuteScalar(@"SELECT COUNT(*) + var count = db.ExecuteScalar($@"SELECT COUNT(*) FROM umbracoNode -JOIN uDocument ON umbracoNode.id=uDocument.nodeId +JOIN {Constants.DatabaseSchema.Tables.Document} ON umbracoNode.id={Constants.DatabaseSchema.Tables.Document}.nodeId LEFT JOIN cmsContentNu nuEdited ON (umbracoNode.id=nuEdited.nodeId AND nuEdited.published=0) LEFT JOIN cmsContentNu nuPublished ON (umbracoNode.id=nuPublished.nodeId AND nuPublished.published=1) WHERE umbracoNode.nodeObjectType=@objType -AND nuEdited.nodeId IS NULL OR (uDocument.published=1 AND nuPublished.nodeId IS NULL);" +AND nuEdited.nodeId IS NULL OR ({Constants.DatabaseSchema.Tables.Document}.published=1 AND nuPublished.nodeId IS NULL);" , new { objType = contentObjectType }); return count == 0; diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlStore.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlStore.cs index 8c56ffd87f..4c5047fdb3 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlStore.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlStore.cs @@ -494,16 +494,18 @@ AND (umbracoNode.id=@id)"; return xml; } - public XmlNode GetPreviewXmlNode(int contentId) - { - const string sql = @"SELECT umbracoNode.id, umbracoNode.parentId, umbracoNode.sortOrder, umbracoNode.Level, -cmsPreviewXml.xml, uDocument.published + private static readonly string PreviewXmlNodeSql = $@"SELECT umbracoNode.id, umbracoNode.parentId, umbracoNode.sortOrder, umbracoNode.Level, +cmsPreviewXml.xml, {Constants.DatabaseSchema.Tables.Document}.published FROM umbracoNode JOIN cmsPreviewXml ON (cmsPreviewXml.nodeId=umbracoNode.id) -JOIN uDocument ON (uDocument.nodeId=umbracoNode.id) +JOIN {Constants.DatabaseSchema.Tables.Document} ON ({Constants.DatabaseSchema.Tables.Document}.nodeId=umbracoNode.id) WHERE umbracoNode.nodeObjectType = @nodeObjectType AND (umbracoNode.id=@id)"; + public XmlNode GetPreviewXmlNode(int contentId) + { + var sql = PreviewXmlNodeSql; + XmlDto xmlDto; using (var scope = _scopeProvider.CreateScope()) { @@ -837,32 +839,32 @@ AND (umbracoNode.id=@id)"; #region Database - private const string ReadTreeCmsContentXmlSql = @"SELECT + private static readonly string ReadTreeCmsContentXmlSql = $@"SELECT umbracoNode.id, umbracoNode.parentId, umbracoNode.sortOrder, umbracoNode.level, umbracoNode.path, - cmsContentXml.xml, cmsContentXml.rv, uDocument.published + cmsContentXml.xml, cmsContentXml.rv, {Constants.DatabaseSchema.Tables.Document}.published FROM umbracoNode JOIN cmsContentXml ON (cmsContentXml.nodeId=umbracoNode.id) -JOIN uDocument ON (uDocument.nodeId=umbracoNode.id) -WHERE umbracoNode.nodeObjectType = @nodeObjectType AND uDocument.published=1 +JOIN {Constants.DatabaseSchema.Tables.Document} ON ({Constants.DatabaseSchema.Tables.Document}.nodeId=umbracoNode.id) +WHERE umbracoNode.nodeObjectType = @nodeObjectType AND {Constants.DatabaseSchema.Tables.Document}.published=1 ORDER BY umbracoNode.level, umbracoNode.sortOrder"; - private const string ReadBranchCmsContentXmlSql = @"SELECT + private static readonly string ReadBranchCmsContentXmlSql = $@"SELECT umbracoNode.id, umbracoNode.parentId, umbracoNode.sortOrder, umbracoNode.level, umbracoNode.path, - cmsContentXml.xml, cmsContentXml.rv, uDocument.published + cmsContentXml.xml, cmsContentXml.rv, {Constants.DatabaseSchema.Tables.Document}.published FROM umbracoNode JOIN cmsContentXml ON (cmsContentXml.nodeId=umbracoNode.id) -JOIN uDocument ON (uDocument.nodeId=umbracoNode.id) -WHERE umbracoNode.nodeObjectType = @nodeObjectType AND uDocument.published=1 AND (umbracoNode.id = @id OR umbracoNode.path LIKE @path) +JOIN {Constants.DatabaseSchema.Tables.Document} ON ({Constants.DatabaseSchema.Tables.Document}.nodeId=umbracoNode.id) +WHERE umbracoNode.nodeObjectType = @nodeObjectType AND {Constants.DatabaseSchema.Tables.Document}.published=1 AND (umbracoNode.id = @id OR umbracoNode.path LIKE @path) ORDER BY umbracoNode.level, umbracoNode.sortOrder"; - private const string ReadCmsContentXmlForContentTypesSql = @"SELECT + private static readonly string ReadCmsContentXmlForContentTypesSql = $@"SELECT umbracoNode.id, umbracoNode.parentId, umbracoNode.sortOrder, umbracoNode.level, umbracoNode.path, - cmsContentXml.xml, cmsContentXml.rv, uDocument.published + cmsContentXml.xml, cmsContentXml.rv, {Constants.DatabaseSchema.Tables.Document}.published FROM umbracoNode JOIN cmsContentXml ON (cmsContentXml.nodeId=umbracoNode.id) -JOIN uDocument ON (uDocument.nodeId=umbracoNode.id) -JOIN uContent ON (uDocument.nodeId=uContent.nodeId) -WHERE umbracoNode.nodeObjectType = @nodeObjectType AND uDocument.published=1 AND uContent.contentTypeId IN (@ids) +JOIN {Constants.DatabaseSchema.Tables.Document} ON ({Constants.DatabaseSchema.Tables.Document}.nodeId=umbracoNode.id) +JOIN {Constants.DatabaseSchema.Tables.Content} ON ({Constants.DatabaseSchema.Tables.Document}.nodeId={Constants.DatabaseSchema.Tables.Content}.nodeId) +WHERE umbracoNode.nodeObjectType = @nodeObjectType AND {Constants.DatabaseSchema.Tables.Document}.published=1 AND {Constants.DatabaseSchema.Tables.Content}.contentTypeId IN (@ids) ORDER BY umbracoNode.level, umbracoNode.sortOrder"; private const string ReadMoreCmsContentXmlSql = @"SELECT @@ -873,13 +875,13 @@ JOIN cmsContentXml ON (cmsContentXml.nodeId=umbracoNode.id) WHERE umbracoNode.nodeObjectType = @nodeObjectType ORDER BY umbracoNode.level, umbracoNode.sortOrder"; - private const string ReadCmsPreviewXmlSql1 = @"SELECT + private static readonly string ReadCmsPreviewXmlSql1 = $@"SELECT umbracoNode.id, umbracoNode.parentId, umbracoNode.sortOrder, umbracoNode.level, umbracoNode.path, - cmsPreviewXml.xml, cmsPreviewXml.rv, uDocument.published + cmsPreviewXml.xml, cmsPreviewXml.rv, {Constants.DatabaseSchema.Tables.Document}.published FROM umbracoNode JOIN cmsPreviewXml ON (cmsPreviewXml.nodeId=umbracoNode.id) -JOIN uDocument ON (uDocument.nodeId=umbracoNode.id) -WHERE umbracoNode.nodeObjectType = @nodeObjectType AND uDocument.published=1 +JOIN {Constants.DatabaseSchema.Tables.Document} ON ({Constants.DatabaseSchema.Tables.Document}.nodeId=umbracoNode.id) +WHERE umbracoNode.nodeObjectType = @nodeObjectType AND {Constants.DatabaseSchema.Tables.Document}.published=1 AND (umbracoNode.path=@path OR"; // @path LIKE concat(umbracoNode.path, ',%')"; private const string ReadCmsPreviewXmlSql2 = @") @@ -1711,15 +1713,15 @@ WHERE cmsContentXml.nodeId IN ( // db.Execute(@"DELETE cmsContentXml //FROM cmsContentXml //JOIN umbracoNode ON (cmsContentXml.nodeId=umbracoNode.Id) - //JOIN uContent ON (cmsContentXml.nodeId=uContent.nodeId) + //JOIN {Constants.DatabaseSchema.Tables.Content} ON (cmsContentXml.nodeId={Constants.DatabaseSchema.Tables.Content}.nodeId) //WHERE umbracoNode.nodeObjectType=@objType - //AND uContent.contentTypeId IN (@ctypes)", - db.Execute(@"DELETE FROM cmsContentXml + //AND {Constants.DatabaseSchema.Tables.Content}.contentTypeId IN (@ctypes)", + db.Execute($@"DELETE FROM cmsContentXml WHERE cmsContentXml.nodeId IN ( SELECT id FROM umbracoNode - JOIN uContent ON uContent.nodeId=umbracoNode.id + JOIN {Constants.DatabaseSchema.Tables.Content} ON {Constants.DatabaseSchema.Tables.Content}.nodeId=umbracoNode.id WHERE umbracoNode.nodeObjectType=@objType - AND uContent.contentTypeId IN (@ctypes) + AND {Constants.DatabaseSchema.Tables.Content}.contentTypeId IN (@ctypes) )", new { objType = contentObjectType, ctypes = contentTypeIdsA }); } @@ -1782,15 +1784,15 @@ WHERE cmsPreviewXml.nodeId IN ( // db.Execute(@"DELETE cmsPreviewXml //FROM cmsPreviewXml //JOIN umbracoNode ON (cmsPreviewXml.nodeId=umbracoNode.Id) - //JOIN uContent ON (cmsPreviewXml.nodeId=uContent.nodeId) + //JOIN {Constants.DatabaseSchema.Tables.Content} ON (cmsPreviewXml.nodeId={Constants.DatabaseSchema.Tables.Content}.nodeId) //WHERE umbracoNode.nodeObjectType=@objType - //AND uContent.contentTypeId IN (@ctypes)", - db.Execute(@"DELETE FROM cmsPreviewXml + //AND {Constants.DatabaseSchema.Tables.Content}.contentTypeId IN (@ctypes)", + db.Execute($@"DELETE FROM cmsPreviewXml WHERE cmsPreviewXml.nodeId IN ( SELECT id FROM umbracoNode - JOIN uContent ON uContent.nodeId=umbracoNode.id + JOIN {Constants.DatabaseSchema.Tables.Content} ON {Constants.DatabaseSchema.Tables.Content}.nodeId=umbracoNode.id WHERE umbracoNode.nodeObjectType=@objType - AND uContent.contentTypeId IN (@ctypes) + AND {Constants.DatabaseSchema.Tables.Content}.contentTypeId IN (@ctypes) )", new { objType = contentObjectType, ctypes = contentTypeIdsA }); } @@ -1805,7 +1807,7 @@ WHERE cmsPreviewXml.nodeId IN ( long total; do { - // .GetPagedResultsByQuery implicitely adds (uDocument.newest = 1) which + // .GetPagedResultsByQuery implicitely adds ({Constants.DatabaseSchema.Tables.Document}.newest = 1) which // is what we want for preview (ie latest version of a content, published or not) var descendants = _documentRepository.GetPage(query, pageIndex++, groupSize, out total, "Path", Direction.Ascending, true); const bool published = true; // previewXml contains edit content! @@ -1857,15 +1859,15 @@ WHERE cmsContentXml.nodeId IN ( // db.Execute(@"DELETE cmsContentXml //FROM cmsContentXml //JOIN umbracoNode ON (cmsContentXml.nodeId=umbracoNode.Id) - //JOIN uContent ON (cmsContentXml.nodeId=uContent.nodeId) + //JOIN {Constants.DatabaseSchema.Tables.Content} ON (cmsContentXml.nodeId={Constants.DatabaseSchema.Tables.Content}.nodeId) //WHERE umbracoNode.nodeObjectType=@objType - //AND uContent.contentTypeId IN (@ctypes)", - db.Execute(@"DELETE FROM cmsContentXml + //AND {Constants.DatabaseSchema.Tables.Content}.contentTypeId IN (@ctypes)", + db.Execute($@"DELETE FROM cmsContentXml WHERE cmsContentXml.nodeId IN ( SELECT id FROM umbracoNode - JOIN uContent ON uContent.nodeId=umbracoNode.id + JOIN {Constants.DatabaseSchema.Tables.Content} ON {Constants.DatabaseSchema.Tables.Content}.nodeId=umbracoNode.id WHERE umbracoNode.nodeObjectType=@objType - AND uContent.contentTypeId IN (@ctypes) + AND {Constants.DatabaseSchema.Tables.Content}.contentTypeId IN (@ctypes) )", new { objType = mediaObjectType, ctypes = contentTypeIdsA }); } @@ -1926,15 +1928,15 @@ WHERE cmsContentXml.nodeId IN ( // db.Execute(@"DELETE cmsContentXml //FROM cmsContentXml //JOIN umbracoNode ON (cmsContentXml.nodeId=umbracoNode.Id) - //JOIN uContent ON (cmsContentXml.nodeId=uContent.nodeId) + //JOIN {Constants.DatabaseSchema.Tables.Content} ON (cmsContentXml.nodeId={Constants.DatabaseSchema.Tables.Content}.nodeId) //WHERE umbracoNode.nodeObjectType=@objType - //AND uContent.contentTypeId IN (@ctypes)", - db.Execute(@"DELETE FROM cmsContentXml + //AND {Constants.DatabaseSchema.Tables.Content}.contentTypeId IN (@ctypes)", + db.Execute($@"DELETE FROM cmsContentXml WHERE cmsContentXml.nodeId IN ( SELECT id FROM umbracoNode - JOIN uContent ON uContent.nodeId=umbracoNode.id + JOIN {Constants.DatabaseSchema.Tables.Content} ON {Constants.DatabaseSchema.Tables.Content}.nodeId=umbracoNode.id WHERE umbracoNode.nodeObjectType=@objType - AND uContent.contentTypeId IN (@ctypes) + AND {Constants.DatabaseSchema.Tables.Content}.contentTypeId IN (@ctypes) )", new { objType = memberObjectType, ctypes = contentTypeIdsA }); } @@ -1977,9 +1979,9 @@ WHERE cmsContentXml.nodeId IN ( var contentObjectType = Constants.ObjectTypes.Document; var db = scope.Database; - var count = db.ExecuteScalar(@"SELECT COUNT(*) + var count = db.ExecuteScalar($@"SELECT COUNT(*) FROM umbracoNode -JOIN uDocument ON (umbracoNode.id=uDocument.nodeId and uDocument.published=1) +JOIN {Constants.DatabaseSchema.Tables.Document} ON (umbracoNode.id={Constants.DatabaseSchema.Tables.Document}.nodeId and {Constants.DatabaseSchema.Tables.Document}.published=1) LEFT JOIN cmsContentXml ON (umbracoNode.id=cmsContentXml.nodeId) WHERE umbracoNode.nodeObjectType=@objType AND cmsContentXml.nodeId IS NULL OR cmsContentXml.xml NOT LIKE '% key=""' @@ -2018,9 +2020,9 @@ AND cmsPreviewXml.nodeId IS NULL OR cmsPreviewXml.xml NOT LIKE '% key=""' var mediaObjectType = Constants.ObjectTypes.Media; var db = scope.Database; - var count = db.ExecuteScalar(@"SELECT COUNT(*) + var count = db.ExecuteScalar($@"SELECT COUNT(*) FROM umbracoNode -JOIN uDocument ON (umbracoNode.id=uDocument.nodeId and uDocument.published=1) +JOIN {Constants.DatabaseSchema.Tables.Document} ON (umbracoNode.id={Constants.DatabaseSchema.Tables.Document}.nodeId and {Constants.DatabaseSchema.Tables.Document}.published=1) LEFT JOIN cmsContentXml ON (umbracoNode.id=cmsContentXml.nodeId) WHERE umbracoNode.nodeObjectType=@objType AND cmsContentXml.nodeId IS NULL OR cmsContentXml.xml NOT LIKE '% key=""' From 0710311e70790c373c4edb60db58f2584600b31d Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 22 Mar 2018 17:27:34 +1100 Subject: [PATCH 05/14] uncomments an ignore attribute on a test that should definitely be passable --- src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs index 1166ce8743..03ea7391f9 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs @@ -217,7 +217,6 @@ namespace Umbraco.Tests.Persistence.Repositories } [Test] - [Ignore("has bugs")] public void Can_Perform_Get_On_UserRepository() { // Arrange From d852c435591a2a3dce437fdbb37d8d7857234a6e Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 22 Mar 2018 17:33:16 +1100 Subject: [PATCH 06/14] oops, didn't mean to commit new lang tests --- .../Repositories/LanguageRepositoryTest.cs | 23 ------------------- 1 file changed, 23 deletions(-) diff --git a/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs index d56936df9e..3d0b484a50 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs @@ -219,29 +219,6 @@ namespace Umbraco.Tests.Persistence.Repositories // Assert Assert.That(languageBR.HasIdentity, Is.True); Assert.That(languageBR.Id, Is.EqualTo(6)); //With 5 existing entries the Id should be 6 - Assert.IsFalse(languageBR.IsDefaultVariantLanguage); - Assert.IsFalse(languageBR.Mandatory); - } - } - - [Test] - public void Can_Perform_Add_On_LanguageRepository_With_Boolean_Properties() - { - // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) - { - var repository = CreateRepository(provider); - - // Act - var languageBR = new Language("pt-BR") { CultureName = "pt-BR", IsDefaultVariantLanguage = true, Mandatory = true }; - repository.Save(languageBR); - - // Assert - Assert.That(languageBR.HasIdentity, Is.True); - Assert.That(languageBR.Id, Is.EqualTo(6)); //With 5 existing entries the Id should be 6 - Assert.IsTrue(languageBR.IsDefaultVariantLanguage); - Assert.IsTrue(languageBR.Mandatory); } } From b3fb23a67aaa44cf08f696ee95d331cba51e0b66 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 22 Mar 2018 17:51:38 +1100 Subject: [PATCH 07/14] Adds language entity changes and tests --- .../Upgrade/V_8_0_0/LanguageColumns.cs | 15 ++++++++++++ .../Migrations/Upgrade/V_8_0_0/SuperZero.cs | 1 + src/Umbraco.Core/Models/ILanguage.cs | 10 ++++++++ src/Umbraco.Core/Models/Language.cs | 16 +++++++++++++ .../Persistence/Dtos/LanguageDto.cs | 12 ++++++++++ .../Persistence/Factories/LanguageFactory.cs | 4 ++-- .../Repositories/LanguageRepositoryTest.cs | 23 +++++++++++++++++++ 7 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/LanguageColumns.cs diff --git a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/LanguageColumns.cs b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/LanguageColumns.cs new file mode 100644 index 0000000000..18246ac14b --- /dev/null +++ b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/LanguageColumns.cs @@ -0,0 +1,15 @@ +namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0 +{ + public class LanguageColumns : MigrationBase + { + protected LanguageColumns(IMigrationContext context) : base(context) + { + } + + public override void Migrate() + { + Create.Column("isDefaultVariantLang").OnTable(Constants.DatabaseSchema.Tables.Language).AsBoolean().NotNullable(); + Create.Column("mandatory").OnTable(Constants.DatabaseSchema.Tables.Language).AsBoolean().NotNullable(); + } + } +} diff --git a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/SuperZero.cs b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/SuperZero.cs index ba29880e79..3ea761016b 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/SuperZero.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/SuperZero.cs @@ -1,5 +1,6 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0 { + public class SuperZero : MigrationBase { public SuperZero(IMigrationContext context) diff --git a/src/Umbraco.Core/Models/ILanguage.cs b/src/Umbraco.Core/Models/ILanguage.cs index 8eb9063302..23cef54180 100644 --- a/src/Umbraco.Core/Models/ILanguage.cs +++ b/src/Umbraco.Core/Models/ILanguage.cs @@ -23,5 +23,15 @@ namespace Umbraco.Core.Models /// [IgnoreDataMember] CultureInfo CultureInfo { get; } + + /// + /// Defines if this language is the default variant language when language variants are in use + /// + bool IsDefaultVariantLanguage { get; set; } + + /// + /// If true, a variant node cannot be published unless this language variant is created + /// + bool Mandatory { get; set; } } } diff --git a/src/Umbraco.Core/Models/Language.cs b/src/Umbraco.Core/Models/Language.cs index 6dfe59778f..a143a8c457 100644 --- a/src/Umbraco.Core/Models/Language.cs +++ b/src/Umbraco.Core/Models/Language.cs @@ -17,6 +17,8 @@ namespace Umbraco.Core.Models private string _isoCode; private string _cultureName; + private bool _isDefaultVariantLanguage; + private bool _mandatory; public Language(string isoCode) { @@ -28,6 +30,8 @@ namespace Umbraco.Core.Models { public readonly PropertyInfo IsoCodeSelector = ExpressionHelper.GetPropertyInfo(x => x.IsoCode); public readonly PropertyInfo CultureNameSelector = ExpressionHelper.GetPropertyInfo(x => x.CultureName); + public readonly PropertyInfo IsDefaultVariantLanguageSelector = ExpressionHelper.GetPropertyInfo(x => x.IsDefaultVariantLanguage); + public readonly PropertyInfo MandatorySelector = ExpressionHelper.GetPropertyInfo(x => x.Mandatory); } /// @@ -55,5 +59,17 @@ namespace Umbraco.Core.Models /// [IgnoreDataMember] public CultureInfo CultureInfo => CultureInfo.GetCultureInfo(IsoCode); + + public bool IsDefaultVariantLanguage + { + get => _isDefaultVariantLanguage; + set => SetPropertyValueAndDetectChanges(value, ref _isDefaultVariantLanguage, Ps.Value.IsDefaultVariantLanguageSelector); + } + + public bool Mandatory + { + get => _mandatory; + set => SetPropertyValueAndDetectChanges(value, ref _mandatory, Ps.Value.MandatorySelector); + } } } diff --git a/src/Umbraco.Core/Persistence/Dtos/LanguageDto.cs b/src/Umbraco.Core/Persistence/Dtos/LanguageDto.cs index 83745a2bfe..f88d9fbb5c 100644 --- a/src/Umbraco.Core/Persistence/Dtos/LanguageDto.cs +++ b/src/Umbraco.Core/Persistence/Dtos/LanguageDto.cs @@ -22,5 +22,17 @@ namespace Umbraco.Core.Persistence.Dtos [NullSetting(NullSetting = NullSettings.Null)] [Length(100)] public string CultureName { get; set; } + + /// + /// Defines if this language is the default variant language when language variants are in use + /// + [Column("isDefaultVariantLang")] + public bool IsDefaultVariantLanguage { get; set; } + + /// + /// If true, a variant node cannot be published unless this language variant is created + /// + [Column("mandatory")] + public bool Mandatory { get; set; } } } diff --git a/src/Umbraco.Core/Persistence/Factories/LanguageFactory.cs b/src/Umbraco.Core/Persistence/Factories/LanguageFactory.cs index f15313622b..f79dab1bbd 100644 --- a/src/Umbraco.Core/Persistence/Factories/LanguageFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/LanguageFactory.cs @@ -8,7 +8,7 @@ namespace Umbraco.Core.Persistence.Factories { public ILanguage BuildEntity(LanguageDto dto) { - var lang = new Language(dto.IsoCode) { CultureName = dto.CultureName, Id = dto.Id }; + var lang = new Language(dto.IsoCode) { CultureName = dto.CultureName, Id = dto.Id, IsDefaultVariantLanguage = dto.IsDefaultVariantLanguage, Mandatory = dto.Mandatory }; // reset dirty initial properties (U4-1946) lang.ResetDirtyProperties(false); return lang; @@ -16,7 +16,7 @@ namespace Umbraco.Core.Persistence.Factories public LanguageDto BuildDto(ILanguage entity) { - var dto = new LanguageDto { CultureName = entity.CultureName, IsoCode = entity.IsoCode }; + var dto = new LanguageDto { CultureName = entity.CultureName, IsoCode = entity.IsoCode, IsDefaultVariantLanguage = entity.IsDefaultVariantLanguage, Mandatory = entity.Mandatory }; if (entity.HasIdentity) dto.Id = short.Parse(entity.Id.ToString(CultureInfo.InvariantCulture)); diff --git a/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs index 3d0b484a50..d56936df9e 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs @@ -219,6 +219,29 @@ namespace Umbraco.Tests.Persistence.Repositories // Assert Assert.That(languageBR.HasIdentity, Is.True); Assert.That(languageBR.Id, Is.EqualTo(6)); //With 5 existing entries the Id should be 6 + Assert.IsFalse(languageBR.IsDefaultVariantLanguage); + Assert.IsFalse(languageBR.Mandatory); + } + } + + [Test] + public void Can_Perform_Add_On_LanguageRepository_With_Boolean_Properties() + { + // Arrange + var provider = TestObjects.GetScopeProvider(Logger); + using (var scope = provider.CreateScope()) + { + var repository = CreateRepository(provider); + + // Act + var languageBR = new Language("pt-BR") { CultureName = "pt-BR", IsDefaultVariantLanguage = true, Mandatory = true }; + repository.Save(languageBR); + + // Assert + Assert.That(languageBR.HasIdentity, Is.True); + Assert.That(languageBR.Id, Is.EqualTo(6)); //With 5 existing entries the Id should be 6 + Assert.IsTrue(languageBR.IsDefaultVariantLanguage); + Assert.IsTrue(languageBR.Mandatory); } } From 01b48a5aab49c496ead711a1092cd042b62c6a6a Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 22 Mar 2018 23:15:52 +1100 Subject: [PATCH 08/14] adds logic for repository and unit tests --- .../Implement/LanguageRepository.cs | 17 +++++++++++ .../Services/Implement/LocalizationService.cs | 2 +- src/Umbraco.Core/Umbraco.Core.csproj | 1 + .../Repositories/LanguageRepositoryTest.cs | 30 +++++++++++++++++++ .../Services/LocalizationServiceTests.cs | 22 ++++++++++++++ 5 files changed, 71 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/LanguageRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/LanguageRepository.cs index 784191279d..1397d79ea8 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/LanguageRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/LanguageRepository.cs @@ -107,6 +107,14 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { ((EntityBase)entity).AddingEntity(); + if (entity.IsDefaultVariantLanguage) + { + //if this entity is flagged as the default, we need to set all others to false + Database.Execute($"UPDATE {SqlSyntax.GetQuotedColumnName(Constants.DatabaseSchema.Tables.Language)} SET {SqlSyntax.GetQuotedColumnName("isDefaultVariantLang")} = 0"); + //We need to clear the whole cache since all languages will be updated + IsolatedCache.ClearAllCache(); + } + var factory = new LanguageFactory(); var dto = factory.BuildDto(entity); @@ -114,12 +122,21 @@ namespace Umbraco.Core.Persistence.Repositories.Implement entity.Id = id; entity.ResetDirtyProperties(); + } protected override void PersistUpdatedItem(ILanguage entity) { ((EntityBase)entity).UpdatingEntity(); + if (entity.IsDefaultVariantLanguage) + { + //if this entity is flagged as the default, we need to set all others to false + Database.Execute($"UPDATE {SqlSyntax.GetQuotedColumnName(Constants.DatabaseSchema.Tables.Language)} SET {SqlSyntax.GetQuotedColumnName("isDefaultVariantLang")} = 0"); + //We need to clear the whole cache since all languages will be updated + IsolatedCache.ClearAllCache(); + } + var factory = new LanguageFactory(); var dto = factory.BuildDto(entity); diff --git a/src/Umbraco.Core/Services/Implement/LocalizationService.cs b/src/Umbraco.Core/Services/Implement/LocalizationService.cs index 70103d9a06..1af053b787 100644 --- a/src/Umbraco.Core/Services/Implement/LocalizationService.cs +++ b/src/Umbraco.Core/Services/Implement/LocalizationService.cs @@ -411,7 +411,7 @@ namespace Umbraco.Core.Services.Implement } } - #region Event Handlers + #region Events /// /// Occurs before Delete /// diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 00f1a85d79..7089d164bc 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -315,6 +315,7 @@ + diff --git a/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs index d56936df9e..0033c2524b 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs @@ -245,6 +245,36 @@ namespace Umbraco.Tests.Persistence.Repositories } } + [Test] + public void Can_Perform_Add_On_LanguageRepository_With_New_Deafult() + { + // Arrange + var provider = TestObjects.GetScopeProvider(Logger); + using (var scope = provider.CreateScope()) + { + var repository = CreateRepository(provider); + + var languageBR = (ILanguage)new Language("pt-BR") { CultureName = "pt-BR", IsDefaultVariantLanguage = true, Mandatory = true }; + repository.Save(languageBR); + var languageEN = new Language("en-AU") { CultureName = "en-AU" }; + repository.Save(languageEN); + + Assert.IsTrue(languageBR.IsDefaultVariantLanguage); + Assert.IsTrue(languageBR.Mandatory); + + // Act + + var languageNZ = new Language("en-NZ") { CultureName = "en-NZ", IsDefaultVariantLanguage = true, Mandatory = true }; + repository.Save(languageNZ); + languageBR = repository.Get(languageBR.Id); + + // Assert + + Assert.IsFalse(languageBR.IsDefaultVariantLanguage); + Assert.IsTrue(languageNZ.IsDefaultVariantLanguage); + } + } + [Test] public void Can_Perform_Update_On_LanguageRepository() { diff --git a/src/Umbraco.Tests/Services/LocalizationServiceTests.cs b/src/Umbraco.Tests/Services/LocalizationServiceTests.cs index b7f958cb8e..e39ebfee8e 100644 --- a/src/Umbraco.Tests/Services/LocalizationServiceTests.cs +++ b/src/Umbraco.Tests/Services/LocalizationServiceTests.cs @@ -364,6 +364,28 @@ namespace Umbraco.Tests.Services Assert.NotNull(result); } + [Test] + public void Set_Default_Language() + { + var localizationService = ServiceContext.LocalizationService; + var language = new Core.Models.Language("en-AU"); + language.IsDefaultVariantLanguage = true; + localizationService.Save(language); + var result = localizationService.GetLanguageById(language.Id); + + Assert.IsTrue(result.IsDefaultVariantLanguage); + + var language2 = new Core.Models.Language("en-NZ"); + language2.IsDefaultVariantLanguage = true; + localizationService.Save(language2); + var result2 = localizationService.GetLanguageById(language2.Id); + //re-get + result = localizationService.GetLanguageById(language.Id); + + Assert.IsTrue(result2.IsDefaultVariantLanguage); + Assert.IsFalse(result.IsDefaultVariantLanguage); + } + [Test] public void Deleted_Language_Should_Not_Exist() { From a4c9d8f1bf0d6ed50985b91168f9f3f5ca75de5c Mon Sep 17 00:00:00 2001 From: Claus Date: Thu, 22 Mar 2018 15:34:28 +0100 Subject: [PATCH 09/14] typos --- .../Persistence/Repositories/LanguageRepositoryTest.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs index 0033c2524b..fbf43a1889 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs @@ -2,14 +2,10 @@ using System.Linq; using Moq; using NUnit.Framework; -using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Persistence; - -using Umbraco.Core.Persistence.Querying; -using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.Scoping; using Umbraco.Tests.TestHelpers; @@ -33,8 +29,6 @@ namespace Umbraco.Tests.Persistence.Repositories return new LanguageRepository((IScopeAccessor) provider, CacheHelper.CreateDisabledCacheHelper(), Mock.Of()); } - - [Test] public void Can_Perform_Get_On_LanguageRepository() { @@ -109,7 +103,7 @@ namespace Umbraco.Tests.Persistence.Repositories } [Test] - public void Get_WhenIdDoesntExist_ReturnsNull() + public void Get_When_Id_Doesnt_Exist_Returns_Null() { // Arrange var provider = TestObjects.GetScopeProvider(Logger); @@ -246,7 +240,7 @@ namespace Umbraco.Tests.Persistence.Repositories } [Test] - public void Can_Perform_Add_On_LanguageRepository_With_New_Deafult() + public void Can_Perform_Add_On_LanguageRepository_With_New_Default() { // Arrange var provider = TestObjects.GetScopeProvider(Logger); From 3a3d6239f0d6a607ebd1c46b6ef87a5a87dfacd7 Mon Sep 17 00:00:00 2001 From: Claus Date: Thu, 22 Mar 2018 15:35:51 +0100 Subject: [PATCH 10/14] U4-11144 GetManifestFiles fails if there's no App_Plugins folder --- src/Umbraco.Core/Manifest/ManifestParser.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Core/Manifest/ManifestParser.cs b/src/Umbraco.Core/Manifest/ManifestParser.cs index 32070b3542..cad491aeb1 100644 --- a/src/Umbraco.Core/Manifest/ManifestParser.cs +++ b/src/Umbraco.Core/Manifest/ManifestParser.cs @@ -120,7 +120,12 @@ namespace Umbraco.Core.Manifest // gets all manifest files (recursively) private IEnumerable GetManifestFiles() - => Directory.GetFiles(_path, "package.manifest", SearchOption.AllDirectories); + { + if (Directory.Exists(_path) == false) + return new string[0]; + return Directory.GetFiles(_path, "package.manifest", SearchOption.AllDirectories); + } + private static string TrimPreamble(string text) { From 59bac5c2a64bc2989ec8ca1751032ef034132d5a Mon Sep 17 00:00:00 2001 From: Stephan Date: Thu, 22 Mar 2018 17:51:34 +0100 Subject: [PATCH 11/14] Fix a few things, the v8 way --- src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs | 6 ++++-- .../Migrations/Upgrade/V_8_0_0/LanguageColumns.cs | 14 ++++++++------ .../Migrations/Upgrade/V_8_0_0/SuperZero.cs | 1 - .../Repositories/Implement/LanguageRepository.cs | 4 ++-- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs b/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs index 16ec3d0a30..03e52e6e97 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs @@ -64,7 +64,7 @@ namespace Umbraco.Core.Migrations.Upgrade // // when installing, the source state is empty, and the target state should be the final state. - Add(string.Empty, "{CA7DB949-3EF4-403D-8464-F9BA36A52E87}"); + Add(string.Empty, "{7F0BF916-F64E-4B25-864A-170D6E6B68E5}"); // UPGRADE FROM 7 // @@ -84,7 +84,8 @@ namespace Umbraco.Core.Migrations.Upgrade .Chain("{8640C9E4-A1C0-4C59-99BB-609B4E604981}") .Chain("{DD1B99AF-8106-4E00-BAC7-A43003EA07F8}") .Chain("{9DF05B77-11D1-475C-A00A-B656AF7E0908}") - .Chain("{CA7DB949-3EF4-403D-8464-F9BA36A52E87}");; + .Chain("{9E98CF10-3AE9-437B-AF54-8697D251A541}") + .Chain("{7F0BF916-F64E-4B25-864A-170D6E6B68E5}"); // 7.8.1 = same as 7.8.0 From("{init-7.8.1}") @@ -156,6 +157,7 @@ namespace Umbraco.Core.Migrations.Upgrade Chain("{139F26D7-7E08-48E3-81D9-E50A21A72F67}"); Chain("{CC1B1201-1328-443C-954A-E0BBB8CCC1B5}"); Chain("{CA7DB949-3EF4-403D-8464-F9BA36A52E87}"); + Chain("{7F0BF916-F64E-4B25-864A-170D6E6B68E5}"); } } } diff --git a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/LanguageColumns.cs b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/LanguageColumns.cs index 18246ac14b..4538c6343e 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/LanguageColumns.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/LanguageColumns.cs @@ -1,15 +1,17 @@ -namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0 +using Umbraco.Core.Persistence.Dtos; + +namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0 { public class LanguageColumns : MigrationBase { - protected LanguageColumns(IMigrationContext context) : base(context) - { - } + protected LanguageColumns(IMigrationContext context) + : base(context) + { } public override void Migrate() { - Create.Column("isDefaultVariantLang").OnTable(Constants.DatabaseSchema.Tables.Language).AsBoolean().NotNullable(); - Create.Column("mandatory").OnTable(Constants.DatabaseSchema.Tables.Language).AsBoolean().NotNullable(); + AddColumn(Constants.DatabaseSchema.Tables.Language, "isDefaultVariantLang"); + AddColumn(Constants.DatabaseSchema.Tables.Language, "mandatory"); } } } diff --git a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/SuperZero.cs b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/SuperZero.cs index 3ea761016b..ba29880e79 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/SuperZero.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/SuperZero.cs @@ -1,6 +1,5 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0 { - public class SuperZero : MigrationBase { public SuperZero(IMigrationContext context) diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/LanguageRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/LanguageRepository.cs index 1397d79ea8..2d27479a95 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/LanguageRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/LanguageRepository.cs @@ -110,7 +110,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement if (entity.IsDefaultVariantLanguage) { //if this entity is flagged as the default, we need to set all others to false - Database.Execute($"UPDATE {SqlSyntax.GetQuotedColumnName(Constants.DatabaseSchema.Tables.Language)} SET {SqlSyntax.GetQuotedColumnName("isDefaultVariantLang")} = 0"); + Database.Execute(Sql().Update(u => u.Set(x => x.IsDefaultVariantLanguage, false))); //We need to clear the whole cache since all languages will be updated IsolatedCache.ClearAllCache(); } @@ -132,7 +132,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement if (entity.IsDefaultVariantLanguage) { //if this entity is flagged as the default, we need to set all others to false - Database.Execute($"UPDATE {SqlSyntax.GetQuotedColumnName(Constants.DatabaseSchema.Tables.Language)} SET {SqlSyntax.GetQuotedColumnName("isDefaultVariantLang")} = 0"); + Database.Execute(Sql().Update(u => u.Set(x => x.IsDefaultVariantLanguage, false))); //We need to clear the whole cache since all languages will be updated IsolatedCache.ClearAllCache(); } From 19a408fcaeda6dab8a95e3ca2e2c9192342cb26e Mon Sep 17 00:00:00 2001 From: Claus Date: Mon, 26 Mar 2018 10:55:49 +0200 Subject: [PATCH 12/14] U4-11121 New LanguagesController (back office editor controller) for persisting language changes --- src/Umbraco.Web/Editors/LanguageController.cs | 83 +++++++++++++++++++ src/Umbraco.Web/Models/Culture.cs | 8 ++ src/Umbraco.Web/Models/Language.cs | 13 +++ src/Umbraco.Web/Umbraco.Web.csproj | 3 + 4 files changed, 107 insertions(+) create mode 100644 src/Umbraco.Web/Editors/LanguageController.cs create mode 100644 src/Umbraco.Web/Models/Culture.cs create mode 100644 src/Umbraco.Web/Models/Language.cs diff --git a/src/Umbraco.Web/Editors/LanguageController.cs b/src/Umbraco.Web/Editors/LanguageController.cs new file mode 100644 index 0000000000..20932f6bf9 --- /dev/null +++ b/src/Umbraco.Web/Editors/LanguageController.cs @@ -0,0 +1,83 @@ +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Web.Http; +using Umbraco.Core.Persistence; +using Umbraco.Web.Models; +using Umbraco.Web.Mvc; + +namespace Umbraco.Web.Editors +{ + /// + /// Backoffice controller supporting the dashboard for language administration. + /// + [PluginController("UmbracoApi")] + public class LanguageController : UmbracoAuthorizedJsonController + { + /// + /// Returns all cultures available for creating languages. + /// + /// + [HttpGet] + public IEnumerable GetAllCultures() + { + return CultureInfo.GetCultures(CultureTypes.AllCultures) + .Select(x => new Culture {IsoCode = x.Name, Name = x.DisplayName}); + } + + /// + /// Returns all currently configured languages. + /// + /// + [HttpGet] + public IEnumerable GetAllLanguages() + { + var allLanguages = Services.LocalizationService.GetAllLanguages(); + + return allLanguages.Select(x => new Language + { + Id = x.Id, + IsoCode = x.IsoCode, + Name = x.CultureInfo.DisplayName, + IsDefaultVariantLanguage = x.IsDefaultVariantLanguage, + Mandatory = x.Mandatory + }); + } + + /// + /// Deletes a language with a given ID + /// + [HttpDelete] + [HttpPost] + public void DeleteLanguage(int id) + { + var language = Services.LocalizationService.GetLanguageById(id); + if (language == null) + { + throw new EntityNotFoundException(id, $"Could not find language by id: '{id}'."); + } + Services.LocalizationService.Delete(language); + } + + /// + /// Saves a bulk set of languages with default/mandatory settings and returns the full set of languages configured. + /// + [HttpPost] + public IEnumerable SaveLanguages(IEnumerable languages) + { + foreach (var l in languages) + { + var language = Services.LocalizationService.GetLanguageByIsoCode(l.IsoCode); + if (language == null) + { + language = new Core.Models.Language(l.IsoCode); + } + language.Mandatory = l.Mandatory; + language.IsDefaultVariantLanguage = l.IsDefaultVariantLanguage; + Services.LocalizationService.Save(language); + } + + return GetAllLanguages(); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Models/Culture.cs b/src/Umbraco.Web/Models/Culture.cs new file mode 100644 index 0000000000..16ebc6bc2a --- /dev/null +++ b/src/Umbraco.Web/Models/Culture.cs @@ -0,0 +1,8 @@ +namespace Umbraco.Web.Models +{ + public class Culture + { + public string IsoCode { get; set; } + public string Name { get; set; } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Models/Language.cs b/src/Umbraco.Web/Models/Language.cs new file mode 100644 index 0000000000..4fdf418eef --- /dev/null +++ b/src/Umbraco.Web/Models/Language.cs @@ -0,0 +1,13 @@ +using System.Globalization; + +namespace Umbraco.Web.Models +{ + public class Language + { + public int Id { get; set; } + public string IsoCode { get; set; } + public string Name { get; set; } + public bool IsDefaultVariantLanguage { get; set; } + public bool Mandatory { get; set; } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 20358b3d4d..5551354d56 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -136,6 +136,7 @@ + @@ -221,6 +222,8 @@ + + From 487e4cbe2086946ddab9e885b021a20f547a5019 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 28 Mar 2018 12:50:15 +1100 Subject: [PATCH 13/14] Fixes various migration stuff - language migration was broken (public ctor), the custom sql in KeyValueService was incorrect, moved to migration syntax, InsertDataExpression didn't work, fixed with v7 code that does work, changes some Database.Execute to Execute.Sql so logging occurs. Fixes packages.config inclusion --- .../Expressions/InsertDataExpression.cs | 11 ++- .../Migrations/MigrationBase_Extra.cs | 23 ++++--- src/Umbraco.Core/Migrations/MigrationPlan.cs | 5 +- .../Upgrade/V_8_0_0/DataTypeMigration.cs | 7 +- .../Upgrade/V_8_0_0/LanguageColumns.cs | 2 +- .../Persistence/Dtos/LanguageDto.cs | 2 + .../Services/Implement/KeyValueService.cs | 67 +++++++++++-------- src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 4 +- 8 files changed, 73 insertions(+), 48 deletions(-) diff --git a/src/Umbraco.Core/Migrations/Expressions/Insert/Expressions/InsertDataExpression.cs b/src/Umbraco.Core/Migrations/Expressions/Insert/Expressions/InsertDataExpression.cs index d06a5a9bfe..7fbd7765e3 100644 --- a/src/Umbraco.Core/Migrations/Expressions/Insert/Expressions/InsertDataExpression.cs +++ b/src/Umbraco.Core/Migrations/Expressions/Insert/Expressions/InsertDataExpression.cs @@ -32,8 +32,15 @@ namespace Umbraco.Core.Migrations.Expressions.Insert.Expressions { foreach (var item in Rows) { - var cols = string.Join(",", item.Select(x => x.Key)); - var vals = string.Join(",", item.Select(x => x.Value)); + var cols = ""; + var vals = ""; + foreach (var keyVal in item) + { + cols += SqlSyntax.GetQuotedColumnName(keyVal.Key) + ","; + vals += GetQuotedValue(keyVal.Value) + ","; + } + cols = cols.TrimEnd(','); + vals = vals.TrimEnd(','); var sql = string.Format(SqlSyntax.InsertData, SqlSyntax.GetQuotedTableName(TableName), diff --git a/src/Umbraco.Core/Migrations/MigrationBase_Extra.cs b/src/Umbraco.Core/Migrations/MigrationBase_Extra.cs index 91342de867..9f4c45f0ad 100644 --- a/src/Umbraco.Core/Migrations/MigrationBase_Extra.cs +++ b/src/Umbraco.Core/Migrations/MigrationBase_Extra.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Linq; using Umbraco.Core.Persistence.DatabaseModelDefinitions; +using Umbraco.Core.Persistence.SqlSyntax; namespace Umbraco.Core.Migrations { @@ -11,26 +12,30 @@ namespace Umbraco.Core.Migrations { // provides extra methods for migrations + //fixme - why do we have tableName and provide a table type which we can just extract the table name from? protected void AddColumn(string tableName, string columnName) { - //if (ColumnExists(tableName, columnName)) - // throw new InvalidOperationException($"Column {tableName}.{columnName} already exists."); + if (ColumnExists(tableName, columnName)) return; var table = DefinitionFactory.GetTableDefinition(typeof(T), SqlSyntax); var column = table.Columns.First(x => x.Name == columnName); var createSql = SqlSyntax.Format(column); - Database.Execute(string.Format(SqlSyntax.AddColumn, SqlSyntax.GetQuotedTableName(tableName), createSql)); + + Execute.Sql(string.Format(SqlSyntax.AddColumn, SqlSyntax.GetQuotedTableName(table.Name), createSql)).Do(); } protected void AddColumn(string tableName, string columnName, out IEnumerable sqls) { - //if (ColumnExists(tableName, columnName)) - // throw new InvalidOperationException($"Column {tableName}.{columnName} already exists."); + if (ColumnExists(tableName, columnName)) + { + sqls = Enumerable.Empty(); + return; + } var table = DefinitionFactory.GetTableDefinition(typeof(T), SqlSyntax); var column = table.Columns.First(x => x.Name == columnName); var createSql = SqlSyntax.Format(column, SqlSyntax.GetQuotedTableName(tableName), out sqls); - Database.Execute(string.Format(SqlSyntax.AddColumn, SqlSyntax.GetQuotedTableName(tableName), createSql)); + Execute.Sql(string.Format(SqlSyntax.AddColumn, SqlSyntax.GetQuotedTableName(tableName), createSql)).Do(); } protected void AlterColumn(string tableName, string columnName) @@ -39,14 +44,14 @@ namespace Umbraco.Core.Migrations var column = table.Columns.First(x => x.Name == columnName); SqlSyntax.Format(column, SqlSyntax.GetQuotedTableName(tableName), out var sqls); foreach (var sql in sqls) - Database.Execute(sql); + Execute.Sql(sql).Do(); } protected void ReplaceColumn(string tableName, string currentName, string newName) { AddColumn(tableName, newName, out var sqls); - Database.Execute($"UPDATE {SqlSyntax.GetQuotedTableName(tableName)} SET {SqlSyntax.GetQuotedColumnName(newName)}={SqlSyntax.GetQuotedColumnName(currentName)}"); - foreach (var sql in sqls) Database.Execute(sql); + Execute.Sql($"UPDATE {SqlSyntax.GetQuotedTableName(tableName)} SET {SqlSyntax.GetQuotedColumnName(newName)}={SqlSyntax.GetQuotedColumnName(currentName)}").Do(); + foreach (var sql in sqls) Execute.Sql(sql).Do(); Delete.Column(currentName).FromTable(tableName).Do(); } diff --git a/src/Umbraco.Core/Migrations/MigrationPlan.cs b/src/Umbraco.Core/Migrations/MigrationPlan.cs index 909415336b..f686ff283e 100644 --- a/src/Umbraco.Core/Migrations/MigrationPlan.cs +++ b/src/Umbraco.Core/Migrations/MigrationPlan.cs @@ -159,9 +159,8 @@ namespace Umbraco.Core.Migrations var nextState = transition.TargetState; origState = nextState; - - // ReSharper disable once AccessToModifiedClosure - _logger.Info("At \"{0}\".", () => origState); + + _logger.Info("At \"{0}\".", origState); if (!_transitions.TryGetValue(origState, out transition)) throw new Exception($"Unknown state \"{origState}\"."); diff --git a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DataTypeMigration.cs b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DataTypeMigration.cs index 202a4f0c0a..65db0cdd2d 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DataTypeMigration.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DataTypeMigration.cs @@ -29,18 +29,17 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0 Rename.Table("cmsDataType").To(Constants.DatabaseSchema.Tables.DataType).Do(); // create column - // fixme it is annoying that these are NOT written out to the log?! AddColumn(Constants.DatabaseSchema.Tables.DataType, "config"); - Database.Execute(Sql().Update(u => u.Set(x => x.Configuration, string.Empty))); + Execute.Sql(Sql().Update(u => u.Set(x => x.Configuration, string.Empty)).SQL).Do(); // re-create *all* keys and indexes foreach (var x in DatabaseSchemaCreator.OrderedTables) Create.KeysAndIndexes(x.Value).Do(); // renames - Database.Execute(Sql() + Execute.Sql(Sql() .Update(u => u.Set(x => x.EditorAlias, "Umbraco.ColorPicker")) - .Where(x => x.EditorAlias == "Umbraco.ColorPickerAlias")); + .Where(x => x.EditorAlias == "Umbraco.ColorPickerAlias").SQL).Do(); // from preValues to configuration... var sql = Sql() diff --git a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/LanguageColumns.cs b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/LanguageColumns.cs index 4538c6343e..e8a1197d37 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/LanguageColumns.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/LanguageColumns.cs @@ -4,7 +4,7 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0 { public class LanguageColumns : MigrationBase { - protected LanguageColumns(IMigrationContext context) + public LanguageColumns(IMigrationContext context) : base(context) { } diff --git a/src/Umbraco.Core/Persistence/Dtos/LanguageDto.cs b/src/Umbraco.Core/Persistence/Dtos/LanguageDto.cs index f88d9fbb5c..78e5670830 100644 --- a/src/Umbraco.Core/Persistence/Dtos/LanguageDto.cs +++ b/src/Umbraco.Core/Persistence/Dtos/LanguageDto.cs @@ -27,12 +27,14 @@ namespace Umbraco.Core.Persistence.Dtos /// Defines if this language is the default variant language when language variants are in use /// [Column("isDefaultVariantLang")] + [Constraint(Default = "0")] public bool IsDefaultVariantLanguage { get; set; } /// /// If true, a variant node cannot be published unless this language variant is created /// [Column("mandatory")] + [Constraint(Default = "0")] public bool Mandatory { get; set; } } } diff --git a/src/Umbraco.Core/Services/Implement/KeyValueService.cs b/src/Umbraco.Core/Services/Implement/KeyValueService.cs index 6f911ceedc..9b91325eab 100644 --- a/src/Umbraco.Core/Services/Implement/KeyValueService.cs +++ b/src/Umbraco.Core/Services/Implement/KeyValueService.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using Umbraco.Core.Logging; using Umbraco.Core.Migrations; @@ -34,8 +35,8 @@ namespace Umbraco.Core.Services.Implement private void Initialize() { - // all this cannot be achieved via migrations since it needs to run - // before any migration, in order to figure out migrations + // all this cannot be achieved via default migrations since it needs to run + // before any migration, in order to figure out migrations, ironically we are using a custom migration to do this using (var scope = _scopeProvider.CreateScope()) { @@ -46,38 +47,48 @@ namespace Umbraco.Core.Services.Implement return; } - // drop the 'identity' on umbracoLock primary key - foreach (var sql in new[] - { - // create a temp. id column and copy values - "alter table umbracoLock add column nid int null;", - "update umbracoLock set nid = id;", - // drop the id column entirely (cannot just drop identity) - "alter table umbracoLock drop constraint PK_umbracoLock;", - "alter table umbracoLock drop column id;", - // recreate the id column without identity and copy values - "alter table umbracoLock add column id int null;", - "update umbracoLock set id = nid;", - // drop the temp. id column - "alter table umbracoLock drop column nid;", - // complete the primary key - "alter table umbracoLock alter column id int not null;", - "alter table umbracoLock add constraint PK_umbracoLock primary key (id);" - }) - scope.Database.Execute(sql); - - // insert the key-value lock - scope.Database.Execute($@"INSERT {scope.SqlContext.SqlSyntax.GetQuotedTableName(Constants.DatabaseSchema.Tables.Lock)} (id, name, value) -VALUES ({Constants.Locks.KeyValues}, 'KeyValues', 1);"); - - // create the key-value table var context = new MigrationContext(scope.Database, _logger); - new CreateBuilder(context).Table().Do(); + var initMigration = new InitializeMigration(context); + initMigration.Migrate(); scope.Complete(); } } + /// + /// A custom migration that executes standalone during the Initialize phase of this service + /// + private class InitializeMigration : MigrationBase + { + public InitializeMigration(IMigrationContext context) : base(context) + { + } + + public override void Migrate() + { + // create a temp. id column and copy values + Alter.Table(Constants.DatabaseSchema.Tables.Lock).AddColumn("nid").AsInt32().Nullable().Do(); + Execute.Sql("update umbracoLock set nid = id").Do(); + // drop the id column entirely (cannot just drop identity) + Delete.PrimaryKey("PK_umbracoLock").FromTable(Constants.DatabaseSchema.Tables.Lock).Do(); + Delete.Column("id").FromTable(Constants.DatabaseSchema.Tables.Lock).Do(); + // recreate the id column without identity and copy values + Alter.Table(Constants.DatabaseSchema.Tables.Lock).AddColumn("id").AsInt32().Nullable().Do(); + Execute.Sql("update umbracoLock set id = nid").Do(); + // drop the temp. id column + Delete.Column("nid").FromTable(Constants.DatabaseSchema.Tables.Lock).Do(); + // complete the primary key + Alter.Table(Constants.DatabaseSchema.Tables.Lock).AlterColumn("id").AsInt32().NotNullable().PrimaryKey("PK_umbracoLock").Do(); + + // insert the key-value lock + Insert.IntoTable(Constants.DatabaseSchema.Tables.Lock).Row(new {id = Constants.Locks.KeyValues, name = "KeyValues", value = 1}).Do(); + + // create the key-value table if it's not there + if (TableExists(Constants.DatabaseSchema.Tables.KeyValue) == false) + Create.Table().Do(); + } + } + /// public string GetValue(string key) { diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index 4c8df3cc87..e918cf169d 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -674,7 +674,9 @@ SettingsSingleFileGenerator Settings.Designer.cs - + + Designer + UI.xml From 7adc9864726c40a72bf1cee45f3d09a85102fff7 Mon Sep 17 00:00:00 2001 From: Stephan Date: Wed, 28 Mar 2018 12:40:52 +0200 Subject: [PATCH 14/14] Cleanup various migration stuff --- .../Expressions/InsertDataExpression.cs | 24 +++++++++------ .../Migrations/MigrationBase_Extra.cs | 29 ++++++++++++++++--- .../Services/Implement/KeyValueService.cs | 17 ++++++----- 3 files changed, 49 insertions(+), 21 deletions(-) diff --git a/src/Umbraco.Core/Migrations/Expressions/Insert/Expressions/InsertDataExpression.cs b/src/Umbraco.Core/Migrations/Expressions/Insert/Expressions/InsertDataExpression.cs index 7fbd7765e3..7efe457402 100644 --- a/src/Umbraco.Core/Migrations/Expressions/Insert/Expressions/InsertDataExpression.cs +++ b/src/Umbraco.Core/Migrations/Expressions/Insert/Expressions/InsertDataExpression.cs @@ -32,19 +32,25 @@ namespace Umbraco.Core.Migrations.Expressions.Insert.Expressions { foreach (var item in Rows) { - var cols = ""; - var vals = ""; + var cols = new StringBuilder(); + var vals = new StringBuilder(); + var first = true; foreach (var keyVal in item) { - cols += SqlSyntax.GetQuotedColumnName(keyVal.Key) + ","; - vals += GetQuotedValue(keyVal.Value) + ","; + if (first) + { + first = false; + } + else + { + cols.Append(","); + vals.Append(","); + } + cols.Append(SqlSyntax.GetQuotedColumnName(keyVal.Key)); + vals.Append(GetQuotedValue(keyVal.Value)); } - cols = cols.TrimEnd(','); - vals = vals.TrimEnd(','); - var sql = string.Format(SqlSyntax.InsertData, - SqlSyntax.GetQuotedTableName(TableName), - cols, vals); + var sql = string.Format(SqlSyntax.InsertData, SqlSyntax.GetQuotedTableName(TableName), cols, vals); stmts.Append(sql); AppendStatementSeparator(stmts); diff --git a/src/Umbraco.Core/Migrations/MigrationBase_Extra.cs b/src/Umbraco.Core/Migrations/MigrationBase_Extra.cs index 9f4c45f0ad..b1b405bcf4 100644 --- a/src/Umbraco.Core/Migrations/MigrationBase_Extra.cs +++ b/src/Umbraco.Core/Migrations/MigrationBase_Extra.cs @@ -12,19 +12,41 @@ namespace Umbraco.Core.Migrations { // provides extra methods for migrations - //fixme - why do we have tableName and provide a table type which we can just extract the table name from? + protected void AddColumn(string columnName) + { + var table = DefinitionFactory.GetTableDefinition(typeof(T), SqlSyntax); + AddColumn(table, table.Name, columnName); + } + protected void AddColumn(string tableName, string columnName) + { + var table = DefinitionFactory.GetTableDefinition(typeof(T), SqlSyntax); + AddColumn(table, tableName, columnName); + } + + private void AddColumn(TableDefinition table, string tableName, string columnName) { if (ColumnExists(tableName, columnName)) return; - var table = DefinitionFactory.GetTableDefinition(typeof(T), SqlSyntax); var column = table.Columns.First(x => x.Name == columnName); var createSql = SqlSyntax.Format(column); - Execute.Sql(string.Format(SqlSyntax.AddColumn, SqlSyntax.GetQuotedTableName(table.Name), createSql)).Do(); + Execute.Sql(string.Format(SqlSyntax.AddColumn, SqlSyntax.GetQuotedTableName(tableName), createSql)).Do(); + } + + protected void AddColumn(string columnName, out IEnumerable sqls) + { + var table = DefinitionFactory.GetTableDefinition(typeof(T), SqlSyntax); + AddColumn(table, table.Name, columnName, out sqls); } protected void AddColumn(string tableName, string columnName, out IEnumerable sqls) + { + var table = DefinitionFactory.GetTableDefinition(typeof(T), SqlSyntax); + AddColumn(table, tableName, columnName, out sqls); + } + + private void AddColumn(TableDefinition table, string tableName, string columnName, out IEnumerable sqls) { if (ColumnExists(tableName, columnName)) { @@ -32,7 +54,6 @@ namespace Umbraco.Core.Migrations return; } - var table = DefinitionFactory.GetTableDefinition(typeof(T), SqlSyntax); var column = table.Columns.First(x => x.Name == columnName); var createSql = SqlSyntax.Format(column, SqlSyntax.GetQuotedTableName(tableName), out sqls); Execute.Sql(string.Format(SqlSyntax.AddColumn, SqlSyntax.GetQuotedTableName(tableName), createSql)).Do(); diff --git a/src/Umbraco.Core/Services/Implement/KeyValueService.cs b/src/Umbraco.Core/Services/Implement/KeyValueService.cs index 9b91325eab..cb1c423535 100644 --- a/src/Umbraco.Core/Services/Implement/KeyValueService.cs +++ b/src/Umbraco.Core/Services/Implement/KeyValueService.cs @@ -35,8 +35,9 @@ namespace Umbraco.Core.Services.Implement private void Initialize() { - // all this cannot be achieved via default migrations since it needs to run - // before any migration, in order to figure out migrations, ironically we are using a custom migration to do this + // all this cannot be achieved via an UmbracoPlan migration since it needs to + // run before any migration, in order to figure out the current plan's state. + // (does not prevent us from using a migration to do it, though) using (var scope = _scopeProvider.CreateScope()) { @@ -56,13 +57,13 @@ namespace Umbraco.Core.Services.Implement } /// - /// A custom migration that executes standalone during the Initialize phase of this service + /// A custom migration that executes standalone during the Initialize phase of this service. /// private class InitializeMigration : MigrationBase { - public InitializeMigration(IMigrationContext context) : base(context) - { - } + public InitializeMigration(IMigrationContext context) + : base(context) + { } public override void Migrate() { @@ -79,9 +80,9 @@ namespace Umbraco.Core.Services.Implement Delete.Column("nid").FromTable(Constants.DatabaseSchema.Tables.Lock).Do(); // complete the primary key Alter.Table(Constants.DatabaseSchema.Tables.Lock).AlterColumn("id").AsInt32().NotNullable().PrimaryKey("PK_umbracoLock").Do(); - + // insert the key-value lock - Insert.IntoTable(Constants.DatabaseSchema.Tables.Lock).Row(new {id = Constants.Locks.KeyValues, name = "KeyValues", value = 1}).Do(); + Insert.IntoTable(Constants.DatabaseSchema.Tables.Lock).Row(new {id = Constants.Locks.KeyValues, name = "KeyValues", value = 1}).Do(); // create the key-value table if it's not there if (TableExists(Constants.DatabaseSchema.Tables.KeyValue) == false)