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