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