Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
0.00% |
0 / 1 |
|
0.00% |
0 / 3 |
CRAP | |
0.00% |
0 / 77 |
ProjectInfo | |
0.00% |
0 / 1 |
|
0.00% |
0 / 3 |
506 | |
0.00% |
0 / 77 |
processInfoList | |
0.00% |
0 / 1 |
342 | |
0.00% |
0 / 55 |
|||
getProjectName | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 9 |
|||
filterProjectInfo | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 13 |
<?php | |
/** | |
* @file | |
* Contains \Drupal\Core\Utility\ProjectInfo. | |
* | |
* API for building lists of installed projects. | |
*/ | |
namespace Drupal\Core\Utility; | |
use Drupal\Core\Extension\Extension; | |
/** | |
* Performs operations on drupal.org project data. | |
*/ | |
class ProjectInfo { | |
/** | |
* Populates an array of project data. | |
* | |
* This iterates over a list of the installed modules or themes and groups | |
* them by project and status. A few parts of this function assume that | |
* enabled modules and themes are always processed first, and if uninstalled | |
* modules or themes are being processed (there is a setting to control if | |
* uninstalled code should be included in the Available updates report or | |
* not),those are only processed after $projects has been populated with | |
* information about the enabled code. 'Hidden' modules and themes are | |
* ignored if they are not installed. 'Hidden' Modules and themes in the | |
* "Testing" package are ignored regardless of installation status. | |
* | |
* This function also records the latest change time on the .info.yml files | |
* for each module or theme, which is important data which is used when | |
* deciding if the available update data should be invalidated. | |
* | |
* @param array $projects | |
* Reference to the array of project data of what's installed on this site. | |
* @param \Drupal\Core\Extension\Extension[] $list | |
* Array of data to process to add the relevant info to the $projects array. | |
* @param string $project_type | |
* The kind of data in the list. Can be 'module' or 'theme'. | |
* @param bool $status | |
* Boolean that controls what status (enabled or uninstalled) to process out | |
* of the $list and add to the $projects array. | |
* @param array $additional_whitelist | |
* (optional) Array of additional elements to be collected from the .info.yml | |
* file. Defaults to array(). | |
*/ | |
function processInfoList(array &$projects, array $list, $project_type, $status, array $additional_whitelist = array()) { | |
foreach ($list as $file) { | |
// Just projects with a matching status should be listed. | |
if ($file->status != $status) { | |
continue; | |
} | |
// Skip if the .info.yml file is broken. | |
if (empty($file->info)) { | |
continue; | |
} | |
// Skip if it's a hidden project and the project is not installed. | |
if (!empty($file->info['hidden']) && empty($status)) { | |
continue; | |
} | |
// Skip if it's a hidden project and the project is a test project. Tests | |
// should use hook_system_info_alter() to test ProjectInfo's | |
// functionality. | |
if (!empty($file->info['hidden']) && isset($file->info['package']) && $file->info['package'] == 'Testing') { | |
continue; | |
} | |
// If the .info.yml doesn't define the 'project', try to figure it out. | |
if (!isset($file->info['project'])) { | |
$file->info['project'] = $this->getProjectName($file); | |
} | |
// If we still don't know the 'project', give up. | |
if (empty($file->info['project'])) { | |
continue; | |
} | |
// If we don't already know it, grab the change time on the .info.yml file | |
// itself. Note: we need to use the ctime, not the mtime (modification | |
// time) since many (all?) tar implementations will go out of their way to | |
// set the mtime on the files it creates to the timestamps recorded in the | |
// tarball. We want to see the last time the file was changed on disk, | |
// which is left alone by tar and correctly set to the time the .info.yml | |
// file was unpacked. | |
if (!isset($file->info['_info_file_ctime'])) { | |
$file->info['_info_file_ctime'] = $file->getCTime(); | |
} | |
if (!isset($file->info['datestamp'])) { | |
$file->info['datestamp'] = 0; | |
} | |
$project_name = $file->info['project']; | |
// Figure out what project type we're going to use to display this module | |
// or theme. If the project name is 'drupal', we don't want it to show up | |
// under the usual "Modules" section, we put it at a special "Drupal Core" | |
// section at the top of the report. | |
if ($project_name == 'drupal') { | |
$project_display_type = 'core'; | |
} | |
else { | |
$project_display_type = $project_type; | |
} | |
if (empty($status)) { | |
// If we're processing uninstalled modules or themes, append a suffix. | |
$project_display_type .= '-disabled'; | |
} | |
if (!isset($projects[$project_name])) { | |
// Only process this if we haven't done this project, since a single | |
// project can have multiple modules or themes. | |
$projects[$project_name] = array( | |
'name' => $project_name, | |
// Only save attributes from the .info.yml file we care about so we do | |
// not bloat our RAM usage needlessly. | |
'info' => $this->filterProjectInfo($file->info, $additional_whitelist), | |
'datestamp' => $file->info['datestamp'], | |
'includes' => array($file->getName() => $file->info['name']), | |
'project_type' => $project_display_type, | |
'project_status' => $status, | |
); | |
} | |
elseif ($projects[$project_name]['project_type'] == $project_display_type) { | |
// Only add the file we're processing to the 'includes' array for this | |
// project if it is of the same type and status (which is encoded in the | |
// $project_display_type). This prevents listing all the uninstalled | |
// modules included with an enabled project if we happen to be checking | |
// for uninstalled modules, too. | |
$projects[$project_name]['includes'][$file->getName()] = $file->info['name']; | |
$projects[$project_name]['info']['_info_file_ctime'] = max($projects[$project_name]['info']['_info_file_ctime'], $file->info['_info_file_ctime']); | |
$projects[$project_name]['datestamp'] = max($projects[$project_name]['datestamp'], $file->info['datestamp']); | |
} | |
elseif (empty($status)) { | |
// If we have a project_name that matches, but the project_display_type | |
// does not, it means we're processing a uninstalled module or theme | |
// that belongs to a project that has some enabled code. In this case, | |
// we add the uninstalled thing into a separate array for separate | |
// display. | |
$projects[$project_name]['disabled'][$file->getName()] = $file->info['name']; | |
} | |
} | |
} | |
/** | |
* Determines what project a given file object belongs to. | |
* | |
* @param \Drupal\Core\Extension\Extension $file | |
* An extension object. | |
* | |
* @return string | |
* The canonical project short name. | |
*/ | |
function getProjectName(Extension $file) { | |
$project_name = ''; | |
if (isset($file->info['project'])) { | |
$project_name = $file->info['project']; | |
} | |
elseif (strpos($file->getPath(), 'core/modules') === 0) { | |
$project_name = 'drupal'; | |
} | |
return $project_name; | |
} | |
/** | |
* Filters the project .info.yml data to only save attributes we need. | |
* | |
* @param array $info | |
* Array of .info.yml file data as returned by | |
* \Drupal\Core\Extension\InfoParser. | |
* @param $additional_whitelist | |
* (optional) Array of additional elements to be collected from the .info.yml | |
* file. Defaults to array(). | |
* | |
* @return | |
* Array of .info.yml file data we need for the update manager. | |
* | |
* @see \Drupal\Core\Utility\ProjectInfo->processInfoList() | |
*/ | |
function filterProjectInfo($info, $additional_whitelist = array()) { | |
$whitelist = array( | |
'_info_file_ctime', | |
'datestamp', | |
'major', | |
'name', | |
'package', | |
'project', | |
'project status url', | |
'version', | |
); | |
$whitelist = array_merge($whitelist, $additional_whitelist); | |
return array_intersect_key($info, array_combine($whitelist, $whitelist)); | |
} | |
} |