Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
0.00% |
0 / 1 |
|
0.00% |
0 / 5 |
CRAP | |
0.00% |
0 / 89 |
UpdateManager | |
0.00% |
0 / 1 |
|
0.00% |
0 / 5 |
210 | |
0.00% |
0 / 89 |
__construct | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 9 |
|||
refreshUpdateData | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 8 |
|||
getProjects | |
0.00% |
0 / 1 |
20 | |
0.00% |
0 / 18 |
|||
projectStorage | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 24 |
|||
fetchDataBatch | |
0.00% |
0 / 1 |
30 | |
0.00% |
0 / 30 |
<?php | |
/** | |
* @file | |
* Contains \Drupal\update\UpdateManager. | |
*/ | |
namespace Drupal\update; | |
use Drupal\Core\Config\ConfigFactoryInterface; | |
use Drupal\Core\DependencyInjection\DependencySerializationTrait; | |
use Drupal\Core\Extension\ModuleHandlerInterface; | |
use Drupal\Core\Extension\ThemeHandlerInterface; | |
use Drupal\Core\KeyValueStore\KeyValueFactoryInterface; | |
use Drupal\Core\StringTranslation\TranslationInterface; | |
use Drupal\Core\StringTranslation\StringTranslationTrait; | |
use Drupal\Core\Utility\ProjectInfo; | |
/** | |
* Default implementation of UpdateManagerInterface. | |
*/ | |
class UpdateManager implements UpdateManagerInterface { | |
use DependencySerializationTrait; | |
use StringTranslationTrait; | |
/** | |
* The update settings | |
* | |
* @var \Drupal\Core\Config\Config | |
*/ | |
protected $updateSettings; | |
/** | |
* Module Handler Service. | |
* | |
* @var \Drupal\Core\Extension\ModuleHandlerInterface | |
*/ | |
protected $moduleHandler; | |
/** | |
* Update Processor Service. | |
* | |
* @var \Drupal\update\UpdateProcessorInterface | |
*/ | |
protected $updateProcessor; | |
/** | |
* An array of installed and enabled projects. | |
* | |
* @var array | |
*/ | |
protected $projects; | |
/** | |
* The key/value store. | |
* | |
* @var \Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface | |
*/ | |
protected $keyValueStore; | |
/** | |
* Update available releases key/value store. | |
* | |
* @var \Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface | |
*/ | |
protected $availableReleasesTempStore; | |
/** | |
* The theme handler. | |
* | |
* @var \Drupal\Core\Extension\ThemeHandlerInterface | |
*/ | |
protected $themeHandler; | |
/** | |
* Constructs a UpdateManager. | |
* | |
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory | |
* The config factory. | |
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler | |
* The Module Handler service | |
* @param \Drupal\update\UpdateProcessorInterface $update_processor | |
* The Update Processor service. | |
* @param \Drupal\Core\StringTranslation\TranslationInterface $translation | |
* The translation service. | |
* @param \Drupal\Core\KeyValueStore\KeyValueFactoryInterface $key_value_expirable_factory | |
* The expirable key/value factory. | |
* @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler | |
* The theme handler. | |
*/ | |
public function __construct(ConfigFactoryInterface $config_factory, ModuleHandlerInterface $module_handler, UpdateProcessorInterface $update_processor, TranslationInterface $translation, KeyValueFactoryInterface $key_value_expirable_factory, ThemeHandlerInterface $theme_handler) { | |
$this->updateSettings = $config_factory->get('update.settings'); | |
$this->moduleHandler = $module_handler; | |
$this->updateProcessor = $update_processor; | |
$this->stringTranslation = $translation; | |
$this->keyValueStore = $key_value_expirable_factory->get('update'); | |
$this->themeHandler = $theme_handler; | |
$this->availableReleasesTempStore = $key_value_expirable_factory->get('update_available_releases'); | |
$this->projects = array(); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function refreshUpdateData() { | |
// Since we're fetching new available update data, we want to clear | |
// of both the projects we care about, and the current update status of the | |
// site. We do *not* want to clear the cache of available releases just yet, | |
// since that data (even if it's stale) can be useful during | |
// \Drupal\Update\UpdateManager::getProjects(); for example, to modules | |
// that implement hook_system_info_alter() such as cvs_deploy. | |
$this->keyValueStore->delete('update_project_projects'); | |
$this->keyValueStore->delete('update_project_data'); | |
$projects = $this->getProjects(); | |
// Now that we have the list of projects, we should also clear the available | |
// release data, since even if we fail to fetch new data, we need to clear | |
// out the stale data at this point. | |
$this->availableReleasesTempStore->deleteAll(); | |
foreach ($projects as $project) { | |
$this->updateProcessor->createFetchTask($project); | |
} | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function getProjects() { | |
if (empty($this->projects)) { | |
// Retrieve the projects from storage, if present. | |
$this->projects = $this->projectStorage('update_project_projects'); | |
if (empty($this->projects)) { | |
// Still empty, so we have to rebuild. | |
$module_data = system_rebuild_module_data(); | |
$theme_data = $this->themeHandler->rebuildThemeData(); | |
$project_info = new ProjectInfo(); | |
$project_info->processInfoList($this->projects, $module_data, 'module', TRUE); | |
$project_info->processInfoList($this->projects, $theme_data, 'theme', TRUE); | |
if ($this->updateSettings->get('check.disabled_extensions')) { | |
$project_info->processInfoList($this->projects, $module_data, 'module', FALSE); | |
$project_info->processInfoList($this->projects, $theme_data, 'theme', FALSE); | |
} | |
// Allow other modules to alter projects before fetching and comparing. | |
$this->moduleHandler->alter('update_projects', $this->projects); | |
// Store the site's project data for at most 1 hour. | |
$this->keyValueStore->setWithExpire('update_project_projects', $this->projects, 3600); | |
} | |
} | |
return $this->projects; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function projectStorage($key) { | |
$projects = array(); | |
// On certain paths, we should clear the data and recompute the projects for | |
// update status of the site to avoid presenting stale information. | |
$route_names = array( | |
'update.theme_update', | |
'system.modules_list', | |
'system.theme_install', | |
'update.module_update', | |
'update.module_install', | |
'update.status', | |
'update.report_update', | |
'update.report_install', | |
'update.settings', | |
'system.status', | |
'update.manual_status', | |
'update.confirmation_page', | |
'system.themes_page', | |
); | |
if (in_array(\Drupal::routeMatch()->getRouteName(), $route_names)) { | |
$this->keyValueStore->delete($key); | |
} | |
else { | |
$projects = $this->keyValueStore->get($key, array()); | |
} | |
return $projects; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function fetchDataBatch(&$context) { | |
if (empty($context['sandbox']['max'])) { | |
$context['finished'] = 0; | |
$context['sandbox']['max'] = $this->updateProcessor->numberOfQueueItems(); | |
$context['sandbox']['progress'] = 0; | |
$context['message'] = $this->t('Checking available update data ...'); | |
$context['results']['updated'] = 0; | |
$context['results']['failures'] = 0; | |
$context['results']['processed'] = 0; | |
} | |
// Grab another item from the fetch queue. | |
for ($i = 0; $i < 5; $i++) { | |
if ($item = $this->updateProcessor->claimQueueItem()) { | |
if ($this->updateProcessor->processFetchTask($item->data)) { | |
$context['results']['updated']++; | |
$context['message'] = $this->t('Checked available update data for %title.', array('%title' => $item->data['info']['name'])); | |
} | |
else { | |
$context['message'] = $this->t('Failed to check available update data for %title.', array('%title' => $item->data['info']['name'])); | |
$context['results']['failures']++; | |
} | |
$context['sandbox']['progress']++; | |
$context['results']['processed']++; | |
$context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max']; | |
$this->updateProcessor->deleteQueueItem($item); | |
} | |
else { | |
// If the queue is currently empty, we're done. It's possible that | |
// another thread might have added new fetch tasks while we were | |
// processing this batch. In that case, the usual 'finished' math could | |
// get confused, since we'd end up processing more tasks that we thought | |
// we had when we started and initialized 'max' with numberOfItems(). By | |
// forcing 'finished' to be exactly 1 here, we ensure that batch | |
// processing is terminated. | |
$context['finished'] = 1; | |
return; | |
} | |
} | |
} | |
} |