devel.drush8.inc 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. <?php
  2. /**
  3. * @file
  4. * This file is only used by Drush8. Drush9 discovers its commands via tagged
  5. * service(s) in devel.services.yml. Also see classes in src/Commands.
  6. */
  7. use Drupal\Component\Uuid\Php;
  8. /**
  9. * Implements hook_drush_command().
  10. */
  11. function devel_drush_command() {
  12. $items['devel-reinstall'] = array(
  13. 'description' => dt('Uninstall, and Install a list of projects.'),
  14. 'drush dependencies' => array('pm'),
  15. 'arguments' => array(
  16. 'projects' => dt('A space-separated list of project names.'),
  17. ),
  18. 'allow-additional-options' => array('pm-uninstall', 'pm-enable'),
  19. 'required-arguments' => 1,
  20. 'aliases' => array('dre'),
  21. );
  22. $items['fn-hook'] = array(
  23. 'description' => 'List implementations of a given hook and explore the source of the selected one.',
  24. 'arguments' => array(
  25. 'hook' => 'The name of the hook to explore (e.g. "menu" for hook_menu()).'
  26. ),
  27. 'examples' => array(
  28. 'fn-hook cron' => 'List implementations of hook_cron().',
  29. ),
  30. 'allow-additional-options' => array('fn-view'),
  31. 'required-arguments' => 1,
  32. 'aliases' => array('fnh', 'hook'),
  33. );
  34. $items['fn-event'] = array(
  35. 'description' => 'List implementations of a given event and explore source of specified one.',
  36. 'arguments' => array(
  37. 'event' => 'The name of the event to explore. If omitted, a list of events is shown.'
  38. ),
  39. 'examples' => array(
  40. 'fn-event' => 'Pick a Kernel event, then pick an implementation, and then view its source code.',
  41. 'fn-event kernel.terminate' => 'Pick a terminate subscribers and view its source code.',
  42. ),
  43. 'allow-additional-options' => array('fn-view'),
  44. 'aliases' => array('fne', 'event'),
  45. );
  46. $items['fn-view'] = array(
  47. 'description' => 'Show the source of specified function or method.',
  48. 'arguments' => array(
  49. 'function' => 'The name of the function or method to view.',
  50. ),
  51. 'options' => array(
  52. 'pipe' => 'Output just the filename of the function or method',
  53. 'format' => 'Specify how the filename should be printed. Available placeholders are @startline, @endline and @file',
  54. ),
  55. 'examples' => array(
  56. 'fn-view drupal_set_breadcrumb' => 'View the source code for function "drupal_set_breadcrumb"',
  57. 'vi `drush --pipe fn-view user_access --format=\'+@startline @file\'`' => 'Edit the file that contains the function "user_access"',
  58. 'fn-view NodeController::load' => 'View the source code for method load in the class NodeController'
  59. ),
  60. 'aliases' => array('fnv'),
  61. 'required-arguments' => 1,
  62. );
  63. $items['devel-token'] = array(
  64. 'description' => dt('List available tokens'),
  65. 'aliases' => array('token'),
  66. //@todo support --format option for json, csv, etc.
  67. );
  68. $items['devel-container-services'] = array(
  69. 'description' => 'Get a list of available container services.',
  70. 'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_FULL,
  71. 'core' => array('8+'),
  72. 'aliases' => array('dcs'),
  73. 'options' => array(
  74. 'format' => 'Format to output. Allowed values are: json, export, html.',
  75. ),
  76. 'arguments' => array(
  77. 'prefix' => 'A prefix to filter the service list by.',
  78. ),
  79. 'examples' => array(
  80. 'drush container-services' => 'Gets a list of all available container services',
  81. 'drush container-services plugin.manager' => 'Get all services containing "plugin.manager"',
  82. ),
  83. 'outputformat' => array(
  84. 'default' => 'list',
  85. 'pipe-format' => 'export',
  86. ),
  87. );
  88. $items['devel-generate-uuid'] = array(
  89. 'description' => 'Generate a UUID.',
  90. 'core' => array('8+'),
  91. 'examples' => array(
  92. "drush devel-generate-uuid" => "Outputs a Universally Unique IDentifier.",
  93. ),
  94. 'aliases' => array('uuid'),
  95. 'outputformat' => array(
  96. 'default' => 'string',
  97. ),
  98. );
  99. return $items;
  100. }
  101. /**
  102. * A command callback. This is faster than 3 separate bootstraps.
  103. */
  104. function drush_devel_reinstall() {
  105. $projects = func_get_args();
  106. $args = array_merge(array('pm-uninstall'), $projects);
  107. call_user_func_array('drush_invoke', $args);
  108. $args = array_merge(array('pm-enable'), $projects);
  109. call_user_func_array('drush_invoke', $args);
  110. }
  111. /**
  112. * Command handler. Show hook implementations.
  113. */
  114. function drush_devel_fn_hook($hook) {
  115. // Get implementations in the .install files as well.
  116. include_once './core/includes/install.inc';
  117. drupal_load_updates();
  118. if ($hook_implementations = \Drupal::moduleHandler()->getImplementations($hook)) {
  119. if ($choice = drush_choice(array_combine($hook_implementations, $hook_implementations), 'Enter the number of the hook implementation you wish to view.')) {
  120. return drush_devel_fn_view($choice . "_$hook");
  121. }
  122. }
  123. else {
  124. drush_log(dt('No implementations.'), 'ok');
  125. }
  126. }
  127. /**
  128. * Command handler. Show hook implementations.
  129. */
  130. function drush_devel_fn_event($event = NULL) {
  131. $dispatcher = Drupal::service('event_dispatcher');
  132. if (empty($event)) {
  133. $events = array('kernel.controller', 'kernel.exception', 'kernel.request', 'kernel.response', 'kernel.terminate', 'kernel.view');
  134. $events = array_combine($events, $events);
  135. if (!$event = drush_choice($events, 'Enter the event you wish to explore.')) {
  136. return drush_user_abort();
  137. }
  138. }
  139. if ($implementations = $dispatcher->getListeners($event)) {
  140. foreach ($implementations as $implementation) {
  141. $callable = get_class($implementation[0]) . '::' . $implementation[1];
  142. $choices[$callable] = $callable;
  143. }
  144. if ($choice = drush_choice($choices, 'Enter the number of the implementation you wish to view.')) {
  145. return drush_devel_fn_view($choice);
  146. }
  147. }
  148. else {
  149. drush_log(dt('No implementations.'), 'ok');
  150. }
  151. }
  152. /**
  153. * Command handler. Show source code of specified function or method.
  154. */
  155. function drush_devel_fn_view($function_name) {
  156. // Get implementations in the .install files as well.
  157. include_once './core/includes/install.inc';
  158. drupal_load_updates();
  159. if (strpos($function_name, '::') === FALSE) {
  160. if (!function_exists($function_name)) {
  161. return drush_set_error(dt('Function not found'));
  162. }
  163. $reflect = new ReflectionFunction($function_name);
  164. }
  165. else {
  166. list($class, $method) = explode('::', $function_name);
  167. if (!method_exists($class, $method)) {
  168. return drush_set_error(dt('Method not found'));
  169. }
  170. $reflect = new ReflectionMethod($class, $method);
  171. }
  172. $func_info = array('@file' => $reflect->getFileName(), '@startline' => $reflect->getStartLine(), '@endline' => $reflect->getEndLine());
  173. $format = drush_get_option('format', '@file');
  174. drush_print_pipe(dt($format, $func_info));
  175. drush_print(dt("// file: @file, lines @startline-@endline", $func_info));
  176. _drush_devel_print_function($reflect->getFileName(), $reflect->getStartLine(), $reflect->getEndLine());
  177. }
  178. /**
  179. * Command callback. List available tokens.
  180. */
  181. function drush_devel_token() {
  182. $rows[] = array(dt('Group'), dt('Token'), dt('Name'));
  183. $all = \Drupal::token()->getInfo();
  184. foreach ($all['tokens'] as $group => $tokens) {
  185. foreach ($tokens as $key => $token) {
  186. $rows[] = array($group, $key, $token['name']);
  187. }
  188. }
  189. drush_print_table($rows, TRUE);
  190. }
  191. /**
  192. * Command callback. Outputs a UUID.
  193. *
  194. * @return string
  195. * A freshly generated UUID.
  196. */
  197. function drush_devel_generate_uuid() {
  198. $uuid = new Php();
  199. return $uuid->generate();
  200. }
  201. /**
  202. * Print the specified function, including any
  203. * doxygen-style comments that come before it.
  204. */
  205. function _drush_devel_print_function($file, $start_line, $end_line) {
  206. $line_num = 0;
  207. $doxygen = NULL;
  208. $fp = fopen( $file, 'r' );
  209. while (!feof($fp) && ($line_num < ($start_line - 1))) {
  210. $line = fgets($fp);
  211. ++$line_num;
  212. if (substr($line,0,3) == '/**') {
  213. $doxygen = $line;
  214. }
  215. elseif (isset($doxygen)) {
  216. $doxygen .= $line;
  217. if ($line_num + 1 == $start_line) {
  218. drush_print(rtrim($doxygen));
  219. }
  220. if (strstr($line, '*/') !== FALSE) {
  221. $doxygen = NULL;
  222. }
  223. }
  224. }
  225. while (!feof($fp) && ($line_num < $end_line)) {
  226. $line = fgets($fp);
  227. ++$line_num;
  228. drush_print(rtrim($line));
  229. }
  230. }
  231. /**
  232. * Command callback to list available container services.
  233. */
  234. function drush_devel_container_services($prefix = NULL) {
  235. $container = Drupal::getContainer();
  236. if (empty($container)) {
  237. return drush_set_error(dt('No container was found.'));
  238. }
  239. // Get a list of all available service IDs.
  240. $services = $container->getServiceIds();
  241. // If there is a prefix, try to find matches.
  242. if (isset($prefix)) {
  243. $services = preg_grep("/$prefix/", $services);
  244. }
  245. if (empty($services)) {
  246. return drush_log(dt('No container services found.'), 'ok');
  247. }
  248. sort($services);
  249. return $services;
  250. }