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