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