Merge pull request #11157 from jitendrapurohit/4.7.27
[civicrm-core.git] / CRM / Upgrade / Incremental / php / FourSeven.php
CommitLineData
6cc25669
CW
1<?php
2/*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.7 |
5 +--------------------------------------------------------------------+
0f03f337 6 | Copyright CiviCRM LLC (c) 2004-2017 |
6cc25669
CW
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/**
bf6a5362 28 * Upgrade logic for 4.7
6cc25669 29 */
bf6a5362 30class CRM_Upgrade_Incremental_php_FourSeven extends CRM_Upgrade_Incremental_Base {
6cc25669 31
f431d51f
J
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 *
3bdf1f3a 38 * @param string $preUpgradeMessage
f431d51f
J
39 * @param string $rev
40 * a version number, e.g. '4.4.alpha1', '4.4.beta3', '4.4.0'.
41 * @param null $currentVer
f431d51f
J
42 */
43 public function setPreUpgradeMessage(&$preUpgradeMessage, $rev, $currentVer = NULL) {
44 if ($rev == '4.7.alpha1') {
f431d51f
J
45 // CRM-16478 Remove custom fatal error template path option
46 $config = CRM_Core_Config::singleton();
18b3bef6 47 if (!empty($config->fatalErrorTemplate) && $config->fatalErrorTemplate != 'CRM/common/fatal.tpl') {
f431d51f
J
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 }
f431d51f 50 }
a40fd1ac
CW
51 if ($rev == '4.7.alpha4') {
52 // CRM-17004 Warn of Moneris removal
87a33a95
CW
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')) {
a40fd1ac
CW
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 }
b9446a4c 62 if ($rev == '4.7.13') {
4b9e9cda
SL
63 $preUpgradeMessage .= '<p>' . ts('A new permission has been added called %1 This Permission is now used to control access to the Manage Tags screen', array(1 => 'manage tags')) . '</p>';
64 }
17511f38
TO
65 if ($rev == '4.7.22') {
66 // Based on support inquiries for 4.7.21, show message during 4.7.22.
67 // For affected users, this issue prevents loading the regular status screen.
68 if (!$this->checkImageUploadDir()) {
69 $preUpgradeMessage .= '<p>' . ts('There appears to be an inconsistency in the configuration of "Image Upload URL" and "Image Upload Directory".') . '</p>'
70 . '<p>'
71 . ts('Further advice will be displayed at the end of the upgrade.')
72 . '</p>';
73 }
74 }
9f8c485f 75 if ($rev == '4.7.27') {
5ad18cc2 76 $params = array(
77 1 => 'Close accounting batches created by user',
78 2 => 'Close all accounting batches',
79 3 => 'Reopen accounting batches created by user',
80 4 => 'Reopen all accounting batches',
81 5 => 'https://wiki.civicrm.org/confluence/display/CRMDOC/Default+Permissions+and+Roles',
82 );
83 $preUpgradeMessage .= '<p>' . ts('A new set of batch permissions has been added called "%1", "%2", "%3" and "%4". These permissions are now used to control access to the Accounting Batches tasks. If your users need to be able to Reopen or Close batches you may need to give them additional permissions. <a href=%5>Read more</a>', $params) . '</p>';
84 }
f431d51f
J
85 }
86
6cc25669
CW
87 /**
88 * Compute any messages which should be displayed after upgrade.
89 *
90 * @param string $postUpgradeMessage
91 * alterable.
92 * @param string $rev
93 * an intermediate version; note that setPostUpgradeMessage is called repeatedly with different $revs.
6cc25669
CW
94 */
95 public function setPostUpgradeMessage(&$postUpgradeMessage, $rev) {
6dbe2c23
CW
96 if ($rev == '4.7.alpha1') {
97 $config = CRM_Core_Config::singleton();
bf6a5362 98 // FIXME: Performing an upgrade step during postUpgrade message phase is probably bad
6dbe2c23
CW
99 $editor_id = self::updateWysiwyg();
100 $msg = NULL;
101 $ext_href = 'href="' . CRM_Utils_System::url('civicrm/admin/extensions', 'reset=1') . '"';
102 $dsp_href = 'href="' . CRM_Utils_System::url('civicrm/admin/setting/preferences/display', 'reset=1') . '"';
103 $blog_href = 'href="https://civicrm.org/blogs/colemanw/big-changes-wysiwyg-editing-47"';
104 switch ($editor_id) {
105 // TinyMCE
106 case 1:
107 $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));
108 break;
109
110 // Drupal/Joomla editor
111 case 3:
112 case 4:
113 $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));
114 break;
115 }
116 if ($msg) {
117 $postUpgradeMessage .= '<p>' . $msg . '</p>';
118 }
119 $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>';
dd55005c 120
121 $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).');
f431d51f
J
122
123 $postUpgradeMessage .= '<p>' . ts('The custom fatal error template setting has been removed.') . '</p>';
6dbe2c23 124 }
a742ee50
TO
125 //if ($rev == '4.7.11') {
126 // $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'");
127 //}
11769bd1 128 if ($rev == '4.7.11') {
9867e465 129 $postUpgradeMessage .= '<br /><br />' . ts("By default, CiviCRM now disables the ability to import directly from SQL. To use this feature, you must explicitly grant permission 'import SQL datasource'.");
11769bd1 130 }
c7c54ade
CW
131 if ($rev == '4.7.14') {
132 $ck_href = 'href="' . CRM_Utils_System::url('civicrm/admin/ckeditor') . '"';
133 $postUpgradeMessage .= '<p>' . ts('CiviMail no longer forces CKEditor to add html/head/body tags to email content because some sites place these in the message header/footer. This was added in 4.7.5 and is now disabled by default.')
3444e690 134 . '<br />' . ts('You can re-enable it by visiting the <a %1>CKEditor Config</a> screen and setting "fullPage = true" under the Advanced Options of the CiviMail preset.', array(1 => $ck_href))
c7c54ade
CW
135 . '</p>';
136 }
c4aa623c 137 if ($rev == '4.7.19') {
7dffc2a7 138 $postUpgradeMessage .= '<br /><br />' . ts('Default version of the following System Workflow Message Templates have been modified: <ul><li>Additional Payment Receipt or Refund Notification</li><li>Contribution Invoice</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).');
eca6c81c
SL
139 $check = CRM_Core_DAO::singleValueQuery("SELECT count(id) FROM civicrm_domain");
140 $smsCheck = CRM_Core_DAO::singleValueQuery("SELECT count(id) FROM civicrm_sms_provider");
141 if ($check > 1 && (bool) $smsCheck) {
142 $postUpgradeMessage .= '<p>civicrm_sms_provider ' . ts('has now had a domain id column added. As there is more than 1 domains in this install you need to manually set the domain id for the providers in this install') . '</p>';
143 }
c4aa623c 144 }
17511f38
TO
145 if ($rev == '4.7.22') {
146 // Based on support inquiries for 4.7.21, show message during 4.7.22.
147 // For affected users, this issue prevents loading the regular status screen.
148 if (!$this->checkImageUploadDir()) {
149 $config = CRM_Core_Config::singleton();
150 $postUpgradeMessage .=
151 '<h3>' . ts('Warning') . '</h3>'
152 . '<p>' . ts('There appears to be an inconsistency in the configuration of "Image Upload URL" and "Image Upload Directory".') . '</p>'
153 . sprintf("<ul><li><b>imageUploadDir</b>: <code>%s</code></li><li><b>imageUploadURL</b>: <code>%s</code></li></ul>", htmlentities($config->imageUploadDir), htmlentities($config->imageUploadURL))
154 . '<p>'
155 . ts('You may need to check that: <ul><li>(a) the path and URL match,</li><li> (b) the httpd/htaccess policy allows requests for files inside this folder,</li><li>and (c) the web domain matches the normal web domain.</ul>')
156 . '</p>'
157 . '<p><em>'
158 . ts('(Note: Although files should be readable, it is best if they are not listable or browseable.)')
159 . '</em></p>'
160 . '<p>'
161 . ts('If this remains unresolved, then some important screens may fail to load.')
162 . '</p>';
163 }
164 }
a058f8a1 165 if ($rev == '4.7.23') {
9cad3ff4
CW
166 $postUpgradeMessage .= '<br /><br />' . ts('Default version of the following System Workflow Message Templates have been modified: <ul><li>Contribution Invoice</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).');
167 }
6cc25669
CW
168 }
169
6cc25669
CW
170 /**
171 * Upgrade function.
172 *
173 * @param string $rev
174 */
175 public function upgrade_4_7_alpha1($rev) {
8c748d50 176 $this->addTask('Drop action scheudle mapping foreign key', 'dropActionScheudleMappingForeignKey');
b604d7ec 177 $this->addTask('Migrate \'on behalf of\' information to module_data', 'migrateOnBehalfOfInfo');
bf6a5362 178 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
f806379b 179 $this->addTask(ts('Migrate Settings to %1', array(1 => $rev)), 'migrateSettings', $rev);
b604d7ec 180 $this->addTask('Add Getting Started dashlet', 'addGettingStartedDashlet', $rev);
a40fd1ac
CW
181 }
182
183 /**
184 * Upgrade function.
185 *
186 * @param string $rev
187 */
188 public function upgrade_4_7_alpha4($rev) {
189 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
058b8a5e 190 $this->addTask(ts('Remove %1', array(1 => 'Moneris')), 'removePaymentProcessorType', 'Moneris');
b2222b9f 191 $this->addTask('Update Smart Groups', 'fixContactTypeInSmartGroups');
6cc25669
CW
192 }
193
0094ac08
CW
194 /**
195 * Upgrade function.
196 *
197 * @param string $rev
198 */
199 public function upgrade_4_7_beta2($rev) {
200 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
201 $this->addTask('Delete unused file', 'deleteVersionCheckCacheFile');
202 }
203
fb1f3850
DRJ
204 /**
205 * Upgrade function.
206 *
207 * @param string $rev
208 */
902e557f 209 public function upgrade_4_7_beta6($rev) {
13599400 210 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
fb1f3850 211 $this->addTask('Disable flexible jobs extension', 'disableFlexibleJobsExtension');
20d5377e 212 $this->addTask('Add Index to financial_trxn trxn_id field', 'addIndexFinancialTrxnTrxnID');
fb1f3850
DRJ
213 }
214
8ca47f5c 215 /**
216 * Upgrade function.
217 *
218 * @param string $rev
219 */
220 public function upgrade_4_7_1($rev) {
2af0b023 221 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
8ca47f5c 222 $this->addTask('Add Index to civicrm_contribution creditnote_id field', 'addIndexContributionCreditNoteID');
223 }
224
2179c899 225 /**
226 * Upgrade function.
227 *
228 * @param string $rev
229 */
230 public function upgrade_4_7_2($rev) {
2af0b023 231 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
2179c899 232 $this->addTask('Fix Index on civicrm_financial_item combined entity_id + entity_table', 'addCombinedIndexFinancialItemEntityIDEntityType');
1f395432 233 $this->addTask('enable financial account relationships for chargeback & refund', 'addRefundAndChargeBackAccountsIfNotExist');
3fe26f4c 234 $this->addTask('Add Index to civicrm_contribution.source', 'addIndexContributionSource');
2179c899 235 }
236
fd28b6a0 237 /**
238 * Upgrade function.
239 *
240 * @param string $rev
241 */
242 public function upgrade_4_7_3($rev) {
2af0b023 243 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
fd28b6a0 244 $this->addTask('Add Index to civicrm_contribution.total_amount', 'addIndexContributionAmount');
245 }
246
6eb752fa 247 /**
248 * Upgrade function.
249 *
250 * @param string $rev
251 */
252 public function upgrade_4_7_4($rev) {
2af0b023 253 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
6eb752fa 254 $this->addTask('Add Contact Deleted by Merge Activity Type', 'addDeletedByMergeActivityType');
255 }
256
2cbdd085
J
257 /**
258 * Upgrade function.
259 *
260 * @param string $rev
261 */
6a2d3987 262 public function upgrade_4_7_7($rev) {
2cbdd085 263 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
6a2d3987
J
264 // https://issues.civicrm.org/jira/browse/CRM-18006
265 if (CRM_Core_DAO::checkTableExists('civicrm_install_canary')) {
266 CRM_Core_DAO::executeQuery('ALTER TABLE civicrm_install_canary ENGINE=InnoDB');
267 }
2cbdd085
J
268 }
269
2af0b023
CW
270 /**
271 * Upgrade function.
272 *
273 * @param string $rev
274 */
6a2d3987 275 public function upgrade_4_7_8($rev) {
2af0b023 276 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
6a2d3987 277 $this->addTask('Upgrade mailing foreign key constraints', 'upgradeMailingFKs');
065ffec9
TO
278 }
279
da1ecd73
SL
280 /**
281 * Upgrade function.
282 *
283 * @param string $rev
284 */
e8a4535e 285 public function upgrade_4_7_10($rev) {
da1ecd73 286 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
b5095b43
CW
287 $this->addTask('Upgrade Add Help Pre and Post Fields to price value table', 'addHelpPreAndHelpPostFieldsPriceFieldValue');
288 $this->addTask('Alter index and type for image URL', 'alterIndexAndTypeForImageURL');
da1ecd73
SL
289 }
290
00c27b41
CW
291 /**
292 * Upgrade function.
293 *
294 * @param string $rev
295 */
296 public function upgrade_4_7_11($rev) {
297 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
298 $this->addTask('Dashboard schema updates', 'dashboardSchemaUpdate');
b5095b43 299 $this->addTask('Fill in setting "remote_profile_submissions"', 'migrateRemoteSubmissionsSetting');
00c27b41
CW
300 }
301
7c61320c
SL
302 /**
303 * Upgrade function.
304 *
305 * @param string $rev
306 */
307 public function upgrade_4_7_12($rev) {
308 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
b5095b43 309 $this->addTask('Add Data Type column to civicrm_option_group', 'addDataTypeColumnToOptionGroupTable');
7c61320c 310 }
cb5962bd
SL
311 /**
312 * Upgrade function.
313 *
314 * @param string $rev
315 */
316 public function upgrade_4_7_13($rev) {
317 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
6846f088
CW
318 $this->addTask('CRM-19372 - Add column to allow for payment processors to set what card types are accepted', 'addColumn',
319 'civicrm_payment_processor', 'accepted_credit_cards', "text DEFAULT NULL COMMENT 'array of accepted credit card types'");
cb5962bd
SL
320 }
321
7ad5ae6a
CW
322 /**
323 * Upgrade function.
324 *
325 * @param string $rev
326 */
327 public function upgrade_4_7_14($rev) {
328 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
329 $this->addTask('Add WYSIWYG Editor Presets', 'addWysiwygPresets');
330 }
7c61320c 331
b412f764
CW
332 /**
333 * Upgrade function.
334 *
335 * @param string $rev
336 */
337 public function upgrade_4_7_15($rev) {
6846f088
CW
338 $this->addTask('CRM-19626 - Add min_amount column to civicrm_price_set', 'addColumn',
339 'civicrm_price_set', 'min_amount', "INT(10) UNSIGNED DEFAULT '0' COMMENT 'Minimum Amount required for this set.'");
b412f764
CW
340 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
341 }
342
703875d8
TO
343 /**
344 * Upgrade function.
345 *
346 * @param string $rev
347 */
348 public function upgrade_4_7_16($rev) {
73c5338d
CW
349 $this->addTask('CRM-19723 - Add icon column to civicrm_option_value', 'addColumn',
350 'civicrm_option_value', 'icon', "varchar(255) COMMENT 'crm-i icon class' DEFAULT NULL");
351 $this->addTask('CRM-19769 - Add color column to civicrm_tag', 'addColumn',
352 'civicrm_tag', 'color', "varchar(255) COMMENT 'Hex color value e.g. #ffffff' DEFAULT NULL");
353 $this->addTask('CRM-19779 - Add color column to civicrm_option_value', 'addColumn',
354 'civicrm_option_value', 'color', "varchar(255) COMMENT 'Hex color value e.g. #ffffff' DEFAULT NULL");
703875d8 355 $this->addTask('Add new CiviMail fields', 'addMailingTemplateType');
cd063b10
CW
356 $this->addTask('CRM-19770 - Add is_star column to civicrm_activity', 'addColumn',
357 'civicrm_activity', 'is_star', "tinyint DEFAULT '0' COMMENT 'Activity marked as favorite.'");
73c5338d 358 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
703875d8
TO
359 }
360
36610486 361 /**
362 * Upgrade function.
363 *
364 * @param string $rev
365 */
366 public function upgrade_4_7_18($rev) {
367 $this->addTask('Update Kenyan Provinces', 'updateKenyanProvinces');
368 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
369 }
370
8712faa9
PN
371 /**
372 * Upgrade function.
373 *
374 * @param string $rev
375 */
376 public function upgrade_4_7_19($rev) {
040073c9
CW
377 if (CRM_Core_BAO_SchemaHandler::checkIfFieldExists('civicrm_financial_account', 'opening_balance')) {
378 $query = "SELECT id FROM civicrm_financial_account WHERE opening_balance <> 0 OR current_period_opening_balance <> 0";
379 $result = CRM_Core_DAO::executeQuery($query);
380 if (!$result->N) {
381 $this->addTask('Drop Column current_period_opening_balance From civicrm_financial_account table.', 'dropColumn', 'civicrm_financial_account', 'current_period_opening_balance');
382 $this->addTask('Drop Column opening_balance From civicrm_financial_account table.', 'dropColumn', 'civicrm_financial_account', 'opening_balance');
383 }
8712faa9 384 }
4eae8dda 385 $this->addTask('CRM-19961 - Add domain_id column to civicrm_sms_provider', 'addColumn',
61612722 386 'civicrm_sms_provider', 'domain_id', "int(10) unsigned COMMENT 'Which Domain is this sms provier for'");
4eae8dda 387 $this->addTask('CRM-19961 - Populate domain id table and perhaps add foreign key', 'populateSMSProviderDomainId');
8712faa9 388 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
ccfd6962 389 $this->addTask('CRM-16633 - Add "Change Case Subject" activity', 'addChangeCaseSubjectActivityType');
460931ca
JP
390 $this->addTask('Add is_public column to civicrm_custom_group', 'addColumn',
391 'civicrm_custom_group', 'is_public', "boolean DEFAULT '1' COMMENT 'Is this property public?'");
8712faa9
PN
392 }
393
6f0dad97
SL
394 /**
395 * Upgrade function.
396 *
397 * @param string $rev
398 */
399 public function upgrade_4_7_20($rev) {
400 $this->addtask('Fix Schema on civicrm_action_schedule', 'fixSchemaOnCiviCRMActionSchedule');
401 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
040073c9
CW
402 $this->addTask('Add activity_status column to civicrm_mail_settings', 'addColumn',
403 'civicrm_mail_settings', 'activity_status', "varchar (255) DEFAULT NULL COMMENT 'Name of status to use when creating email to activity.'");
6f0dad97
SL
404 }
405
9cad3ff4
CW
406 /**
407 * Upgrade function.
408 *
409 * @param string $rev
410 */
a058f8a1 411 public function upgrade_4_7_23($rev) {
9cad3ff4
CW
412 $this->addTask('CRM-20387 - Add invoice_number column to civicrm_contribution', 'addColumn',
413 'civicrm_contribution', 'invoice_number', "varchar(255) COMMENT 'Human readable invoice number' DEFAULT NULL");
414 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
415 }
416
e87b39f4
SL
417 /**
418 * Upgrade function.
419 *
420 * @param string $rev
421 */
422 public function upgrade_4_7_25($rev) {
07683c33 423 $this->addTask("CRM-20927 - Add column to 'civicrm_menu' for additional metadata", 'addColumn',
e87b39f4 424 'civicrm_menu', 'module_data', "text COMMENT 'All other menu metadata not stored in other fields'");
58e9d364 425 $this->addTask('CRM-21052 - Determine activity revision policy', 'pickActivityRevisionPolicy');
e87b39f4 426 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
41ace555
SL
427 $this->addTask('Add cancel button text column to civicrm_uf_group', 'addColumn',
428 'civicrm_uf_group', 'cancel_button_text', "varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'Custom Text to display on the cancel button when used in create or edit mode'", TRUE);
429 $this->addTask('Add Submit button text column to civicrm_uf_group', 'addColumn',
430 'civicrm_uf_group', 'submit_button_text', "varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'Custom Text to display on the submit button on profile edit/create screens'", TRUE);
f6cecca8
TO
431
432 $this->addTask('CRM-20958 - Add created_date to civicrm_activity', 'addColumn',
433 'civicrm_activity', 'created_date', "timestamp NULL DEFAULT NULL COMMENT 'When was the activity was created.'");
434 $this->addTask('CRM-20958 - Add modified_date to civicrm_activity', 'addColumn',
435 'civicrm_activity', 'modified_date', "timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'When was the activity (or closely related entity) was created or modified or deleted.'");
436 $this->addTask('CRM-20958 - Add created_date to civicrm_case', 'addColumn',
437 'civicrm_case', 'created_date', "timestamp NULL DEFAULT NULL COMMENT 'When was the case was created.'");
438 $this->addTask('CRM-20958 - Add modified_date to civicrm_case', 'addColumn',
439 'civicrm_case', 'modified_date', "timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'When was the case (or closely related entity) was created or modified or deleted.'");
38a9c653 440 $this->addTask('Rebuild Multilingual Schema', 'rebuildMultilingalSchema');
e87b39f4
SL
441 }
442
619d3303
SL
443 /**
444 * Upgrade function.
445 *
446 * @param string $rev
447 */
9f8c485f 448 public function upgrade_4_7_27($rev) {
619d3303 449 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
be2faa1d 450 $this->addTask('CRM-21234 Missing subdivisions of Tajikistan', 'tajikistanMissingSubdivisions');
e7a6eae8
SL
451 $this->addTask('CRM-20892 - Add modified_date to civicrm_mailing', 'addColumn',
452 'civicrm_mailing', 'modified_date', "timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'When the mailing (or closely related entity) was created or modified or deleted.'");
4926ede8 453 $this->addTask('CRM-21195 - Add icon field to civicrm_navigation', 'addColumn',
c88f9a4d 454 'civicrm_navigation', 'icon', "varchar(255) NULL DEFAULT NULL COMMENT 'CSS class name for an icon'");
a13c171d
CR
455 $this->addTask('CRM-12167 - Add visibility column to civicrm_price_field_value', 'addColumn',
456 'civicrm_price_field_value', 'visibility_id', 'int(10) unsigned DEFAULT 1 COMMENT "Implicit FK to civicrm_option_group with name = \'visibility\'"');
07c25637 457 $this->addTask('Remove broken Contribution_logging reports', 'removeContributionLoggingReports');
619d3303 458 }
e87b39f4 459
2af0b023 460 /*
2cbdbcef 461 * Important! All upgrade functions MUST add a 'runSql' task.
2af0b023
CW
462 * Uncomment and use the following template for a new upgrade version
463 * (change the x in the function name):
464 */
465
466 // /**
467 // * Upgrade function.
468 // *
469 // * @param string $rev
470 // */
471 // public function upgrade_4_7_x($rev) {
472 // $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
473 // // Additional tasks here...
b5095b43
CW
474 // // Note: do not use ts() in the addTask description because it adds unnecessary strings to transifex.
475 // // The above is an exception because 'Upgrade DB to %1: SQL' is generic & reusable.
2af0b023
CW
476 // }
477
6cc25669
CW
478 /**
479 * CRM-16354
480 *
6dbe2c23 481 * @return int
6cc25669 482 */
6dbe2c23 483 public static function updateWysiwyg() {
aaffa79f 484 $editorID = Civi::settings()->get('editor_id');
6dbe2c23
CW
485 // Previously a numeric value indicated one of 4 wysiwyg editors shipped in core, and no value indicated 'Textarea'
486 // Now the options are "Textarea", "CKEditor", and the rest have been dropped from core.
487 $newEditor = $editorID ? "CKEditor" : "Textarea";
08ef4ddd 488 Civi::settings()->set('editor_id', $newEditor);
6cc25669 489
6dbe2c23 490 return $editorID;
6cc25669
CW
491 }
492
f806379b
TO
493 /**
494 * Migrate any last remaining options from `civicrm_domain.config_backend` to `civicrm_setting`.
495 * Cleanup setting schema.
496 *
497 * @param CRM_Queue_TaskContext $ctx
498 * @return bool
499 */
5c9edd99 500 public static function migrateSettings(CRM_Queue_TaskContext $ctx) {
4cc9e637
TO
501 // Tip: If there are problems with adding the new uniqueness index, try inspecting:
502 // SELECT name, domain_id, contact_id, count(*) AS dupes FROM civicrm_setting cs GROUP BY name, domain_id, contact_id HAVING dupes > 1;
503
504 // Nav records are expendable. https://forum.civicrm.org/index.php?topic=36933.0
505 CRM_Core_DAO::executeQuery('DELETE FROM civicrm_setting WHERE contact_id IS NOT NULL AND name = "navigation"');
3ddd2901 506
726e6261
SL
507 CRM_Core_DAO::executeQuery('ALTER TABLE civicrm_setting DROP INDEX index_group_name');
508 CRM_Core_DAO::executeQuery('ALTER TABLE civicrm_setting DROP COLUMN group_name');
509
3ddd2901
SL
510 // Handle Strange activity_tab_filter settings.
511 CRM_Core_DAO::executeQuery('CREATE TABLE civicrm_activity_setting LIKE civicrm_setting');
726e6261 512 CRM_Core_DAO::executeQuery('ALTER TABLE civicrm_activity_setting ADD UNIQUE INDEX index_domain_contact_name (domain_id, contact_id, name)');
3ddd2901 513 CRM_Core_DAO::executeQuery('INSERT INTO civicrm_activity_setting (name, contact_id, domain_id, value)
726e6261 514 SELECT DISTINCT name, contact_id, domain_id, value
3ddd2901
SL
515 FROM civicrm_setting
516 WHERE name = "activity_tab_filter"
517 AND value is not NULL');
ee4d8422 518 CRM_Core_DAO::executeQuery('DELETE FROM civicrm_setting WHERE name = "activity_tab_filter"');
4cc9e637 519
e6a2c901 520 $date = CRM_Utils_Time::getTime('Y-m-d H:i:s');
f806379b 521 CRM_Core_DAO::executeQuery('ALTER TABLE civicrm_setting ADD UNIQUE INDEX index_domain_contact_name (domain_id, contact_id, name)');
e6a2c901
SL
522 CRM_Core_DAO::executeQuery("INSERT INTO civicrm_setting (name, contact_id, domain_id, value, is_domain, created_id, created_date)
523 SELECT name, contact_id, domain_id, value, 0, contact_id,'$date'
3ddd2901 524 FROM civicrm_activity_setting
e6a2c901
SL
525 WHERE name = 'activity_tab_filter'
526 AND value is not NULL"
d09d52ce 527 );
3ddd2901 528 CRM_Core_DAO::executeQuery('DROP TABLE civicrm_activity_setting');
f806379b
TO
529
530 $domainDao = CRM_Core_DAO::executeQuery('SELECT id, config_backend FROM civicrm_domain');
531 while ($domainDao->fetch()) {
532 $settings = CRM_Upgrade_Incremental_php_FourSeven::convertBackendToSettings($domainDao->id, $domainDao->config_backend);
533 CRM_Core_Error::debug_var('convertBackendToSettings', array(
534 'domainId' => $domainDao->id,
535 'backend' => $domainDao->config_backend,
536 'settings' => $settings,
537 ));
538
539 foreach ($settings as $name => $value) {
540 $rowParams = array(
541 1 => array($domainDao->id, 'Positive'),
542 2 => array($name, 'String'),
543 3 => array(serialize($value), 'String'),
544 );
545 $settingId = CRM_Core_DAO::singleValueQuery(
546 'SELECT id FROM civicrm_setting WHERE domain_id = %1 AND name = %2',
547 $rowParams);
548 if (!$settingId) {
549 CRM_Core_DAO::executeQuery(
550 'INSERT INTO civicrm_setting (domain_id, name, value, is_domain) VALUES (%1,%2,%3,1)',
551 $rowParams);
552 }
553 }
554 }
555
9e726168 556 CRM_Core_DAO::executeQuery('ALTER TABLE civicrm_domain DROP COLUMN config_backend');
f806379b
TO
557
558 return TRUE;
559 }
560
561 /**
562 * Take a config_backend blob and produce an equivalent list of settings.
563 *
564 * @param int $domainId
565 * Domain ID.
566 * @param string $config_backend
567 * Serialized blob.
568 * @return array
569 */
570 public static function convertBackendToSettings($domainId, $config_backend) {
571 if (!$config_backend) {
572 return array();
573 }
574
575 $backend = unserialize($config_backend);
576 if (!$backend) {
577 return array();
578 }
579
580 $mappings = \CRM_Core_Config_MagicMerge::getPropertyMap();
581 $settings = array();
582 foreach ($backend as $propertyName => $propertyValue) {
583 if (isset($mappings[$propertyName][0]) && preg_match('/^setting/', $mappings[$propertyName][0])) {
584 // $mapping format: $propertyName => Array(0 => $type, 1 => $setting|NULL).
585 $settingName = isset($mappings[$propertyName][1]) ? $mappings[$propertyName][1] : $propertyName;
586 $settings[$settingName] = $propertyValue;
587 }
588 }
589
590 return $settings;
591 }
592
0a95c936 593 /**
594 * Add Getting Started dashlet to dashboard
595 *
596 * @param \CRM_Queue_TaskContext $ctx
597 *
598 * @return bool
599 */
5c9edd99 600 public static function addGettingStartedDashlet(CRM_Queue_TaskContext $ctx) {
9c4a04f2 601 $sql = "SELECT count(*) FROM civicrm_dashboard WHERE name='getting-started'";
e1674273 602 $res = CRM_Core_DAO::singleValueQuery($sql);
603 $domainId = CRM_Core_Config::domainID();
604 if ($res <= 0) {
605 $sql = "INSERT INTO `civicrm_dashboard`
a8b704c5 606 ( `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)";
e1674273 607 CRM_Core_DAO::executeQuery($sql);
608 // Add default position for Getting Started Dashlet ( left column)
609 $sql = "INSERT INTO `civicrm_dashboard_contact` (dashboard_id, contact_id, column_no, is_active)
610SELECT (SELECT MAX(id) FROM `civicrm_dashboard`), contact_id, 0, IF (SUM(is_active) > 0, 1, 0)
429da6a1 611FROM `civicrm_dashboard_contact` JOIN `civicrm_contact` WHERE civicrm_dashboard_contact.contact_id = civicrm_contact.id GROUP BY contact_id";
e1674273 612 CRM_Core_DAO::executeQuery($sql);
613 }
0a95c936 614 return TRUE;
e1674273 615 }
4175ee03 616
6b1e1a2c 617 /**
618 * Migrate on-behalf information to uf_join.module_data as on-behalf columns will be dropped
619 * on DB upgrade
620 *
621 * @param CRM_Queue_TaskContext $ctx
622 *
623 * @return bool
624 * TRUE for success
625 */
626 public static function migrateOnBehalfOfInfo(CRM_Queue_TaskContext $ctx) {
d3e92c88 627 $domain = new CRM_Core_DAO_Domain();
628 $domain->find(TRUE);
6b1e1a2c 629
d3e92c88 630 // fetch onBehalf entry in UFJoin table
6b1e1a2c 631 $ufGroupDAO = new CRM_Core_DAO_UFJoin();
632 $ufGroupDAO->module = 'OnBehalf';
633 $ufGroupDAO->find(TRUE);
634
f635ab77 635 $forOrgColums = array('is_for_organization');
d3e92c88 636 if ($domain->locales) {
637 $locales = explode(CRM_Core_DAO::VALUE_SEPARATOR, $domain->locales);
638 foreach ($locales as $locale) {
639 $forOrgColums[] = "for_organization_{$locale}";
640 }
641 }
642 else {
643 $forOrgColums[] = "for_organization";
644 }
645
646 $query = "
647 SELECT " . implode(", ", $forOrgColums) . ", uj.id as join_id, uj.uf_group_id as uf_group_id
648 FROM civicrm_contribution_page cp
649 INNER JOIN civicrm_uf_join uj ON uj.entity_id = cp.id AND uj.module = 'OnBehalf'";
650 $dao = CRM_Core_DAO::executeQuery($query, array(), TRUE, NULL, FALSE, FALSE);
6b1e1a2c 651
652 if ($dao->N) {
6b1e1a2c 653 while ($dao->fetch()) {
654 $onBehalfParams['on_behalf'] = array('is_for_organization' => $dao->is_for_organization);
655 if ($domain->locales) {
6b1e1a2c 656 foreach ($locales as $locale) {
657 $for_organization = "for_organization_{$locale}";
658 $onBehalfParams['on_behalf'] += array(
659 $locale => array(
660 'for_organization' => $dao->$for_organization,
661 ),
662 );
663 }
664 }
665 else {
666 $onBehalfParams['on_behalf'] += array(
667 'default' => array(
668 'for_organization' => $dao->for_organization,
669 ),
670 );
671 }
672 $ufJoinParam = array(
673 'id' => $dao->join_id,
674 'module' => 'on_behalf',
d3e92c88 675 'uf_group_id' => $dao->uf_group_id,
6b1e1a2c 676 'module_data' => json_encode($onBehalfParams),
677 );
678 CRM_Core_BAO_UFJoin::create($ufJoinParam);
679 }
680 }
681
682 return TRUE;
9e42a501
TO
683 }
684
685 /**
686 * v4.7.11 adds a new setting "remote_profile_submissions". This is
687 * long-standing feature that existing sites may be using; however, it's
688 * a bit prone to abuse. For new sites, the default is to disable it
689 * (since that is more secure). For existing sites, the default is to
690 * enable it (since that is more compatible).
691 *
692 * @param \CRM_Queue_TaskContext $ctx
693 *
694 * @return bool
695 */
5c9edd99 696 public static function migrateRemoteSubmissionsSetting(CRM_Queue_TaskContext $ctx) {
9e42a501
TO
697 $domains = CRM_Core_DAO::executeQuery("SELECT DISTINCT d.id FROM civicrm_domain d LEFT JOIN civicrm_setting s ON d.id=s.domain_id AND s.name = 'remote_profile_submissions' WHERE s.id IS NULL");
698 while ($domains->fetch()) {
699 CRM_Core_DAO::executeQuery(
700 "INSERT INTO civicrm_setting (`name`, `value`, `domain_id`, `is_domain`, `contact_id`, `component_id`, `created_date`, `created_id`)
701 VALUES (%2, %3, %4, %5, NULL, NULL, %6, NULL)",
702 array(
703 2 => array('remote_profile_submissions', 'String'),
704 3 => array('s:1:"1";', 'String'),
705 4 => array($domains->id, 'Integer'),
706 5 => array(1, 'Integer'),
707 6 => array(date('Y-m-d H:i:s'), 'String'),
708 )
709 );
710 }
711 return TRUE;
6b1e1a2c 712 }
cb804cd9 713
b2222b9f
CW
714 /**
715 * CRM-11782 - Get rid of VALUE_SEPARATOR character in saved search form values
716 *
717 * @param \CRM_Queue_TaskContext $ctx
718 *
719 * @return bool
720 */
5c9edd99 721 public static function fixContactTypeInSmartGroups(CRM_Queue_TaskContext $ctx) {
b2222b9f
CW
722 $sep = CRM_Core_DAO::VALUE_SEPARATOR;
723 $dao = CRM_Core_DAO::executeQuery("SELECT id, form_values FROM civicrm_saved_search WHERE form_values LIKE '%$sep%'");
724 while ($dao->fetch()) {
725 $formValues = unserialize($dao->form_values);
726 if (isset($formValues['contact_type']) && is_array($formValues['contact_type'])) {
727 $newVals = array();
728 foreach ($formValues['contact_type'] as $key => $val) {
729 $newVals[str_replace($sep, '__', $key)] = is_string($val) ? str_replace($sep, '__', $val) : $val;
730 }
731 $formValues['contact_type'] = $newVals;
732 }
733 CRM_Core_DAO::executeQuery("UPDATE civicrm_saved_search SET form_values = %1 WHERE id = {$dao->id}", array(1 => array(serialize($formValues), 'String')));
734 }
735
736 return TRUE;
737 }
738
0094ac08
CW
739 /**
740 * CRM-17637 - Ths file location has been moved; delete the old one
741 *
742 * @param \CRM_Queue_TaskContext $ctx
743 *
744 * @return bool
745 */
5c9edd99 746 public static function deleteVersionCheckCacheFile(CRM_Queue_TaskContext $ctx) {
0094ac08
CW
747 $config = CRM_Core_Config::singleton();
748 $cacheFile = $config->uploadDir . 'version-info-cache.json';
749 if (file_exists($cacheFile)) {
750 unlink($cacheFile);
751 }
752 return TRUE;
753 }
754
fb1f3850
DRJ
755 /**
756 * CRM-17669 and CRM-17686, make scheduled jobs more flexible, disable the 4.6 extension if installed
757 *
758 * @param \CRM_Queue_TaskContext $ctx
759 *
760 * @return bool
761 */
5c9edd99 762 public static function disableFlexibleJobsExtension(CRM_Queue_TaskContext $ctx) {
d357221c
DRJ
763 try {
764 civicrm_api3('Extension', 'disable', array('key' => 'com.klangsoft.flexiblejobs'));
765 }
766 catch (CiviCRM_API3_Exception $e) {
767 // just ignore if the extension isn't installed
768 }
fb1f3850
DRJ
769
770 return TRUE;
771 }
772
20d5377e 773 /**
774 * CRM-17752 add index to civicrm_financial_trxn.trxn_id (deliberately non-unique).
775 *
776 * @param \CRM_Queue_TaskContext $ctx
777 *
778 * @return bool
779 */
5c9edd99 780 public static function addIndexFinancialTrxnTrxnID(CRM_Queue_TaskContext $ctx) {
20d5377e 781 $tables = array('civicrm_financial_trxn' => array('trxn_id'));
782 CRM_Core_BAO_SchemaHandler::createIndexes($tables);
783 return TRUE;
784 }
785
8ca47f5c 786 /**
787 * CRM-17882 Add index to civicrm_contribution.credit_note_id.
788 *
789 * @param \CRM_Queue_TaskContext $ctx
790 *
791 * @return bool
792 */
5c9edd99 793 public static function addIndexContributionCreditNoteID(CRM_Queue_TaskContext $ctx) {
8ca47f5c 794 $tables = array('civicrm_contribution' => array('creditnote_id'));
795 CRM_Core_BAO_SchemaHandler::createIndexes($tables);
796 return TRUE;
797 }
798
2179c899 799 /**
800 * CRM-17775 Add correct index for table civicrm_financial_item.
801 *
802 * Note that the entity ID should always precede the entity_table as
803 * it is more unique. This is better for performance and does not cause fallback
804 * to no index if table it omitted.
805 *
806 * @return bool
807 */
5c9edd99 808 public static function addCombinedIndexFinancialItemEntityIDEntityType() {
2179c899 809 CRM_Core_BAO_SchemaHandler::dropIndexIfExists('civicrm_financial_item', 'UI_id');
810 CRM_Core_BAO_SchemaHandler::dropIndexIfExists('civicrm_financial_item', 'IX_Entity');
811 CRM_Core_BAO_SchemaHandler::createIndexes(array(
812 'civicrm_financial_item' => array(array('entity_id', 'entity_table')),
813 ));
814 return TRUE;
815 }
816
1f395432 817 /**
818 * CRM-17951 Add accounts option values for refund and chargeback.
819 *
820 * Add Chargeback contribution status and Chargeback and Contra account relationships,
821 * checking first if one exists.
822 */
5c9edd99 823 public static function addRefundAndChargeBackAccountsIfNotExist() {
1f395432 824 // First we enable and edit the record for Credit contra - this exists but is disabled for most sites.
825 // Using the ensure function (below) will not enabled a disabled option (by design).
826 CRM_Core_DAO::executeQuery("UPDATE civicrm_option_value v
827 INNER JOIN civicrm_option_group g on v.option_group_id=g.id and g.name='account_relationship'
828 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'
829 WHERE v.name = 'Credit/Contra Account is';");
830
831 CRM_Core_BAO_OptionValue::ensureOptionValueExists(array(
832 'option_group_id' => 'account_relationship',
4a907feb
EM
833 'name' => 'Chargeback Account is',
834 'label' => ts('Chargeback Account is'),
1f395432 835 'is_active' => TRUE,
836 'component_id' => 'CiviContribute',
837 ));
838
839 CRM_Core_BAO_OptionValue::ensureOptionValueExists(array(
840 'option_group_id' => 'contribution_status',
841 'name' => 'Chargeback',
842 'label' => ts('Chargeback'),
843 'is_active' => TRUE,
844 'component_id' => 'CiviContribute',
845 ));
846 return TRUE;
847 }
848
3fe26f4c 849 /**
850 * CRM-17999 Add index to civicrm_contribution.source.
851 *
852 * @param \CRM_Queue_TaskContext $ctx
853 *
854 * @return bool
855 */
5c9edd99 856 public static function addIndexContributionSource(CRM_Queue_TaskContext $ctx) {
3fe26f4c 857 CRM_Core_BAO_SchemaHandler::createIndexes(array('civicrm_contribution' => array('source')));
858 return TRUE;
859 }
860
fd28b6a0 861 /**
862 * CRM-18124 Add index to civicrm_contribution.total_amount.
863 *
864 * Note that I made this a combined index with receive_date because the issue included
865 * both criteria and they seemed likely to be used in conjunction to me in other cases.
866 *
867 * @param \CRM_Queue_TaskContext $ctx
868 *
869 * @return bool
870 */
5c9edd99 871 public static function addIndexContributionAmount(CRM_Queue_TaskContext $ctx) {
fd28b6a0 872 CRM_Core_BAO_SchemaHandler::createIndexes(array(
873 'civicrm_contribution' => array(array('total_amount', 'receive_date')),
874 ));
875 return TRUE;
876 }
877
6eb752fa 878 /**
879 * CRM-18124 Add index to civicrm_contribution.total_amount.
880 *
881 * Note that I made this a combined index with receive_date because the issue included
882 * both criteria and they seemed likely to be used in conjunction to me in other cases.
883 *
884 * @param \CRM_Queue_TaskContext $ctx
885 *
886 * @return bool
887 */
5c9edd99 888 public static function addDeletedByMergeActivityType(CRM_Queue_TaskContext $ctx) {
6eb752fa 889 CRM_Core_BAO_OptionValue::ensureOptionValueExists(array(
890 'option_group_id' => 'activity_type',
891 'name' => 'Contact Deleted by Merge',
892 'label' => ts('Contact Deleted by Merge'),
893 'description' => ts('Contact was merged into another contact'),
894 'is_active' => TRUE,
e14e412b 895 'filter' => 1,
6eb752fa 896 ));
897 return TRUE;
898 }
899
da1ecd73
SL
900 /**
901 * CRM-12252 Add Help Pre and Help Post Fields for Price Field Value Table.
902 *
903 * @param \CRM_Queue_TaskContext $ctx
904 *
905 * @return bool
906 */
5c9edd99 907 public static function addHelpPreAndHelpPostFieldsPriceFieldValue(CRM_Queue_TaskContext $ctx) {
da1ecd73
SL
908 $domain = new CRM_Core_DAO_Domain();
909 $domain->find(TRUE);
910 if ($domain->locales) {
911 $locales = explode(CRM_Core_DAO::VALUE_SEPARATOR, $domain->locales);
912 foreach ($locales as $locale) {
01ee8ba6 913 if (!CRM_Core_BAO_SchemaHandler::checkIfFieldExists("civicrm_price_field_value", "help_pre_{$locale}")) {
3dc870a2
SL
914 CRM_Core_DAO::executeQuery("ALTER TABLE `civicrm_price_field_value`
915 ADD COLUMN `help_pre_{$locale}` text COLLATE utf8_unicode_ci COMMENT 'Price field option pre help text.'", array(), TRUE, NULL, FALSE, FALSE);
da1ecd73 916 }
01ee8ba6 917 if (!CRM_Core_BAO_SchemaHandler::checkIfFieldExists("civicrm_price_field_value", "help_post_{$locale}")) {
3dc870a2
SL
918 CRM_Core_DAO::executeQuery("ALTER TABLE `civicrm_price_field_value`
919 ADD COLUMN `help_post_{$locale}` text COLLATE utf8_unicode_ci COMMENT 'Price field option post help text.'", array(), TRUE, NULL, FALSE, FALSE);
da1ecd73
SL
920 }
921 }
41ace555 922 CRM_Core_I18n_Schema::rebuildMultilingualSchema($locales, NULL, TRUE);
da1ecd73
SL
923 }
924 else {
925 if (!CRM_Core_BAO_SchemaHandler::checkIfFieldExists('civicrm_price_field_value', 'help_pre')) {
3dc870a2
SL
926 CRM_Core_DAO::executeQuery("ALTER TABLE `civicrm_price_field_value`
927 ADD COLUMN `help_pre` text COLLATE utf8_unicode_ci COMMENT 'Price field option pre help text.'");
da1ecd73
SL
928 }
929 if (!CRM_Core_BAO_SchemaHandler::checkIfFieldExists('civicrm_price_field_value', 'help_post')) {
3dc870a2
SL
930 CRM_Core_DAO::executeQuery("ALTER TABLE `civicrm_price_field_value`
931 ADD COLUMN `help_post` text COLLATE utf8_unicode_ci COMMENT 'Price field option post help text.'");
da1ecd73
SL
932 }
933 }
934 return TRUE;
935 }
936
8c748d50
SL
937 /**
938 * CRM-18464 Check if Foreign key exists and also drop any index of same name accidentially created.
939 *
940 * @param \CRM_Queue_TaskContext $ctx
941 *
942 * @return bool
943 */
944 public static function dropActionScheudleMappingForeignKey(CRM_Queue_TaskContext $ctx) {
945 CRM_Core_BAO_SchemaHandler::safeRemoveFK('civicrm_action_schedule', 'FK_civicrm_action_schedule_mapping_id');
8c748d50
SL
946 return TRUE;
947 }
948
2cbdd085
J
949 /**
950 * CRM-18345 Don't delete mailing data on email/phone deletion
951 * Implemented here in CRM-18526
952 *
953 * @param \CRM_Queue_TaskContext $ctx
954 *
955 * @return bool
956 */
5c9edd99 957 public static function upgradeMailingFKs(CRM_Queue_TaskContext $ctx) {
2cbdd085
J
958
959 // Safely drop the foreign keys
169475b7
SL
960 CRM_Core_BAO_SchemaHandler::safeRemoveFK('civicrm_mailing_event_queue', 'FK_civicrm_mailing_event_queue_email_id');
961 CRM_Core_BAO_SchemaHandler::safeRemoveFK('civicrm_mailing_event_queue', 'FK_civicrm_mailing_event_queue_phone_id');
962 CRM_Core_BAO_SchemaHandler::safeRemoveFK('civicrm_mailing_recipients', 'FK_civicrm_mailing_recipients_email_id');
963 CRM_Core_BAO_SchemaHandler::safeRemoveFK('civicrm_mailing_recipients', 'FK_civicrm_mailing_recipients_phone_id');
2cbdd085
J
964
965 // Set up the new foreign keys
966 CRM_Core_DAO::executeQuery("SET FOREIGN_KEY_CHECKS = 0;");
967
968 CRM_Core_DAO::executeQuery("
969 ALTER TABLE `civicrm_mailing_event_queue`
970 ADD CONSTRAINT `FK_civicrm_mailing_event_queue_email_id`
971 FOREIGN KEY (`email_id`)
972 REFERENCES `civicrm_email`(`id`)
973 ON DELETE SET NULL
974 ON UPDATE RESTRICT;
975 ");
976
977 CRM_Core_DAO::executeQuery("
978 ALTER TABLE `civicrm_mailing_event_queue`
979 ADD CONSTRAINT `FK_civicrm_mailing_event_queue_phone_id`
980 FOREIGN KEY (`phone_id`)
981 REFERENCES `civicrm_phone`(`id`)
982 ON DELETE SET NULL
983 ON UPDATE RESTRICT;
984 ");
985
986 CRM_Core_DAO::executeQuery("
987 ALTER TABLE `civicrm_mailing_recipients`
988 ADD CONSTRAINT `FK_civicrm_mailing_recipients_email_id`
989 FOREIGN KEY (`email_id`)
990 REFERENCES `civicrm_email`(`id`)
991 ON DELETE SET NULL
992 ON UPDATE RESTRICT;
993 ");
994
995 CRM_Core_DAO::executeQuery("
996 ALTER TABLE `civicrm_mailing_recipients`
997 ADD CONSTRAINT `FK_civicrm_mailing_recipients_phone_id`
998 FOREIGN KEY (`phone_id`)
999 REFERENCES `civicrm_phone`(`id`)
1000 ON DELETE SET NULL
1001 ON UPDATE RESTRICT;
1002 ");
1003
1004 CRM_Core_DAO::executeQuery("SET FOREIGN_KEY_CHECKS = 1;");
1005
1006 return TRUE;
1007 }
1008
00c27b41
CW
1009 /**
1010 * CRM-17663 - Dashboard schema changes
1011 *
1012 * @param \CRM_Queue_TaskContext $ctx
1013 *
1014 * @return bool
1015 */
5c9edd99 1016 public static function dashboardSchemaUpdate(CRM_Queue_TaskContext $ctx) {
00c27b41
CW
1017 if (!CRM_Core_BAO_SchemaHandler::checkIfIndexExists('civicrm_dashboard_contact', 'index_dashboard_id_contact_id')) {
1018 // Delete any stray duplicate rows and add unique index to prevent new dupes and enable INSERT/UPDATE combo query
1019 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');
1020 CRM_Core_DAO::executeQuery('ALTER TABLE civicrm_dashboard_contact ADD UNIQUE INDEX index_dashboard_id_contact_id (dashboard_id, contact_id);');
1021 }
87568e34
SL
1022 $domain = new CRM_Core_DAO_Domain();
1023 $domain->find(TRUE);
41ace555
SL
1024 CRM_Core_BAO_SchemaHandler::dropColumn('civicrm_dashboard_contact', 'content', FALSE, TRUE);
1025 CRM_Core_BAO_SchemaHandler::dropColumn('civicrm_dashboard_contact', 'is_minimized', FALSE, TRUE);
1026 CRM_Core_BAO_SchemaHandler::dropColumn('civicrm_dashboard_contact', 'is_fullscreen', FALSE, TRUE);
1027 CRM_Core_BAO_SchemaHandler::dropColumn('civicrm_dashboard_contact', 'created_date', FALSE, TRUE);
1028 CRM_Core_BAO_SchemaHandler::dropColumn('civicrm_dashboard', 'is_fullscreen', FALSE, TRUE);
1029 CRM_Core_BAO_SchemaHandler::dropColumn('civicrm_dashboard', 'is_minimized', FALSE, TRUE);
1030 CRM_Core_BAO_SchemaHandler::dropColumn('civicrm_dashboard', 'column_no', FALSE, TRUE);
1031 CRM_Core_BAO_SchemaHandler::dropColumn('civicrm_dashboard', 'weight', FALSE, TRUE);
242055d3
CW
1032
1033 CRM_Core_DAO::executeQuery('UPDATE civicrm_dashboard SET url = REPLACE(url, "&snippet=5", ""), fullscreen_url = REPLACE(fullscreen_url, "&snippet=5", "")');
a8f56d71
CW
1034
1035 if (!CRM_Core_BAO_SchemaHandler::checkIfFieldExists('civicrm_dashboard', 'cache_minutes')) {
8c3f9072
SL
1036 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."',
1037 array(), TRUE, NULL, FALSE, FALSE);
1038 }
1039 if ($domain->locales) {
1040 $locales = explode(CRM_Core_DAO::VALUE_SEPARATOR, $domain->locales);
41ace555 1041 CRM_Core_I18n_Schema::rebuildMultilingualSchema($locales, NULL, TRUE);
a8f56d71
CW
1042 }
1043
1044 CRM_Core_DAO::executeQuery('UPDATE civicrm_dashboard SET cache_minutes = 1440 WHERE name = "blog"');
1045 CRM_Core_DAO::executeQuery('UPDATE civicrm_dashboard SET cache_minutes = 7200 WHERE name IN ("activity","getting-started")');
242055d3 1046 return TRUE;
00c27b41
CW
1047 }
1048
8e2e96a5 1049 /**
1050 * CRM-19100 - Alter Index and Type for Image URL
1051 * @return bool
1052 */
1053 public static function alterIndexAndTypeForImageURL() {
98daafd5 1054 $length = array();
1055 CRM_Core_BAO_SchemaHandler::dropIndexIfExists('civicrm_contact', 'index_image_url');
8e2e96a5 1056 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.'");
98daafd5 1057
1058 $length['civicrm_contact']['image_URL'] = 128;
1059 CRM_Core_BAO_SchemaHandler::createIndexes(array('civicrm_contact' => array('image_URL')), 'index', $length);
8e2e96a5 1060
1061 return TRUE;
1062 }
1063
bc854509 1064 /**
1065 * Add mailing template type.
1066 *
1067 * @return bool
1068 */
703875d8
TO
1069 public static function addMailingTemplateType() {
1070 if (!CRM_Core_DAO::checkFieldExists('civicrm_mailing', 'template_type', FALSE)) {
1071 CRM_Core_DAO::executeQuery('
1072 ALTER TABLE civicrm_mailing
1073 ADD COLUMN `template_type` varchar(64) NOT NULL DEFAULT \'traditional\' COMMENT \'The language/processing system used for email templates.\',
1074 ADD COLUMN `template_options` longtext COMMENT \'Advanced options used by the email templating system. (JSON encoded)\'
1075 ');
1076 }
1077 return TRUE;
1078 }
1079
d0e7e124
SL
1080 /**
1081 * CRM-18651 Add DataType column to Option Group Table
1082 * @return bool
1083 */
1084 public static function addDataTypeColumnToOptionGroupTable() {
7c61320c 1085 if (!CRM_Core_BAO_SchemaHandler::checkIfFieldExists('civicrm_option_group', 'data_type')) {
a37e4e6c
SL
1086 CRM_Core_DAO::executeQuery("ALTER TABLE `civicrm_option_group` ADD COLUMN `data_type` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL comment 'Data Type of Option Group.'",
1087 array(), TRUE, NULL, FALSE, FALSE);
1088 }
1089 $domain = new CRM_Core_DAO_Domain();
1090 $domain->find(TRUE);
1091 if ($domain->locales) {
1092 $locales = explode(CRM_Core_DAO::VALUE_SEPARATOR, $domain->locales);
41ace555 1093 CRM_Core_I18n_Schema::rebuildMultilingualSchema($locales, NULL, TRUE);
d0e7e124 1094 }
a37e4e6c 1095
d0e7e124
SL
1096 CRM_Core_DAO::executeQuery("UPDATE `civicrm_option_group` SET `data_type` = 'Integer'
1097 WHERE name IN ('activity_type', 'gender', 'payment_instrument', 'participant_role', 'event_type')");
1098 return TRUE;
1099 }
1100
7ad5ae6a
CW
1101 /**
1102 * CRM-19372 Add field to store accepted credit credit cards for a payment processor.
1103 * @return bool
1104 */
1105 public static function addWysiwygPresets() {
1106 CRM_Core_BAO_OptionGroup::ensureOptionGroupExists(array(
1107 'name' => 'wysiwyg_presets',
1108 'title' => ts('WYSIWYG Editor Presets'),
1109 'is_reserved' => 1,
1110 ));
1111 $values = array(
1112 'default' => array('label' => ts('Default'), 'is_default' => 1),
1113 'civimail' => array('label' => ts('CiviMail'), 'component_id' => 'CiviMail'),
1114 'civievent' => array('label' => ts('CiviEvent'), 'component_id' => 'CiviEvent'),
1115 );
1116 foreach ($values as $name => $value) {
34273b2a 1117 CRM_Core_BAO_OptionValue::ensureOptionValueExists($value + array(
7ad5ae6a
CW
1118 'name' => $name,
1119 'option_group_id' => 'wysiwyg_presets',
1120 ));
1121 }
1122 $fileName = Civi::paths()->getPath('[civicrm.files]/persist/crm-ckeditor-config.js');
99316116 1123 // Ensure the config file contains the allowedContent setting
7ad5ae6a
CW
1124 if (file_exists($fileName)) {
1125 $config = file_get_contents($fileName);
1126 $pos = strrpos($config, '};');
1127 $setting = "\n\tconfig.allowedContent = true;\n";
1128 $config = substr_replace($config, $setting, $pos, 0);
1129 unlink($fileName);
949a87e8
CW
1130 $newFileName = Civi::paths()->getPath('[civicrm.files]/persist/crm-ckeditor-default.js');
1131 file_put_contents($newFileName, $config);
7ad5ae6a 1132 }
7ad5ae6a
CW
1133 return TRUE;
1134 }
1135
36610486 1136 /**
1137 * Update Kenyan Provinces to reflect changes per CRM-20062
1138 *
1139 * @param \CRM_Queue_TaskContext $ctx
1140 */
35e62234 1141 public static function updateKenyanProvinces(CRM_Queue_TaskContext $ctx) {
36610486 1142 $kenyaCountryID = CRM_Core_DAO::singleValueQuery('SELECT max(id) from civicrm_country where iso_code = "KE"');
1143 $oldProvinces = array(
1144 'Nairobi Municipality',
1145 'Coast',
1146 'North-Eastern Kaskazini Mashariki',
1147 'Rift Valley',
1148 'Western Magharibi',
1149 );
1150 self::deprecateStateProvinces($kenyaCountryID, $oldProvinces);
1151 return TRUE;
1152 }
1153
1154 /**
1155 * Deprecate provinces that no longer exist.
1156 *
1157 * @param int $countryID
1158 * @param array $provinces
1159 */
1160 public static function deprecateStateProvinces($countryID, $provinces) {
1161 foreach ($provinces as $province) {
1162 $existingStateID = CRM_Core_DAO::singleValueQuery("
1163 SELECT id FROM civicrm_state_province
1164 WHERE country_id = %1
1165 AND name = %2
1166 ",
1167 array(1 => array($countryID, 'Int'), 2 => array($province, 'String')));
1168
1169 if (!$existingStateID) {
1170 continue;
1171 }
1172 if (!CRM_Core_DAO::singleValueQuery("
1173 SELECT count(*) FROM civicrm_address
1174 WHERE state_province_id = %1
1175 ", array(1 => array($existingStateID, 'Int')))
1176 ) {
1177 CRM_Core_DAO::executeQuery("DELETE FROM civicrm_state_province WHERE id = %1", array(1 => array($existingStateID, 'Int')));
1178 }
1179 else {
1180 $params = array('1' => array(ts("Former - $province"), 'String'));
1181 CRM_Core_DAO::executeQuery("
1182 UPDATE civicrm_state_province SET name = %1 WHERE id = $existingStateID
1183 ", $params);
1184 }
1185 }
1186 }
1187
4eae8dda
SL
1188 /**
1189 * CRM-19961
1190 * Poputate newly added domain id column and add foriegn key onto table.
1191 */
1192 public static function populateSMSProviderDomainId() {
1193 $count = CRM_Core_DAO::singleValueQuery("SELECT count(id) FROM civicrm_domain");
9cec4195 1194 if ($count == 1) {
4eae8dda
SL
1195 CRM_Core_DAO::executeQuery("UPDATE civicrm_sms_provider SET domain_id = (SELECT id FROM civicrm_domain)");
1196 }
27e82c24 1197 if (!parent::checkFKExists('civicrm_sms_provider', 'FK_civicrm_sms_provider_domain_id')) {
f5078cc0
SL
1198 CRM_Core_DAO::executeQuery("SET FOREIGN_KEY_CHECKS = 0;");
1199 CRM_Core_DAO::executeQuery("ALTER TABLE `civicrm_sms_provider`
1200 ADD CONSTRAINT FK_civicrm_sms_provider_domain_id
1201 FOREIGN KEY (`domain_id`) REFERENCES `civicrm_domain`(`id`)
1202 ON DELETE SET NULL");
4eae8dda 1203
f5078cc0
SL
1204 CRM_Core_DAO::executeQuery("SET FOREIGN_KEY_CHECKS = 1;");
1205 }
4eae8dda
SL
1206 return TRUE;
1207 }
1208
ccfd6962
CW
1209 /**
1210 * CRM-16633 - Add activity type for Change Case Status
1211 *
1212 * @param \CRM_Queue_TaskContext $ctx
1213 *
1214 * @return bool
1215 */
1216 public static function addChangeCaseSubjectActivityType(CRM_Queue_TaskContext $ctx) {
1217 CRM_Core_BAO_OptionValue::ensureOptionValueExists(array(
1218 'option_group_id' => 'activity_type',
1219 'name' => 'Change Case Subject',
1220 'label' => ts('Change Case Subject'),
1221 'is_active' => TRUE,
1222 'component_id' => 'CiviCase',
1223 'icon' => 'fa-pencil-square-o',
1224 ));
1225 return TRUE;
1226 }
1227
6f0dad97
SL
1228 /**
1229 * CRM-19986 fix schema differnces in civicrm_action_schedule
1230 */
1231 public static function fixSchemaOnCiviCRMActionSchedule() {
27e82c24 1232 if (!parent::checkFKExists('civicrm_action_schedule', 'FK_civicrm_action_schedule_sms_template_id')) {
6f0dad97
SL
1233 CRM_Core_DAO::executeQuery("ALTER TABLE `civicrm_action_schedule`
1234 ADD CONSTRAINT FK_civicrm_action_schedule_sms_template_id
1235 FOREIGN KEY (`sms_template_id`) REFERENCES `civicrm_msg_template`(`id`)
1236 ON DELETE SET NULL");
1237 }
1238 CRM_Core_DAO::executeQuery("ALTER TABLE `civicrm_action_schedule`
1239 CHANGE `mapping_id` `mapping_id` varchar(64) COLLATE
1240 utf8_unicode_ci DEFAULT NULL COMMENT 'Name/ID of the mapping to use on this table'");
1241 return TRUE;
1242 }
1243
58e9d364
TO
1244 public static function pickActivityRevisionPolicy(CRM_Queue_TaskContext $ctx) {
1245 // CRM-21052 - If site is using activity revisions, continue doing so. Otherwise, switch out.
1246 $count = CRM_Core_DAO::singleValueQuery('SELECT count(*) FROM civicrm_activity WHERE is_current_revision = 0 OR original_id IS NOT NULL');
1247 Civi::settings()->set('civicaseActivityRevisions', $count > 0);
1248 return TRUE;
1249 }
1250
be2faa1d
TO
1251 /**
1252 * Add in missing Tajikistan Subdivisions
1253 *
1254 * @param \CRM_Queue_TaskContext $ctx
1255 *
1256 * @return bool
1257 */
1258 public static function tajikistanMissingSubdivisions(CRM_Queue_TaskContext $ctx) {
1259 $sql = 'INSERT INTO civicrm_state_province (id, country_id, abbreviation, name) VALUES';
1260 $updates = array();
1261 if (!CRM_Core_DAO::singleValueQuery("Select id FROM civicrm_state_province WHERE country_id = 1209 AND name = 'Dushanbe'")) {
1262 $updates[] = '(NULL, 1209, "DU", "Dushanbe")';
1263 }
1264 if (!CRM_Core_DAO::singleValueQuery("Select id FROM civicrm_state_province WHERE country_id = 1209 AND name = 'Nohiyahoi Tobei JumhurĂ­'")) {
1265 $updates[] = '(NULL, 1209, "RA", "Nohiyahoi Tobei JumhurĂ­")';
1266 }
1267 if (!empty($updates)) {
1268 CRM_Core_DAO::executeQuery($sql . implode(', ', $updates));
1269 }
1270 return TRUE;
1271 }
1272
07c25637 1273 /**
1274 * Remove the contribution logging reports which have been broken for a very long time.
1275 *
1276 * @param \CRM_Queue_TaskContext $ctx
1277 *
1278 * @return bool
1279 */
1280 public static function removeContributionLoggingReports(CRM_Queue_TaskContext $ctx) {
1281 if (class_exists('CRM_Report_Form_Contribute_LoggingDetail') || class_exists('CRM_Report_Form_Contribute_LoggingSummary')) {
1282 // Perhaps the site has overridden these classes. The core ones are broken but they
1283 // may have functional ones.
1284 return TRUE;
1285 }
1286 $options = civicrm_api3('OptionValue', 'get', array('option_group_id' => 'report_template', 'options' => array('limit' => 0)));
1287 foreach ($options['values'] as $option) {
1288 if ($option['name'] === 'CRM_Report_Form_Contribute_LoggingDetail' || $option['name'] === 'CRM_Report_Form_Contribute_LoggingSummary') {
1289 $instances = civicrm_api3('ReportInstance', 'get', array('report_id' => $option['value']));
1290 if ($instances['count']) {
1291 foreach ($instances['values'] as $instance) {
1292 if ($instance['navigation_id']) {
1293 civicrm_api3('Navigation', 'delete', array('id' => $instance['navigation_id']));
1294 }
1295 civicrm_api3('ReportInstance', 'delete', array('id' => $instance['id']));
1296 }
1297 }
1298 civicrm_api3('OptionValue', 'delete', array('id' => $option['id']));
1299 }
1300 }
1301 return TRUE;
1302 }
1303
17511f38
TO
1304 /**
1305 * @return bool
1306 */
1307 protected function checkImageUploadDir() {
1308 $config = CRM_Core_Config::singleton();
1309 $check = new CRM_Utils_Check_Component_Security();
1310 return $config->imageUploadDir && $config->imageUploadURL && $check->isDirAccessible($config->imageUploadDir, $config->imageUploadURL);
1311 }
1312
6cc25669 1313}