diff --git a/src/Orchard.Specs/Orchard.Specs.csproj b/src/Orchard.Specs/Orchard.Specs.csproj index 0d6693518..cdc4d4544 100644 --- a/src/Orchard.Specs/Orchard.Specs.csproj +++ b/src/Orchard.Specs/Orchard.Specs.csproj @@ -228,10 +228,6 @@ {9916839C-39FC-4CEB-A5AF-89CA7E87119F} Orchard.Core - - {67C1D3AF-A0EC-46B2-BAE1-DF1DA8E0B890} - Orchard.DevTools - {D10AD48F-407D-4DB5-A328-173EC7CB010F} Orchard.Roles diff --git a/src/Orchard.Tests.Modules/Orchard.Tests.Modules.csproj b/src/Orchard.Tests.Modules/Orchard.Tests.Modules.csproj index 82b375e1b..010a7cda9 100644 --- a/src/Orchard.Tests.Modules/Orchard.Tests.Modules.csproj +++ b/src/Orchard.Tests.Modules/Orchard.Tests.Modules.csproj @@ -106,6 +106,7 @@ + @@ -127,6 +128,10 @@ {9916839C-39FC-4CEB-A5AF-89CA7E87119F} Orchard.Core + + {C0C45321-B51D-4D8D-9B7B-AA4C2E0B2962} + Orchard.CodeGeneration + {D10AD48F-407D-4DB5-A328-173EC7CB010F} Orchard.Roles diff --git a/src/Orchard.Web/Modules/Orchard.CodeGeneration/CodeGenerationTemplates/Controller.txt b/src/Orchard.Web/Modules/Orchard.CodeGeneration/CodeGenerationTemplates/Controller.txt new file mode 100644 index 000000000..2e1d7a9e4 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.CodeGeneration/CodeGenerationTemplates/Controller.txt @@ -0,0 +1,16 @@ +using System.Web.Mvc; +using Orchard.Localization; +using Orchard; + +namespace $$ModuleName$$.Controllers { + public class $$ControllerName$$ : Controller { + public IOrchardServices Services { get; set; } + + public $$ControllerName$$(IOrchardServices services) { + Services = services; + T = NullLocalizer.Instance; + } + + public Localizer T { get; set; } + } +} diff --git a/src/Orchard.Web/Modules/Orchard.CodeGeneration/CodeGenerationTemplates/DataMigration.txt b/src/Orchard.Web/Modules/Orchard.CodeGeneration/CodeGenerationTemplates/DataMigration.txt new file mode 100644 index 000000000..e80ad786c --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.CodeGeneration/CodeGenerationTemplates/DataMigration.txt @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using Orchard.ContentManagement.Drivers; +using Orchard.ContentManagement.MetaData; +using Orchard.ContentManagement.MetaData.Builders; +using Orchard.Core.Contents.Extensions; +using Orchard.Data.Migration; + +namespace $$FeatureName$$.DataMigrations { + public class $$ClassName$$DataMigration : DataMigrationImpl { + + public int Create() { +$$Commands$$ + + return 1; + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.CodeGeneration/CodeGenerationTemplates/ModuleAssemblyInfo.txt b/src/Orchard.Web/Modules/Orchard.CodeGeneration/CodeGenerationTemplates/ModuleAssemblyInfo.txt new file mode 100644 index 000000000..22a4eceba --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.CodeGeneration/CodeGenerationTemplates/ModuleAssemblyInfo.txt @@ -0,0 +1,34 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("$$ModuleName$$")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyProduct("Orchard")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("$$ModuleTypeLibGuid$$")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/Orchard.Web/Modules/Orchard.CodeGeneration/CodeGenerationTemplates/ModuleCsProj.txt b/src/Orchard.Web/Modules/Orchard.CodeGeneration/CodeGenerationTemplates/ModuleCsProj.txt new file mode 100644 index 000000000..fd2336c8c --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.CodeGeneration/CodeGenerationTemplates/ModuleCsProj.txt @@ -0,0 +1,130 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {$$ModuleProjectGuid$$} + {F85E285D-A4E0-4152-9332-AB1D724D3325};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + $$ModuleName$$ + $$ModuleName$$ + v4.0 + false + + + 3.5 + + + + + true + full + false + bin\ + DEBUG;TRACE + prompt + 4 + AllRules.ruleset + + + pdbonly + true + bin\ + TRACE + prompt + 4 + AllRules.ruleset + + + + + + 3.5 + + + + + + + + False + ..\..\..\..\lib\aspnetmvc\System.Web.Mvc.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6} + Orchard.Framework + + + {9916839C-39FC-4CEB-A5AF-89CA7E87119F} + Orchard.Core + + + + + + + + $(ProjectDir)\..\Manifests + + + + + + + + + + + + False + True + 45979 + / + + + False + True + http://orchard.codeplex.com + False + + + + + \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.CodeGeneration/CodeGenerationTemplates/ModuleManifest.txt b/src/Orchard.Web/Modules/Orchard.CodeGeneration/CodeGenerationTemplates/ModuleManifest.txt new file mode 100644 index 000000000..193964f30 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.CodeGeneration/CodeGenerationTemplates/ModuleManifest.txt @@ -0,0 +1,10 @@ +name: $$ModuleName$$ +antiforgery: enabled +author: The Orchard Team +website: http://orchardproject.net +version: 0.5.0 +orchardversion: 0.5.0 +description: Description for the module +features: + $$ModuleName$$: + Description: Description for feature $$ModuleName$$. \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.CodeGeneration/CodeGenerationTemplates/ModuleWebConfig.txt b/src/Orchard.Web/Modules/Orchard.CodeGeneration/CodeGenerationTemplates/ModuleWebConfig.txt new file mode 100644 index 000000000..87bf40af5 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.CodeGeneration/CodeGenerationTemplates/ModuleWebConfig.txt @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Orchard.Web/Modules/Orchard.CodeGeneration/CodeGenerationTemplates/ViewsWebConfig.txt b/src/Orchard.Web/Modules/Orchard.CodeGeneration/CodeGenerationTemplates/ViewsWebConfig.txt new file mode 100644 index 000000000..7022197d4 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.CodeGeneration/CodeGenerationTemplates/ViewsWebConfig.txt @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Orchard.Web/Modules/Orchard.CodeGeneration/Commands/CodeGenerationCommands.cs b/src/Orchard.Web/Modules/Orchard.CodeGeneration/Commands/CodeGenerationCommands.cs new file mode 100644 index 000000000..caed8bf12 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.CodeGeneration/Commands/CodeGenerationCommands.cs @@ -0,0 +1,228 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Web.Hosting; +using Orchard.Commands; +using Orchard.Data.Migration.Generator; +using Orchard.CodeGeneration.Services; +using Orchard.Data.Migration.Schema; +using Orchard.Environment.Extensions; +using Orchard.Environment.Extensions.Models; + +namespace Orchard.CodeGeneration.Commands { + + [OrchardFeature("Generate")] + public class CodeGenerationCommands : DefaultOrchardCommandHandler { + private readonly IExtensionManager _extensionManager; + private readonly ISchemaCommandGenerator _schemaCommandGenerator; + + private const string ModuleName = "CodeGeneration"; + + public CodeGenerationCommands( + IExtensionManager extensionManager, + ISchemaCommandGenerator schemaCommandGenerator) { + _extensionManager = extensionManager; + _schemaCommandGenerator = schemaCommandGenerator; + } + + [OrchardSwitch] + public bool IncludeInSolution { get; set; } + + [CommandHelp("generate create datamigration \r\n\t" + "Create a new Data Migration class")] + [CommandName("generate create datamigration")] + public void CreateDataMigration(string featureName) { + Context.Output.WriteLine(T("Creating Data Migration for {0}", featureName)); + + ExtensionDescriptor extensionDescriptor = _extensionManager.AvailableExtensions().FirstOrDefault(extension => extension.ExtensionType == "Module" && + extension.Features.Any(feature => String.Equals(feature.Name, featureName, StringComparison.OrdinalIgnoreCase))); + + if (extensionDescriptor == null) { + Context.Output.WriteLine(T("Creating data migration failed: target Feature {0} could not be found.", featureName)); + return; + } + + string dataMigrationsPath = HostingEnvironment.MapPath("~/Modules/" + extensionDescriptor.Name + "/DataMigrations/"); + string dataMigrationPath = dataMigrationsPath + extensionDescriptor.DisplayName + "DataMigration.cs"; + string templatesPath = HostingEnvironment.MapPath("~/Modules/Orchard." + ModuleName + "/CodeGenerationTemplates/"); + string moduleCsProjPath = HostingEnvironment.MapPath(string.Format("~/Modules/{0}/{0}.csproj", extensionDescriptor.Name)); + + if (!Directory.Exists(dataMigrationsPath)) { + Directory.CreateDirectory(dataMigrationsPath); + } + + if (File.Exists(dataMigrationPath)) { + Context.Output.WriteLine(T("Data migration already exists in target Module {0}.", extensionDescriptor.Name)); + return; + } + + List commands = _schemaCommandGenerator.GetCreateFeatureCommands(featureName, false).ToList(); + + var stringWriter = new StringWriter(); + var interpreter = new CodeGenerationCommandInterpreter(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$$", extensionDescriptor.DisplayName); + dataMigrationText = dataMigrationText.Replace("$$Commands$$", stringWriter.ToString()); + File.WriteAllText(dataMigrationPath, dataMigrationText); + + string projectFileText = File.ReadAllText(moduleCsProjPath); + + // The string searches in solution/project files can be made aware of comment lines. + if ( projectFileText.Contains("\r\n ", "DataMigrations\\" + extensionDescriptor.DisplayName + "DataMigration.cs"); + projectFileText = projectFileText.Insert(projectFileText.LastIndexOf("\r\n \r\n \r\n ", "DataMigrations\\" + extensionDescriptor.DisplayName + "DataMigration.cs"); + projectFileText = projectFileText.Insert(projectFileText.LastIndexOf(""), itemGroupReference); + } + + File.WriteAllText(moduleCsProjPath, projectFileText); + TouchSolution(); + Context.Output.WriteLine(T("Data migration created successfully in Module {0}", extensionDescriptor.Name)); + } + + [CommandHelp("generate create module [/IncludeInSolution:true|false]\r\n\t" + "Create a new Orchard module")] + [CommandName("generate 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)) ) { + Context.Output.WriteLine(T("Creating Module {0} failed: a module of the same name already exists", moduleName)); + return; + } + + IntegrateModule(moduleName); + Context.Output.WriteLine(T("Module {0} created successfully", moduleName)); + } + + + [CommandHelp("generate create controller \r\n\t" + "Create a new Orchard controller in a module")] + [CommandName("generate create controller")] + public void CreateController(string moduleName, string controllerName) { + Context.Output.WriteLine(T("Creating Controller {0} in Module {1}", controllerName, moduleName)); + + ExtensionDescriptor extensionDescriptor = _extensionManager.AvailableExtensions().FirstOrDefault(extension => extension.ExtensionType == "Module" && + string.Equals(moduleName, extension.DisplayName, StringComparison.OrdinalIgnoreCase)); + + if (extensionDescriptor == null) { + Context.Output.WriteLine(T("Creating Controller {0} failed: target Module {1} could not be found.", controllerName, moduleName)); + return; + } + + string moduleControllersPath = HostingEnvironment.MapPath("~/Modules/" + extensionDescriptor.Name + "/Controllers/"); + string controllerPath = moduleControllersPath + controllerName + ".cs"; + string moduleCsProjPath = HostingEnvironment.MapPath(string.Format("~/Modules/{0}/{0}.csproj", extensionDescriptor.Name)); + string templatesPath = HostingEnvironment.MapPath("~/Modules/Orchard." + ModuleName + "/CodeGenerationTemplates/"); + + if (!Directory.Exists(moduleControllersPath)) { + Directory.CreateDirectory(moduleControllersPath); + } + if (File.Exists(controllerPath)) { + Context.Output.WriteLine(T("Controller {0} already exists in target Module {1}.", controllerName, moduleName)); + return; + } + + string controllerText = File.ReadAllText(templatesPath + "Controller.txt"); + controllerText = controllerText.Replace("$$ModuleName$$", moduleName); + controllerText = controllerText.Replace("$$ControllerName$$", controllerName); + File.WriteAllText(controllerPath, controllerText); + string projectFileText = File.ReadAllText(moduleCsProjPath); + + // The string searches in solution/project files can be made aware of comment lines. + if (projectFileText.Contains("\r\n ", "Controllers\\" + controllerName + ".cs"); + projectFileText = projectFileText.Insert(projectFileText.LastIndexOf("\r\n \r\n \r\n ", "Controllers\\" + controllerName + ".cs"); + projectFileText = projectFileText.Insert(projectFileText.LastIndexOf(""), itemGroupReference); + } + + File.WriteAllText(moduleCsProjPath, projectFileText); + Context.Output.WriteLine(T("Controller {0} created successfully in Module {1}", controllerName, moduleName)); + TouchSolution(); + } + + private void IntegrateModule(string moduleName) { + string rootWebProjectPath = HostingEnvironment.MapPath("~/Orchard.Web.csproj"); + string projectGuid = Guid.NewGuid().ToString().ToUpper(); + + CreateFilesFromTemplates(moduleName, projectGuid); + // The string searches in solution/project files can be made aware of comment lines. + if (IncludeInSolution) { + // Add project to Orchard.sln + string solutionPath = Directory.GetParent(rootWebProjectPath).Parent.FullName + "\\Orchard.sln"; + if (File.Exists(solutionPath)) { + string projectReference = string.Format( + "EndProject\r\nProject(\"{{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}}\") = \"{0}\", \"Orchard.Web\\Modules\\{0}\\{0}.csproj\", \"{{{1}}}\"\r\n", + moduleName, projectGuid); + string projectConfiguationPlatforms = string.Format( + "GlobalSection(ProjectConfigurationPlatforms) = postSolution\r\n\t\t{{{0}}}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{{{0}}}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{{{0}}}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{{{0}}}.Release|Any CPU.Build.0 = Release|Any CPU\r\n", + projectGuid); + string solutionText = File.ReadAllText(solutionPath); + solutionText = solutionText.Insert(solutionText.LastIndexOf("EndProject\r\n"), projectReference); + solutionText = solutionText.Replace("GlobalSection(ProjectConfigurationPlatforms) = postSolution\r\n", projectConfiguationPlatforms); + solutionText = solutionText.Insert(solutionText.LastIndexOf("EndGlobalSection"), "\t{" + projectGuid + "} = {E9C9F120-07BA-4DFB-B9C3-3AFB9D44C9D5}\r\n\t"); + + File.WriteAllText(solutionPath, solutionText); + TouchSolution(); + } + else { + Context.Output.WriteLine(T("Warning: Solution file could not be found at {0}", solutionPath)); + } + } + } + + private static void CreateFilesFromTemplates(string moduleName, string projectGuid) { + string modulePath = HostingEnvironment.MapPath("~/Modules/" + moduleName + "/"); + string propertiesPath = modulePath + "Properties"; + string templatesPath = HostingEnvironment.MapPath("~/Modules/Orchard." + ModuleName + "/CodeGenerationTemplates/"); + + Directory.CreateDirectory(modulePath); + Directory.CreateDirectory(propertiesPath); + Directory.CreateDirectory(modulePath + "Controllers"); + Directory.CreateDirectory(modulePath + "Views"); + File.WriteAllText(modulePath + "\\Views\\Web.config", File.ReadAllText(templatesPath + "ViewsWebConfig.txt")); + Directory.CreateDirectory(modulePath + "Models"); + Directory.CreateDirectory(modulePath + "Scripts"); + + string templateText = File.ReadAllText(templatesPath + "ModuleAssemblyInfo.txt"); + templateText = templateText.Replace("$$ModuleName$$", moduleName); + templateText = templateText.Replace("$$ModuleTypeLibGuid$$", Guid.NewGuid().ToString()); + File.WriteAllText(propertiesPath + "\\AssemblyInfo.cs", templateText); + File.WriteAllText(modulePath + "\\Web.config", File.ReadAllText(templatesPath + "ModuleWebConfig.txt")); + templateText = File.ReadAllText(templatesPath + "ModuleManifest.txt"); + templateText = templateText.Replace("$$ModuleName$$", moduleName); + File.WriteAllText(modulePath + "\\Module.txt", templateText); + templateText = File.ReadAllText(templatesPath + "\\ModuleCsProj.txt"); + templateText = templateText.Replace("$$ModuleName$$", moduleName); + templateText = templateText.Replace("$$ModuleProjectGuid$$", projectGuid); + File.WriteAllText(modulePath + "\\" + moduleName + ".csproj", templateText); + } + + private void TouchSolution() { + string rootWebProjectPath = HostingEnvironment.MapPath("~/Orchard.Web.csproj"); + string solutionPath = Directory.GetParent(rootWebProjectPath).Parent.FullName + "\\Orchard.sln"; + if (!File.Exists(solutionPath)) { + Context.Output.WriteLine(T("Warning: Solution file could not be found at {0}", solutionPath)); + return; + } + + try { + File.SetLastWriteTime(solutionPath, DateTime.Now); + } + catch { + Context.Output.WriteLine(T("An unexpected error occured while trying to refresh the Visual Studio solution. Please reload it.")); + } + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.CodeGeneration/Module.txt b/src/Orchard.Web/Modules/Orchard.CodeGeneration/Module.txt new file mode 100644 index 000000000..bddae50b7 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.CodeGeneration/Module.txt @@ -0,0 +1,11 @@ +Name: Code generation module +antiforgery: enabled +author: The Orchard Team +website: http://orchardproject.net +version: 0.1.0 +orchardversion: 0.6.0 +description: +features: + Generate: + Description: Tools to create Orchard components. + Category: Developer \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.CodeGeneration/Orchard.CodeGeneration.csproj b/src/Orchard.Web/Modules/Orchard.CodeGeneration/Orchard.CodeGeneration.csproj new file mode 100644 index 000000000..faef74dd8 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.CodeGeneration/Orchard.CodeGeneration.csproj @@ -0,0 +1,128 @@ + + + + Debug + AnyCPU + + + 2.0 + {C0C45321-B51D-4D8D-9B7B-AA4C2E0B2962} + {F85E285D-A4E0-4152-9332-AB1D724D3325};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + Orchard.CodeGeneration + Orchard.CodeGeneration + v4.0 + false + + + true + full + false + bin\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\ + TRACE + prompt + 4 + + + + ..\..\..\..\lib\nhprof\HibernatingRhinos.Profiler.Appender.dll + + + + + + + + + + 3.5 + + + 3.5 + + + 3.5 + + + False + ..\..\..\..\lib\aspnetmvc\System.Web.Mvc.dll + + + 3.5 + + + + 3.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + {2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6} + Orchard.Framework + + + {9916839C-39FC-4CEB-A5AF-89CA7E87119F} + Orchard.Core + + + + + + + + + + + + + False + True + 53274 + / + + + False + False + + + False + + + + + \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.CodeGeneration/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.CodeGeneration/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..979584f46 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.CodeGeneration/Properties/AssemblyInfo.cs @@ -0,0 +1,33 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Orchard.CodeGeneration")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyProduct("Orchard")] +[assembly: AssemblyCopyright("Copyright © CodePlex Foundation 2009")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("a5ae5869-1454-4fe8-a998-a3f2e79c91a3")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("0.5.0")] +[assembly: AssemblyFileVersion("0.5.0")] \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.CodeGeneration/Services/CodeGenerationCommandInterpreter.cs b/src/Orchard.Web/Modules/Orchard.CodeGeneration/Services/CodeGenerationCommandInterpreter.cs new file mode 100644 index 000000000..a4907ed47 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.CodeGeneration/Services/CodeGenerationCommandInterpreter.cs @@ -0,0 +1,111 @@ +using System.Collections.Generic; +using System.Data; +using System.IO; +using System.Linq; +using Orchard.Data.Migration.Interpreters; +using Orchard.Data.Migration.Schema; + +namespace Orchard.CodeGeneration.Services { + public class CodeGenerationCommandInterpreter : AbstractDataMigrationInterpreter { + private readonly TextWriter _output; + + public CodeGenerationCommandInterpreter(TextWriter output) { + _output = output; + } + + public override void Visit(CreateTableCommand command) { + _output.WriteLine("\t\t\t// Creating table {0}", command.Name); + _output.WriteLine("\t\t\tSchemaBuilder.CreateTable(\"{0}\", table => table", command.Name); + + var matchContentPartRecord = command.TableCommands.OfType().Any( + c => + c.IsPrimaryKey + && c.ColumnName == "Id" + && !c.IsIdentity + && c.DbType == DbType.Int32); + + var matchContentPartVersionRecord = matchContentPartRecord && command.TableCommands.OfType().Any( + c => + c.ColumnName == "ContentItemRecord_id" + && c.DbType == DbType.Int32); + + if ( matchContentPartVersionRecord ) { + _output.WriteLine("\t\t\t\t.ContentPartVersionRecord()"); + } + else if ( matchContentPartRecord ) { + _output.WriteLine("\t\t\t\t.ContentPartRecord()"); + } + + foreach ( var createColumn in command.TableCommands.OfType() ) { + if(createColumn.ColumnName == "Id" && matchContentPartRecord) { + continue; + } + + if(createColumn.ColumnName == "ContentItemRecord_id" && matchContentPartVersionRecord) { + continue; + } + + var type = createColumn.DbType.ToString(); + var field = createColumn.ColumnName; + var options = new List(); + + if ( createColumn.IsPrimaryKey ) { + options.Add("PrimaryKey()"); + } + + if ( createColumn.IsIdentity ) { + options.Add("Identity()"); + } + + if ( createColumn.IsUnique ) { + options.Add("Unique()"); + } + + if ( createColumn.IsNotNull ) { + options.Add("NotNull()"); + } + + if ( createColumn.Length.HasValue ) { + if ( createColumn.Length == 10000 ) { + options.Add("Unlimited()"); + } + else { + 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.CodeGeneration/Web.config b/src/Orchard.Web/Modules/Orchard.CodeGeneration/Web.config new file mode 100644 index 000000000..97c1c726a --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.CodeGeneration/Web.config @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Orchard.sln b/src/Orchard.sln index b85065f36..d37cab7bb 100644 --- a/src/Orchard.sln +++ b/src/Orchard.sln @@ -27,8 +27,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.Core", "Orchard.Web EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.Core.Tests", "Orchard.Core.Tests\Orchard.Core.Tests.csproj", "{2FC1D9C8-446D-4414-B252-5E9FBE61EB63}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.DevTools", "Orchard.Web\Modules\Orchard.DevTools\Orchard.DevTools.csproj", "{67C1D3AF-A0EC-46B2-BAE1-DF1DA8E0B890}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.Setup", "Orchard.Web\Modules\Orchard.Setup\Orchard.Setup.csproj", "{8C7FCBC2-E6E1-405E-BFB5-D8D9E67A09C4}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MSBuild.Orchard.Tasks", "Tools\MSBuild.Orchard.Tasks\MSBuild.Orchard.Tasks.csproj", "{5E5E7A21-C7B2-44D8-8593-2F9541AE041D}" @@ -84,6 +82,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Futures.Widgets", "Orchard. EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lucene", "Orchard.Web\Modules\Lucene\Lucene.csproj", "{D5D447D7-EF8E-43A6-B9A4-3B025DD9F45D}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.Experimental", "Orchard.Web\Modules\Orchard.Experimental\Orchard.Experimental.csproj", "{AB3C207C-0126-4143-8D62-1119DF80D366}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.CodeGeneration", "Orchard.Web\Modules\Orchard.CodeGeneration\Orchard.CodeGeneration.csproj", "{C0C45321-B51D-4D8D-9B7B-AA4C2E0B2962}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution CodeCoverage|Any CPU = CodeCoverage|Any CPU @@ -183,16 +185,6 @@ Global {2FC1D9C8-446D-4414-B252-5E9FBE61EB63}.FxCop|Any CPU.Build.0 = Release|Any CPU {2FC1D9C8-446D-4414-B252-5E9FBE61EB63}.Release|Any CPU.ActiveCfg = Release|Any CPU {2FC1D9C8-446D-4414-B252-5E9FBE61EB63}.Release|Any CPU.Build.0 = Release|Any CPU - {67C1D3AF-A0EC-46B2-BAE1-DF1DA8E0B890}.CodeCoverage|Any CPU.ActiveCfg = Release|Any CPU - {67C1D3AF-A0EC-46B2-BAE1-DF1DA8E0B890}.CodeCoverage|Any CPU.Build.0 = Release|Any CPU - {67C1D3AF-A0EC-46B2-BAE1-DF1DA8E0B890}.Coverage|Any CPU.ActiveCfg = Release|Any CPU - {67C1D3AF-A0EC-46B2-BAE1-DF1DA8E0B890}.Coverage|Any CPU.Build.0 = Release|Any CPU - {67C1D3AF-A0EC-46B2-BAE1-DF1DA8E0B890}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {67C1D3AF-A0EC-46B2-BAE1-DF1DA8E0B890}.Debug|Any CPU.Build.0 = Debug|Any CPU - {67C1D3AF-A0EC-46B2-BAE1-DF1DA8E0B890}.FxCop|Any CPU.ActiveCfg = Release|Any CPU - {67C1D3AF-A0EC-46B2-BAE1-DF1DA8E0B890}.FxCop|Any CPU.Build.0 = Release|Any CPU - {67C1D3AF-A0EC-46B2-BAE1-DF1DA8E0B890}.Release|Any CPU.ActiveCfg = Release|Any CPU - {67C1D3AF-A0EC-46B2-BAE1-DF1DA8E0B890}.Release|Any CPU.Build.0 = Release|Any CPU {8C7FCBC2-E6E1-405E-BFB5-D8D9E67A09C4}.CodeCoverage|Any CPU.ActiveCfg = Release|Any CPU {8C7FCBC2-E6E1-405E-BFB5-D8D9E67A09C4}.CodeCoverage|Any CPU.Build.0 = Release|Any CPU {8C7FCBC2-E6E1-405E-BFB5-D8D9E67A09C4}.Coverage|Any CPU.ActiveCfg = Release|Any CPU @@ -443,6 +435,26 @@ Global {D5D447D7-EF8E-43A6-B9A4-3B025DD9F45D}.FxCop|Any CPU.Build.0 = Release|Any CPU {D5D447D7-EF8E-43A6-B9A4-3B025DD9F45D}.Release|Any CPU.ActiveCfg = Release|Any CPU {D5D447D7-EF8E-43A6-B9A4-3B025DD9F45D}.Release|Any CPU.Build.0 = Release|Any CPU + {AB3C207C-0126-4143-8D62-1119DF80D366}.CodeCoverage|Any CPU.ActiveCfg = Release|Any CPU + {AB3C207C-0126-4143-8D62-1119DF80D366}.CodeCoverage|Any CPU.Build.0 = Release|Any CPU + {AB3C207C-0126-4143-8D62-1119DF80D366}.Coverage|Any CPU.ActiveCfg = Release|Any CPU + {AB3C207C-0126-4143-8D62-1119DF80D366}.Coverage|Any CPU.Build.0 = Release|Any CPU + {AB3C207C-0126-4143-8D62-1119DF80D366}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AB3C207C-0126-4143-8D62-1119DF80D366}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AB3C207C-0126-4143-8D62-1119DF80D366}.FxCop|Any CPU.ActiveCfg = Release|Any CPU + {AB3C207C-0126-4143-8D62-1119DF80D366}.FxCop|Any CPU.Build.0 = Release|Any CPU + {AB3C207C-0126-4143-8D62-1119DF80D366}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AB3C207C-0126-4143-8D62-1119DF80D366}.Release|Any CPU.Build.0 = Release|Any CPU + {C0C45321-B51D-4D8D-9B7B-AA4C2E0B2962}.CodeCoverage|Any CPU.ActiveCfg = Release|Any CPU + {C0C45321-B51D-4D8D-9B7B-AA4C2E0B2962}.CodeCoverage|Any CPU.Build.0 = Release|Any CPU + {C0C45321-B51D-4D8D-9B7B-AA4C2E0B2962}.Coverage|Any CPU.ActiveCfg = Release|Any CPU + {C0C45321-B51D-4D8D-9B7B-AA4C2E0B2962}.Coverage|Any CPU.Build.0 = Release|Any CPU + {C0C45321-B51D-4D8D-9B7B-AA4C2E0B2962}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C0C45321-B51D-4D8D-9B7B-AA4C2E0B2962}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C0C45321-B51D-4D8D-9B7B-AA4C2E0B2962}.FxCop|Any CPU.ActiveCfg = Release|Any CPU + {C0C45321-B51D-4D8D-9B7B-AA4C2E0B2962}.FxCop|Any CPU.Build.0 = Release|Any CPU + {C0C45321-B51D-4D8D-9B7B-AA4C2E0B2962}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C0C45321-B51D-4D8D-9B7B-AA4C2E0B2962}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -450,7 +462,6 @@ Global GlobalSection(NestedProjects) = preSolution {79AED36E-ABD0-4747-93D3-8722B042454B} = {E9C9F120-07BA-4DFB-B9C3-3AFB9D44C9D5} {D10AD48F-407D-4DB5-A328-173EC7CB010F} = {E9C9F120-07BA-4DFB-B9C3-3AFB9D44C9D5} - {67C1D3AF-A0EC-46B2-BAE1-DF1DA8E0B890} = {E9C9F120-07BA-4DFB-B9C3-3AFB9D44C9D5} {8C7FCBC2-E6E1-405E-BFB5-D8D9E67A09C4} = {E9C9F120-07BA-4DFB-B9C3-3AFB9D44C9D5} {CDE24A24-01D3-403C-84B9-37722E18DFB7} = {E9C9F120-07BA-4DFB-B9C3-3AFB9D44C9D5} {17F86780-9A1F-4AA1-86F1-875EEC2730C7} = {E9C9F120-07BA-4DFB-B9C3-3AFB9D44C9D5} @@ -468,6 +479,8 @@ Global {EA2B9121-EF54-40A6-A53E-6593C86EE696} = {E9C9F120-07BA-4DFB-B9C3-3AFB9D44C9D5} {4BE4EB01-AC56-4048-924E-2CA77F509ABA} = {E9C9F120-07BA-4DFB-B9C3-3AFB9D44C9D5} {D5D447D7-EF8E-43A6-B9A4-3B025DD9F45D} = {E9C9F120-07BA-4DFB-B9C3-3AFB9D44C9D5} + {AB3C207C-0126-4143-8D62-1119DF80D366} = {E9C9F120-07BA-4DFB-B9C3-3AFB9D44C9D5} + {C0C45321-B51D-4D8D-9B7B-AA4C2E0B2962} = {E9C9F120-07BA-4DFB-B9C3-3AFB9D44C9D5} {ABC826D4-2FA1-4F2F-87DE-E6095F653810} = {74E681ED-FECC-4034-B9BD-01B0BB1BDECA} {F112851D-B023-4746-B6B1-8D2E5AD8F7AA} = {74E681ED-FECC-4034-B9BD-01B0BB1BDECA} {6CB3EB30-F725-45C0-9742-42599BA8E8D2} = {74E681ED-FECC-4034-B9BD-01B0BB1BDECA}