You are here

class SiteAuditCheckExtensionsDuplicate in Site Audit 7

Same name and namespace in other branches
  1. 8.2 Check/Extensions/Duplicate.php \SiteAuditCheckExtensionsDuplicate

Class SiteAuditCheckExtensionsDuplicate.

Hierarchy

Expanded class hierarchy of SiteAuditCheckExtensionsDuplicate

File

Check/Extensions/Duplicate.php, line 10
Contains \SiteAudit\Check\Extensions\Duplicate.

View source
class SiteAuditCheckExtensionsDuplicate extends SiteAuditCheckAbstract {

  /**
   * Implements \SiteAudit\Check\Abstract\getLabel().
   */
  public function getLabel() {
    return dt('Duplicates');
  }

  /**
   * Implements \SiteAudit\Check\Abstract\getDescription().
   */
  public function getDescription() {
    return dt('Check for duplicate extensions in the site codebase.');
  }

  /**
   * Implements \SiteAudit\Check\Abstract\getResultFail().
   */
  public function getResultFail() {
  }

  /**
   * Implements \SiteAudit\Check\Abstract\getResultInfo().
   */
  public function getResultInfo() {
  }

  /**
   * Implements \SiteAudit\Check\Abstract\getResultPass().
   */
  public function getResultPass() {
    return dt('No duplicate extensions were detected.');
  }

  /**
   * Implements \SiteAudit\Check\Abstract\getResultWarn().
   */
  public function getResultWarn() {
    $ret_val = dt('The following duplicate extensions were found:');
    if (drush_get_option('html')) {
      $ret_val = '<p>' . $ret_val . '</p>';
      $ret_val .= '<table class="table table-condensed">';
      $ret_val .= '<thead><tr><th>' . dt('Name') . '</th><th>' . dt('Paths') . '</th></thead>';
      $ret_val .= '<tbody>';
      foreach ($this->registry['extensions_dupe'] as $name => $extension_infos) {
        $ret_val .= '<tr><td>' . $name . '</td>';
        $paths = array();
        foreach ($extension_infos as $extension_info) {
          $extension = $extension_info['path'];
          if ($extension_info['version']) {
            $extension .= ' (' . $extension_info['version'] . ')';
          }
          $paths[] = $extension;
        }
        $ret_val .= '<td>' . implode('<br/>', $paths) . '</td></tr>';
      }
      $ret_val .= '</tbody>';
      $ret_val .= '</table>';
    }
    else {
      foreach ($this->registry['extensions_dupe'] as $name => $extension_infos) {
        $ret_val .= PHP_EOL;
        if (!drush_get_option('json')) {
          $ret_val .= str_repeat(' ', 6);
        }
        $ret_val .= $name . PHP_EOL;
        $extension_list = '';
        foreach ($extension_infos as $extension_info) {
          $extension_list .= str_repeat(' ', 8);
          $extension_list .= $extension_info['path'];
          if ($extension_info['version']) {
            $extension_list .= ' (' . $extension_info['version'] . ')';
          }
          $extension_list .= PHP_EOL;
        }
        $ret_val .= rtrim($extension_list);
      }
    }
    return $ret_val;
  }

  /**
   * Implements \SiteAudit\Check\Abstract\getAction().
   */
  public function getAction() {
    if ($this->score != SiteAuditCheckAbstract::AUDIT_CHECK_SCORE_PASS) {
      return dt('Prune your codebase to have only one copy of any given extension. If you are using an installation profile, work with the maintainer to update the relevant modules. If you remove an enabled module, you may have to rebuild the registry.');
    }
  }

