5 * Documentation of the Drush API.
9 * Declare a new command.
11 function hook_drush_command() {
12 // To learn more, run `drush topic docs-commands` and
13 // `drush topic docs-examplecommand`.
17 * All Drush commands are invoked in a specific order, using
18 * drush-made hooks, very similar to the Drupal hook system. See drush_invoke()
19 * for the actual implementation.
21 * For any commandfile named "hook", the following hooks are called, in
22 * order, for the command "COMMAND":
24 * 0. drush_COMMAND_init()
25 * 1. drush_hook_COMMAND_pre_validate()
26 * 2. drush_hook_COMMAND_validate()
27 * 3. drush_hook_pre_COMMAND()
28 * 4. drush_hook_COMMAND()
29 * 5. drush_hook_post_COMMAND()
31 * For example, here are the hook opportunities for a mysite.drush.inc file
32 * that wants to hook into the `pm-download` command.
34 * 1. drush_mysite_pm_download_pre_validate()
35 * 2. drush_mysite_pm_download_validate()
36 * 3. drush_mysite_pre_pm_download()
37 * 4. drush_mysite_pm_download()
38 * 5. drush_mysite_post_pm_download()
40 * Note that the drush_COMMAND_init() hook is only for use by the
41 * commandfile that defines the command.
43 * If any of hook function fails, either by calling drush_set_error
44 * or by returning FALSE as its function result, then the rollback
45 * mechanism is called. To fail with an error, call drush_set_error:
47 * return drush_set_error('MY_ERROR_CODE', dt('Error message.'));
49 * To allow the user to confirm or cancel a command, use drush_confirm
50 * and drush_user_abort:
52 * if (!drush_confirm(dt('Are you sure?'))) {
53 * return drush_user_abort();
56 * The rollback mechanism will call, in reverse, all _rollback hooks.
57 * The mysite command file can implement the following rollback hooks:
59 * 1. drush_mysite_post_pm_download_rollback()
60 * 2. drush_mysite_pm_download_rollback()
61 * 3. drush_mysite_pre_pm_download_rollback()
62 * 4. drush_mysite_pm_download_validate_rollback()
63 * 5. drush_mysite_pm_download_pre_validate_rollback()
65 * Before any command is called, hook_drush_init() is also called.
66 * hook_drush_exit() is called at the very end of command invocation.
68 * @see includes/command.inc
70 * @see hook_drush_init()
71 * @see drush_COMMAND_init()
72 * @see drush_hook_COMMAND_pre_validate()
73 * @see drush_hook_COMMAND_validate()
74 * @see drush_hook_pre_COMMAND()
75 * @see drush_hook_COMMAND()
76 * @see drush_hook_post_COMMAND()
77 * @see drush_hook_post_COMMAND_rollback()
78 * @see drush_hook_COMMAND_rollback()
79 * @see drush_hook_pre_COMMAND_rollback()
80 * @see drush_hook_COMMAND_validate_rollback()
81 * @see drush_hook_COMMAND_pre_validate_rollback()
82 * @see hook_drush_exit()
91 * Take action before any command is run.
93 * Logging an error stops command execution.
95 function hook_drush_init() {
100 * Initialize a command prior to validation.
102 * If a command needs to bootstrap to a higher level, this is best done in the
103 * command init hook. It is permisible to bootstrap in any hook, but note that
104 * if bootstrapping adds more commandfiles (*.drush.inc) to the commandfile
105 * list, the newly-added commandfiles will not have any hooks called until the
106 * next phase. For example, a command that calls drush_bootstrap_max() in
107 * drush_hook_COMMAND() would only permit commandfiles from modules enabled in
108 * the site to participate in drush_hook_post_COMMAND() hooks.
110 function drush_COMMAND_init() {
111 drush_bootstrap_max();
115 * Run before a specific command validates.
117 * Logging an error stops command execution, and the rollback function (if any)
118 * for each hook implementation is invoked.
120 * @see drush_hook_COMMAND_pre_validate_rollback()
122 function drush_hook_COMMAND_pre_validate() {
127 * Run before a specific command executes.
129 * Logging an error stops command execution, and the rollback function (if any)
130 * for each hook implementation is invoked.
132 * @see drush_hook_COMMAND_validate_rollback()
134 function drush_hook_COMMAND_validate() {
139 * Run before a specific command executes.
141 * Logging an error stops command execution, and the rollback function (if any)
142 * for each hook implementation is invoked, in addition to the validate
145 * @see drush_hook_pre_COMMAND_rollback()
146 * @see drush_hook_COMMAND_validate_rollback()
148 function drush_hook_pre_COMMAND() {
153 * Implementation of the actual drush command.
155 * This is where most of the stuff should happen.
157 * Logging an error stops command execution, and the rollback function (if any)
158 * for each hook implementation is invoked, in addition to pre and
159 * validate rollbacks.
161 * @return mixed|false
162 * The return value will be passed along to the caller if --backend option is
163 * present. A boolean FALSE indicates failure and rollback will be inititated.
165 * @see drush_hook_COMMAND_rollback()
166 * @see drush_hook_pre_COMMAND_rollback()
167 * @see drush_hook_COMMAND_validate_rollback()
169 function drush_hook_COMMAND() {
174 * Run after a specific command executes.
176 * Logging an error stops command execution, and the rollback function (if any)
177 * for each hook implementation is invoked, in addition to pre, normal
178 * and validate rollbacks.
180 * @see drush_hook_post_COMMAND_rollback()
181 * @see drush_hook_COMMAND_rollback()
182 * @see drush_hook_pre_COMMAND_rollback()
183 * @see drush_hook_COMMAND_validate_rollback()
185 function drush_hook_post_COMMAND() {
190 * Take action after any command is run.
192 function hook_drush_exit() {
197 * Adjust the contents of any command structure prior to dispatch.
199 * @see core_drush_command_alter()
201 function hook_drush_command_alter(&$command) {
206 * Adjust the contents of a site alias.
208 function hook_drush_sitealias_alter(&$alias_record) {
209 // If the alias is "remote", but the remote site is
210 // the system this command is running on, convert the
211 // alias record to a local alias.
212 if (isset($alias_record['remote-host'])) {
213 $uname = php_uname('n');
214 if ($alias_record['remote-host'] == $uname) {
215 unset($alias_record['remote-host']);
216 unset($alias_record['remote-user']);
222 * Take action after a project has been downloaded.
224 function hook_drush_pm_post_download($project, $release) {
229 * Take action after a project has been updated.
231 function hook_pm_post_update($project_name, $installed_release, $project) {
235 * Adjust the location a project should be copied to after being downloaded.
237 * See @pm_drush_pm_download_destination_alter().
239 function hook_drush_pm_download_destination_alter(&$project, $release) {
240 if ($some_condition) {
241 $project['project_install_location'] = '/path/to/install/to/' . $project['project_dir'];
246 * Automatically download project dependencies at pm-enable time.
248 * Use a pre-pm_enable hook to download before your module is enabled,
249 * or a post-pm_enable hook (drush_hook_post_pm_enable) to run after
250 * your module is enabled.
252 * Your hook will be called every time pm-enable is executed; you should
253 * only download dependencies when your module is being enabled. Respect
254 * the --skip flag, and take no action if it is present.
256 function drush_hook_pre_pm_enable() {
257 // Get the list of modules being enabled; only download dependencies if our
258 // module name appears in the list.
259 $modules = drush_get_context('PM_ENABLE_MODULES');
260 if (in_array('hook', $modules) && !drush_get_option('skip')) {
261 $url = 'http://server.com/path/MyLibraryName.tgz';
262 $path = drush_get_context('DRUSH_DRUPAL_ROOT');
263 drush_include_engine('drupal', 'environment');
264 if (drush_module_exists('libraries')) {
265 $path .= '/' . libraries_get_path('MyLibraryName') . '/MyLibraryName.tgz';
268 $path .= '/' . drupal_get_path('module', 'hook') . '/MyLibraryName.tgz';
270 drush_download_file($url, $path) && drush_tarball_extract($path);
275 * Sql-sync sanitization example.
277 * This is equivalent to the built-in --sanitize option of sql-sync, but
278 * simplified to only work with default values on Drupal 6 + mysql.
280 * @see sql_drush_sql_sync_sanitize()
282 function hook_drush_sql_sync_sanitize($source) {
283 $table = drush_get_option('db-prefix') ? '{users}' : 'users';
284 drush_sql_register_post_sync_op('my-sanitize-id',
285 dt('Reset passwords and email addresses in user table.'),
286 "UPDATE $table SET pass = MD5('password'), mail = concat('user+', uid, '@localhost') WHERE uid > 0;");
290 * Add help components to a command.
292 function hook_drush_help_alter(&$command) {
293 if ($command['command'] == 'sql-sync') {
294 $command['options']['myoption'] = "Description of modification of sql-sync done by hook";
295 $command['sub-options']['sanitize']['my-sanitize-option'] = "Description of sanitization option added by hook (grouped with --sanitize option)";
297 if ($command['command'] == 'global-options') {
298 // Recommended: don't show global hook options in brief global options help.
299 if ($command['#brief'] === FALSE) {
300 $command['options']['myglobaloption'] = 'Description of option used globally in all commands (e.g. in a commandfile init hook)';
306 * Add/edit options to cache-clear command.
308 * @param array $types
309 * Adjust types as needed. Is passed by reference.
311 * @param bool $include_bootstrapped_types
312 * If FALSE, omit types which require a FULL bootstrap.
314 function hook_drush_cache_clear(&$types, $include_bootstrapped_types) {
315 $types['views'] = 'views_invalidate_cache';
319 * Inform drush about one or more engine types.
321 * This hook allow to declare available engine types, the cli option to select
322 * between engine implementatins, which one to use by default, global options
323 * and other parameters. Commands may override this info when declaring the
327 * An array whose keys are engine type names and whose values describe
328 * the characteristics of the engine type in relation to command definitions:
330 * - description: The engine type description.
331 * - topic: If specified, the name of the topic command that will
332 * display the automatically generated topic for this engine.
333 * - topic-file: If specified, the path to the file that will be
334 * displayed at the head of the automatically generated topic for
335 * this engine. This path is relative to the Drush root directory;
336 * non-core commandfiles should therefore use:
337 * 'topic-file' => dirname(__FILE__) . '/mytopic.html';
338 * - topics: If set, contains a list of topics that should be added to
339 * the "Topics" section of any command that uses this engine. Note
340 * that if 'topic' is set, it will automatically be added to the topics
341 * list, and therefore does not need to also be listed here.
342 * - option: The command line option to choose an implementation for
344 * FALSE means there's no option. That is, the engine type is for internal
345 * usage of the command and thus an implementation is not selectable.
346 * - default: The default implementation to use by the engine type.
347 * - options: Engine options common to all implementations.
348 * - add-options-to-command: If there's a single implementation for this
349 * engine type, add its options as command level options.
350 * - combine-help: If there are multiple implementations for this engine
351 * type, then instead of adding multiple help items in the form of
352 * --engine-option=engine-type [description], instead combine all help
353 * options into a single --engine-option that lists the different possible
354 * values that can be used.
356 * @see drush_get_engine_types_info()
357 * @see pm_drush_engine_type_info()
359 function hook_drush_engine_type_info() {
362 'description' => 'Choose a dessert while the sandwich is baked.',
363 'option' => 'dessert',
364 'default' => 'ice-cream',
365 'options' => 'sweetness',
366 'add-options-to-command' => FALSE,
372 * Inform drush about one or more engines implementing a given engine type.
374 * - description: The engine implementation's description.
375 * - implemented-by: The engine that actually implements this engine.
376 * This is useful to allow the implementation of similar engines
377 * in the reference one.
378 * Defaults to the engine type key (e.g. 'ice-cream').
379 * - verbose-only: The engine implementation will only appear in help
380 * output in --verbose mode.
382 * This hook allow to declare implementations for an engine type.
384 * @see pm_drush_engine_package_handler()
385 * @see pm_drush_engine_version_control()
387 function hook_drush_engine_ENGINE_TYPE() {
389 'ice-cream' => array(
390 'description' => 'Feature rich ice-cream with all kind of additives.',
392 'flavour' => 'Choose your favorite flavour',
395 'frozen-yogurt' => array(
396 'description' => 'Frozen dairy dessert made with yogurt instead of milk and cream.',
397 'implemented-by' => 'ice-cream',
403 * Alter the order that hooks are invoked.
405 * When implementing a given hook we may need to ensure it is invoked before
406 * or after another implementation of the same hook. For example, let's say
407 * you want to implement a hook that would be called after drush_make. You'd
408 * write a drush_MY_MODULE_post_make() function. But if you need your hook to
409 * be called before drush_make_post_make(), you can ensure this by implemen-
410 * ting MY_MODULE_drush_invoke_alter().
412 * @see drush_command_invoke_all_ref()
414 function hook_drush_invoke_alter($modules, $hook) {
415 if ($hook == 'some_hook') {
416 // Take the module who's hooks would normally be called last.
417 $module = array_pop($modules);
418 // Ensure it'll be called first for 'some_hook'.
419 array_unshift($modules, $module);
424 * @} End of "addtogroup hooks".