bootstrap.inc

  1. 8.0.x tests/bootstrap.inc
  2. 8.0.x includes/bootstrap.inc
  3. 6.x includes/bootstrap.inc
  4. 7.x tests/bootstrap.inc
  5. 7.x includes/bootstrap.inc
  6. 5.x includes/bootstrap.inc
  7. master includes/bootstrap.inc
  8. master tests/bootstrap.inc

Functions

Namesort descending Description
drush_autoload Used by a Drush extension to request that its Composer autoload files be loaded by Drush, if they have not already been.
drush_bootstrap Bootstrap Drush to the desired phase.
drush_bootstrap_error Helper function to collect any errors that occur during the bootstrap process. Always returns FALSE, for convenience.
drush_bootstrap_max Bootstrap to the highest level possible, without triggering any errors.
drush_bootstrap_max_to_sitealias Bootstrap the specified site alias. The site alias must be a valid alias to a local site.
drush_bootstrap_to_phase Bootstrap to the specified phase.
drush_bootstrap_validate Validate whether a bootstrap phase can be reached.
drush_bootstrap_value Helper function to store any context settings that are being validated.
drush_has_boostrapped Determine whether a given bootstrap phase has been completed
_drush_bootstrap_output_prepare
_drush_bootstrap_phases Returns an array that determines what bootstrap phases are necessary to bootstrap the CMS.
_drush_bootstrap_selected_uri Find the URI that has been selected by the cwd if it was not previously set via the --uri / -l option

Constants

Namesort descending Description
DRUSH_BOOTSTRAP_DRUPAL_CONFIGURATION Load the settings from the Drupal sites directory.
DRUSH_BOOTSTRAP_DRUPAL_DATABASE Connect to the Drupal database using the database credentials loaded during the previous bootstrap phase.
DRUSH_BOOTSTRAP_DRUPAL_FULL Fully initialize Drupal.
DRUSH_BOOTSTRAP_DRUPAL_LOGIN Log in to the initialiased Drupal site.
DRUSH_BOOTSTRAP_DRUPAL_ROOT Set up and test for a valid drupal root, either through the -r/--root options, or evaluated based on the current working directory.
DRUSH_BOOTSTRAP_DRUPAL_SITE Set up a Drupal site directory and the correct environment variables to allow Drupal to find the configuration file.
DRUSH_BOOTSTRAP_DRUSH @deprecated
DRUSH_BOOTSTRAP_MAX Use drush_bootstrap_max instead of drush_bootstrap_to_phase
DRUSH_BOOTSTRAP_NONE No bootstrap.

File

