Simplifying recipe step API for implementers.

This commit is contained in:
Sipke Schoorstra
2015-07-15 12:53:19 +01:00
parent de58b4253d
commit 901c11a1ea
22 changed files with 1178 additions and 1239 deletions

View File

@@ -159,7 +159,7 @@
<Compile Include="Packaging\Services\FileBasedProjectSystemTests.cs" /> <Compile Include="Packaging\Services\FileBasedProjectSystemTests.cs" />
<Compile Include="Packaging\Services\FolderUpdaterTests.cs" /> <Compile Include="Packaging\Services\FolderUpdaterTests.cs" />
<Compile Include="Packaging\Services\PackageInstallerTests.cs" /> <Compile Include="Packaging\Services\PackageInstallerTests.cs" />
<Compile Include="Recipes\RecipeHandlers\ModuleRecipeHandlerTest.cs" /> <Compile Include="Recipes\RecipeHandlers\ModuleStepTest.cs" />
<Compile Include="Recipes\RecipeHandlers\ThemeRecipeHandlerTest.cs" /> <Compile Include="Recipes\RecipeHandlers\ThemeRecipeHandlerTest.cs" />
<Compile Include="Recipes\Services\RecipeManagerTests.cs" /> <Compile Include="Recipes\Services\RecipeManagerTests.cs" />
<Compile Include="Scripting.Dlr\EvaluatorTests.cs" /> <Compile Include="Scripting.Dlr\EvaluatorTests.cs" />

View File

