#5375: Exporting various items in a predictable order.

Fixes 5375
This commit is contained in:
Sipke Schoorstra
2015-07-09 14:11:34 +01:00
parent 85b06375a0
commit 537adf9cba
7 changed files with 38 additions and 19 deletions

View File

@@ -93,7 +93,7 @@ namespace Orchard.ImportExport.Controllers {
}; };
UpdateModel(viewModel); UpdateModel(viewModel);
var contentTypesToExport = viewModel.ContentTypes.Where(c => c.IsChecked).Select(c => c.ContentTypeName); var contentTypesToExport = viewModel.ContentTypes.Where(c => c.IsChecked).Select(c => c.ContentTypeName).ToList();
var customSteps = viewModel.CustomSteps.Where(c => c.IsChecked).Select(c => c.CustomStep); var customSteps = viewModel.CustomSteps.Where(c => c.IsChecked).Select(c => c.CustomStep);
var exportOptions = new ExportOptions { var exportOptions = new ExportOptions {

View File

@@ -5,6 +5,7 @@ using System.Xml;
using System.Xml.Linq; using System.Xml.Linq;
using Orchard.ContentManagement; using Orchard.ContentManagement;
using Orchard.ContentManagement.MetaData; using Orchard.ContentManagement.MetaData;
using Orchard.ContentManagement.MetaData.Models;
using Orchard.Environment.Descriptor; using Orchard.Environment.Descriptor;
using Orchard.FileSystems.AppData; using Orchard.FileSystems.AppData;
using Orchard.ImportExport.Models; using Orchard.ImportExport.Models;
@@ -24,6 +25,7 @@ namespace Orchard.ImportExport.Services {
private readonly IShellDescriptorManager _shellDescriptorManager; private readonly IShellDescriptorManager _shellDescriptorManager;
private readonly IClock _clock; private readonly IClock _clock;
private readonly IEnumerable<IExportEventHandler> _exportEventHandlers; private readonly IEnumerable<IExportEventHandler> _exportEventHandlers;
private readonly IContentManager _contentManager;
private const string ExportsDirectory = "Exports"; private const string ExportsDirectory = "Exports";
public ImportExportService( public ImportExportService(
@@ -35,7 +37,9 @@ namespace Orchard.ImportExport.Services {
IRecipeManager recipeManager, IRecipeManager recipeManager,
IShellDescriptorManager shellDescriptorManager, IShellDescriptorManager shellDescriptorManager,
IClock clock, IClock clock,
IEnumerable<IExportEventHandler> exportEventHandlers) { IEnumerable<IExportEventHandler> exportEventHandlers,
IContentManager contentManager) {
_orchardServices = orchardServices; _orchardServices = orchardServices;
_contentDefinitionManager = contentDefinitionManager; _contentDefinitionManager = contentDefinitionManager;
_contentDefinitionWriter = contentDefinitionWriter; _contentDefinitionWriter = contentDefinitionWriter;
@@ -45,6 +49,7 @@ namespace Orchard.ImportExport.Services {
_shellDescriptorManager = shellDescriptorManager; _shellDescriptorManager = shellDescriptorManager;
_clock = clock; _clock = clock;
_exportEventHandlers = exportEventHandlers; _exportEventHandlers = exportEventHandlers;
_contentManager = contentManager;
Logger = NullLogger.Instance; Logger = NullLogger.Instance;
T = NullLocalizer.Instance; T = NullLocalizer.Instance;
} }
@@ -63,7 +68,7 @@ namespace Orchard.ImportExport.Services {
//items need to be retrieved //items need to be retrieved
IEnumerable<ContentItem> contentItems = null; IEnumerable<ContentItem> contentItems = null;
if (exportOptions.ExportData) { if (exportOptions.ExportData) {
contentItems = _orchardServices.ContentManager.Query(GetContentExportVersionOptions(exportOptions.VersionHistoryOptions), contentTypes.ToArray()).List(); contentItems = _orchardServices.ContentManager.Query(GetContentExportVersionOptions(exportOptions.VersionHistoryOptions), contentTypes.ToArray()).List().ToArray();
} }
return Export(contentTypes, contentItems, exportOptions); return Export(contentTypes, contentItems, exportOptions);
@@ -118,19 +123,22 @@ namespace Orchard.ImportExport.Services {
var typesToExport = _contentDefinitionManager.ListTypeDefinitions() var typesToExport = _contentDefinitionManager.ListTypeDefinitions()
.Where(typeDefinition => contentTypes.Contains(typeDefinition.Name)) .Where(typeDefinition => contentTypes.Contains(typeDefinition.Name))
.ToList(); .ToList();
var partsToExport = new List<string>(); var partsToExport = new Dictionary<string, ContentPartDefinition>();
foreach (var contentTypeDefinition in typesToExport) { foreach (var contentTypeDefinition in typesToExport.OrderBy(x => x.Name)) {
foreach (var contentPartDefinition in contentTypeDefinition.Parts) { foreach (var contentPartDefinition in contentTypeDefinition.Parts) {
if (partsToExport.Contains(contentPartDefinition.PartDefinition.Name)) { if (partsToExport.ContainsKey(contentPartDefinition.PartDefinition.Name)) {
continue; continue;
} }
partsToExport.Add(contentPartDefinition.PartDefinition.Name); partsToExport.Add(contentPartDefinition.PartDefinition.Name, contentPartDefinition.PartDefinition);
partsElement.Add(_contentDefinitionWriter.Export(contentPartDefinition.PartDefinition));
} }
typesElement.Add(_contentDefinitionWriter.Export(contentTypeDefinition)); typesElement.Add(_contentDefinitionWriter.Export(contentTypeDefinition));
} }
foreach (var part in partsToExport.Values.OrderBy(x => x.Name)) {
partsElement.Add(_contentDefinitionWriter.Export(part));
}
return new XElement("Metadata", typesElement, partsElement); return new XElement("Metadata", typesElement, partsElement);
} }
@@ -138,7 +146,7 @@ namespace Orchard.ImportExport.Services {
var siteContentItem = _orchardServices.WorkContext.CurrentSite.ContentItem; var siteContentItem = _orchardServices.WorkContext.CurrentSite.ContentItem;
var exportedElements = ExportContentItem(siteContentItem).Elements().ToList(); var exportedElements = ExportContentItem(siteContentItem).Elements().ToList();
foreach (var contentPart in siteContentItem.Parts) { foreach (var contentPart in siteContentItem.Parts.OrderBy(x => x.PartDefinition.Name)) {
var exportedElement = exportedElements.FirstOrDefault(element => element.Name == contentPart.PartDefinition.Name); var exportedElement = exportedElements.FirstOrDefault(element => element.Name == contentPart.PartDefinition.Name);
//Get all simple attributes if exported element is null //Get all simple attributes if exported element is null
@@ -146,6 +154,7 @@ namespace Orchard.ImportExport.Services {
var simpleAttributes = var simpleAttributes =
ExportSettingsPartAttributes(contentPart) ExportSettingsPartAttributes(contentPart)
.Where(attribute => exportedElement == null || exportedElement.Attributes().All(xAttribute => xAttribute.Name != attribute.Name)) .Where(attribute => exportedElement == null || exportedElement.Attributes().All(xAttribute => xAttribute.Name != attribute.Name))
.OrderBy(x => x.Name.LocalName)
.ToList(); .ToList();
if (simpleAttributes.Any()) { if (simpleAttributes.Any()) {
@@ -158,11 +167,12 @@ namespace Orchard.ImportExport.Services {
} }
} }
exportedElements = exportedElements.OrderBy(x => x.Name.LocalName).ToList();
return new XElement("Settings", exportedElements); return new XElement("Settings", exportedElements);
} }
private IEnumerable<XAttribute> ExportSettingsPartAttributes(ContentPart sitePart) { private IEnumerable<XAttribute> ExportSettingsPartAttributes(ContentPart sitePart) {
foreach (var property in sitePart.GetType().GetProperties()) { foreach (var property in sitePart.GetType().GetProperties().OrderBy(x => x.Name)) {
var propertyType = property.PropertyType; var propertyType = property.PropertyType;
// Supported types (we also know they are not indexed properties). // Supported types (we also know they are not indexed properties).
@@ -185,9 +195,17 @@ namespace Orchard.ImportExport.Services {
if (batchSize.HasValue && batchSize.Value > 0) if (batchSize.HasValue && batchSize.Value > 0)
data.SetAttributeValue("BatchSize", batchSize); data.SetAttributeValue("BatchSize", batchSize);
foreach (var contentType in contentTypes) { var orderedContentItemsQuery =
from contentItem in contentItems
let identity = _contentManager.GetItemMetadata(contentItem).Identity.ToString()
orderby identity
select contentItem;
var orderedContentItems = orderedContentItemsQuery.ToList();
foreach (var contentType in contentTypes.OrderBy(x => x)) {
var type = contentType; var type = contentType;
var items = contentItems.Where(i => i.ContentType == type); var items = orderedContentItems.Where(i => i.ContentType == type);
foreach (var contentItem in items) { foreach (var contentItem in items) {
var contentItemElement = ExportContentItem(contentItem); var contentItemElement = ExportContentItem(contentItem);
if (contentItemElement != null) if (contentItemElement != null)

View File

@@ -27,7 +27,7 @@ namespace Orchard.Layouts.ImportExport {
return; return;
} }
var elements = _repository.Table.ToList(); var elements = _repository.Table.OrderBy(x => x.ElementTypeName).ToList();
if (!elements.Any()) { if (!elements.Any()) {
return; return;

View File

@@ -25,7 +25,7 @@ namespace Orchard.Modules.ImportExport {
var enabledFeatures = _featureManager.GetEnabledFeatures(); var enabledFeatures = _featureManager.GetEnabledFeatures();
var root = new XElement("Feature", new XAttribute("enable", String.Join(", ", enabledFeatures.Select(x => x.Id)))); var root = new XElement("Feature", new XAttribute("enable", String.Join(", ", enabledFeatures.Select(x => x.Id).OrderBy(x => x))));
context.Document.Element("Orchard").Add(root); context.Document.Element("Orchard").Add(root);
} }

View File

@@ -35,7 +35,7 @@ namespace Orchard.Roles.ImportExport {
var root = new XElement("Roles"); var root = new XElement("Roles");
context.Document.Element("Orchard").Add(root); context.Document.Element("Orchard").Add(root);
foreach (var role in roles) { foreach (var role in roles.OrderBy(x => x)) {
root.Add(new XElement("Role", root.Add(new XElement("Role",
new XAttribute("Name", role.Name), new XAttribute("Name", role.Name),
new XAttribute("Permissions", string.Join(",", role.RolesPermissions.Select(rolePermission => rolePermission.Permission.Name))))); new XAttribute("Permissions", string.Join(",", role.RolesPermissions.Select(rolePermission => rolePermission.Permission.Name)))));

View File

@@ -36,7 +36,7 @@ namespace Orchard.Workflows.ImportExport {
var root = new XElement("Workflows"); var root = new XElement("Workflows");
context.Document.Element("Orchard").Add(root); context.Document.Element("Orchard").Add(root);
foreach (var workflowDefinition in workflowDefinitions) { foreach (var workflowDefinition in workflowDefinitions.OrderBy(x => x.Name)) {
root.Add(new XElement("Workflow", root.Add(new XElement("Workflow",
new XAttribute("Name", workflowDefinition.Name), new XAttribute("Name", workflowDefinition.Name),
new XAttribute("Enabled", workflowDefinition.Enabled), new XAttribute("Enabled", workflowDefinition.Enabled),

View File

@@ -1,4 +1,5 @@
using System.Xml; using System.Linq;
using System.Xml;
using System.Xml.Linq; using System.Xml.Linq;
using Orchard.ContentManagement.MetaData.Models; using Orchard.ContentManagement.MetaData.Models;
using Orchard.Validation; using Orchard.Validation;
@@ -36,7 +37,7 @@ namespace Orchard.ContentManagement.MetaData.Services {
typeElement.Add(new XAttribute("DisplayName", contentTypeDefinition.DisplayName)); typeElement.Add(new XAttribute("DisplayName", contentTypeDefinition.DisplayName));
} }
foreach (var typePart in contentTypeDefinition.Parts) { foreach (var typePart in contentTypeDefinition.Parts.OrderBy(x => x.PartDefinition.Name)) {
typeElement.Add(NewElement(typePart.PartDefinition.Name, typePart.Settings)); typeElement.Add(NewElement(typePart.PartDefinition.Name, typePart.Settings));
} }
@@ -52,7 +53,7 @@ namespace Orchard.ContentManagement.MetaData.Services {
Argument.ThrowIfNull(contentPartDefinition, "contentPartDefinition"); Argument.ThrowIfNull(contentPartDefinition, "contentPartDefinition");
var partElement = NewElement(contentPartDefinition.Name, contentPartDefinition.Settings); var partElement = NewElement(contentPartDefinition.Name, contentPartDefinition.Settings);
foreach (var partField in contentPartDefinition.Fields) { foreach (var partField in contentPartDefinition.Fields.OrderBy(x => x.Name)) {
var attributeName = string.Format("{0}.{1}", partField.Name, partField.FieldDefinition.Name); var attributeName = string.Format("{0}.{1}", partField.Name, partField.FieldDefinition.Name);
var partFieldElement = NewElement(attributeName, partField.Settings); var partFieldElement = NewElement(attributeName, partField.Settings);
partElement.Add(partFieldElement); partElement.Add(partFieldElement);