cli.drush.inc

  1. 8.0.x commands/core/cli.drush.inc
  2. 7.x commands/core/cli.drush.inc
  3. master commands/core/cli.drush.inc

Functions

Namesort descending Description
cli_drush_command Implements hook_drush_command().
drush_cli_core_cli Command callback.
drush_history_path_cli Returns the file path for the CLI history.
_drush_core_cli_get_casters Returns a mapped array of casters for use in the shell.
_drush_core_cli_get_commands Returns a filtered list of Drush commands used for CLI commands.
_drush_core_cli_get_php_keywords Returns a list of PHP keywords.

File

commands/core/cli.drush.inc
View source
  1. <?php
  2. use Drush\Log\LogLevel;
  3. use Drupal\Component\Assertion\Handle;
  4. use Drush\Psysh\DrushHelpCommand;
  5. use Drush\Psysh\DrushCommand;
  6. use Drush\Psysh\Shell;
  7. /**
  8. * Implements hook_drush_command().
  9. */
  10. function cli_drush_command() {
  11. $items['core-cli'] = array(
  12. 'description' => 'Open an interactive shell on a Drupal site.',
  13. 'remote-tty' => TRUE,
  14. 'aliases' => array('php'),
  15. 'bootstrap' => DRUSH_BOOTSTRAP_MAX,
  16. 'topics' => array('docs-repl'),
  17. 'options' => array(
  18. 'version-history' => 'Use command history based on Drupal version (Default is per site).',
  19. ),
  20. );
  21. $items['docs-repl'] = array(
  22. 'description' => 'repl.md',
  23. 'hidden' => TRUE,
  24. 'topic' => TRUE,
  25. 'bootstrap' => DRUSH_BOOTSTRAP_NONE,
  26. 'callback' => 'drush_print_file',
  27. 'callback arguments' => array(drush_get_context('DOC_PREFIX', DRUSH_BASE_PATH) . '/docs/repl.md'),
  28. );
  29. return $items;
  30. }
  31. /**
  32. * Command callback.
  33. */
  34. function drush_cli_core_cli() {
  35. $drupal_major_version = drush_drupal_major_version();
  36. $configuration = new \Psy\Configuration();
  37. // Set the Drush specific history file path.
  38. $configuration->setHistoryFile(drush_history_path_cli());
  39. $shell = new Shell($configuration);
  40. if ($drupal_major_version >= 8) {
  41. // Register the assertion handler so exceptions are thrown instead of errors
  42. // being triggered. This plays nicer with PsySH.
  43. Handle::register();
  44. $shell->setScopeVariables(['container' => \Drupal::getContainer()]);
  45. // Add Drupal 8 specific casters to the shell configuration.
  46. $configuration->addCasters(_drush_core_cli_get_casters());
  47. }
  48. // Add Drush commands to the shell.
  49. $commands = [new DrushHelpCommand()];
  50. foreach (drush_commands_categorize(_drush_core_cli_get_commands()) as $category_data) {
  51. $category_title = (string) $category_data['title'];
  52. foreach ($category_data['commands'] as $command_config) {
  53. $command = new DrushCommand($command_config);
  54. // Set the category label on each.
  55. $command->setCategory($category_title);
  56. $commands[] = $command;
  57. }
  58. }
  59. $shell->addCommands($commands);
  60. // PsySH will never return control to us, but our shutdown handler will still
  61. // run after the user presses ^D. Mark this command as completed to avoid a
  62. // spurious error message.
  63. drush_set_context('DRUSH_EXECUTION_COMPLETED', TRUE);
  64. // Run the terminate event before the shell is run. Otherwise, if the shell
  65. // is forking processes (the default), any child processes will close the
  66. // database connection when they are killed. So when we return back to the
  67. // parent process after, there is no connection. This will be called after the
  68. // command in preflight still, but the subscriber instances are already
  69. // created from before. Call terminate() regardless, this is a no-op for all
  70. // DrupalBoot classes except DrupalBoot8.
  71. if ($bootstrap = \Drush::bootstrap()) {
  72. $bootstrap->terminate();
  73. }
  74. // To fix the above problem in Drupal 7, the connection can be closed manually.
  75. // This will make sure a new connection is created again in child loops. So
  76. // any shutdown functions will still run ok after the shell has exited.
  77. if ($drupal_major_version == 7) {
  78. Database::closeConnection();
  79. }
  80. $shell->run();
  81. }
  82. /**
  83. * Returns a filtered list of Drush commands used for CLI commands.
  84. *
  85. * @return array
  86. */
  87. function _drush_core_cli_get_commands() {
  88. $commands = drush_get_commands();
  89. $ignored_commands = ['help', 'drush-psysh', 'php-eval', 'core-cli', 'php'];
  90. $php_keywords = _drush_core_cli_get_php_keywords();
  91. foreach ($commands as $name => $config) {
  92. // Ignore some commands that don't make sense inside PsySH, are PHP keywords
  93. // are hidden, or are aliases.
  94. if (in_array($name, $ignored_commands) || in_array($name, $php_keywords) || !empty($config['hidden']) || ($name !== $config['command'])) {
  95. unset($commands[$name]);
  96. }
  97. else {
  98. // Make sure the command aliases don't contain any PHP keywords.
  99. if (!empty($config['aliases'])) {
  100. $commands[$name]['aliases'] = array_diff($commands[$name]['aliases'], $php_keywords);
  101. }
  102. }
  103. }
  104. return $commands;
  105. }
  106. /**
  107. * Returns a mapped array of casters for use in the shell.
  108. *
  109. * These are Symfony VarDumper casters.
  110. * See http://symfony.com/doc/current/components/var_dumper/advanced.html#casters
  111. * for more information.
  112. *
  113. * @return array.
  114. * An array of caster callbacks keyed by class or interface.
  115. */
  116. function _drush_core_cli_get_casters() {
  117. return [
  118. 'Drupal\Core\Entity\ContentEntityInterface' => 'Drush\Psysh\Caster::castContentEntity',
  119. 'Drupal\Core\Field\FieldItemListInterface' => 'Drush\Psysh\Caster::castFieldItemList',
  120. 'Drupal\Core\Field\FieldItemInterface' => 'Drush\Psysh\Caster::castFieldItem',
  121. 'Drupal\Core\Config\Entity\ConfigEntityInterface' => 'Drush\Psysh\Caster::castConfigEntity',
  122. 'Drupal\Core\Config\ConfigBase' => 'Drush\Psysh\Caster::castConfig',
  123. 'Drupal\Component\DependencyInjection\Container' => 'Drush\Psysh\Caster::castContainer',
  124. 'Drupal\Component\Render\MarkupInterface' => 'Drush\Psysh\Caster::castMarkup',
  125. ];
  126. }
  127. /**
  128. * Returns the file path for the CLI history.
  129. *
  130. * This can either be site specific (default) or Drupal version specific.
  131. *
  132. * @return string.
  133. */
  134. function drush_history_path_cli() {
  135. $cli_directory = drush_directory_cache('cli');
  136. // If only the Drupal version is being used for the history.
  137. if (drush_get_option('version-history', FALSE)) {
  138. $drupal_major_version = drush_drupal_major_version();
  139. $file_name = "drupal-$drupal_major_version";
  140. }
  141. // If there is an alias, use that in the site specific name. Otherwise,
  142. // use a hash of the root path.
  143. else {
  144. if ($alias = drush_get_context('DRUSH_TARGET_SITE_ALIAS')) {
  145. $site = drush_sitealias_get_record($alias);
  146. $site_suffix = $site['#name'];
  147. }
  148. else {
  149. $site_suffix = md5(DRUPAL_ROOT);
  150. }
  151. $file_name = "drupal-site-$site_suffix";
  152. }
  153. $full_path = "$cli_directory/$file_name";
  154. // Output the history path if verbose is enabled.
  155. if (drush_get_context('DRUSH_VERBOSE')) {
  156. drush_log(dt('History: @full_path', ['@full_path' => $full_path]), LogLevel::INFO);
  157. }
  158. return $full_path;
  159. }
  160. /**
  161. * Returns a list of PHP keywords.
  162. *
  163. * This will act as a blacklist for command and alias names.
  164. *
  165. * @return array
  166. */
  167. function _drush_core_cli_get_php_keywords() {
  168. return [
  169. '__halt_compiler',
  170. 'abstract',
  171. 'and',
  172. 'array',
  173. 'as',
  174. 'break',
  175. 'callable',
  176. 'case',
  177. 'catch',
  178. 'class',
  179. 'clone',
  180. 'const',
  181. 'continue',
  182. 'declare',
  183. 'default',
  184. 'die',
  185. 'do',
  186. 'echo',
  187. 'else',
  188. 'elseif',
  189. 'empty',
  190. 'enddeclare',
  191. 'endfor',
  192. 'endforeach',
  193. 'endif',
  194. 'endswitch',
  195. 'endwhile',
  196. 'eval',
  197. 'exit',
  198. 'extends',
  199. 'final',
  200. 'for',
  201. 'foreach',
  202. 'function',
  203. 'global',
  204. 'goto',
  205. 'if',
  206. 'implements',
  207. 'include',
  208. 'include_once',
  209. 'instanceof',
  210. 'insteadof',
  211. 'interface',
  212. 'isset',
  213. 'list',
  214. 'namespace',
  215. 'new',
  216. 'or',
  217. 'print',
  218. 'private',
  219. 'protected',
  220. 'public',
  221. 'require',
  222. 'require_once',
  223. 'return',
  224. 'static',
  225. 'switch',
  226. 'throw',
  227. 'trait',
  228. 'try',
  229. 'unset',
  230. 'use',
  231. 'var',
  232. 'while',
  233. 'xor',
  234. ];
  235. }