diff --git a/src/SolutionInfo.cs b/src/SolutionInfo.cs index f4da17e45a..4277feeef2 100644 --- a/src/SolutionInfo.cs +++ b/src/SolutionInfo.cs @@ -12,4 +12,4 @@ using System.Resources; [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyFileVersion("7.6.0")] -[assembly: AssemblyInformationalVersion("7.6.0-alpha033")] \ No newline at end of file +[assembly: AssemblyInformationalVersion("7.6.0-alpha034")] \ No newline at end of file diff --git a/src/Umbraco.Core/Configuration/UmbracoVersion.cs b/src/Umbraco.Core/Configuration/UmbracoVersion.cs index fe45c0117d..61393a4c7c 100644 --- a/src/Umbraco.Core/Configuration/UmbracoVersion.cs +++ b/src/Umbraco.Core/Configuration/UmbracoVersion.cs @@ -24,7 +24,7 @@ namespace Umbraco.Core.Configuration /// Gets the version comment (like beta or RC). /// /// The version comment. - public static string CurrentComment { get { return "alpha033"; } } + public static string CurrentComment { get { return "alpha034"; } } // Get the version of the umbraco.dll by looking at a class in that dll // Had to do it like this due to medium trust issues, see: http://haacked.com/archive/2010/11/04/assembly-location-and-medium-trust.aspx diff --git a/src/Umbraco.Core/Models/IMacroProperty.cs b/src/Umbraco.Core/Models/IMacroProperty.cs index a6c1d9ca5f..8726f51317 100644 --- a/src/Umbraco.Core/Models/IMacroProperty.cs +++ b/src/Umbraco.Core/Models/IMacroProperty.cs @@ -1,3 +1,4 @@ +using System; using System.Runtime.Serialization; using Umbraco.Core.Models.EntityBase; @@ -11,6 +12,9 @@ namespace Umbraco.Core.Models [DataMember] int Id { get; set; } + [DataMember] + Guid Key { get; set; } + /// /// Gets or sets the Alias of the Property /// diff --git a/src/Umbraco.Core/Models/Macro.cs b/src/Umbraco.Core/Models/Macro.cs index ef5479c316..e32e5b5ab9 100644 --- a/src/Umbraco.Core/Models/Macro.cs +++ b/src/Umbraco.Core/Models/Macro.cs @@ -1,13 +1,10 @@ using System; using System.Collections.Generic; -using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; using System.Linq; using System.Reflection; using System.Runtime.Serialization; -using System.Text.RegularExpressions; -using Umbraco.Core.IO; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Strings; diff --git a/src/Umbraco.Core/Models/MacroProperty.cs b/src/Umbraco.Core/Models/MacroProperty.cs index 0f29c18881..605160c124 100644 --- a/src/Umbraco.Core/Models/MacroProperty.cs +++ b/src/Umbraco.Core/Models/MacroProperty.cs @@ -15,7 +15,7 @@ namespace Umbraco.Core.Models { public MacroProperty() { - + _key = Guid.NewGuid(); } /// @@ -30,6 +30,7 @@ namespace Umbraco.Core.Models _alias = alias; _name = name; _sortOrder = sortOrder; + _key = Guid.NewGuid(); //try to get the new mapped parameter editor var mapped = LegacyParameterEditorAliasConverter.GetNewAliasFromLegacyAlias(editorAlias, false); @@ -55,6 +56,7 @@ namespace Umbraco.Core.Models _alias = alias; _name = name; _sortOrder = sortOrder; + _key = Guid.NewGuid(); //try to get the new mapped parameter editor var mapped = LegacyParameterEditorAliasConverter.GetNewAliasFromLegacyAlias(editorAlias, false); @@ -66,6 +68,7 @@ namespace Umbraco.Core.Models _editorAlias = editorAlias; } + private Guid _key; private string _alias; private string _name; private int _sortOrder; @@ -76,6 +79,7 @@ namespace Umbraco.Core.Models private class PropertySelectors { + public readonly PropertyInfo KeySelector = ExpressionHelper.GetPropertyInfo(x => x.Key); public readonly PropertyInfo AliasSelector = ExpressionHelper.GetPropertyInfo(x => x.Alias); public readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo(x => x.Name); public readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo(x => x.SortOrder); @@ -83,6 +87,16 @@ namespace Umbraco.Core.Models public readonly PropertyInfo PropertyTypeSelector = ExpressionHelper.GetPropertyInfo(x => x.EditorAlias); } + /// + /// Gets or sets the Key of the Property + /// + [DataMember] + public Guid Key + { + get { return _key; } + set { SetPropertyValueAndDetectChanges(value, ref _key, Ps.Value.KeySelector); } + } + /// /// Gets or sets the Alias of the Property /// diff --git a/src/Umbraco.Core/Models/Rdbms/MacroDto.cs b/src/Umbraco.Core/Models/Rdbms/MacroDto.cs index 855b4d1f93..aea65cc268 100644 --- a/src/Umbraco.Core/Models/Rdbms/MacroDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/MacroDto.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; @@ -13,6 +14,10 @@ namespace Umbraco.Core.Models.Rdbms [PrimaryKeyColumn] public int Id { get; set; } + [Column("uniqueId")] + [Index(IndexTypes.UniqueNonClustered, Name = "IX_cmsMacroUniqueId")] + public Guid UniqueId { get; set; } + [Column("macroUseInEditor")] [Constraint(Default = "0")] public bool UseInEditor { get; set; } diff --git a/src/Umbraco.Core/Models/Rdbms/MacroPropertyDto.cs b/src/Umbraco.Core/Models/Rdbms/MacroPropertyDto.cs index e2efddc829..8e6148e859 100644 --- a/src/Umbraco.Core/Models/Rdbms/MacroPropertyDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/MacroPropertyDto.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Persistence; +using System; +using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; namespace Umbraco.Core.Models.Rdbms @@ -11,7 +12,11 @@ namespace Umbraco.Core.Models.Rdbms [Column("id")] [PrimaryKeyColumn] public int Id { get; set; } - + + [Column("uniqueId")] + [Index(IndexTypes.UniqueNonClustered, Name = "IX_cmsMacroUniqueId")] + public Guid UniqueId { get; set; } + [Column("editorAlias")] public string EditorAlias { get; set; } diff --git a/src/Umbraco.Core/Persistence/Factories/MacroFactory.cs b/src/Umbraco.Core/Persistence/Factories/MacroFactory.cs index 2ec20b08eb..6a59ec1d58 100644 --- a/src/Umbraco.Core/Persistence/Factories/MacroFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/MacroFactory.cs @@ -7,12 +7,10 @@ namespace Umbraco.Core.Persistence.Factories { internal class MacroFactory { - #region Implementation of IEntityFactory - public IMacro BuildEntity(MacroDto dto) { var model = new Macro(dto.Id, dto.UseInEditor, dto.RefreshRate, dto.Alias, dto.Name, dto.ScriptType, dto.ScriptAssembly, dto.Xslt, dto.CacheByPage, dto.CachePersonalized, dto.DontRender, dto.Python); - + model.Key = dto.UniqueId; try { @@ -20,7 +18,7 @@ namespace Umbraco.Core.Persistence.Factories foreach (var p in dto.MacroPropertyDtos) { - model.Properties.Add(new MacroProperty(p.Id, p.Alias, p.Name, p.SortOrder, p.EditorAlias)); + model.Properties.Add(new MacroProperty(p.Id, p.Alias, p.Name, p.SortOrder, p.EditorAlias) { Key = p.UniqueId }); } //on initial construction we don't want to have dirty properties tracked @@ -38,6 +36,7 @@ namespace Umbraco.Core.Persistence.Factories { var dto = new MacroDto() { + UniqueId = entity.Key, Alias = entity.Alias, CacheByPage = entity.CacheByPage, CachePersonalized = entity.CacheByMember, @@ -58,8 +57,6 @@ namespace Umbraco.Core.Persistence.Factories return dto; } - #endregion - private List BuildPropertyDtos(IMacro entity) { var list = new List(); @@ -67,6 +64,7 @@ namespace Umbraco.Core.Persistence.Factories { var text = new MacroPropertyDto { + UniqueId = p.Key, Alias = p.Alias, Name = p.Name, Macro = entity.Id, diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/AddMacroUniqueIdColumn.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/AddMacroUniqueIdColumn.cs new file mode 100644 index 0000000000..3fc7d718e4 --- /dev/null +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/AddMacroUniqueIdColumn.cs @@ -0,0 +1,73 @@ +using System; +using System.Linq; +using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; +using Umbraco.Core.Persistence.SqlSyntax; + +namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero +{ + [Migration("7.6.0", 0, GlobalSettings.UmbracoMigrationName)] + public class AddMacroUniqueIdColumn : MigrationBase + { + public AddMacroUniqueIdColumn(ISqlSyntaxProvider sqlSyntax, ILogger logger) + : base(sqlSyntax, logger) + { } + + public override void Up() + { + var columns = SqlSyntax.GetColumnsInSchema(Context.Database).ToArray(); + + if (columns.Any(x => x.TableName.InvariantEquals("cmsMacro") && x.ColumnName.InvariantEquals("uniqueId")) == false) + { + Create.Column("uniqueId").OnTable("cmsMacro").AsGuid().Nullable(); + Execute.Code(UpdateMacroGuids); + Alter.Column("uniqueId").OnTable("cmsMacro").AsGuid().NotNullable(); + Create.Index("IX_cmsMacroUniqueId").OnTable("cmsMacro").OnColumn("uniqueId") + .Ascending() + .WithOptions().NonClustered() + .WithOptions().Unique(); + + } + + if (columns.Any(x => x.TableName.InvariantEquals("cmsMacroProperty") && x.ColumnName.InvariantEquals("uniqueId")) == false) + { + Create.Column("uniqueId").OnTable("cmsMacroProperty").AsGuid().Nullable(); + Execute.Code(UpdateMacroPropertyGuids); + Alter.Column("uniqueId").OnTable("cmsMacroProperty").AsGuid().NotNullable(); + Create.Index("IX_cmsMacroPropertyUniqueId").OnTable("cmsMacroProperty").OnColumn("uniqueId") + .Ascending() + .WithOptions().NonClustered() + .WithOptions().Unique(); + } + } + + private static string UpdateMacroGuids(Database database) + { + var updates = database.Query("SELECT id, macroAlias FROM cmsMacro") + .Select(macro => Tuple.Create((int) macro.id, ((string) macro.macroAlias).ToGuid())) + .ToList(); + + foreach (var update in updates) + database.Execute("UPDATE cmsMacro set uniqueId=@guid WHERE id=@id", new { guid = update.Item2, id = update.Item1 }); + + return string.Empty; + } + + private static string UpdateMacroPropertyGuids(Database database) + { + var updates = database.Query("SELECT id, macroPropertyAlias FROM cmsMacroProperty") + .Select(macro => Tuple.Create((int) macro.id, ((string) macro.macroPropertyAlias).ToGuid())) + .ToList(); + + foreach (var update in updates) + database.Execute("UPDATE cmsMacroProperty set uniqueId=@guid WHERE id=@id", new { guid = update.Item2, id = update.Item1 }); + + return string.Empty; + } + + public override void Down() + { + throw new NotImplementedException(); + } + } +} diff --git a/src/Umbraco.Core/Persistence/Relators/MacroPropertyRelator.cs b/src/Umbraco.Core/Persistence/Relators/MacroPropertyRelator.cs index 2f457edfd8..fb563fa25c 100644 --- a/src/Umbraco.Core/Persistence/Relators/MacroPropertyRelator.cs +++ b/src/Umbraco.Core/Persistence/Relators/MacroPropertyRelator.cs @@ -3,48 +3,6 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Relators { - //internal class TaskUserRelator - //{ - // internal TaskDto Current; - - // internal TaskDto Map(TaskDto a, UserDto p) - // { - // // Terminating call. Since we can return null from this function - // // we need to be ready for PetaPoco to callback later with null - // // parameters - // if (a == null) - // return Current; - - // // Is this the same TaskDto as the current one we're processing - // if (Current != null && Current.Id == a.Id) - // { - // // Yes, set the user - // Current.MacroPropertyDtos.Add(p); - - // // Return null to indicate we're not done with this Macro yet - // return null; - // } - - // // This is a different Macro to the current one, or this is the - // // first time through and we don't have one yet - - // // Save the current Macro - // var prev = Current; - - // // Setup the new current Macro - // Current = a; - // Current.MacroPropertyDtos = new List(); - // //this can be null since we are doing a left join - // if (p.Alias != null) - // { - // Current.MacroPropertyDtos.Add(p); - // } - - // // Return the now populated previous Macro (or null if first time through) - // return prev; - // } - //} - internal class MacroPropertyRelator { internal MacroDto Current; diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IMacroRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IMacroRepository.cs index 496012ef10..6600d528ad 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IMacroRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IMacroRepository.cs @@ -1,9 +1,10 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using Umbraco.Core.Models; namespace Umbraco.Core.Persistence.Repositories { - internal interface IMacroRepository : IRepositoryQueryable + internal interface IMacroRepository : IRepositoryQueryable, IReadRepository { //IEnumerable GetAll(params string[] aliases); diff --git a/src/Umbraco.Core/Persistence/Repositories/MacroRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MacroRepository.cs index 4d21059758..a295989aa9 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MacroRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MacroRepository.cs @@ -26,7 +26,17 @@ namespace Umbraco.Core.Persistence.Repositories { var sql = GetBaseQuery(false); sql.Where(GetBaseWhereClause(), new { Id = id }); + return GetBySql(sql); + } + public IMacro Get(Guid id) + { + var sql = GetBaseQuery().Where("uniqueId=@id", new[] { id }); + return GetBySql(sql); + } + + private IMacro GetBySql(Sql sql) + { var macroDto = Database.Fetch(new MacroPropertyRelator().Map, sql).FirstOrDefault(); if (macroDto == null) return null; @@ -41,26 +51,26 @@ namespace Umbraco.Core.Persistence.Repositories return entity; } - protected override IEnumerable PerformGetAll(params int[] ids) + public IEnumerable GetAll(params Guid[] ids) { - if (ids.Any()) - { - return PerformGetAllOnIds(ids); - } - - var sql = GetBaseQuery(false); - - return ConvertFromDtos(Database.Fetch(new MacroPropertyRelator().Map, sql)) - .ToArray();// we don't want to re-iterate again! + return ids.Length > 0 ? ids.Select(Get) : GetAllAll(); } - private IEnumerable PerformGetAllOnIds(params int[] ids) + public bool Exists(Guid id) { - if (ids.Any() == false) yield break; - foreach (var id in ids) - { - yield return Get(id); - } + return Get(id) != null; + } + + protected override IEnumerable PerformGetAll(params int[] ids) + { + return ids.Length > 0 ? ids.Select(Get) : GetAllAll(); + } + + private IEnumerable GetAllAll() + { + var sql = GetBaseQuery(false); + return ConvertFromDtos(Database.Fetch(new MacroPropertyRelator().Map, sql)) + .ToArray();// we don't want to re-iterate again! } private IEnumerable ConvertFromDtos(IEnumerable dtos) diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 12e3c336da..8ad7cbc744 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -453,6 +453,7 @@ + diff --git a/src/umbraco.cms/businesslogic/macro/Macro.cs b/src/umbraco.cms/businesslogic/macro/Macro.cs index 0b043a90a3..0ce2c45c6b 100644 --- a/src/umbraco.cms/businesslogic/macro/Macro.cs +++ b/src/umbraco.cms/businesslogic/macro/Macro.cs @@ -48,6 +48,14 @@ namespace umbraco.cms.businesslogic.macro { get { return MacroEntity.Id; } } + + /// + /// key + /// + public Guid Key + { + get { return MacroEntity.Key; } + } /// /// If set to true, the macro can be inserted on documents using the richtexteditor. @@ -178,6 +186,7 @@ namespace umbraco.cms.businesslogic.macro { return MacroEntity.Properties.Select(x => new MacroProperty { + Key = x.Key, Alias = x.Alias, Name = x.Name, SortOrder = x.SortOrder, diff --git a/src/umbraco.cms/businesslogic/macro/MacroProperty.cs b/src/umbraco.cms/businesslogic/macro/MacroProperty.cs index ff3a58d46a..0944324275 100644 --- a/src/umbraco.cms/businesslogic/macro/MacroProperty.cs +++ b/src/umbraco.cms/businesslogic/macro/MacroProperty.cs @@ -36,6 +36,7 @@ namespace umbraco.cms.businesslogic.macro /// public MacroProperty() { + Key = Guid.NewGuid(); } /// @@ -75,6 +76,11 @@ namespace umbraco.cms.businesslogic.macro /// The id. public int Id { get; private set; } + /// + /// Gets the key. + /// + public Guid Key { get; set; } + /// /// Gets or sets the macro. /// @@ -147,10 +153,11 @@ namespace umbraco.cms.businesslogic.macro private void Setup() { using (var sqlHelper = Application.SqlHelper) - using (var dr = sqlHelper.ExecuteReader("select macro, editorAlias, macroPropertySortOrder, macroPropertyAlias, macroPropertyName from cmsMacroProperty where id = @id", sqlHelper.CreateParameter("@id", Id))) + using (var dr = sqlHelper.ExecuteReader("select uniqueId, macro, editorAlias, macroPropertySortOrder, macroPropertyAlias, macroPropertyName from cmsMacroProperty where id = @id", sqlHelper.CreateParameter("@id", Id))) { if (dr.Read()) { + Key = dr.GetGuid("uniqueId"); Macro = new Macro(dr.GetInt("macro")); SortOrder = (int)dr.GetByte("macroPropertySortOrder"); Alias = dr.GetString("macroPropertyAlias");