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