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