diff --git a/build/UmbracoVersion.txt b/build/UmbracoVersion.txt index 22a8c5dbec..027df04f32 100644 --- a/build/UmbracoVersion.txt +++ b/build/UmbracoVersion.txt @@ -1,3 +1,3 @@ # Usage: on line 2 put the release version, on line 3 put the version comment (example: beta) 7.6.0 -RC \ No newline at end of file +RC2 \ No newline at end of file diff --git a/src/SolutionInfo.cs b/src/SolutionInfo.cs index 80d52f6319..50f6feecf5 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-RC")] \ No newline at end of file +[assembly: AssemblyInformationalVersion("7.6.0-RC2")] \ No newline at end of file diff --git a/src/Umbraco.Core/Configuration/UmbracoVersion.cs b/src/Umbraco.Core/Configuration/UmbracoVersion.cs index a797850bd3..d8a41642e5 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 "RC"; } } + public static string CurrentComment { get { return "RC2"; } } // 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/Persistence/Migrations/Syntax/Alter/AlterSyntaxBuilder.cs b/src/Umbraco.Core/Persistence/Migrations/Syntax/Alter/AlterSyntaxBuilder.cs index e253f8e607..fc1971858f 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Syntax/Alter/AlterSyntaxBuilder.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Syntax/Alter/AlterSyntaxBuilder.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Persistence.Migrations.Syntax.Alter.Column; +using System; +using Umbraco.Core.Persistence.Migrations.Syntax.Alter.Column; using Umbraco.Core.Persistence.Migrations.Syntax.Alter.Expressions; using Umbraco.Core.Persistence.Migrations.Syntax.Alter.Table; using Umbraco.Core.Persistence.SqlSyntax; @@ -25,6 +26,15 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Alter return new AlterTableBuilder(_context, _databaseProviders, expression); } + /// + /// The problem with this is that only under particular circumstances is the expression added to the context + /// so you wouldn't actually know if you are using it correctly or not and chances are you are not and therefore + /// the statement won't even execute whereas using the IAlterTableSyntax to modify a column is guaranteed to add + /// the expression to the context. + /// + /// + /// + [Obsolete("Use the IAlterTableSyntax to modify a column instead, this will be removed in future versions")] public IAlterColumnSyntax Column(string columnName) { var expression = new AlterColumnExpression(_context.CurrentDatabaseProvider, _databaseProviders, _sqlSyntax) {Column = {Name = columnName}}; diff --git a/src/Umbraco.Core/Persistence/Migrations/Syntax/Alter/IAlterSyntaxBuilder.cs b/src/Umbraco.Core/Persistence/Migrations/Syntax/Alter/IAlterSyntaxBuilder.cs index 479c2eadce..77db6b8cde 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Syntax/Alter/IAlterSyntaxBuilder.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Syntax/Alter/IAlterSyntaxBuilder.cs @@ -1,11 +1,22 @@ -using Umbraco.Core.Persistence.Migrations.Syntax.Alter.Column; +using System; +using Umbraco.Core.Persistence.Migrations.Syntax.Alter.Column; using Umbraco.Core.Persistence.Migrations.Syntax.Alter.Table; namespace Umbraco.Core.Persistence.Migrations.Syntax.Alter { public interface IAlterSyntaxBuilder : IFluentSyntax { - IAlterTableSyntax Table(string tableName); + IAlterTableSyntax Table(string tableName); + + /// + /// The problem with this is that only under particular circumstances is the expression added to the context + /// so you wouldn't actually know if you are using it correctly or not and chances are you are not and therefore + /// the statement won't even execute whereas using the IAlterTableSyntax to modify a column is guaranteed to add + /// the expression to the context. + /// + /// + /// + [Obsolete("Use the IAlterTableSyntax to modify a column instead, this will be removed in future versions")] IAlterColumnSyntax Column(string columnName); } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/AddIndexToCmsMemberLoginName.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/AddIndexToCmsMemberLoginName.cs index 092176aa9e..c7fae7b2aa 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/AddIndexToCmsMemberLoginName.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/AddIndexToCmsMemberLoginName.cs @@ -4,7 +4,7 @@ using Umbraco.Core.Persistence.SqlSyntax; namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero { - [Migration("7.6.0", 0, Constants.System.UmbracoMigrationName)] + [Migration("7.6.0", 3, Constants.System.UmbracoMigrationName)] public class AddIndexToCmsMemberLoginName : MigrationBase { public AddIndexToCmsMemberLoginName(ISqlSyntaxProvider sqlSyntax, ILogger logger) @@ -12,18 +12,43 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero { } public override void Up() - { - var dbIndexes = SqlSyntax.GetDefinedIndexesDefinitions(Context.Database); - - //make sure it doesn't already exist - if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsMember_LoginName")) == false) + { + Execute.Code(database => { - Create.Index("IX_cmsMember_LoginName").OnTable("cmsMember") - .OnColumn("LoginName") - .Ascending() - .WithOptions() - .NonClustered(); - } + //Now we need to check if we can actually d6 this because we won't be able to if there's data in there that is too long + //http://issues.umbraco.org/issue/U4-9758 + + var colLen = (SqlSyntax is MySqlSyntaxProvider) + ? database.ExecuteScalar("select max(LENGTH(LoginName)) from cmsMember") + : database.ExecuteScalar("select max(datalength(LoginName)) from cmsMember"); + + if (colLen < 900 == false && colLen != null) + { + return null; + } + + var dbIndexes = SqlSyntax.GetDefinedIndexesDefinitions(Context.Database); + + //make sure it doesn't already exist + if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsMember_LoginName")) == false) + { + var localContext = new LocalMigrationContext(Context.CurrentDatabaseProvider, database, SqlSyntax, Logger); + + //we can apply the index + localContext.Create.Index("IX_cmsMember_LoginName").OnTable("cmsMember") + .OnColumn("LoginName") + .Ascending() + .WithOptions() + .NonClustered(); + + return localContext.GetSql(); + } + + return null; + + }); + + } public override void Down() diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/NormalizeTemplateGuids.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/NormalizeTemplateGuids.cs new file mode 100644 index 0000000000..3a2e398665 --- /dev/null +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/NormalizeTemplateGuids.cs @@ -0,0 +1,48 @@ +using System; +using System.Linq; +using Umbraco.Core.Logging; +using Umbraco.Core.Persistence.SqlSyntax; + +namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero +{ + [Migration("7.6.0", 0, Constants.System.UmbracoMigrationName)] + public class NormalizeTemplateGuids : MigrationBase + { + public NormalizeTemplateGuids(ISqlSyntaxProvider sqlSyntax, ILogger logger) + : base(sqlSyntax, logger) + { } + + public override void Up() + { + Execute.Code(UpdateTemplateGuids); + } + + private static string UpdateTemplateGuids(Database database) + { + // we need this migration because ppl running pre-7.6 on Cloud and Courier have templates in different + // environments having different GUIDs (Courier does not sync template GUIDs) and we need to normalize + // these GUIDs so templates with the same alias on different environments have the same GUID. + // however, if already running a prerelease version of 7.6, we do NOT want to normalize the GUIDs as quite + // probably, we are already running Deploy and the GUIDs are OK. assuming noone is running a prerelease + // of 7.6 on Courier. + // so... testing if we already have a 7.6.0 version installed. not pretty but...? + // + var version = database.FirstOrDefault("SELECT version FROM umbracoMigration WHERE name=@name ORDER BY version DESC", new { name = Constants.System.UmbracoMigrationName }); + if (version != null && version.StartsWith("7.6.0")) return string.Empty; + + var updates = database.Query("SELECT id, text FROM umbracoNode WHERE nodeObjectType = @guid", new { guid = Constants.ObjectTypes.TemplateTypeGuid}) + .Select(template => Tuple.Create((int) template.id, ("template____" + (string) template.text).ToGuid())) + .ToList(); + + foreach (var update in updates) + database.Execute("UPDATE umbracoNode 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/Migrations/Upgrades/TargetVersionSevenSixZero/ReduceLoginNameColumnsSize.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/ReduceLoginNameColumnsSize.cs new file mode 100644 index 0000000000..140bfa3553 --- /dev/null +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/ReduceLoginNameColumnsSize.cs @@ -0,0 +1,52 @@ +using System.Linq; +using Umbraco.Core.Logging; +using Umbraco.Core.Persistence.SqlSyntax; + +namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero +{ + [Migration("7.6.0", 2, Constants.System.UmbracoMigrationName)] + public class ReduceLoginNameColumnsSize : MigrationBase + { + public ReduceLoginNameColumnsSize(ISqlSyntaxProvider sqlSyntax, ILogger logger) + : base(sqlSyntax, logger) + { } + + public override void Up() + { + //Now we need to check if we can actually d6 this because we won't be able to if there's data in there that is too long + //http://issues.umbraco.org/issue/U4-9758 + + Execute.Code(database => + { + var dbIndexes = SqlSyntax.GetDefinedIndexesDefinitions(database); + + var colLen = (SqlSyntax is MySqlSyntaxProvider) + ? database.ExecuteScalar("select max(LENGTH(LoginName)) from cmsMember") + : database.ExecuteScalar("select max(datalength(LoginName)) from cmsMember"); + + if (colLen < 900 == false) return null; + + var localContext = new LocalMigrationContext(Context.CurrentDatabaseProvider, database, SqlSyntax, Logger); + + //if it exists we need to drop it first + if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsMember_LoginName"))) + { + localContext.Delete.Index("IX_cmsMember_LoginName").OnTable("cmsMember"); + } + + //we can apply the col length change + localContext.Alter.Table("cmsMember") + .AlterColumn("LoginName") + .AsString(225) + .NotNullable(); + + return localContext.GetSql(); + }); + } + + public override void Down() + { + + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/UpdateUniqueIdToHaveCorrectIndexType.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/UpdateUniqueIdToHaveCorrectIndexType.cs index 8eeca45cb1..79d7b3111c 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/UpdateUniqueIdToHaveCorrectIndexType.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/UpdateUniqueIdToHaveCorrectIndexType.cs @@ -29,7 +29,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe }).ToArray(); //must be non-nullable - Alter.Column("uniqueID").OnTable("umbracoNode").AsGuid().NotNullable(); + Alter.Table("umbracoNode").AlterColumn("uniqueID").AsGuid().NotNullable(); //make sure it already exists if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_umbracoNodeUniqueID"))) diff --git a/src/Umbraco.Core/Persistence/Repositories/PublicAccessRepository.cs b/src/Umbraco.Core/Persistence/Repositories/PublicAccessRepository.cs index a38281f785..f38a882e92 100644 --- a/src/Umbraco.Core/Persistence/Repositories/PublicAccessRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/PublicAccessRepository.cs @@ -132,6 +132,11 @@ namespace Umbraco.Core.Persistence.Repositories Database.Update(dto); + foreach (var removedRule in entity.RemovedRules) + { + Database.Delete("WHERE id=@Id", new { Id = removedRule }); + } + foreach (var rule in entity.Rules) { if (rule.HasIdentity) @@ -157,10 +162,6 @@ namespace Umbraco.Core.Persistence.Repositories rule.Id = rule.Key.GetHashCode(); } } - foreach (var removedRule in entity.RemovedRules) - { - Database.Delete("WHERE id=@Id", new {Id = removedRule}); - } entity.ClearRemovedRules(); diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 434a45f4c9..41e6614d86 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -515,6 +515,8 @@ + + diff --git a/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js index 45dba79ad5..5d2129668e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js @@ -60,10 +60,13 @@ // sync tree // if master template alias has changed move the node to it's new location if(oldMasterTemplateAlias !== vm.template.masterTemplateAlias) { - - // move node to new location in tree - //first we need to remove the node that we're working on - treeService.removeNode(vm.page.menu.currentNode); + + // When creating a new template the id is -1. Make sure We don't remove the root node. + if (vm.page.menu.currentNode.id !== "-1") { + // move node to new location in tree + //first we need to remove the node that we're working on + treeService.removeNode(vm.page.menu.currentNode); + } // update stored alias to the new one so the node won't move again unless the alias is changed again oldMasterTemplateAlias = vm.template.masterTemplateAlias; diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index b656ebe186..0452b7d5db 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -206,8 +206,8 @@ System - - ..\packages\System.Collections.Immutable.1.3.1\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + + ..\packages\System.Collections.Immutable.1.1.36\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll @@ -239,8 +239,8 @@ False False - - ..\packages\System.Reflection.Metadata.1.4.2\lib\portable-net45+win8\System.Reflection.Metadata.dll + + ..\packages\System.Reflection.Metadata.1.0.21\lib\portable-net45+win8\System.Reflection.Metadata.dll diff --git a/src/Umbraco.Web.UI/packages.config b/src/Umbraco.Web.UI/packages.config index 910d4d82d4..555740eda3 100644 --- a/src/Umbraco.Web.UI/packages.config +++ b/src/Umbraco.Web.UI/packages.config @@ -35,7 +35,7 @@ - - + + \ No newline at end of file diff --git a/src/Umbraco.Web/Editors/TemplateController.cs b/src/Umbraco.Web/Editors/TemplateController.cs index 40effc10fa..78855c95c2 100644 --- a/src/Umbraco.Web/Editors/TemplateController.cs +++ b/src/Umbraco.Web/Editors/TemplateController.cs @@ -105,8 +105,7 @@ namespace Umbraco.Web.Editors { throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState)); } - - + if (display.Id > 0) { // update @@ -131,8 +130,34 @@ namespace Umbraco.Web.Editors }else { template.SetMasterTemplate(master); - } + //After updating the master - ensure we update the path property if it has any children already assigned + var templateHasChildren = Services.FileService.GetTemplateDescendants(display.Id); + + foreach (var childTemplate in templateHasChildren) + { + //template ID to find + var templateIdInPath = "," + display.Id + ","; + + if (string.IsNullOrEmpty(childTemplate.Path)) + { + continue; + } + + //Find position in current comma seperate string path (so we get the correct children path) + var positionInPath = childTemplate.Path.IndexOf(templateIdInPath) + templateIdInPath.Length; + + //Get the substring of the child & any children (descendants it may have too) + var childTemplatePath = childTemplate.Path.Substring(positionInPath); + + //As we are updating the template to be a child of a master + //Set the path to the master's path + its current template id + the current child path substring + childTemplate.Path = master.Path + "," + display.Id + "," + childTemplatePath; + + //Save the children with the updated path + Services.FileService.SaveTemplate(childTemplate); + } + } } else { diff --git a/src/Umbraco.Web/PublishedContentExtensions.cs b/src/Umbraco.Web/PublishedContentExtensions.cs index 7972f109f9..36d1306ab6 100644 --- a/src/Umbraco.Web/PublishedContentExtensions.cs +++ b/src/Umbraco.Web/PublishedContentExtensions.cs @@ -540,7 +540,7 @@ namespace Umbraco.Web var filtered = dynamicDocumentList.Where(predicate); return filtered.Count() == 1; } - + #endregion #region AsDynamic @@ -806,7 +806,7 @@ namespace Umbraco.Web public static HtmlString IsOdd(this IPublishedContent content, string valueIfTrue, string valueIfFalse) { return new HtmlString(content.IsOdd() ? valueIfTrue : valueIfFalse); - } + } #endregion @@ -836,7 +836,7 @@ namespace Umbraco.Web { return content.IsNotEqual(other, valueIfTrue, string.Empty); } - + public static HtmlString IsNotEqual(this IPublishedContent content, IPublishedContent other, string valueIfTrue, string valueIfFalse) { return new HtmlString(content.IsNotEqual(other) ? valueIfTrue : valueIfFalse); @@ -1125,7 +1125,7 @@ namespace Umbraco.Web { return content.Ancestors(maxLevel).FirstOrDefault(); } - + /// /// Gets the content or its nearest ancestor. /// @@ -1186,7 +1186,7 @@ namespace Umbraco.Web { return content.AncestorsOrSelf(maxLevel).FirstOrDefault(); } - + internal static IEnumerable AncestorsOrSelf(this IPublishedContent content, bool orSelf, Func func) { var ancestorsOrSelf = content.EnumerateAncestors(orSelf); @@ -1237,7 +1237,7 @@ namespace Umbraco.Web where T : class, IPublishedContent { return parentNodes.SelectMany(x => x.DescendantsOrSelf()); - } + } // as per XPath 1.0 specs §2.2, @@ -1285,7 +1285,7 @@ namespace Umbraco.Web { return content.Descendants(level).OfType(); } - + public static IEnumerable DescendantsOrSelf(this IPublishedContent content) { return content.DescendantsOrSelf(true, null); @@ -1366,7 +1366,7 @@ namespace Umbraco.Web { return content.DescendantOrSelf(level) as T; } - + internal static IEnumerable DescendantsOrSelf(this IPublishedContent content, bool orSelf, Func func) { return content.EnumerateDescendants(orSelf).Where(x => func == null || func(x)); @@ -1390,7 +1390,7 @@ namespace Umbraco.Web foreach (var child2 in child.EnumerateDescendants()) yield return child2; } - + #endregion #region Axes: following-sibling, preceding-sibling, following, preceding + pseudo-axes up, down, next, previous @@ -1413,8 +1413,8 @@ namespace Umbraco.Web public static IPublishedContent Up(this IPublishedContent content, string contentTypeAlias) { - return string.IsNullOrEmpty(contentTypeAlias) - ? content.Parent + return string.IsNullOrEmpty(contentTypeAlias) + ? content.Parent : content.Ancestor(contentTypeAlias); } @@ -1799,13 +1799,19 @@ namespace Umbraco.Web return content.Children().FirstOrDefault(); } - /// - /// Gets the children of the content in a DataTable. - /// + public static IPublishedContent FirstChild(this IPublishedContent content, Func predicate) + where T : class, IPublishedContent + { + return content.Children().FirstOrDefault(predicate); + } + + /// + /// Gets the children of the content in a DataTable. + /// /// The content. /// An optional content type alias. /// The children of the content. - public static DataTable ChildrenAsTable(this IPublishedContent content, string contentTypeAliasFilter = "") + public static DataTable ChildrenAsTable(this IPublishedContent content, string contentTypeAliasFilter = "") { return GenerateDataTable(content, contentTypeAliasFilter); } @@ -1824,7 +1830,7 @@ namespace Umbraco.Web : null : content.Children.FirstOrDefault(x => x.DocumentTypeAlias == contentTypeAliasFilter); if (firstNode == null) - return new DataTable(); //no children found + return new DataTable(); //no children found //use new utility class to create table so that we don't have to maintain code in many places, just one var dt = Core.DataTableExtensions.GenerateDataTable( @@ -1964,7 +1970,7 @@ namespace Umbraco.Web public static CultureInfo GetCulture(this IPublishedContent content, Uri current = null) { return Models.ContentExtensions.GetCulture(UmbracoContext.Current, - ApplicationContext.Current.Services.DomainService, + ApplicationContext.Current.Services.DomainService, ApplicationContext.Current.Services.LocalizationService, ApplicationContext.Current.Services.ContentService, content.Id, content.Path,