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