Unverified Commit 5e0a4ce7 authored by Alex Pott's avatar Alex Pott
Browse files

Issue #3490841 by nicxvan, dww, smustgrave: Create hook_runtime_requirements()...

Issue #3490841 by nicxvan, dww, smustgrave: Create hook_runtime_requirements() and hook_runtime_requirements_alter()
parent 928a5cbd
Loading
Loading
Loading
Loading
Loading
+88 −0
Original line number Diff line number Diff line
@@ -1187,6 +1187,94 @@ function hook_requirements_alter(array &$requirements): void {
  unset($requirements['foo']);
}

/**
 * Check runtime requirements and do status reporting.
 *
 * Requirements are displayed on the 'Status report' (/admin/reports/status).
 *
 * Runtime requirements do not impact installation or updates of modules that
 * define them. These requirements are only used to display information on the
 * status report but do not impact site behavior. They can be used for more
 * general status information like maintenance tasks and security issues.
 * The returned requirements will be listed on the status report in the
 * administration section, with an indication of the severity level.
 * Moreover, any requirement with a severity of REQUIREMENT_ERROR will result in
 * a notice on the 'Configuration' administration page (/admin/config).
 *
 * @return array
 *   An associative array where the keys are arbitrary but must be unique (it
 *   is suggested to use the module short name as a prefix) and the values are
 *   themselves associative arrays with the following elements:
 *   - title: The name of the requirement.
 *   - value: The current value (e.g., version, time, level, etc).
 *   - description: The description of the requirement/status.
 *   - severity: (optional) The requirement's severity level, one of:
 *     - REQUIREMENT_INFO: For info only.
 *     - REQUIREMENT_OK: The requirement is satisfied.
 *     - REQUIREMENT_WARNING: The requirement failed with a warning.
 *     - REQUIREMENT_ERROR: The requirement failed with an error.
 *     Defaults to REQUIREMENT_OK.
 */
function hook_runtime_requirements(): array {
  $requirements = [];

  // Report Drupal version
  $requirements['drupal'] = [
    'title' => t('Drupal'),
    'value' => \Drupal::VERSION,
    'severity' => REQUIREMENT_INFO,
  ];

  // Test PHP version
  $requirements['php'] = [
    'title' => t('PHP'),
    'value' => Link::fromTextAndUrl(phpversion(), Url::fromRoute('system.php'))->toString(),
  ];
  if (version_compare(phpversion(), \Drupal::MINIMUM_PHP) < 0) {
    $requirements['php']['description'] = t('Your PHP installation is too old. Drupal requires at least PHP %version.', ['%version' => \Drupal::MINIMUM_PHP]);
    $requirements['php']['severity'] = REQUIREMENT_ERROR;
  }

  // Report cron status
  $cron_last = \Drupal::state()->get('system.cron_last');
  $requirements['cron']['title'] = t('Cron maintenance tasks');
  if (is_numeric($cron_last)) {
    $requirements['cron']['description'] = '';
    $requirements['cron']['value'] = t('Last run @time ago', ['@time' => \Drupal::service('date.formatter')->formatTimeDiffSince($cron_last)]);
  }
  else {
    $requirements['cron']['description'] = t('Cron has not run. It appears cron jobs have not been setup on your system. Check the help pages for <a href=":url">configuring cron jobs</a>.', [':url' => 'https://www.drupal.org/docs/administering-a-drupal-site/cron-automated-tasks/cron-automated-tasks-overview']);
    $requirements['cron']['value'] = t('Never run');
    $requirements['cron']['severity'] = REQUIREMENT_ERROR;
  }
  $requirements['cron']['description'] .= ' ' . t('You can <a href=":cron">run cron manually</a>.', [':cron' => Url::fromRoute('system.run_cron')->toString()]);

  return $requirements;
}

