mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2026-02-09 09:16:41 +08:00
Created ExportAction abstraction and RecipeBuilder implementation.
This commit is contained in:
@@ -7,28 +7,26 @@ using Orchard.ContentManagement;
|
|||||||
using Orchard.ImportExport.Services;
|
using Orchard.ImportExport.Services;
|
||||||
using Orchard.ImportExport.ViewModels;
|
using Orchard.ImportExport.ViewModels;
|
||||||
using Orchard.Localization;
|
using Orchard.Localization;
|
||||||
using Orchard.Recipes.Models;
|
|
||||||
using Orchard.Recipes.Services;
|
using Orchard.Recipes.Services;
|
||||||
using Orchard.UI.Notify;
|
using Orchard.UI.Notify;
|
||||||
using Orchard.Utility.Extensions;
|
|
||||||
|
|
||||||
namespace Orchard.ImportExport.Controllers {
|
namespace Orchard.ImportExport.Controllers {
|
||||||
public class AdminController : Controller, IUpdateModel {
|
public class AdminController : Controller, IUpdateModel {
|
||||||
private readonly IImportExportService _importExportService;
|
private readonly IImportExportService _importExportService;
|
||||||
private readonly IRecipeResultAccessor _recipeResultAccessor;
|
private readonly IRecipeResultAccessor _recipeResultAccessor;
|
||||||
private readonly IEnumerable<IRecipeBuilderStep> _exportStepProviders;
|
private readonly IEnumerable<IExportAction> _exportActions;
|
||||||
private readonly IRecipeParser _recipeParser;
|
private readonly IRecipeParser _recipeParser;
|
||||||
|
|
||||||
public AdminController(
|
public AdminController(
|
||||||
IOrchardServices services,
|
IOrchardServices services,
|
||||||
IImportExportService importExportService,
|
IImportExportService importExportService,
|
||||||
IRecipeResultAccessor recipeResultAccessor,
|
IRecipeResultAccessor recipeResultAccessor,
|
||||||
IEnumerable<IRecipeBuilderStep> exportStepProviders,
|
IEnumerable<IExportAction> exportActions,
|
||||||
IRecipeParser recipeParser) {
|
IRecipeParser recipeParser) {
|
||||||
|
|
||||||
_importExportService = importExportService;
|
_importExportService = importExportService;
|
||||||
_recipeResultAccessor = recipeResultAccessor;
|
_recipeResultAccessor = recipeResultAccessor;
|
||||||
_exportStepProviders = exportStepProviders;
|
_exportActions = exportActions;
|
||||||
_recipeParser = recipeParser;
|
_recipeParser = recipeParser;
|
||||||
Services = services;
|
Services = services;
|
||||||
T = NullLocalizer.Instance;
|
T = NullLocalizer.Instance;
|
||||||
@@ -72,15 +70,12 @@ namespace Orchard.ImportExport.Controllers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ActionResult Export() {
|
public ActionResult Export() {
|
||||||
var exportSteps = _exportStepProviders.OrderBy(x => x.Priority).Select(x => new ExportStepViewModel {
|
var actions = _exportActions.OrderBy(x => x.Priority).Select(x => new ExportActionViewModel {
|
||||||
Name = x.Name,
|
|
||||||
DisplayName = x.DisplayName,
|
|
||||||
Description = x.Description,
|
|
||||||
Editor = x.BuildEditor(Services.New)
|
Editor = x.BuildEditor(Services.New)
|
||||||
}).Where(x => x != null);
|
}).Where(x => x != null).ToList();
|
||||||
|
|
||||||
var viewModel = new ExportViewModel {
|
var viewModel = new ExportViewModel {
|
||||||
ExportSteps = exportSteps.ToList()
|
Actions = actions
|
||||||
};
|
};
|
||||||
|
|
||||||
return View(viewModel);
|
return View(viewModel);
|
||||||
@@ -90,32 +85,22 @@ namespace Orchard.ImportExport.Controllers {
|
|||||||
public ActionResult ExportPOST(ExportViewModel viewModel) {
|
public ActionResult ExportPOST(ExportViewModel viewModel) {
|
||||||
if (!Services.Authorizer.Authorize(Permissions.Export, T("Not allowed to export.")))
|
if (!Services.Authorizer.Authorize(Permissions.Export, T("Not allowed to export.")))
|
||||||
return new HttpUnauthorizedResult();
|
return new HttpUnauthorizedResult();
|
||||||
|
|
||||||
var exportStepNames = viewModel.ExportSteps.Where(x => x.IsSelected).Select(x => x.Name);
|
var actions = _exportActions.OrderBy(x => x.Priority).ToList();
|
||||||
var exportStepsQuery = from name in exportStepNames
|
|
||||||
let provider = _exportStepProviders.SingleOrDefault(x => x.Name == name)
|
foreach (var action in actions) {
|
||||||
where provider != null
|
action.UpdateEditor(Services.New, this);
|
||||||
select provider;
|
|
||||||
var exportSteps = exportStepsQuery.ToArray();
|
|
||||||
|
|
||||||
foreach (var exportStep in exportSteps) {
|
|
||||||
exportStep.UpdateEditor(Services.New, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var recipeDocument = _importExportService.ExportXml(exportSteps);
|
var exportActionContext = new ExportActionContext {
|
||||||
var recipe = _recipeParser.ParseRecipe(recipeDocument);
|
ActionResult = RedirectToAction("Export")
|
||||||
var exportFileName = GetExportFileName(recipe);
|
};
|
||||||
var exportFilePath = _importExportService.WriteExportFile(recipeDocument);
|
|
||||||
|
|
||||||
return File(exportFilePath, "text/xml", exportFileName);
|
foreach (var action in actions) {
|
||||||
}
|
action.Execute(exportActionContext);
|
||||||
|
}
|
||||||
private string GetExportFileName(Recipe recipe) {
|
|
||||||
return String.IsNullOrWhiteSpace(recipe.Name)
|
return exportActionContext.ActionResult;
|
||||||
? "export.xml"
|
|
||||||
: String.Format(recipe.IsSetupRecipe
|
|
||||||
? "{0}.recipe.xml"
|
|
||||||
: "{0}.export.xml", recipe.Name.HtmlClassify());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IUpdateModel.TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) {
|
bool IUpdateModel.TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) {
|
||||||
|
|||||||
@@ -71,18 +71,24 @@
|
|||||||
<Compile Include="Models\ExportOptions.cs" />
|
<Compile Include="Models\ExportOptions.cs" />
|
||||||
<Compile Include="Permissions.cs" />
|
<Compile Include="Permissions.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="Providers\ExportActions\RecipeBuilder.cs" />
|
||||||
<Compile Include="Recipes\Builders\CustomStepsStep.cs" />
|
<Compile Include="Recipes\Builders\CustomStepsStep.cs" />
|
||||||
|
<Compile Include="Services\ExportAction.cs" />
|
||||||
|
<Compile Include="Services\ExportActionContext.cs" />
|
||||||
<Compile Include="Services\ExportContext.cs" />
|
<Compile Include="Services\ExportContext.cs" />
|
||||||
|
<Compile Include="Services\IExportAction.cs" />
|
||||||
<Compile Include="ViewModels\CustomStepEntry.cs" />
|
<Compile Include="ViewModels\CustomStepEntry.cs" />
|
||||||
<Compile Include="Services\ICustomExportStep.cs" />
|
<Compile Include="Services\ICustomExportStep.cs" />
|
||||||
<Compile Include="Services\IExportEventHandler.cs" />
|
<Compile Include="Services\IExportEventHandler.cs" />
|
||||||
<Compile Include="Services\IImportExportService.cs" />
|
<Compile Include="Services\IImportExportService.cs" />
|
||||||
<Compile Include="Services\ImportExportService.cs" />
|
<Compile Include="Services\ImportExportService.cs" />
|
||||||
<Compile Include="ViewModels\CustomStepsViewModel.cs" />
|
<Compile Include="ViewModels\CustomStepsViewModel.cs" />
|
||||||
|
<Compile Include="ViewModels\ExportActionViewModel.cs" />
|
||||||
<Compile Include="ViewModels\ExportStepViewModel.cs" />
|
<Compile Include="ViewModels\ExportStepViewModel.cs" />
|
||||||
<Compile Include="ViewModels\ExportViewModel.cs" />
|
<Compile Include="ViewModels\ExportViewModel.cs" />
|
||||||
<Compile Include="ViewModels\ImportResultViewModel.cs" />
|
<Compile Include="ViewModels\ImportResultViewModel.cs" />
|
||||||
<Compile Include="ViewModels\ImportViewModel.cs" />
|
<Compile Include="ViewModels\ImportViewModel.cs" />
|
||||||
|
<Compile Include="ViewModels\RecipeBuilderViewModel.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="Module.txt" />
|
<Content Include="Module.txt" />
|
||||||
@@ -123,10 +129,15 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="Views\Admin\ImportResult.cshtml" />
|
<Content Include="Views\Admin\ImportResult.cshtml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup />
|
<ItemGroup>
|
||||||
|
<Folder Include="Providers\ImportActions\" />
|
||||||
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="Views\EditorTemplates\ExportSteps\CustomSteps.cshtml" />
|
<Content Include="Views\EditorTemplates\ExportSteps\CustomSteps.cshtml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="Views\EditorTemplates\ExportActions\RecipeBuilder.cshtml" />
|
||||||
|
</ItemGroup>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
||||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Web.Mvc;
|
||||||
|
using Orchard.ContentManagement;
|
||||||
|
using Orchard.ImportExport.Services;
|
||||||
|
using Orchard.ImportExport.ViewModels;
|
||||||
|
using Orchard.Mvc;
|
||||||
|
using Orchard.Recipes.Models;
|
||||||
|
using Orchard.Recipes.Services;
|
||||||
|
using Orchard.Utility.Extensions;
|
||||||
|
|
||||||
|
namespace Orchard.ImportExport.Providers.ExportActions {
|
||||||
|
public class RecipeBuilder : ExportAction {
|
||||||
|
private readonly IEnumerable<IRecipeBuilderStep> _recipeBuilderSteps;
|
||||||
|
private readonly IImportExportService _importExportService;
|
||||||
|
private readonly IRecipeParser _recipeParser;
|
||||||
|
|
||||||
|
public RecipeBuilder(IEnumerable<IRecipeBuilderStep> recipeBuilderSteps, IImportExportService importExportService, IRecipeParser recipeParser) {
|
||||||
|
_recipeBuilderSteps = recipeBuilderSteps;
|
||||||
|
_importExportService = importExportService;
|
||||||
|
_recipeParser = recipeParser;
|
||||||
|
|
||||||
|
RecipeBuilderSteps = new List<IRecipeBuilderStep>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Name { get { return "RecipeBuilder"; } }
|
||||||
|
|
||||||
|
public IList<IRecipeBuilderStep> RecipeBuilderSteps { get; set; }
|
||||||
|
|
||||||
|
public override dynamic BuildEditor(dynamic shapeFactory) {
|
||||||
|
return UpdateEditor(shapeFactory, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override dynamic UpdateEditor(dynamic shapeFactory, IUpdateModel updater) {
|
||||||
|
var builderSteps = _recipeBuilderSteps.OrderBy(x => x.Priority).Select(x => new ExportStepViewModel {
|
||||||
|
Name = x.Name,
|
||||||
|
DisplayName = x.DisplayName,
|
||||||
|
Description = x.Description,
|
||||||
|
Editor = x.BuildEditor(shapeFactory)
|
||||||
|
}).Where(x => x != null);
|
||||||
|
|
||||||
|
var viewModel = new RecipeBuilderViewModel {
|
||||||
|
Steps = builderSteps.ToList()
|
||||||
|
};
|
||||||
|
|
||||||
|
if (updater != null) {
|
||||||
|
if (updater.TryUpdateModel(viewModel, Prefix, null, null)) {
|
||||||
|
var exportStepNames = viewModel.Steps.Where(x => x.IsSelected).Select(x => x.Name);
|
||||||
|
var stepsQuery = from name in exportStepNames
|
||||||
|
let provider = _recipeBuilderSteps.SingleOrDefault(x => x.Name == name)
|
||||||
|
where provider != null
|
||||||
|
select provider;
|
||||||
|
var steps = stepsQuery.ToArray();
|
||||||
|
var stepUpdater = new Updater(updater, secondHalf => String.Format("{0}.{1}", Prefix, secondHalf));
|
||||||
|
foreach (var exportStep in steps) {
|
||||||
|
exportStep.UpdateEditor(shapeFactory, stepUpdater);
|
||||||
|
}
|
||||||
|
|
||||||
|
RecipeBuilderSteps = steps;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return shapeFactory.EditorTemplate(TemplateName: "ExportActions/RecipeBuilder", Model: viewModel, Prefix: Prefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Execute(ExportActionContext context) {
|
||||||
|
var recipeDocument = _importExportService.ExportXml(RecipeBuilderSteps);
|
||||||
|
var recipe = _recipeParser.ParseRecipe(recipeDocument);
|
||||||
|
var exportFileName = GetExportFileName(recipe);
|
||||||
|
var exportFilePath = _importExportService.WriteExportFile(recipeDocument);
|
||||||
|
var actionResult = new FilePathResult(exportFilePath, "text/xml");
|
||||||
|
|
||||||
|
actionResult.FileDownloadName = exportFileName;
|
||||||
|
context.ActionResult = actionResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetExportFileName(Recipe recipe) {
|
||||||
|
return String.IsNullOrWhiteSpace(recipe.Name)
|
||||||
|
? "export.xml"
|
||||||
|
: String.Format(recipe.IsSetupRecipe
|
||||||
|
? "{0}.recipe.xml"
|
||||||
|
: "{0}.export.xml", recipe.Name.HtmlClassify());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
using Orchard.ContentManagement;
|
||||||
|
|
||||||
|
namespace Orchard.ImportExport.Services {
|
||||||
|
public abstract class ExportAction : IExportAction {
|
||||||
|
public virtual int Priority { get { return 0; } }
|
||||||
|
public abstract string Name { get; }
|
||||||
|
|
||||||
|
protected virtual string Prefix {
|
||||||
|
get { return GetType().Name; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual dynamic BuildEditor(dynamic shapeFactory) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual dynamic UpdateEditor(dynamic shapeFactory, IUpdateModel updater) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void Execute(ExportActionContext exportActionContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
using System.Web.Mvc;
|
||||||
|
|
||||||
|
namespace Orchard.ImportExport.Services {
|
||||||
|
public class ExportActionContext {
|
||||||
|
public ActionResult ActionResult { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
using Orchard.ContentManagement;
|
||||||
|
|
||||||
|
namespace Orchard.ImportExport.Services {
|
||||||
|
public interface IExportAction : IDependency {
|
||||||
|
int Priority { get; }
|
||||||
|
string Name { get; }
|
||||||
|
|
||||||
|
dynamic BuildEditor(dynamic shapeFactory);
|
||||||
|
dynamic UpdateEditor(dynamic shapeFactory, IUpdateModel updater);
|
||||||
|
void Execute(ExportActionContext exportActionContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
namespace Orchard.ImportExport.ViewModels {
|
||||||
|
public class ExportActionViewModel {
|
||||||
|
public dynamic Editor { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,6 @@
|
|||||||
|
|
||||||
namespace Orchard.ImportExport.ViewModels {
|
namespace Orchard.ImportExport.ViewModels {
|
||||||
public class ExportViewModel {
|
public class ExportViewModel {
|
||||||
public IList<ExportStepViewModel> ExportSteps { get; set; }
|
public IList<ExportActionViewModel> Actions { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Orchard.ImportExport.ViewModels {
|
||||||
|
public class RecipeBuilderViewModel {
|
||||||
|
public IList<ExportStepViewModel> Steps { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,28 +1,12 @@
|
|||||||
@using Orchard.Utility.Extensions
|
@model Orchard.ImportExport.ViewModels.ExportViewModel
|
||||||
@model Orchard.ImportExport.ViewModels.ExportViewModel
|
|
||||||
@{ Layout.Title = T("Export").ToString(); }
|
@{ Layout.Title = T("Export").ToString(); }
|
||||||
@using (Html.BeginFormAntiForgeryPost()) {
|
@using (Html.BeginFormAntiForgeryPost()) {
|
||||||
Html.ValidationSummary();
|
Html.ValidationSummary();
|
||||||
var exportStepIndex = 0;
|
|
||||||
foreach (var exportStep in Model.ExportSteps) {
|
|
||||||
var stepName = Html.NameFor(m => m.ExportSteps[exportStepIndex].IsSelected).ToString();
|
|
||||||
var stepId = stepName.HtmlClassify();
|
|
||||||
|
|
||||||
<fieldset class="recipe-builder-step recipe-builder-step-@exportStep.Name.HtmlClassify()">
|
foreach(var action in Model.Actions) {
|
||||||
<legend>
|
<div class="export-action">
|
||||||
<input type="hidden" name="@Html.NameFor(m => m.ExportSteps[exportStepIndex].Name)" value="@Model.ExportSteps[exportStepIndex].Name"/>
|
@Display(action.Editor)
|
||||||
<input type="checkbox" id="@stepId" name="@stepName" value="true"/>
|
</div>
|
||||||
<label for="@stepId" class="forcheckbox">@exportStep.DisplayName</label>
|
|
||||||
</legend>
|
|
||||||
@Html.Hint(@exportStep.Description)
|
|
||||||
<div data-controllerid="@stepId">
|
|
||||||
@Display(exportStep.Editor)
|
|
||||||
</div>
|
|
||||||
</fieldset>
|
|
||||||
exportStepIndex++;
|
|
||||||
if (exportStepIndex < Model.ExportSteps.Count) {
|
|
||||||
<hr />
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
<button type="submit" class="primaryAction">@T("Export")</button>
|
<button type="submit" class="primaryAction">@T("Export")</button>
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
@using Orchard.Utility.Extensions
|
||||||
|
@model Orchard.ImportExport.ViewModels.RecipeBuilderViewModel
|
||||||
|
@{
|
||||||
|
var exportStepIndex = 0;
|
||||||
|
foreach (var exportStep in Model.Steps) {
|
||||||
|
var stepName = Html.NameFor(m => m.Steps[exportStepIndex].IsSelected).ToString();
|
||||||
|
var stepId = stepName.HtmlClassify();
|
||||||
|
|
||||||
|
<fieldset class="recipe-builder-step recipe-builder-step-@exportStep.Name.HtmlClassify()">
|
||||||
|
<legend>
|
||||||
|
<input type="hidden" name="@Html.NameFor(m => m.Steps[exportStepIndex].Name)" value="@Model.Steps[exportStepIndex].Name" />
|
||||||
|
<input type="checkbox" id="@stepId" name="@stepName" value="true" />
|
||||||
|
<label for="@stepId" class="forcheckbox">@exportStep.DisplayName</label>
|
||||||
|
</legend>
|
||||||
|
@Html.Hint(@exportStep.Description)
|
||||||
|
<div data-controllerid="@stepId">
|
||||||
|
@Display(exportStep.Editor)
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
exportStepIndex++;
|
||||||
|
if (exportStepIndex < Model.Steps.Count) {
|
||||||
|
<hr />
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user