Adding rollback method on content manager.

The Rollback method allows for reverting to a previous version by creating a new version based on the specified previous one.
This commit is contained in:
Sipke Schoorstra
2014-10-21 01:18:28 -07:00
parent 57b09bc697
commit 9106dce276
11 changed files with 114 additions and 5 deletions

View File

@@ -146,6 +146,14 @@ namespace Orchard.ContentManagement {
versionRecord = _contentItemVersionRepository.Get(options.VersionRecordId);
}
else if (options.VersionNumber != 0) {
// short-circuit if item held in session
if (session.RecallVersionNumber(id, options.VersionRecordId, out contentItem)) {
return contentItem;
}
versionRecord = _contentItemVersionRepository.Get(x => x.ContentItemRecord.Id == id && x.Number == options.VersionNumber);
}
else if (session.RecallContentRecordId(id, out contentItem)) {
// try to reload a previously loaded published content item
@@ -486,9 +494,7 @@ namespace Orchard.ContentManagement {
if (contentItem.VersionRecord == null) {
// produce root record to determine the model id
contentItem.VersionRecord = new ContentItemVersionRecord {
ContentItemRecord = new ContentItemRecord {
},
ContentItemRecord = new ContentItemRecord(),
Number = 1,
Latest = true,
Published = true
@@ -559,6 +565,43 @@ namespace Orchard.ContentManagement {
return importContentSession.Get(copyId, element.Name.LocalName);
}
public virtual ContentItem Rollback(ContentItem contentItem, VersionOptions options) {
// Invoke handlers.
Handlers.Invoke(handler => handler.RollingBack(new RollbackContentContext(contentItem, options)), Logger);
// Get the latest version.
var latestVersionRecord = contentItem.Record.Versions.Single(x => x.Latest);
// Unpublish the latest version.
latestVersionRecord.Published = false;
// Get the specified version.
var specifiedVersionContentItem =
contentItem.VersionRecord.Number == options.VersionNumber || contentItem.VersionRecord.Id == options.VersionRecordId
? contentItem
: Get(contentItem.Id, options);
// Create a new version record based on the specified version record.
var rolledBackContentItem = BuildNewVersion(specifiedVersionContentItem);
rolledBackContentItem.VersionRecord.Published = options.IsPublished;
// Deferring the assignment of ContentType as loading a Record might force NHibernate to AutoFlush
// the ContentPart, and needs the ContentItemRecord to be created before (created in previous statement)
rolledBackContentItem.VersionRecord.ContentItemRecord.ContentType = AcquireContentTypeRecord(contentItem.ContentType);
// Invoke handlers.
Handlers.Invoke(handler => handler.RolledBack(new RollbackContentContext(rolledBackContentItem, options)), Logger);
if (options.IsPublished) {
var publishContext = new PublishContentContext(rolledBackContentItem, previousItemVersionRecord: latestVersionRecord);
Handlers.Invoke(handler => handler.Publishing(publishContext), Logger);
Handlers.Invoke(handler => handler.Published(publishContext), Logger);
}
return rolledBackContentItem;
}
/// <summary>
/// Lookup for a content item based on a <see cref="ContentIdentity"/>. If multiple
/// resolvers can give a result, the one with the highest priority is used. As soon as

View File

@@ -1,12 +1,15 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
namespace Orchard.ContentManagement {
public class DefaultContentManagerSession : IContentManagerSession {
private readonly IDictionary<int, ContentItem> _itemByVersionRecordId = new Dictionary<int, ContentItem>();
private readonly IDictionary<Tuple<int, int>, ContentItem> _itemByVersionNumber = new Dictionary<Tuple<int, int>, ContentItem>();
private readonly IDictionary<int, ContentItem> _publishedItemsByContentRecordId = new Dictionary<int, ContentItem>();
public void Store(ContentItem item) {
_itemByVersionRecordId.Add(item.VersionRecord.Id, item);
_itemByVersionNumber.Add(Tuple.Create(item.Id, item.Version), item);
// is it the Published version ?
if (item.VersionRecord.Latest && item.VersionRecord.Published) {
@@ -18,6 +21,10 @@ namespace Orchard.ContentManagement {
return _itemByVersionRecordId.TryGetValue(id, out item);
}
public bool RecallVersionNumber(int id, int version, out ContentItem item) {
return _itemByVersionNumber.TryGetValue(Tuple.Create(id, version), out item);
}
public bool RecallContentRecordId(int id, out ContentItem item) {
return _publishedItemsByContentRecordId.TryGetValue(id, out item);
}

View File

@@ -124,6 +124,8 @@ namespace Orchard.ContentManagement.Handlers {
public Action<RemoveContentContext, TPart> OnRemoved { get; set; }
public Action<IndexContentContext, TPart> OnIndexing { get; set; }
public Action<IndexContentContext, TPart> OnIndexed { get; set; }
public Action<RollbackContentContext, TPart> OnRollingBack { get; set; }
public Action<RollbackContentContext, TPart> OnRolledBack { get; set; }
protected override void Activated(ActivatedContentContext context, TPart instance) {
if (OnActivated != null) OnActivated(context, instance);
}
@@ -183,7 +185,14 @@ namespace Orchard.ContentManagement.Handlers {
if ( OnIndexed != null )
OnIndexed(context, instance);
}
protected override void RollingBack(RollbackContentContext context, TPart instance) {
if (OnRollingBack != null)
OnRollingBack(context, instance);
}
protected override void RolledBack(RollbackContentContext context, TPart instance) {
if (OnRolledBack != null)
OnRolledBack(context, instance);
}
}
class InlineTemplateFilter<TPart> : TemplateFilterBase<TPart> where TPart : class, IContent {
@@ -341,6 +350,14 @@ namespace Orchard.ContentManagement.Handlers {
Exported(context);
}
void IContentHandler.RollingBack(RollbackContentContext context) {
RollingBack(context);
}
void IContentHandler.RolledBack(RollbackContentContext context) {
RolledBack(context);
}
void IContentHandler.GetContentItemMetadata(GetContentItemMetadataContext context) {
foreach (var filter in Filters.OfType<IContentTemplateFilter>())
filter.GetContentItemMetadata(context);
@@ -396,6 +413,8 @@ namespace Orchard.ContentManagement.Handlers {
protected virtual void Imported(ImportContentContext context) { }
protected virtual void Exporting(ExportContentContext context) { }
protected virtual void Exported(ExportContentContext context) { }
protected virtual void RollingBack(RollbackContentContext context) { }
protected virtual void RolledBack(RollbackContentContext context) { }
protected virtual void GetItemMetadata(GetContentItemMetadataContext context) { }
protected virtual void BuildDisplayShape(BuildDisplayContext context) { }

View File

@@ -24,6 +24,8 @@
public virtual void Imported(ImportContentContext context) {}
public virtual void Exporting(ExportContentContext context) {}
public virtual void Exported(ExportContentContext context) {}
public virtual void RollingBack(RollbackContentContext context) { }
public virtual void RolledBack(RollbackContentContext context) { }
public virtual void GetContentItemMetadata(GetContentItemMetadataContext context) {}
public virtual void BuildDisplay(BuildDisplayContext context) {}

View File

@@ -29,5 +29,7 @@
void BuildDisplay(BuildDisplayContext context);
void BuildEditor(BuildEditorContext context);
void UpdateEditor(UpdateEditorContext context);
void RollingBack(RollbackContentContext context);
void RolledBack(RollbackContentContext context);
}
}

View File

@@ -19,5 +19,7 @@ namespace Orchard.ContentManagement.Handlers {
void Removed(RemoveContentContext context);
void Indexing(IndexContentContext context);
void Indexed(IndexContentContext context);
void RollingBack(RollbackContentContext context);
void RolledBack(RollbackContentContext context);
}
}

View File

@@ -0,0 +1,9 @@
namespace Orchard.ContentManagement.Handlers {
public class RollbackContentContext : ContentContextBase {
public VersionOptions VersionOptions { get; set; }
public RollbackContentContext(ContentItem contentItem, VersionOptions versionOptions) : base(contentItem) {
VersionOptions = versionOptions;
}
}
}

View File

@@ -21,6 +21,8 @@ namespace Orchard.ContentManagement.Handlers {
protected virtual void Removed(RemoveContentContext context, TPart instance) { }
protected virtual void Indexing(IndexContentContext context, TPart instance) { }
protected virtual void Indexed(IndexContentContext context, TPart instance) { }
protected virtual void RollingBack(RollbackContentContext context, TPart instance) { }
protected virtual void RolledBack(RollbackContentContext context, TPart instance) { }
void IContentStorageFilter.Activated(ActivatedContentContext context) {
if (context.ContentItem.Is<TPart>())
@@ -117,5 +119,14 @@ namespace Orchard.ContentManagement.Handlers {
Indexed(context, context.ContentItem.As<TPart>());
}
void IContentStorageFilter.RollingBack(RollbackContentContext context) {
if (context.ContentItem.Is<TPart>())
RollingBack(context, context.ContentItem.As<TPart>());
}
void IContentStorageFilter.RolledBack(RollbackContentContext context) {
if (context.ContentItem.Is<TPart>())
RolledBack(context, context.ContentItem.As<TPart>());
}
}
}

View File

@@ -41,6 +41,13 @@ namespace Orchard.ContentManagement {
/// <returns>Clone of the item</returns>
ContentItem Clone(ContentItem contentItem);
/// <summary>
/// Rolls back the specified content item by creating a new version based on the specified version.
/// </summary>
/// <param name="contentItem">The content item to roll back.</param>
/// <param name="options">The version to roll back to. Either specify the version record id, version number, and IsPublished to publish the new version.</param>
/// <returns>Returns the latest version of the content item, which is based on the specified version.</returns>
ContentItem Rollback(ContentItem contentItem, VersionOptions options);
/// <summary>
/// Gets the content item with the specified id
@@ -169,6 +176,11 @@ namespace Orchard.ContentManagement {
/// </summary>
public static VersionOptions VersionRecord(int id) { return new VersionOptions { VersionRecordId = id }; }
/// <summary>
/// Creates a new version based on the specified version number.
/// </summary>
public static VersionOptions Rollback(int version, bool publish = false) { return new VersionOptions { VersionNumber = version, IsPublished = publish}; }
public bool IsLatest { get; private set; }
public bool IsPublished { get; private set; }
public bool IsDraft { get; private set; }

View File

@@ -2,6 +2,7 @@
public interface IContentManagerSession : IDependency {
void Store(ContentItem item);
bool RecallVersionRecordId(int id, out ContentItem item);
bool RecallVersionNumber(int id, int version, out ContentItem item);
bool RecallContentRecordId(int id, out ContentItem item);
void Clear();

View File

@@ -149,6 +149,7 @@
<Compile Include="ContentManagement\Aspects\ILocalizableAspect.cs" />
<Compile Include="ContentManagement\ContentIdentity.cs" />
<Compile Include="ContentManagement\DefaultHqlQuery.cs" />
<Compile Include="ContentManagement\Handlers\RollbackContentContext.cs" />
<Compile Include="ContentManagement\InfosetHelper.cs" />
<Compile Include="ContentManagement\XmlHelper.cs" />
<Compile Include="ContentManagement\Handlers\TemplateFilterForPart.cs" />