mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-26 20:16:15 +08:00
Merge remote-tracking branch 'origin/1.10.x' into dev
This commit is contained in:
@@ -205,7 +205,8 @@ namespace Orchard.Tests.Modules.Users.Controllers {
|
||||
@"Ima.Fool@example.com",
|
||||
@"""Ima.Fool""@example.com",
|
||||
@"""Ima Fool""@example.com",
|
||||
"2xxx1414@i.ua"
|
||||
"2xxx1414@i.ua",
|
||||
"Dreißig-öffentliche-Ämter-in-Übersee@Beispiel.de"
|
||||
)]
|
||||
string email)
|
||||
{
|
||||
|
||||
@@ -1,10 +1,20 @@
|
||||
using Orchard.ContentManagement.MetaData;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Orchard.Autoroute.Models;
|
||||
using Orchard.Autoroute.Settings;
|
||||
using Orchard.ContentManagement.MetaData;
|
||||
using Orchard.Core.Contents.Extensions;
|
||||
using Orchard.Data.Migration;
|
||||
using Orchard.Localization.Services;
|
||||
|
||||
namespace Orchard.Autoroute
|
||||
{
|
||||
public class Migrations : DataMigrationImpl {
|
||||
namespace Orchard.Autoroute {
|
||||
public class Migrations : DataMigrationImpl {
|
||||
private readonly ICultureManager _cultureManager;
|
||||
|
||||
public Migrations(ICultureManager cultureManager) {
|
||||
_cultureManager = cultureManager;
|
||||
}
|
||||
|
||||
public int Create() {
|
||||
SchemaBuilder.CreateTable("AutoroutePartRecord",
|
||||
@@ -49,5 +59,46 @@ namespace Orchard.Autoroute
|
||||
|
||||
return 4;
|
||||
}
|
||||
|
||||
public int UpdateFrom4() {
|
||||
// Adding some culture neutral patterns if they don't exist
|
||||
var autoroutePartDefinitions = ContentDefinitionManager.ListTypeDefinitions()
|
||||
.Where(t => t.Parts.Any(p => p.PartDefinition.Name.Equals(typeof(AutoroutePart).Name)))
|
||||
.Select(s => new { contentTypeName = s.Name, autoroutePart = s.Parts.First(x => x.PartDefinition.Name == "AutoroutePart") });
|
||||
|
||||
foreach (var partDefinition in autoroutePartDefinitions) {
|
||||
var settingsDictionary = partDefinition.autoroutePart.Settings;
|
||||
var settings = settingsDictionary.GetModel<AutorouteSettings>();
|
||||
|
||||
if (!settings.Patterns.Any(x => String.IsNullOrWhiteSpace(x.Culture))) {
|
||||
string siteCulture = _cultureManager.GetSiteCulture();
|
||||
List<string> newPatterns = new List<string>();
|
||||
|
||||
if (settings.Patterns.Any(x => String.Equals(x.Culture, siteCulture, StringComparison.OrdinalIgnoreCase))) {
|
||||
var siteCulturePatterns = settings.Patterns.Where(x => String.Equals(x.Culture, siteCulture, StringComparison.OrdinalIgnoreCase)).ToList();
|
||||
|
||||
foreach (RoutePattern pattern in siteCulturePatterns) {
|
||||
newPatterns.Add(String.Format("{{\"Name\":\"{0}\",\"Pattern\":\"{1}\",\"Description\":\"{2}\"}}", pattern.Name, pattern.Pattern, pattern.Description));
|
||||
}
|
||||
}
|
||||
else {
|
||||
newPatterns.Add(String.Format("{{\"Name\":\"{0}\",\"Pattern\":\"{1}\",\"Description\":\"{2}\"}}", "Title", "{Content.Slug}", "my-title"));
|
||||
}
|
||||
|
||||
if (settingsDictionary.ContainsKey("AutorouteSettings.PatternDefinitions")) {
|
||||
string oldPatterns = settingsDictionary["AutorouteSettings.PatternDefinitions"];
|
||||
if (oldPatterns.StartsWith("[") && oldPatterns.EndsWith("]"))
|
||||
newPatterns.Add(oldPatterns.Substring(1, oldPatterns.Length - 2));
|
||||
}
|
||||
|
||||
ContentDefinitionManager.AlterTypeDefinition(partDefinition.contentTypeName, cfg => cfg
|
||||
.WithPart("AutoroutePart", builder => builder
|
||||
.WithSetting("AutorouteSettings.PatternDefinitions", "[" + String.Join(",", newPatterns) + "]")
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -50,19 +50,24 @@ namespace Orchard.Autoroute.Providers.ContentDefinition {
|
||||
|
||||
public void ContentPartAttached(ContentPartAttachedContext context) {
|
||||
if (context.ContentPartName == "AutoroutePart") {
|
||||
//Create pattern and default pattern for each culture installed
|
||||
// Create pattern and default pattern for each culture installed and for the neutral culture
|
||||
|
||||
//get cultures
|
||||
// Get cultures
|
||||
var SiteCultures = _cultureManager.ListCultures().ToList();
|
||||
|
||||
//Create Patterns and DefaultPatterns
|
||||
// Adding a null culture for the culture neutral pattern
|
||||
List<string> cultures = new List<string>();
|
||||
cultures.Add(null);
|
||||
cultures.AddRange(SiteCultures);
|
||||
|
||||
// Create Patterns and DefaultPatterns
|
||||
var settings = new AutorouteSettings {
|
||||
Patterns = new List<RoutePattern>()
|
||||
};
|
||||
|
||||
List<RoutePattern> newPatterns = new List<RoutePattern>();
|
||||
List<DefaultPattern> newDefaultPatterns = new List<DefaultPattern>();
|
||||
foreach (string culture in SiteCultures) {
|
||||
foreach (string culture in cultures) {
|
||||
newPatterns.Add(new RoutePattern {
|
||||
Name = "Title",
|
||||
Description = "my-title",
|
||||
|
||||
@@ -135,35 +135,47 @@ namespace Orchard.Autoroute.Services {
|
||||
|
||||
public RoutePattern GetDefaultPattern(string contentType, string culture) {
|
||||
var settings = GetTypePartSettings(contentType).GetModel<AutorouteSettings>();
|
||||
var defaultPattern = settings.DefaultPatterns.FirstOrDefault(x => x.Culture == culture);
|
||||
var defaultPatternIndex = defaultPattern != null ? defaultPattern.PatternIndex : "0";
|
||||
|
||||
if (String.IsNullOrWhiteSpace(defaultPatternIndex))
|
||||
defaultPatternIndex = "0";
|
||||
if (settings.UseCulturePattern) {
|
||||
var defaultPatternIndex = "0";
|
||||
|
||||
if (!settings.DefaultPatterns.Any(x => String.Equals(x.Culture, culture, StringComparison.OrdinalIgnoreCase))) {
|
||||
var patternIndex = String.IsNullOrWhiteSpace(settings.DefaultPatternIndex) ? "0" : settings.DefaultPatternIndex;
|
||||
// Lazy updating from old setting.
|
||||
if (String.Equals(culture, _cultureManager.GetSiteCulture(), StringComparison.OrdinalIgnoreCase)) {
|
||||
settings.DefaultPatterns.Add(new DefaultPattern { PatternIndex = patternIndex, Culture = culture });
|
||||
return settings.Patterns.Where(x => x.Culture == null).ElementAt(Convert.ToInt32(defaultPatternIndex));
|
||||
if (!settings.DefaultPatterns.Any(x => String.Equals(x.Culture, culture, StringComparison.OrdinalIgnoreCase))) {
|
||||
// If no default pattern exists for the language return the default culture neutral pattern if it exists, else a generic pattern
|
||||
if (settings.Patterns.Any(x => String.IsNullOrEmpty(x.Culture))) {
|
||||
defaultPatternIndex = GetDefaultPatternIndex(contentType, null);
|
||||
return settings.Patterns.Where(x => String.IsNullOrEmpty(x.Culture)).ElementAt(Convert.ToInt32(defaultPatternIndex));
|
||||
}
|
||||
else {
|
||||
return new RoutePattern { Name = "Title", Description = "my-title", Pattern = "{Content.Slug}", Culture = culture };
|
||||
}
|
||||
}
|
||||
else {
|
||||
settings.DefaultPatterns.Add(new DefaultPattern { PatternIndex = "0", Culture = culture });
|
||||
return new RoutePattern { Name = "Title", Description = "my-title", Pattern = "{Content.Slug}", Culture = culture };
|
||||
|
||||
// If patterns for the specified culture exist search one of them, else search a culture neutral pattern
|
||||
var patternCultureSearch = settings.Patterns.Any(x => String.Equals(x.Culture, culture, StringComparison.OrdinalIgnoreCase)) ? culture : null;
|
||||
defaultPatternIndex = GetDefaultPatternIndex(contentType, patternCultureSearch);
|
||||
|
||||
if (settings.Patterns.Any()) {
|
||||
if (settings.Patterns.Where(x => x.Culture == patternCultureSearch).ElementAt(Convert.ToInt32(defaultPatternIndex)) != null) {
|
||||
return settings.Patterns.Where(x => x.Culture == patternCultureSearch).ElementAt(Convert.ToInt32(defaultPatternIndex));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Using the culture neutral pattern
|
||||
if (settings.Patterns.Any(x => String.IsNullOrEmpty(x.Culture))) {
|
||||
var defaultPatternIndex = GetDefaultPatternIndex(contentType, null);
|
||||
|
||||
// If no default culture neutral pattern exist use the default pattern
|
||||
if (!settings.DefaultPatterns.Any(x => String.IsNullOrEmpty(x.Culture))) {
|
||||
var patternIndex = String.IsNullOrWhiteSpace(settings.DefaultPatternIndex) ? "0" : settings.DefaultPatternIndex;
|
||||
settings.DefaultPatterns.Add(new DefaultPattern { PatternIndex = patternIndex, Culture = null });
|
||||
}
|
||||
|
||||
return settings.Patterns.Where(x => String.IsNullOrEmpty(x.Culture)).ElementAt(Convert.ToInt32(defaultPatternIndex));
|
||||
}
|
||||
}
|
||||
|
||||
// Return a default pattern if set.
|
||||
var patternCultureSearch = settings.Patterns.Any(x => String.Equals(x.Culture, culture, StringComparison.OrdinalIgnoreCase)) ? culture : null;
|
||||
|
||||
if (settings.Patterns.Any()) {
|
||||
if (settings.Patterns.Where(x => x.Culture == patternCultureSearch).ElementAt(Convert.ToInt32(defaultPatternIndex)) != null) {
|
||||
return settings.Patterns.Where(x => x.Culture == patternCultureSearch).ElementAt(Convert.ToInt32(defaultPatternIndex));
|
||||
};
|
||||
}
|
||||
|
||||
// Return a default pattern if none is defined.
|
||||
// Return a default pattern if none is defined
|
||||
return new RoutePattern { Name = "Title", Description = "my-title", Pattern = "{Content.Slug}", Culture = culture };
|
||||
}
|
||||
|
||||
@@ -222,6 +234,23 @@ namespace Orchard.Autoroute.Services {
|
||||
return contentDefinition.Parts.First(x => x.PartDefinition.Name == "AutoroutePart").Settings;
|
||||
}
|
||||
|
||||
private string GetDefaultPatternIndex(string contentType, string culture) {
|
||||
var settings = GetTypePartSettings(contentType).GetModel<AutorouteSettings>();
|
||||
|
||||
DefaultPattern defaultPattern = null;
|
||||
if (String.IsNullOrEmpty(culture))
|
||||
defaultPattern = settings.DefaultPatterns.FirstOrDefault(x => String.IsNullOrEmpty(x.Culture));
|
||||
else
|
||||
defaultPattern = settings.DefaultPatterns.FirstOrDefault(x => String.Equals(x.Culture, culture, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
var defaultPatternIndex = defaultPattern != null ? defaultPattern.PatternIndex : "0";
|
||||
|
||||
if (String.IsNullOrWhiteSpace(defaultPatternIndex))
|
||||
defaultPatternIndex = "0";
|
||||
|
||||
return defaultPatternIndex;
|
||||
}
|
||||
|
||||
private static int? GetSlugVersion(string path, string potentialConflictingPath) {
|
||||
int v;
|
||||
var slugParts = potentialConflictingPath.Split(new[] { path }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
@@ -28,56 +28,55 @@ namespace Orchard.Autoroute.Settings {
|
||||
|
||||
var settings = definition.Settings.GetModel<AutorouteSettings>();
|
||||
|
||||
//get cultures
|
||||
// Get cultures
|
||||
settings.SiteCultures = _cultureManager.ListCultures().ToList();
|
||||
//get default site culture
|
||||
// Get default site culture
|
||||
settings.DefaultSiteCulture = _cultureManager.GetSiteCulture();
|
||||
|
||||
//if a culture is not set on the pattern we set it to the default site culture for backward compatibility
|
||||
if (!settings.Patterns.Any(x => String.Equals(x.Culture, settings.DefaultSiteCulture, StringComparison.OrdinalIgnoreCase))) {
|
||||
foreach (RoutePattern pattern in settings.Patterns.Where(x => String.IsNullOrWhiteSpace(x.Culture))) {
|
||||
settings.Patterns.Where(x => x.GetHashCode() == pattern.GetHashCode()).FirstOrDefault().Culture = settings.DefaultSiteCulture;
|
||||
}
|
||||
}
|
||||
|
||||
//Adding Patterns for the UI
|
||||
// Adding Patterns for the UI
|
||||
List<RoutePattern> newPatterns = new List<RoutePattern>();
|
||||
|
||||
// Adding a null culture for the culture neutral pattern
|
||||
List<string> cultures = new List<string>();
|
||||
cultures.Add(null);
|
||||
cultures.AddRange(settings.SiteCultures);
|
||||
|
||||
int current = 0;
|
||||
foreach (string culture in settings.SiteCultures) {
|
||||
foreach (string culture in cultures) {
|
||||
// Adding all existing patterns for the culture
|
||||
foreach (RoutePattern routePattern in settings.Patterns.Where(x => String.Equals(x.Culture, culture, StringComparison.OrdinalIgnoreCase))) {
|
||||
if (settings.Patterns.Any(x => String.Equals(x.Culture, culture, StringComparison.OrdinalIgnoreCase))) {
|
||||
newPatterns.Add(settings.Patterns[current]);
|
||||
} else {
|
||||
newPatterns.Add(new RoutePattern {
|
||||
Name = "Title",
|
||||
Description = "my-title",
|
||||
Pattern = "{Content.Slug}",
|
||||
Culture = settings.DefaultSiteCulture
|
||||
});
|
||||
}
|
||||
newPatterns.Add(settings.Patterns[current]);
|
||||
current++;
|
||||
}
|
||||
|
||||
//We add a pattern for each culture if there is none
|
||||
// Adding a pattern for each culture if there is none
|
||||
if (!settings.Patterns.Where(x => String.Equals(x.Culture, culture, StringComparison.OrdinalIgnoreCase)).Any()) {
|
||||
newPatterns.Add(new RoutePattern { Culture = culture, Name = "Title", Description = "my-title", Pattern = "{Content.Slug}" });
|
||||
}
|
||||
|
||||
//we add a new empty line for each culture
|
||||
// Adding a new empty line for each culture
|
||||
newPatterns.Add(new RoutePattern { Culture = culture, Name = null, Description = null, Pattern = null });
|
||||
|
||||
// if the content type has no defaultPattern for autoroute, then assign one
|
||||
if (!settings.DefaultPatterns.Any(x => String.Equals(x.Culture, culture, StringComparison.OrdinalIgnoreCase))) {
|
||||
//if we are in the default culture check the old setting
|
||||
// If the content type has no defaultPattern for autoroute, assign one
|
||||
bool defaultPatternExists = false;
|
||||
if (String.IsNullOrEmpty(culture))
|
||||
defaultPatternExists = settings.DefaultPatterns.Any(x => String.IsNullOrEmpty(x.Culture));
|
||||
else
|
||||
defaultPatternExists = settings.DefaultPatterns.Any(x => String.Equals(x.Culture, culture, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (!defaultPatternExists) {
|
||||
// If in the default culture check the old setting
|
||||
if (String.Equals(culture, _cultureManager.GetSiteCulture(), StringComparison.OrdinalIgnoreCase)) {
|
||||
var defaultPatternIndex = settings.DefaultPatternIndex;
|
||||
if (!String.IsNullOrWhiteSpace(defaultPatternIndex)) {
|
||||
var patternIndex = defaultPatternIndex;
|
||||
settings.DefaultPatterns.Add(new DefaultPattern { Culture = settings.DefaultSiteCulture, PatternIndex = patternIndex });
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
settings.DefaultPatterns.Add(new DefaultPattern { PatternIndex = "0", Culture = culture });
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
settings.DefaultPatterns.Add(new DefaultPattern { PatternIndex = "0", Culture = culture });
|
||||
}
|
||||
}
|
||||
@@ -96,25 +95,51 @@ namespace Orchard.Autoroute.Settings {
|
||||
Patterns = new List<RoutePattern>()
|
||||
};
|
||||
|
||||
//get cultures
|
||||
// Get cultures
|
||||
settings.SiteCultures = _cultureManager.ListCultures().ToList();
|
||||
|
||||
if (updateModel.TryUpdateModel(settings, "AutorouteSettings", null, null)) {
|
||||
//TODO need to add validations client and/or server side here
|
||||
// remove empty patterns
|
||||
|
||||
// If some default pattern is an empty pattern set it to the first pattern for the language
|
||||
List<DefaultPattern> newDefaultPatterns = new List<DefaultPattern>();
|
||||
|
||||
foreach (var defaultPattern in settings.DefaultPatterns) {
|
||||
RoutePattern correspondingPattern = null;
|
||||
|
||||
if (string.IsNullOrEmpty(defaultPattern.Culture))
|
||||
correspondingPattern = settings.Patterns.Where(x => String.IsNullOrEmpty(x.Culture)).ElementAt(Convert.ToInt32(defaultPattern.PatternIndex));
|
||||
else
|
||||
correspondingPattern = settings.Patterns.Where(x => String.Equals(x.Culture, defaultPattern.Culture, StringComparison.OrdinalIgnoreCase)).ElementAt(Convert.ToInt32(defaultPattern.PatternIndex));
|
||||
|
||||
if (String.IsNullOrWhiteSpace(correspondingPattern.Name) && String.IsNullOrWhiteSpace(correspondingPattern.Pattern) && String.IsNullOrWhiteSpace(correspondingPattern.Description))
|
||||
newDefaultPatterns.Add(new DefaultPattern { Culture = defaultPattern.Culture, PatternIndex = "0" });
|
||||
else
|
||||
newDefaultPatterns.Add(defaultPattern);
|
||||
}
|
||||
|
||||
settings.DefaultPatterns = newDefaultPatterns;
|
||||
|
||||
// Remove empty patterns
|
||||
var patterns = settings.Patterns;
|
||||
patterns.RemoveAll(p => String.IsNullOrWhiteSpace(p.Name) && String.IsNullOrWhiteSpace(p.Pattern) && String.IsNullOrWhiteSpace(p.Description));
|
||||
|
||||
//If there is no default pattern for each culture we set default ones
|
||||
// Adding a null culture for the culture neutral pattern
|
||||
List<string> cultures = new List<string>();
|
||||
cultures.Add(null);
|
||||
cultures.AddRange(settings.SiteCultures);
|
||||
|
||||
//If there is no pattern for some culture create a default one
|
||||
List<RoutePattern> newPatterns = new List<RoutePattern>();
|
||||
int current = 0;
|
||||
foreach (string culture in settings.SiteCultures) {
|
||||
foreach (string culture in cultures) {
|
||||
if (settings.Patterns.Any(x => String.Equals(x.Culture, culture, StringComparison.OrdinalIgnoreCase))) {
|
||||
foreach (RoutePattern routePattern in settings.Patterns.Where(x => String.Equals(x.Culture, culture, StringComparison.OrdinalIgnoreCase))) {
|
||||
newPatterns.Add(settings.Patterns[current]);
|
||||
current++;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
newPatterns.Add(new RoutePattern {
|
||||
Name = "Title",
|
||||
Description = "my-title",
|
||||
@@ -128,7 +153,7 @@ namespace Orchard.Autoroute.Settings {
|
||||
|
||||
settings.Patterns = newPatterns;
|
||||
|
||||
// update the settings builder
|
||||
// Update the settings builder
|
||||
settings.Build(builder);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
@model Orchard.Autoroute.Settings.AutorouteSettings
|
||||
@using Orchard.Utility.Extensions;
|
||||
|
||||
@{
|
||||
Script.Require("AutorouteBrowser");
|
||||
Style.Require("AutorouteSettings");
|
||||
|
||||
int patternCount = 0;
|
||||
int patternCultureCount = 0;
|
||||
|
||||
List<string> cultures = new List<string>();
|
||||
cultures.Add(null);
|
||||
cultures.AddRange(Model.SiteCultures);
|
||||
}
|
||||
<fieldset>
|
||||
<div>
|
||||
@@ -40,10 +44,10 @@
|
||||
int i = 1;
|
||||
string cssClass = "";
|
||||
}
|
||||
<li class="first selected"><a class="culture" href="#cat-@Model.DefaultSiteCulture">@Model.DefaultSiteCulture</a></li>
|
||||
@foreach (var culture in Model.SiteCultures) {
|
||||
if (culture != Model.DefaultSiteCulture) {
|
||||
cssClass = i == Model.SiteCultures.Count - 1 ? "last" : "middle";
|
||||
<li class="first selected"><a class="culture" href="#cat-culture-neutral">@T("All cultures")</a></li>
|
||||
@foreach (var culture in cultures) {
|
||||
if (!String.IsNullOrEmpty(culture)) {
|
||||
cssClass = i == cultures.Count - 1 ? "last" : "middle";
|
||||
<li class="@cssClass" style="@(Model.UseCulturePattern == false ? "display:none;" : "")"><a class="culture" href="#cat-@culture">@culture</a></li>
|
||||
i++;
|
||||
}
|
||||
@@ -51,8 +55,8 @@
|
||||
</ul>
|
||||
</div>
|
||||
<div id="content">
|
||||
@foreach (var culture in Model.SiteCultures) {
|
||||
<fieldset id="cat-@culture" class="items @(culture == Model.DefaultSiteCulture ? "default" : "")" style="@(culture == Model.DefaultSiteCulture ? "display:block;" : "display:none;")">
|
||||
@foreach (var culture in cultures) {
|
||||
<fieldset id="cat-@(String.IsNullOrEmpty(culture) ? "culture-neutral" : culture)" class="items @(String.IsNullOrEmpty(culture) ? "default" : "")" style="@(String.IsNullOrEmpty(culture) ? "display:block;" : "display:none;")">
|
||||
<table class="autoroute-settings-patterns">
|
||||
<tr>
|
||||
<th class="autoroute-settings-default">@T("Default")</th>
|
||||
@@ -63,7 +67,7 @@
|
||||
</tr>
|
||||
@for (int index = 0; index < Model.Patterns.Where(x => x.Culture == culture).Count(); index++) {
|
||||
<tr>
|
||||
<td>@Html.RadioButtonFor(m => m.DefaultPatterns[Model.SiteCultures.IndexOf(culture)].Culture, culture + "|" + patternCultureCount, patternCultureCount.ToString() == Model.DefaultPatterns[Model.SiteCultures.IndexOf(culture)].PatternIndex ? new { @checked = "checked" } : null)</td>
|
||||
<td>@Html.RadioButtonFor(m => m.DefaultPatterns[cultures.IndexOf(culture)].Culture, culture + "|" + patternCultureCount, patternCultureCount.ToString() == Model.DefaultPatterns[cultures.IndexOf(culture)].PatternIndex ? new { @checked = "checked" } : null)</td>
|
||||
<td>@Html.TextBoxFor(m => m.Patterns[patternCount].Name, new { @class = "text" })</td>
|
||||
<td>@Html.TextBoxFor(m => m.Patterns[patternCount].Pattern, new { @class = "tokenized text" })</td>
|
||||
<td>@Html.TextBoxFor(m => m.Patterns[patternCount].Description, new { @class = "text" })</td>
|
||||
|
||||
@@ -165,6 +165,13 @@ namespace Orchard.ImportExport.Commands {
|
||||
}
|
||||
|
||||
if (!String.IsNullOrEmpty(customSteps)) {
|
||||
var customStepsList = customSteps.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
foreach (var customStepName in customStepsList) {
|
||||
GetOrCreateElement(stepsElement, customStepName);
|
||||
}
|
||||
|
||||
//Still need CustomStepsStep to support older export steps created by users
|
||||
var customStepsElement = GetOrCreateElement(stepsElement, "CustomSteps");
|
||||
customStepsElement.Attr("Steps", customSteps);
|
||||
}
|
||||
|
||||
@@ -14,11 +14,13 @@ using Orchard.Recipes.Services;
|
||||
namespace Orchard.ImportExport.Providers.ExportActions {
|
||||
public class BuildRecipeAction : ExportAction {
|
||||
private readonly IEnumerable<IRecipeBuilderStep> _recipeBuilderSteps;
|
||||
private readonly IRecipeBuilderStepResolver _recipeBuilderStepResolver;
|
||||
private readonly IRecipeBuilder _recipeBuilder;
|
||||
private readonly IOrchardServices _orchardServices;
|
||||
|
||||
public BuildRecipeAction(IEnumerable<IRecipeBuilderStep> recipeBuilderSteps, IRecipeBuilder recipeBuilder, IOrchardServices orchardServices) {
|
||||
public BuildRecipeAction(IRecipeBuilderStepResolver recipeBuilderStepResolver, IEnumerable<IRecipeBuilderStep> recipeBuilderSteps, IRecipeBuilder recipeBuilder, IOrchardServices orchardServices) {
|
||||
_recipeBuilderSteps = recipeBuilderSteps;
|
||||
_recipeBuilderStepResolver = recipeBuilderStepResolver;
|
||||
_recipeBuilder = recipeBuilder;
|
||||
_orchardServices = orchardServices;
|
||||
|
||||
@@ -60,10 +62,7 @@ namespace Orchard.ImportExport.Providers.ExportActions {
|
||||
}
|
||||
else {
|
||||
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 stepsQuery = _recipeBuilderStepResolver.Resolve(exportStepNames);
|
||||
var steps = stepsQuery.ToArray();
|
||||
var stepUpdater = new Updater(updater, secondHalf => String.Format("{0}.{1}", Prefix, secondHalf));
|
||||
foreach (var exportStep in steps) {
|
||||
@@ -86,7 +85,7 @@ namespace Orchard.ImportExport.Providers.ExportActions {
|
||||
return;
|
||||
|
||||
foreach (var stepElement in recipeBuilderStepsElement.Elements()) {
|
||||
var step = _recipeBuilderSteps.SingleOrDefault(x => x.Name == stepElement.Name.LocalName);
|
||||
var step = _recipeBuilderStepResolver.Resolve(stepElement.Name.LocalName);
|
||||
|
||||
if (step != null) {
|
||||
var stepContext = new RecipeBuilderStepConfigurationContext(stepElement);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Orchard.Environment.Extensions;
|
||||
using Orchard.Security;
|
||||
using Orchard.UI.Navigation;
|
||||
|
||||
namespace Orchard.JobsQueue {
|
||||
@@ -11,6 +12,7 @@ namespace Orchard.JobsQueue {
|
||||
builder
|
||||
.AddImageSet("jobsqueue")
|
||||
.Add(T("Jobs Queue"), "15.0", item => {
|
||||
item.Permission(StandardPermissions.SiteOwner);
|
||||
item.Action("List", "Admin", new { area = "Orchard.JobsQueue" });
|
||||
item.LinkToFirstChild(false);
|
||||
});
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.MediaLibrary.Providers;
|
||||
using Orchard.Security;
|
||||
|
||||
namespace Orchard.MediaLibrary.Implementation {
|
||||
public class DefaultMediaUsername : IMediaFolderProvider {
|
||||
public virtual string GetFolderName(IUser content) {
|
||||
string folder = "";
|
||||
foreach (char c in content.UserName) {
|
||||
if (char.IsLetterOrDigit(c)) {
|
||||
folder += c;
|
||||
}
|
||||
else
|
||||
folder += "_" + String.Format("{0:X}", Convert.ToInt32(c));
|
||||
}
|
||||
return folder;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -128,6 +128,7 @@
|
||||
<Compile Include="Extensions\MediaMetaDataExtensions.cs" />
|
||||
<Compile Include="Factories\VectorImageFactory.cs" />
|
||||
<Compile Include="Handlers\MediaLibrarySettingsPartHandler.cs" />
|
||||
<Compile Include="Implementation\DefaultMediaUsername.cs" />
|
||||
<Compile Include="Models\MediaLibrarySettingsPart.cs" />
|
||||
<Compile Include="Models\VectorImagePart.cs" />
|
||||
<Compile Include="Models\IMediaFolder.cs" />
|
||||
@@ -200,6 +201,7 @@
|
||||
<Compile Include="ResourceManifest.cs" />
|
||||
<Compile Include="Security\MediaAuthorizationEventHandler.cs" />
|
||||
<Compile Include="Services\IMediaLibraryService.cs" />
|
||||
<Compile Include="Providers\IMediaFolderProvider.cs" />
|
||||
<Compile Include="Services\MediaLibraryService.cs" />
|
||||
<Compile Include="Services\Shapes.cs" />
|
||||
<Compile Include="Services\XmlRpcHandler.cs" />
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
using Orchard.Security;
|
||||
|
||||
namespace Orchard.MediaLibrary.Providers {
|
||||
public interface IMediaFolderProvider : IDependency {
|
||||
string GetFolderName(IUser content);
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ using Orchard.MediaLibrary.Factories;
|
||||
using Orchard.MediaLibrary.Models;
|
||||
using Orchard.Core.Title.Models;
|
||||
using Orchard.Validation;
|
||||
using Orchard.MediaLibrary.Providers;
|
||||
|
||||
namespace Orchard.MediaLibrary.Services {
|
||||
public class MediaLibraryService : IMediaLibraryService {
|
||||
@@ -19,18 +20,20 @@ namespace Orchard.MediaLibrary.Services {
|
||||
private readonly IMimeTypeProvider _mimeTypeProvider;
|
||||
private readonly IStorageProvider _storageProvider;
|
||||
private readonly IEnumerable<IMediaFactorySelector> _mediaFactorySelectors;
|
||||
|
||||
private readonly IMediaFolderProvider _mediaFolderProvider;
|
||||
private static char[] HttpUnallowed = new char[] { '<', '>', '*', '%', '&', ':', '\\', '?', '#' };
|
||||
|
||||
public MediaLibraryService(
|
||||
IOrchardServices orchardServices,
|
||||
IMimeTypeProvider mimeTypeProvider,
|
||||
IStorageProvider storageProvider,
|
||||
IEnumerable<IMediaFactorySelector> mediaFactorySelectors) {
|
||||
IEnumerable<IMediaFactorySelector> mediaFactorySelectors,
|
||||
IMediaFolderProvider mediaFolderProvider) {
|
||||
_orchardServices = orchardServices;
|
||||
_mimeTypeProvider = mimeTypeProvider;
|
||||
_storageProvider = storageProvider;
|
||||
_mediaFactorySelectors = mediaFactorySelectors;
|
||||
_mediaFolderProvider = mediaFolderProvider;
|
||||
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
@@ -229,8 +232,7 @@ namespace Orchard.MediaLibrary.Services {
|
||||
|
||||
if (_orchardServices.Authorizer.Authorize(Permissions.ManageOwnMedia)) {
|
||||
var currentUser = _orchardServices.WorkContext.CurrentUser;
|
||||
var userPath = _storageProvider.Combine("Users", currentUser.UserName);
|
||||
|
||||
var userPath = _storageProvider.Combine("Users", _mediaFolderProvider.GetFolderName(currentUser));
|
||||
return new MediaFolder() {
|
||||
Name = currentUser.UserName,
|
||||
MediaPath = userPath
|
||||
|
||||
@@ -24,7 +24,7 @@ using Orchard.Utility.Extensions;
|
||||
namespace Orchard.Projections.Drivers {
|
||||
public class ProjectionPartDriver : ContentPartDriver<ProjectionPart> {
|
||||
private readonly IRepository<QueryPartRecord> _queryRepository;
|
||||
private readonly IProjectionManager _projectionManager;
|
||||
private readonly IProjectionManagerExtension _projectionManager;
|
||||
private readonly IFeedManager _feedManager;
|
||||
private readonly ITokenizer _tokenizer;
|
||||
private readonly IDisplayHelperFactory _displayHelperFactory;
|
||||
@@ -34,7 +34,7 @@ namespace Orchard.Projections.Drivers {
|
||||
public ProjectionPartDriver(
|
||||
IOrchardServices services,
|
||||
IRepository<QueryPartRecord> queryRepository,
|
||||
IProjectionManager projectionManager,
|
||||
IProjectionManagerExtension projectionManager,
|
||||
IFeedManager feedManager,
|
||||
ITokenizer tokenizer,
|
||||
IDisplayHelperFactory displayHelperFactory,
|
||||
@@ -110,7 +110,7 @@ namespace Orchard.Projections.Drivers {
|
||||
_feedManager.Register(metaData.DisplayText, "rss", new RouteValueDictionary { { "projection", part.Id } });
|
||||
|
||||
// execute the query
|
||||
var contentItems = _projectionManager.GetContentItems(query.Id, pager.GetStartIndex() + part.Record.Skip, pager.PageSize).ToList();
|
||||
var contentItems = _projectionManager.GetContentItems(query.Id, part, pager.GetStartIndex() + part.Record.Skip, pager.PageSize).ToList();
|
||||
|
||||
// sanity check so that content items with ProjectionPart can't be added here, or it will result in an infinite loop
|
||||
contentItems = contentItems.Where(x => !x.Has<ProjectionPart>()).ToList();
|
||||
@@ -122,7 +122,7 @@ namespace Orchard.Projections.Drivers {
|
||||
|
||||
// create pager shape
|
||||
if (part.Record.DisplayPager) {
|
||||
var contentItemsCount = _projectionManager.GetCount(query.Id) - part.Record.Skip;
|
||||
var contentItemsCount = _projectionManager.GetCount(query.Id, part) - part.Record.Skip;
|
||||
contentItemsCount = Math.Max(0, contentItemsCount);
|
||||
pagerShape.TotalItemCount(contentItemsCount);
|
||||
}
|
||||
|
||||
@@ -175,6 +175,7 @@
|
||||
<Compile Include="Providers\Layouts\ShapeLayoutForms.cs" />
|
||||
<Compile Include="Providers\Properties\CustomValueProperties.cs" />
|
||||
<Compile Include="Navigation\NavigationQueryProvider.cs" />
|
||||
<Compile Include="Services\IProjectionManagerExtension.cs" />
|
||||
<Compile Include="Shapes.cs" />
|
||||
<Compile Include="Descriptors\Layout\LayoutComponentResult.cs" />
|
||||
<Compile Include="Descriptors\Layout\LayoutContext.cs" />
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
using System.Collections.Generic;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Projections.Descriptors;
|
||||
using Orchard.Projections.Descriptors.Property;
|
||||
using Orchard.Projections.Descriptors.Filter;
|
||||
using Orchard.Projections.Descriptors.Layout;
|
||||
using Orchard.Projections.Descriptors.SortCriterion;
|
||||
|
||||
namespace Orchard.Projections.Services {
|
||||
public interface IProjectionManagerExtension : IProjectionManager {
|
||||
|
||||
IEnumerable<ContentItem> GetContentItems(int queryId, ContentPart part, int skip = 0, int count = 0);
|
||||
int GetCount(int queryId, ContentPart part);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,7 +14,7 @@ using Orchard.Projections.Models;
|
||||
using Orchard.Tokens;
|
||||
|
||||
namespace Orchard.Projections.Services {
|
||||
public class ProjectionManager : IProjectionManager{
|
||||
public class ProjectionManager : IProjectionManagerExtension {
|
||||
private readonly ITokenizer _tokenizer;
|
||||
private readonly IEnumerable<IFilterProvider> _filterProviders;
|
||||
private readonly IEnumerable<ISortCriterionProvider> _sortCriterionProviders;
|
||||
@@ -104,6 +104,33 @@ namespace Orchard.Projections.Services {
|
||||
}
|
||||
|
||||
public int GetCount(int queryId) {
|
||||
return GetCount(queryId, null);
|
||||
}
|
||||
|
||||
public int GetCount(int queryId, ContentPart part) {
|
||||
var queryRecord = _queryRepository.Get(queryId);
|
||||
|
||||
if (queryRecord == null) {
|
||||
throw new ArgumentException("queryId");
|
||||
}
|
||||
|
||||
// prepares tokens
|
||||
Dictionary<string, object> tokens = new Dictionary<string, object>();
|
||||
if (part != null) {
|
||||
tokens.Add("Content", part.ContentItem);
|
||||
}
|
||||
|
||||
// aggregate the result for each group query
|
||||
return GetContentQueries(queryRecord, Enumerable.Empty<SortCriterionRecord>(), tokens)
|
||||
.Sum(contentQuery => contentQuery.Count());
|
||||
}
|
||||
|
||||
public IEnumerable<ContentItem> GetContentItems(int queryId, int skip = 0, int count = 0) {
|
||||
return GetContentItems(queryId, null, skip, count);
|
||||
}
|
||||
|
||||
public IEnumerable<ContentItem> GetContentItems(int queryId, ContentPart part, int skip = 0, int count = 0) {
|
||||
var availableSortCriteria = DescribeSortCriteria().ToList();
|
||||
|
||||
var queryRecord = _queryRepository.Get(queryId);
|
||||
|
||||
@@ -111,36 +138,27 @@ namespace Orchard.Projections.Services {
|
||||
throw new ArgumentException("queryId");
|
||||
}
|
||||
|
||||
// aggregate the result for each group query
|
||||
|
||||
return GetContentQueries(queryRecord, Enumerable.Empty<SortCriterionRecord>())
|
||||
.Sum(contentQuery => contentQuery.Count());
|
||||
}
|
||||
|
||||
public IEnumerable<ContentItem> GetContentItems(int queryId, int skip = 0, int count = 0) {
|
||||
var availableSortCriteria = DescribeSortCriteria().ToList();
|
||||
|
||||
var queryRecord = _queryRepository.Get(queryId);
|
||||
|
||||
if(queryRecord == null) {
|
||||
throw new ArgumentException("queryId");
|
||||
}
|
||||
|
||||
var contentItems = new List<ContentItem>();
|
||||
|
||||
// prepares tokens
|
||||
Dictionary<string, object> tokens = new Dictionary<string, object>();
|
||||
if (part != null) {
|
||||
tokens.Add("Content", part.ContentItem);
|
||||
}
|
||||
|
||||
// aggregate the result for each group query
|
||||
foreach(var contentQuery in GetContentQueries(queryRecord, queryRecord.SortCriteria.OrderBy(sc => sc.Position))) {
|
||||
foreach (var contentQuery in GetContentQueries(queryRecord, queryRecord.SortCriteria.OrderBy(sc => sc.Position), tokens)) {
|
||||
contentItems.AddRange(contentQuery.Slice(skip, count));
|
||||
}
|
||||
|
||||
if(queryRecord.FilterGroups.Count <= 1) {
|
||||
if (queryRecord.FilterGroups.Count <= 1) {
|
||||
return contentItems;
|
||||
}
|
||||
|
||||
// re-executing the sorting with the cumulated groups
|
||||
var ids = contentItems.Select(c => c.Id).ToArray();
|
||||
|
||||
if(ids.Length == 0) {
|
||||
if (ids.Length == 0) {
|
||||
return Enumerable.Empty<ContentItem>();
|
||||
}
|
||||
|
||||
@@ -173,9 +191,13 @@ namespace Orchard.Projections.Services {
|
||||
return groupQuery.Slice(skip, count);
|
||||
}
|
||||
|
||||
public IEnumerable<IHqlQuery> GetContentQueries(QueryPartRecord queryRecord, IEnumerable<SortCriterionRecord> sortCriteria) {
|
||||
public IEnumerable<IHqlQuery> GetContentQueries(QueryPartRecord queryRecord, IEnumerable<SortCriterionRecord> sortCriteria, Dictionary<string, object> tokens) {
|
||||
|
||||
var availableFilters = DescribeFilters().ToList();
|
||||
var availableSortCriteria = DescribeSortCriteria().ToList();
|
||||
if (tokens == null) {
|
||||
tokens = new Dictionary<string, object>();
|
||||
}
|
||||
|
||||
// pre-executing all groups
|
||||
foreach (var group in queryRecord.FilterGroups) {
|
||||
@@ -184,7 +206,7 @@ namespace Orchard.Projections.Services {
|
||||
|
||||
// iterate over each filter to apply the alterations to the query object
|
||||
foreach (var filter in group.Filters) {
|
||||
var tokenizedState = _tokenizer.Replace(filter.State, new Dictionary<string, object>());
|
||||
var tokenizedState = _tokenizer.Replace(filter.State, tokens);
|
||||
var filterContext = new FilterContext {
|
||||
Query = contentQuery,
|
||||
State = FormParametersHelper.ToDynamic(tokenizedState)
|
||||
|
||||
@@ -9,13 +9,13 @@ namespace Orchard.Recipes.Providers.RecipeHandlers {
|
||||
/// Delegates execution of the step to the appropriate recipe execution step implementation.
|
||||
/// </summary>
|
||||
public class RecipeExecutionStepHandler : Component, IRecipeHandler {
|
||||
private readonly IEnumerable<IRecipeExecutionStep> _recipeExecutionSteps;
|
||||
public RecipeExecutionStepHandler(IEnumerable<IRecipeExecutionStep> recipeExecutionSteps) {
|
||||
_recipeExecutionSteps = recipeExecutionSteps;
|
||||
private readonly IRecipeExecutionStepResolver _recipeExecutionStepResolver;
|
||||
public RecipeExecutionStepHandler(IRecipeExecutionStepResolver recipeExecutionStepResolver) {
|
||||
_recipeExecutionStepResolver = recipeExecutionStepResolver;
|
||||
}
|
||||
|
||||
public void ExecuteRecipeStep(RecipeContext recipeContext) {
|
||||
var executionStep = _recipeExecutionSteps.FirstOrDefault(x => x.Names.Contains(recipeContext.RecipeStep.Name));
|
||||
var executionStep = _recipeExecutionStepResolver.Resolve(recipeContext.RecipeStep.Name);
|
||||
var recipeExecutionContext = new RecipeExecutionContext {ExecutionId = recipeContext.ExecutionId, RecipeStep = recipeContext.RecipeStep};
|
||||
|
||||
if (executionStep != null) {
|
||||
|
||||
@@ -52,6 +52,7 @@ namespace Orchard.Scripting.CSharp.Services {
|
||||
|
||||
Engine.Run("using System;");
|
||||
Engine.Run("using System.Collections.Generic;");
|
||||
Engine.Run("using System.Linq;");
|
||||
Engine.Run("var dictionary = new Dictionary<string, dynamic>();");
|
||||
Dictionary = Engine.Evaluate("dictionary") as IDictionary<string, dynamic>;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ using System.Web.Security;
|
||||
namespace Orchard.Users.Models {
|
||||
public sealed class UserPart : ContentPart<UserPartRecord>, IUser {
|
||||
public const string EmailPattern =
|
||||
@"^(?![\.@])(""([^""\r\\]|\\[""\r\\])*""|([-a-z0-9!#$%&'*+/=?^_`{|}~]|(?<!\.)\.)*)(?<!\.)"
|
||||
@"^(?![\.@])(""([^""\r\\]|\\[""\r\\])*""|([-\p{L}0-9!#$%&'*+/=?^_`{|}~]|(?<!\.)\.)*)(?<!\.)"
|
||||
+ @"@([a-z0-9][\w-]*\.)+[a-z]{2,}$";
|
||||
|
||||
public const int MaxUserNameLength = 255;
|
||||
|
||||
@@ -190,12 +190,16 @@
|
||||
<Compile Include="Recipes\Models\BuildContext.cs" />
|
||||
<Compile Include="Recipes\Services\IRecipeBuilder.cs" />
|
||||
<Compile Include="Recipes\Services\IRecipeBuilderStep.cs" />
|
||||
<Compile Include="Recipes\Services\IRecipeBuilderStepResolver.cs" />
|
||||
<Compile Include="Recipes\Services\IRecipeExecutionStep.cs" />
|
||||
<Compile Include="Recipes\Services\IRecipeExecutionStepResolver.cs" />
|
||||
<Compile Include="Recipes\Services\IRecipeExecutor.cs" />
|
||||
<Compile Include="Recipes\Services\IRecipeResultAccessor.cs" />
|
||||
<Compile Include="Recipes\Services\RecipeBuilder.cs" />
|
||||
<Compile Include="Recipes\Services\RecipeBuilderStep.cs" />
|
||||
<Compile Include="Recipes\Models\RecipeExecutionContext.cs" />
|
||||
<Compile Include="Recipes\Services\RecipeExecutionStepResolver.cs" />
|
||||
<Compile Include="Recipes\Services\RecipeBuilderStepResolver.cs" />
|
||||
<Compile Include="Recipes\Services\RecipeExecutionLogger.cs" />
|
||||
<Compile Include="Recipes\Services\RecipeExecutionStep.cs" />
|
||||
<Compile Include="Recipes\Services\RecipeExecutor.cs" />
|
||||
|
||||
10
src/Orchard/Recipes/Services/IRecipeBuilderStepResolver.cs
Normal file
10
src/Orchard/Recipes/Services/IRecipeBuilderStepResolver.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Orchard.Recipes.Services
|
||||
{
|
||||
public interface IRecipeBuilderStepResolver : IDependency
|
||||
{
|
||||
IRecipeBuilderStep Resolve(string exportStepName);
|
||||
IEnumerable<IRecipeBuilderStep> Resolve(IEnumerable<string> exportStepNames);
|
||||
}
|
||||
}
|
||||
10
src/Orchard/Recipes/Services/IRecipeExecutionStepResolver.cs
Normal file
10
src/Orchard/Recipes/Services/IRecipeExecutionStepResolver.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Orchard.Recipes.Services
|
||||
{
|
||||
public interface IRecipeExecutionStepResolver :IDependency
|
||||
{
|
||||
IRecipeExecutionStep Resolve(string importStepName);
|
||||
IEnumerable<IRecipeExecutionStep> Resolve(IEnumerable<string> exportStepNames);
|
||||
}
|
||||
}
|
||||
28
src/Orchard/Recipes/Services/RecipeBuilderStepResolver.cs
Normal file
28
src/Orchard/Recipes/Services/RecipeBuilderStepResolver.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Orchard.Recipes.Services
|
||||
{
|
||||
public class RecipeBuilderStepResolver : IRecipeBuilderStepResolver
|
||||
{
|
||||
private readonly IEnumerable<IRecipeBuilderStep> _recipeBuilderSteps;
|
||||
|
||||
public RecipeBuilderStepResolver(IEnumerable<IRecipeBuilderStep> recipeBuilderSteps) {
|
||||
_recipeBuilderSteps = recipeBuilderSteps;
|
||||
}
|
||||
|
||||
public IRecipeBuilderStep Resolve(string exportStepName) {
|
||||
return _recipeBuilderSteps.SingleOrDefault(x => x.Name == exportStepName);
|
||||
}
|
||||
|
||||
public IEnumerable<IRecipeBuilderStep> Resolve(IEnumerable<string> exportStepNames) {
|
||||
return from name in exportStepNames
|
||||
let provider = _recipeBuilderSteps.SingleOrDefault(x => x.Name == name)
|
||||
where provider != null
|
||||
select provider;
|
||||
}
|
||||
}
|
||||
}
|
||||
28
src/Orchard/Recipes/Services/RecipeExecutionStepResolver.cs
Normal file
28
src/Orchard/Recipes/Services/RecipeExecutionStepResolver.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Orchard.Recipes.Services
|
||||
{
|
||||
public class RecipeExecutionStepResolver : IRecipeExecutionStepResolver
|
||||
{
|
||||
private readonly IEnumerable<IRecipeExecutionStep> _recipeExecutionSteps;
|
||||
|
||||
public RecipeExecutionStepResolver(IEnumerable<IRecipeExecutionStep> recipeExecutionSteps) {
|
||||
_recipeExecutionSteps = recipeExecutionSteps;
|
||||
}
|
||||
|
||||
public IRecipeExecutionStep Resolve(string importStepName) {
|
||||
return _recipeExecutionSteps.SingleOrDefault(x => x.Names.Contains(importStepName));
|
||||
}
|
||||
|
||||
public IEnumerable<IRecipeExecutionStep> Resolve(IEnumerable<string> importStepNames) {
|
||||
return from name in importStepNames
|
||||
let provider = _recipeExecutionSteps.SingleOrDefault(x => x.Names.Contains(name))
|
||||
where provider != null
|
||||
select provider;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user