Making Import/Export extensible

--HG--
branch : 1.x
This commit is contained in:
Sebastien Ros
2012-06-22 12:56:45 -07:00
parent 6b0b68a0d9
commit f8f0707c79
8 changed files with 122 additions and 30 deletions

View File

@@ -14,10 +14,17 @@ namespace Orchard.ImportExport.Controllers {
public class AdminController : Controller {
private readonly IImportExportService _importExportService;
private readonly IContentDefinitionManager _contentDefinitionManager;
private readonly ICustomExportStep _customExportStep;
public AdminController(IOrchardServices services, IImportExportService importExportService, IContentDefinitionManager contentDefinitionManager) {
public AdminController(
IOrchardServices services,
IImportExportService importExportService,
IContentDefinitionManager contentDefinitionManager,
ICustomExportStep customExportStep
) {
_importExportService = importExportService;
_contentDefinitionManager = contentDefinitionManager;
_customExportStep = customExportStep;
Services = services;
T = NullLocalizer.Instance;
}
@@ -50,10 +57,18 @@ namespace Orchard.ImportExport.Controllers {
}
public ActionResult Export() {
var viewModel = new ExportViewModel { ContentTypes = new List<ContentTypeEntry>() };
var customSteps = new List<string>();
_customExportStep.Register(customSteps);
var viewModel = new ExportViewModel {
ContentTypes = new List<ContentTypeEntry>(),
CustomSteps = customSteps.Select(x => new CustomStepEntry { CustomStep = x }).ToList()
};
foreach (var contentType in _contentDefinitionManager.ListTypeDefinitions().OrderBy(c => c.Name)) {
viewModel.ContentTypes.Add(new ContentTypeEntry { ContentTypeName = contentType.Name });
}
return View(viewModel);
}
@@ -62,11 +77,21 @@ namespace Orchard.ImportExport.Controllers {
if (!Services.Authorizer.Authorize(Permissions.Export, T("Not allowed to export.")))
return new HttpUnauthorizedResult();
var viewModel = new ExportViewModel { ContentTypes = new List<ContentTypeEntry>() };
var viewModel = new ExportViewModel {
ContentTypes = new List<ContentTypeEntry>(),
CustomSteps = new List<CustomStepEntry>()
};
UpdateModel(viewModel);
var contentTypesToExport = viewModel.ContentTypes.Where(c => c.IsChecked).Select(c => c.ContentTypeName);
var exportOptions = new ExportOptions { ExportMetadata = viewModel.Metadata, ExportSiteSettings = viewModel.SiteSettings };
var customSteps = viewModel.CustomSteps.Where(c => c.IsChecked).Select(c => c.CustomStep);
var exportOptions = new ExportOptions {
ExportMetadata = viewModel.Metadata,
ExportSiteSettings = viewModel.SiteSettings,
CustomSteps = customSteps
};
if (viewModel.Data) {
exportOptions.ExportData = true;
exportOptions.VersionHistoryOptions = (VersionHistoryOptions)Enum.Parse(typeof(VersionHistoryOptions), viewModel.DataImportChoice, true);

View File

@@ -1,9 +1,12 @@
namespace Orchard.ImportExport.Models {
using System.Collections.Generic;
namespace Orchard.ImportExport.Models {
public class ExportOptions {
public bool ExportMetadata { get; set; }
public bool ExportData { get; set; }
public VersionHistoryOptions VersionHistoryOptions { get; set; }
public bool ExportSiteSettings { get; set; }
public IEnumerable<string> CustomSteps { get; set; }
}
public enum VersionHistoryOptions {

View File

@@ -53,6 +53,8 @@
<Compile Include="Models\ExportOptions.cs" />
<Compile Include="Permissions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Services\ICustomExportStep.cs" />
<Compile Include="Services\IExportEventHandler.cs" />
<Compile Include="Services\IImportExportService.cs" />
<Compile Include="Services\ImportExportService.cs" />
<Compile Include="ViewModels\ExportViewModel.cs" />

View File

@@ -0,0 +1,8 @@
using System.Collections.Generic;
using Orchard.Events;
namespace Orchard.ImportExport.Services {
public interface ICustomExportStep : IEventHandler {
void Register(IList<string> steps);
}
}

View File

@@ -0,0 +1,17 @@
using System.Collections.Generic;
using System.Xml.Linq;
using Orchard.Events;
using Orchard.ImportExport.Models;
namespace Orchard.ImportExport.Services {
public class ExportContext {
public XDocument Document { get; set; }
public IEnumerable<string> ContentTypes { get; set; }
public ExportOptions ExportOptions { get; set; }
}
public interface IExportEventHandler : IEventHandler {
void Exporting(ExportContext context);
void Exported(ExportContext context);
}
}

View File

@@ -23,6 +23,7 @@ namespace Orchard.ImportExport.Services {
private readonly IRecipeParser _recipeParser;
private readonly IRecipeManager _recipeManager;
private readonly IShellDescriptorManager _shellDescriptorManager;
private readonly IEnumerable<IExportEventHandler> _exportEventHandlers;
private const string ExportsDirectory = "Exports";
public ImportExportService(
@@ -32,7 +33,8 @@ namespace Orchard.ImportExport.Services {
IAppDataFolder appDataFolder,
IRecipeParser recipeParser,
IRecipeManager recipeManager,
IShellDescriptorManager shellDescriptorManager) {
IShellDescriptorManager shellDescriptorManager,
IEnumerable<IExportEventHandler> exportEventHandlers) {
_orchardServices = orchardServices;
_contentDefinitionManager = contentDefinitionManager;
_contentDefinitionWriter = contentDefinitionWriter;
@@ -40,6 +42,7 @@ namespace Orchard.ImportExport.Services {
_recipeParser = recipeParser;
_recipeManager = recipeManager;
_shellDescriptorManager = shellDescriptorManager;
_exportEventHandlers = exportEventHandlers;
Logger = NullLogger.Instance;
T = NullLocalizer.Instance;
}
@@ -56,6 +59,14 @@ namespace Orchard.ImportExport.Services {
public string Export(IEnumerable<string> contentTypes, ExportOptions exportOptions) {
var exportDocument = CreateExportRoot();
var context = new ExportContext {
Document = exportDocument,
ContentTypes = contentTypes,
ExportOptions = exportOptions
};
_exportEventHandlers.Invoke(x => x.Exporting(context), Logger);
if (exportOptions.ExportMetadata) {
exportDocument.Element("Orchard").Add(ExportMetadata(contentTypes));
}
@@ -68,6 +79,8 @@ namespace Orchard.ImportExport.Services {
exportDocument.Element("Orchard").Add(ExportData(contentTypes, exportOptions.VersionHistoryOptions));
}
_exportEventHandlers.Invoke(x => x.Exported(context), Logger);
return WriteExportFile(exportDocument.ToString());
}

View File

@@ -3,6 +3,7 @@
namespace Orchard.ImportExport.ViewModels {
public class ExportViewModel {
public IList<ContentTypeEntry> ContentTypes { get; set; }
public IList<CustomStepEntry> CustomSteps { get; set; }
public virtual bool Metadata { get; set; }
public virtual bool Data { get; set; }
public virtual string DataImportChoice { get; set; }
@@ -13,4 +14,9 @@ namespace Orchard.ImportExport.ViewModels {
public string ContentTypeName { get; set; }
public bool IsChecked { get; set; }
}
public class CustomStepEntry {
public string CustomStep { get; set; }
public bool IsChecked { get; set; }
}
}

View File

@@ -3,7 +3,7 @@
@{ Layout.Title = T("Export").ToString(); }
@using(Html.BeginFormAntiForgeryPost()) {
@using (Html.BeginFormAntiForgeryPost()) {
Html.ValidationSummary();
<fieldset>
<legend>@T("Choose the types to include in the export file:")</legend>
@@ -15,36 +15,54 @@
<input type="checkbox" value="true" name="@Html.NameOf(m => m.ContentTypes[contentTypeIndex].IsChecked)" id="@Html.NameOf(m => m.ContentTypes[contentTypeIndex].IsChecked)" />
<label class="forcheckbox" for="@Html.NameOf(m => m.ContentTypes[contentTypeIndex].IsChecked)">@Model.ContentTypes[contentTypeIndex].ContentTypeName.CamelFriendly()</label>
</li>
contentTypeIndex = contentTypeIndex + 1;
}
contentTypeIndex = contentTypeIndex + 1;
}
</ol>
</fieldset>
<hr />
<fieldset>
<legend>@T("Choose what to save for these types:")</legend>
<div>
@Html.EditorFor(m => m.Metadata)
<label class="forcheckbox" for="@Html.FieldIdFor( m => m.Metadata)">@T("Metadata")</label>
<span class="hint">@T("Metadata is the definition of your content types: what parts and fields they have, with what settings.")</span>
</div>
<div>
@Html.EditorFor(m => m.Data)
<label class="forcheckbox" for="@Html.FieldIdFor( m => m.Data)">@T("Data")</label>
<span class="hint">@T("Data is the actual content of your site.")</span>
</div>
<div>
<p>@T("Version History")</p>
<legend>@T("Choose what to save for these types:")</legend>
<div>
@Html.EditorFor(m => m.Metadata)
<label class="forcheckbox" for="@Html.FieldIdFor(m => m.Metadata)">@T("Metadata")</label>
<span class="hint">@T("Metadata is the definition of your content types: what parts and fields they have, with what settings.")</span>
</div>
<div>
@Html.EditorFor(m => m.Data)
<label class="forcheckbox" for="@Html.FieldIdFor(m => m.Data)">@T("Data")</label>
<span class="hint">@T("Data is the actual content of your site.")</span>
</div>
<div>
<p>@T("Version History")</p>
@Html.RadioButtonFor(m => m.DataImportChoice, "Published", new { id = "Published", Checked = "Checked" })
<label for="@Html.FieldIdFor(m => m.DataImportChoice)" class="forcheckbox">@T("Only Published Versions")</label>
<br />
<br />
@Html.RadioButtonFor(m => m.DataImportChoice, "Draft", new { id = "Draft" })
<label for="@Html.FieldIdFor(m => m.DataImportChoice)" class="forcheckbox">@T("Only Drafts")</label>
</div>
<div>
@Html.EditorFor(m => m.SiteSettings)
<label class="forcheckbox" for="@Html.FieldIdFor( m => m.SiteSettings)">@T("Site Settings")</label><br />
<span class="hint">@T("Please verify that you are not exporting confidential information, such as passwords or application keys.")</span>
</div>
</fieldset>
<button type="submit" class="primaryAction">@T("Export")</button>
<div>
@Html.EditorFor(m => m.SiteSettings)
<label class="forcheckbox" for="@Html.FieldIdFor(m => m.SiteSettings)">@T("Site Settings")</label><br />
<span class="hint">@T("Please verify that you are not exporting confidential information, such as passwords or application keys.")</span>
</div>
</fieldset>
if (Model.CustomSteps.Any()) {
<fieldset>
<legend>@T("Choose the custom steps to execute in the export file:")</legend>
<ol>
@{ var customStepIndex = 0; }
@foreach (var customStepEntry in Model.CustomSteps) {
<li>
<input type="hidden" value="@Model.CustomSteps[customStepIndex].CustomStep" name="@Html.NameOf(m => m.CustomSteps[customStepIndex].CustomStep)"/>
<input type="checkbox" value="true" name="@Html.NameOf(m => m.CustomSteps[customStepIndex].IsChecked)" id="@Html.NameOf(m => m.CustomSteps[customStepIndex].IsChecked)" />
<label class="forcheckbox" for="@Html.NameOf(m => m.CustomSteps[customStepIndex].IsChecked)">@Model.CustomSteps[customStepIndex].CustomStep.CamelFriendly()</label>
</li>
customStepIndex = customStepIndex + 1;
}
</ol>
</fieldset>
}
<button type="submit" class="primaryAction">@T("Export")</button>
}