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; | |
| } | |
| } | |
| } | |
| } |