public function ProjectCollector::collectProjects in Upgrade Status 8.3
Same name and namespace in other branches
- 8 src/ProjectCollector.php \Drupal\upgrade_status\ProjectCollector::collectProjects()
- 8.2 src/ProjectCollector.php \Drupal\upgrade_status\ProjectCollector::collectProjects()
Collect projects of installed modules grouped by custom and contrib.
Return value
\Drupal\Core\Extension\Extension[] An array keyed by project names. Extensions selected as projects without a defined project name get one based on their topmost parent extension and only that topmost extension gets included in the list.
1 call to ProjectCollector::collectProjects()
- ProjectCollector::loadProject in src/
ProjectCollector.php - Returns a single extension based on type and machine name.
File
- src/
ProjectCollector.php, line 182
Class
- ProjectCollector
- Collects projects and their associated metadata collated for Upgrade Status.
Namespace
Drupal\upgrade_statusCode
public function collectProjects() {
$projects = [];
$modules = $this->moduleExtensionList
->getList();
$themes = $this->themeExtensionList
->getList();
$profiles = $this->profileExtensionList
->getList();
$extensions = array_merge($modules, $themes, $profiles);
unset($modules, $themes, $profiles);
$update_check_for_uninstalled = $this->configFactory
->get('update.settings')
->get('check.disabled_extensions');
/** @var \Drupal\Core\Extension\Extension $extension */
foreach ($extensions as $key => $extension) {
if ($extension->origin === 'core') {
// Ignore core extensions for the sake of upgrade status.
continue;
}
// If the project is already specified in this extension, use that.
$project = isset($extension->info['project']) ? $extension->info['project'] : '';
if (isset($projects[$project])) {
// If we already have a representative of this project in the list,
// don't add this extension.
// @todo Make sure to use the extension with the shortest file path.
// If the existing project was already Drupal 9 compatible, consider
// this subcomponent as well. If this component was enabled, it would
// affect how we consider the Drupal 9 compatibility.
if (!empty($projects[$project]->info['upgrade_status_next_major_compatible']) && !empty($extension->status)) {
// Overwrite compatibility. If this is still compatible, it will
// keep being TRUE, otherwise FALSE.
$projects[$project]->info['upgrade_status_next_major_compatible'] = isset($extension->info['core_version_requirement']) && self::isCompatibleWithNextMajorDrupal($extension->info['core_version_requirement']);
}
continue;
}
if (strpos($key, 'upgrade_status') === 0 && !drupal_valid_test_ua()) {
// Don't add the Upgrade Status modules to the list if not in tests.
// Upgrade status is a temporary site component and does have
// intentional deprecated API use for the sake of testing. Avoid
// distracting site owners with this.
continue;
}
// Attempt to identify if the project was contrib based on the directory
// structure it is in. Extension placement is not a mandatory requirement
// and theoretically this could lead to false positives, but if
// composer_deploy or git_deploy is not available (and/or did not
// identify the project for us), this is all we can do. Ignore our test
// modules for this scenario.
if (empty($project)) {
$type = self::TYPE_CUSTOM;
if (strpos($extension
->getPath(), '/contrib/') && strpos($key, 'upgrade_status_test_') !== 0) {
$type = self::TYPE_CONTRIB;
}
}
elseif ($project === 'drupal') {
$type = self::TYPE_CUSTOM;
}
else {
$type = self::TYPE_CONTRIB;
}
// Add additional information to the extension info for our tracking.
// Keep this on a cloned extension object so we are not polluting runtime
// extension information elsewhere.
$extdata = clone $extension;
$extdata->info['upgrade_status_type'] = $type;
$extdata->info['upgrade_status_next_major_compatible'] = isset($extdata->info['core_version_requirement']) && self::isCompatibleWithNextMajorDrupal($extdata->info['core_version_requirement']);
// Save this as a possible project to consider.
$projects[$key] = $extdata;
}
// Collate extensions to projects, removing sub-extensions.
$projects = $this
->collateExtensionsIntoProjects($projects);
// After the collation is done, assign project names based on the topmost
// extension. While this is not always right for drupal.org projects, this
// is the best guess we have.
foreach ($projects as $name => $extension) {
if (!isset($extension->info['project'])) {
$projects[$name]->info['project'] = $name;
}
// Add available update information to contrib projects found.
if ($extension->info['upgrade_status_type'] == self::TYPE_CONTRIB) {
// Look up by drupal.org project info not $name because the two may be different.
$project_update = $this->availableUpdates
->get($extension->info['project']);
if (!isset($project_update['releases']) || is_null($project_update['releases'])) {
// Releases were either not checked or not available.
$projects[$name]->info['upgrade_status_update'] = $update_check_for_uninstalled ? self::UPDATE_NOT_AVAILABLE : self::UPDATE_NOT_CHECKED;
}
else {
// Add Drupal 9 compatibility info from the update's data.
$latest_release = reset($project_update['releases']);
$projects[$name]->info['upgrade_status_update_compatible'] = FALSE;
if (!empty($latest_release['core_compatibility']) && self::isCompatibleWithNextMajorDrupal($latest_release['core_compatibility'])) {
$projects[$name]->info['upgrade_status_update_compatible'] = TRUE;
}
// Denormalize update info into the extension info for our own use.
if ($extension->info['version'] !== $latest_release['version']) {
$projects[$name]->info['upgrade_status_update'] = self::UPDATE_AVAILABLE;
$link = $project_update['link'] . '/releases/' . $latest_release['version'];
$projects[$name]->info['upgrade_status_update_link'] = $link;
$projects[$name]->info['upgrade_status_update_version'] = $latest_release['version'];
}
else {
// If the current version is already the latest, store that.
$projects[$name]->info['upgrade_status_update'] = self::UPDATE_ALREADY_INSTALLED;
}
}
}
// Get scan results if there was any.
$scan_result = $this
->getResults($name);
// Pick a suggested next step for this project.
if ($extension->info['upgrade_status_next_major_compatible'] && $extension->info['upgrade_status_type'] == self::TYPE_CONTRIB) {
// If the project was contrib and already Drupal 9 compatible, relax.
$extension->info['upgrade_status_next'] = self::NEXT_RELAX;
}
elseif (empty($extension->status)) {
// Uninstalled modules should be removed.
$extension->info['upgrade_status_next'] = self::NEXT_REMOVE;
}
elseif (isset($extension->info['upgrade_status_update']) && $extension->info['upgrade_status_update'] == self::UPDATE_AVAILABLE) {
// If there was a Drupal 9 compatible update or even a yet incompatible
// update to this project, the best course of action is to update to
// that, since that should move closer to Drupal 9 compatibility.
$extension->info['upgrade_status_next'] = self::NEXT_UPDATE;
}
elseif ($extension->info['upgrade_status_type'] == self::TYPE_CONTRIB) {
// For installed contributed modules that do not have compatile updates, collaborate.
$extension->info['upgrade_status_next'] = self::NEXT_COLLABORATE;
}
else {
// If there was no scanning result yet, next step is to scan this project.
if (empty($scan_result) || empty($scan_result['data']['totals']['upgrade_status_next'])) {
$extension->info['upgrade_status_next'] = self::NEXT_SCAN;
}
else {
$extension->info['upgrade_status_next'] = $scan_result['data']['totals']['upgrade_status_next'];
}
}
}
return $projects;
}