Fixes: U4-6099 cmsLanguageText.languageId needs to be a foreign key to the umbracoLanguage table
This commit is contained in:
@@ -27,6 +27,7 @@ namespace Umbraco.Core
|
||||
/// <summary>
|
||||
/// The root id for all top level dictionary items
|
||||
/// </summary>
|
||||
[Obsolete("There is no dictionary root item id anymore, it is simply null")]
|
||||
public const string DictionaryItemRootId = "41c7638d-f529-4bff-853e-59a0c2fb1bde";
|
||||
}
|
||||
|
||||
|
||||
@@ -14,22 +14,22 @@ namespace Umbraco.Core.Models
|
||||
[DataContract(IsReference = true)]
|
||||
public class DictionaryItem : Entity, IDictionaryItem
|
||||
{
|
||||
private Guid _parentId;
|
||||
private Guid? _parentId;
|
||||
private string _itemKey;
|
||||
private IEnumerable<IDictionaryTranslation> _translations;
|
||||
|
||||
public DictionaryItem(string itemKey)
|
||||
: this(new Guid(Constants.Conventions.Localization.DictionaryItemRootId), itemKey)
|
||||
: this(null, itemKey)
|
||||
{}
|
||||
|
||||
public DictionaryItem(Guid parentId, string itemKey)
|
||||
public DictionaryItem(Guid? parentId, string itemKey)
|
||||
{
|
||||
_parentId = parentId;
|
||||
_itemKey = itemKey;
|
||||
_translations = new List<IDictionaryTranslation>();
|
||||
}
|
||||
|
||||
private static readonly PropertyInfo ParentIdSelector = ExpressionHelper.GetPropertyInfo<DictionaryItem, Guid>(x => x.ParentId);
|
||||
private static readonly PropertyInfo ParentIdSelector = ExpressionHelper.GetPropertyInfo<DictionaryItem, Guid?>(x => x.ParentId);
|
||||
private static readonly PropertyInfo ItemKeySelector = ExpressionHelper.GetPropertyInfo<DictionaryItem, string>(x => x.ItemKey);
|
||||
private static readonly PropertyInfo TranslationsSelector = ExpressionHelper.GetPropertyInfo<DictionaryItem, IEnumerable<IDictionaryTranslation>>(x => x.Translations);
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace Umbraco.Core.Models
|
||||
/// Gets or Sets the Parent Id of the Dictionary Item
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public Guid ParentId
|
||||
public Guid? ParentId
|
||||
{
|
||||
get { return _parentId; }
|
||||
set
|
||||
@@ -95,11 +95,7 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
base.AddingEntity();
|
||||
|
||||
Key = Guid.NewGuid();
|
||||
|
||||
//If ParentId is not set we should default to the root parent id
|
||||
if(ParentId == Guid.Empty)
|
||||
_parentId = new Guid(Constants.Conventions.Localization.DictionaryItemRootId);
|
||||
Key = Guid.NewGuid();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Umbraco.Core.Models
|
||||
/// Gets or Sets the Parent Id of the Dictionary Item
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
Guid ParentId { get; set; }
|
||||
Guid? ParentId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Key for the Dictionary Item
|
||||
|
||||
@@ -19,7 +19,9 @@ namespace Umbraco.Core.Models.Rdbms
|
||||
public Guid UniqueId { get; set; }
|
||||
|
||||
[Column("parent")]
|
||||
public Guid Parent { get; set; }
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
[ForeignKey(typeof(DictionaryDto), Column = "id")]
|
||||
public Guid? Parent { get; set; }
|
||||
|
||||
[Column("key")]
|
||||
[Length(1000)]
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Umbraco.Core.Models.Rdbms
|
||||
public int PrimaryKey { get; set; }
|
||||
|
||||
[Column("languageId")]
|
||||
[ForeignKey(typeof(LanguageDto), Column = "id")]
|
||||
public int LanguageId { get; set; }
|
||||
|
||||
[Column("UniqueId")]
|
||||
|
||||
@@ -151,6 +151,13 @@ namespace Umbraco.Core.Persistence
|
||||
_db.Update<UserDto>("SET id = @IdAfter WHERE id = @IdBefore AND userLogin = @Login", new { IdAfter = 0, IdBefore = 1, Login = "admin" });
|
||||
}
|
||||
|
||||
//Loop through index statements and execute sql
|
||||
foreach (var sql in indexSql)
|
||||
{
|
||||
int createdIndex = _db.Execute(new Sql(sql));
|
||||
_logger.Info<Database>(string.Format("Create Index sql {0}:\n {1}", createdIndex, sql));
|
||||
}
|
||||
|
||||
//Loop through foreignkey statements and execute sql
|
||||
foreach (var sql in foreignSql)
|
||||
{
|
||||
@@ -158,12 +165,7 @@ namespace Umbraco.Core.Persistence
|
||||
_logger.Info<Database>(string.Format("Create Foreign Key sql {0}:\n {1}", createdFk, sql));
|
||||
}
|
||||
|
||||
//Loop through index statements and execute sql
|
||||
foreach (var sql in indexSql)
|
||||
{
|
||||
int createdIndex = _db.Execute(new Sql(sql));
|
||||
_logger.Info<Database>(string.Format("Create Index sql {0}:\n {1}", createdIndex, sql));
|
||||
}
|
||||
|
||||
|
||||
transaction.Complete();
|
||||
}
|
||||
|
||||
@@ -48,8 +48,8 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
|
||||
{7, typeof (DataTypeDto)},
|
||||
{8, typeof (DataTypePreValueDto)},
|
||||
{9, typeof (DictionaryDto)},
|
||||
{10, typeof (LanguageTextDto)},
|
||||
{11, typeof (LanguageDto)},
|
||||
{10, typeof (LanguageDto)},
|
||||
{11, typeof (LanguageTextDto)},
|
||||
{12, typeof (DomainDto)},
|
||||
{13, typeof (LogDto)},
|
||||
{14, typeof (MacroDto)},
|
||||
|
||||
@@ -53,5 +53,32 @@ namespace Umbraco.Core.Persistence.Migrations
|
||||
/// to ensure they are not executed twice.
|
||||
/// </summary>
|
||||
internal string Name { get; set; }
|
||||
|
||||
protected string GetQuotedValue(object val)
|
||||
{
|
||||
if (val == null) return "NULL";
|
||||
|
||||
var type = val.GetType();
|
||||
|
||||
switch (Type.GetTypeCode(type))
|
||||
{
|
||||
case TypeCode.Boolean:
|
||||
return ((bool)val) ? "1" : "0";
|
||||
case TypeCode.Single:
|
||||
case TypeCode.Double:
|
||||
case TypeCode.Decimal:
|
||||
case TypeCode.SByte:
|
||||
case TypeCode.Int16:
|
||||
case TypeCode.Int32:
|
||||
case TypeCode.Int64:
|
||||
case TypeCode.Byte:
|
||||
case TypeCode.UInt16:
|
||||
case TypeCode.UInt32:
|
||||
case TypeCode.UInt64:
|
||||
return val.ToString();
|
||||
default:
|
||||
return SqlSyntaxContext.SqlSyntaxProvider.GetQuotedValue(val.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -44,7 +44,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete.Expressions
|
||||
whereClauses.Add(string.Format("{0} {1} {2}",
|
||||
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName(item.Key),
|
||||
item.Value == null ? "IS" : "=",
|
||||
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedValue(item.Value.ToString())));
|
||||
GetQuotedValue(item.Value)));
|
||||
}
|
||||
|
||||
deleteItems.Add(string.Format(SqlSyntaxContext.SqlSyntaxProvider.DeleteData,
|
||||
|
||||
@@ -60,29 +60,6 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Insert.Expressions
|
||||
return string.Join(",", insertItems);
|
||||
}
|
||||
|
||||
private string GetQuotedValue(object val)
|
||||
{
|
||||
var type = val.GetType();
|
||||
|
||||
switch (Type.GetTypeCode(type))
|
||||
{
|
||||
case TypeCode.Boolean:
|
||||
return ((bool) val) ? "1" : "0";
|
||||
case TypeCode.Single:
|
||||
case TypeCode.Double:
|
||||
case TypeCode.Decimal:
|
||||
case TypeCode.SByte:
|
||||
case TypeCode.Int16:
|
||||
case TypeCode.Int32:
|
||||
case TypeCode.Int64:
|
||||
case TypeCode.Byte:
|
||||
case TypeCode.UInt16:
|
||||
case TypeCode.UInt32:
|
||||
case TypeCode.UInt64:
|
||||
return val.ToString();
|
||||
default:
|
||||
return SqlSyntaxContext.SqlSyntaxProvider.GetQuotedValue(val.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Update.Expressions
|
||||
{
|
||||
updateItems.Add(string.Format("{0} = {1}",
|
||||
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName(item.Key),
|
||||
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedValue(item.Value.ToString())));
|
||||
GetQuotedValue(item.Value)));
|
||||
}
|
||||
|
||||
if (IsAllRows)
|
||||
@@ -46,7 +46,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Update.Expressions
|
||||
whereClauses.Add(string.Format("{0} {1} {2}",
|
||||
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName(item.Key),
|
||||
item.Value == null ? "IS" : "=",
|
||||
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedValue(item.Value.ToString())));
|
||||
GetQuotedValue(item.Value)));
|
||||
}
|
||||
}
|
||||
return string.Format(SqlSyntaxContext.SqlSyntaxProvider.UpdateData,
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZero
|
||||
{
|
||||
[Migration("7.3.0", 14, GlobalSettings.UmbracoMigrationName)]
|
||||
public class AddForeignKeysForLanguageAndDictionaryTables : MigrationBase
|
||||
{
|
||||
public AddForeignKeysForLanguageAndDictionaryTables(ISqlSyntaxProvider sqlSyntax, ILogger logger)
|
||||
: base(sqlSyntax, logger)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Up()
|
||||
{
|
||||
var constraints = SqlSyntax.GetConstraintsPerColumn(Context.Database).Distinct().ToArray();
|
||||
|
||||
//if the FK doesn't exist
|
||||
if (constraints.Any(x => x.Item1.InvariantEquals("cmsLanguageText") && x.Item2.InvariantEquals("umbracoLanguage") && x.Item3.InvariantEquals("FK_cmsLanguageText_umbracoLanguage_id")) == false)
|
||||
{
|
||||
//Somehow, a language text item might end up with a language Id of zero or one that no longer exists
|
||||
//before we add the foreign key
|
||||
foreach (var pk in Context.Database.Query<int>(
|
||||
"SELECT cmsLanguageText.pk FROM cmsLanguageText WHERE cmsLanguageText.languageId NOT IN (SELECT umbracoLanguage.id FROM umbracoLanguage)"))
|
||||
{
|
||||
Delete.FromTable("cmsLanguageText").Row(new { pk = pk });
|
||||
}
|
||||
|
||||
//now we need to create a foreign key
|
||||
Create.ForeignKey("FK_cmsLanguageText_umbracoLanguage_id").FromTable("cmsLanguageText").ForeignColumn("languageId")
|
||||
.ToTable("umbracoLanguage").PrimaryColumn("id").OnDeleteOrUpdate(Rule.None);
|
||||
|
||||
Alter.Table("cmsDictionary").AlterColumn("parent").AsGuid().Nullable();
|
||||
|
||||
//set the parent to null if it equals the default dictionary item root id
|
||||
foreach (var pk in Context.Database.Query<int>("SELECT pk FROM cmsDictionary WHERE parent NOT IN (SELECT id FROM cmsDictionary)"))
|
||||
{
|
||||
Update.Table("cmsDictionary").Set(new { parent = (Guid?)null }).Where(new { pk = pk });
|
||||
}
|
||||
|
||||
Create.ForeignKey("FK_cmsDictionary_cmsDictionary_id").FromTable("cmsDictionary").ForeignColumn("parent")
|
||||
.ToTable("cmsDictionary").PrimaryColumn("id").OnDeleteOrUpdate(Rule.None);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public override void Down()
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -103,12 +103,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
return new List<string>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Top Level Parent Guid Id
|
||||
/// </summary>
|
||||
protected override Guid NodeObjectTypeId
|
||||
{
|
||||
get { return new Guid(Constants.Conventions.Localization.DictionaryItemRootId); }
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -18,7 +18,6 @@ namespace Umbraco.Core.Services
|
||||
/// </summary>
|
||||
public class LocalizationService : RepositoryService, ILocalizationService
|
||||
{
|
||||
private static readonly Guid RootParentId = new Guid(Constants.Conventions.Localization.DictionaryItemRootId);
|
||||
|
||||
[Obsolete("Use the constructors that specify all dependencies instead")]
|
||||
public LocalizationService()
|
||||
@@ -93,7 +92,7 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
}
|
||||
|
||||
var item = new DictionaryItem(parentId.HasValue ? parentId.Value : RootParentId, key);
|
||||
var item = new DictionaryItem(parentId, key);
|
||||
|
||||
if (defaultValue.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
@@ -188,7 +187,7 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
using (var repository = RepositoryFactory.CreateDictionaryRepository(UowProvider.GetUnitOfWork()))
|
||||
{
|
||||
var query = Query<IDictionaryItem>.Builder.Where(x => x.ParentId == RootParentId);
|
||||
var query = Query<IDictionaryItem>.Builder.Where(x => x.ParentId == null);
|
||||
var items = repository.GetByQuery(query);
|
||||
|
||||
return items;
|
||||
|
||||
@@ -381,6 +381,7 @@
|
||||
<Compile Include="Persistence\Mappers\DomainMapper.cs" />
|
||||
<Compile Include="Persistence\Mappers\MigrationEntryMapper.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenThreeZero\AddExternalLoginsTable.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenThreeZero\AddForeignKeysForLanguageAndDictionaryTables.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenThreeZero\AddMigrationTable.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenThreeZero\AddPublicAccessTables.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenThreeZero\AddUniqueIdPropertyTypeColumn.cs" />
|
||||
|
||||
@@ -258,6 +258,7 @@ namespace Umbraco.Tests.Persistence
|
||||
using (Transaction transaction = Database.GetTransaction())
|
||||
{
|
||||
DatabaseSchemaHelper.CreateTable<DictionaryDto>();
|
||||
DatabaseSchemaHelper.CreateTable<LanguageDto>();
|
||||
DatabaseSchemaHelper.CreateTable<LanguageTextDto>();
|
||||
|
||||
//transaction.Complete();
|
||||
|
||||
@@ -179,7 +179,7 @@ namespace Umbraco.Tests.Services
|
||||
|
||||
Assert.Greater(item.Id, 0);
|
||||
Assert.IsTrue(item.HasIdentity);
|
||||
Assert.AreEqual(new Guid(Constants.Conventions.Localization.DictionaryItemRootId), item.ParentId);
|
||||
Assert.IsFalse(item.ParentId.HasValue);
|
||||
Assert.AreEqual("Testing123", item.ItemKey);
|
||||
Assert.AreEqual(1, item.Translations.Count());
|
||||
}
|
||||
@@ -197,7 +197,7 @@ namespace Umbraco.Tests.Services
|
||||
Assert.IsNotNull(item);
|
||||
Assert.Greater(item.Id, 0);
|
||||
Assert.IsTrue(item.HasIdentity);
|
||||
Assert.AreEqual(new Guid(Constants.Conventions.Localization.DictionaryItemRootId), item.ParentId);
|
||||
Assert.IsFalse(item.ParentId.HasValue);
|
||||
Assert.AreEqual("Testing12345", item.ItemKey);
|
||||
var allLangs = ServiceContext.LocalizationService.GetAllLanguages();
|
||||
Assert.Greater(allLangs.Count(), 0);
|
||||
|
||||
@@ -93,8 +93,8 @@ namespace umbraco.cms.businesslogic
|
||||
|
||||
[Obsolete("This is no longer used and will be removed from the codebase in future versions")]
|
||||
public bool IsTopMostItem()
|
||||
{
|
||||
return _dictionaryItem.ParentId == new Guid(Constants.Conventions.Localization.DictionaryItemRootId);
|
||||
{
|
||||
return _dictionaryItem.ParentId.HasValue == false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -105,9 +105,9 @@ namespace umbraco.cms.businesslogic
|
||||
get
|
||||
{
|
||||
//EnsureCache();
|
||||
if (_parent == null)
|
||||
if (_parent == null && _dictionaryItem.ParentId.HasValue)
|
||||
{
|
||||
var p = ApplicationContext.Current.Services.LocalizationService.GetDictionaryItemById(_dictionaryItem.ParentId);
|
||||
var p = ApplicationContext.Current.Services.LocalizationService.GetDictionaryItemById(_dictionaryItem.ParentId.Value);
|
||||
|
||||
if (p == null)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user