diff --git a/src/Orchard.Web/Modules/Orchard.Dashboards/Web.config b/src/Orchard.Web/Modules/Orchard.Dashboards/Web.config
index 0e1f9723e..020c2b855 100644
--- a/src/Orchard.Web/Modules/Orchard.Dashboards/Web.config
+++ b/src/Orchard.Web/Modules/Orchard.Dashboards/Web.config
@@ -3,22 +3,22 @@
-
-
-
-
+
+
+
+
-
+
-
-
-
-
-
+
+
+
+
+
@@ -32,7 +32,7 @@
-
+
@@ -41,4 +41,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Orchard.Web/Modules/Orchard.ImportExport/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.ImportExport/Controllers/AdminController.cs
index c6fbc6bdc..aea0e79e4 100644
--- a/src/Orchard.Web/Modules/Orchard.ImportExport/Controllers/AdminController.cs
+++ b/src/Orchard.Web/Modules/Orchard.ImportExport/Controllers/AdminController.cs
@@ -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 {
diff --git a/src/Orchard.Web/Modules/Orchard.ImportExport/Orchard.ImportExport.csproj b/src/Orchard.Web/Modules/Orchard.ImportExport/Orchard.ImportExport.csproj
index 27d2255e0..9bc33d63a 100644
--- a/src/Orchard.Web/Modules/Orchard.ImportExport/Orchard.ImportExport.csproj
+++ b/src/Orchard.Web/Modules/Orchard.ImportExport/Orchard.ImportExport.csproj
@@ -25,6 +25,7 @@
+
true
@@ -108,9 +109,7 @@
-
-
-
+
diff --git a/src/Orchard.Web/Modules/Orchard.ImportExport/Services/ImportExportService.cs b/src/Orchard.Web/Modules/Orchard.ImportExport/Services/ImportExportService.cs
index c621c2f9b..6778bd31a 100644
--- a/src/Orchard.Web/Modules/Orchard.ImportExport/Services/ImportExportService.cs
+++ b/src/Orchard.Web/Modules/Orchard.ImportExport/Services/ImportExportService.cs
@@ -4,17 +4,15 @@ using System.Linq;
using System.Xml;
using System.Xml.Linq;
using Orchard.ContentManagement;
-using Orchard.ContentManagement.Handlers;
using Orchard.ContentManagement.MetaData;
+using Orchard.ContentManagement.MetaData.Models;
using Orchard.Environment.Descriptor;
using Orchard.FileSystems.AppData;
using Orchard.ImportExport.Models;
using Orchard.Localization;
using Orchard.Logging;
-using Orchard.Recipes.Models;
using Orchard.Recipes.Services;
using Orchard.Services;
-using VersionOptions = Orchard.ContentManagement.VersionOptions;
namespace Orchard.ImportExport.Services {
public class ImportExportService : IImportExportService {
@@ -27,6 +25,7 @@ namespace Orchard.ImportExport.Services {
private readonly IShellDescriptorManager _shellDescriptorManager;
private readonly IClock _clock;
private readonly IEnumerable _exportEventHandlers;
+ private readonly IContentManager _contentManager;
private const string ExportsDirectory = "Exports";
public ImportExportService(
@@ -38,7 +37,9 @@ namespace Orchard.ImportExport.Services {
IRecipeManager recipeManager,
IShellDescriptorManager shellDescriptorManager,
IClock clock,
- IEnumerable exportEventHandlers) {
+ IEnumerable exportEventHandlers,
+ IContentManager contentManager) {
+
_orchardServices = orchardServices;
_contentDefinitionManager = contentDefinitionManager;
_contentDefinitionWriter = contentDefinitionWriter;
@@ -48,6 +49,7 @@ namespace Orchard.ImportExport.Services {
_shellDescriptorManager = shellDescriptorManager;
_clock = clock;
_exportEventHandlers = exportEventHandlers;
+ _contentManager = contentManager;
Logger = NullLogger.Instance;
T = NullLocalizer.Instance;
}
@@ -66,7 +68,7 @@ namespace Orchard.ImportExport.Services {
//items need to be retrieved
IEnumerable 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);
@@ -121,19 +123,22 @@ namespace Orchard.ImportExport.Services {
var typesToExport = _contentDefinitionManager.ListTypeDefinitions()
.Where(typeDefinition => contentTypes.Contains(typeDefinition.Name))
.ToList();
- var partsToExport = new List();
+ var partsToExport = new Dictionary();
- 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);
}
@@ -141,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
@@ -149,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()) {
@@ -161,11 +167,12 @@ namespace Orchard.ImportExport.Services {
}
}
+ exportedElements = exportedElements.OrderBy(x => x.Name.LocalName).ToList();
return new XElement("Settings", exportedElements);
}
private IEnumerable 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).
@@ -188,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)
diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/ImportExport/ElementsExportHandler.cs b/src/Orchard.Web/Modules/Orchard.Layouts/ImportExport/ElementsExportHandler.cs
index e85960e42..c122f8745 100644
--- a/src/Orchard.Web/Modules/Orchard.Layouts/ImportExport/ElementsExportHandler.cs
+++ b/src/Orchard.Web/Modules/Orchard.Layouts/ImportExport/ElementsExportHandler.cs
@@ -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;
diff --git a/src/Orchard.Web/Modules/Orchard.Modules/ImportExport/FeaturesExportHandler.cs b/src/Orchard.Web/Modules/Orchard.Modules/ImportExport/FeaturesExportHandler.cs
new file mode 100644
index 000000000..a6eb194ee
--- /dev/null
+++ b/src/Orchard.Web/Modules/Orchard.Modules/ImportExport/FeaturesExportHandler.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Xml.Linq;
+using Orchard.Environment.Features;
+using Orchard.Events;
+
+namespace Orchard.Modules.ImportExport {
+ public interface IExportEventHandler : IEventHandler {
+ void Exporting(dynamic context);
+ void Exported(dynamic context);
+ }
+
+ public class FeaturesExportHandler : IExportEventHandler {
+ private readonly IFeatureManager _featureManager;
+
+ public FeaturesExportHandler(IFeatureManager featureManager) {
+ _featureManager = featureManager;
+ }
+
+ public void Exporting(dynamic context) {
+ if (!((IEnumerable)context.ExportOptions.CustomSteps).Contains("Features")) {
+ return;
+ }
+
+ var enabledFeatures = _featureManager.GetEnabledFeatures();
+
+ var root = new XElement("Feature", new XAttribute("enable", String.Join(", ", enabledFeatures.Select(x => x.Id).OrderBy(x => x))));
+ context.Document.Element("Orchard").Add(root);
+ }
+
+ public void Exported(dynamic context) {
+ }
+ }
+}
+
diff --git a/src/Orchard.Web/Modules/Orchard.Modules/ImportExport/FeaturesStep.cs b/src/Orchard.Web/Modules/Orchard.Modules/ImportExport/FeaturesStep.cs
new file mode 100644
index 000000000..09ed03ae0
--- /dev/null
+++ b/src/Orchard.Web/Modules/Orchard.Modules/ImportExport/FeaturesStep.cs
@@ -0,0 +1,14 @@
+using System.Collections.Generic;
+using Orchard.Events;
+
+namespace Orchard.Modules.ImportExport {
+ public interface ICustomExportStep : IEventHandler {
+ void Register(IList steps);
+ }
+
+ public class FeaturesStep : ICustomExportStep {
+ public void Register(IList steps) {
+ steps.Add("Features");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Orchard.Web/Modules/Orchard.Modules/Module.txt b/src/Orchard.Web/Modules/Orchard.Modules/Module.txt
index 230cb0004..fef422ee6 100644
--- a/src/Orchard.Web/Modules/Orchard.Modules/Module.txt
+++ b/src/Orchard.Web/Modules/Orchard.Modules/Module.txt
@@ -7,3 +7,13 @@ OrchardVersion: 1.9
Description: The Modules module enables the administrator of the site to manage the installed modules as well as activate and de-activate features.
FeatureDescription: Standard module and feature management.
Category: Core
+Features:
+ Orchard.Modules:
+ Description: Standard module and feature management.
+ Dependencies: Orchard.jQuery
+ Category: Core
+ Orchard.Modules.ExportFeatures:
+ Name: Export Features
+ Description: Provides feature export capability.
+ Category: Deployment
+ Dependencies: Orchard.ImportExport
diff --git a/src/Orchard.Web/Modules/Orchard.Modules/Orchard.Modules.csproj b/src/Orchard.Web/Modules/Orchard.Modules/Orchard.Modules.csproj
index 873103541..48c3a1a63 100644
--- a/src/Orchard.Web/Modules/Orchard.Modules/Orchard.Modules.csproj
+++ b/src/Orchard.Web/Modules/Orchard.Modules/Orchard.Modules.csproj
@@ -25,6 +25,7 @@
+
true
@@ -64,12 +65,15 @@
False
..\..\..\..\lib\aspnetmvc\System.Web.Mvc.dll
+
+
+
diff --git a/src/Orchard.Web/Modules/Orchard.Roles/ImportExport/RolesExportEventHandler.cs b/src/Orchard.Web/Modules/Orchard.Roles/ImportExport/RolesExportEventHandler.cs
index d0b67e04d..d4b528f37 100644
--- a/src/Orchard.Web/Modules/Orchard.Roles/ImportExport/RolesExportEventHandler.cs
+++ b/src/Orchard.Web/Modules/Orchard.Roles/ImportExport/RolesExportEventHandler.cs
@@ -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)))));
diff --git a/src/Orchard.Web/Modules/Orchard.Workflows/ImportExport/WorkflowsExportEventHandler.cs b/src/Orchard.Web/Modules/Orchard.Workflows/ImportExport/WorkflowsExportEventHandler.cs
index 9943b1b82..f8acefcee 100644
--- a/src/Orchard.Web/Modules/Orchard.Workflows/ImportExport/WorkflowsExportEventHandler.cs
+++ b/src/Orchard.Web/Modules/Orchard.Workflows/ImportExport/WorkflowsExportEventHandler.cs
@@ -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),
diff --git a/src/Orchard.Web/Modules/Orchard.Workflows/Module.txt b/src/Orchard.Web/Modules/Orchard.Workflows/Module.txt
index 245e7fbe2..83a7e0640 100644
--- a/src/Orchard.Web/Modules/Orchard.Workflows/Module.txt
+++ b/src/Orchard.Web/Modules/Orchard.Workflows/Module.txt
@@ -11,7 +11,7 @@ Features:
Description: Provides tools to create custom workflows.
Dependencies: Orchard.Tokens, Orchard.Forms, Orchard.jQuery
Orchard.Workflows.Timer:
- Name: Workflows Timer
+ Name: Workflows Timer
Description: Provides a Timer activity.
Category: Workflows
Dependencies: Orchard.Workflows
diff --git a/src/Orchard/ContentManagement/MetaData/Services/ContentDefinitionWriter.cs b/src/Orchard/ContentManagement/MetaData/Services/ContentDefinitionWriter.cs
index 9c300f255..d72412db2 100644
--- a/src/Orchard/ContentManagement/MetaData/Services/ContentDefinitionWriter.cs
+++ b/src/Orchard/ContentManagement/MetaData/Services/ContentDefinitionWriter.cs
@@ -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);