DrupalBoot.php

  1. 8.0.x lib/Drush/Boot/DrupalBoot.php
  2. 7.x lib/Drush/Boot/DrupalBoot.php
  3. master lib/Drush/Boot/DrupalBoot.php

Namespace

Drush\Boot

Classes

Namesort descending Description
DrupalBoot

File

lib/Drush/Boot/DrupalBoot.php
View source
  1. <?php
  2. namespace Drush\Boot;
  3. use Drush\Log\LogLevel;
  4. abstract class DrupalBoot extends BaseBoot {
  5. function __construct() {
  6. }
  7. function valid_root($path) {
  8. }
  9. function get_version($drupal_root) {
  10. }
  11. function get_profile() {
  12. }
  13. function conf_path($require_settings = TRUE, $reset = FALSE) {
  14. return conf_path($require_settings = TRUE, $reset = FALSE);
  15. }
  16. /**
  17. * Bootstrap phases used with Drupal:
  18. *
  19. * DRUSH_BOOTSTRAP_DRUSH = Only Drush.
  20. * DRUSH_BOOTSTRAP_DRUPAL_ROOT = Find a valid Drupal root.
  21. * DRUSH_BOOTSTRAP_DRUPAL_SITE = Find a valid Drupal site.
  22. * DRUSH_BOOTSTRAP_DRUPAL_CONFIGURATION = Load the site's settings.
  23. * DRUSH_BOOTSTRAP_DRUPAL_DATABASE = Initialize the database.
  24. * DRUSH_BOOTSTRAP_DRUPAL_FULL = Initialize Drupal fully.
  25. * DRUSH_BOOTSTRAP_DRUPAL_LOGIN = Log into Drupal with a valid user.
  26. *
  27. * The value is the name of the method of the Boot class to
  28. * execute when bootstrapping. Prior to bootstrapping, a "validate"
  29. * method is called, if defined. The validate method name is the
  30. * bootstrap method name with "_validate" appended.
  31. */
  32. function bootstrap_phases() {
  33. return array(
  34. DRUSH_BOOTSTRAP_DRUSH => 'bootstrap_drush',
  35. DRUSH_BOOTSTRAP_DRUPAL_ROOT => 'bootstrap_drupal_root',
  36. DRUSH_BOOTSTRAP_DRUPAL_SITE => 'bootstrap_drupal_site',
  37. DRUSH_BOOTSTRAP_DRUPAL_CONFIGURATION => 'bootstrap_drupal_configuration',
  38. DRUSH_BOOTSTRAP_DRUPAL_DATABASE => 'bootstrap_drupal_database',
  39. DRUSH_BOOTSTRAP_DRUPAL_FULL => 'bootstrap_drupal_full',
  40. DRUSH_BOOTSTRAP_DRUPAL_LOGIN => 'bootstrap_drupal_login');
  41. }
  42. /**
  43. * List of bootstrap phases where Drush should stop and look for commandfiles.
  44. *
  45. * For Drupal, we try at these bootstrap phases:
  46. *
  47. * - Drush preflight: to find commandfiles in any system location,
  48. * out of a Drupal installation.
  49. * - Drupal root: to find commandfiles based on Drupal core version.
  50. * - Drupal full: to find commandfiles defined within a Drupal directory.
  51. *
  52. * Once a command is found, Drush will ensure a bootstrap to the phase
  53. * declared by the command.
  54. *
  55. * @return array of PHASE indexes.
  56. */
  57. function bootstrap_init_phases() {
  58. return array(DRUSH_BOOTSTRAP_DRUSH, DRUSH_BOOTSTRAP_DRUPAL_ROOT, DRUSH_BOOTSTRAP_DRUPAL_FULL);
  59. }
  60. function enforce_requirement(&$command) {
  61. parent::enforce_requirement($command);
  62. $this->drush_enforce_requirement_drupal_dependencies($command);
  63. }
  64. function report_command_error($command) {
  65. // If we reach this point, command doesn't fit requirements or we have not
  66. // found either a valid or matching command.
  67. // If no command was found check if it belongs to a disabled module.
  68. if (!$command) {
  69. $command = $this->drush_command_belongs_to_disabled_module();
  70. }
  71. parent::report_command_error($command);
  72. }
  73. function command_defaults() {
  74. return array(
  75. 'drupal dependencies' => array(),
  76. 'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_LOGIN,
  77. );
  78. }
  79. /**
  80. * @return array of strings - paths to directories where contrib
  81. * modules can be found
  82. */
  83. abstract function contrib_modules_paths();
  84. /**
  85. * @return array of strings - paths to directories where contrib
  86. * themes can be found
  87. */
  88. abstract function contrib_themes_paths();
  89. function commandfile_searchpaths($phase, $phase_max = FALSE) {
  90. if (!$phase_max) {
  91. $phase_max = $phase;
  92. }
  93. $searchpath = array();
  94. switch ($phase) {
  95. case DRUSH_BOOTSTRAP_DRUPAL_ROOT:
  96. $drupal_root = drush_get_context('DRUSH_SELECTED_DRUPAL_ROOT');
  97. $searchpath[] = $drupal_root . '/../drush';
  98. $searchpath[] = $drupal_root . '/drush';
  99. $searchpath[] = $drupal_root . '/sites/all/drush';
  100. // Add the drupalboot.drush.inc commandfile.
  101. // $searchpath[] = __DIR__;
  102. break;
  103. case DRUSH_BOOTSTRAP_DRUPAL_SITE:
  104. // If we are going to stop bootstrapping at the site, then
  105. // we will quickly add all commandfiles that we can find for
  106. // any extension associated with the site, whether it is enabled
  107. // or not. If we are, however, going to continue on to bootstrap
  108. // all the way to DRUSH_BOOTSTRAP_DRUPAL_FULL, then we will
  109. // instead wait for that phase, which will more carefully add
  110. // only those Drush commandfiles that are associated with
  111. // enabled modules.
  112. if ($phase_max < DRUSH_BOOTSTRAP_DRUPAL_FULL) {
  113. $searchpath = array_merge($searchpath, $this->contrib_modules_paths());
  114. // Adding commandfiles located within /profiles. Try to limit to one profile for speed. Note
  115. // that Drupal allows enabling modules from a non-active profile so this logic is kinda dodgy.
  116. $cid = drush_cid_install_profile();
  117. if ($cached = drush_cache_get($cid)) {
  118. $profile = $cached->data;
  119. $searchpath[] = "profiles/$profile/modules";
  120. $searchpath[] = "profiles/$profile/themes";
  121. }
  122. else {
  123. // If install_profile is not available, scan all profiles.
  124. $searchpath[] = "profiles";
  125. $searchpath[] = "sites/all/profiles";
  126. }
  127. $searchpath = array_merge($searchpath, $this->contrib_themes_paths());
  128. }
  129. break;
  130. case DRUSH_BOOTSTRAP_DRUPAL_CONFIGURATION:
  131. // Nothing to do here anymore. Left for documentation.
  132. break;
  133. case DRUSH_BOOTSTRAP_DRUPAL_FULL:
  134. // Add enabled module paths, excluding the install profile. Since we are bootstrapped,
  135. // we can use the Drupal API.
  136. $ignored_modules = drush_get_option_list('ignored-modules', array());
  137. $cid = drush_cid_install_profile();
  138. if ($cached = drush_cache_get($cid)) {
  139. $ignored_modules[] = $cached->data;
  140. }
  141. foreach (array_diff(drush_module_list(), $ignored_modules) as $module) {
  142. $filepath = drupal_get_path('module', $module);
  143. if ($filepath && $filepath != '/') {
  144. $searchpath[] = $filepath;
  145. }
  146. }
  147. $searchpath[] = drupal_get_path('theme', drush_theme_get_admin());
  148. $searchpath[] = drupal_get_path('theme', drush_theme_get_default());
  149. break;
  150. }
  151. return $searchpath;
  152. }
  153. /**
  154. * Check if the given command belongs to a disabled module.
  155. *
  156. * @return array
  157. * Array with a command-like bootstrap error or FALSE if Drupal was not
  158. * bootstrapped fully or the command does not belong to a disabled module.
  159. */
  160. function drush_command_belongs_to_disabled_module() {
  161. if (drush_has_boostrapped(DRUSH_BOOTSTRAP_DRUPAL_FULL)) {
  162. _drush_find_commandfiles(DRUSH_BOOTSTRAP_DRUPAL_SITE, DRUSH_BOOTSTRAP_DRUPAL_CONFIGURATION);
  163. drush_get_commands(TRUE);
  164. $commands = drush_get_commands();
  165. $arguments = drush_get_arguments();
  166. $command_name = array_shift($arguments);
  167. if (isset($commands[$command_name])) {
  168. // We found it. Load its module name and set an error.
  169. if (is_array($commands[$command_name]['drupal dependencies']) && count($commands[$command_name]['drupal dependencies'])) {
  170. $modules = implode(', ', $commands[$command_name]['drupal dependencies']);
  171. }
  172. else {
  173. // The command does not define Drupal dependencies. Derive them.
  174. $command_files = commandfiles_cache()->get();
  175. $command_path = $commands[$command_name]['path'] . DIRECTORY_SEPARATOR . $commands[$command_name]['commandfile'] . '.drush.inc';
  176. $modules = array_search($command_path, $command_files);
  177. }
  178. return array(
  179. 'bootstrap_errors' => array(
  180. 'DRUSH_COMMAND_DEPENDENCY_ERROR' => dt('Command !command needs the following module(s) enabled to run: !dependencies.', array(
  181. '!command' => $command_name,
  182. '!dependencies' => $modules,
  183. )),
  184. ),
  185. );
  186. }
  187. }
  188. return FALSE;
  189. }
  190. /**
  191. * Check that a command has its declared dependencies available or have no
  192. * dependencies.
  193. *
  194. * @param $command
  195. * Command to check. Any errors will be added to the 'bootstrap_errors' element.
  196. *
  197. * @return
  198. * TRUE if command is valid.
  199. */
  200. function drush_enforce_requirement_drupal_dependencies(&$command) {
  201. // If the command bootstrap is DRUSH_BOOTSTRAP_MAX, then we will
  202. // allow the requirements to pass if we have not successfully
  203. // bootstrapped Drupal. The combination of DRUSH_BOOTSTRAP_MAX
  204. // and 'drupal dependencies' indicates that the drush command
  205. // will use the dependent modules only if they are available.
  206. if ($command['bootstrap'] == DRUSH_BOOTSTRAP_MAX) {
  207. // If we have not bootstrapped, then let the dependencies pass;
  208. // if we have bootstrapped, then enforce them.
  209. if (drush_get_context('DRUSH_BOOTSTRAP_PHASE') < DRUSH_BOOTSTRAP_DRUPAL_FULL) {
  210. return TRUE;
  211. }
  212. }
  213. // If there are no drupal dependencies, then do nothing
  214. if (!empty($command['drupal dependencies'])) {
  215. foreach ($command['drupal dependencies'] as $dependency) {
  216. drush_include_engine('drupal', 'environment');
  217. if(!drush_module_exists($dependency)) {
  218. $command['bootstrap_errors']['DRUSH_COMMAND_DEPENDENCY_ERROR'] = dt('Command !command needs the following modules installed/enabled to run: !dependencies.', array('!command' => $command['command'], '!dependencies' => implode(', ', $command['drupal dependencies'])));
  219. return FALSE;
  220. }
  221. }
  222. }
  223. return TRUE;
  224. }
  225. /**
  226. * Validate the DRUSH_BOOTSTRAP_DRUPAL_ROOT phase.
  227. *
  228. * In this function, we will check if a valid Drupal directory is available.
  229. * We also determine the value that will be stored in the DRUSH_DRUPAL_ROOT
  230. * context and DRUPAL_ROOT constant if it is considered a valid option.
  231. */
  232. function bootstrap_drupal_root_validate() {
  233. $drupal_root = drush_get_context('DRUSH_SELECTED_DRUPAL_ROOT');
  234. if (empty($drupal_root)) {
  235. return drush_bootstrap_error('DRUSH_NO_DRUPAL_ROOT', dt("A Drupal installation directory could not be found"));
  236. }
  237. if (!$signature = drush_valid_root($drupal_root)) {
  238. return drush_bootstrap_error('DRUSH_INVALID_DRUPAL_ROOT', dt("The directory !drupal_root does not contain a valid Drupal installation", array('!drupal_root' => $drupal_root)));
  239. }
  240. $version = drush_drupal_version($drupal_root);
  241. $major_version = drush_drupal_major_version($drupal_root);
  242. if ($major_version <= 5) {
  243. return drush_set_error('DRUSH_DRUPAL_VERSION_UNSUPPORTED', dt('Drush !drush_version does not support Drupal !major_version.', array('!drush_version' => DRUSH_VERSION, '!major_version' => $major_version)));
  244. }
  245. drush_bootstrap_value('drupal_root', realpath($drupal_root));
  246. define('DRUSH_DRUPAL_SIGNATURE', $signature);
  247. return TRUE;
  248. }
  249. /**
  250. * Bootstrap Drush with a valid Drupal Directory.
  251. *
  252. * In this function, the pwd will be moved to the root
  253. * of the Drupal installation.
  254. *
  255. * The DRUSH_DRUPAL_ROOT context, DRUSH_DRUPAL_CORE context, DRUPAL_ROOT, and the
  256. * DRUSH_DRUPAL_CORE constants are populated from the value that we determined during
  257. * the validation phase.
  258. *
  259. * We also now load the drushrc.php for this specific Drupal site.
  260. * We can now include files from the Drupal Tree, and figure
  261. * out more context about the platform, such as the version of Drupal.
  262. */
  263. function bootstrap_drupal_root() {
  264. // Load the config options from Drupal's /drush and sites/all/drush directories.
  265. drush_load_config('drupal');
  266. $drupal_root = drush_set_context('DRUSH_DRUPAL_ROOT', drush_bootstrap_value('drupal_root'));
  267. chdir($drupal_root);
  268. $version = drush_drupal_version();
  269. $major_version = drush_drupal_major_version();
  270. $core = $this->bootstrap_drupal_core($drupal_root);
  271. // DRUSH_DRUPAL_CORE should point to the /core folder in Drupal 8+ or to DRUPAL_ROOT
  272. // in prior versions.
  273. drush_set_context('DRUSH_DRUPAL_CORE', $core);
  274. define('DRUSH_DRUPAL_CORE', $core);
  275. _drush_preflight_global_options();
  276. drush_log(dt("Initialized Drupal !version root directory at !drupal_root", array("!version" => $version, '!drupal_root' => $drupal_root)), LogLevel::BOOTSTRAP);
  277. }
  278. /**
  279. * VALIDATE the DRUSH_BOOTSTRAP_DRUPAL_SITE phase.
  280. *
  281. * In this function we determine the URL used for the command,
  282. * and check for a valid settings.php file.
  283. *
  284. * To do this, we need to set up the $_SERVER environment variable,
  285. * to allow us to use conf_path to determine what Drupal will load
  286. * as a configuration file.
  287. */
  288. function bootstrap_drupal_site_validate() {
  289. // Define the selected conf path as soon as we have identified that
  290. // we have selected a Drupal site. Drush used to set this context
  291. // during the drush_bootstrap_drush phase.
  292. $drush_uri = _drush_bootstrap_selected_uri();
  293. drush_set_context('DRUSH_SELECTED_DRUPAL_SITE_CONF_PATH', drush_conf_path($drush_uri));
  294. $this->bootstrap_drupal_site_setup_server_global($drush_uri);
  295. return $this->bootstrap_drupal_site_validate_settings_present();
  296. }
  297. /**
  298. * Set up the $_SERVER globals so that Drupal will see the same values
  299. * that it does when serving pages via the web server.
  300. */
  301. function bootstrap_drupal_site_setup_server_global($drush_uri) {
  302. // Fake the necessary HTTP headers that Drupal needs:
  303. if ($drush_uri) {
  304. $drupal_base_url = parse_url($drush_uri);
  305. // If there's no url scheme set, add http:// and re-parse the url
  306. // so the host and path values are set accurately.
  307. if (!array_key_exists('scheme', $drupal_base_url)) {
  308. $drush_uri = 'http://' . $drush_uri;
  309. $drupal_base_url = parse_url($drush_uri);
  310. }
  311. // Fill in defaults.
  312. $drupal_base_url += array(
  313. 'path' => '',
  314. 'host' => NULL,
  315. 'port' => NULL,
  316. );
  317. $_SERVER['HTTP_HOST'] = $drupal_base_url['host'];
  318. if ($drupal_base_url['scheme'] == 'https') {
  319. $_SERVER['HTTPS'] = 'on';
  320. }
  321. if ($drupal_base_url['port']) {
  322. $_SERVER['HTTP_HOST'] .= ':' . $drupal_base_url['port'];
  323. }
  324. $_SERVER['SERVER_PORT'] = $drupal_base_url['port'];
  325. $_SERVER['REQUEST_URI'] = $drupal_base_url['path'] . '/';
  326. }
  327. else {
  328. $_SERVER['HTTP_HOST'] = 'default';
  329. $_SERVER['REQUEST_URI'] = '/';
  330. }
  331. $_SERVER['PHP_SELF'] = $_SERVER['REQUEST_URI'] . 'index.php';
  332. $_SERVER['SCRIPT_NAME'] = $_SERVER['PHP_SELF'];
  333. $_SERVER['REMOTE_ADDR'] = '127.0.0.1';
  334. $_SERVER['REQUEST_METHOD'] = NULL;
  335. $_SERVER['SERVER_SOFTWARE'] = NULL;
  336. $_SERVER['HTTP_USER_AGENT'] = NULL;
  337. $_SERVER['SCRIPT_FILENAME'] = DRUPAL_ROOT . '/index.php';
  338. }
  339. /**
  340. * Validate that the Drupal site has all of the settings that it
  341. * needs to operated.
  342. */
  343. function bootstrap_drupal_site_validate_settings_present() {
  344. $site = drush_bootstrap_value('site', $_SERVER['HTTP_HOST']);
  345. $conf_path = drush_bootstrap_value('conf_path', $this->conf_path(TRUE, TRUE));
  346. $conf_file = "$conf_path/settings.php";
  347. if (!file_exists($conf_file)) {
  348. return drush_bootstrap_error('DRUPAL_SITE_SETTINGS_NOT_FOUND', dt("Could not find a Drupal settings.php file at !file.",
  349. array('!file' => $conf_file)));
  350. }
  351. return TRUE;
  352. }
  353. /**
  354. * Called by bootstrap_drupal_site to do the main work
  355. * of the drush drupal site bootstrap.
  356. */
  357. function bootstrap_do_drupal_site() {
  358. $drush_uri = drush_get_context('DRUSH_SELECTED_URI');
  359. drush_set_context('DRUSH_URI', $drush_uri);
  360. $site = drush_set_context('DRUSH_DRUPAL_SITE', drush_bootstrap_value('site'));
  361. $conf_path = drush_set_context('DRUSH_DRUPAL_SITE_ROOT', drush_bootstrap_value('conf_path'));
  362. drush_log(dt("Initialized Drupal site !site at !site_root", array('!site' => $site, '!site_root' => $conf_path)), LogLevel::BOOTSTRAP);
  363. _drush_preflight_global_options();
  364. }
  365. /**
  366. * Initialize a site on the Drupal root.
  367. *
  368. * We now set various contexts that we determined and confirmed to be valid.
  369. * Additionally we load an optional drushrc.php file in the site directory.
  370. */
  371. function bootstrap_drupal_site() {
  372. drush_load_config('site');
  373. $this->bootstrap_do_drupal_site();
  374. }
  375. /**
  376. * Initialize and load the Drupal configuration files.
  377. *
  378. * We process and store a normalized set of database credentials
  379. * from the loaded configuration file, so we can validate them
  380. * and access them easily in the future.
  381. *
  382. * Also override Drupal variables as per --variables option.
  383. */
  384. function bootstrap_drupal_configuration() {
  385. global $conf;
  386. $override = array(
  387. 'dev_query' => FALSE, // Force Drupal6 not to store queries since we are not outputting them.
  388. 'cron_safe_threshold' => 0, // Don't run poormanscron during Drush request (D7+).
  389. );
  390. $current_override = drush_get_option_list('variables');
  391. foreach ($current_override as $name => $value) {
  392. if (is_numeric($name) && (strpos($value, '=') !== FALSE)) {
  393. list($name, $value) = explode('=', $value, 2);
  394. }
  395. $override[$name] = $value;
  396. }
  397. $conf = is_array($conf) ? array_merge($conf, $override) : $conf;
  398. }
  399. /**
  400. * Validate the DRUSH_BOOTSTRAP_DRUPAL_DATABASE phase
  401. *
  402. * Attempt to make a working database connection using the
  403. * database credentials that were loaded during the previous
  404. * phase.
  405. */
  406. function bootstrap_drupal_database_validate() {
  407. if (!drush_valid_db_credentials()) {
  408. return drush_bootstrap_error('DRUSH_DRUPAL_DB_ERROR');
  409. }
  410. return TRUE;
  411. }
  412. /**
  413. * Test to see if the Drupal database has a specified
  414. * table or tables.
  415. *
  416. * This is a bootstrap helper function designed to be called
  417. * from the bootstrap_drupal_database_validate() methods of
  418. * derived DrupalBoot classes. If a database exists, but is
  419. * empty, then the Drupal database bootstrap will fail. To
  420. * prevent this situation, we test for some table that is needed
  421. * in an ordinary bootstrap, and return FALSE from the validate
  422. * function if it does not exist, so that we do not attempt to
  423. * start the database bootstrap.
  424. *
  425. * Note that we must manually do our own prefix testing here,
  426. * because the existing wrappers we have for handling prefixes
  427. * depend on bootstrapping to the "database" phase, and therefore
  428. * are not available to validate this same phase.
  429. *
  430. * @param $required_tables
  431. * Array of table names, or string with one table name
  432. *
  433. * @return TRUE if all tables in input parameter exist in
  434. * the database.
  435. */
  436. function bootstrap_drupal_database_has_table($required_tables) {
  437. try {
  438. $sql = drush_sql_get_class();
  439. $spec = $sql->db_spec();
  440. $prefix = isset($spec['prefix']) ? $spec['prefix'] : NULL;
  441. if (!is_array($prefix)) {
  442. $prefix = array('default' => $prefix);
  443. }
  444. $tables = $sql->listTables();
  445. foreach ((array)$required_tables as $required_table) {
  446. $prefix_key = array_key_exists($required_table, $prefix) ? $required_table : 'default';
  447. if (!in_array($prefix[$prefix_key] . $required_table, $tables)) {
  448. return FALSE;
  449. }
  450. }
  451. }
  452. catch (Exception $e) {
  453. // Usually the checks above should return a result without
  454. // throwing an exception, but we'll catch any that are
  455. // thrown just in case.
  456. return FALSE;
  457. }
  458. return TRUE;
  459. }
  460. /**
  461. * Boostrap the Drupal database.
  462. */
  463. function bootstrap_drupal_database() {
  464. // We presume that our derived classes will connect and then
  465. // either fail, or call us via parent::
  466. drush_log(dt("Successfully connected to the Drupal database."), LogLevel::BOOTSTRAP);
  467. }
  468. /**
  469. * Attempt to load the full Drupal system.
  470. */
  471. function bootstrap_drupal_full() {
  472. drush_include_engine('drupal', 'environment');
  473. $this->add_logger();
  474. // Write correct install_profile to cache as needed. Used by _drush_find_commandfiles().
  475. $cid = drush_cid_install_profile();
  476. $install_profile = $this->get_profile();
  477. if ($cached_install_profile = drush_cache_get($cid)) {
  478. // We have a cached profile. Check it for correctness and save new value if needed.
  479. if ($cached_install_profile->data != $install_profile) {
  480. drush_cache_set($cid, $install_profile);
  481. }
  482. }
  483. else {
  484. // No cached entry so write to cache.
  485. drush_cache_set($cid, $install_profile);
  486. }
  487. _drush_log_drupal_messages();
  488. }
  489. /**
  490. * Log into the bootstrapped Drupal site with a specific
  491. * username or user id.
  492. */
  493. function bootstrap_drupal_login() {
  494. $uid_or_name = drush_set_context('DRUSH_USER', drush_get_option('user', 0));
  495. $userversion = drush_user_get_class();
  496. if (!$account = $userversion->load_by_uid($uid_or_name)) {
  497. if (!$account = $userversion->load_by_name($uid_or_name)) {
  498. if (is_numeric($uid_or_name)) {
  499. $message = dt('Could not login with user ID !user.', array('!user' => $uid_or_name));
  500. if ($uid_or_name === 0) {
  501. $message .= ' ' . dt('This is typically caused by importing a MySQL database dump from a faulty tool which re-numbered the anonymous user ID in the users table. See !link for help recovering from this situation.', array('!link' => 'http://drupal.org/node/1029506'));
  502. }
  503. }
  504. else {
  505. $message = dt('Could not login with user account `!user\'.', array('!user' => $uid_or_name));
  506. }
  507. return drush_set_error('DRUPAL_USER_LOGIN_FAILED', $message);
  508. }
  509. }
  510. $userversion->setCurrentUser($account);
  511. _drush_log_drupal_messages();
  512. }
  513. }