3 namespace Drush\Commands\generate;
5 use DrupalCodeGenerator\GeneratorDiscovery;
6 use DrupalCodeGenerator\Helper\Dumper;
7 use DrupalCodeGenerator\Helper\Renderer;
8 use DrupalCodeGenerator\TwigEnvironment;
9 use Drush\Commands\DrushCommands;
10 use Drush\Commands\generate\Helper\InputHandler;
11 use Drush\Commands\generate\Helper\OutputHandler;
12 use Drush\Commands\help\ListCommands;
14 use Drush\Drupal\DrushServiceModifier;
15 use Symfony\Component\Console\Application;
16 use Symfony\Component\Console\Input\StringInput;
17 use Symfony\Component\Filesystem\Filesystem;
20 * Drush generate command.
22 class GenerateCommands extends DrushCommands
26 * Generate boilerplate code for modules/plugins/services etc.
28 * Drush asks questions so that the generated code is as polished as possible. After
29 * generating, Drush lists the files that were created.
33 * @param string $generator A generator name. Omit to pick from available Generators.
34 * @option answers A JSON string containing pairs of question and answers.
35 * @option directory Absolute path to a base directory for file writing.
36 * @usage drush generate
37 * Pick from available generators and then run it.
38 * @usage drush generate controller
39 * Generate a controller class for your module.
40 * @usage drush generate drush-command-file
41 * Generate a Drush commandfile for your module.
42 * @topics docs:generators
45 public function generate($generator = '', $options = ['answers' => self::REQ, 'directory' => self::REQ])
48 // Disallow default Symfony console commands.
49 if ($generator == 'help' || $generator == 'list') {
53 $application = $this->createApplication();
55 $all = $application->all();
56 unset($all['help'], $all['list']);
57 $namespaced = ListCommands::categorize($all, '-');
58 $preamble = dt('Run `drush generate [command]` and answer a few questions in order to write starter code to your project.');
59 ListCommands::renderListCLI($application, $namespaced, $this->output(), $preamble);
62 // Symfony console cannot recognize the command by alias when
63 // multiple commands have the same prefix.
64 if ($generator == 'module') {
65 $generator = 'module-standard';
68 // Create an isolated input.
71 '--answers=' . escapeshellarg($options['answers']),
72 '--directory=' . $options['directory']
74 return $application->run(new StringInput(implode(' ', $argv)));
79 * Creates Drush generate application.
81 * @return \Symfony\Component\Console\Application
82 * Symfony console application.
84 protected function createApplication()
86 $application = new Application('Drush generate', Drush::getVersion());
87 $helperSet = $application->getHelperSet();
90 if (Drush::affirmative()) {
92 } elseif (Drush::negative()) {
95 $dumper = new Dumper(new Filesystem(), $override);
96 $helperSet->set($dumper);
98 $twig_loader = new \Twig_Loader_Filesystem();
99 $renderer = new Renderer(new TwigEnvironment($twig_loader));
100 $helperSet->set($renderer);
102 $helperSet->set(new InputHandler());
103 $helperSet->set(new OutputHandler());
105 // Discover generators.
106 $discovery = new GeneratorDiscovery(new Filesystem());
109 * Discover generators.
111 $dcg_generators = $discovery->getGenerators([DCG_ROOT . '/src/Command/Drupal_8'], '\DrupalCodeGenerator\Command\Drupal_8');
112 $drush_generators = $discovery->getGenerators([__DIR__ . '/Generators'], '\Drush\Commands\generate\Generators');
113 $config_paths = $this->getConfig()->get('runtime.commandfile.paths', []);
117 foreach ($config_paths as $path) {
118 $global_paths[] = $path . '/Generators';
119 $global_paths[] = $path . '/src/Generators';
122 $global_paths = array_filter($global_paths, 'file_exists');
123 $global_generators = $discovery->getGenerators($global_paths, '\Drush\Generators');
125 $module_generators = [];
127 if (Drush::bootstrapManager()->hasBootstrapped(DRUSH_BOOTSTRAP_DRUPAL_FULL)) {
128 $container = \Drupal::getContainer();
129 if ($container->has(DrushServiceModifier::DRUSH_GENERATOR_SERVICES)) {
130 $module_generators = $container->get(DrushServiceModifier::DRUSH_GENERATOR_SERVICES)->getCommandList();
134 /** @var \Symfony\Component\Console\Command\Command[] $generators */
135 $generators = array_merge($dcg_generators, $drush_generators, $global_generators, $module_generators);
137 foreach ($generators as $generator) {
138 $sub_names = explode(':', $generator->getName());
139 if ($sub_names[0] == 'd8') {
140 // Remove d8 namespace.
141 array_shift($sub_names);
143 $new_name = implode('-', $sub_names);
144 $generator->setName($new_name);
145 // Remove alias if it is same as new name.
146 if ($aliases = $generator->getAliases()) {
147 $generator->setAliases(array_diff($aliases, [$new_name]));
151 $application->addCommands($generators);
153 $application->setAutoExit(false);