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