@@ -1,252 +1,252 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Xml.Linq; using System.Xml.Linq;
using Autofac; using Autofac;
using NuGet; using NuGet;
using NUnit.Framework; using NUnit.Framework;
using Orchard.Caching; using Orchard.Caching;
using Orchard.Core.Settings.Descriptor; using Orchard.Core.Settings.Descriptor;
using Orchard.Core.Settings.Descriptor.Records; using Orchard.Core.Settings.Descriptor.Records;
using Orchard.Core.Settings.State; using Orchard.Core.Settings.State;
using Orchard.Data.Migration; using Orchard.Data.Migration;
using Orchard.Environment.Configuration; using Orchard.Environment.Configuration;
using Orchard.Environment.Descriptor; using Orchard.Environment.Descriptor;
using Orchard.Environment.Descriptor.Models; using Orchard.Environment.Descriptor.Models;
using Orchard.Environment.Extensions; using Orchard.Environment.Extensions;
using Orchard.Environment.Extensions.Folders; using Orchard.Environment.Extensions.Folders;
using Orchard.Environment.Extensions.Models; using Orchard.Environment.Extensions.Models;
using Orchard.Environment.Features; using Orchard.Environment.Features;
using Orchard.Environment.State; using Orchard.Environment.State;
using Orchard.Events; using Orchard.Events;
using Orchard.Packaging.GalleryServer; using Orchard.Packaging.GalleryServer;
using Orchard.Packaging.Models; using Orchard.Packaging.Models;
using Orchard.Packaging.Services; using Orchard.Packaging.Services;
using Orchard.Recipes.Models; using Orchard.Recipes.Models;
using Orchard.Recipes.RecipeHandlers; using Orchard.Recipes.RecipeExecutionSteps;
using Orchard.Recipes.Services; using Orchard.Recipes.Services;
using Orchard.Tests.Environment.Extensions; using Orchard.Tests.Environment.Extensions;
using Orchard.Tests.Environment.Features; using Orchard.Tests.Environment.Features;
using Orchard.Tests.Stubs; using Orchard.Tests.Stubs;
using IPackageManager = Orchard.Packaging.Services.IPackageManager; using IPackageManager = Orchard.Packaging.Services.IPackageManager;
using Orchard.Tests.Modules.Recipes.Services;
namespace Orchard.Tests.Modules.Recipes.RecipeHandlers {
namespace Orchard.Tests.Modules.Recipes.RecipeHandlers { [TestFixture]
[TestFixture] public class ModuleStepTest : DatabaseEnabledTestsBase {
public class ModuleRecipeHandlerTest : DatabaseEnabledTestsBase { private ExtensionManagerTests.StubFolders _folders;
private ExtensionManagerTests.StubFolders _folders; private StubPackagingSourceManager _packagesInRepository;
private StubPackagingSourceManager _packagesInRepository; private StubPackageManager _packageManager;
private StubPackageManager _packageManager;
protected override IEnumerable<Type> DatabaseTypes {
protected override IEnumerable<Type> DatabaseTypes { get {
get { return new[] {
return new[] { typeof (ShellDescriptorRecord),
typeof (ShellDescriptorRecord), typeof (ShellFeatureRecord),
typeof (ShellFeatureRecord), typeof (ShellParameterRecord),
typeof (ShellParameterRecord), };
}; }
} }
}
public override void Register(ContainerBuilder builder) {
public override void Register(ContainerBuilder builder) { builder.RegisterInstance(new ShellSettings { Name = "Default" });
builder.RegisterInstance(new ShellSettings { Name = "Default" });
_folders = new ExtensionManagerTests.StubFolders();
_folders = new ExtensionManagerTests.StubFolders(); _packagesInRepository = new StubPackagingSourceManager();
_packagesInRepository = new StubPackagingSourceManager(); _packageManager = new StubPackageManager();
_packageManager = new StubPackageManager(); builder.RegisterInstance(_folders).As<IExtensionFolders>();
builder.RegisterInstance(_folders).As<IExtensionFolders>(); builder.RegisterType<ExtensionManager>().As<IExtensionManager>();
builder.RegisterType<ExtensionManager>().As<IExtensionManager>(); builder.RegisterType<FeatureManager>().As<IFeatureManager>();
builder.RegisterType<FeatureManager>().As<IFeatureManager>(); builder.RegisterType<StubCacheManager>().As<ICacheManager>();
builder.RegisterType<StubCacheManager>().As<ICacheManager>(); builder.RegisterType<StubParallelCacheContext>().As<IParallelCacheContext>();
builder.RegisterType<StubParallelCacheContext>().As<IParallelCacheContext>(); builder.RegisterType<StubAsyncTokenProvider>().As<IAsyncTokenProvider>();
builder.RegisterType<StubAsyncTokenProvider>().As<IAsyncTokenProvider>(); builder.RegisterType<ShellDescriptorManager>().As<IShellDescriptorManager>().SingleInstance();
builder.RegisterType<ShellDescriptorManager>().As<IShellDescriptorManager>().SingleInstance(); builder.RegisterType<StubDataMigrationManager>().As<IDataMigrationManager>();
builder.RegisterType<StubDataMigrationManager>().As<IDataMigrationManager>(); builder.RegisterInstance(_packagesInRepository).As<IPackagingSourceManager>();
builder.RegisterInstance(_packagesInRepository).As<IPackagingSourceManager>(); builder.RegisterInstance(_packageManager).As<IPackageManager>();
builder.RegisterInstance(_packageManager).As<IPackageManager>(); builder.RegisterType<ShellStateManager>().As<IShellStateManager>().SingleInstance();
builder.RegisterType<ShellStateManager>().As<IShellStateManager>().SingleInstance(); builder.RegisterType<StubEventBus>().As<IEventBus>().SingleInstance();
builder.RegisterType<StubEventBus>().As<IEventBus>().SingleInstance(); builder.RegisterType<ModuleStep>();
builder.RegisterType<ModuleRecipeHandler>(); builder.RegisterSource(new EventsRegistrationSource());
builder.RegisterSource(new EventsRegistrationSource()); }
}
[Test]
[Test] public void ExecuteRecipeStepTest() {
public void ExecuteRecipeStepTest() { _folders.Manifests.Add("SuperWiki", @"
_folders.Manifests.Add("SuperWiki", @" Name: SuperWiki
Name: SuperWiki Version: 1.0.3
Version: 1.0.3 OrchardVersion: 1
OrchardVersion: 1 Features:
Features: SuperWiki:
SuperWiki: Description: My super wiki module for Orchard.
Description: My super wiki module for Orchard. ");
"); _packagesInRepository.AddPublishedPackage(new PublishedPackage {
_packagesInRepository.AddPublishedPackage(new PublishedPackage { Id = "Orchard.Module.SuperWiki",
Id = "Orchard.Module.SuperWiki", PackageType = DefaultExtensionTypes.Module,
PackageType = DefaultExtensionTypes.Module, Title = "SuperWiki",
Title = "SuperWiki", Version = "1.0.3",
Version = "1.0.3", IsLatestVersion = true,
IsLatestVersion = true, });
});
IShellDescriptorManager shellDescriptorManager = _container.Resolve<IShellDescriptorManager>();
IShellDescriptorManager shellDescriptorManager = _container.Resolve<IShellDescriptorManager>(); // No features enabled
// No features enabled shellDescriptorManager.UpdateShellDescriptor(0,
shellDescriptorManager.UpdateShellDescriptor(0, Enumerable.Empty<ShellFeature>(),
Enumerable.Empty<ShellFeature>(), Enumerable.Empty<ShellParameter>());
Enumerable.Empty<ShellParameter>());
var moduleStep = _container.Resolve<ModuleStep>();
ModuleRecipeHandler moduleRecipeHandler = _container.Resolve<ModuleRecipeHandler>(); var recipeContext = new RecipeContext { RecipeStep = new RecipeStep { Name = "Module", Step = new XElement("SuperWiki") } };
var recipeExecutionContext = new RecipeExecutionContext {RecipeStep = recipeContext.RecipeStep};
RecipeContext recipeContext = new RecipeContext { RecipeStep = new RecipeStep { Name = "Module", Step = new XElement("SuperWiki") } }; recipeContext.RecipeStep.Step.Add(new XAttribute("packageId", "Orchard.Module.SuperWiki"));
recipeContext.RecipeStep.Step.Add(new XAttribute("packageId", "Orchard.Module.SuperWiki")); recipeContext.RecipeStep.Step.Add(new XAttribute("repository", "test"));
recipeContext.RecipeStep.Step.Add(new XAttribute("repository", "test"));
IFeatureManager featureManager = _container.Resolve<IFeatureManager>();
IFeatureManager featureManager = _container.Resolve<IFeatureManager>(); IEnumerable<FeatureDescriptor> enabledFeatures = featureManager.GetEnabledFeatures();
IEnumerable<FeatureDescriptor> enabledFeatures = featureManager.GetEnabledFeatures(); Assert.That(enabledFeatures.Count(), Is.EqualTo(0));
Assert.That(enabledFeatures.Count(), Is.EqualTo(0)); moduleStep.Execute(recipeExecutionContext);
moduleRecipeHandler.ExecuteRecipeStep(recipeContext);
var availableFeatures = featureManager.GetAvailableFeatures().Where(x => x.Id == "SuperWiki").FirstOrDefault();
var availableFeatures = featureManager.GetAvailableFeatures().Where(x => x.Id == "SuperWiki").FirstOrDefault(); Assert.That(availableFeatures.Id, Is.EqualTo("SuperWiki"));
Assert.That(availableFeatures.Id, Is.EqualTo("SuperWiki")); Assert.That(recipeContext.Executed, Is.True);
Assert.That(recipeContext.Executed, Is.True); }
}
[Test]
[Test] public void ExecuteRecipeStepNeedsNameTest() {
public void ExecuteRecipeStepNeedsNameTest() { _folders.Manifests.Add("SuperWiki", @"
_folders.Manifests.Add("SuperWiki", @" Name: SuperWiki
Name: SuperWiki Version: 1.0.3
Version: 1.0.3 OrchardVersion: 1
OrchardVersion: 1 Features:
Features: SuperWiki:
SuperWiki: Description: My super wiki module for Orchard.
Description: My super wiki module for Orchard. ");
");
var moduleStep = _container.Resolve<ModuleStep>();
ModuleRecipeHandler moduleRecipeHandler = _container.Resolve<ModuleRecipeHandler>(); var recipeContext = new RecipeContext { RecipeStep = new RecipeStep { Name = "Module", Step = new XElement("SuperWiki") } };
var recipeExecutionContext = new RecipeExecutionContext { RecipeStep = recipeContext.RecipeStep };
RecipeContext recipeContext = new RecipeContext { RecipeStep = new RecipeStep { Name = "Module", Step = new XElement("SuperWiki") } }; recipeContext.RecipeStep.Step.Add(new XAttribute("repository", "test"));
recipeContext.RecipeStep.Step.Add(new XAttribute("repository", "test"));
Assert.Throws(typeof (InvalidOperationException), () => moduleStep.Execute(recipeExecutionContext));
Assert.Throws(typeof (InvalidOperationException), () => moduleRecipeHandler.ExecuteRecipeStep(recipeContext)); }
}
[Test]
[Test] public void ExecuteRecipeStepWithRepositoryAndVersionNotLatestTest() {
public void ExecuteRecipeStepWithRepositoryAndVersionNotLatestTest() { _packagesInRepository.AddPublishedPackage(new PublishedPackage {
_packagesInRepository.AddPublishedPackage(new PublishedPackage { Id = "Orchard.Module.SuperWiki",
Id = "Orchard.Module.SuperWiki", PackageType = DefaultExtensionTypes.Module,
PackageType = DefaultExtensionTypes.Module, Title = "SuperWiki",
Title = "SuperWiki", Version = "1.0.3",
Version = "1.0.3", IsLatestVersion = true,
IsLatestVersion = true, });
}); _packagesInRepository.AddPublishedPackage(new PublishedPackage {
_packagesInRepository.AddPublishedPackage(new PublishedPackage { Id = "Orchard.Module.SuperWiki",
Id = "Orchard.Module.SuperWiki", PackageType = DefaultExtensionTypes.Module,
PackageType = DefaultExtensionTypes.Module, Title = "SuperWiki",
Title = "SuperWiki", Version = "1.0.2",
Version = "1.0.2", IsLatestVersion = false,
IsLatestVersion = false, });
});
var moduleStep = _container.Resolve<ModuleStep>();
ModuleRecipeHandler moduleRecipeHandler = _container.Resolve<ModuleRecipeHandler>(); var recipeContext = new RecipeContext { RecipeStep = new RecipeStep { Name = "Module", Step = new XElement("SuperWiki") } };
var recipeExecutionContext = new RecipeExecutionContext { RecipeStep = recipeContext.RecipeStep };
RecipeContext recipeContext = new RecipeContext { RecipeStep = new RecipeStep { Name = "Module", Step = new XElement("SuperWiki") } };
recipeContext.RecipeStep.Step.Add(new XAttribute("packageId", "Orchard.Module.SuperWiki")); recipeContext.RecipeStep.Step.Add(new XAttribute("packageId", "Orchard.Module.SuperWiki"));
recipeContext.RecipeStep.Step.Add(new XAttribute("repository", "test")); recipeContext.RecipeStep.Step.Add(new XAttribute("repository", "test"));
recipeContext.RecipeStep.Step.Add(new XAttribute("version", "1.0.2")); recipeContext.RecipeStep.Step.Add(new XAttribute("version", "1.0.2"));
moduleRecipeHandler.ExecuteRecipeStep(recipeContext); moduleStep.Execute(recipeExecutionContext);
var installedPackage = _packageManager.GetInstalledPackages().FirstOrDefault(info => info.ExtensionName == "Orchard.Module.SuperWiki"); var installedPackage = _packageManager.GetInstalledPackages().FirstOrDefault(info => info.ExtensionName == "Orchard.Module.SuperWiki");
Assert.That(installedPackage, Is.Not.Null); Assert.That(installedPackage, Is.Not.Null);
Assert.That(installedPackage.ExtensionVersion, Is.EqualTo("1.0.2")); Assert.That(installedPackage.ExtensionVersion, Is.EqualTo("1.0.2"));
Assert.That(recipeContext.Executed, Is.True); Assert.That(recipeContext.Executed, Is.True);
} }
internal class StubPackagingSourceManager : IPackagingSourceManager { internal class StubPackagingSourceManager : IPackagingSourceManager {
private List<PublishedPackage> _publishedPackages = new List<PublishedPackage>(); private readonly List<PublishedPackage> _publishedPackages = new List<PublishedPackage>();
public IEnumerable<PackagingSource> GetSources() { public IEnumerable<PackagingSource> GetSources() {
return Enumerable.Empty<PackagingSource>(); return Enumerable.Empty<PackagingSource>();
} }
public int AddSource(string feedTitle, string feedUrl) { public int AddSource(string feedTitle, string feedUrl) {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public void RemoveSource(int id) { public void RemoveSource(int id) {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public IEnumerable<PackagingEntry> GetExtensionList(bool includeScreenshots, PackagingSource packagingSource = null, Func<IQueryable<PublishedPackage>, IQueryable<PublishedPackage>> query = null) { public IEnumerable<PackagingEntry> GetExtensionList(bool includeScreenshots, PackagingSource packagingSource = null, Func<IQueryable<PublishedPackage>, IQueryable<PublishedPackage>> query = null) {
return query(_publishedPackages.AsQueryable()).Select(package => CreatePackagingEntry(package)); return query(_publishedPackages.AsQueryable()).Select(package => CreatePackagingEntry(package));
} }
public int GetExtensionCount(PackagingSource packagingSource = null, Func<IQueryable<PublishedPackage>, IQueryable<PublishedPackage>> query = null) { public int GetExtensionCount(PackagingSource packagingSource = null, Func<IQueryable<PublishedPackage>, IQueryable<PublishedPackage>> query = null) {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public void AddPublishedPackage(PublishedPackage package) { public void AddPublishedPackage(PublishedPackage package) {
_publishedPackages.Add(package); _publishedPackages.Add(package);
} }
private static PackagingEntry CreatePackagingEntry(PublishedPackage package) { private static PackagingEntry CreatePackagingEntry(PublishedPackage package) {
return new PackagingEntry { return new PackagingEntry {
PackageId = package.Id, PackageId = package.Id,
Title = package.Title, Title = package.Title,
Version = package.Version, Version = package.Version,
}; };
} }
} }
internal class StubPackageManager : IPackageManager { internal class StubPackageManager : IPackageManager {
private IList<PackageInfo> _installedPackages = new List<PackageInfo>(); private readonly IList<PackageInfo> _installedPackages = new List<PackageInfo>();
public IEnumerable<PackageInfo> GetInstalledPackages() { public IEnumerable<PackageInfo> GetInstalledPackages() {
return _installedPackages; return _installedPackages;
} }
public PackageData Harvest(string extensionName) { public PackageData Harvest(string extensionName) {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public PackageInfo Install(IPackage package, string location, string applicationPath) { public PackageInfo Install(IPackage package, string location, string applicationPath) {
return null; return null;
} }
public PackageInfo Install(string packageId, string version, string location, string applicationPath) { public PackageInfo Install(string packageId, string version, string location, string applicationPath) {
var package = new PackageInfo { var package = new PackageInfo {
ExtensionName = packageId, ExtensionName = packageId,
ExtensionVersion = version, ExtensionVersion = version,
}; };
_installedPackages.Add(package); _installedPackages.Add(package);
return package; return package;
} }
public void Uninstall(string packageId, string applicationPath) { public void Uninstall(string packageId, string applicationPath) {
} }
public ExtensionDescriptor GetExtensionDescriptor(IPackage package, string extensionType) { public ExtensionDescriptor GetExtensionDescriptor(IPackage package, string extensionType) {
throw new NotImplementedException(); throw new NotImplementedException();
} }
} }
internal class StubDataMigrationManager : IDataMigrationManager { internal class StubDataMigrationManager : IDataMigrationManager {
public bool IsFeatureAlreadyInstalled(string feature) { public bool IsFeatureAlreadyInstalled(string feature) {
return true; return true;
} }
public IEnumerable<string> GetFeaturesThatNeedUpdate() { public IEnumerable<string> GetFeaturesThatNeedUpdate() {
return Enumerable.Empty<string>(); return Enumerable.Empty<string>();
} }
public void Update(string feature) { public void Update(string feature) {
} }
public void Update(IEnumerable<string> features) { public void Update(IEnumerable<string> features) {
} }
public void Uninstall(string feature) { public void Uninstall(string feature) {
} }
} }
} }
} }

View File

@@ -1,7 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Web.Hosting;
using System.Xml.Linq; using System.Xml.Linq;
using Autofac; using Autofac;
using NUnit.Framework; using NUnit.Framework;
@@ -23,21 +22,21 @@ using Orchard.FileSystems.VirtualPath;
using Orchard.Packaging.GalleryServer; using Orchard.Packaging.GalleryServer;
using Orchard.Packaging.Services; using Orchard.Packaging.Services;
using Orchard.Recipes.Models; using Orchard.Recipes.Models;
using Orchard.Recipes.RecipeHandlers; using Orchard.Recipes.RecipeExecutionSteps;
using Orchard.Recipes.Services;
using Orchard.Tests.DisplayManagement.Descriptors; using Orchard.Tests.DisplayManagement.Descriptors;
using Orchard.Tests.Environment.Extensions; using Orchard.Tests.Environment.Extensions;
using Orchard.Tests.Environment.Features; using Orchard.Tests.Environment.Features;
using Orchard.Tests.Stubs; using Orchard.Tests.Stubs;
using Orchard.Tests.UI.Navigation; using Orchard.Tests.UI.Navigation;
using Orchard.Themes.Services; using Orchard.Themes.Services;
using IPackageManager = Orchard.Packaging.Services.IPackageManager;
namespace Orchard.Tests.Modules.Recipes.RecipeHandlers { namespace Orchard.Tests.Modules.Recipes.RecipeHandlers {
[TestFixture] [TestFixture]
public class ThemeRecipeHandlerTest : DatabaseEnabledTestsBase { public class ThemeRecipeHandlerTest : DatabaseEnabledTestsBase {
private ExtensionManagerTests.StubFolders _folders; private ExtensionManagerTests.StubFolders _folders;
private ModuleRecipeHandlerTest.StubPackagingSourceManager _packagesInRepository; private ModuleStepTest.StubPackagingSourceManager _packagesInRepository;
private ModuleRecipeHandlerTest.StubPackageManager _packageManager; private ModuleStepTest.StubPackageManager _packageManager;
protected override IEnumerable<Type> DatabaseTypes { protected override IEnumerable<Type> DatabaseTypes {
get { get {
@@ -50,13 +49,13 @@ namespace Orchard.Tests.Modules.Recipes.RecipeHandlers {
} }
public override void Register(ContainerBuilder builder) { public override void Register(ContainerBuilder builder) {
var _testVirtualPathProvider = new StylesheetBindingStrategyTests.TestVirtualPathProvider(); var testVirtualPathProvider = new StylesheetBindingStrategyTests.TestVirtualPathProvider();
builder.RegisterInstance(new ShellSettings { Name = "Default" }); builder.RegisterInstance(new ShellSettings { Name = "Default" });
_folders = new ExtensionManagerTests.StubFolders(); _folders = new ExtensionManagerTests.StubFolders();
_packagesInRepository = new ModuleRecipeHandlerTest.StubPackagingSourceManager(); _packagesInRepository = new ModuleStepTest.StubPackagingSourceManager();
_packageManager = new ModuleRecipeHandlerTest.StubPackageManager(); _packageManager = new ModuleStepTest.StubPackageManager();
builder.RegisterInstance(_folders).As<IExtensionFolders>(); builder.RegisterInstance(_folders).As<IExtensionFolders>();
builder.RegisterType<ExtensionManager>().As<IExtensionManager>(); builder.RegisterType<ExtensionManager>().As<IExtensionManager>();
builder.RegisterType<FeatureManager>().As<IFeatureManager>(); builder.RegisterType<FeatureManager>().As<IFeatureManager>();
@@ -64,16 +63,16 @@ namespace Orchard.Tests.Modules.Recipes.RecipeHandlers {
builder.RegisterType<StubParallelCacheContext>().As<IParallelCacheContext>(); builder.RegisterType<StubParallelCacheContext>().As<IParallelCacheContext>();
builder.RegisterType<StubAsyncTokenProvider>().As<IAsyncTokenProvider>(); builder.RegisterType<StubAsyncTokenProvider>().As<IAsyncTokenProvider>();
builder.RegisterType<ShellDescriptorManager>().As<IShellDescriptorManager>().SingleInstance(); builder.RegisterType<ShellDescriptorManager>().As<IShellDescriptorManager>().SingleInstance();
builder.RegisterType<ModuleRecipeHandlerTest.StubDataMigrationManager>().As<IDataMigrationManager>(); builder.RegisterType<ModuleStepTest.StubDataMigrationManager>().As<IDataMigrationManager>();
builder.RegisterInstance(_packagesInRepository).As<IPackagingSourceManager>(); builder.RegisterInstance(_packagesInRepository).As<IPackagingSourceManager>();
builder.RegisterInstance(_packageManager).As<IPackageManager>(); builder.RegisterInstance(_packageManager).As<IPackageManager>();
builder.RegisterType<ShellStateManager>().As<IShellStateManager>().SingleInstance(); builder.RegisterType<ShellStateManager>().As<IShellStateManager>().SingleInstance();
builder.RegisterInstance(_testVirtualPathProvider).As<IVirtualPathProvider>(); builder.RegisterInstance(testVirtualPathProvider).As<IVirtualPathProvider>();
builder.RegisterType<StubEventBus>().As<IEventBus>().SingleInstance(); builder.RegisterType<StubEventBus>().As<IEventBus>().SingleInstance();
builder.RegisterType<ThemeService>().As<IThemeService>(); builder.RegisterType<ThemeService>().As<IThemeService>();
builder.RegisterType<StubOrchardServices>().As<IOrchardServices>(); builder.RegisterType<StubOrchardServices>().As<IOrchardServices>();
builder.RegisterType<StubSiteThemeService>().As<ISiteThemeService>(); builder.RegisterType<StubSiteThemeService>().As<ISiteThemeService>();
builder.RegisterType<ThemeRecipeHandler>(); builder.RegisterType<ThemeStep>();
builder.RegisterSource(new EventsRegistrationSource()); builder.RegisterSource(new EventsRegistrationSource());
} }
@@ -101,16 +100,17 @@ Features:
Enumerable.Empty<ShellFeature>(), Enumerable.Empty<ShellFeature>(),
Enumerable.Empty<ShellParameter>()); Enumerable.Empty<ShellParameter>());
ThemeRecipeHandler themeRecipeHandler = _container.Resolve<ThemeRecipeHandler>(); var themeStep = _container.Resolve<ThemeStep>();
var recipeContext = new RecipeContext { RecipeStep = new RecipeStep { Name = "Theme", Step = new XElement("SuperWiki") } };
var recipeExecutionContext = new RecipeExecutionContext {RecipeStep = recipeContext.RecipeStep};
RecipeContext recipeContext = new RecipeContext { RecipeStep = new RecipeStep { Name = "Theme", Step = new XElement("SuperWiki") } };
recipeContext.RecipeStep.Step.Add(new XAttribute("packageId", "Orchard.Theme.SuperWiki")); recipeContext.RecipeStep.Step.Add(new XAttribute("packageId", "Orchard.Theme.SuperWiki"));
recipeContext.RecipeStep.Step.Add(new XAttribute("repository", "test")); recipeContext.RecipeStep.Step.Add(new XAttribute("repository", "test"));
IFeatureManager featureManager = _container.Resolve<IFeatureManager>(); var featureManager = _container.Resolve<IFeatureManager>();
IEnumerable<FeatureDescriptor> enabledFeatures = featureManager.GetEnabledFeatures(); var enabledFeatures = featureManager.GetEnabledFeatures();
Assert.That(enabledFeatures.Count(), Is.EqualTo(0)); Assert.That(enabledFeatures.Count(), Is.EqualTo(0));
themeRecipeHandler.ExecuteRecipeStep(recipeContext); themeStep.Execute(recipeExecutionContext);
// without setting enable no feature should be activated... // without setting enable no feature should be activated...
featureManager.GetEnabledFeatures(); featureManager.GetEnabledFeatures();
@@ -118,7 +118,7 @@ Features:
// Adding enable the feature should get active // Adding enable the feature should get active
recipeContext.RecipeStep.Step.Add(new XAttribute("enable", true)); recipeContext.RecipeStep.Step.Add(new XAttribute("enable", true));
themeRecipeHandler.ExecuteRecipeStep(recipeContext); themeStep.Execute(recipeExecutionContext);
enabledFeatures = featureManager.GetEnabledFeatures(); enabledFeatures = featureManager.GetEnabledFeatures();
Assert.That(enabledFeatures.FirstOrDefault(feature => feature.Id.Equals("SuperWiki")), Is.Not.Null); Assert.That(enabledFeatures.FirstOrDefault(feature => feature.Id.Equals("SuperWiki")), Is.Not.Null);
@@ -137,12 +137,12 @@ Features:
Description: My super wiki module for Orchard. Description: My super wiki module for Orchard.
"); ");
ThemeRecipeHandler themeRecipeHandler = _container.Resolve<ThemeRecipeHandler>(); var themeStep = _container.Resolve<ThemeStep>();
var recipeContext = new RecipeContext { RecipeStep = new RecipeStep { Name = "Theme", Step = new XElement("SuperWiki") } };
var recipeExecutionContext = new RecipeExecutionContext { RecipeStep = recipeContext.RecipeStep };
RecipeContext recipeContext = new RecipeContext { RecipeStep = new RecipeStep { Name = "Theme", Step = new XElement("SuperWiki") } };
recipeContext.RecipeStep.Step.Add(new XAttribute("repository", "test")); recipeContext.RecipeStep.Step.Add(new XAttribute("repository", "test"));
Assert.Throws(typeof (InvalidOperationException), () => themeStep.Execute(recipeExecutionContext));
Assert.Throws(typeof (InvalidOperationException), () => themeRecipeHandler.ExecuteRecipeStep(recipeContext));
} }
[Test] [Test]
@@ -162,14 +162,15 @@ Features:
IsLatestVersion = false, IsLatestVersion = false,
}); });
ThemeRecipeHandler themeRecipeHandler = _container.Resolve<ThemeRecipeHandler>(); var themeStep = _container.Resolve<ThemeStep>();
var recipeContext = new RecipeContext { RecipeStep = new RecipeStep { Name = "Theme", Step = new XElement("SuperWiki") } };
var recipeExecutionContext = new RecipeExecutionContext { RecipeStep = recipeContext.RecipeStep };
RecipeContext recipeContext = new RecipeContext { RecipeStep = new RecipeStep { Name = "Theme", Step = new XElement("SuperWiki") } };
recipeContext.RecipeStep.Step.Add(new XAttribute("packageId", "Orchard.Theme.SuperWiki")); recipeContext.RecipeStep.Step.Add(new XAttribute("packageId", "Orchard.Theme.SuperWiki"));
recipeContext.RecipeStep.Step.Add(new XAttribute("repository", "test")); recipeContext.RecipeStep.Step.Add(new XAttribute("repository", "test"));
recipeContext.RecipeStep.Step.Add(new XAttribute("version", "1.0.2")); recipeContext.RecipeStep.Step.Add(new XAttribute("version", "1.0.2"));
themeRecipeHandler.ExecuteRecipeStep(recipeContext); themeStep.Execute(recipeExecutionContext);
var installedPackage = _packageManager.GetInstalledPackages().FirstOrDefault(info => info.ExtensionName == "Orchard.Theme.SuperWiki"); var installedPackage = _packageManager.GetInstalledPackages().FirstOrDefault(info => info.ExtensionName == "Orchard.Theme.SuperWiki");
Assert.That(installedPackage, Is.Not.Null); Assert.That(installedPackage, Is.Not.Null);

View File

@@ -113,7 +113,7 @@ namespace Orchard.ImportExport.Commands {
} }
if (SiteSettings) { if (SiteSettings) {
var siteSettingsStep = _orchardServices.WorkContext.Resolve<SiteSettingsBuilderStep>(); var siteSettingsStep = _orchardServices.WorkContext.Resolve<SettingsBuilderStep>();
recipeBuilderSteps.Add(siteSettingsStep); recipeBuilderSteps.Add(siteSettingsStep);
} }

View File

@@ -84,18 +84,22 @@
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RecipeBuilders\ContentRecipeBuilderStep.cs" /> <Compile Include="RecipeBuilders\ContentRecipeBuilderStep.cs" />
<Compile Include="RecipeBuilders\RecipeMetadataBuilderStep.cs" /> <Compile Include="RecipeBuilders\RecipeMetadataBuilderStep.cs" />
<Compile Include="RecipeBuilders\SiteSettingsBuilderStep.cs" /> <Compile Include="RecipeBuilders\SettingsBuilderStep.cs" />
<Compile Include="RecipeHandlers\CommandRecipeHandler.cs" /> <Compile Include="RecipeExecutionSteps\CommandStep.cs" />
<Compile Include="RecipeHandlers\DataRecipeHandler.cs" /> <Compile Include="RecipeExecutionSteps\ContentStep.cs" />
<Compile Include="RecipeHandlers\FeatureRecipeHandler.cs" /> <Compile Include="RecipeExecutionSteps\FeatureStep.cs" />
<Compile Include="RecipeHandlers\MetadataRecipeHandler.cs" /> <Compile Include="RecipeExecutionSteps\ContentSchemaStep.cs" />
<Compile Include="RecipeHandlers\MigrationRecipeHandler.cs" /> <Compile Include="RecipeExecutionSteps\MigrationStep.cs" />
<Compile Include="RecipeHandlers\ModuleRecipeHandler.cs" /> <Compile Include="RecipeExecutionSteps\ModuleStep.cs" />
<Compile Include="RecipeHandlers\SettingsRecipeHandler.cs" /> <Compile Include="RecipeExecutionSteps\SettingsStep.cs" />
<Compile Include="RecipeHandlers\ThemeRecipeHandler.cs" /> <Compile Include="RecipeExecutionSteps\ThemeStep.cs" />
<Compile Include="RecipeHandlers\RecipeExecutionStepHandler.cs" />
<Compile Include="Routes.cs" /> <Compile Include="Routes.cs" />
<Compile Include="Services\BuildContext.cs" /> <Compile Include="Services\BuildContext.cs" />
<Compile Include="Services\IRecipeExecutionStep.cs" />
<Compile Include="Services\IRecipeExecutor.cs" /> <Compile Include="Services\IRecipeExecutor.cs" />
<Compile Include="Services\RecipeExecutionContext.cs" />
<Compile Include="Services\RecipeExecutionStep.cs" />
<Compile Include="Services\RecipeExecutor.cs" /> <Compile Include="Services\RecipeExecutor.cs" />
<Compile Include="Services\IRecipeBuilder.cs" /> <Compile Include="Services\IRecipeBuilder.cs" />
<Compile Include="Services\RecipeBuilder.cs" /> <Compile Include="Services\RecipeBuilder.cs" />
@@ -152,7 +156,7 @@
<Content Include="Views\EditorTemplates\ExportSteps\RecipeMetadata.cshtml" /> <Content Include="Views\EditorTemplates\ExportSteps\RecipeMetadata.cshtml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="Views\EditorTemplates\ExportSteps\SiteSettings.cshtml" /> <Content Include="Views\EditorTemplates\ExportSteps\Settings.cshtml" />
</ItemGroup> </ItemGroup>
<PropertyGroup> <PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion> <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>

View File

@@ -104,11 +104,11 @@ namespace Orchard.Recipes.RecipeBuilders {
partsElement.Add(_contentDefinitionWriter.Export(part)); partsElement.Add(_contentDefinitionWriter.Export(part));
} }
return new XElement("Metadata", typesElement, partsElement); return new XElement("ContentSchema", typesElement, partsElement);
} }
private XElement ExportData(IEnumerable<string> contentTypes, IEnumerable<ContentItem> contentItems, int? batchSize) { private XElement ExportData(IEnumerable<string> contentTypes, IEnumerable<ContentItem> contentItems, int? batchSize) {
var data = new XElement("Data"); var data = new XElement("Content");
if (batchSize.HasValue && batchSize.Value > 0) if (batchSize.HasValue && batchSize.Value > 0)
data.SetAttributeValue("BatchSize", batchSize); data.SetAttributeValue("BatchSize", batchSize);

View File

@@ -7,23 +7,23 @@ using Orchard.Recipes.Services;
using Orchard.Recipes.ViewModels; using Orchard.Recipes.ViewModels;
namespace Orchard.Recipes.RecipeBuilders { namespace Orchard.Recipes.RecipeBuilders {
public class SiteSettingsBuilderStep : RecipeBuilderStep { public class SettingsBuilderStep : RecipeBuilderStep {
private readonly IOrchardServices _orchardServices; private readonly IOrchardServices _orchardServices;
public SiteSettingsBuilderStep(IOrchardServices orchardServices) { public SettingsBuilderStep(IOrchardServices orchardServices) {
_orchardServices = orchardServices; _orchardServices = orchardServices;
} }
public override string Name { public override string Name {
get { return "SiteSettings"; } get { return "Settings"; }
} }
public override LocalizedString DisplayName { public override LocalizedString DisplayName {
get { return T("Site Settings"); } get { return T("Settings"); }
} }
public override LocalizedString Description { public override LocalizedString Description {
get { return T("Exports site settings."); } get { return T("Exports settings."); }
} }
public override int Priority { get { return 20; } } public override int Priority { get { return 20; } }
@@ -34,7 +34,7 @@ namespace Orchard.Recipes.RecipeBuilders {
public override dynamic UpdateEditor(dynamic shapeFactory, IUpdateModel updater) { public override dynamic UpdateEditor(dynamic shapeFactory, IUpdateModel updater) {
var viewModel = new SiteSettingsStepViewModel(); var viewModel = new SiteSettingsStepViewModel();
return shapeFactory.EditorTemplate(TemplateName: "ExportSteps/SiteSettings", Model: viewModel, Prefix: Prefix); return shapeFactory.EditorTemplate(TemplateName: "ExportSteps/Settings", Model: viewModel, Prefix: Prefix);
} }
public override void Build(BuildContext context) { public override void Build(BuildContext context) {

View File

@@ -1,212 +1,198 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Orchard.Commands; using Orchard.Commands;
using Orchard.Localization; using Orchard.Logging;
using Orchard.Logging; using Orchard.Recipes.Services;
using Orchard.Recipes.Models;
using Orchard.Recipes.Services; namespace Orchard.Recipes.RecipeExecutionSteps {
public class CommandStep : RecipeExecutionStep {
namespace Orchard.Recipes.RecipeHandlers { private readonly ICommandManager _commandManager;
public class CommandRecipeHandler : IRecipeHandler { private readonly CommandParser _commandParser;
private readonly ICommandManager _commandManager;
private readonly CommandParser _commandParser; public CommandStep(ICommandManager commandManager) {
_commandManager = commandManager;
public CommandRecipeHandler(ICommandManager commandManager) { _commandParser = new CommandParser();
_commandManager = commandManager; }
_commandParser = new CommandParser();
Logger = NullLogger.Instance; public override string Name { get { return "Command"; } }
T = NullLocalizer.Instance;
} /*
<Command>
public Localizer T { get; set; } command1
public ILogger Logger { get; set; } command2
command3
/* </Command>
<Command> */
command1 // Run Orchard commands.
command2 public override void Execute(RecipeExecutionContext context) {
command3 var commands =
</Command> context.RecipeStep.Step.Value
*/ .Split(new[] {"\r\n", "\n"}, StringSplitOptions.RemoveEmptyEntries)
// run Orchard commands. .Select(commandEntry => commandEntry.Trim());
public void ExecuteRecipeStep(RecipeContext recipeContext) {
if (!String.Equals(recipeContext.RecipeStep.Name, "Command", StringComparison.OrdinalIgnoreCase)) { foreach (var command in commands) {
return; if (!String.IsNullOrEmpty(command)) {
} Logger.Information("Executing command: {0}", command);
try {
Logger.Information("Executing recipe step '{0}'; ExecutionId={1}", recipeContext.RecipeStep.Name, recipeContext.ExecutionId); var commandParameters = _commandParser.ParseCommandParameters(command);
var input = new StringReader("");
var commands = var output = new StringWriter();
recipeContext.RecipeStep.Step.Value _commandManager.Execute(new CommandParameters { Arguments = commandParameters.Arguments, Input = input, Output = output, Switches = commandParameters.Switches });
.Split(new[] {"\r\n", "\n"}, StringSplitOptions.RemoveEmptyEntries) }
.Select(commandEntry => commandEntry.Trim()); catch (Exception ex) {
Logger.Error(ex, "Error while executing command: {0}", command);
foreach (var command in commands) { throw;
if (!String.IsNullOrEmpty(command)) { }
Logger.Information("Executing command: {0}", command); }
try { }
var commandParameters = _commandParser.ParseCommandParameters(command); }
var input = new StringReader(""); }
var output = new StringWriter();
_commandManager.Execute(new CommandParameters { Arguments = commandParameters.Arguments, Input = input, Output = output, Switches = commandParameters.Switches }); // Utility class for parsing lines of commands.
} // Note: This lexer handles double quotes pretty harshly by design.
catch (Exception ex) { // In case you needed them in your arguments, hopefully single quotes work for you as a replacement on the receiving end.
Logger.Error(ex, "Error while executing command: {0}", command); class CommandParser {
throw; public CommandParameters ParseCommandParameters(string command) {
} var args = SplitArgs(command);
} var arguments = new List<string>();
} var result = new CommandParameters {
Switches = new Dictionary<string, string>()
recipeContext.Executed = true; };
Logger.Information("Finished executing recipe step '{0}'.", recipeContext.RecipeStep.Name);
} foreach (var arg in args) {
} if (arg.StartsWith("/")) {
//If arg is not empty and starts with '/'
// Utility class for parsing lines of commands.
// Note: This lexer handles double quotes pretty harshly by design. int index = arg.IndexOf(':');
// In case you needed them in your arguments, hopefully single quotes work for you as a replacement on the receiving end. var switchName = (index < 0 ? arg.Substring(1) : arg.Substring(1, index - 1));
class CommandParser { var switchValue = (index < 0 || index >= arg.Length ? string.Empty : arg.Substring(index + 1));
public CommandParameters ParseCommandParameters(string command) {
var args = SplitArgs(command); if (string.IsNullOrEmpty(switchName))
var arguments = new List<string>(); {
var result = new CommandParameters { throw new ArgumentException(string.Format("Invalid switch syntax: \"{0}\". Valid syntax is /<switchName>[:<switchValue>].", arg));
Switches = new Dictionary<string, string>() }
};
result.Switches.Add(switchName, switchValue);
foreach (var arg in args) { }
if (arg.StartsWith("/")) { else {
//If arg is not empty and starts with '/' arguments.Add(arg);
}
int index = arg.IndexOf(':'); }
var switchName = (index < 0 ? arg.Substring(1) : arg.Substring(1, index - 1));
var switchValue = (index < 0 || index >= arg.Length ? string.Empty : arg.Substring(index + 1)); result.Arguments = arguments;
return result;
if (string.IsNullOrEmpty(switchName)) }
{
throw new ArgumentException(string.Format("Invalid switch syntax: \"{0}\". Valid syntax is /<switchName>[:<switchValue>].", arg)); class State {
} private readonly string _commandLine;
private readonly StringBuilder _stringBuilder;
result.Switches.Add(switchName, switchValue); private readonly List<string> _arguments;
} private int _index;
else {
arguments.Add(arg); public State(string commandLine) {
} _commandLine = commandLine;
} _stringBuilder = new StringBuilder();
_arguments = new List<string>();
result.Arguments = arguments; }
return result;
} public StringBuilder StringBuilder { get { return _stringBuilder; } }
public bool EOF { get { return _index >= _commandLine.Length; } }
class State { public char Current { get { return _commandLine[_index]; } }
private readonly string _commandLine; public IEnumerable<string> Arguments { get { return _arguments; } }
private readonly StringBuilder _stringBuilder;
private readonly List<string> _arguments; public void AddArgument() {
private int _index; _arguments.Add(StringBuilder.ToString());
StringBuilder.Clear();
public State(string commandLine) { }
_commandLine = commandLine;
_stringBuilder = new StringBuilder(); public void AppendCurrent() {
_arguments = new List<string>(); StringBuilder.Append(Current);
} }
public StringBuilder StringBuilder { get { return _stringBuilder; } } public void Append(char ch) {
public bool EOF { get { return _index >= _commandLine.Length; } } StringBuilder.Append(ch);
public char Current { get { return _commandLine[_index]; } } }
public IEnumerable<string> Arguments { get { return _arguments; } }
public void MoveNext() {
public void AddArgument() { if (!EOF)
_arguments.Add(StringBuilder.ToString()); _index++;
StringBuilder.Clear(); }
} }
public void AppendCurrent() { /// <summary>
StringBuilder.Append(Current); /// Implement the same logic as found at
} /// http://msdn.microsoft.com/en-us/library/17w5ykft.aspx
/// The 3 special characters are quote, backslash and whitespaces, in order
public void Append(char ch) { /// of priority.
StringBuilder.Append(ch); /// The semantics of a quote is: whatever the state of the lexer, copy
} /// all characters verbatim until the next quote or EOF.
/// The semantics of backslash is: If the next character is a backslash or a quote,
public void MoveNext() { /// copy the next character. Otherwise, copy the backslash and the next character.
if (!EOF) /// The semantics of whitespace is: end the current argument and move on to the next one.
_index++; /// </summary>
} private static IEnumerable<string> SplitArgs(string commandLine) {
} var state = new State(commandLine);
while (!state.EOF) {
/// <summary> switch (state.Current) {
/// Implement the same logic as found at case '"':
/// http://msdn.microsoft.com/en-us/library/17w5ykft.aspx ProcessQuote(state);
/// The 3 special characters are quote, backslash and whitespaces, in order break;
/// of priority.
/// The semantics of a quote is: whatever the state of the lexer, copy case '\\':
/// all characters verbatim until the next quote or EOF. ProcessBackslash(state);
/// The semantics of backslash is: If the next character is a backslash or a quote, break;
/// copy the next character. Otherwise, copy the backslash and the next character.
/// The semantics of whitespace is: end the current argument and move on to the next one. case ' ':
/// </summary> case '\t':
private static IEnumerable<string> SplitArgs(string commandLine) { if (state.StringBuilder.Length > 0)
var state = new State(commandLine); state.AddArgument();
while (!state.EOF) { state.MoveNext();
switch (state.Current) { break;
case '"':
ProcessQuote(state); default:
break; state.AppendCurrent();
state.MoveNext();
case '\\': break;
ProcessBackslash(state); }
break; }
if (state.StringBuilder.Length > 0)
case ' ': state.AddArgument();
case '\t': return state.Arguments;
if (state.StringBuilder.Length > 0) }
state.AddArgument();
state.MoveNext(); private static void ProcessQuote(State state) {
break; state.MoveNext();
while (!state.EOF) {
default: if (state.Current == '"') {
state.AppendCurrent(); state.MoveNext();
state.MoveNext(); break;
break; }
} state.AppendCurrent();
} state.MoveNext();
if (state.StringBuilder.Length > 0) }
state.AddArgument();
return state.Arguments; state.AddArgument();
} }
private static void ProcessQuote(State state) { private static void ProcessBackslash(State state) {
state.MoveNext(); state.MoveNext();
while (!state.EOF) { if (state.EOF) {
if (state.Current == '"') { state.Append('\\');
state.MoveNext(); return;
break; }
}
state.AppendCurrent(); if (state.Current == '"') {
state.MoveNext(); state.Append('"');
} state.MoveNext();
}
state.AddArgument(); else {
} state.Append('\\');
state.AppendCurrent();
private static void ProcessBackslash(State state) { state.MoveNext();
state.MoveNext(); }
if (state.EOF) { }
state.Append('\\'); }
return;
}
if (state.Current == '"') {
state.Append('"');
state.MoveNext();
}
else {
state.Append('\\');
state.AppendCurrent();
state.MoveNext();
}
}
}
} }

View File

@@ -1,100 +1,86 @@
using System; using System;
using System.Xml; using System.Xml;
using Orchard.ContentManagement.MetaData; using Orchard.ContentManagement.MetaData;
using Orchard.ContentTypes.Events; using Orchard.ContentTypes.Events;
using Orchard.Localization; using Orchard.Logging;
using Orchard.Logging; using Orchard.Recipes.Services;
using Orchard.Recipes.Models;
using Orchard.Recipes.Services; namespace Orchard.Recipes.RecipeExecutionSteps {
public class ContentSchemaStep : RecipeExecutionStep {
namespace Orchard.Recipes.RecipeHandlers { private readonly IContentDefinitionManager _contentDefinitionManager;
public class MetadataRecipeHandler : IRecipeHandler { private readonly IContentDefinitionReader _contentDefinitionReader;
private readonly IContentDefinitionManager _contentDefinitionManager; private readonly IContentDefinitionEventHandler _contentDefinitonEventHandlers;
private readonly IContentDefinitionReader _contentDefinitionReader;
private readonly IContentDefinitionEventHandler _contentDefinitonEventHandlers; public override string Name { get { return "ContentSchema"; } }
public MetadataRecipeHandler( public ContentSchemaStep(
IContentDefinitionManager contentDefinitionManager, IContentDefinitionManager contentDefinitionManager,
IContentDefinitionReader contentDefinitionReader, IContentDefinitionReader contentDefinitionReader,
IContentDefinitionEventHandler contentDefinitonEventHandlers) { IContentDefinitionEventHandler contentDefinitonEventHandlers) {
_contentDefinitionManager = contentDefinitionManager; _contentDefinitionManager = contentDefinitionManager;
_contentDefinitionReader = contentDefinitionReader; _contentDefinitionReader = contentDefinitionReader;
_contentDefinitonEventHandlers = contentDefinitonEventHandlers; _contentDefinitonEventHandlers = contentDefinitonEventHandlers;
Logger = NullLogger.Instance; }
T = NullLocalizer.Instance;
} /*
<ContentDefinition>
public Localizer T { get; set; } <Types>
public ILogger Logger { get; set; } <Blog creatable="true">
<Body format="abodyformat"/>
/* </Blog>
<Metadata> </Types>
<Types> <Parts>
<Blog creatable="true"> </Parts>
<Body format="abodyformat"/> </ContentDefinition>
</Blog> */
</Types> // Set type settings and attach parts to types.
<Parts> // Create dynamic parts.
</Parts> public override void Execute(RecipeExecutionContext context) {
</Metadata> foreach (var metadataElement in context.RecipeStep.Step.Elements()) {
*/ Logger.Debug("Processing element '{0}'.", metadataElement.Name.LocalName);
// Set type settings and attach parts to types. switch (metadataElement.Name.LocalName) {
// Create dynamic parts. case "Types":
public void ExecuteRecipeStep(RecipeContext recipeContext) { foreach (var element in metadataElement.Elements()) {
if (!String.Equals(recipeContext.RecipeStep.Name, "Metadata", StringComparison.OrdinalIgnoreCase)) { var typeElement = element;
return; var typeName = XmlConvert.DecodeName(element.Name.LocalName);
}
Logger.Information("Importing content type '{0}'.", typeName);
Logger.Information("Executing recipe step '{0}'; ExecutionId={1}", recipeContext.RecipeStep.Name, recipeContext.ExecutionId); try {
_contentDefinitonEventHandlers.ContentTypeImporting(new ContentTypeImportingContext { ContentTypeDefinition = _contentDefinitionManager.GetTypeDefinition(typeName), ContentTypeName = typeName });
foreach (var metadataElement in recipeContext.RecipeStep.Step.Elements()) { _contentDefinitionManager.AlterTypeDefinition(typeName, alteration => _contentDefinitionReader.Merge(typeElement, alteration));
Logger.Debug("Processing element '{0}'.", metadataElement.Name.LocalName); _contentDefinitonEventHandlers.ContentTypeImported(new ContentTypeImportedContext { ContentTypeDefinition = _contentDefinitionManager.GetTypeDefinition(typeName) });
switch (metadataElement.Name.LocalName) { }
case "Types": catch (Exception ex) {
foreach (var element in metadataElement.Elements()) { Logger.Error(ex, "Error while importing content type '{0}'.", typeName);
var typeElement = element; throw;
var typeName = XmlConvert.DecodeName(element.Name.LocalName); }
}
Logger.Information("Importing content type '{0}'.", typeName); break;
try {
_contentDefinitonEventHandlers.ContentTypeImporting(new ContentTypeImportingContext { ContentTypeDefinition = _contentDefinitionManager.GetTypeDefinition(typeName), ContentTypeName = typeName }); case "Parts":
_contentDefinitionManager.AlterTypeDefinition(typeName, alteration => _contentDefinitionReader.Merge(typeElement, alteration)); foreach (var element in metadataElement.Elements()) {
_contentDefinitonEventHandlers.ContentTypeImported(new ContentTypeImportedContext { ContentTypeDefinition = _contentDefinitionManager.GetTypeDefinition(typeName) }); var partElement = element;
} var partName = XmlConvert.DecodeName(element.Name.LocalName);
catch (Exception ex) {
Logger.Error(ex, "Error while importing content type '{0}'.", typeName); Logger.Information("Importing content part '{0}'.", partName);
throw; try {
} _contentDefinitonEventHandlers.ContentPartImporting(new ContentPartImportingContext { ContentPartDefinition = _contentDefinitionManager.GetPartDefinition(partName), ContentPartName = partName });
} _contentDefinitionManager.AlterPartDefinition(partName, alteration => _contentDefinitionReader.Merge(partElement, alteration));
break; _contentDefinitonEventHandlers.ContentPartImported(new ContentPartImportedContext { ContentPartDefinition = _contentDefinitionManager.GetPartDefinition(partName)});
}
case "Parts": catch (Exception ex) {
foreach (var element in metadataElement.Elements()) { Logger.Error(ex, "Error while importing content part '{0}'.", partName);
var partElement = element; throw;
var partName = XmlConvert.DecodeName(element.Name.LocalName); }
}
Logger.Information("Importing content part '{0}'.", partName); break;
try {
_contentDefinitonEventHandlers.ContentPartImporting(new ContentPartImportingContext { ContentPartDefinition = _contentDefinitionManager.GetPartDefinition(partName), ContentPartName = partName }); default:
_contentDefinitionManager.AlterPartDefinition(partName, alteration => _contentDefinitionReader.Merge(partElement, alteration)); Logger.Warning("Unrecognized element '{0}' encountered; skipping", metadataElement.Name.LocalName);
_contentDefinitonEventHandlers.ContentPartImported(new ContentPartImportedContext { ContentPartDefinition = _contentDefinitionManager.GetPartDefinition(partName)}); break;
} }
catch (Exception ex) { }
Logger.Error(ex, "Error while importing content part '{0}'.", partName); }
throw; }
}
}
break;
default:
Logger.Warning("Unrecognized element '{0}' encountered; skipping", metadataElement.Name.LocalName);
break;
}
}
recipeContext.Executed = true;
Logger.Information("Finished executing recipe step '{0}'.", recipeContext.RecipeStep.Name);
}
}
} }

View File

@@ -1,120 +1,106 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Xml.Linq; using System.Xml.Linq;
using Orchard.ContentManagement; using Orchard.ContentManagement;
using Orchard.Data; using Orchard.Data;
using Orchard.Localization; using Orchard.Logging;
using Orchard.Logging; using Orchard.Recipes.Services;
using Orchard.Recipes.Models;
using Orchard.Recipes.Services; namespace Orchard.Recipes.RecipeExecutionSteps {
public class ContentStep : RecipeExecutionStep {
namespace Orchard.Recipes.RecipeHandlers { private readonly IOrchardServices _orchardServices;
public class DataRecipeHandler : IRecipeHandler { private readonly ITransactionManager _transactionManager;
private readonly IOrchardServices _orchardServices;
private readonly ITransactionManager _transactionManager; public ContentStep(IOrchardServices orchardServices, ITransactionManager transactionManager) {
_orchardServices = orchardServices;
public DataRecipeHandler(IOrchardServices orchardServices, ITransactionManager transactionManager) { _transactionManager = transactionManager;
_orchardServices = orchardServices; }
_transactionManager = transactionManager;
Logger = NullLogger.Instance; public override string Name { get { return "Content"; } }
T = NullLocalizer.Instance;
} // <Data />
// Import Data.
public Localizer T { get; set; } public override void Execute(RecipeExecutionContext context) {
public ILogger Logger { get; set; } var importContentSession = new ImportContentSession(_orchardServices.ContentManager);
// <Data /> // Populate local dictionary with elements and their ids.
// Import Data var elementDictionary = CreateElementDictionary(context.RecipeStep.Step);
public void ExecuteRecipeStep(RecipeContext recipeContext) {
if (!String.Equals(recipeContext.RecipeStep.Name, "Data", StringComparison.OrdinalIgnoreCase)) { // Populate import session with all identities to be imported.
return; foreach (var identity in elementDictionary.Keys) {
} importContentSession.Set(identity, elementDictionary[identity].Name.LocalName);
}
Logger.Information("Executing recipe step '{0}'; ExecutionId={1}", recipeContext.RecipeStep.Name, recipeContext.ExecutionId);
// Determine if the import is to be batched in multiple transactions.
var importContentSession = new ImportContentSession(_orchardServices.ContentManager); var startIndex = 0;
var batchSize = GetBatchSizeForDataStep(context.RecipeStep.Step);
// Populate local dictionary with elements and their ids Logger.Debug("Using batch size {0}.", batchSize);
var elementDictionary = CreateElementDictionary(recipeContext.RecipeStep.Step);
// Run the import.
//Populate import session with all identities to be imported try {
foreach (var identity in elementDictionary.Keys) { while (startIndex < elementDictionary.Count) {
importContentSession.Set(identity, elementDictionary[identity].Name.LocalName); Logger.Debug("Importing batch starting at index {0}.", startIndex);
} importContentSession.InitializeBatch(startIndex, batchSize);
//Determine if the import is to be batched in multiple transactions // The session determines which items are included in the current batch
var startIndex = 0; // so that dependencies can be managed within the same transaction.
int batchSize = GetBatchSizeForDataStep(recipeContext.RecipeStep.Step); var nextIdentity = importContentSession.GetNextInBatch();
Logger.Debug("Using batch size {0}.", batchSize); while (nextIdentity != null) {
var itemId = "";
//Run the import if (elementDictionary[nextIdentity.ToString()].HasAttributes) {
try { itemId = elementDictionary[nextIdentity.ToString()].FirstAttribute.Value;
while (startIndex < elementDictionary.Count) { }
Logger.Debug("Importing batch starting at index {0}.", startIndex); Logger.Information("Importing data item '{0}'.", itemId);
importContentSession.InitializeBatch(startIndex, batchSize); try {
_orchardServices.ContentManager.Import(
//the session determines which items are included in the current batch elementDictionary[nextIdentity.ToString()],
//so that dependencies can be managed within the same transaction importContentSession);
var nextIdentity = importContentSession.GetNextInBatch(); }
while (nextIdentity != null) { catch (Exception ex) {
var itemId = ""; Logger.Error(ex, "Error while importing data item '{0}'.", itemId);
if (elementDictionary[nextIdentity.ToString()].HasAttributes) { throw;
itemId = elementDictionary[nextIdentity.ToString()].FirstAttribute.Value; }
} nextIdentity = importContentSession.GetNextInBatch();
Logger.Information("Importing data item '{0}'.", itemId); }
try {
_orchardServices.ContentManager.Import( startIndex += batchSize;
elementDictionary[nextIdentity.ToString()],
importContentSession); // Create a new transaction for each batch.
} if (startIndex < elementDictionary.Count) {
catch (Exception ex) { _transactionManager.RequireNew();
Logger.Error(ex, "Error while importing data item '{0}'.", itemId); }
throw;
} Logger.Debug("Finished importing batch starting at index {0}.", startIndex);
nextIdentity = importContentSession.GetNextInBatch(); }
} }
catch (Exception) {
startIndex += batchSize; // Ensure a failed batch is rolled back.
_transactionManager.Cancel();
//Create a new transaction for each batch throw;
if (startIndex < elementDictionary.Count) { }
_transactionManager.RequireNew(); }
}
private Dictionary<string, XElement> CreateElementDictionary(XElement step) {
Logger.Debug("Finished importing batch starting at index {0}.", startIndex); var elementDictionary = new Dictionary<string, XElement>();
} foreach (var element in step.Elements()) {
} if (element.Attribute("Id") == null
catch (Exception) { || string.IsNullOrEmpty(element.Attribute("Id").Value))
//Ensure a failed batch is rolled back continue;
_transactionManager.Cancel();
throw; var identity = new ContentIdentity(element.Attribute("Id").Value).ToString();
} elementDictionary[identity] = element;
}
recipeContext.Executed = true; return elementDictionary;
Logger.Information("Finished executing recipe step '{0}'.", recipeContext.RecipeStep.Name); }
}
private int GetBatchSizeForDataStep(XElement step) {
private Dictionary<string, XElement> CreateElementDictionary(XElement step) { int batchSize;
var elementDictionary = new Dictionary<string, XElement>(); if (step.Attribute("BatchSize") == null ||
foreach (var element in step.Elements()) { !int.TryParse(step.Attribute("BatchSize").Value, out batchSize) ||
if (element.Attribute("Id") == null batchSize <= 0) {
|| string.IsNullOrEmpty(element.Attribute("Id").Value)) batchSize = int.MaxValue;
continue; }
return batchSize;
var identity = new ContentIdentity(element.Attribute("Id").Value).ToString(); }
elementDictionary[identity] = element; }
} }
return elementDictionary;
}
private int GetBatchSizeForDataStep(XElement step) {
int batchSize;
if (step.Attribute("BatchSize") == null ||
!int.TryParse(step.Attribute("BatchSize").Value, out batchSize) ||
batchSize <= 0) {
batchSize = int.MaxValue;
}
return batchSize;
}
}
}

View File

@@ -1,79 +1,65 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Orchard.Environment.Features; using Orchard.Environment.Features;
using Orchard.Localization; using Orchard.Logging;
using Orchard.Logging; using Orchard.Recipes.Services;
using Orchard.Recipes.Models;
using Orchard.Recipes.Services; namespace Orchard.Recipes.RecipeExecutionSteps {
public class FeatureStep : RecipeExecutionStep {
namespace Orchard.Recipes.RecipeHandlers { private readonly IFeatureManager _featureManager;
public class FeatureRecipeHandler : IRecipeHandler {
private readonly IFeatureManager _featureManager; public FeatureStep(IFeatureManager featureManager) {
_featureManager = featureManager;
public FeatureRecipeHandler(IFeatureManager featureManager) { }
_featureManager = featureManager;
Logger = NullLogger.Instance; public override string Name { get { return "Feature"; } }
T = NullLocalizer.Instance;
} // <Feature enable="f1,f2,f3" disable="f4" />
// Enable/Disable features.
public Localizer T { get; set; } public override void Execute(RecipeExecutionContext recipeContext) {
public ILogger Logger { get; set; } var featuresToEnable = new List<string>();
var featuresToDisable = new List<string>();
// <Feature enable="f1,f2,f3" disable="f4" /> foreach (var attribute in recipeContext.RecipeStep.Step.Attributes()) {
// Enable/Disable features. if (String.Equals(attribute.Name.LocalName, "disable", StringComparison.OrdinalIgnoreCase)) {
public void ExecuteRecipeStep(RecipeContext recipeContext) { featuresToDisable = ParseFeatures(attribute.Value);
if (!String.Equals(recipeContext.RecipeStep.Name, "Feature", StringComparison.OrdinalIgnoreCase)) { }
return; else if (String.Equals(attribute.Name.LocalName, "enable", StringComparison.OrdinalIgnoreCase)) {
} featuresToEnable = ParseFeatures(attribute.Value);
}
Logger.Information("Executing recipe step '{0}'; ExecutionId={1}", recipeContext.RecipeStep.Name, recipeContext.ExecutionId); else {
Logger.Warning("Unrecognized attribute '{0}' encountered; skipping", attribute.Name.LocalName);
var featuresToEnable = new List<string>(); }
var featuresToDisable = new List<string>(); }
foreach (var attribute in recipeContext.RecipeStep.Step.Attributes()) {
if (String.Equals(attribute.Name.LocalName, "disable", StringComparison.OrdinalIgnoreCase)) { var availableFeatures = _featureManager.GetAvailableFeatures().Select(x => x.Id).ToArray();
featuresToDisable = ParseFeatures(attribute.Value); foreach (var featureName in featuresToDisable) {
} if (!availableFeatures.Contains(featureName)) {
else if (String.Equals(attribute.Name.LocalName, "enable", StringComparison.OrdinalIgnoreCase)) { throw new InvalidOperationException(string.Format("Could not disable feature {0} because it was not found.", featureName));
featuresToEnable = ParseFeatures(attribute.Value); }
} }
else {
Logger.Warning("Unrecognized attribute '{0}' encountered; skipping", attribute.Name.LocalName); foreach (var featureName in featuresToEnable) {
} if (!availableFeatures.Contains(featureName)) {
} throw new InvalidOperationException(string.Format("Could not enable feature {0} because it was not found.", featureName));
}
var availableFeatures = _featureManager.GetAvailableFeatures().Select(x => x.Id).ToArray(); }
foreach (var featureName in featuresToDisable) {
if (!availableFeatures.Contains(featureName)) { if (featuresToDisable.Any()) {
throw new InvalidOperationException(string.Format("Could not disable feature {0} because it was not found.", featureName)); Logger.Information("Disabling features: {0}", String.Join(";", featuresToDisable));
} _featureManager.DisableFeatures(featuresToDisable, true);
} }
if (featuresToEnable.Any()) {
foreach (var featureName in featuresToEnable) { Logger.Information("Enabling features: {0}", String.Join(";", featuresToEnable));
if (!availableFeatures.Contains(featureName)) { _featureManager.EnableFeatures(featuresToEnable, true);
throw new InvalidOperationException(string.Format("Could not enable feature {0} because it was not found.", featureName)); }
} }
}
private static List<string> ParseFeatures(string csv) {
if (featuresToDisable.Any()) { return csv.Split(',')
Logger.Information("Disabling features: {0}", String.Join(";", featuresToDisable)); .Select(value => value.Trim())
_featureManager.DisableFeatures(featuresToDisable, true); .Where(sanitizedValue => !String.IsNullOrEmpty(sanitizedValue))
} .ToList();
if (featuresToEnable.Any()) { }
Logger.Information("Enabling features: {0}", String.Join(";", featuresToEnable)); }
_featureManager.EnableFeatures(featuresToEnable, true);
}
recipeContext.Executed = true;
Logger.Information("Finished executing recipe step '{0}'.", recipeContext.RecipeStep.Name);
}
private static List<string> ParseFeatures(string csv) {
return csv.Split(',')
.Select(value => value.Trim())
.Where(sanitizedValue => !String.IsNullOrEmpty(sanitizedValue))
.ToList();
}
}
} }

View File

@@ -1,80 +1,66 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Orchard.Data.Migration; using Orchard.Data.Migration;
using Orchard.Localization; using Orchard.Logging;
using Orchard.Logging; using Orchard.Recipes.Services;
using Orchard.Recipes.Models;
using Orchard.Recipes.Services; namespace Orchard.Recipes.RecipeExecutionSteps {
public class MigrationStep : RecipeExecutionStep {
namespace Orchard.Recipes.RecipeHandlers { private readonly IDataMigrationManager _dataMigrationManager;
public class MigrationRecipeHandler : IRecipeHandler {
private readonly IDataMigrationManager _dataMigrationManager; public MigrationStep(IDataMigrationManager dataMigrationManager) {
_dataMigrationManager = dataMigrationManager;
public MigrationRecipeHandler(IDataMigrationManager dataMigrationManager) { }
_dataMigrationManager = dataMigrationManager;
Logger = NullLogger.Instance; public override string Name { get { return "Migration"; } }
T = NullLocalizer.Instance;
} // <Migration features="f1, f2" />
// <Migration features="*" />
public Localizer T { get; set; } // Run migration for features.
public ILogger Logger { get; set; } public override void Execute(RecipeExecutionContext context) {
var runAll = false;
// <Migration features="f1, f2" /> var features = new List<string>();
// <Migration features="*" /> foreach (var attribute in context.RecipeStep.Step.Attributes()) {
// Run migration for features. if (String.Equals(attribute.Name.LocalName, "features", StringComparison.OrdinalIgnoreCase)) {
public void ExecuteRecipeStep(RecipeContext recipeContext) { features = ParseFeatures(attribute.Value);
if (!String.Equals(recipeContext.RecipeStep.Name, "Migration", StringComparison.OrdinalIgnoreCase)) { if (features.Contains("*"))
return; runAll = true;
} }
else {
Logger.Information("Executing recipe step '{0}'; ExecutionId={1}", recipeContext.RecipeStep.Name, recipeContext.ExecutionId); Logger.Warning("Unrecognized attribute '{0}' encountered; skipping.", attribute.Name.LocalName);
}
bool runAll = false; }
var features = new List<string>();
foreach (var attribute in recipeContext.RecipeStep.Step.Attributes()) { if (runAll) {
if (String.Equals(attribute.Name.LocalName, "features", StringComparison.OrdinalIgnoreCase)) { foreach (var feature in _dataMigrationManager.GetFeaturesThatNeedUpdate()) {
features = ParseFeatures(attribute.Value); Logger.Information("Updating feature '{0}'.", feature);
if (features.Contains("*")) try {
runAll = true; _dataMigrationManager.Update(feature);
} }
else { catch (Exception ex) {
Logger.Warning("Unrecognized attribute '{0}' encountered; skipping.", attribute.Name.LocalName); Logger.Error(ex, "Error while updating feature '{0}'", feature);
} throw;
} }
}
if (runAll) { }
foreach (var feature in _dataMigrationManager.GetFeaturesThatNeedUpdate()) { else {
Logger.Information("Updating feature '{0}'.", feature); Logger.Information("Updating features: {0}", String.Join(";", features));
try { try {
_dataMigrationManager.Update(feature); _dataMigrationManager.Update(features);
} }
catch (Exception ex) { catch (Exception ex) {
Logger.Error(ex, "Error while updating feature '{0}'", feature); Logger.Error(ex, "Error while updating features: {0}", String.Join(";", features));
throw; throw;
} }
} }
} }
else {
Logger.Information("Updating features: {0}", String.Join(";", features)); private static List<string> ParseFeatures(string csv) {
try { return csv.Split(',')
_dataMigrationManager.Update(features); .Select(value => value.Trim())
} .Where(sanitizedValue => !String.IsNullOrEmpty(sanitizedValue))
catch (Exception ex) { .ToList();
Logger.Error(ex, "Error while updating features: {0}", String.Join(";", features)); }
throw; }
}
}
recipeContext.Executed = true;
Logger.Information("Finished executing recipe step '{0}'.", recipeContext.RecipeStep.Name);
}
private static List<string> ParseFeatures(string csv) {
return csv.Split(',')
.Select(value => value.Trim())
.Where(sanitizedValue => !String.IsNullOrEmpty(sanitizedValue))
.ToList();
}
}
} }

View File

@@ -1,111 +1,97 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Web.Hosting; using System.Web.Hosting;
using Orchard.Environment.Extensions; using Orchard.Environment.Extensions;
using Orchard.Environment.Extensions.Models; using Orchard.Environment.Extensions.Models;
using Orchard.Localization; using Orchard.Logging;
using Orchard.Logging; using Orchard.Packaging.Models;
using Orchard.Packaging.Models; using Orchard.Packaging.Services;
using Orchard.Packaging.Services; using Orchard.Recipes.Services;
using Orchard.Recipes.Models;
using Orchard.Recipes.Services; namespace Orchard.Recipes.RecipeExecutionSteps {
public class ModuleStep : RecipeExecutionStep {
namespace Orchard.Recipes.RecipeHandlers { private readonly IPackagingSourceManager _packagingSourceManager;
public class ModuleRecipeHandler : IRecipeHandler { private readonly IPackageManager _packageManager;
private readonly IPackagingSourceManager _packagingSourceManager; private readonly IExtensionManager _extensionManager;
private readonly IPackageManager _packageManager;
private readonly IExtensionManager _extensionManager; public ModuleStep(
IPackagingSourceManager packagingSourceManager,
public ModuleRecipeHandler( IPackageManager packageManager,
IPackagingSourceManager packagingSourceManager, IExtensionManager extensionManager) {
IPackageManager packageManager,
IExtensionManager extensionManager) { _packagingSourceManager = packagingSourceManager;
_packagingSourceManager = packagingSourceManager; _packageManager = packageManager;
_packageManager = packageManager; _extensionManager = extensionManager;
_extensionManager = extensionManager; }
Logger = NullLogger.Instance; public override string Name { get { return "Module"; } }
T = NullLocalizer.Instance;
} // <Module packageId="module1" [repository="somerepo"] version="1.1" />
// Install modules from feed.
public Localizer T { get; set; } public override void Execute(RecipeExecutionContext context) {
public ILogger Logger { get; set; } string packageId = null, version = null, repository = null;
foreach (var attribute in context.RecipeStep.Step.Attributes()) {
// <Module packageId="module1" [repository="somerepo"] version="1.1" /> if (String.Equals(attribute.Name.LocalName, "packageId", StringComparison.OrdinalIgnoreCase)) {
// install modules from feed. packageId = attribute.Value;
public void ExecuteRecipeStep(RecipeContext recipeContext) { }
if (!String.Equals(recipeContext.RecipeStep.Name, "Module", StringComparison.OrdinalIgnoreCase)) { else if (String.Equals(attribute.Name.LocalName, "version", StringComparison.OrdinalIgnoreCase)) {
return; version = attribute.Value;
} }
else if (String.Equals(attribute.Name.LocalName, "repository", StringComparison.OrdinalIgnoreCase)) {
Logger.Information("Executing recipe step '{0}'; ExecutionId={1}", recipeContext.RecipeStep.Name, recipeContext.ExecutionId); repository = attribute.Value;
}
string packageId = null, version = null, repository = null; else {
foreach (var attribute in recipeContext.RecipeStep.Step.Attributes()) { throw new InvalidOperationException(String.Format("Unrecognized attribute {0} encountered in step Module.", attribute.Name.LocalName));
if (String.Equals(attribute.Name.LocalName, "packageId", StringComparison.OrdinalIgnoreCase)) { }
packageId = attribute.Value; }
}
else if (String.Equals(attribute.Name.LocalName, "version", StringComparison.OrdinalIgnoreCase)) { if (packageId == null) {
version = attribute.Value; throw new InvalidOperationException("PackageId is required in a Module declaration in a recipe file.");
} }
else if (String.Equals(attribute.Name.LocalName, "repository", StringComparison.OrdinalIgnoreCase)) {
repository = attribute.Value; // download and install module from the orchard feed or a custom feed if repository is specified.
} var enforceVersion = version != null;
else { var installed = false;
throw new InvalidOperationException(string.Format("Unrecognized attribute {0} encountered in step Module.", attribute.Name.LocalName)); PackagingEntry packagingEntry = null;
}
} var packagingSource = _packagingSourceManager.GetSources().FirstOrDefault();
if (repository != null) {
if (packageId == null) { packagingSource = new PackagingSource {FeedTitle = repository, FeedUrl = repository};
throw new InvalidOperationException("PackageId is required in a Module declaration in a recipe file."); }
}
if (enforceVersion) {
// download and install module from the orchard feed or a custom feed if repository is specified. packagingEntry = _packagingSourceManager.GetExtensionList(false, packagingSource,
bool enforceVersion = version != null; packages => packages.Where(package =>
bool installed = false; package.PackageType.Equals(DefaultExtensionTypes.Module) &&
PackagingEntry packagingEntry = null; package.Id.Equals(packageId, StringComparison.OrdinalIgnoreCase) &&
package.Version.Equals(version, StringComparison.OrdinalIgnoreCase))).FirstOrDefault();
var packagingSource = _packagingSourceManager.GetSources().FirstOrDefault(); }
if (repository != null) { else {
packagingSource = new PackagingSource {FeedTitle = repository, FeedUrl = repository}; packagingEntry = _packagingSourceManager.GetExtensionList(false, packagingSource,
} packages => packages.Where(package =>
package.PackageType.Equals(DefaultExtensionTypes.Module) &&
if (enforceVersion) { package.Id.Equals(packageId, StringComparison.OrdinalIgnoreCase) &&
packagingEntry = _packagingSourceManager.GetExtensionList(false, packagingSource, package.IsLatestVersion)).FirstOrDefault();
packages => packages.Where(package => }
package.PackageType.Equals(DefaultExtensionTypes.Module) &&
package.Id.Equals(packageId, StringComparison.OrdinalIgnoreCase) && if (packagingEntry != null) {
package.Version.Equals(version, StringComparison.OrdinalIgnoreCase))).FirstOrDefault(); if (!ModuleAlreadyInstalled(packagingEntry.PackageId)) {
} Logger.Information("Installing module {0}.", packagingEntry.Title);
else { _packageManager.Install(packagingEntry.PackageId, packagingEntry.Version, packagingSource.FeedUrl, HostingEnvironment.MapPath("~/"));
packagingEntry = _packagingSourceManager.GetExtensionList(false, packagingSource, }
packages => packages.Where(package => installed = true;
package.PackageType.Equals(DefaultExtensionTypes.Module) && }
package.Id.Equals(packageId, StringComparison.OrdinalIgnoreCase) &&
package.IsLatestVersion)).FirstOrDefault(); if (!installed) {
} throw new InvalidOperationException(String.Format("Module {0} was not found in the specified location.", packageId));
}
if (packagingEntry != null) { }
if (!ModuleAlreadyInstalled(packagingEntry.PackageId)) {
Logger.Information("Installing module {0}.", packagingEntry.Title); private bool ModuleAlreadyInstalled(string packageId) {
_packageManager.Install(packagingEntry.PackageId, packagingEntry.Version, packagingSource.FeedUrl, HostingEnvironment.MapPath("~/")); return _extensionManager.AvailableExtensions().Where(m => DefaultExtensionTypes.IsModule(m.ExtensionType))
} .Any(module => module.Id.Equals(
installed = true; packageId.Substring(PackagingSourceManager.GetExtensionPrefix(DefaultExtensionTypes.Module).Length),
} StringComparison.OrdinalIgnoreCase));
}
if (!installed) { }
throw new InvalidOperationException(string.Format("Module {0} was not found in the specified location.", packageId));
}
recipeContext.Executed = true;
Logger.Information("Finished executing recipe step '{0}'.", recipeContext.RecipeStep.Name);
}
private bool ModuleAlreadyInstalled(string packageId) {
return _extensionManager.AvailableExtensions().Where(m => DefaultExtensionTypes.IsModule(m.ExtensionType))
.Any(module => module.Id.Equals(
packageId.Substring(PackagingSourceManager.GetExtensionPrefix(DefaultExtensionTypes.Module).Length),
StringComparison.OrdinalIgnoreCase));
}
}
} }

View File

@@ -1,101 +1,88 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Xml.Linq; using System.Xml.Linq;
using Orchard.ContentManagement; using Orchard.ContentManagement;
using Orchard.ContentManagement.Handlers; using Orchard.ContentManagement.Handlers;
using Orchard.Localization; using Orchard.Localization;
using Orchard.Logging; using Orchard.Logging;
using Orchard.Recipes.Models; using Orchard.Recipes.Models;
using Orchard.Recipes.Services; using Orchard.Recipes.Services;
using Orchard.Settings; using Orchard.Settings;
namespace Orchard.Recipes.RecipeHandlers { namespace Orchard.Recipes.RecipeExecutionSteps {
public class SettingsRecipeHandler : IRecipeHandler { public class SettingsStep : RecipeExecutionStep {
private readonly ISiteService _siteService; private readonly ISiteService _siteService;
private readonly IContentManager _contentManager; private readonly IContentManager _contentManager;
private readonly Lazy<IEnumerable<IContentHandler>> _handlers; private readonly Lazy<IEnumerable<IContentHandler>> _handlers;
public SettingsRecipeHandler(ISiteService siteService, IContentManager contentManager, Lazy<IEnumerable<IContentHandler>> handlers) { public SettingsStep(ISiteService siteService, IContentManager contentManager, Lazy<IEnumerable<IContentHandler>> handlers) {
_siteService = siteService; _siteService = siteService;
_contentManager = contentManager; _contentManager = contentManager;
_handlers = handlers; _handlers = handlers;
Logger = NullLogger.Instance; }
T = NullLocalizer.Instance;
} public override string Name { get { return "Settings"; } }
private IEnumerable<IContentHandler> Handlers { get { return _handlers.Value; } }
public Localizer T { get; set; }
public ILogger Logger { get; set; } /*
private IEnumerable<IContentHandler> Handlers { get { return _handlers.Value; } } <Settings>
<SiteSettingsPart PageSize="30" />
/* <CommentSettingsPart ModerateComments="true" />
<Settings> </Settings>
<SiteSettingsPart PageSize="30" /> */
<CommentSettingsPart ModerateComments="true" /> // Set site and part settings.
</Settings> public override void Execute(RecipeExecutionContext context) {
*/ var siteContentItem = _siteService.GetSiteSettings().ContentItem;
// Set site and part settings. var importContentSession = new ImportContentSession(_contentManager);
public void ExecuteRecipeStep(RecipeContext recipeContext) { var importContentContext = new ImportContentContext(siteContentItem, context.RecipeStep.Step, importContentSession);
if (!String.Equals(recipeContext.RecipeStep.Name, "Settings", StringComparison.OrdinalIgnoreCase)) {
return; foreach (var contentHandler in Handlers) {
} contentHandler.Importing(importContentContext);
}
Logger.Information("Executing recipe step '{0}'; ExecutionId={1}", recipeContext.RecipeStep.Name, recipeContext.ExecutionId);
foreach (var contentPart in siteContentItem.Parts) {
var siteContentItem = _siteService.GetSiteSettings().ContentItem; var partElement = importContentContext.Data.Element(contentPart.PartDefinition.Name);
if (partElement == null) {
var importContentSession = new ImportContentSession(_contentManager); continue;
}
var context = new ImportContentContext(siteContentItem, recipeContext.RecipeStep.Step, importContentSession);
foreach (var contentHandler in Handlers) { Logger.Information("Importing settings part '{0}'.", contentPart.PartDefinition.Name);
contentHandler.Importing(context); try {
} ImportSettingPart(contentPart, partElement);
}
foreach (var contentPart in siteContentItem.Parts) { catch (Exception ex) {
var partElement = context.Data.Element(contentPart.PartDefinition.Name); Logger.Error(ex, "Error while importing settings part '{0}'.", contentPart.PartDefinition.Name);
if (partElement == null) { throw;
continue; }
} }
Logger.Information("Importing settings part '{0}'.", contentPart.PartDefinition.Name); foreach (var contentHandler in Handlers) {
try { contentHandler.Imported(importContentContext);
ImportSettingPart(contentPart, partElement); }
} }
catch (Exception ex) {
Logger.Error(ex, "Error while importing settings part '{0}'.", contentPart.PartDefinition.Name); private void ImportSettingPart(ContentPart sitePart, XElement element) {
throw;
} foreach (var attribute in element.Attributes()) {
} var attributeName = attribute.Name.LocalName;
var attributeValue = attribute.Value;
foreach (var contentHandler in Handlers) {
contentHandler.Imported(context); var property = sitePart.GetType().GetProperty(attributeName);
} if (property == null) {
continue;
recipeContext.Executed = true; }
Logger.Information("Finished executing recipe step '{0}'.", recipeContext.RecipeStep.Name);
} var propertyType = property.PropertyType;
if (propertyType == typeof(string)) {
private void ImportSettingPart(ContentPart sitePart, XElement element) { property.SetValue(sitePart, attributeValue, null);
}
foreach (var attribute in element.Attributes()) { else if (propertyType == typeof(bool)) {
var attributeName = attribute.Name.LocalName; property.SetValue(sitePart, Boolean.Parse(attributeValue), null);
var attributeValue = attribute.Value; }
else if (propertyType == typeof(int)) {
var property = sitePart.GetType().GetProperty(attributeName); property.SetValue(sitePart, Int32.Parse(attributeValue), null);
if (property == null) { }
continue; }
} }
}
var propertyType = property.PropertyType; }
if (propertyType == typeof(string)) {
property.SetValue(sitePart, attributeValue, null);
}
else if (propertyType == typeof(bool)) {
property.SetValue(sitePart, Boolean.Parse(attributeValue), null);
}
else if (propertyType == typeof(int)) {
property.SetValue(sitePart, Int32.Parse(attributeValue), null);
}
}
}
}
}

View File

@@ -1,138 +1,123 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Web.Hosting; using System.Web.Hosting;
using Orchard.Environment.Extensions; using Orchard.Environment.Extensions;
using Orchard.Environment.Extensions.Models; using Orchard.Environment.Extensions.Models;
using Orchard.Localization; using Orchard.Logging;
using Orchard.Logging; using Orchard.Packaging.Models;
using Orchard.Packaging.Models; using Orchard.Packaging.Services;
using Orchard.Packaging.Services; using Orchard.Recipes.Services;
using Orchard.Recipes.Models; using Orchard.Themes.Services;
using Orchard.Recipes.Services;
using Orchard.Themes.Services; namespace Orchard.Recipes.RecipeExecutionSteps {
public class ThemeStep : RecipeExecutionStep {
namespace Orchard.Recipes.RecipeHandlers { private readonly IPackagingSourceManager _packagingSourceManager;
public class ThemeRecipeHandler : IRecipeHandler { private readonly IPackageManager _packageManager;
private readonly IPackagingSourceManager _packagingSourceManager; private readonly IExtensionManager _extensionManager;
private readonly IPackageManager _packageManager; private readonly IThemeService _themeService;
private readonly IExtensionManager _extensionManager; private readonly ISiteThemeService _siteThemeService;
private readonly IThemeService _themeService;
private readonly ISiteThemeService _siteThemeService; public ThemeStep(
IPackagingSourceManager packagingSourceManager,
public ThemeRecipeHandler( IPackageManager packageManager,
IPackagingSourceManager packagingSourceManager, IExtensionManager extensionManager,
IPackageManager packageManager, IThemeService themeService,
IExtensionManager extensionManager, ISiteThemeService siteThemeService) {
IThemeService themeService,
ISiteThemeService siteThemeService) { _packagingSourceManager = packagingSourceManager;
_packageManager = packageManager;
_packagingSourceManager = packagingSourceManager; _extensionManager = extensionManager;
_packageManager = packageManager; _themeService = themeService;
_extensionManager = extensionManager; _siteThemeService = siteThemeService;
_themeService = themeService; }
_siteThemeService = siteThemeService;
public override string Name { get { return "Theme"; } }
Logger = NullLogger.Instance;
T = NullLocalizer.Instance; // <Theme packageId="theme1" repository="somethemerepo" version="1.1" enable="true" current="true" />
} // Install themes from feed.
public override void Execute(RecipeExecutionContext context) {
public Localizer T { get; set; } bool enable = false, current = false;
public ILogger Logger { get; set; } string packageId = null, version = null, repository = null;
// <Theme packageId="theme1" repository="somethemerepo" version="1.1" enable="true" current="true" /> foreach (var attribute in context.RecipeStep.Step.Attributes()) {
// install themes from feed. if (String.Equals(attribute.Name.LocalName, "enable", StringComparison.OrdinalIgnoreCase)) {
public void ExecuteRecipeStep(RecipeContext recipeContext) { enable = Boolean.Parse(attribute.Value);
if (!String.Equals(recipeContext.RecipeStep.Name, "Theme", StringComparison.OrdinalIgnoreCase)) { }
return; else if (String.Equals(attribute.Name.LocalName, "current", StringComparison.OrdinalIgnoreCase)) {
} current = Boolean.Parse(attribute.Value);
}
Logger.Information("Executing recipe step '{0}'; ExecutionId={1}", recipeContext.RecipeStep.Name, recipeContext.ExecutionId); else if (String.Equals(attribute.Name.LocalName, "packageId", StringComparison.OrdinalIgnoreCase)) {
packageId = attribute.Value;
bool enable = false, current = false; }
string packageId = null, version = null, repository = null; else if (String.Equals(attribute.Name.LocalName, "version", StringComparison.OrdinalIgnoreCase)) {
version = attribute.Value;
foreach (var attribute in recipeContext.RecipeStep.Step.Attributes()) { }
if (String.Equals(attribute.Name.LocalName, "enable", StringComparison.OrdinalIgnoreCase)) { else if (String.Equals(attribute.Name.LocalName, "repository", StringComparison.OrdinalIgnoreCase)) {
enable = Boolean.Parse(attribute.Value); repository = attribute.Value;
} }
else if (String.Equals(attribute.Name.LocalName, "current", StringComparison.OrdinalIgnoreCase)) { else {
current = Boolean.Parse(attribute.Value); Logger.Warning("Unrecognized attribute '{0}' encountered; skipping.", attribute.Name.LocalName);
} }
else if (String.Equals(attribute.Name.LocalName, "packageId", StringComparison.OrdinalIgnoreCase)) { }
packageId = attribute.Value;
} if (packageId == null) {
else if (String.Equals(attribute.Name.LocalName, "version", StringComparison.OrdinalIgnoreCase)) { throw new InvalidOperationException("The PackageId attribute is required on a Theme declaration in a recipe file.");
version = attribute.Value; }
}
else if (String.Equals(attribute.Name.LocalName, "repository", StringComparison.OrdinalIgnoreCase)) { // Download and install theme from the orchard feed or a custom feed if repository is specified.
repository = attribute.Value; var enforceVersion = version != null;
} var installed = false;
else { PackagingEntry packagingEntry = null;
Logger.Warning("Unrecognized attribute '{0}' encountered; skipping.", attribute.Name.LocalName);
} var packagingSource = _packagingSourceManager.GetSources().FirstOrDefault();
} if (repository != null) {
packagingSource = new PackagingSource { FeedTitle = repository, FeedUrl = repository };
if (packageId == null) { }
throw new InvalidOperationException("The PackageId attribute is required on a Theme declaration in a recipe file.");
} if (enforceVersion) {
packagingEntry = _packagingSourceManager.GetExtensionList(false, packagingSource,
// download and install theme from the orchard feed or a custom feed if repository is specified. packages => packages.Where(package =>
bool enforceVersion = version != null; package.PackageType.Equals(DefaultExtensionTypes.Theme) &&
bool installed = false; package.Id.Equals(packageId, StringComparison.OrdinalIgnoreCase) &&
PackagingEntry packagingEntry = null; package.Version.Equals(version, StringComparison.OrdinalIgnoreCase))).FirstOrDefault();
}
var packagingSource = _packagingSourceManager.GetSources().FirstOrDefault(); else {
if (repository != null) { packagingEntry = _packagingSourceManager.GetExtensionList(false, packagingSource,
packagingSource = new PackagingSource { FeedTitle = repository, FeedUrl = repository }; packages => packages.Where(package =>
} package.PackageType.Equals(DefaultExtensionTypes.Theme) &&
package.Id.Equals(packageId, StringComparison.OrdinalIgnoreCase) &&
if (enforceVersion) { package.IsLatestVersion)).FirstOrDefault();
packagingEntry = _packagingSourceManager.GetExtensionList(false, packagingSource, }
packages => packages.Where(package =>
package.PackageType.Equals(DefaultExtensionTypes.Theme) && if (packagingEntry != null) {
package.Id.Equals(packageId, StringComparison.OrdinalIgnoreCase) && if (!ThemeAlreadyInstalled(packagingEntry.PackageId)) {
package.Version.Equals(version, StringComparison.OrdinalIgnoreCase))).FirstOrDefault(); Logger.Information("Installing theme package '{0}'.", packagingEntry.PackageId);
} _packageManager.Install(packagingEntry.PackageId, packagingEntry.Version, packagingSource.FeedUrl, HostingEnvironment.MapPath("~/"));
else { }
packagingEntry = _packagingSourceManager.GetExtensionList(false, packagingSource, if (current) {
packages => packages.Where(package => Logger.Information("Enabling theme '{0}'.", packagingEntry.Title);
package.PackageType.Equals(DefaultExtensionTypes.Theme) && _themeService.EnableThemeFeatures(packagingEntry.Title);
package.Id.Equals(packageId, StringComparison.OrdinalIgnoreCase) && Logger.Information("Setting theme '{0}' as the site theme.", packagingEntry.Title);
package.IsLatestVersion)).FirstOrDefault(); _siteThemeService.SetSiteTheme(packagingEntry.Title);
} }
else if (enable) {
if (packagingEntry != null) { Logger.Information("Enabling theme '{0}'.", packagingEntry.Title);
if (!ThemeAlreadyInstalled(packagingEntry.PackageId)) { _themeService.EnableThemeFeatures(packagingEntry.Title);
Logger.Information("Installing theme package '{0}'.", packagingEntry.PackageId); }
_packageManager.Install(packagingEntry.PackageId, packagingEntry.Version, packagingSource.FeedUrl, HostingEnvironment.MapPath("~/"));
} installed = true;
if (current) { }
Logger.Information("Enabling theme '{0}'.", packagingEntry.Title);
_themeService.EnableThemeFeatures(packagingEntry.Title); if (!installed) {
Logger.Information("Setting theme '{0}' as the site theme.", packagingEntry.Title); throw new InvalidOperationException(String.Format("Theme '{0}' was not found in the specified location.", packageId));
_siteThemeService.SetSiteTheme(packagingEntry.Title); }
} }
else if (enable) {
Logger.Information("Enabling theme '{0}'.", packagingEntry.Title); private bool ThemeAlreadyInstalled(string packageId) {
_themeService.EnableThemeFeatures(packagingEntry.Title); return _extensionManager.AvailableExtensions().Where(t => DefaultExtensionTypes.IsTheme(t.ExtensionType))
} .Any(theme => theme.Id.Equals(
packageId.Substring(PackagingSourceManager.GetExtensionPrefix(DefaultExtensionTypes.Theme).Length),
installed = true; StringComparison.OrdinalIgnoreCase));
} }
}
if (!installed) {
throw new InvalidOperationException(string.Format("Theme '{0}' was not found in the specified location.", packageId));
}
recipeContext.Executed = true;
Logger.Information("Finished executing recipe step '{0}'.", recipeContext.RecipeStep.Name);
}
private bool ThemeAlreadyInstalled(string packageId) {
return _extensionManager.AvailableExtensions().Where(t => DefaultExtensionTypes.IsTheme(t.ExtensionType))
.Any(theme => theme.Id.Equals(
packageId.Substring(PackagingSourceManager.GetExtensionPrefix(DefaultExtensionTypes.Theme).Length),
StringComparison.OrdinalIgnoreCase));
}
}
} }

View File

@@ -0,0 +1,29 @@
using System.Collections.Generic;
using System.Linq;
using Orchard.Logging;
using Orchard.Recipes.Models;
using Orchard.Recipes.Services;
namespace Orchard.Recipes.RecipeHandlers {
/// <summary>
/// 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;
}
public void ExecuteRecipeStep(RecipeContext recipeContext) {
var executionStep = _recipeExecutionSteps.FirstOrDefault(x => x.Name == recipeContext.RecipeStep.Name);
var recipeExecutionContext = new RecipeExecutionContext {ExecutionId = recipeContext.ExecutionId, RecipeStep = recipeContext.RecipeStep};
if (executionStep != null) {
Logger.Information("Executing recipe step '{0}'; ExecutionId={1}", recipeContext.RecipeStep.Name, recipeContext.ExecutionId);
executionStep.Execute(recipeExecutionContext);
Logger.Information("Finished executing recipe step '{0}'.", recipeContext.RecipeStep.Name);
recipeContext.Executed = true;
}
}
}
}

