Skip to content

Instantly share code, notes, and snippets.

@theapi
Last active December 16, 2015 18:49
Show Gist options
  • Save theapi/5480927 to your computer and use it in GitHub Desktop.
Save theapi/5480927 to your computer and use it in GitHub Desktop.
<?php
/**
* @file
* drush command.
*/
/**
* Implementation of hook_drush_command().
*
* In this hook, you specify which commands your
* drush module makes available, what it does and
* description.
*
* Notice how this structure closely resembles how
* you define menu hooks.
*
* See `drush topic docs-commands` for a list of recognized keys.
*
* @return
* An associative array describing your command(s).
*/
function dennis_drush_command() {
$items = array();
// The 'dennis-syncl-db' command
$items['dennis-sync-db'] = array(
'description' => "Get a db",
'arguments' => array(
'site' => 'The site to download',
),
'options' => array(
'src' => array(
'description' => 'The src alias to sync from.',
'example-value' => '@kontraband_migration',
),
'no-cache' => 'Do not cache the sql-dump file.',
'updb' => 'Run update db after import.',
),
'examples' => array(
'drush d-db kontraband' => 'Downloads kontraband.',
),
'aliases' => array('d-db'),
'bootstrap' => DRUSH_BOOTSTRAP_DRUSH, // No bootstrap at all.
);
// The 'dennis-make-site' command
$items['dennis-make-site'] = array(
'description' => "Check out a repo",
'arguments' => array(
'site' => 'The repo',
),
'examples' => array(
'drush d-make kontraband' => 'Makes the kontraband repo.',
),
'aliases' => array('d-make'),
'bootstrap' => DRUSH_BOOTSTRAP_DRUSH, // No bootstrap at all.
);
$items['dennis-pre-sync-cleanup'] = array(
'description' => "Calls modules implementations of hook_dennis_sync_pre_cleanup",
);
$items['dennis-post-sync-cleanup'] = array(
'description' => "Calls modules implementations of hook_dennis_sync_post_cleanup",
);
return $items;
}
/**
* Implementation of hook_drush_help().
*
* This function is called whenever a drush user calls
* 'drush help <name-of-your-command>'. 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.
*
* @param
* A string with the help section (prepend with 'drush:')
*
* @return
* A string with the help text for your command.
*/
function dennis_drush_help($section) {
switch ($section) {
case 'drush:dennis-sync-db':
return dt("This command will download the db of the requested site.");
case 'drush:dennis-make-site':
return dt("This command will check out & make the repo.");
// 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:dennis:title':
return dt("Dennis 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:dennis:summary':
return dt("Automates your dennis workflows.");
}
}
/**
* This 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. However, the specified callback function must still begin
* with "drush_commandfile_" (e.g. 'callback' => "drush_example_foo_execute")
* if you want that all hook functions are still called (e.g.
* drush_example_pre_foo_execute, and so on).
*
* 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_dennis_sync_db($site, $src_alias = NULL) {
$args = drush_get_arguments();
$site = $args[1];
//TODO: What happens if more than one person is dumping the db at the same time?
// - does the dump get written to by everyone and get buggered?
$src_alias = drush_get_option('src', '@' . $site . '_live');
$arguments = array(
$src_alias,
'@' . $site,
);
//var_dump(drush_get_merged_options(), $arguments); exit;
// NB: --structure-tables-key=common requires drushrc.php (taken from example.drush.php)
$options = array(
'-y',
'--no-ordered-dump',
'--structure-tables-key=common',
'--create-db',
'--disable=cdn,memcache_admin',
'--vagrant',
);
if (drush_get_option('no-cache', FALSE)) {
$options[] = '--no-cache';
}
if (drush_get_option('updb', FALSE)) {
$options[] = '--updb';
}
drush_invoke_process('@' . $site, 'sql-sync', $arguments, $options);
}
/**
* Implementation of 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_dennis_sync_db_validate() {
$args = drush_get_arguments();
if (empty($args[1])) {
return drush_set_error('DENNIS_DRUSH', dt('What site?'));
}
}
/**
* Implement hook post sql sync.
*
*/
function drush_dennis_post_sql_sync($source = NULL, $destination = NULL) {
drush_invoke_process($destination, 'registry-rebuild');
//var_dump(drush_get_merged_options());
$site = str_replace('@', '', $destination);
// See if a site want to do post sync stuff before the default calls
drush_invoke_process($destination, 'dennis-pre-sync-cleanup');
$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));
}
drush_invoke_process($destination, 'solr-set-env-url', array('http://localhost:8080/solr3/solr3'));
// Set some variables
drush_invoke_process($destination, 'vset', array('varnish_control_terminal', '127.0.0.1:6082'));
drush_invoke_process($destination, 'vdel', array('googleanalytics-account'));
drush_invoke_process($destination, 'vset', array('file_public_path', 'sites/' . $site . '/files'));
drush_invoke_process($destination, 'cc', array('all'));
if (drush_get_option('updb')) {
// run update db
drush_print('---- Running updatedb ----', 2);
drush_invoke_process($destination, 'updatedb');
}
// See if a site want to do post sync stuff after the default calls
drush_invoke_process($destination, 'dennis-post-sync-cleanup');
drush_print();
drush_print("#");
drush_print('# Site should now be viewable at: http://' . $site . '.vm.didev.co.uk');
drush_print("#");
drush_print();
}
/**
*
*/
function drush_dennis_make_site($site) {
$args = drush_get_arguments();
$site = $args[1];
// TODO - nonkludgify
// currently a straightish port of the repo checkout part of downloadDb.sh
$exec = 'hg clone http://fogbugz.dennisinteractive.co.uk/kiln/Repo/Drupal-Sites/' . $site . '/0-1 /home/vagrant/repos/' . $site;
$exec_result = drush_op_system($exec);
$result = ($exec_result == 0);
if (!$result) {
drush_set_error('DRUSH_DENNIS_FAILED', dt("Could not clone repo for !site", array('!site' => $site)));
}
if (file_exists('/home/vagrant/repos/' . $site . '/site.make')) {
$arguments = array(
'/home/vagrant/repos/' . $site . '/site.make', // makefile
);
$options = array(
'-y',
'--working-copy',
'--no-gitinfofile',
'--no-core',
'--contrib-destination=.',
);
drush_invoke_process('@' . $site, 'make', $arguments, $options);
}
// setting.php etc
if (!file_exists('/home/vagrant/repos/' . $site . '/settings.php')) {
}
}
/**
* Implementation of 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_dennis_make_site_validate() {
$args = drush_get_arguments();
if (empty($args[1])) {
return drush_set_error('DENNIS_DRUSH', dt('What site?'));
}
}
function drush_dennis_pre_sync_cleanup() {
module_invoke_all('dennis_sync_pre_cleanup');
}
function drush_dennis_post_sync_cleanup() {
module_invoke_all('dennis_post_sync_cleanup');
}
/**
* Give a progress report of the sql import
* @param string $file
* @param string $import_command
*/
function drush_dennis_import_progress($file, $import_command) {
$size = filesize($file);
$bytes = 0;
$percent = 0;
$handle = popen($import_command, "w");
if (!$handle) {
echo "FAILED to open $import_command\n";
exit;
}
$sql_fp = fopen($file, 'r');
if (!$sql_fp) {
echo "FAILED to open $file\n";
exit;
}
echo "\nImporting: ";
while (!feof($sql_fp)) {
$contents = fread($sql_fp, 8192);
$bytes += 8192;
$current_precent = floor($bytes / $size * 100);
if ($current_precent > $percent) {
$percent = $current_precent;
echo $percent . "% ";
}
fwrite($handle, $contents);
}
echo "\n";
pclose($handle);
fclose($sql_fp);
}
/**
* Replacement for drush_op_system() used in sql_sync so that we can get a progress report from sql_sync
* @param string $import_exec
*/
function drush_dennis_sql_sync_op_system($import_exec) {
// To get the progress we need to pipe the sql into mysql via php php rather than a system call
// get the $pre_import_commands that may be getting piped into the mysql command
$piped_parts = explode('|', $import_exec);
if (isset($piped_parts[1])) {
$pre_import_commands = $piped_parts[0];
$cmd = trim($piped_parts[1]);
}
else {
$cmd = trim($piped_parts[0]);
}
// sql_sync uses '<' to import the sql file into mysql
$cmd_parts = explode('<', $cmd);
if (!isset($cmd_parts[1])) {
// not what's expected so use the original function
drush_op_system($import_exec);
return;
}
$file = trim($cmd_parts[1]);
$import_command = trim($cmd_parts[0]);
if (!empty($pre_import_commands)) {
// the command will have two db commands separated by a ';'
$cmd_parts = explode(';', $import_command);
if (!isset($cmd_parts[1])) {
// not what's expected so use the original function
drush_op_system($import_exec);
return;
}
$pre_command = trim($cmd_parts[0]);
$import_command = trim($cmd_parts[1]);
$import_exec = $pre_import_commands . ' | ' . $pre_command;
// do the pre commands
drush_op_system($import_exec);
}
// now do the import command with progress
drush_dennis_import_progress($file, $import_command);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment