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