Mercurial > hg > isophonics-drupal-site
comparison core/modules/update/src/UpdateManager.php @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4c8ae668cc8c |
---|---|
1 <?php | |
2 | |
3 namespace Drupal\update; | |
4 | |
5 use Drupal\Core\Config\ConfigFactoryInterface; | |
6 use Drupal\Core\DependencyInjection\DependencySerializationTrait; | |
7 use Drupal\Core\Extension\ModuleHandlerInterface; | |
8 use Drupal\Core\Extension\ThemeHandlerInterface; | |
9 use Drupal\Core\KeyValueStore\KeyValueFactoryInterface; | |
10 use Drupal\Core\StringTranslation\TranslationInterface; | |
11 use Drupal\Core\StringTranslation\StringTranslationTrait; | |
12 use Drupal\Core\Utility\ProjectInfo; | |
13 | |
14 /** | |
15 * Default implementation of UpdateManagerInterface. | |
16 */ | |
17 class UpdateManager implements UpdateManagerInterface { | |
18 use DependencySerializationTrait; | |
19 use StringTranslationTrait; | |
20 | |
21 /** | |
22 * The update settings | |
23 * | |
24 * @var \Drupal\Core\Config\Config | |
25 */ | |
26 protected $updateSettings; | |
27 | |
28 /** | |
29 * Module Handler Service. | |
30 * | |
31 * @var \Drupal\Core\Extension\ModuleHandlerInterface | |
32 */ | |
33 protected $moduleHandler; | |
34 | |
35 /** | |
36 * Update Processor Service. | |
37 * | |
38 * @var \Drupal\update\UpdateProcessorInterface | |
39 */ | |
40 protected $updateProcessor; | |
41 | |
42 /** | |
43 * An array of installed and enabled projects. | |
44 * | |
45 * @var array | |
46 */ | |
47 protected $projects; | |
48 | |
49 /** | |
50 * The key/value store. | |
51 * | |
52 * @var \Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface | |
53 */ | |
54 protected $keyValueStore; | |
55 | |
56 /** | |
57 * Update available releases key/value store. | |
58 * | |
59 * @var \Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface | |
60 */ | |
61 protected $availableReleasesTempStore; | |
62 | |
63 /** | |
64 * The theme handler. | |
65 * | |
66 * @var \Drupal\Core\Extension\ThemeHandlerInterface | |
67 */ | |
68 protected $themeHandler; | |
69 | |
70 /** | |
71 * Constructs a UpdateManager. | |
72 * | |
73 * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory | |
74 * The config factory. | |
75 * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler | |
76 * The Module Handler service | |
77 * @param \Drupal\update\UpdateProcessorInterface $update_processor | |
78 * The Update Processor service. | |
79 * @param \Drupal\Core\StringTranslation\TranslationInterface $translation | |
80 * The translation service. | |
81 * @param \Drupal\Core\KeyValueStore\KeyValueFactoryInterface $key_value_expirable_factory | |
82 * The expirable key/value factory. | |
83 * @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler | |
84 * The theme handler. | |
85 */ | |
86 public function __construct(ConfigFactoryInterface $config_factory, ModuleHandlerInterface $module_handler, UpdateProcessorInterface $update_processor, TranslationInterface $translation, KeyValueFactoryInterface $key_value_expirable_factory, ThemeHandlerInterface $theme_handler) { | |
87 $this->updateSettings = $config_factory->get('update.settings'); | |
88 $this->moduleHandler = $module_handler; | |
89 $this->updateProcessor = $update_processor; | |
90 $this->stringTranslation = $translation; | |
91 $this->keyValueStore = $key_value_expirable_factory->get('update'); | |
92 $this->themeHandler = $theme_handler; | |
93 $this->availableReleasesTempStore = $key_value_expirable_factory->get('update_available_releases'); | |
94 $this->projects = []; | |
95 } | |
96 | |
97 /** | |
98 * {@inheritdoc} | |
99 */ | |
100 public function refreshUpdateData() { | |
101 | |
102 // Since we're fetching new available update data, we want to clear | |
103 // of both the projects we care about, and the current update status of the | |
104 // site. We do *not* want to clear the cache of available releases just yet, | |
105 // since that data (even if it's stale) can be useful during | |
106 // \Drupal\Update\UpdateManager::getProjects(); for example, to modules | |
107 // that implement hook_system_info_alter() such as cvs_deploy. | |
108 $this->keyValueStore->delete('update_project_projects'); | |
109 $this->keyValueStore->delete('update_project_data'); | |
110 | |
111 $projects = $this->getProjects(); | |
112 | |
113 // Now that we have the list of projects, we should also clear the available | |
114 // release data, since even if we fail to fetch new data, we need to clear | |
115 // out the stale data at this point. | |
116 $this->availableReleasesTempStore->deleteAll(); | |
117 | |
118 foreach ($projects as $project) { | |
119 $this->updateProcessor->createFetchTask($project); | |
120 } | |
121 } | |
122 | |
123 /** | |
124 * {@inheritdoc} | |
125 */ | |
126 public function getProjects() { | |
127 if (empty($this->projects)) { | |
128 // Retrieve the projects from storage, if present. | |
129 $this->projects = $this->projectStorage('update_project_projects'); | |
130 if (empty($this->projects)) { | |
131 // Still empty, so we have to rebuild. | |
132 $module_data = system_rebuild_module_data(); | |
133 $theme_data = $this->themeHandler->rebuildThemeData(); | |
134 $project_info = new ProjectInfo(); | |
135 $project_info->processInfoList($this->projects, $module_data, 'module', TRUE); | |
136 $project_info->processInfoList($this->projects, $theme_data, 'theme', TRUE); | |
137 if ($this->updateSettings->get('check.disabled_extensions')) { | |
138 $project_info->processInfoList($this->projects, $module_data, 'module', FALSE); | |
139 $project_info->processInfoList($this->projects, $theme_data, 'theme', FALSE); | |
140 } | |
141 // Allow other modules to alter projects before fetching and comparing. | |
142 $this->moduleHandler->alter('update_projects', $this->projects); | |
143 // Store the site's project data for at most 1 hour. | |
144 $this->keyValueStore->setWithExpire('update_project_projects', $this->projects, 3600); | |
145 } | |
146 } | |
147 return $this->projects; | |
148 } | |
149 | |
150 /** | |
151 * {@inheritdoc} | |
152 */ | |
153 public function projectStorage($key) { | |
154 $projects = []; | |
155 | |
156 // On certain paths, we should clear the data and recompute the projects for | |
157 // update status of the site to avoid presenting stale information. | |
158 $route_names = [ | |
159 'update.theme_update', | |
160 'system.modules_list', | |
161 'system.theme_install', | |
162 'update.module_update', | |
163 'update.module_install', | |
164 'update.status', | |
165 'update.report_update', | |
166 'update.report_install', | |
167 'update.settings', | |
168 'system.status', | |
169 'update.manual_status', | |
170 'update.confirmation_page', | |
171 'system.themes_page', | |
172 ]; | |
173 if (in_array(\Drupal::routeMatch()->getRouteName(), $route_names)) { | |
174 $this->keyValueStore->delete($key); | |
175 } | |
176 else { | |
177 $projects = $this->keyValueStore->get($key, []); | |
178 } | |
179 return $projects; | |
180 } | |
181 | |
182 /** | |
183 * {@inheritdoc} | |
184 */ | |
185 public function fetchDataBatch(&$context) { | |
186 if (empty($context['sandbox']['max'])) { | |
187 $context['finished'] = 0; | |
188 $context['sandbox']['max'] = $this->updateProcessor->numberOfQueueItems(); | |
189 $context['sandbox']['progress'] = 0; | |
190 $context['message'] = $this->t('Checking available update data ...'); | |
191 $context['results']['updated'] = 0; | |
192 $context['results']['failures'] = 0; | |
193 $context['results']['processed'] = 0; | |
194 } | |
195 | |
196 // Grab another item from the fetch queue. | |
197 for ($i = 0; $i < 5; $i++) { | |
198 if ($item = $this->updateProcessor->claimQueueItem()) { | |
199 if ($this->updateProcessor->processFetchTask($item->data)) { | |
200 $context['results']['updated']++; | |
201 $context['message'] = $this->t('Checked available update data for %title.', ['%title' => $item->data['info']['name']]); | |
202 } | |
203 else { | |
204 $context['message'] = $this->t('Failed to check available update data for %title.', ['%title' => $item->data['info']['name']]); | |
205 $context['results']['failures']++; | |
206 } | |
207 $context['sandbox']['progress']++; | |
208 $context['results']['processed']++; | |
209 $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max']; | |
210 $this->updateProcessor->deleteQueueItem($item); | |
211 } | |
212 else { | |
213 // If the queue is currently empty, we're done. It's possible that | |
214 // another thread might have added new fetch tasks while we were | |
215 // processing this batch. In that case, the usual 'finished' math could | |
216 // get confused, since we'd end up processing more tasks that we thought | |
217 // we had when we started and initialized 'max' with numberOfItems(). By | |
218 // forcing 'finished' to be exactly 1 here, we ensure that batch | |
219 // processing is terminated. | |
220 $context['finished'] = 1; | |
221 return; | |
222 } | |
223 } | |
224 } | |
225 | |
226 } |