View File

@@ -0,0 +1,6 @@
namespace Orchard.Recipes.Services {
public interface IRecipeExecutionStep : IDependency {
string Name { get; }
void Execute(RecipeExecutionContext context);
}
}

View File

@@ -0,0 +1,8 @@
using Orchard.Recipes.Models;
namespace Orchard.Recipes.Services {
public class RecipeExecutionContext {
public string ExecutionId { get; set; }
public RecipeStep RecipeStep { get; set; }
}
}

View File

@@ -0,0 +1,6 @@
namespace Orchard.Recipes.Services {
public abstract class RecipeExecutionStep : Component, IRecipeExecutionStep {
public abstract string Name { get; }
public abstract void Execute(RecipeExecutionContext context);
}
}

View File

@@ -17,6 +17,7 @@ namespace Orchard.Recipes.Services {
IRecipeScheduler recipeScheduler, IRecipeScheduler recipeScheduler,
IRecipeExecuteEventHandler recipeExecuteEventHandler, IRecipeExecuteEventHandler recipeExecuteEventHandler,
IRepository<RecipeStepResultRecord> recipeStepResultRecordRepository) { IRepository<RecipeStepResultRecord> recipeStepResultRecordRepository) {
_recipeStepQueue = recipeStepQueue; _recipeStepQueue = recipeStepQueue;
_recipeScheduler = recipeScheduler; _recipeScheduler = recipeScheduler;
_recipeExecuteEventHandler = recipeExecuteEventHandler; _recipeExecuteEventHandler = recipeExecuteEventHandler;

View File

@@ -2,13 +2,12 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Orchard.Data; using Orchard.Data;
using Orchard.Localization;
using Orchard.Logging; using Orchard.Logging;
using Orchard.Recipes.Events; using Orchard.Recipes.Events;
using Orchard.Recipes.Models; using Orchard.Recipes.Models;
namespace Orchard.Recipes.Services { namespace Orchard.Recipes.Services {
public class RecipeStepExecutor : IRecipeStepExecutor { public class RecipeStepExecutor : Component, IRecipeStepExecutor {
private readonly IRecipeStepQueue _recipeStepQueue; private readonly IRecipeStepQueue _recipeStepQueue;
private readonly IEnumerable<IRecipeHandler> _recipeHandlers; private readonly IEnumerable<IRecipeHandler> _recipeHandlers;
private readonly IRecipeExecuteEventHandler _recipeExecuteEventHandler; private readonly IRecipeExecuteEventHandler _recipeExecuteEventHandler;
@@ -19,18 +18,13 @@ namespace Orchard.Recipes.Services {
IEnumerable<IRecipeHandler> recipeHandlers, IEnumerable<IRecipeHandler> recipeHandlers,
IRecipeExecuteEventHandler recipeExecuteEventHandler, IRecipeExecuteEventHandler recipeExecuteEventHandler,
IRepository<RecipeStepResultRecord> recipeStepResultRecordRepository) { IRepository<RecipeStepResultRecord> recipeStepResultRecordRepository) {
_recipeStepQueue = recipeStepQueue; _recipeStepQueue = recipeStepQueue;
_recipeHandlers = recipeHandlers; _recipeHandlers = recipeHandlers;
_recipeExecuteEventHandler = recipeExecuteEventHandler; _recipeExecuteEventHandler = recipeExecuteEventHandler;
_recipeStepResultRecordRepository = recipeStepResultRecordRepository; _recipeStepResultRecordRepository = recipeStepResultRecordRepository;
Logger = NullLogger.Instance;
T = NullLocalizer.Instance;
} }
public Localizer T { get; set; }
public ILogger Logger { get; set; }
public bool ExecuteNextStep(string executionId) { public bool ExecuteNextStep(string executionId) {
var nextRecipeStep = _recipeStepQueue.Dequeue(executionId); var nextRecipeStep = _recipeStepQueue.Dequeue(executionId);
if (nextRecipeStep == null) { if (nextRecipeStep == null) {
@@ -45,9 +39,11 @@ namespace Orchard.Recipes.Services {
try { try {
_recipeExecuteEventHandler.RecipeStepExecuting(executionId, recipeContext); _recipeExecuteEventHandler.RecipeStepExecuting(executionId, recipeContext);
foreach (var recipeHandler in _recipeHandlers) { foreach (var recipeHandler in _recipeHandlers) {
recipeHandler.ExecuteRecipeStep(recipeContext); recipeHandler.ExecuteRecipeStep(recipeContext);
} }
UpdateStepResultRecord(executionId, nextRecipeStep.Name, isSuccessful: true); UpdateStepResultRecord(executionId, nextRecipeStep.Name, isSuccessful: true);
_recipeExecuteEventHandler.RecipeStepExecuted(executionId, recipeContext); _recipeExecuteEventHandler.RecipeStepExecuted(executionId, recipeContext);
} }