You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

624 lines
23 KiB

3 years ago
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016, ownCloud, Inc.
  4. * @copyright Copyright (c) 2016, Lukas Reschke <lukas@statuscode.ch>
  5. *
  6. * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
  7. * @author Bjoern Schiessle <bjoern@schiessle.org>
  8. * @author Christoph Wurst <christoph@winzerhof-wurst.at>
  9. * @author Frank Karlitschek <frank@karlitschek.de>
  10. * @author Georg Ehrke <oc.list@georgehrke.com>
  11. * @author Joas Schilling <coding@schilljs.com>
  12. * @author Lukas Reschke <lukas@statuscode.ch>
  13. * @author Morris Jobke <hey@morrisjobke.de>
  14. * @author Robin Appelman <robin@icewind.nl>
  15. * @author Roeland Jago Douma <roeland@famdouma.nl>
  16. * @author Steffen Lindner <mail@steffen-lindner.de>
  17. * @author Thomas Müller <thomas.mueller@tmit.eu>
  18. * @author Victor Dubiniuk <dubiniuk@owncloud.com>
  19. * @author Vincent Petry <pvince81@owncloud.com>
  20. *
  21. * @license AGPL-3.0
  22. *
  23. * This code is free software: you can redistribute it and/or modify
  24. * it under the terms of the GNU Affero General Public License, version 3,
  25. * as published by the Free Software Foundation.
  26. *
  27. * This program is distributed in the hope that it will be useful,
  28. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  29. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  30. * GNU Affero General Public License for more details.
  31. *
  32. * You should have received a copy of the GNU Affero General Public License, version 3,
  33. * along with this program. If not, see <http://www.gnu.org/licenses/>
  34. *
  35. */
  36. namespace OC;
  37. use OC\DB\MigrationService;
  38. use OC\Hooks\BasicEmitter;
  39. use OC\IntegrityCheck\Checker;
  40. use OC_App;
  41. use OCP\IConfig;
  42. use OCP\ILogger;
  43. use OCP\Util;
  44. use Symfony\Component\EventDispatcher\GenericEvent;
  45. /**
  46. * Class that handles autoupdating of ownCloud
  47. *
  48. * Hooks provided in scope \OC\Updater
  49. * - maintenanceStart()
  50. * - maintenanceEnd()
  51. * - dbUpgrade()
  52. * - failure(string $message)
  53. */
  54. class Updater extends BasicEmitter {
  55. /** @var ILogger $log */
  56. private $log;
  57. /** @var IConfig */
  58. private $config;
  59. /** @var Checker */
  60. private $checker;
  61. /** @var Installer */
  62. private $installer;
  63. private $logLevelNames = [
  64. 0 => 'Debug',
  65. 1 => 'Info',
  66. 2 => 'Warning',
  67. 3 => 'Error',
  68. 4 => 'Fatal',
  69. ];
  70. /**
  71. * @param IConfig $config
  72. * @param Checker $checker
  73. * @param ILogger $log
  74. * @param Installer $installer
  75. */
  76. public function __construct(IConfig $config,
  77. Checker $checker,
  78. ILogger $log = null,
  79. Installer $installer) {
  80. $this->log = $log;
  81. $this->config = $config;
  82. $this->checker = $checker;
  83. $this->installer = $installer;
  84. }
  85. /**
  86. * runs the update actions in maintenance mode, does not upgrade the source files
  87. * except the main .htaccess file
  88. *
  89. * @return bool true if the operation succeeded, false otherwise
  90. */
  91. public function upgrade() {
  92. $this->emitRepairEvents();
  93. $this->logAllEvents();
  94. $logLevel = $this->config->getSystemValue('loglevel', ILogger::WARN);
  95. $this->emit('\OC\Updater', 'setDebugLogLevel', [ $logLevel, $this->logLevelNames[$logLevel] ]);
  96. $this->config->setSystemValue('loglevel', ILogger::DEBUG);
  97. $wasMaintenanceModeEnabled = $this->config->getSystemValueBool('maintenance');
  98. if (!$wasMaintenanceModeEnabled) {
  99. $this->config->setSystemValue('maintenance', true);
  100. $this->emit('\OC\Updater', 'maintenanceEnabled');
  101. }
  102. // Clear CAN_INSTALL file if not on git
  103. if (\OC_Util::getChannel() !== 'git' && is_file(\OC::$configDir.'/CAN_INSTALL')) {
  104. if (!unlink(\OC::$configDir . '/CAN_INSTALL')) {
  105. $this->log->error('Could not cleanup CAN_INSTALL from your config folder. Please remove this file manually.');
  106. }
  107. }
  108. $installedVersion = $this->config->getSystemValue('version', '0.0.0');
  109. $currentVersion = implode('.', \OCP\Util::getVersion());
  110. $this->log->debug('starting upgrade from ' . $installedVersion . ' to ' . $currentVersion, ['app' => 'core']);
  111. $success = true;
  112. try {
  113. $this->doUpgrade($currentVersion, $installedVersion);
  114. } catch (HintException $exception) {
  115. $this->log->logException($exception, ['app' => 'core']);
  116. $this->emit('\OC\Updater', 'failure', [$exception->getMessage() . ': ' .$exception->getHint()]);
  117. $success = false;
  118. } catch (\Exception $exception) {
  119. $this->log->logException($exception, ['app' => 'core']);
  120. $this->emit('\OC\Updater', 'failure', [get_class($exception) . ': ' .$exception->getMessage()]);
  121. $success = false;
  122. }
  123. $this->emit('\OC\Updater', 'updateEnd', [$success]);
  124. if (!$wasMaintenanceModeEnabled && $success) {
  125. $this->config->setSystemValue('maintenance', false);
  126. $this->emit('\OC\Updater', 'maintenanceDisabled');
  127. } else {
  128. $this->emit('\OC\Updater', 'maintenanceActive');
  129. }
  130. $this->emit('\OC\Updater', 'resetLogLevel', [ $logLevel, $this->logLevelNames[$logLevel] ]);
  131. $this->config->setSystemValue('loglevel', $logLevel);
  132. $this->config->setSystemValue('installed', true);
  133. return $success;
  134. }
  135. /**
  136. * Return version from which this version is allowed to upgrade from
  137. *
  138. * @return array allowed previous versions per vendor
  139. */
  140. private function getAllowedPreviousVersions() {
  141. // this should really be a JSON file
  142. require \OC::$SERVERROOT . '/version.php';
  143. /** @var array $OC_VersionCanBeUpgradedFrom */
  144. return $OC_VersionCanBeUpgradedFrom;
  145. }
  146. /**
  147. * Return vendor from which this version was published
  148. *
  149. * @return string Get the vendor
  150. */
  151. private function getVendor() {
  152. // this should really be a JSON file
  153. require \OC::$SERVERROOT . '/version.php';
  154. /** @var string $vendor */
  155. return (string) $vendor;
  156. }
  157. /**
  158. * Whether an upgrade to a specified version is possible
  159. * @param string $oldVersion
  160. * @param string $newVersion
  161. * @param array $allowedPreviousVersions
  162. * @return bool
  163. */
  164. public function isUpgradePossible($oldVersion, $newVersion, array $allowedPreviousVersions) {
  165. $version = explode('.', $oldVersion);
  166. $majorMinor = $version[0] . '.' . $version[1];
  167. $currentVendor = $this->config->getAppValue('core', 'vendor', '');
  168. // Vendor was not set correctly on install, so we have to white-list known versions
  169. if ($currentVendor === '' && isset($allowedPreviousVersions['owncloud'][$oldVersion])) {
  170. $currentVendor = 'owncloud';
  171. }
  172. if ($currentVendor === 'nextcloud') {
  173. return isset($allowedPreviousVersions[$currentVendor][$majorMinor])
  174. && (version_compare($oldVersion, $newVersion, '<=') ||
  175. $this->config->getSystemValue('debug', false));
  176. }
  177. // Check if the instance can be migrated
  178. return isset($allowedPreviousVersions[$currentVendor][$majorMinor]) ||
  179. isset($allowedPreviousVersions[$currentVendor][$oldVersion]);
  180. }
  181. /**
  182. * runs the update actions in maintenance mode, does not upgrade the source files
  183. * except the main .htaccess file
  184. *
  185. * @param string $currentVersion current version to upgrade to
  186. * @param string $installedVersion previous version from which to upgrade from
  187. *
  188. * @throws \Exception
  189. */
  190. private function doUpgrade($currentVersion, $installedVersion) {
  191. // Stop update if the update is over several major versions
  192. $allowedPreviousVersions = $this->getAllowedPreviousVersions();
  193. if (!$this->isUpgradePossible($installedVersion, $currentVersion, $allowedPreviousVersions)) {
  194. throw new \Exception('Updates between multiple major versions and downgrades are unsupported.');
  195. }
  196. // Update .htaccess files
  197. try {
  198. Setup::updateHtaccess();
  199. Setup::protectDataDirectory();
  200. } catch (\Exception $e) {
  201. throw new \Exception($e->getMessage());
  202. }
  203. // create empty file in data dir, so we can later find
  204. // out that this is indeed an ownCloud data directory
  205. // (in case it didn't exist before)
  206. file_put_contents($this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/.ocdata', '');
  207. // pre-upgrade repairs
  208. $repair = new Repair(Repair::getBeforeUpgradeRepairSteps(), \OC::$server->getEventDispatcher());
  209. $repair->run();
  210. $this->doCoreUpgrade();
  211. try {
  212. // TODO: replace with the new repair step mechanism https://github.com/owncloud/core/pull/24378
  213. Setup::installBackgroundJobs();
  214. } catch (\Exception $e) {
  215. throw new \Exception($e->getMessage());
  216. }
  217. // update all shipped apps
  218. $this->checkAppsRequirements();
  219. $this->doAppUpgrade();
  220. // Update the appfetchers version so it downloads the correct list from the appstore
  221. \OC::$server->getAppFetcher()->setVersion($currentVersion);
  222. // upgrade appstore apps
  223. $this->upgradeAppStoreApps(\OC::$server->getAppManager()->getInstalledApps());
  224. $autoDisabledApps = \OC::$server->getAppManager()->getAutoDisabledApps();
  225. $this->upgradeAppStoreApps($autoDisabledApps, true);
  226. // install new shipped apps on upgrade
  227. OC_App::loadApps(['authentication']);
  228. $errors = Installer::installShippedApps(true);
  229. foreach ($errors as $appId => $exception) {
  230. /** @var \Exception $exception */
  231. $this->log->logException($exception, ['app' => $appId]);
  232. $this->emit('\OC\Updater', 'failure', [$appId . ': ' . $exception->getMessage()]);
  233. }
  234. // post-upgrade repairs
  235. $repair = new Repair(Repair::getRepairSteps(), \OC::$server->getEventDispatcher());
  236. $repair->run();
  237. //Invalidate update feed
  238. $this->config->setAppValue('core', 'lastupdatedat', 0);
  239. // Check for code integrity if not disabled
  240. if (\OC::$server->getIntegrityCodeChecker()->isCodeCheckEnforced()) {
  241. $this->emit('\OC\Updater', 'startCheckCodeIntegrity');
  242. $this->checker->runInstanceVerification();
  243. $this->emit('\OC\Updater', 'finishedCheckCodeIntegrity');
  244. }
  245. // only set the final version if everything went well
  246. $this->config->setSystemValue('version', implode('.', Util::getVersion()));
  247. $this->config->setAppValue('core', 'vendor', $this->getVendor());
  248. }
  249. protected function doCoreUpgrade() {
  250. $this->emit('\OC\Updater', 'dbUpgradeBefore');
  251. // execute core migrations
  252. $ms = new MigrationService('core', \OC::$server->getDatabaseConnection());
  253. $ms->migrate();
  254. $this->emit('\OC\Updater', 'dbUpgrade');
  255. }
  256. /**
  257. * @param string $version the oc version to check app compatibility with
  258. */
  259. protected function checkAppUpgrade($version) {
  260. $apps = \OC_App::getEnabledApps();
  261. $this->emit('\OC\Updater', 'appUpgradeCheckBefore');
  262. $appManager = \OC::$server->getAppManager();
  263. foreach ($apps as $appId) {
  264. $info = \OC_App::getAppInfo($appId);
  265. $compatible = \OC_App::isAppCompatible($version, $info);
  266. $isShipped = $appManager->isShipped($appId);
  267. if ($compatible && $isShipped && \OC_App::shouldUpgrade($appId)) {
  268. /**
  269. * FIXME: The preupdate check is performed before the database migration, otherwise database changes
  270. * are not possible anymore within it. - Consider this when touching the code.
  271. * @link https://github.com/owncloud/core/issues/10980
  272. * @see \OC_App::updateApp
  273. */
  274. if (file_exists(\OC_App::getAppPath($appId) . '/appinfo/preupdate.php')) {
  275. $this->includePreUpdate($appId);
  276. }
  277. if (file_exists(\OC_App::getAppPath($appId) . '/appinfo/database.xml')) {
  278. $this->emit('\OC\Updater', 'appSimulateUpdate', [$appId]);
  279. \OC_DB::simulateUpdateDbFromStructure(\OC_App::getAppPath($appId) . '/appinfo/database.xml');
  280. }
  281. }
  282. }
  283. $this->emit('\OC\Updater', 'appUpgradeCheck');
  284. }
  285. /**
  286. * Includes the pre-update file. Done here to prevent namespace mixups.
  287. * @param string $appId
  288. */
  289. private function includePreUpdate($appId) {
  290. include \OC_App::getAppPath($appId) . '/appinfo/preupdate.php';
  291. }
  292. /**
  293. * upgrades all apps within a major ownCloud upgrade. Also loads "priority"
  294. * (types authentication, filesystem, logging, in that order) afterwards.
  295. *
  296. * @throws NeedsUpdateException
  297. */
  298. protected function doAppUpgrade() {
  299. $apps = \OC_App::getEnabledApps();
  300. $priorityTypes = ['authentication', 'filesystem', 'logging'];
  301. $pseudoOtherType = 'other';
  302. $stacks = [$pseudoOtherType => []];
  303. foreach ($apps as $appId) {
  304. $priorityType = false;
  305. foreach ($priorityTypes as $type) {
  306. if (!isset($stacks[$type])) {
  307. $stacks[$type] = [];
  308. }
  309. if (\OC_App::isType($appId, [$type])) {
  310. $stacks[$type][] = $appId;
  311. $priorityType = true;
  312. break;
  313. }
  314. }
  315. if (!$priorityType) {
  316. $stacks[$pseudoOtherType][] = $appId;
  317. }
  318. }
  319. foreach ($stacks as $type => $stack) {
  320. foreach ($stack as $appId) {
  321. if (\OC_App::shouldUpgrade($appId)) {
  322. $this->emit('\OC\Updater', 'appUpgradeStarted', [$appId, \OC_App::getAppVersion($appId)]);
  323. \OC_App::updateApp($appId);
  324. $this->emit('\OC\Updater', 'appUpgrade', [$appId, \OC_App::getAppVersion($appId)]);
  325. }
  326. if ($type !== $pseudoOtherType) {
  327. // load authentication, filesystem and logging apps after
  328. // upgrading them. Other apps my need to rely on modifying
  329. // user and/or filesystem aspects.
  330. \OC_App::loadApp($appId);
  331. }
  332. }
  333. }
  334. }
  335. /**
  336. * check if the current enabled apps are compatible with the current
  337. * ownCloud version. disable them if not.
  338. * This is important if you upgrade ownCloud and have non ported 3rd
  339. * party apps installed.
  340. *
  341. * @return array
  342. * @throws \Exception
  343. */
  344. private function checkAppsRequirements() {
  345. $isCoreUpgrade = $this->isCodeUpgrade();
  346. $apps = OC_App::getEnabledApps();
  347. $version = implode('.', Util::getVersion());
  348. $disabledApps = [];
  349. $appManager = \OC::$server->getAppManager();
  350. foreach ($apps as $app) {
  351. // check if the app is compatible with this version of ownCloud
  352. $info = OC_App::getAppInfo($app);
  353. if ($info === null || !OC_App::isAppCompatible($version, $info)) {
  354. if ($appManager->isShipped($app)) {
  355. throw new \UnexpectedValueException('The files of the app "' . $app . '" were not correctly replaced before running the update');
  356. }
  357. \OC::$server->getAppManager()->disableApp($app, true);
  358. $this->emit('\OC\Updater', 'incompatibleAppDisabled', [$app]);
  359. }
  360. // no need to disable any app in case this is a non-core upgrade
  361. if (!$isCoreUpgrade) {
  362. continue;
  363. }
  364. // shipped apps will remain enabled
  365. if ($appManager->isShipped($app)) {
  366. continue;
  367. }
  368. // authentication and session apps will remain enabled as well
  369. if (OC_App::isType($app, ['session', 'authentication'])) {
  370. continue;
  371. }
  372. }
  373. return $disabledApps;
  374. }
  375. /**
  376. * @return bool
  377. */
  378. private function isCodeUpgrade() {
  379. $installedVersion = $this->config->getSystemValue('version', '0.0.0');
  380. $currentVersion = implode('.', Util::getVersion());
  381. if (version_compare($currentVersion, $installedVersion, '>')) {
  382. return true;
  383. }
  384. return false;
  385. }
  386. /**
  387. * @param array $disabledApps
  388. * @param bool $reenable
  389. * @throws \Exception
  390. */
  391. private function upgradeAppStoreApps(array $disabledApps, $reenable = false) {
  392. foreach ($disabledApps as $app) {
  393. try {
  394. $this->emit('\OC\Updater', 'checkAppStoreAppBefore', [$app]);
  395. if ($this->installer->isUpdateAvailable($app)) {
  396. $this->emit('\OC\Updater', 'upgradeAppStoreApp', [$app]);
  397. $this->installer->updateAppstoreApp($app);
  398. }
  399. $this->emit('\OC\Updater', 'checkAppStoreApp', [$app]);
  400. if ($reenable) {
  401. $ocApp = new \OC_App();
  402. $ocApp->enable($app);
  403. }
  404. } catch (\Exception $ex) {
  405. $this->log->logException($ex, ['app' => 'core']);
  406. }
  407. }
  408. }
  409. /**
  410. * Forward messages emitted by the repair routine
  411. */
  412. private function emitRepairEvents() {
  413. $dispatcher = \OC::$server->getEventDispatcher();
  414. $dispatcher->addListener('\OC\Repair::warning', function ($event) {
  415. if ($event instanceof GenericEvent) {
  416. $this->emit('\OC\Updater', 'repairWarning', $event->getArguments());
  417. }
  418. });
  419. $dispatcher->addListener('\OC\Repair::error', function ($event) {
  420. if ($event instanceof GenericEvent) {
  421. $this->emit('\OC\Updater', 'repairError', $event->getArguments());
  422. }
  423. });
  424. $dispatcher->addListener('\OC\Repair::info', function ($event) {
  425. if ($event instanceof GenericEvent) {
  426. $this->emit('\OC\Updater', 'repairInfo', $event->getArguments());
  427. }
  428. });
  429. $dispatcher->addListener('\OC\Repair::step', function ($event) {
  430. if ($event instanceof GenericEvent) {
  431. $this->emit('\OC\Updater', 'repairStep', $event->getArguments());
  432. }
  433. });
  434. }
  435. private function logAllEvents() {
  436. $log = $this->log;
  437. $dispatcher = \OC::$server->getEventDispatcher();
  438. $dispatcher->addListener('\OC\DB\Migrator::executeSql', function ($event) use ($log) {
  439. if (!$event instanceof GenericEvent) {
  440. return;
  441. }
  442. $log->info('\OC\DB\Migrator::executeSql: ' . $event->getSubject() . ' (' . $event->getArgument(0) . ' of ' . $event->getArgument(1) . ')', ['app' => 'updater']);
  443. });
  444. $dispatcher->addListener('\OC\DB\Migrator::checkTable', function ($event) use ($log) {
  445. if (!$event instanceof GenericEvent) {
  446. return;
  447. }
  448. $log->info('\OC\DB\Migrator::checkTable: ' . $event->getSubject() . ' (' . $event->getArgument(0) . ' of ' . $event->getArgument(1) . ')', ['app' => 'updater']);
  449. });
  450. $repairListener = function ($event) use ($log) {
  451. if (!$event instanceof GenericEvent) {
  452. return;
  453. }
  454. switch ($event->getSubject()) {
  455. case '\OC\Repair::startProgress':
  456. $log->info('\OC\Repair::startProgress: Starting ... ' . $event->getArgument(1) . ' (' . $event->getArgument(0) . ')', ['app' => 'updater']);
  457. break;
  458. case '\OC\Repair::advance':
  459. $desc = $event->getArgument(1);
  460. if (empty($desc)) {
  461. $desc = '';
  462. }
  463. $log->info('\OC\Repair::advance: ' . $desc . ' (' . $event->getArgument(0) . ')', ['app' => 'updater']);
  464. break;
  465. case '\OC\Repair::finishProgress':
  466. $log->info('\OC\Repair::finishProgress', ['app' => 'updater']);
  467. break;
  468. case '\OC\Repair::step':
  469. $log->info('\OC\Repair::step: Repair step: ' . $event->getArgument(0), ['app' => 'updater']);
  470. break;
  471. case '\OC\Repair::info':
  472. $log->info('\OC\Repair::info: Repair info: ' . $event->getArgument(0), ['app' => 'updater']);
  473. break;
  474. case '\OC\Repair::warning':
  475. $log->warning('\OC\Repair::warning: Repair warning: ' . $event->getArgument(0), ['app' => 'updater']);
  476. break;
  477. case '\OC\Repair::error':
  478. $log->error('\OC\Repair::error: Repair error: ' . $event->getArgument(0), ['app' => 'updater']);
  479. break;
  480. }
  481. };
  482. $dispatcher->addListener('\OC\Repair::startProgress', $repairListener);
  483. $dispatcher->addListener('\OC\Repair::advance', $repairListener);
  484. $dispatcher->addListener('\OC\Repair::finishProgress', $repairListener);
  485. $dispatcher->addListener('\OC\Repair::step', $repairListener);
  486. $dispatcher->addListener('\OC\Repair::info', $repairListener);
  487. $dispatcher->addListener('\OC\Repair::warning', $repairListener);
  488. $dispatcher->addListener('\OC\Repair::error', $repairListener);
  489. $this->listen('\OC\Updater', 'maintenanceEnabled', function () use ($log) {
  490. $log->info('\OC\Updater::maintenanceEnabled: Turned on maintenance mode', ['app' => 'updater']);
  491. });
  492. $this->listen('\OC\Updater', 'maintenanceDisabled', function () use ($log) {
  493. $log->info('\OC\Updater::maintenanceDisabled: Turned off maintenance mode', ['app' => 'updater']);
  494. });
  495. $this->listen('\OC\Updater', 'maintenanceActive', function () use ($log) {
  496. $log->info('\OC\Updater::maintenanceActive: Maintenance mode is kept active', ['app' => 'updater']);
  497. });
  498. $this->listen('\OC\Updater', 'updateEnd', function ($success) use ($log) {
  499. if ($success) {
  500. $log->info('\OC\Updater::updateEnd: Update successful', ['app' => 'updater']);
  501. } else {
  502. $log->error('\OC\Updater::updateEnd: Update failed', ['app' => 'updater']);
  503. }
  504. });
  505. $this->listen('\OC\Updater', 'dbUpgradeBefore', function () use ($log) {
  506. $log->info('\OC\Updater::dbUpgradeBefore: Updating database schema', ['app' => 'updater']);
  507. });
  508. $this->listen('\OC\Updater', 'dbUpgrade', function () use ($log) {
  509. $log->info('\OC\Updater::dbUpgrade: Updated database', ['app' => 'updater']);
  510. });
  511. $this->listen('\OC\Updater', 'dbSimulateUpgradeBefore', function () use ($log) {
  512. $log->info('\OC\Updater::dbSimulateUpgradeBefore: Checking whether the database schema can be updated (this can take a long time depending on the database size)', ['app' => 'updater']);
  513. });
  514. $this->listen('\OC\Updater', 'dbSimulateUpgrade', function () use ($log) {
  515. $log->info('\OC\Updater::dbSimulateUpgrade: Checked database schema update', ['app' => 'updater']);
  516. });
  517. $this->listen('\OC\Updater', 'incompatibleAppDisabled', function ($app) use ($log) {
  518. $log->info('\OC\Updater::incompatibleAppDisabled: Disabled incompatible app: ' . $app, ['app' => 'updater']);
  519. });
  520. $this->listen('\OC\Updater', 'checkAppStoreAppBefore', function ($app) use ($log) {
  521. $log->info('\OC\Updater::checkAppStoreAppBefore: Checking for update of app "' . $app . '" in appstore', ['app' => 'updater']);
  522. });
  523. $this->listen('\OC\Updater', 'upgradeAppStoreApp', function ($app) use ($log) {
  524. $log->info('\OC\Updater::upgradeAppStoreApp: Update app "' . $app . '" from appstore', ['app' => 'updater']);
  525. });
  526. $this->listen('\OC\Updater', 'checkAppStoreApp', function ($app) use ($log) {
  527. $log->info('\OC\Updater::checkAppStoreApp: Checked for update of app "' . $app . '" in appstore', ['app' => 'updater']);
  528. });
  529. $this->listen('\OC\Updater', 'appUpgradeCheckBefore', function () use ($log) {
  530. $log->info('\OC\Updater::appUpgradeCheckBefore: Checking updates of apps', ['app' => 'updater']);
  531. });
  532. $this->listen('\OC\Updater', 'appSimulateUpdate', function ($app) use ($log) {
  533. $log->info('\OC\Updater::appSimulateUpdate: Checking whether the database schema for <' . $app . '> can be updated (this can take a long time depending on the database size)', ['app' => 'updater']);
  534. });
  535. $this->listen('\OC\Updater', 'appUpgradeCheck', function () use ($log) {
  536. $log->info('\OC\Updater::appUpgradeCheck: Checked database schema update for apps', ['app' => 'updater']);
  537. });
  538. $this->listen('\OC\Updater', 'appUpgradeStarted', function ($app) use ($log) {
  539. $log->info('\OC\Updater::appUpgradeStarted: Updating <' . $app . '> ...', ['app' => 'updater']);
  540. });
  541. $this->listen('\OC\Updater', 'appUpgrade', function ($app, $version) use ($log) {
  542. $log->info('\OC\Updater::appUpgrade: Updated <' . $app . '> to ' . $version, ['app' => 'updater']);
  543. });
  544. $this->listen('\OC\Updater', 'failure', function ($message) use ($log) {
  545. $log->error('\OC\Updater::failure: ' . $message, ['app' => 'updater']);
  546. });
  547. $this->listen('\OC\Updater', 'setDebugLogLevel', function () use ($log) {
  548. $log->info('\OC\Updater::setDebugLogLevel: Set log level to debug', ['app' => 'updater']);
  549. });
  550. $this->listen('\OC\Updater', 'resetLogLevel', function ($logLevel, $logLevelName) use ($log) {
  551. $log->info('\OC\Updater::resetLogLevel: Reset log level to ' . $logLevelName . '(' . $logLevel . ')', ['app' => 'updater']);
  552. });
  553. $this->listen('\OC\Updater', 'startCheckCodeIntegrity', function () use ($log) {
  554. $log->info('\OC\Updater::startCheckCodeIntegrity: Starting code integrity check...', ['app' => 'updater']);
  555. });
  556. $this->listen('\OC\Updater', 'finishedCheckCodeIntegrity', function () use ($log) {
  557. $log->info('\OC\Updater::finishedCheckCodeIntegrity: Finished code integrity check', ['app' => 'updater']);
  558. });
  559. }
  560. }