Merge pull request #16903 from eileenmcnaughton/settting_better
[civicrm-core.git] / CRM / Upgrade / Form.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
5 | |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
10 */
11
12 /**
13 *
14 * @package CRM
15 * @copyright CiviCRM LLC https://civicrm.org/licensing
16 * $Id$
17 *
18 */
19 class CRM_Upgrade_Form extends CRM_Core_Form {
20 const QUEUE_NAME = 'CRM_Upgrade';
21
22 /**
23 * Minimum size of MySQL's thread_stack option
24 *
25 * @see install/index.php MINIMUM_THREAD_STACK
26 */
27 const MINIMUM_THREAD_STACK = 192;
28
29 /**
30 * Minimum previous CiviCRM version we can directly upgrade from
31 */
32 const MINIMUM_UPGRADABLE_VERSION = '4.2.9';
33
34 /**
35 * @var \CRM_Core_Config
36 */
37 protected $_config;
38
39 /**
40 * Upgrade for multilingual.
41 *
42 * @var bool
43 */
44 public $multilingual = FALSE;
45
46 /**
47 * Locales available for multilingual upgrade.
48 *
49 * @var array
50 */
51 public $locales;
52
53 /**
54 * Constructor for the basic form page.
55 *
56 * We should not use QuickForm directly. This class provides a lot
57 * of default convenient functions, rules and buttons
58 *
59 * @param object $state
60 * State associated with this form.
61 * @param const|\enum|int $action The mode the form is operating in (None/Create/View/Update/Delete)
62 * @param string $method
63 * The type of http method used (GET/POST).
64 * @param string $name
65 * The name of the form if different from class name.
66 */
67 public function __construct(
68 $state = NULL,
69 $action = CRM_Core_Action::NONE,
70 $method = 'post',
71 $name = NULL
72 ) {
73 $this->_config = CRM_Core_Config::singleton();
74
75 $domain = new CRM_Core_DAO_Domain();
76 $domain->find(TRUE);
77
78 $this->multilingual = (bool) $domain->locales;
79 $this->locales = explode(CRM_Core_DAO::VALUE_SEPARATOR, $domain->locales);
80
81 $smarty = CRM_Core_Smarty::singleton();
82 //$smarty->compile_dir = $this->_config->templateCompileDir;
83 $smarty->assign('multilingual', $this->multilingual);
84 $smarty->assign('locales', $this->locales);
85
86 // we didn't call CRM_Core_BAO_ConfigSetting::retrieve(), so we need to set $dbLocale by hand
87 if ($this->multilingual) {
88 global $dbLocale;
89 $dbLocale = "_{$this->_config->lcMessages}";
90 }
91
92 parent::__construct($state, $action, $method, $name);
93 }
94
95 /**
96 * @param $version
97 *
98 * @return mixed
99 */
100 public static function &incrementalPhpObject($version) {
101 static $incrementalPhpObject = [];
102
103 $versionParts = explode('.', $version);
104 $versionName = CRM_Utils_EnglishNumber::toCamelCase($versionParts[0]) . CRM_Utils_EnglishNumber::toCamelCase($versionParts[1]);
105
106 if (!array_key_exists($versionName, $incrementalPhpObject)) {
107 $className = "CRM_Upgrade_Incremental_php_{$versionName}";
108 $incrementalPhpObject[$versionName] = new $className();
109 }
110 return $incrementalPhpObject[$versionName];
111 }
112
113 /**
114 * @param $version
115 * @param $release
116 *
117 * @return bool
118 */
119 public function checkVersionRelease($version, $release) {
120 $versionParts = explode('.', $version);
121 return ($versionParts[2] == $release);
122 }
123
124 /**
125 * @param $constraints
126 *
127 * @return array
128 */
129 public function checkSQLConstraints(&$constraints) {
130 $pass = $fail = 0;
131 foreach ($constraints as $constraint) {
132 if ($this->checkSQLConstraint($constraint)) {
133 $pass++;
134 }
135 else {
136 $fail++;
137 }
138 return [$pass, $fail];
139 }
140 }
141
142 /**
143 * @param $constraint
144 *
145 * @return bool
146 */
147 public function checkSQLConstraint($constraint) {
148 // check constraint here
149 return TRUE;
150 }
151
152 /**
153 * @param string $fileName
154 * @param bool $isQueryString
155 */
156 public function source($fileName, $isQueryString = FALSE) {
157 if ($isQueryString) {
158 CRM_Utils_File::runSqlQuery($this->_config->dsn,
159 $fileName, NULL
160 );
161 }
162 else {
163 CRM_Utils_File::sourceSQLFile($this->_config->dsn,
164 $fileName, NULL
165 );
166 }
167 }
168
169 public function preProcess() {
170 CRM_Utils_System::setTitle($this->getTitle());
171 if (!$this->verifyPreDBState($errorMessage)) {
172 if (!isset($errorMessage)) {
173 $errorMessage = 'pre-condition failed for current upgrade step';
174 }
175 CRM_Core_Error::fatal($errorMessage);
176 }
177 $this->assign('recentlyViewed', FALSE);
178 }
179
180 public function buildQuickForm() {
181 $this->addDefaultButtons($this->getButtonTitle(),
182 'next',
183 NULL,
184 TRUE
185 );
186 }
187
188 /**
189 * Getter function for title. Should be over-ridden by derived class
190 *
191 * @return string
192 */
193
194 /**
195 * @return string
196 */
197 public function getTitle() {
198 return ts('Title not Set');
199 }
200
201 /**
202 * @return string
203 */
204 public function getFieldsetTitle() {
205 return '';
206 }
207
208 /**
209 * @return string
210 */
211 public function getButtonTitle() {
212 return ts('Continue');
213 }
214
215 /**
216 * Use the form name to create the tpl file name.
217 *
218 * @return string
219 */
220
221 /**
222 * @return string
223 */
224 public function getTemplateFileName() {
225 $this->assign('title',
226 $this->getFieldsetTitle()
227 );
228 $this->assign('message',
229 $this->getTemplateMessage()
230 );
231 return 'CRM/Upgrade/Base.tpl';
232 }
233
234 public function postProcess() {
235 $this->upgrade();
236
237 if (!$this->verifyPostDBState($errorMessage)) {
238 if (!isset($errorMessage)) {
239 $errorMessage = 'post-condition failed for current upgrade step';
240 }
241 CRM_Core_Error::fatal($errorMessage);
242 }
243 }
244
245 /**
246 * @param $query
247 *
248 * @return Object
249 */
250 public function runQuery($query) {
251 return CRM_Core_DAO::executeQuery($query);
252 }
253
254 /**
255 * @param $version
256 *
257 * @return Object
258 */
259 public function setVersion($version) {
260 $this->logVersion($version);
261
262 $query = "
263 UPDATE civicrm_domain
264 SET version = '$version'
265 ";
266 return $this->runQuery($query);
267 }
268
269 /**
270 * @param $newVersion
271 *
272 * @return bool
273 */
274 public function logVersion($newVersion) {
275 if ($newVersion) {
276 $oldVersion = CRM_Core_BAO_Domain::version();
277
278 $session = CRM_Core_Session::singleton();
279 $logParams = [
280 'entity_table' => 'civicrm_domain',
281 'entity_id' => 1,
282 'data' => "upgrade:{$oldVersion}->{$newVersion}",
283 // lets skip 'modified_id' for now, as it causes FK issues And
284 // is not very important for now.
285 'modified_date' => date('YmdHis'),
286 ];
287 CRM_Core_BAO_Log::add($logParams);
288 return TRUE;
289 }
290
291 return FALSE;
292 }
293
294 /**
295 * @param $version
296 *
297 * @return bool
298 */
299 public function checkVersion($version) {
300 $domainID = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_Domain',
301 $version, 'id',
302 'version'
303 );
304 return (bool) $domainID;
305 }
306
307 /**
308 * @return array
309 * @throws Exception
310 */
311 public function getRevisionSequence() {
312 $revList = [];
313 $sqlDir = implode(DIRECTORY_SEPARATOR,
314 [dirname(__FILE__), 'Incremental', 'sql']
315 );
316 $sqlFiles = scandir($sqlDir);
317
318 $sqlFilePattern = '/^((\d{1,2}\.\d{1,2})\.(\d{1,2}\.)?(\d{1,2}|\w{4,7}))\.(my)?sql(\.tpl)?$/i';
319 foreach ($sqlFiles as $file) {
320 if (preg_match($sqlFilePattern, $file, $matches)) {
321 if (!in_array($matches[1], $revList)) {
322 $revList[] = $matches[1];
323 }
324 }
325 }
326
327 usort($revList, 'version_compare');
328 return $revList;
329 }
330
331 /**
332 * @param $rev
333 * @param int $index
334 *
335 * @return null
336 */
337 public static function getRevisionPart($rev, $index = 1) {
338 $revPattern = '/^((\d{1,2})\.\d{1,2})\.(\d{1,2}|\w{4,7})?$/i';
339 preg_match($revPattern, $rev, $matches);
340
341 return array_key_exists($index, $matches) ? $matches[$index] : NULL;
342 }
343
344 /**
345 * @param $tplFile
346 * @param $rev
347 *
348 * @return bool
349 */
350 public function processLocales($tplFile, $rev) {
351 $smarty = CRM_Core_Smarty::singleton();
352 $smarty->assign('domainID', CRM_Core_Config::domainID());
353
354 $this->source($smarty->fetch($tplFile), TRUE);
355
356 if ($this->multilingual) {
357 CRM_Core_I18n_Schema::rebuildMultilingualSchema($this->locales, $rev);
358 }
359 return $this->multilingual;
360 }
361
362 /**
363 * @param $rev
364 */
365 public function setSchemaStructureTables($rev) {
366 if ($this->multilingual) {
367 CRM_Core_I18n_Schema::schemaStructureTables($rev, TRUE);
368 }
369 }
370
371 /**
372 * @param $rev
373 *
374 * @throws Exception
375 */
376 public function processSQL($rev) {
377 $sqlFile = implode(DIRECTORY_SEPARATOR,
378 [
379 dirname(__FILE__),
380 'Incremental',
381 'sql',
382 $rev . '.mysql',
383 ]
384 );
385 $tplFile = "$sqlFile.tpl";
386
387 if (file_exists($tplFile)) {
388 $this->processLocales($tplFile, $rev);
389 }
390 else {
391 if (!file_exists($sqlFile)) {
392 CRM_Core_Error::fatal("sqlfile - $rev.mysql not found.");
393 }
394 $this->source($sqlFile);
395 }
396 }
397
398 /**
399 * Determine the start and end version of the upgrade process.
400 *
401 * @return array(0=>$currentVer, 1=>$latestVer)
402 */
403 public function getUpgradeVersions() {
404 $latestVer = CRM_Utils_System::version();
405 $currentVer = CRM_Core_BAO_Domain::version(TRUE);
406 if (!$currentVer) {
407 CRM_Core_Error::fatal(ts('Version information missing in civicrm database.'));
408 }
409 elseif (stripos($currentVer, 'upgrade')) {
410 CRM_Core_Error::fatal(ts('Database check failed - the database looks to have been partially upgraded. You may want to reload the database with the backup and try the upgrade process again.'));
411 }
412 if (!$latestVer) {
413 CRM_Core_Error::fatal(ts('Version information missing in civicrm codebase.'));
414 }
415
416 return [$currentVer, $latestVer];
417 }
418
419 /**
420 * Determine if $currentVer can be upgraded to $latestVer
421 *
422 * @param $currentVer
423 * @param $latestVer
424 *
425 * @return mixed, a string error message or boolean 'false' if OK
426 */
427 public function checkUpgradeableVersion($currentVer, $latestVer) {
428 $error = FALSE;
429 // since version is suppose to be in valid format at this point, especially after conversion ($convertVer),
430 // lets do a pattern check -
431 if (!CRM_Utils_System::isVersionFormatValid($currentVer)) {
432 $error = ts('Database is marked with invalid version format. You may want to investigate this before you proceed further.');
433 }
434 elseif (version_compare($currentVer, $latestVer) > 0) {
435 // DB version number is higher than codebase being upgraded to. This is unexpected condition-fatal error.
436 $error = ts('Your database is marked with an unexpected version number: %1. The automated upgrade to version %2 can not be run - and the %2 codebase may not be compatible with your database state. You will need to determine the correct version corresponding to your current database state. You may want to revert to the codebase you were using prior to beginning this upgrade until you resolve this problem.',
437 [1 => $currentVer, 2 => $latestVer]
438 );
439 }
440 elseif (version_compare($currentVer, $latestVer) == 0) {
441 $error = ts('Your database has already been upgraded to CiviCRM %1',
442 [1 => $latestVer]
443 );
444 }
445 elseif (version_compare($currentVer, self::MINIMUM_UPGRADABLE_VERSION) < 0) {
446 $error = ts('CiviCRM versions prior to %1 cannot be upgraded directly to %2. This upgrade will need to be done in stages. First download an intermediate version (the LTS may be a good choice) and upgrade to that before proceeding to this version.',
447 [1 => self::MINIMUM_UPGRADABLE_VERSION, 2 => $latestVer]
448 );
449 }
450
451 if (version_compare(phpversion(), CRM_Upgrade_Incremental_General::MIN_INSTALL_PHP_VER) < 0) {
452 $error = ts('CiviCRM %3 requires PHP version %1 (or newer), but the current system uses %2 ',
453 [
454 1 => CRM_Upgrade_Incremental_General::MIN_INSTALL_PHP_VER,
455 2 => phpversion(),
456 3 => $latestVer,
457 ]);
458 }
459
460 // check for mysql trigger privileges
461 if (!\Civi::settings()->get('logging_no_trigger_permission') && !CRM_Core_DAO::checkTriggerViewPermission(FALSE, TRUE)) {
462 $error = ts('CiviCRM %1 requires MySQL trigger privileges.',
463 [1 => $latestVer]);
464 }
465
466 if (CRM_Core_DAO::getGlobalSetting('thread_stack', 0) < (1024 * self::MINIMUM_THREAD_STACK)) {
467 $error = ts('CiviCRM %1 requires MySQL thread stack >= %2k', [
468 1 => $latestVer,
469 2 => self::MINIMUM_THREAD_STACK,
470 ]);
471 }
472
473 return $error;
474 }
475
476 /**
477 * Determine if $currentver already matches $latestVer
478 *
479 * @param $currentVer
480 * @param $latestVer
481 *
482 * @return mixed, a string error message or boolean 'false' if OK
483 */
484 public function checkCurrentVersion($currentVer, $latestVer) {
485 $error = FALSE;
486
487 // since version is suppose to be in valid format at this point, especially after conversion ($convertVer),
488 // lets do a pattern check -
489 if (!CRM_Utils_System::isVersionFormatValid($currentVer)) {
490 $error = ts('Database is marked with invalid version format. You may want to investigate this before you proceed further.');
491 }
492 elseif (version_compare($currentVer, $latestVer) != 0) {
493 $error = ts('Your database is not configured for version %1',
494 [1 => $latestVer]
495 );
496 }
497 return $error;
498 }
499
500 /**
501 * Fill the queue with upgrade tasks.
502 *
503 * @param string $currentVer
504 * the original revision.
505 * @param string $latestVer
506 * the target (final) revision.
507 * @param string $postUpgradeMessageFile
508 * path of a modifiable file which lists the post-upgrade messages.
509 *
510 * @return CRM_Queue_Service
511 */
512 public static function buildQueue($currentVer, $latestVer, $postUpgradeMessageFile) {
513 $upgrade = new CRM_Upgrade_Form();
514
515 // Ensure that queue can be created
516 if (!CRM_Queue_BAO_QueueItem::findCreateTable()) {
517 CRM_Core_Error::fatal(ts('Failed to find or create queueing table'));
518 }
519 $queue = CRM_Queue_Service::singleton()->create([
520 'name' => self::QUEUE_NAME,
521 'type' => 'Sql',
522 'reset' => TRUE,
523 ]);
524
525 $task = new CRM_Queue_Task(
526 ['CRM_Upgrade_Form', 'doFileCleanup'],
527 [$postUpgradeMessageFile],
528 "Cleanup old files"
529 );
530 $queue->createItem($task);
531
532 $task = new CRM_Queue_Task(
533 ['CRM_Upgrade_Form', 'disableOldExtensions'],
534 [$postUpgradeMessageFile],
535 "Checking extensions"
536 );
537 $queue->createItem($task);
538
539 $revisions = $upgrade->getRevisionSequence();
540 foreach ($revisions as $rev) {
541 // proceed only if $currentVer < $rev
542 if (version_compare($currentVer, $rev) < 0) {
543 $beginTask = new CRM_Queue_Task(
544 // callback
545 ['CRM_Upgrade_Form', 'doIncrementalUpgradeStart'],
546 // arguments
547 [$rev],
548 "Begin Upgrade to $rev"
549 );
550 $queue->createItem($beginTask);
551
552 $task = new CRM_Queue_Task(
553 // callback
554 ['CRM_Upgrade_Form', 'doIncrementalUpgradeStep'],
555 // arguments
556 [$rev, $currentVer, $latestVer, $postUpgradeMessageFile],
557 "Upgrade DB to $rev"
558 );
559 $queue->createItem($task);
560
561 $task = new CRM_Queue_Task(
562 // callback
563 ['CRM_Upgrade_Form', 'doIncrementalUpgradeFinish'],
564 // arguments
565 [$rev, $currentVer, $latestVer, $postUpgradeMessageFile],
566 "Finish Upgrade DB to $rev"
567 );
568 $queue->createItem($task);
569 }
570 }
571
572 return $queue;
573 }
574
575 /**
576 * Find any old, orphaned files that should have been deleted.
577 *
578 * These files can get left behind, eg, if you use the Joomla
579 * upgrade procedure.
580 *
581 * The earlier we can do this, the better - don't want upgrade logic
582 * to inadvertently rely on old/relocated files.
583 *
584 * @param \CRM_Queue_TaskContext $ctx
585 * @param string $postUpgradeMessageFile
586 * @return bool
587 */
588 public static function doFileCleanup(CRM_Queue_TaskContext $ctx, $postUpgradeMessageFile) {
589 $source = new CRM_Utils_Check_Component_Source();
590 $files = $source->findOrphanedFiles();
591 $errors = [];
592 foreach ($files as $file) {
593 if (is_dir($file['path'])) {
594 @rmdir($file['path']);
595 }
596 else {
597 @unlink($file['path']);
598 }
599
600 if (file_exists($file['path'])) {
601 $errors[] = sprintf("<li>%s</li>", htmlentities($file['path']));
602 }
603 }
604
605 if (!empty($errors)) {
606 file_put_contents($postUpgradeMessageFile,
607 '<br/><br/>' . ts('Some old files could not be removed. Please remove them.')
608 . '<ul>' . implode("\n", $errors) . '</ul>',
609 FILE_APPEND
610 );
611 }
612
613 return TRUE;
614 }
615
616 /**
617 * Disable/uninstall any extensions not compatible with this new version.
618 *
619 * @param \CRM_Queue_TaskContext $ctx
620 * @param string $postUpgradeMessageFile
621 * @return bool
622 */
623 public static function disableOldExtensions(CRM_Queue_TaskContext $ctx, $postUpgradeMessageFile) {
624 $messages = [];
625 $manager = CRM_Extension_System::singleton()->getManager();
626 foreach ($manager->getStatuses() as $key => $status) {
627 $obsolete = $manager->isIncompatible($key);
628 if ($obsolete) {
629 if (!empty($obsolete['disable']) && in_array($status, [$manager::STATUS_INSTALLED, $manager::STATUS_INSTALLED_MISSING])) {
630 try {
631 $manager->disable($key);
632 // Update the status for the sake of uninstall below.
633 $status = $status == $manager::STATUS_INSTALLED ? $manager::STATUS_DISABLED : $manager::STATUS_DISABLED_MISSING;
634 // This message is intentionally overwritten by uninstall below as it would be redundant
635 $messages[$key] = ts('The extension %1 is now obsolete and has been disabled.', [1 => $key]);
636 }
637 catch (CRM_Extension_Exception $e) {
638 $messages[] = ts('The obsolete extension %1 could not be removed due to an error. It is recommended to remove this extension manually.', [1 => $key]);
639 }
640 }
641 if (!empty($obsolete['uninstall']) && in_array($status, [$manager::STATUS_DISABLED, $manager::STATUS_DISABLED_MISSING])) {
642 try {
643 $manager->uninstall($key);
644 $messages[$key] = ts('The extension %1 is now obsolete and has been uninstalled.', [1 => $key]);
645 if ($status == $manager::STATUS_DISABLED) {
646 $messages[$key] .= ' ' . ts('You can remove it from your extensions directory.');
647 }
648 }
649 catch (CRM_Extension_Exception $e) {
650 $messages[] = ts('The obsolete extension %1 could not be removed due to an error. It is recommended to remove this extension manually.', [1 => $key]);
651 }
652 }
653 if (!empty($obsolete['force-uninstall'])) {
654 CRM_Core_DAO::executeQuery('UPDATE civicrm_extension SET is_active = 0 WHERE full_name = %1', [
655 1 => [$key, 'String'],
656 ]);
657 }
658 }
659 }
660 if ($messages) {
661 file_put_contents($postUpgradeMessageFile,
662 '<br/><br/><ul><li>' . implode("</li>\n<li>", $messages) . '</li></ul>',
663 FILE_APPEND
664 );
665 }
666
667 return TRUE;
668 }
669
670 /**
671 * Perform an incremental version update.
672 *
673 * @param CRM_Queue_TaskContext $ctx
674 * @param string $rev
675 * the target (intermediate) revision e.g '3.2.alpha1'.
676 *
677 * @return bool
678 */
679 public static function doIncrementalUpgradeStart(CRM_Queue_TaskContext $ctx, $rev) {
680 $upgrade = new CRM_Upgrade_Form();
681
682 // as soon as we start doing anything we append ".upgrade" to version.
683 // this also helps detect any partial upgrade issues
684 $upgrade->setVersion($rev . '.upgrade');
685
686 return TRUE;
687 }
688
689 /**
690 * Perform an incremental version update.
691 *
692 * @param CRM_Queue_TaskContext $ctx
693 * @param string $rev
694 * the target (intermediate) revision e.g '3.2.alpha1'.
695 * @param string $originalVer
696 * the original revision.
697 * @param string $latestVer
698 * the target (final) revision.
699 * @param string $postUpgradeMessageFile
700 * path of a modifiable file which lists the post-upgrade messages.
701 *
702 * @return bool
703 */
704 public static function doIncrementalUpgradeStep(CRM_Queue_TaskContext $ctx, $rev, $originalVer, $latestVer, $postUpgradeMessageFile) {
705 $upgrade = new CRM_Upgrade_Form();
706
707 $phpFunctionName = 'upgrade_' . str_replace('.', '_', $rev);
708
709 $versionObject = $upgrade->incrementalPhpObject($rev);
710
711 // pre-db check for major release.
712 if ($upgrade->checkVersionRelease($rev, 'alpha1')) {
713 if (!(is_callable([$versionObject, 'verifyPreDBstate']))) {
714 CRM_Core_Error::fatal("verifyPreDBstate method was not found for $rev");
715 }
716
717 $error = NULL;
718 if (!($versionObject->verifyPreDBstate($error))) {
719 if (!isset($error)) {
720 $error = "post-condition failed for current upgrade for $rev";
721 }
722 CRM_Core_Error::fatal($error);
723 }
724
725 }
726
727 $upgrade->setSchemaStructureTables($rev);
728
729 if (is_callable([$versionObject, $phpFunctionName])) {
730 $versionObject->$phpFunctionName($rev, $originalVer, $latestVer);
731 }
732 else {
733 $upgrade->processSQL($rev);
734 }
735
736 // set post-upgrade-message if any
737 if (is_callable([$versionObject, 'setPostUpgradeMessage'])) {
738 $postUpgradeMessage = file_get_contents($postUpgradeMessageFile);
739 $versionObject->setPostUpgradeMessage($postUpgradeMessage, $rev);
740 file_put_contents($postUpgradeMessageFile, $postUpgradeMessage);
741 }
742
743 return TRUE;
744 }
745
746 /**
747 * Perform an incremental version update.
748 *
749 * @param CRM_Queue_TaskContext $ctx
750 * @param string $rev
751 * the target (intermediate) revision e.g '3.2.alpha1'.
752 * @param string $currentVer
753 * the original revision.
754 * @param string $latestVer
755 * the target (final) revision.
756 * @param string $postUpgradeMessageFile
757 * path of a modifiable file which lists the post-upgrade messages.
758 *
759 * @return bool
760 */
761 public static function doIncrementalUpgradeFinish(CRM_Queue_TaskContext $ctx, $rev, $currentVer, $latestVer, $postUpgradeMessageFile) {
762 $upgrade = new CRM_Upgrade_Form();
763 $upgrade->setVersion($rev);
764 CRM_Utils_System::flushCache();
765
766 $config = CRM_Core_Config::singleton();
767 $config->userSystem->flush();
768 return TRUE;
769 }
770
771 public static function doFinish() {
772 $upgrade = new CRM_Upgrade_Form();
773 list($ignore, $latestVer) = $upgrade->getUpgradeVersions();
774 // Seems extraneous in context, but we'll preserve old behavior
775 $upgrade->setVersion($latestVer);
776
777 // Clear cached metadata.
778 Civi::service('settings_manager')->flush();
779
780 // cleanup caches CRM-8739
781 $config = CRM_Core_Config::singleton();
782 $config->cleanupCaches(1);
783
784 $versionCheck = new CRM_Utils_VersionCheck();
785 $versionCheck->flushCache();
786
787 // Rebuild all triggers and re-enable logging if needed
788 $logging = new CRM_Logging_Schema();
789 $logging->fixSchemaDifferences();
790
791 CRM_Core_ManagedEntities::singleton(TRUE)->reconcile(TRUE);
792 }
793
794 /**
795 * Compute any messages which should be displayed before upgrade
796 * by calling the 'setPreUpgradeMessage' on each incremental upgrade
797 * object.
798 *
799 * @param string $preUpgradeMessage
800 * alterable.
801 * @param $currentVer
802 * @param $latestVer
803 */
804 public function setPreUpgradeMessage(&$preUpgradeMessage, $currentVer, $latestVer) {
805 // check for changed message templates
806 CRM_Upgrade_Incremental_General::checkMessageTemplate($preUpgradeMessage, $latestVer, $currentVer);
807 // set global messages
808 CRM_Upgrade_Incremental_General::setPreUpgradeMessage($preUpgradeMessage, $currentVer, $latestVer);
809
810 // Scan through all php files and see if any file is interested in setting pre-upgrade-message
811 // based on $currentVer, $latestVer.
812 // Please note, at this point upgrade hasn't started executing queries.
813 $revisions = $this->getRevisionSequence();
814 foreach ($revisions as $rev) {
815 if (version_compare($currentVer, $rev) < 0) {
816 $versionObject = $this->incrementalPhpObject($rev);
817 CRM_Upgrade_Incremental_General::updateMessageTemplate($preUpgradeMessage, $rev);
818 if (is_callable([$versionObject, 'setPreUpgradeMessage'])) {
819 $versionObject->setPreUpgradeMessage($preUpgradeMessage, $rev, $currentVer);
820 }
821 }
822 }
823 }
824
825 }