INFRA-132 - Remove white space after an opening "(" or before a closing ")"
[civicrm-core.git] / CRM / Upgrade / Incremental / php / FourFour.php
CommitLineData
a47a2f90 1<?php
2/*
3 +--------------------------------------------------------------------+
39de6fd5 4 | CiviCRM version 4.6 |
a47a2f90 5 +--------------------------------------------------------------------+
06b69b18 6 | Copyright CiviCRM LLC (c) 2004-2014 |
a47a2f90 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 +--------------------------------------------------------------------+
25*/
26
27/**
28 *
29 * @package CRM
06b69b18 30 * @copyright CiviCRM LLC (c) 2004-2014
a47a2f90 31 * $Id$
32 *
33 */
34class CRM_Upgrade_Incremental_php_FourFour {
35 const BATCH_SIZE = 5000;
36
52592398
TO
37 const MAX_WORD_REPLACEMENT_SIZE = 255;
38
624e56fa
EM
39 /**
40 * @param $errors
41 *
42 * @return bool
43 */
00be9182 44 public function verifyPreDBstate(&$errors) {
a47a2f90 45 return TRUE;
46 }
47
48 /**
49 * Compute any messages which should be displayed beforeupgrade
50 *
51 * Note: This function is called iteratively for each upcoming
52 * revision to the database.
53 *
d0f74b53 54 * @param $preUpgradeMessage
c68f8bfa
TO
55 * @param $rev
56 * String, a version number, e.g. '4.4.alpha1', '4.4.beta3', '4.4.0'.
d0f74b53
EM
57 * @param null $currentVer
58 *
a47a2f90 59 * @return void
60 */
00be9182 61 public function setPreUpgradeMessage(&$preUpgradeMessage, $rev, $currentVer = NULL) {
52592398
TO
62 if ($rev == '4.4.beta1') {
63 $apiCalls = self::getConfigArraysAsAPIParams(FALSE);
64 $oversizedEntries = 0;
65 foreach ($apiCalls as $params) {
66 if (!self::isValidWordReplacement($params)) {
67 $oversizedEntries++;
68 }
69 }
70 if ($oversizedEntries > 0) {
71 $preUpgradeMessage .= '<br/>' . ts("WARNING: There are %1 word-replacement entries which will not be valid in v4.4+ (eg with over 255 characters). They will be dropped during upgrade. For details, consult the CiviCRM log.", array(
72 1 => $oversizedEntries
73 ));
74 }
75 }
a47a2f90 76 }
77
78 /**
79 * Compute any messages which should be displayed after upgrade
80 *
c68f8bfa
TO
81 * @param $postUpgradeMessage
82 * String, alterable.
83 * @param $rev
84 * String, an intermediate version; note that setPostUpgradeMessage is called repeatedly with different $revs.
a47a2f90 85 * @return void
86 */
00be9182 87 public function setPostUpgradeMessage(&$postUpgradeMessage, $rev) {
61320313 88 if ($rev == '4.4.1') {
634e1a1a
DL
89 $config = CRM_Core_Config::singleton();
90 if (!empty($config->useIDS)) {
61320313 91 $postUpgradeMessage .= '<br />' . ts("The setting to skip IDS check has been removed. Your site has this configured in civicrm.settings.php but it will no longer work. Instead, use the new permission 'skip IDS check' to bypass the IDS system.");
634e1a1a
DL
92 }
93 }
9e58e6ff 94 if ($rev == '4.4.3') {
09163e8a 95 $postUpgradeMessage .= '<br /><br />' . ts('Default versions of the following System Workflow Message Templates have been modified to handle new functionality: <ul><li>Events - Registration Confirmation and Receipt (on-line)</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).');
9e58e6ff 96 }
1543f800
DG
97 if ($rev == '4.4.3') {
98 $query = "SELECT cft.id financial_trxn
99FROM civicrm_financial_trxn cft
100LEFT JOIN civicrm_entity_financial_trxn ceft ON ceft.financial_trxn_id = cft.id
101LEFT JOIN civicrm_contribution cc ON ceft.entity_id = cc.id
102WHERE ceft.entity_table = 'civicrm_contribution' AND cft.payment_instrument_id IS NULL;";
103 $dao = CRM_Core_DAO::executeQuery($query);
104 if ($dao->N) {
105 $postUpgradeMessage .= '<br /><br /><strong>' . ts('Your database contains %1 financial transaction records with no payment instrument (Paid By is empty). If you use the Accounting Batches feature this may result in unbalanced transactions. If you do not use this feature, you can ignore the condition (although you will be required to select a Paid By value for new transactions). <a href="%2" target="_blank">You can review steps to correct transactions with missing payment instruments on the wiki.</a>', array(1 => $dao->N, 2 => 'http://wiki.civicrm.org/confluence/display/CRMDOC/Fixing+Transactions+Missing+a+Payment+Instrument+-+4.4.3+Upgrades')) . '</strong>';
106 }
107 }
9b873358 108 if ($rev == '4.4.6') {
e418776c 109 $postUpgradeMessage .= '<br /><br /><strong>'. ts('Your contact image urls have been upgraded. If your contact image urls did not follow the standard format for image Urls they have not been upgraded. Please check the log to see image urls that were not upgraded.');
5da97e99 110 }
a47a2f90 111 }
112
624e56fa
EM
113 /**
114 * @param $rev
115 *
116 * @return bool
117 */
00be9182 118 public function upgrade_4_4_alpha1($rev) {
634e1a1a 119 // task to process sql
d1401e86 120 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => '4.4.alpha1')), 'task_4_4_x_runSql', $rev);
a47a2f90 121
122 // Consolidate activity contacts CRM-12274.
d1401e86 123 $this->addTask('Consolidate activity contacts', 'activityContacts');
a47a2f90 124
125 return TRUE;
126 }
127
624e56fa
EM
128 /**
129 * @param $rev
130 */
00be9182 131 public function upgrade_4_4_beta1($rev) {
d1401e86 132 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => '4.4.beta1')), 'task_4_4_x_runSql', $rev);
7ee2786a 133
56d4e0ab 134 // add new 'data' column in civicrm_batch
135 $query = 'ALTER TABLE civicrm_batch ADD data LONGTEXT NULL COMMENT "cache entered data"';
d427e40e 136 CRM_Core_DAO::executeQuery($query, array(), TRUE, NULL, FALSE, FALSE);
56d4e0ab 137
7ee2786a 138 // check if batch entry data exists in civicrm_cache table
f1811020 139 $query = 'SELECT path, data FROM civicrm_cache WHERE group_name = "batch entry"';
7ee2786a 140 $dao = CRM_Core_DAO::executeQuery($query);
141 while ($dao->fetch()) {
142 // get batch id $batchId[2]
143 $batchId = explode('-', $dao->path);
144 $data = unserialize($dao->data);
145
146 // move the data to civicrm_batch table
147 CRM_Core_DAO::setFieldValue('CRM_Batch_DAO_Batch', $batchId[2], 'data', json_encode(array('values' => $data)));
148 }
149
150 // delete entries from civicrm_cache table
f1811020 151 $query = 'DELETE FROM civicrm_cache WHERE group_name = "batch entry"';
7ee2786a 152 CRM_Core_DAO::executeQuery($query);
ba457d64 153
d1401e86 154 $this->addTask('Migrate custom word-replacements', 'wordReplacements');
7ee2786a 155 }
156
624e56fa
EM
157 /**
158 * @param $rev
159 */
00be9182 160 public function upgrade_4_4_1($rev) {
95c0a77c 161 $config = CRM_Core_Config::singleton();
6b12405a
RN
162 // CRM-13327 upgrade handling for the newly added name badges
163 $ogID = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionGroup', 'name_badge', 'id', 'name');
164 $nameBadges = array_flip(array_values(CRM_Core_BAO_OptionValue::getOptionValuesAssocArrayFromName('name_badge')));
165 unset($nameBadges['Avery 5395']);
166 if (!empty($nameBadges)) {
167 $dimension = '{"paper-size":"a4","orientation":"portrait","font-name":"times","font-size":6,"font-style":"","NX":2,"NY":4,"metric":"mm","lMargin":6,"tMargin":19,"SpaceX":0,"SpaceY":0,"width":100,"height":65,"lPadding":0,"tPadding":0}';
168 $query = "UPDATE civicrm_option_value
169 SET value = '{$dimension}'
170 WHERE option_group_id = %1 AND name = 'Fattorini Name Badge 100x65'";
171
172 CRM_Core_DAO::executeQuery($query, array(1 => array($ogID, 'Integer')));
173 }
174 else {
175 $dimensions = array(
176 1 => '{"paper-size":"a4","orientation":"landscape","font-name":"times","font-size":6,"font-style":"","NX":2,"NY":1,"metric":"mm","lMargin":25,"tMargin":27,"SpaceX":0,"SpaceY":35,"width":106,"height":150,"lPadding":5,"tPadding":5}',
177 2 => '{"paper-size":"a4","orientation":"portrait","font-name":"times","font-size":6,"font-style":"","NX":2,"NY":4,"metric":"mm","lMargin":6,"tMargin":19,"SpaceX":0,"SpaceY":0,"width":100,"height":65,"lPadding":0,"tPadding":0}',
178 3 => '{"paper-size":"a4","orientation":"portrait","font-name":"times","font-size":6,"font-style":"","NX":2,"NY":2,"metric":"mm","lMargin":10,"tMargin":28,"SpaceX":0,"SpaceY":0,"width":96,"height":121,"lPadding":5,"tPadding":5}',
179 );
180 $insertStatements = array(
181 1 => "($ogID, %1, '{$dimensions[1]}', %1, NULL, 0, NULL, 2, NULL, 0, 0, 1, NULL, NULL)",
182 2 => "($ogID, %2, '{$dimensions[2]}', %2, NULL, 0, NULL, 3, NULL, 0, 0, 1, NULL, NULL)",
183 3 => "($ogID, %3, '{$dimensions[3]}', %3, NULL, 0, NULL, 4, NULL, 0, 0, 1, NULL, NULL)",
184 );
185
186 $queryParams = array(
187 1 => array('A6 Badge Portrait 150x106', 'String'),
188 2 => array('Fattorini Name Badge 100x65', 'String'),
189 3 => array('Hanging Badge 3-3/4" x 4-3"/4', 'String'),
190 );
3a88e331 191
6b12405a
RN
192 foreach ($insertStatements as $values) {
193 $query = 'INSERT INTO civicrm_option_value (`option_group_id`, `label`, `value`, `name`, `grouping`, `filter`, `is_default`, `weight`, `description`, `is_optgroup`, `is_reserved`, `is_active`, `component_id`, `visibility_id`) VALUES' . $values;
194 CRM_Core_DAO::executeQuery($query, $queryParams);
195 }
196 }
197
95c0a77c
CW
198 // CRM-12578 - Prior to this version a CSS file under drupal would disable core css
199 if (!empty($config->customCSSURL) && strpos($config->userFramework, 'Drupal') === 0) {
200 // The new setting doesn't exist yet - need to create it first
201 CRM_Core_BAO_Setting::updateSettingsFromMetaData();
202 CRM_Core_BAO_Setting::setItem('1', CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, 'disable_core_css');
203 }
204
fcab62b4
CW
205 // CRM-13701 - Fix $config->timeInputFormat
206 $sql = "
207 SELECT time_format
208 FROM civicrm_preferences_date
209 WHERE time_format IS NOT NULL
210 AND time_format <> ''
211 LIMIT 1
212 ";
213 $timeInputFormat = CRM_Core_DAO::singleValueQuery($sql);
214 if ($timeInputFormat && $timeInputFormat != $config->timeInputFormat) {
215 $params = array('timeInputFormat' => $timeInputFormat);
216 CRM_Core_BAO_ConfigSetting::add($params);
217 }
218
187e382a
PJ
219 // CRM-13698 - add 'Available' and 'No-show' activity statuses
220 $insertStatus = array();
221 $nsinc = $avinc = $inc = 0;
222 if (!CRM_Core_OptionGroup::getValue('activity_status', 'Available', 'name')) {
223 $insertStatus[] = "(%1, 'Available', %2, 'Available', NULL, 0, NULL, %3, 0, 0, 1, NULL, NULL)";
224 $avinc = $inc = 1;
225 }
5b8e40ab
CW
226 if (!CRM_Core_OptionGroup::getValue('activity_status', 'No_show', 'name')) {
227 $insertStatus[] = "(%1, 'No-show', %4, 'No_show', NULL, 0, NULL, %5, 0, 0, 1, NULL, NULL)";
187e382a
PJ
228 $nsinc = $inc + 1;
229 }
230 if (!empty($insertStatus)) {
231 $acOptionGroupID = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionGroup', 'activity_status', 'id', 'name');
232 $maxVal = CRM_Core_DAO::singleValueQuery("SELECT MAX(ROUND(op.value)) FROM civicrm_option_value op WHERE op.option_group_id = $acOptionGroupID");
233 $maxWeight = CRM_Core_DAO::singleValueQuery("SELECT MAX(weight) FROM civicrm_option_value WHERE option_group_id = $acOptionGroupID");
234
235 $p[1] = array($acOptionGroupID, 'Integer');
236 if ($avinc) {
e418776c
TO
237 $p[2] = array($avinc + $maxVal, 'Integer');
238 $p[3] = array($avinc + $maxWeight, 'Integer');
187e382a
PJ
239 }
240 if ($nsinc) {
e418776c
TO
241 $p[4] = array($nsinc + $maxVal, 'Integer');
242 $p[5] = array($nsinc + $maxWeight, 'Integer');
187e382a
PJ
243 }
244 $insertStatus = implode(',', $insertStatus);
245
246 $sql = "
247INSERT INTO
248 civicrm_option_value (`option_group_id`, label, `value`, `name`, `grouping`, `filter`, `is_default`, `weight`, `is_optgroup`, `is_reserved`, `is_active`, `component_id`, `visibility_id`)
249VALUES {$insertStatus}";
250 CRM_Core_DAO::executeQuery($sql, $p);
251 }
252
6b12405a 253 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => '4.4.1')), 'task_4_4_x_runSql', $rev);
44379fac 254 $this->addTask('Patch word-replacement schema', 'wordReplacements_patch', $rev);
6b12405a
RN
255 }
256
624e56fa
EM
257 /**
258 * @param $rev
259 *
260 * @return bool
261 */
00be9182 262 public function upgrade_4_4_4($rev) {
23e300df
PJ
263 $fkConstraint = array();
264 if (!CRM_Core_DAO::checkFKConstraintInFormat('civicrm_activity_contact', 'activity_id')) {
265 $fkConstraint[] = "ADD CONSTRAINT `FK_civicrm_activity_contact_activity_id` FOREIGN KEY (`activity_id`) REFERENCES `civicrm_activity` (`id`) ON DELETE CASCADE";
266 }
267 if (!CRM_Core_DAO::checkFKConstraintInFormat('civicrm_activity_contact', 'contact_id')) {
268 $fkConstraint[] = "ADD CONSTRAINT `FK_civicrm_activity_contact_contact_id` FOREIGN KEY (`contact_id`) REFERENCES `civicrm_contact` (`id`) ON DELETE CASCADE;
269";
270 }
271
272 if (!empty($fkConstraint)) {
273 $fkConstraint = implode(',', $fkConstraint);
274 $sql = "ALTER TABLE `civicrm_activity_contact`
275{$fkConstraint}
276";
277 // CRM-14036 : delete entries of un-mapped contacts
e418776c 278 CRM_Core_DAO::executeQuery("DELETE ac FROM civicrm_activity_contact ac
23e300df
PJ
279LEFT JOIN civicrm_contact c
280ON c.id = ac.contact_id
281WHERE c.id IS NULL;
282");
e418776c
TO
283 // delete entries of un-mapped activities
284 CRM_Core_DAO::executeQuery("DELETE ac FROM civicrm_activity_contact ac
23e300df
PJ
285LEFT JOIN civicrm_activity a
286ON a.id = ac.activity_id
287WHERE a.id IS NULL;
288");
289
290 CRM_Core_DAO::executeQuery("SET FOREIGN_KEY_CHECKS=0;");
291 CRM_Core_DAO::executeQuery($sql);
292 CRM_Core_DAO::executeQuery("SET FOREIGN_KEY_CHECKS=1;");
293 }
294
fa4916a4 295 // task to process sql
296 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => '4.4.4')), 'task_4_4_x_runSql', $rev);
297
7bfaef22 298 // CRM-13892 : add `name` column to dashboard schema
fa4916a4 299 $query = "
300ALTER TABLE civicrm_dashboard
301 ADD name varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'Internal name of dashlet.' AFTER domain_id ";
9359d28c 302 CRM_Core_DAO::executeQuery($query, array(), TRUE, NULL, FALSE, FALSE);
fa4916a4 303
304 $dashboard = new CRM_Core_DAO_Dashboard();
305 $dashboard->find();
306 while ($dashboard->fetch()) {
307 $urlElements = explode('/', $dashboard->url);
308 if ($urlElements[1] == 'dashlet') {
309 $url = explode('&', $urlElements[2]);
310 $name = $url[0];
311 }
312 elseif ($urlElements[1] == 'report') {
313 $url = explode('&', $urlElements[3]);
314 $name = 'report/' .$url[0];
315 }
316 $values .= "
317 WHEN {$dashboard->id} THEN '{$name}'
318 ";
319 }
320
321 $query = "
322 UPDATE civicrm_dashboard
323 SET name = CASE id
324 {$values}
325 END;
326 ";
9359d28c 327 CRM_Core_DAO::executeQuery($query, array(), TRUE, NULL, FALSE, FALSE);
d0f74b53 328
52df1bbd
DG
329 // CRM-13998 : missing alter statements for civicrm_report_instance
330 $this->addTask(ts('Confirm civicrm_report_instance sql table for upgrades'), 'updateReportInstanceTable');
331
f15ec728 332 return TRUE;
fa4916a4 333 }
334
624e56fa
EM
335 /**
336 * @param $rev
337 */
9b873358 338 public function upgrade_4_4_6($rev) {
e71693e1 339 $sql = "SELECT count(*) AS count FROM INFORMATION_SCHEMA.STATISTICS where ".
92fae7a2 340 "TABLE_SCHEMA = database() AND INDEX_NAME = 'index_image_url' AND TABLE_NAME = 'civicrm_contact';";
e71693e1
JM
341 $dao = CRM_Core_DAO::executeQuery($sql);
342 $dao->fetch();
4014394e 343 if ($dao->count < 1) {
e71693e1
JM
344 $sql = "CREATE INDEX index_image_url ON civicrm_contact (image_url);";
345 $dao = CRM_Core_DAO::executeQuery($sql);
346 }
347 $minId = CRM_Core_DAO::singleValueQuery('SELECT coalesce(min(id),0) FROM civicrm_contact WHERE image_URL IS NOT NULL');
348 $maxId = CRM_Core_DAO::singleValueQuery('SELECT coalesce(max(id),0) FROM civicrm_contact WHERE image_URL IS NOT NULL');
5da97e99
M
349 for ($startId = $minId; $startId <= $maxId; $startId += self::BATCH_SIZE) {
350 $endId = $startId + self::BATCH_SIZE - 1;
351 $title = ts('Upgrade image_urls (%1 => %2)', array(1 => $startId, 2 => $endId));
352 $this->addTask($title, 'upgradeImageUrls', $startId, $endId);
353 }
354 }
355
624e56fa
EM
356 /**
357 * @param CRM_Queue_TaskContext $ctx
100fef9d
CW
358 * @param int $startId
359 * @param int $endId
624e56fa
EM
360 *
361 * @return bool
362 */
00be9182 363 public function upgrade_4_4_7($rev, $originalVer, $latestVer) {
0e19dab5
TO
364 // For WordPress/Joomla(?), cleanup broken image_URL from 4.4.6 upgrades - https://issues.civicrm.org/jira/browse/CRM-14971
365 $exBackendUrl = CRM_Utils_System::url('civicrm/contact/imagefile', 'photo=XXX', TRUE); // URL formula from 4.4.6 upgrade
366 $exFrontendUrl = CRM_Utils_System::url('civicrm/contact/imagefile', 'photo=XXX', TRUE, NULL, TRUE, TRUE);
367 if ($originalVer == '4.4.6' && $exBackendUrl != $exFrontendUrl) {
368 $minId = CRM_Core_DAO::singleValueQuery('SELECT coalesce(min(id),0) FROM civicrm_contact WHERE image_URL IS NOT NULL');
369 $maxId = CRM_Core_DAO::singleValueQuery('SELECT coalesce(max(id),0) FROM civicrm_contact WHERE image_URL IS NOT NULL');
370 for ($startId = $minId; $startId <= $maxId; $startId += self::BATCH_SIZE) {
371 $endId = $startId + self::BATCH_SIZE - 1;
372 $title = ts('Upgrade image_urls (%1 => %2)', array(1 => $startId, 2 => $endId));
373 $this->addTask($title, 'cleanupBackendImageUrls', $startId, $endId);
374 }
375 }
97f4ef9c 376 $this->addTask(ts('Update saved search information'), 'changeSavedSearch');
0e19dab5
TO
377 }
378
9b873358 379 public static function upgradeImageUrls(CRM_Queue_TaskContext $ctx, $startId, $endId) {
0e19dab5 380 $dao = self::findContactImageUrls($startId, $endId);
5da97e99 381 $failures = array();
9b873358 382 while ($dao->fetch()) {
5da97e99
M
383 $imageURL = $dao->image_url;
384 $baseurl = CIVICRM_UF_BASEURL;
385 $baselen = strlen($baseurl);
9b873358 386 if (substr($imageURL, 0, $baselen) == $baseurl) {
94fbf0d0
ME
387 $photo = basename($dao->image_url);
388 $config = CRM_Core_Config::singleton();
389 $fullpath = $config->customFileUploadDir.$photo;
9b873358 390 if (file_exists($fullpath)) {
e418776c
TO
391 // For anyone who upgraded 4.4.6 release (eg 4.4.0=>4.4.6), the $newImageUrl incorrectly used backend URLs.
392 // For anyone who skipped 4.4.6 (eg 4.4.0=>4.4.7), the $newImageUrl correctly uses frontend URLs
393 self::setContactImageUrl($dao->id,
0e19dab5 394 CRM_Utils_System::url('civicrm/contact/imagefile', 'photo='.$photo, TRUE, NULL, TRUE, TRUE));
5da97e99 395 }
77b97be7 396 else{
e418776c 397 $failures[$dao->id] = $dao->image_url;
94fbf0d0 398 }
5da97e99 399 }
e418776c
TO
400 else{
401 $failures[$dao->id] = $dao->image_url;
402 }
403 }
5da97e99
M
404 CRM_Core_Error::debug_var('imageUrlsNotUpgraded', $failures);
405 return TRUE;
406 }
407
00be9182 408 public static function changeSavedSearch(CRM_Queue_TaskContext $ctx) {
97f4ef9c 409 $membershipStatuses = array_flip(CRM_Member_PseudoConstant::membershipStatus());
410
411 $dao = new CRM_Contact_DAO_SavedSearch();
412 $dao->find();
413 while ($dao->fetch()) {
414 $formValues = CRM_Contact_BAO_SavedSearch::getFormValues($dao->id);
415 if (!empty($formValues['mapper'])) {
416 foreach ($formValues['mapper'] as $key => $value) {
417 foreach ($value as $k => $v) {
418 if ($v[0] == 'Membership' && in_array($v[1], array('membership_status', 'membership_status_id'))) {
419 $value = $formValues['value'][$key][$k];
420 $op = $formValues['operator'][$key][$k];
421 if ($op == 'IN') {
422 $value = trim($value);
423 $value = str_replace('(', '', $value);
424 $value = str_replace(')', '', $value);
425
426 $v = explode(',', $value);
427 $value = array();
428 foreach ($v as $k1 => $v2) {
429 if (is_numeric($v2)) {
430 break 2;
431 }
432 $value[$k1] = $membershipStatuses[$v2];
433 }
434 $formValues['value'][$key][$k] = "(" . implode(',', $value) . ")";
435 }
436 elseif (in_array($op, array('=', '!='))) {
437 if (is_numeric($value)) {
438 break;
439 }
440 $formValues['value'][$key][$k] = $membershipStatuses[$value];
441 }
442 }
443 }
444 }
445 $dao->form_values = serialize($formValues);
446 $dao->save();
447 }
448 }
449
450 return TRUE;
451 }
452
0e19dab5
TO
453 /**
454 * For WordPress/Joomla(?) sites which upgraded to 4.4.6, find back-end image_URLs
455 * (e.g. "http://example.com/wp-admin/admin.php?page=CiviCRM&amp;q=civicrm/contact/imagefile&amp;photo=123.jpg")
456 * and convert them to front-end URLs
457 * (e.g. "http://example.com/?page=CiviCRM&amp;q=civicrm/contact/imagefile&amp;photo=123.jpg").
458 *
459 * @param CRM_Queue_TaskContext $ctx
100fef9d
CW
460 * @param int $startId
461 * @param int $endId
0e19dab5
TO
462 * @return bool
463 */
00be9182 464 public static function cleanupBackendImageUrls(CRM_Queue_TaskContext $ctx, $startId, $endId) {
0e19dab5
TO
465 $dao = self::findContactImageUrls($startId, $endId);
466 while ($dao->fetch()) {
467 $imageUrl = str_replace('&amp;', '&', $dao->image_url);
468 if (preg_match(":civicrm/contact/imagefile.*photo=:", $imageUrl)) {
469 // looks like one of ours
470 $imageUrlParts = parse_url($imageUrl);
471 parse_str($imageUrlParts['query'], $imageUrlQuery);
472 self::setContactImageUrl($dao->id,
473 CRM_Utils_System::url('civicrm/contact/imagefile', 'photo='.$imageUrlQuery['photo'], TRUE, NULL, TRUE, TRUE));
474 }
475 }
476 return TRUE;
477 }
478
479 /**
480 * @param int $startId
481 * @param int $endId
482 * @return CRM_Core_DAO columns include "id" and "image_URL"
483 */
484 public static function findContactImageUrls($startId, $endId) {
485 $sql = "
486SELECT id, image_url
487FROM civicrm_contact
488WHERE 1
489AND id BETWEEN %1 AND %2
490AND image_URL IS NOT NULL
491";
492
493 $params = array(
494 1 => array($startId, 'Integer'),
495 2 => array($endId, 'Integer'),
496 );
497 $dao = CRM_Core_DAO::executeQuery($sql, $params, TRUE, NULL, FALSE, FALSE);
498 return $dao;
499 }
500
501 /**
502 * @param int $cid
503 * @param string $newImageUrl
504 */
505 public static function setContactImageUrl($cid, $newImageUrl) {
506 $sql = 'UPDATE civicrm_contact SET image_url=%1 WHERE id=%2';
507 $params = array(
508 1 => array($newImageUrl, 'String'),
509 2 => array($cid, 'Integer'),
510 );
511 $updatedao = CRM_Core_DAO::executeQuery($sql, $params);
512 }
513
a47a2f90 514 /**
515 * Update activity contacts CRM-12274
516 *
77b97be7
EM
517 * @param CRM_Queue_TaskContext $ctx
518 *
a47a2f90 519 * @return bool TRUE for success
520 */
00be9182 521 public static function activityContacts(CRM_Queue_TaskContext $ctx) {
a47a2f90 522 $upgrade = new CRM_Upgrade_Form();
127ca309 523
e7e657f0 524 $activityContacts = CRM_Core_OptionGroup::values('activity_contacts', FALSE, FALSE, FALSE, NULL, 'name');
b95507ab 525 $ovValue[] = $sourceID = CRM_Utils_Array::key('Activity Source', $activityContacts);
526 $ovValue[] = $assigneeID = CRM_Utils_Array::key('Activity Assignees', $activityContacts);
527 $ovValue[] = $targetID = CRM_Utils_Array::key('Activity Targets', $activityContacts);
634e1a1a 528
9744c42c 529 $optionGroupID = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionGroup', 'activity_contacts', 'id', 'name');
b95507ab 530 if (!empty($ovValue)) {
531 $ovValues = implode(', ', $ovValue);
532 $query = "
634e1a1a 533UPDATE civicrm_option_value
b95507ab 534SET is_reserved = 1
535WHERE option_group_id = {$optionGroupID} AND value IN ($ovValues)";
536
537 $dao = CRM_Core_DAO::executeQuery($query);
538 }
539
9744c42c 540 if (!$assigneeID) {
b95507ab 541 $assigneeID = 1;
9744c42c 542 $value[] = "({$optionGroupID}, 'Activity Assignees', 1, 'Activity Assignees', 1, 1, 1)";
543 }
544 if (!$sourceID) {
b95507ab 545 $sourceID = 2;
9744c42c 546 $value[] = "({$optionGroupID}, 'Activity Source', 2, 'Activity Source', 2, 1, 1)";
547 }
548 if (!$targetID) {
b95507ab 549 $targetID = 3;
9744c42c 550 $value[] = "({$optionGroupID}, 'Activity Targets', 3, 'Activity Targets', 3, 1, 1)";
551 }
552
481a74f4 553 if (!$assigneeID || !$sourceID || !$targetID) {
e418776c 554 $insert = "
9744c42c 555INSERT INTO civicrm_option_value
556(option_group_id, label, value, name, weight, is_reserved, is_active)
557VALUES
558
559";
560 $values = implode(', ', $value);
561 $query = $insert . $values;
562 $dao = CRM_Core_DAO::executeQuery($query);
563 }
564
3a88e331
DL
565 // sometimes an user does not make a clean backup and the above table
566 // already exists, so lets delete this table - CRM-13665
187e382a 567 $query = "DROP TABLE IF EXISTS civicrm_activity_contact";
3a88e331 568 $dao = CRM_Core_DAO::executeQuery($query);
9744c42c 569
a47a2f90 570 $query = "
127ca309 571CREATE TABLE IF NOT EXISTS civicrm_activity_contact (
572 id int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'Activity contact id',
573 activity_id int(10) unsigned NOT NULL COMMENT 'Foreign key to the activity for this record.',
574 contact_id int(10) unsigned NOT NULL COMMENT 'Foreign key to the contact for this record.',
575 record_type_id int(10) unsigned DEFAULT NULL COMMENT 'The record type id for this row',
576 PRIMARY KEY (id),
577 UNIQUE KEY UI_activity_contact (contact_id,activity_id,record_type_id),
578 KEY FK_civicrm_activity_contact_activity_id (activity_id)
a47a2f90 579) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
580";
581
582 $dao = CRM_Core_DAO::executeQuery($query);
634e1a1a
DL
583
584 $query = "
127ca309 585INSERT INTO civicrm_activity_contact (activity_id, contact_id, record_type_id)
586SELECT activity_id, target_contact_id, {$targetID} as record_type_id
a47a2f90 587FROM civicrm_activity_target";
588
589 $dao = CRM_Core_DAO::executeQuery($query);
590
634e1a1a 591 $query = "
127ca309 592INSERT INTO civicrm_activity_contact (activity_id, contact_id, record_type_id)
593SELECT activity_id, assignee_contact_id, {$assigneeID} as record_type_id
a47a2f90 594FROM civicrm_activity_assignment";
595 $dao = CRM_Core_DAO::executeQuery($query);
634e1a1a 596
a47a2f90 597 $query = "
127ca309 598 INSERT INTO civicrm_activity_contact (activity_id, contact_id, record_type_id)
599SELECT id, source_contact_id, {$sourceID} as record_type_id
634e1a1a 600FROM civicrm_activity
a47a2f90 601WHERE source_contact_id IS NOT NULL";
602
603 $dao = CRM_Core_DAO::executeQuery($query);
604
e418776c
TO
605 $query = "DROP TABLE civicrm_activity_target";
606 $dao = CRM_Core_DAO::executeQuery($query);
a47a2f90 607
e418776c
TO
608 $query = "DROP TABLE civicrm_activity_assignment";
609 $dao = CRM_Core_DAO::executeQuery($query);
a47a2f90 610
e418776c 611 $query = "ALTER TABLE civicrm_activity
a47a2f90 612 DROP FOREIGN KEY FK_civicrm_activity_source_contact_id";
634e1a1a 613
e418776c 614 $dao = CRM_Core_DAO::executeQuery($query);
a47a2f90 615
e418776c
TO
616 $query = "ALTER TABLE civicrm_activity DROP COLUMN source_contact_id";
617 $dao = CRM_Core_DAO::executeQuery($query);
a47a2f90 618
e418776c 619 return TRUE;
ba457d64
TO
620 }
621
622 /**
623 * Migrate word-replacements from $config to civicrm_word_replacement
624 *
d0f74b53
EM
625 * @param CRM_Queue_TaskContext $ctx
626 *
ba457d64
TO
627 * @return bool TRUE for success
628 * @see http://issues.civicrm.org/jira/browse/CRM-13187
629 */
00be9182 630 public static function wordReplacements(CRM_Queue_TaskContext $ctx) {
ba457d64 631 $query = "
7c312eca
TO
632CREATE TABLE IF NOT EXISTS `civicrm_word_replacement` (
633 `id` int unsigned NOT NULL AUTO_INCREMENT COMMENT 'Word replacement ID',
02ffc0f2
TO
634 `find_word` varchar(255) COLLATE utf8_bin COMMENT 'Word which need to be replaced',
635 `replace_word` varchar(255) COLLATE utf8_bin COMMENT 'Word which will replace the word in find',
7c312eca
TO
636 `is_active` tinyint COMMENT 'Is this entry active?',
637 `match_type` enum('wildcardMatch', 'exactMatch') DEFAULT 'wildcardMatch',
638 `domain_id` int unsigned COMMENT 'FK to Domain ID. This is for Domain specific word replacement',
639 PRIMARY KEY ( `id` ),
44379fac 640 UNIQUE INDEX `UI_domain_find` (domain_id, find_word),
7c312eca
TO
641 CONSTRAINT FK_civicrm_word_replacement_domain_id FOREIGN KEY (`domain_id`) REFERENCES `civicrm_domain`(`id`)
642) ENGINE=InnoDB DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
643 ";
ba457d64
TO
644 $dao = CRM_Core_DAO::executeQuery($query);
645
daa14c0c 646 self::rebuildWordReplacementTable();
ba457d64 647 return TRUE;
a47a2f90 648 }
649
44379fac
TO
650 /**
651 * Fix misconfigured constraints created in 4.4.0. To distinguish the good
652 * and bad configurations, we change the constraint name from "UI_find"
653 * (the original name in 4.4.0) to "UI_domain_find" (the new name in
654 * 4.4.1).
655 *
d0f74b53
EM
656 * @param CRM_Queue_TaskContext $ctx
657 * @param $rev
658 *
44379fac
TO
659 * @return bool TRUE for success
660 * @see http://issues.civicrm.org/jira/browse/CRM-13655
661 */
00be9182 662 public static function wordReplacements_patch(CRM_Queue_TaskContext $ctx, $rev) {
44379fac
TO
663 if (CRM_Core_DAO::checkConstraintExists('civicrm_word_replacement', 'UI_find')) {
664 CRM_Core_DAO::executeQuery("ALTER TABLE civicrm_word_replacement DROP FOREIGN KEY FK_civicrm_word_replacement_domain_id;");
665 CRM_Core_DAO::executeQuery("ALTER TABLE civicrm_word_replacement DROP KEY FK_civicrm_word_replacement_domain_id;");
666 CRM_Core_DAO::executeQuery("ALTER TABLE civicrm_word_replacement DROP KEY UI_find;");
667 CRM_Core_DAO::executeQuery("ALTER TABLE civicrm_word_replacement MODIFY COLUMN `find_word` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT 'Word which need to be replaced';");
668 CRM_Core_DAO::executeQuery("ALTER TABLE civicrm_word_replacement MODIFY COLUMN `replace_word` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT 'Word which will replace the word in find';");
669 CRM_Core_DAO::executeQuery("ALTER TABLE civicrm_word_replacement ADD CONSTRAINT UI_domain_find UNIQUE KEY `UI_domain_find` (`domain_id`,`find_word`);");
670 CRM_Core_DAO::executeQuery("ALTER TABLE civicrm_word_replacement ADD CONSTRAINT FK_civicrm_word_replacement_domain_id FOREIGN KEY (`domain_id`) REFERENCES `civicrm_domain` (`id`);");
671 }
672 return TRUE;
673 }
674
a47a2f90 675 /**
676 * (Queue Task Callback)
677 */
00be9182 678 public static function task_4_4_x_runSql(CRM_Queue_TaskContext $ctx, $rev) {
a47a2f90 679 $upgrade = new CRM_Upgrade_Form();
680 $upgrade->processSQL($rev);
681
682 return TRUE;
683 }
684
685 /**
686 * Syntatic sugar for adding a task which (a) is in this class and (b) has
687 * a high priority.
688 *
689 * After passing the $funcName, you can also pass parameters that will go to
690 * the function. Note that all params must be serializable.
691 */
692 protected function addTask($title, $funcName) {
693 $queue = CRM_Queue_Service::singleton()->load(array(
694 'type' => 'Sql',
695 'name' => CRM_Upgrade_Form::QUEUE_NAME,
696 ));
697
698 $args = func_get_args();
699 $title = array_shift($args);
700 $funcName = array_shift($args);
701 $task = new CRM_Queue_Task(
702 array(get_class($this), $funcName),
703 $args,
704 $title
705 );
706 $queue->createItem($task, array('weight' => -1));
707 }
cbe56ea6
TO
708
709 /**
daa14c0c
TO
710 * Get all the word-replacements stored in config-arrays
711 * and convert them to params for the WordReplacement.create API.
712 *
0f65e834
TO
713 * Note: This function is duplicated in CRM_Core_BAO_WordReplacement and
714 * CRM_Upgrade_Incremental_php_FourFour to ensure that the incremental upgrade
715 * step behaves consistently even as the BAO evolves in future versions.
716 * However, if there's a bug in here prior to 4.4.0, we should apply the
717 * bugfix in both places.
718 *
c68f8bfa
TO
719 * @param bool $rebuildEach
720 * Whether to perform rebuild after each individual API call.
daa14c0c
TO
721 * @return array Each item is $params for WordReplacement.create
722 * @see CRM_Core_BAO_WordReplacement::convertConfigArraysToAPIParams
cbe56ea6 723 */
00be9182 724 public static function getConfigArraysAsAPIParams($rebuildEach) {
cbe56ea6 725 $wordReplacementCreateParams = array();
cbe56ea6 726 // get all domains
daa14c0c
TO
727 $result = civicrm_api3('domain', 'get', array(
728 'return' => array('locale_custom_strings'),
729 ));
cbe56ea6
TO
730 if (!empty($result["values"])) {
731 foreach ($result["values"] as $value) {
732 $params = array();
cbe56ea6 733 $params["domain_id"] = $value["id"];
63b71ea8 734 $params["options"] = array('wp-rebuild' => $rebuildEach);
cbe56ea6 735 // unserialize word match string
8f3ccaf0
DG
736 $localeCustomArray = array();
737 if (!empty($value["locale_custom_strings"])) {
738 $localeCustomArray = unserialize($value["locale_custom_strings"]);
739 }
cbe56ea6
TO
740 if (!empty($localeCustomArray)) {
741 $wordMatchArray = array();
7c312eca 742 // Traverse Language array
cbe56ea6 743 foreach ($localeCustomArray as $localCustomData) {
7c312eca
TO
744 // Traverse status array "enabled" "disabled"
745 foreach ($localCustomData as $status => $matchTypes) {
e418776c 746 $params["is_active"] = ($status == "enabled") ? TRUE : FALSE;
7c312eca
TO
747 // Traverse Match Type array "wildcardMatch" "exactMatch"
748 foreach ($matchTypes as $matchType => $words) {
749 $params["match_type"] = $matchType;
750 foreach ($words as $word => $replace) {
751 $params["find_word"] = $word;
752 $params["replace_word"] = $replace;
753 $wordReplacementCreateParams[] = $params;
754 }
755 }
cbe56ea6
TO
756 }
757 }
758 }
759 }
760 }
761 return $wordReplacementCreateParams;
8d57c529 762 }
ba457d64 763
daa14c0c
TO
764 /**
765 * Get all the word-replacements stored in config-arrays
766 * and write them out as records in civicrm_word_replacement.
0f65e834
TO
767 *
768 * Note: This function is duplicated in CRM_Core_BAO_WordReplacement and
769 * CRM_Upgrade_Incremental_php_FourFour to ensure that the incremental upgrade
770 * step behaves consistently even as the BAO evolves in future versions.
771 * However, if there's a bug in here prior to 4.4.0, we should apply the
772 * bugfix in both places.
daa14c0c
TO
773 */
774 public static function rebuildWordReplacementTable() {
775 civicrm_api3('word_replacement', 'replace', array(
776 'options' => array('match' => array('domain_id', 'find_word')),
52592398 777 'values' => array_filter(self::getConfigArraysAsAPIParams(FALSE), array(__CLASS__, 'isValidWordReplacement')),
daa14c0c
TO
778 ));
779 CRM_Core_BAO_WordReplacement::rebuild();
ba457d64 780 }
52df1bbd 781
d0f74b53 782
52df1bbd
DG
783 /***
784 * CRM-13998 missing alter statements for civicrm_report_instance
785 ***/
786 public function updateReportInstanceTable() {
787
d0f74b53 788 // add civicrm_report_instance.name
52df1bbd
DG
789
790 $sql = "SELECT count(*) FROM information_schema.columns "
791 . "WHERE table_schema = database() AND table_name = 'civicrm_report_instance' AND COLUMN_NAME = 'name' ";
792
793 $res = CRM_Core_DAO::singleValueQuery($sql);
794
481a74f4 795 if ($res <= 0) {
52df1bbd
DG
796 $sql = "ALTER TABLE civicrm_report_instance ADD `name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'when combined with report_id/template uniquely identifies the instance'";
797 $res = CRM_Core_DAO::executeQuery($sql);
798 }
799
d0f74b53 800 // add civicrm_report_instance args
52df1bbd
DG
801
802 $sql = "SELECT count(*) FROM information_schema.columns WHERE table_schema = database() AND table_name = 'civicrm_report_instance' AND COLUMN_NAME = 'args' ";
803
804 $res = CRM_Core_DAO::singleValueQuery($sql);
805
481a74f4 806 if ($res <= 0) {
52df1bbd
DG
807 $sql = "ALTER TABLE civicrm_report_instance ADD `args` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'arguments that are passed in the url when invoking the instance'";
808
809 $res = CRM_Core_DAO::executeQuery($sql);
810 }
811
812 return TRUE;
813 }
52592398
TO
814
815 /**
816 * @param array $params
817 * @return bool TRUE if $params is valid
818 */
00be9182 819 public static function isValidWordReplacement($params) {
89b6dcf0 820 $result = strlen($params['find_word']) <= self::MAX_WORD_REPLACEMENT_SIZE && strlen($params['replace_word']) <= self::MAX_WORD_REPLACEMENT_SIZE;
52592398
TO
821 if (!$result) {
822 CRM_Core_Error::debug_var('invalidWordReplacement', $params);
823 }
824 return $result;
825 }
a47a2f90 826}