includes/bootstrap.inc
View source
  1. <?php
  2. use Drush\Log\LogLevel;
  3. /**
  4. * No bootstrap.
  5. *
  6. * Commands that only preflight, but do not bootstrap, should use
  7. * a bootstrap level of DRUSH_BOOTSTRAP_NONE.
  8. */
  9. define('DRUSH_BOOTSTRAP_NONE', -1);
  10. /**
  11. * Use drush_bootstrap_max instead of drush_bootstrap_to_phase
  12. *
  13. * This constant is only usable as the value of the 'bootstrap'
  14. * item of a command object, or as the parameter to
  15. * drush_bootstrap_to_phase. It is not a real bootstrap state.
  16. */
  17. define('DRUSH_BOOTSTRAP_MAX', -2);
  18. /**
  19. * @deprecated
  20. *
  21. * No longer used, but 0 remains reserved. Drush always runs preflight.
  22. * Commands may alternatively use DRUSH_BOOTSTRAP_NONE.
  23. */
  24. define('DRUSH_BOOTSTRAP_DRUSH', 0);
  25. // TODO: Move all of the constants below to a Drupal-specific file.
  26. // We can't do this until commands are declaring which CMS they work
  27. // with, because right now, commands that do not declare a 'bootstrap'
  28. // level default to DRUSH_BOOTSTRAP_DRUPAL_LOGIN, so we need this constant,
  29. // at least, available in non-Drupal contexts.
  30. /**
  31. * Set up and test for a valid drupal root, either through the -r/--root options,
  32. * or evaluated based on the current working directory.
  33. *
  34. * Any code that interacts with an entire Drupal installation, and not a specific
  35. * site on the Drupal installation should use this bootstrap phase.
  36. */
  37. define('DRUSH_BOOTSTRAP_DRUPAL_ROOT', 1);
  38. /**
  39. * Set up a Drupal site directory and the correct environment variables to
  40. * allow Drupal to find the configuration file.
  41. *
  42. * If no site is specified with the -l / --uri options, Drush will assume the
  43. * site is 'default', which mimics Drupal's behaviour.
  44. *
  45. * If you want to avoid this behaviour, it is recommended that you use the
  46. * DRUSH_BOOTSTRAP_DRUPAL_ROOT bootstrap phase instead.
  47. *
  48. * Any code that needs to modify or interact with a specific Drupal site's
  49. * settings.php file should bootstrap to this phase.
  50. */
  51. define('DRUSH_BOOTSTRAP_DRUPAL_SITE', 2);
  52. /**
  53. * Load the settings from the Drupal sites directory.
  54. *
  55. * This phase is analagous to the DRUPAL_BOOTSTRAP_CONFIGURATION bootstrap phase in Drupal
  56. * itself, and this is also the first step where Drupal specific code is included.
  57. *
  58. * This phase is commonly used for code that interacts with the Drupal install API,
  59. * as both install.php and update.php start at this phase.
  60. */
  61. define('DRUSH_BOOTSTRAP_DRUPAL_CONFIGURATION', 3);
  62. /**
  63. * Connect to the Drupal database using the database credentials loaded
  64. * during the previous bootstrap phase.
  65. *
  66. * This phase is analogous to the DRUPAL_BOOTSTRAP_DATABASE bootstrap phase in
  67. * Drupal.
  68. *
  69. * Any code that needs to interact with the Drupal database API needs to
  70. * be bootstrapped to at least this phase.
  71. */
  72. define('DRUSH_BOOTSTRAP_DRUPAL_DATABASE', 4);
  73. /**
  74. * Fully initialize Drupal.
  75. *
  76. * This is analogous to the DRUPAL_BOOTSTRAP_FULL bootstrap phase in
  77. * Drupal.
  78. *
  79. * Any code that interacts with the general Drupal API should be
  80. * bootstrapped to this phase.
  81. */
  82. define('DRUSH_BOOTSTRAP_DRUPAL_FULL', 5);
  83. /**
  84. * Log in to the initialiased Drupal site.
  85. *
  86. * This is the default bootstrap phase all commands will try to reach,
  87. * unless otherwise specified.
  88. *
  89. * This bootstrap phase is used after the site has been
  90. * fully bootstrapped.
  91. *
  92. * This phase will log you in to the drupal site with the username
  93. * or user ID specified by the --user/ -u option.
  94. *
  95. * Use this bootstrap phase for your command if you need to have access
  96. * to information for a specific user, such as listing nodes that might
  97. * be different based on who is logged in.
  98. */
  99. define('DRUSH_BOOTSTRAP_DRUPAL_LOGIN', 6);
  100. /**
  101. * Find the URI that has been selected by the cwd
  102. * if it was not previously set via the --uri / -l option
  103. */
  104. function _drush_bootstrap_selected_uri() {
  105. $uri = drush_get_context('DRUSH_SELECTED_URI');
  106. if (empty($uri)) {
  107. $site_path = drush_site_path();
  108. if ($site_path) {
  109. $site_path = _drush_convert_path($site_path);
  110. }
  111. $elements = explode('/', $site_path);
  112. $current = array_pop($elements);
  113. if (!$current) {
  114. $current = 'default';
  115. }
  116. $uri = 'http://'. $current;
  117. $uri = drush_set_context('DRUSH_SELECTED_URI', $uri);
  118. drush_sitealias_create_self_alias();
  119. }
  120. return $uri;
  121. }
  122. /**
  123. * Helper function to store any context settings that are being validated.
  124. */
  125. function drush_bootstrap_value($context, $value = null) {
  126. $values =& drush_get_context('DRUSH_BOOTSTRAP_VALUES', array());
  127. if (isset($value)) {
  128. $values[$context] = $value;
  129. }
  130. if (array_key_exists($context, $values)) {
  131. return $values[$context];
  132. }
  133. return null;
  134. }
  135. /**
  136. * Returns an array that determines what bootstrap phases
  137. * are necessary to bootstrap the CMS.
  138. *
  139. * @param bool $function_names
  140. * (optional) If TRUE, return an array of method names index by their
  141. * corresponding phase values. Otherwise return an array of phase values.
  142. *
  143. * @return array
  144. *
  145. * @see \Drush\Boot\Boot::bootstrap_phases()
  146. */
  147. function _drush_bootstrap_phases($function_names = FALSE) {
  148. $result = array();
  149. if ($bootstrap = \Drush::bootstrap()) {
  150. $result = $bootstrap->bootstrap_phases();
  151. if (!$function_names) {
  152. $result = array_keys($result);
  153. }
  154. }
  155. return $result;
  156. }
  157. /**
  158. * Bootstrap Drush to the desired phase.
  159. *
  160. * This function will sequentially bootstrap each
  161. * lower phase up to the phase that has been requested.
  162. *
  163. * @param int $phase
  164. * The bootstrap phase to bootstrap to.
  165. * @param int $phase_max
  166. * (optional) The maximum level to boot to. This does not have a use in this
  167. * function itself but can be useful for other code called from within this
  168. * function, to know if e.g. a caller is in the process of booting to the
  169. * specified level. If specified, it should never be lower than $phase.
  170. *
  171. * @return bool
  172. * TRUE if the specified bootstrap phase has completed.
  173. *
  174. * @see \Drush\Boot\Boot::bootstrap_phases()
  175. */
  176. function drush_bootstrap($phase, $phase_max = FALSE) {
  177. $bootstrap = \Drush::bootstrap();
  178. $phases = _drush_bootstrap_phases(TRUE);
  179. $result = TRUE;
  180. // If the requested phase does not exist in the list of available
  181. // phases, it means that the command requires bootstrap to a certain
  182. // level, but no site root could be found.
  183. if (!isset($phases[$phase])) {
  184. $result = drush_bootstrap_error('DRUSH_NO_SITE', dt("We could not find an applicable site for that command."));
  185. }
  186. // Once we start bootstrapping past the DRUSH_BOOTSTRAP_DRUSH phase, we
  187. // will latch the bootstrap object, and prevent it from changing.
  188. if ($phase > DRUSH_BOOTSTRAP_DRUSH) {
  189. \Drush::bootstrapManager()->latch($bootstrap);
  190. }
  191. drush_set_context('DRUSH_BOOTSTRAPPING', TRUE);
  192. foreach ($phases as $phase_index => $current_phase) {
  193. $bootstrapped_phase = drush_get_context('DRUSH_BOOTSTRAP_PHASE', -1);
  194. if ($phase_index > $phase) {
  195. break;
  196. }
  197. if ($phase_index > $bootstrapped_phase) {
  198. if ($result = drush_bootstrap_validate($phase_index)) {
  199. if (method_exists($bootstrap, $current_phase) && !drush_get_error()) {
  200. drush_log(dt("Drush bootstrap phase : !function()", array('!function' => $current_phase)), LogLevel::BOOTSTRAP);
  201. $bootstrap->{$current_phase}();
  202. // Reset commandfile cache and find any new command files that are available during this bootstrap phase.
  203. drush_get_commands(TRUE);
  204. _drush_find_commandfiles($phase_index, $phase_max);
  205. }
  206. drush_set_context('DRUSH_BOOTSTRAP_PHASE', $phase_index);
  207. }
  208. }
  209. }
  210. drush_set_context('DRUSH_BOOTSTRAPPING', FALSE);
  211. if (!$result || drush_get_error()) {
  212. $errors = drush_get_context('DRUSH_BOOTSTRAP_ERRORS', array());
  213. foreach ($errors as $code => $message) {
  214. drush_set_error($code, $message);
  215. }
  216. }
  217. return !drush_get_error();
  218. }
  219. /**
  220. * Determine whether a given bootstrap phase has been completed
  221. *
  222. * This function name has a typo which makes me laugh so we choose not to
  223. * fix it. Take a deep breath, and smile. See
  224. * http://en.wikipedia.org/wiki/HTTP_referer
  225. *
  226. *
  227. * @param int $phase
  228. * The bootstrap phase to test
  229. *
  230. * @return bool
  231. * TRUE if the specified bootstrap phase has completed.
  232. */
  233. function drush_has_boostrapped($phase) {
  234. $phase_index = drush_get_context('DRUSH_BOOTSTRAP_PHASE');
  235. return isset($phase_index) && ($phase_index >= $phase);
  236. }
  237. /**
  238. * Validate whether a bootstrap phase can be reached.
  239. *
  240. * This function will validate the settings that will be used
  241. * during the actual bootstrap process, and allow commands to
  242. * progressively bootstrap to the highest level that can be reached.
  243. *
  244. * This function will only run the validation function once, and
  245. * store the result from that execution in a local static. This avoids
  246. * validating phases multiple times.
  247. *
  248. * @param int $phase
  249. * The bootstrap phase to validate to.
  250. *
  251. * @return bool
  252. * TRUE if bootstrap is possible, FALSE if the validation failed.
  253. *
  254. * @see \Drush\Boot\Boot::bootstrap_phases()
  255. */
  256. function drush_bootstrap_validate($phase) {
  257. $bootstrap = \Drush::bootstrap();
  258. $phases = _drush_bootstrap_phases(TRUE);
  259. static $result_cache = array();
  260. if (!array_key_exists($phase, $result_cache)) {
  261. drush_set_context('DRUSH_BOOTSTRAP_ERRORS', array());
  262. drush_set_context('DRUSH_BOOTSTRAP_VALUES', array());
  263. foreach ($phases as $phase_index => $current_phase) {
  264. $validated_phase = drush_get_context('DRUSH_BOOTSTRAP_VALIDATION_PHASE', -1);
  265. if ($phase_index > $phase) {
  266. break;
  267. }
  268. if ($phase_index > $validated_phase) {
  269. $current_phase .= '_validate';
  270. if (method_exists($bootstrap, $current_phase)) {
  271. $result_cache[$phase_index] = $bootstrap->{$current_phase}();
  272. }
  273. else {
  274. $result_cache[$phase_index] = TRUE;
  275. }
  276. drush_set_context('DRUSH_BOOTSTRAP_VALIDATION_PHASE', $phase_index);
  277. }
  278. }
  279. }
  280. return $result_cache[$phase];
  281. }
  282. /**
  283. * Bootstrap to the specified phase.
  284. *
  285. * @param int $max_phase_index
  286. * Only attempt bootstrap to the specified level.
  287. *
  288. * @return bool
  289. * TRUE if the specified bootstrap phase has completed.
  290. */
  291. function drush_bootstrap_to_phase($max_phase_index) {
  292. if ($max_phase_index == DRUSH_BOOTSTRAP_MAX) {
  293. // Bootstrap as far as we can without throwing an error, but log for
  294. // debugging purposes.
  295. drush_log(dt("Trying to bootstrap as far as we can."), 'debug');
  296. drush_bootstrap_max();
  297. return TRUE;
  298. }
  299. drush_log(dt("Bootstrap to phase !phase.", array('!phase' => $max_phase_index)), LogLevel::BOOTSTRAP);
  300. $phases = _drush_bootstrap_phases();
  301. $result = TRUE;
  302. // Try to bootstrap to the maximum possible level, without generating errors
  303. foreach ($phases as $phase_index) {
  304. if ($phase_index > $max_phase_index) {
  305. // Stop trying, since we achieved what was specified.
  306. break;
  307. }
  308. if (drush_bootstrap_validate($phase_index)) {
  309. if ($phase_index > drush_get_context('DRUSH_BOOTSTRAP_PHASE', DRUSH_BOOTSTRAP_NONE)) {
  310. $result = drush_bootstrap($phase_index, $max_phase_index);
  311. }
  312. }
  313. else {
  314. $result = FALSE;
  315. break;
  316. }
  317. }
  318. return $result;
  319. }
  320. /**
  321. * Bootstrap to the highest level possible, without triggering any errors.
  322. *
  323. * @param int $max_phase_index
  324. * (optional) Only attempt bootstrap to the specified level.
  325. *
  326. * @return int
  327. * The maximum phase to which we bootstrapped.
  328. */
  329. function drush_bootstrap_max($max_phase_index = FALSE) {
  330. $phases = _drush_bootstrap_phases(TRUE);
  331. if (!$max_phase_index) {
  332. $max_phase_index = count($phases);
  333. }
  334. // Try to bootstrap to the maximum possible level, without generating errors.
  335. foreach ($phases as $phase_index => $current_phase) {
  336. if ($phase_index > $max_phase_index) {
  337. // Stop trying, since we achieved what was specified.
  338. break;
  339. }
  340. if (drush_bootstrap_validate($phase_index)) {
  341. if ($phase_index > drush_get_context('DRUSH_BOOTSTRAP_PHASE')) {
  342. drush_bootstrap($phase_index, $max_phase_index);
  343. }
  344. }
  345. else {
  346. // drush_bootstrap_validate() only logs successful validations. For us,
  347. // knowing what failed can also be important.
  348. $previous = drush_get_context('DRUSH_BOOTSTRAP_PHASE');
  349. drush_log(dt("Bootstrap phase !function() failed to validate; continuing at !current().", array('!function' => $current_phase, '!current' => $phases[$previous])), 'debug');
  350. break;
  351. }
  352. }
  353. return drush_get_context('DRUSH_BOOTSTRAP_PHASE');
  354. }
  355. /**
  356. * Bootstrap the specified site alias. The site alias must
  357. * be a valid alias to a local site.
  358. *
  359. * @param $site_record
  360. * The alias record for the given site alias.
  361. * @see drush_sitealias_get_record().
  362. * @param $max_phase_index
  363. * Only attempt bootstrap to the specified level.
  364. * @returns TRUE if attempted to bootstrap, or FALSE
  365. * if no bootstrap attempt was made.
  366. */
  367. function drush_bootstrap_max_to_sitealias($site_record, $max_phase_index = NULL) {
  368. if ((array_key_exists('root', $site_record) && !array_key_exists('remote-host', $site_record))) {
  369. drush_sitealias_set_alias_context($site_record);
  370. drush_bootstrap_max($max_phase_index);
  371. return TRUE;
  372. }
  373. return FALSE;
  374. }
  375. /**
  376. * Helper function to collect any errors that occur during the bootstrap process.
  377. * Always returns FALSE, for convenience.
  378. */
  379. function drush_bootstrap_error($code, $message = null) {
  380. $errors = drush_get_context('DRUSH_BOOTSTRAP_ERRORS');
  381. $errors[$code] = $message;
  382. drush_set_context('DRUSH_BOOTSTRAP_ERRORS', $errors);
  383. return FALSE;
  384. }
  385. function _drush_bootstrap_output_prepare() {
  386. // Note that as soon as we set the DRUSH_BACKEND context, we change
  387. // the behavior of drush_log(). It is therefore important that we
  388. // should not set this context until immediately before we call ob_start
  389. // (i.e., in this function).
  390. $backend = drush_set_context('DRUSH_BACKEND', drush_get_option('backend'));
  391. $quiet = drush_get_context('DRUSH_QUIET');
  392. if ($backend) {
  393. // Load options passed as a JSON encoded string through STDIN.
  394. $stdin_options = _drush_backend_get_stdin();
  395. if (is_array($stdin_options)) {
  396. drush_set_context('stdin', $stdin_options);
  397. }
  398. // Add an output buffer handler to collect output/pass through backend
  399. // packets. Using a chunksize of 2 ensures that each line is flushed
  400. // straight away.
  401. if ($quiet) {
  402. // Pass through of backend packets, discard regular output.
  403. ob_start('drush_backend_output_discard', 2);
  404. }
  405. else {
  406. // Collect output.
  407. ob_start('drush_backend_output_collect', 2);
  408. }
  409. }
  410. // In non-backend quiet mode we start buffering and discards it on command
  411. // completion.
  412. if ($quiet && !$backend) {
  413. ob_start();
  414. }
  415. }
  416. /**
  417. * Used by a Drush extension to request that its Composer autoload
  418. * files be loaded by Drush, if they have not already been.
  419. *
  420. * Usage:
  421. *
  422. * function mycommandfile_drush_init() {
  423. * drush_autoload(__FILE__)
  424. * }
  425. *
  426. */
  427. function drush_autoload($commandfile) {
  428. $already_added = commandfiles_cache()->add($commandfile);
  429. $dir = dirname($commandfile);
  430. $candidates = array("vendor/autoload.php", "../../../vendor/autoload.php");
  431. $drush_autoload_file = drush_get_context('DRUSH_VENDOR_PATH', '');
  432. foreach ($candidates as $candidate) {
  433. $autoload = $dir . '/' . $candidate;
  434. if (file_exists($autoload) && (realpath($autoload) != $drush_autoload_file)) {
  435. include $autoload;
  436. }
  437. }
  438. }