CRM-15928. Rename variable to be more descriptive, update inline docs.
[civicrm-core.git] / CRM / Upgrade / Incremental / php / FourSeven.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.7 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2016 |
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 * Upgrade logic for 4.7
29 */
30 class CRM_Upgrade_Incremental_php_FourSeven extends CRM_Upgrade_Incremental_Base {
31
32 /**
33 * Compute any messages which should be displayed beforeupgrade.
34 *
35 * Note: This function is called iteratively for each upcoming
36 * revision to the database.
37 *
38 * @param string $preUpgradeMessage
39 * @param string $rev
40 * a version number, e.g. '4.4.alpha1', '4.4.beta3', '4.4.0'.
41 * @param null $currentVer
42 */
43 public function setPreUpgradeMessage(&$preUpgradeMessage, $rev, $currentVer = NULL) {
44 if ($rev == '4.7.alpha1') {
45 // CRM-16478 Remove custom fatal error template path option
46 $config = CRM_Core_Config::singleton();
47 if (!empty($config->fatalErrorTemplate) && $config->fatalErrorTemplate != 'CRM/common/fatal.tpl') {
48 $preUpgradeMessage .= '<p>' . ts('The custom fatal error template setting will be removed during the upgrade. You are currently using this custom template: %1 . Following the upgrade you will need to use the standard approach to overriding template files, as described in the documentation.', array(1 => $config->fatalErrorTemplate)) . '</p>';
49 }
50 }
51 if ($rev == '4.7.alpha4') {
52 // CRM-17004 Warn of Moneris removal
53 $count = 1;
54 // Query only works in 4.3+
55 if (version_compare($currentVer, "4.3.0") > 0) {
56 $count = CRM_Core_DAO::singleValueQuery("SELECT COUNT(id) FROM civicrm_payment_processor WHERE payment_processor_type_id IN (SELECT id FROM civicrm_payment_processor_type WHERE name = 'Moneris')");
57 }
58 if ($count && !function_exists('moneris_civicrm_managed')) {
59 $preUpgradeMessage .= '<p>' . ts('The %1 payment processor is no longer bundled with CiviCRM. After upgrading you will need to install the extension to continue using it.', array(1 => 'Moneris')) . '</p>';
60 }
61 }
62 }
63
64 /**
65 * Compute any messages which should be displayed after upgrade.
66 *
67 * @param string $postUpgradeMessage
68 * alterable.
69 * @param string $rev
70 * an intermediate version; note that setPostUpgradeMessage is called repeatedly with different $revs.
71 */
72 public function setPostUpgradeMessage(&$postUpgradeMessage, $rev) {
73 if ($rev == '4.7.alpha1') {
74 $config = CRM_Core_Config::singleton();
75 // FIXME: Performing an upgrade step during postUpgrade message phase is probably bad
76 $editor_id = self::updateWysiwyg();
77 $msg = NULL;
78 $ext_href = 'href="' . CRM_Utils_System::url('civicrm/admin/extensions', 'reset=1') . '"';
79 $dsp_href = 'href="' . CRM_Utils_System::url('civicrm/admin/setting/preferences/display', 'reset=1') . '"';
80 $blog_href = 'href="https://civicrm.org/blogs/colemanw/big-changes-wysiwyg-editing-47"';
81 switch ($editor_id) {
82 // TinyMCE
83 case 1:
84 $msg = ts('Your configured editor "TinyMCE" is no longer part of the main CiviCRM download. To continue using it, visit the <a %1>Manage Extensions</a> page to download and install the TinyMCE extension.', array(1 => $ext_href));
85 break;
86
87 // Drupal/Joomla editor
88 case 3:
89 case 4:
90 $msg = ts('CiviCRM no longer integrates with the "%1 Default Editor." Your wysiwyg setting has been reset to the built-in CKEditor. <a %2>Learn more...</a>', array(1 => $config->userFramework, 2 => $blog_href));
91 break;
92 }
93 if ($msg) {
94 $postUpgradeMessage .= '<p>' . $msg . '</p>';
95 }
96 $postUpgradeMessage .= '<p>' . ts('CiviCRM now includes the easy-to-use CKEditor Configurator. To customize the features and display of your wysiwyg editor, visit the <a %1>Display Preferences</a> page. <a %2>Learn more...</a>', array(1 => $dsp_href, 2 => $blog_href)) . '</p>';
97
98 $postUpgradeMessage .= '<br /><br />' . ts('Default version of the following System Workflow Message Templates have been modified: <ul><li>Personal Campaign Pages - Owner Notification</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).');
99
100 $postUpgradeMessage .= '<p>' . ts('The custom fatal error template setting has been removed.') . '</p>';
101 }
102 if ($rev == '4.7.21') {
103 $postUpgradeMessage .= '<br /><br />' . ts("WARNING: For increased security, profile submissions embedded in remote sites are no longer allowed to create or edit data by default. If you need to allow users to submit profiles from external sites, you can restore this at Administer > System Settings > Misc (Undelete, PDFs, Limits, Logging, Captcha, etc.) > 'Accept profile submissions from external sites'");
104 }
105 }
106
107 /**
108 * Upgrade function.
109 *
110 * @param string $rev
111 */
112 public function upgrade_4_7_alpha1($rev) {
113 $this->addTask('Migrate \'on behalf of\' information to module_data', 'migrateOnBehalfOfInfo');
114 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
115 $this->addTask(ts('Migrate Settings to %1', array(1 => $rev)), 'migrateSettings', $rev);
116 $this->addTask('Add Getting Started dashlet', 'addGettingStartedDashlet', $rev);
117 }
118
119 /**
120 * Upgrade function.
121 *
122 * @param string $rev
123 */
124 public function upgrade_4_7_alpha4($rev) {
125 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
126 $this->addTask(ts('Remove %1', array(1 => 'Moneris')), 'removePaymentProcessorType', 'Moneris');
127 $this->addTask('Update Smart Groups', 'fixContactTypeInSmartGroups');
128 }
129
130 /**
131 * Upgrade function.
132 *
133 * @param string $rev
134 */
135 public function upgrade_4_7_beta2($rev) {
136 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
137 $this->addTask('Delete unused file', 'deleteVersionCheckCacheFile');
138 }
139
140 /**
141 * Upgrade function.
142 *
143 * @param string $rev
144 */
145 public function upgrade_4_7_beta6($rev) {
146 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
147 $this->addTask('Disable flexible jobs extension', 'disableFlexibleJobsExtension');
148 $this->addTask('Add Index to financial_trxn trxn_id field', 'addIndexFinancialTrxnTrxnID');
149 }
150
151 /**
152 * Upgrade function.
153 *
154 * @param string $rev
155 */
156 public function upgrade_4_7_1($rev) {
157 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
158 $this->addTask('Add Index to civicrm_contribution creditnote_id field', 'addIndexContributionCreditNoteID');
159 }
160
161 /**
162 * Upgrade function.
163 *
164 * @param string $rev
165 */
166 public function upgrade_4_7_2($rev) {
167 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
168 $this->addTask('Fix Index on civicrm_financial_item combined entity_id + entity_table', 'addCombinedIndexFinancialItemEntityIDEntityType');
169 $this->addTask('enable financial account relationships for chargeback & refund', 'addRefundAndChargeBackAccountsIfNotExist');
170 $this->addTask('Add Index to civicrm_contribution.source', 'addIndexContributionSource');
171 }
172
173 /**
174 * Upgrade function.
175 *
176 * @param string $rev
177 */
178 public function upgrade_4_7_3($rev) {
179 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
180 $this->addTask('Add Index to civicrm_contribution.total_amount', 'addIndexContributionAmount');
181 }
182
183 /**
184 * Upgrade function.
185 *
186 * @param string $rev
187 */
188 public function upgrade_4_7_4($rev) {
189 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
190 $this->addTask('Add Contact Deleted by Merge Activity Type', 'addDeletedByMergeActivityType');
191 }
192
193 /**
194 * Upgrade function.
195 *
196 * @param string $rev
197 */
198 public function upgrade_4_7_7($rev) {
199 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
200 // https://issues.civicrm.org/jira/browse/CRM-18006
201 if (CRM_Core_DAO::checkTableExists('civicrm_install_canary')) {
202 CRM_Core_DAO::executeQuery('ALTER TABLE civicrm_install_canary ENGINE=InnoDB');
203 }
204 }
205
206 /**
207 * Upgrade function.
208 *
209 * @param string $rev
210 */
211 public function upgrade_4_7_8($rev) {
212 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
213 $this->addTask('Upgrade mailing foreign key constraints', 'upgradeMailingFKs');
214 }
215
216 /**
217 * Upgrade function.
218 *
219 * @param string $rev
220 */
221 public function upgrade_4_7_10($rev) {
222 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
223 $this->addTask(ts('Upgrade Add Help Pre and Post Fields to price value table'), 'addHelpPreAndHelpPostFieldsPriceFieldValue');
224 $this->addTask(ts('Alter index and type for image URL'), 'alterIndexAndTypeForImageURL');
225 }
226
227 /**
228 * Upgrade function.
229 *
230 * @param string $rev
231 */
232 public function upgrade_4_7_11($rev) {
233 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
234 $this->addTask('Dashboard schema updates', 'dashboardSchemaUpdate');
235 }
236
237 /*
238 * Important! All upgrade functions MUST call the 'runSql' task.
239 * Uncomment and use the following template for a new upgrade version
240 * (change the x in the function name):
241 */
242
243 // /**
244 // * Upgrade function.
245 // *
246 // * @param string $rev
247 // */
248 // public function upgrade_4_7_x($rev) {
249 // $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
250 // // Additional tasks here...
251 // }
252
253 /**
254 * CRM-16354
255 *
256 * @return int
257 */
258 public static function updateWysiwyg() {
259 $editorID = Civi::settings()->get('editor_id');
260 // Previously a numeric value indicated one of 4 wysiwyg editors shipped in core, and no value indicated 'Textarea'
261 // Now the options are "Textarea", "CKEditor", and the rest have been dropped from core.
262 $newEditor = $editorID ? "CKEditor" : "Textarea";
263 Civi::settings()->set('editor_id', $newEditor);
264
265 return $editorID;
266 }
267
268 /**
269 * Migrate any last remaining options from `civicrm_domain.config_backend` to `civicrm_setting`.
270 * Cleanup setting schema.
271 *
272 * @param CRM_Queue_TaskContext $ctx
273 * @return bool
274 */
275 public function migrateSettings(CRM_Queue_TaskContext $ctx) {
276 // Tip: If there are problems with adding the new uniqueness index, try inspecting:
277 // SELECT name, domain_id, contact_id, count(*) AS dupes FROM civicrm_setting cs GROUP BY name, domain_id, contact_id HAVING dupes > 1;
278
279 // Nav records are expendable. https://forum.civicrm.org/index.php?topic=36933.0
280 CRM_Core_DAO::executeQuery('DELETE FROM civicrm_setting WHERE contact_id IS NOT NULL AND name = "navigation"');
281
282 CRM_Core_DAO::executeQuery('ALTER TABLE civicrm_setting DROP INDEX index_group_name');
283 CRM_Core_DAO::executeQuery('ALTER TABLE civicrm_setting DROP COLUMN group_name');
284
285 // Handle Strange activity_tab_filter settings.
286 CRM_Core_DAO::executeQuery('CREATE TABLE civicrm_activity_setting LIKE civicrm_setting');
287 CRM_Core_DAO::executeQuery('ALTER TABLE civicrm_activity_setting ADD UNIQUE INDEX index_domain_contact_name (domain_id, contact_id, name)');
288 CRM_Core_DAO::executeQuery('INSERT INTO civicrm_activity_setting (name, contact_id, domain_id, value)
289 SELECT DISTINCT name, contact_id, domain_id, value
290 FROM civicrm_setting
291 WHERE name = "activity_tab_filter"
292 AND value is not NULL');
293 CRM_Core_DAO::executeQuery('DELETE FROM civicrm_setting WHERE name = "activity_tab_filter"');
294
295 $date = CRM_Utils_Time::getTime('Y-m-d H:i:s');
296 CRM_Core_DAO::executeQuery('ALTER TABLE civicrm_setting ADD UNIQUE INDEX index_domain_contact_name (domain_id, contact_id, name)');
297 CRM_Core_DAO::executeQuery("INSERT INTO civicrm_setting (name, contact_id, domain_id, value, is_domain, created_id, created_date)
298 SELECT name, contact_id, domain_id, value, 0, contact_id,'$date'
299 FROM civicrm_activity_setting
300 WHERE name = 'activity_tab_filter'
301 AND value is not NULL"
302 );
303 CRM_Core_DAO::executeQuery('DROP TABLE civicrm_activity_setting');
304
305 $domainDao = CRM_Core_DAO::executeQuery('SELECT id, config_backend FROM civicrm_domain');
306 while ($domainDao->fetch()) {
307 $settings = CRM_Upgrade_Incremental_php_FourSeven::convertBackendToSettings($domainDao->id, $domainDao->config_backend);
308 CRM_Core_Error::debug_var('convertBackendToSettings', array(
309 'domainId' => $domainDao->id,
310 'backend' => $domainDao->config_backend,
311 'settings' => $settings,
312 ));
313
314 foreach ($settings as $name => $value) {
315 $rowParams = array(
316 1 => array($domainDao->id, 'Positive'),
317 2 => array($name, 'String'),
318 3 => array(serialize($value), 'String'),
319 );
320 $settingId = CRM_Core_DAO::singleValueQuery(
321 'SELECT id FROM civicrm_setting WHERE domain_id = %1 AND name = %2',
322 $rowParams);
323 if (!$settingId) {
324 CRM_Core_DAO::executeQuery(
325 'INSERT INTO civicrm_setting (domain_id, name, value, is_domain) VALUES (%1,%2,%3,1)',
326 $rowParams);
327 }
328 }
329 }
330
331 CRM_Core_DAO::executeQuery('ALTER TABLE civicrm_domain DROP COLUMN config_backend');
332
333 return TRUE;
334 }
335
336 /**
337 * Take a config_backend blob and produce an equivalent list of settings.
338 *
339 * @param int $domainId
340 * Domain ID.
341 * @param string $config_backend
342 * Serialized blob.
343 * @return array
344 */
345 public static function convertBackendToSettings($domainId, $config_backend) {
346 if (!$config_backend) {
347 return array();
348 }
349
350 $backend = unserialize($config_backend);
351 if (!$backend) {
352 return array();
353 }
354
355 $mappings = \CRM_Core_Config_MagicMerge::getPropertyMap();
356 $settings = array();
357 foreach ($backend as $propertyName => $propertyValue) {
358 if (isset($mappings[$propertyName][0]) && preg_match('/^setting/', $mappings[$propertyName][0])) {
359 // $mapping format: $propertyName => Array(0 => $type, 1 => $setting|NULL).
360 $settingName = isset($mappings[$propertyName][1]) ? $mappings[$propertyName][1] : $propertyName;
361 $settings[$settingName] = $propertyValue;
362 }
363 }
364
365 return $settings;
366 }
367
368 /**
369 * Add Getting Started dashlet to dashboard
370 *
371 * @param \CRM_Queue_TaskContext $ctx
372 *
373 * @return bool
374 */
375 public function addGettingStartedDashlet(CRM_Queue_TaskContext $ctx) {
376 $sql = "SELECT count(*) FROM civicrm_dashboard WHERE name='getting-started'";
377 $res = CRM_Core_DAO::singleValueQuery($sql);
378 $domainId = CRM_Core_Config::domainID();
379 if ($res <= 0) {
380 $sql = "INSERT INTO `civicrm_dashboard`
381 ( `domain_id`, `name`, `label`, `url`, `permission`, `permission_operator`, `column_no`, `is_minimized`, `is_active`, `weight`, `fullscreen_url`, `is_fullscreen`, `is_reserved`) VALUES ( {$domainId}, 'getting-started', 'Getting Started', 'civicrm/dashlet/getting-started?reset=1&snippet=5', 'access CiviCRM', NULL, 0, 0, 1, 0, 'civicrm/dashlet/getting-started?reset=1&snippet=5&context=dashletFullscreen', 1, 1)";
382 CRM_Core_DAO::executeQuery($sql);
383 // Add default position for Getting Started Dashlet ( left column)
384 $sql = "INSERT INTO `civicrm_dashboard_contact` (dashboard_id, contact_id, column_no, is_active)
385 SELECT (SELECT MAX(id) FROM `civicrm_dashboard`), contact_id, 0, IF (SUM(is_active) > 0, 1, 0)
386 FROM `civicrm_dashboard_contact` JOIN `civicrm_contact` WHERE civicrm_dashboard_contact.contact_id = civicrm_contact.id GROUP BY contact_id";
387 CRM_Core_DAO::executeQuery($sql);
388 }
389 return TRUE;
390 }
391
392 /**
393 * Migrate on-behalf information to uf_join.module_data as on-behalf columns will be dropped
394 * on DB upgrade
395 *
396 * @param CRM_Queue_TaskContext $ctx
397 *
398 * @return bool
399 * TRUE for success
400 */
401 public static function migrateOnBehalfOfInfo(CRM_Queue_TaskContext $ctx) {
402 $domain = new CRM_Core_DAO_Domain();
403 $domain->find(TRUE);
404
405 // fetch onBehalf entry in UFJoin table
406 $ufGroupDAO = new CRM_Core_DAO_UFJoin();
407 $ufGroupDAO->module = 'OnBehalf';
408 $ufGroupDAO->find(TRUE);
409
410 $forOrgColums = array();
411 if ($domain->locales) {
412 $locales = explode(CRM_Core_DAO::VALUE_SEPARATOR, $domain->locales);
413 foreach ($locales as $locale) {
414 $forOrgColums[] = "for_organization_{$locale}";
415 }
416 }
417 else {
418 $forOrgColums[] = "for_organization";
419 }
420
421 $query = "
422 SELECT " . implode(", ", $forOrgColums) . ", uj.id as join_id, uj.uf_group_id as uf_group_id
423 FROM civicrm_contribution_page cp
424 INNER JOIN civicrm_uf_join uj ON uj.entity_id = cp.id AND uj.module = 'OnBehalf'";
425 $dao = CRM_Core_DAO::executeQuery($query, array(), TRUE, NULL, FALSE, FALSE);
426
427 if ($dao->N) {
428 while ($dao->fetch()) {
429 $onBehalfParams['on_behalf'] = array('is_for_organization' => $dao->is_for_organization);
430 if ($domain->locales) {
431 foreach ($locales as $locale) {
432 $for_organization = "for_organization_{$locale}";
433 $onBehalfParams['on_behalf'] += array(
434 $locale => array(
435 'for_organization' => $dao->$for_organization,
436 ),
437 );
438 }
439 }
440 else {
441 $onBehalfParams['on_behalf'] += array(
442 'default' => array(
443 'for_organization' => $dao->for_organization,
444 ),
445 );
446 }
447 $ufJoinParam = array(
448 'id' => $dao->join_id,
449 'module' => 'on_behalf',
450 'uf_group_id' => $dao->uf_group_id,
451 'module_data' => json_encode($onBehalfParams),
452 );
453 CRM_Core_BAO_UFJoin::create($ufJoinParam);
454 }
455 }
456
457 return TRUE;
458 }
459
460 /**
461 * CRM-11782 - Get rid of VALUE_SEPARATOR character in saved search form values
462 *
463 * @param \CRM_Queue_TaskContext $ctx
464 *
465 * @return bool
466 */
467 public function fixContactTypeInSmartGroups(CRM_Queue_TaskContext $ctx) {
468 $sep = CRM_Core_DAO::VALUE_SEPARATOR;
469 $dao = CRM_Core_DAO::executeQuery("SELECT id, form_values FROM civicrm_saved_search WHERE form_values LIKE '%$sep%'");
470 while ($dao->fetch()) {
471 $formValues = unserialize($dao->form_values);
472 if (isset($formValues['contact_type']) && is_array($formValues['contact_type'])) {
473 $newVals = array();
474 foreach ($formValues['contact_type'] as $key => $val) {
475 $newVals[str_replace($sep, '__', $key)] = is_string($val) ? str_replace($sep, '__', $val) : $val;
476 }
477 $formValues['contact_type'] = $newVals;
478 }
479 CRM_Core_DAO::executeQuery("UPDATE civicrm_saved_search SET form_values = %1 WHERE id = {$dao->id}", array(1 => array(serialize($formValues), 'String')));
480 }
481
482 return TRUE;
483 }
484
485 /**
486 * CRM-17637 - Ths file location has been moved; delete the old one
487 *
488 * @param \CRM_Queue_TaskContext $ctx
489 *
490 * @return bool
491 */
492 public function deleteVersionCheckCacheFile(CRM_Queue_TaskContext $ctx) {
493 $config = CRM_Core_Config::singleton();
494 $cacheFile = $config->uploadDir . 'version-info-cache.json';
495 if (file_exists($cacheFile)) {
496 unlink($cacheFile);
497 }
498 return TRUE;
499 }
500
501 /**
502 * CRM-17669 and CRM-17686, make scheduled jobs more flexible, disable the 4.6 extension if installed
503 *
504 * @param \CRM_Queue_TaskContext $ctx
505 *
506 * @return bool
507 */
508 public function disableFlexibleJobsExtension(CRM_Queue_TaskContext $ctx) {
509 try {
510 civicrm_api3('Extension', 'disable', array('key' => 'com.klangsoft.flexiblejobs'));
511 }
512 catch (CiviCRM_API3_Exception $e) {
513 // just ignore if the extension isn't installed
514 }
515
516 return TRUE;
517 }
518
519 /**
520 * CRM-17752 add index to civicrm_financial_trxn.trxn_id (deliberately non-unique).
521 *
522 * @param \CRM_Queue_TaskContext $ctx
523 *
524 * @return bool
525 */
526 public function addIndexFinancialTrxnTrxnID(CRM_Queue_TaskContext $ctx) {
527 $tables = array('civicrm_financial_trxn' => array('trxn_id'));
528 CRM_Core_BAO_SchemaHandler::createIndexes($tables);
529 return TRUE;
530 }
531
532 /**
533 * CRM-17882 Add index to civicrm_contribution.credit_note_id.
534 *
535 * @param \CRM_Queue_TaskContext $ctx
536 *
537 * @return bool
538 */
539 public function addIndexContributionCreditNoteID(CRM_Queue_TaskContext $ctx) {
540 $tables = array('civicrm_contribution' => array('creditnote_id'));
541 CRM_Core_BAO_SchemaHandler::createIndexes($tables);
542 return TRUE;
543 }
544
545 /**
546 * CRM-17775 Add correct index for table civicrm_financial_item.
547 *
548 * Note that the entity ID should always precede the entity_table as
549 * it is more unique. This is better for performance and does not cause fallback
550 * to no index if table it omitted.
551 *
552 * @return bool
553 */
554 public function addCombinedIndexFinancialItemEntityIDEntityType() {
555 CRM_Core_BAO_SchemaHandler::dropIndexIfExists('civicrm_financial_item', 'UI_id');
556 CRM_Core_BAO_SchemaHandler::dropIndexIfExists('civicrm_financial_item', 'IX_Entity');
557 CRM_Core_BAO_SchemaHandler::createIndexes(array(
558 'civicrm_financial_item' => array(array('entity_id', 'entity_table')),
559 ));
560 return TRUE;
561 }
562
563 /**
564 * CRM-17951 Add accounts option values for refund and chargeback.
565 *
566 * Add Chargeback contribution status and Chargeback and Contra account relationships,
567 * checking first if one exists.
568 */
569 public function addRefundAndChargeBackAccountsIfNotExist() {
570 // First we enable and edit the record for Credit contra - this exists but is disabled for most sites.
571 // Using the ensure function (below) will not enabled a disabled option (by design).
572 CRM_Core_DAO::executeQuery("UPDATE civicrm_option_value v
573 INNER JOIN civicrm_option_group g on v.option_group_id=g.id and g.name='account_relationship'
574 SET v.is_active=1, v.label='Credit/Contra Revenue Account is', v.name='Credit/Contra Revenue Account is', v.description='Credit/Contra Revenue Account is'
575 WHERE v.name = 'Credit/Contra Account is';");
576
577 CRM_Core_BAO_OptionValue::ensureOptionValueExists(array(
578 'option_group_id' => 'account_relationship',
579 'name' => 'Chargeback Account is',
580 'label' => ts('Chargeback Account is'),
581 'is_active' => TRUE,
582 'component_id' => 'CiviContribute',
583 ));
584
585 CRM_Core_BAO_OptionValue::ensureOptionValueExists(array(
586 'option_group_id' => 'contribution_status',
587 'name' => 'Chargeback',
588 'label' => ts('Chargeback'),
589 'is_active' => TRUE,
590 'component_id' => 'CiviContribute',
591 ));
592 return TRUE;
593 }
594
595 /**
596 * CRM-17999 Add index to civicrm_contribution.source.
597 *
598 * @param \CRM_Queue_TaskContext $ctx
599 *
600 * @return bool
601 */
602 public function addIndexContributionSource(CRM_Queue_TaskContext $ctx) {
603 CRM_Core_BAO_SchemaHandler::createIndexes(array('civicrm_contribution' => array('source')));
604 return TRUE;
605 }
606
607 /**
608 * CRM-18124 Add index to civicrm_contribution.total_amount.
609 *
610 * Note that I made this a combined index with receive_date because the issue included
611 * both criteria and they seemed likely to be used in conjunction to me in other cases.
612 *
613 * @param \CRM_Queue_TaskContext $ctx
614 *
615 * @return bool
616 */
617 public function addIndexContributionAmount(CRM_Queue_TaskContext $ctx) {
618 CRM_Core_BAO_SchemaHandler::createIndexes(array(
619 'civicrm_contribution' => array(array('total_amount', 'receive_date')),
620 ));
621 return TRUE;
622 }
623
624 /**
625 * CRM-18124 Add index to civicrm_contribution.total_amount.
626 *
627 * Note that I made this a combined index with receive_date because the issue included
628 * both criteria and they seemed likely to be used in conjunction to me in other cases.
629 *
630 * @param \CRM_Queue_TaskContext $ctx
631 *
632 * @return bool
633 */
634 public function addDeletedByMergeActivityType(CRM_Queue_TaskContext $ctx) {
635 CRM_Core_BAO_OptionValue::ensureOptionValueExists(array(
636 'option_group_id' => 'activity_type',
637 'name' => 'Contact Deleted by Merge',
638 'label' => ts('Contact Deleted by Merge'),
639 'description' => ts('Contact was merged into another contact'),
640 'is_active' => TRUE,
641 'filter' => 1,
642 ));
643 return TRUE;
644 }
645
646 /**
647 * CRM-12252 Add Help Pre and Help Post Fields for Price Field Value Table.
648 *
649 * @param \CRM_Queue_TaskContext $ctx
650 *
651 * @return bool
652 */
653 public function addHelpPreAndHelpPostFieldsPriceFieldValue(CRM_Queue_TaskContext $ctx) {
654 $domain = new CRM_Core_DAO_Domain();
655 $domain->find(TRUE);
656 if ($domain->locales) {
657 $locales = explode(CRM_Core_DAO::VALUE_SEPARATOR, $domain->locales);
658 foreach ($locales as $locale) {
659 if (!CRM_Core_BAO_SchemaHandler::checkIfFieldExists("civicrm_price_field_value", "help_pre_{$locale}")) {
660 CRM_Core_DAO::executeQuery("ALTER TABLE `civicrm_price_field_value`
661 ADD COLUMN `help_pre_{$locale}` text COLLATE utf8_unicode_ci COMMENT 'Price field option pre help text.'", array(), TRUE, NULL, FALSE, FALSE);
662 }
663 if (!CRM_Core_BAO_SchemaHandler::checkIfFieldExists("civicrm_price_field_value", "help_post_{$locale}")) {
664 CRM_Core_DAO::executeQuery("ALTER TABLE `civicrm_price_field_value`
665 ADD COLUMN `help_post_{$locale}` text COLLATE utf8_unicode_ci COMMENT 'Price field option post help text.'", array(), TRUE, NULL, FALSE, FALSE);
666 }
667 }
668 CRM_Core_I18n_Schema::rebuildMultilingualSchema($locales, NULL);
669 }
670 else {
671 if (!CRM_Core_BAO_SchemaHandler::checkIfFieldExists('civicrm_price_field_value', 'help_pre')) {
672 CRM_Core_DAO::executeQuery("ALTER TABLE `civicrm_price_field_value`
673 ADD COLUMN `help_pre` text COLLATE utf8_unicode_ci COMMENT 'Price field option pre help text.'");
674 }
675 if (!CRM_Core_BAO_SchemaHandler::checkIfFieldExists('civicrm_price_field_value', 'help_post')) {
676 CRM_Core_DAO::executeQuery("ALTER TABLE `civicrm_price_field_value`
677 ADD COLUMN `help_post` text COLLATE utf8_unicode_ci COMMENT 'Price field option post help text.'");
678 }
679 }
680 return TRUE;
681 }
682
683 /**
684 * CRM-18345 Don't delete mailing data on email/phone deletion
685 * Implemented here in CRM-18526
686 *
687 * @param \CRM_Queue_TaskContext $ctx
688 *
689 * @return bool
690 */
691 public function upgradeMailingFKs(CRM_Queue_TaskContext $ctx) {
692
693 // Safely drop the foreign keys
694 CRM_Core_BAO_SchemaHandler::safeRemoveFK('civicrm_mailing_event_queue', 'FK_civicrm_mailing_event_queue_email_id');
695 CRM_Core_BAO_SchemaHandler::safeRemoveFK('civicrm_mailing_event_queue', 'FK_civicrm_mailing_event_queue_phone_id');
696 CRM_Core_BAO_SchemaHandler::safeRemoveFK('civicrm_mailing_recipients', 'FK_civicrm_mailing_recipients_email_id');
697 CRM_Core_BAO_SchemaHandler::safeRemoveFK('civicrm_mailing_recipients', 'FK_civicrm_mailing_recipients_phone_id');
698
699 // Set up the new foreign keys
700 CRM_Core_DAO::executeQuery("SET FOREIGN_KEY_CHECKS = 0;");
701
702 CRM_Core_DAO::executeQuery("
703 ALTER TABLE `civicrm_mailing_event_queue`
704 ADD CONSTRAINT `FK_civicrm_mailing_event_queue_email_id`
705 FOREIGN KEY (`email_id`)
706 REFERENCES `civicrm_email`(`id`)
707 ON DELETE SET NULL
708 ON UPDATE RESTRICT;
709 ");
710
711 CRM_Core_DAO::executeQuery("
712 ALTER TABLE `civicrm_mailing_event_queue`
713 ADD CONSTRAINT `FK_civicrm_mailing_event_queue_phone_id`
714 FOREIGN KEY (`phone_id`)
715 REFERENCES `civicrm_phone`(`id`)
716 ON DELETE SET NULL
717 ON UPDATE RESTRICT;
718 ");
719
720 CRM_Core_DAO::executeQuery("
721 ALTER TABLE `civicrm_mailing_recipients`
722 ADD CONSTRAINT `FK_civicrm_mailing_recipients_email_id`
723 FOREIGN KEY (`email_id`)
724 REFERENCES `civicrm_email`(`id`)
725 ON DELETE SET NULL
726 ON UPDATE RESTRICT;
727 ");
728
729 CRM_Core_DAO::executeQuery("
730 ALTER TABLE `civicrm_mailing_recipients`
731 ADD CONSTRAINT `FK_civicrm_mailing_recipients_phone_id`
732 FOREIGN KEY (`phone_id`)
733 REFERENCES `civicrm_phone`(`id`)
734 ON DELETE SET NULL
735 ON UPDATE RESTRICT;
736 ");
737
738 CRM_Core_DAO::executeQuery("SET FOREIGN_KEY_CHECKS = 1;");
739
740 return TRUE;
741 }
742
743 /**
744 * CRM-17663 - Dashboard schema changes
745 *
746 * @param \CRM_Queue_TaskContext $ctx
747 *
748 * @return bool
749 */
750 public function dashboardSchemaUpdate(CRM_Queue_TaskContext $ctx) {
751 if (!CRM_Core_BAO_SchemaHandler::checkIfIndexExists('civicrm_dashboard_contact', 'index_dashboard_id_contact_id')) {
752 // Delete any stray duplicate rows and add unique index to prevent new dupes and enable INSERT/UPDATE combo query
753 CRM_Core_DAO::executeQuery('DELETE c1 FROM civicrm_dashboard_contact c1, civicrm_dashboard_contact c2 WHERE c1.contact_id = c2.contact_id AND c1.dashboard_id = c2.dashboard_id AND c1.id > c2.id');
754 CRM_Core_DAO::executeQuery('ALTER TABLE civicrm_dashboard_contact ADD UNIQUE INDEX index_dashboard_id_contact_id (dashboard_id, contact_id);');
755 }
756 CRM_Core_BAO_SchemaHandler::dropColumn('civicrm_dashboard_contact', 'content');
757 CRM_Core_BAO_SchemaHandler::dropColumn('civicrm_dashboard_contact', 'is_minimized');
758 CRM_Core_BAO_SchemaHandler::dropColumn('civicrm_dashboard_contact', 'is_fullscreen');
759 CRM_Core_BAO_SchemaHandler::dropColumn('civicrm_dashboard_contact', 'created_date');
760 CRM_Core_BAO_SchemaHandler::dropColumn('civicrm_dashboard', 'is_fullscreen');
761 CRM_Core_BAO_SchemaHandler::dropColumn('civicrm_dashboard', 'is_minimized');
762 CRM_Core_BAO_SchemaHandler::dropColumn('civicrm_dashboard', 'column_no');
763 CRM_Core_BAO_SchemaHandler::dropColumn('civicrm_dashboard', 'weight');
764
765 CRM_Core_DAO::executeQuery('UPDATE civicrm_dashboard SET url = REPLACE(url, "&snippet=5", ""), fullscreen_url = REPLACE(fullscreen_url, "&snippet=5", "")');
766
767 if (!CRM_Core_BAO_SchemaHandler::checkIfFieldExists('civicrm_dashboard', 'cache_minutes')) {
768 CRM_Core_DAO::executeQuery('ALTER TABLE civicrm_dashboard ADD COLUMN cache_minutes int unsigned NOT NULL DEFAULT 60 COMMENT "Number of minutes to cache dashlet content in browser localStorage."');
769 }
770
771 CRM_Core_DAO::executeQuery('UPDATE civicrm_dashboard SET cache_minutes = 1440 WHERE name = "blog"');
772 CRM_Core_DAO::executeQuery('UPDATE civicrm_dashboard SET cache_minutes = 7200 WHERE name IN ("activity","getting-started")');
773 return TRUE;
774 }
775
776 /**
777 * CRM-19100 - Alter Index and Type for Image URL
778 * @return bool
779 */
780 public static function alterIndexAndTypeForImageURL() {
781 $length = array();
782 CRM_Core_BAO_SchemaHandler::dropIndexIfExists('civicrm_contact', 'index_image_url');
783 CRM_Core_DAO::executeQuery("ALTER TABLE `civicrm_contact` CHANGE `image_URL` `image_URL` TEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT 'optional URL for preferred image (photo, logo, etc.) to display for this contact.'");
784
785 $length['civicrm_contact']['image_URL'] = 128;
786 CRM_Core_BAO_SchemaHandler::createIndexes(array('civicrm_contact' => array('image_URL')), 'index', $length);
787
788 return TRUE;
789 }
790
791 }