Adding support for import/export.

This enables elements to export additional information such as content item references by storing their identities.
This commit is contained in:
Sipke Schoorstra 2014-11-13 18:25:05 -08:00
parent fbac586231
commit a0390c88bd
25 changed files with 228 additions and 13 deletions

View File

@ -104,7 +104,7 @@ namespace Orchard.Layouts.Controllers {
var describeContext = DescribeElementsContext.Empty;
var descriptor = _elementManager.GetElementDescriptorByTypeName(describeContext, blueprint.BaseElementTypeName);
var state = ElementStateHelper.Deserialize(blueprint.BaseElementState);
var element = _elementManager.ActivateElement(descriptor, new ActivateElementArgs { ElementState = state });
var element = _elementManager.ActivateElement(descriptor, new ActivateElementArgs { State = state });
var context = CreateEditorContext(element, state);
var editorResult = _elementManager.BuildEditor(context);
@ -127,7 +127,7 @@ namespace Orchard.Layouts.Controllers {
var describeContext = DescribeElementsContext.Empty;
var descriptor = _elementManager.GetElementDescriptorByTypeName(describeContext, blueprint.BaseElementTypeName);
var state = ElementStateHelper.Deserialize(model.ElementState).Combine(Request.Form.ToDictionary());
var element = _elementManager.ActivateElement(descriptor, new ActivateElementArgs { ElementState = state });
var element = _elementManager.ActivateElement(descriptor, new ActivateElementArgs { State = state });
var context = CreateEditorContext(element, elementState: state);
var editorResult = _elementManager.UpdateEditor(context);
var viewModel = new EditElementBlueprintViewModel {

View File

@ -96,7 +96,7 @@ namespace Orchard.Layouts.Controllers {
var describeContext = CreateDescribeContext(layoutId, contentType);
var descriptor = _elementManager.GetElementDescriptorByTypeName(describeContext, model.TypeName);
var state = ElementStateHelper.Deserialize(model.ElementState).Combine(Request.Form.ToDictionary());
var element = _elementManager.ActivateElement(descriptor, new ActivateElementArgs { ElementState = state });
var element = _elementManager.ActivateElement(descriptor, new ActivateElementArgs { State = state });
var context = CreateEditorContext(describeContext.Content, element, elementState: state);
var editorResult = _elementManager.UpdateEditor(context);
var viewModel = new EditElementViewModel {
@ -124,7 +124,7 @@ namespace Orchard.Layouts.Controllers {
var describeContext = CreateDescribeContext(layoutId, contentType);
var descriptor = _elementManager.GetElementDescriptorByTypeName(describeContext, typeName);
var state = ElementStateHelper.Deserialize(elementState);
var element = _elementManager.ActivateElement(descriptor, new ActivateElementArgs { ElementState = state });
var element = _elementManager.ActivateElement(descriptor, new ActivateElementArgs { State = state });
var context = CreateEditorContext(describeContext.Content, element, elementState: state);
var editorResult = _elementManager.BuildEditor(context);
@ -147,7 +147,7 @@ namespace Orchard.Layouts.Controllers {
var describeContext = CreateDescribeContext(layoutId, contentType);
var descriptor = _elementManager.GetElementDescriptorByTypeName(describeContext, model.TypeName);
var state = ElementStateHelper.Deserialize(model.ElementState).Combine(Request.Form.ToDictionary(), removeNonExistingItems: true);
var element = _elementManager.ActivateElement(descriptor, new ActivateElementArgs { ElementState = state });
var element = _elementManager.ActivateElement(descriptor, new ActivateElementArgs { State = state });
var context = CreateEditorContext(describeContext.Content, element, state);
var editorResult = _elementManager.UpdateEditor(context);
var viewModel = new EditElementViewModel {

View File

@ -1,8 +1,10 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using Orchard.ContentManagement;
using Orchard.Layouts.Framework.Display;
using Orchard.Layouts.Framework.Drivers;
using Orchard.Layouts.Helpers;
using Orchard.Layouts.ViewModels;
using ContentItem = Orchard.Layouts.Elements.ContentItem;
@ -44,6 +46,28 @@ namespace Orchard.Layouts.Drivers {
context.ElementShape.ContentItems = contentItemShapes;
}
protected override void OnExporting(ContentItem element, ExportElementContext context) {
var contentItems = GetContentItems(element.ContentItemIds).ToArray();
if (!contentItems.Any())
return;
var identities = contentItems.Select(x => _contentManager.GetItemMetadata(x).Identity.ToString()).ToArray();
context.ExportableState["ContentItems"] = String.Join(",", identities);
}
protected override void OnImporting(ContentItem element, ImportElementContext context) {
var contentItemIdentities = context.ExportableState.Get("ContentItems");
if (String.IsNullOrWhiteSpace(contentItemIdentities))
return;
var identities = contentItemIdentities.Split(',');
var contentItems = identities.Select(x => context.Session.GetItemFromSession(x)).Where(x => x != null);
element.ContentItemIds = contentItems.Select(x => x.Id);
}
protected IEnumerable<ContentManagement.ContentItem> GetContentItems(IEnumerable<int> ids) {
return _contentManager.GetMany<IContent>(ids, VersionOptions.Published, QueryHints.Empty).Select(x => x.ContentItem);
}

View File

@ -25,7 +25,7 @@ namespace Orchard.Layouts.Drivers {
var describeContext = CreateDescribeContext(part);
var descriptor = _elementManager.GetElementDescriptorByTypeName(describeContext, part.ElementTypeName);
var state = ElementStateHelper.Deserialize(part.ElementState);
var element = _elementManager.ActivateElement(descriptor, new ActivateElementArgs { ElementState = state});
var element = _elementManager.ActivateElement(descriptor, new ActivateElementArgs { State = state});
var elementShape = _elementDisplay.DisplayElement(element, part, displayType);
return shapeHelper.Parts_ElementWrapper(ElementShape: elementShape);
@ -41,7 +41,7 @@ namespace Orchard.Layouts.Drivers {
var describeContext = CreateDescribeContext(part);
var descriptor = _elementManager.GetElementDescriptorByTypeName(describeContext, part.ElementTypeName);
var state = ElementStateHelper.Deserialize(part.ElementState);
var element = _elementManager.ActivateElement(descriptor, new ActivateElementArgs { ElementState = state });
var element = _elementManager.ActivateElement(descriptor, new ActivateElementArgs { State = state });
var context = (ElementEditorContext)CreateEditorContext(describeContext.Content, element, updater, shapeHelper);
var editorResult = updater != null ? _elementManager.UpdateEditor(context) : _elementManager.BuildEditor(context);
var viewModel = new ElementWrapperPartViewModel {

View File

@ -1,8 +1,10 @@
using System.Linq;
using System;
using System.Linq;
using Orchard.ContentManagement;
using Orchard.Layouts.Elements;
using Orchard.Layouts.Framework.Display;
using Orchard.Layouts.Framework.Drivers;
using Orchard.Layouts.Helpers;
using Orchard.Layouts.ViewModels;
using Orchard.MediaLibrary.Models;
using ContentItem = Orchard.Layouts.Elements.ContentItem;
@ -37,6 +39,22 @@ namespace Orchard.Layouts.Drivers {
context.ElementShape.ImagePart = image;
}
protected override void OnExporting(Image element, ExportElementContext context) {
var image = element.MediaId != null ? GetImage(element.MediaId.Value) : default(ImagePart);
if (image == null)
return;
context.ExportableState["Image"] = _contentManager.GetItemMetadata(image).Identity.ToString();
}
protected override void OnImporting(Image element, ImportElementContext context) {
var imageIdentity = context.ExportableState.Get("Image");
var image = !String.IsNullOrWhiteSpace(imageIdentity) ? context.Session.GetItemFromSession(imageIdentity) : default(ContentManagement.ContentItem);
element.MediaId = image != null ? image.Id : default(int?);
}
protected ImagePart GetImage(int id) {
return _contentManager.Get<ImagePart>(id, VersionOptions.Published);
}

View File

@ -4,6 +4,7 @@ using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
using Orchard.ContentManagement.Handlers;
using Orchard.Layouts.Framework.Display;
using Orchard.Layouts.Framework.Drivers;
using Orchard.Layouts.Framework.Elements;
using Orchard.Layouts.Framework.Serialization;
using Orchard.Layouts.Helpers;
@ -79,6 +80,8 @@ namespace Orchard.Layouts.Drivers {
}
protected override void Exporting(LayoutPart part, ExportContentContext context) {
_layoutManager.Exporting(new ExportLayoutContext { Layout = part });
context.Element(part.PartDefinition.Name).SetElementValue("LayoutState", part.LayoutState);
if (part.TemplateId != null) {
@ -93,6 +96,10 @@ namespace Orchard.Layouts.Drivers {
protected override void Importing(LayoutPart part, ImportContentContext context) {
part.LayoutState = context.Data.Element(part.PartDefinition.Name).El("LayoutState");
_layoutManager.Importing(new ImportLayoutContext {
Layout = part,
Session = new ImportContentContextWrapper(context)
});
context.ImportAttribute(part.PartDefinition.Name, "TemplateId", s => part.TemplateId = GetTemplateId(context, s));
}

View File

@ -1,9 +1,11 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using Orchard.ContentManagement;
using Orchard.Layouts.Elements;
using Orchard.Layouts.Framework.Display;
using Orchard.Layouts.Framework.Drivers;
using Orchard.Layouts.Helpers;
using Orchard.Layouts.ViewModels;
using ContentItem = Orchard.Layouts.Elements.ContentItem;
@ -46,6 +48,28 @@ namespace Orchard.Layouts.Drivers {
context.ElementShape.ContentItems = contentItemShapes;
}
protected override void OnExporting(MediaItem element, ExportElementContext context) {
var contentItems = GetContentItems(element.MediaItemIds).ToArray();
if (!contentItems.Any())
return;
var identities = contentItems.Select(x => _contentManager.GetItemMetadata(x).Identity.ToString()).ToArray();
context.ExportableState["ContentItems"] = String.Join(",", identities);
}
protected override void OnImporting(MediaItem element, ImportElementContext context) {
var contentItemIdentities = context.ExportableState.Get("ContentItems");
if (String.IsNullOrWhiteSpace(contentItemIdentities))
return;
var identities = contentItemIdentities.Split(',');
var contentItems = identities.Select(x => context.Session.GetItemFromSession(x)).Where(x => x != null);
element.MediaItemIds = contentItems.Select(x => x.Id);
}
protected IEnumerable<ContentManagement.ContentItem> GetContentItems(IEnumerable<int> ids) {
return _contentManager.GetMany<IContent>(ids, VersionOptions.Published, QueryHints.Empty).Select(x => x.ContentItem);
}

View File

@ -38,6 +38,14 @@ namespace Orchard.Layouts.Framework.Drivers {
OnBuildDocument((TElement)context.Element, context);
}
public void Exporting(ExportElementContext context) {
OnExporting((TElement)context.Element, context);
}
public void Importing(ImportElementContext context) {
OnImporting((TElement)context.Element, context);
}
protected virtual EditorResult OnBuildEditor(TElement element, ElementEditorContext context) {
return null;
}
@ -61,6 +69,12 @@ namespace Orchard.Layouts.Framework.Drivers {
protected virtual void OnBuildDocument(TElement element, BuildElementDocumentContext context) {
}
protected virtual void OnExporting(TElement element, ExportElementContext context) {
}
protected virtual void OnImporting(TElement element, ImportElementContext context) {
}
protected EditorResult Editor(ElementEditorContext context, params dynamic[] editorShapes) {
foreach (var editorShape in editorShapes) {
if (String.IsNullOrWhiteSpace(editorShape.Metadata.Position)) {

View File

@ -0,0 +1,14 @@
using Orchard.Layouts.Framework.Elements;
using Orchard.Layouts.Models;
namespace Orchard.Layouts.Framework.Drivers {
public class ExportElementContext {
public ExportElementContext() {
ExportableState = new StateDictionary();
}
public ILayoutAspect Layout { get; set; }
public IElement Element { get; set; }
public StateDictionary ExportableState { get; set; }
}
}

View File

@ -0,0 +1,7 @@
using Orchard.Layouts.Models;
namespace Orchard.Layouts.Framework.Drivers {
public class ExportLayoutContext {
public ILayoutAspect Layout { get; set; }
}
}

View File

@ -0,0 +1,7 @@
using Orchard.ContentManagement;
namespace Orchard.Layouts.Framework.Drivers {
public interface IContentImportSession {
ContentItem GetItemFromSession(string id);
}
}

View File

@ -12,5 +12,7 @@ namespace Orchard.Layouts.Framework.Drivers {
void Removing(ElementRemovingContext context);
void Indexing(ElementIndexingContext context);
void BuildDocument(BuildElementDocumentContext context);
void Exporting(ExportElementContext context);
void Importing(ImportElementContext context);
}
}

View File

@ -0,0 +1,16 @@
using Orchard.ContentManagement;
using Orchard.ContentManagement.Handlers;
namespace Orchard.Layouts.Framework.Drivers {
public class ImportContentContextWrapper : IContentImportSession {
private readonly ImportContentContext _context;
public ImportContentContextWrapper(ImportContentContext context) {
_context = context;
}
public ContentItem GetItemFromSession(string id) {
return _context.GetItemFromSession(id);
}
}
}

View File

@ -0,0 +1,15 @@
using Orchard.Layouts.Framework.Elements;
using Orchard.Layouts.Models;
namespace Orchard.Layouts.Framework.Drivers {
public class ImportElementContext {
public ImportElementContext() {
ExportableState = new StateDictionary();
}
public ILayoutAspect Layout { get; set; }
public IElement Element { get; set; }
public StateDictionary ExportableState { get; set; }
public IContentImportSession Session { get; set; }
}
}

View File

@ -0,0 +1,8 @@
using Orchard.Layouts.Models;
namespace Orchard.Layouts.Framework.Drivers {
public class ImportLayoutContext {
public ILayoutAspect Layout { get; set; }
public IContentImportSession Session { get; set; }
}
}

View File

@ -6,6 +6,7 @@ namespace Orchard.Layouts.Framework.Elements {
protected Element() {
T = NullLocalizer.Instance;
State = new StateDictionary();
ExportableState = new StateDictionary();
}
public IContainer Container { get; set; }
@ -27,6 +28,7 @@ namespace Orchard.Layouts.Framework.Elements {
}
public abstract string Category { get; }
public Localizer T { get; set; }
public StateDictionary ExportableState { get; set; }
public ElementDescriptor Descriptor { get; set; }
public StateDictionary State { get; set; }
public bool IsTemplated { get; set; }

View File

@ -10,6 +10,7 @@ namespace Orchard.Layouts.Framework.Elements {
bool HasEditor { get; }
bool IsTemplated { get; set; }
StateDictionary State { get; set; }
StateDictionary ExportableState { get; set; }
ElementDescriptor Descriptor { get; set; }
int Index { get; set; }
Localizer T { get; set; }

View File

@ -44,6 +44,7 @@ namespace Orchard.Layouts.Framework.Serialization {
var dto = new {
typeName = element.Descriptor.TypeName,
state = element.State.Serialize(),
exportableState = element.ExportableState.Serialize(),
index = index,
elements = container != null ? container.Elements.Select(Serialize).ToList() : new List<object>(),
isTemplated = element.IsTemplated
@ -58,6 +59,7 @@ namespace Orchard.Layouts.Framework.Serialization {
return null;
var elementState = ElementStateHelper.Deserialize((string)node["state"]);
var elementExportableState = ElementStateHelper.Deserialize((string)node["exportableState"]);
var childNodes = node["elements"];
var elementDescriptor = _elementManager.GetElementDescriptorByTypeName(describeContext, elementTypeName);
@ -68,7 +70,8 @@ namespace Orchard.Layouts.Framework.Serialization {
new ActivateElementArgs {
Container = parent,
Index = index,
ElementState = elementState
State = elementState,
ExportableState = elementExportableState
});
var container = element as IContainer;

View File

@ -214,6 +214,10 @@
<ItemGroup>
<Compile Include="AdminMenu.cs" />
<Compile Include="Controllers\BlueprintAdminController.cs" />
<Compile Include="Framework\Drivers\ImportContentContextWrapper.cs" />
<Compile Include="Framework\Drivers\IContentImportSession.cs" />
<Compile Include="Framework\Drivers\ExportElementContext.cs" />
<Compile Include="Framework\Drivers\ExportLayoutContext.cs" />
<Compile Include="Drivers\VectorImageDriver.cs" />
<Compile Include="Drivers\ProjectionDriver.cs" />
<Compile Include="Drivers\ImageDriver.cs" />
@ -224,6 +228,8 @@
<Compile Include="Elements\Projection.cs" />
<Compile Include="Filters\ControllerAccessorFilter.cs" />
<Compile Include="Framework\Display\ElementCreatingDisplayShapeContext.cs" />
<Compile Include="Framework\Drivers\ImportElementContext.cs" />
<Compile Include="Framework\Drivers\ImportLayoutContext.cs" />
<Compile Include="Framework\Elements\ElementIndexingContext.cs" />
<Compile Include="Framework\Elements\LayoutIndexingContext.cs" />
<Compile Include="Handlers\ElementDriversCoordinator.cs" />

View File

@ -5,6 +5,7 @@ namespace Orchard.Layouts.Services {
public static readonly ActivateElementArgs Empty = new ActivateElementArgs();
public IContainer Container { get; set; }
public int Index { get; set; }
public StateDictionary ElementState { get; set; }
public StateDictionary State { get; set; }
public StateDictionary ExportableState { get; set; }
}
}

View File

@ -33,7 +33,8 @@ namespace Orchard.Layouts.Services {
element.Descriptor = descriptor;
element.T = T;
element.Index = args.Index;
element.State = args.ElementState ?? new StateDictionary();
element.State = args.State ?? new StateDictionary();
element.ExportableState = args.ExportableState ?? new StateDictionary();
_elementEventHandler.Created(new ElementCreatedContext {
Element = element,

View File

@ -178,6 +178,29 @@ namespace Orchard.Layouts.Services {
return document;
}
public void Exporting(IEnumerable<IElement> elements, ExportLayoutContext context) {
InvokeDriver(elements, (driver, element) => {
var exportElementContext = new ExportElementContext {
Layout = context.Layout,
Element = element
};
driver.Exporting(exportElementContext);
element.ExportableState = new StateDictionary(exportElementContext.ExportableState);
});
}
public void Importing(IEnumerable<IElement> elements, ImportLayoutContext context) {
InvokeDriver(elements, (driver, element) => {
var importElementContext = new ImportElementContext {
Layout = context.Layout,
Element = element,
ExportableState = element.ExportableState,
Session = context.Session
};
driver.Importing(importElementContext);
});
}
private IDictionary<string, Category> GetCategories() {
var providers = _categoryProviders.Value;
var categories = providers.SelectMany(x => x.GetCategories());

View File

@ -25,5 +25,7 @@ namespace Orchard.Layouts.Services {
void Removing(LayoutSavingContext context);
void Indexing(LayoutIndexingContext context);
LayoutDocument BuildDocument(ILayoutAspect layout, IEnumerable<IElement> elements);
void Exporting(IEnumerable<IElement> elements, ExportLayoutContext context);
void Importing(IEnumerable<IElement> elements, ImportLayoutContext context);
}
}

View File

@ -1,5 +1,6 @@
using System.Collections.Generic;
using Orchard.ContentManagement;
using Orchard.Layouts.Framework.Drivers;
using Orchard.Layouts.Framework.Elements;
using Orchard.Layouts.Models;
@ -36,5 +37,7 @@ namespace Orchard.Layouts.Services {
IEnumerable<LayoutPart> GetTemplateClients(int templateId, VersionOptions versionOptions);
IEnumerable<IElement> CreateDefaultLayout();
void Exporting(ExportLayoutContext context);
void Importing(ImportLayoutContext context);
}
}

View File

@ -4,6 +4,7 @@ using System.Linq;
using Orchard.ContentManagement;
using Orchard.Layouts.Elements;
using Orchard.Layouts.Framework.Display;
using Orchard.Layouts.Framework.Drivers;
using Orchard.Layouts.Framework.Elements;
using Orchard.Layouts.Framework.Serialization;
using Orchard.Layouts.Helpers;
@ -49,6 +50,22 @@ namespace Orchard.Layouts.Services {
return _elementManager.BuildDocument(layout, elements);
}
public void Exporting(ExportLayoutContext context) {
var elementTree = LoadElements(context.Layout).ToArray();
var elements = elementTree.Flatten().ToArray();
_elementManager.Exporting(elements, context);
context.Layout.LayoutState = _serializer.Serialize(elementTree);
}
public void Importing(ImportLayoutContext context) {
var elementTree = LoadElements(context.Layout).ToArray();
var elements = elementTree.Flatten().ToArray();
_elementManager.Importing(elements, context);
context.Layout.LayoutState = _serializer.Serialize(elementTree);
}
public dynamic RenderLayout(ILayoutAspect layout, string state = null, string displayType = null) {
var elements = _serializer.Deserialize(state ?? layout.LayoutState, new DescribeElementsContext { Content = layout });
var layoutRoot = _elementDisplay.DisplayElements(elements, layout, displayType);