--- /dev/null
+<?php
+
+namespace Drush\Commands\generate\Helper;
+
+use Drush\Drush;
+use DrupalCodeGenerator\Helper\InputHandler as BaseInputHandler;
+use DrupalCodeGenerator\Utils;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+/**
+ * Generators input handler.
+ */
+class InputHandler extends BaseInputHandler
+{
+
+ /**
+ * {@inheritdoc}
+ */
+ public function collectVars(InputInterface $input, OutputInterface $output, array $questions, array $vars = [])
+ {
+ /** @var \DrupalCodeGenerator\Command\GeneratorInterface $command */
+ $command = $this->getHelperSet()->getCommand();
+ $destination = $command->getDestination();
+
+ $this->preprocessQuestions($questions, $destination);
+
+ $existing_extension = in_array($destination, ['modules/%', 'themes/%']);
+
+ // If both name and machine_name questions are defined it is quite
+ // possible that we can provide the extension name without interacting
+ // with a user.
+ if (isset($questions['name'], $questions['machine_name']) && $existing_extension) {
+ // Collect only machine_name answer.
+ $vars += parent::collectVars($input, $output, ['machine_name' => $questions['machine_name']]);
+ unset($questions['machine_name']);
+
+ if ($destination == 'modules/%') {
+ $moduleHandler = \Drupal::moduleHandler();
+ if ($moduleHandler->moduleExists($vars['machine_name'])) {
+ $vars['name'] = $moduleHandler->getName($vars['machine_name']);
+ unset($questions['name']);
+ }
+ } elseif ($destination == 'themes/%') {
+ $themeHandler = \Drupal::service('theme_handler');
+ if ($themeHandler->themeExists($vars['machine_name'])) {
+ $vars['name'] = $themeHandler->getName($vars['machine_name']);
+ unset($questions['name']);
+ }
+ }
+ }
+
+ // Collect all other variables.
+ $vars += parent::collectVars($input, $output, $questions, $vars);
+
+ // Set an appropriate directory for dumped files.
+ if (empty($input->getOption('directory')) && ($directory = $this->getDirectory($vars, $destination))) {
+ $command->setDirectory($directory);
+ }
+
+ return $vars;
+ }
+
+ /**
+ * Modifies questions for better DX.
+ *
+ * @param \Symfony\Component\Console\Question\Question[] $questions
+ * List of questions to modify.
+ * @param string $destination
+ * The destination for dumped files.
+ */
+ protected function preprocessQuestions(array &$questions, $destination)
+ {
+ if (!isset($questions['machine_name'])) {
+ return;
+ }
+
+ $root_directory = basename(Utils::getExtensionRoot(Drush::config()->cwd()));
+
+ // Module related generators.
+ if ($destination == 'modules/%') {
+ // Prepare list of modules.
+ $modules = [];
+ $moduleHandler = \Drupal::moduleHandler();
+ foreach ($moduleHandler->getModuleList() as $machine_name => $module) {
+ $modules[$machine_name] = $moduleHandler->getName($machine_name);
+ }
+
+ // Name question.
+ if (isset($questions['name'])) {
+ $questions['name']->setAutocompleterValues($modules);
+ $default_name = $root_directory ? Utils::machine2human($root_directory) : '';
+ $this->setQuestionDefault($questions['name'], $default_name);
+ }
+
+ // Machine name question.
+ $questions['machine_name']->setAutocompleterValues(array_keys($modules));
+ $default_machine_name = $root_directory ? Utils::human2machine($root_directory) : '';
+ $this->setQuestionDefault($questions['machine_name'], $default_machine_name);
+
+ // Theme related generators.
+ } elseif ($destination == 'themes/%') {
+ // Prepare list of themes.
+ $themes = [];
+ foreach (\Drupal::service('theme_handler')->listInfo() as $machine_name => $theme) {
+ $themes[$machine_name] = $theme->info['name'];
+ }
+
+ // Name question.
+ if (isset($questions['name'])) {
+ $questions['name']->setAutocompleterValues(array_values($themes));
+ }
+
+ // Machine name question.
+ $questions['machine_name']->setAutocompleterValues(array_keys($themes));
+ $default_machine_name = $root_directory ? Utils::human2machine($root_directory) : '';
+ $this->setQuestionDefault($questions['machine_name'], $default_machine_name);
+ } elseif (isset($questions['name'])) {
+ // For other generator types simply reset default value set by DCG.
+ $this->setQuestionDefault($questions['name'], '');
+ }
+ }
+
+ /**
+ * Defines the directory where generated files should be dumped.
+ *
+ * @param array $vars
+ * Collected variables.
+ * @param string|bool $destination
+ * The destination for dumped files.
+ *
+ * @return string $directory
+ * The directory to dump file or false it cannot be determined.
+ */
+ protected function getDirectory(array $vars, $destination)
+ {
+
+ // Check if the generator can handle it itself.
+ if (is_callable($destination)) {
+ $directory = $destination($vars);
+ } else {
+ $modules_dir = is_dir(DRUPAL_ROOT . '/modules/custom') ?
+ 'modules/custom' : 'modules';
+
+ $directory = false;
+ switch ($destination) {
+ case 'modules':
+ $directory = $modules_dir;
+ break;
+
+ case 'themes':
+ $directory = 'themes';
+ break;
+
+ case 'modules/%':
+ if (isset($vars['machine_name'])) {
+ $machine_name = $vars['machine_name'];
+ $modules = \Drupal::moduleHandler()->getModuleList();
+ $directory = isset($modules[$machine_name])
+ ? $modules[$machine_name]->getPath()
+ : $modules_dir . '/' . $machine_name;
+ }
+ break;
+
+ case 'themes/%':
+ if (isset($vars['machine_name'])) {
+ $machine_name = $vars['machine_name'];
+ $themes = \Drupal::service('theme_handler')->listInfo();
+ $directory = isset($themes[$machine_name])
+ ? $themes[$machine_name]->getPath()
+ : 'themes/' . $machine_name;
+ }
+ break;
+
+ case 'profiles':
+ $directory = 'profiles';
+ break;
+
+ case 'sites/default':
+ $directory = 'sites/default';
+ break;
+ }
+ }
+
+ return $directory;
+ }
+}