#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);
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 exportOptions = new ExportOptions {

View File

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

View File

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

View File

@@ -25,7 +25,7 @@ namespace Orchard.Modules.ImportExport {
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);
}

View File

@@ -35,7 +35,7 @@ namespace Orchard.Roles.ImportExport {
var root = new XElement("Roles");
context.Document.Element("Orchard").Add(root);
foreach (var role in roles) {
foreach (var role in roles.OrderBy(x => x)) {
root.Add(new XElement("Role",
new XAttribute("Name", role.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");
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",
new XAttribute("Name", workflowDefinition.Name),
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 Orchard.ContentManagement.MetaData.Models;
using Orchard.Validation;
@@ -36,7 +37,7 @@ namespace Orchard.ContentManagement.MetaData.Services {
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));
}
@@ -52,7 +53,7 @@ namespace Orchard.ContentManagement.MetaData.Services {
Argument.ThrowIfNull(contentPartDefinition, "contentPartDefinition");
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 partFieldElement = NewElement(attributeName, partField.Settings);
partElement.Add(partFieldElement);