remove never-used option value
[civicrm-core.git] / CRM / Upgrade / Incremental / php / FourFive.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
5 | |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
10 */
11
12 /**
13 * Upgrade logic for 4.5
14 */
15 class CRM_Upgrade_Incremental_php_FourFive extends CRM_Upgrade_Incremental_Base {
16
17 /**
18 * Compute any messages which should be displayed after upgrade.
19 *
20 * @param string $postUpgradeMessage
21 * alterable.
22 * @param string $rev
23 * an intermediate version; note that setPostUpgradeMessage is called repeatedly with different $revs.
24 */
25 public function setPostUpgradeMessage(&$postUpgradeMessage, $rev) {
26 if ($rev == '4.5.alpha1') {
27 $postUpgradeMessage .= '<br /><br />' . ts('Default versions of the following System Workflow Message Templates have been modified to handle new functionality: <ul><li>Contributions - Receipt (off-line)</li><li>Contributions - Receipt (on-line)</li><li>Contributions - Recurring Start and End Notification</li><li>Contributions - Recurring Updates</li><li>Memberships - Receipt (on-line)</li><li>Memberships - Signup and Renewal Receipts (off-line)</li><li>Pledges - Acknowledgement</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). (<a href="%1">learn more...</a>)', [1 => 'http://wiki.civicrm.org/confluence/display/CRMDOC/Updating+System+Workflow+Message+Templates+after+Upgrades+-+method+1+-+kdiff']);
28 $postUpgradeMessage .= '<br /><br />' . ts('This release allows you to view and edit multiple-record custom field sets in a table format which will be more usable in some cases. You can try out the format by navigating to Administer > Custom Data & Screens > Custom Fields. Click Settings for a custom field set and change Display Style to "Tab with Tables".');
29 $postUpgradeMessage .= '<br /><br />' . ts('This release changes the way that anonymous event registrations match participants with existing contacts. By default, all event participants will be matched with existing individuals using the Unsupervised rule, even if multiple registrations with the same email address are allowed. However, you can now select a different matching rule to use for each event. Please review your events to make sure you choose the appropriate matching rule and collect sufficient information for it to match contacts.');
30 }
31 if ($rev == '4.5.beta2') {
32 $postUpgradeMessage .= '<br /><br />' . ts('If you use CiviMail for newsletters or other communications, check out the new sample CiviMail templates which use responsive design to optimize display on mobile devices (Administer > Communications > Message Templates ).');
33 }
34 if ($rev == '4.5.1') {
35 $postUpgradeMessage .= '<br /><br />' . ts('WARNING: If you use CiviCase with v4.5.alpha*, v4.5.beta*, or v4.5.0, it is possible that previous upgrades corrupted some CiviCase metadata. If you have not already done so, please identify any custom field sets, smart groups, or reports which refer to CiviCase and ensure that they are properly configured.');
36 }
37 }
38
39 /**
40 * @param $rev
41 *
42 * @return bool
43 */
44 public function upgrade_4_5_alpha1($rev) {
45 // task to process sql
46 $this->addTask('Migrate honoree information to module_data', 'migrateHonoreeInfo');
47 $this->addTask(ts('Upgrade DB to %1: SQL', [1 => '4.5.alpha1']), 'runSql', $rev);
48 $this->addTask('Set default for Individual name fields configuration', 'addNameFieldOptions');
49
50 // CRM-14522 - The below schema checking is done as foreign key name
51 // for pdf_format_id column varies for different databases
52 // if DB is been into upgrade for 3.4.2 version, it would have pdf_format_id name for FK
53 // else FK_civicrm_msg_template_pdf_format_id
54 $config = CRM_Core_Config::singleton();
55 $dsn = CRM_Utils_SQL::autoSwitchDSN($config->dsn);
56 $dbUf = DB::parseDSN($dsn);
57 $query = "
58 SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
59 WHERE TABLE_NAME = 'civicrm_msg_template'
60 AND CONSTRAINT_TYPE = 'FOREIGN KEY'
61 AND TABLE_SCHEMA = %1
62 ";
63 $params = [1 => [$dbUf['database'], 'String']];
64 $dao = CRM_Core_DAO::executeQuery($query, $params, TRUE, NULL, FALSE, FALSE);
65 if ($dao->fetch()) {
66 if ($dao->CONSTRAINT_NAME == 'FK_civicrm_msg_template_pdf_format_id' ||
67 $dao->CONSTRAINT_NAME == 'pdf_format_id'
68 ) {
69 $sqlDropFK = "ALTER TABLE `civicrm_msg_template`
70 DROP FOREIGN KEY `{$dao->CONSTRAINT_NAME}`,
71 DROP KEY `{$dao->CONSTRAINT_NAME}`";
72 CRM_Core_DAO::executeQuery($sqlDropFK, [], TRUE, NULL, FALSE, FALSE);
73 }
74 }
75
76 return TRUE;
77 }
78
79 /**
80 * @param $rev
81 *
82 * @return bool
83 */
84 public function upgrade_4_5_beta9($rev) {
85 $this->addTask(ts('Upgrade DB to %1: SQL', [1 => '4.5.beta9']), 'runSql', $rev);
86
87 $entityTable = [
88 'Participant' => 'civicrm_participant_payment',
89 'Contribution' => 'civicrm_contribution',
90 'Membership' => 'civicrm_membership',
91 ];
92
93 foreach ($entityTable as $label => $tableName) {
94 list($minId, $maxId) = CRM_Core_DAO::executeQuery("SELECT coalesce(min(id),0), coalesce(max(id),0)
95 FROM {$tableName}")->getDatabaseResult()->fetchRow();
96 for ($startId = $minId; $startId <= $maxId; $startId += self::BATCH_SIZE) {
97 $endId = $startId + self::BATCH_SIZE - 1;
98 $title = ts("Upgrade DB to 4.5.beta9: Fix line items for {$label} (%1 => %2)", [
99 1 => $startId,
100 2 => $endId,
101 ]);
102 $this->addTask($title, 'task_4_5_0_fixLineItem', $startId, $endId, $label);
103 }
104 }
105 return TRUE;
106 }
107
108 /**
109 * (Queue Task Callback)
110 *
111 * update the line items
112 *
113 *
114 * @param CRM_Queue_TaskContext $ctx
115 * @param int $startId
116 * the first/lowest entity ID to convert.
117 * @param int $endId
118 * the last/highest entity ID to convert.
119 * @param string $entityTable
120 *
121 * @return bool
122 */
123 public static function task_4_5_0_fixLineItem(CRM_Queue_TaskContext $ctx, $startId, $endId, $entityTable) {
124
125 $sqlParams = [
126 1 => [$startId, 'Integer'],
127 2 => [$endId, 'Integer'],
128 ];
129 switch ($entityTable) {
130 case 'Contribution':
131 // update all the line item entity_table and entity_id with contribution due to bug CRM-15055
132 CRM_Core_DAO::executeQuery("UPDATE civicrm_line_item li
133 INNER JOIN civicrm_contribution cc ON cc.id = li.contribution_id
134 SET entity_id = li.contribution_id, entity_table = 'civicrm_contribution'
135 WHERE li.contribution_id IS NOT NULL AND li.entity_table <> 'civicrm_participant' AND (cc.id BETWEEN %1 AND %2)", $sqlParams);
136
137 // update the civicrm_line_item.contribution_id
138 CRM_Core_DAO::executeQuery("UPDATE civicrm_line_item li
139 INNER JOIN civicrm_contribution cc ON cc.id = li.entity_id
140 SET contribution_id = entity_id
141 WHERE li.contribution_id IS NULL AND li.entity_table = 'civicrm_contribution' AND (cc.id BETWEEN %1 AND %2)", $sqlParams);
142 break;
143
144 case 'Participant':
145 // update the civicrm_line_item.contribution_id
146 CRM_Core_DAO::executeQuery("UPDATE civicrm_line_item li
147 INNER JOIN civicrm_participant_payment pp ON pp.participant_id = li.entity_id
148 SET li.contribution_id = pp.contribution_id
149 WHERE li.entity_table = 'civicrm_participant' AND li.contribution_id IS NULL AND (pp.id BETWEEN %1 AND %2)", $sqlParams);
150 break;
151
152 case 'Membership':
153 $upgrade = new CRM_Upgrade_Form();
154 // update the line item of membership
155 CRM_Core_DAO::executeQuery("UPDATE civicrm_line_item li
156 INNER JOIN civicrm_membership_payment mp ON mp.contribution_id = li.contribution_id
157 INNER JOIN civicrm_membership cm ON mp.membership_id = cm.id
158 INNER JOIN civicrm_price_field_value pv ON pv.id = li.price_field_value_id
159 SET li.entity_table = 'civicrm_membership', li.entity_id = mp.membership_id
160 WHERE li.entity_table = 'civicrm_contribution'
161 AND pv.membership_type_id IS NOT NULL AND cm.membership_type_id = pv.membership_type_id AND (cm.id BETWEEN %1 AND %2)", $sqlParams);
162
163 CRM_Core_DAO::executeQuery("UPDATE civicrm_line_item li
164 INNER JOIN civicrm_membership_payment mp ON mp.contribution_id = li.contribution_id
165 INNER JOIN civicrm_price_field_value pv ON pv.id = li.price_field_value_id
166 SET li.entity_table = 'civicrm_membership', li.entity_id = mp.membership_id
167 WHERE li.entity_table = 'civicrm_contribution'
168 AND pv.membership_type_id IS NOT NULL AND (mp.membership_id BETWEEN %1 AND %2)", $sqlParams);
169
170 CRM_Core_DAO::executeQuery("INSERT INTO civicrm_line_item (entity_table, entity_id, price_field_id, label,
171 qty, unit_price, line_total, price_field_value_id, financial_type_id)
172 SELECT 'civicrm_membership', cm.id, cpf.id price_field_id, cpfv.label, 1 as qty, cpfv.amount, cpfv.amount line_total,
173 cpfv.id price_field_value_id, cpfv.financial_type_id FROM civicrm_membership cm
174 LEFT JOIN civicrm_membership_payment cmp ON cmp.membership_id = cm.id
175 INNER JOIN civicrm_price_field_value cpfv ON cpfv.membership_type_id = cm.membership_type_id
176 INNER JOIN civicrm_price_field cpf ON cpf.id = cpfv.price_field_id
177 INNER JOIN civicrm_price_set cps ON cps.id = cpf.price_set_id
178 WHERE cmp.contribution_id IS NULL AND cps.name = 'default_membership_type_amount' AND (cm.id BETWEEN %1 AND %2)", $sqlParams);
179 break;
180 }
181 return TRUE;
182 }
183
184 /**
185 * Add defaults for the newly introduced name fields configuration in 'contact_edit_options' setting
186 *
187 * @param CRM_Queue_TaskContext $ctx
188 *
189 * @return bool
190 * TRUE for success
191 */
192 public static function addNameFieldOptions(CRM_Queue_TaskContext $ctx) {
193 $query = "SELECT `value` FROM `civicrm_setting` WHERE `group_name` = 'CiviCRM Preferences' AND `name` = 'contact_edit_options'";
194 $dao = CRM_Core_DAO::executeQuery($query);
195 $dao->fetch();
196 $oldValue = unserialize($dao->value);
197
198 $newValue = $oldValue . '12\ 114\ 115\ 116\ 117\ 1';
199
200 $query = "UPDATE `civicrm_setting` SET `value` = %1 WHERE `group_name` = 'CiviCRM Preferences' AND `name` = 'contact_edit_options'";
201 $params = [1 => [serialize($newValue), 'String']];
202 CRM_Core_DAO::executeQuery($query, $params);
203
204 return TRUE;
205 }
206
207 /**
208 * Migrate honoree information to uf_join.module_data as honoree columns (text and title) will be dropped
209 * on DB upgrade
210 *
211 * @param CRM_Queue_TaskContext $ctx
212 *
213 * @return bool
214 * TRUE for success
215 */
216 public static function migrateHonoreeInfo(CRM_Queue_TaskContext $ctx) {
217 $query = "ALTER TABLE `civicrm_uf_join`
218 ADD COLUMN `module_data` longtext COMMENT 'Json serialized array of data used by the ufjoin.module'";
219 CRM_Core_DAO::executeQuery($query);
220
221 $honorTypes = array_keys(CRM_Core_OptionGroup::values('honor_type'));
222 $ufGroupDAO = new CRM_Core_DAO_UFGroup();
223 $ufGroupDAO->name = 'new_individual';
224 $ufGroupDAO->find(TRUE);
225
226 $query = "SELECT * FROM civicrm_contribution_page";
227 $dao = CRM_Core_DAO::executeQuery($query);
228
229 if ($dao->N) {
230 $domain = new CRM_Core_DAO_Domain();
231 $domain->find(TRUE);
232 while ($dao->fetch()) {
233 $honorParams = ['soft_credit' => ['soft_credit_types' => $honorTypes]];
234 if ($domain->locales) {
235 $locales = explode(CRM_Core_DAO::VALUE_SEPARATOR, $domain->locales);
236 foreach ($locales as $locale) {
237 $honor_block_title = "honor_block_title_{$locale}";
238 $honor_block_text = "honor_block_text_{$locale}";
239 $honorParams['soft_credit'] += [
240 $locale => [
241 'honor_block_title' => $dao->$honor_block_title,
242 'honor_block_text' => $dao->$honor_block_text,
243 ],
244 ];
245 }
246 }
247 else {
248 $honorParams['soft_credit'] += [
249 'default' => [
250 'honor_block_title' => $dao->honor_block_title,
251 'honor_block_text' => $dao->honor_block_text,
252 ],
253 ];
254 }
255 $ufJoinParam = [
256 'module' => 'soft_credit',
257 'entity_table' => 'civicrm_contribution_page',
258 'is_active' => $dao->honor_block_is_active,
259 'entity_id' => $dao->id,
260 'uf_group_id' => $ufGroupDAO->id,
261 'module_data' => json_encode($honorParams),
262 ];
263 CRM_Core_BAO_UFJoin::create($ufJoinParam);
264 }
265 }
266
267 return TRUE;
268 }
269
270 /**
271 * Upgrade function.
272 *
273 * @param string $rev
274 * @return bool
275 */
276 public function upgrade_4_5_9($rev) {
277 // Task to process sql.
278 $this->addTask('Upgrade DB to 4.5.9: Fix saved searches consisting of multi-choice custom field(s)', 'updateSavedSearch');
279
280 return TRUE;
281 }
282
283 /**
284 * Update saved search for multi-select custom fields on DB upgrade
285 *
286 * @param CRM_Queue_TaskContext $ctx
287 *
288 * @return bool TRUE for success
289 */
290 public static function updateSavedSearch(CRM_Queue_TaskContext $ctx) {
291 $sql = "SELECT id, form_values FROM civicrm_saved_search";
292 $dao = CRM_Core_DAO::executeQuery($sql);
293 while ($dao->fetch()) {
294 $copy = $formValues = unserialize($dao->form_values);
295 $update = FALSE;
296 foreach ($copy as $field => $data_value) {
297 if (preg_match('/^custom_/', $field) && is_array($data_value) && !array_key_exists("${field}_operator", $formValues)) {
298 // Now check for CiviCRM_OP_OR as either key or value in the data_value array.
299 // This is the conclusive evidence of an old-style data format.
300 if (array_key_exists('CiviCRM_OP_OR', $data_value) || FALSE !== array_search('CiviCRM_OP_OR', $data_value)) {
301 // We have old style data. Mark this record to be updated.
302 $update = TRUE;
303 $op = 'and';
304 if (!preg_match('/^custom_([0-9]+)/', $field, $matches)) {
305 // fatal error?
306 continue;
307 }
308 $fieldID = $matches[1];
309 if (array_key_exists('CiviCRM_OP_OR', $data_value)) {
310 // This indicates data structure identified by jamie in the form:
311 // value1 => 1, value2 => , value3 => 1.
312 $data_value = array_keys($data_value, 1);
313
314 // If CiviCRM_OP_OR - change OP from default to OR
315 if ($data_value['CiviCRM_OP_OR'] == 1) {
316 $op = 'or';
317 }
318 unset($data_value['CiviCRM_OP_OR']);
319 }
320 else {
321 // The value is here, but it is not set as a key.
322 // This is using the style identified by Monish - the existence of the value
323 // indicates an OR search and values are set in the form of:
324 // 0 => value1, 1 => value1, 3 => value2.
325 $key = array_search('CiviCRM_OP_OR', $data_value);
326 $op = 'or';
327 unset($data_value[$key]);
328 }
329
330 //If only Or operator has been chosen, means we need to select all values and
331 //so to execute OR operation between these values according to new data structure
332 if (count($data_value) == 0 && $op == 'or') {
333 $customOption = CRM_Core_BAO_CustomOption::getCustomOption($fieldID);
334 foreach ($customOption as $option) {
335 $data_value[] = $option['value'] ?? NULL;
336 }
337 }
338
339 $formValues[$field] = $data_value;
340 $formValues["${field}_operator"] = $op;
341 }
342 }
343 }
344
345 if ($update) {
346 $sql = "UPDATE civicrm_saved_search SET form_values = %0 WHERE id = %1";
347 CRM_Core_DAO::executeQuery($sql,
348 [
349 [serialize($formValues), 'String'],
350 [$dao->id, 'Integer'],
351 ]
352 );
353 }
354 }
355 return TRUE;
356 }
357
358 }