1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* @copyright Copyright (c) 2016, ownCloud, Inc. |
4
|
|
|
* |
5
|
|
|
* @author Arthur Schiwon <[email protected]> |
6
|
|
|
* @author Bart Visscher <[email protected]> |
7
|
|
|
* @author Björn Schießle <[email protected]> |
8
|
|
|
* @author Frank Karlitschek <[email protected]> |
9
|
|
|
* @author Joas Schilling <[email protected]> |
10
|
|
|
* @author Lukas Reschke <[email protected]> |
11
|
|
|
* @author Morris Jobke <[email protected]> |
12
|
|
|
* @author Robin Appelman <[email protected]> |
13
|
|
|
* @author Robin McCorkell <[email protected]> |
14
|
|
|
* @author Steffen Lindner <[email protected]> |
15
|
|
|
* @author Thomas Müller <[email protected]> |
16
|
|
|
* @author Victor Dubiniuk <[email protected]> |
17
|
|
|
* @author Vincent Petry <[email protected]> |
18
|
|
|
* |
19
|
|
|
* @license AGPL-3.0 |
20
|
|
|
* |
21
|
|
|
* This code is free software: you can redistribute it and/or modify |
22
|
|
|
* it under the terms of the GNU Affero General Public License, version 3, |
23
|
|
|
* as published by the Free Software Foundation. |
24
|
|
|
* |
25
|
|
|
* This program is distributed in the hope that it will be useful, |
26
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
27
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
28
|
|
|
* GNU Affero General Public License for more details. |
29
|
|
|
* |
30
|
|
|
* You should have received a copy of the GNU Affero General Public License, version 3, |
31
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/> |
32
|
|
|
* |
33
|
|
|
*/ |
34
|
|
|
|
35
|
|
|
namespace OC; |
36
|
|
|
|
37
|
|
|
use OC\Hooks\BasicEmitter; |
38
|
|
|
use OC\IntegrityCheck\Checker; |
39
|
|
|
use OC_App; |
40
|
|
|
use OC_Installer; |
41
|
|
|
use OC_Util; |
42
|
|
|
use OCP\IConfig; |
43
|
|
|
use OC\Setup; |
44
|
|
|
use OCP\ILogger; |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* Class that handles autoupdating of ownCloud |
48
|
|
|
* |
49
|
|
|
* Hooks provided in scope \OC\Updater |
50
|
|
|
* - maintenanceStart() |
51
|
|
|
* - maintenanceEnd() |
52
|
|
|
* - dbUpgrade() |
53
|
|
|
* - failure(string $message) |
54
|
|
|
*/ |
55
|
|
|
class Updater extends BasicEmitter { |
56
|
|
|
|
57
|
|
|
/** @var ILogger $log */ |
58
|
|
|
private $log; |
59
|
|
|
|
60
|
|
|
/** @var \OC\HTTPHelper $helper */ |
61
|
|
|
private $httpHelper; |
62
|
|
|
|
63
|
|
|
/** @var IConfig */ |
64
|
|
|
private $config; |
65
|
|
|
|
66
|
|
|
/** @var Checker */ |
67
|
|
|
private $checker; |
68
|
|
|
|
69
|
|
|
/** @var bool */ |
70
|
|
|
private $simulateStepEnabled; |
71
|
|
|
|
72
|
|
|
/** @var bool */ |
73
|
|
|
private $updateStepEnabled; |
74
|
|
|
|
75
|
|
|
/** @var bool */ |
76
|
|
|
private $skip3rdPartyAppsDisable; |
77
|
|
|
|
78
|
|
|
private $logLevelNames = [ |
79
|
|
|
0 => 'Debug', |
80
|
|
|
1 => 'Info', |
81
|
|
|
2 => 'Warning', |
82
|
|
|
3 => 'Error', |
83
|
|
|
4 => 'Fatal', |
84
|
|
|
]; |
85
|
|
|
|
86
|
|
|
/** |
87
|
|
|
* @param HTTPHelper $httpHelper |
88
|
|
|
* @param IConfig $config |
89
|
|
|
* @param Checker $checker |
90
|
|
|
* @param ILogger $log |
91
|
|
|
*/ |
92
|
|
|
public function __construct(HTTPHelper $httpHelper, |
93
|
|
|
IConfig $config, |
94
|
|
|
Checker $checker, |
95
|
|
|
ILogger $log = null) { |
96
|
|
|
$this->httpHelper = $httpHelper; |
97
|
|
|
$this->log = $log; |
98
|
|
|
$this->config = $config; |
99
|
|
|
$this->checker = $checker; |
100
|
|
|
$this->simulateStepEnabled = true; |
101
|
|
|
$this->updateStepEnabled = true; |
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
/** |
105
|
|
|
* Sets whether the database migration simulation must |
106
|
|
|
* be enabled. |
107
|
|
|
* This can be set to false to skip this test. |
108
|
|
|
* |
109
|
|
|
* @param bool $flag true to enable simulation, false otherwise |
110
|
|
|
*/ |
111
|
|
|
public function setSimulateStepEnabled($flag) { |
112
|
|
|
$this->simulateStepEnabled = $flag; |
113
|
|
|
} |
114
|
|
|
|
115
|
|
|
/** |
116
|
|
|
* Sets whether the update must be performed. |
117
|
|
|
* This can be set to false to skip the actual update. |
118
|
|
|
* |
119
|
|
|
* @param bool $flag true to enable update, false otherwise |
120
|
|
|
*/ |
121
|
|
|
public function setUpdateStepEnabled($flag) { |
122
|
|
|
$this->updateStepEnabled = $flag; |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
/** |
126
|
|
|
* Sets whether the update disables 3rd party apps. |
127
|
|
|
* This can be set to true to skip the disable. |
128
|
|
|
* |
129
|
|
|
* @param bool $flag false to not disable, true otherwise |
130
|
|
|
*/ |
131
|
|
|
public function setSkip3rdPartyAppsDisable($flag) { |
132
|
|
|
$this->skip3rdPartyAppsDisable = $flag; |
133
|
|
|
} |
134
|
|
|
|
135
|
|
|
/** |
136
|
|
|
* Check if a new version is available |
137
|
|
|
* |
138
|
|
|
* @return array|bool |
139
|
|
|
*/ |
140
|
|
|
public function check() { |
141
|
|
|
|
142
|
|
|
// Look up the cache - it is invalidated all 30 minutes |
143
|
|
|
if (((int)$this->config->getAppValue('core', 'lastupdatedat') + 1800) > time()) { |
144
|
|
|
return json_decode($this->config->getAppValue('core', 'lastupdateResult'), true); |
145
|
|
|
} |
146
|
|
|
|
147
|
|
|
$updaterUrl = $this->config->getSystemValue('updater.server.url', 'https://updates.nextcloud.com/updater_server/'); |
148
|
|
|
|
149
|
|
|
$this->config->setAppValue('core', 'lastupdatedat', time()); |
150
|
|
|
|
151
|
|
|
if ($this->config->getAppValue('core', 'installedat', '') === '') { |
152
|
|
|
$this->config->setAppValue('core', 'installedat', microtime(true)); |
153
|
|
|
} |
154
|
|
|
|
155
|
|
|
$version = \OCP\Util::getVersion(); |
156
|
|
|
$version['installed'] = $this->config->getAppValue('core', 'installedat'); |
157
|
|
|
$version['updated'] = $this->config->getAppValue('core', 'lastupdatedat'); |
158
|
|
|
$version['updatechannel'] = \OC_Util::getChannel(); |
159
|
|
|
$version['edition'] = \OC_Util::getEditionString(); |
160
|
|
|
$version['build'] = \OC_Util::getBuild(); |
161
|
|
|
$versionString = implode('x', $version); |
162
|
|
|
|
163
|
|
|
//fetch xml data from updater |
164
|
|
|
$url = $updaterUrl . '?version=' . $versionString; |
165
|
|
|
|
166
|
|
|
$tmp = []; |
167
|
|
|
$xml = $this->httpHelper->getUrlContent($url); |
|
|
|
|
168
|
|
|
if ($xml) { |
169
|
|
|
$loadEntities = libxml_disable_entity_loader(true); |
170
|
|
|
$data = @simplexml_load_string($xml); |
171
|
|
|
libxml_disable_entity_loader($loadEntities); |
172
|
|
|
if ($data !== false) { |
173
|
|
|
$tmp['version'] = (string)$data->version; |
174
|
|
|
$tmp['versionstring'] = (string)$data->versionstring; |
175
|
|
|
$tmp['url'] = (string)$data->url; |
176
|
|
|
$tmp['web'] = (string)$data->web; |
177
|
|
|
$tmp['autoupdater'] = (string)$data->autoupdater; |
178
|
|
|
} else { |
179
|
|
|
libxml_clear_errors(); |
180
|
|
|
} |
181
|
|
|
} else { |
182
|
|
|
$data = []; |
183
|
|
|
} |
184
|
|
|
|
185
|
|
|
// Cache the result |
186
|
|
|
$this->config->setAppValue('core', 'lastupdateResult', json_encode($data)); |
187
|
|
|
return $tmp; |
188
|
|
|
} |
189
|
|
|
|
190
|
|
|
/** |
191
|
|
|
* runs the update actions in maintenance mode, does not upgrade the source files |
192
|
|
|
* except the main .htaccess file |
193
|
|
|
* |
194
|
|
|
* @return bool true if the operation succeeded, false otherwise |
195
|
|
|
*/ |
196
|
|
|
public function upgrade() { |
197
|
|
|
$logLevel = $this->config->getSystemValue('loglevel', \OCP\Util::WARN); |
198
|
|
|
$this->emit('\OC\Updater', 'setDebugLogLevel', [ $logLevel, $this->logLevelNames[$logLevel] ]); |
199
|
|
|
$this->config->setSystemValue('loglevel', \OCP\Util::DEBUG); |
200
|
|
|
|
201
|
|
|
$wasMaintenanceModeEnabled = $this->config->getSystemValue('maintenance', false); |
202
|
|
|
|
203
|
|
|
if(!$wasMaintenanceModeEnabled) { |
204
|
|
|
$this->config->setSystemValue('maintenance', true); |
205
|
|
|
$this->emit('\OC\Updater', 'maintenanceEnabled'); |
206
|
|
|
} |
207
|
|
|
|
208
|
|
|
$installedVersion = $this->config->getSystemValue('version', '0.0.0'); |
209
|
|
|
$currentVersion = implode('.', \OCP\Util::getVersion()); |
210
|
|
|
$this->log->debug('starting upgrade from ' . $installedVersion . ' to ' . $currentVersion, array('app' => 'core')); |
211
|
|
|
|
212
|
|
|
$success = true; |
213
|
|
|
try { |
214
|
|
|
$this->doUpgrade($currentVersion, $installedVersion); |
215
|
|
|
} catch (HintException $exception) { |
216
|
|
|
$this->log->logException($exception, ['app' => 'core']); |
217
|
|
|
$this->emit('\OC\Updater', 'failure', array($exception->getMessage() . ': ' .$exception->getHint())); |
218
|
|
|
$success = false; |
219
|
|
|
} catch (\Exception $exception) { |
220
|
|
|
$this->log->logException($exception, ['app' => 'core']); |
221
|
|
|
$this->emit('\OC\Updater', 'failure', array(get_class($exception) . ': ' .$exception->getMessage())); |
222
|
|
|
$success = false; |
223
|
|
|
} |
224
|
|
|
|
225
|
|
|
$this->emit('\OC\Updater', 'updateEnd', array($success)); |
226
|
|
|
|
227
|
|
|
if(!$wasMaintenanceModeEnabled && $success) { |
228
|
|
|
$this->config->setSystemValue('maintenance', false); |
229
|
|
|
$this->emit('\OC\Updater', 'maintenanceDisabled'); |
230
|
|
|
} else { |
231
|
|
|
$this->emit('\OC\Updater', 'maintenanceActive'); |
232
|
|
|
} |
233
|
|
|
|
234
|
|
|
$this->emit('\OC\Updater', 'resetLogLevel', [ $logLevel, $this->logLevelNames[$logLevel] ]); |
235
|
|
|
$this->config->setSystemValue('loglevel', $logLevel); |
236
|
|
|
$this->config->setSystemValue('installed', true); |
237
|
|
|
|
238
|
|
|
return $success; |
239
|
|
|
} |
240
|
|
|
|
241
|
|
|
/** |
242
|
|
|
* Return version from which this version is allowed to upgrade from |
243
|
|
|
* |
244
|
|
|
* @return string allowed previous version |
245
|
|
|
*/ |
246
|
|
|
private function getAllowedPreviousVersion() { |
247
|
|
|
// this should really be a JSON file |
248
|
|
|
require \OC::$SERVERROOT . '/version.php'; |
249
|
|
|
/** @var array $OC_VersionCanBeUpgradedFrom */ |
250
|
|
|
return implode('.', $OC_VersionCanBeUpgradedFrom); |
|
|
|
|
251
|
|
|
} |
252
|
|
|
|
253
|
|
|
/** |
254
|
|
|
* Whether an upgrade to a specified version is possible |
255
|
|
|
* @param string $oldVersion |
256
|
|
|
* @param string $newVersion |
257
|
|
|
* @param string $allowedPreviousVersion |
258
|
|
|
* @return bool |
259
|
|
|
*/ |
260
|
|
|
public function isUpgradePossible($oldVersion, $newVersion, $allowedPreviousVersion) { |
261
|
|
|
return (version_compare($allowedPreviousVersion, $oldVersion, '<=') |
262
|
|
|
&& (version_compare($oldVersion, $newVersion, '<=') || $this->config->getSystemValue('debug', false))); |
263
|
|
|
} |
264
|
|
|
|
265
|
|
|
/** |
266
|
|
|
* Forward messages emitted by the repair routine |
267
|
|
|
* |
268
|
|
|
* @param Repair $repair repair routine |
269
|
|
|
*/ |
270
|
|
|
private function emitRepairMessages(Repair $repair) { |
271
|
|
|
$repair->listen('\OC\Repair', 'warning', function ($description) { |
272
|
|
|
$this->emit('\OC\Updater', 'repairWarning', array($description)); |
273
|
|
|
}); |
274
|
|
|
$repair->listen('\OC\Repair', 'error', function ($description) { |
275
|
|
|
$this->emit('\OC\Updater', 'repairError', array($description)); |
276
|
|
|
}); |
277
|
|
|
$repair->listen('\OC\Repair', 'info', function ($description) { |
278
|
|
|
$this->emit('\OC\Updater', 'repairInfo', array($description)); |
279
|
|
|
}); |
280
|
|
|
$repair->listen('\OC\Repair', 'step', function ($description) { |
281
|
|
|
$this->emit('\OC\Updater', 'repairStep', array($description)); |
282
|
|
|
}); |
283
|
|
|
} |
284
|
|
|
|
285
|
|
|
/** |
286
|
|
|
* runs the update actions in maintenance mode, does not upgrade the source files |
287
|
|
|
* except the main .htaccess file |
288
|
|
|
* |
289
|
|
|
* @param string $currentVersion current version to upgrade to |
290
|
|
|
* @param string $installedVersion previous version from which to upgrade from |
291
|
|
|
* |
292
|
|
|
* @throws \Exception |
293
|
|
|
*/ |
294
|
|
|
private function doUpgrade($currentVersion, $installedVersion) { |
295
|
|
|
// Stop update if the update is over several major versions |
296
|
|
|
$allowedPreviousVersion = $this->getAllowedPreviousVersion(); |
297
|
|
|
if (!self::isUpgradePossible($installedVersion, $currentVersion, $allowedPreviousVersion)) { |
298
|
|
|
throw new \Exception('Updates between multiple major versions and downgrades are unsupported.'); |
299
|
|
|
} |
300
|
|
|
|
301
|
|
|
// Update .htaccess files |
302
|
|
|
try { |
303
|
|
|
Setup::updateHtaccess(); |
304
|
|
|
Setup::protectDataDirectory(); |
305
|
|
|
} catch (\Exception $e) { |
306
|
|
|
throw new \Exception($e->getMessage()); |
307
|
|
|
} |
308
|
|
|
|
309
|
|
|
// create empty file in data dir, so we can later find |
310
|
|
|
// out that this is indeed an ownCloud data directory |
311
|
|
|
// (in case it didn't exist before) |
312
|
|
|
file_put_contents($this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/.ocdata', ''); |
313
|
|
|
|
314
|
|
|
// pre-upgrade repairs |
315
|
|
|
$repair = new Repair(Repair::getBeforeUpgradeRepairSteps()); |
316
|
|
|
$this->emitRepairMessages($repair); |
317
|
|
|
$repair->run(); |
318
|
|
|
|
319
|
|
|
// simulate DB upgrade |
320
|
|
|
if ($this->simulateStepEnabled) { |
321
|
|
|
$this->checkCoreUpgrade(); |
322
|
|
|
|
323
|
|
|
// simulate apps DB upgrade |
324
|
|
|
$this->checkAppUpgrade($currentVersion); |
325
|
|
|
|
326
|
|
|
} |
327
|
|
|
|
328
|
|
|
if ($this->updateStepEnabled) { |
329
|
|
|
$this->doCoreUpgrade(); |
330
|
|
|
|
331
|
|
|
// update all shipped apps |
332
|
|
|
$disabledApps = $this->checkAppsRequirements(); |
333
|
|
|
$this->doAppUpgrade(); |
334
|
|
|
|
335
|
|
|
// upgrade appstore apps |
336
|
|
|
$this->upgradeAppStoreApps($disabledApps); |
337
|
|
|
|
338
|
|
|
// install new shipped apps on upgrade |
339
|
|
|
OC_App::loadApps('authentication'); |
340
|
|
|
$errors = OC_Installer::installShippedApps(true); |
341
|
|
|
foreach ($errors as $appId => $exception) { |
342
|
|
|
/** @var \Exception $exception */ |
343
|
|
|
$this->log->logException($exception, ['app' => $appId]); |
344
|
|
|
$this->emit('\OC\Updater', 'failure', [$appId . ': ' . $exception->getMessage()]); |
345
|
|
|
} |
346
|
|
|
|
347
|
|
|
// post-upgrade repairs |
348
|
|
|
$repair = new Repair(Repair::getRepairSteps()); |
349
|
|
|
$this->emitRepairMessages($repair); |
350
|
|
|
$repair->run(); |
351
|
|
|
|
352
|
|
|
//Invalidate update feed |
353
|
|
|
$this->config->setAppValue('core', 'lastupdatedat', 0); |
354
|
|
|
|
355
|
|
|
// Check for code integrity if not disabled |
356
|
|
|
if(\OC::$server->getIntegrityCodeChecker()->isCodeCheckEnforced()) { |
357
|
|
|
$this->emit('\OC\Updater', 'startCheckCodeIntegrity'); |
358
|
|
|
$this->checker->runInstanceVerification(); |
359
|
|
|
$this->emit('\OC\Updater', 'finishedCheckCodeIntegrity'); |
360
|
|
|
} |
361
|
|
|
|
362
|
|
|
// only set the final version if everything went well |
363
|
|
|
$this->config->setSystemValue('version', implode('.', \OCP\Util::getVersion())); |
364
|
|
|
} |
365
|
|
|
} |
366
|
|
|
|
367
|
|
|
protected function checkCoreUpgrade() { |
368
|
|
|
$this->emit('\OC\Updater', 'dbSimulateUpgradeBefore'); |
369
|
|
|
|
370
|
|
|
// simulate core DB upgrade |
371
|
|
|
\OC_DB::simulateUpdateDbFromStructure(\OC::$SERVERROOT . '/db_structure.xml'); |
372
|
|
|
|
373
|
|
|
$this->emit('\OC\Updater', 'dbSimulateUpgrade'); |
374
|
|
|
} |
375
|
|
|
|
376
|
|
|
protected function doCoreUpgrade() { |
377
|
|
|
$this->emit('\OC\Updater', 'dbUpgradeBefore'); |
378
|
|
|
|
379
|
|
|
// do the real upgrade |
380
|
|
|
\OC_DB::updateDbFromStructure(\OC::$SERVERROOT . '/db_structure.xml'); |
381
|
|
|
|
382
|
|
|
$this->emit('\OC\Updater', 'dbUpgrade'); |
383
|
|
|
} |
384
|
|
|
|
385
|
|
|
/** |
386
|
|
|
* @param string $version the oc version to check app compatibility with |
387
|
|
|
*/ |
388
|
|
|
protected function checkAppUpgrade($version) { |
389
|
|
|
$apps = \OC_App::getEnabledApps(); |
390
|
|
|
$this->emit('\OC\Updater', 'appUpgradeCheckBefore'); |
391
|
|
|
|
392
|
|
|
foreach ($apps as $appId) { |
393
|
|
|
$info = \OC_App::getAppInfo($appId); |
394
|
|
|
$compatible = \OC_App::isAppCompatible($version, $info); |
|
|
|
|
395
|
|
|
$isShipped = \OC_App::isShipped($appId); |
396
|
|
|
|
397
|
|
|
if ($compatible && $isShipped && \OC_App::shouldUpgrade($appId)) { |
398
|
|
|
/** |
399
|
|
|
* FIXME: The preupdate check is performed before the database migration, otherwise database changes |
400
|
|
|
* are not possible anymore within it. - Consider this when touching the code. |
401
|
|
|
* @link https://github.com/owncloud/core/issues/10980 |
402
|
|
|
* @see \OC_App::updateApp |
403
|
|
|
*/ |
404
|
|
|
if (file_exists(\OC_App::getAppPath($appId) . '/appinfo/preupdate.php')) { |
405
|
|
|
$this->includePreUpdate($appId); |
406
|
|
|
} |
407
|
|
|
if (file_exists(\OC_App::getAppPath($appId) . '/appinfo/database.xml')) { |
408
|
|
|
$this->emit('\OC\Updater', 'appSimulateUpdate', array($appId)); |
409
|
|
|
\OC_DB::simulateUpdateDbFromStructure(\OC_App::getAppPath($appId) . '/appinfo/database.xml'); |
410
|
|
|
} |
411
|
|
|
} |
412
|
|
|
} |
413
|
|
|
|
414
|
|
|
$this->emit('\OC\Updater', 'appUpgradeCheck'); |
415
|
|
|
} |
416
|
|
|
|
417
|
|
|
/** |
418
|
|
|
* Includes the pre-update file. Done here to prevent namespace mixups. |
419
|
|
|
* @param string $appId |
420
|
|
|
*/ |
421
|
|
|
private function includePreUpdate($appId) { |
422
|
|
|
include \OC_App::getAppPath($appId) . '/appinfo/preupdate.php'; |
423
|
|
|
} |
424
|
|
|
|
425
|
|
|
/** |
426
|
|
|
* upgrades all apps within a major ownCloud upgrade. Also loads "priority" |
427
|
|
|
* (types authentication, filesystem, logging, in that order) afterwards. |
428
|
|
|
* |
429
|
|
|
* @throws NeedsUpdateException |
430
|
|
|
*/ |
431
|
|
|
protected function doAppUpgrade() { |
432
|
|
|
$apps = \OC_App::getEnabledApps(); |
433
|
|
|
$priorityTypes = array('authentication', 'filesystem', 'logging'); |
434
|
|
|
$pseudoOtherType = 'other'; |
435
|
|
|
$stacks = array($pseudoOtherType => array()); |
436
|
|
|
|
437
|
|
|
foreach ($apps as $appId) { |
438
|
|
|
$priorityType = false; |
439
|
|
|
foreach ($priorityTypes as $type) { |
440
|
|
|
if(!isset($stacks[$type])) { |
441
|
|
|
$stacks[$type] = array(); |
442
|
|
|
} |
443
|
|
|
if (\OC_App::isType($appId, $type)) { |
444
|
|
|
$stacks[$type][] = $appId; |
445
|
|
|
$priorityType = true; |
446
|
|
|
break; |
447
|
|
|
} |
448
|
|
|
} |
449
|
|
|
if (!$priorityType) { |
450
|
|
|
$stacks[$pseudoOtherType][] = $appId; |
451
|
|
|
} |
452
|
|
|
} |
453
|
|
|
foreach ($stacks as $type => $stack) { |
454
|
|
|
foreach ($stack as $appId) { |
455
|
|
|
if (\OC_App::shouldUpgrade($appId)) { |
456
|
|
|
$this->emit('\OC\Updater', 'appUpgradeStarted', array($appId, \OC_App::getAppVersion($appId))); |
457
|
|
|
\OC_App::updateApp($appId); |
458
|
|
|
$this->emit('\OC\Updater', 'appUpgrade', array($appId, \OC_App::getAppVersion($appId))); |
459
|
|
|
} |
460
|
|
|
if($type !== $pseudoOtherType) { |
461
|
|
|
// load authentication, filesystem and logging apps after |
462
|
|
|
// upgrading them. Other apps my need to rely on modifying |
463
|
|
|
// user and/or filesystem aspects. |
464
|
|
|
\OC_App::loadApp($appId, false); |
465
|
|
|
} |
466
|
|
|
} |
467
|
|
|
} |
468
|
|
|
} |
469
|
|
|
|
470
|
|
|
/** |
471
|
|
|
* check if the current enabled apps are compatible with the current |
472
|
|
|
* ownCloud version. disable them if not. |
473
|
|
|
* This is important if you upgrade ownCloud and have non ported 3rd |
474
|
|
|
* party apps installed. |
475
|
|
|
* |
476
|
|
|
* @return array |
477
|
|
|
* @throws \Exception |
478
|
|
|
*/ |
479
|
|
|
private function checkAppsRequirements() { |
480
|
|
|
$isCoreUpgrade = $this->isCodeUpgrade(); |
481
|
|
|
$apps = OC_App::getEnabledApps(); |
482
|
|
|
$version = \OCP\Util::getVersion(); |
483
|
|
|
$disabledApps = []; |
484
|
|
|
foreach ($apps as $app) { |
485
|
|
|
// check if the app is compatible with this version of ownCloud |
486
|
|
|
$info = OC_App::getAppInfo($app); |
487
|
|
|
if(!OC_App::isAppCompatible($version, $info)) { |
|
|
|
|
488
|
|
|
OC_App::disable($app); |
489
|
|
|
$this->emit('\OC\Updater', 'incompatibleAppDisabled', array($app)); |
490
|
|
|
} |
491
|
|
|
// no need to disable any app in case this is a non-core upgrade |
492
|
|
|
if (!$isCoreUpgrade) { |
493
|
|
|
continue; |
494
|
|
|
} |
495
|
|
|
// shipped apps will remain enabled |
496
|
|
|
if (OC_App::isShipped($app)) { |
497
|
|
|
continue; |
498
|
|
|
} |
499
|
|
|
// authentication and session apps will remain enabled as well |
500
|
|
|
if (OC_App::isType($app, ['session', 'authentication'])) { |
501
|
|
|
continue; |
502
|
|
|
} |
503
|
|
|
|
504
|
|
|
// disable any other 3rd party apps if not overriden |
505
|
|
|
if(!$this->skip3rdPartyAppsDisable) { |
506
|
|
|
\OC_App::disable($app); |
507
|
|
|
$disabledApps[]= $app; |
508
|
|
|
$this->emit('\OC\Updater', 'thirdPartyAppDisabled', array($app)); |
509
|
|
|
}; |
510
|
|
|
} |
511
|
|
|
return $disabledApps; |
512
|
|
|
} |
513
|
|
|
|
514
|
|
|
/** |
515
|
|
|
* @return bool |
516
|
|
|
*/ |
517
|
|
|
private function isCodeUpgrade() { |
518
|
|
|
$installedVersion = $this->config->getSystemValue('version', '0.0.0'); |
519
|
|
|
$currentVersion = implode('.', \OCP\Util::getVersion()); |
520
|
|
|
if (version_compare($currentVersion, $installedVersion, '>')) { |
521
|
|
|
return true; |
522
|
|
|
} |
523
|
|
|
return false; |
524
|
|
|
} |
525
|
|
|
|
526
|
|
|
/** |
527
|
|
|
* @param array $disabledApps |
528
|
|
|
* @throws \Exception |
529
|
|
|
*/ |
530
|
|
|
private function upgradeAppStoreApps(array $disabledApps) { |
531
|
|
|
foreach($disabledApps as $app) { |
532
|
|
|
try { |
533
|
|
|
if (OC_Installer::isUpdateAvailable($app)) { |
|
|
|
|
534
|
|
|
$ocsId = \OC::$server->getConfig()->getAppValue($app, 'ocsid', ''); |
535
|
|
|
|
536
|
|
|
$this->emit('\OC\Updater', 'upgradeAppStoreApp', array($app)); |
537
|
|
|
OC_Installer::updateAppByOCSId($ocsId); |
538
|
|
|
} |
539
|
|
|
} catch (\Exception $ex) { |
540
|
|
|
$this->log->logException($ex, ['app' => 'core']); |
541
|
|
|
} |
542
|
|
|
} |
543
|
|
|
} |
544
|
|
|
} |
545
|
|
|
|
546
|
|
|
|
This method has been deprecated. The supplier of the class has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.