  /**
   * Implements \SiteAudit\Check\Abstract\calculateScore().
   */
  public function calculateScore() {
    $this->registry['extensions_dupe'] = array();
    $drupal_root = drush_get_context('DRUSH_SELECTED_DRUPAL_ROOT');
    $command = "find {$drupal_root} -xdev -type f -name '*.info' -o -path './" . variable_get('file_public_path', conf_path() . '/files') . "' -prune";
    exec($command, $result);
    foreach ($result as $path) {
      $path_parts = explode('/', $path);
      $name = substr(array_pop($path_parts), 0, -5);

      // Safe duplicates.
      if (in_array($name, array(
        'drupal_system_listing_compatible_test',
        'drupal_system_listing_incompatible_test',
      ))) {
        continue;
      }
      if (!isset($this->registry['extensions_dupe'][$name])) {
        $this->registry['extensions_dupe'][$name] = array();
      }
      $extension_info = array(
        'path' => substr($path, strlen($drupal_root) + 1),
        'version' => NULL,
      );
      $info = file($drupal_root . '/' . $extension_info['path']);
      foreach ($info as $line) {
        if (strpos($line, 'version') === 0) {
          $version = explode('=', $line);
          if (isset($version[1])) {
            $extension_info['version'] = trim(str_replace('"', '', $version[1]));
          }
        }
      }
      $this->registry['extensions_dupe'][$name][] = $extension_info;
    }

    // Review the detected extensions.
    foreach ($this->registry['extensions_dupe'] as $extension_name => $extension_infos) {

      // No duplicates.
      if (count($extension_infos) == 1) {
        unset($this->registry['extensions_dupe'][$extension_name]);
        continue;
      }

      // If every path is within an installation profile, ignore.
      $paths_in_profile = 0;
      foreach ($extension_infos as $index => $extension_info) {
        if (strpos($extension_info['path'], 'profiles/') === 0) {
          $paths_in_profile++;
        }
      }
      if ($paths_in_profile == count($extension_infos)) {
        unset($this->registry['extensions_dupe'][$extension_name]);
        continue;
      }

      // Allow overrides of installation profile extensions.
      $extension_object = $this->registry['extensions'][$extension_name];
      if (isset($extension_object->info['version']) && $extension_object->info['version'] && $paths_in_profile && drush_get_extension_status($extension_object) == 'enabled' && strpos($extension_object->uri, 'profiles/') === FALSE) {
        $skip = TRUE;
        foreach ($extension_infos as $extension_info) {

          // Not within the profile and there's version information.
          if (strpos($extension_info['path'], 'profiles/') !== FALSE && $extension_info['version']) {

            // If the installed version is equal or newer to the enabled.
            if (version_compare($extension_object->info['version'], $extension_info['version']) < 1) {
              $skip = FALSE;
              break;
            }
          }
        }
        if ($skip === TRUE) {
          unset($this->registry['extensions_dupe'][$extension_name]);
        }
      }
    }

    // Determine score.
    if (count($this->registry['extensions_dupe'])) {
      return SiteAuditCheckAbstract::AUDIT_CHECK_SCORE_WARN;
    }
    return SiteAuditCheckAbstract::AUDIT_CHECK_SCORE_PASS;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
SiteAuditCheckAbstract::$abort protected property Indicate that no other checks should be run after this check.
SiteAuditCheckAbstract::$optOut protected property User has opted out of this check in configuration.
SiteAuditCheckAbstract::$percentOverride protected property If set, will override the Report's percentage.
SiteAuditCheckAbstract::$registry protected property Use for passing data between checks within a report.
SiteAuditCheckAbstract::$score protected property Quantifiable number associated with result on a scale of 0 to 2.
SiteAuditCheckAbstract::AUDIT_CHECK_SCORE_FAIL constant
SiteAuditCheckAbstract::AUDIT_CHECK_SCORE_INFO constant
SiteAuditCheckAbstract::AUDIT_CHECK_SCORE_PASS constant
SiteAuditCheckAbstract::AUDIT_CHECK_SCORE_WARN constant
SiteAuditCheckAbstract::getPercentOverride public function Get the report percent override, if any.
SiteAuditCheckAbstract::getRegistry public function Get the check registry.
SiteAuditCheckAbstract::getRelativePath public function Gives path relative to DRUPAL_ROOT of the path is inside Drupal.
SiteAuditCheckAbstract::getResult public function Determine the result message based on the score.
SiteAuditCheckAbstract::getScore public function Get a quantifiable number representing a check result; lazy initialization.
SiteAuditCheckAbstract::getScoreCssClass public function Get the CSS class associated with a score.
SiteAuditCheckAbstract::getScoreDrushLevel public function Get the Drush message level associated with a score.
SiteAuditCheckAbstract::getScoreLabel public function Get a human readable label for a score.
SiteAuditCheckAbstract::renderAction public function Display action items for a user to perform.
SiteAuditCheckAbstract::shouldAbort public function Determine whether the check failed so badly that the report must stop.
SiteAuditCheckAbstract::__construct public function Constructor.
SiteAuditCheckExtensionsDuplicate::calculateScore public function Implements \SiteAudit\Check\Abstract\calculateScore(). Overrides SiteAuditCheckAbstract::calculateScore
SiteAuditCheckExtensionsDuplicate::getAction public function Implements \SiteAudit\Check\Abstract\getAction(). Overrides SiteAuditCheckAbstract::getAction
SiteAuditCheckExtensionsDuplicate::getDescription public function Implements \SiteAudit\Check\Abstract\getDescription(). Overrides SiteAuditCheckAbstract::getDescription
SiteAuditCheckExtensionsDuplicate::getLabel public function Implements \SiteAudit\Check\Abstract\getLabel(). Overrides SiteAuditCheckAbstract::getLabel
SiteAuditCheckExtensionsDuplicate::getResultFail public function Implements \SiteAudit\Check\Abstract\getResultFail(). Overrides SiteAuditCheckAbstract::getResultFail
SiteAuditCheckExtensionsDuplicate::getResultInfo public function Implements \SiteAudit\Check\Abstract\getResultInfo(). Overrides SiteAuditCheckAbstract::getResultInfo
SiteAuditCheckExtensionsDuplicate::getResultPass public function Implements \SiteAudit\Check\Abstract\getResultPass(). Overrides SiteAuditCheckAbstract::getResultPass
SiteAuditCheckExtensionsDuplicate::getResultWarn public function Implements \SiteAudit\Check\Abstract\getResultWarn(). Overrides SiteAuditCheckAbstract::getResultWarn