[ Index ]

PHP Cross Reference of Drupal 6 (gatewave)

title

Body

[close]

/sites/all/modules/features/ -> features.drush.inc (source)

   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  }


Generated: Thu Mar 24 11:18:33 2011 Cross-referenced by PHPXref 0.7