From d428ebc2f85944534cf9ee53fe18633b6b239aa5 Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Mon, 5 Jul 2010 13:35:50 -0700 Subject: [PATCH 1/6] Data migration for developers - NHibernate auto-update is explicitly run by the user (dev) through a DevTool Controller Action or Command - Generate the create method from the nhib schema --HG-- branch : dev --- ...TraceEnabledDataServicesProviderFactory.cs | 2 +- .../Builders/SessionFactoryBuilderTests.cs | 8 +- .../DataMigration/DataMigrationTests.cs | 1 - .../Commands/ScaffoldingCommands.cs | 57 ++++++++++- .../Controllers/DataMigrationController.cs | 23 +++++ .../Orchard.DevTools/Orchard.DevTools.csproj | 5 + .../ScaffoldingTemplates/DataMigration.txt | 13 +++ .../Services/ScaffoldingCommandInterpreter.cs | 78 +++++++++++++++ .../ViewModels/DataMigrationIndexViewModel.cs | 6 ++ .../Views/DataMigration/Index.aspx | 9 ++ .../Commands/IndexingCommands.cs | 2 - .../DataMigrations/IndexingDataMigration.cs | 1 - .../Orchard.Indexing/Orchard.Indexing.csproj | 2 +- .../Commands/DataMigrationCommands.cs | 61 ++++++++++-- .../Data/Migration/DataMigrationManager.cs | 16 ++- .../DefaultDataMigrationGenerator.cs | 14 --- .../Generator/ISchemaCommandGenerator.cs | 24 +++++ .../Generator/SchemaCommandGenerator.cs | 97 +++++++++++++++++++ .../Data/Migration/IDataMigrationGenerator.cs | 11 --- .../AbstractDataMigrationInterpreter.cs | 41 ++++++++ .../DefaultDataMigrationInterpreter.cs | 76 +++++++-------- .../Interpreters/StringCommandInterpreter.cs | 36 +++++++ .../Migration/Schema/CreateTableCommand.cs | 22 +---- .../Data/Migration/Schema/SchemaUtils.cs | 30 ++++++ .../Providers/AbstractDataServicesProvider.cs | 25 +---- .../Data/Providers/IDataServicesProvider.cs | 4 +- .../Providers/SQLiteDataServicesProvider.cs | 2 +- .../Providers/SessionFactoryParameters.cs | 1 - .../SqlServerDataServicesProvider.cs | 2 +- src/Orchard/Data/SessionFactoryHolder.cs | 51 +++------- src/Orchard/Orchard.Framework.csproj | 7 +- 31 files changed, 556 insertions(+), 171 deletions(-) create mode 100644 src/Orchard.Web/Modules/Orchard.DevTools/Controllers/DataMigrationController.cs create mode 100644 src/Orchard.Web/Modules/Orchard.DevTools/ScaffoldingTemplates/DataMigration.txt create mode 100644 src/Orchard.Web/Modules/Orchard.DevTools/Services/ScaffoldingCommandInterpreter.cs create mode 100644 src/Orchard.Web/Modules/Orchard.DevTools/ViewModels/DataMigrationIndexViewModel.cs create mode 100644 src/Orchard.Web/Modules/Orchard.DevTools/Views/DataMigration/Index.aspx delete mode 100644 src/Orchard/Data/Migration/DefaultDataMigrationGenerator.cs create mode 100644 src/Orchard/Data/Migration/Generator/ISchemaCommandGenerator.cs create mode 100644 src/Orchard/Data/Migration/Generator/SchemaCommandGenerator.cs delete mode 100644 src/Orchard/Data/Migration/IDataMigrationGenerator.cs create mode 100644 src/Orchard/Data/Migration/Interpreters/AbstractDataMigrationInterpreter.cs create mode 100644 src/Orchard/Data/Migration/Interpreters/StringCommandInterpreter.cs create mode 100644 src/Orchard/Data/Migration/Schema/SchemaUtils.cs diff --git a/src/Orchard.Specs/Hosting/TraceEnabledDataServicesProviderFactory.cs b/src/Orchard.Specs/Hosting/TraceEnabledDataServicesProviderFactory.cs index 18712a91a..76e3a8e8f 100644 --- a/src/Orchard.Specs/Hosting/TraceEnabledDataServicesProviderFactory.cs +++ b/src/Orchard.Specs/Hosting/TraceEnabledDataServicesProviderFactory.cs @@ -12,7 +12,7 @@ namespace Orchard.Specs.Hosting { class TraceEnabledBuilder : SQLiteDataServicesProvider { public TraceEnabledBuilder(string dataFolder, string connectionString) : base(dataFolder, connectionString) { } - protected override IPersistenceConfigurer GetPersistenceConfigurer(bool createDatabase) { + public override IPersistenceConfigurer GetPersistenceConfigurer(bool createDatabase) { var config = (SQLiteConfiguration)base.GetPersistenceConfigurer(createDatabase); //config.ShowSql(); return config; diff --git a/src/Orchard.Tests/Data/Builders/SessionFactoryBuilderTests.cs b/src/Orchard.Tests/Data/Builders/SessionFactoryBuilderTests.cs index a841c1ef8..2d0368ac3 100644 --- a/src/Orchard.Tests/Data/Builders/SessionFactoryBuilderTests.cs +++ b/src/Orchard.Tests/Data/Builders/SessionFactoryBuilderTests.cs @@ -64,12 +64,12 @@ namespace Orchard.Tests.Data.Builders { var parameters = new SessionFactoryParameters { Provider = "SQLite", DataFolder = _tempDataFolder, - UpdateSchema = true, RecordDescriptors = recordDescriptors }; var sessionFactory = manager .CreateProvider(parameters) - .BuildSessionFactory(parameters); + .BuildConfiguration(parameters) + .BuildSessionFactory(); var session = sessionFactory.OpenSession(); @@ -102,12 +102,12 @@ namespace Orchard.Tests.Data.Builders { Provider = "SqlServer", DataFolder = _tempDataFolder, ConnectionString = "Data Source=.\\SQLEXPRESS;AttachDbFileName=" + databasePath + ";Integrated Security=True;User Instance=True;", - UpdateSchema = true, RecordDescriptors = recordDescriptors, }; var sessionFactory = manager .CreateProvider(parameters) - .BuildSessionFactory(parameters); + .BuildConfiguration(parameters) + .BuildSessionFactory(); diff --git a/src/Orchard.Tests/DataMigration/DataMigrationTests.cs b/src/Orchard.Tests/DataMigration/DataMigrationTests.cs index d2f14709d..53b69a822 100644 --- a/src/Orchard.Tests/DataMigration/DataMigrationTests.cs +++ b/src/Orchard.Tests/DataMigration/DataMigrationTests.cs @@ -59,7 +59,6 @@ namespace Orchard.Tests.DataMigration { builder.RegisterInstance(_folders).As(); builder.RegisterType().As(); builder.RegisterType().As(); - builder.RegisterType().As(); builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>)); _session = _sessionFactory.OpenSession(); builder.RegisterInstance(new DefaultContentManagerTests.TestSessionLocator(_session)).As(); diff --git a/src/Orchard.Web/Modules/Orchard.DevTools/Commands/ScaffoldingCommands.cs b/src/Orchard.Web/Modules/Orchard.DevTools/Commands/ScaffoldingCommands.cs index 8ef6923cb..f929d33bc 100644 --- a/src/Orchard.Web/Modules/Orchard.DevTools/Commands/ScaffoldingCommands.cs +++ b/src/Orchard.Web/Modules/Orchard.DevTools/Commands/ScaffoldingCommands.cs @@ -3,27 +3,80 @@ using System.IO; using System.Linq; using System.Web.Hosting; using Orchard.Commands; +using Orchard.Data.Migration; +using Orchard.Data.Migration.Generator; +using Orchard.Data.Migration.Interpreters; +using Orchard.DevTools.Services; using Orchard.Environment.Extensions; namespace Orchard.DevTools.Commands { [OrchardFeature("Scaffolding")] public class ScaffoldingCommands : DefaultOrchardCommandHandler { private readonly IExtensionManager _extensionManager; + private readonly IDataMigrationManager _dataMigrationManager; + private readonly IDataMigrationInterpreter _dataMigrationInterpreter; + private readonly ISchemaCommandGenerator _schemaCommandGenerator; - public ScaffoldingCommands(IExtensionManager extensionManager) { + public ScaffoldingCommands(IExtensionManager extensionManager, + IDataMigrationManager dataMigrationManager, + IDataMigrationInterpreter dataMigrationInterpreter, + ISchemaCommandGenerator schemaCommandGenerator) { _extensionManager = extensionManager; + _dataMigrationManager = dataMigrationManager; + _dataMigrationInterpreter = dataMigrationInterpreter; + _schemaCommandGenerator = schemaCommandGenerator; } [OrchardSwitch] public bool IncludeInSolution { get; set; } + [CommandHelp("scaffolding create datamigration \r\n\t" + "Create a new Data Migration class")] + [CommandName("scaffolding create datamigration")] + public void CreateDataMigration(string featureName) { + Context.Output.WriteLine(T("Creating Data Migration for {0}", featureName)); + + foreach ( var extension in _extensionManager.AvailableExtensions() ) { + if ( extension.ExtensionType == "Module" && extension.Features.Any(f => String.Equals(f.Name, featureName, StringComparison.OrdinalIgnoreCase)) ) { + string dataMigrationsPath = HostingEnvironment.MapPath("~/Modules/" + extension.Name + "/DataMigrations/"); + string dataMigrationPath = dataMigrationsPath + extension.DisplayName + "DataMigration.cs"; + string templatesPath = HostingEnvironment.MapPath("~/Modules/Orchard.DevTools/ScaffoldingTemplates/"); + if ( !Directory.Exists(dataMigrationsPath) ) { + Directory.CreateDirectory(dataMigrationsPath); + } + if ( File.Exists(dataMigrationPath) ) { + Context.Output.WriteLine(T("Data migration already exists in target Module {0}.", extension.Name)); + return; + } + + var commands = _schemaCommandGenerator.GetCreateFeatureCommands(featureName, false).ToList(); + + var stringWriter = new StringWriter(); + var interpreter = new ScaffoldingCommandInterpreter(stringWriter); + + foreach ( var command in commands ) { + interpreter.Visit(command); + stringWriter.WriteLine(); + } + + string dataMigrationText = File.ReadAllText(templatesPath + "DataMigration.txt"); + dataMigrationText = dataMigrationText.Replace("$$FeatureName$$", featureName); + dataMigrationText = dataMigrationText.Replace("$$ClassName$$", extension.DisplayName); + dataMigrationText = dataMigrationText.Replace("$$Commands$$", stringWriter.ToString()); + File.WriteAllText(dataMigrationPath, dataMigrationText); + Context.Output.WriteLine(T("Data migration created successfully in Module {0}", extension.DisplayName)); + return; + } + } + Context.Output.WriteLine(T("Creating data migration failed: target Feature {0} could not be found.", featureName)); + } + [CommandHelp("scaffolding create module [/IncludeInSolution:true|false]\r\n\t" + "Create a new Orchard module")] [CommandName("scaffolding create module")] [OrchardSwitches("IncludeInSolution")] public void CreateModule(string moduleName) { Context.Output.WriteLine(T("Creating Module {0}", moduleName)); - if (_extensionManager.AvailableExtensions().Any(extension => extension.ExtensionType == "Module" && String.Equals(moduleName, extension.DisplayName, StringComparison.OrdinalIgnoreCase))) { + if ( _extensionManager.AvailableExtensions().Any(extension => extension.ExtensionType == "Module" && String.Equals(moduleName, extension.DisplayName, StringComparison.OrdinalIgnoreCase)) ) { Context.Output.WriteLine(T("Creating Module {0} failed: a module of the same name already exists", moduleName)); return; } diff --git a/src/Orchard.Web/Modules/Orchard.DevTools/Controllers/DataMigrationController.cs b/src/Orchard.Web/Modules/Orchard.DevTools/Controllers/DataMigrationController.cs new file mode 100644 index 000000000..443319d54 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.DevTools/Controllers/DataMigrationController.cs @@ -0,0 +1,23 @@ +using System.Web.Mvc; +using Orchard.Data.Migration.Generator; +using Orchard.DevTools.ViewModels; + +namespace Orchard.DevTools.Controllers { + [ValidateInput(false)] + public class DataMigrationController : Controller { + private readonly ISchemaCommandGenerator _schemaCommandGenerator; + + public DataMigrationController(ISchemaCommandGenerator schemaCommandGenerator) { + _schemaCommandGenerator = schemaCommandGenerator; + } + + public ActionResult Index() { + var model = new DataMigrationIndexViewModel (); + + _schemaCommandGenerator.UpdateDatabase(); + + return View(model); + } + + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.DevTools/Orchard.DevTools.csproj b/src/Orchard.Web/Modules/Orchard.DevTools/Orchard.DevTools.csproj index d348d426b..024727911 100644 --- a/src/Orchard.Web/Modules/Orchard.DevTools/Orchard.DevTools.csproj +++ b/src/Orchard.Web/Modules/Orchard.DevTools/Orchard.DevTools.csproj @@ -73,6 +73,7 @@ + @@ -80,9 +81,12 @@ + + + @@ -92,6 +96,7 @@ + diff --git a/src/Orchard.Web/Modules/Orchard.DevTools/ScaffoldingTemplates/DataMigration.txt b/src/Orchard.Web/Modules/Orchard.DevTools/ScaffoldingTemplates/DataMigration.txt new file mode 100644 index 000000000..e671bd79a --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.DevTools/ScaffoldingTemplates/DataMigration.txt @@ -0,0 +1,13 @@ +using System.Data; +using Orchard.Data.Migration; + +namespace $$FeatureName$$.DataMigrations { + public class $$ClassName$$DataMigration : DataMigrationImpl { + + public int Create() { + $$Commands$$ + + return 0100; + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.DevTools/Services/ScaffoldingCommandInterpreter.cs b/src/Orchard.Web/Modules/Orchard.DevTools/Services/ScaffoldingCommandInterpreter.cs new file mode 100644 index 000000000..b68ee832f --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.DevTools/Services/ScaffoldingCommandInterpreter.cs @@ -0,0 +1,78 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Orchard.Data.Migration.Interpreters; +using Orchard.Data.Migration.Schema; + +namespace Orchard.DevTools.Services { + public class ScaffoldingCommandInterpreter : AbstractDataMigrationInterpreter { + private readonly TextWriter _output; + + public ScaffoldingCommandInterpreter(TextWriter output) { + _output = output; + } + + public override void Visit(CreateTableCommand command) { + _output.WriteLine("// Creating table {0}", command.Name); + _output.WriteLine("\t\t\tSchemaBuilder.CreateTable(\"{0}\", table => table", command.Name); + + foreach ( var createColumn in command.TableCommands.OfType() ) { + var type = createColumn.DbType.ToString(); + var field = createColumn.ColumnName; + var options = new List(); + + if ( createColumn.IsPrimaryKey ) { + options.Add(string.Format("WithLength({0})", createColumn.Length)); + } + + if ( createColumn.IsUnique ) { + options.Add("Unique()"); + } + + if ( createColumn.IsNotNull ) { + options.Add("NotNull()"); + } + + if ( createColumn.IsPrimaryKey ) { + options.Add("PrimaryKey()"); + } + + if ( createColumn.Length.HasValue ) { + options.Add(string.Format("WithLength({0})", createColumn.Length )); + } + + if ( createColumn.Precision > 0 ) { + options.Add(string.Format("WithPrecision({0})", createColumn.Precision)); + options.Add(string.Format("WithScale({0})", createColumn.Scale)); + } + + _output.WriteLine("\t\t\t\t.Column(\"{0}\", DbType.{1}{2})", field, type, options.Any() ? ", column => column." + string.Join(".", options) : string.Empty); + } + + _output.WriteLine("\t\t\t);"); + + } + + public override void Visit(AlterTableCommand command) { + _output.WriteLine("// Altering table {0}", command.Name); + } + + public override void Visit(DropTableCommand command) { + _output.WriteLine("// Dropping table {0}", command.Name); + _output.WriteLine("\t\t\tSchemaBuilder.DropTable(\"{0}\", command.Name);"); + } + + public override void Visit(SqlStatementCommand command) { + _output.WriteLine("// Executing sql statement\n\n {0}", command.Sql); + } + + public override void Visit(CreateForeignKeyCommand command) { + _output.WriteLine("// Creating foreign key {0}", command.Name); + } + + public override void Visit(DropForeignKeyCommand command) { + _output.WriteLine("// Dropping foreign key {0}", command.Name); + } + + } +} diff --git a/src/Orchard.Web/Modules/Orchard.DevTools/ViewModels/DataMigrationIndexViewModel.cs b/src/Orchard.Web/Modules/Orchard.DevTools/ViewModels/DataMigrationIndexViewModel.cs new file mode 100644 index 000000000..bf5b7e0a1 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.DevTools/ViewModels/DataMigrationIndexViewModel.cs @@ -0,0 +1,6 @@ +using Orchard.Mvc.ViewModels; + +namespace Orchard.DevTools.ViewModels { + public class DataMigrationIndexViewModel : BaseViewModel { + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.DevTools/Views/DataMigration/Index.aspx b/src/Orchard.Web/Modules/Orchard.DevTools/Views/DataMigration/Index.aspx new file mode 100644 index 000000000..962308436 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.DevTools/Views/DataMigration/Index.aspx @@ -0,0 +1,9 @@ +<%@ Page Language="C#" Inherits="Orchard.Mvc.ViewPage" %> + + +

Data Migration

diff --git a/src/Orchard.Web/Modules/Orchard.Indexing/Commands/IndexingCommands.cs b/src/Orchard.Web/Modules/Orchard.Indexing/Commands/IndexingCommands.cs index 0799cdb97..292546ab1 100644 --- a/src/Orchard.Web/Modules/Orchard.Indexing/Commands/IndexingCommands.cs +++ b/src/Orchard.Web/Modules/Orchard.Indexing/Commands/IndexingCommands.cs @@ -3,8 +3,6 @@ using System.Collections.Generic; using System.Linq; using Orchard.Commands; using Orchard.ContentManagement; -using Orchard.Indexing; -using Orchard.Security; using Orchard.Tasks.Indexing; namespace Orchard.Indexing.Commands { diff --git a/src/Orchard.Web/Modules/Orchard.Indexing/DataMigrations/IndexingDataMigration.cs b/src/Orchard.Web/Modules/Orchard.Indexing/DataMigrations/IndexingDataMigration.cs index c1c11bd9d..9cd38b71a 100644 --- a/src/Orchard.Web/Modules/Orchard.Indexing/DataMigrations/IndexingDataMigration.cs +++ b/src/Orchard.Web/Modules/Orchard.Indexing/DataMigrations/IndexingDataMigration.cs @@ -5,7 +5,6 @@ namespace Orchard.Indexing.DataMigrations { public class IndexingDataMigration : DataMigrationImpl { public int Create() { - SchemaBuilder.CreateTable("IndexingTaskRecord", table => table .Column("Id", column => column.PrimaryKey()) .Column("Action") diff --git a/src/Orchard.Web/Modules/Orchard.Indexing/Orchard.Indexing.csproj b/src/Orchard.Web/Modules/Orchard.Indexing/Orchard.Indexing.csproj index ccc3e3f4d..079d90f0e 100644 --- a/src/Orchard.Web/Modules/Orchard.Indexing/Orchard.Indexing.csproj +++ b/src/Orchard.Web/Modules/Orchard.Indexing/Orchard.Indexing.csproj @@ -64,7 +64,7 @@ - + diff --git a/src/Orchard/Data/Migration/Commands/DataMigrationCommands.cs b/src/Orchard/Data/Migration/Commands/DataMigrationCommands.cs index 745b2fffd..24e8e3c4b 100644 --- a/src/Orchard/Data/Migration/Commands/DataMigrationCommands.cs +++ b/src/Orchard/Data/Migration/Commands/DataMigrationCommands.cs @@ -1,24 +1,33 @@ using System; +using System.Linq; using Orchard.Commands; +using Orchard.Data.Migration.Generator; +using Orchard.Data.Migration.Interpreters; namespace Orchard.Data.Migration.Commands { public class DataMigrationCommands : DefaultOrchardCommandHandler { private readonly IDataMigrationManager _dataMigrationManager; + private readonly IDataMigrationInterpreter _dataMigrationInterpreter; + private readonly ISchemaCommandGenerator _schemaCommandGenerator; public DataMigrationCommands( - IDataMigrationManager dataMigrationManager) { + IDataMigrationManager dataMigrationManager, + IDataMigrationInterpreter dataMigrationInterpreter, + ISchemaCommandGenerator schemaCommandGenerator + ) { _dataMigrationManager = dataMigrationManager; + _dataMigrationInterpreter = dataMigrationInterpreter; + _schemaCommandGenerator = schemaCommandGenerator; } [OrchardSwitch] - public string Feature { get; set; } + public bool Drop { get; set; } [CommandName("upgrade database")] - [CommandHelp("upgrade database /Feature: \r\n\t" + "Upgrades or create the database tables for the named ")] - [OrchardSwitches("Feature")] - public string UpgradeDatabase() { + [CommandHelp("upgrade database \r\n\t" + "Upgrades or create the database tables for the ")] + public string UpgradeDatabase(string featureName) { try { - _dataMigrationManager.Update(Feature); + _dataMigrationManager.Update(featureName); } catch ( Exception ex ) { Context.Output.WriteLine(T("An error occured while upgrading the database: " + ex.Message)); @@ -27,5 +36,45 @@ namespace Orchard.Data.Migration.Commands { return "Database upgraded"; } + + [CommandName("update database")] + [CommandHelp("update database \r\n\t" + "Automatically updates the database schema for the enabled features")] + public string UpdateDatabase() { + try { + _schemaCommandGenerator.UpdateDatabase(); + } + catch ( Exception ex ) { + Context.Output.WriteLine(T("An error occured while updating the database: " + ex.Message)); + return "Update terminated."; + } + + return "Database updated"; + } + + [CommandName("create tables")] + [CommandHelp("create tables [/Drop:true|false] \r\n\t" + "Creates the database tables for the and optionaly drops them before if specified")] + [OrchardSwitches("Drop")] + public string CreateTables(string featureName) { + var stringInterpreter = new StringCommandInterpreter(Context.Output); + try { + var commands = _schemaCommandGenerator.GetCreateFeatureCommands(featureName, Drop).ToList(); + if ( commands.Any() ) { + + foreach (var command in commands) { + stringInterpreter.Visit(command); + _dataMigrationInterpreter.Visit(command); + } + } + else { + return "There are no tables to create for this feature."; + } + } + catch ( Exception ex ) { + Context.Output.WriteLine(T("An error occured while creating the tables: " + ex.Message)); + return "Tables creation terminated."; + } + + return "Tables created"; + } } } \ No newline at end of file diff --git a/src/Orchard/Data/Migration/DataMigrationManager.cs b/src/Orchard/Data/Migration/DataMigrationManager.cs index 6c258680a..163d07e84 100644 --- a/src/Orchard/Data/Migration/DataMigrationManager.cs +++ b/src/Orchard/Data/Migration/DataMigrationManager.cs @@ -3,10 +3,15 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text.RegularExpressions; +using FluentNHibernate.Cfg; +using NHibernate.Tool.hbm2ddl; +using Orchard.Data.Migration.Generator; using Orchard.Data.Migration.Interpreters; using Orchard.Data.Migration.Records; using Orchard.Data.Migration.Schema; +using Orchard.Data.Providers; using Orchard.Environment.Extensions; +using Orchard.Environment.ShellBuilders.Models; using Orchard.Environment.State; using Orchard.Logging; @@ -19,16 +24,21 @@ namespace Orchard.Data.Migration { private readonly IRepository _dataMigrationRepository; private readonly IExtensionManager _extensionManager; private readonly IDataMigrationInterpreter _interpreter; + private readonly ISchemaCommandGenerator _generator; public DataMigrationManager( IEnumerable dataMigrations, IRepository dataMigrationRepository, IExtensionManager extensionManager, - IDataMigrationInterpreter interpreter) { + IDataMigrationInterpreter interpreter, + ISchemaCommandGenerator generator + ) { _dataMigrations = dataMigrations; _dataMigrationRepository = dataMigrationRepository; _extensionManager = extensionManager; _interpreter = interpreter; + _generator = generator; + Logger = NullLogger.Instance; } @@ -93,7 +103,7 @@ namespace Orchard.Data.Migration { var migrations = GetDataMigrations(feature); - // apply update methods to each migration class for the module + // apply update methods to each migration class for the module)))) foreach ( var migration in migrations ) { // copy the objet for the Linq query var tempMigration = migration; @@ -149,7 +159,7 @@ namespace Orchard.Data.Migration { // apply update methods to each migration class for the module foreach (var migration in migrations) { - // copy the objet for the Linq query + // copy the object for the Linq query var tempMigration = migration; // get current version for this migration diff --git a/src/Orchard/Data/Migration/DefaultDataMigrationGenerator.cs b/src/Orchard/Data/Migration/DefaultDataMigrationGenerator.cs deleted file mode 100644 index 5aeaea29e..000000000 --- a/src/Orchard/Data/Migration/DefaultDataMigrationGenerator.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Orchard.Data.Migration.Schema; -using Orchard.Environment.ShellBuilders.Models; - -namespace Orchard.Data.Migration { - public class DefaultDataMigrationGenerator : IDataMigrationGenerator { - public IEnumerable CreateCommands(IEnumerable records) { - - - return Enumerable.Empty(); - } - } -} diff --git a/src/Orchard/Data/Migration/Generator/ISchemaCommandGenerator.cs b/src/Orchard/Data/Migration/Generator/ISchemaCommandGenerator.cs new file mode 100644 index 000000000..acfda2eab --- /dev/null +++ b/src/Orchard/Data/Migration/Generator/ISchemaCommandGenerator.cs @@ -0,0 +1,24 @@ +using System.Collections.Generic; +using Orchard.Data.Migration.Schema; + +namespace Orchard.Data.Migration.Generator { + public interface ISchemaCommandGenerator : IDependency { + /// + /// Returns a set of instances to execute in order to create the tables requiered by the specified feature. + /// + /// The name of the feature from which the tables need to be created. + /// Whether to generate drop commands for the created tables. + IEnumerable GetCreateFeatureCommands(string feature, bool drop); + + /// + /// Automatically updates the tables in the database. + /// + void UpdateDatabase(); + + /// + /// Creates the tables in the database. + /// + void CreateDatabase(); + + } +} \ No newline at end of file diff --git a/src/Orchard/Data/Migration/Generator/SchemaCommandGenerator.cs b/src/Orchard/Data/Migration/Generator/SchemaCommandGenerator.cs new file mode 100644 index 000000000..c9c462dc7 --- /dev/null +++ b/src/Orchard/Data/Migration/Generator/SchemaCommandGenerator.cs @@ -0,0 +1,97 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using NHibernate.Cfg; +using NHibernate.Mapping; +using NHibernate.Tool.hbm2ddl; +using Orchard.Data.Migration.Schema; +using Orchard.Data.Providers; +using NHibernate.Dialect; +using Orchard.Environment.Extensions; + +namespace Orchard.Data.Migration.Generator { + public class SchemaCommandGenerator : ISchemaCommandGenerator { + private readonly IDataServicesProviderFactory _dataServicesProviderFactory; + private readonly ISessionFactoryHolder _sessionFactoryHolder; + + public SchemaCommandGenerator( + IDataServicesProviderFactory dataServicesProviderFactory, + ISessionFactoryHolder sessionFactoryHolder) { + _dataServicesProviderFactory = dataServicesProviderFactory; + _sessionFactoryHolder = sessionFactoryHolder; + } + + public IEnumerable GetCreateFeatureCommands(string feature, bool drop) { + var parameters = _sessionFactoryHolder.GetSessionFactoryParameters(); + + if (!parameters.RecordDescriptors.Any()) { + yield break; + } + + var configuration = _dataServicesProviderFactory.CreateProvider(parameters).BuildConfiguration(parameters); + var dialect = Dialect.GetDialect(configuration.Properties); + var mapping = configuration.BuildMapping(); + + // get the tables using reflection + var tablesField = typeof(Configuration).GetField("tables", BindingFlags.Instance | BindingFlags.NonPublic); + var tables = ((IDictionary) tablesField.GetValue(configuration)).Values; + + + foreach(var table in tables.Where(t => parameters.RecordDescriptors.Any(rd => rd.Feature.Descriptor.Name == feature && rd.TableName == t.Name))) { + if(drop) { + yield return new DropTableCommand(table.Name); + } + + var command = new CreateTableCommand(table.Name); + + foreach(var column in table.ColumnIterator) { + var table1 = table; + var column1 = column; + var sqlType = column1.GetSqlTypeCode(mapping); + command.Column(column.Name, sqlType.DbType, + action => { + if (table1.PrimaryKey.Columns.Any(c => c.Name == column1.Name)) { + action.PrimaryKey(); + } + + if (column1.IsLengthDefined()) { + action.WithLength(column1.Length); + } + + if (column1.IsPrecisionDefined()) { + action.WithPrecision((byte) column1.Precision); + action.WithScale((byte) column1.Scale); + } + if (column1.IsNullable) { + action.Nullable(); + } + + if ( column1.IsUnique ) { + action.Unique(); + } + + if(column1.DefaultValue != null) { + action.WithDefault(column1.DefaultValue); + } + }); + } + + yield return command; + } + } + + public void UpdateDatabase() { + var parameters = _sessionFactoryHolder.GetSessionFactoryParameters(); + var configuration = _dataServicesProviderFactory.CreateProvider(parameters).BuildConfiguration(parameters); + new SchemaUpdate(configuration).Execute(false, true); + } + + public void CreateDatabase() { + var parameters = _sessionFactoryHolder.GetSessionFactoryParameters(); + var configuration = _dataServicesProviderFactory.CreateProvider(parameters).BuildConfiguration(parameters); + new SchemaExport(configuration).Execute(false, true, false); + } + + } +} diff --git a/src/Orchard/Data/Migration/IDataMigrationGenerator.cs b/src/Orchard/Data/Migration/IDataMigrationGenerator.cs deleted file mode 100644 index 2ce898dfd..000000000 --- a/src/Orchard/Data/Migration/IDataMigrationGenerator.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.Collections.Generic; -using FluentNHibernate.Cfg; -using Orchard.Data.Migration.Schema; -using Orchard.Environment.ShellBuilders.Models; - -namespace Orchard.Data.Migration { - // Builds and runs the representative migration create calls - public interface IDataMigrationGenerator : IDependency { - IEnumerable CreateCommands(IEnumerable records); - } -} diff --git a/src/Orchard/Data/Migration/Interpreters/AbstractDataMigrationInterpreter.cs b/src/Orchard/Data/Migration/Interpreters/AbstractDataMigrationInterpreter.cs new file mode 100644 index 000000000..4cd6a9439 --- /dev/null +++ b/src/Orchard/Data/Migration/Interpreters/AbstractDataMigrationInterpreter.cs @@ -0,0 +1,41 @@ +using Orchard.Data.Migration.Schema; + +namespace Orchard.Data.Migration.Interpreters { + public abstract class AbstractDataMigrationInterpreter { + + public void Visit(ISchemaBuilderCommand command) { + var schemaCommand = command as SchemaCommand; + if (schemaCommand == null) { + return; + } + + switch ( schemaCommand.Type ) { + case SchemaCommandType.CreateTable: + Visit((CreateTableCommand)schemaCommand); + break; + case SchemaCommandType.AlterTable: + Visit((AlterTableCommand)schemaCommand); + break; + case SchemaCommandType.DropTable: + Visit((DropTableCommand)schemaCommand); + break; + case SchemaCommandType.SqlStatement: + Visit((SqlStatementCommand)schemaCommand); + break; + case SchemaCommandType.CreateForeignKey: + Visit((CreateForeignKeyCommand)schemaCommand); + break; + case SchemaCommandType.DropForeignKey: + Visit((DropForeignKeyCommand)schemaCommand); + break; + } + } + + public abstract void Visit(CreateTableCommand command); + public abstract void Visit(AlterTableCommand command); + public abstract void Visit(DropTableCommand command); + public abstract void Visit(SqlStatementCommand command); + public abstract void Visit(CreateForeignKeyCommand command); + public abstract void Visit(DropForeignKeyCommand command); + } +} diff --git a/src/Orchard/Data/Migration/Interpreters/DefaultDataMigrationInterpreter.cs b/src/Orchard/Data/Migration/Interpreters/DefaultDataMigrationInterpreter.cs index fb2db6ee3..c9313ca82 100644 --- a/src/Orchard/Data/Migration/Interpreters/DefaultDataMigrationInterpreter.cs +++ b/src/Orchard/Data/Migration/Interpreters/DefaultDataMigrationInterpreter.cs @@ -7,25 +7,40 @@ using NHibernate; using NHibernate.Dialect; using NHibernate.SqlTypes; using Orchard.Data.Migration.Schema; +using Orchard.Data.Providers; using Orchard.Environment.Configuration; using Orchard.Logging; namespace Orchard.Data.Migration.Interpreters { - public class DefaultDataMigrationInterpreter : IDataMigrationInterpreter { + public class DefaultDataMigrationInterpreter : AbstractDataMigrationInterpreter, IDataMigrationInterpreter { private readonly ShellSettings _shellSettings; private readonly IEnumerable _commandInterpreters; private readonly ISession _session; private readonly Dialect _dialect; private readonly List _sqlStatements; + private readonly IDataServicesProviderFactory _dataServicesProviderFactory; + private readonly ISessionFactoryHolder _sessionFactoryHolder; + private const char Space = ' ' ; - public DefaultDataMigrationInterpreter(ShellSettings shellSettings, ISessionLocator sessionLocator, IEnumerable commandInterpreters) { + public DefaultDataMigrationInterpreter( + ShellSettings shellSettings, + ISessionLocator sessionLocator, + IEnumerable commandInterpreters, + IDataServicesProviderFactory dataServicesProviderFactory, + ISessionFactoryHolder sessionFactoryHolder) { _shellSettings = shellSettings; _commandInterpreters = commandInterpreters; _session = sessionLocator.For(typeof(DefaultDataMigrationInterpreter)); _sqlStatements = new List(); - _dialect = _shellSettings.DataProvider == "SQLite" ? (Dialect) new SQLiteDialect() : new MsSql2008Dialect(); + _dataServicesProviderFactory = dataServicesProviderFactory; + _sessionFactoryHolder = sessionFactoryHolder; + Logger = NullLogger.Instance; + + var parameters = _sessionFactoryHolder.GetSessionFactoryParameters(); + var configuration = _dataServicesProviderFactory.CreateProvider(parameters).BuildConfiguration(parameters); + _dialect = Dialect.GetDialect(configuration.Properties); } public ILogger Logger { get; set; } @@ -34,35 +49,7 @@ namespace Orchard.Data.Migration.Interpreters { get { return _sqlStatements; } } - public void Visit(ISchemaBuilderCommand command) { - var schemaCommand = command as SchemaCommand; - if (schemaCommand == null) { - return; - } - - switch ( schemaCommand.Type ) { - case SchemaCommandType.CreateTable: - Visit((CreateTableCommand)schemaCommand); - break; - case SchemaCommandType.AlterTable: - Visit((AlterTableCommand)schemaCommand); - break; - case SchemaCommandType.DropTable: - Visit((DropTableCommand)schemaCommand); - break; - case SchemaCommandType.SqlStatement: - Visit((SqlStatementCommand)schemaCommand); - break; - case SchemaCommandType.CreateForeignKey: - Visit((CreateForeignKeyCommand)schemaCommand); - break; - case SchemaCommandType.DropForeignKey: - Visit((DropForeignKeyCommand)schemaCommand); - break; - } - } - - public void Visit(CreateTableCommand command) { + public override void Visit(CreateTableCommand command) { if ( ExecuteCustomInterpreter(command) ) { return; @@ -103,7 +90,7 @@ namespace Orchard.Data.Migration.Interpreters { RunPendingStatements(); } - public void Visit(DropTableCommand command) { + public override void Visit(DropTableCommand command) { if ( ExecuteCustomInterpreter(command) ) { return; } @@ -116,7 +103,7 @@ namespace Orchard.Data.Migration.Interpreters { RunPendingStatements(); } - public void Visit(AlterTableCommand command) { + public override void Visit(AlterTableCommand command) { if ( ExecuteCustomInterpreter(command) ) { return; } @@ -229,18 +216,21 @@ namespace Orchard.Data.Migration.Interpreters { _dialect.QuoteForColumnName(command.IndexName)); _sqlStatements.Add(builder.ToString()); } - public void Visit(SqlStatementCommand command) { - if (command.Providers.Count == 0 || command.Providers.Contains(_shellSettings.DataProvider) ) { - if (ExecuteCustomInterpreter(command)) { - return; - } - _sqlStatements.Add(command.Sql); - RunPendingStatements(); + public override void Visit(SqlStatementCommand command) { + if (command.Providers.Count != 0 && !command.Providers.Contains(_shellSettings.DataProvider)) { + return; } + + if (ExecuteCustomInterpreter(command)) { + return; + } + _sqlStatements.Add(command.Sql); + + RunPendingStatements(); } - public void Visit(CreateForeignKeyCommand command) { + public override void Visit(CreateForeignKeyCommand command) { if ( ExecuteCustomInterpreter(command) ) { return; } @@ -261,7 +251,7 @@ namespace Orchard.Data.Migration.Interpreters { RunPendingStatements(); } - public void Visit(DropForeignKeyCommand command) { + public override void Visit(DropForeignKeyCommand command) { if ( ExecuteCustomInterpreter(command) ) { return; } diff --git a/src/Orchard/Data/Migration/Interpreters/StringCommandInterpreter.cs b/src/Orchard/Data/Migration/Interpreters/StringCommandInterpreter.cs new file mode 100644 index 000000000..056b45ac6 --- /dev/null +++ b/src/Orchard/Data/Migration/Interpreters/StringCommandInterpreter.cs @@ -0,0 +1,36 @@ +using System.IO; +using Orchard.Data.Migration.Schema; + +namespace Orchard.Data.Migration.Interpreters { + public class StringCommandInterpreter : AbstractDataMigrationInterpreter { + private readonly TextWriter _output; + + public StringCommandInterpreter(TextWriter output) { + _output = output; + } + + public override void Visit(CreateTableCommand command) { + _output.WriteLine("Creating table {0}", command.Name); + } + + public override void Visit(AlterTableCommand command) { + _output.WriteLine("Altering table {0}", command.Name); + } + + public override void Visit(DropTableCommand command) { + _output.WriteLine("Dropping table {0}", command.Name); + } + + public override void Visit(SqlStatementCommand command) { + _output.WriteLine("Executing sql statement\n\n {0}", command.Sql); + } + + public override void Visit(CreateForeignKeyCommand command) { + _output.WriteLine("Creating foreign key {0}", command.Name); + } + + public override void Visit(DropForeignKeyCommand command) { + _output.WriteLine("Dropping foreign key {0}", command.Name); + } + } +} diff --git a/src/Orchard/Data/Migration/Schema/CreateTableCommand.cs b/src/Orchard/Data/Migration/Schema/CreateTableCommand.cs index 5c295e385..eefc48aa3 100644 --- a/src/Orchard/Data/Migration/Schema/CreateTableCommand.cs +++ b/src/Orchard/Data/Migration/Schema/CreateTableCommand.cs @@ -19,25 +19,7 @@ namespace Orchard.Data.Migration.Schema { } public CreateTableCommand Column(string columnName, Action column = null) { - var dbType = System.Data.DbType.Object; - switch(System.Type.GetTypeCode(typeof(T))) { - case TypeCode.String : - dbType = DbType.String; - break; - case TypeCode.Int32: - dbType = DbType.Int32; - break; - case TypeCode.DateTime: - dbType = DbType.DateTime; - break; - case TypeCode.Boolean: - dbType = DbType.Boolean; - break; - default: - Enum.TryParse(System.Type.GetTypeCode(typeof (T)).ToString(), true, out dbType); - break; - } - + var dbType = SchemaUtils.ToDbType(typeof (T)); return Column(columnName, dbType, column); } @@ -50,5 +32,7 @@ namespace Orchard.Data.Migration.Schema { /// TODO: Call Column() with necessary information for content part records return this; } + + } } diff --git a/src/Orchard/Data/Migration/Schema/SchemaUtils.cs b/src/Orchard/Data/Migration/Schema/SchemaUtils.cs new file mode 100644 index 000000000..71bd85c36 --- /dev/null +++ b/src/Orchard/Data/Migration/Schema/SchemaUtils.cs @@ -0,0 +1,30 @@ +using System; +using System.Data; + +namespace Orchard.Data.Migration.Schema { + public static class SchemaUtils { + public static DbType ToDbType(Type type) { + DbType dbType; + switch ( System.Type.GetTypeCode(type) ) { + case TypeCode.String: + dbType = DbType.String; + break; + case TypeCode.Int32: + dbType = DbType.Int32; + break; + case TypeCode.DateTime: + dbType = DbType.DateTime; + break; + case TypeCode.Boolean: + dbType = DbType.Boolean; + break; + default: + Enum.TryParse(Type.GetTypeCode(type).ToString(), true, out dbType); + break; + } + + return dbType; + } + + } +} diff --git a/src/Orchard/Data/Providers/AbstractDataServicesProvider.cs b/src/Orchard/Data/Providers/AbstractDataServicesProvider.cs index f32517e88..170308a65 100644 --- a/src/Orchard/Data/Providers/AbstractDataServicesProvider.cs +++ b/src/Orchard/Data/Providers/AbstractDataServicesProvider.cs @@ -16,30 +16,16 @@ using Orchard.Environment.ShellBuilders.Models; namespace Orchard.Data.Providers { public abstract class AbstractDataServicesProvider : IDataServicesProvider { - protected abstract IPersistenceConfigurer GetPersistenceConfigurer(bool createDatabase); + public abstract IPersistenceConfigurer GetPersistenceConfigurer(bool createDatabase); - public ISessionFactory BuildSessionFactory(SessionFactoryParameters parameters) { + public Configuration BuildConfiguration(SessionFactoryParameters parameters) { var database = GetPersistenceConfigurer(parameters.CreateDatabase); var persistenceModel = CreatePersistenceModel(parameters.RecordDescriptors); - var sessionFactory = Fluently.Configure() + return Fluently.Configure() .Database(database) .Mappings(m => m.AutoMappings.Add(persistenceModel)) - .ExposeConfiguration(config => Initialization(parameters, config)) - .BuildSessionFactory(); - - return sessionFactory; - } - - private static void Initialization(SessionFactoryParameters parameters, Configuration configuration) { - if (parameters.CreateDatabase) { - var export = new SchemaExport(configuration); - export.Execute(false/*script*/, true/*export*/, false/*justDrop*/); - } - else if (parameters.UpdateSchema) { - var update = new SchemaUpdate(configuration); - update.Execute(false/*script*/, true /*doUpdate*/); - } + .BuildConfiguration(); } public static AutoPersistenceModel CreatePersistenceModel(IEnumerable recordDescriptors) { @@ -65,8 +51,5 @@ namespace Orchard.Data.Providers { public IEnumerable GetTypes() { return _recordDescriptors.Select(descriptor => descriptor.Type); } } - - - } } \ No newline at end of file diff --git a/src/Orchard/Data/Providers/IDataServicesProvider.cs b/src/Orchard/Data/Providers/IDataServicesProvider.cs index 19e5a3176..7c9c909a3 100644 --- a/src/Orchard/Data/Providers/IDataServicesProvider.cs +++ b/src/Orchard/Data/Providers/IDataServicesProvider.cs @@ -1,10 +1,12 @@ using System; using FluentNHibernate.Cfg; +using FluentNHibernate.Cfg.Db; using NHibernate; using NHibernate.Cfg; namespace Orchard.Data.Providers { public interface IDataServicesProvider : ITransientDependency { - ISessionFactory BuildSessionFactory(SessionFactoryParameters sessionFactoryParameters); + Configuration BuildConfiguration(SessionFactoryParameters sessionFactoryParameters); + IPersistenceConfigurer GetPersistenceConfigurer(bool createDatabase); } } diff --git a/src/Orchard/Data/Providers/SQLiteDataServicesProvider.cs b/src/Orchard/Data/Providers/SQLiteDataServicesProvider.cs index dbc619391..634309cd7 100644 --- a/src/Orchard/Data/Providers/SQLiteDataServicesProvider.cs +++ b/src/Orchard/Data/Providers/SQLiteDataServicesProvider.cs @@ -15,7 +15,7 @@ namespace Orchard.Data.Providers { get { return "SQLite"; } } - protected override IPersistenceConfigurer GetPersistenceConfigurer(bool createDatabase) { + public override IPersistenceConfigurer GetPersistenceConfigurer(bool createDatabase) { var persistence = SQLiteConfiguration.Standard; if (string.IsNullOrEmpty(_connectionString)) { var dataFile = Path.Combine(_dataFolder, "Orchard.db"); diff --git a/src/Orchard/Data/Providers/SessionFactoryParameters.cs b/src/Orchard/Data/Providers/SessionFactoryParameters.cs index d7ca8855c..e607582e5 100644 --- a/src/Orchard/Data/Providers/SessionFactoryParameters.cs +++ b/src/Orchard/Data/Providers/SessionFactoryParameters.cs @@ -5,6 +5,5 @@ namespace Orchard.Data.Providers { public class SessionFactoryParameters : DataServiceParameters { public IEnumerable RecordDescriptors { get; set; } public bool CreateDatabase { get; set; } - public bool UpdateSchema { get; set; } } } diff --git a/src/Orchard/Data/Providers/SqlServerDataServicesProvider.cs b/src/Orchard/Data/Providers/SqlServerDataServicesProvider.cs index 34ee1e0a0..5d61f558d 100644 --- a/src/Orchard/Data/Providers/SqlServerDataServicesProvider.cs +++ b/src/Orchard/Data/Providers/SqlServerDataServicesProvider.cs @@ -16,7 +16,7 @@ namespace Orchard.Data.Providers { get { return "SqlServer"; } } - protected override IPersistenceConfigurer GetPersistenceConfigurer(bool createDatabase) { + public override IPersistenceConfigurer GetPersistenceConfigurer(bool createDatabase) { var persistence = MsSqlConfiguration.MsSql2008; if (string.IsNullOrEmpty(_connectionString)) { throw new NotImplementedException(); diff --git a/src/Orchard/Data/SessionFactoryHolder.cs b/src/Orchard/Data/SessionFactoryHolder.cs index f462050a1..d5ab906ff 100644 --- a/src/Orchard/Data/SessionFactoryHolder.cs +++ b/src/Orchard/Data/SessionFactoryHolder.cs @@ -13,8 +13,7 @@ using Orchard.Logging; namespace Orchard.Data { public interface ISessionFactoryHolder : ISingletonDependency { ISessionFactory GetSessionFactory(); - void CreateDatabase(); - void UpdateSchema(); + SessionFactoryParameters GetSessionFactoryParameters(); } public class SessionFactoryHolder : ISessionFactoryHolder { @@ -42,61 +41,41 @@ namespace Orchard.Data { public Localizer T { get; set; } public ILogger Logger { get; set; } - public void CreateDatabase() { - lock (this) { - if (_sessionFactory != null) { - Logger.Error("CreateSchema can not be called after a session factory was created"); - throw new OrchardCoreException(T("CreateSchema can not be called after a session factory was created")); - } - - _sessionFactory = BuildSessionFactory(true /*createDatabase*/, false /*updateSchema*/); - } - } - - public void UpdateSchema() { - lock (this) { - if (_sessionFactory != null) { - Logger.Error("UpdateSchema can not be called after a session factory was created"); - throw new OrchardCoreException(T("UpdateSchema can not be called after a session factory was created")); - } - - _sessionFactory = BuildSessionFactory(false /*createDatabase*/, true /*updateSchema*/); - } - } - public ISessionFactory GetSessionFactory() { lock (this) { if (_sessionFactory == null) { - _sessionFactory = BuildSessionFactory(false /*createDatabase*/, false /*updateSchema*/); + _sessionFactory = BuildSessionFactory(); } } return _sessionFactory; } - private ISessionFactory BuildSessionFactory(bool createDatabase, bool updateSchema) { + private ISessionFactory BuildSessionFactory() { Logger.Debug("Building session factory"); + var parameters = GetSessionFactoryParameters(); + + var sessionFactory = _dataServicesProviderFactory + .CreateProvider(parameters) + .BuildConfiguration(parameters) + .BuildSessionFactory(); + + return sessionFactory; + } + + public SessionFactoryParameters GetSessionFactoryParameters() { var shellPath = _appDataFolder.Combine("Sites", _shellSettings.Name); _appDataFolder.CreateDirectory(shellPath); var shellFolder = _appDataFolder.MapPath(shellPath); - var parameters = new SessionFactoryParameters { + return new SessionFactoryParameters { Provider = _shellSettings.DataProvider, DataFolder = shellFolder, ConnectionString = _shellSettings.DataConnectionString, - CreateDatabase = createDatabase, - UpdateSchema = updateSchema, RecordDescriptors = _shellBlueprint.Records, }; - - var sessionFactory = _dataServicesProviderFactory - .CreateProvider(parameters) - .BuildSessionFactory(parameters); - - return sessionFactory; } - } diff --git a/src/Orchard/Orchard.Framework.csproj b/src/Orchard/Orchard.Framework.csproj index a4a40d938..e9337076f 100644 --- a/src/Orchard/Orchard.Framework.csproj +++ b/src/Orchard/Orchard.Framework.csproj @@ -359,13 +359,18 @@ Code + + + + + @@ -379,8 +384,6 @@ - - From fb87fb9dd42be8ebf5e6e6f0d71e6d8fd66d989d Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Mon, 5 Jul 2010 14:41:56 -0700 Subject: [PATCH 2/6] Code clean up --HG-- branch : dev --- src/Orchard.Tests/DataMigration/SchemaBuilderTests.cs | 1 - .../Orchard.DevTools/Commands/ScaffoldingCommands.cs | 8 -------- .../Modules/Orchard.Indexing/Orchard.Indexing.csproj | 2 +- src/Orchard/Data/Migration/DataMigrationManager.cs | 4 ---- .../Data/Migration/Generator/SchemaCommandGenerator.cs | 6 ++---- src/Orchard/Data/SessionFactoryHolder.cs | 6 +----- 6 files changed, 4 insertions(+), 23 deletions(-) diff --git a/src/Orchard.Tests/DataMigration/SchemaBuilderTests.cs b/src/Orchard.Tests/DataMigration/SchemaBuilderTests.cs index 2053bffc1..a0ee24ec7 100644 --- a/src/Orchard.Tests/DataMigration/SchemaBuilderTests.cs +++ b/src/Orchard.Tests/DataMigration/SchemaBuilderTests.cs @@ -1,5 +1,4 @@ using System.Data; -using System.Linq; using Autofac; using NHibernate; using NUnit.Framework; diff --git a/src/Orchard.Web/Modules/Orchard.DevTools/Commands/ScaffoldingCommands.cs b/src/Orchard.Web/Modules/Orchard.DevTools/Commands/ScaffoldingCommands.cs index f929d33bc..6422474da 100644 --- a/src/Orchard.Web/Modules/Orchard.DevTools/Commands/ScaffoldingCommands.cs +++ b/src/Orchard.Web/Modules/Orchard.DevTools/Commands/ScaffoldingCommands.cs @@ -3,9 +3,7 @@ using System.IO; using System.Linq; using System.Web.Hosting; using Orchard.Commands; -using Orchard.Data.Migration; using Orchard.Data.Migration.Generator; -using Orchard.Data.Migration.Interpreters; using Orchard.DevTools.Services; using Orchard.Environment.Extensions; @@ -13,17 +11,11 @@ namespace Orchard.DevTools.Commands { [OrchardFeature("Scaffolding")] public class ScaffoldingCommands : DefaultOrchardCommandHandler { private readonly IExtensionManager _extensionManager; - private readonly IDataMigrationManager _dataMigrationManager; - private readonly IDataMigrationInterpreter _dataMigrationInterpreter; private readonly ISchemaCommandGenerator _schemaCommandGenerator; public ScaffoldingCommands(IExtensionManager extensionManager, - IDataMigrationManager dataMigrationManager, - IDataMigrationInterpreter dataMigrationInterpreter, ISchemaCommandGenerator schemaCommandGenerator) { _extensionManager = extensionManager; - _dataMigrationManager = dataMigrationManager; - _dataMigrationInterpreter = dataMigrationInterpreter; _schemaCommandGenerator = schemaCommandGenerator; } diff --git a/src/Orchard.Web/Modules/Orchard.Indexing/Orchard.Indexing.csproj b/src/Orchard.Web/Modules/Orchard.Indexing/Orchard.Indexing.csproj index 079d90f0e..ccc3e3f4d 100644 --- a/src/Orchard.Web/Modules/Orchard.Indexing/Orchard.Indexing.csproj +++ b/src/Orchard.Web/Modules/Orchard.Indexing/Orchard.Indexing.csproj @@ -64,7 +64,7 @@ - + diff --git a/src/Orchard/Data/Migration/DataMigrationManager.cs b/src/Orchard/Data/Migration/DataMigrationManager.cs index 163d07e84..9a29521a8 100644 --- a/src/Orchard/Data/Migration/DataMigrationManager.cs +++ b/src/Orchard/Data/Migration/DataMigrationManager.cs @@ -3,15 +3,11 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text.RegularExpressions; -using FluentNHibernate.Cfg; -using NHibernate.Tool.hbm2ddl; using Orchard.Data.Migration.Generator; using Orchard.Data.Migration.Interpreters; using Orchard.Data.Migration.Records; using Orchard.Data.Migration.Schema; -using Orchard.Data.Providers; using Orchard.Environment.Extensions; -using Orchard.Environment.ShellBuilders.Models; using Orchard.Environment.State; using Orchard.Logging; diff --git a/src/Orchard/Data/Migration/Generator/SchemaCommandGenerator.cs b/src/Orchard/Data/Migration/Generator/SchemaCommandGenerator.cs index c9c462dc7..51e1a6353 100644 --- a/src/Orchard/Data/Migration/Generator/SchemaCommandGenerator.cs +++ b/src/Orchard/Data/Migration/Generator/SchemaCommandGenerator.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using System.Reflection; using NHibernate.Cfg; @@ -8,7 +7,6 @@ using NHibernate.Tool.hbm2ddl; using Orchard.Data.Migration.Schema; using Orchard.Data.Providers; using NHibernate.Dialect; -using Orchard.Environment.Extensions; namespace Orchard.Data.Migration.Generator { public class SchemaCommandGenerator : ISchemaCommandGenerator { @@ -30,7 +28,7 @@ namespace Orchard.Data.Migration.Generator { } var configuration = _dataServicesProviderFactory.CreateProvider(parameters).BuildConfiguration(parameters); - var dialect = Dialect.GetDialect(configuration.Properties); + Dialect.GetDialect(configuration.Properties); var mapping = configuration.BuildMapping(); // get the tables using reflection diff --git a/src/Orchard/Data/SessionFactoryHolder.cs b/src/Orchard/Data/SessionFactoryHolder.cs index d5ab906ff..c7a41d5cf 100644 --- a/src/Orchard/Data/SessionFactoryHolder.cs +++ b/src/Orchard/Data/SessionFactoryHolder.cs @@ -1,10 +1,6 @@ -using System; -using System.IO; -using NHibernate; +using NHibernate; using Orchard.Data.Providers; using Orchard.Environment.Configuration; -using Orchard.Environment.Descriptor; -using Orchard.Environment.Descriptor.Models; using Orchard.Environment.ShellBuilders.Models; using Orchard.FileSystems.AppData; using Orchard.Localization; From 48c00c30a4eed896e6ecd9b232c1316d431a757a Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Tue, 6 Jul 2010 11:35:38 -0700 Subject: [PATCH 3/6] Added better UI for Data migration developer tools --HG-- branch : dev --- .../Controllers/DataMigrationController.cs | 31 ++++++++++++++----- .../Orchard.DevTools/Orchard.DevTools.csproj | 1 - .../ViewModels/DataMigrationIndexViewModel.cs | 6 ---- .../Views/DataMigration/Index.aspx | 12 +++---- .../Orchard.DevTools/Views/Home/Index.aspx | 2 +- 5 files changed, 28 insertions(+), 24 deletions(-) delete mode 100644 src/Orchard.Web/Modules/Orchard.DevTools/ViewModels/DataMigrationIndexViewModel.cs diff --git a/src/Orchard.Web/Modules/Orchard.DevTools/Controllers/DataMigrationController.cs b/src/Orchard.Web/Modules/Orchard.DevTools/Controllers/DataMigrationController.cs index 443319d54..e2488d413 100644 --- a/src/Orchard.Web/Modules/Orchard.DevTools/Controllers/DataMigrationController.cs +++ b/src/Orchard.Web/Modules/Orchard.DevTools/Controllers/DataMigrationController.cs @@ -1,23 +1,38 @@ -using System.Web.Mvc; +using System; +using System.Web.Mvc; using Orchard.Data.Migration.Generator; -using Orchard.DevTools.ViewModels; +using Orchard.Localization; +using Orchard.Mvc.ViewModels; +using Orchard.UI.Notify; namespace Orchard.DevTools.Controllers { [ValidateInput(false)] public class DataMigrationController : Controller { private readonly ISchemaCommandGenerator _schemaCommandGenerator; - public DataMigrationController(ISchemaCommandGenerator schemaCommandGenerator) { + public DataMigrationController(ISchemaCommandGenerator schemaCommandGenerator, IOrchardServices orchardServices) { _schemaCommandGenerator = schemaCommandGenerator; + Services = orchardServices; } + public IOrchardServices Services { get; set; } + public Localizer T { get; set; } + public ActionResult Index() { - var model = new DataMigrationIndexViewModel (); - - _schemaCommandGenerator.UpdateDatabase(); - - return View(model); + return View(new BaseViewModel()); } + public ActionResult UpdateDatabase() { + try { + + _schemaCommandGenerator.UpdateDatabase(); + Services.Notifier.Information(T("Database updated successfuly")); + } + catch (Exception ex) { + Services.Notifier.Error(T("An error occured while updating the database: {0}", ex.Message)); + } + + return RedirectToAction("Index"); + } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.DevTools/Orchard.DevTools.csproj b/src/Orchard.Web/Modules/Orchard.DevTools/Orchard.DevTools.csproj index 024727911..073d0e9c7 100644 --- a/src/Orchard.Web/Modules/Orchard.DevTools/Orchard.DevTools.csproj +++ b/src/Orchard.Web/Modules/Orchard.DevTools/Orchard.DevTools.csproj @@ -86,7 +86,6 @@ -
diff --git a/src/Orchard.Web/Modules/Orchard.DevTools/ViewModels/DataMigrationIndexViewModel.cs b/src/Orchard.Web/Modules/Orchard.DevTools/ViewModels/DataMigrationIndexViewModel.cs deleted file mode 100644 index bf5b7e0a1..000000000 --- a/src/Orchard.Web/Modules/Orchard.DevTools/ViewModels/DataMigrationIndexViewModel.cs +++ /dev/null @@ -1,6 +0,0 @@ -using Orchard.Mvc.ViewModels; - -namespace Orchard.DevTools.ViewModels { - public class DataMigrationIndexViewModel : BaseViewModel { - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.DevTools/Views/DataMigration/Index.aspx b/src/Orchard.Web/Modules/Orchard.DevTools/Views/DataMigration/Index.aspx index 962308436..b02ec3b03 100644 --- a/src/Orchard.Web/Modules/Orchard.DevTools/Views/DataMigration/Index.aspx +++ b/src/Orchard.Web/Modules/Orchard.DevTools/Views/DataMigration/Index.aspx @@ -1,9 +1,5 @@ -<%@ Page Language="C#" Inherits="Orchard.Mvc.ViewPage" %> +<%@ Page Language="C#" Inherits="Orchard.Mvc.ViewPage"%> +<%@ Import Namespace="Orchard.Mvc.ViewModels"%> +

<%: Html.TitleForPage(T("Data migration").ToString()) %>

+

<%: Html.ActionLink(T("Update database").ToString(), "UpdateDatabase", "DataMigration") %>

- -

Data Migration

diff --git a/src/Orchard.Web/Modules/Orchard.DevTools/Views/Home/Index.aspx b/src/Orchard.Web/Modules/Orchard.DevTools/Views/Home/Index.aspx index 5b1a2def6..3e7859f27 100644 --- a/src/Orchard.Web/Modules/Orchard.DevTools/Views/Home/Index.aspx +++ b/src/Orchard.Web/Modules/Orchard.DevTools/Views/Home/Index.aspx @@ -4,4 +4,4 @@

<%: Html.ActionLink(T("Contents").ToString(), "Index", "Content") %>

<%: Html.ActionLink(T("Metadata").ToString(), "Index", "Metadata") %>

<%: Html.ActionLink(T("Test Unauthorized Request").ToString(), "NotAuthorized", "Home")%>

- +

<%: Html.ActionLink(T("Data migration").ToString(), "Index", "DataMigration")%>

From 4ed7964cbf58258755a7715aaa6fef0d39e65e80 Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Tue, 6 Jul 2010 11:39:26 -0700 Subject: [PATCH 4/6] Added menu item for developer tools --HG-- branch : dev --- src/Orchard.Web/Modules/Orchard.DevTools/AdminMenu.cs | 9 +++++++-- .../Orchard.DevTools/Views/DataMigration/Index.aspx | 4 ++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.DevTools/AdminMenu.cs b/src/Orchard.Web/Modules/Orchard.DevTools/AdminMenu.cs index 92029ca21..c3a7cb9b9 100644 --- a/src/Orchard.Web/Modules/Orchard.DevTools/AdminMenu.cs +++ b/src/Orchard.Web/Modules/Orchard.DevTools/AdminMenu.cs @@ -1,11 +1,16 @@ -using Orchard.UI.Navigation; +using Orchard.Localization; +using Orchard.UI.Navigation; namespace Orchard.DevTools { public class AdminMenu : INavigationProvider { public string MenuName { get { return "admin"; } } + public Localizer T { get; set; } public void GetNavigation(NavigationBuilder builder) { - + builder.Add(T("Site Configuration"), "11", + menu => menu + .Add(T("Developer Tools"), "10.0", item => item.Action("Index", "Home", new { area = "Orchard.DevTools" }) + )); } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.DevTools/Views/DataMigration/Index.aspx b/src/Orchard.Web/Modules/Orchard.DevTools/Views/DataMigration/Index.aspx index b02ec3b03..7a5ba876d 100644 --- a/src/Orchard.Web/Modules/Orchard.DevTools/Views/DataMigration/Index.aspx +++ b/src/Orchard.Web/Modules/Orchard.DevTools/Views/DataMigration/Index.aspx @@ -1,5 +1,5 @@ <%@ Page Language="C#" Inherits="Orchard.Mvc.ViewPage"%> <%@ Import Namespace="Orchard.Mvc.ViewModels"%> -

<%: Html.TitleForPage(T("Data migration").ToString()) %>

-

<%: Html.ActionLink(T("Update database").ToString(), "UpdateDatabase", "DataMigration") %>

+

<%: Html.TitleForPage(T("Data Migration").ToString()) %>

+

<%: Html.ActionLink(T("Update Database").ToString(), "UpdateDatabase", "DataMigration") %>

From 8b9a8e14ea601ae27a0be81f5ec7547d75ea2652 Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Tue, 6 Jul 2010 12:51:26 -0700 Subject: [PATCH 5/6] Features list display link to update schema if available --HG-- branch : dev --- .../Controllers/AdminController.cs | 28 +++++++++++++++++-- .../ViewModels/FeaturesViewModel.cs | 1 + .../Orchard.Modules/Views/Admin/Features.ascx | 12 ++++++-- .../Modules/Orchard.Modules/styles/admin.css | 12 +++++++- .../Data/Migration/DataMigrationManager.cs | 6 +--- 5 files changed, 49 insertions(+), 10 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.Modules/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.Modules/Controllers/AdminController.cs index 228a1ffce..c9edbd46a 100644 --- a/src/Orchard.Web/Modules/Orchard.Modules/Controllers/AdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.Modules/Controllers/AdminController.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Web; using System.Web.Mvc; +using Orchard.Data.Migration; using Orchard.Localization; using Orchard.Modules.ViewModels; using Orchard.Mvc.Results; @@ -11,10 +12,12 @@ using Orchard.Utility.Extensions; namespace Orchard.Modules.Controllers { public class AdminController : Controller { private readonly IModuleService _moduleService; + private readonly IDataMigrationManager _dataMigrationManager; - public AdminController(IOrchardServices services, IModuleService moduleService) { + public AdminController(IOrchardServices services, IModuleService moduleService, IDataMigrationManager dataMigrationManager) { Services = services; _moduleService = moduleService; + _dataMigrationManager = dataMigrationManager; T = NullLocalizer.Instance; } @@ -68,7 +71,9 @@ namespace Orchard.Modules.Controllers { return new HttpUnauthorizedResult(); var features = _moduleService.GetAvailableFeatures().ToList(); - return View(new FeaturesViewModel {Features = features}); + var featuresThatNeedUpdate = _dataMigrationManager.GetFeaturesThatNeedUpdate(); + + return View(new FeaturesViewModel { Features = features, FeaturesThatNeedUpdate = featuresThatNeedUpdate }); } [HttpPost] @@ -96,5 +101,24 @@ namespace Orchard.Modules.Controllers { return RedirectToAction("Features"); } + + [HttpPost] + public ActionResult Update(string id, bool? force) { + if ( !Services.Authorizer.Authorize(Permissions.ManageFeatures, T("Not allowed to manage features")) ) + return new HttpUnauthorizedResult(); + + if ( string.IsNullOrEmpty(id) ) + return new NotFoundResult(); + + try { + _dataMigrationManager.Update(id); + Services.Notifier.Information(T("The feature {0} was updated succesfuly", id)); + } + catch(Exception ex) { + Services.Notifier.Error(T("An error occured while updating the feature {0}: {1}", id, ex.Message)); + } + + return RedirectToAction("Features"); + } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Modules/ViewModels/FeaturesViewModel.cs b/src/Orchard.Web/Modules/Orchard.Modules/ViewModels/FeaturesViewModel.cs index fc98504a8..028bd671c 100644 --- a/src/Orchard.Web/Modules/Orchard.Modules/ViewModels/FeaturesViewModel.cs +++ b/src/Orchard.Web/Modules/Orchard.Modules/ViewModels/FeaturesViewModel.cs @@ -4,5 +4,6 @@ using Orchard.Mvc.ViewModels; namespace Orchard.Modules.ViewModels { public class FeaturesViewModel : BaseViewModel { public IEnumerable Features { get; set; } + public IEnumerable FeaturesThatNeedUpdate { get; set; } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Features.ascx b/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Features.ascx index 8c0184511..0b660d61c 100644 --- a/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Features.ascx +++ b/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Features.ascx @@ -29,7 +29,7 @@ //hmmm...I feel like I've done this before... var featureId = feature.Descriptor.Name.AsFeatureId(n => T(n)); var featureState = feature.IsEnabled ? "enabled" : "disabled"; - var featureClassName = string.Format("feature {0}", featureState); + var featureClassName = string.Format("feature {0}", featureState + (Model.FeaturesThatNeedUpdate.Contains(feature.Descriptor.Name) ? " update" : String.Empty)); if (feature == features.First()) featureClassName += " first"; if (feature == features.Last()) @@ -65,7 +65,15 @@ <%: Html.Hidden("force", true)%> <% } - } %> + } + if(Model.FeaturesThatNeedUpdate.Contains(feature.Descriptor.Name)){ + using (Html.BeginFormAntiForgeryPost(string.Format("{0}", Url.Action("Update", new { area = "Orchard.Modules" })), FormMethod.Post, new {@class = "inline link"})) { %> + <%: Html.Hidden("id", feature.Descriptor.Name, new { id = "" })%> + <%: Html.Hidden("force", true)%> + <% + } + } + %> <% } %> diff --git a/src/Orchard.Web/Modules/Orchard.Modules/styles/admin.css b/src/Orchard.Web/Modules/Orchard.Modules/styles/admin.css index 8aada2d0f..6c98fa853 100644 --- a/src/Orchard.Web/Modules/Orchard.Modules/styles/admin.css +++ b/src/Orchard.Web/Modules/Orchard.Modules/styles/admin.css @@ -110,6 +110,16 @@ top:.4em; } +a.update { + margin-left:.5em; +} +.features .update.feature { + background:#ecc; +} +.features.summary-view .update.feature { + border-color:#e77; +} + .cathedral { bottom:0; font-size:.8em; @@ -121,4 +131,4 @@ .cathedral a:visited, .cathedral form.inline.link button { color:#aeaeae; -} \ No newline at end of file +} diff --git a/src/Orchard/Data/Migration/DataMigrationManager.cs b/src/Orchard/Data/Migration/DataMigrationManager.cs index 9a29521a8..e4f7bf2c3 100644 --- a/src/Orchard/Data/Migration/DataMigrationManager.cs +++ b/src/Orchard/Data/Migration/DataMigrationManager.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text.RegularExpressions; -using Orchard.Data.Migration.Generator; using Orchard.Data.Migration.Interpreters; using Orchard.Data.Migration.Records; using Orchard.Data.Migration.Schema; @@ -20,20 +19,17 @@ namespace Orchard.Data.Migration { private readonly IRepository _dataMigrationRepository; private readonly IExtensionManager _extensionManager; private readonly IDataMigrationInterpreter _interpreter; - private readonly ISchemaCommandGenerator _generator; public DataMigrationManager( IEnumerable dataMigrations, IRepository dataMigrationRepository, IExtensionManager extensionManager, - IDataMigrationInterpreter interpreter, - ISchemaCommandGenerator generator + IDataMigrationInterpreter interpreter ) { _dataMigrations = dataMigrations; _dataMigrationRepository = dataMigrationRepository; _extensionManager = extensionManager; _interpreter = interpreter; - _generator = generator; Logger = NullLogger.Instance; } From e9a0e097320bcb27dbe11385999550101b88a445 Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Tue, 6 Jul 2010 13:55:20 -0700 Subject: [PATCH 6/6] Hide the Manage Content admin menu item --HG-- branch : dev --- src/Orchard.Web/Core/Contents/AdminMenu.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Orchard.Web/Core/Contents/AdminMenu.cs b/src/Orchard.Web/Core/Contents/AdminMenu.cs index 0851117cf..6eefc5d61 100644 --- a/src/Orchard.Web/Core/Contents/AdminMenu.cs +++ b/src/Orchard.Web/Core/Contents/AdminMenu.cs @@ -18,10 +18,10 @@ namespace Orchard.Core.Contents { public string MenuName { get { return "admin"; } } public void GetNavigation(NavigationBuilder builder) { - var contentTypeDefinitions = _contentDefinitionManager.ListTypeDefinitions().OrderBy(d => d.Name); + //var contentTypeDefinitions = _contentDefinitionManager.ListTypeDefinitions().OrderBy(d => d.Name); - builder.Add(T("Content"), "1", menu => { - menu.Add(T("Manage Content"), "1.2", item => item.Action("List", "Admin", new {area = "Orchard.ContentTypes"})); + //builder.Add(T("Content"), "1", menu => { + // menu.Add(T("Manage Content"), "1.2", item => item.Action("List", "Admin", new {area = "Orchard.ContentTypes"})); //foreach (var contentTypeDefinition in contentTypeDefinitions) { // var ci = _contentManager.New(contentTypeDefinition.Name); // var cim = _contentManager.GetItemMetadata(ci); @@ -29,7 +29,7 @@ namespace Orchard.Core.Contents { // if (createRouteValues.Any()) // menu.Add(T("Create New {0}", contentTypeDefinition.DisplayName), "1.3", item => item.Action(cim.CreateRouteValues["Action"] as string, cim.CreateRouteValues["Controller"] as string, cim.CreateRouteValues)); //} - }); + //}); } } } \ No newline at end of file