00001 <?php
00002
00003
00004 include_once 'includes/multi.inc';
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 function multi_drush_help($section) {
00025 switch ($section) {
00026 case 'drush:multi-status':
00027 return dt("Status of your multisite installation.");
00028 case 'drush:multi-exec':
00029 return dt('Execute a drush command for all sites in your multisite installation.');
00030 case 'drush:multi-drupalupdate':
00031 return dt('Run a drupal minor update on your multisite installation.');
00032 case 'drush:multi-site':
00033 return dt('Create a new site in your your multisite installation within a files, modules and themes directory.');
00034 case 'drush:multi-create':
00035 return dt('Create a multisite installation.');
00036 case 'drush:multi-sql-dump':
00037 return dt('Execute \'sql dump\' for all sites in your your multisite installation. The default pattern for the result-file is $uri . \'_\' . date(\'Y-m-d\TH:i\').sql, where $uri is the foldername of a site.');
00038 case 'drush:multi-nagios':
00039 return 'For the use as nagios plugin. Print a message and returns with exit status 2 (Critical) if there is a drupal update available.';
00040 }
00041 }
00042
00043
00044
00045
00046
00047
00048
00049 function multi_drush_command() {
00050 $items = array();
00051
00052 $items['multi-status'] = array(
00053 'callback' => 'multi_status',
00054 'aliases' => array('mst'),
00055 'description' => 'Status of your drupal multisite installation',
00056 'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_ROOT,
00057 'examples' => array(
00058 'drush -r /path/to/drupal multi-status' => 'Displays the status.',
00059 ),
00060 );
00061 $items['multi-nagios'] = array(
00062 'callback' => 'multi_nagios',
00063 'aliases' => array('mna', 'nagios'),
00064 'description' => 'Message and exit code for nagios.',
00065 'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_ROOT,
00066 'examples' => array(
00067 'drush -r /path/to/drupal multi-nagios' =>
00068 "We assume that drupal-6.14 is the recommended release.\n" .
00069 "With an older version, eg. drupal-6.13 we get:\n" .
00070 "DRUPAL ROOT CRITICAL: drupal-6.13 @ /var/www/drupal-6.13\n" .
00071 " - drupal-6.14 (2009-09-16 21:40) available, see http://drupal.org/node/579476 for details.\n" .
00072 "with exit status 2\n" .
00073 "Or if we are running the recommended version:\n" .
00074 "'DRUPAL ROOT OK: drupal-6.14 @ /path/to/drupal/6.x is uptodate.'\n" .
00075 "with exit status 0.",
00076 'drush -r /path/to/drupal multi-nagios --file=/path/to/file' => 'Same as above with a specified file.',
00077 'drush -r /path/to/drupal -l example.com multi-nagios' =>
00078 "If there are no updates available, this will produce to following output:\n" .
00079 "DRUPAL SITE OK - example.com @ /path/to/drupal/example.com: All modules are uptodate.\n" .
00080 "If there are available updates, it might produce the following output:\n" .
00081 "DRUPAL SITE CRITICAL - example.com @ /path/to/drupal/sites/example.com:\n" .
00082 "there are updates for admin_menu,drupal,image, see http://example.com/?q=admin/reports/updates for datails.\n" .
00083 "NOTE: If there is a site at sites/default, this command runs on site basis, although ou have only specified the Drupal installation."
00084 ),
00085 'options' => array(
00086 '--file' => "Path to release information file, this could be a (temp) file to avoid nrpe-socket timeouts.\n" .
00087 "It is also possible to supply path via URI, like http://updates.drupal.org/release-history/drupal/6.x.\n" .
00088 "NOTE: This option is only available for checking the Drupal installation."
00089 ),
00090 );
00091 $items['multi-moo'] = array(
00092 'aliases' => array('moo'),
00093 'callback' => 'multi_moo',
00094 'bootstrap' => DRUSH_BOOTSTRAP_DRUSH,
00095 );
00096 $items['multi-exec'] = array(
00097 'aliases' => array('mex'),
00098 'description' => 'Run a drush command on all sites in your multisite installation. Implemented drush commands are: \'cache clear\', \'cron\', \'update\', \'updatecode\', \'updatedb\', \'watchdog delete\', \'watchdog show\' and \'refresh\'.',
00099 'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_ROOT,
00100 'examples' => array(
00101 'drush -r /path/to/drupal multi-exec cron' => 'Run all cron hooks on all sites in your multisite installation.',
00102 'drush -r /path/to/drupal multi-exec variable-set --argument=\'site_offline 1\' --option=\'--nocolor\'' => 'Put all sites in maintenance mode without using color highlighting on log messages.',
00103 'drush -r /path/to/drupal multi-exec updatedb' => 'Execute the update.php process for all sites.',
00104 ),
00105 'options' => array(
00106 '--argument' => 'Argument to pass to drush command e.g. \'php\' as type for \'watchdog delete\' and \'watchdog show\'.',
00107 '--option' => 'Option to pass to drush command. or drush itself e.g. \--nocolor\' to suppress color highlighting on log messages.',
00108 ),
00109 'arguments' => array(
00110 'command' => 'The drush command to execute. For drush commands with blanks like \'watchdog show\' make sure to use single or double quotes. Mandatory.',
00111 ),
00112 );
00113 $items['multi-drupalupdate'] = array(
00114 'aliases' => array('mdr', 'drupalupdate'),
00115 'description' => 'Update your drupal installation to the current version minor release, if available.',
00116 'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_ROOT,
00117 'options' => array(
00118 '--sql-dump' => 'Calls multi_sql_dump for all sites before starting the drupalupdate. See "drush help multi sql dump" for options and details.',
00119 '--updatedb' => 'Put sites in maintenance mode before drupalupdate, execute updatedb and put sites back from maintenance mode after drupalupdate.',
00120 ),
00121 'examples' => array(
00122 'drush -r /path/to/drupal multi-drupalupdate' => 'Update your drupal installation to the recommended release.',
00123 'drush -r /path/to/drupal multi-drupalupdate --sql-dump --comment="before drupaldate" --update' =>
00124 'Runs a "multi-drupalupdate" on /path/to/drupal with making sql dumps of all sites with optional comment "before drupalupdate" for sql dump filenames and execution of "updatedb" afterwards',
00125 ),
00126 );
00127 $items['multi-site'] = array(
00128 'aliases' => array('msi', 'site'),
00129 'description' => 'Create a site in your drupal installation',
00130 'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_ROOT,
00131 'examples' => array(
00132 'drush -r /path/to/drupal multi-site example.com --create-directories=dir1,dir2,dir3' =>
00133 "Create the site 'example.com' within a settings.php,\n" .
00134 "a 'files', 'themes', 'modules' directory\n" .
00135 "and the additional directories 'dir1', 'dir2' and 'dir3' in /path/to/drupal/sites.",
00136 ),
00137 'options' => array(
00138 '--create-directories' => 'Comma seperated list of aditional directories.',
00139 ),
00140 'arguments' => array(
00141 'site-name' => 'Name of the site. Mandatory.',
00142 ),
00143 );
00144 $items['multi-create'] = array(
00145 'aliases' => array('mcr', 'create'),
00146 'description' => 'Create a multisite installation',
00147 'bootstrap' => DRUSH_BOOTSTRAP_DRUSH,
00148 'examples' => array(
00149 'drush multi-create /var/www --core=6.x' =>
00150 'Creates a Drupal 6 multisite installation in /var/www with creating the directories '.
00151 '6.x_backup, 6.x_profiles and 6.x_sites, in /var/www ' .
00152 'linked as sites and backup withing the drupal installation folder.',
00153 'drush multi-create /var/www --makefile=/path/to/makefile.make' =>
00154 'Creates a Drupal multisite installation in /var/www by using the supplied makefile' .
00155 ' at /path/to/makefile.make.',
00156 ),
00157 'options' => array(
00158
00159 '--makefile' => "Path to drush_make makefile. \nThe makefile must contain the core specification (eg. \"core = 6.x\" for Drupal 6)\nand Drupal as project (projects[] = drupal).",
00160 '--core' => "Drupal core version (5.x, 6.x). \nTakes default from pm_parse_project_version(array('drupal') if not supplied.",
00161 ),
00162 'arguments' => array(
00163 '/path/to/installation' => 'Path to where drupal should be installed. Mandatory',
00164 ),
00165 );
00166 $items['multi-sql-dump'] = array(
00167 'aliases' => array('msq'),
00168 'description' => 'Exports the Drupal DB as SQL for all sites. File pattern is ${uri} and a \'_date(\'Y-m-d\TH:i\').sql suffix.',
00169 'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_ROOT,
00170 'examples' => array(
00171 'drush -r /path/to/drupal multi-sql-dump --bzip2 --comment=before-update-to-6.15 --target=$HOME/db_backups' =>
00172 'Run \'sql dump\' on all sites with comment \'before-update-to-6.15\' as comment for each result file. ' .
00173 'The result files are bzip compressed and stored in \'db_backups\' in your home dirctory.' .
00174 "\nDump name schema:\n'\${uri}'_before-update-to-6.1_{date('Y-m-d\TH:i')}.sql.bz2'."
00175 ),
00176 'options' => array(
00177 '--target' => 'Absolute Path to the directory where to store the sql dumps. Default /tmp.',
00178 '--dump-type' => "Arguments:\n" .
00179 "\"full\" Creates one file for all tables (default).\n" .
00180 '"tables" Creates for each table within each database a seperate file.',
00181 '--comment' => 'Comment for filename. May contain alphanumics, \'-\' and \'_\'.',
00182 '--datetime' => 'Adds an optional datetime string to each result file. Format YYYY-MM-DDThh:mm',
00183
00184
00185 '--bzip2' => 'Use bzip2 for compression of each sql dump.',
00186 ),
00187 );
00188 return $items;
00189 }
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200 function multi_status() {
00201
00202
00203 $status = drush_core_status();
00204
00205
00206 $sites = array();
00207 $sites = _multi_scan_sites();
00208
00209
00210 $status .= sprintf(" %-18s: %s\n", 'Site Counter', count($sites));
00211
00212
00213 if(count($sites) != 0 ){
00214 $status .= sprintf(" %-18s: %s\n", 'Sites', implode(' ', $sites));
00215 }
00216
00217
00218 if (count($versions = _multi_previous_installations()) != 0) {
00219 $status .= sprintf(" %-18s: %s\n", 'Prev.Installations', implode(' ', $versions));
00220 }
00221
00222
00223 if ($recommended_version = _multi_recommended_version(
00224 drush_drupal_major_version(), 'drupal', TRUE)
00225 ) {
00226 if (drush_drupal_version() < $recommended_version) {
00227 $status .= sprintf(" %-18s: \033[31m\033[1m%s\033[0m\n",
00228 'Drupal Core', $recommended_version . " available"
00229 );
00230 }
00231 else {
00232 $status .= sprintf(" %-18s: %s\n", 'Drupal Core', 'Uptodate');
00233 }
00234 }
00235 else {
00236 $status .= sprintf(" %-18s: \033[31m\033[1m%s\033[0m\n",
00237 'Drupal core status', $recommended_version . 'Unknown'
00238 );
00239 }
00240 drush_print($status);
00241 }
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251 function multi_nagios() {
00252
00253
00254 (drush_get_option('uri')) ? $uri = drush_get_option('uri') : $uri = drush_get_option('l');
00255
00256 if (!empty($uri)) {
00257 if (_multi_check_site($uri)) {
00258
00259 return _multi_nagios_site();
00260 }
00261 }
00262 else {
00263
00264 return _multi_nagios_root();
00265 }
00266 }
00267
00268
00269
00270
00271
00272
00273 function multi_moo() {
00274
00275 $cowsay = "\n ------------\n";
00276 $cowsay .= "< i <3 drush >\n";
00277 $cowsay .= " ------------\n";
00278 $cowsay .= " \ ^__^\n";
00279 $cowsay .= " \ (oo)\_______\n";
00280 $cowsay .= " (__)\ )\/\\\n";
00281 $cowsay .= " ||----w |\n";
00282 $cowsay .= " || ||\n";
00283 $cowsay .= "This drush has super cow powers!";
00284 drush_print($cowsay);
00285 }
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305 function drush_multi_sql_dump_validate() {
00306
00307
00308 if (in_array('--bzip2', $argv = $GLOBALS['argv'])) {
00309 drush_set_option('--bzip2', TRUE);
00310 }
00311
00312
00313 if (in_array('--datetime', $argv = $GLOBALS['argv'])) {
00314
00315 $datetime = drush_get_option('datetime');
00316 if (isset($datetime)) {
00317 drush_set_option('datetime', '_' . date('Y-m-d\TH:i')) ;
00318 }
00319
00320 }
00321
00322
00323 $target = drush_get_option('target');
00324 if (!empty($target)) {
00325 if (!is_dir($target)) {
00326 return drush_set_error('MULTI_TARGET_IS_NOT_A_DIRECTORY', 'Supplied argument for target is not a directory. Aborting.');
00327 }
00328
00329
00330 if (!is_writable($target)) {
00331 return drush_set_error('MULTI_TARGET_NOT_WRITABLE',
00332 dt('Directory !dir is not writable. Aborting.', array('!dir' => $target))
00333 );
00334 }
00335 }
00336 else {
00337
00338 drush_set_option('target', '/tmp');
00339 }
00340
00341
00342 $comment = drush_get_option('comment');
00343 if (isset($comment) && !preg_match("/^[a-zA-Z0-9\-_]{1,}$/", $comment)) {
00344 return drush_set_error('MULTI_INVALID_COMMENT_ARGUMENT',
00345 dt('Invalid argument for comment, only alphanumerics, "-" and "_" allowed. Aborting.')
00346 );
00347 }
00348
00349
00350 $dump_type = drush_get_option('dump-type','full');
00351
00352 $dump_types = array('full','tables');
00353 if (!in_array($dump_type, $dump_types )) {
00354 return drush_set_error('MULTI_INVALID_DUMP_TYPE_ARGUMENT',
00355 dt('Invalid argument for dump-type. Aborting.')
00356 );
00357 }
00358 }
00359
00360
00361
00362
00363 function drush_multi_sql_dump() {
00364
00365 $sites = array();
00366 $sites = _multi_scan_sites();
00367
00368 $dump_type = drush_get_option('dump-type', 'full');
00369
00370 $datetime = drush_get_option('datetime');
00371 $comment = drush_get_option('comment');
00372 $target = drush_get_option('target');
00373
00374
00375
00376
00377 if ($dump_type == 'full') {
00378
00379 foreach ($sites as $site) {
00380 drush_set_option('uri', $site);
00381 drush_bootstrap_max();
00382 $db_spec = _drush_sql_get_db_spec();
00383 drush_bootstrap_validate(DRUSH_BOOTSTRAP_DRUSH);
00384
00385
00386 $result_file = $target . '/' . $site . $datetime . $comment . '.sql';
00387
00388
00389 drush_set_option('result-file', $result_file);
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402 $exec = drush_sql_dump($db_spec);
00403 if (drush_op('system', $exec) == 0) {
00404 drush_log(
00405 dt('SQL dump for site !site, database !database saved in !file.',
00406 array(
00407 '!site' => $site,
00408 '!database' => $db_spec['database'],
00409 '!file' => $result_file
00410 )
00411 ),
00412 'success'
00413 );
00414 if (drush_get_option('--bzip2')) {
00415
00416 if (is_file($result_file . '.bz2')){
00417 drush_shell_exec('rm '. $result_file . '.bz2');
00418 drush_log(
00419 dt('Overwriting existing file !file',
00420 array('!file' => $result_file . '.bz2')
00421 ),
00422 'success'
00423 );
00424 }
00425 if (drush_shell_exec("bzip2 \"$result_file\"")) {
00426 drush_log(dt('Compressed !file using bzip2.',
00427 array('!file' => $result_file)),
00428 'success'
00429 );
00430 }
00431 }
00432 }
00433 }
00434 }
00435
00436 else {
00437
00438 foreach ($sites as $site) {
00439 drush_set_option('uri', $site);
00440 drush_bootstrap_max();
00441 $db_spec = _drush_sql_get_db_spec();
00442
00443
00444 $exec = 'echo "SHOW TABLES"|';
00445 $exec.= 'mysql -u' . $db_spec['username'];
00446 $exec.= ' -p'. $db_spec['password'];
00447 $exec.= ' '. $db_spec['database'];
00448 $output = shell_exec($exec);
00449
00450 $tables = array();
00451 $tables = explode("\n", $output);
00452
00453 unset($tables[0]);
00454
00455 unset($tables[sizeof($tables)]);
00456
00457
00458 foreach($tables as $table) {
00459
00460
00461 $result_file = $target . '/' . $site . '.' . $table . $datetime . $comment . '.sql';
00462
00463
00464 $exec = 'mysqldump -u' . $db_spec['username'];
00465 $exec.= ' -p'. $db_spec['password'];
00466 $exec.= ' '. $db_spec['database'] .' ' . $table;
00467
00468 if (drush_shell_exec($exec . '>' . $result_file)) {
00469 drush_log(
00470 dt('SQL dump for site !site, datebase !database, table !table saved in !file.',
00471 array(
00472 '!site' => $site,
00473 '!database' => $db_spec['database'],
00474 '!table' => $table,
00475 '!file' => $result_file
00476 )
00477 ),
00478 'success'
00479 );
00480 if (drush_get_option('--bzip2')) {
00481
00482 if (is_file($result_file . '.bz2')){
00483 drush_shell_exec('rm '. $result_file . '.bz2');
00484 drush_log(
00485 dt('Overwriting existing file !file',
00486 array('!file' => $result_file . '.bz2')
00487 ),
00488 'notice'
00489 );
00490 }
00491 if (drush_shell_exec("bzip2 \"$result_file\"")) {
00492 drush_log(dt('Compressed !file using bzip2.',
00493 array('!file' => $result_file)),
00494 'success'
00495 );
00496 }
00497 }
00498 }
00499 }
00500 }
00501 }
00502 }
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516 function drush_multi_exec_validate ($command) {
00517
00518 if (empty($command)) {
00519 return drush_set_error('MULTI_DRUSH_EXEC_MISSING_DRUSH_COMMAND',
00520 dt('Missing drush-command. Aborting,')
00521 );
00522 }
00523
00524
00525 $commands = array(
00526 'cache-clear', 'cc',
00527 'pm-refresh', 'rf',
00528 'pm-update', 'up',
00529 'pm-updatecode', 'upc',
00530 'pm-download', 'dl',
00531 'pm-enable', 'en',
00532 'pm-disable', 'dis',
00533 'pm-uninstall',
00534 'statusmodules', 'sm',
00535 'watchdog-show', 'ws',
00536 'watchdog-delete', 'wd-del',
00537 'sql-query', 'sqlq',
00538 'variable-set', 'vset',
00539 'variable-get', 'vget',
00540 'variable-delete', 'vdel',
00541 'updatedb', 'updb',
00542 'cron', 'eval', 'script',
00543 );
00544
00545 if (!in_array($command, $commands)) {
00546 return drush_set_error('MULTI_DRUSH_EXEC_UNKNOWN_DRUSH_COMMAND',
00547 dt('Unknown drush-command. Aborting,')
00548 );
00549 }
00550 }
00551
00552
00553
00554
00555
00556 function drush_multi_exec($command) {
00557
00558
00559
00560
00561
00562
00563 $drush = DRUSH_COMMAND;
00564
00565
00566 $root = ' -r ' . drush_get_context('DRUSH_DRUPAL_ROOT');
00567
00568
00569 $uri = ' -l ';
00570
00571
00572 $command = ' ' . $command;
00573
00574
00575
00576 $yes = ' -y';
00577
00578
00579 $arg = ' ' . drush_get_option('argument');
00580
00581
00582 $opt = ' ' . drush_get_option('option');
00583
00584 $sites = array();
00585 $sites = _multi_scan_sites();
00586
00587 foreach ($sites as $site) {
00588 $cmd = $drush . $yes . $root . $uri . $site . $command . $arg . $opt;
00589 drush_shell_exec($cmd);
00590
00591 foreach (drush_shell_exec_output() as $line) {
00592 drush_print($line);
00593 }
00594 }
00595 }
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608 function drush_multi_create_validate($destination) {
00609
00610
00611 if (!$destination) {
00612 return drush_set_error('MULTI_MISSING_DESTINATION',
00613 dt('Missing argument for destination. Aborting'));
00614 }
00615 else if (!is_dir($destination)) {
00616 return drush_set_error('MULTI_INVALID_DESTINATION',
00617 dt('Invalid argument for destination, !destination is no directory. Aborting',
00618 array('!destination' => $destination)
00619 )
00620 );
00621 }
00622 else if (!is_writable($destination)){
00623 return drush_set_error('MULTI_DESTINATION_NOT_WRITABLE',
00624 dt('Destination !destination is not writable. Aborting',
00625 array('!destination' => realpath($destination))
00626 )
00627 );
00628 }
00629
00630
00631 $makefile = drush_get_option('makefile');
00632 if ($makefile) {
00633 if (!is_file($makefile)) {
00634 return drush_set_error('MULTI_INVALID_MAKEFILE',
00635 dt('Invalid argument for makefile, file !makefile does not exist. Aborting',
00636 array('!makefile' => $makefile)
00637 )
00638 );
00639 }
00640 drush_set_option('makefile', realpath($makefile));
00641
00642 if (!drush_is_command('make')) {
00643 return drush_set_error('MULTI_MAKE_UNAVAILABLE', 'Could not find drush_make');
00644 }
00645 $core = FALSE;
00646 $parsed_makefile = drush_make_parse_info_file($makefile);
00647 $core = (int) $parsed_makefile['core'];
00648
00649 if (!$core) {
00650 return drush_set_error('MULTI_MAKE_NO_CORE', 'Core must be supplied in the makefile. Aborting.');
00651 }
00652
00653 drush_set_option('core', $core);
00654 if (!in_array('drupal', $parsed_makefile['projects'])){
00655 return drush_set_error('MULTI_MAKE_NO_DRUPAL','Drupal must be supplied in the makefile. Aborting.');
00656 }
00657 }
00658
00659 else {
00660 $core = (int)drush_get_option('core');
00661
00662 if (!$core) {
00663 $parsed_version = array();
00664 $parsed_version = pm_parse_project_version(array('drupal'));
00665 $recommended_core = ((int)$parsed_version['drupal']['drupal_version']);
00666 drush_set_option('core', $recommended_core);
00667 }
00668
00669 else if (!_multi_check_project($core)) {
00670 return drush_set_error('MULTI_INVALID_MAJORVERSION', dt('Invalid argument for major-version. Aborting'));
00671 }
00672 }
00673 }
00674
00675
00676
00677
00678
00679 function drush_multi_create($destination) {
00680
00681
00682 $destination = realpath($destination);
00683
00684
00685 $core = drush_get_option('core');
00686 if (!$recommended_version = _multi_recommended_version($core)) {
00687 return $recommended_version;
00688 }
00689 $recommended_version = 'drupal-' . strtolower($recommended_version['version']);
00690
00691
00692 if ($makefile = rtrim(drush_get_option('makefile'), '/')) {
00693 if (!$recommended_version = _multi_recommended_version($core)) {
00694 return $recommended_version;
00695 }
00696 $recommended_version = 'drupal-' . strtolower($recommended_version['version']);
00697
00698 drush_invoke('make', $makefile, $destination . '/' . $recommended_version);
00699 }
00700
00701 else {
00702 drush_set_option('package-handler', 'wget');
00703 drush_set_option('destination', $destination);
00704 drush_set_context('DRUSH_NOCOLOR', 1);
00705 drush_invoke('pm-download', $recommended_version);
00706 drush_set_context('DRUSH_NOCOLOR', 0);
00707 }
00708
00709
00710 if (!drush_op('chdir', $destination)) {
00711 return drush_set_error('MULTI_COULD_NOT_CHANGE_TO_DESTINATION',
00712 dt('Could not change to !destination. Aborting.',
00713 array('!destination' => $destination)
00714 )
00715 );
00716 }
00717
00718
00719 if (!drush_op('mkdir', $core . '.x_backup')) {
00720 return drush_set_error('MULTI_COULD_NOT_CREATE_BACKUP_DIR',
00721 dt('Could not create backup directory "!pwd/!core.x_backup". Aborting.',
00722 array('!pwd' => drush_cwd(), '!core' => $core)
00723 )
00724 );
00725 }
00726
00727
00728 if (!drush_op('mkdir', $core . '.x_sites')) {
00729 return drush_set_error('MULTI_COULD_NOT_CREATE_SITES_DIR',
00730 dt('Could not create sites directory "!pwd/!core.x_sites". Aborting.',
00731 array('!pwd' => drush_cwd(), '!core' => $core)
00732 )
00733 );
00734 }
00735
00736 $dir = realpath($destination . '/' . $recommended_version . '/sites');
00737
00738
00739 $exec = 'cp -r ' . $dir . '/* ' . $core . '.x_sites';
00740 if (!drush_shell_exec($exec)) {
00741 return drush_set_error('MULTI_COULD_NOT_COPY_SITES_DEFAULT_DIR',
00742 dt('Could not copy !dir to !target',
00743 array('!dir' => $dir . '/default', '!target' => $core . '.x_sites')
00744 )
00745 );
00746 }
00747
00748
00749
00750 $exec = 'mv ' . $dir . ' ' . $dir . '.bak';
00751 if (!drush_shell_exec($exec)) {
00752 return drush_set_error('MULTI_COULD_NOT_RENAME_SITES_DIR',
00753 dt('Could not rename sites directory !dir to !target',
00754 array('!dir' => $dir, '!target' => $dir . '.bak')
00755 )
00756 );
00757 }
00758
00759
00760 if (!drush_op('mkdir', $core . '.x_profiles')) {
00761 return drush_set_error('MULTI_COULD_NOT_CREATE_PROFILES_DIR',
00762 dt('Could not create profiles directory "!pwd/!core.x_profiles". Aborting.',
00763 array('!pwd' => drush_cwd(),
00764 '!core' => $core)
00765 )
00766 );
00767 }
00768
00769 $dir = realpath($destination . '/' . $recommended_version . '/profiles');
00770
00771
00772 $exec = 'cp -r ' . $dir . '/* ' . $core . '.x_profiles';
00773 if (!drush_shell_exec($exec)) {
00774 return drush_set_error('MULTI_COULD_NOT_COPY_PROFILES_DEFAULT_DIR',
00775 dt('Could not copy !dir to !target',
00776 array('!dir' => $dir . '/default', '!target' => $core . '.x_profiles')
00777 )
00778 );
00779 }
00780
00781
00782
00783 $exec = 'mv ' . $dir . ' ' . $dir . '.bak';
00784 if (!drush_shell_exec($exec)) {
00785 return drush_set_error('MULTI_COULD_NOT_RENAME_DEFAULT_DIR',
00786 dt('Could not rename profiles directory !dir to !target',
00787 array('!dir' => $dir, '!target' => $dir . '.bak')
00788 )
00789 );
00790 }
00791
00792
00793 if(drush_op('chdir', realpath($destination . '/' . $recommended_version))) {
00794
00795 $sites_dir = _multi_relative_path($destination . '/' . $core .'.x_sites');
00796 if (!drush_op('symlink', $sites_dir, 'sites')) {
00797 return drush_set_error('MULTI_COULD_NOT_CREATE_SITES_SYMLINK',
00798 dt('symlink(): Unable to create symlink from !source into !target for sites-directory.',
00799 array('!source' => $sites_dir, '!target' => getcwd() .'/sites')
00800 )
00801 );
00802 }
00803
00804 $backup_dir = _multi_relative_path($destination . '/' . $core .'.x_backup');
00805 if (!drush_op('symlink', $backup_dir, 'backup')) {
00806 return drush_set_error('MULTI_COULD_NOT_CREATE_BACKUP_SYMLINK',
00807 dt('symlink(): Unable to create relative symlink from !target into !target for backup-directory.',
00808 array('!target' => $sites_dir, '!target' => getcwd())
00809 )
00810 );
00811 }
00812
00813 $profiles_dir = _multi_relative_path($destination . '/' . $core .'.x_profiles');
00814 if (!drush_op('symlink', $profiles_dir, 'profiles')) {
00815 return drush_set_error('MULTI_COULD_NOT_CREATE_PROFILES_SYMLINK',
00816 dt('symlink(): Unable to create relative symlink from !target into !target for backup-directory.',
00817 array('!target' => $profiles_dir, '!target' => getcwd())
00818 )
00819 );
00820 }
00821 }
00822 else {
00823 return drush_set_error('MULTI_COULD_NOT_CREATE_SITES_SYMLINK',
00824 dt('symlink(): Unable to create relative symlink from !target into !target for backup-directory.',
00825 array('!source' => $sites_dir, '!target' => getcwd())
00826 )
00827 );
00828 }
00829
00830 drush_op('chdir', $destination);
00831
00832
00833 if (!drush_op('symlink', $recommended_version, $core . '.x')) {
00834 return drush_set_error('MULTI_COULD_NOT_SYMLINK_DOKUMENT_ROOT',
00835 dt('symlink(): Could not create symlink from !drupal to !major.x for DOCUMENT_ROOT',
00836 array('!drupal' => $recommended_version, '!major' => $core)
00837 )
00838 );
00839 }
00840 }
00841
00842
00843
00844
00845 function drush_multi_create_rollback($destination) {
00846
00847 }
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862 function drush_multi_drupalupdate_validate () {
00863
00864
00865 if (!is_writable(realpath(rtrim(drush_get_context('DRUSH_DRUPAL_ROOT'),'/') . '/..'))) {
00866 drush_set_error('MULTI_DRUPALUPDATE_DESTINATION_NOT_WRITABLE',
00867 dt('\'!destination\' is not writable, check permission. Aborting.',
00868 array('!destination' => $dest)
00869 )
00870 );
00871 }
00872
00873 $drupal_root = rtrim(drush_get_context('DRUSH_DRUPAL_ROOT'),'/');
00874
00875
00876 if (is_link($drupal_root)) {
00877
00878 $path_pieces = explode('/', $drupal_root);
00879 $link_name = $path_pieces[count($path_pieces)-1];
00880
00881 drush_set_context('DRUPAL_ROOT_SYMLINK', $link_name);
00882
00883 drush_set_context('DRUSH_DRUPAL_ROOT', $drupal_root);
00884 }
00885 else {
00886 drush_set_error('MULTI_DRUPALUPDATE_DRUPAL_ROOT_IS_NO_SYMLINK',
00887 dt('Drupal root !drupal_root is not a symbolic link. Aborting.',
00888 array('!drupal_root' => $drupal_root)
00889 )
00890 );
00891 }
00892
00893
00894 if (!$recommended_version = _multi_recommended_version(drush_drupal_major_version())) {
00895
00896 return $recommended_version;
00897 }
00898 $recommended_version = 'drupal-' . strtolower($recommended_version['version']);
00899
00900 drush_set_context('DRUPAL_RECOMMENDED_VERSION', $recommended_version);
00901
00902
00903 if (_multi_current_version() == $recommended_version) {
00904 drush_print('Your drupal version is uptodate. Aborting');
00905 return MULTI_NOTHING_TO_DO;
00906 }
00907
00908
00909 if (in_array('--updatedb', $argv = $GLOBALS['argv'])) {
00910 drush_set_option('--updatedb', TRUE);
00911 }
00912
00913
00914 if (in_array('--sql-dump', $argv = $GLOBALS['argv'])) {
00915 drush_set_option('--sql-dump', TRUE);
00916 }
00917 }
00918
00919
00920
00921
00922
00923
00924
00925
00926 function drush_multi_pre_multi_drupalupdate() {
00927
00928 if (drush_get_option('--sql-dump')) {
00929 drush_set_option('option', '--nocolor');
00930 drush_invoke('multi-sql-dump');
00931 }
00932 if (drush_get_option('--updatedb')) {
00933
00934 drush_set_option('argument', 'site_offline 1');
00935 drush_set_option('option', '--nocolor');
00936 drush_invoke('multi-exec', 'variable-set');
00937 drush_unset_option('argument');
00938 drush_unset_option('option');
00939 }
00940 }
00941
00942
00943
00944
00945
00946
00947
00948
00949 function drush_multi_drupalupdate() {
00950
00951
00952 $drupal_root = drush_get_context('DRUSH_DRUPAL_ROOT');
00953 $link_name = drush_get_context('DRUPAL_ROOT_SYMLINK');
00954 $recommended_version = drush_get_context('DRUPAL_RECOMMENDED_VERSION');
00955 $version = drush_drupal_version();
00956 $dest = realpath($drupal_root . '/../');
00957
00958
00959 drush_set_option('destination', $dest);
00960 drush_set_option('package-handler', 'wget');
00961 drush_set_context('DRUSH_NOCOLOR', 1);
00962 drush_invoke('pm-download', $recommended_version);
00963 drush_set_context('DRUSH_NOCOLOR', 0);
00964
00965
00966
00967
00968 _multi_preserve_symlinks($drupal_root, $dest . '/' . $recommended_version);
00969
00970
00971 if (drush_op('chdir', '..')) {
00972
00973 if (!drush_op('unlink', $link_name)) {
00974 return drush_set_error('DRUSH_SM_COULD_NOT_UNLINK_DOKUMENT_ROOT',
00975 dt('unlink(): Could not unlink !doc_root.', array('!doc_root' => $link_name))
00976 );
00977 }
00978
00979 if (!drush_op('symlink', $recommended_version, $link_name)) {
00980 return drush_set_error('DRUSH_SM_COULD_NOT_SYMLINK_DOKUMENT_ROOT',
00981 dt('symlink(): Could not create symlink from !drupal to !link for DOCUMENT_ROOT.',
00982 array('!drupal' => $recommended_version, '!link' => $link_name)
00983 )
00984 );
00985 }
00986 }
00987
00988 else {
00989 return drush_set_error('DRUSH_SM_COULD_CHANGE_INTO_DRUPAL_PARENT',
00990 dt('chdir(): Could not change to parent of drupal directory.')
00991 );
00992 }
00993 }
00994
00995
00996
00997
00998 function drush_multi_drupalupdate_rollback() {
00999
01000 }
01001
01002
01003
01004
01005
01006
01007
01008
01009 function drush_multi_post_multi_drupalupdate() {
01010
01011 if (drush_get_option('--updatedb')) {
01012
01013 drush_set_option('option','--nocolor');
01014 drush_invoke('multi-exec', 'updatedb');
01015
01016 drush_set_option('argument', 'site_offline 0');
01017 drush_invoke('multi-exec', 'variable-set');
01018 drush_unset_option('option');
01019 drush_unset_option('argument');
01020 drush_log(dt('Drupalupdate finished.'), 'completed');
01021 }
01022 else {
01023 drush_log(dt('Drupalupdate finished, now you should run update.php for each site'), 'completed');
01024 }
01025 }
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039 function drush_multi_site_validate($site_name) {
01040
01041 if (!$site_name) {
01042 return drush_set_error('MULTI_SITE_MISSING_SITE_ARGUMENT',
01043 dt('Missing site argument.')
01044 );
01045 }
01046 else {
01047
01048 }
01049
01050 if($directories_option = drush_get_option('create-directories')) {
01051 $directories = array();
01052 $directories = explode(',', $directories_option);
01053 foreach ($directories as $directory) {
01054
01055 ltrim($directory, '/');
01056 }
01057 }
01058 }
01059
01060
01061
01062
01063
01064 function drush_multi_pre_multi_site($site_name) {
01065
01066 $sites_dir = rtrim(drush_get_context('DRUSH_DRUPAL_ROOT'),'/') . '/sites/';
01067 if (!is_writable($sites_dir)) {
01068 return drush_set_error('MULTI_SITE_SITES_DIR_NOT_WRITABLE',
01069 dt('Site directory \'!sites_dir\' is not writable.', array('!sites_dir' => $sites_dir))
01070 );
01071 }
01072 if (is_dir($sites_dir .'/' . $site_name)) {
01073 return drush_set_error('MULTI_SITE_SITE_DIR_ALREADY_EXISTS',
01074 dt('The supplied sitename !site_name already exists within !sites_dir. Aborting.',
01075 array(
01076 '!site_name' => $site_name,
01077 '!sites_dir' => $sites_dir
01078 )
01079 )
01080 );
01081 }
01082 }
01083
01084
01085
01086
01087
01088 function drush_multi_site($site_name) {
01089
01090 $sites_dir = rtrim(drush_get_context('DRUSH_DRUPAL_ROOT'),'/') . '/sites/';
01091 $site = $sites_dir . $site_name;
01092
01093
01094 if (!drush_op('mkdir', $site)) {
01095 drush_set_error('MULTI_SITE_COULD_NOT_CREATE_SITE_DIR',
01096 dt('Could not create site directory !dir.', array('!dir' => $site))
01097 );
01098 }
01099
01100
01101 if (!drush_op('chdir', $site)) {
01102 drush_set_error('MULTI_SITE_COULD_NOT_CWD',
01103 dt('Could not change to !dir.', array('!dir' => $site))
01104 );
01105 }
01106
01107
01108 switch (drush_drupal_major_version()){
01109 case '5':
01110
01111 $settings_src = $sites_dir . 'default/settings.php';
01112 if (!drush_op('copy', $settings_src, 'settings.php')) {
01113 drush_set_error('MULTI_SITE_COULD_NOT_COPY_DEFAULT_SETTINGS',
01114 dt('Could not copy !src to settings.php.', array('!src' => $settings_src))
01115 );
01116 }
01117 break;
01118 case '6':
01119 case '7':
01120
01121 $settings_src = $sites_dir . 'default/default.settings.php';
01122 if (!drush_op('copy', $settings_src, 'settings.php')) {
01123 drush_set_error('MULTI_SITE_COULD_NOT_COPY_DEFAULT_SETTINGS',
01124 dt('Could not copy !src to settings.php.', array('!src' => $settings_src))
01125 );
01126 }
01127 break;
01128 }
01129
01130 $directories = array();
01131
01132
01133 $directories[] = 'files';
01134 $directories[] = 'modules';
01135 $directories[] = 'themes';
01136
01137
01138 if($directories_option = drush_get_option('create-directories')) {
01139 $tmp = array();
01140 $tmp = explode(',', $directories_option);
01141 $directories = array_merge($directories, $tmp);
01142 }
01143
01144
01145 drush_op('mkdir', implode(' ', $directories), 0755, TRUE);
01146 }
01147
01148
01149
01150
01151
01152
01153 function drush_multi_post_multi_site($site_name){
01154
01155 $site_path = drush_get_context('DRUSH_DRUPAL_ROOT') . '/sites/' . $site_name;
01156
01157 $apache_user = drush_get_option('multi-apache-user');
01158 $apache_group = drush_get_option('multi-apache-group');
01159
01160 if ($apache_user){
01161 drush_op('chown', $site_path . '/settings.php', $apache_user);
01162 drush_op('chown', $site_path . '/files', $apache_user);
01163 }
01164 if ($apache_group){
01165 drush_op('chgrp', $site_path . '/settings.php', $apache_group);
01166 drush_op('chgrp', $site_path . '/files', $apache_group);
01167 }
01168 }
01169
01170
01171
01172
01173
01174 function drush_multi_site_rollback($site_name) {
01175 if (!drush_cmp_error('MULTI_SITE_COULD_NOT_CREATE_SITE_DIR')) {
01176 delete_dir(rtrim(drush_get_context('DRUSH_DRUPAL_ROOT'),'/') . '/sites/'. $site_name);
01177 }
01178 }
01179
01180