Merge remote-tracking branch 'origin/v13/dev' into v14/dev
# Conflicts: # src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs # Ignored Conflicts (Umbraco.Web.UI.Client is completly replaced in v14) # src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbtour/umbtourstep.directive.js # src/Umbraco.Web.UI.Client/src/views/components/application/umb-tour.html # src/Umbraco.Web.UI.Client/src/views/components/application/umbtour/umb-tour-step-content.html # src/Umbraco.Web.UI.Client/src/views/components/application/umbtour/umb-tour-step-counter.html # src/Umbraco.Web.UI.Client/src/views/components/application/umbtour/umb-tour-step-header.html # src/Umbraco.Web.UI.Client~HEAD # src/Umbraco.Web.UI.Login/package-lock.json # src/Umbraco.Web.UI.Login/package.json
This commit is contained in:
@@ -174,15 +174,17 @@ public static class ContentRepositoryExtensions
|
||||
foreach (IProperty property in content.Properties)
|
||||
{
|
||||
// each property type may or may not support the variation
|
||||
if (!property.PropertyType?.SupportsVariation(culture, "*", true) ?? false)
|
||||
if ((!property.PropertyType?.SupportsVariation(culture, "*", true) ?? false) &&
|
||||
!(property.PropertyType?.Variations == ContentVariation.Nothing))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (IPropertyValue pvalue in property.Values)
|
||||
{
|
||||
if ((property.PropertyType?.SupportsVariation(pvalue.Culture, pvalue.Segment, true) ?? false) &&
|
||||
(culture == "*" || (pvalue.Culture?.InvariantEquals(culture) ?? false)))
|
||||
if (((property.PropertyType?.SupportsVariation(pvalue.Culture, pvalue.Segment, true) ?? false) &&
|
||||
(culture == "*" || (pvalue.Culture?.InvariantEquals(culture) ?? false))) ||
|
||||
property.PropertyType?.Variations == ContentVariation.Nothing)
|
||||
{
|
||||
property.SetValue(null, pvalue.Culture, pvalue.Segment);
|
||||
}
|
||||
@@ -193,7 +195,8 @@ public static class ContentRepositoryExtensions
|
||||
IPropertyCollection otherProperties = other.Properties;
|
||||
foreach (IProperty otherProperty in otherProperties)
|
||||
{
|
||||
if (!otherProperty?.PropertyType?.SupportsVariation(culture, "*", true) ?? true)
|
||||
if ((!otherProperty?.PropertyType?.SupportsVariation(culture, "*", true) ?? true) &&
|
||||
!(otherProperty?.PropertyType?.Variations == ContentVariation.Nothing))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -203,8 +206,9 @@ public static class ContentRepositoryExtensions
|
||||
{
|
||||
foreach (IPropertyValue pvalue in otherProperty.Values)
|
||||
{
|
||||
if (otherProperty.PropertyType.SupportsVariation(pvalue.Culture, pvalue.Segment, true) &&
|
||||
(culture == "*" || (pvalue.Culture?.InvariantEquals(culture) ?? false)))
|
||||
if (((otherProperty?.PropertyType.SupportsVariation(pvalue.Culture, pvalue.Segment, true) ?? false) &&
|
||||
(culture == "*" ||(pvalue.Culture?.InvariantEquals(culture) ?? false))) ||
|
||||
otherProperty?.PropertyType?.Variations == ContentVariation.Nothing)
|
||||
{
|
||||
var value = published ? pvalue.PublishedValue : pvalue.EditedValue;
|
||||
content.SetValue(alias, value, pvalue.Culture, pvalue.Segment);
|
||||
|
||||
@@ -10,12 +10,12 @@ public enum RefreshMethodType
|
||||
// that enum should get merged somehow with MessageType and renamed somehow
|
||||
// but at the moment it is exposed in CacheRefresher webservice through RefreshInstruction
|
||||
// so for the time being we keep it as-is for backward compatibility reasons
|
||||
RefreshAll,
|
||||
RefreshByGuid,
|
||||
RefreshById,
|
||||
RefreshByIds,
|
||||
RefreshByJson,
|
||||
RemoveById,
|
||||
RefreshAll = 0,
|
||||
RefreshByGuid = 1,
|
||||
RefreshById = 2,
|
||||
RefreshByIds = 3,
|
||||
RefreshByJson = 4,
|
||||
RemoveById = 5,
|
||||
|
||||
// would adding values break backward compatibility?
|
||||
// RemoveByIds
|
||||
|
||||
@@ -62,6 +62,7 @@ public class UmbracoPlan : MigrationPlan
|
||||
To<V_13_0_0.ChangeWebhookRequestObjectColumnToNvarcharMax>("{F74CDA0C-7AAA-48C8-94C6-C6EC3C06F599}");
|
||||
To<V_13_0_0.ChangeWebhookUrlColumnsToNvarcharMax>("{21C42760-5109-4C03-AB4F-7EA53577D1F5}");
|
||||
To<V_13_0_0.AddExceptionOccured>("{6158F3A3-4902-4201-835E-1ED7F810B2D8}");
|
||||
To<V_13_3_0.AlignUpgradedDatabase>("{985AF2BA-69D3-4DBA-95E0-AD3FA7459FA7}");
|
||||
|
||||
// To 14.0.0
|
||||
To<V_14_0_0.AddPropertyEditorUiAliasColumn>("{419827A0-4FCE-464B-A8F3-247C6092AF55}");
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
using NPoco;
|
||||
using Umbraco.Cms.Infrastructure.Persistence;
|
||||
using Umbraco.Cms.Infrastructure.Persistence.Dtos;
|
||||
using ColumnInfo = Umbraco.Cms.Infrastructure.Persistence.SqlSyntax.ColumnInfo;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_13_3_0;
|
||||
|
||||
/// <summary>
|
||||
/// We see some differences between an updated database and a fresh one,
|
||||
/// the purpose of this migration is to align the two.
|
||||
/// </summary>
|
||||
public class AlignUpgradedDatabase : MigrationBase
|
||||
{
|
||||
public AlignUpgradedDatabase(IMigrationContext context)
|
||||
: base(context)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Migrate()
|
||||
{
|
||||
// We ignore SQLite since it's considered a development DB
|
||||
if (DatabaseType == DatabaseType.SQLite)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ColumnInfo[] columns = SqlSyntax.GetColumnsInSchema(Context.Database).ToArray();
|
||||
Tuple<string, string, string, bool>[] indexes = SqlSyntax.GetDefinedIndexes(Database).ToArray();
|
||||
|
||||
DropCacheInstructionDefaultConstraint(columns);
|
||||
AlignContentVersionTable(columns);
|
||||
UpdateExternalLoginIndexes(indexes);
|
||||
AlignNodeTable(columns);
|
||||
MakeRelationTypeIndexUnique(indexes);
|
||||
RemoveUserGroupDefault(columns);
|
||||
MakeWebhookUrlNotNullable(columns);
|
||||
MakeWebhookLogUrlNotNullable(columns);
|
||||
}
|
||||
|
||||
private void MakeIndexUnique<TDto>(string tableName, string indexName, IEnumerable<Tuple<string, string, string, bool>> indexes)
|
||||
{
|
||||
// Let's only mess with the indexes if we have to.
|
||||
// Indexes are in format TableName, IndexName, ColumnName, IsUnique
|
||||
Tuple<string, string, string, bool>? loginProviderIndex = indexes.FirstOrDefault(x =>
|
||||
x.Item1 == tableName && x.Item2 == indexName);
|
||||
|
||||
// Item4 == IsUnique
|
||||
if (loginProviderIndex?.Item4 is false)
|
||||
{
|
||||
// The recommended way to change an index from non-unique to unique is to drop and recreate it.
|
||||
DeleteIndex<TDto>(indexName);
|
||||
CreateIndex<TDto>(indexName);
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveDefaultConstraint(string tableName, string columnName, IEnumerable<ColumnInfo> columns)
|
||||
{
|
||||
ColumnInfo? targetColumn = columns
|
||||
.FirstOrDefault(x => x.TableName == tableName && x.ColumnName == columnName);
|
||||
|
||||
if (targetColumn is null)
|
||||
{
|
||||
throw new InvalidOperationException($"Could not find {columnName} column on {tableName} table.");
|
||||
}
|
||||
|
||||
if (targetColumn.ColumnDefault is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Delete.DefaultConstraint()
|
||||
.OnTable(tableName)
|
||||
.OnColumn(columnName)
|
||||
.Do();
|
||||
}
|
||||
|
||||
private void RenameColumn(string tableName, string oldColumnName, string newColumnName, IEnumerable<ColumnInfo> columns)
|
||||
{
|
||||
ColumnInfo? targetColumn = columns
|
||||
.FirstOrDefault(x => x.TableName == tableName && x.ColumnName == oldColumnName);
|
||||
|
||||
if (targetColumn is null)
|
||||
{
|
||||
// The column was not found I.E. the column is correctly named
|
||||
return;
|
||||
}
|
||||
|
||||
Rename.Column(oldColumnName)
|
||||
.OnTable(tableName)
|
||||
.To(newColumnName)
|
||||
.Do();
|
||||
}
|
||||
|
||||
private void MakeNvarCharColumnNotNullable(string tableName, string columnName, IEnumerable<ColumnInfo> columns)
|
||||
{
|
||||
ColumnInfo? targetColumn = columns.FirstOrDefault(x => x.TableName == tableName && x.ColumnName == columnName);
|
||||
|
||||
if (targetColumn is null)
|
||||
{
|
||||
throw new InvalidOperationException($"Could not find {columnName} column in {tableName} table.");
|
||||
}
|
||||
|
||||
if (targetColumn.IsNullable is false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Alter.Table(tableName)
|
||||
.AlterColumn(columnName)
|
||||
.AsCustom("nvarchar(max)")
|
||||
.NotNullable()
|
||||
.Do();
|
||||
}
|
||||
|
||||
private void DropCacheInstructionDefaultConstraint(IEnumerable<ColumnInfo> columns)
|
||||
=> RemoveDefaultConstraint("umbracoCacheInstruction", "jsonInstruction", columns);
|
||||
|
||||
private void AlignContentVersionTable(ColumnInfo[] columns)
|
||||
{
|
||||
// We need to do this to ensure we don't try to rename the constraint if it doesn't exist.
|
||||
const string tableName = "umbracoContentVersion";
|
||||
const string columnName = "VersionDate";
|
||||
ColumnInfo? versionDateColumn = columns
|
||||
.FirstOrDefault(x => x is { TableName: tableName, ColumnName: columnName });
|
||||
|
||||
if (versionDateColumn is null)
|
||||
{
|
||||
// The column was not found I.E. the column is correctly named
|
||||
return;
|
||||
}
|
||||
|
||||
RenameColumn(tableName, columnName, "versionDate", columns);
|
||||
|
||||
// Renames the default constraint for the column,
|
||||
// apparently the content version table used to be prefixed with cms and not umbraco
|
||||
// We don't have a fluid way to rename the default constraint so we have to use raw SQL
|
||||
// This should be okay though since we are only running this migration on SQL Server
|
||||
Sql<ISqlContext> renameConstraintQuery = Database.SqlContext.Sql(
|
||||
"EXEC sp_rename N'DF_cmsContentVersion_VersionDate', N'DF_umbracoContentVersion_versionDate', N'OBJECT'");
|
||||
Database.Execute(renameConstraintQuery);
|
||||
}
|
||||
|
||||
private void UpdateExternalLoginIndexes(IEnumerable<Tuple<string, string, string, bool>> indexes)
|
||||
{
|
||||
const string userMemberOrKeyIndexName = "IX_umbracoExternalLogin_userOrMemberKey";
|
||||
|
||||
MakeIndexUnique<ExternalLoginDto>("umbracoExternalLogin", "IX_umbracoExternalLogin_LoginProvider", indexes);
|
||||
|
||||
if (IndexExists(userMemberOrKeyIndexName))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CreateIndex<ExternalLoginDto>(userMemberOrKeyIndexName);
|
||||
}
|
||||
|
||||
private void AlignNodeTable(ColumnInfo[] columns)
|
||||
{
|
||||
const string tableName = "umbracoNode";
|
||||
RenameColumn(tableName, "parentID", "parentId", columns);
|
||||
RenameColumn(tableName, "uniqueID", "uniqueId", columns);
|
||||
|
||||
const string extraIndexName = "IX_umbracoNode_ParentId";
|
||||
if (IndexExists(extraIndexName))
|
||||
{
|
||||
DeleteIndex<NodeDto>(extraIndexName);
|
||||
}
|
||||
}
|
||||
|
||||
private void MakeRelationTypeIndexUnique(Tuple<string, string, string, bool>[] indexes)
|
||||
=> MakeIndexUnique<RelationTypeDto>("umbracoRelationType", "IX_umbracoRelationType_alias", indexes);
|
||||
|
||||
private void RemoveUserGroupDefault(ColumnInfo[] columns)
|
||||
=> RemoveDefaultConstraint("umbracoUserGroup", "hasAccessToAllLanguages", columns);
|
||||
|
||||
private void MakeWebhookUrlNotNullable(ColumnInfo[] columns)
|
||||
=> MakeNvarCharColumnNotNullable("umbracoWebhook", "url", columns);
|
||||
|
||||
private void MakeWebhookLogUrlNotNullable(ColumnInfo[] columns)
|
||||
=> MakeNvarCharColumnNotNullable("umbracoWebhookLog", "url", columns);
|
||||
}
|
||||
Reference in New Issue
Block a user