Merge pull request #5872 from OrchardCMS/issue/5848/importexport

Refactored Import process.
This commit is contained in:
Daniel Stolt
2015-10-12 21:39:21 +02:00
29 changed files with 316 additions and 71 deletions
@@ -202,6 +202,7 @@ namespace Orchard.Tests.ContentManagement {
private void Import(XElement element) {
var importContentSession = new ImportContentSession(_contentManager);
_contentManager.Import(element, importContentSession);
_contentManager.CompleteImport(element, importContentSession);
}
private XElement CreateContentElement(string title = "Dummy", string identity = "123456789012345678901234567890ab", string version = null) {
@@ -1,4 +1,6 @@
using System.Linq;
using System;
using System.Diagnostics.Eventing.Reader;
using System.Linq;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
using Orchard.ContentManagement.Handlers;
@@ -87,7 +89,37 @@ namespace Orchard.Layouts.Drivers {
context.Element(part.PartDefinition.Name).SetValue(exportableData);
}
protected override void Exported(ElementWrapperPart part, ExportContentContext context) {
var describeContext = CreateDescribeContext(part);
var descriptor = _elementManager.GetElementDescriptorByTypeName(describeContext, part.ElementTypeName);
var data = ElementDataHelper.Deserialize(part.ElementData);
var element = _elementManager.ActivateElement(descriptor, e => e.Data = data);
_elementManager.Exported(new[] { element }, new ExportLayoutContext());
var exportableData = _serializer.Serialize(element);
context.Element(part.PartDefinition.Name).SetValue(exportableData);
}
protected override void Importing(ElementWrapperPart part, ImportContentContext context) {
HandleImportEvent(part, context, (describeContext, element) => {
_elementManager.Importing(new[] { element }, new ImportLayoutContext { Session = new ImportContentContextWrapper(context) });
});
}
protected override void Imported(ElementWrapperPart part, ImportContentContext context) {
HandleImportEvent(part, context, (describeContext, element) => {
_elementManager.Imported(new[] { element }, new ImportLayoutContext { Session = new ImportContentContextWrapper(context) });
});
}
protected override void ImportCompleted(ElementWrapperPart part, ImportContentContext context) {
HandleImportEvent(part, context, (describeContext, element) => {
_elementManager.ImportCompleted(new[] { element }, new ImportLayoutContext { Session = new ImportContentContextWrapper(context) });
});
}
private void HandleImportEvent(ElementWrapperPart part, ImportContentContext context, Action<DescribeElementsContext, Element> callback) {
var root = context.Data.Element(part.PartDefinition.Name);
if (root == null)
@@ -97,7 +129,7 @@ namespace Orchard.Layouts.Drivers {
var describeContext = CreateDescribeContext(part);
var element = _serializer.Deserialize(exportedData, describeContext);
_elementManager.Importing(new[]{element}, new ImportLayoutContext { Session = new ImportContentContextWrapper(context)});
callback(describeContext, element);
part.ElementData = element.Data.Serialize();
}
@@ -135,9 +135,7 @@ namespace Orchard.Layouts.Drivers {
protected override void Exporting(LayoutPart part, ExportContentContext context) {
_layoutManager.Exporting(new ExportLayoutContext { Layout = part });
context.Element(part.PartDefinition.Name).SetElementValue("LayoutData", part.LayoutData);
if (part.TemplateId != null) {
var template = part.ContentItem.ContentManager.Get(part.TemplateId.Value);
@@ -148,21 +146,41 @@ namespace Orchard.Layouts.Drivers {
}
}
protected override void Exported(LayoutPart part, ExportContentContext context) {
_layoutManager.Exported(new ExportLayoutContext { Layout = part });
context.Element(part.PartDefinition.Name).SetElementValue("LayoutData", part.LayoutData);
}
protected override void Importing(LayoutPart part, ImportContentContext context) {
HandleImportEvent(part, context, importLayoutContext => {
context.ImportChildEl(part.PartDefinition.Name, "LayoutData", s => {
part.LayoutData = s;
_layoutManager.Importing(importLayoutContext);
});
context.ImportAttribute(part.PartDefinition.Name, "TemplateId", s => part.TemplateId = GetTemplateId(context, s));
});
}
protected override void Imported(LayoutPart part, ImportContentContext context) {
HandleImportEvent(part, context, importLayoutContext => _layoutManager.Imported(importLayoutContext));
}
protected override void ImportCompleted(LayoutPart part, ImportContentContext context) {
HandleImportEvent(part, context, importLayoutContext => _layoutManager.ImportCompleted(importLayoutContext));
}
private void HandleImportEvent(LayoutPart part, ImportContentContext context, Action<ImportLayoutContext> callback) {
// Don't do anything if the tag is not specified.
if (context.Data.Element(part.PartDefinition.Name) == null) {
return;
}
context.ImportChildEl(part.PartDefinition.Name, "LayoutData", s => {
part.LayoutData = s;
_layoutManager.Importing(new ImportLayoutContext {
Layout = part,
Session = new ImportContentContextWrapper(context)
});
callback(new ImportLayoutContext {
Layout = part,
Session = new ImportContentContextWrapper(context)
});
context.ImportAttribute(part.PartDefinition.Name, "TemplateId", s => part.TemplateId = GetTemplateId(context, s));
}
private static int? GetTemplateId(ImportContentContext context, string templateIdentity) {
@@ -298,7 +298,7 @@ namespace Orchard.Layouts.Drivers {
}
}
protected override void OnImporting(Projection element, ImportElementContext context) {
protected override void OnImportCompleted(Projection element, ImportElementContext context) {
var queryIdentity = context.ExportableData.Get("QueryId");
var query = queryIdentity != null ? context.Session.GetItemFromSession(queryIdentity) : default(ContentManagement.ContentItem);
@@ -41,10 +41,22 @@ namespace Orchard.Layouts.Framework.Drivers {
OnExporting((TElement)context.Element, context);
}
public void Exported(ExportElementContext context) {
OnExported((TElement)context.Element, context);
}
public void Importing(ImportElementContext context) {
OnImporting((TElement)context.Element, context);
}
public void Imported(ImportElementContext context) {
OnImported((TElement)context.Element, context);
}
public void ImportCompleted(ImportElementContext context) {
OnImportCompleted((TElement)context.Element, context);
}
protected virtual EditorResult OnBuildEditor(TElement element, ElementEditorContext context) {
return null;
}
@@ -71,9 +83,18 @@ namespace Orchard.Layouts.Framework.Drivers {
protected virtual void OnExporting(TElement element, ExportElementContext context) {
}
protected virtual void OnExported(TElement element, ExportElementContext context) {
}
protected virtual void OnImporting(TElement element, ImportElementContext context) {
}
protected virtual void OnImported(TElement element, ImportElementContext context) {
}
protected virtual void OnImportCompleted(TElement element, ImportElementContext context) {
}
protected EditorResult Editor(ElementEditorContext context, params dynamic[] editorShapes) {
foreach (var editorShape in editorShapes) {
if (String.IsNullOrWhiteSpace(editorShape.Metadata.Position)) {
@@ -12,6 +12,9 @@ namespace Orchard.Layouts.Framework.Drivers {
void LayoutSaving(ElementSavingContext context);
void Removing(ElementRemovingContext context);
void Exporting(ExportElementContext context);
void Exported(ExportElementContext context);
void Importing(ImportElementContext context);
void Imported(ImportElementContext context);
void ImportCompleted(ImportElementContext context);
}
}
@@ -157,13 +157,26 @@ namespace Orchard.Layouts.Services {
InvokeDriver(elements, (driver, element) => {
var exportElementContext = new ExportElementContext {
Layout = context.Layout,
Element = element
Element = element,
ExportableData = element.ExportableData
};
driver.Exporting(exportElementContext);
element.ExportableData = new ElementDataDictionary(exportElementContext.ExportableData);
});
}
public void Exported(IEnumerable<Element> elements, ExportLayoutContext context) {
InvokeDriver(elements, (driver, element) => {
var exportElementContext = new ExportElementContext {
Layout = context.Layout,
Element = element,
ExportableData = element.ExportableData
};
driver.Exported(exportElementContext);
element.ExportableData = new ElementDataDictionary(exportElementContext.ExportableData);
});
}
public void Importing(IEnumerable<Element> elements, ImportLayoutContext context) {
InvokeDriver(elements, (driver, element) => {
var importElementContext = new ImportElementContext {
@@ -176,6 +189,30 @@ namespace Orchard.Layouts.Services {
});
}
public void Imported(IEnumerable<Element> elements, ImportLayoutContext context) {
InvokeDriver(elements, (driver, element) => {
var importElementContext = new ImportElementContext {
Layout = context.Layout,
Element = element,
ExportableData = element.ExportableData,
Session = context.Session
};
driver.Imported(importElementContext);
});
}
public void ImportCompleted(IEnumerable<Element> elements, ImportLayoutContext context) {
InvokeDriver(elements, (driver, element) => {
var importElementContext = new ImportElementContext {
Layout = context.Layout,
Element = element,
ExportableData = element.ExportableData,
Session = context.Session
};
driver.ImportCompleted(importElementContext);
});
}
private IDictionary<string, Category> GetCategories() {
var providers = _categoryProviders.Value;
var categories = providers.SelectMany(x => x.GetCategories());
@@ -23,6 +23,9 @@ namespace Orchard.Layouts.Services {
void Saving(LayoutSavingContext context);
void Removing(LayoutSavingContext context);
void Exporting(IEnumerable<Element> elements, ExportLayoutContext context);
void Exported(IEnumerable<Element> elements, ExportLayoutContext context);
void Importing(IEnumerable<Element> elements, ImportLayoutContext context);
void Imported(IEnumerable<Element> elements, ImportLayoutContext context);
void ImportCompleted(IEnumerable<Element> elements, ImportLayoutContext context);
}
}
@@ -54,6 +54,9 @@ namespace Orchard.Layouts.Services {
IEnumerable<LayoutPart> GetTemplateClients(int templateId, VersionOptions versionOptions);
IEnumerable<Element> CreateDefaultLayout();
void Exporting(ExportLayoutContext context);
void Exported(ExportLayoutContext context);
void Importing(ImportLayoutContext context);
void Imported(ImportLayoutContext context);
void ImportCompleted(ImportLayoutContext context);
}
}
@@ -67,6 +67,14 @@ namespace Orchard.Layouts.Services {
context.Layout.LayoutData = _serializer.Serialize(elementTree);
}
public void Exported(ExportLayoutContext context) {
var elementTree = LoadElements(context.Layout).ToArray();
var elements = elementTree.Flatten().ToArray();
_elementManager.Exported(elements, context);
context.Layout.LayoutData = _serializer.Serialize(elementTree);
}
public void Importing(ImportLayoutContext context) {
var elementTree = LoadElements(context.Layout).ToArray();
var elements = elementTree.Flatten().ToArray();
@@ -75,6 +83,22 @@ namespace Orchard.Layouts.Services {
context.Layout.LayoutData = _serializer.Serialize(elementTree);
}
public void Imported(ImportLayoutContext context) {
var elementTree = LoadElements(context.Layout).ToArray();
var elements = elementTree.Flatten().ToArray();
_elementManager.Imported(elements, context);
context.Layout.LayoutData = _serializer.Serialize(elementTree);
}
public void ImportCompleted(ImportLayoutContext context) {
var elementTree = LoadElements(context.Layout).ToArray();
var elements = elementTree.Flatten().ToArray();
_elementManager.ImportCompleted(elements, context);
context.Layout.LayoutData = _serializer.Serialize(elementTree);
}
public dynamic RenderLayout(string data, string displayType = null, IContent content = null) {
var elements = _serializer.Deserialize(data, new DescribeElementsContext { Content = content });
var layoutRoot = _elementDisplay.DisplayElements(elements, content, displayType);
@@ -11,7 +11,6 @@ using Orchard.Projections.Descriptors.Property;
using Orchard.Projections.Models;
using Orchard.Projections.Services;
using Orchard.Projections.ViewModels;
using Orchard.Security;
using Orchard.UI.Admin;
using Orchard.UI.Notify;
@@ -96,9 +95,8 @@ namespace Orchard.Projections.Controllers {
if (!Services.Authorizer.Authorize(Permissions.ManageQueries, T("Not authorized to manage queries")))
return new HttpUnauthorizedResult();
// validating form values
// Validating form values.
model.Layout = _projectionManager.DescribeLayouts().SelectMany(x => x.Descriptors).FirstOrDefault(x => x.Category == model.Category && x.Type == model.Type);
_formManager.Validate(new ValidatingContext { FormName = model.Layout.Form, ModelState = ModelState, ValueProvider = ValueProvider });
var form = _formManager.Build(model.Layout.Form) ?? Services.New.EmptyForm();
@@ -107,13 +105,13 @@ namespace Orchard.Projections.Controllers {
model.Form = form;
if (ModelState.IsValid) {
var layoutRecord = new LayoutRecord { Category = model.Category, Type = model.Type };
var layoutRecord = new LayoutRecord { Guid = Guid.NewGuid() ,Category = model.Category, Type = model.Type };
var query = _queryService.GetQuery(model.QueryId);
query.Layouts.Add(layoutRecord);
var dictionary = formCollection.AllKeys.ToDictionary(key => key, formCollection.Get);
// save form parameters
// Save form parameters.
layoutRecord.State = FormParametersHelper.ToString(dictionary);
layoutRecord.Description = model.Description;
layoutRecord.Display = model.Display;
@@ -132,7 +130,7 @@ namespace Orchard.Projections.Controllers {
if (!Services.Authorizer.Authorize(Permissions.ManageQueries, T("Not authorized to manage queries")))
return new HttpUnauthorizedResult();
LayoutRecord layoutRecord = _repository.Get(id);
var layoutRecord = _repository.Get(id);
if (layoutRecord == null) {
return HttpNotFound();
@@ -140,7 +138,7 @@ namespace Orchard.Projections.Controllers {
var layoutDescriptor = _projectionManager.DescribeLayouts().SelectMany(x => x.Descriptors).FirstOrDefault(x => x.Category == layoutRecord.Category && x.Type == layoutRecord.Type);
// build the form, and let external components alter it
// Build the form, and let external components alter it.
var form = _formManager.Build(layoutDescriptor.Form) ?? Services.New.EmptyForm();
var viewModel = new LayoutEditViewModel {
@@ -156,7 +154,7 @@ namespace Orchard.Projections.Controllers {
GroupPropertyId = layoutRecord.GroupProperty == null ? 0 : layoutRecord.GroupProperty.Id
};
// bind form with existing values
// Bind form with existing values.
var parameters = FormParametersHelper.FromString(layoutRecord.State);
_formManager.Bind(form, new DictionaryValueProvider<string>(parameters, CultureInfo.InvariantCulture));
@@ -192,7 +190,7 @@ namespace Orchard.Projections.Controllers {
[HttpPost, ActionName("Edit")]
public ActionResult EditPost(LayoutEditViewModel model, FormCollection formCollection) {
// validating form values
// Validating form values.
var layout = _projectionManager.DescribeLayouts().SelectMany(x => x.Descriptors).FirstOrDefault(x => x.Category == model.Category && x.Type == model.Type);
_formManager.Validate(new ValidatingContext { FormName = layout.Form, ModelState = ModelState, ValueProvider = ValueProvider });
@@ -207,7 +205,7 @@ namespace Orchard.Projections.Controllers {
var dictionary = formCollection.AllKeys.ToDictionary(key => key, formCollection.Get);
// save form parameters
// Save form parameters.
layoutRecord.State = FormParametersHelper.ToString(dictionary);
layoutRecord.Description = model.Description;
layoutRecord.Display = model.Display;
@@ -307,23 +307,22 @@ namespace Orchard.Projections.Drivers {
context.ImportAttribute(part.PartDefinition.Name, "DisplayPager", x => part.Record.DisplayPager = Boolean.Parse(x));
}
protected override void Imported(ProjectionPart part, ImportContentContext context) {
// assign the query only when everythin is imported
protected override void ImportCompleted(ProjectionPart part, ImportContentContext context) {
// Assign the query only when everything is imported.
var query = context.Attribute(part.PartDefinition.Name, "Query");
if (query != null) {
part.Record.QueryPartRecord = context.GetItemFromSession(query).As<QueryPart>().Record;
var layoutIndex = context.Attribute(part.PartDefinition.Name, "LayoutIndex");
int layoutIndexValue;
if (layoutIndex != null
if (layoutIndex != null
&& Int32.TryParse(layoutIndex, out layoutIndexValue)
&& layoutIndexValue >= 0
&& part.Record.QueryPartRecord.Layouts.Count > layoutIndexValue)
{
&& part.Record.QueryPartRecord.Layouts.Count > layoutIndexValue) {
part.Record.LayoutRecord = part.Record.QueryPartRecord.Layouts[Int32.Parse(layoutIndex)];
}
}
}
protected override void Exporting(ProjectionPart part, ExportContentContext context) {
context.Element(part.PartDefinition.Name).SetAttributeValue("Items", part.Record.Items);
context.Element(part.PartDefinition.Name).SetAttributeValue("ItemsPerPage", part.Record.ItemsPerPage);
@@ -65,12 +65,12 @@ namespace Orchard.Projections.Drivers {
}
return new XElement("SortCriterion",
new XAttribute("Category", sortCriterion.Category ?? ""),
new XAttribute("Description", sortCriterion.Description ?? ""),
new XAttribute("Position", sortCriterion.Position),
new XAttribute("State", state ?? ""),
new XAttribute("Type", sortCriterion.Type ?? "")
);
new XAttribute("Category", sortCriterion.Category ?? ""),
new XAttribute("Description", sortCriterion.Description ?? ""),
new XAttribute("Position", sortCriterion.Position),
new XAttribute("State", state ?? ""),
new XAttribute("Type", sortCriterion.Type ?? "")
);
})
),
new XElement("Layouts",
@@ -83,20 +83,21 @@ namespace Orchard.Projections.Drivers {
}
return new XElement("Layout",
// Attributes
new XAttribute("Category", layout.Category ?? ""),
new XAttribute("Description", layout.Description ?? ""),
new XAttribute("State", state ?? ""),
new XAttribute("Display", layout.Display),
new XAttribute("DisplayType", layout.DisplayType ?? ""),
new XAttribute("Type", layout.Type ?? ""),
// Attributes
new XAttribute("Guid", layout.Guid),
new XAttribute("Category", layout.Category ?? ""),
new XAttribute("Description", layout.Description ?? ""),
new XAttribute("State", state ?? ""),
new XAttribute("Display", layout.Display),
new XAttribute("DisplayType", layout.DisplayType ?? ""),
new XAttribute("Type", layout.Type ?? ""),
// Properties
new XElement("Properties", layout.Properties.Select(GetPropertyXml)),
// Properties
new XElement("Properties", layout.Properties.Select(GetPropertyXml)),
// Group
new XElement("Group", GetPropertyXml(layout.GroupProperty))
);
// Group
new XElement("Group", GetPropertyXml(layout.GroupProperty))
);
})
)
);
@@ -161,6 +162,7 @@ namespace Orchard.Projections.Drivers {
part.Record.Layouts.Clear();
foreach (var item in queryElement.Element("Layouts").Elements("Layout").Select(layout => {
var guid = layout.Attr("Guid");
var category = layout.Attribute("Category").Value;
var type = layout.Attribute("Type").Value;
var state = layout.Attribute("State").Value;
@@ -171,7 +173,7 @@ namespace Orchard.Projections.Drivers {
}
return new LayoutRecord {
Guid = !String.IsNullOrWhiteSpace(guid) ? Guid.Parse(guid) : Guid.NewGuid(),
Category = category,
Description = layout.Attribute("Description").Value,
Display = int.Parse(layout.Attribute("Display").Value),
@@ -1,4 +1,5 @@
using System.Data;
using System;
using System.Data;
using Orchard.ContentManagement.MetaData;
using Orchard.Core.Common.Models;
using Orchard.Core.Contents.Extensions;
@@ -102,6 +103,7 @@ namespace Orchard.Projections {
SchemaBuilder.CreateTable("LayoutRecord",
table => table
.Column<int>("Id", c => c.PrimaryKey().Identity())
.Column<Guid>("Guid")
.Column<string>("Category", c => c.WithLength(64))
.Column<string>("Type", c => c.WithLength(64))
.Column<string>("Description", c => c.WithLength(255))
@@ -112,6 +114,9 @@ namespace Orchard.Projections {
.Column<int>("GroupProperty_id")
);
SchemaBuilder.AlterTable("LayoutRecord", table => table
.CreateIndex("IDX_LR_GUID", "Guid"));
SchemaBuilder.CreateTable("PropertyRecord",
table => table
.Column<int>("Id", c => c.PrimaryKey().Identity())
@@ -262,16 +267,26 @@ namespace Orchard.Projections {
ContentDefinitionManager.AlterTypeDefinition("ProjectionPage", cfg => cfg.Listable());
return 3;
return 4;
}
public int UpdateFrom2() {
SchemaBuilder.AlterTable("ProjectionPartRecord",
table => table
.AlterColumn("PagerSuffix", c => c.WithType(DbType.String).WithLength(255))
);
SchemaBuilder.AlterTable("ProjectionPartRecord", table => table
.AlterColumn("PagerSuffix", c => c.WithType(DbType.String).WithLength(255))
);
return 3;
}
public int UpdateFrom3() {
SchemaBuilder.AlterTable("LayoutRecord", table => table
.AddColumn<Guid>("Guid")
);
SchemaBuilder.AlterTable("LayoutRecord", table => table
.CreateIndex("IDX_LR_GUID", "Guid"));
return 4;
}
}
}
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Orchard.Data.Conventions;
@@ -9,6 +10,7 @@ namespace Orchard.Projections.Models {
}
public virtual int Id { get; set; }
public virtual Guid Guid { get; set; }
public virtual string Description { get; set; }
public virtual string Category { get; set; }
public virtual string Type { get; set; }
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Xml.Linq;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Handlers;
using Orchard.Data;
using Orchard.Localization;
using Orchard.Logging;
@@ -13,14 +14,17 @@ namespace Orchard.Recipes.Providers.Executors {
public class ContentStep : RecipeExecutionStep {
private readonly IOrchardServices _orchardServices;
private readonly ITransactionManager _transactionManager;
private readonly Lazy<IEnumerable<IContentHandler>> _handlers;
public ContentStep(
IOrchardServices orchardServices,
ITransactionManager transactionManager,
Lazy<IEnumerable<IContentHandler>> handlers,
RecipeExecutionLogger logger) : base(logger) {
_orchardServices = orchardServices;
_transactionManager = transactionManager;
_handlers = handlers;
BatchSize = 64;
}
@@ -71,6 +75,18 @@ namespace Orchard.Recipes.Providers.Executors {
// <Data />
// Import Data.
public override void Execute(RecipeExecutionContext context) {
// Run the import.
BatchedInvoke(context, "Import", (itemId, nextIdentityValue, element, importContentSession, elementDictionary) => {
_orchardServices.ContentManager.Import(element, importContentSession);
});
// Invoke ImportCompleted.
BatchedInvoke(context, "ImportCompleted", (itemId, nextIdentityValue, element, importContentSession, elementDictionary) => {
_orchardServices.ContentManager.CompleteImport(element, importContentSession);
});
}
private void BatchedInvoke(RecipeExecutionContext context, string batchLabel, Action<string, string, XElement, ImportContentSession, IDictionary<string, XElement>> contentItemAction) {
var importContentSession = new ImportContentSession(_orchardServices.ContentManager);
// Populate local dictionary with elements and their ids.
@@ -82,15 +98,15 @@ namespace Orchard.Recipes.Providers.Executors {
}
// Determine if the import is to be batched in multiple transactions.
var batchSize = GetBatchSizeForDataStep(context.RecipeStep.Step);
var startIndex = 0;
var itemIndex = 0;
var batchSize = GetBatchSizeForDataStep(context.RecipeStep.Step);
Logger.Debug("Using batch size {0}.", batchSize);
// Run the import.
Logger.Debug("Using batch size {0} for '{1}'.", batchSize, batchLabel);
try {
while (startIndex < elementDictionary.Count) {
Logger.Debug("Importing batch starting at index {0}.", startIndex);
Logger.Debug("Batch '{0}' execution starting at index {1}.", batchLabel, startIndex);
importContentSession.InitializeBatch(startIndex, batchSize);
// The session determines which items are included in the current batch
@@ -102,14 +118,12 @@ namespace Orchard.Recipes.Providers.Executors {
if (elementDictionary[nextIdentityValue].HasAttributes) {
itemId = elementDictionary[nextIdentityValue].FirstAttribute.Value;
}
Logger.Information("Importing data item '{0}' (item {1}/{2}).", itemId, itemIndex + 1, elementDictionary.Count);
Logger.Information("Handling content item '{0}' (item {1}/{2} of '{3}').", itemId, itemIndex + 1, elementDictionary.Count, batchLabel);
try {
_orchardServices.ContentManager.Import(
elementDictionary[nextIdentityValue],
importContentSession);
contentItemAction(itemId, nextIdentityValue, elementDictionary[nextIdentityValue], importContentSession, elementDictionary);
}
catch (Exception ex) {
Logger.Error(ex, "Error while importing data item '{0}'.", itemId);
Logger.Error(ex, "Error while handling content item '{0}' (item {1}/{2} of '{3}').", itemId, itemIndex + 1, elementDictionary.Count, batchLabel);
throw;
}
itemIndex++;
@@ -123,7 +137,7 @@ namespace Orchard.Recipes.Providers.Executors {
_transactionManager.RequireNew();
}
Logger.Debug("Finished importing batch starting at index {0}.", startIndex);
Logger.Debug("Finished batch '{0}' starting at index {1}.", batchLabel, startIndex);
}
}
catch (Exception) {
@@ -563,11 +563,9 @@ namespace Orchard.ContentManagement {
public virtual ContentItem Clone(ContentItem contentItem) {
// Mostly taken from: http://orchard.codeplex.com/discussions/396664
var importContentSession = new ImportContentSession(this);
var element = Export(contentItem);
// If a handler prevents this element from being exported, it can't be cloned
// If a handler prevents this element from being exported, it can't be cloned.
if (element == null) {
throw new InvalidOperationException("The content item couldn't be cloned because a handler prevented it from being exported.");
}
@@ -578,9 +576,10 @@ namespace Orchard.ContentManagement {
var status = element.Attribute("Status");
if (status != null) status.SetValue("Draft"); // So the copy is always a draft.
var importContentSession = new ImportContentSession(this);
importContentSession.Set(copyId, element.Name.LocalName);
Import(element, importContentSession);
CompleteImport(element, importContentSession);
return importContentSession.Get(copyId, element.Name.LocalName);
}
@@ -790,6 +789,26 @@ namespace Orchard.ContentManagement {
}
}
public void CompleteImport(XElement element, ImportContentSession importContentSession) {
var elementId = element.Attribute("Id");
if (elementId == null) {
return;
}
var identity = elementId.Value;
if (String.IsNullOrWhiteSpace(identity)) {
return;
}
var item = importContentSession.Get(identity, VersionOptions.Latest, XmlConvert.DecodeName(element.Name.LocalName));
var context = new ImportContentContext(item, element, importContentSession);
foreach (var handler in _handlers.Value) {
handler.ImportCompleted(context);
}
}
public XElement Export(ContentItem contentItem) {
var context = new ExportContentContext(contentItem, new XElement(XmlConvert.EncodeLocalName(contentItem.ContentType)));
@@ -63,6 +63,10 @@ namespace Orchard.ContentManagement.Drivers {
Process(context.ContentItem, (part, field) => Imported(part, field, context), context.Logger);
}
void IContentFieldDriver.ImportCompleted(ImportContentContext context) {
Process(context.ContentItem, (part, field) => ImportCompleted(part, field, context), context.Logger);
}
void IContentFieldDriver.Exporting(ExportContentContext context) {
Process(context.ContentItem, (part, field) => Exporting(part, field, context), context.Logger);
}
@@ -110,6 +114,7 @@ namespace Orchard.ContentManagement.Drivers {
protected virtual void Importing(ContentPart part, TField field, ImportContentContext context) { }
protected virtual void Imported(ContentPart part, TField field, ImportContentContext context) { }
protected virtual void ImportCompleted(ContentPart part, TField field, ImportContentContext context) { }
protected virtual void Exporting(ContentPart part, TField field, ExportContentContext context) { }
protected virtual void Exported(ContentPart part, TField field, ExportContentContext context) { }
@@ -129,6 +129,12 @@ namespace Orchard.ContentManagement.Drivers {
Imported(part, context);
}
void IContentPartDriver.ImportCompleted(ImportContentContext context) {
var part = context.ContentItem.As<TContent>();
if (part != null)
ImportCompleted(part, context);
}
void IContentPartDriver.Exporting(ExportContentContext context) {
var part = context.ContentItem.As<TContent>();
if (part != null)
@@ -149,6 +155,7 @@ namespace Orchard.ContentManagement.Drivers {
protected virtual void Importing(TContent part, ImportContentContext context) { }
protected virtual void Imported(TContent part, ImportContentContext context) { }
protected virtual void ImportCompleted(TContent part, ImportContentContext context) { }
protected virtual void Exporting(TContent part, ExportContentContext context) { }
protected virtual void Exported(TContent part, ExportContentContext context) { }
@@ -89,6 +89,13 @@ namespace Orchard.ContentManagement.Drivers.Coordinators {
}
}
public override void ImportCompleted(ImportContentContext context) {
context.Logger = Logger;
foreach (var contentFieldDriver in _drivers) {
contentFieldDriver.ImportCompleted(context);
}
}
public override void Exporting(ExportContentContext context) {
context.Logger = Logger;
foreach (var contentFieldDriver in _drivers.OrderBy(x => x.GetFieldInfo().First().FieldTypeName)) {
@@ -78,6 +78,12 @@ namespace Orchard.ContentManagement.Drivers.Coordinators {
}
}
public override void ImportCompleted(ImportContentContext context) {
foreach (var contentPartDriver in _drivers) {
contentPartDriver.ImportCompleted(context);
}
}
public override void Exporting(ExportContentContext context) {
foreach (var contentPartDriver in _drivers.OrderBy(x => x.GetPartInfo().First().PartName)) {
contentPartDriver.Exporting(context);
@@ -9,6 +9,7 @@ namespace Orchard.ContentManagement.Drivers {
DriverResult UpdateEditorShape(UpdateEditorContext context);
void Importing(ImportContentContext context);
void Imported(ImportContentContext context);
void ImportCompleted(ImportContentContext context);
void Exporting(ExportContentContext context);
void Exported(ExportContentContext context);
void Describe(DescribeMembersContext context);
@@ -9,6 +9,7 @@ namespace Orchard.ContentManagement.Drivers {
DriverResult UpdateEditor(UpdateEditorContext context);
void Importing(ImportContentContext context);
void Imported(ImportContentContext context);
void ImportCompleted(ImportContentContext context);
void Exporting(ExportContentContext context);
void Exported(ExportContentContext context);
IEnumerable<ContentPartInfo> GetPartInfo();
@@ -104,6 +104,10 @@ namespace Orchard.ContentManagement.Handlers {
Filters.Add(new InlineStorageFilter<TPart> { OnImported = handler });
}
protected void OnImportCompleted<TPart>(Action<ImportContentContext, TPart> handler) where TPart : class, IContent {
Filters.Add(new InlineStorageFilter<TPart> { OnImportCompleted = handler });
}
protected void OnExporting<TPart>(Action<ExportContentContext, TPart> handler) where TPart : class, IContent {
Filters.Add(new InlineStorageFilter<TPart> { OnExporting = handler });
}
@@ -157,6 +161,7 @@ namespace Orchard.ContentManagement.Handlers {
public Action<IndexContentContext, TPart> OnIndexed { get; set; }
public Action<ImportContentContext, TPart> OnImporting { get; set; }
public Action<ImportContentContext, TPart> OnImported { get; set; }
public Action<ImportContentContext, TPart> OnImportCompleted { get; set; }
public Action<ExportContentContext, TPart> OnExporting { get; set; }
public Action<ExportContentContext, TPart> OnExported { get; set; }
public Action<RestoreContentContext, TPart> OnRestoring { get; set; }
@@ -230,6 +235,10 @@ namespace Orchard.ContentManagement.Handlers {
if (OnImported != null)
OnImported(context, instance);
}
protected override void ImportCompleted(ImportContentContext context, TPart instance) {
if (OnImportCompleted != null)
OnImportCompleted(context, instance);
}
protected override void Exporting(ExportContentContext context, TPart instance) {
if (OnExporting != null)
OnExporting(context, instance);
@@ -407,6 +416,12 @@ namespace Orchard.ContentManagement.Handlers {
Imported(context);
}
void IContentHandler.ImportCompleted(ImportContentContext importContentContext) {
foreach (var filter in Filters.OfType<IContentStorageFilter>())
filter.ImportCompleted(importContentContext);
ImportCompleted(importContentContext);
}
void IContentHandler.Exporting(ExportContentContext context) {
foreach (var filter in Filters.OfType<IContentStorageFilter>())
filter.Exporting(context);
@@ -496,6 +511,7 @@ namespace Orchard.ContentManagement.Handlers {
protected virtual void Importing(ImportContentContext context) { }
protected virtual void Imported(ImportContentContext context) { }
protected virtual void ImportCompleted(ImportContentContext context) { }
protected virtual void Exporting(ExportContentContext context) { }
protected virtual void Exported(ExportContentContext context) { }
protected virtual void Restoring(RestoreContentContext context) { }
@@ -22,6 +22,7 @@
public virtual void Indexed(IndexContentContext context) {}
public virtual void Importing(ImportContentContext context) {}
public virtual void Imported(ImportContentContext context) {}
public virtual void ImportCompleted(ImportContentContext importContentContext) {}
public virtual void Exporting(ExportContentContext context) {}
public virtual void Exported(ExportContentContext context) {}
public virtual void Restoring(RestoreContentContext context) { }
@@ -22,6 +22,7 @@
void Indexed(IndexContentContext context);
void Importing(ImportContentContext context);
void Imported(ImportContentContext context);
void ImportCompleted(ImportContentContext importContentContext);
void Exporting(ExportContentContext context);
void Exported(ExportContentContext context);
@@ -21,6 +21,7 @@ namespace Orchard.ContentManagement.Handlers {
void Indexed(IndexContentContext context);
void Importing(ImportContentContext context);
void Imported(ImportContentContext context);
void ImportCompleted(ImportContentContext context);
void Exporting(ExportContentContext context);
void Exported(ExportContentContext context);
void Restoring(RestoreContentContext context);
@@ -23,6 +23,7 @@ namespace Orchard.ContentManagement.Handlers {
protected virtual void Indexed(IndexContentContext context, TPart instance) { }
protected virtual void Importing(ImportContentContext context, TPart instance) { }
protected virtual void Imported(ImportContentContext context, TPart instance) { }
protected virtual void ImportCompleted(ImportContentContext context, TPart instance) { }
protected virtual void Exporting(ExportContentContext context, TPart instance) { }
protected virtual void Exported(ExportContentContext context, TPart instance) { }
protected virtual void Restoring(RestoreContentContext context, TPart instance) { }
@@ -135,6 +136,11 @@ namespace Orchard.ContentManagement.Handlers {
Imported(context, context.ContentItem.As<TPart>());
}
void IContentStorageFilter.ImportCompleted(ImportContentContext context) {
if (context.ContentItem.Is<TPart>())
ImportCompleted(context, context.ContentItem.As<TPart>());
}
void IContentStorageFilter.Exporting(ExportContentContext context) {
if (context.ContentItem.Is<TPart>())
Exporting(context, context.ContentItem.As<TPart>());
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Xml.Linq;
using Orchard.ContentManagement.Handlers;
using Orchard.ContentManagement.MetaData.Models;
using Orchard.Indexing;
@@ -92,6 +93,7 @@ namespace Orchard.ContentManagement {
XElement Export(ContentItem contentItem);
void Import(XElement element, ImportContentSession importContentSession);
void CompleteImport(XElement element, ImportContentSession importContentSession);
/// <summary>
/// Clears the current referenced content items