protected function UpgradeStatusForm::buildEnvironmentChecks in Upgrade Status 8.3
Same name and namespace in other branches
- 8.2 src/Form/UpgradeStatusForm.php \Drupal\upgrade_status\Form\UpgradeStatusForm::buildEnvironmentChecks()
Builds a list of environment checks.
Return value
array Build array. The overall environment status (TRUE, FALSE or NULL) is indicated in the 'status' key, while a 'description' key explains the environment requirements on a high level.
1 call to UpgradeStatusForm::buildEnvironmentChecks()
- UpgradeStatusForm::buildForm in src/
Form/ UpgradeStatusForm.php - Form constructor.
File
- src/
Form/ UpgradeStatusForm.php, line 670
Class
Namespace
Drupal\upgrade_status\FormCode
protected function buildEnvironmentChecks() {
$status = TRUE;
$header = [
'requirement' => [
'data' => $this
->t('Requirement'),
'class' => 'requirement-label',
],
'status' => [
'data' => $this
->t('Status'),
'class' => 'status-info',
],
];
$build['data'] = [
'#type' => 'table',
'#header' => $header,
'#rows' => [],
];
if ($this->nextMajor == 10) {
// @todo update this as the situation develops.
$build['description'] = $this
->t('<a href=":environment">Drupal 10 environment requirements are still evolving</a>. Upgrades to Drupal 10 are planned to be supported from Drupal 9.3.x and Drupal 9.4.x.', [
':environment' => 'https://www.drupal.org/project/drupal/issues/3118147',
]);
// Check PHP version.
$version = PHP_VERSION;
if (version_compare($version, '8.0.0') >= 0) {
$class = 'no-known-error';
}
else {
$class = 'known-error';
$status = FALSE;
}
$build['data']['#rows'][] = [
'class' => [
$class,
],
'data' => [
'requirement' => [
'class' => 'requirement-label',
'data' => $this
->t('PHP version should be at least 8.0.0. Before updating to PHP 8, use <code>$ composer why-not php:8</code> to check if any projects need updating for compatibility. Also check custom projects manually.'),
],
'status' => [
'data' => $this
->t('Version @version', [
'@version' => $version,
]),
'class' => 'status-info',
],
],
];
// Check JSON support in database.
$class = 'no-known-error';
$requirement = $this
->t('Supported.');
try {
$this->database
->query('SELECT JSON_TYPE(\'1\')');
} catch (\Exception $e) {
$class = 'known-error';
$status = FALSE;
$requirement = $this
->t('Not supported.');
}
$build['data']['#rows'][] = [
'class' => [
$class,
],
'data' => [
'requirement' => [
'class' => 'requirement-label',
'data' => $this
->t('Database JSON support required'),
],
'status' => [
'data' => $requirement,
'class' => 'status-info',
],
],
];
// Check user roles on the site for invalid permissions.
$class = 'no-known-error';
$requirement = [
$this
->t('None found.'),
];
$user_roles = Role::loadMultiple();
$all_permissions = array_keys(\Drupal::service('user.permissions')
->getPermissions());
foreach ($user_roles as $role) {
$role_permissions = $role
->getPermissions();
$valid_role_permissions = array_intersect($role_permissions, $all_permissions);
$invalid_role_permissions = array_diff($role_permissions, $valid_role_permissions);
if (!empty($invalid_role_permissions)) {
$class = 'known-error';
$status = FALSE;
$requirement = [
$this
->t('"@permissions" of user role: "@role".', [
'@permissions' => implode('", "', $invalid_role_permissions),
'@role' => $role
->label(),
]),
];
}
}
$build['data']['#rows'][] = [
'class' => [
$class,
],
'data' => [
'requirement' => [
'class' => 'requirement-label',
'data' => $this
->t('Invalid permissions will trigger runtime exceptions in Drupal 10. Permissions should be defined in a permissions.yml file or a permission callback. See https://www.drupal.org/node/3193348'),
],
'status' => [
'data' => join(' ', $requirement),
'class' => 'status-info',
],
],
];
// Check for deprecated or obsolete core extensions.
$class = 'no-known-error';
$requirement = $this
->t('None installed.');
$deprecated_or_obsolete = $this->projectCollector
->collectCoreDeprecatedAndObsoleteExtensions();
if (!empty($deprecated_or_obsolete)) {
$class = 'known-error';
$status = FALSE;
$requirement = join(', ', $deprecated_or_obsolete);
}
$build['data']['#rows'][] = [
'class' => [
$class,
],
'data' => [
'requirement' => [
'class' => 'requirement-label',
'data' => $this
->t('Deprecated or obsolete core extensions installed. These will be removed in the next major version.'),
],
'status' => [
'data' => $requirement,
'class' => 'status-info',
],
],
];
// Save the overall status indicator in the build array. It will be
// popped off later to be used in the summary table.
$build['status'] = $status;
return $build;
}
$build['description'] = $this
->t('<a href=":upgrade">Upgrades to Drupal 9 are supported from Drupal 8.8.x and Drupal 8.9.x</a>. It is suggested to update to the latest Drupal 8 version available. <a href=":platform">Several hosting platform requirements have been raised for Drupal 9</a>.', [
':upgrade' => 'https://www.drupal.org/docs/9/how-to-prepare-your-drupal-7-or-8-site-for-drupal-9/upgrading-a-drupal-8-site-to-drupal-9',
':platform' => 'https://www.drupal.org/docs/9/how-drupal-9-is-made-and-what-is-included/environment-requirements-of-drupal-9',
]);
// Check Drupal version. Link to update if available.
$core_version_info = [
'#type' => 'markup',
'#markup' => $this
->t('Version @version and up to date.', [
'@version' => \Drupal::VERSION,
]),
];
$has_core_update = FALSE;
$core_update_info = $this->releaseStore
->get('drupal');
if (isset($core_update_info['releases']) && is_array($core_update_info['releases'])) {
// Find the latest release that are higher than our current and is not beta/alpha/rc.
foreach ($core_update_info['releases'] as $version => $release) {
$major_version = explode('.', $version)[0];
if (version_compare($version, \Drupal::VERSION) > 0 && empty($release['version_extra']) && $major_version === '8') {
$link = $core_update_info['link'] . '/releases/' . $version;
$core_version_info = [
'#type' => 'link',
'#title' => $this
->t('Version @current allows to upgrade but @new is available.', [
'@current' => \Drupal::VERSION,
'@new' => $version,
]),
'#url' => Url::fromUri($link),
];
$has_core_update = TRUE;
break;
}
}
}
if (version_compare(\Drupal::VERSION, '8.8.0') >= 0) {
if (!$has_core_update) {
$class = 'no-known-error';
}
else {
$class = 'known-warning';
}
}
else {
$status = FALSE;
$class = 'known-error';
}
$build['data']['#rows'][] = [
'class' => $class,
'data' => [
'requirement' => [
'class' => 'requirement-label',
'data' => $this
->t('Drupal core should be 8.8.x or 8.9.x'),
],
'status' => [
'data' => $core_version_info,
'class' => 'status-info',
],
],
];
// Check PHP version.
$version = PHP_VERSION;
if (version_compare($version, '7.3.0') >= 0) {
$class = 'no-known-error';
}
else {
$class = 'known-error';
$status = FALSE;
}
$build['data']['#rows'][] = [
'class' => [
$class,
],
'data' => [
'requirement' => [
'class' => 'requirement-label',
'data' => $this
->t('PHP version should be at least 7.3.0'),
],
'status' => [
'data' => $this
->t('Version @version', [
'@version' => $version,
]),
'class' => 'status-info',
],
],
];
// Check database version.
$type = $this->database
->databaseType();
$version = $this->database
->version();
// If running on Drupal 8, the mysql driver might
// mis-report the database version.
if ($this->nextMajor == 9) {
$versionFixer = new CorrectDbServerVersion($this->database);
$version = $versionFixer
->getCorrectedDbServerVersion($version);
}
// MariaDB databases report as MySQL. Detect MariaDB separately based on code from
// https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Database%21Driver%21mysql%21Connection.php/function/Connection%3A%3AgetMariaDbVersionMatch/9.0.x
// See also https://www.drupal.org/node/3119156 for test values.
if ($type == 'mysql') {
// MariaDB may prefix its version string with '5.5.5-', which should be
// ignored.
// @see https://github.com/MariaDB/server/blob/f6633bf058802ad7da8196d01fd19d75c53f7274/include/mysql_com.h#L42.
$regex = '/^(?:5\\.5\\.5-)?(\\d+\\.\\d+\\.\\d+.*-mariadb.*)/i';
preg_match($regex, $version, $matches);
if (!empty($matches[1])) {
$type = 'MariaDB';
$version = $matches[1];
$requirement = $this
->t('When using MariaDB, minimum version is 10.3.7');
if (version_compare($version, '10.3.7') >= 0) {
$class = 'no-known-error';
}
elseif (version_compare($version, '10.1.0') >= 0) {
$class = 'known-warning';
$requirement .= ' ' . $this
->t('Alternatively, <a href=":driver">install the MariaDB 10.1 driver for Drupal 9</a> for now.', [
':driver' => 'https://www.drupal.org/project/mysql56',
]);
}
else {
$status = FALSE;
$class = 'known-error';
$requirement .= ' ' . $this
->t('Once updated to at least 10.1, you can also <a href=":driver">install the MariaDB 10.1 driver for Drupal 9</a> for now.', [
':driver' => 'https://www.drupal.org/project/mysql56',
]);
}
}
else {
$type = 'MySQL or Percona Server';
$requirement = $this
->t('When using MySQL/Percona, minimum version is 5.7.8');
if (version_compare($version, '5.7.8') >= 0) {
$class = 'no-known-error';
}
elseif (version_compare($version, '5.6.0') >= 0) {
$class = 'known-warning';
$requirement .= ' ' . $this
->t('Alternatively, <a href=":driver">install the MySQL 5.6 driver for Drupal 9</a> for now.', [
':driver' => 'https://www.drupal.org/project/mysql56',
]);
}
else {
$status = FALSE;
$class = 'known-error';
$requirement .= ' ' . $this
->t('Once updated to at least 5.6, you can also <a href=":driver">install the MySQL 5.6 driver for Drupal 9</a> for now.', [
':driver' => 'https://www.drupal.org/project/mysql56',
]);
}
}
}
elseif ($type == 'pgsql') {
$type = 'PostgreSQL';
$requirement = $this
->t('When using PostgreSQL, minimum version is 10 <a href=":trgm">with the pg_trgm extension</a> (The extension is not checked here).', [
':trgm' => 'https://www.postgresql.org/docs/10/pgtrgm.html',
]);
if (version_compare($version, '10') >= 0) {
$class = 'no-known-error';
}
else {
$status = FALSE;
$class = 'known-error';
}
}
elseif ($type == 'sqlite') {
$type = 'SQLite';
$requirement = $this
->t('When using SQLite, minimum version is 3.26');
if (version_compare($version, '3.26') >= 0) {
$class = 'no-known-error';
}
else {
$status = FALSE;
$class = 'known-error';
}
}
$build['data']['#rows'][] = [
'class' => [
$class,
],
'data' => [
'requirement' => [
'class' => 'requirement-label',
'data' => [
'#type' => 'markup',
'#markup' => $requirement,
],
],
'status' => [
'data' => $type . ' ' . $version,
'class' => 'status-info',
],
],
];
// Check Apache. Logic is based on system_requirements() code.
$request_object = \Drupal::request();
$software = $request_object->server
->get('SERVER_SOFTWARE');
if (strpos($software, 'Apache') !== FALSE && preg_match('!^Apache/([\\d\\.]+) !', $software, $found)) {
$version = $found[1];
if (version_compare($version, '2.4.7') >= 0) {
$class = 'no-known-error';
}
else {
$status = FALSE;
$class = 'known-error';
}
$label = $this
->t('Version @version', [
'@version' => $version,
]);
}
else {
$class = '';
$label = $this
->t('Version cannot be detected or not using Apache, check manually.');
}
$build['data']['#rows'][] = [
'class' => [
$class,
],
'data' => [
'requirement' => [
'class' => 'requirement-label',
'data' => $this
->t('When using Apache, minimum version is 2.4.7'),
],
'status' => [
'data' => $label,
'class' => 'status-info',
],
],
];
// Check Drush. We only detect site-local drush for now.
if (class_exists('\\Drush\\Drush')) {
$version = call_user_func('\\Drush\\Drush::getMajorVersion');
if (version_compare($version, '10') >= 0) {
$class = 'no-known-error';
}
else {
$status = FALSE;
$class = 'known-error';
}
$label = $this
->t('Version @version', [
'@version' => $version,
]);
}
else {
$class = '';
$label = $this
->t('Version cannot be detected, check manually.');
}
$build['data']['#rows'][] = [
'class' => $class,
'data' => [
'requirement' => [
'class' => 'requirement-label',
'data' => $this
->t('When using Drush, minimum version is 10'),
],
'status' => [
'data' => $label,
'class' => 'status-info',
],
],
];
// Check deprecated $config_directories if after Drupal 8.8.0. On older
// Drupal versions, the replacement is not supported and the setting may
// be generated by platforms like ddev, leading to false positives that
// the user should not even resolve yet before updating core.
if (version_compare(\Drupal::VERSION, '8.8.0') >= 0) {
$class = 'no-known-error';
$requirement = $this
->t('Use of $config_directories in settings.php is deprecated.');
$label = $this
->t('Not used');
$is_deprecated = $this
->isDeprecatedConfigDirectorySettingUsed();
if ($is_deprecated !== FALSE) {
$status = FALSE;
$class = 'known-error';
if ($is_deprecated === TRUE) {
$label = $this
->t('Deprecated configuration used');
$requirement .= ' ' . $this
->t('<a href=":settings">Use $settings[\'config_sync_directory\'] instead.</a>', [
':settings' => 'https://www.drupal.org/node/3018145',
]);
}
else {
$label = $this
->t('Deprecated and new configuration used');
$requirement .= ' ' . $this
->t('<a href=":settings">Use $settings[\'config_sync_directory\'] only.</a>', [
':settings' => 'https://www.drupal.org/node/3018145',
]);
}
}
$build['data']['#rows'][] = [
'class' => $class,
'data' => [
'requirement' => [
'class' => 'requirement-label',
'data' => [
'#type' => 'markup',
'#markup' => $requirement,
],
],
'status' => [
'data' => $label,
'class' => 'status-info',
],
],
];
}
// Save the overall status indicator in the build array. It will be
// popped off later to be used in the summary table.
$build['status'] = $status;
return $build;
}