From 98666530b4f99b6147f53d071d557761d95c02c0 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Wed, 5 Aug 2015 17:11:04 +0100 Subject: [PATCH] #4097: Changed Import to accommodate expected behavior as defined as part of the issue. This formalizes what we decided should happen when importing recipes in combination with various possible statuses a content item can have and how the import affects this. --- .../DefaultContentManagerImportTests.cs | 224 ++++++++++++++++++ .../Handlers/DummyHandler.cs | 12 + .../Orchard.Framework.Tests.csproj | 2 + .../Services/IdentifierResolverSelector.cs | 2 +- .../Services/AliasResolverSelector.cs | 2 +- .../Services/UserResolverSelector.cs | 2 +- .../Services/LayerResolverSelector.cs | 2 +- .../DefaultContentManager.cs | 9 +- 8 files changed, 249 insertions(+), 6 deletions(-) create mode 100644 src/Orchard.Tests/ContentManagement/DefaultContentManagerImportTests.cs create mode 100644 src/Orchard.Tests/ContentManagement/Handlers/DummyHandler.cs diff --git a/src/Orchard.Tests/ContentManagement/DefaultContentManagerImportTests.cs b/src/Orchard.Tests/ContentManagement/DefaultContentManagerImportTests.cs new file mode 100644 index 000000000..d33d326c9 --- /dev/null +++ b/src/Orchard.Tests/ContentManagement/DefaultContentManagerImportTests.cs @@ -0,0 +1,224 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Xml.Linq; +using Autofac; +using Moq; +using NUnit.Framework; +using Orchard.Caching; +using Orchard.ContentManagement; +using Orchard.ContentManagement.Drivers; +using Orchard.ContentManagement.Drivers.Coordinators; +using Orchard.ContentManagement.Handlers; +using Orchard.ContentManagement.MetaData; +using Orchard.ContentManagement.Records; +using Orchard.Core.Common.Drivers; +using Orchard.Core.Common.Handlers; +using Orchard.Core.Common.Models; +using Orchard.Core.Common.Services; +using Orchard.Core.Title.Drivers; +using Orchard.Core.Title.Handlers; +using Orchard.Core.Title.Models; +using Orchard.Tests.ContentManagement.Handlers; +using Orchard.Tests.Stubs; + +namespace Orchard.Tests.ContentManagement { + [TestFixture] + public class DefaultContentManagerImportTests : DatabaseEnabledTestsBase { + private const string ContentTypeName = "Dummy"; + private IContentManager _contentManager; + private Mock _contentDefinitionManager; + + protected override IEnumerable DatabaseTypes { + get { + return new[] { + typeof (ContentTypeRecord), + typeof (ContentItemRecord), + typeof (ContentItemVersionRecord), + typeof (TitlePartRecord), + typeof (IdentityPartRecord) + }; + } + } + + public override void Register(ContainerBuilder builder) { + _contentDefinitionManager = new Mock(); + + builder.RegisterType().As(); + builder.RegisterType().As(); + builder.RegisterType().As(); + builder.RegisterType().As(); + builder.RegisterType().As(); + builder.RegisterType().As(); + builder.RegisterType().As(); + builder.RegisterType().As(); + builder.RegisterType().As(); + builder.RegisterType().As(); + builder.RegisterType().As(); + builder.RegisterType().As(); + builder.RegisterType().As(); + builder.RegisterInstance(_contentDefinitionManager.Object); + } + + public override void Init() { + base.Init(); + _contentManager = _container.Resolve(); + } + + [Test] + public void ImportingDraftShouldCreateNewDraft() { + // Create a draft element and import it. + var element = CreateContentElement(version: "Draft"); + Import(element); + + // Assert that we have the one draft. + var allContentItems = _contentManager.Query(VersionOptions.Latest).List().ToList(); + Assert.That(allContentItems.Count, Is.EqualTo(1)); + Assert.That(allContentItems[0].IsPublished(), Is.False); + + // Assert that the draft has been created with the imported values. + var item = _contentManager.Get(allContentItems[0].Id, VersionOptions.Latest); + Assert.That(item.As().Title, Is.EqualTo("Dummy")); + } + + [Test] + public void ImportingPublishedShouldCreateNewPublished() { + // Create a published element and import it. + var element = CreateContentElement(version: "Published"); + Import(element); + + // Assert that we have the one published item. + var allContentItems = _contentManager.Query(VersionOptions.Latest).List().ToList(); + Assert.That(allContentItems.Count, Is.EqualTo(1)); + Assert.That(allContentItems[0].IsPublished(), Is.True); + + // Assert that the published item has been created with the imported values. + var item = _contentManager.Get(allContentItems[0].Id, VersionOptions.Latest); + Assert.That(item.As().Title, Is.EqualTo("Dummy")); + } + + [Test] + public void ImportingDraftShouldUpdateExistingDraft() { + // Create a draft and an export of it. + var contentItem = _contentManager.New(ContentTypeName); + contentItem.As().Title = "Dummy"; + _contentManager.Create(contentItem, VersionOptions.Draft); + var element = _contentManager.Export(contentItem); + + // Change the title and then import the element. + element.Element("TitlePart").Attr("Title", "Smarty"); + Import(element); + + // Assert that we still have the one draft. + var allContentItems = _contentManager.Query(VersionOptions.Latest).List().ToList(); + Assert.That(allContentItems.Count, Is.EqualTo(1)); + var updatedContentItem = allContentItems[0]; + Assert.That(updatedContentItem.As().Identifier, Is.EqualTo(contentItem.As().Identifier)); + + // Assert that the draft has been updated with the imported change. + Assert.That(updatedContentItem.As().Title, Is.EqualTo("Smarty")); + } + + [Test] + public void ImportingDraftShouldCreateNewDraftForExistingPublished() { + // Create a draft and an export of it. + var contentItem = _contentManager.New(ContentTypeName); + contentItem.As().Title = "Draft Dummy"; + _contentManager.Create(contentItem, VersionOptions.Draft); + var element = _contentManager.Export(contentItem); + + // Change the title and publish the draft. + contentItem.As().Title = "Published Dummy"; + _contentManager.Publish(contentItem); + + // Import the element representing the draft. + Import(element); + + // Assert that version one is still the published one but no more the latest. + var published = _contentManager.Get(contentItem.Id, VersionOptions.Number(1)); + Assert.That(published.VersionRecord.Published, Is.True); + Assert.That(published.VersionRecord.Latest, Is.False); + Assert.That(published.As().Title, Is.EqualTo("Published Dummy")); + + // Assert that a new draft was created for the published item. + var latest = _contentManager.Get(contentItem.Id, VersionOptions.Number(2)); + Assert.That(latest.VersionRecord.Published, Is.False); + Assert.That(latest.VersionRecord.Latest, Is.True); + Assert.That(latest.As().Title, Is.EqualTo("Draft Dummy")); + } + + [Test] + public void ImportingPublishedShouldUpdateAndPublishExistingDraft() { + // Create a draft and an export of it. + var contentItem = _contentManager.New(ContentTypeName); + contentItem.As().Title = "Draft Dummy"; + _contentManager.Create(contentItem, VersionOptions.Draft); + var element = _contentManager.Export(contentItem); + + // Change the title and publish the draft. + element.Element("TitlePart").Attr("Title", "Published Dummy"); + element.Attr("Status", "Published"); + + // Import the element representing the published version. + Import(element); + + // Assert that no additional version was created. + var allVersions = _contentManager.GetAllVersions(contentItem.Id).ToList(); + Assert.That(allVersions.Count, Is.EqualTo(1)); + + // Assert that the item has been updated and published. + var published = _contentManager.Get(contentItem.Id, VersionOptions.Number(1)); + Assert.That(published.VersionRecord.Published, Is.True); + Assert.That(published.VersionRecord.Latest, Is.True); + Assert.That(published.As().Title, Is.EqualTo("Published Dummy")); + } + + [Test] + public void ImportingPublishedShouldUpdateAndPublishExistingPublishedItem() { + // Create a published item and an export of it. + var contentItem = _contentManager.New(ContentTypeName); + contentItem.As().Title = "Published Dummy"; + _contentManager.Create(contentItem, VersionOptions.Published); + var element = _contentManager.Export(contentItem); + + // Change the title and publish the item. + element.Element("TitlePart").Attr("Title", "Published Smarty"); + + // Import the element representing the updated published version. + Import(element); + + // Assert that an additional version was created. + var allVersions = _contentManager.GetAllVersions(contentItem.Id).ToList(); + Assert.That(allVersions.Count, Is.EqualTo(2)); + + // Assert that no additional item was created. + var allItems = _contentManager.Query(VersionOptions.Latest).List().ToList(); + Assert.That(allItems.Count, Is.EqualTo(1)); + + // Assert that the item has been updated and published. + var published = _contentManager.Get(contentItem.Id, VersionOptions.Number(2)); + Assert.That(published.VersionRecord.Published, Is.True); + Assert.That(published.VersionRecord.Latest, Is.True); + Assert.That(published.As().Title, Is.EqualTo("Published Smarty")); + } + + private void Import(XElement element) { + var importContentSession = new ImportContentSession(_contentManager); + _contentManager.Import(element, importContentSession); + } + + private XElement CreateContentElement(string title = "Dummy", string identity = "123456789012345678901234567890ab", string version = null) { + var identifier = "/Identifier=" + identity; + var element = + new XElement("Dummy", + version != null ? new XAttribute("Status", version) : default(XAttribute), + new XAttribute("Id", identifier), + new XElement("IdentityPart", + new XAttribute("Identifier", identity)), + new XElement("TitlePart", + new XAttribute("Title", title))); + + return element; + } + } +} \ No newline at end of file diff --git a/src/Orchard.Tests/ContentManagement/Handlers/DummyHandler.cs b/src/Orchard.Tests/ContentManagement/Handlers/DummyHandler.cs new file mode 100644 index 000000000..4e54ccec4 --- /dev/null +++ b/src/Orchard.Tests/ContentManagement/Handlers/DummyHandler.cs @@ -0,0 +1,12 @@ +using Orchard.ContentManagement.Handlers; +using Orchard.Core.Common.Models; +using Orchard.Core.Title.Models; + +namespace Orchard.Tests.ContentManagement.Handlers { + public class DummyHandler : ContentHandler { + public DummyHandler() { + Filters.Add(new ActivatingFilter("Dummy")); + Filters.Add(new ActivatingFilter("Dummy")); + } + } +} diff --git a/src/Orchard.Tests/Orchard.Framework.Tests.csproj b/src/Orchard.Tests/Orchard.Framework.Tests.csproj index 7e37eb6b5..c26fc9d28 100644 --- a/src/Orchard.Tests/Orchard.Framework.Tests.csproj +++ b/src/Orchard.Tests/Orchard.Framework.Tests.csproj @@ -162,6 +162,8 @@ Code + + diff --git a/src/Orchard.Web/Core/Common/Services/IdentifierResolverSelector.cs b/src/Orchard.Web/Core/Common/Services/IdentifierResolverSelector.cs index 1dff609c5..6e6fc8474 100644 --- a/src/Orchard.Web/Core/Common/Services/IdentifierResolverSelector.cs +++ b/src/Orchard.Web/Core/Common/Services/IdentifierResolverSelector.cs @@ -30,7 +30,7 @@ namespace Orchard.Core.Common.Services { } return _contentManager - .Query() + .Query(VersionOptions.Latest) .Where(p => p.Identifier == identifier) .List() .Where(c => ContentIdentity.ContentIdentityEqualityComparer.AreEquivalent( diff --git a/src/Orchard.Web/Modules/Orchard.Autoroute/Services/AliasResolverSelector.cs b/src/Orchard.Web/Modules/Orchard.Autoroute/Services/AliasResolverSelector.cs index 7de2347d0..96f60715d 100644 --- a/src/Orchard.Web/Modules/Orchard.Autoroute/Services/AliasResolverSelector.cs +++ b/src/Orchard.Web/Modules/Orchard.Autoroute/Services/AliasResolverSelector.cs @@ -29,7 +29,7 @@ namespace Orchard.Autoroute.Services { } return _contentManager - .Query() + .Query(VersionOptions.Latest) .Where(p => p.DisplayAlias == identifier) .List(); } diff --git a/src/Orchard.Web/Modules/Orchard.Users/Services/UserResolverSelector.cs b/src/Orchard.Web/Modules/Orchard.Users/Services/UserResolverSelector.cs index 0641551cc..5011ba0c6 100644 --- a/src/Orchard.Web/Modules/Orchard.Users/Services/UserResolverSelector.cs +++ b/src/Orchard.Web/Modules/Orchard.Users/Services/UserResolverSelector.cs @@ -30,7 +30,7 @@ namespace Orchard.Users.Services { } return _contentManager - .Query() + .Query(VersionOptions.Latest) .Where(p => p.UserName == identifier) .List() .Where(c => ContentIdentity.ContentIdentityEqualityComparer.AreEquivalent( diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Services/LayerResolverSelector.cs b/src/Orchard.Web/Modules/Orchard.Widgets/Services/LayerResolverSelector.cs index 9b4b95c13..655e5e2d9 100644 --- a/src/Orchard.Web/Modules/Orchard.Widgets/Services/LayerResolverSelector.cs +++ b/src/Orchard.Web/Modules/Orchard.Widgets/Services/LayerResolverSelector.cs @@ -30,7 +30,7 @@ namespace Orchard.Widgets.Services { } return _contentManager - .Query() + .Query(VersionOptions.Latest) .Where(p => p.Name == identifier) .List() .Where(c => ContentIdentity.ContentIdentityEqualityComparer.AreEquivalent( diff --git a/src/Orchard/ContentManagement/DefaultContentManager.cs b/src/Orchard/ContentManagement/DefaultContentManager.cs index 8272cac8a..048ea4dc0 100644 --- a/src/Orchard/ContentManagement/DefaultContentManager.cs +++ b/src/Orchard/ContentManagement/DefaultContentManager.cs @@ -746,8 +746,13 @@ namespace Orchard.ContentManagement { Create(item); } } + else { + // If the existing item is published, create a new draft for that item. + if (item.IsPublished()) + item = Get(item.Id, VersionOptions.DraftRequired); + } - // create a version record if import handlers need it + // Create a version record if import handlers need it. if(item.VersionRecord == null) { item.VersionRecord = new ContentItemVersionRecord { ContentItemRecord = new ContentItemRecord { @@ -770,7 +775,7 @@ namespace Orchard.ContentManagement { var savedItem = Get(item.Id, VersionOptions.Latest); - // the item has been pre-created in the first pass of the import, create it in db + // The item has been pre-created in the first pass of the import, create it in db. if(savedItem == null) { if (status != null && status.Value == "Draft") { Create(item, VersionOptions.Draft);