
| Current Path : /var/www/html/ift/vendor/chi-teck/drupal-code-generator/src/Command/ |
Linux ift1.ift-informatik.de 5.4.0-216-generic #236-Ubuntu SMP Fri Apr 11 19:53:21 UTC 2025 x86_64 |
| Current File : /var/www/html/ift/vendor/chi-teck/drupal-code-generator/src/Command/Navigation.php |
<?php
namespace DrupalCodeGenerator\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\ChoiceQuestion;
/**
* Implements generate command.
*/
class Navigation extends Command {
/**
* Menu tree.
*
* @var array
*/
protected $menuTree;
/**
* Name of the generator to execute.
*
* @var string
*/
protected $generatorName;
/**
* Command labels.
*
* @var array
*/
protected $labels = [
'd7' => 'Drupal 7',
'd8' => 'Drupal 8',
];
/**
* Aliases for some sub-menus.
*
* @var array
*/
protected $defaultAliases = [
'service' => 'd8:service',
'plugin' => 'd8:plugin',
'theme' => 'd8:theme',
'module' => 'd8:module',
'form' => 'd8:form',
'test' => 'd8:test',
'yml' => 'd8:yml',
'links' => 'd8:yml:links',
];
/**
* Constructs menu command.
*
* @param \DrupalCodeGenerator\Command\GeneratorInterface[] $commands
* List of registered commands.
*/
public function __construct(array $commands) {
parent::__construct();
// Initialize the menu structure.
$this->menuTree = [];
$aliases = array_keys($this->defaultAliases);
// Build aliases for the navigation based on command namespaces.
foreach ($commands as $command) {
$command_name = $command->getName();
$sub_names = explode(':', $command_name);
$this->arraySetNestedValue($this->menuTree, $sub_names, TRUE);
// The last sub-name is actual command name so it cannot be used as an
// alias for navigation command.
$last_sub_name = array_pop($sub_names);
// Collect command labels.
if ($label = $command->getLabel()) {
$this->labels[$last_sub_name] = $label;
}
// We cannot use $application->getNamespaces() here because the
// application is not available at this point.
$alias = '';
foreach ($sub_names as $sub_name) {
$alias = $alias ? $alias . ':' . $sub_name : $sub_name;
$aliases[] = $alias;
}
}
$this->setAliases(array_unique($aliases));
$this->recursiveKsort($this->menuTree);
}
/**
* {@inheritdoc}
*/
public function getUsages() {
return ['<generator>'];
}
/**
* {@inheritdoc}
*/
protected function configure() {
$this
->setName('navigation')
->setDescription('Provides an interactive menu to select generator')
->setHelp('Run `dcg list` to check out all available generators.')
->setHidden(TRUE)
->addOption(
'directory',
'-d',
InputOption::VALUE_OPTIONAL,
'Working directory'
)
->addOption(
'answers',
'-a',
InputOption::VALUE_OPTIONAL,
'Default JSON formatted answers'
);
}
/**
* {@inheritdoc}
*/
protected function interact(InputInterface $input, OutputInterface $output) {
$style = new OutputFormatterStyle('black', 'cyan', []);
$output->getFormatter()->setStyle('title', $style);
$command_name = $input->getFirstArgument();
// Before version 3.3.6 of Symfony console getFistArgument returned default
// command name.
$command_name = $command_name == 'navigation' ? NULL : $command_name;
if (isset($this->defaultAliases[$command_name])) {
$command_name = $this->defaultAliases[$command_name];
}
$menu_trail = $command_name ? explode(':', $command_name) : [];
$this->generatorName = $this->selectGenerator($input, $output, $menu_trail);
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output) {
if (!$this->generatorName) {
return 0;
}
// Run the generator.
return $this->getApplication()
->find($this->generatorName)
->run($input, $output);
}
/**
* Returns a generator selected by the user from a multilevel console menu.
*
* @param \Symfony\Component\Console\Input\InputInterface $input
* Input instance.
* @param \Symfony\Component\Console\Output\OutputInterface $output
* Output instance.
* @param array $menu_trail
* Menu trail.
*
* @return string|null
* Generator name or null if user decided to exit the navigation.
*/
protected function selectGenerator(InputInterface $input, OutputInterface $output, array $menu_trail) {
// Narrow down menu tree.
$active_menu_tree = $this->menuTree;
foreach ($menu_trail as $active_menu_item) {
$active_menu_tree = $active_menu_tree[$active_menu_item];
}
// The $active_menu_tree can be either an array of menu items or TRUE if the
// user reached the final menu point.
if ($active_menu_tree === TRUE) {
return implode(':', $menu_trail);
}
$sub_menu_labels = $command_labels = [];
foreach ($active_menu_tree as $menu_item => $subtree) {
if (is_array($subtree)) {
$sub_menu_labels[$menu_item] = $this->createMenuItemLabel($menu_item, TRUE);
}
else {
$command_labels[$menu_item] = $this->createMenuItemLabel($menu_item, FALSE);
}
}
asort($sub_menu_labels);
asort($command_labels);
// Generally the choices array consists of the following parts:
// - Reference to the parent menu level.
// - Sorted list of nested menu levels.
// - Sorted list of commands.
$choices = ['..' => '..'] + $sub_menu_labels + $command_labels;
$question = new ChoiceQuestion('<title> Select generator: </title>', array_values($choices));
$question->setPrompt(count($choices) <= 10 ? ' ➤➤➤ ' : ' ➤➤➤➤ ');
$answer_label = $this->getHelper('question')->ask($input, $output, $question);
$answer = array_search($answer_label, $choices);
if ($answer == '..') {
// Exit the application if the user selected zero on the top menu level.
if (count($menu_trail) == 0) {
return NULL;
}
// Decrease menu level.
array_pop($menu_trail);
}
else {
// Increase menu level.
$menu_trail[] = $answer;
}
return $this->selectGenerator($input, $output, $menu_trail);
}
/**
* Creates a human readable label for a given menu item.
*
* @param string $menu_item
* Machine name of the menu item.
* @param bool $comment
* A boolean indicating that the label should be wrapped with comment tag.
*
* @return string
* The menu label.
*/
protected function createMenuItemLabel($menu_item, $comment) {
$label = isset($this->labels[$menu_item]) ?
$this->labels[$menu_item] : str_replace(['-', '_'], ' ', ucfirst($menu_item));
return $comment ? "<comment>$label</comment>" : $label;
}
/**
* Sort multi-dimensional array by keys.
*
* @param array $array
* An array being sorted.
*
* @return array
* Sorted array.
*/
protected function recursiveKsort(array &$array) {
foreach ($array as &$value) {
if (is_array($value)) {
$this->recursiveKsort($value);
}
}
return ksort($array);
}
/**
* Sets a value in a nested array with variable depth.
*
* @param array $array
* A reference to the array to modify.
* @param array $parents
* An array of parent keys, starting with the outermost key.
* @param mixed $value
* The value to set.
*
* @see https://api.drupal.org/api/drupal/includes!common.inc/function/drupal_array_set_nested_value/7
*/
protected function arraySetNestedValue(array &$array, array $parents, $value) {
$ref = &$array;
foreach ($parents as $parent) {
if (isset($ref) && !is_array($ref)) {
$ref = [];
}
$ref = &$ref[$parent];
}
if (!isset($ref)) {
$ref = $value;
}
}
}