public function DeprecationAnalyser::analyse in Upgrade Status 8
Analyse the codebase of an extension including all its sub-components.
Parameters
\Drupal\Core\Extension\Extension $extension: The extension to analyse.
Return value
null Errors are logged to the logger, data is stored to keyvalue storage.
Overrides DeprecationAnalyserInterface::analyse
File
- src/
DeprecationAnalyser.php, line 156
Class
Namespace
Drupal\upgrade_statusCode
public function analyse(Extension $extension) {
// Prepare for possible fatal errors while autoloading or due to issues with
// dependencies.
drupal_register_shutdown_function([
$this,
'logFatalError',
], $extension);
// Set the autoloader for PHPStan.
if (!isset($GLOBALS['autoloaderInWorkingDirectory'])) {
$GLOBALS['autoloaderInWorkingDirectory'] = DRUPAL_ROOT . '/autoload.php';
}
$project_dir = DRUPAL_ROOT . '/' . $extension->subpath;
$paths = $this
->getDirContents($project_dir);
foreach ($paths as $key => $file_path) {
if (substr($file_path, -3) !== 'php' && substr($file_path, -7) !== '.module' && substr($file_path, -8) !== '.install' && substr($file_path, -3) !== 'inc') {
unset($paths[$key]);
}
}
$this->logger
->notice($this
->t("Extension @project_machine_name contains @number files to process.", [
'@project_machine_name' => $extension
->getName(),
'@number' => count($paths),
]));
$result = [];
$result['date'] = REQUEST_TIME;
$result['data'] = [
'totals' => [
'errors' => 0,
'file_errors' => 0,
],
'files' => [],
];
// Manually add on info file incompatibility to phpstan results.
$info = $extension->info;
if (!isset($info['core_version_requirement'])) {
$result['data']['files'][$extension
->getFilename()]['messages'] = [
[
'message' => 'Add <code>core_version_requirement: ^8 || ^9</code> to ' . $extension
->getFilename() . ' to designate that the module is compatible with Drupal 9. See https://www.drupal.org/node/3070687.',
'line' => 0,
],
];
$result['data']['totals']['errors']++;
$result['data']['totals']['file_errors']++;
}
elseif (!Semver::satisfies('9.0.0', $info['core_version_requirement'])) {
$result['data']['files'][$extension
->getFilename()]['messages'] = [
[
'message' => "The current value <code>core_version_requirement: {$info['core_version_requirement']}</code> in {$extension->getFilename()} is not compatible with Drupal 9.0.0. See https://www.drupal.org/node/3070687.",
'line' => 0,
],
];
$result['data']['totals']['errors']++;
$result['data']['totals']['file_errors']++;
}
if (!empty($paths)) {
$num_of_files = $this->config
->get('paths_per_scan') ?: 30;
// @todo: refactor and validate.
for ($offset = 0; $offset <= count($paths); $offset += $num_of_files) {
$files = array_slice($paths, $offset, $num_of_files);
if (!empty($files)) {
$raw_errors = $this
->runPhpStan($files);
$errors = json_decode($raw_errors, TRUE);
if (!is_array($errors)) {
continue;
}
$result['data']['totals']['errors'] += $errors['totals']['errors'];
$result['data']['totals']['file_errors'] += $errors['totals']['file_errors'];
$result['data']['files'] = array_merge($result['data']['files'], $errors['files']);
}
}
}
foreach ($result['data']['files'] as $path => &$errors) {
if (!empty($errors['messages'])) {
foreach ($errors['messages'] as &$error) {
// Overwrite message with processed text. Save category.
list($message, $category) = $this
->categorizeMessage($error['message'], $extension);
$error['message'] = $message;
$error['upgrade_status_category'] = $category;
// Sum up the error based on the category it ended up in. Split the
// categories into two high level buckets needing attention now or
// later for Drupal 9 compatibility. Ignore Drupal 10 here.
@$result['data']['totals']['upgrade_status_category'][$category]++;
if (in_array($category, [
'safe',
'old',
])) {
@$result['data']['totals']['upgrade_status_split']['error']++;
}
elseif (in_array($category, [
'later',
'uncategorized',
])) {
@$result['data']['totals']['upgrade_status_split']['warning']++;
}
}
}
}
// For contributed projects, attempt to grab Drupal 9 plan information.
if (!empty($extension->info['project'])) {
/** @var \Psr\Http\Message\ResponseInterface $response */
$response = $this->httpClient
->request('GET', 'https://www.drupal.org/api-d7/node.json?field_project_machine_name=' . $extension
->getName());
if ($response
->getStatusCode()) {
$data = json_decode($response
->getBody(), TRUE);
if (!empty($data['list'][0]['field_next_major_version_info']['value'])) {
$result['plans'] = str_replace('href="/', 'href="https://drupal.org/', $data['list'][0]['field_next_major_version_info']['value']);
// @todo implement "replaced by" collection once drupal.org exposes
// that in an accessible way
// @todo once/if drupal.org deprecation testing is in place, grab
// the status from there so we know if it improves by updating
}
}
}
// Store the analysis results in our storage bin.
$this->scanResultStorage
->set($extension
->getName(), json_encode($result));
}