INFRA-132 - @param type fixes
[civicrm-core.git] / CRM / Upgrade / Incremental / php / FourTwo.php
CommitLineData
6a488035
TO
1<?php
2
3/*
4 +--------------------------------------------------------------------+
39de6fd5 5 | CiviCRM version 4.6 |
6a488035 6 +--------------------------------------------------------------------+
06b69b18 7 | Copyright CiviCRM LLC (c) 2004-2014 |
6a488035
TO
8 +--------------------------------------------------------------------+
9 | This file is a part of CiviCRM. |
10 | |
11 | CiviCRM is free software; you can copy, modify, and distribute it |
12 | under the terms of the GNU Affero General Public License |
13 | Version 3, 19 November 2007. |
14 | |
15 | CiviCRM is distributed in the hope that it will be useful, but |
16 | WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
18 | See the GNU Affero General Public License for more details. |
19 | |
20 | You should have received a copy of the GNU Affero General Public |
21 | License along with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26*/
27
28/**
29 *
30 * @package CRM
06b69b18 31 * @copyright CiviCRM LLC (c) 2004-2014
6a488035
TO
32 * $Id$
33 *
34 */
35class CRM_Upgrade_Incremental_php_FourTwo {
36 const BATCH_SIZE = 5000;
37 const SETTINGS_SNIPPET_PATTERN = '/CRM_Core_ClassLoader::singleton\(\)-\>register/';
38 const SETTINGS_SNIPPET = "\nrequire_once 'CRM/Core/ClassLoader.php';\nCRM_Core_ClassLoader::singleton()->register();\n";
39
624e56fa
EM
40 /**
41 * @param $errors
42 *
43 * @return bool
44 */
00be9182 45 public function verifyPreDBstate(&$errors) {
6a488035
TO
46 return TRUE;
47 }
48
49 /**
50 * Compute any messages which should be displayed beforeupgrade
51 *
52 * Note: This function is called iteratively for each upcoming
53 * revision to the database.
54 *
77b97be7 55 * @param $preUpgradeMessage
5a4f6742
CW
56 * @param string $rev
57 * a version number, e.g. '4.2.alpha1', '4.2.beta3', '4.2.0'.
77b97be7
EM
58 * @param null $currentVer
59 *
6a488035
TO
60 * @return void
61 */
00be9182 62 public function setPreUpgradeMessage(&$preUpgradeMessage, $rev, $currentVer = NULL) {
6a488035 63 if ($rev == '4.2.alpha1') {
e418776c 64 $tables = array('civicrm_contribution_page', 'civicrm_event', 'civicrm_group', 'civicrm_contact');
9b873358 65 if (!CRM_Core_DAO::schemaRequiresRebuilding($tables)) {
10a5be27 66 $errors = ts("The upgrade has identified some schema integrity issues in the database. It seems some of your constraints are missing. You will have to rebuild your schema before re-trying the upgrade. Please refer to %1.", array(1 => CRM_Utils_System::docURL2("Ensuring Schema Integrity on Upgrades", FALSE, "Ensuring Schema Integrity on Upgrades", NULL, NULL, "wiki")));
6a488035
TO
67 CRM_Core_Error::fatal($errors);
68 return FALSE;
69 }
70
71 // CRM-10613, CRM-11120
72 $query = "
73SELECT mp.contribution_id, mp.membership_id, mem.membership_type_id, mem.start_date, mem.end_date, mem.status_id, mem.contact_id
74FROM civicrm_membership_payment mp
75INNER JOIN ( SELECT cmp.contribution_id
76 FROM civicrm_membership_payment cmp
77 LEFT JOIN civicrm_line_item cli ON cmp.contribution_id=cli.entity_id and cli.entity_table = 'civicrm_contribution'
78 WHERE cli.entity_id IS NULL
79 GROUP BY cmp.contribution_id
80 HAVING COUNT(cmp.membership_id) > 1) submp ON submp.contribution_id = mp.contribution_id
81INNER JOIN civicrm_membership mem ON mem.id = mp.membership_id
82ORDER BY mp.contribution_id, mp.membership_id";
83 $invalidData = CRM_Core_DAO::executeQuery($query);
84 if ($invalidData->N) {
85 $invalidDataMessage = "<br /><strong>" . ts('The upgrade is being aborted due to data integrity issues in your database. There are multiple membership records linked to the same contribution record. This is unexpected, and some of the membership records may be duplicates. The problem record sets are listed below. Refer to <a href="%1">this wiki page for instructions on repairing your database</a> so that you can run the upgrade successfully.
481a74f4 86 ', array(1 => 'http://wiki.civicrm.org/confluence/display/CRMDOC42/Repair+database+script+for+4.2+upgrades')) . "</strong>";
6a488035
TO
87 $membershipType = CRM_Member_PseudoConstant::membershipType();
88 $membershipStatus = CRM_Member_PseudoConstant::membershipStatus();
89 $invalidDataMessage .= "<table border=1><tr><th>Contact-ID</th><th>Contribution-ID</th><th>Membership-ID</th><th>Membership Type</th><th>Start Date</th><th>End Date</th><th>Membership Status</th></tr>";
90 while ($invalidData->fetch()) {
91 $invalidDataMessage .= "<tr>";
92 $invalidDataMessage .= "<td>{$invalidData->contact_id}</td>";
93 $invalidDataMessage .= "<td>{$invalidData->contribution_id}</td>";
94 $invalidDataMessage .= "<td>{$invalidData->membership_id}</td>";
95 $invalidDataMessage .= "<td>" . CRM_Utils_Array::value($invalidData->membership_type_id, $membershipType) . "</td>";
96 $invalidDataMessage .= "<td>{$invalidData->start_date}</td>";
97 $invalidDataMessage .= "<td>{$invalidData->end_date}</td>";
98 $invalidDataMessage .= "<td>" . CRM_Utils_Array::value($invalidData->status_id, $membershipStatus) . "</td>";
99 $invalidDataMessage .= "</tr>";
e418776c 100 }
6a488035
TO
101 $invalidDataMessage .= "</table><p>" . ts('If you have reviewed the cleanup script documentation on the wiki and you are ready to run the cleanup now - <a href="%1">click here</a>.', array(1 => CRM_Utils_System::url('civicrm/upgrade/cleanup425', 'reset=1'))) . "</p>";
102 CRM_Core_Error::fatal($invalidDataMessage);
103 return FALSE;
6a488035 104 }
e418776c 105 }
6a488035
TO
106
107 if ($rev == '4.2.beta2') {
108 // note: error conditions are also checked in upgrade_4_2_beta2()
109 if (!defined('CIVICRM_SETTINGS_PATH')) {
110 $preUpgradeMessage .= '<br />' . ts('Could not determine path to civicrm.settings.php. Please manually locate it and add these lines at the bottom: <pre>%1</pre>', array(
21dfd5f5 111 1 => self::SETTINGS_SNIPPET,
6a488035 112 ));
0db6c3e1
TO
113 }
114 elseif (preg_match(self::SETTINGS_SNIPPET_PATTERN, file_get_contents(CIVICRM_SETTINGS_PATH))) {
6a488035 115 // OK, nothing to do
0db6c3e1
TO
116 }
117 elseif (!is_writable(CIVICRM_SETTINGS_PATH)) {
6a488035
TO
118 $preUpgradeMessage .= '<br />' . ts('The settings file (%1) must be updated. Please make it writable or manually add these lines:<pre>%2</pre>', array(
119 1 => CIVICRM_SETTINGS_PATH,
21dfd5f5 120 2 => self::SETTINGS_SNIPPET,
6a488035
TO
121 ));
122 }
123 }
124 if ($rev == '4.2.2' && version_compare($currentVer, '3.3.alpha1') >= 0) {
125 $query = " SELECT cli.id
126FROM `civicrm_line_item` cli
127INNER JOIN civicrm_membership_payment cmp ON cmp.contribution_id = cli.entity_id AND cli.entity_table = 'civicrm_contribution'
128INNER JOIN civicrm_price_field_value cpfv ON cpfv.id = cli.price_field_value_id
129INNER JOIN civicrm_price_field cpf ON cpf.id = cpfv.price_field_id and cpf.id != cli.price_field_id
130INNER JOIN civicrm_price_set cps ON cps.id = cpf.price_set_id AND cps.name <>'default_membership_type_amount' ";
131 $dao = CRM_Core_DAO::executeQuery($query);
132 if ($dao->N) {
86bfa4f6 133 $preUpgradeMessage .= "<br /><strong>" . ts('We have identified extraneous data in your database that a previous upgrade likely introduced. We STRONGLY recommend making a backup of your site before continuing. We also STRONGLY suggest fixing this issue with unneeded records BEFORE you upgrade. You can find more information about this issue and the way to fix it by visiting <a href="http://forum.civicrm.org/index.php/topic,26181.0.html">http://forum.civicrm.org/index.php/topic,26181.0.html</a>.') . "</strong>";
6a488035
TO
134 }
135 }
136
137 if (version_compare($rev, '4.2.9') >= 0) {
138 //CRM-11980
139 $sql = "SELECT id FROM civicrm_option_group WHERE name LIKE 'civicrm_price_field.amount.%' LIMIT 1";
140 $dao = CRM_Core_DAO::executeQuery($sql);
141 if ($dao->fetch()) {
142 $errors = ts("We found unexpected data values from an older version of CiviCRM in your database. The upgrade can not be run until this condition is corrected.<br /><br />Details: One or more rows are present in the civicrm_option_group with name like 'civicrm_price_field.amount.%'. <a href='%1'>Check here for information on diagnosing and correcting this problem.</a>", array(1 => 'http://forum.civicrm.org/index.php/topic,27744.msg118748.html#msg118748'));
f813f78e 143 CRM_Core_Error::fatal($errors);
6a488035 144 return FALSE;
e418776c 145 }
6a488035
TO
146 }
147 }
148
149 /**
150 * Compute any messages which should be displayed after upgrade
151 *
5a4f6742
CW
152 * @param string $postUpgradeMessage
153 * alterable.
154 * @param string $rev
155 * an intermediate version; note that setPostUpgradeMessage is called repeatedly with different $revs.
6a488035
TO
156 * @return void
157 */
00be9182 158 public function setPostUpgradeMessage(&$postUpgradeMessage, $rev) {
6a488035
TO
159 if ($rev == '4.2.beta5') {
160 $config = CRM_Core_Config::singleton();
161 if (!empty($config->extensionsDir)) {
162 $postUpgradeMessage .= '<br />' . ts('Please <a href="%1" target="_blank">configure the Extension Resource URL</a>.', array(
21dfd5f5 163 1 => CRM_Utils_System::url('civicrm/admin/setting/url', 'reset=1'),
6a488035 164 ));
e418776c 165 }
6a488035
TO
166 }
167 if ($rev == '4.2.7') {
168 $postUpgradeMessage .= '<br />' . ts('If you have configured a report instance to allow anonymous access, you will need to reset the permission to Everyone for that instance (under the Report Settings pane).');
e418776c 169 }
6a488035
TO
170 }
171
624e56fa
EM
172 /**
173 * @param $rev
174 */
00be9182 175 public function upgrade_4_2_alpha1($rev) {
6a488035
TO
176 //checking whether the foreign key exists before dropping it
177 //drop foreign key queries of CRM-9850
178 $params = array();
e418776c
TO
179 $tables = array(
180 'civicrm_contribution_page' => 'FK_civicrm_contribution_page_payment_processor_id',
6a488035
TO
181 'civicrm_event' => 'FK_civicrm_event_payment_processor_id',
182 'civicrm_group' => 'FK_civicrm_group_saved_search_id',
183 );
9b873358 184 foreach ($tables as $tableName => $fKey) {
e418776c 185 $foreignKeyExists = CRM_Core_DAO::checkConstraintExists($tableName, $fKey);
9b873358 186 if ($foreignKeyExists) {
6a488035
TO
187 CRM_Core_DAO::executeQuery("ALTER TABLE {$tableName} DROP FOREIGN KEY {$fKey}", $params, TRUE, NULL, FALSE, FALSE);
188 CRM_Core_DAO::executeQuery("ALTER TABLE {$tableName} DROP INDEX {$fKey}", $params, TRUE, NULL, FALSE, FALSE);
189 }
190 }
191 // Drop index UI_title for civicrm_price_set
192 $domain = new CRM_Core_DAO_Domain;
193 $domain->find(TRUE);
194 if ($domain->locales) {
195 $locales = explode(CRM_Core_DAO::VALUE_SEPARATOR, $domain->locales);
196 foreach ($locales as $locale) {
197 $query = "SHOW KEYS FROM `civicrm_price_set` WHERE key_name = 'UI_title_{$locale}'";
198 $dao = CRM_Core_DAO::executeQuery($query, $params, TRUE, NULL, FALSE, FALSE);
199 if ($dao->N) {
200 CRM_Core_DAO::executeQuery("ALTER TABLE `civicrm_price_set` DROP INDEX `UI_title_{$locale}`", $params, TRUE, NULL, FALSE, FALSE);
201 }
202 }
0db6c3e1
TO
203 }
204 else {
6a488035
TO
205 $query = "SHOW KEYS FROM `civicrm_price_set` WHERE key_name = 'UI_title'";
206 $dao = CRM_Core_DAO::executeQuery($query);
207 if ($dao->N) {
208 CRM_Core_DAO::executeQuery("ALTER TABLE `civicrm_price_set` DROP INDEX `UI_title`");
209 }
210 }
211
212 // Some steps take a long time, so we break them up into separate
213 // tasks and enqueue them separately.
d1401e86 214 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => '4.2.alpha1')), 'task_4_2_x_runSql', $rev);
6a488035
TO
215 $this->addTask(ts('Upgrade DB to 4.2.alpha1: Price Sets'), 'task_4_2_alpha1_createPriceSets', $rev);
216 self::convertContribution();
217 $this->addTask(ts('Upgrade DB to 4.2.alpha1: Event Profile'), 'task_4_2_alpha1_eventProfile');
218 }
219
624e56fa
EM
220 /**
221 * @param $rev
222 */
00be9182 223 public function upgrade_4_2_beta2($rev) {
6a488035
TO
224 // note: error conditions are also checked in setPreUpgradeMessage()
225 if (defined('CIVICRM_SETTINGS_PATH')) {
226 if (!preg_match(self::SETTINGS_SNIPPET_PATTERN, file_get_contents(CIVICRM_SETTINGS_PATH))) {
227 if (is_writable(CIVICRM_SETTINGS_PATH)) {
228 file_put_contents(CIVICRM_SETTINGS_PATH, self::SETTINGS_SNIPPET, FILE_APPEND);
229 }
230 }
231 }
232 }
233
624e56fa
EM
234 /**
235 * @param $rev
236 */
00be9182 237 public function upgrade_4_2_beta3($rev) {
d1401e86 238 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => '4.2.beta3')), 'task_4_2_x_runSql', $rev);
6a488035
TO
239 $minParticipantId = CRM_Core_DAO::singleValueQuery('SELECT coalesce(min(id),0) FROM civicrm_participant');
240 $maxParticipantId = CRM_Core_DAO::singleValueQuery('SELECT coalesce(max(id),0) FROM civicrm_participant');
241
242 for ($startId = $minParticipantId; $startId <= $maxParticipantId; $startId += self::BATCH_SIZE) {
243 $endId = $startId + self::BATCH_SIZE - 1;
244 $title = ts('Upgrade DB to 4.2.alpha1: Participant (%1 => %2)', array(1 => $startId, 2 => $endId));
245 $this->addTask($title, 'task_4_2_alpha1_convertParticipants', $startId, $endId);
246 }
247 }
248
624e56fa
EM
249 /**
250 * @param $rev
251 */
00be9182 252 public function upgrade_4_2_beta5($rev) {
6a488035
TO
253 // CRM-10629 Create a setting for extension URLs
254 // For some reason, this isn't working when placed in the .sql file
255 CRM_Core_DAO::executeQuery("
256 INSERT INTO civicrm_setting(group_name,name,value,domain_id,is_domain)
257 VALUES ('URL Preferences', 'extensionsURL',NULL,1,1);
258 ");
259 }
260
624e56fa
EM
261 /**
262 * @param $rev
263 */
00be9182 264 public function upgrade_4_2_0($rev) {
d1401e86 265 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => '4.2.0')), 'task_4_2_x_runSql', $rev);
6a488035
TO
266 }
267
624e56fa
EM
268 /**
269 * @param $rev
270 */
00be9182 271 public function upgrade_4_2_2($rev) {
d1401e86 272 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => '4.2.2')), 'task_4_2_x_runSql', $rev);
6a488035
TO
273 //create line items for memberships and participants for api/import
274 self::convertContribution();
275
276 // CRM-10937 Fix the title on civicrm_dedupe_rule_group
277 $upgrade = new CRM_Upgrade_Form();
278 if ($upgrade->multilingual) {
279 // Check if the 'title' field exists
280 $query = "SELECT column_name
281 FROM information_schema.COLUMNS
282 WHERE table_name = 'civicrm_dedupe_rule_group'
283 AND table_schema = DATABASE()
284 AND column_name = 'title'";
285
286 $dao = CRM_Core_DAO::executeQuery($query);
287
288 if (!$dao->N) {
289 $domain = new CRM_Core_DAO_Domain;
290 $domain->find(TRUE);
291
292 if ($domain->locales) {
293 $locales = explode(CRM_Core_DAO::VALUE_SEPARATOR, $domain->locales);
294 $locale = array_shift($locales);
295
296 // Use the first language (they should all have the same value)
297 CRM_Core_DAO::executeQuery("ALTER TABLE `civicrm_dedupe_rule_group` CHANGE `title_{$locale}` `title` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'Label of the rule group'", $params, TRUE, NULL, FALSE, FALSE);
298
299 // Drop remaining the column for the remaining languages
300 foreach ($locales as $locale) {
301 CRM_Core_DAO::executeQuery("ALTER TABLE `civicrm_dedupe_rule_group` DROP `title_{$locale}`", $params, TRUE, NULL, FALSE, FALSE);
302 }
303 }
304 }
305 }
306 }
307
624e56fa
EM
308 /**
309 * @param $rev
310 */
00be9182 311 public function upgrade_4_2_3($rev) {
d1401e86 312 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => '4.2.3')), 'task_4_2_x_runSql', $rev);
6a488035
TO
313 // CRM-10953 Remove duplicate activity type for 'Reminder Sent' which is mistakenly inserted by 4.2.alpha1 upgrade script
314 $queryMin = "
315SELECT coalesce(min(value),0) from civicrm_option_value ov
316WHERE ov.option_group_id =
317 (SELECT id from civicrm_option_group og WHERE og.name = 'activity_type') AND
318ov.name = 'Reminder Sent'";
319
320 $minReminderSent = CRM_Core_DAO::singleValueQuery($queryMin);
321
322 $queryMax = "
323SELECT coalesce(max(value),0) from civicrm_option_value ov
324WHERE ov.option_group_id =
325 (SELECT id from civicrm_option_group og WHERE og.name = 'activity_type') AND
326ov.name = 'Reminder Sent'";
327
328 $maxReminderSent = CRM_Core_DAO::singleValueQuery($queryMax);
329
330 // If we have two different values, replace new value with original in any activities
331 if ($maxReminderSent > $minReminderSent) {
332 $query = "
333UPDATE civicrm_activity
334SET activity_type_id = {$minReminderSent}
335WHERE activity_type_id = {$maxReminderSent}";
336
337 CRM_Core_DAO::executeQuery($query);
338
339 // Then delete the newer (duplicate) option_value row
340 $query = "
341DELETE from civicrm_option_value
342 WHERE option_group_id =
343 (SELECT id from civicrm_option_group og WHERE og.name = 'activity_type') AND
344 value = '{$maxReminderSent}'";
345
346 CRM_Core_DAO::executeQuery($query);
347 }
348 }
349
624e56fa
EM
350 /**
351 * @param $rev
352 */
00be9182 353 public function upgrade_4_2_5($rev) {
d1401e86 354 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => '4.2.5')), 'task_4_2_x_runSql', $rev);
6a488035
TO
355 //CRM-11077
356 $sql = " SELECT cpse.entity_id, cpse.price_set_id
357FROM `civicrm_price_set_entity` cpse
358LEFT JOIN civicrm_price_set cps ON cps.id = cpse.price_set_id
359LEFT JOIN civicrm_price_set_entity cpse1 ON cpse1.price_set_id = cpse.price_set_id
360WHERE cpse.entity_table = 'civicrm_event' AND cps.is_quick_config = 1
361GROUP BY cpse.id
362HAVING COUNT(cpse.price_set_id) > 1 AND MIN(cpse1.id) <> cpse.id ";
363
364 $dao = CRM_Core_DAO::executeQuery($sql);
365 while ($dao->fetch()) {
366 if ($dao->price_set_id) {
367 $copyPriceSet = &CRM_Upgrade_Snapshot_V4p2_Price_BAO_Set::copy($dao->price_set_id);
368 CRM_Upgrade_Snapshot_V4p2_Price_BAO_Set::addTo('civicrm_event', $dao->entity_id, $copyPriceSet->id);
369 }
370 }
371 }
372
9b873358 373 public function convertContribution() {
6a488035
TO
374 $minContributionId = CRM_Core_DAO::singleValueQuery('SELECT coalesce(min(id),0) FROM civicrm_contribution');
375 $maxContributionId = CRM_Core_DAO::singleValueQuery('SELECT coalesce(max(id),0) FROM civicrm_contribution');
376 for ($startId = $minContributionId; $startId <= $maxContributionId; $startId += self::BATCH_SIZE) {
377 $endId = $startId + self::BATCH_SIZE - 1;
378 $title = ts('Upgrade DB to 4.2.alpha1: Contributions (%1 => %2)', array(1 => $startId, 2 => $endId));
379 $this->addTask($title, 'task_4_2_alpha1_convertContributions', $startId, $endId);
380 }
381 $minParticipantId = CRM_Core_DAO::singleValueQuery('SELECT coalesce(min(id),0) FROM civicrm_participant');
382 $maxParticipantId = CRM_Core_DAO::singleValueQuery('SELECT coalesce(max(id),0) FROM civicrm_participant');
383
384 for ($startId = $minParticipantId; $startId <= $maxParticipantId; $startId += self::BATCH_SIZE) {
385 $endId = $startId + self::BATCH_SIZE - 1;
386 $title = ts('Upgrade DB to 4.2.alpha1: Participant (%1 => %2)', array(1 => $startId, 2 => $endId));
387 $this->addTask($title, 'task_4_2_alpha1_convertParticipants', $startId, $endId);
388 }
389 }
390
391 /**
392 * (Queue Task Callback)
393 *
394 * Upgrade code to create priceset for contribution pages and events
395 */
00be9182 396 public static function task_4_2_alpha1_createPriceSets(CRM_Queue_TaskContext $ctx, $rev) {
6a488035 397 $upgrade = new CRM_Upgrade_Form();
9d72cede
EM
398 $daoName = array(
399 'civicrm_contribution_page' => array(
6a488035 400 'CRM_Contribute_BAO_ContributionPage',
21dfd5f5 401 CRM_Core_Component::getComponentID('CiviContribute'),
6a488035 402 ),
9d72cede 403 'civicrm_event' => array(
6a488035 404 'CRM_Event_BAO_Event',
21dfd5f5 405 CRM_Core_Component::getComponentID('CiviEvent'),
6a488035
TO
406 ),
407 );
408
409 // get all option group used for event and contribution page
410 $query = "
411SELECT id, name
412FROM civicrm_option_group
413WHERE name LIKE '%.amount.%' ";
414 $dao = CRM_Core_DAO::executeQuery($query);
415 while ($dao->fetch()) {
416 $addTo = explode('.', $dao->name);
a7488080 417 if (!empty($addTo[2])) {
e418776c 418 $options = array('optionGroup' => $dao->name);
6a488035
TO
419 self::createPriceSet($daoName, $addTo, $options);
420 }
421 CRM_Core_OptionGroup::deleteAssoc($dao->name);
422 }
423
424 //create pricesets for contribution with only other amount
425 $query = "
426SELECT ccp.id as contribution_page_id, ccp.is_allow_other_amount, cmb.id as membership_block_id
427FROM civicrm_contribution_page ccp
428LEFT JOIN civicrm_membership_block cmb ON cmb.entity_id = ccp.id AND cmb.entity_table = 'civicrm_contribution_page'
429LEFT JOIN civicrm_price_set_entity cpse ON cpse.entity_id = ccp.id and cpse.entity_table = 'civicrm_contribution_page'
430WHERE cpse.price_set_id IS NULL";
431 $dao = CRM_Core_DAO::executeQuery($query);
432 $addTo = array('civicrm_contribution_page');
433 while ($dao->fetch()) {
434 $addTo[2] = $dao->contribution_page_id;
e418776c
TO
435 $options = array(
436 'otherAmount' => $dao->is_allow_other_amount,
481a74f4 437 'membership' => $dao->membership_block_id);
6a488035
TO
438 self::createPriceSet($daoName, $addTo, $options);
439 }
440
441 return TRUE;
442 }
443
444 /**
445 * (Queue Task Callback)
446 */
00be9182 447 public static function task_4_2_x_runSql(CRM_Queue_TaskContext $ctx, $rev) {
e418776c
TO
448 $upgrade = new CRM_Upgrade_Form();
449 $upgrade->processSQL($rev);
6a488035 450
e418776c
TO
451 // now rebuild all the triggers
452 // CRM-9716
453 // FIXME // CRM_Core_DAO::triggerRebuild();
6a488035 454
e418776c 455 return TRUE;
6a488035
TO
456 }
457
458 /**
459 *
c490a46a 460 * create price sets
6a488035 461 */
e418776c 462 public static function createPriceSet($daoName, $addTo, $options = array()) {
6a488035
TO
463 $query = "SELECT title FROM {$addTo[0]} where id =%1";
464 $setParams['title'] = CRM_Core_DAO::singleValueQuery($query,
465 array(1 => array($addTo[2], 'Integer'))
466 );
467 $pageTitle = strtolower(CRM_Utils_String::munge($setParams['title'], '_', 245));
468
469 // an event or contrib page has been deleted but left the option group behind - (this may be fixed in later versions?)
470 // we should probably delete the option group - but at least early exit here as the code following it does not fatal
471 // CRM-10298
481a74f4 472 if (empty($pageTitle)) {
6a488035
TO
473 return;
474 }
475
476 $optionValue = array();
a7488080 477 if (!empty($options['optionGroup'])) {
6a488035 478 CRM_Core_OptionGroup::getAssoc($options['optionGroup'], $optionValue);
e418776c 479 if (empty($optionValue)) {
6a488035 480 return;
e418776c 481 }
6a488035 482 }
8cc574cf 483 elseif (empty($options['otherAmount']) && empty($options['membership'])) {
ab44179e
PJ
484 //CRM-12273
485 //if options group, otherAmount, membersip is empty then return, contribution should be default price set
486 return;
487 }
6a488035 488
e418776c 489 if (! CRM_Core_DAO::getFieldValue('CRM_Upgrade_Snapshot_V4p2_Price_BAO_Set', $pageTitle, 'id', 'name', TRUE)) {
6a488035
TO
490 $setParams['name'] = $pageTitle;
491 }
492 else {
e418776c 493 $timeSec = explode(".", microtime(TRUE));
6a488035
TO
494 $setParams['name'] = $pageTitle . '_' . date('is', $timeSec[0]) . $timeSec[1];
495 }
496 $setParams['extends'] = $daoName[$addTo[0]][1];
497 $setParams['is_quick_config'] = 1;
498 $priceSet = CRM_Upgrade_Snapshot_V4p2_Price_BAO_Set::create($setParams);
499 CRM_Upgrade_Snapshot_V4p2_Price_BAO_Set::addTo($addTo[0], $addTo[2], $priceSet->id, 1);
500
501 $fieldParams['price_set_id'] = $priceSet->id;
a7488080 502 if (!empty($options['optionGroup'])) {
6a488035
TO
503 $fieldParams['html_type'] = 'Radio';
504 $fieldParams['is_required'] = 1;
505 if ($addTo[0] == 'civicrm_event') {
506 $query = "SELECT fee_label FROM civicrm_event where id =%1";
507 $fieldParams['name'] = $fieldParams['label'] = CRM_Core_DAO::singleValueQuery($query,
508 array(1 => array($addTo[2], 'Integer'))
509 );
510 $defaultAmountColumn = 'default_fee_id';
511 }
512 else {
513 $options['membership'] = 1;
514 $fieldParams['name'] = strtolower(CRM_Utils_String::munge("Contribution Amount", '_', 245));
515 $fieldParams['label'] = "Contribution Amount";
516 $defaultAmountColumn = 'default_amount_id';
517 $options['otherAmount'] = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_ContributionPage', $addTo[2], 'is_allow_other_amount');
a7488080 518 if (!empty($options['otherAmount'])) {
6a488035
TO
519 $fieldParams['is_required'] = 0;
520 }
521 }
522 $fieldParams['option_label'] = $optionValue['label'];
523 $fieldParams['option_amount'] = $optionValue['value'];
524 $fieldParams['option_weight'] = $optionValue['weight'];
f813f78e 525 $fieldParams['is_quick_config'] = $setParams['is_quick_config'];
6a488035
TO
526 if ($defaultAmount = CRM_Core_DAO::getFieldValue($daoName[$addTo[0]][0], $addTo[2], $defaultAmountColumn)) {
527 $fieldParams['default_option'] = array_search($defaultAmount, $optionValue['amount_id']);
528 }
529 $priceField = CRM_Upgrade_Snapshot_V4p2_Price_BAO_Field::create($fieldParams);
530
531 }
a7488080 532 if (!empty($options['membership'])) {
6a488035
TO
533 $dao = new CRM_Member_DAO_MembershipBlock();
534 $dao->entity_table = 'civicrm_contribution_page';
535 $dao->entity_id = $addTo[2];
536
537 if ($dao->find(TRUE)) {
538 if ($dao->membership_types) {
539 $fieldParams = array(
540 'name' => strtolower(CRM_Utils_String::munge("Membership Amount", '_', 245)),
541 'label' => "Membership Amount",
542 'is_required' => $dao->is_required,
543 'is_display_amounts' => $dao->display_min_fee,
544 'is_active' => $dao->is_active,
545 'price_set_id' => $priceSet->id,
546 'html_type' => 'Radio',
547 'weight' => 1,
548 );
549 $membershipTypes = unserialize($dao->membership_types);
550 $rowcount = 0;
551 foreach ($membershipTypes as $membershipType => $autoRenew) {
552 $membershipTypeDetail = CRM_Member_BAO_MembershipType::getMembershipTypeDetails($membershipType);
553 $rowcount++;
554 $fieldParams['option_label'][$rowcount] = $membershipTypeDetail['name'];
555 $fieldParams['option_amount'][$rowcount] = $membershipTypeDetail['minimum_fee'];
556 $fieldParams['option_weight'][$rowcount] = $rowcount;
557 $fieldParams['membership_type_id'][$rowcount] = $membershipType;
558 if ($membershipType == $dao->membership_type_default) {
559 $fieldParams['default_option'] = $rowcount;
560 }
561 }
562 $priceField = CRM_Upgrade_Snapshot_V4p2_Price_BAO_Field::create($fieldParams);
563
564 $setParams = array(
565 'id' => $priceSet->id,
566 'extends' => CRM_Core_Component::getComponentID('CiviMember'),
567 'contribution_type_id' => CRM_Core_DAO::getFieldValue($daoName[$addTo[0]][0], $addTo[2], 'contribution_type_id'),
568 );
569 CRM_Upgrade_Snapshot_V4p2_Price_BAO_Set::create($setParams);
570 }
571 }
572 }
a7488080 573 if (!empty($options['otherAmount'])) {
6a488035
TO
574
575 $fieldParams = array(
576 'name' => strtolower(CRM_Utils_String::munge("Other Amount", '_', 245)),
577 'label' => "Other Amount",
578 'is_required' => 0,
579 'is_display_amounts' => 0,
580 'is_active' => 1,
581 'price_set_id' => $priceSet->id,
582 'html_type' => 'Text',
583 'weight' => 3,
584 );
585 $fieldParams['option_label'][1] = "Other Amount";
586 $fieldParams['option_amount'][1] = 1;
587 $fieldParams['option_weight'][1] = 1;
588 $priceField = CRM_Upgrade_Snapshot_V4p2_Price_BAO_Field::create($fieldParams);
589 }
590 }
591
592 /**
593 * (Queue Task Callback)
594 *
595 * Find any contribution records and create corresponding line-item
596 * records.
597 *
77b97be7 598 * @param CRM_Queue_TaskContext $ctx
5a4f6742
CW
599 * @param int $startId
600 * the first/lowest contribution ID to convert.
601 * @param int $endId
602 * the last/highest contribution ID to convert.
77b97be7
EM
603 *
604 * @return bool
6a488035 605 */
00be9182 606 public static function task_4_2_alpha1_convertContributions(CRM_Queue_TaskContext $ctx, $startId, $endId) {
6a488035
TO
607 $upgrade = new CRM_Upgrade_Form();
608 $query = "
609 INSERT INTO civicrm_line_item(`entity_table` ,`entity_id` ,`price_field_id` ,`label` , `qty` ,`unit_price` ,`line_total` ,`participant_count` ,`price_field_value_id`)
610 SELECT 'civicrm_contribution',cc.id, cpf.id as price_field_id, cpfv.label, 1, cc.total_amount, cc.total_amount line_total, 0, cpfv.id as price_field_value
611 FROM civicrm_membership_payment cmp
612 LEFT JOIN `civicrm_contribution` cc ON cc.id = cmp.contribution_id
613 LEFT JOIN civicrm_line_item cli ON cc.id=cli.entity_id and cli.entity_table = 'civicrm_contribution'
614 LEFT JOIN civicrm_membership cm ON cm.id=cmp.membership_id
615 LEFT JOIN civicrm_membership_type cmt ON cmt.id = cm.membership_type_id
616 LEFT JOIN civicrm_price_field cpf ON BINARY cpf.name = cmt.member_of_contact_id
617 LEFT JOIN civicrm_price_field_value cpfv ON cpfv.membership_type_id = cm.membership_type_id AND cpf.id = cpfv.price_field_id
618 WHERE (cc.id BETWEEN %1 AND %2) AND cli.entity_id IS NULL ;
619 ";
620 $sqlParams = array(
621 1 => array($startId, 'Integer'),
622 2 => array($endId, 'Integer'),
623 );
624 CRM_Core_DAO::executeQuery($query, $sqlParams);
625
626 // create lineitems for contribution done for membership
627 $sql = "
628SELECT cc.id, cmp.membership_id, cpse.price_set_id, cc.total_amount
629FROM civicrm_contribution cc
630LEFT JOIN civicrm_line_item cli ON cc.id=cli.entity_id AND cli.entity_table = 'civicrm_contribution'
631LEFT JOIN civicrm_membership_payment cmp ON cc.id = cmp.contribution_id
632LEFT JOIN civicrm_participant_payment cpp ON cc.id = cpp.contribution_id
633LEFT JOIN civicrm_price_set_entity cpse on cpse.entity_table = 'civicrm_contribution_page' AND cpse.entity_id = cc.contribution_page_id
634WHERE (cc.id BETWEEN %1 AND %2)
635AND cli.entity_id IS NULL AND cc.contribution_page_id IS NOT NULL AND cpp.contribution_id IS NULL
636GROUP BY cc.id
637";
638 $result = CRM_Core_DAO::executeQuery($sql, $sqlParams);
639
640 while ($result->fetch()) {
641 $sql = "
642SELECT cpf.id, cpfv.id as price_field_value_id, cpfv.label, cpfv.amount, cpfv.count
643FROM civicrm_price_field cpf
644LEFT JOIN civicrm_price_field_value cpfv ON cpf.id = cpfv.price_field_id
645WHERE cpf.price_set_id = %1
646";
647 $lineParams = array(
648 'entity_table' => 'civicrm_contribution',
649 'entity_id' => $result->id,
650 );
651 if ($result->membership_id) {
652 $sql .= " AND cpf.name = %2 AND cpfv.membership_type_id = %3 ";
653 $params = array(
654 '1' => array($result->price_set_id, 'Integer'),
655 '2' => array('membership_amount', 'String'),
656 '3' => array(CRM_Core_DAO::getFieldValue('CRM_Member_DAO_Membership', $result->membership_id, 'membership_type_id'), 'Integer'),
657 );
658 $res = CRM_Core_DAO::executeQuery($sql, $params);
659 if ($res->fetch()) {
660 $lineParams += array(
661 'price_field_id' => $res->id,
662 'label' => $res->label,
663 'qty' => 1,
664 'unit_price' => $res->amount,
665 'line_total' => $res->amount,
666 'participant_count' => $res->count ? $res->count : 0,
667 'price_field_value_id' => $res->price_field_value_id,
668 );
669 }
670 else {
671 $lineParams['price_field_id'] = CRM_Core_DAO::getFieldValue('CRM_Upgrade_Snapshot_V4p2_Price_DAO_Field', $result->price_set_id, 'id', 'price_set_id');
672 $lineParams['label'] = 'Membership Amount';
673 $lineParams['qty'] = 1;
674 $lineParams['unit_price'] = $lineParams['line_total'] = $result->total_amount;
675 $lineParams['participant_count'] = 0;
676 }
677 }
678 else {
679 $sql .= "AND cpfv.amount = %2";
ab44179e
PJ
680
681 //CRM-12273
682 //check if price_set_id is exist, if not use the default contribution amount
9b873358 683 if (isset($result->price_set_id)) {
ab44179e
PJ
684 $priceSetId = $result->price_set_id;
685 }
92e4c2a5 686 else {
9da8dc8c 687 $defaultPriceSets = CRM_Price_BAO_PriceSet::getDefaultPriceSet();
ab44179e 688 foreach ($defaultPriceSets as $key => $pSet) {
9b873358 689 if ($pSet['name'] == 'contribution_amount') {
ab44179e
PJ
690 $priceSetId = $pSet['setID'];
691 }
692 }
693 }
694
6a488035 695 $params = array(
ab44179e 696 '1' => array($priceSetId, 'Integer'),
6a488035
TO
697 '2' => array($result->total_amount, 'String'),
698 );
699 $res = CRM_Core_DAO::executeQuery($sql, $params);
700 if ($res->fetch()) {
701 $lineParams += array(
702 'price_field_id' => $res->id,
703 'label' => $res->label,
704 'qty' => 1,
705 'unit_price' => $res->amount,
706 'line_total' => $res->amount,
707 'participant_count' => $res->count ? $res->count : 0,
708 'price_field_value_id' => $res->price_field_value_id,
709 );
710 }
711 else {
712 $params = array(
ab44179e 713 'price_set_id' => $priceSetId,
6a488035
TO
714 'name' => 'other_amount',
715 );
716 $defaults = array();
717 CRM_Upgrade_Snapshot_V4p2_Price_BAO_Field::retrieve($params, $defaults);
718 if (!empty($defaults)) {
719 $lineParams['price_field_id'] = $defaults['id'];
720 $lineParams['label'] = $defaults['label'];
721 $lineParams['price_field_value_id'] =
722 CRM_Core_DAO::getFieldValue('CRM_Upgrade_Snapshot_V4p2_Price_DAO_FieldValue', $defaults['id'], 'id', 'price_field_id');
723 }
724 else {
725 $lineParams['price_field_id'] =
ab44179e 726 CRM_Core_DAO::getFieldValue('CRM_Upgrade_Snapshot_V4p2_Price_DAO_Field', $priceSetId, 'id', 'price_set_id');
6a488035
TO
727 $lineParams['label'] = 'Contribution Amount';
728 }
729 $lineParams['qty'] = 1;
730 $lineParams['participant_count'] = 0;
731 $lineParams['unit_price'] = $lineParams['line_total'] = $result->total_amount;
732 }
733 }
734 CRM_Upgrade_Snapshot_V4p2_Price_BAO_LineItem::create($lineParams);
735 }
736
737 return TRUE;
738 }
739
740 /**
741 * (Queue Task Callback)
742 *
743 * Find any participant records and create corresponding line-item
744 * records.
745 *
77b97be7 746 * @param CRM_Queue_TaskContext $ctx
5a4f6742
CW
747 * @param int $startId
748 * the first/lowest participant ID to convert.
749 * @param int $endId
750 * the last/highest participant ID to convert.
77b97be7
EM
751 *
752 * @return bool
6a488035 753 */
00be9182 754 public static function task_4_2_alpha1_convertParticipants(CRM_Queue_TaskContext $ctx, $startId, $endId) {
6a488035
TO
755 $upgrade = new CRM_Upgrade_Form();
756 //create lineitems for participant in edge cases using default price set for contribution.
757 $query = "
758SELECT cp.id as participant_id, cp.fee_amount, cp.fee_level,ce.is_monetary,
759 cpse.price_set_id, cpf.id as price_field_id, cpfv.id as price_field_value_id
760FROM civicrm_participant cp
761LEFT JOIN civicrm_line_item cli ON cli.entity_id=cp.id and cli.entity_table = 'civicrm_participant'
762LEFT JOIN civicrm_event ce ON ce.id=cp.event_id
763LEFT JOIN civicrm_price_set_entity cpse ON cp.event_id = cpse.entity_id and cpse.entity_table = 'civicrm_event'
764LEFT JOIN civicrm_price_field cpf ON cpf.price_set_id = cpse.price_set_id
765LEFT JOIN civicrm_price_field_value cpfv ON cpfv.price_field_id = cpf.id AND cpfv.label = cp.fee_level
766WHERE (cp.id BETWEEN %1 AND %2)
767AND cli.entity_id IS NULL AND cp.fee_amount IS NOT NULL";
768 $sqlParams = array(
769 1 => array($startId, 'Integer'),
770 2 => array($endId, 'Integer'),
771 );
772 $dao = CRM_Core_DAO::executeQuery($query, $sqlParams);
773 if ($dao->N) {
774 $defaultPriceSetId = CRM_Core_DAO::getFieldValue('CRM_Upgrade_Snapshot_V4p2_Price_DAO_Set', 'default_contribution_amount', 'id', 'name');
775 $priceSets = current(CRM_Upgrade_Snapshot_V4p2_Price_BAO_Set::getSetDetail($defaultPriceSetId));
776 $fieldID = key($priceSets['fields']);
777 }
778
779 while ($dao->fetch()) {
780 $lineParams = array(
781 'entity_table' => 'civicrm_participant',
782 'entity_id' => $dao->participant_id,
783 'label' => $dao->fee_level ? $dao->fee_level : ts('Default'),
784 'qty' => 1,
785 'unit_price' => $dao->fee_amount,
786 'line_total' => $dao->fee_amount,
787 'participant_count' => 1,
788 );
789 if ($dao->is_monetary && $dao->price_field_id) {
790 $lineParams += array(
791 'price_field_id' => $dao->price_field_id,
792 'price_field_value_id' => $dao->price_field_value_id,
793 );
794 $priceSetId = $dao->price_set_id;
0db6c3e1
TO
795 }
796 else {
6a488035
TO
797 $lineParams['price_field_id'] = $fieldID;
798 $priceSetId = $defaultPriceSetId;
799 }
800 CRM_Upgrade_Snapshot_V4p2_Price_BAO_LineItem::create($lineParams);
801 }
802 return TRUE;
803 }
804
805 /**
806 * (Queue Task Callback)
807 *
808 * Create an event registration profile with a single email field CRM-9587
809 */
00be9182 810 public static function task_4_2_alpha1_eventProfile(CRM_Queue_TaskContext $ctx) {
6a488035
TO
811 $upgrade = new CRM_Upgrade_Form();
812 $profileTitle = ts('Your Registration Info');
37044cde 813
6a488035
TO
814 $sql = "
815INSERT INTO civicrm_uf_group
816 (is_active, group_type, title, help_pre, help_post, limit_listings_group_id, post_URL, add_to_group_id, add_captcha, is_map, is_edit_link, is_uf_link, is_update_dupe, cancel_URL, is_cms_user, notify, is_reserved, name, created_id, created_date, is_proximity_search)
817VALUES
37044cde 818 (1, 'Individual, Contact', %1, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0, NULL, 0, NULL, 0, 'event_registration', NULL, NULL, 0);
6a488035 819";
37044cde
ML
820
821 $params = array(
822 1 => array($profileTitle, 'String'),
823 );
824
825 CRM_Core_DAO::executeQuery($sql, $params);
6a488035
TO
826
827 $eventRegistrationId = CRM_Core_DAO::singleValueQuery('SELECT LAST_INSERT_ID()');
828 $sql = "
829INSERT INTO civicrm_uf_field
830 (uf_group_id, field_name, is_active, is_view, is_required, weight, help_post, help_pre, visibility, in_selector, is_searchable, location_type_id, phone_type_id, label, field_type, is_reserved)
831VALUES
832 ({$eventRegistrationId}, 'email', 1, 0, 1, 1, NULL, NULL, 'User and User Admin Only', 0, 0, NULL, NULL, 'Email Address', 'Contact', 0);
833";
834 CRM_Core_DAO::executeQuery($sql);
835
836 $sql = "SELECT * FROM civicrm_event WHERE is_online_registration = 1;";
837 $events = CRM_Core_DAO::executeQuery($sql);
838 while ($events->fetch()) {
839 // Get next weights for the event registration profile
840 $nextMainWeight = $nextAdditionalWeight = 1;
841 $sql = "
842SELECT weight
843FROM civicrm_uf_join
844WHERE entity_id = {$events->id} AND module = 'CiviEvent'
845ORDER BY weight DESC LIMIT 1";
846 $weights = CRM_Core_DAO::executeQuery($sql);
847 $weights->fetch();
848 if (isset($weights->weight)) {
849 $nextMainWeight += $weights->weight;
850 }
851 $sql = "
852SELECT weight
853FROM civicrm_uf_join
854WHERE entity_id = {$events->id} AND module = 'CiviEvent_Additional'
855ORDER BY weight DESC LIMIT 1";
856 $weights = CRM_Core_DAO::executeQuery($sql);
857 $weights->fetch();
858 if (isset($weights->weight)) {
859 $nextAdditionalWeight += $weights->weight;
860 }
861 // Add an event registration profile to the event
862 $sql = "
863INSERT INTO civicrm_uf_join
864 (is_active, module, entity_table, entity_id, weight, uf_group_id)
865VALUES
866 (1, 'CiviEvent', 'civicrm_event', {$events->id}, {$nextMainWeight}, {$eventRegistrationId});
867";
868 CRM_Core_DAO::executeQuery($sql);
869 $sql = "
870INSERT INTO civicrm_uf_join
871 (is_active, module, entity_table, entity_id, weight, uf_group_id)
872VALUES
873 (1, 'CiviEvent_Additional', 'civicrm_event', {$events->id}, {$nextAdditionalWeight}, {$eventRegistrationId});";
874 CRM_Core_DAO::executeQuery($sql);
875 }
876 return TRUE;
877 }
878
879 /**
880 * Syntatic sugar for adding a task which (a) is in this class and (b) has
881 * a high priority.
882 *
883 * After passing the $funcName, you can also pass parameters that will go to
884 * the function. Note that all params must be serializable.
885 */
886 protected function addTask($title, $funcName) {
887 $queue = CRM_Queue_Service::singleton()->load(array(
888 'type' => 'Sql',
889 'name' => CRM_Upgrade_Form::QUEUE_NAME,
890 ));
891
892 $args = func_get_args();
893 $title = array_shift($args);
894 $funcName = array_shift($args);
895 $task = new CRM_Queue_Task(
896 array(get_class($this), $funcName),
897 $args,
898 $title
899 );
900 $queue->createItem($task, array('weight' => -1));
901 }
902
624e56fa
EM
903 /**
904 * @return array
905 */
6a488035
TO
906 public static function deleteInvalidPairs() {
907 require_once 'CRM/Member/PseudoConstant.php';
908 require_once 'CRM/Contribute/PseudoConstant.php';
909 $processedRecords = array();
910
911 $tempTableName1 = CRM_Core_DAO::createTempTableName();
912 // 1. collect all duplicates
913 $sql = "
914 CREATE TEMPORARY TABLE {$tempTableName1} SELECT mp.id as payment_id, mp.contribution_id, mp.membership_id, mem.membership_type_id, mem.start_date, mem.end_date, mem.status_id, mem.contact_id, con.contribution_status_id
915 FROM civicrm_membership_payment mp
916 INNER JOIN ( SELECT cmp.contribution_id
917 FROM civicrm_membership_payment cmp
918 LEFT JOIN civicrm_line_item cli ON cmp.contribution_id=cli.entity_id and cli.entity_table = 'civicrm_contribution'
919 WHERE cli.entity_id IS NULL
920 GROUP BY cmp.contribution_id
921 HAVING COUNT(cmp.membership_id) > 1) submp ON submp.contribution_id = mp.contribution_id
922 INNER JOIN civicrm_membership mem ON mem.id = mp.membership_id
923 INNER JOIN civicrm_contribution con ON con.id = mp.contribution_id
924 ORDER BY mp.contribution_id, mp.membership_id";
925 $dao = CRM_Core_DAO::executeQuery($sql);
926
927 $tempTableName2 = CRM_Core_DAO::createTempTableName();
928 // 2. collect all records that are going to be retained
929 $sql = "
930 CREATE TEMPORARY TABLE {$tempTableName2}
931 SELECT MAX(payment_id) as payment_id FROM {$tempTableName1} GROUP BY contribution_id HAVING COUNT(*) > 1";
932 CRM_Core_DAO::executeQuery($sql);
933
934 // 3. do the un-linking
935 $sql = "
936 DELETE cmp.*
937 FROM civicrm_membership_payment cmp
938 INNER JOIN $tempTableName1 temp1 ON temp1.payment_id = cmp.id
939 LEFT JOIN $tempTableName2 temp2 ON temp1.payment_id = temp2.payment_id
940 WHERE temp2.payment_id IS NULL";
941 CRM_Core_DAO::executeQuery($sql);
942
943 // 4. show all records that were Processed, i.e Retained vs Un-linked
944 $sql = "
945 SELECT temp1.contact_id, temp1.contribution_id, temp1.contribution_status_id, temp1.membership_id, temp1.membership_type_id, temp1.start_date, temp1.end_date, temp1.status_id, temp2.payment_id as retain_id
946 FROM $tempTableName1 temp1
947 LEFT JOIN $tempTableName2 temp2 ON temp1.payment_id = temp2.payment_id";
948 $dao = CRM_Core_DAO::executeQuery($sql);
949 if ($dao->N) {
950 $membershipType = CRM_Member_PseudoConstant::membershipType();
951 $membershipStatus = CRM_Member_PseudoConstant::membershipStatus();
952 $contributionStatus = CRM_Contribute_PseudoConstant::contributionStatus();
953 while ($dao->fetch()) {
954 $status = $dao->retain_id ? 'Retained' : 'Un-linked';
955 $memType = CRM_Utils_Array::value($dao->membership_type_id, $membershipType);
956 $memStatus = CRM_Utils_Array::value($dao->status_id, $membershipStatus);
957 $contribStatus = CRM_Utils_Array::value($dao->contribution_status_id, $contributionStatus);
958 $processedRecords[] = array($dao->contact_id, $dao->contribution_id, $contribStatus, $dao->membership_id,
959 $memType, $dao->start_date, $dao->end_date, $memStatus, $status);
e418776c 960 }
6a488035
TO
961 }
962
481a74f4 963 if (!empty($processedRecords)) {
6a488035 964 CRM_Core_Error::debug_log_message("deleteInvalidPairs() - The following records have been processed. Membership records with action:");
481a74f4
TO
965 CRM_Core_Error::debug_log_message("Contact ID, ContributionID, Contribution Status, MembershipID, Membership Type, Start Date, End Date, Membership Status, Action");
966 foreach ($processedRecords as $record) {
6a488035
TO
967 CRM_Core_Error::debug_log_message(implode(', ', $record));
968 }
0db6c3e1
TO
969 }
970 else {
6a488035
TO
971 CRM_Core_Error::debug_log_message("deleteInvalidPairs() - Could not find any records to process.");
972 }
973 return $processedRecords;
974 }
975
976}