From f00e8b4efc061fbe6627b9cb71020f2ca8216ebb Mon Sep 17 00:00:00 2001 From: Morten Christensen Date: Thu, 24 Jan 2013 08:18:22 -0100 Subject: [PATCH 1/8] Adding update statement to template repository, so templates can be properly removed. --- src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs b/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs index 372f0571a0..edb5e7b75d 100644 --- a/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs @@ -153,6 +153,7 @@ namespace Umbraco.Core.Persistence.Repositories { "DELETE FROM umbracoUser2NodeNotify WHERE nodeId = @Id", "DELETE FROM umbracoUser2NodePermission WHERE nodeId = @Id", + "UPDATE cmsDocument SET templateId = NULL WHERE nodeId = @Id", "DELETE FROM cmsDocumentType WHERE templateNodeId = @Id", "DELETE FROM cmsTemplate WHERE nodeId = @Id", "DELETE FROM umbracoNode WHERE id = @Id" From b17dcd2b56a343894b18c6fb17aa9ca0381b5c32 Mon Sep 17 00:00:00 2001 From: Morten Christensen Date: Thu, 24 Jan 2013 09:50:27 -0100 Subject: [PATCH 2/8] Fixes U4-1516 by ensuring that referenced templates are deleted prior to deleting the actual template. Removing uncommented code from the Media class as well as from the ContentExtension class. Added saving of Media Xml to MediaService upon saving. Removing referenced media test from csproj as cs file was missing. --- src/Umbraco.Core/Models/ContentExtensions.cs | 53 +------------ src/Umbraco.Core/Services/MediaService.cs | 9 +++ src/Umbraco.Tests/Umbraco.Tests.csproj | 3 +- src/umbraco.cms/businesslogic/media/Media.cs | 75 ------------------- .../businesslogic/template/Template.cs | 3 +- src/umbraco.cms/businesslogic/web/Document.cs | 2 + 6 files changed, 15 insertions(+), 130 deletions(-) diff --git a/src/Umbraco.Core/Models/ContentExtensions.cs b/src/Umbraco.Core/Models/ContentExtensions.cs index 3e0f95d8a5..2b97f57b66 100644 --- a/src/Umbraco.Core/Models/ContentExtensions.cs +++ b/src/Umbraco.Core/Models/ContentExtensions.cs @@ -54,55 +54,6 @@ namespace Umbraco.Core.Models } } - /* - /// - /// Sets and uploads the file from a HttpPostedFileBase object as the property value - /// - /// to add property value to - /// Alias of the property to save the value on - /// The containing the file that will be uploaded - public static void SetPropertyValue(this IMedia media, string propertyTypeAlias, HttpPostedFileBase value) - { - var name = - IOHelper.SafeFileName( - value.FileName.Substring(value.FileName.LastIndexOf(IOHelper.DirSepChar) + 1, - value.FileName.Length - value.FileName.LastIndexOf(IOHelper.DirSepChar) - 1) - .ToLower()); - - if(string.IsNullOrEmpty(name) == false) - SetFileOnContent(media, propertyTypeAlias, name, value.InputStream); - } - - /// - /// Sets and uploads the file from a HttpPostedFile object as the property value - /// - /// to add property value to - /// Alias of the property to save the value on - /// The containing the file that will be uploaded - public static void SetPropertyValue(this IMedia media, string propertyTypeAlias, HttpPostedFile value) - { - var name = - IOHelper.SafeFileName( - value.FileName.Substring(value.FileName.LastIndexOf(IOHelper.DirSepChar) + 1, - value.FileName.Length - value.FileName.LastIndexOf(IOHelper.DirSepChar) - 1) - .ToLower()); - - if (string.IsNullOrEmpty(name) == false) - SetFileOnContent(media, propertyTypeAlias, name, value.InputStream); - } - - /// - /// Sets and uploads the file from a HttpPostedFileWrapper object as the property value - /// - /// to add property value to - /// Alias of the property to save the value on - /// The containing the file that will be uploaded - public static void SetPropertyValue(this IMedia media, string propertyTypeAlias, HttpPostedFileWrapper value) - { - if (string.IsNullOrEmpty(value.FileName) == false) - SetFileOnContent(media, propertyTypeAlias, value.FileName, value.InputStream); - } - */ /// /// Sets and uploads the file from a HttpPostedFileBase object as the property value /// @@ -403,7 +354,6 @@ namespace Umbraco.Core.Models /// Xml representation of the passed in public static XElement ToXml(this IContent content) { - //nodeName should match Casing.SafeAliasWithForcingCheck(content.ContentType.Alias); var nodeName = UmbracoSettings.UseLegacyXmlSchema ? "node" : content.ContentType.Alias.ToSafeAliasWithForcingCheck(); @@ -419,7 +369,6 @@ namespace Umbraco.Core.Models } return x; - } /// @@ -427,7 +376,7 @@ namespace Umbraco.Core.Models /// /// to generate xml for /// Xml representation of the passed in - internal static XElement ToXml(this IMedia media) + public static XElement ToXml(this IMedia media) { //nodeName should match Casing.SafeAliasWithForcingCheck(content.ContentType.Alias); var nodeName = UmbracoSettings.UseLegacyXmlSchema ? "node" : media.ContentType.Alias.ToSafeAliasWithForcingCheck(); diff --git a/src/Umbraco.Core/Services/MediaService.cs b/src/Umbraco.Core/Services/MediaService.cs index bb5d0ac844..be2e1d063f 100644 --- a/src/Umbraco.Core/Services/MediaService.cs +++ b/src/Umbraco.Core/Services/MediaService.cs @@ -3,9 +3,11 @@ using System.Collections; using System.Collections.Generic; using System.Linq; using System.Web; +using System.Xml.Linq; using Umbraco.Core.Auditing; using Umbraco.Core.Events; using Umbraco.Core.Models; +using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.UnitOfWork; @@ -479,6 +481,13 @@ namespace Umbraco.Core.Services SetUser(media, userId); repository.AddOrUpdate(media); uow.Commit(); + + var xml = media.ToXml(); + var poco = new ContentXmlDto { NodeId = media.Id, Xml = xml.ToString(SaveOptions.None) }; + var exists = uow.Database.FirstOrDefault("WHERE nodeId = @Id", new { Id = media.Id }) != null; + int result = exists + ? uow.Database.Update(poco) + : Convert.ToInt32(uow.Database.Insert(poco)); } Saved.RaiseEvent(new SaveEventArgs(media, false), this); diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index 27380cb453..d10dccca8a 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -175,7 +175,6 @@ - @@ -313,6 +312,7 @@ + Always @@ -402,6 +402,7 @@ + diff --git a/src/umbraco.cms/businesslogic/media/Media.cs b/src/umbraco.cms/businesslogic/media/Media.cs index b25d543cef..076fc37a3e 100644 --- a/src/umbraco.cms/businesslogic/media/Media.cs +++ b/src/umbraco.cms/businesslogic/media/Media.cs @@ -81,15 +81,6 @@ namespace umbraco.cms.businesslogic.media ApplicationContext.Current.Services.MediaService.Save(media); var tmp = new Media(media); - /*Guid newId = Guid.NewGuid(); - // Updated to match level from base node - CMSNode n = new CMSNode(ParentId); - int newLevel = n.Level; - newLevel++; - CMSNode.MakeNew(ParentId, _objectType, u.Id, newLevel, Name, newId); - Media tmp = new Media(newId); - tmp.CreateContent(dct);*/ - NewEventArgs e = new NewEventArgs(); tmp.OnNew(e); @@ -105,16 +96,6 @@ namespace umbraco.cms.businesslogic.media { var children = ApplicationContext.Current.Services.MediaService.GetRootMedia(); return children.Select(x => new Media(x)).ToArray(); - - /*Guid[] topNodeIds = CMSNode.TopMostNodeIds(_objectType); - - Media[] retval = new Media[topNodeIds.Length]; - for (int i = 0; i < topNodeIds.Length; i++) - { - Media d = new Media(topNodeIds[i]); - retval[i] = d; - } - return retval;*/ } [Obsolete("Obsolete, Use Umbraco.Core.Services.MediaService.GetChildren()", false)] @@ -122,26 +103,6 @@ namespace umbraco.cms.businesslogic.media { var children = ApplicationContext.Current.Services.MediaService.GetChildren(nodeId); return children.Select(x => new Media(x)).ToList(); - - /*List tmp = new List(); - using (IRecordsReader dr = - SqlHelper.ExecuteReader( - string.Format(m_SQLOptimizedMany.Trim() - , "umbracoNode.parentID = @parentId" - , "umbracoNode.sortOrder") - , SqlHelper.CreateParameter("@nodeObjectType", _objectType) - , SqlHelper.CreateParameter("@parentId", nodeId))) - { - - while (dr.Read()) - { - Media d = new Media(dr.GetInt("id"), true); - d.PopulateMediaFromReader(dr); - tmp.Add(d); - } - - } - return tmp;*/ } [Obsolete("Obsolete, Use Umbraco.Core.Services.MediaService.GetMediaOfMediaType()", false)] @@ -149,23 +110,6 @@ namespace umbraco.cms.businesslogic.media { var children = ApplicationContext.Current.Services.MediaService.GetMediaOfMediaType(mediaTypeId); return children.Select(x => new Media(x)).ToList(); - - /*var tmp = new List(); - using (IRecordsReader dr = - SqlHelper.ExecuteReader( - string.Format(m_SQLOptimizedMany.Trim(), "cmsContent.contentType = @contentTypeId", "umbracoNode.sortOrder"), - SqlHelper.CreateParameter("@nodeObjectType", _objectType), - SqlHelper.CreateParameter("@contentTypeId", mediaTypeId))) - { - while (dr.Read()) - { - Media d = new Media(dr.GetInt("id"), true); - d.PopulateMediaFromReader(dr); - tmp.Add(d); - } - } - - return tmp.ToArray();*/ } /// @@ -178,25 +122,6 @@ namespace umbraco.cms.businesslogic.media public static void DeleteFromType(MediaType dt) { ApplicationContext.Current.Services.MediaService.DeleteMediaOfType(dt.Id); - - //get all document for the document type and order by level (top level first) - /*var medias = Media.GetMediaOfMediaType(dt.Id) - .OrderByDescending(x => x.Level); - - foreach (Media media in medias) - { - //before we delete this document, we need to make sure we don't end up deleting other documents that - //are not of this document type that are children. So we'll move all of it's children to the trash first. - foreach (Media m in media.GetDescendants()) - { - if (m.ContentType.Id != dt.Id) - { - m.MoveToTrash(); - } - } - - media.DeletePermanently(); - }*/ } #endregion diff --git a/src/umbraco.cms/businesslogic/template/Template.cs b/src/umbraco.cms/businesslogic/template/Template.cs index f6220b7f27..ea074ec77c 100644 --- a/src/umbraco.cms/businesslogic/template/Template.cs +++ b/src/umbraco.cms/businesslogic/template/Template.cs @@ -320,8 +320,6 @@ namespace umbraco.cms.businesslogic.template // remove from documents Document.RemoveTemplateFromDocument(this.Id); - - } public void RemoveFromDocumentTypes() @@ -329,6 +327,7 @@ namespace umbraco.cms.businesslogic.template foreach (DocumentType dt in DocumentType.GetAllAsList().Where(x => x.allowedTemplates.Select(t => t.Id).Contains(this.Id))) { dt.RemoveTemplate(this.Id); + dt.Save(); } } diff --git a/src/umbraco.cms/businesslogic/web/Document.cs b/src/umbraco.cms/businesslogic/web/Document.cs index 4b57ddd758..d1d2b35650 100644 --- a/src/umbraco.cms/businesslogic/web/Document.cs +++ b/src/umbraco.cms/businesslogic/web/Document.cs @@ -428,6 +428,8 @@ namespace umbraco.cms.businesslogic.web { ApplicationContext.Current.DatabaseContext.Database.Execute( "update cmsDocument set templateId = NULL where templateId = @TemplateId", new {TemplateId = templateId}); + //We need to clear cache for Documents since this is touching the database directly + RuntimeCacheProvider.Current.Clear(); } /// From 23141e1e8cb525676eb68947deb93d4fd65590e7 Mon Sep 17 00:00:00 2001 From: Morten Christensen Date: Thu, 24 Jan 2013 12:25:48 -0100 Subject: [PATCH 3/8] Fixing broken media tests after having added ToXml and saving of xml to ContentXml table in the MediaService --- src/Umbraco.Core/Models/ContentExtensions.cs | 20 +++++-------------- .../Repositories/UserRepository.cs | 4 ++-- src/Umbraco.Core/Services/ServiceContext.cs | 2 +- src/Umbraco.Tests/Models/ContentXmlTest.cs | 6 +----- .../Repositories/MediaRepositoryTest.cs | 20 +++++++++++++++++++ .../Services/ThreadSafetyServiceTest.cs | 19 ++++++++++++++++++ 6 files changed, 48 insertions(+), 23 deletions(-) diff --git a/src/Umbraco.Core/Models/ContentExtensions.cs b/src/Umbraco.Core/Models/ContentExtensions.cs index 2b97f57b66..9893994d4e 100644 --- a/src/Umbraco.Core/Models/ContentExtensions.cs +++ b/src/Umbraco.Core/Models/ContentExtensions.cs @@ -299,21 +299,9 @@ namespace Umbraco.Core.Models } /// - /// Gets the for the Creator of this media item. + /// Gets the for the Creator of this content/media item. /// - internal static IProfile GetCreatorProfile(this IMedia media) - { - using (var repository = RepositoryResolver.Current.Factory.CreateUserRepository( - PetaPocoUnitOfWorkProvider.CreateUnitOfWork())) - { - return repository.GetProfileById(media.CreatorId); - } - } - - /// - /// Gets the for the Creator of this content. - /// - public static IProfile GetCreatorProfile(this IContent content) + public static IProfile GetCreatorProfile(this IContentBase content) { using (var repository = RepositoryResolver.Current.Factory.CreateUserRepository( PetaPocoUnitOfWorkProvider.CreateUnitOfWork())) @@ -383,7 +371,9 @@ namespace Umbraco.Core.Models var x = media.ToXml(nodeName); x.Add(new XAttribute("nodeType", media.ContentType.Id)); - x.Add(new XAttribute("writerName", media.GetCreatorProfile().Name)); + //TODO Using the GetCreatorProfile extension method seems to be causing threading/connection problems because of the way the repo is used + //x.Add(new XAttribute("writerName", media.GetCreatorProfile().Name)); + x.Add(new XAttribute("writerName", string.Empty)); x.Add(new XAttribute("writerID", media.CreatorId)); x.Add(new XAttribute("version", media.Version)); x.Add(new XAttribute("template", 0)); diff --git a/src/Umbraco.Core/Persistence/Repositories/UserRepository.cs b/src/Umbraco.Core/Persistence/Repositories/UserRepository.cs index a42c626027..d88a00f187 100644 --- a/src/Umbraco.Core/Persistence/Repositories/UserRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/UserRepository.cs @@ -36,7 +36,7 @@ namespace Umbraco.Core.Persistence.Repositories var sql = GetBaseQuery(false); sql.Where(GetBaseWhereClause(), new { Id = id }); - var dto = Database.Query(sql).FirstOrDefault(); + var dto = Database.FirstOrDefault(sql); if (dto == null) return null; @@ -139,7 +139,7 @@ namespace Umbraco.Core.Persistence.Repositories var sql = GetBaseQuery(false); sql.Where(GetBaseWhereClause(), new { Id = id }); - var dto = Database.Query(sql).FirstOrDefault(); + var dto = Database.FirstOrDefault(sql); if (dto == null) return null; diff --git a/src/Umbraco.Core/Services/ServiceContext.cs b/src/Umbraco.Core/Services/ServiceContext.cs index 4f5d0d696e..2e857894cd 100644 --- a/src/Umbraco.Core/Services/ServiceContext.cs +++ b/src/Umbraco.Core/Services/ServiceContext.cs @@ -54,7 +54,7 @@ namespace Umbraco.Core.Services _contentService = new Lazy(() => new ContentService(provider, repositoryFactory.Value, publishingStrategy, _userService.Value)); if(_mediaService == null) - _mediaService = new Lazy(() => new MediaService(provider, repositoryFactory.Value)); + _mediaService = new Lazy(() => new MediaService(provider, repositoryFactory.Value, _userService.Value)); if(_macroService == null) _macroService = new Lazy(() => new MacroService(fileProvider, repositoryFactory.Value)); diff --git a/src/Umbraco.Tests/Models/ContentXmlTest.cs b/src/Umbraco.Tests/Models/ContentXmlTest.cs index f05230d191..ab529e0f07 100644 --- a/src/Umbraco.Tests/Models/ContentXmlTest.cs +++ b/src/Umbraco.Tests/Models/ContentXmlTest.cs @@ -1,16 +1,12 @@ -using System; -using System.Linq; +using System.Linq; using System.Xml.Linq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Models; -using Umbraco.Core.ObjectResolution; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Entities; -using Umbraco.Web; using umbraco.editorControls.tinyMCE3; using umbraco.interfaces; -using File = System.IO.File; namespace Umbraco.Tests.Models { diff --git a/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs index c1f42d9df4..99a156fbf5 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using NUnit.Framework; +using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Persistence; @@ -9,6 +10,8 @@ using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.UnitOfWork; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Entities; +using umbraco.editorControls.tinyMCE3; +using umbraco.interfaces; namespace Umbraco.Tests.Persistence.Repositories { @@ -18,6 +21,20 @@ namespace Umbraco.Tests.Persistence.Repositories [SetUp] public override void Initialize() { + //NOTE The DataTypesResolver is only necessary because we are using the Save method in the MediaService + //this ensures its reset + PluginManager.Current = new PluginManager(); + + //for testing, we'll specify which assemblies are scanned for the PluginTypeResolver + PluginManager.Current.AssembliesToScan = new[] + { + typeof(IDataType).Assembly, + typeof(tinyMCE3dataType).Assembly + }; + + DataTypesResolver.Current = new DataTypesResolver( + PluginManager.Current.ResolveDataTypes()); + base.Initialize(); CreateTestData(); @@ -288,6 +305,9 @@ namespace Umbraco.Tests.Persistence.Repositories [TearDown] public override void TearDown() { + //reset the app context + DataTypesResolver.Reset(); + base.TearDown(); } diff --git a/src/Umbraco.Tests/Services/ThreadSafetyServiceTest.cs b/src/Umbraco.Tests/Services/ThreadSafetyServiceTest.cs index c64e1b9628..db288eda23 100644 --- a/src/Umbraco.Tests/Services/ThreadSafetyServiceTest.cs +++ b/src/Umbraco.Tests/Services/ThreadSafetyServiceTest.cs @@ -13,6 +13,8 @@ using Umbraco.Core.Publishing; using Umbraco.Core.Services; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Entities; +using umbraco.editorControls.tinyMCE3; +using umbraco.interfaces; namespace Umbraco.Tests.Services { @@ -25,6 +27,20 @@ namespace Umbraco.Tests.Services [SetUp] public override void Initialize() { + //NOTE The DataTypesResolver is only necessary because we are using the Save method in the MediaService + //this ensures its reset + PluginManager.Current = new PluginManager(); + + //for testing, we'll specify which assemblies are scanned for the PluginTypeResolver + PluginManager.Current.AssembliesToScan = new[] + { + typeof(IDataType).Assembly, + typeof(tinyMCE3dataType).Assembly + }; + + DataTypesResolver.Current = new DataTypesResolver( + PluginManager.Current.ResolveDataTypes()); + base.Initialize(); //we need to use our own custom IDatabaseFactory for the DatabaseContext because we MUST ensure that @@ -47,6 +63,9 @@ namespace Umbraco.Tests.Services [TearDown] public override void TearDown() { + //reset the app context + DataTypesResolver.Reset(); + _error = null; //dispose! From 25f91cc0da7fd0eb8313e72ecb9d7d964469b0f1 Mon Sep 17 00:00:00 2001 From: Morten Christensen Date: Thu, 24 Jan 2013 13:49:41 -0100 Subject: [PATCH 4/8] Fixes U4-1534 so documents containing the tag datatype is properly copied. Copying a document with a Tags datatype on it would only work if a new TagRelationship is created. --- src/Umbraco.Core/Models/Content.cs | 6 +++++ src/Umbraco.Core/Models/EntityBase/Entity.cs | 2 +- src/Umbraco.Core/Services/ContentService.cs | 23 +++++++++++++++----- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/Umbraco.Core/Models/Content.cs b/src/Umbraco.Core/Models/Content.cs index 61cb495679..218d8be580 100644 --- a/src/Umbraco.Core/Models/Content.cs +++ b/src/Umbraco.Core/Models/Content.cs @@ -312,6 +312,12 @@ namespace Umbraco.Core.Models clone.Version = Guid.NewGuid(); clone.ResetIdentity(); + foreach (var property in clone.Properties) + { + property.ResetIdentity(); + property.Version = clone.Version; + } + return clone; } diff --git a/src/Umbraco.Core/Models/EntityBase/Entity.cs b/src/Umbraco.Core/Models/EntityBase/Entity.cs index 18ceff06ad..6c081ea0b4 100644 --- a/src/Umbraco.Core/Models/EntityBase/Entity.cs +++ b/src/Umbraco.Core/Models/EntityBase/Entity.cs @@ -85,7 +85,7 @@ namespace Umbraco.Core.Models.EntityBase } } - protected void ResetIdentity() + internal virtual void ResetIdentity() { _hasIdentity = false; _id = default(int); diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs index fb8a3168ed..67e0982019 100644 --- a/src/Umbraco.Core/Services/ContentService.cs +++ b/src/Umbraco.Core/Services/ContentService.cs @@ -791,9 +791,8 @@ namespace Umbraco.Core.Services var copy = ((Content)content).Clone(); copy.ParentId = parentId; - // A copy should never be set to published - // automatically even if the original was - this.UnPublish(copy, userId); + // A copy should never be set to published automatically even if the original was. + copy.ChangePublishedState(PublishedState.Unpublished); if (Copying.IsRaisedEventCancelled(new CopyEventArgs(content, copy, parentId), this)) return null; @@ -806,14 +805,15 @@ namespace Umbraco.Core.Services repository.AddOrUpdate(copy); uow.Commit(); - var uploadFieldId = new Guid("5032a6e6-69e3-491d-bb28-cd31cd11086c"); - if (content.Properties.Any(x => x.PropertyType.DataTypeId == uploadFieldId)) + //Special case for the Upload DataType + var uploadDataTypeId = new Guid("5032a6e6-69e3-491d-bb28-cd31cd11086c"); + if (content.Properties.Any(x => x.PropertyType.DataTypeId == uploadDataTypeId)) { bool isUpdated = false; var fs = FileSystemProviderManager.Current.GetFileSystemProvider(); //Loop through properties to check if the content contains media that should be deleted - foreach (var property in content.Properties.Where(x => x.PropertyType.DataTypeId == uploadFieldId + foreach (var property in content.Properties.Where(x => x.PropertyType.DataTypeId == uploadDataTypeId && string.IsNullOrEmpty(x.Value.ToString()) == false)) { if (fs.FileExists(IOHelper.MapPath(property.Value.ToString()))) @@ -841,6 +841,17 @@ namespace Umbraco.Core.Services uow.Commit(); } } + + //Special case for the Tags DataType + var tagsDataTypeId = new Guid("4023e540-92f5-11dd-ad8b-0800200c9a66"); + if (content.Properties.Any(x => x.PropertyType.DataTypeId == tagsDataTypeId)) + { + var tags = uow.Database.Fetch("WHERE nodeId = @Id", new {Id = content.Id}); + foreach (var tag in tags) + { + uow.Database.Insert(new TagRelationshipDto {NodeId = copy.Id, TagId = tag.TagId}); + } + } } //NOTE This 'Relation' part should eventually be delegated to a RelationService From b7fedb664bad239363748dd573fb33d863592033 Mon Sep 17 00:00:00 2001 From: Morten Christensen Date: Thu, 24 Jan 2013 14:47:24 -0100 Subject: [PATCH 5/8] Refactoring DatabaseSchemaCreation to allow for schema validation. --- .../Initial/DatabaseSchemaCreation.cs | 182 ++++++++++-------- src/Umbraco.Core/Umbraco.Core.csproj | 2 + 2 files changed, 105 insertions(+), 79 deletions(-) diff --git a/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaCreation.cs b/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaCreation.cs index 4e2f60eb3c..9392c047bf 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaCreation.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaCreation.cs @@ -1,4 +1,8 @@ -using Umbraco.Core.Models.Rdbms; +using System; +using System.Collections.Generic; +using System.Linq; +using Umbraco.Core.Events; +using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Migrations.Initial { @@ -7,13 +11,110 @@ namespace Umbraco.Core.Persistence.Migrations.Initial /// internal class DatabaseSchemaCreation { + #region Private Members private readonly Database _database; + private static readonly Dictionary OrderedTables = new Dictionary + { + {0, typeof (NodeDto)}, + {1, typeof (TemplateDto)}, + {2, typeof (ContentDto)}, + {3, typeof (ContentVersionDto)}, + {4, typeof (DocumentDto)}, + {5, typeof (ContentTypeDto)}, + {6, typeof (DocumentTypeDto)}, + {7, typeof (DataTypeDto)}, + {8, typeof (DataTypePreValueDto)}, + {9, typeof (DictionaryDto)}, + {10, typeof (LanguageTextDto)}, + {11, typeof (LanguageDto)}, + {12, typeof (DomainDto)}, + {13, typeof (LogDto)}, + {14, typeof (MacroDto)}, + {15, typeof (MacroPropertyTypeDto)}, + {16, typeof (MacroPropertyDto)}, + {17, typeof (MemberTypeDto)}, + {18, typeof (MemberDto)}, + {19, typeof (Member2MemberGroupDto)}, + {20, typeof (ContentXmlDto)}, + {21, typeof (PreviewXmlDto)}, + {22, typeof (PropertyTypeGroupDto)}, + {23, typeof (PropertyTypeDto)}, + {24, typeof (PropertyDataDto)}, + {25, typeof (RelationTypeDto)}, + {26, typeof (RelationDto)}, + {27, typeof (StylesheetDto)}, + {28, typeof (StylesheetPropertyDto)}, + {29, typeof (TagDto)}, + {30, typeof (TagRelationshipDto)}, + {31, typeof (UserLoginDto)}, + {32, typeof (UserTypeDto)}, + {33, typeof (UserDto)}, + {34, typeof (TaskTypeDto)}, + {35, typeof (TaskDto)}, + {36, typeof (ContentType2ContentTypeDto)}, + { + 37, + typeof (ContentTypeAllowedContentTypeDto) + }, + {38, typeof (User2AppDto)}, + {39, typeof (User2NodeNotifyDto)}, + {40, typeof (User2NodePermissionDto)} + }; + #endregion public DatabaseSchemaCreation(Database database) { _database = database; } + /// + /// Initialize the database by creating the umbraco db schema + /// + public void InitializeDatabaseSchema() + { + var e = new DatabaseCreationEventArgs(); + FireBeforeCreation(e); + + if (!e.Cancel) + { + foreach (var item in OrderedTables.OrderBy(x => x.Key)) + { + _database.CreateTable(false, item.Value); + } + } + + FireAfterCreation(e); + } + + /// + /// Validates the schema of the current database + /// + public DatabaseSchemaResult ValidateSchema() + { + var result = new DatabaseSchemaResult(); + + foreach (var item in OrderedTables.OrderBy(x => x.Key)) + { + var tableNameAttribute = item.Value.FirstAttribute(); + if (tableNameAttribute != null) + { + var tableExist = _database.TableExist(tableNameAttribute.Value); + if (tableExist) + { + result.Successes.Add(tableNameAttribute.Value, "Table exists"); + } + else + { + result.Errors.Add(tableNameAttribute.Value, "Table does not exist"); + } + } + } + + return result; + } + + #region Events + /// /// The save event handler /// @@ -51,83 +152,6 @@ namespace Umbraco.Core.Persistence.Migrations.Initial } } - /// - /// Initialize the database by creating the umbraco db schema - /// - public void InitializeDatabaseSchema() - { - var e = new DatabaseCreationEventArgs(); - FireBeforeCreation(e); - - if (!e.Cancel) - { - _database.CreateTable(); - - _database.CreateTable(); - - _database.CreateTable(); - _database.CreateTable(); - _database.CreateTable(); - - _database.CreateTable(); - _database.CreateTable(); - - //_database.CreateTable(); - //_database.CreateTable(); - - _database.CreateTable(); - _database.CreateTable(); - - _database.CreateTable(); - _database.CreateTable(); - - _database.CreateTable(); - _database.CreateTable(); - - _database.CreateTable(); - - _database.CreateTable(); - _database.CreateTable(); - _database.CreateTable(); - - _database.CreateTable(); - _database.CreateTable(); - _database.CreateTable(); - - _database.CreateTable(); - _database.CreateTable(); - - _database.CreateTable(); - _database.CreateTable(); - _database.CreateTable(); - - _database.CreateTable(); - _database.CreateTable(); - - _database.CreateTable(); - _database.CreateTable(); - - _database.CreateTable(); - _database.CreateTable(); - - _database.CreateTable(); - _database.CreateTable(); - _database.CreateTable(); - - _database.CreateTable(); - _database.CreateTable(); - - _database.CreateTable(); - _database.CreateTable(); - - _database.CreateTable(); - _database.CreateTable(); - _database.CreateTable(); - } - - FireAfterCreation(e); - } + #endregion } - - internal class DatabaseCreationEventArgs : System.ComponentModel.CancelEventArgs{} } \ No newline at end of file diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 2b556f637f..0aeab69175 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -123,6 +123,7 @@ + @@ -265,6 +266,7 @@ + From f6e354314ba354710855b49b05357d958a13e91b Mon Sep 17 00:00:00 2001 From: Morten Christensen Date: Thu, 24 Jan 2013 14:47:44 -0100 Subject: [PATCH 6/8] Minor optimization to SaveAndPublish method in ContentService. --- src/Umbraco.Core/Services/ContentService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs index 67e0982019..da443413c7 100644 --- a/src/Umbraco.Core/Services/ContentService.cs +++ b/src/Umbraco.Core/Services/ContentService.cs @@ -1252,7 +1252,7 @@ namespace Umbraco.Core.Services //We need to check if children and their publish state to ensure that we republish content that was previously published if (HasChildren(content.Id)) { - var children = GetChildrenDeep(content.Id); + var children = GetDescendants(content); var shouldBeRepublished = children.Where(child => HasPublishedVersion(child.Id)); if (omitCacheRefresh == false) From 82455136bb77a07402065b1842589a7b17d87b57 Mon Sep 17 00:00:00 2001 From: Morten Christensen Date: Thu, 24 Jan 2013 14:59:03 -0100 Subject: [PATCH 7/8] Missing files --- .../Events/DatabaseCreationEventArgs.cs | 4 ++++ .../Migrations/Initial/DatabaseSchemaResult.cs | 17 +++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 src/Umbraco.Core/Events/DatabaseCreationEventArgs.cs create mode 100644 src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaResult.cs diff --git a/src/Umbraco.Core/Events/DatabaseCreationEventArgs.cs b/src/Umbraco.Core/Events/DatabaseCreationEventArgs.cs new file mode 100644 index 0000000000..5fb9cc0d97 --- /dev/null +++ b/src/Umbraco.Core/Events/DatabaseCreationEventArgs.cs @@ -0,0 +1,4 @@ +namespace Umbraco.Core.Events +{ + internal class DatabaseCreationEventArgs : System.ComponentModel.CancelEventArgs{} +} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaResult.cs b/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaResult.cs new file mode 100644 index 0000000000..71997028ce --- /dev/null +++ b/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaResult.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; + +namespace Umbraco.Core.Persistence.Migrations.Initial +{ + public class DatabaseSchemaResult + { + public DatabaseSchemaResult() + { + Errors = new Dictionary(); + Successes = new Dictionary(); + } + + public IDictionary Errors { get; set; } + + public IDictionary Successes { get; set; } + } +} \ No newline at end of file From d3f9e13eae6457fe78e847f551be1e6258c481c6 Mon Sep 17 00:00:00 2001 From: Morten Christensen Date: Thu, 24 Jan 2013 14:59:58 -0100 Subject: [PATCH 8/8] Adding ncrunch ignore --- .hgignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgignore b/.hgignore index ee97264e54..71050adcb1 100644 --- a/.hgignore +++ b/.hgignore @@ -14,6 +14,7 @@ syntax: glob obj/ [Rr]elease*/ _ReSharper*/ +_NCrunch_*/ *.ncrunchsolution *.ncrunchsolution.user *.ncrunchproject