From be7179b962495afcb9752f420d51de17bd25f1e9 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 2 Oct 2013 17:10:12 +1000 Subject: [PATCH] Fixed up the TagRelationshipDto to have the correct columns, keys, etc.. as our upgrade, updated the old tags API to support the new changes. --- .../Models/Rdbms/TagRelationshipDto.cs | 8 +- .../TargetVersionSeven/AlterTagsTable.cs | 19 +++-- .../Upgrades/ValidateV7UpgradeTest.cs | 2 +- src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 1 + src/umbraco.cms/businesslogic/Tags/Tag.cs | 75 +++++++++++++++---- 5 files changed, 83 insertions(+), 22 deletions(-) diff --git a/src/Umbraco.Core/Models/Rdbms/TagRelationshipDto.cs b/src/Umbraco.Core/Models/Rdbms/TagRelationshipDto.cs index 8f64c9ba9c..4fc936713a 100644 --- a/src/Umbraco.Core/Models/Rdbms/TagRelationshipDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/TagRelationshipDto.cs @@ -9,12 +9,16 @@ namespace Umbraco.Core.Models.Rdbms internal class TagRelationshipDto { [Column("nodeId")] - [PrimaryKeyColumn(AutoIncrement = false, Name = "PK_cmsTagRelationship", OnColumns = "nodeId, tagId")] - [ForeignKey(typeof(NodeDto))] + [PrimaryKeyColumn(AutoIncrement = false, Name = "PK_cmsTagRelationship", OnColumns = "nodeId, propertyTypeId, tagId")] + [ForeignKey(typeof(ContentDto), Name = "FK_cmsTagRelationship_cmsContent", Column = "nodeId")] public int NodeId { get; set; } [Column("tagId")] [ForeignKey(typeof(TagDto))] public int TagId { get; set; } + + [Column("propertyTypeId")] + [ForeignKey(typeof(PropertyTypeDto), Name = "FK_cmsTagRelationship_cmsPropertyType")] + public int PropertyTypeId { get; set; } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AlterTagsTable.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AlterTagsTable.cs index f6a20aee1c..aa49dd61ea 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AlterTagsTable.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AlterTagsTable.cs @@ -28,6 +28,9 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven //we need to drop the primary key Delete.PrimaryKey("PK_cmsTagRelationship").FromTable("cmsTagRelationship"); + + //drop the foreign key on umbracoNode + Delete.ForeignKey("FK_cmsTagRelationship_umbracoNode_id").OnTable("cmsTagRelationship"); } private void Upgrade() @@ -55,8 +58,8 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven if (propertyTypes.Length == 0) { LogHelper.Warn("There was no cmsContent reference for cmsTagRelationship for nodeId " - + tr.NodeId + - ". The new tag system only supports tags with references to content in the umbracoNode and cmsPropertyType tables. This row will be deleted: " + + tr.NodeId + + ". The new tag system only supports tags with references to content in the cmsContent and cmsPropertyType tables. This row will be deleted: " + string.Format("nodeId: {0}, tagId: {1}", tr.NodeId, tr.TagId)); Delete.FromTable("cmsTagRelationship").Row(new { nodeId = tr.NodeId, tagId = tr.TagId }); } @@ -99,9 +102,15 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven .PrimaryColumn("id") .OnDelete(Rule.Cascade) .OnUpdate(Rule.None); - - //change the column to be not nullable - Alter.Table("cmsTagRelationship").AlterColumn("propertyTypeId").AsInt32().NotNullable(); + + //now we need to add a foreign key to the nodeId column to cmsContent (intead of the original umbracoNode) + Create.ForeignKey("FK_cmsTagRelationship_cmsContent") + .FromTable("cmsTagRelationship") + .ForeignColumn("nodeId") + .ToTable("cmsContent") + .PrimaryColumn("nodeId") + .OnDelete(Rule.Cascade) + .OnUpdate(Rule.None); } diff --git a/src/Umbraco.Tests/Migrations/Upgrades/ValidateV7UpgradeTest.cs b/src/Umbraco.Tests/Migrations/Upgrades/ValidateV7UpgradeTest.cs index 4b3ba23bc8..5349f2c252 100644 --- a/src/Umbraco.Tests/Migrations/Upgrades/ValidateV7UpgradeTest.cs +++ b/src/Umbraco.Tests/Migrations/Upgrades/ValidateV7UpgradeTest.cs @@ -123,7 +123,7 @@ namespace Umbraco.Tests.Migrations.Upgrades + (10 * 5) //the docs that have 2 tag prop per document - these are the update statements + (10 * 5) //the docs that have 2 tag prop per document - these are the insert statements + 1//the delete clause - + 5 , //additional db expressions + + 7 , //additional db expressions migrationContext.Expressions.Count); } } diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index 26f99b22b1..2e2b2089e2 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -424,6 +424,7 @@ create.aspx + ASPXCodeBehind create.aspx diff --git a/src/umbraco.cms/businesslogic/Tags/Tag.cs b/src/umbraco.cms/businesslogic/Tags/Tag.cs index 9b6fabd438..d9a2b16898 100644 --- a/src/umbraco.cms/businesslogic/Tags/Tag.cs +++ b/src/umbraco.cms/businesslogic/Tags/Tag.cs @@ -2,6 +2,9 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using Umbraco.Core; +using Umbraco.Core.Logging; +using Umbraco.Core.Models.Rdbms; using umbraco.DataLayer; using umbraco.BusinessLogic; using umbraco.interfaces; @@ -13,6 +16,12 @@ namespace umbraco.cms.businesslogic.Tags public class Tag : ITag { + private const string SqlGetTagPropertyIdsForNode = @"SELECT cmsPropertyType.id FROM cmsPropertyType + INNER JOIN cmsContent ON cmsContent.contentType = cmsPropertyType.contentTypeId + INNER JOIN cmsDataType ON cmsDataType.nodeId = cmsPropertyType.dataTypeId + WHERE cmsContent.nodeId = {0} + AND cmsDataType.propertyEditorAlias = '" + Constants.PropertyEditors.TagsAlias + "'"; + #region Constructors public Tag() { } public Tag(int id, string tag, string group, int nodeCount) @@ -53,14 +62,46 @@ namespace umbraco.cms.businesslogic.Tags public static void AssociateTagToNode(int nodeId, int tagId) { - SqlHelper.ExecuteNonQuery("INSERT INTO cmsTagRelationShip(nodeId,tagId) VALUES (@nodeId, @tagId)", - SqlHelper.CreateParameter("@nodeId", nodeId), - SqlHelper.CreateParameter("@tagId", tagId) - ); + //need to check if there's a tag property type to associate with the node, this is a new change with the db change + var tagProperties = ApplicationContext.Current.DatabaseContext.Database.Fetch( + string.Format(SqlGetTagPropertyIdsForNode, nodeId)).ToArray(); + if (tagProperties.Any() == false) + { + throw new InvalidOperationException("Cannot associate a tag to a node that doesn't have a Property Type assigned to a Tag Property Editor"); + } + if (tagProperties.Length > 1) + { + LogHelper.Warn("Because the legacy Tag data layer is being used, the tags being associated with the node will only be associated with the first found Property Type containing a Tag Property Editor"); + } + + if (ApplicationContext.Current.DatabaseContext.Database.ExecuteScalar( + "SELECT COUNT(*) FROM cmsTagRelationship WHERE nodeId=@nodeId AND tagId=@tagId AND propertyTypeId=@propertyTypeId", + new {tagId = tagId, nodeId = nodeId, propertyTypeId = tagProperties[0]}) == 0) + { + ApplicationContext.Current.DatabaseContext.Database.Insert(new TagRelationshipDto + { + NodeId = nodeId, + TagId = tagId, + PropertyTypeId = tagProperties[0] + }); + } + } public static void AddTagsToNode(int nodeId, string tags, string group) { + //need to check if there's a tag property type to associate with the node, this is a new change with the db change + var tagProperties = ApplicationContext.Current.DatabaseContext.Database.Fetch( + string.Format(SqlGetTagPropertyIdsForNode, nodeId)).ToArray(); + if (tagProperties.Any() == false) + { + throw new InvalidOperationException("Cannot associate a tag to a node that doesn't have a Property Type assigned to a Tag Property Editor"); + } + if (tagProperties.Length > 1) + { + LogHelper.Warn("Because the legacy Tag data layer is being used, the tags being associated with the node will only be associated with the first found Property Type containing a Tag Property Editor"); + } + string[] allTags = tags.Split(",".ToCharArray()); for (int i = 0; i < allTags.Length; i++) { @@ -69,15 +110,8 @@ namespace umbraco.cms.businesslogic.Tags if (id == 0) id = AddTag(allTags[i], group); - //GE 2011-10-31 - //if not exists is not supported on SQLCE - //SqlHelper.ExecuteNonQuery("if not exists(select nodeId from cmsTagRelationShip where nodeId = @nodeId and tagId = @tagId) INSERT INTO cmsTagRelationShip(nodeId,tagId) VALUES (@nodeId, @tagId)", - // SqlHelper.CreateParameter("@nodeId", nodeId), - // SqlHelper.CreateParameter("@tagId", id) - // ); - //Perform a subselect insert into cmsTagRelationship using a left outer join to perform the if not exists check - string sql = "insert into cmsTagRelationship (nodeId,tagId) select " + string.Format("{0}", nodeId) + ", " + string.Format("{0}", id) + " from cmsTags "; + var sql = "insert into cmsTagRelationship (nodeId,tagId,propertyTypeId) select " + string.Format("{0}", nodeId) + ", " + string.Format("{0}", id) + ", " + string.Format("{0}", tagProperties[0]) + " from cmsTags "; //sorry, gotta do this, @params not supported in join clause sql += "left outer join cmsTagRelationship on (cmsTags.id = cmsTagRelationship.TagId and cmsTagRelationship.nodeId = " + string.Format("{0}", nodeId) + ") "; sql += "where cmsTagRelationship.tagId is null and cmsTags.id = " + string.Format("{0}", id); @@ -91,6 +125,19 @@ namespace umbraco.cms.businesslogic.Tags public static void MergeTagsToNode(int nodeId, string tags, string group) { + //need to check if there's a tag property type to associate with the node, this is a new change with the db change + var tagProperties = ApplicationContext.Current.DatabaseContext.Database.Fetch( + string.Format(SqlGetTagPropertyIdsForNode, nodeId)).ToArray(); + if (tagProperties.Any() == false) + { + throw new InvalidOperationException("Cannot associate a tag to a node that doesn't have a Property Type assigned to a Tag Property Editor"); + } + if (tagProperties.Length > 1) + { + LogHelper.Warn("Because the legacy Tag data layer is being used, the tags being associated with the node will only be associated with the first found Property Type containing a Tag Property Editor"); + } + + //GE 2011-11-01 //When you have a new CSV list of tags (e.g. from control) and want to push those to the DB, the only way to do this //is delete all the existing tags and add the new ones. @@ -126,8 +173,8 @@ namespace umbraco.cms.businesslogic.Tags SqlHelper.ExecuteNonQuery(sql); //adds any tags found in csv that aren't in tagrelationships - sql = "insert into cmsTagRelationship (TagId,NodeId) "; - sql += "select NewTagsSet.Id, " + string.Format("{0}", nodeId) + " from "; + sql = "insert into cmsTagRelationship (TagId,NodeId,propertyTypeId) "; + sql += "select NewTagsSet.Id, " + string.Format("{0}", nodeId) + ", " + string.Format("{0}", tagProperties[0]) + " from "; sql += "( "; sql += "select NewTags.Id from "; sql += " " + TagSet + " ";