commiting uncommited changes on live site
[weblabels.fsf.org.git] / crm.fsf.org / 20131203 / files / sites / all / modules-old / civicrm / CRM / Upgrade / Incremental / php / FourFive.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.6 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2015 |
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-2015
32 * $Id$
33 *
34 */
35 class CRM_Upgrade_Incremental_php_FourFive {
36 const BATCH_SIZE = 5000;
37
38 /**
39 * @param $errors
40 *
41 * @return bool
42 */
43 public function verifyPreDBstate(&$errors) {
44 return TRUE;
45 }
46
47 /**
48 * Compute any messages which should be displayed beforeupgrade.
49 *
50 * Note: This function is called iteratively for each upcoming
51 * revision to the database.
52 *
53 * @param $preUpgradeMessage
54 * @param string $rev
55 * a version number, e.g. '4.4.alpha1', '4.4.beta3', '4.4.0'.
56 * @param null $currentVer
57 *
58 * @return void
59 */
60 public function setPreUpgradeMessage(&$preUpgradeMessage, $rev, $currentVer = NULL) {
61 }
62
63 /**
64 * Compute any messages which should be displayed after upgrade.
65 *
66 * @param string $postUpgradeMessage
67 * alterable.
68 * @param string $rev
69 * an intermediate version; note that setPostUpgradeMessage is called repeatedly with different $revs.
70 * @return void
71 */
72 public function setPostUpgradeMessage(&$postUpgradeMessage, $rev) {
73 if ($rev == '4.5.alpha1') {
74 $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'));
75 $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".');
76 $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.');
77 }
78 if ($rev == '4.5.beta2') {
79 $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 ).');
80 }
81 if ($rev == '4.5.1') {
82 $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.');
83 }
84 }
85
86 /**
87 * @param $rev
88 *
89 * @return bool
90 */
91 public function upgrade_4_5_alpha1($rev) {
92 // task to process sql
93 $this->addTask(ts('Migrate honoree information to module_data'), 'migrateHonoreeInfo');
94 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => '4.5.alpha1')), 'task_4_5_x_runSql', $rev);
95 $this->addTask(ts('Set default for Individual name fields configuration'), 'addNameFieldOptions');
96
97 // CRM-14522 - The below schema checking is done as foreign key name
98 // for pdf_format_id column varies for different databases
99 // if DB is been into upgrade for 3.4.2 version, it would have pdf_format_id name for FK
100 // else FK_civicrm_msg_template_pdf_format_id
101 $config = CRM_Core_Config::singleton();
102 $dbUf = DB::parseDSN($config->dsn);
103 $query = "
104 SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
105 WHERE TABLE_NAME = 'civicrm_msg_template'
106 AND CONSTRAINT_TYPE = 'FOREIGN KEY'
107 AND TABLE_SCHEMA = %1
108 ";
109 $params = array(1 => array($dbUf['database'], 'String'));
110 $dao = CRM_Core_DAO::executeQuery($query, $params, TRUE, NULL, FALSE, FALSE);
111 if ($dao->fetch()) {
112 if ($dao->CONSTRAINT_NAME == 'FK_civicrm_msg_template_pdf_format_id' ||
113 $dao->CONSTRAINT_NAME == 'pdf_format_id'
114 ) {
115 $sqlDropFK = "ALTER TABLE `civicrm_msg_template`
116 DROP FOREIGN KEY `{$dao->CONSTRAINT_NAME}`,
117 DROP KEY `{$dao->CONSTRAINT_NAME}`";
118 CRM_Core_DAO::executeQuery($sqlDropFK, CRM_Core_DAO::$_nullArray, TRUE, NULL, FALSE, FALSE);
119 }
120 }
121
122 return TRUE;
123 }
124
125 /**
126 * @param $rev
127 *
128 * @return bool
129 */
130 public function upgrade_4_5_beta9($rev) {
131 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => '4.5.beta9')), 'task_4_5_x_runSql', $rev);
132
133 $entityTable = array(
134 'Participant' => 'civicrm_participant_payment',
135 'Contribution' => 'civicrm_contribution',
136 'Membership' => 'civicrm_membership',
137 );
138
139 foreach ($entityTable as $label => $tableName) {
140 list($minId, $maxId) = CRM_Core_DAO::executeQuery("SELECT coalesce(min(id),0), coalesce(max(id),0)
141 FROM {$tableName}")->getDatabaseResult()->fetchRow();
142 for ($startId = $minId; $startId <= $maxId; $startId += self::BATCH_SIZE) {
143 $endId = $startId + self::BATCH_SIZE - 1;
144 $title = ts("Upgrade DB to 4.5.beta9: Fix line items for {$label} (%1 => %2)", array(
145 1 => $startId,
146 2 => $endId,
147 ));
148 $this->addTask($title, 'task_4_5_0_fixLineItem', $startId, $endId, $label);
149 }
150 }
151 return TRUE;
152 }
153
154 /**
155 * (Queue Task Callback)
156 *
157 * update the line items
158 *
159 *
160 * @param CRM_Queue_TaskContext $ctx
161 * @param int $startId
162 * the first/lowest entity ID to convert.
163 * @param int $endId
164 * the last/highest entity ID to convert.
165 * @param
166 *
167 * @return bool
168 */
169 public static function task_4_5_0_fixLineItem(CRM_Queue_TaskContext $ctx, $startId, $endId, $entityTable) {
170
171 $sqlParams = array(
172 1 => array($startId, 'Integer'),
173 2 => array($endId, 'Integer'),
174 );
175 switch ($entityTable) {
176 case 'Contribution':
177 // update all the line item entity_table and entity_id with contribution due to bug CRM-15055
178 CRM_Core_DAO::executeQuery("UPDATE civicrm_line_item li
179 INNER JOIN civicrm_contribution cc ON cc.id = li.contribution_id
180 SET entity_id = li.contribution_id, entity_table = 'civicrm_contribution'
181 WHERE li.contribution_id IS NOT NULL AND li.entity_table <> 'civicrm_participant' AND (cc.id BETWEEN %1 AND %2)", $sqlParams);
182
183 // update the civicrm_line_item.contribution_id
184 CRM_Core_DAO::executeQuery("UPDATE civicrm_line_item li
185 INNER JOIN civicrm_contribution cc ON cc.id = li.entity_id
186 SET contribution_id = entity_id
187 WHERE li.contribution_id IS NULL AND li.entity_table = 'civicrm_contribution' AND (cc.id BETWEEN %1 AND %2)", $sqlParams);
188 break;
189
190 case 'Participant':
191 // update the civicrm_line_item.contribution_id
192 CRM_Core_DAO::executeQuery("UPDATE civicrm_line_item li
193 INNER JOIN civicrm_participant_payment pp ON pp.participant_id = li.entity_id
194 SET li.contribution_id = pp.contribution_id
195 WHERE li.entity_table = 'civicrm_participant' AND li.contribution_id IS NULL AND (pp.id BETWEEN %1 AND %2)", $sqlParams);
196 break;
197
198 case 'Membership':
199 $upgrade = new CRM_Upgrade_Form();
200 // update the line item of membership
201 CRM_Core_DAO::executeQuery("UPDATE civicrm_line_item li
202 INNER JOIN civicrm_membership_payment mp ON mp.contribution_id = li.contribution_id
203 INNER JOIN civicrm_membership cm ON mp.membership_id = cm.id
204 INNER JOIN civicrm_price_field_value pv ON pv.id = li.price_field_value_id
205 SET li.entity_table = 'civicrm_membership', li.entity_id = mp.membership_id
206 WHERE li.entity_table = 'civicrm_contribution'
207 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);
208
209 CRM_Core_DAO::executeQuery("UPDATE civicrm_line_item li
210 INNER JOIN civicrm_membership_payment mp ON mp.contribution_id = li.contribution_id
211 INNER JOIN civicrm_price_field_value pv ON pv.id = li.price_field_value_id
212 SET li.entity_table = 'civicrm_membership', li.entity_id = mp.membership_id
213 WHERE li.entity_table = 'civicrm_contribution'
214 AND pv.membership_type_id IS NOT NULL AND (mp.membership_id BETWEEN %1 AND %2)", $sqlParams);
215
216 CRM_Core_DAO::executeQuery("INSERT INTO civicrm_line_item (entity_table, entity_id, price_field_id, label,
217 qty, unit_price, line_total, price_field_value_id, financial_type_id)
218 SELECT 'civicrm_membership', cm.id, cpf.id price_field_id, cpfv.label, 1 as qty, cpfv.amount, cpfv.amount line_total,
219 cpfv.id price_field_value_id, cpfv.financial_type_id FROM civicrm_membership cm
220 LEFT JOIN civicrm_membership_payment cmp ON cmp.membership_id = cm.id
221 INNER JOIN civicrm_price_field_value cpfv ON cpfv.membership_type_id = cm.membership_type_id
222 INNER JOIN civicrm_price_field cpf ON cpf.id = cpfv.price_field_id
223 INNER JOIN civicrm_price_set cps ON cps.id = cpf.price_set_id
224 WHERE cmp.contribution_id IS NULL AND cps.name = 'default_membership_type_amount' AND (cm.id BETWEEN %1 AND %2)", $sqlParams);
225 break;
226 }
227 return TRUE;
228 }
229
230 /**
231 * Add defaults for the newly introduced name fields configuration in 'contact_edit_options' setting
232 *
233 * @param CRM_Queue_TaskContext $ctx
234 *
235 * @return bool
236 * TRUE for success
237 */
238 public static function addNameFieldOptions(CRM_Queue_TaskContext $ctx) {
239 $query = "SELECT `value` FROM `civicrm_setting` WHERE `group_name` = 'CiviCRM Preferences' AND `name` = 'contact_edit_options'";
240 $dao = CRM_Core_DAO::executeQuery($query);
241 $dao->fetch();
242 $oldValue = unserialize($dao->value);
243
244 $newValue = $oldValue . '12\ 114\ 115\ 116\ 117\ 1';
245
246 $query = "UPDATE `civicrm_setting` SET `value` = %1 WHERE `group_name` = 'CiviCRM Preferences' AND `name` = 'contact_edit_options'";
247 $params = array(1 => array(serialize($newValue), 'String'));
248 CRM_Core_DAO::executeQuery($query, $params);
249
250 return TRUE;
251 }
252
253 /**
254 * Migrate honoree information to uf_join.module_data as honoree columns (text and title) will be dropped
255 * on DB upgrade
256 *
257 * @param CRM_Queue_TaskContext $ctx
258 *
259 * @return bool
260 * TRUE for success
261 */
262 public static function migrateHonoreeInfo(CRM_Queue_TaskContext $ctx) {
263 $query = "ALTER TABLE `civicrm_uf_join`
264 ADD COLUMN `module_data` longtext COMMENT 'Json serialized array of data used by the ufjoin.module'";
265 CRM_Core_DAO::executeQuery($query);
266
267 $honorTypes = array_keys(CRM_Core_OptionGroup::values('honor_type'));
268 $ufGroupDAO = new CRM_Core_DAO_UFGroup();
269 $ufGroupDAO->name = 'new_individual';
270 $ufGroupDAO->find(TRUE);
271
272 $query = "SELECT * FROM civicrm_contribution_page";
273 $dao = CRM_Core_DAO::executeQuery($query);
274
275 if ($dao->N) {
276 $domain = new CRM_Core_DAO_Domain();
277 $domain->find(TRUE);
278 while ($dao->fetch()) {
279 $honorParams = array('soft_credit' => array('soft_credit_types' => $honorTypes));
280 if ($domain->locales) {
281 $locales = explode(CRM_Core_DAO::VALUE_SEPARATOR, $domain->locales);
282 foreach ($locales as $locale) {
283 $honor_block_title = "honor_block_title_{$locale}";
284 $honor_block_text = "honor_block_text_{$locale}";
285 $honorParams['soft_credit'] += array(
286 $locale => array(
287 'honor_block_title' => $dao->$honor_block_title,
288 'honor_block_text' => $dao->$honor_block_text,
289 ),
290 );
291 }
292 }
293 else {
294 $honorParams['soft_credit'] += array(
295 'default' => array(
296 'honor_block_title' => $dao->honor_block_title,
297 'honor_block_text' => $dao->honor_block_text,
298 ),
299 );
300 }
301 $ufJoinParam = array(
302 'module' => 'soft_credit',
303 'entity_table' => 'civicrm_contribution_page',
304 'is_active' => $dao->honor_block_is_active,
305 'entity_id' => $dao->id,
306 'uf_group_id' => $ufGroupDAO->id,
307 'module_data' => json_encode($honorParams),
308 );
309 CRM_Core_BAO_UFJoin::create($ufJoinParam);
310 }
311 }
312
313 return TRUE;
314 }
315
316 /**
317 * Upgrade function.
318 *
319 * @param string $rev
320 */
321 public function upgrade_4_5_9($rev) {
322 // Task to process sql.
323 $this->addTask(ts('Upgrade DB to 4.5.9: Fix saved searches consisting of multi-choice custom field(s)'), 'updateSavedSearch');
324
325 return TRUE;
326 }
327
328 /**
329 * Update saved search for multi-select custom fields on DB upgrade
330 *
331 * @param CRM_Queue_TaskContext $ctx
332 *
333 * @return bool TRUE for success
334 */
335 public static function updateSavedSearch(CRM_Queue_TaskContext $ctx) {
336 $sql = "SELECT id, form_values FROM civicrm_saved_search";
337 $dao = CRM_Core_DAO::executeQuery($sql);
338 while ($dao->fetch()) {
339 $copy = $formValues = unserialize($dao->form_values);
340 $update = FALSE;
341 foreach ($copy as $field => $data_value) {
342 if (preg_match('/^custom_/', $field) && is_array($data_value) && !array_key_exists("${field}_operator", $formValues)) {
343 // Now check for CiviCRM_OP_OR as either key or value in the data_value array.
344 // This is the conclusive evidence of an old-style data format.
345 if (array_key_exists('CiviCRM_OP_OR', $data_value) || FALSE !== array_search('CiviCRM_OP_OR', $data_value)) {
346 // We have old style data. Mark this record to be updated.
347 $update = TRUE;
348 $op = 'and';
349 if (!preg_match('/^custom_([0-9]+)/', $field, $matches)) {
350 // fatal error?
351 continue;
352 }
353 $fieldID = $matches[1];
354 if (array_key_exists('CiviCRM_OP_OR', $data_value)) {
355 // This indicates data structure identified by jamie in the form:
356 // value1 => 1, value2 => , value3 => 1.
357 $data_value = array_keys($data_value, 1);
358
359 // If CiviCRM_OP_OR - change OP from default to OR
360 if ($data_value['CiviCRM_OP_OR'] == 1) {
361 $op = 'or';
362 }
363 unset($data_value['CiviCRM_OP_OR']);
364 }
365 else {
366 // The value is here, but it is not set as a key.
367 // This is using the style identified by Monish - the existence of the value
368 // indicates an OR search and values are set in the form of:
369 // 0 => value1, 1 => value1, 3 => value2.
370 $key = array_search('CiviCRM_OP_OR', $data_value);
371 $op = 'or';
372 unset($data_value[$key]);
373 }
374
375 //If only Or operator has been chosen, means we need to select all values and
376 //so to execute OR operation between these values according to new data structure
377 if (count($data_value) == 0 && $op == 'or') {
378 $customOption = CRM_Core_BAO_CustomOption::getCustomOption($fieldID);
379 foreach ($customOption as $option) {
380 $data_value[] = CRM_Utils_Array::value('value', $option);
381 }
382 }
383
384 $formValues[$field] = $data_value;
385 $formValues["${field}_operator"] = $op;
386 }
387 }
388 }
389
390 if ($update) {
391 $sql = "UPDATE civicrm_saved_search SET form_values = %0 WHERE id = %1";
392 CRM_Core_DAO::executeQuery($sql,
393 array(
394 array(serialize($formValues), 'String'),
395 array($dao->id, 'Integer'),
396 )
397 );
398 }
399 }
400 return TRUE;
401 }
402
403
404 /**
405 * (Queue Task Callback)
406 */
407 public static function task_4_5_x_runSql(CRM_Queue_TaskContext $ctx, $rev) {
408 $upgrade = new CRM_Upgrade_Form();
409 $upgrade->processSQL($rev);
410
411 return TRUE;
412 }
413
414 /**
415 * Syntactic sugar for adding a task which (a) is in this class and (b) has
416 * a high priority.
417 *
418 * After passing the $funcName, you can also pass parameters that will go to
419 * the function. Note that all params must be serializable.
420 */
421 protected function addTask($title, $funcName) {
422 $queue = CRM_Queue_Service::singleton()->load(array(
423 'type' => 'Sql',
424 'name' => CRM_Upgrade_Form::QUEUE_NAME,
425 ));
426
427 $args = func_get_args();
428 $title = array_shift($args);
429 $funcName = array_shift($args);
430 $task = new CRM_Queue_Task(
431 array(get_class($this), $funcName),
432 $args,
433 $title
434 );
435 $queue->createItem($task, array('weight' => -1));
436 }
437
438 }