/**
 * Alters runtime requirements data.
 *
 * Implementations are able to alter the title, value, description or the
 * severity of certain requirements defined by hook_requirements() and
 * hook_runtime_requirements() implementations, or even remove such entries.
 *
 * @param array $requirements
 *   The requirements data to be altered.
 *
 * @see hook_runtime_requirements()
 */
function hook_runtime_requirements_alter(array &$requirements): void {
  // Change the title from 'PHP' to 'PHP version'.
  $requirements['php']['title'] = t('PHP version');

  // Decrease the 'update status' requirement severity from warning to info.
  $requirements['update status']['severity'] = REQUIREMENT_INFO;

  // Remove a requirements entry.
  unset($requirements['foo']);
}

/**
 * @} End of "addtogroup hooks".
 */
+0 −48
Original line number Diff line number Diff line
@@ -57,54 +57,6 @@ function file_schema(): array {
  return $schema;
}

/**
 * Implements hook_requirements().
 *
 * Display information about getting upload progress bars working.
 */
function file_requirements($phase): array {
  $requirements = [];

  if ($phase != 'runtime') {
    return $requirements;
  }

  $server_software = \Drupal::request()->server->get('SERVER_SOFTWARE', '');

  // Get the web server identity.
  $is_nginx = preg_match("/Nginx/i", $server_software);
  $is_apache = preg_match("/Apache/i", $server_software);
  $fastcgi = $is_apache && ((str_contains($server_software, 'mod_fastcgi') || str_contains($server_software, 'mod_fcgi')));

  // Check the uploadprogress extension is loaded.
  if (extension_loaded('uploadprogress')) {
    $value = t('Enabled (<a href="http://pecl.php.net/package/uploadprogress">PECL uploadprogress</a>)');
    $description = NULL;
  }
  else {
    $value = t('Not enabled');
    $description = t('Your server is capable of displaying file upload progress, but does not have the required libraries. It is recommended to install the <a href="http://pecl.php.net/package/uploadprogress">PECL uploadprogress library</a>.');
  }

  // Adjust the requirement depending on what the server supports.
  if (!$is_apache && !$is_nginx) {
    $value = t('Not enabled');
    $description = t('Your server is not capable of displaying file upload progress. File upload progress requires an Apache server running PHP with mod_php or Nginx with PHP-FPM.');
  }
  elseif ($fastcgi) {
    $value = t('Not enabled');
    $description = t('Your server is not capable of displaying file upload progress. File upload progress requires PHP be run with mod_php or PHP-FPM and not as FastCGI.');
  }

  $requirements['file_progress'] = [
    'title' => t('Upload progress'),
    'value' => $value,
    'description' => $description,
  ];

  return $requirements;
}

/**
 * Implements hook_update_last_removed().
 */
+57 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\file\Hook;

use Drupal\Core\Hook\Attribute\Hook;
use Drupal\Core\StringTranslation\StringTranslationTrait;

/**
 * Requirements for the File module.
 */
class FileRequirements {

  use StringTranslationTrait;

