Newer
Older
* Core drush commands.
*/
/**
* Implementation of hook_drush_command().
*
* In this hook, you specify which commands your
* drush module makes available, what it does and
* Notice how this structure closely resembles how
* you define menu hooks.
*
* @return
* An associative array describing your command(s).
*/
Owen Barton
committed
function core_drush_command() {
Moshe Weitzman
committed
$items['help'] = array(
Moshe Weitzman
committed
'description' => 'Print this help message. See `drush help help` for more options.',
Moshe Weitzman
committed
'bootstrap' => DRUSH_BOOTSTRAP_DRUSH, // No bootstrap.
Moshe Weitzman
committed
'allow-additional-options' => TRUE,
Moshe Weitzman
committed
'options' => array(
Greg Anderson
committed
'sort' => 'Sort commands in alphabetical order. drush waits for full bootstrap before printing any commands when this option is used.',
Moshe Weitzman
committed
'filter' => array(
'description' => 'Restrict command list to those commands defined in the specified file. Omit value to choose from a list of names.',
'example-value' => 'category',
'value' => 'optional',
),
Moshe Weitzman
committed
'format' => 'Format to output . Allowed values are: json, export, html.',
'html' => 'Print help for all commands in HTML format. Deprecated - see --format option.',
Greg Anderson
committed
'pipe' => 'A list of available commands, one per line.',
Moshe Weitzman
committed
),
'arguments' => array(
'command' => 'A command name, or command alias.',
),
Moshe Weitzman
committed
'examples' => array(
Moshe Weitzman
committed
'drush' => 'List all commands.',
'drush --filter=devel_generate' => 'Show only commands defined in devel_generate.drush.inc',
Moshe Weitzman
committed
'drush help pm-download' => 'Show help for one command.',
'drush help dl' => 'Show help for one command using an alias.',
Moshe Weitzman
committed
),
'topics' => array('docs-readme'),
Moshe Weitzman
committed
);
$items['version'] = array(
'description' => 'Show drush version.',
'bootstrap' => DRUSH_BOOTSTRAP_DRUSH, // No bootstrap.
'options' => array(
'pipe' => 'Print just the version number, and nothing else.',
Moshe Weitzman
committed
'self-update' => 'Check for pending updates to Drush itself. Set to 0 to disable.',
greg.1.anderson
committed
'outputformat' => array(
'default' => 'key-value',
'pipe-format' => 'string',
'label' => 'Drush Version',
Greg Anderson
committed
'output-data-type' => 'format-single',
);
$items['self-update'] = array(
Moshe Weitzman
committed
'description' => 'Check to see if there is a newer Drush release available.',
'bootstrap' => DRUSH_BOOTSTRAP_DRUSH, // No bootstrap.
'aliases' => array('selfupdate'),
);
Greg Anderson
committed
$items['core-cron'] = array(
'description' => 'Run all cron hooks in all active modules for specified site.',
Greg Anderson
committed
'aliases' => array('cron'),
'description' => 'Apply any database updates required (as with running update.php).',
'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_SITE,
Moshe Weitzman
committed
'aliases' => array('updb'),
);
$items['core-config'] = array(
'description' => 'Edit drushrc, site alias, and Drupal settings.php files.',
'bootstrap' => DRUSH_BOOTSTRAP_MAX,
'arguments' => array(
'filter' => 'A substring for filtering the list of files. Omit this argument to choose from loaded files.',
),
Greg Anderson
committed
'options' => array(
'bg' => 'Run editor in the background. Does not work with editors such as `vi` that run in the terminal.',
),
'examples' => array(
'drush core-config' => 'Pick from a list of config/alias/settings files. Open selected in editor.',
Greg Anderson
committed
'drush --bg core-config' => 'Return to shell prompt as soon as the editor window opens.',
'drush core-config etc' => 'Edit the global configuration file.',
'drush core-config demo.alia' => 'Edit a particular alias file.',
'drush core-config sett' => 'Edit settings.php for the current Drupal site.',
'drush core-config --choice=2' => 'Edit the second file in the choice list.',
),
'aliases' => array('conf', 'config'),
);
Greg Anderson
committed
$items['core-status'] = array(
'description' => 'Provides a birds-eye view of the current Drupal installation, if any.',
'bootstrap' => DRUSH_BOOTSTRAP_MAX,
Greg Anderson
committed
'aliases' => array('status', 'st'),
Greg Anderson
committed
'examples' => array(
Moshe Weitzman
committed
'drush core-status version' => 'Show all status lines that contain version information.',
'drush core-status --pipe' => 'A list key=value items separated by line breaks.',
'drush core-status drush-version --pipe' => 'Emit just the drush version with no label.',
Moshe Weitzman
committed
'drush core-status config-active --pipe' => 'Emit just the active Config directory with no label.',
Greg Anderson
committed
),
'arguments' => array(
Greg Anderson
committed
'item' => 'Optional. The status item line(s) to display.',
Greg Anderson
committed
),
'options' => array(
'show-passwords' => 'Show database password.',
Greg Anderson
committed
'full' => 'Show all drush aliases in the report, even if there are a lot.',
Moshe Weitzman
committed
),
greg.1.anderson
committed
'outputformat' => array(
'default' => 'key-value',
'pipe-format' => 'ini',
Julien Dubreuil
committed
'field-labels' => array('drupal-version' => 'Drupal version', 'uri' => 'Site URI', 'db-driver' => 'Database driver', 'db-host' => 'Database hostname', 'db-username' => 'Database username', 'db-password' => 'Database password', 'db-name' => 'Database name', 'db-status' => 'Database', 'bootstrap' => 'Drupal bootstrap', 'user' => 'Drupal user', 'theme' => 'Default theme', 'admin-theme' => 'Administration theme', 'php-conf' => 'PHP configuration', 'drush-version' => 'Drush version', 'drush-conf' => 'Drush configuration', 'drush-alias-files' => 'Drush alias files', 'root' => 'Drupal root', 'site-path' => 'Site path', 'root' => 'Drupal root', 'site' => 'Site path', 'themes' => 'Themes path', 'modules' => 'Modules path', 'files' => 'File directory path', 'private' => 'Private file directory path', 'temp' => 'Temporary file directory path', 'config-active' => 'Active config directory path', 'config-staging' => 'Staging config directory path', 'files-path' => 'File directory path', 'temp-path' => 'Temporary file directory path', '%paths' => 'Other paths'),
greg.1.anderson
committed
'formatted-filter' => '_drush_core_status_format_table_data',
'private-fields' => 'db-password',
greg.1.anderson
committed
'simplify-single' => TRUE,
'table-metadata' => array(
'list-separator' => ' ',
Greg Anderson
committed
'output-data-type' => 'format-list',
'topics' => array('docs-readme'),
$path_names = array(
);
Greg Anderson
committed
$items['core-requirements'] = array(
'description' => 'Provides information about things that may be wrong in your Drupal installation, if any.',
'aliases' => array('status-report','rq'),
'examples' => array(
'drush core-requirements' => 'Show all status lines from the Status Report admin page.',
'drush core-requirements --severity=2' => 'Show only the red lines from the Status Report admin page.',
'drush core-requirements --pipe' => 'Print out a short report in the format "identifier=severity", where severity 2=error, 1=warning, and 0/-1=OK',
Greg Anderson
committed
),
'options' => array(
Moshe Weitzman
committed
'severity' => array(
'description' => 'Only show status report messages with a severity greater than or equal to the specified value.',
'value' => 'required',
'example-value' => '3',
),
'ignore' => 'Comma-separated list of requirements to remove from output. Run with --pipe to see key values to use.',
Greg Anderson
committed
),
greg.1.anderson
committed
'outputformat' => array(
'default' => 'table',
'pipe-format' => 'ini',
'field-labels' => array('title' => 'Title', 'severity' => 'Severity', 'sid' => 'SID', 'description' => 'Description', 'value' => 'Summary', 'reason' => 'Reason', 'weight' => 'Weight'),
'fields-default' => array('title', 'severity', 'description'),
'column-widths' => array('severity' => 8),
'concatenate-columns' => array('description' => array('value', 'description')),
'strip-tags' => TRUE,
'ini-item' => 'sid',
'key-value-item' => 'severity',
'list-metadata' => array(
'list-item' => 'severity',
Greg Anderson
committed
'output-data-type' => 'format-table',
Greg Anderson
committed
);
$items['php-eval'] = array(
'description' => 'Evaluate arbitrary php code after bootstrapping Drupal (if available).',
'examples' => array(
'drush php-eval "variable_set(\'hello\', \'world\');"' => 'Sets the hello variable using Drupal API.',
),
'arguments' => array(
'code' => 'PHP code',
),
'required-arguments' => TRUE,
'allow-additional-options' => TRUE,
'bootstrap' => DRUSH_BOOTSTRAP_MAX,
'aliases' => array('eval', 'ev'),
greg.1.anderson
committed
'outputformat' => array(
'default' => 'export',
$items['php-script'] = array(
'examples' => array(
Moshe Weitzman
committed
'drush php-script scratch' => 'Run scratch.php script. See commands/core directory.',
'drush php-script example --script-path=/path/to/scripts:/another/path' => 'Run script from specified paths',
'drush php-script' => 'List all available scripts.',
Greg Anderson
committed
'' => '',
"#!/usr/bin/env drush\n<?php\nvariable_set('key', drush_shift());" => "Execute php code with a full Drupal bootstrap directly from a shell script.",
),
'arguments' => array(
'filename' => 'Optional. The file you wish to execute (without extension). If omitted, list files ending in .php in the current working directory and specified script-path. Some might not be real drush scripts. Beware.',
),
Moshe Weitzman
committed
'options' => array(
Moshe Weitzman
committed
'script-path' => array(
'description' => "Additional paths to search for scripts, separated by : (Unix-based systems) or ; (Windows).",
'example-value' => '~/scripts',
),
'allow-additional-options' => TRUE,
'bootstrap' => DRUSH_BOOTSTRAP_MAX,
'aliases' => array('scr'),
'topics' => array('docs-examplescript', 'docs-scripts'),
Moshe Weitzman
committed
$items['core-execute'] = array(
'description' => 'Execute a shell command. Usually used with a site alias.',
'bootstrap' => DRUSH_BOOTSTRAP_DRUSH, // No bootstrap.
'arguments' => array(
Moshe Weitzman
committed
),
Moshe Weitzman
committed
'options' => drush_shell_exec_proc_build_options(),
'required-arguments' => TRUE,
'allow-additional-options' => TRUE,
'handle-remote-commands' => TRUE,
Greg Anderson
committed
'strict-option-handling' => TRUE,
Moshe Weitzman
committed
'examples' => array(
Moshe Weitzman
committed
'drush core-execute git pull origin rebase' => 'Retrieve latest code from git',
Moshe Weitzman
committed
),
'aliases' => array('exec', 'execute'),
'topics' => array('docs-aliases'),
);
Greg Anderson
committed
$items['core-rsync'] = array(
'description' => 'Rsync the Drupal tree to/from another server using ssh.',
'bootstrap' => DRUSH_BOOTSTRAP_DRUSH, // No bootstrap.
'arguments' => array(
'source' => 'May be rsync path or site alias. See rsync documentation and example.aliases.drushrc.php.',
'destination' => 'May be rsync path or site alias. See rsync documentation and example.aliases.drushrc.php.',
Moshe Weitzman
committed
),
'options' => array(
Moshe Weitzman
committed
'mode' => 'The unary flags to pass to rsync; --mode=rultz implies rsync -rultz. Default is -akz.',
Greg Anderson
committed
'exclude-conf' => 'Excludes settings.php from being rsynced. Default.',
Greg Anderson
committed
'include-conf' => 'Allow settings.php to be rsynced. Default is to exclude settings.php.',
'include-vcs' => 'Include special version control directories (e.g. .svn). Default is to exclude vcs files.',
Greg Anderson
committed
'exclude-files' => 'Exclude the files directory.',
'exclude-sites' => 'Exclude all directories in "sites/" except for "sites/all".',
'exclude-other-sites' => 'Exclude all directories in "sites/" except for "sites/all" and the site directory for the site being synced. Note: if the site directory is different between the source and destination, use --exclude-sites followed by "drush rsync @from:%site @to:%site"',
'exclude-paths' => 'List of paths to exclude, seperated by : (Unix-based systems) or ; (Windows).',
'include-paths' => 'List of paths to include, seperated by : (Unix-based systems) or ; (Windows).',
'{rsync-option-name}' => "Replace {rsync-option-name} with the rsync option (or option='value') that you would like to pass through to rsync. Examples include --delete, --exclude=*.sql, --filter='merge /etc/rsync/default.rules', etc. See the rsync documentation for a complete explaination of all the rsync options and values.",
Greg Anderson
committed
'strict-option-handling' => TRUE,
'examples' => array(
'drush rsync @dev @stage' => 'Rsync Drupal root from Drush alias dev to the alias stage (one of which must be local).',
'drush rsync ./ @stage:%files/img' => 'Rsync all files in the current directory to the \'img\' directory in the file storage folder on the Drush alias stage.',
'drush -s rsync @dev @stage --exclude=*.sql --delete' => "Simulate Rsync Drupal root from the Drush alias dev to the alias stage (one of which must be local), excluding all files that match the filter '*.sql' and delete all files on the destination that are no longer on the source.",
Greg Anderson
committed
'aliases' => array('rsync'),
'topics' => array('docs-aliases'),
Moshe Weitzman
committed
$items['site-install'] = array(
Moshe Weitzman
committed
'description' => 'Install Drupal along with modules/themes/configuration using the specified install profile.',
'arguments' => array(
Moshe Weitzman
committed
'profile' => 'the install profile you wish to run. defaults to \'default\' in D6, \'standard\' in D7+',
Moshe Weitzman
committed
'key=value...' => 'any additional settings you wish to pass to the profile. Fully supported on D7+, partially supported on D6 (single step configure forms only). The key is in the form [form name].[parameter name] on D7 or just [parameter name] on D6.',
),
'options' => array(
Moshe Weitzman
committed
'db-url' => array(
'description' => 'A Drupal 6 style database URL. Only required for initial install - not re-install.',
'example-value' => 'mysql://root:pass@127.0.0.1/db',
),
git
committed
'db-prefix' => 'An optional table prefix to use for initial install. Can be a key-value array of tables/prefixes in a drushrc file (not the command line).',
'db-su' => array(
'description' => 'Account to use when creating a new database. Must have Grant permission (mysql only). Optional.',
'example-value' => 'root',
),
'db-su-pw' => array(
'description' => 'Password for the "db-su" account. Optional.',
'example-value' => 'pass',
),
Moshe Weitzman
committed
'account-name' => 'uid1 name. Defaults to admin',
'account-pass' => 'uid1 pass. Defaults to a randomly generated password. If desired, set a fixed password in drushrc.php.',
'account-mail' => 'uid1 email. Defaults to admin@example.com',
Moshe Weitzman
committed
'locale' => array(
'description' => 'A short language code. Sets the default site language. Language files must already be present. You may use download command to get them.',
'example-value' => 'en-GB',
),
Moshe Weitzman
committed
'clean-url'=> 'Defaults to 1',
Moshe Weitzman
committed
'site-name' => 'Defaults to Site-Install',
Moshe Weitzman
committed
'site-mail' => 'From: for system mailings. Defaults to admin@example.com',
Moshe Weitzman
committed
'sites-subdir' => array(
'description' => "Name of directory under 'sites' which should be created. Only needed when the subdirectory does not already exist. Defaults to 'default'",
'value' => 'required',
'example-value' => 'directory_name',
),
),
Moshe Weitzman
committed
'examples' => array(
'drush site-install expert --locale=uk' => '(Re)install using the expert install profile. Set default language to Ukranian.',
'drush site-install --db-url=mysql://root:pass@localhost:port/dbname' => 'Install using the specified DB params.',
Moshe Weitzman
committed
'drush site-install --db-url=sqlite://sites/example.com/files/.ht.sqlite' => 'Install using SQLite (D7+ only).',
'drush site-install --account-name=joe --account-pass=mom' => 'Re-install with specified uid1 credentials.',
Moshe Weitzman
committed
'drush site-install standard install_configure_form.site_default_country=FR my_profile_form.my_settings.key=value' => 'Pass additional arguments to the profile (D7 example shown here - for D6, omit the form id).',
Moshe Weitzman
committed
"drush site-install install_configure_form.update_status_module='array(FALSE,FALSE)'" => 'Disable email notification during install and later. If your server has no smtp, this gets rid of an error during install.',
Moshe Weitzman
committed
),
'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_ROOT,
Moshe Weitzman
committed
'aliases' => array('si'),
);
Greg Anderson
committed
$items['drupal-directory'] = array(
Jonathan
committed
'description' => 'Return path to a given module/theme directory.',
Moshe Weitzman
committed
'arguments' => array(
Greg Anderson
committed
'target' => 'A module/theme name, or special names like root, files, private, or an alias : path alias string such as @alias:%files. Defaults to root.',
Moshe Weitzman
committed
),
'options' => array(
'component' => "The portion of the evaluated path to return. Defaults to 'path'; 'name' returns the site alias of the target.",
'local' => "Reject any target that specifies a remote site.",
),
Moshe Weitzman
committed
'examples' => array(
Greg Anderson
committed
'cd `drush dd devel`' => 'Navigate into the devel module directory',
'cd `drush dd` ' => 'Navigate to the root of your Drupal site',
'cd `drush dd files`' => 'Navigate to the files directory.',
'drush dd @alias:%files' => 'Print the path to the files directory on the site @alias.',
'edit `drush dd devel`/devel.module' => "Open devel module in your editor (customize 'edit' for your editor)",
Moshe Weitzman
committed
),
Greg Anderson
committed
'aliases' => array('dd'),
'bootstrap' => DRUSH_BOOTSTRAP_DRUSH,
Moshe Weitzman
committed
);
$items['batch-process'] = array(
Jonathan
committed
'description' => 'Process operations in the specified batch set',
'hidden' => TRUE,
Owen Barton
committed
'arguments' => array(
'batch-id' => 'The batch id that will be processed.',
Owen Barton
committed
),
'required-arguments' => TRUE,
'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_LOGIN,
);
$items['updatedb-batch-process'] = array(
Jonathan
committed
'description' => 'Perform update functions',
'hidden' => TRUE,
'arguments' => array(
'batch-id' => 'The batch id that will be processed',
),
'required-arguments' => TRUE,
'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_SITE,
);
Moshe Weitzman
committed
$items['core-global-options'] = array(
Jonathan
committed
'description' => 'All global options',
Moshe Weitzman
committed
'hidden' => TRUE,
'topic' => TRUE,
'bootstrap' => DRUSH_BOOTSTRAP_DRUSH,
);
Owen Barton
committed
$items['core-quick-drupal'] = array(
'description' => 'Download, install, serve and login to Drupal with minimal configuration and dependencies.',
'bootstrap' => DRUSH_BOOTSTRAP_DRUSH,
'aliases' => array('qd'),
'arguments' => array(
'site' => 'Short name for the site to be created - used as a directory name and as sqlite file name. Optional - if omitted timestamped "quick-drupal" directory will be used instead.',
'projects' => 'A list of projects to download into the new site. If projects contain extensions (modules or themes) with the same name they will be enabled by default. See --enable option to control this behaviour further.',
),
'examples' => array(
'drush qd' => 'Download and install stable release of Drupal into a timestamped directory, start server, and open the site logged in as admin.',
Moshe Weitzman
committed
'drush qd --profile=minimal --dev --cache --core=drupal-8.x --yes' => 'Fire up dev release of Drupal site with minimal install profile.',
Owen Barton
committed
'drush qd testsite devel --server=:8081/admin --browser=firefox --cache --yes' => 'Fire up stable release (using the cache) of Drupal site called "testsite", download and enable devel module, start a server on port 8081 and open /admin in firefox.',
'drush qd commercesite --core=commerce_kickstart --profile=commerce_kickstart --cache --yes --watchdog' => 'Download and install the "Commerce Kickstart" distribution/install profile, display watchdog messages on the server console.',
Greg Anderson
committed
'drush qd --makefile=mysite.make' => 'Create and install a site from a makefile.',
Owen Barton
committed
),
);
// Add in options/engines.
drush_core_quick_drupal_options($items);
// Add in topics for engines
$items += drush_get_engine_topics();
/**
* Command argument complete callback.
*
* @return
* Array of available command names.
*/
function core_help_complete() {
return array('values' => array_keys(drush_get_commands()));
}
/**
* Command argument complete callback.
*
* @return
* Array of available profile names.
*/
function core_site_install_complete() {
$max = drush_bootstrap_max(DRUSH_BOOTSTRAP_DRUPAL_ROOT);
if ($max >= DRUSH_BOOTSTRAP_DRUPAL_ROOT) {
return array('values' => array_keys(drush_find_profiles(DRUPAL_ROOT)));
}
}
/**
* Command argument complete callback.
*
* @return
* Array of available site aliases.
*/
function core_core_rsync_complete() {
return array('values' => array_keys(_drush_sitealias_all_list()));
}
/**
* @defgroup engines Engine types
* @{
*/
/**
* Implementation of hook_drush_engine_type_info().
*/
function core_drush_engine_type_info() {
$info = array();
$info['drupal'] = array();
return $info;
/**
* Implements hook_drush_engine_ENGINE_TYPE().
*/
function core_drush_engine_drupal() {
$engines = array();
$engines['batch'] = array();
$engines['update'] = array();
Moshe Weitzman
committed
$engines['environment'] = array();
$engines['site_install'] = array();
return $engines;
}
/**
* Command handler. Execute update.php code from drush.
*/
function drush_core_updatedb() {
if (drush_get_context('DRUSH_SIMULATE')) {
drush_log(dt('updatedb command does not support --simulate option.'), 'ok');
return TRUE;
drush_include_engine('drupal', 'update', drush_drupal_major_version());
Greg Anderson
committed
if (update_main() === FALSE) {
return FALSE;
}
Moshe Weitzman
committed
if (drush_drupal_major_version() <= 6) {
Jonathan Hedstrom
committed
// Clear all caches in a new process. We just performed major surgery.
drush_invoke_process('@self', 'cache-clear', array('all'));
Moshe Weitzman
committed
}
else {
// Should be unnecessary on D7.
// On D7 site-upgrade, this cache_clear was leading to:
// Call to undefined function field_read_fields() in field_sql_storage.install line 17
}
drush_log(dt('Finished performing updates.'), 'ok');
}
/**
* Implementation of hook_drush_help().
*
* This function is called whenever a drush user calls
* 'drush help <name-of-your-command>'
*
* @param
* A string with the help section (prepend with 'drush:')
*
* @return
* A string with the help text for your command.
*/
Owen Barton
committed
function core_drush_help($section) {
case 'meta:core:title':
return dt("Core drush commands");
Greg Anderson
committed
case 'drush:help':
return dt("Drush provides an extensive help system that describes both drush commands and topics of general interest. Use `drush help --filter` to present a list of command categories to view, and `drush topic` for a list of topics that go more in-depth on how to use and extend drush.");
case 'drush:php-script':
Greg Anderson
committed
return dt("Runs the given php script(s) after a full Drupal bootstrap. A useful alternative to eval command when your php is lengthy or you can't be bothered to figure out bash quoting. If you plan to share a script with others, consider making a full drush command instead, since that's more self-documenting. Drush provides commandline options to the script via drush_get_option('option-name'), and commandline arguments can be accessed either via drush_get_arguments(), which returns all arguments in an array, or drush_shift(), which removes the next argument from the list and returns it.");
Moshe Weitzman
committed
case 'drush:rsync':
return dt("Sync the entire drupal directory or a subdirectory to a <destination> using ssh. Excludes reserved files and directories for supported VCSs. Useful for pushing copies of your tree to a staging server, or retrieving a files directory from a remote site. Relative paths start from the Drupal root directory if a site alias is used; otherwise they start from the current working directory.");
Greg Anderson
committed
case 'drush:drupal-directory':
Moshe Weitzman
committed
return dt("Return the filesystem path for modules/themes and other key folders.");
case 'error:DRUSH_DRUPAL_DB_ERROR':
$message = dt("Drush was not able to start (bootstrap) the Drupal database.\n");
Jonathan
committed
$message .= dt("Hint: This may occur when Drush is trying to:\n");
$message .= dt(" * bootstrap a site that has not been installed or does not have a configured database. In this case you can select another site with a working database setup by specifying the URI to use with the --uri parameter on the command line. See `drush topic docs-aliases` for details.\n");
$message .= dt(" * connect the database through a socket. The socket file may be wrong or the php-cli may have no access to it in a jailed shell. See http://drupal.org/node/1428638 for details.\n");
$message .= dt("\nDrush was attempting to connect to: \n!credentials\n", array('!credentials' => _core_site_credentials(12)));
case 'error:DRUSH_DRUPAL_BOOTSTRAP_ERROR':
$message = dt("Drush was not able to start (bootstrap) Drupal.\n");
$message .= dt("Hint: This error can only occur once the database connection has already been successfully initiated, therefore this error generally points to a site configuration issue, and not a problem connecting to the database.\n");
$message .= dt("\nDrush was attempting to connect to: \n!credentials\n", array('!credentials' => _core_site_credentials(12)));
break;
// TODO: consolidate with SQL commands?
function _core_site_credentials($right_margin = 0) {
// Leave some space on the right so that we can put the result into the
// drush_log, which will again wordwrap the result.
$original_columns = drush_get_context('DRUSH_COLUMNS', 80);
drush_set_context('DRUSH_COLUMNS', $original_columns - $right_margin);
Greg Anderson
committed
$status_table = _core_site_status_table();
$metadata = drush_get_command_format_metadata('core-status');
$output = drush_format($status_table, $metadata, 'key-value');
drush_set_context('DRUSH_COLUMNS', $original_columns);
return $output;
Greg Anderson
committed
}
function _core_site_credential_table($status_table) {
$credentials = '';
foreach ($status_table as $key => $value) {
Greg Anderson
committed
$credentials .= sprintf(" %-18s: %s\n", $key, $value);
Greg Anderson
committed
}
return $credentials;
}
Greg Anderson
committed
function _core_path_aliases($project = '') {
$paths = array();
if ($drupal_root = drush_get_context('DRUSH_DRUPAL_ROOT')) {
$paths['%root'] = $drupal_root;
if ($site_root = drush_get_context('DRUSH_DRUPAL_SITE_ROOT')) {
$paths['%site'] = $site_root;
if (is_dir($modules_path = conf_path() . '/modules')) {
$paths['%modules'] = $modules_path;
}
else {
$paths['%modules'] = 'sites/all/modules';
}
if (is_dir($themes_path = conf_path() . '/themes')) {
$paths['%themes'] = $themes_path;
}
else {
$paths['%themes'] = 'sites/all/themes';
Moshe Weitzman
committed
if (drush_drupal_major_version() >= 8 && drush_get_context('DRUSH_BOOTSTRAP_PHASE') >= DRUSH_BOOTSTRAP_DRUPAL_CONFIGURATION) {
Moshe Weitzman
committed
$paths['%config-active'] = config_get_config_directory(CONFIG_ACTIVE_DIRECTORY);
$paths['%config-staging'] = config_get_config_directory(CONFIG_STAGING_DIRECTORY);
}
Greg Anderson
committed
if (drush_drupal_major_version() >= 7) {
if (drush_get_context('DRUSH_BOOTSTRAP_PHASE') >= DRUSH_BOOTSTRAP_DRUPAL_SITE) {
$paths['%files'] = variable_get('file_public_path', conf_path() . '/files');
Jonathan
committed
$private_path = variable_get('file_private_path', FALSE);
Kate Marshalkina
committed
if (!empty($private_path)) {
Jonathan
committed
$paths['%private'] = $private_path;
}
Moshe Weitzman
committed
Jonathan
committed
}
Greg Anderson
committed
}
elseif (function_exists('file_directory_path')) {
$paths['%files'] = file_directory_path();
}
if (function_exists('file_directory_temp')) {
$paths['%temp'] = file_directory_temp();
}
Greg Anderson
committed
// If the 'project' parameter was specified, then search
// for a project (or a few) and add its path to the path list
if (!empty($project)) {
Greg Anderson
committed
drush_include_engine('drupal', 'environment');
$modules = drush_get_modules();
Greg Anderson
committed
foreach(explode(',', $project) as $target) {
Greg Anderson
committed
if (array_key_exists($target, $modules)) {
$paths['%' . $target] = DRUPAL_ROOT . '/' . dirname($modules[$target]->filename);
Greg Anderson
committed
}
}
}
}
}
// Add in all of the global paths from $options['path-aliases']
$paths = array_merge($paths, drush_get_option('path-aliases', array()));
Greg Anderson
committed
return $paths;
}
function _core_site_status_table($project = '') {
Greg Anderson
committed
$phase = drush_get_context('DRUSH_BOOTSTRAP_PHASE');
Moshe Weitzman
committed
if ($drupal_root = drush_get_context('DRUSH_DRUPAL_ROOT')) {
$status_table['drupal-version'] = drush_drupal_version();
Moshe Weitzman
committed
if ($site_root = drush_get_context('DRUSH_DRUPAL_SITE_ROOT')) {
$status_table['uri'] = drush_get_context('DRUSH_URI');
Moshe Weitzman
committed
if ($creds = drush_get_context('DRUSH_DB_CREDENTIALS')) {
$status_table['db-driver'] = $creds['driver'];
if (!empty($creds['unix_socket'])) {
$status_table['db-socket'] = $creds['unix_socket'];
}
else {
$status_table['db-hostname'] = $creds['host'];
}
$status_table['db-username'] = $creds['user'];
$status_table['db-name'] = $creds['name'];
$status_table['db-password'] = $creds['pass'];
if ($phase > DRUSH_BOOTSTRAP_DRUPAL_DATABASE) {
$status_table['db-status'] = dt('Connected');
if ($phase > DRUSH_BOOTSTRAP_DRUPAL_FULL) {
$status_table['bootstrap'] = dt('Successful');
if ($phase == DRUSH_BOOTSTRAP_DRUPAL_LOGIN) {
global $user;
$username = ($user->uid) ? $user->name : dt('Anonymous');
$status_table['user'] = $username;
}
}
}
Moshe Weitzman
committed
}
}
$status_table['theme'] = drush_theme_get_default();
$status_table['admin-theme'] = drush_theme_get_admin();
Moshe Weitzman
committed
if ($php_ini_files = _drush_core_config_php_ini_files()) {
$status_table['php-conf'] = $php_ini_files;
Greg Anderson
committed
}
$status_table['drush-version'] = DRUSH_VERSION;
$status_table['drush-conf'] = drush_flatten_array(drush_get_context_options('context-path', ''));
Greg Anderson
committed
$alias_files = _drush_sitealias_find_alias_files();
$status_table['drush-alias-files'] = $alias_files;
Greg Anderson
committed
$paths = _core_path_aliases($project);
if (!empty($paths)) {
foreach ($paths as $target => $one_path) {
$name = $target;
if (substr($name,0,1) == '%') {
$name = substr($name,1);
}
$status_table[$name] = $one_path;
}
}
Greg Anderson
committed
// Store the paths into the '%paths' index; this will be
// used by other code, but will not be included in the output
// of the drush status command.
$status_table['%paths'] = $paths;
Greg Anderson
committed
return $status_table;
// Adjust the status output for any non-pipe output format
function _drush_core_status_format_table_data($output, $metadata) {
// Hide any key that begins with a %
foreach ($output as $key => $value) {
if ($key[0] == '%') {
unset($output[$key]);
}
}
// Hide 'Modules path' and 'Themes path' as well, because that's
// the way it's always been.
unset($output['modules']);
unset($output['themes']);
// Shorten the list of alias files if there are too many
if (drush_get_option('full', FALSE) == FALSE) {
if (isset($output['drush-alias-files']) && count($output['drush-alias-files']) > 24) {
$msg = dt("\nThere are !count more alias files. Run with --full to see the full list.", array('!count' => count($output['drush-alias-files']) - 1));
$output['drush-alias-files'] = array($output['drush-alias-files'][0] , $msg);
}
}
return $output;
}
/**
* Command callback. Runs cron hooks.
*
* This is where the action takes place.
*
* In this function, all of Drupals API is (usually) available, including
* any functions you have added in your own modules/themes.
*
* To print something to the terminal window, use drush_print().
*
*/
function drush_core_cron() {
if (drupal_cron_run()) {
drush_log(dt('Cron run successful.'), 'success');
}
else {
return drush_set_error('DRUSH_CRON_FAILED', dt('Cron run failed.'));
/**
* Command callback. Edit drushrc and alias files.
*/
function drush_core_config($filter = NULL) {
$all = drush_core_config_load();
// Apply any filter that was supplied.
if ($filter) {
foreach ($all as $key => $file) {
if (strpos($file, $filter) === FALSE) {
unset($all[$key]);
}
}
}
$all = drush_map_assoc(array_values($all));
Moshe Weitzman
committed
$exec = drush_get_editor();
if (count($all) == 1) {
Moshe Weitzman
committed
$filepath = current($all);
return drush_shell_exec_interactive($exec, $filepath, $filepath);
}
else {
$choice = drush_choice($all, 'Enter a number to choose which file to edit.', '!key');
if ($choice !== FALSE) {
Moshe Weitzman
committed
$filepath = $all[$choice];
drush_shell_exec_interactive($exec, $filepath, $filepath);
}
}
}
/**
* Command argument complete callback.
*
* @return
* Array of available configuration files for editing.
*/
function core_core_config_complete() {
return array('values' => drush_core_config_load(FALSE));
}
function drush_core_config_load($headers = TRUE) {
Moshe Weitzman
committed
$php_header = $php = $rcs_header = $rcs = $aliases_header = $aliases = $drupal_header = $drupal = array();
$php = _drush_core_config_php_ini_files();
if (!empty($php)) {
if ($headers) {
$php_header = array('phpini' => '-- PHP ini files --');
}
}
drush_sitealias_load_all();
if ($rcs = drush_get_context_options('context-path', TRUE)) {
if ($headers) {
$rcs_header = array('drushrc' => '-- Drushrc --');
}
}
if ($aliases = drush_get_context('drush-alias-files')) {
if ($headers) {
$aliases_header = array('aliases' => '-- Aliases --');
}
}
if ($site_root = drush_get_context('DRUSH_DRUPAL_SITE_ROOT')) {
$drupal = array_merge(array(realpath($site_root . '/settings.php'), realpath(DRUPAL_ROOT . '/.htaccess')));
if ($headers) {
$drupal_header = array('drupal' => '-- Drupal --');
}
}
Moshe Weitzman
committed
return array_merge($php_header, $php, $rcs_header, $rcs, $aliases_header, $aliases, $drupal_header, $drupal);
}
function _drush_core_config_php_ini_files() {
$ini_files = array();
Greg Anderson
committed
$ini_files[] = php_ini_loaded_file();
Moshe Weitzman
committed
foreach (array(DRUSH_BASE_PATH, '/etc/drush', drush_server_home() . '/.drush') as $ini_dir) {
if (file_exists($ini_dir . "/php.ini")) {
$ini_files[] = realpath($ini_dir . "/php.ini");
}
if (file_exists($ini_dir . "/drush.ini")) {
$ini_files[] = realpath($ini_dir . "/drush.ini");
}
}
return $ini_files;
}
Greg Anderson
committed
/**
* Command callback. Provides information from the 'Status Reports' admin page.
*/
function drush_core_requirements() {
include_once DRUSH_DRUPAL_CORE . '/includes/install.inc';
$severities = array(
REQUIREMENT_INFO => t('Info'),
REQUIREMENT_OK => t('OK'),
REQUIREMENT_WARNING => t('Warning'),
REQUIREMENT_ERROR => t('Error'),
Greg Anderson
committed
drupal_load_updates();
$requirements = module_invoke_all('requirements', 'runtime');
// If a module uses "$requirements[] = " instead of
// "$requirements['label'] = ", then build a label from
// the title.
foreach($requirements as $key => $info) {
if (is_numeric($key)) {
unset($requirements[$key]);
$new_key = strtolower(str_replace(' ', '_', $info['title']));
$requirements[$new_key] = $info;
}
}
$ignore_requirements = drush_get_option_list('ignore');
foreach ($ignore_requirements as $ignore) {
unset($requirements[$ignore]);
}
ksort($requirements);
Greg Anderson
committed
$min_severity = drush_get_option('severity', -1);
Greg Anderson
committed
foreach($requirements as $key => $info) {
$severity = array_key_exists('severity', $info) ? $info['severity'] : -1;
$requirements[$key]['sid'] = $severity;
$requirements[$key]['severity'] = $severities[$severity];
if ($severity < $min_severity) {
unset($requirements[$key]);
Greg Anderson
committed
}
}
return $requirements;
}
/**
* Command callback. Provides a birds-eye view of the current Drupal
* installation.
*/
function drush_core_status() {
$status_table = _core_site_status_table(drush_get_option('project',''));
Greg Anderson
committed
// If args are specified, filter out any entry that is not named
// (in other words, only show lines named by one of the arg values)
$args = func_get_args();
if (!empty($args)) {
$field_list = $args;
$metadata = drush_get_command_format_metadata('core-status');
foreach ($metadata['field-labels'] as $field_key => $field_label) {
if (_drush_core_is_named_in_array($field_label, $args)) {
$field_list[] = $field_key;
}
}
Greg Anderson
committed
foreach ($status_table as $key => $value) {
if (!_drush_core_is_named_in_array($key, $field_list)) {
Greg Anderson
committed
unset($status_table[$key]);
}
}
}
return $status_table;
// Command callback. Show all global options. Exposed via topic command.
Moshe Weitzman
committed
function drush_core_global_options() {
drush_print(dt('These options are applicable to most drush commands.'));
drush_print();
Greg Anderson
committed
$fake = drush_global_options_command(FALSE);
$global_option_rows = drush_format_help_section($fake, 'options');
drush_print_table($global_option_rows);
drush_print();
drush_print("See also: `drush topic docs-strict-options`");
Moshe Weitzman
committed
}
Greg Anderson
committed
function _drush_core_is_named_in_array($key, $the_array) {
$is_named = FALSE;
Greg Anderson
committed
$simplified_key = str_replace(array(' ', '_', '-'), array('', '', ''), $key);
Greg Anderson
committed
foreach ($the_array as $name) {
if (stristr($simplified_key, str_replace(array(' ', '_', '-'), array('', '', ''), $name))) {
$is_named = TRUE;
}
}
Greg Anderson
committed
return $is_named;
}
Owen Barton
committed
/**
* Callback for core-quick-drupal command.
*/
function drush_core_quick_drupal() {
$requests = FALSE;
Greg Anderson
committed
$make_projects = array();
Owen Barton
committed
$args = func_get_args();
Greg Anderson
committed
$name = drush_get_option('use-name');
drush_set_option('backend', TRUE);
Greg Anderson
committed
$makefile = drush_get_option('makefile');
Greg Anderson
committed
if (drush_get_option('use-existing', FALSE)) {
$root = drush_get_option('root', FALSE);
if (!$root) {
return drush_set_error('QUICK_DRUPAL_NO_ROOT_SPECIFIED', 'Must specify site with --root when using --use-existing.');
}
if (empty($name)) {
$name = basename($root);
}
$base = dirname($root);
Owen Barton
committed
}
else {
Greg Anderson
committed
if (!empty($args) && empty($name)) {
$name = array_shift($args);
Owen Barton
committed
}
Greg Anderson
committed
if (empty($name)) {
$name = 'quick-drupal-' . gmdate('YmdHis', $_SERVER['REQUEST_TIME']);
}
Greg Anderson
committed
$root = drush_get_option('root', FALSE);
Greg Anderson
committed
$core = drush_get_option('core', 'drupal');
Greg Anderson
committed
$project_rename = $core;
if ($root) {
$base = dirname($root);
$project_rename = basename($root);
}
else {
$base = getcwd() . '/' . $name;
$root = $base . '/' . $core;
}
if (!empty($makefile)) {
// Invoke 'drush make $makefile'.
$result = drush_invoke_process('@none', 'make', array($makefile, $root));
if ($result['error_status'] != 0) {
return drush_set_error('DRUSH_QD_MAKE', 'Could not make; aborting.');
}
$make_projects = array_diff(array_keys($result['object']['projects']), array('drupal'));
}
else {
drush_mkdir($base);
drush_set_option('destination', $base);
drush_set_option('drupal-project-rename', $project_rename);
if (drush_invoke('pm-download', array($core)) === FALSE) {
return drush_set_error('QUICK_DRUPAL_CORE_DOWNLOAD_FAIL', 'Drupal core download/extract failed.');
}
Greg Anderson
committed
}
Owen Barton
committed
}
if (!drush_get_option('db-url', FALSE)) {
drush_set_option('db-url', 'sqlite:' . $base . '/' . $name . '.sqlite');
}
Greg Anderson
committed
drush_set_option('root', $root);
Owen Barton
committed
if (!drush_bootstrap_to_phase(DRUSH_BOOTSTRAP_DRUPAL_ROOT)) {
return drush_set_error('QUICK_DRUPAL_ROOT_LOCATE_FAIL', 'Unable to locate Drupal root directory.');
}
Greg Anderson
committed
if (!empty($args)) {
$requests = pm_parse_arguments($args, FALSE);
}
Owen Barton
committed
if ($requests) {
// Unset --destination, so that downloads go to the site directories.
drush_unset_option('destination');
if (drush_invoke('pm-download', $requests) === FALSE) {
return drush_set_error('QUICK_DRUPAL_PROJECT_DOWNLOAD_FAIL', 'Project download/extract failed.');
}
}
drush_invoke('site-install', array(drush_get_option('profile')));
// Log in with the admin user.
Greg Anderson
committed
// TODO: If site-install is given a sites-subdir other than 'default',
// then it will bootstrap to DRUSH_BOOTSTRAP_DRUPAL_SITE get the installer
Greg Anderson
committed
// to recognize the desired site directory. This somehow interferes
// with our desire to bootstrap to DRUSH_BOOTSTRAP_DRUPAL_LOGIN here.
// We could do the last few steps in a new process iff uri is not 'default'.
Owen Barton
committed
drush_set_option('user', '1');
if (!drush_bootstrap_to_phase(DRUSH_BOOTSTRAP_DRUPAL_LOGIN)) {
return drush_set_error('QUICK_DRUPAL_INSTALL_FAIL', 'Drupal core install failed.');
}
Greg Anderson
committed
$enable = array_merge(pm_parse_arguments(drush_get_option('enable', $requests)), $make_projects);
Owen Barton
committed
if (!empty($enable)) {
if (drush_invoke('pm-enable', $enable) === FALSE) {
return drush_set_error('QUICK_DRUPAL_PROJECT_ENABLE_FAIL', 'Project enable failed.');
}
}
drush_print(dt('Login URL: ') . drush_invoke('user-login'));
Greg Anderson
committed
if (!drush_get_option('no-server', FALSE)) {
if ($server = drush_get_option('server', '/')) {
drush_invoke('runserver', array($server));
}
Owen Barton
committed
}
}
/**
* Include options and engines for core-quick-drupal command, aggregated from
* other command options that are available. We prefix option descriptons,
* to make the long list more navigable.
*
* @param $items
* The core commandfile command array, by reference. Used to include
* site-install options and add options and engines for core-quick-drupal.
*/
function drush_core_quick_drupal_options(&$items) {
$options = array(
'core' => 'Drupal core to download. Defaults to "drupal" (latest stable version).',
Greg Anderson
committed
'use-existing' => 'Use an existing Drupal root, specified with --root. Overrides --core.',
Owen Barton
committed
'profile' => 'The install profile to use. Defaults to standard.',
'enable' => 'Specific extensions (modules or themes) to enable. By default, extensions with the same name as requested projects will be enabled automatically.',
'server' => 'Host IP address and port number to bind to and path to open in web browser (hyphen to clear a default path), all elements optional. See runserver examples for shorthand.',
'no-server' => 'Avoid starting runserver (and browser) for the created Drupal site.',
'browser' => 'Optional name of a browser to open site in. If omitted the OS default browser will be used. Set --no-browser to disable.',
Greg Anderson
committed
'use-name' => array('hidden' => TRUE, 'description' => 'Overrides "name" argument.'),
Greg Anderson
committed
'makefile' => array('description' => 'Makefile to use. Makefile must specify which version of Drupal core to build.', 'example-value' => 'mysite.make', 'value' => 'optional'),
'root' => array('description' => 'Path to Drupal root.', 'example-value' => '/path/to/root', 'value' => 'optional'),
Owen Barton
committed
);
$pm = pm_drush_command();
foreach ($pm['pm-download']['options'] as $option => $description) {
if (is_array($description)) {
$description = $description['description'];
}
Owen Barton
committed
$options[$option] = 'Download option: ' . $description;
}
// Unset a few options that are not usable here, as we control them ourselves
// or they are otherwise implied by the environment.
unset($options['destination']);
unset($options['drupal-project-rename']);
unset($options['default-major']);
unset($options['use-site-dir']);
foreach ($items['site-install']['options'] as $option => $description) {
if (is_array($description)) {
$description = $description['description'];
}
Owen Barton
committed
$options[$option] = 'Site install option: ' . $description;
}
unset($options['sites-subdir']);
$runserver = runserver_drush_command();
foreach ($runserver['runserver']['options'] as $option => $description) {
$options[$option] = 'Runserver option: ' . $description;
}
unset($options['user']);
$items['core-quick-drupal']['options'] = $options;
$items['core-quick-drupal']['engines'] = $pm['pm-download']['engines'];
}
Greg Anderson
committed
/**
* Command callback. Runs "naked" php scripts