5 * annotationcommand_adapter.inc
8 use Consolidation\AnnotatedCommand\CommandFileDiscovery;
9 use Consolidation\AnnotatedCommand\AnnotatedCommandFactory;
10 use Consolidation\AnnotatedCommand\CommandProcessor;
11 use Consolidation\AnnotatedCommand\Hooks\HookManager;
12 use Consolidation\OutputFormatters\FormatterManager;
13 use Consolidation\OutputFormatters\Options\FormatterOptions;
14 use Symfony\Component\Console\Input\ArrayInput;
15 use Consolidation\AnnotatedCommand\AnnotationData;
16 use Consolidation\AnnotatedCommand\CommandData;
17 use Drush\Command\DrushInputAdapter;
18 use Drush\Command\DrushOutputAdapter;
20 use Symfony\Component\Console\Output\ConsoleOutput;
23 * Cache the command file discovery object. Drush 9 uses dependency injection.
25 * @return CommandFileDiscovery
27 function annotationcommand_adapter_get_discovery() {
29 if (!isset($discovery)) {
30 $discovery = new CommandFileDiscovery();
32 ->setIncludeFilesAtBase(false)
33 ->setSearchLocations(['Commands'])
34 ->setSearchPattern('#.*Commands.php$#');
40 * Initialize and cache the command factory. Drush 9 uses dependency injection.
42 * @return AnnotatedCommandFactory
44 function annotationcommand_adapter_get_factory() {
46 if (!isset($factory)) {
47 $factory = new AnnotatedCommandFactory();
48 $factory->commandProcessor()->hookManager()->add('annotatedcomand_adapter_backend_result', HookManager::EXTRACT_OUTPUT);
49 $formatter = new FormatterManager();
50 $formatter->addDefaultFormatters();
51 $formatter->addDefaultSimplifiers();
52 $factory->commandProcessor()->setFormatterManager($formatter);
58 * Fetch the command processor from the factory.
60 * @return AnnotatedCommandFactory
62 function annotationcommand_adapter_get_processor() {
63 $factory = annotationcommand_adapter_get_factory();
64 return $factory->commandProcessor();
68 * Fetch the formatter manager from the command processor
70 * @return FormatterManager
72 function annotatedcomand_adapter_get_formatter() {
73 $commandProcessor = annotationcommand_adapter_get_processor();
74 return $commandProcessor->formatterManager();
78 * Callback function called by HookManager::EXTRACT_OUTPUT to set
81 function annotatedcomand_adapter_backend_result($structured_data) {
82 $return = drush_backend_get_result();
84 drush_backend_set_result($structured_data);
89 * Return the cached commands built by annotationcommand_adapter_discover.
90 * @see drush_get_commands()
92 function annotationcommand_adapter_commands() {
93 $annotation_commandfiles = drush_get_context('DRUSH_ANNOTATED_COMMANDFILES');
94 // Remove any entry in the commandfiles list from an ignored module.
95 $ignored = implode('|', drush_get_option_list('ignored-modules'));
96 $regex = "#/(modules|themes|profiles)(/|/.*/)($ignored)/#";
97 foreach ($annotation_commandfiles as $key => $path) {
98 if (preg_match($regex, $path)) {
99 unset($annotation_commandfiles[$key]);
102 $commands = annotationcommand_adapter_get_commands($annotation_commandfiles);
103 $module_service_commands = drush_get_context('DRUSH_MODULE_SERVICE_COMMANDS');
104 return array_merge($commands, $module_service_commands);
108 * Search for annotation commands at the provided search path.
109 * @see _drush_find_commandfiles()
111 function annotationcommand_adapter_discover($searchpath, $phase = false, $phase_max = false) {
112 if (empty($searchpath)) {
115 if (($phase >= DRUSH_BOOTSTRAP_DRUPAL_SITE) && (drush_drupal_major_version() >= 8)) {
118 $annotation_commandfiles = [];
119 // Assemble a cid specific to the bootstrap phase and searchpaths.
120 // Bump $cf_version when making a change to a dev version of Drush
121 // that invalidates the commandfile cache.
123 $cid = drush_get_cid('annotationfiles-' . $phase, array(), array_merge($searchpath, array($cf_version)));
124 $command_cache = drush_cache_get($cid);
125 if (isset($command_cache->data)) {
126 $annotation_commandfiles = $command_cache->data;
129 // Check to see if this is the Drush searchpath for instances where we are
130 // NOT going to do a full bootstrap (e.g. when running a help command)
131 if (($phase == DRUSH_BOOTSTRAP_DRUPAL_SITE) && ($phase_max < DRUSH_BOOTSTRAP_DRUPAL_FULL)) {
132 $searchpath = annotationcommand_adapter_refine_searchpaths($searchpath);
134 $discovery = annotationcommand_adapter_get_discovery();
135 $annotation_commandfiles = $discovery->discoverNamespaced($searchpath, '\Drupal');
136 drush_cache_set($cid, $annotation_commandfiles);
139 'DRUSH_ANNOTATED_COMMANDFILES',
141 drush_get_context('DRUSH_ANNOTATED_COMMANDFILES'),
142 $annotation_commandfiles
148 * This function is set as the $command['callback'] for Symfony Console commands
149 * e.g. those provided by Drupal 8 modules. Note that Drush 9 calls these with
150 * Symfony's Application::run() method, but Drush 8 continues to use the
151 * legacy Drush command dispatcher for all commands.
153 * @return bolean false if command failed (expect drush_set_error was called in this case)
155 function annotationcommand_adapter_run_console_command() {
156 $args = func_get_args();
157 $command = drush_get_command();
159 $console_command = $command['drush-console-command'];
160 // TODO: Build an appropriate input object
161 $input = annotationcommand_adapter_build_input($console_command, $args);
162 $output = new ConsoleOutput();
163 $result = $console_command->run($input, $output);
169 * TODO: This could probably just be a DrushInputAdapter now.
171 function annotationcommand_adapter_build_input($console_command, $userArgs) {
173 $defaultOptions = [];
174 $definition = $console_command->getDefinition();
175 $inputArguments = $definition->getArguments();
176 foreach ($inputArguments as $key => $inputOption) {
177 $value = array_shift($userArgs);
178 if (!isset($value)) {
179 $value = $inputOption->getDefault();
181 $args[$key] = $value;
183 $inputOptions = $definition->getOptions();
184 foreach ($inputOptions as $option => $inputOption) {
185 $defaultOptions[$option] = $inputOption->getDefault();
187 foreach ($defaultOptions as $option => $value) {
188 $args["--$option"] = drush_get_option($option, $value);
190 // TODO: Need to add global options. Note that ArrayInput is validated.
191 $input = new ArrayInput($args, $definition);
196 * Collect all of the options defined in every relevant context, and
197 * merge them together to form the options array.
201 function annotationcommand_adapter_get_options($command) {
202 $default_options = isset($command['consolidation-option-defaults']) ? $command['consolidation-option-defaults'] : [];
203 $options = drush_redispatch_get_options() + $default_options;
205 $options += drush_get_merged_options();
211 * This function is set as the $command['callback'] for commands that have
212 * been converted to annotated commands. Note that Drush 9 calls these with
213 * Symfony's Application::run() method, but Drush 8 continues to use the
214 * legacy Drush command dispatcher for all commands.
216 * @return bolean false if command failed (expect drush_set_error was called in this case)
218 function annotationcommand_adapter_process_command() {
219 $userArgs = func_get_args();
220 $commandprocessor = annotationcommand_adapter_get_processor();
221 $command = drush_get_command();
222 annotationcommand_adapter_add_hook_options($command);
224 foreach ($command['consolidation-arg-defaults'] as $key => $default) {
225 $value = array_shift($userArgs);
226 if (!isset($value)) {
229 $args[$key] = $value;
232 $input = new DrushInputAdapter($args, annotationcommand_adapter_get_options($command), $command['command']);
233 $output = new DrushOutputAdapter();
234 $annotationData = $command['annotations'];
235 $commandData = new CommandData(
240 $commandData->setIncludeOptionsInArgs($command['add-options-to-arguments']);
241 $names = annotationcommand_adapter_command_names($command);
243 // n.b.: backend result is set by a post-alter hook.
244 $result = $commandprocessor->process(
247 $command['annotated-command-callback'],
255 * Internal function called by annotationcommand_adapter_commands, which
256 * is called by drush_get_commands().
258 * @param array $annotation_commandfiles path => class mapping
262 function annotationcommand_adapter_get_commands($annotation_commandfiles) {
264 // This will give us a list containing something akin to:
265 // 'modules/default_content/src/CliTools/DefaultContentCommands.php' =>
266 // '\\Drupal\\default_content\\CliTools\\DefaultContentCommands',
267 foreach ($annotation_commandfiles as $commandfile_path => $commandfile_class) {
268 if (file_exists($commandfile_path)) {
269 $commandhandler = annotationcommand_adapter_create_commandfile_instance($commandfile_path, $commandfile_class);
270 $commands_for_this_commandhandler = annotationcommand_adapter_get_commands_for_commandhandler($commandhandler, $commandfile_path);
271 $commands = array_merge($commands, $commands_for_this_commandhandler);
278 * Create and cache a commandfile instance.
280 * @param string $commandfile_path Path to the commandfile implementation
281 * @param string $commandfile_class Namespace and class of the commandfile object
285 function annotationcommand_adapter_create_commandfile_instance($commandfile_path, $commandfile_class) {
286 $cache =& drush_get_context('DRUSH_ANNOTATION_COMMANDFILE_INSTANCES');
287 if (!isset($cache[$commandfile_path])) {
288 include_once $commandfile_path;
289 $commandhandler = new $commandfile_class;
290 $cache[$commandfile_path] = $commandhandler;
292 return $cache[$commandfile_path];
298 function annotationcommand_adapter_cache_module_console_commands($console_command, $commandfile_path = null) {
299 if (!isset($commandfile_path)) {
300 $class = new \ReflectionClass($console_command);
301 $commandfile_path = $class->getFileName();
303 $module_service_commands = drush_get_context('DRUSH_MODULE_SERVICE_COMMANDS');
304 $commands = annotationcommand_adapter_get_command_for_console_command($console_command, $commandfile_path);
305 drush_set_context('DRUSH_MODULE_SERVICE_COMMANDS', array_merge($commands, $module_service_commands));
311 function annotationcommand_adapter_cache_module_service_commands($commandhandler, $commandfile_path = null) {
312 if (!isset($commandfile_path)) {
313 $class = new \ReflectionClass($commandhandler);
314 $commandfile_path = $class->getFileName();
316 $module_service_commands = drush_get_context('DRUSH_MODULE_SERVICE_COMMANDS');
317 $commands = annotationcommand_adapter_get_commands_for_commandhandler($commandhandler, $commandfile_path, false);
318 drush_set_context('DRUSH_MODULE_SERVICE_COMMANDS', array_merge($commands, $module_service_commands));
322 * Convert a Symfony Console command into a Drush $command record
324 * @param Symfony\Component\Console\Command\Command $console_command The Symfony Console command to convert
325 * @param string $commandfile_path Path to console command file
327 * @return array Drush $command record
329 function annotationcommand_adapter_get_command_for_console_command($console_command, $commandfile_path) {
331 $commandfile = basename($commandfile_path, '.php');
332 $factory = annotationcommand_adapter_get_factory();
333 $inputDefinition = $console_command->getDefinition();
334 $inputArguments = $inputDefinition->getArguments();
335 $inputOptions = $inputDefinition->getOptions();
336 $aliases = $console_command->getAliases();
337 $command_name = strtolower($console_command->getName());
338 $standard_alias = str_replace(':', '-', $command_name);
339 if ($command_name != $standard_alias) {
340 $aliases[] = $standard_alias;
343 'name' => $command_name,
344 'callback' => 'annotationcommand_adapter_run_console_command',
345 'drush-console-command' => $console_command,
346 'commandfile' => $commandfile,
347 'category' => $commandfile,
350 'description' => $console_command->getDescription(),
351 'examples' => $console_command->getUsages(),
352 'aliases' => $aliases,
354 foreach ($inputArguments as $arg => $inputArg) {
355 $command['arguments'][$arg] = $inputArg->getDescription();
357 $command['required-arguments'] = $inputDefinition->getArgumentRequiredCount();
358 foreach ($inputOptions as $option => $inputOption) {
359 $description = $inputOption->getDescription();
360 $default = $inputOption->getDefault();
361 $command['options'][$option] = ['description' => $description];
362 if (!empty($default)) {
363 $command['options'][$option]['example-value'] = $default;
366 $command += drush_command_defaults($command_name, $commandfile, $commandfile_path);
367 $commands[$command_name] = $command;
372 * Convert an annotated command command handler object into a Drush $command record.
374 * @param object $commandhandler Command handler object
375 * @param string $commandfile_path
376 * @param boolean $includeAllPublicMethods TODO remove this, make it 'false' always
378 * @return array Drush $command record
380 function annotationcommand_adapter_get_commands_for_commandhandler($commandhandler, $commandfile_path, $includeAllPublicMethods = true) {
381 $cache =& drush_get_context('DRUSH_ANNOTATION_COMMANDS_FOR_COMMANDFILE');
382 if (isset($cache[$commandfile_path])) {
383 return $cache[$commandfile_path];
385 $factory = annotationcommand_adapter_get_factory();
387 $commandfile = basename($commandfile_path, '.php');
389 $commandinfo_list = $factory->getCommandInfoListFromClass($commandhandler);
391 foreach ($commandinfo_list as $commandinfo) {
392 // Hooks are automatically registered when the commandhandler is
393 // created via registerCommandClass(), so we don't need to do it again here.
394 // $factory->registerCommandHook($commandinfo, $commandhandler);
395 $aliases = $commandinfo->getAliases();
396 $command_name = strtolower($commandinfo->getName());
397 $standard_alias = str_replace(':', '-', $command_name);
398 if ($command_name != $standard_alias) {
399 $aliases[] = $standard_alias;
401 $handle_remote_commands = $commandinfo->getAnnotation('handle-remote-commands') == 'true';
402 // TODO: if there is no 'bootstrap' annotation, maybe we should default to NONE instead of FULL?
403 if ($bootstrap = $commandinfo->getAnnotation('bootstrap')) {
404 $bootstrap = constant($bootstrap);
407 'name' => $command_name,
408 //'callback' => [$commandhandler, $commandinfo->getMethodName()],
409 'callback' => 'annotationcommand_adapter_process_command',
410 'annotated-command-callback' => [$commandhandler, $commandinfo->getMethodName()],
411 'commandfile' => $commandfile,
412 'category' => $commandfile,
415 'description' => $commandinfo->getDescription(),
416 'examples' => $commandinfo->getExampleUsages(),
417 'bootstrap' => $bootstrap,
418 'handle-remote-commands' => $handle_remote_commands,
419 'aliases' => $aliases,
420 'add-options-to-arguments' => TRUE,
421 'consolidation-output-formatters' => TRUE,
422 'consolidation-option-defaults' => $commandinfo->options()->getValues(),
423 'consolidation-arg-defaults' => $commandinfo->arguments()->getValues(),
425 $required_arguments = 0;
426 foreach ($commandinfo->arguments()->getValues() as $arg => $default) {
427 $command['arguments'][$arg] = $commandinfo->arguments()->getDescription($arg);
428 if (!isset($default)) {
429 ++$required_arguments;
432 $command['required-arguments'] = $required_arguments;
433 foreach ($commandinfo->options()->getValues() as $option => $default) {
434 $description = $commandinfo->options()->getDescription($option);
435 $command['options'][$option] = ['description' => $description];
436 if (!empty($default)) {
437 $command['options'][$option]['example-value'] = $default;
439 $fn = 'annotationcommand_adapter_alter_option_description_' . $option;
440 if (function_exists($fn)) {
441 $command['options'][$option] = $fn($command['options'][$option], $commandinfo, $default);
444 $command['annotations'] = $commandinfo->getAnnotations();
445 // If the command has a '@return' annotation, then
446 // remember information we will need to use the output formatter.
447 $returnType = $commandinfo->getReturnType();
448 if (isset($returnType)) {
449 $command['return-type'] = $returnType;
451 $command += drush_command_defaults($command_name, $commandfile, $commandfile_path);
452 $commands[$command_name] = $command;
454 $cache[$commandfile_path] = $commands;
459 * Modify a $command record, adding option definitions defined by any
462 * @param array $command Drush command record to modify
464 function annotationcommand_adapter_add_hook_options(&$command)
466 // Get options added by hooks. We postpone doing this until the
467 // last minute rather than doing it when processing commandfiles
468 // so that we do not need to worry about what order we process the
469 // commandfiles in -- we can load extensions late, and still have
470 // the extension hook a core command, or have an early-loaded global
471 // extension hook a late-loaded extension (e.g. attached to a module).
472 $names = annotationcommand_adapter_command_names($command);
473 $names[] = '*'; // we are missing annotations here; maybe we just don't support that? (TODO later, maybe)
474 $factory = annotationcommand_adapter_get_factory();
475 $extraOptions = $factory->hookManager()->getHookOptions($names);
476 foreach ($extraOptions as $commandinfo) {
477 if (!isset($command['consolidation-option-defaults'])) {
478 $command['consolidation-option-defaults'] = array();
480 $command['consolidation-option-defaults'] += $commandinfo->options()->getValues();
481 foreach ($commandinfo->options()->getValues() as $option => $default) {
482 $description = $commandinfo->options()->getDescription($option);
483 $command['options'][$option] = ['description' => $description];
484 if (!empty($default)) {
485 $command['options'][$option]['example-value'] = $default;
487 $fn = 'annotationcommand_adapter_alter_option_description_' . $option;
488 if (function_exists($fn)) {
489 $command['options'][$option] = $fn($command['options'][$option], $commandinfo, $default);
496 * Build all of the name variants for a Drush $command record
498 * @param array $command Drush command record
502 function annotationcommand_adapter_command_names($command)
504 $names = array_merge(
505 [$command['command']],
508 if (!empty($command['annotated-command-callback'])) {
509 $commandHandler = $command['annotated-command-callback'][0];
510 $reflectionClass = new \ReflectionClass($commandHandler);
511 $commandFileClass = $reflectionClass->getName();
512 $names[] = $commandFileClass;
518 * Convert from an old-style Drush initialize hook into annotated-command hooks.
519 * @see _drush_invoke_hooks().
521 * @param string[] $names All of the applicable names for the command being hooked
522 * @param CommandData $commandData All of the parameter data associated with the
523 * current command invokation, including the InputInterface, OutputInterface
526 function annotationcommand_adapter_call_initialize($names, CommandData $commandData)
528 $factory = annotationcommand_adapter_get_factory();
529 $hookManager = $factory->hookManager();
531 $hooks = $hookManager->getHooks(
534 HookManager::PRE_INITIALIZE,
535 HookManager::INITIALIZE,
536 HookManager::POST_INITIALIZE,
538 $commandData->annotationData()
541 foreach ((array)$hooks as $hook) {
542 $hook($commandData->input(), $commandData->annotationData());
547 * Convert from an old-style Drush pre-validate hook into annotated-command hooks.
548 * @see _drush_invoke_hooks().
550 * @param string[] $names All of the applicable names for the command being hooked
551 * @param CommandData $commandData All of the parameter data associated with the
552 * current command invokation, including the InputInterface, OutputInterface
555 * @return boolean|object
557 function annotationcommand_adapter_call_hook_pre_validate($names, CommandData $commandData)
559 return annotationcommand_adapter_call_validate_interface(
562 HookManager::PRE_ARGUMENT_VALIDATOR,
569 * Convert from an old-style Drush validate hook into annotated-command hooks.
570 * @see _drush_invoke_hooks().
572 * @param string[] $names All of the applicable names for the command being hooked
573 * @param CommandData $commandData All of the parameter data associated with the
574 * current command invokation, including the InputInterface, OutputInterface
577 * @return boolean|object
579 function annotationcommand_adapter_call_hook_validate($names, CommandData $commandData)
581 return annotationcommand_adapter_call_validate_interface(
584 HookManager::ARGUMENT_VALIDATOR,
591 * Convert from an old-style Drush pre-command hook into annotated-command hooks.
592 * @see _drush_invoke_hooks().
594 * @param string[] $names All of the applicable names for the command being hooked
595 * @param CommandData $commandData All of the parameter data associated with the
596 * current command invokation, including the InputInterface, OutputInterface
599 * @return boolean|object
601 function annotationcommand_adapter_call_hook_pre_command($names, CommandData $commandData)
603 return annotationcommand_adapter_call_validate_interface(
606 HookManager::PRE_COMMAND_HOOK,
613 * Convert from an old-style Drush 'command' hook into annotated-command hooks.
614 * @see _drush_invoke_hooks().
616 * @param string[] $names All of the applicable names for the command being hooked
617 * @param CommandData $commandData All of the parameter data associated with the
618 * current command invokation, including the InputInterface, OutputInterface
621 * @return boolean|object
623 function annotationcommand_adapter_call_hook_command($names, CommandData $commandData)
625 return annotationcommand_adapter_call_validate_interface(
628 HookManager::COMMAND_HOOK,
635 * Convert from an old-style Drush post-command hook into annotated-command hooks.
636 * @see _drush_invoke_hooks().
638 * @param string[] $names All of the applicable names for the command being hooked
639 * @param CommandData $commandData All of the parameter data associated with the
640 * current command invokation, including the InputInterface, OutputInterface
642 * @param mixed $return The return value of the command being executed
644 * @return mixed The altered command return value
646 function annotationcommand_adapter_call_hook_post_command($names, CommandData $commandData, $return)
648 return annotationcommand_adapter_call_process_interface(
651 HookManager::POST_COMMAND_HOOK,
659 * After the primary Drush command hook is called, call all of the annotated-command
660 * process and alter hooks.
661 * @see _drush_invoke_hooks().
663 * @param string[] $names All of the applicable names for the command being hooked
664 * @param CommandData $commandData All of the parameter data associated with the
665 * current command invokation, including the InputInterface, OutputInterface
667 * @param mixed $return The return value of the command being executed
669 * @return mixed The altered command return value
671 function annotationcommand_adapter_call_hook_process_and_alter($names, $commandData, $return)
673 return annotationcommand_adapter_call_process_interface(
676 HookManager::PRE_PROCESS_RESULT,
677 HookManager::PROCESS_RESULT,
678 HookManager::POST_PROCESS_RESULT,
679 HookManager::PRE_ALTER_RESULT,
680 HookManager::ALTER_RESULT,
681 HookManager::POST_ALTER_RESULT,
689 * Given a list of hooks that conform to the interface ProcessResultInterface,
690 * call them and return the result.
692 * @param string[] $names All of the applicable names for the command being hooked
693 * @param string[] $hooks All of the HookManager hooks that should be called
694 * @param CommandData $commandData All of the parameter data associated with the
695 * current command invokation, including the InputInterface, OutputInterface
697 * @param mixed $return The return value of the command being executed
699 * @return mixed The altered command return value
701 function annotationcommand_adapter_call_process_interface($names, $hooks, CommandData $commandData, $return)
703 $factory = annotationcommand_adapter_get_factory();
704 $hookManager = $factory->hookManager();
706 $hooks = $hookManager->getHooks($names, $hooks, $commandData->annotationData());
708 foreach ((array)$hooks as $hook) {
709 $result = $hook($return, $commandData);
710 if (isset($result)) {
718 * Given a list of hooks that conform to the interface ValidatorInterface,
719 * call them and return the result.
721 * @param string[] $names All of the applicable names for the command being hooked
722 * @param string[] $hooks All of the HookManager hooks that should be called
723 * @param CommandData $commandData All of the parameter data associated with the
724 * current command invokation, including the InputInterface, OutputInterface
727 * @return boolean|object
729 function annotationcommand_adapter_call_validate_interface($names, $hooks, CommandData $commandData)
731 $factory = annotationcommand_adapter_get_factory();
732 $hookManager = $factory->hookManager();
734 $annotationData = $commandData->annotationData();
735 $hooks = $hookManager->getHooks($names, $hooks, $annotationData);
737 foreach ((array)$hooks as $hook) {
738 $validated = $hook($commandData);
739 // TODO: if $validated is a CommandError, maybe the best thing to do is 'return drush_set_error()'?
740 if (is_object($validated) || ($validated === false)) {
750 function annotationcommand_adapter_alter_option_description_format($option_help, $commandinfo, $default) {
751 $formatterManager = annotatedcomand_adapter_get_formatter();
752 $return_type = $commandinfo->getReturnType();
753 if (!empty($return_type)) {
754 $available_formats = $formatterManager->validFormats($return_type);
755 $option_help['description'] = dt('Select output format. Available: !formats.', array('!formats' => implode(', ', $available_formats)));
756 if (!empty($default)) {
757 $option_help['description'] .= dt(' Default is !default.', array('!default' => $default));
766 function annotationcommand_adapter_alter_option_description_fields($option_help, $commandinfo, $default) {
767 $formatOptions = new FormatterOptions($commandinfo->getAnnotations()->getArrayCopy());
768 $field_labels = $formatOptions->get(FormatterOptions::FIELD_LABELS);
769 $default_fields = $formatOptions->get(FormatterOptions::DEFAULT_FIELDS, [], array_keys($field_labels));
770 $available_fields = array_keys($field_labels);
771 $option_help['example-value'] = implode(', ', $default_fields);
772 $option_help['description'] = dt('Fields to output. All available fields are: !available.', array('!available' => implode(', ', $available_fields)));
777 * In some circumstances, Drush just does a deep search for any *.drush.inc
778 * file, so that it can find all commands, in enabled and disabled modules alike,
779 * for the purpose of displaying the help text for that command.
781 function annotationcommand_adapter_refine_searchpaths($searchpath) {
783 foreach ($searchpath as $path) {
785 $pattern = '/.*\.info$/';
786 if (drush_drupal_major_version() > 7) {
787 $pattern = '/.*\.info.yml$/';
789 $locations = drush_scan_directory($path, $pattern, ['.', '..'], false, $max_depth);
791 // Search for any directory that might be a module or theme (contains
792 // a *.info or a *.info.yml file)
793 foreach ($locations as $key => $info) {
794 $result[dirname($key)] = true;
797 return array_keys($result);