Issue #2030775 by Sutharsan, webflo: Reduce dependency of Locale on Update module .
parent
9dbbb4dd98
commit
c56cb20453
|
@ -0,0 +1,229 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Contains \Drupal\Core\Utility\ProjectInfo.
|
||||||
|
*
|
||||||
|
* API for building lists of installed projects.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Drupal\Core\Utility;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 disabled
|
||||||
|
* modules or themes are being processed (there is a setting to control if
|
||||||
|
* disabled 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 are always ignored.
|
||||||
|
* 'Hidden' themes are ignored only if they have no enabled sub-themes.
|
||||||
|
* 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 $projects
|
||||||
|
* Reference to the array of project data of what's installed on this site.
|
||||||
|
* @param $list
|
||||||
|
* Array of data to process to add the relevant info to the $projects array.
|
||||||
|
* @param $project_type
|
||||||
|
* The kind of data in the list. Can be 'module' or 'theme'.
|
||||||
|
* @param $status
|
||||||
|
* Boolean that controls what status (enabled or disabled) to process out of
|
||||||
|
* the $list and add to the $projects array.
|
||||||
|
* @param $additional_whitelist
|
||||||
|
* (optional) Array of additional elements to be collected from the .info.yml
|
||||||
|
* file. Defaults to array().
|
||||||
|
*/
|
||||||
|
function processInfoList(&$projects, $list, $project_type, $status, $additional_whitelist = array()) {
|
||||||
|
foreach ($list as $file) {
|
||||||
|
// A disabled or hidden base theme of an enabled sub-theme still has all
|
||||||
|
// of its code run by the sub-theme, so we include it in our "enabled"
|
||||||
|
// projects list.
|
||||||
|
if ($status && !empty($file->sub_themes)) {
|
||||||
|
foreach ($file->sub_themes as $key => $name) {
|
||||||
|
// Build a list of enabled sub-themes.
|
||||||
|
if ($list[$key]->status) {
|
||||||
|
$file->enabled_sub_themes[$key] = $name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If the theme is disabled and there are no enabled subthemes, we
|
||||||
|
// should ignore this base theme for the enabled case. If the site is
|
||||||
|
// trying to display disabled themes, we'll catch it then.
|
||||||
|
if (!$file->status && empty($file->enabled_sub_themes)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Otherwise, just add projects of the proper status to our list.
|
||||||
|
elseif ($file->status != $status) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip if the .info.yml file is broken.
|
||||||
|
if (empty($file->info)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip if it's a hidden module or hidden theme without enabled sub-themes.
|
||||||
|
if (!empty($file->info['hidden']) && empty($file->enabled_sub_themes)) {
|
||||||
|
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'])) {
|
||||||
|
$info_filename = dirname($file->uri) . '/' . $file->name . '.info.yml';
|
||||||
|
$file->info['_info_file_ctime'] = filectime($info_filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
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) && empty($file->enabled_sub_themes)) {
|
||||||
|
// If we're processing disabled modules or themes, append a suffix.
|
||||||
|
// However, we don't do this to a a base theme with enabled
|
||||||
|
// subthemes, since we treat that case as if it is enabled.
|
||||||
|
$project_display_type .= '-disabled';
|
||||||
|
}
|
||||||
|
// Add a list of sub-themes that "depend on" the project and a list of base
|
||||||
|
// themes that are "required by" the project.
|
||||||
|
if ($project_name == 'drupal') {
|
||||||
|
// Drupal core is always required, so this extra info would be noise.
|
||||||
|
$sub_themes = array();
|
||||||
|
$base_themes = array();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Add list of enabled sub-themes.
|
||||||
|
$sub_themes = !empty($file->enabled_sub_themes) ? $file->enabled_sub_themes : array();
|
||||||
|
// Add list of base themes.
|
||||||
|
$base_themes = !empty($file->base_themes) ? $file->base_themes : array();
|
||||||
|
}
|
||||||
|
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->name => $file->info['name']),
|
||||||
|
'project_type' => $project_display_type,
|
||||||
|
'project_status' => $status,
|
||||||
|
'sub_themes' => $sub_themes,
|
||||||
|
'base_themes' => $base_themes,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
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 disabled
|
||||||
|
// modules included with an enabled project if we happen to be checking
|
||||||
|
// for disabled modules, too.
|
||||||
|
$projects[$project_name]['includes'][$file->name] = $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']);
|
||||||
|
if (!empty($sub_themes)) {
|
||||||
|
$projects[$project_name]['sub_themes'] += $sub_themes;
|
||||||
|
}
|
||||||
|
if (!empty($base_themes)) {
|
||||||
|
$projects[$project_name]['base_themes'] += $base_themes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elseif (empty($status)) {
|
||||||
|
// If we have a project_name that matches, but the project_display_type
|
||||||
|
// does not, it means we're processing a disabled module or theme that
|
||||||
|
// belongs to a project that has some enabled code. In this case, we add
|
||||||
|
// the disabled thing into a separate array for separate display.
|
||||||
|
$projects[$project_name]['disabled'][$file->name] = $file->info['name'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines what project a given file object belongs to.
|
||||||
|
*
|
||||||
|
* @param $file
|
||||||
|
* A file object as returned by system_get_files_database().
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The canonical project short name.
|
||||||
|
*
|
||||||
|
* @see system_get_files_database()
|
||||||
|
*/
|
||||||
|
function getProjectName($file) {
|
||||||
|
$project_name = '';
|
||||||
|
if (isset($file->info['project'])) {
|
||||||
|
$project_name = $file->info['project'];
|
||||||
|
}
|
||||||
|
elseif (isset($file->filename) && (strpos($file->filename, '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_parse_info_file().
|
||||||
|
* @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, drupal_map_assoc($whitelist));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -6,9 +6,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Drupal\Core\Cache;
|
use Drupal\Core\Cache;
|
||||||
|
use Drupal\Core\Utility\ProjectInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load the common translation API.
|
* Load common APIs.
|
||||||
*/
|
*/
|
||||||
// @todo Combine functions differently in files to avoid unnecessary includes.
|
// @todo Combine functions differently in files to avoid unnecessary includes.
|
||||||
// Follow-up issue http://drupal.org/node/1834298
|
// Follow-up issue http://drupal.org/node/1834298
|
||||||
|
@ -126,11 +127,6 @@ function locale_translation_build_projects() {
|
||||||
* Array of project data including .info.yml file data.
|
* Array of project data including .info.yml file data.
|
||||||
*/
|
*/
|
||||||
function locale_translation_project_list() {
|
function locale_translation_project_list() {
|
||||||
// This function depends on Update module. We degrade gracefully.
|
|
||||||
if (!Drupal::moduleHandler()->moduleExists('update')) {
|
|
||||||
return array();
|
|
||||||
}
|
|
||||||
|
|
||||||
$projects = &drupal_static(__FUNCTION__, array());
|
$projects = &drupal_static(__FUNCTION__, array());
|
||||||
if (empty($projects)) {
|
if (empty($projects)) {
|
||||||
module_load_include('compare.inc', 'update');
|
module_load_include('compare.inc', 'update');
|
||||||
|
@ -143,11 +139,12 @@ function locale_translation_project_list() {
|
||||||
);
|
);
|
||||||
$module_data = _locale_translation_prepare_project_list(system_rebuild_module_data(), 'module');
|
$module_data = _locale_translation_prepare_project_list(system_rebuild_module_data(), 'module');
|
||||||
$theme_data = _locale_translation_prepare_project_list(system_rebuild_theme_data(), 'theme');
|
$theme_data = _locale_translation_prepare_project_list(system_rebuild_theme_data(), 'theme');
|
||||||
update_process_info_list($projects, $module_data, 'module', TRUE, $additional_whitelist);
|
$project_info = new ProjectInfo();
|
||||||
update_process_info_list($projects, $theme_data, 'theme', TRUE, $additional_whitelist);
|
$project_info->processInfoList($projects, $module_data, 'module', TRUE, $additional_whitelist);
|
||||||
|
$project_info->processInfoList($projects, $theme_data, 'theme', TRUE, $additional_whitelist);
|
||||||
if ($config->get('translation.check_disabled_modules')) {
|
if ($config->get('translation.check_disabled_modules')) {
|
||||||
update_process_info_list($projects, $module_data, 'module', FALSE, $additional_whitelist);
|
$project_info->processInfoList($projects, $module_data, 'module', FALSE, $additional_whitelist);
|
||||||
update_process_info_list($projects, $theme_data, 'theme', FALSE, $additional_whitelist);
|
$project_info->processInfoList($projects, $theme_data, 'theme', FALSE, $additional_whitelist);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allow other modules to alter projects before fetching and comparing.
|
// Allow other modules to alter projects before fetching and comparing.
|
||||||
|
@ -159,9 +156,10 @@ function locale_translation_project_list() {
|
||||||
/**
|
/**
|
||||||
* Prepare module and theme data.
|
* Prepare module and theme data.
|
||||||
*
|
*
|
||||||
* Modify .info.yml file data before it is processed by update_process_info_list().
|
* Modify .info.yml file data before it is processed by
|
||||||
* In order for update_process_info_list() to recognize a project, it requires
|
* \Drupal\Core\Utility\ProjectInfo->processInfoList(). In order for
|
||||||
* the 'project' parameter in the .info.yml file data.
|
* \Drupal\Core\Utility\ProjectInfo->processInfoList() to recognize a project,
|
||||||
|
* it requires the 'project' parameter in the .info.yml file data.
|
||||||
*
|
*
|
||||||
* Custom modules or themes can bring their own gettext translation file. To
|
* Custom modules or themes can bring their own gettext translation file. To
|
||||||
* enable import of this file the module or theme defines "interface translation
|
* enable import of this file the module or theme defines "interface translation
|
||||||
|
@ -179,8 +177,9 @@ function locale_translation_project_list() {
|
||||||
function _locale_translation_prepare_project_list($data, $type) {
|
function _locale_translation_prepare_project_list($data, $type) {
|
||||||
foreach ($data as $name => $file) {
|
foreach ($data as $name => $file) {
|
||||||
// Include interface translation projects. To allow
|
// Include interface translation projects. To allow
|
||||||
// update_process_info_list() to identify this as a project the 'project'
|
// \Drupal\Core\Utility\ProjectInfo->processInfoList() to identify this as
|
||||||
// property is filled with the 'interface translation project' value.
|
// a project the 'project' property is filled with the
|
||||||
|
// 'interface translation project' value.
|
||||||
if (isset($file->info['interface translation project'])) {
|
if (isset($file->info['interface translation project'])) {
|
||||||
$data[$name]->info['project'] = $file->info['interface translation project'];
|
$data[$name]->info['project'] = $file->info['interface translation project'];
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
|
|
||||||
namespace Drupal\update\Tests;
|
namespace Drupal\update\Tests;
|
||||||
|
|
||||||
|
use Drupal\Core\Utility\ProjectInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests behavior related to handling updates to contributed modules and themes.
|
* Tests behavior related to handling updates to contributed modules and themes.
|
||||||
*/
|
*/
|
||||||
|
@ -287,7 +289,8 @@ class UpdateContribTest extends UpdateTestBase {
|
||||||
config('update_test.settings')->set('system_info', $system_info)->save();
|
config('update_test.settings')->set('system_info', $system_info)->save();
|
||||||
$projects = update_get_projects();
|
$projects = update_get_projects();
|
||||||
$theme_data = system_rebuild_theme_data();
|
$theme_data = system_rebuild_theme_data();
|
||||||
update_process_info_list($projects, $theme_data, 'theme', TRUE);
|
$project_info = new ProjectInfo();
|
||||||
|
$project_info->processInfoList($projects, $theme_data, 'theme', TRUE);
|
||||||
|
|
||||||
$this->assertTrue(!empty($projects['update_test_basetheme']), 'Valid base theme (update_test_basetheme) was found.');
|
$this->assertTrue(!empty($projects['update_test_basetheme']), 'Valid base theme (update_test_basetheme) was found.');
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,11 +28,11 @@
|
||||||
* includes all the metadata documented in the comments below for each project
|
* includes all the metadata documented in the comments below for each project
|
||||||
* (either module or theme) that is currently enabled. The array is initially
|
* (either module or theme) that is currently enabled. The array is initially
|
||||||
* populated inside update_get_projects() with the help of
|
* populated inside update_get_projects() with the help of
|
||||||
* update_process_info_list(), so look there for examples of how to populate
|
* \Drupal\Core\Utility\ProjectInfo->processInfoList(), so look there for
|
||||||
* the array with real values.
|
* examples of how to populate the array with real values.
|
||||||
*
|
*
|
||||||
* @see update_get_projects()
|
* @see update_get_projects()
|
||||||
* @see update_process_info_list()
|
* @see \Drupal\Core\Utility\ProjectInfo->processInfoList()
|
||||||
*/
|
*/
|
||||||
function hook_update_projects_alter(&$projects) {
|
function hook_update_projects_alter(&$projects) {
|
||||||
// Hide a site-specific module from the list.
|
// Hide a site-specific module from the list.
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
* Code required only when comparing available updates to existing data.
|
* Code required only when comparing available updates to existing data.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use Drupal\Core\Utility\ProjectInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches an array of installed and enabled projects.
|
* Fetches an array of installed and enabled projects.
|
||||||
*
|
*
|
||||||
|
@ -61,11 +63,12 @@ function update_get_projects() {
|
||||||
// Still empty, so we have to rebuild.
|
// Still empty, so we have to rebuild.
|
||||||
$module_data = system_rebuild_module_data();
|
$module_data = system_rebuild_module_data();
|
||||||
$theme_data = system_rebuild_theme_data();
|
$theme_data = system_rebuild_theme_data();
|
||||||
update_process_info_list($projects, $module_data, 'module', TRUE);
|
$project_info = new ProjectInfo();
|
||||||
update_process_info_list($projects, $theme_data, 'theme', TRUE);
|
$project_info->processInfoList($projects, $module_data, 'module', TRUE);
|
||||||
|
$project_info->processInfoList($projects, $theme_data, 'theme', TRUE);
|
||||||
if (config('update.settings')->get('check.disabled_extensions')) {
|
if (config('update.settings')->get('check.disabled_extensions')) {
|
||||||
update_process_info_list($projects, $module_data, 'module', FALSE);
|
$project_info->processInfoList($projects, $module_data, 'module', FALSE);
|
||||||
update_process_info_list($projects, $theme_data, 'theme', FALSE);
|
$project_info->processInfoList($projects, $theme_data, 'theme', FALSE);
|
||||||
}
|
}
|
||||||
// Allow other modules to alter projects before fetching and comparing.
|
// Allow other modules to alter projects before fetching and comparing.
|
||||||
drupal_alter('update_projects', $projects);
|
drupal_alter('update_projects', $projects);
|
||||||
|
@ -76,191 +79,6 @@ function update_get_projects() {
|
||||||
return $projects;
|
return $projects;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 disabled
|
|
||||||
* modules or themes are being processed (there is a setting to control if
|
|
||||||
* disabled 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 are always ignored.
|
|
||||||
* 'Hidden' themes are ignored only if they have no enabled sub-themes.
|
|
||||||
* 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 $projects
|
|
||||||
* Reference to the array of project data of what's installed on this site.
|
|
||||||
* @param $list
|
|
||||||
* Array of data to process to add the relevant info to the $projects array.
|
|
||||||
* @param $project_type
|
|
||||||
* The kind of data in the list. Can be 'module' or 'theme'.
|
|
||||||
* @param $status
|
|
||||||
* Boolean that controls what status (enabled or disabled) to process out of
|
|
||||||
* the $list and add to the $projects array.
|
|
||||||
* @param $additional_whitelist
|
|
||||||
* (optional) Array of additional elements to be collected from the .info.yml
|
|
||||||
* file. Defaults to array().
|
|
||||||
*
|
|
||||||
* @see update_get_projects()
|
|
||||||
*/
|
|
||||||
function update_process_info_list(&$projects, $list, $project_type, $status, $additional_whitelist = array()) {
|
|
||||||
foreach ($list as $file) {
|
|
||||||
// A disabled or hidden base theme of an enabled sub-theme still has all
|
|
||||||
// of its code run by the sub-theme, so we include it in our "enabled"
|
|
||||||
// projects list.
|
|
||||||
if ($status && !empty($file->sub_themes)) {
|
|
||||||
foreach ($file->sub_themes as $key => $name) {
|
|
||||||
// Build a list of enabled sub-themes.
|
|
||||||
if ($list[$key]->status) {
|
|
||||||
$file->enabled_sub_themes[$key] = $name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// If the theme is disabled and there are no enabled subthemes, we
|
|
||||||
// should ignore this base theme for the enabled case. If the site is
|
|
||||||
// trying to display disabled themes, we'll catch it then.
|
|
||||||
if (!$file->status && empty($file->enabled_sub_themes)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Otherwise, just add projects of the proper status to our list.
|
|
||||||
elseif ($file->status != $status) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip if the .info.yml file is broken.
|
|
||||||
if (empty($file->info)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip if it's a hidden module or hidden theme without enabled sub-themes.
|
|
||||||
if (!empty($file->info['hidden']) && empty($file->enabled_sub_themes)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the .info.yml doesn't define the 'project', try to figure it out.
|
|
||||||
if (!isset($file->info['project'])) {
|
|
||||||
$file->info['project'] = update_get_project_name($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'])) {
|
|
||||||
$info_filename = dirname($file->uri) . '/' . $file->name . '.info.yml';
|
|
||||||
$file->info['_info_file_ctime'] = filectime($info_filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
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) && empty($file->enabled_sub_themes)) {
|
|
||||||
// If we're processing disabled modules or themes, append a suffix.
|
|
||||||
// However, we don't do this to a a base theme with enabled
|
|
||||||
// subthemes, since we treat that case as if it is enabled.
|
|
||||||
$project_display_type .= '-disabled';
|
|
||||||
}
|
|
||||||
// Add a list of sub-themes that "depend on" the project and a list of base
|
|
||||||
// themes that are "required by" the project.
|
|
||||||
if ($project_name == 'drupal') {
|
|
||||||
// Drupal core is always required, so this extra info would be noise.
|
|
||||||
$sub_themes = array();
|
|
||||||
$base_themes = array();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Add list of enabled sub-themes.
|
|
||||||
$sub_themes = !empty($file->enabled_sub_themes) ? $file->enabled_sub_themes : array();
|
|
||||||
// Add list of base themes.
|
|
||||||
$base_themes = !empty($file->base_themes) ? $file->base_themes : array();
|
|
||||||
}
|
|
||||||
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' => update_filter_project_info($file->info, $additional_whitelist),
|
|
||||||
'datestamp' => $file->info['datestamp'],
|
|
||||||
'includes' => array($file->name => $file->info['name']),
|
|
||||||
'project_type' => $project_display_type,
|
|
||||||
'project_status' => $status,
|
|
||||||
'sub_themes' => $sub_themes,
|
|
||||||
'base_themes' => $base_themes,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
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 disabled
|
|
||||||
// modules included with an enabled project if we happen to be checking
|
|
||||||
// for disabled modules, too.
|
|
||||||
$projects[$project_name]['includes'][$file->name] = $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']);
|
|
||||||
if (!empty($sub_themes)) {
|
|
||||||
$projects[$project_name]['sub_themes'] += $sub_themes;
|
|
||||||
}
|
|
||||||
if (!empty($base_themes)) {
|
|
||||||
$projects[$project_name]['base_themes'] += $base_themes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
elseif (empty($status)) {
|
|
||||||
// If we have a project_name that matches, but the project_display_type
|
|
||||||
// does not, it means we're processing a disabled module or theme that
|
|
||||||
// belongs to a project that has some enabled code. In this case, we add
|
|
||||||
// the disabled thing into a separate array for separate display.
|
|
||||||
$projects[$project_name]['disabled'][$file->name] = $file->info['name'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines what project a given file object belongs to.
|
|
||||||
*
|
|
||||||
* @param $file
|
|
||||||
* A file object as returned by system_get_files_database().
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* The canonical project short name.
|
|
||||||
*
|
|
||||||
* @see system_get_files_database()
|
|
||||||
*/
|
|
||||||
function update_get_project_name($file) {
|
|
||||||
$project_name = '';
|
|
||||||
if (isset($file->info['project'])) {
|
|
||||||
$project_name = $file->info['project'];
|
|
||||||
}
|
|
||||||
elseif (isset($file->filename) && (strpos($file->filename, 'core/modules') === 0)) {
|
|
||||||
$project_name = 'drupal';
|
|
||||||
}
|
|
||||||
return $project_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines version and type information for currently installed projects.
|
* Determines version and type information for currently installed projects.
|
||||||
*
|
*
|
||||||
|
@ -800,32 +618,3 @@ function update_project_storage($key) {
|
||||||
}
|
}
|
||||||
return $projects;
|
return $projects;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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_parse_info_file().
|
|
||||||
* @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 update_process_info_list()
|
|
||||||
*/
|
|
||||||
function update_filter_project_info($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, drupal_map_assoc($whitelist));
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue