Merge remote-tracking branch 'upstream/4.5' into 4.5-4.6-2015-03-16-17-24-33
[civicrm-core.git] / CRM / Upgrade / Incremental / php / FourFive.php
CommitLineData
296342b1
OB
1<?php
2/*
3 +--------------------------------------------------------------------+
39de6fd5 4 | CiviCRM version 4.6 |
296342b1 5 +--------------------------------------------------------------------+
06b69b18 6 | Copyright CiviCRM LLC (c) 2004-2014 |
296342b1
OB
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. |
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 along with this program; if not, contact CiviCRM LLC |
21 | at info[AT]civicrm[DOT]org. If you have questions about the |
22 | GNU Affero General Public License or the licensing of CiviCRM, |
23 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
24 +--------------------------------------------------------------------+
d25dd0ee 25 */
296342b1
OB
26
27/**
28 *
29 * @package CRM
06b69b18 30 * @copyright CiviCRM LLC (c) 2004-2014
296342b1
OB
31 * $Id$
32 *
33 */
34class CRM_Upgrade_Incremental_php_FourFive {
35 const BATCH_SIZE = 5000;
36
624e56fa
EM
37 /**
38 * @param $errors
39 *
40 * @return bool
41 */
00be9182 42 public function verifyPreDBstate(&$errors) {
296342b1
OB
43 return TRUE;
44 }
45
46 /**
fe482240 47 * Compute any messages which should be displayed beforeupgrade.
296342b1
OB
48 *
49 * Note: This function is called iteratively for each upcoming
50 * revision to the database.
51 *
d0f74b53 52 * @param $preUpgradeMessage
5a4f6742
CW
53 * @param string $rev
54 * a version number, e.g. '4.4.alpha1', '4.4.beta3', '4.4.0'.
d0f74b53
EM
55 * @param null $currentVer
56 *
296342b1
OB
57 * @return void
58 */
00be9182 59 public function setPreUpgradeMessage(&$preUpgradeMessage, $rev, $currentVer = NULL) {
296342b1
OB
60 }
61
62 /**
fe482240 63 * Compute any messages which should be displayed after upgrade.
296342b1 64 *
5a4f6742
CW
65 * @param string $postUpgradeMessage
66 * alterable.
67 * @param string $rev
68 * an intermediate version; note that setPostUpgradeMessage is called repeatedly with different $revs.
296342b1
OB
69 * @return void
70 */
00be9182 71 public function setPostUpgradeMessage(&$postUpgradeMessage, $rev) {
1421174e 72 if ($rev == '4.5.alpha1') {
e2cd07fc 73 $postUpgradeMessage .= '<br /><br />' . ts('Default versions of the following System Workflow Message Templates have been modified to handle new functionality: <ul><li>Contributions - Receipt (off-line)</li><li>Contributions - Receipt (on-line)</li><li>Contributions - Recurring Start and End Notification</li><li>Contributions - Recurring Updates</li><li>Memberships - Receipt (on-line)</li><li>Memberships - Signup and Renewal Receipts (off-line)</li><li>Pledges - Acknowledgement</li></ul> If you have modified these templates, please review the new default versions and implement updates as needed to your copies (Administer > Communications > Message Templates > System Workflow Messages). (<a href="%1">learn more...</a>)', array(1 => 'http://wiki.civicrm.org/confluence/display/CRMDOC/Updating+System+Workflow+Message+Templates+after+Upgrades+-+method+1+-+kdiff'));
b05a0fb6 74 $postUpgradeMessage .= '<br /><br />' . ts('This release allows you to view and edit multiple-record custom field sets in a table format which will be more usable in some cases. You can try out the format by navigating to Administer > Custom Data & Screens > Custom Fields. Click Settings for a custom field set and change Display Style to "Tab with Tables".');
03390e26 75 $postUpgradeMessage .= '<br /><br />' . ts('This release changes the way that anonymous event registrations match participants with existing contacts. By default, all event participants will be matched with existing individuals using the Unsupervised rule, even if multiple registrations with the same email address are allowed. However, you can now select a different matching rule to use for each event. Please review your events to make sure you choose the appropriate matching rule and collect sufficient information for it to match contacts.');
1421174e 76 }
7c3d751c
DG
77 if ($rev == '4.5.beta2') {
78 $postUpgradeMessage .= '<br /><br />' . ts('If you use CiviMail for newsletters or other communications, check out the new sample CiviMail templates which use responsive design to optimize display on mobile devices (Administer > Communications > Message Templates ).');
79 }
0cc5fafb 80 if ($rev == '4.5.1') {
df7a207d 81 $postUpgradeMessage .= '<br /><br />' . ts('WARNING: If you use CiviCase with v4.5.alpha*, v4.5.beta*, or v4.5.0, it is possible that previous upgrades corrupted some CiviCase metadata. If you have not already done so, please identify any custom field sets, smart groups, or reports which refer to CiviCase and ensure that they are properly configured.');
0cc5fafb 82 }
296342b1
OB
83 }
84
624e56fa
EM
85 /**
86 * @param $rev
87 *
88 * @return bool
89 */
00be9182 90 public function upgrade_4_5_alpha1($rev) {
296342b1 91 // task to process sql
3182e644 92 $this->addTask(ts('Migrate honoree information to module_data'), 'migrateHonoreeInfo');
d8f8b40f 93 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => '4.5.alpha1')), 'task_4_5_x_runSql', $rev);
8b49cb50
OB
94 $this->addTask(ts('Set default for Individual name fields configuration'), 'addNameFieldOptions');
95
64542f7e
PJ
96 // CRM-14522 - The below schema checking is done as foreign key name
97 // for pdf_format_id column varies for different databases
98 // if DB is been into upgrade for 3.4.2 version, it would have pdf_format_id name for FK
99 // else FK_civicrm_msg_template_pdf_format_id
100 $config = CRM_Core_Config::singleton();
101 $dbUf = DB::parseDSN($config->dsn);
102 $query = "
103SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
104WHERE TABLE_NAME = 'civicrm_msg_template'
105AND CONSTRAINT_TYPE = 'FOREIGN KEY'
106AND TABLE_SCHEMA = %1
107";
108 $params = array(1 => array($dbUf['database'], 'String'));
109 $dao = CRM_Core_DAO::executeQuery($query, $params, TRUE, NULL, FALSE, FALSE);
110 if ($dao->fetch()) {
111 if ($dao->CONSTRAINT_NAME == 'FK_civicrm_msg_template_pdf_format_id' ||
353ffa53
TO
112 $dao->CONSTRAINT_NAME == 'pdf_format_id'
113 ) {
64542f7e
PJ
114 $sqlDropFK = "ALTER TABLE `civicrm_msg_template`
115DROP FOREIGN KEY `{$dao->CONSTRAINT_NAME}`,
116DROP KEY `{$dao->CONSTRAINT_NAME}`";
117 CRM_Core_DAO::executeQuery($sqlDropFK, CRM_Core_DAO::$_nullArray, TRUE, NULL, FALSE, FALSE);
118 }
119 }
120
8b49cb50
OB
121 return TRUE;
122 }
123
f49da658
PN
124 /**
125 * @param $rev
126 *
127 * @return bool
128 */
00be9182 129 public function upgrade_4_5_beta9($rev) {
d8f8b40f 130 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => '4.5.beta9')), 'task_4_5_x_runSql', $rev);
0cc5fafb 131
15ed8da7
PN
132 $entityTable = array(
133 'Participant' => 'civicrm_participant_payment',
17ea44da 134 'Contribution' => 'civicrm_contribution',
15ed8da7
PN
135 'Membership' => 'civicrm_membership',
136 );
0cc5fafb 137
15ed8da7
PN
138 foreach ($entityTable as $label => $tableName) {
139 list($minId, $maxId) = CRM_Core_DAO::executeQuery("SELECT coalesce(min(id),0), coalesce(max(id),0)
140 FROM {$tableName}")->getDatabaseResult()->fetchRow();
141 for ($startId = $minId; $startId <= $maxId; $startId += self::BATCH_SIZE) {
142 $endId = $startId + self::BATCH_SIZE - 1;
353ffa53
TO
143 $title = ts("Upgrade DB to 4.5.beta9: Fix line items for {$label} (%1 => %2)", array(
144 1 => $startId,
af9b09df 145 2 => $endId,
353ffa53 146 ));
15ed8da7 147 $this->addTask($title, 'task_4_5_0_fixLineItem', $startId, $endId, $label);
0cc5fafb 148 }
149 }
f49da658
PN
150 return TRUE;
151 }
152
153 /**
154 * (Queue Task Callback)
155 *
c490a46a 156 * update the line items
0cc5fafb 157 *
f49da658
PN
158 *
159 * @param CRM_Queue_TaskContext $ctx
5a4f6742
CW
160 * @param int $startId
161 * the first/lowest entity ID to convert.
162 * @param int $endId
163 * the last/highest entity ID to convert.
0cc5fafb 164 * @param
f49da658
PN
165 *
166 * @return bool
167 */
00be9182 168 public static function task_4_5_0_fixLineItem(CRM_Queue_TaskContext $ctx, $startId, $endId, $entityTable) {
0cc5fafb 169
f49da658
PN
170 $sqlParams = array(
171 1 => array($startId, 'Integer'),
172 2 => array($endId, 'Integer'),
173 );
174 switch ($entityTable) {
0cc5fafb 175 case 'Contribution':
f49da658 176 // update all the line item entity_table and entity_id with contribution due to bug CRM-15055
17ea44da
PN
177 CRM_Core_DAO::executeQuery("UPDATE civicrm_line_item li
178 INNER JOIN civicrm_contribution cc ON cc.id = li.contribution_id
179 SET entity_id = li.contribution_id, entity_table = 'civicrm_contribution'
180 WHERE li.contribution_id IS NOT NULL AND li.entity_table <> 'civicrm_participant' AND (cc.id BETWEEN %1 AND %2)", $sqlParams);
0cc5fafb 181
f49da658 182 // update the civicrm_line_item.contribution_id
17ea44da 183 CRM_Core_DAO::executeQuery("UPDATE civicrm_line_item li
0cc5fafb 184 INNER JOIN civicrm_contribution cc ON cc.id = li.entity_id
f49da658 185 SET contribution_id = entity_id
0cc5fafb 186 WHERE li.contribution_id IS NULL AND li.entity_table = 'civicrm_contribution' AND (cc.id BETWEEN %1 AND %2)", $sqlParams);
f49da658 187 break;
0cc5fafb 188
15ed8da7 189 case 'Participant':
f49da658 190 // update the civicrm_line_item.contribution_id
0cc5fafb 191 CRM_Core_DAO::executeQuery("UPDATE civicrm_line_item li
f49da658
PN
192 INNER JOIN civicrm_participant_payment pp ON pp.participant_id = li.entity_id
193 SET li.contribution_id = pp.contribution_id
17ea44da 194 WHERE li.entity_table = 'civicrm_participant' AND li.contribution_id IS NULL AND (pp.id BETWEEN %1 AND %2)", $sqlParams);
f49da658 195 break;
0cc5fafb 196
15ed8da7 197 case 'Membership':
f49da658
PN
198 $upgrade = new CRM_Upgrade_Form();
199 // update the line item of membership
200 CRM_Core_DAO::executeQuery("UPDATE civicrm_line_item li
201 INNER JOIN civicrm_membership_payment mp ON mp.contribution_id = li.contribution_id
202 INNER JOIN civicrm_membership cm ON mp.membership_id = cm.id
203 INNER JOIN civicrm_price_field_value pv ON pv.id = li.price_field_value_id
204 SET li.entity_table = 'civicrm_membership', li.entity_id = mp.membership_id
205 WHERE li.entity_table = 'civicrm_contribution'
17ea44da 206 AND pv.membership_type_id IS NOT NULL AND cm.membership_type_id = pv.membership_type_id AND (cm.id BETWEEN %1 AND %2)", $sqlParams);
0cc5fafb 207
f49da658
PN
208 CRM_Core_DAO::executeQuery("UPDATE civicrm_line_item li
209 INNER JOIN civicrm_membership_payment mp ON mp.contribution_id = li.contribution_id
210 INNER JOIN civicrm_price_field_value pv ON pv.id = li.price_field_value_id
211 SET li.entity_table = 'civicrm_membership', li.entity_id = mp.membership_id
212 WHERE li.entity_table = 'civicrm_contribution'
17ea44da 213 AND pv.membership_type_id IS NOT NULL AND (mp.membership_id BETWEEN %1 AND %2)", $sqlParams);
0cc5fafb 214
17ea44da 215 CRM_Core_DAO::executeQuery("INSERT INTO civicrm_line_item (entity_table, entity_id, price_field_id, label,
f49da658 216 qty, unit_price, line_total, price_field_value_id, financial_type_id)
0cc5fafb 217 SELECT 'civicrm_membership', cm.id, cpf.id price_field_id, cpfv.label, 1 as qty, cpfv.amount, cpfv.amount line_total,
f49da658
PN
218 cpfv.id price_field_value_id, cpfv.financial_type_id FROM civicrm_membership cm
219 LEFT JOIN civicrm_membership_payment cmp ON cmp.membership_id = cm.id
17ea44da
PN
220 INNER JOIN civicrm_price_field_value cpfv ON cpfv.membership_type_id = cm.membership_type_id
221 INNER JOIN civicrm_price_field cpf ON cpf.id = cpfv.price_field_id
222 INNER JOIN civicrm_price_set cps ON cps.id = cpf.price_set_id
f49da658
PN
223 WHERE cmp.contribution_id IS NULL AND cps.name = 'default_membership_type_amount' AND (cm.id BETWEEN %1 AND %2)", $sqlParams);
224 break;
0cc5fafb 225 }
f49da658
PN
226 return TRUE;
227 }
228
8b49cb50
OB
229 /**
230 * Add defaults for the newly introduced name fields configuration in 'contact_edit_options' setting
231 *
d0f74b53
EM
232 * @param CRM_Queue_TaskContext $ctx
233 *
a6c01b45
CW
234 * @return bool
235 * TRUE for success
8b49cb50 236 */
00be9182 237 public static function addNameFieldOptions(CRM_Queue_TaskContext $ctx) {
8b49cb50
OB
238 $query = "SELECT `value` FROM `civicrm_setting` WHERE `group_name` = 'CiviCRM Preferences' AND `name` = 'contact_edit_options'";
239 $dao = CRM_Core_DAO::executeQuery($query);
240 $dao->fetch();
241 $oldValue = unserialize($dao->value);
242
243 $newValue = $oldValue . '12\ 114\ 115\ 116\ 117\ 1';
244
245 $query = "UPDATE `civicrm_setting` SET `value` = %1 WHERE `group_name` = 'CiviCRM Preferences' AND `name` = 'contact_edit_options'";
246 $params = array(1 => array(serialize($newValue), 'String'));
247 CRM_Core_DAO::executeQuery($query, $params);
248
296342b1
OB
249 return TRUE;
250 }
251
3182e644 252 /**
253 * Migrate honoree information to uf_join.module_data as honoree columns (text and title) will be dropped
254 * on DB upgrade
255 *
256 * @param CRM_Queue_TaskContext $ctx
257 *
a6c01b45
CW
258 * @return bool
259 * TRUE for success
3182e644 260 */
00be9182 261 public static function migrateHonoreeInfo(CRM_Queue_TaskContext $ctx) {
3182e644 262 $query = "ALTER TABLE `civicrm_uf_join`
263 ADD COLUMN `module_data` longtext COMMENT 'Json serialized array of data used by the ufjoin.module'";
e418776c 264 CRM_Core_DAO::executeQuery($query);
3182e644 265
266 $honorTypes = array_keys(CRM_Core_OptionGroup::values('honor_type'));
267 $ufGroupDAO = new CRM_Core_DAO_UFGroup();
268 $ufGroupDAO->name = 'new_individual';
269 $ufGroupDAO->find(TRUE);
270
271 $query = "SELECT * FROM civicrm_contribution_page";
272 $dao = CRM_Core_DAO::executeQuery($query);
273
274 if ($dao->N) {
2177d15c 275 $domain = new CRM_Core_DAO_Domain();
3182e644 276 $domain->find(TRUE);
277 while ($dao->fetch()) {
278 $honorParams = array('soft_credit' => array('soft_credit_types' => $honorTypes));
279 if ($domain->locales) {
280 $locales = explode(CRM_Core_DAO::VALUE_SEPARATOR, $domain->locales);
281 foreach ($locales as $locale) {
e418776c
TO
282 $honor_block_title = "honor_block_title_{$locale}";
283 $honor_block_text = "honor_block_text_{$locale}";
3182e644 284 $honorParams['soft_credit'] += array(
285 $locale => array(
286 'honor_block_title' => $dao->$honor_block_title,
287 'honor_block_text' => $dao->$honor_block_text,
288 ),
289 );
290 }
291 }
292 else {
293 $honorParams['soft_credit'] += array(
294 'default' => array(
295 'honor_block_title' => $dao->honor_block_title,
296 'honor_block_text' => $dao->honor_block_text,
297 ),
298 );
299 }
300 $ufJoinParam = array(
301 'module' => 'soft_credit',
302 'entity_table' => 'civicrm_contribution_page',
303 'is_active' => $dao->honor_block_is_active,
304 'entity_id' => $dao->id,
305 'uf_group_id' => $ufGroupDAO->id,
306 'module_data' => json_encode($honorParams),
307 );
308 CRM_Core_BAO_UFJoin::create($ufJoinParam);
309 }
310 }
311
312 return TRUE;
313 }
314
bb606fef 315 /**
316 * Upgrade function.
317 *
318 * @param string $rev
319 */
c50c7e9f 320 public function upgrade_4_5_9($rev) {
bb606fef 321 // Task to process sql.
c50c7e9f 322 $this->addTask(ts('Upgrade DB to 4.5.9: Fix saved searches consisting of multi-choice custom field(s)'), 'updateSavedSearch');
bb606fef 323
324 return TRUE;
325 }
326
327 /**
328 * Update saved search for multi-select custom fields on DB upgrade
329 *
330 * @param CRM_Queue_TaskContext $ctx
331 *
332 * @return bool TRUE for success
333 */
334 static function updateSavedSearch(CRM_Queue_TaskContext $ctx) {
335 $sql = "SELECT id, form_values FROM civicrm_saved_search";
336 $dao = CRM_Core_DAO::executeQuery($sql);
337 while ($dao->fetch()) {
00e0fd5e
JM
338 $copy = $formValues = unserialize($dao->form_values);
339 $update = FALSE;
340 foreach ($copy as $field => $data_value) {
6a4282e5 341 if (preg_match('/^custom_/', $field) && is_array($data_value) && !array_key_exists("${field}_operator", $formValues)) {
00e0fd5e
JM
342 // Now check for CiviCRM_OP_OR as either key or value in the data_value array.
343 // This is the conclusive evidence of an old-style data format.
344 if(array_key_exists('CiviCRM_OP_OR', $data_value) || FALSE !== array_search('CiviCRM_OP_OR', $data_value)) {
345 // We have old style data. Mark this record to be updated.
346 $update = TRUE;
347 $op = 'and';
348 if(!preg_match('/^custom_([0-9]+)/', $field, $matches)) {
349 // fatal error?
350 continue;
351 }
352 $fieldID= $matches[1];
353 if (array_key_exists('CiviCRM_OP_OR', $data_value)) {
354 // This indicates data structure identified by jamie in the form:
355 // value1 => 1, value2 => , value3 => 1.
356 $data_value = array_keys($data_value, 1);
357
358 // If CiviCRM_OP_OR - change OP from default to OR
359 if($data_value['CiviCRM_OP_OR'] == 1) {
6a4282e5 360 $op = 'or';
6a4282e5 361 }
00e0fd5e
JM
362 unset($data_value['CiviCRM_OP_OR']);
363 }
364 else {
365 // The value is here, but it is not set as a key.
366 // This is using the style identified by Monish - the existence of the value
367 // indicates an OR search and values are set in the form of:
368 // 0 => value1, 1 => value1, 3 => value2.
6a4282e5 369 $key = array_search('CiviCRM_OP_OR', $data_value);
00e0fd5e
JM
370 $op = 'or';
371 unset($data_value[$key]);
09ffa0c1 372 }
00e0fd5e
JM
373
374 $formValues[$field] = $data_value;
375 $formValues["${field}_operator"] = $op;
09ffa0c1 376 }
bb606fef 377 }
378 }
bb606fef 379
00e0fd5e
JM
380 if($update) {
381 $sql = "UPDATE civicrm_saved_search SET form_values = %0 WHERE id = %1";
382 CRM_Core_DAO::executeQuery($sql,
383 array(
384 array(serialize($formValues), 'String'),
385 array($dao->id, 'Integer'),
386 )
387 );
388 }
389 }
bb606fef 390 return TRUE;
391 }
392
393
296342b1
OB
394 /**
395 * (Queue Task Callback)
396 */
00be9182 397 public static function task_4_5_x_runSql(CRM_Queue_TaskContext $ctx, $rev) {
296342b1
OB
398 $upgrade = new CRM_Upgrade_Form();
399 $upgrade->processSQL($rev);
400
401 return TRUE;
402 }
403
404 /**
d0f74b53 405 * Syntactic sugar for adding a task which (a) is in this class and (b) has
296342b1
OB
406 * a high priority.
407 *
408 * After passing the $funcName, you can also pass parameters that will go to
409 * the function. Note that all params must be serializable.
410 */
411 protected function addTask($title, $funcName) {
412 $queue = CRM_Queue_Service::singleton()->load(array(
413 'type' => 'Sql',
414 'name' => CRM_Upgrade_Form::QUEUE_NAME,
415 ));
416
417 $args = func_get_args();
418 $title = array_shift($args);
419 $funcName = array_shift($args);
420 $task = new CRM_Queue_Task(
421 array(get_class($this), $funcName),
422 $args,
423 $title
424 );
425 $queue->createItem($task, array('weight' => -1));
426 }
96025800 427
296342b1 428}