mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-07-15 22:09:40 +08:00
228 lines
14 KiB
C#
228 lines
14 KiB
C#
![]() |
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 <feature-name> \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<SchemaCommand> 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("<Compile Include") ) {
|
|||
|
string compileReference = string.Format("<Compile Include=\"{0}\" />\r\n ", "DataMigrations\\" + extensionDescriptor.DisplayName + "DataMigration.cs");
|
|||
|
projectFileText = projectFileText.Insert(projectFileText.LastIndexOf("<Compile Include"), compileReference);
|
|||
|
}
|
|||
|
else {
|
|||
|
string itemGroupReference = string.Format("</ItemGroup>\r\n <ItemGroup>\r\n <Compile Include=\"{0}\" />\r\n ", "DataMigrations\\" + extensionDescriptor.DisplayName + "DataMigration.cs");
|
|||
|
projectFileText = projectFileText.Insert(projectFileText.LastIndexOf("</ItemGroup>"), itemGroupReference);
|
|||
|
}
|
|||
|
|
|||
|
File.WriteAllText(moduleCsProjPath, projectFileText);
|
|||
|
TouchSolution();
|
|||
|
Context.Output.WriteLine(T("Data migration created successfully in Module {0}", extensionDescriptor.Name));
|
|||
|
}
|
|||
|
|
|||
|
[CommandHelp("generate create module <module-name> [/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 <module-name> <controller-name>\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("<Compile Include")) {
|
|||
|
string compileReference = string.Format("<Compile Include=\"{0}\" />\r\n ", "Controllers\\" + controllerName + ".cs");
|
|||
|
projectFileText = projectFileText.Insert(projectFileText.LastIndexOf("<Compile Include"), compileReference);
|
|||
|
}
|
|||
|
else {
|
|||
|
string itemGroupReference = string.Format("</ItemGroup>\r\n <ItemGroup>\r\n <Compile Include=\"{0}\" />\r\n ", "Controllers\\" + controllerName + ".cs");
|
|||
|
projectFileText = projectFileText.Insert(projectFileText.LastIndexOf("</ItemGroup>"), 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."));
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|