From 564c9f0f80fd4a18e7589b9ed0501302a452a083 Mon Sep 17 00:00:00 2001 From: Moshe Weitzman Date: Mon, 20 Feb 2017 12:14:36 -0500 Subject: [PATCH] Update /examples for Drush 9 (#2629) --- docs/commands.md | 8 +- docs/examples.md | 12 +- examples/Commands/PolicyCommands.php | 52 +++ examples/Commands/SandwichCommands.php | 120 +++++++ examples/Commands/SyncViaHttpCommands.php | 92 ++++++ examples/Commands/XkcdCommands.php | 53 +++ examples/{ => Commands}/sandwich-nocolor.txt | 0 .../sandwich-topic.md} | 0 examples/{ => Commands}/sandwich.txt | 0 examples/example.aliases.drushrc.php | 17 +- examples/example.drushrc.php | 13 - examples/pm_update.drush.inc | 19 -- examples/policy.drush.inc | 150 --------- examples/sandwich.drush.inc | 308 ------------------ examples/sync_enable.drush.inc | 122 ------- examples/sync_via_http.drush.inc | 126 ------- includes/drush.inc | 2 +- 17 files changed, 329 insertions(+), 765 deletions(-) create mode 100644 examples/Commands/PolicyCommands.php create mode 100644 examples/Commands/SandwichCommands.php create mode 100644 examples/Commands/SyncViaHttpCommands.php create mode 100644 examples/Commands/XkcdCommands.php rename examples/{ => Commands}/sandwich-nocolor.txt (100%) rename examples/{sandwich-topic.txt => Commands/sandwich-topic.md} (100%) rename examples/{ => Commands}/sandwich.txt (100%) delete mode 100644 examples/pm_update.drush.inc delete mode 100644 examples/policy.drush.inc delete mode 100644 examples/sandwich.drush.inc delete mode 100644 examples/sync_enable.drush.inc delete mode 100644 examples/sync_via_http.drush.inc diff --git a/docs/commands.md b/docs/commands.md index 8e0b691d7b..78f5504133 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -3,10 +3,10 @@ Creating Custom Drush Commands Creating a new Drush command is very easy. Follow these simple steps: -1. Copy the example commandfile at examples/SandwichCommands.php to mymodule/src/Drush/Commands/MyModuleCommands.php -1. Edit the namespace and classnames to match your file. -1. For next step, use the classes for the core Drush commands at /lib/Drush/Commands as inspiration and documention. -1. Rename and edit the makeMeASandwich method. Carefully add/edit/remove annotations above the method and put your logic inside the method. +1. Copy the example commandfile at lib/Drush/Commands/examples/Commands/SandwichCommands.php to mymodule/src/Drush/Commands/MyModuleCommands.php +1. Edit the namespace and classnames in your file to match the file's location. +1. Use the classes for the core Drush commands at /lib/Drush/Commands as inspiration and documentation. +1. Rename and edit the makeSandwich() method. Carefully add/edit/remove annotations above the method and put your logic inside the method. Drush searches for commandfiles in the following locations: diff --git a/docs/examples.md b/docs/examples.md index 71c1cea65d..470ee8fdc0 100644 --- a/docs/examples.md +++ b/docs/examples.md @@ -1,4 +1,4 @@ -The _examples_ folder contains example files which you may copy and edit as needed. Read the documentation right in the file. If you see an opportunity to improve the file, please submit a pull request. +The _examples_ folder contains excellent example files which you may copy and edit as needed. Read the documentation right in the file. If you see an opportunity to improve the file, please submit a pull request. * [drush.wrapper](https://raw.githubusercontent.com/drush-ops/drush/master/examples/drush.wrapper). A handy launcher script which calls the Drush located in vendor/bin/drush and can add options like --local, --root, etc. * [example.aliases.drushrc.php](https://raw.githubusercontent.com/drush-ops/drush/master/examples/example.aliases.drushrc.php). Example site alias definitions. @@ -10,9 +10,7 @@ The _examples_ folder contains example files which you may copy and edit as need * [example.prompt.sh](https://raw.githubusercontent.com/drush-ops/drush/master/examples/example.prompt.sh). Displays Git repository and Drush alias status in your prompt. * [git-bisect.example.sh](https://raw.githubusercontent.com/drush-ops/drush/master/examples/git-bisect.example.sh). Spelunking through Drush's git history with bisect. * [helloworld.script](https://raw.githubusercontent.com/drush-ops/drush/master/examples/helloworld.script). An example Drush script. -* [pm_update.drush.inc](https://raw.githubusercontent.com/drush-ops/drush/master/examples/pm_update.drush.inc). Restore sqlsrv driver after core update. -* [policy.drush.inc](https://raw.githubusercontent.com/drush-ops/drush/master/examples/policy.drush.inc). A policy file can disallow prohibited commands/options etc. -* [sandwich.drush.inc](https://raw.githubusercontent.com/drush-ops/drush/master/examples/sandwich.drush.inc). A fun example command inspired by a famous XKCD comic. -* [sync_via_http.drush.inc](https://raw.githubusercontent.com/drush-ops/drush/master/examples/sync_via_http.drush.inc). sql-sync modification that transfers via http instead of rsync. -* [sync_enable.drush.inc](https://raw.githubusercontent.com/drush-ops/drush/master/examples/sync_enable.drush.inc). Automatically enable modules after a sql-sync. -* [xkcd.drush.inc](https://raw.githubusercontent.com/drush-ops/drush/master/examples/xkcd.drush.inc). A fun example command that browses XKCD comics. +* [PolicyCommands](https://raw.githubusercontent.com/drush-ops/drush/master/examples/Commands/PolicyCommands.php). A policy file can disallow prohibited commands/options etc. +* [SandwichCommands](https://raw.githubusercontent.com/drush-ops/drush/master/lib/Drush/examples/Commands/SandwichCommands.php). A fun example command inspired by a famous XKCD comic. +* [SyncViaHttpCommands](https://raw.githubusercontent.com/drush-ops/drush/master/examples/Commands/SyncViaHttpCommands.php). sql-sync modification that transfers via http instead of rsync. +* [XkcdCommands](https://raw.githubusercontent.com/drush-ops/drush/master/examples/Commands/XkcdCommands.php). A fun example command that browses XKCD comics. diff --git a/examples/Commands/PolicyCommands.php b/examples/Commands/PolicyCommands.php new file mode 100644 index 0000000000..4e8fd53183 --- /dev/null +++ b/examples/Commands/PolicyCommands.php @@ -0,0 +1,52 @@ +input()->getArgument('destination') == '@prod') { + throw new \Exception(dt('Per !file, you may never overwrite the production database.', ['!file' => __FILE__])); + } + } + + /** + * Limit rsync operations to production site. + * + * hook validate core-rsync + */ + public function rsyncValidate(CommandData $commandData) { + if (preg_match("/^@prod/", $commandData->input()->getArgument('destination'))) { + throw new \Exception(dt('Per !file, you may never rsync to the production site.', ['!file' => __FILE__])); + } + } + + /** + * Unauthorized may not execute updates. + * + * @hook validate updatedb + */ + public function validateUpdateDb(CommandData $commandData) { + if (!$commandData->input()->getOption('secret') == 'mysecret') { + throw new \Exception(dt('UpoateDb command requires a secret token per site policy.')); + } + } + + /** + * @hook option updatedb + * @option secret A required token else user may not run updatedb command. + */ + public function optionsetUpdateDb() {} +} \ No newline at end of file diff --git a/examples/Commands/SandwichCommands.php b/examples/Commands/SandwichCommands.php new file mode 100644 index 0000000000..5c891b76b4 --- /dev/null +++ b/examples/Commands/SandwichCommands.php @@ -0,0 +1,120 @@ + NULL]) { + if ($spreads = _convert_csv_to_array('spreads')) { + $list = implode(' and ', $spreads); + $str_spreads = ' with just a dash of ' . $list; + } + $msg = dt('Okay. Enjoy this !filling sandwich!str_spreads.', + array('!filling' => $filling, '!str_spreads' => $str_spreads) + ); + drush_print("\n" . $msg . "\n"); + $this->printFile(__DIR__ . '/sandwich-nocolor.txt'); + } + + /** + * Show a table of information about available spreads. + * + * @command xkcd-spreads + * @aliases xspreads + * @bootstrap DRUSH_BOOTSTRAP_NONE + * @field-labels + * name: Name + * description: Description + * available: Num + * taste: Taste + * + * @return \Consolidation\OutputFormatters\StructuredData\RowsOfFields + */ + public function spread($options = ['format' => 'table']) { + $data = array( + 'ketchup' => array( + 'name' => 'Ketchup', + 'description' => 'Some say its a vegetable, but we know its a sweet spread.', + 'available' => '7', + 'taste' => 'sweet', + ), + 'mayonnaise' => array( + 'name' => 'Mayonnaise', + 'description' => 'A nice dairy-free spead.', + 'available' => '12', + 'taste' => 'creamy', + ), + 'mustard' => array( + 'name' => 'Mustard', + 'description' => 'Pardon me, but could you please pass that plastic yellow bottle?', + 'available' => '8', + 'taste' => 'tangy', + ), + 'pickles' => array( + 'name' => 'Pickles', + 'description' => 'A necessary part of any sandwich that does not taste terrible.', + 'available' => '63', + 'taste' => 'tasty', + ), + ); + return new RowsOfFields($data); + } + + /** + * Commandfiles may also add topics. These will appear in + * the list of topics when `drush topic` is executed. + * To view the topic below, run `drush --include=/full/path/to/examples topic` + */ + + /** + * Ruminations on the true meaning and philosophy of sandwiches. + * + * @command sandwich-exposition + * @hidden + * @topic + * @bootstrap DRUSH_BOOTSTRAP_NONE + */ + public function ruminate() { + self::printFile(__DIR__ . '/sandwich-topic.md'); + } + + /** + * @hook validate make-me-a-sandwich + */ + public function sandwichValidate(CommandData $commandData) { + $name = posix_getpwuid(posix_geteuid()); + if ($name['name'] !== 'root') { + throw new \Exception(dt('What? Make your own sandwich.')); + } + } + + /** + * Command argument complete callback. + * + * Provides argument values for shell completion. + * + * @return array + * Array of popular fillings. + */ + function complete() { + return array('values' => array('turkey', 'cheese', 'jelly', 'butter')); + } +} \ No newline at end of file diff --git a/examples/Commands/SyncViaHttpCommands.php b/examples/Commands/SyncViaHttpCommands.php new file mode 100644 index 0000000000..a313f3b092 --- /dev/null +++ b/examples/Commands/SyncViaHttpCommands.php @@ -0,0 +1,92 @@ +input()->getOption('http-sync'); + if (!empty($sql_dump_download_url)) { + $user = $commandData->input()->getOption('http-sync-user'); + $password = $commandData->input()->getOption('http-sync-password'); + $source_dump_file = $this->downloadFile($sql_dump_download_url, $user, $password); + $commandData->input()->setOption('target-dump', $source_dump_file); + $commandData->input()->setOption('no-dump', TRUE); + $commandData->input()->setOption('no-sync', TRUE); + } + } + + /** + * Downloads a file. + * + * Optionally uses user authentication, using either wget or curl, as available. + */ + protected function downloadFile($url, $user = FALSE, $password = FALSE, $destination = FALSE, $overwrite = TRUE) { + static $use_wget; + if ($use_wget === NULL) { + $use_wget = drush_shell_exec('which wget'); + } + + $destination_tmp = drush_tempnam('download_file'); + if ($use_wget) { + if ($user && $password) { + drush_shell_exec("wget -q --timeout=30 --user=%s --password=%s -O %s %s", $user, $password, $destination_tmp, $url); + } + else { + drush_shell_exec("wget -q --timeout=30 -O %s %s", $destination_tmp, $url); + } + } + else { + if ($user && $password) { + drush_shell_exec("curl -s -L --connect-timeout 30 --user %s:%s -o %s %s", $user, $password, $destination_tmp, $url); + } + else { + drush_shell_exec("curl -s -L --connect-timeout 30 -o %s %s", $destination_tmp, $url); + } + } + if (!drush_get_context('DRUSH_SIMULATE')) { + if (!drush_file_not_empty($destination_tmp) && $file = @file_get_contents($url)) { + @file_put_contents($destination_tmp, $file); + } + if (!drush_file_not_empty($destination_tmp)) { + // Download failed. + throw new \Exception(dt("The URL !url could not be downloaded.", array('!url' => $url))); + } + } + if ($destination) { + drush_move_dir($destination_tmp, $destination, $overwrite); + return $destination; + } + return $destination_tmp; + } +} \ No newline at end of file diff --git a/examples/Commands/XkcdCommands.php b/examples/Commands/XkcdCommands.php new file mode 100644 index 0000000000..ac4393d2e2 --- /dev/null +++ b/examples/Commands/XkcdCommands.php @@ -0,0 +1,53 @@ + 'open', 'google-custom-search-api-key' => NULL]) { + if (empty($search)) { + drush_start_browser('http://xkcd.com'); + } + elseif (is_numeric($search)) { + drush_start_browser('http://xkcd.com/' . $search); + } + elseif ($search == 'random') { + $xkcd_response = @json_decode(file_get_contents('http://xkcd.com/info.0.json')); + if (!empty($xkcd_response->num)) { + drush_start_browser('http://xkcd.com/' . rand(1, $xkcd_response->num)); + } + } + else { + // This uses an API key with a limited number of searches per. + $search_response = @json_decode(file_get_contents('https://www.googleapis.com/customsearch/v1?key=' . drush_get_option('google-custom-search-api-key', 'AIzaSyDpE01VDNNT73s6CEeJRdSg5jukoG244ek') . '&cx=012652707207066138651:zudjtuwe28q&q=' . $search)); + if (!empty($search_response->items)) { + foreach ($search_response->items as $item) { + drush_start_browser($item->link); + } + } + else { + throw new \Exception(dt('The search failed or produced no results.')); + } + } + } +} \ No newline at end of file diff --git a/examples/sandwich-nocolor.txt b/examples/Commands/sandwich-nocolor.txt similarity index 100% rename from examples/sandwich-nocolor.txt rename to examples/Commands/sandwich-nocolor.txt diff --git a/examples/sandwich-topic.txt b/examples/Commands/sandwich-topic.md similarity index 100% rename from examples/sandwich-topic.txt rename to examples/Commands/sandwich-topic.md diff --git a/examples/sandwich.txt b/examples/Commands/sandwich.txt similarity index 100% rename from examples/sandwich.txt rename to examples/Commands/sandwich.txt diff --git a/examples/example.aliases.drushrc.php b/examples/example.aliases.drushrc.php index ddcd9f9a1d..d5de2762f5 100644 --- a/examples/example.aliases.drushrc.php +++ b/examples/example.aliases.drushrc.php @@ -186,12 +186,8 @@ * Although most aliases will contain only a few options, a number * of settings that are commonly used appear below: * - * - 'uri': In Drupal 7 and 8, the value of --uri should always be the same as + * - 'uri': The value of --uri should always be the same as * when the site is being accessed from a web browser (e.g. http://example.com) - * In Drupal 6, the value of --uri should always be the same as the site's folder - * name in the 'sites' folder (e.g. default); it is best if the site folder name - * matches the URI from the browser, and is consistent on every instance of the - * same site (e.g. also use sites/example.com for http://example.com). * - 'root': The Drupal root; must not be specified as a relative path. * - 'remote-host': The fully-qualified domain name of the remote system * hosting the Drupal instance. **Important Note: The remote-host option @@ -223,12 +219,9 @@ * specified. * - '%root': A reference to the Drupal root defined in the 'root' item in the * site alias record. - * - 'php': path to custom php interpreter. Windows support limited to Cygwin. + * - 'php': path to custom php interpreter. * - 'php-options': commandline options for php interpreter, you may * want to set this to '-d error_reporting="E_ALL^E_DEPRECATED"' - * - 'variables' : An array of name/value pairs which override Drupal - * variables/config. These values take precedence even over settings.php - * overrides. * - 'command-specific': These options will only be set if the alias * is used with the specified command. In the example below, the option * `--no-dump` will be selected whenever the @stage alias @@ -305,9 +298,6 @@ # '%files' => 'sites/mydrupalsite.com/files', # '%custom' => '/my/custom/path', # ), -# 'variables' => array( -# 'site_name' => 'My Drupal site', -# ), # 'command-specific' => array ( # 'sql-sync' => array ( # 'no-dump' => TRUE, @@ -322,9 +312,6 @@ #$aliases['dev'] = array( # 'uri' => 'http://dev.example.com', # 'root' => '/path/to/drupal/root', -# 'variables' => array( -# 'mail_system' => array('default-system' => 'DevelMailLog'), -# ), # ); #$aliases['server'] = array( # 'remote-host' => 'mystagingserver.myisp.com', diff --git a/examples/example.drushrc.php b/examples/example.drushrc.php index b1bc10398e..acd8213799 100644 --- a/examples/example.drushrc.php +++ b/examples/example.drushrc.php @@ -16,7 +16,6 @@ * 3. In any location, as specified by the --config (-c) option. * 4. User's .drush folder (i.e. ~/.drush/drushrc.php). * 5. System wide configuration folder (e.g. /etc/drush/drushrc.php). - * 6. Drush installation folder. * * If a configuration file is found in any of the above locations, it will be * loaded and merged with other configuration files in the search list. @@ -86,17 +85,12 @@ # $options['shell-aliases']['dis-all'] = '!drush -y dis `drush pml --status=enabled --type=module --no-core --pipe`'; # $options['shell-aliases']['self-alias'] = 'site-alias @self --with-db --alias-name=new'; # $options['shell-aliases']['site-get'] = '@none php-eval "return drush_sitealias_site_get();"'; -// Add a 'pm-clone' to simplify git cloning from drupal.org. -# $options['shell-aliases']['pm-clone'] = 'pm-download --gitusername=YOURUSERNAME --package-handler=git_drupalorg'; // Save a sanitized sql dump. Customize alias names and --result-file. # $options['shell-aliases']['sql-dump-sanitized'] = '!drush sql-sync @source @temp --sanitize && drush @temp sql-dump --result-file=/example && drush @temp sql-drop'; // Load a drushrc.php configuration file from the current working directory. # $options['config'][] = './drushrc.php'; -// Clone extensions (modules, themes, etc.) from drupal.org via 'pm-download'. -# $options['package-handler'] = 'git_drupalorg'; - /** * Specify folders to search for Drush command files (*.drush.inc). These * values are always merged with include paths defined on the command line or @@ -222,13 +216,6 @@ */ # $options['skip-tables']['common'] = array('migration_*'); -/** - * Override specific entries in Drupal's variable system or settings.php (D7 only). - */ -# $options['variables']['site_name'] = 'My Drupal site'; -# $options['variables']['theme_default'] = 'minnelli'; -# $options['variables']['anonymous'] = 'Visitor'; - /** * Command-specific execution options: * diff --git a/examples/pm_update.drush.inc b/examples/pm_update.drush.inc deleted file mode 100644 index 3ba610e195..0000000000 --- a/examples/pm_update.drush.inc +++ /dev/null @@ -1,19 +0,0 @@ - "Makes a delicious sandwich.", - 'arguments' => array( - 'filling' => 'The type of the sandwich (turkey, cheese, etc.). Defaults to ascii.', - ), - 'options' => array( - 'spreads' => array( - 'description' => 'Comma delimited list of spreads.', - 'example-value' => 'mayonnaise,mustard', - ), - ), - 'examples' => array( - 'drush mmas turkey --spreads=ketchup,mustard' => 'Make a terrible-tasting sandwich that is lacking in pickles.', - ), - 'aliases' => array('mmas'), - // No bootstrap at all. - 'bootstrap' => DRUSH_BOOTSTRAP_NONE, - ); - - // The 'sandwiches-served' command. Informs how many 'mmas' commands - // completed. - $items['sandwiches-served'] = array( - 'description' => "Report how many sandwiches we have made.", - 'examples' => array( - 'drush sandwiches-served' => 'Show how many sandwiches we have served.', - ), - 'aliases' => array('sws'), - // Example output engine data: command returns a single keyed - // data item (e.g. array("served" => 1)) that can either be - // printed with a label (e.g. "served: 1"), or output raw with - // --pipe (e.g. "1"). - 'engines' => array( - 'outputformat' => array( - 'default' => 'key-value', - 'pipe-format' => 'string', - 'label' => 'Sandwiches Served', - 'require-engine-capability' => array('format-single'), - ), - ), - // No bootstrap at all. - 'bootstrap' => DRUSH_BOOTSTRAP_NONE, - ); - - // The 'spreads-status' command. Prints a table about available spreads. - $items['spreads-status'] = array( - 'description' => "Show a table of information about available spreads.", - 'examples' => array( - 'drush spreads-status' => 'Show a table of spreads.', - ), - 'aliases' => array('sps'), - // Example output engine data: command returns a deep array - // that can either be printed in table format or as a json array. - 'engines' => array( - 'outputformat' => array( - 'default' => 'table', - 'pipe-format' => 'json', - // Commands that return deep arrays will usually use - // machine-ids for the column data. A 'field-labels' - // item maps from the machine-id to a human-readable label. - 'field-labels' => array( - 'name' => 'Name', - 'description' => 'Description', - 'available' => 'Num', - 'taste' => 'Taste', - ), - // In table format, the 'column-widths' item is consulted - // to determine the default weights for any named column. - 'column-widths' => array( - 'name' => 10, - 'available' => 3, - ), - 'require-engine-capability' => array('format-table'), - ), - ), - // No bootstrap at all. - 'bootstrap' => DRUSH_BOOTSTRAP_NONE, - ); - - // Commandfiles may also add topics. These will appear in - // the list of topics when `drush topic` is executed. - // To view this topic, run `drush --include=/full/path/to/examples topic` - $items['sandwich-exposition'] = array( - 'description' => 'Ruminations on the true meaning and philosophy of sandwiches.', - 'hidden' => TRUE, - 'topic' => TRUE, - 'bootstrap' => DRUSH_BOOTSTRAP_NONE, - 'callback' => 'drush_print_file', - 'callback arguments' => array(dirname(__FILE__) . '/sandwich-topic.txt'), - ); - - return $items; -} - -/** - * Implements hook_drush_help(). - * - * This function is called whenever a drush user calls - * 'drush help '. This hook is optional. If a command - * does not implement this hook, the command's description is used instead. - * - * This hook is also used to look up help metadata, such as help - * category title and summary. See the comments below for a description. - */ -function sandwich_drush_help($section) { - switch ($section) { - case 'drush:make-me-a-sandwich': - return dt("This command will make you a delicious sandwich, just how you like it."); - - // The 'title' meta item is used to name a group of - // commands in `drush help`. If a title is not defined, - // the default is "All commands in ___", with the - // specific name of the commandfile (e.g. sandwich). - // Command files with less than four commands will - // be placed in the "Other commands" section, _unless_ - // they define a title. It is therefore preferable - // to not define a title unless the file defines a lot - // of commands. - case 'meta:sandwich:title': - return dt("Sandwich commands"); - - // The 'summary' meta item is displayed in `drush help --filter`, - // and is used to give a general idea what the commands in this - // command file do, and what they have in common. - case 'meta:sandwich:summary': - return dt("Automates your sandwich-making business workflows."); - } -} - -/** - * Implements drush_hook_COMMAND_validate(). - * - * The validate command should exit with - * `return drush_set_error(...)` to stop execution of - * the command. In practice, calling drush_set_error - * OR returning FALSE is sufficient. See drush.api.php - * for more details. - */ -function drush_sandwich_make_me_a_sandwich_validate() { - if (drush_is_windows()) { - // $name = drush_get_username(); - // @todo Implement check for elevated process using w32api - // as sudo is not available for Windows - // @see http://php.net/manual/en/book.w32api.php - // @see http://social.msdn.microsoft.com/Forums/en/clr/thread/0957c58c-b30b-4972-a319-015df11b427d - } - else { - $name = posix_getpwuid(posix_geteuid()); - if ($name['name'] !== 'root') { - return drush_set_error('MAKE_IT_YOUSELF', dt('What? Make your own sandwich.')); - } - } -} - -/** - * Implements drush_hook_COMMAND(). - * - * The command callback is where the action takes place. - * - * The function name should be same as command name but with dashes turned to - * underscores and 'drush_commandfile_' prepended, where 'commandfile' is - * taken from the file 'commandfile.drush.inc', which in this case is - * 'sandwich'. Note also that a simplification step is also done in instances - * where the commandfile name is the same as the beginning of the command name, - * "drush_example_example_foo" is simplified to just "drush_example_foo". - * To also implement a hook that is called before your command, implement - * "drush_hook_pre_example_foo". For a list of all available hooks for a - * given command, run drush in --debug mode. - * - * If for some reason you do not want your hook function to be named - * after your command, you may define a 'callback' item in your command - * object that specifies the exact name of the function that should be - * called. - * - * In this function, all of Drupal's API is (usually) available, including - * any functions you have added in your own modules/themes. - * - * @see drush_invoke() - * @see drush.api.php - */ -function drush_sandwich_make_me_a_sandwich($filling = 'ascii') { - $str_spreads = ''; - // Read options with drush_get_option. Note that the options _must_ - // be documented in the $items structure for this command in the 'command' - // hook. See `drush topic docs-commands` for more information. - if ($spreads = drush_get_option('spreads')) { - $list = implode(' and ', explode(',', $spreads)); - $str_spreads = ' with just a dash of ' . $list; - } - $msg = dt('Okay. Enjoy this !filling sandwich!str_spreads.', - array('!filling' => $filling, '!str_spreads' => $str_spreads) - ); - drush_print("\n" . $msg . "\n"); - - if (drush_get_context('DRUSH_NOCOLOR')) { - $filename = dirname(__FILE__) . '/sandwich-nocolor.txt'; - } - else { - $filename = dirname(__FILE__) . '/sandwich.txt'; - } - drush_print(file_get_contents($filename)); - // Find out how many sandwiches have been served, and set - // the cached value to one greater. - $served = drush_sandwich_sandwiches_served(); - drush_cache_set(drush_get_cid('sandwiches-served'), $served + 1); -} - -/** - * Implements drush_hook_COMMAND(). - * - * Demonstrates how to return a simple value that is transformed by - * the selected formatter to display either with a label (using the - * key-value formatter) or as the raw value itself (using the string formatter). - */ -function drush_sandwich_sandwiches_served() { - $served = 0; - $served_object = drush_cache_get(drush_get_cid('sandwiches-served')); - if ($served_object) { - $served = $served_object->data; - } - // In the default format, key-value, this return value - // will print " Sandwiches Served : 1". In the default pipe - // format, only the array value ("1") is returned. - return $served; -} - -/** - * Implements drush_hook_COMMAND(). - * - * This ficticious command shows how a deep array can be constructed - * and used as a command return value that can be output by different - * output formatters. - */ -function drush_sandwich_spreads_status() { - return array( - 'ketchup' => array( - 'name' => 'Ketchup', - 'description' => 'Some say its a vegetable, but we know its a sweet spread.', - 'available' => '7', - 'taste' => 'sweet', - ), - 'mayonnaise' => array( - 'name' => 'Mayonnaise', - 'description' => 'A nice dairy-free spead.', - 'available' => '12', - 'taste' => 'creamy', - ), - 'mustard' => array( - 'name' => 'Mustard', - 'description' => 'Pardon me, but could you please pass that plastic yellow bottle?', - 'available' => '8', - 'taste' => 'tangy', - ), - 'pickles' => array( - 'name' => 'Pickles', - 'description' => 'A necessary part of any sandwich that does not taste terrible.', - 'available' => '63', - 'taste' => 'tasty', - ), - ); -} - -/** - * Command argument complete callback. - * - * Provides argument values for shell completion. - * - * @return array - * Array of popular fillings. - */ -function sandwich_make_me_a_sandwich_complete() { - return array('values' => array('turkey', 'cheese', 'jelly', 'butter')); -} diff --git a/examples/sync_enable.drush.inc b/examples/sync_enable.drush.inc deleted file mode 100644 index d8ccb1011b..0000000000 --- a/examples/sync_enable.drush.inc +++ /dev/null @@ -1,122 +0,0 @@ - '/srv/www/drupal', - * 'uri' => 'site.com', - * 'target-command-specific' => array( - * 'sql-sync' => array( - * 'enable' => array('devel', 'hacked'), - * 'disable' => array('securepages'), - * 'permission' => array( - * 'authenticated user' => array( - * 'add' => array('access devel information', 'access environment indicator'), - * 'remove' => 'change own password', - * ), - * 'anonymous user' => array( - * 'add' => 'access environment indicator', - * ), - * ), - * ), - * ), - * ); - * @endcode - * - * To use this feature, copy the 'target-command-specific' - * item from the example alias above, place it in your development - * site aliases, and customize the development module list - * to suit. You must also copy the sync_enable.drush.inc - * file to a location where Drush will find it, such as - * $HOME/.drush. See `drush topic docs-commands` for more - * information. - * - * To set variables on a development site: - * - * Instead of calling variable_set and variable_delete in a post-sync - * hook, consider adding $conf variables to settings.php. - * - * For example: - * - * $conf['error_level'] = 2; - * error_reporting(E_ALL); - * ini_set('display_errors', TRUE); - * ini_set('display_startup_errors', TRUE); - * $conf['preprocess_css'] = 0; - * $conf['cache'] = 0; - * $conf['googleanalytics_account'] = ''; - */ - -/** - * Implements hook_drush_help_alter(). - * - * When a hook extends a command with additional options, it must - * implement help alter and declare the option(s). Doing so will add - * the option to the help text for the modified command, and will also - * allow the new option to be specified on the command line. Without - * this, Drush will fail with an error when a user attempts to use - * the option. - */ -function sync_enable_drush_help_alter(&$command) { - if ($command['command'] == 'sql-sync') { - $command['options']['updb'] = "Apply database updates on the target database after the sync operation has completed."; - $command['options']['enable'] = "Enable the specified modules in the target database after the sync operation has completed."; - $command['options']['disable'] = "Disable the specified modules in the target database after the sync operation has completed."; - $command['options']['permission'] = "Add or remove permissions from a role in the target database after the sync operation has completed. The value of this option must be an array, so it may only be specified in a site alias record or drush configuration file. See `drush topic docs-example-sync-extension`."; - } -} - -/** - * Implements drush_hook_post_COMMAND(). - * - * The post hook is only called if the sql-sync operation completes - * without an error. When called, we check to see if the user specified - * any modules to enable/disable. If so, we will call pm-enable/pm-disable on - * each module. - */ -function drush_sync_enable_post_sql_sync($source = NULL, $destination = NULL) { - $updb = drush_get_option('updb', FALSE); - if ($updb) { - drush_log('Run database updates', 'ok'); - drush_invoke_process($destination, 'updatedb', array(), array('yes' => TRUE)); - } - $modules_to_enable = drush_get_option_list('enable'); - if (!empty($modules_to_enable)) { - drush_log(dt("Enable !modules post-sql-sync", array('!modules' => implode(',', $modules_to_enable))), 'ok'); - drush_invoke_process($destination, 'pm-enable', $modules_to_enable, array('yes' => TRUE)); - } - $modules_to_disable = drush_get_option_list('disable'); - if (!empty($modules_to_disable)) { - drush_log(dt("Disable !modules post-sql-sync", array('!modules' => implode(',', $modules_to_disable))), 'ok'); - drush_invoke_process($destination, 'pm-disable', $modules_to_disable, array('yes' => TRUE)); - } - $permissions_table = drush_get_option('permission'); - if (!empty($permissions_table)) { - foreach ($permissions_table as $role_name => $actions) { - if (array_key_exists('add', $actions)) { - $permissions_to_add = is_array($actions['add']) ? $actions['add'] : explode(', ', $actions['add']); - foreach ($permissions_to_add as $permission) { - $values = drush_invoke_process($destination, 'role-add-perm', array($role_name, $permission), array(), array('integrate' => TRUE)); - } - } - if (array_key_exists('remove', $actions)) { - $permissions_to_remove = is_array($actions['remove']) ? $actions['remove'] : explode(', ', $actions['remove']); - foreach ($permissions_to_remove as $permission) { - $values = drush_invoke_process($destination, 'role-remove-perm', array($role_name, $permission), array(), array('integrate' => TRUE)); - } - } - } - } -} diff --git a/examples/sync_via_http.drush.inc b/examples/sync_via_http.drush.inc deleted file mode 100644 index cf44d2132d..0000000000 --- a/examples/sync_via_http.drush.inc +++ /dev/null @@ -1,126 +0,0 @@ - '/srv/www/drupal', - * 'uri' => 'staging.site.com', - * 'source-command-specific' => array( - * 'sql-sync' => array( - * 'http-sync' => 'https://staging.site.com/protected-directory/site-database-dump.sql', - * 'http-sync-user' => 'wwwadmin', - * 'http-sync-password' => 'secretsecret', - * ), - * ), - * ); - * @endcode - * - * To use this feature, copy the 'source-command-specific' - * item from the example alias above, place it in your staging - * site aliases, and custom the access credentials as - * necessary. You must also copy the sync_via_http.drush.inc - * file to a location where Drush will find it, such as - * $HOME/.drush. See `drush topic docs-commands` for more - * information. - * - * IMPORTANT NOTE: This example does not cause the sql dump - * to be performed; it is presumed that the dump file already - * exists at the provided URL. For a full solution, a web page - * that initiated an sql-dump (or perhaps a local sql-sync followed - * by an sql-sanitize and then an sql-dump) would be necessary. - */ - -/** - * Implements hook_drush_help_alter(). - * - * When a hook extends a command with additional options, it must - * implement help alter and declare the option(s). Doing so will add - * the option to the help text for the modified command, and will also - * allow the new option to be specified on the command line. Without - * this, Drush will fail with an error when a user attempts to use - * the option. - */ -function sync_via_http_drush_help_alter(&$command) { - if ($command['command'] == 'sql-sync') { - $command['options']['http-sync'] = "Copy the database via http instead of rsync. Value is the url that the existing database dump can be found at."; - $command['sub-options']['http-sync']['http-sync-user'] = "Username for the protected directory containing the sql dump."; - $command['sub-options']['http-sync']['http-sync-password'] = "Password for the same directory."; - } -} - -/** - * Implements drush_hook_pre_COMMAND(). - * - * During the pre hook, determine if the http-sync option has been - * specified. If it has been, then disable the normal ssh + rsync - * dump-and-transfer that sql-sync usually does, and transfer the - * database dump via an http download. - */ -function drush_sync_via_http_pre_sql_sync($source = NULL, $destination = NULL) { - $sql_dump_download_url = drush_get_option('http-sync'); - if (!empty($sql_dump_download_url)) { - $user = drush_get_option('http-sync-user', FALSE); - $password = drush_get_option('http-sync-password', FALSE); - $source_dump_file = _drush_sync_via_http_download_file($sql_dump_download_url, $user, $password); - if ($source_dump_file === FALSE) { - return drush_set_error('DRUSH_CANNOT_DOWNLOAD', dt("The URL !url could not be downloaded.", array('!url' => $sql_dump_download_url))); - } - drush_set_option('target-dump', $source_dump_file); - drush_set_option('no-dump', TRUE); - drush_set_option('no-sync', TRUE); - } -} - -/** - * Downloads a files. - * - * Optionaly uses user authentication, using either wget or curl, as available. - */ -function _drush_sync_via_http_download_file($url, $user = FALSE, $password = FALSE, $destination = FALSE, $overwrite = TRUE) { - static $use_wget; - if ($use_wget === NULL) { - $use_wget = drush_shell_exec('which wget'); - } - - $destination_tmp = drush_tempnam('download_file'); - if ($use_wget) { - if ($user && $password) { - drush_shell_exec("wget -q --timeout=30 --user=%s --password=%s -O %s %s", $user, $password, $destination_tmp, $url); - } - else { - drush_shell_exec("wget -q --timeout=30 -O %s %s", $destination_tmp, $url); - } - } - else { - if ($user && $password) { - drush_shell_exec("curl -s -L --connect-timeout 30 --user %s:%s -o %s %s", $user, $password, $destination_tmp, $url); - } - else { - drush_shell_exec("curl -s -L --connect-timeout 30 -o %s %s", $destination_tmp, $url); - } - } - if (!drush_get_context('DRUSH_SIMULATE')) { - if (!drush_file_not_empty($destination_tmp) && $file = @file_get_contents($url)) { - @file_put_contents($destination_tmp, $file); - } - if (!drush_file_not_empty($destination_tmp)) { - // Download failed. - return FALSE; - } - } - if ($destination) { - drush_move_dir($destination_tmp, $destination, $overwrite); - return $destination; - } - return $destination_tmp; -} diff --git a/includes/drush.inc b/includes/drush.inc index b7dfb3f87f..30ebddcafd 100644 --- a/includes/drush.inc +++ b/includes/drush.inc @@ -285,7 +285,7 @@ function drush_get_global_options($brief = FALSE) { $options['interactive'] = array('short-form' => 'ia', 'description' => "Force interactive mode for commands run on multiple targets (e.g. `drush @site1,@site2 cc --ia`).", 'never-propagate' => TRUE); $options['tty'] = array('hidden' => TRUE, 'description' => "Force allocation of tty for remote commands", 'never-propagate' => TRUE); $options['quiet'] = array('short-form' => 'q', 'description' => 'Suppress non-error messages.'); - $options['include'] = array('short-form' => 'i', 'short-has-arg' => TRUE, 'context' => 'DRUSH_INCLUDE', 'never-post' => TRUE, 'propagate-cli-value' => TRUE, 'merge-pathlist' => TRUE, 'description' => "A list of additional directory paths to search for drush commands.", 'example-value' => '/path/dir'); + $options['include'] = array('short-form' => 'i', 'short-has-arg' => TRUE, 'context' => 'DRUSH_INCLUDE', 'never-post' => TRUE, 'propagate-cli-value' => TRUE, 'merge-pathlist' => TRUE, 'description' => "A list of additional directory paths to search for Drush commands. Commandfiles should be placed in a subfolder called 'Commands'.", 'example-value' => '/path/dir'); $options['exclude'] = array('propagate-cli-value' => TRUE, 'never-post' => TRUE, 'merge-pathlist' => TRUE, 'description' => "A list of files and directory paths to exclude from consideration when searching for drush commandfiles.", 'example-value' => '/path/dir'); $options['config'] = array('short-form' => 'c', 'short-has-arg' => TRUE, 'context' => 'DRUSH_CONFIG', 'never-post' => TRUE, 'propagate-cli-value' => TRUE, 'merge-pathlist' => TRUE, 'description' => "Specify an additional config file to load. See example.drushrc.php.", 'example-value' => '/path/file'); $options['user'] = array('short-form' => 'u', 'short-has-arg' => TRUE, 'propagate-cli-value' => TRUE, 'description' => "Specify a Drupal user to login with. May be a name or a number.", 'example-value' => 'name_or_number');