mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-12-02 19:44:02 +08:00
Breaking up IRecipeManager in two components: IRecipeHarvester (harvest and parse) and IRecipeManager (execute)
Renaming DiscoverRecipes to HarvestRecipes for consistency with other harvesters we have in Orchard. Renaming MetaData to Metadata for the recipe step and its handler. Moving recipe information elements in the recipe to under the Recipe element, renaming root element to Orchard and modifying the parser accordingly. Using element.Name.LocalName in the parser. Fixing whitespaces in a couple places, setting the Orchard.Recipes assembly copyright information and making the assembly securitytransparent. Refactoring code and unit tests as a result of to above. --HG-- branch : recipe
This commit is contained in:
@@ -1,19 +1,21 @@
|
||||
<?xml version="1.0"?>
|
||||
<Recipe>
|
||||
<Name>cms</Name>
|
||||
<Description>a sample Orchard recipe describing a cms</Description>
|
||||
<Author>orchard</Author>
|
||||
<WebSite>http://orchardproject.net</WebSite>
|
||||
<Tags>tag1, tag2</Tags>
|
||||
<Version>1.1</Version>
|
||||
|
||||
<Orchard>
|
||||
<Recipe>
|
||||
<Name>cms</Name>
|
||||
<Description>a sample Orchard recipe describing a cms</Description>
|
||||
<Author>orchard</Author>
|
||||
<WebSite>http://orchardproject.net</WebSite>
|
||||
<Tags>tag1, tag2</Tags>
|
||||
<Version>1.1</Version>
|
||||
</Recipe>
|
||||
|
||||
<!-- Steps -->
|
||||
<Module src="source directory" replace="false" />
|
||||
<Module name="module1" repository="somerepo" version="1.1" replace="true" />
|
||||
|
||||
|
||||
<Feature disable="f1, f2" enable="f3,f4" />
|
||||
|
||||
<MetaData>
|
||||
|
||||
<Metadata>
|
||||
<Types>
|
||||
<Blog creatable="true">
|
||||
<Body format="abodyformat"/>
|
||||
@@ -23,26 +25,27 @@
|
||||
</Parts>
|
||||
<Fields>
|
||||
</Fields>
|
||||
</MetaData>
|
||||
|
||||
</Metadata>
|
||||
|
||||
<Command>
|
||||
command1
|
||||
command2
|
||||
command3
|
||||
</Command>
|
||||
|
||||
|
||||
<Settings>
|
||||
<SiteSettingsPart PageSize="30" />
|
||||
<CommentSettingsPart enableSpamProtection="true" />
|
||||
</Settings>
|
||||
|
||||
|
||||
<Migration feature="f2"/>
|
||||
|
||||
|
||||
<Theme src="source dir" enabled="true" current="true" />
|
||||
<Theme name="theme1" repository="somerepo" replace="true" />
|
||||
|
||||
<CleanUpInactive />
|
||||
|
||||
|
||||
<Custom1 attr1="value1" />
|
||||
<Custom2 attr2="value2" />
|
||||
</Recipe>
|
||||
</Orchard>
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ namespace Orchard.Tests.Modules.Recipes.Services {
|
||||
public class RecipeManagerTests {
|
||||
private IContainer _container;
|
||||
private IRecipeManager _recipeManager;
|
||||
private IRecipeHarvester _recipeHarvester;
|
||||
private IRecipeParser _recipeParser;
|
||||
private IExtensionFolders _folders;
|
||||
|
||||
@@ -61,6 +62,7 @@ namespace Orchard.Tests.Modules.Recipes.Services {
|
||||
var builder = new ContainerBuilder();
|
||||
_folders = new ModuleFolders(new[] { _tempFolderName }, new StubCacheManager(), new StubWebSiteFolder());
|
||||
builder.RegisterType<RecipeManager>().As<IRecipeManager>();
|
||||
builder.RegisterType<RecipeHarvester>().As<IRecipeHarvester>();
|
||||
builder.RegisterType<ExtensionManager>().As<IExtensionManager>();
|
||||
builder.RegisterType<StubCacheManager>().As<ICacheManager>();
|
||||
builder.RegisterInstance(_folders).As<IExtensionFolders>();
|
||||
@@ -72,6 +74,7 @@ namespace Orchard.Tests.Modules.Recipes.Services {
|
||||
_container = builder.Build();
|
||||
_recipeManager = _container.Resolve<IRecipeManager>();
|
||||
_recipeParser = _container.Resolve<IRecipeParser>();
|
||||
_recipeHarvester = _container.Resolve<IRecipeHarvester>();
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
@@ -80,21 +83,21 @@ namespace Orchard.Tests.Modules.Recipes.Services {
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DiscoverRecipesFailsToFindRecipesWhenCalledWithNotExistingExtension() {
|
||||
var recipes = (List<Recipe>) _recipeManager.DiscoverRecipes("cantfindme");
|
||||
public void HarvestRecipesFailsToFindRecipesWhenCalledWithNotExistingExtension() {
|
||||
var recipes = (List<Recipe>) _recipeHarvester.HarvestRecipes("cantfindme");
|
||||
|
||||
Assert.That(recipes.Count, Is.EqualTo(0));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DiscoverRecipesShouldDiscoverRecipeXmlFiles() {
|
||||
var recipes = (List<Recipe>)_recipeManager.DiscoverRecipes("Sample1");
|
||||
public void HarvestRecipesShouldHarvestRecipeXmlFiles() {
|
||||
var recipes = (List<Recipe>)_recipeHarvester.HarvestRecipes("Sample1");
|
||||
Assert.That(recipes.Count, Is.EqualTo(1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ParseRecipeLoadsRecipeMetaDataIntoModel() {
|
||||
var recipes = (List<Recipe>) _recipeManager.DiscoverRecipes("Sample1");
|
||||
var recipes = (List<Recipe>) _recipeHarvester.HarvestRecipes("Sample1");
|
||||
Assert.That(recipes.Count, Is.EqualTo(1));
|
||||
|
||||
var sampleRecipe = recipes[0];
|
||||
@@ -108,7 +111,7 @@ namespace Orchard.Tests.Modules.Recipes.Services {
|
||||
|
||||
[Test]
|
||||
public void ParseRecipeLoadsRecipeStepsIntoModel() {
|
||||
var recipes = (List<Recipe>)_recipeManager.DiscoverRecipes("Sample1");
|
||||
var recipes = (List<Recipe>)_recipeHarvester.HarvestRecipes("Sample1");
|
||||
Assert.That(recipes.Count, Is.EqualTo(1));
|
||||
|
||||
var sampleRecipe = recipes[0];
|
||||
@@ -124,7 +127,7 @@ namespace Orchard.Tests.Modules.Recipes.Services {
|
||||
|
||||
[Test]
|
||||
public void ExecuteInvokesHandlersWithSteps() {
|
||||
var recipes = (List<Recipe>)_recipeManager.DiscoverRecipes("Sample1");
|
||||
var recipes = (List<Recipe>)_recipeHarvester.HarvestRecipes("Sample1");
|
||||
Assert.That(recipes.Count, Is.EqualTo(1));
|
||||
|
||||
var sampleRecipe = recipes[0];
|
||||
|
||||
@@ -7,6 +7,6 @@ OrchardVersion: 1.0.20
|
||||
Description: Provides Orchard Recipes.
|
||||
Features:
|
||||
Orchard.Recipes:
|
||||
Name: Recipes
|
||||
Name: Recipes
|
||||
Description: Implementation of Orchard recipes.
|
||||
Category: Core
|
||||
|
||||
@@ -55,11 +55,12 @@
|
||||
<Compile Include="RecipeHandlers\CleanUpInactiveRecipeHandler.cs" />
|
||||
<Compile Include="RecipeHandlers\CommandRecipeHandler.cs" />
|
||||
<Compile Include="RecipeHandlers\FeatureRecipeHandler.cs" />
|
||||
<Compile Include="RecipeHandlers\MetaDataRecipeHandler.cs" />
|
||||
<Compile Include="RecipeHandlers\MetadataRecipeHandler.cs" />
|
||||
<Compile Include="RecipeHandlers\MigrationRecipeHandler.cs" />
|
||||
<Compile Include="RecipeHandlers\ModuleRecipeHandler.cs" />
|
||||
<Compile Include="RecipeHandlers\SettingsRecipeHandler.cs" />
|
||||
<Compile Include="RecipeHandlers\ThemeRecipeHandler.cs" />
|
||||
<Compile Include="Services\RecipeHarvester.cs" />
|
||||
<Compile Include="Services\RecipeManager.cs" />
|
||||
<Compile Include="Services\RecipeParser.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
@@ -8,9 +8,8 @@ using System.Runtime.InteropServices;
|
||||
[assembly: AssemblyTitle("Orchard.Recipes")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("MSIT")]
|
||||
[assembly: AssemblyProduct("Orchard.Recipes")]
|
||||
[assembly: AssemblyCopyright("Copyright © MSIT 2011")]
|
||||
[assembly: AssemblyProduct("Orchard")]
|
||||
[assembly: AssemblyCopyright("Copyright © Outercurve Foundation 2009")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
@@ -31,5 +30,6 @@ using System.Runtime.InteropServices;
|
||||
//
|
||||
// You can specify all the values or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
[assembly: AssemblyVersion("1.0.20")]
|
||||
[assembly: AssemblyFileVersion("1.0.20")]
|
||||
[assembly: SecurityTransparent]
|
||||
@@ -4,8 +4,8 @@ using Orchard.Recipes.Models;
|
||||
using Orchard.Recipes.Services;
|
||||
|
||||
namespace Orchard.Recipes.RecipeHandlers {
|
||||
public class MetaDataRecipeHandler : IRecipeHandler {
|
||||
public MetaDataRecipeHandler() {
|
||||
public class MetadataRecipeHandler : IRecipeHandler {
|
||||
public MetadataRecipeHandler() {
|
||||
Logger = NullLogger.Instance;
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
@@ -13,7 +13,7 @@ namespace Orchard.Recipes.RecipeHandlers {
|
||||
public Localizer T { get; set; }
|
||||
ILogger Logger { get; set; }
|
||||
|
||||
// handles the <MetaData> step
|
||||
// handles the <Metadata> step
|
||||
public void ExecuteRecipeStep(RecipeContext recipeContext) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Orchard.Environment.Extensions;
|
||||
using Orchard.FileSystems.WebSite;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Logging;
|
||||
using Orchard.Recipes.Models;
|
||||
|
||||
namespace Orchard.Recipes.Services {
|
||||
public class RecipeHarvester : IRecipeHarvester {
|
||||
private readonly IExtensionManager _extensionManager;
|
||||
private readonly IWebSiteFolder _webSiteFolder;
|
||||
private readonly IRecipeParser _recipeParser;
|
||||
|
||||
public RecipeHarvester(
|
||||
IExtensionManager extensionManager,
|
||||
IWebSiteFolder webSiteFolder,
|
||||
IRecipeParser recipeParser) {
|
||||
_extensionManager = extensionManager;
|
||||
_webSiteFolder = webSiteFolder;
|
||||
_recipeParser = recipeParser;
|
||||
|
||||
Logger = NullLogger.Instance;
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
|
||||
public Localizer T { get; set; }
|
||||
ILogger Logger { get; set; }
|
||||
|
||||
public IEnumerable<Recipe> HarvestRecipes(string extensionName) {
|
||||
var recipes = new List<Recipe>();
|
||||
var extension = _extensionManager.GetExtension(extensionName);
|
||||
if (extension != null) {
|
||||
var recipeLocation = Path.Combine(extension.Location, extensionName, "Recipes");
|
||||
var recipeFiles = _webSiteFolder.ListFiles(recipeLocation, true);
|
||||
recipes.AddRange(
|
||||
from recipeFile in recipeFiles
|
||||
where recipeFile.EndsWith(".recipe.xml", StringComparison.OrdinalIgnoreCase)
|
||||
select _recipeParser.ParseRecipe(_webSiteFolder.ReadFile(recipeFile)));
|
||||
}
|
||||
else {
|
||||
Logger.Error("Could not discover recipes because module '{0}' was not found.", extensionName);
|
||||
}
|
||||
|
||||
return recipes;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,27 +1,13 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Orchard.Environment.Extensions;
|
||||
using Orchard.FileSystems.WebSite;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Logging;
|
||||
using Orchard.Recipes.Models;
|
||||
|
||||
namespace Orchard.Recipes.Services {
|
||||
public class RecipeManager : IRecipeManager {
|
||||
private readonly IExtensionManager _extensionManager;
|
||||
private readonly IWebSiteFolder _webSiteFolder;
|
||||
private readonly IRecipeParser _recipeParser;
|
||||
private readonly IEnumerable<IRecipeHandler> _recipeHandlers;
|
||||
|
||||
public RecipeManager(
|
||||
IExtensionManager extensionManager,
|
||||
IWebSiteFolder webSiteFolder,
|
||||
IRecipeParser recipeParser,
|
||||
IEnumerable<IRecipeHandler> recipeHandlers) {
|
||||
_extensionManager = extensionManager;
|
||||
_webSiteFolder = webSiteFolder;
|
||||
_recipeParser = recipeParser;
|
||||
public RecipeManager(IEnumerable<IRecipeHandler> recipeHandlers) {
|
||||
_recipeHandlers = recipeHandlers;
|
||||
|
||||
Logger = NullLogger.Instance;
|
||||
@@ -36,6 +22,7 @@ namespace Orchard.Recipes.Services {
|
||||
|
||||
// TODO: Run each step inside a transaction boundary.
|
||||
// TODO: Output should go into a report.
|
||||
// TODO: Eventually return a guid.tostring("n") execution id
|
||||
foreach (var recipeStep in recipe.RecipeSteps) {
|
||||
recipeContext.RecipeStep = recipeStep;
|
||||
recipeContext.Executed = false;
|
||||
@@ -47,23 +34,5 @@ namespace Orchard.Recipes.Services {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<Recipe> DiscoverRecipes(string extensionName) {
|
||||
var recipes = new List<Recipe>();
|
||||
var extension = _extensionManager.GetExtension(extensionName);
|
||||
if (extension != null) {
|
||||
var recipeLocation = Path.Combine(extension.Location, extensionName, "Recipes");
|
||||
var recipeFiles = _webSiteFolder.ListFiles(recipeLocation, true);
|
||||
recipes.AddRange(
|
||||
from recipeFile in recipeFiles
|
||||
where recipeFile.EndsWith(".recipe.xml")
|
||||
select _recipeParser.ParseRecipe(_webSiteFolder.ReadFile(recipeFile)));
|
||||
}
|
||||
else {
|
||||
Logger.Error("Could not discover recipes because module '{0}' was not found.", extensionName);
|
||||
}
|
||||
|
||||
return recipes;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,29 +26,38 @@ namespace Orchard.Recipes.Services {
|
||||
textReader.Close();
|
||||
|
||||
foreach (var element in recipeTree.Elements()) {
|
||||
switch(element.Name.ToString()) {
|
||||
case "Name":
|
||||
recipe.Name = element.Value;
|
||||
break;
|
||||
case "Description":
|
||||
recipe.Description = element.Value;
|
||||
break;
|
||||
case "Author":
|
||||
recipe.Author = element.Value;
|
||||
break;
|
||||
case "WebSite":
|
||||
recipe.WebSite = element.Value;
|
||||
break;
|
||||
case "Version":
|
||||
recipe.Version = element.Value;
|
||||
break;
|
||||
case "Tags":
|
||||
recipe.Tags = element.Value;
|
||||
break;
|
||||
default:
|
||||
var recipeStep = new RecipeStep {Name = element.Name.ToString(), Step = element};
|
||||
recipeSteps.Add(recipeStep);
|
||||
break;
|
||||
// Recipe mETaDaTA
|
||||
if (element.Name.LocalName == "Recipe") {
|
||||
foreach (var metadataElement in element.Elements()) {
|
||||
switch (metadataElement.Name.LocalName) {
|
||||
case "Name":
|
||||
recipe.Name = metadataElement.Value;
|
||||
break;
|
||||
case "Description":
|
||||
recipe.Description = metadataElement.Value;
|
||||
break;
|
||||
case "Author":
|
||||
recipe.Author = metadataElement.Value;
|
||||
break;
|
||||
case "WebSite":
|
||||
recipe.WebSite = metadataElement.Value;
|
||||
break;
|
||||
case "Version":
|
||||
recipe.Version = metadataElement.Value;
|
||||
break;
|
||||
case "Tags":
|
||||
recipe.Tags = metadataElement.Value;
|
||||
break;
|
||||
default:
|
||||
Logger.Error("Unrecognized recipe metadata element {0} encountered. Skipping.", metadataElement.Name.LocalName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Recipe step
|
||||
else {
|
||||
var recipeStep = new RecipeStep { Name = element.Name.LocalName, Step = element };
|
||||
recipeSteps.Add(recipeStep);
|
||||
}
|
||||
}
|
||||
recipe.RecipeSteps = recipeSteps;
|
||||
|
||||
@@ -195,6 +195,7 @@
|
||||
<Compile Include="Recipes\Models\RecipeContext.cs" />
|
||||
<Compile Include="Recipes\Models\RecipeStep.cs" />
|
||||
<Compile Include="Recipes\Services\IRecipeHandler.cs" />
|
||||
<Compile Include="Recipes\Services\IRecipeHarvester.cs" />
|
||||
<Compile Include="Recipes\Services\IRecipeManager.cs" />
|
||||
<Compile Include="Recipes\Services\IRecipeParser.cs" />
|
||||
<Compile Include="Security\IEncryptionService.cs" />
|
||||
|
||||
8
src/Orchard/Recipes/Services/IRecipeHarvester.cs
Normal file
8
src/Orchard/Recipes/Services/IRecipeHarvester.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
using System.Collections.Generic;
|
||||
using Orchard.Recipes.Models;
|
||||
|
||||
namespace Orchard.Recipes.Services {
|
||||
public interface IRecipeHarvester : IDependency {
|
||||
IEnumerable<Recipe> HarvestRecipes(string extensionName);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using Orchard.Recipes.Models;
|
||||
using Orchard.Recipes.Models;
|
||||
|
||||
namespace Orchard.Recipes.Services {
|
||||
public interface IRecipeManager : IDependency {
|
||||
void Execute(Recipe recipe);
|
||||
IEnumerable<Recipe> DiscoverRecipes(string extensionName);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user