CRM-20062 upgrade component of Kenyan provinces
[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 }
66
67 /**
68 * Compute any messages which should be displayed after upgrade.
69 *
70 * @param string $postUpgradeMessage
71 * alterable.
72 * @param string $rev
73 * an intermediate version; note that setPostUpgradeMessage is called repeatedly with different $revs.
74 */
75 public function setPostUpgradeMessage(&$postUpgradeMessage, $rev) {
76 if ($rev == '4.7.alpha1') {
77 $config = CRM_Core_Config::singleton();
78 // FIXME: Performing an upgrade step during postUpgrade message phase is probably bad
79 $editor_id = self::updateWysiwyg();
80 $msg = NULL;
81 $ext_href = 'href="' . CRM_Utils_System::url('civicrm/admin/extensions', 'reset=1') . '"';
82 $dsp_href = 'href="' . CRM_Utils_System::url('civicrm/admin/setting/preferences/display', 'reset=1') . '"';
83 $blog_href = 'href="https://civicrm.org/blogs/colemanw/big-changes-wysiwyg-editing-47"';
84 switch ($editor_id) {
85 // TinyMCE
86 case 1:
87 $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));
88 break;
89
90 // Drupal/Joomla editor
91 case 3:
92 case 4:
93 $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));
94 break;
95 }
96 if ($msg) {
97 $postUpgradeMessage .= '<p>' . $msg . '</p>';
98 }
99 $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>';
100
101 $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).');
102
103 $postUpgradeMessage .= '<p>' . ts('The custom fatal error template setting has been removed.') . '</p>';
104 }
105 //if ($rev == '4.7.11') {
106 // $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'");
107 //}
108 if ($rev == '4.7.11') {
109 $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'.");
110 }
111 if ($rev == '4.7.14') {
112 $ck_href = 'href="' . CRM_Utils_System::url('civicrm/admin/ckeditor') . '"';
113 $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.')
114 . '<br />' . ts('You can re-enable it by visitng the <a %1>CKEditor Config</a> screen and setting "fullPage = true" under the Advanced Options of the CiviMail preset.', array(1 => $ck_href))
115 . '</p>';
116 }
117 }
118
119 /**
120 * Upgrade function.
121 *
122 * @param string $rev
123 */
124 public function upgrade_4_7_alpha1($rev) {
125 $this->addTask('Drop action scheudle mapping foreign key', 'dropActionScheudleMappingForeignKey');
126 $this->addTask('Migrate \'on behalf of\' information to module_data', 'migrateOnBehalfOfInfo');
127 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
128 $this->addTask(ts('Migrate Settings to %1', array(1 => $rev)), 'migrateSettings', $rev);
129 $this->addTask('Add Getting Started dashlet', 'addGettingStartedDashlet', $rev);
130 }
131
132 /**
133 * Upgrade function.
134 *
135 * @param string $rev
136 */
137 public function upgrade_4_7_alpha4($rev) {
138 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
139 $this->addTask(ts('Remove %1', array(1 => 'Moneris')), 'removePaymentProcessorType', 'Moneris');
140 $this->addTask('Update Smart Groups', 'fixContactTypeInSmartGroups');
141 }
142
143 /**
144 * Upgrade function.
145 *
146 * @param string $rev
147 */
148 public function upgrade_4_7_beta2($rev) {
149 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
150 $this->addTask('Delete unused file', 'deleteVersionCheckCacheFile');
151 }
152
153 /**
154 * Upgrade function.
155 *
156 * @param string $rev
157 */
158 public function upgrade_4_7_beta6($rev) {
159 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
160 $this->addTask('Disable flexible jobs extension', 'disableFlexibleJobsExtension');
161 $this->addTask('Add Index to financial_trxn trxn_id field', 'addIndexFinancialTrxnTrxnID');
162 }
163
164 /**
165 * Upgrade function.
166 *
167 * @param string $rev
168 */
169 public function upgrade_4_7_1($rev) {
170 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
171 $this->addTask('Add Index to civicrm_contribution creditnote_id field', 'addIndexContributionCreditNoteID');
172 }
173
174 /**
175 * Upgrade function.
176 *
177 * @param string $rev
178 */
179 public function upgrade_4_7_2($rev) {
180 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
181 $this->addTask('Fix Index on civicrm_financial_item combined entity_id + entity_table', 'addCombinedIndexFinancialItemEntityIDEntityType');
182 $this->addTask('enable financial account relationships for chargeback & refund', 'addRefundAndChargeBackAccountsIfNotExist');
183 $this->addTask('Add Index to civicrm_contribution.source', 'addIndexContributionSource');
184 }
185
186 /**
187 * Upgrade function.
188 *
189 * @param string $rev
190 */
191 public function upgrade_4_7_3($rev) {
192 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
193 $this->addTask('Add Index to civicrm_contribution.total_amount', 'addIndexContributionAmount');
194 }
195
196 /**
197 * Upgrade function.
198 *
199 * @param string $rev
200 */
201 public function upgrade_4_7_4($rev) {
202 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
203 $this->addTask('Add Contact Deleted by Merge Activity Type', 'addDeletedByMergeActivityType');
204 }
205
206 /**
207 * Upgrade function.
208 *
209 * @param string $rev
210 */
211 public function upgrade_4_7_7($rev) {
212 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
213 // https://issues.civicrm.org/jira/browse/CRM-18006
214 if (CRM_Core_DAO::checkTableExists('civicrm_install_canary')) {
215 CRM_Core_DAO::executeQuery('ALTER TABLE civicrm_install_canary ENGINE=InnoDB');
216 }
217 }
218
219 /**
220 * Upgrade function.
221 *
222 * @param string $rev
223 */
224 public function upgrade_4_7_8($rev) {
225 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
226 $this->addTask('Upgrade mailing foreign key constraints', 'upgradeMailingFKs');
227 }
228
229 /**
230 * Upgrade function.
231 *
232 * @param string $rev
233 */
234 public function upgrade_4_7_10($rev) {
235 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
236 $this->addTask('Upgrade Add Help Pre and Post Fields to price value table', 'addHelpPreAndHelpPostFieldsPriceFieldValue');
237 $this->addTask('Alter index and type for image URL', 'alterIndexAndTypeForImageURL');
238 }
239
240 /**
241 * Upgrade function.
242 *
243 * @param string $rev
244 */
245 public function upgrade_4_7_11($rev) {
246 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
247 $this->addTask('Dashboard schema updates', 'dashboardSchemaUpdate');
248 $this->addTask('Fill in setting "remote_profile_submissions"', 'migrateRemoteSubmissionsSetting');
249 }
250
251 /**
252 * Upgrade function.
253 *
254 * @param string $rev
255 */
256 public function upgrade_4_7_12($rev) {
257 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
258 $this->addTask('Add Data Type column to civicrm_option_group', 'addDataTypeColumnToOptionGroupTable');
259 }
260 /**
261 * Upgrade function.
262 *
263 * @param string $rev
264 */
265 public function upgrade_4_7_13($rev) {
266 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
267 $this->addTask('CRM-19372 - Add column to allow for payment processors to set what card types are accepted', 'addColumn',
268 'civicrm_payment_processor', 'accepted_credit_cards', "text DEFAULT NULL COMMENT 'array of accepted credit card types'");
269 }
270
271 /**
272 * Upgrade function.
273 *
274 * @param string $rev
275 */
276 public function upgrade_4_7_14($rev) {
277 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
278 $this->addTask('Add WYSIWYG Editor Presets', 'addWysiwygPresets');
279 }
280
281 /**
282 * Upgrade function.
283 *
284 * @param string $rev
285 */
286 public function upgrade_4_7_15($rev) {
287 $this->addTask('CRM-19626 - Add min_amount column to civicrm_price_set', 'addColumn',
288 'civicrm_price_set', 'min_amount', "INT(10) UNSIGNED DEFAULT '0' COMMENT 'Minimum Amount required for this set.'");
289 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
290 }
291
292 /**
293 * Upgrade function.
294 *
295 * @param string $rev
296 */
297 public function upgrade_4_7_16($rev) {
298 $this->addTask('CRM-19723 - Add icon column to civicrm_option_value', 'addColumn',
299 'civicrm_option_value', 'icon', "varchar(255) COMMENT 'crm-i icon class' DEFAULT NULL");
300 $this->addTask('CRM-19769 - Add color column to civicrm_tag', 'addColumn',
301 'civicrm_tag', 'color', "varchar(255) COMMENT 'Hex color value e.g. #ffffff' DEFAULT NULL");
302 $this->addTask('CRM-19779 - Add color column to civicrm_option_value', 'addColumn',
303 'civicrm_option_value', 'color', "varchar(255) COMMENT 'Hex color value e.g. #ffffff' DEFAULT NULL");
304 $this->addTask('Add new CiviMail fields', 'addMailingTemplateType');
305 $this->addTask('CRM-19770 - Add is_star column to civicrm_activity', 'addColumn',
306 'civicrm_activity', 'is_star', "tinyint DEFAULT '0' COMMENT 'Activity marked as favorite.'");
307 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
308 }
309
310 /**
311 * Upgrade function.
312 *
313 * @param string $rev
314 */
315 public function upgrade_4_7_18($rev) {
316 $this->addTask('Update Kenyan Provinces', 'updateKenyanProvinces');
317 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
318 }
319
320 /*
321 * Important! All upgrade functions MUST add a 'runSql' task.
322 * Uncomment and use the following template for a new upgrade version
323 * (change the x in the function name):
324 */
325
326 // /**
327 // * Upgrade function.
328 // *
329 // * @param string $rev
330 // */
331 // public function upgrade_4_7_x($rev) {
332 // $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
333 // // Additional tasks here...
334 // // Note: do not use ts() in the addTask description because it adds unnecessary strings to transifex.
335 // // The above is an exception because 'Upgrade DB to %1: SQL' is generic & reusable.
336 // }
337
338 /**
339 * CRM-16354
340 *
341 * @return int
342 */
343 public static function updateWysiwyg() {
344 $editorID = Civi::settings()->get('editor_id');
345 // Previously a numeric value indicated one of 4 wysiwyg editors shipped in core, and no value indicated 'Textarea'
346 // Now the options are "Textarea", "CKEditor", and the rest have been dropped from core.
347 $newEditor = $editorID ? "CKEditor" : "Textarea";
348 Civi::settings()->set('editor_id', $newEditor);
349
350 return $editorID;
351 }
352
353 /**
354 * Migrate any last remaining options from `civicrm_domain.config_backend` to `civicrm_setting`.
355 * Cleanup setting schema.
356 *
357 * @param CRM_Queue_TaskContext $ctx
358 * @return bool
359 */
360 public static function migrateSettings(CRM_Queue_TaskContext $ctx) {
361 // Tip: If there are problems with adding the new uniqueness index, try inspecting:
362 // SELECT name, domain_id, contact_id, count(*) AS dupes FROM civicrm_setting cs GROUP BY name, domain_id, contact_id HAVING dupes > 1;
363
364 // Nav records are expendable. https://forum.civicrm.org/index.php?topic=36933.0
365 CRM_Core_DAO::executeQuery('DELETE FROM civicrm_setting WHERE contact_id IS NOT NULL AND name = "navigation"');
366
367 CRM_Core_DAO::executeQuery('ALTER TABLE civicrm_setting DROP INDEX index_group_name');
368 CRM_Core_DAO::executeQuery('ALTER TABLE civicrm_setting DROP COLUMN group_name');
369
370 // Handle Strange activity_tab_filter settings.
371 CRM_Core_DAO::executeQuery('CREATE TABLE civicrm_activity_setting LIKE civicrm_setting');
372 CRM_Core_DAO::executeQuery('ALTER TABLE civicrm_activity_setting ADD UNIQUE INDEX index_domain_contact_name (domain_id, contact_id, name)');
373 CRM_Core_DAO::executeQuery('INSERT INTO civicrm_activity_setting (name, contact_id, domain_id, value)
374 SELECT DISTINCT name, contact_id, domain_id, value
375 FROM civicrm_setting
376 WHERE name = "activity_tab_filter"
377 AND value is not NULL');
378 CRM_Core_DAO::executeQuery('DELETE FROM civicrm_setting WHERE name = "activity_tab_filter"');
379
380 $date = CRM_Utils_Time::getTime('Y-m-d H:i:s');
381 CRM_Core_DAO::executeQuery('ALTER TABLE civicrm_setting ADD UNIQUE INDEX index_domain_contact_name (domain_id, contact_id, name)');
382 CRM_Core_DAO::executeQuery("INSERT INTO civicrm_setting (name, contact_id, domain_id, value, is_domain, created_id, created_date)
383 SELECT name, contact_id, domain_id, value, 0, contact_id,'$date'
384 FROM civicrm_activity_setting
385 WHERE name = 'activity_tab_filter'
386 AND value is not NULL"
387 );
388 CRM_Core_DAO::executeQuery('DROP TABLE civicrm_activity_setting');
389
390 $domainDao = CRM_Core_DAO::executeQuery('SELECT id, config_backend FROM civicrm_domain');
391 while ($domainDao->fetch()) {
392 $settings = CRM_Upgrade_Incremental_php_FourSeven::convertBackendToSettings($domainDao->id, $domainDao->config_backend);
393 CRM_Core_Error::debug_var('convertBackendToSettings', array(
394 'domainId' => $domainDao->id,
395 'backend' => $domainDao->config_backend,
396 'settings' => $settings,
397 ));
398
399 foreach ($settings as $name => $value) {
400 $rowParams = array(
401 1 => array($domainDao->id, 'Positive'),
402 2 => array($name, 'String'),
403 3 => array(serialize($value), 'String'),
404 );
405 $settingId = CRM_Core_DAO::singleValueQuery(
406 'SELECT id FROM civicrm_setting WHERE domain_id = %1 AND name = %2',
407 $rowParams);
408 if (!$settingId) {
409 CRM_Core_DAO::executeQuery(
410 'INSERT INTO civicrm_setting (domain_id, name, value, is_domain) VALUES (%1,%2,%3,1)',
411 $rowParams);
412 }
413 }
414 }
415
416 CRM_Core_DAO::executeQuery('ALTER TABLE civicrm_domain DROP COLUMN config_backend');
417
418 return TRUE;
419 }
420
421 /**
422 * Take a config_backend blob and produce an equivalent list of settings.
423 *
424 * @param int $domainId
425 * Domain ID.
426 * @param string $config_backend
427 * Serialized blob.
428 * @return array
429 */
430 public static function convertBackendToSettings($domainId, $config_backend) {
431 if (!$config_backend) {
432 return array();
433 }
434
435 $backend = unserialize($config_backend);
436 if (!$backend) {
437 return array();
438 }
439
440 $mappings = \CRM_Core_Config_MagicMerge::getPropertyMap();
441 $settings = array();
442 foreach ($backend as $propertyName => $propertyValue) {
443 if (isset($mappings[$propertyName][0]) && preg_match('/^setting/', $mappings[$propertyName][0])) {
444 // $mapping format: $propertyName => Array(0 => $type, 1 => $setting|NULL).
445 $settingName = isset($mappings[$propertyName][1]) ? $mappings[$propertyName][1] : $propertyName;
446 $settings[$settingName] = $propertyValue;
447 }
448 }
449
450 return $settings;
451 }
452
453 /**
454 * Add Getting Started dashlet to dashboard
455 *
456 * @param \CRM_Queue_TaskContext $ctx
457 *
458 * @return bool
459 */
460 public static function addGettingStartedDashlet(CRM_Queue_TaskContext $ctx) {
461 $sql = "SELECT count(*) FROM civicrm_dashboard WHERE name='getting-started'";
462 $res = CRM_Core_DAO::singleValueQuery($sql);
463 $domainId = CRM_Core_Config::domainID();
464 if ($res <= 0) {
465 $sql = "INSERT INTO `civicrm_dashboard`
466 ( `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)";
467 CRM_Core_DAO::executeQuery($sql);
468 // Add default position for Getting Started Dashlet ( left column)
469 $sql = "INSERT INTO `civicrm_dashboard_contact` (dashboard_id, contact_id, column_no, is_active)
470 SELECT (SELECT MAX(id) FROM `civicrm_dashboard`), contact_id, 0, IF (SUM(is_active) > 0, 1, 0)
471 FROM `civicrm_dashboard_contact` JOIN `civicrm_contact` WHERE civicrm_dashboard_contact.contact_id = civicrm_contact.id GROUP BY contact_id";
472 CRM_Core_DAO::executeQuery($sql);
473 }
474 return TRUE;
475 }
476
477 /**
478 * Migrate on-behalf information to uf_join.module_data as on-behalf columns will be dropped
479 * on DB upgrade
480 *
481 * @param CRM_Queue_TaskContext $ctx
482 *
483 * @return bool
484 * TRUE for success
485 */
486 public static function migrateOnBehalfOfInfo(CRM_Queue_TaskContext $ctx) {
487 $domain = new CRM_Core_DAO_Domain();
488 $domain->find(TRUE);
489
490 // fetch onBehalf entry in UFJoin table
491 $ufGroupDAO = new CRM_Core_DAO_UFJoin();
492 $ufGroupDAO->module = 'OnBehalf';
493 $ufGroupDAO->find(TRUE);
494
495 $forOrgColums = array('is_for_organization');
496 if ($domain->locales) {
497 $locales = explode(CRM_Core_DAO::VALUE_SEPARATOR, $domain->locales);
498 foreach ($locales as $locale) {
499 $forOrgColums[] = "for_organization_{$locale}";
500 }
501 }
502 else {
503 $forOrgColums[] = "for_organization";
504 }
505
506 $query = "
507 SELECT " . implode(", ", $forOrgColums) . ", uj.id as join_id, uj.uf_group_id as uf_group_id
508 FROM civicrm_contribution_page cp
509 INNER JOIN civicrm_uf_join uj ON uj.entity_id = cp.id AND uj.module = 'OnBehalf'";
510 $dao = CRM_Core_DAO::executeQuery($query, array(), TRUE, NULL, FALSE, FALSE);
511
512 if ($dao->N) {
513 while ($dao->fetch()) {
514 $onBehalfParams['on_behalf'] = array('is_for_organization' => $dao->is_for_organization);
515 if ($domain->locales) {
516 foreach ($locales as $locale) {
517 $for_organization = "for_organization_{$locale}";
518 $onBehalfParams['on_behalf'] += array(
519 $locale => array(
520 'for_organization' => $dao->$for_organization,
521 ),
522 );
523 }
524 }
525 else {
526 $onBehalfParams['on_behalf'] += array(
527 'default' => array(
528 'for_organization' => $dao->for_organization,
529 ),
530 );
531 }
532 $ufJoinParam = array(
533 'id' => $dao->join_id,
534 'module' => 'on_behalf',
535 'uf_group_id' => $dao->uf_group_id,
536 'module_data' => json_encode($onBehalfParams),
537 );
538 CRM_Core_BAO_UFJoin::create($ufJoinParam);
539 }
540 }
541
542 return TRUE;
543 }
544
545 /**
546 * v4.7.11 adds a new setting "remote_profile_submissions". This is
547 * long-standing feature that existing sites may be using; however, it's
548 * a bit prone to abuse. For new sites, the default is to disable it
549 * (since that is more secure). For existing sites, the default is to
550 * enable it (since that is more compatible).
551 *
552 * @param \CRM_Queue_TaskContext $ctx
553 *
554 * @return bool
555 */
556 public static function migrateRemoteSubmissionsSetting(CRM_Queue_TaskContext $ctx) {
557 $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");
558 while ($domains->fetch()) {
559 CRM_Core_DAO::executeQuery(
560 "INSERT INTO civicrm_setting (`name`, `value`, `domain_id`, `is_domain`, `contact_id`, `component_id`, `created_date`, `created_id`)
561 VALUES (%2, %3, %4, %5, NULL, NULL, %6, NULL)",
562 array(
563 2 => array('remote_profile_submissions', 'String'),
564 3 => array('s:1:"1";', 'String'),
565 4 => array($domains->id, 'Integer'),
566 5 => array(1, 'Integer'),
567 6 => array(date('Y-m-d H:i:s'), 'String'),
568 )
569 );
570 }
571 return TRUE;
572 }
573
574 /**
575 * CRM-11782 - Get rid of VALUE_SEPARATOR character in saved search form values
576 *
577 * @param \CRM_Queue_TaskContext $ctx
578 *
579 * @return bool
580 */
581 public static function fixContactTypeInSmartGroups(CRM_Queue_TaskContext $ctx) {
582 $sep = CRM_Core_DAO::VALUE_SEPARATOR;
583 $dao = CRM_Core_DAO::executeQuery("SELECT id, form_values FROM civicrm_saved_search WHERE form_values LIKE '%$sep%'");
584 while ($dao->fetch()) {
585 $formValues = unserialize($dao->form_values);
586 if (isset($formValues['contact_type']) && is_array($formValues['contact_type'])) {
587 $newVals = array();
588 foreach ($formValues['contact_type'] as $key => $val) {
589 $newVals[str_replace($sep, '__', $key)] = is_string($val) ? str_replace($sep, '__', $val) : $val;
590 }
591 $formValues['contact_type'] = $newVals;
592 }
593 CRM_Core_DAO::executeQuery("UPDATE civicrm_saved_search SET form_values = %1 WHERE id = {$dao->id}", array(1 => array(serialize($formValues), 'String')));
594 }
595
596 return TRUE;
597 }
598
599 /**
600 * CRM-17637 - Ths file location has been moved; delete the old one
601 *
602 * @param \CRM_Queue_TaskContext $ctx
603 *
604 * @return bool
605 */
606 public static function deleteVersionCheckCacheFile(CRM_Queue_TaskContext $ctx) {
607 $config = CRM_Core_Config::singleton();
608 $cacheFile = $config->uploadDir . 'version-info-cache.json';
609 if (file_exists($cacheFile)) {
610 unlink($cacheFile);
611 }
612 return TRUE;
613 }
614
615 /**
616 * CRM-17669 and CRM-17686, make scheduled jobs more flexible, disable the 4.6 extension if installed
617 *
618 * @param \CRM_Queue_TaskContext $ctx
619 *
620 * @return bool
621 */
622 public static function disableFlexibleJobsExtension(CRM_Queue_TaskContext $ctx) {
623 try {
624 civicrm_api3('Extension', 'disable', array('key' => 'com.klangsoft.flexiblejobs'));
625 }
626 catch (CiviCRM_API3_Exception $e) {
627 // just ignore if the extension isn't installed
628 }
629
630 return TRUE;
631 }
632
633 /**
634 * CRM-17752 add index to civicrm_financial_trxn.trxn_id (deliberately non-unique).
635 *
636 * @param \CRM_Queue_TaskContext $ctx
637 *
638 * @return bool
639 */
640 public static function addIndexFinancialTrxnTrxnID(CRM_Queue_TaskContext $ctx) {
641 $tables = array('civicrm_financial_trxn' => array('trxn_id'));
642 CRM_Core_BAO_SchemaHandler::createIndexes($tables);
643 return TRUE;
644 }
645
646 /**
647 * CRM-17882 Add index to civicrm_contribution.credit_note_id.
648 *
649 * @param \CRM_Queue_TaskContext $ctx
650 *
651 * @return bool
652 */
653 public static function addIndexContributionCreditNoteID(CRM_Queue_TaskContext $ctx) {
654 $tables = array('civicrm_contribution' => array('creditnote_id'));
655 CRM_Core_BAO_SchemaHandler::createIndexes($tables);
656 return TRUE;
657 }
658
659 /**
660 * CRM-17775 Add correct index for table civicrm_financial_item.
661 *
662 * Note that the entity ID should always precede the entity_table as
663 * it is more unique. This is better for performance and does not cause fallback
664 * to no index if table it omitted.
665 *
666 * @return bool
667 */
668 public static function addCombinedIndexFinancialItemEntityIDEntityType() {
669 CRM_Core_BAO_SchemaHandler::dropIndexIfExists('civicrm_financial_item', 'UI_id');
670 CRM_Core_BAO_SchemaHandler::dropIndexIfExists('civicrm_financial_item', 'IX_Entity');
671 CRM_Core_BAO_SchemaHandler::createIndexes(array(
672 'civicrm_financial_item' => array(array('entity_id', 'entity_table')),
673 ));
674 return TRUE;
675 }
676
677 /**
678 * CRM-17951 Add accounts option values for refund and chargeback.
679 *
680 * Add Chargeback contribution status and Chargeback and Contra account relationships,
681 * checking first if one exists.
682 */
683 public static function addRefundAndChargeBackAccountsIfNotExist() {
684 // First we enable and edit the record for Credit contra - this exists but is disabled for most sites.
685 // Using the ensure function (below) will not enabled a disabled option (by design).
686 CRM_Core_DAO::executeQuery("UPDATE civicrm_option_value v
687 INNER JOIN civicrm_option_group g on v.option_group_id=g.id and g.name='account_relationship'
688 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'
689 WHERE v.name = 'Credit/Contra Account is';");
690
691 CRM_Core_BAO_OptionValue::ensureOptionValueExists(array(
692 'option_group_id' => 'account_relationship',
693 'name' => 'Chargeback Account is',
694 'label' => ts('Chargeback Account is'),
695 'is_active' => TRUE,
696 'component_id' => 'CiviContribute',
697 ));
698
699 CRM_Core_BAO_OptionValue::ensureOptionValueExists(array(
700 'option_group_id' => 'contribution_status',
701 'name' => 'Chargeback',
702 'label' => ts('Chargeback'),
703 'is_active' => TRUE,
704 'component_id' => 'CiviContribute',
705 ));
706 return TRUE;
707 }
708
709 /**
710 * CRM-17999 Add index to civicrm_contribution.source.
711 *
712 * @param \CRM_Queue_TaskContext $ctx
713 *
714 * @return bool
715 */
716 public static function addIndexContributionSource(CRM_Queue_TaskContext $ctx) {
717 CRM_Core_BAO_SchemaHandler::createIndexes(array('civicrm_contribution' => array('source')));
718 return TRUE;
719 }
720
721 /**
722 * CRM-18124 Add index to civicrm_contribution.total_amount.
723 *
724 * Note that I made this a combined index with receive_date because the issue included
725 * both criteria and they seemed likely to be used in conjunction to me in other cases.
726 *
727 * @param \CRM_Queue_TaskContext $ctx
728 *
729 * @return bool
730 */
731 public static function addIndexContributionAmount(CRM_Queue_TaskContext $ctx) {
732 CRM_Core_BAO_SchemaHandler::createIndexes(array(
733 'civicrm_contribution' => array(array('total_amount', 'receive_date')),
734 ));
735 return TRUE;
736 }
737
738 /**
739 * CRM-18124 Add index to civicrm_contribution.total_amount.
740 *
741 * Note that I made this a combined index with receive_date because the issue included
742 * both criteria and they seemed likely to be used in conjunction to me in other cases.
743 *
744 * @param \CRM_Queue_TaskContext $ctx
745 *
746 * @return bool
747 */
748 public static function addDeletedByMergeActivityType(CRM_Queue_TaskContext $ctx) {
749 CRM_Core_BAO_OptionValue::ensureOptionValueExists(array(
750 'option_group_id' => 'activity_type',
751 'name' => 'Contact Deleted by Merge',
752 'label' => ts('Contact Deleted by Merge'),
753 'description' => ts('Contact was merged into another contact'),
754 'is_active' => TRUE,
755 'filter' => 1,
756 ));
757 return TRUE;
758 }
759
760 /**
761 * CRM-12252 Add Help Pre and Help Post Fields for Price Field Value Table.
762 *
763 * @param \CRM_Queue_TaskContext $ctx
764 *
765 * @return bool
766 */
767 public static function addHelpPreAndHelpPostFieldsPriceFieldValue(CRM_Queue_TaskContext $ctx) {
768 $domain = new CRM_Core_DAO_Domain();
769 $domain->find(TRUE);
770 if ($domain->locales) {
771 $locales = explode(CRM_Core_DAO::VALUE_SEPARATOR, $domain->locales);
772 foreach ($locales as $locale) {
773 if (!CRM_Core_BAO_SchemaHandler::checkIfFieldExists("civicrm_price_field_value", "help_pre_{$locale}")) {
774 CRM_Core_DAO::executeQuery("ALTER TABLE `civicrm_price_field_value`
775 ADD COLUMN `help_pre_{$locale}` text COLLATE utf8_unicode_ci COMMENT 'Price field option pre help text.'", array(), TRUE, NULL, FALSE, FALSE);
776 }
777 if (!CRM_Core_BAO_SchemaHandler::checkIfFieldExists("civicrm_price_field_value", "help_post_{$locale}")) {
778 CRM_Core_DAO::executeQuery("ALTER TABLE `civicrm_price_field_value`
779 ADD COLUMN `help_post_{$locale}` text COLLATE utf8_unicode_ci COMMENT 'Price field option post help text.'", array(), TRUE, NULL, FALSE, FALSE);
780 }
781 }
782 CRM_Core_I18n_Schema::rebuildMultilingualSchema($locales, NULL);
783 }
784 else {
785 if (!CRM_Core_BAO_SchemaHandler::checkIfFieldExists('civicrm_price_field_value', 'help_pre')) {
786 CRM_Core_DAO::executeQuery("ALTER TABLE `civicrm_price_field_value`
787 ADD COLUMN `help_pre` text COLLATE utf8_unicode_ci COMMENT 'Price field option pre help text.'");
788 }
789 if (!CRM_Core_BAO_SchemaHandler::checkIfFieldExists('civicrm_price_field_value', 'help_post')) {
790 CRM_Core_DAO::executeQuery("ALTER TABLE `civicrm_price_field_value`
791 ADD COLUMN `help_post` text COLLATE utf8_unicode_ci COMMENT 'Price field option post help text.'");
792 }
793 }
794 return TRUE;
795 }
796
797 /**
798 * CRM-18464 Check if Foreign key exists and also drop any index of same name accidentially created.
799 *
800 * @param \CRM_Queue_TaskContext $ctx
801 *
802 * @return bool
803 */
804 public static function dropActionScheudleMappingForeignKey(CRM_Queue_TaskContext $ctx) {
805 CRM_Core_BAO_SchemaHandler::safeRemoveFK('civicrm_action_schedule', 'FK_civicrm_action_schedule_mapping_id');
806 return TRUE;
807 }
808
809 /**
810 * CRM-18345 Don't delete mailing data on email/phone deletion
811 * Implemented here in CRM-18526
812 *
813 * @param \CRM_Queue_TaskContext $ctx
814 *
815 * @return bool
816 */
817 public static function upgradeMailingFKs(CRM_Queue_TaskContext $ctx) {
818
819 // Safely drop the foreign keys
820 CRM_Core_BAO_SchemaHandler::safeRemoveFK('civicrm_mailing_event_queue', 'FK_civicrm_mailing_event_queue_email_id');
821 CRM_Core_BAO_SchemaHandler::safeRemoveFK('civicrm_mailing_event_queue', 'FK_civicrm_mailing_event_queue_phone_id');
822 CRM_Core_BAO_SchemaHandler::safeRemoveFK('civicrm_mailing_recipients', 'FK_civicrm_mailing_recipients_email_id');
823 CRM_Core_BAO_SchemaHandler::safeRemoveFK('civicrm_mailing_recipients', 'FK_civicrm_mailing_recipients_phone_id');
824
825 // Set up the new foreign keys
826 CRM_Core_DAO::executeQuery("SET FOREIGN_KEY_CHECKS = 0;");
827
828 CRM_Core_DAO::executeQuery("
829 ALTER TABLE `civicrm_mailing_event_queue`
830 ADD CONSTRAINT `FK_civicrm_mailing_event_queue_email_id`
831 FOREIGN KEY (`email_id`)
832 REFERENCES `civicrm_email`(`id`)
833 ON DELETE SET NULL
834 ON UPDATE RESTRICT;
835 ");
836
837 CRM_Core_DAO::executeQuery("
838 ALTER TABLE `civicrm_mailing_event_queue`
839 ADD CONSTRAINT `FK_civicrm_mailing_event_queue_phone_id`
840 FOREIGN KEY (`phone_id`)
841 REFERENCES `civicrm_phone`(`id`)
842 ON DELETE SET NULL
843 ON UPDATE RESTRICT;
844 ");
845
846 CRM_Core_DAO::executeQuery("
847 ALTER TABLE `civicrm_mailing_recipients`
848 ADD CONSTRAINT `FK_civicrm_mailing_recipients_email_id`
849 FOREIGN KEY (`email_id`)
850 REFERENCES `civicrm_email`(`id`)
851 ON DELETE SET NULL
852 ON UPDATE RESTRICT;
853 ");
854
855 CRM_Core_DAO::executeQuery("
856 ALTER TABLE `civicrm_mailing_recipients`
857 ADD CONSTRAINT `FK_civicrm_mailing_recipients_phone_id`
858 FOREIGN KEY (`phone_id`)
859 REFERENCES `civicrm_phone`(`id`)
860 ON DELETE SET NULL
861 ON UPDATE RESTRICT;
862 ");
863
864 CRM_Core_DAO::executeQuery("SET FOREIGN_KEY_CHECKS = 1;");
865
866 return TRUE;
867 }
868
869 /**
870 * CRM-17663 - Dashboard schema changes
871 *
872 * @param \CRM_Queue_TaskContext $ctx
873 *
874 * @return bool
875 */
876 public static function dashboardSchemaUpdate(CRM_Queue_TaskContext $ctx) {
877 if (!CRM_Core_BAO_SchemaHandler::checkIfIndexExists('civicrm_dashboard_contact', 'index_dashboard_id_contact_id')) {
878 // Delete any stray duplicate rows and add unique index to prevent new dupes and enable INSERT/UPDATE combo query
879 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');
880 CRM_Core_DAO::executeQuery('ALTER TABLE civicrm_dashboard_contact ADD UNIQUE INDEX index_dashboard_id_contact_id (dashboard_id, contact_id);');
881 }
882 $domain = new CRM_Core_DAO_Domain();
883 $domain->find(TRUE);
884 CRM_Core_BAO_SchemaHandler::dropColumn('civicrm_dashboard_contact', 'content');
885 CRM_Core_BAO_SchemaHandler::dropColumn('civicrm_dashboard_contact', 'is_minimized');
886 CRM_Core_BAO_SchemaHandler::dropColumn('civicrm_dashboard_contact', 'is_fullscreen');
887 CRM_Core_BAO_SchemaHandler::dropColumn('civicrm_dashboard_contact', 'created_date');
888 CRM_Core_BAO_SchemaHandler::dropColumn('civicrm_dashboard', 'is_fullscreen');
889 CRM_Core_BAO_SchemaHandler::dropColumn('civicrm_dashboard', 'is_minimized');
890 CRM_Core_BAO_SchemaHandler::dropColumn('civicrm_dashboard', 'column_no');
891 CRM_Core_BAO_SchemaHandler::dropColumn('civicrm_dashboard', 'weight');
892
893 CRM_Core_DAO::executeQuery('UPDATE civicrm_dashboard SET url = REPLACE(url, "&snippet=5", ""), fullscreen_url = REPLACE(fullscreen_url, "&snippet=5", "")');
894
895 if (!CRM_Core_BAO_SchemaHandler::checkIfFieldExists('civicrm_dashboard', 'cache_minutes')) {
896 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."',
897 array(), TRUE, NULL, FALSE, FALSE);
898 }
899 if ($domain->locales) {
900 $locales = explode(CRM_Core_DAO::VALUE_SEPARATOR, $domain->locales);
901 CRM_Core_I18n_Schema::rebuildMultilingualSchema($locales, NULL);
902 }
903
904 CRM_Core_DAO::executeQuery('UPDATE civicrm_dashboard SET cache_minutes = 1440 WHERE name = "blog"');
905 CRM_Core_DAO::executeQuery('UPDATE civicrm_dashboard SET cache_minutes = 7200 WHERE name IN ("activity","getting-started")');
906 return TRUE;
907 }
908
909 /**
910 * CRM-19100 - Alter Index and Type for Image URL
911 * @return bool
912 */
913 public static function alterIndexAndTypeForImageURL() {
914 $length = array();
915 CRM_Core_BAO_SchemaHandler::dropIndexIfExists('civicrm_contact', 'index_image_url');
916 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.'");
917
918 $length['civicrm_contact']['image_URL'] = 128;
919 CRM_Core_BAO_SchemaHandler::createIndexes(array('civicrm_contact' => array('image_URL')), 'index', $length);
920
921 return TRUE;
922 }
923
924 /**
925 * Add mailing template type.
926 *
927 * @return bool
928 */
929 public static function addMailingTemplateType() {
930 if (!CRM_Core_DAO::checkFieldExists('civicrm_mailing', 'template_type', FALSE)) {
931 CRM_Core_DAO::executeQuery('
932 ALTER TABLE civicrm_mailing
933 ADD COLUMN `template_type` varchar(64) NOT NULL DEFAULT \'traditional\' COMMENT \'The language/processing system used for email templates.\',
934 ADD COLUMN `template_options` longtext COMMENT \'Advanced options used by the email templating system. (JSON encoded)\'
935 ');
936 }
937 return TRUE;
938 }
939
940 /**
941 * CRM-18651 Add DataType column to Option Group Table
942 * @return bool
943 */
944 public static function addDataTypeColumnToOptionGroupTable() {
945 if (!CRM_Core_BAO_SchemaHandler::checkIfFieldExists('civicrm_option_group', 'data_type')) {
946 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.'",
947 array(), TRUE, NULL, FALSE, FALSE);
948 }
949 $domain = new CRM_Core_DAO_Domain();
950 $domain->find(TRUE);
951 if ($domain->locales) {
952 $locales = explode(CRM_Core_DAO::VALUE_SEPARATOR, $domain->locales);
953 CRM_Core_I18n_Schema::rebuildMultilingualSchema($locales, NULL);
954 }
955
956 CRM_Core_DAO::executeQuery("UPDATE `civicrm_option_group` SET `data_type` = 'Integer'
957 WHERE name IN ('activity_type', 'gender', 'payment_instrument', 'participant_role', 'event_type')");
958 return TRUE;
959 }
960
961 /**
962 * CRM-19372 Add field to store accepted credit credit cards for a payment processor.
963 * @return bool
964 */
965 public static function addWysiwygPresets() {
966 CRM_Core_BAO_OptionGroup::ensureOptionGroupExists(array(
967 'name' => 'wysiwyg_presets',
968 'title' => ts('WYSIWYG Editor Presets'),
969 'is_reserved' => 1,
970 ));
971 $values = array(
972 'default' => array('label' => ts('Default'), 'is_default' => 1),
973 'civimail' => array('label' => ts('CiviMail'), 'component_id' => 'CiviMail'),
974 'civievent' => array('label' => ts('CiviEvent'), 'component_id' => 'CiviEvent'),
975 );
976 foreach ($values as $name => $value) {
977 CRM_Core_BAO_OptionValue::ensureOptionValueExists($value + array(
978 'name' => $name,
979 'option_group_id' => 'wysiwyg_presets',
980 ));
981 }
982 $fileName = Civi::paths()->getPath('[civicrm.files]/persist/crm-ckeditor-config.js');
983 // Ensure the config file contains the allowedContent setting
984 if (file_exists($fileName)) {
985 $config = file_get_contents($fileName);
986 $pos = strrpos($config, '};');
987 $setting = "\n\tconfig.allowedContent = true;\n";
988 $config = substr_replace($config, $setting, $pos, 0);
989 unlink($fileName);
990 $newFileName = Civi::paths()->getPath('[civicrm.files]/persist/crm-ckeditor-default.js');
991 file_put_contents($newFileName, $config);
992 }
993 return TRUE;
994 }
995
996 /**
997 * Update Kenyan Provinces to reflect changes per CRM-20062
998 *
999 * @param \CRM_Queue_TaskContext $ctx
1000 */
1001 public function updateKenyanProvinces(CRM_Queue_TaskContext $ctx) {
1002 $kenyaCountryID = CRM_Core_DAO::singleValueQuery('SELECT max(id) from civicrm_country where iso_code = "KE"');
1003 $oldProvinces = array(
1004 'Nairobi Municipality',
1005 'Coast',
1006 'North-Eastern Kaskazini Mashariki',
1007 'Rift Valley',
1008 'Western Magharibi',
1009 );
1010 self::deprecateStateProvinces($kenyaCountryID, $oldProvinces);
1011 return TRUE;
1012 }
1013
1014 /**
1015 * Deprecate provinces that no longer exist.
1016 *
1017 * @param int $countryID
1018 * @param array $provinces
1019 */
1020 public static function deprecateStateProvinces($countryID, $provinces) {
1021 foreach ($provinces as $province) {
1022 $existingStateID = CRM_Core_DAO::singleValueQuery("
1023 SELECT id FROM civicrm_state_province
1024 WHERE country_id = %1
1025 AND name = %2
1026 ",
1027 array(1 => array($countryID, 'Int'), 2 => array($province, 'String')));
1028
1029 if (!$existingStateID) {
1030 continue;
1031 }
1032 if (!CRM_Core_DAO::singleValueQuery("
1033 SELECT count(*) FROM civicrm_address
1034 WHERE state_province_id = %1
1035 ", array(1 => array($existingStateID, 'Int')))
1036 ) {
1037 CRM_Core_DAO::executeQuery("DELETE FROM civicrm_state_province WHERE id = %1", array(1 => array($existingStateID, 'Int')));
1038 }
1039 else {
1040 $params = array('1' => array(ts("Former - $province"), 'String'));
1041 CRM_Core_DAO::executeQuery("
1042 UPDATE civicrm_state_province SET name = %1 WHERE id = $existingStateID
1043 ", $params);
1044 }
1045 }
1046 }
1047
1048 }