| [ Index ] |
PHP Cross Reference of Drupal 6 (gatewave) |
[Summary view] [Print] [Text view]
1 <?php 2 // $Id: features.drush.inc,v 1.1.2.34 2010/07/29 23:47:48 yhahn Exp $ 3 4 /** 5 * @file 6 * Features module drush integration. 7 */ 8 9 /** 10 * Implementation of hook_drush_command(). 11 * 12 * @See drush_parse_command() for a list of recognized keys. 13 * 14 * @return 15 * An associative array describing your command(s). 16 */ 17 function features_drush_command() { 18 $items = array(); 19 20 $items['features-list'] = array( 21 'description' => "List all the available features for your site.", 22 'drupal dependencies' => array('features'), 23 'aliases' => array('fl', 'features'), 24 ); 25 $items['features-export'] = array( 26 'description' => "Export a feature from your site into a module.", 27 'arguments' => array( 28 'feature' => 'Feature name to export.', 29 ), 30 'drupal dependencies' => array('features'), 31 'aliases' => array('fe'), 32 ); 33 $items['features-update'] = array( 34 'description' => "Update a feature module on your site.", 35 'arguments' => array( 36 'feature' => 'A space delimited list of features.', 37 ), 38 'drupal dependencies' => array('features'), 39 'aliases' => array('fu'), 40 ); 41 $items['features-update-all'] = array( 42 'description' => "Update all feature modules on your site.", 43 'arguments' => array( 44 'feature_exclude' => 'A space-delimited list of features to exclude from being updated.', 45 ), 46 'drupal dependencies' => array('features'), 47 'aliases' => array('fu-all', 'fua'), 48 ); 49 $items['features-revert'] = array( 50 'description' => "Revert a feature module on your site.", 51 'arguments' => array( 52 'feature' => 'A space delimited list of features.', 53 ), 54 'options' => array( 55 '--force' => "Force revert even if Features assumes components' state are default.", 56 ), 57 'drupal dependencies' => array('features'), 58 'aliases' => array('fr'), 59 ); 60 $items['features-revert-all'] = array( 61 'description' => "Revert all enabled feature module on your site.", 62 'arguments' => array( 63 'feature_exclude' => 'A space-delimited list of features to exclude from being reverted.', 64 ), 65 'options' => array( 66 '--force' => "Force revert even if Features assumes components' state are default.", 67 ), 68 'drupal dependencies' => array('features'), 69 'aliases' => array('fr-all', 'fra'), 70 ); 71 $items['features-diff'] = array( 72 'description' => "Show the difference between the default and overridden state of a feature.", 73 'arguments' => array( 74 'feature' => 'The feature in question.', 75 ), 76 'drupal dependencies' => array('features', 'diff'), 77 'aliases' => array('fd'), 78 ); 79 80 return $items; 81 } 82 83 /** 84 * Implementation of hook_drush_help(). 85 */ 86 function features_drush_help($section) { 87 switch ($section) { 88 case 'drush:features': 89 return dt("List all the available features for your site."); 90 case 'drush:features-export': 91 return dt("Export a feature from your site into a module."); 92 case 'drush:features-update': 93 return dt("Update a feature module on your site."); 94 case 'drush:features-update-all': 95 return dt("Update all feature modules on your site."); 96 case 'drush:features-revert': 97 return dt("Revert a feature module on your site."); 98 case 'drush:features-revert-all': 99 return dt("Revert all enabled feature module on your site."); 100 case 'drush:features-revert': 101 return dt("Revert a feature module on your site."); 102 case 'drush:features-diff': 103 return dt("Show a diff of a feature module."); 104 } 105 } 106 107 /** 108 * Get a list of all feature modules. 109 */ 110 function drush_features_list() { 111 module_load_include('inc', 'features', 'features.export'); 112 $rows = array(array(dt('Name'), dt('Feature'), dt('Status'), dt('State'))); 113 foreach (features_get_features(NULL, TRUE) as $k => $m) { 114 switch (features_get_storage($m->name)) { 115 case FEATURES_DEFAULT: 116 case FEATURES_REBUILDABLE: 117 $storage = ''; 118 break; 119 case FEATURES_OVERRIDDEN: 120 $storage = dt('Overridden'); 121 break; 122 case FEATURES_NEEDS_REVIEW: 123 $storage = dt('Needs review'); 124 break; 125 } 126 $rows[] = array( 127 $m->info['name'], 128 $m->name, 129 $m->status ? dt('Enabled') : dt('Disabled'), 130 $storage 131 ); 132 } 133 drush_print_table($rows, TRUE); 134 } 135 136 /** 137 * Create a feature module based on a list of components. 138 */ 139 function drush_features_export() { 140 $args = func_get_args(); 141 142 if (count($args) == 1) { 143 // Assume that the user intends to create a module with the same name as the 144 // "value" of the component. 145 list($source, $component) = explode(':', $args[0]); 146 $stub = array($source => array($component)); 147 _drush_features_export($stub, $component); 148 } 149 elseif (count($args) > 1) { 150 // Assume that the user intends to create a new module based on a list of 151 // components. First argument is assumed to be the name. 152 $name = array_shift($args); 153 $stub = array(); 154 foreach ($args as $v) { 155 list($source, $component) = explode(':', $v); 156 $stub[$source][] = $component; 157 } 158 _drush_features_export($stub, array(), $name); 159 } 160 else { 161 $rows = array(array(dt('Available sources'))); 162 foreach (features_get_components(TRUE) as $component => $info) { 163 if ($options = features_invoke($component, 'features_export_options')) { 164 foreach ($options as $key => $value) { 165 $rows[] = array($component .':'. $key); 166 } 167 } 168 } 169 drush_print_table($rows, TRUE); 170 } 171 } 172 173 /** 174 * Update an existing feature module. 175 */ 176 function drush_features_update() { 177 if ($args = func_get_args()) { 178 foreach ($args as $module) { 179 if (($feature = feature_load($module, TRUE)) && module_exists($module)) { 180 _drush_features_export($feature->info['features'], $feature->info['dependencies'], $feature->name, dirname($feature->filename)); 181 } 182 else if ($feature) { 183 _features_drush_set_error($module, 'FEATURES_FEATURE_NOT_ENABLED'); 184 } 185 else { 186 _features_drush_set_error($module); 187 } 188 } 189 } 190 else { 191 // By default just show contexts that are available. 192 $rows = array(array(dt('Available features'))); 193 foreach (features_get_features(NULL, TRUE) as $name => $info) { 194 $rows[] = array($name); 195 } 196 drush_print_table($rows, TRUE); 197 } 198 } 199 200 /** 201 * Update all enabled features. Optionally pass in a list of features to 202 * exclude from being updated. 203 */ 204 function drush_features_update_all() { 205 $features_to_update = array(); 206 $features_to_exclude = func_get_args(); 207 foreach (features_get_features() as $module) { 208 if ($module->status && !in_array($module->name, $features_to_exclude)) { 209 $features_to_update[] = $module->name; 210 } 211 } 212 drush_print(dt('The following modules will be updated: !modules', array('!modules' => implode(', ', $features_to_update)))); 213 if (drush_confirm(dt('Do you really want to continue?'))) { 214 foreach ($features_to_update as $module_name) { 215 drush_backend_invoke('features-update '. $module_name); 216 } 217 } 218 else { 219 drush_die('Aborting.'); 220 } 221 } 222 223 /** 224 * Write a module to the site dir. 225 * 226 * @param $requests 227 * An array of the context requested in this export. 228 * @param $module_name 229 * Optional. The name for the exported module. 230 */ 231 function _drush_features_export($stub, $dependencies, $module_name = NULL, $directory = NULL) { 232 $root = drush_get_option(array('r', 'root'), drush_locate_root()); 233 if ($root) { 234 $directory = isset($directory) ? $directory : 'sites/all/modules/' . $module_name; 235 if (is_dir($directory)) { 236 drush_print(dt('Module appears to already exist in !dir', array('!dir' => $directory))); 237 if (!drush_confirm(dt('Do you really want to continue?'))) { 238 drush_die('Aborting.'); 239 } 240 } 241 else { 242 drush_op('mkdir', $directory); 243 } 244 if (is_dir($directory)) { 245 drupal_flush_all_caches(); 246 module_load_include('inc', 'features', 'features.export'); 247 $export = features_populate($stub, $dependencies, $module_name); 248 if (!feature_load($module_name)) { 249 $export['name'] = $module_name; 250 } 251 $files = features_export_render($export, $module_name, TRUE); 252 foreach ($files as $extension => $file_contents) { 253 if (!in_array($extension, array('module', 'info'))) { 254 $extension .= '.inc'; 255 } 256 drush_op('file_put_contents', "{$directory}/{$module_name}.$extension", $file_contents); 257 } 258 drush_log(dt("Created module: !module in !directory", array('!module' => $module_name, '!directory' => $directory)), 'ok'); 259 } 260 else { 261 drush_die(dt('Couldn\'t create directory !directory', array('!directory' => $directory))); 262 } 263 } 264 else { 265 drush_die(dt('Couldn\'t locate site root')); 266 } 267 } 268 269 /** 270 * Revert a feature to it's code definition. 271 */ 272 function drush_features_revert() { 273 if ($args = func_get_args()) { 274 module_load_include('inc', 'features', 'features.export'); 275 features_include(); 276 277 // Determine if revert should be forced. 278 $force = drush_get_option('force'); 279 foreach ($args as $module) { 280 if (($feature = feature_load($module, TRUE)) && module_exists($module)) { 281 282 $components = array(); 283 // Forcefully revert all components of a feature. 284 if ($force) { 285 foreach (array_keys($feature->info['features']) as $component) { 286 if (features_hook($component, 'features_revert')) { 287 $components[] = $component; 288 } 289 } 290 } 291 // Only revert components that are detected to be Overridden/Needs review. 292 else { 293 $states = features_get_component_states(array($feature->name), FALSE); 294 foreach ($states[$feature->name] as $component => $state) { 295 if (in_array($state, array(FEATURES_OVERRIDDEN, FEATURES_NEEDS_REVIEW)) && features_hook($component, 'features_revert')) { 296 $components[] = $component; 297 } 298 } 299 } 300 301 if (empty($components)) { 302 drush_log(dt('Current state already matches defaults, aborting.'), 'ok'); 303 } 304 else { 305 foreach ($components as $component) { 306 if (drush_confirm(dt('Do you really want to revert !component?', array('!component' => $component)))) { 307 features_revert(array($module => array($component))); 308 drush_log(dt('Reverted !component.', array('!component' => $component)), 'ok'); 309 } 310 else { 311 drush_log(dt('Skipping !component.', array('!component' => $component)), 'ok'); 312 } 313 } 314 } 315 } 316 else if ($feature) { 317 _features_drush_set_error($module, 'FEATURES_FEATURE_NOT_ENABLED'); 318 } 319 else { 320 _features_drush_set_error($module); 321 } 322 } 323 } 324 else { 325 drush_features_list(); 326 return; 327 } 328 } 329 330 /** 331 * Revert all enabled features to their definitions in code. Optionally pass in 332 * a list of features to exclude from being reverted. 333 */ 334 function drush_features_revert_all() { 335 $features_to_revert = array(); 336 $features_to_exclude = func_get_args(); 337 foreach (features_get_features() as $module) { 338 if ($module->status && !in_array($module->name, $features_to_exclude)) { 339 $features_to_revert[] = $module->name; 340 } 341 } 342 drush_print(dt('The following modules will be reverted: !modules', array('!modules' => implode(', ', $features_to_revert)))); 343 if (drush_confirm(dt('Do you really want to continue?'))) { 344 foreach ($features_to_revert as $module_name) { 345 drush_backend_invoke('features-revert '. $module_name); 346 } 347 } 348 else { 349 drush_die('Aborting.'); 350 } 351 } 352 353 /** 354 * Show the diff of a feature module. 355 */ 356 function drush_features_diff() { 357 if (!$args = func_get_args()) { 358 drush_features_list(); 359 return; 360 } 361 $module = $args[0]; 362 $feature = feature_load($module); 363 if (!module_exists($module)) { 364 drush_log(dt('No such feature is enabled: ' . $module), 'error'); 365 return; 366 } 367 module_load_include('inc', 'features', 'features.export'); 368 $overrides = features_detect_overrides($feature); 369 if (empty($overrides)) { 370 drush_log(dt('Feature is in its default state. No diff needed.'), 'ok'); 371 return; 372 } 373 module_load_include('php', 'diff', 'DiffEngine'); 374 375 if (!class_exists('DiffFormatter')) { 376 if (drush_confirm(dt('It seems that the Diff module is not available. Would you like to download and enable it?'))) { 377 // Download it if it's not already here. 378 $project_info = drush_get_projects(); 379 if (empty($project_info['diff']) && !drush_backend_invoke('dl diff')) { 380 return drush_set_error(dt('Diff module could not be downloaded.')); 381 } 382 383 if (!drush_backend_invoke('en diff')) { 384 return drush_set_error(dt('Diff module could not be enabled.')); 385 } 386 } 387 else { 388 return drush_set_error(dt('Diff module is not enabled.')); 389 } 390 // If we're still here, now we can include the DiffEngine again. 391 module_load_include('php', 'diff', 'DiffEngine'); 392 } 393 394 $formatter = new DiffFormatter(); 395 $formatter->leading_context_lines = 2; 396 $formatter->trailing_context_lines = 2; 397 $formatter->show_header = FALSE; 398 399 foreach ($overrides as $component => $items) { 400 $diff = new Diff(explode("\n", $items['default']), explode("\n", $items['normal'])); 401 drush_print(); 402 drush_print(dt("Component: !component", array('!component' => $component))); 403 $rows = explode("\n", $formatter->format($diff)); 404 if (drush_get_context('DRUSH_NOCOLOR')) { 405 $red = $green = "%s"; 406 } 407 else { 408 $red = "\033[31;40m\033[1m%s\033[0m"; 409 $green = "\033[0;32;40m\033[1m%s\033[0m"; 410 } 411 foreach ($rows as $row) { 412 if (strpos($row, '>') === 0) { 413 drush_print(sprintf($green, $row)); 414 } 415 elseif (strpos($row, '<') === 0) { 416 drush_print(sprintf($red, $row)); 417 } 418 else { 419 drush_print($row); 420 } 421 } 422 } 423 } 424 425 /** 426 * Helper function to call drush_set_error(). 427 * 428 * @param $feature 429 * The string name of the feature. 430 * @param $error 431 * A text string identifying the type of error. 432 * @return 433 * FALSE. See drush_set_error(). 434 */ 435 function _features_drush_set_error($feature, $error = '') { 436 $args = array('!feature' => $feature); 437 438 switch ($error) { 439 case 'FEATURES_FEATURE_NOT_ENABLED': 440 $message = 'The feature !feature is not enabled.'; 441 break; 442 default: 443 $error = 'FEATURES_FEATURE_NOT_FOUND'; 444 $message = 'The feature !feature could not be found.'; 445 } 446 447 return drush_set_error($error, dt($message, $args)); 448 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Thu Mar 24 11:18:33 2011 | Cross-referenced by PHPXref 0.7 |