  /**
   * Implements hook_runtime_requirements().
   */
  #[Hook('runtime_requirements')]
  public function runtime(): array {
    $requirements = [];
    $server_software = \Drupal::request()->server->get('SERVER_SOFTWARE', '');

    // Get the web server identity.
    $is_nginx = preg_match("/Nginx/i", $server_software);
    $is_apache = preg_match("/Apache/i", $server_software);
    $fastcgi = $is_apache && ((str_contains($server_software, 'mod_fastcgi') || str_contains($server_software, 'mod_fcgi')));

    // Check the uploadprogress extension is loaded.
    if (extension_loaded('uploadprogress')) {
      $value = $this->t('Enabled (<a href="http://pecl.php.net/package/uploadprogress">PECL uploadprogress</a>)');
      $description = NULL;
    }
    else {
      $value = $this->t('Not enabled');
      $description = $this->t('Your server is capable of displaying file upload progress, but does not have the required libraries. It is recommended to install the <a href="http://pecl.php.net/package/uploadprogress">PECL uploadprogress library</a>.');
    }

    // Adjust the requirement depending on what the server supports.
    if (!$is_apache && !$is_nginx) {
      $value = $this->t('Not enabled');
      $description = $this->t('Your server is not capable of displaying file upload progress. File upload progress requires an Apache server running PHP with mod_php or Nginx with PHP-FPM.');
    }
    elseif ($fastcgi) {
      $value = $this->t('Not enabled');
      $description = $this->t('Your server is not capable of displaying file upload progress. File upload progress requires PHP be run with mod_php or PHP-FPM and not as FastCGI.');
    }

    $requirements['file_progress'] = [
      'title' => $this->t('Upload progress'),
      'value' => $value,
      'description' => $description,
    ];

    return $requirements;
  }

}
+4 −5
Original line number Diff line number Diff line
@@ -32,11 +32,10 @@ public function testUploadRequirements(): void {

    /** @var \Drupal\Core\Extension\ModuleHandlerInterface $moduleHandler */
    $moduleHandler = $this->container->get('module_handler');
    $moduleHandler->loadInclude('file', 'install');

    // Test unspecified server software.
    $this->setServerSoftware(NULL);
    $requirements = \file_requirements('runtime');
    $requirements = $moduleHandler->invoke('file', 'runtime_requirements');
    $this->assertNotEmpty($requirements);

    $this->assertEquals('Upload progress', (string) $requirements['file_progress']['title']);
@@ -45,21 +44,21 @@ public function testUploadRequirements(): void {

    // Test Apache + mod_php.
    $this->setServerSoftware('Apache mod_php');
    $requirements = \file_requirements('runtime');
    $requirements = $moduleHandler->invoke('file', 'runtime_requirements');
    $this->assertNotEmpty($requirements);
    $this->assertEquals('Not enabled', (string) $requirements['file_progress']['value']);
    $this->assertEquals('Your server is capable of displaying file upload progress, but does not have the required libraries. It is recommended to install the <a href="http://pecl.php.net/package/uploadprogress">PECL uploadprogress library</a>.', (string) $requirements['file_progress']['description']);

    // Test Apache + mod_fastcgi.
    $this->setServerSoftware('Apache mod_fastcgi');
    $requirements = \file_requirements('runtime');
    $requirements = $moduleHandler->invoke('file', 'runtime_requirements');
    $this->assertNotEmpty($requirements);
    $this->assertEquals('Not enabled', (string) $requirements['file_progress']['value']);
    $this->assertEquals('Your server is not capable of displaying file upload progress. File upload progress requires PHP be run with mod_php or PHP-FPM and not as FastCGI.', (string) $requirements['file_progress']['description']);

    // Test Nginx.
    $this->setServerSoftware('Nginx');
    $requirements = \file_requirements('runtime');
    $requirements = $moduleHandler->invoke('file', 'runtime_requirements');
    $this->assertNotEmpty($requirements);
    $this->assertEquals('Not enabled', (string) $requirements['file_progress']['value']);
    $this->assertEquals('Your server is capable of displaying file upload progress, but does not have the required libraries. It is recommended to install the <a href="http://pecl.php.net/package/uploadprogress">PECL uploadprogress library</a>.', (string) $requirements['file_progress']['description']);
+3 −0
Original line number Diff line number Diff line
@@ -107,7 +107,10 @@ public function listRequirements() {

    // Check run-time requirements and status information.
    $requirements = $this->moduleHandler->invokeAll('requirements', ['runtime']);
    $runtime_requirements = $this->moduleHandler->invokeAll('runtime_requirements');
    $requirements = array_merge($requirements, $runtime_requirements);
    $this->moduleHandler->alter('requirements', $requirements);
    $this->moduleHandler->alter('runtime_requirements', $requirements);
    uasort($requirements, function ($a, $b) {
      if (!isset($a['weight'])) {
        if (!isset($b['weight'])) {
Loading