Merge pull request #4940 from mlutfy/crm15824
[civicrm-core.git] / CRM / Upgrade / Incremental / php / FourTwo.php
CommitLineData
6a488035 1<?php
6a488035
TO
2/*
3 +--------------------------------------------------------------------+
39de6fd5 4 | CiviCRM version 4.6 |
6a488035 5 +--------------------------------------------------------------------+
06b69b18 6 | Copyright CiviCRM LLC (c) 2004-2014 |
6a488035
TO
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 *
29 * @package CRM
06b69b18 30 * @copyright CiviCRM LLC (c) 2004-2014
6a488035
TO
31 * $Id$
32 *
33 */
34class CRM_Upgrade_Incremental_php_FourTwo {
35 const BATCH_SIZE = 5000;
36 const SETTINGS_SNIPPET_PATTERN = '/CRM_Core_ClassLoader::singleton\(\)-\>register/';
37 const SETTINGS_SNIPPET = "\nrequire_once 'CRM/Core/ClassLoader.php';\nCRM_Core_ClassLoader::singleton()->register();\n";
38
624e56fa
EM
39 /**
40 * @param $errors
41 *
42 * @return bool
43 */
00be9182 44 public function verifyPreDBstate(&$errors) {
6a488035
TO
45 return TRUE;
46 }
47
48 /**
49 * Compute any messages which should be displayed beforeupgrade
50 *
51 * Note: This function is called iteratively for each upcoming
52 * revision to the database.
53 *
77b97be7 54 * @param $preUpgradeMessage
5a4f6742
CW
55 * @param string $rev
56 * a version number, e.g. '4.2.alpha1', '4.2.beta3', '4.2.0'.
77b97be7
EM
57 * @param null $currentVer
58 *
6a488035
TO
59 * @return void
60 */
00be9182 61 public function setPreUpgradeMessage(&$preUpgradeMessage, $rev, $currentVer = NULL) {
6a488035 62 if ($rev == '4.2.alpha1') {
e418776c 63 $tables = array('civicrm_contribution_page', 'civicrm_event', 'civicrm_group', 'civicrm_contact');
9b873358 64 if (!CRM_Core_DAO::schemaRequiresRebuilding($tables)) {
10a5be27 65 $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
66 CRM_Core_Error::fatal($errors);
67 return FALSE;
68 }
69
70 // CRM-10613, CRM-11120
71 $query = "
72SELECT mp.contribution_id, mp.membership_id, mem.membership_type_id, mem.start_date, mem.end_date, mem.status_id, mem.contact_id
73FROM civicrm_membership_payment mp
74INNER JOIN ( SELECT cmp.contribution_id
75 FROM civicrm_membership_payment cmp
76 LEFT JOIN civicrm_line_item cli ON cmp.contribution_id=cli.entity_id and cli.entity_table = 'civicrm_contribution'
77 WHERE cli.entity_id IS NULL
78 GROUP BY cmp.contribution_id
79 HAVING COUNT(cmp.membership_id) > 1) submp ON submp.contribution_id = mp.contribution_id
80INNER JOIN civicrm_membership mem ON mem.id = mp.membership_id
81ORDER BY mp.contribution_id, mp.membership_id";
82 $invalidData = CRM_Core_DAO::executeQuery($query);
83 if ($invalidData->N) {
84 $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 85 ', array(1 => 'http://wiki.civicrm.org/confluence/display/CRMDOC42/Repair+database+script+for+4.2+upgrades')) . "</strong>";
6a488035
TO
86 $membershipType = CRM_Member_PseudoConstant::membershipType();
87 $membershipStatus = CRM_Member_PseudoConstant::membershipStatus();
88 $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>";
89 while ($invalidData->fetch()) {
90 $invalidDataMessage .= "<tr>";
91 $invalidDataMessage .= "<td>{$invalidData->contact_id}</td>";
92 $invalidDataMessage .= "<td>{$invalidData->contribution_id}</td>";
93 $invalidDataMessage .= "<td>{$invalidData->membership_id}</td>";
94 $invalidDataMessage .= "<td>" . CRM_Utils_Array::value($invalidData->membership_type_id, $membershipType) . "</td>";
95 $invalidDataMessage .= "<td>{$invalidData->start_date}</td>";
96 $invalidDataMessage .= "<td>{$invalidData->end_date}</td>";
97 $invalidDataMessage .= "<td>" . CRM_Utils_Array::value($invalidData->status_id, $membershipStatus) . "</td>";
98 $invalidDataMessage .= "</tr>";
e418776c 99 }
6a488035
TO
100 $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>";
101 CRM_Core_Error::fatal($invalidDataMessage);
102 return FALSE;
6a488035 103 }
e418776c 104 }
6a488035
TO
105
106 if ($rev == '4.2.beta2') {
107 // note: error conditions are also checked in upgrade_4_2_beta2()
108 if (!defined('CIVICRM_SETTINGS_PATH')) {
109 $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(
353ffa53
TO
110 1 => self::SETTINGS_SNIPPET,
111 ));
0db6c3e1
TO
112 }
113 elseif (preg_match(self::SETTINGS_SNIPPET_PATTERN, file_get_contents(CIVICRM_SETTINGS_PATH))) {
6a488035 114 // OK, nothing to do
0db6c3e1
TO
115 }
116 elseif (!is_writable(CIVICRM_SETTINGS_PATH)) {
6a488035 117 $preUpgradeMessage .= '<br />' . ts('The settings file (%1) must be updated. Please make it writable or manually add these lines:<pre>%2</pre>', array(
353ffa53
TO
118 1 => CIVICRM_SETTINGS_PATH,
119 2 => self::SETTINGS_SNIPPET,
120 ));
6a488035
TO
121 }
122 }
123 if ($rev == '4.2.2' && version_compare($currentVer, '3.3.alpha1') >= 0) {
124 $query = " SELECT cli.id
125FROM `civicrm_line_item` cli
126INNER JOIN civicrm_membership_payment cmp ON cmp.contribution_id = cli.entity_id AND cli.entity_table = 'civicrm_contribution'
127INNER JOIN civicrm_price_field_value cpfv ON cpfv.id = cli.price_field_value_id
128INNER JOIN civicrm_price_field cpf ON cpf.id = cpfv.price_field_id and cpf.id != cli.price_field_id
129INNER JOIN civicrm_price_set cps ON cps.id = cpf.price_set_id AND cps.name <>'default_membership_type_amount' ";
130 $dao = CRM_Core_DAO::executeQuery($query);
131 if ($dao->N) {
86bfa4f6 132 $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
133 }
134 }
135
136 if (version_compare($rev, '4.2.9') >= 0) {
137 //CRM-11980
138 $sql = "SELECT id FROM civicrm_option_group WHERE name LIKE 'civicrm_price_field.amount.%' LIMIT 1";
139 $dao = CRM_Core_DAO::executeQuery($sql);
140 if ($dao->fetch()) {
141 $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 142 CRM_Core_Error::fatal($errors);
6a488035 143 return FALSE;
e418776c 144 }
6a488035
TO
145 }
146 }
147
148 /**
149 * Compute any messages which should be displayed after upgrade
150 *
5a4f6742
CW
151 * @param string $postUpgradeMessage
152 * alterable.
153 * @param string $rev
154 * an intermediate version; note that setPostUpgradeMessage is called repeatedly with different $revs.
6a488035
TO
155 * @return void
156 */
00be9182 157 public function setPostUpgradeMessage(&$postUpgradeMessage, $rev) {
6a488035
TO
158 if ($rev == '4.2.beta5') {
159 $config = CRM_Core_Config::singleton();
160 if (!empty($config->extensionsDir)) {
161 $postUpgradeMessage .= '<br />' . ts('Please <a href="%1" target="_blank">configure the Extension Resource URL</a>.', array(
353ffa53
TO
162 1 => CRM_Utils_System::url('civicrm/admin/setting/url', 'reset=1'),
163 ));
e418776c 164 }
6a488035
TO
165 }
166 if ($rev == '4.2.7') {
167 $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 168 }
6a488035
TO
169 }
170
624e56fa
EM
171 /**
172 * @param $rev
173 */
00be9182 174 public function upgrade_4_2_alpha1($rev) {
6a488035
TO
175 //checking whether the foreign key exists before dropping it
176 //drop foreign key queries of CRM-9850
177 $params = array();
e418776c 178 $tables = array(
353ffa53
TO
179 'civicrm_contribution_page' => 'FK_civicrm_contribution_page_payment_processor_id',
180 'civicrm_event' => 'FK_civicrm_event_payment_processor_id',
181 'civicrm_group' => 'FK_civicrm_group_saved_search_id',
182 );
9b873358 183 foreach ($tables as $tableName => $fKey) {
e418776c 184 $foreignKeyExists = CRM_Core_DAO::checkConstraintExists($tableName, $fKey);
9b873358 185 if ($foreignKeyExists) {
6a488035
TO
186 CRM_Core_DAO::executeQuery("ALTER TABLE {$tableName} DROP FOREIGN KEY {$fKey}", $params, TRUE, NULL, FALSE, FALSE);
187 CRM_Core_DAO::executeQuery("ALTER TABLE {$tableName} DROP INDEX {$fKey}", $params, TRUE, NULL, FALSE, FALSE);
188 }
189 }
190 // Drop index UI_title for civicrm_price_set
7c550ca0 191 $domain = new CRM_Core_DAO_Domain();
6a488035
TO
192 $domain->find(TRUE);
193 if ($domain->locales) {
194 $locales = explode(CRM_Core_DAO::VALUE_SEPARATOR, $domain->locales);
195 foreach ($locales as $locale) {
196 $query = "SHOW KEYS FROM `civicrm_price_set` WHERE key_name = 'UI_title_{$locale}'";
197 $dao = CRM_Core_DAO::executeQuery($query, $params, TRUE, NULL, FALSE, FALSE);
198 if ($dao->N) {
199 CRM_Core_DAO::executeQuery("ALTER TABLE `civicrm_price_set` DROP INDEX `UI_title_{$locale}`", $params, TRUE, NULL, FALSE, FALSE);
200 }
201 }
0db6c3e1
TO
202 }
203 else {
6a488035
TO
204 $query = "SHOW KEYS FROM `civicrm_price_set` WHERE key_name = 'UI_title'";
205 $dao = CRM_Core_DAO::executeQuery($query);
206 if ($dao->N) {
207 CRM_Core_DAO::executeQuery("ALTER TABLE `civicrm_price_set` DROP INDEX `UI_title`");
208 }
209 }
210
211 // Some steps take a long time, so we break them up into separate
212 // tasks and enqueue them separately.
d1401e86 213 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => '4.2.alpha1')), 'task_4_2_x_runSql', $rev);
6a488035
TO
214 $this->addTask(ts('Upgrade DB to 4.2.alpha1: Price Sets'), 'task_4_2_alpha1_createPriceSets', $rev);
215 self::convertContribution();
216 $this->addTask(ts('Upgrade DB to 4.2.alpha1: Event Profile'), 'task_4_2_alpha1_eventProfile');
217 }
218
624e56fa
EM
219 /**
220 * @param $rev
221 */
00be9182 222 public function upgrade_4_2_beta2($rev) {
6a488035
TO
223 // note: error conditions are also checked in setPreUpgradeMessage()
224 if (defined('CIVICRM_SETTINGS_PATH')) {
225 if (!preg_match(self::SETTINGS_SNIPPET_PATTERN, file_get_contents(CIVICRM_SETTINGS_PATH))) {
226 if (is_writable(CIVICRM_SETTINGS_PATH)) {
227 file_put_contents(CIVICRM_SETTINGS_PATH, self::SETTINGS_SNIPPET, FILE_APPEND);
228 }
229 }
230 }
231 }
232
624e56fa
EM
233 /**
234 * @param $rev
235 */
00be9182 236 public function upgrade_4_2_beta3($rev) {
d1401e86 237 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => '4.2.beta3')), 'task_4_2_x_runSql', $rev);
6a488035
TO
238 $minParticipantId = CRM_Core_DAO::singleValueQuery('SELECT coalesce(min(id),0) FROM civicrm_participant');
239 $maxParticipantId = CRM_Core_DAO::singleValueQuery('SELECT coalesce(max(id),0) FROM civicrm_participant');
240
241 for ($startId = $minParticipantId; $startId <= $maxParticipantId; $startId += self::BATCH_SIZE) {
242 $endId = $startId + self::BATCH_SIZE - 1;
243 $title = ts('Upgrade DB to 4.2.alpha1: Participant (%1 => %2)', array(1 => $startId, 2 => $endId));
244 $this->addTask($title, 'task_4_2_alpha1_convertParticipants', $startId, $endId);
245 }
246 }
247
624e56fa
EM
248 /**
249 * @param $rev
250 */
00be9182 251 public function upgrade_4_2_beta5($rev) {
6a488035
TO
252 // CRM-10629 Create a setting for extension URLs
253 // For some reason, this isn't working when placed in the .sql file
254 CRM_Core_DAO::executeQuery("
255 INSERT INTO civicrm_setting(group_name,name,value,domain_id,is_domain)
256 VALUES ('URL Preferences', 'extensionsURL',NULL,1,1);
257 ");
258 }
259
624e56fa
EM
260 /**
261 * @param $rev
262 */
00be9182 263 public function upgrade_4_2_0($rev) {
d1401e86 264 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => '4.2.0')), 'task_4_2_x_runSql', $rev);
6a488035
TO
265 }
266
624e56fa
EM
267 /**
268 * @param $rev
269 */
00be9182 270 public function upgrade_4_2_2($rev) {
d1401e86 271 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => '4.2.2')), 'task_4_2_x_runSql', $rev);
6a488035
TO
272 //create line items for memberships and participants for api/import
273 self::convertContribution();
274
275 // CRM-10937 Fix the title on civicrm_dedupe_rule_group
276 $upgrade = new CRM_Upgrade_Form();
277 if ($upgrade->multilingual) {
278 // Check if the 'title' field exists
279 $query = "SELECT column_name
280 FROM information_schema.COLUMNS
281 WHERE table_name = 'civicrm_dedupe_rule_group'
282 AND table_schema = DATABASE()
283 AND column_name = 'title'";
284
285 $dao = CRM_Core_DAO::executeQuery($query);
286
287 if (!$dao->N) {
7c550ca0 288 $domain = new CRM_Core_DAO_Domain();
6a488035
TO
289 $domain->find(TRUE);
290
291 if ($domain->locales) {
292 $locales = explode(CRM_Core_DAO::VALUE_SEPARATOR, $domain->locales);
293 $locale = array_shift($locales);
294
295 // Use the first language (they should all have the same value)
296 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);
297
298 // Drop remaining the column for the remaining languages
299 foreach ($locales as $locale) {
300 CRM_Core_DAO::executeQuery("ALTER TABLE `civicrm_dedupe_rule_group` DROP `title_{$locale}`", $params, TRUE, NULL, FALSE, FALSE);
301 }
302 }
303 }
304 }
305 }
306
624e56fa
EM
307 /**
308 * @param $rev
309 */
00be9182 310 public function upgrade_4_2_3($rev) {
d1401e86 311 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => '4.2.3')), 'task_4_2_x_runSql', $rev);
6a488035
TO
312 // CRM-10953 Remove duplicate activity type for 'Reminder Sent' which is mistakenly inserted by 4.2.alpha1 upgrade script
313 $queryMin = "
314SELECT coalesce(min(value),0) from civicrm_option_value ov
315WHERE ov.option_group_id =
316 (SELECT id from civicrm_option_group og WHERE og.name = 'activity_type') AND
317ov.name = 'Reminder Sent'";
318
319 $minReminderSent = CRM_Core_DAO::singleValueQuery($queryMin);
320
321 $queryMax = "
322SELECT coalesce(max(value),0) from civicrm_option_value ov
323WHERE ov.option_group_id =
324 (SELECT id from civicrm_option_group og WHERE og.name = 'activity_type') AND
325ov.name = 'Reminder Sent'";
326
327 $maxReminderSent = CRM_Core_DAO::singleValueQuery($queryMax);
328
329 // If we have two different values, replace new value with original in any activities
330 if ($maxReminderSent > $minReminderSent) {
331 $query = "
332UPDATE civicrm_activity
333SET activity_type_id = {$minReminderSent}
334WHERE activity_type_id = {$maxReminderSent}";
335
336 CRM_Core_DAO::executeQuery($query);
337
338 // Then delete the newer (duplicate) option_value row
339 $query = "
340DELETE from civicrm_option_value
341 WHERE option_group_id =
342 (SELECT id from civicrm_option_group og WHERE og.name = 'activity_type') AND
343 value = '{$maxReminderSent}'";
344
345 CRM_Core_DAO::executeQuery($query);
346 }
347 }
348
624e56fa
EM
349 /**
350 * @param $rev
351 */
00be9182 352 public function upgrade_4_2_5($rev) {
d1401e86 353 $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => '4.2.5')), 'task_4_2_x_runSql', $rev);
6a488035
TO
354 //CRM-11077
355 $sql = " SELECT cpse.entity_id, cpse.price_set_id
356FROM `civicrm_price_set_entity` cpse
357LEFT JOIN civicrm_price_set cps ON cps.id = cpse.price_set_id
358LEFT JOIN civicrm_price_set_entity cpse1 ON cpse1.price_set_id = cpse.price_set_id
359WHERE cpse.entity_table = 'civicrm_event' AND cps.is_quick_config = 1
360GROUP BY cpse.id
361HAVING COUNT(cpse.price_set_id) > 1 AND MIN(cpse1.id) <> cpse.id ";
362
363 $dao = CRM_Core_DAO::executeQuery($sql);
364 while ($dao->fetch()) {
365 if ($dao->price_set_id) {
366 $copyPriceSet = &CRM_Upgrade_Snapshot_V4p2_Price_BAO_Set::copy($dao->price_set_id);
367 CRM_Upgrade_Snapshot_V4p2_Price_BAO_Set::addTo('civicrm_event', $dao->entity_id, $copyPriceSet->id);
368 }
369 }
370 }
371
9b873358 372 public function convertContribution() {
6a488035
TO
373 $minContributionId = CRM_Core_DAO::singleValueQuery('SELECT coalesce(min(id),0) FROM civicrm_contribution');
374 $maxContributionId = CRM_Core_DAO::singleValueQuery('SELECT coalesce(max(id),0) FROM civicrm_contribution');
375 for ($startId = $minContributionId; $startId <= $maxContributionId; $startId += self::BATCH_SIZE) {
376 $endId = $startId + self::BATCH_SIZE - 1;
377 $title = ts('Upgrade DB to 4.2.alpha1: Contributions (%1 => %2)', array(1 => $startId, 2 => $endId));
378 $this->addTask($title, 'task_4_2_alpha1_convertContributions', $startId, $endId);
379 }
380 $minParticipantId = CRM_Core_DAO::singleValueQuery('SELECT coalesce(min(id),0) FROM civicrm_participant');
381 $maxParticipantId = CRM_Core_DAO::singleValueQuery('SELECT coalesce(max(id),0) FROM civicrm_participant');
382
383 for ($startId = $minParticipantId; $startId <= $maxParticipantId; $startId += self::BATCH_SIZE) {
384 $endId = $startId + self::BATCH_SIZE - 1;
385 $title = ts('Upgrade DB to 4.2.alpha1: Participant (%1 => %2)', array(1 => $startId, 2 => $endId));
386 $this->addTask($title, 'task_4_2_alpha1_convertParticipants', $startId, $endId);
387 }
388 }
389
390 /**
391 * (Queue Task Callback)
392 *
393 * Upgrade code to create priceset for contribution pages and events
394 */
00be9182 395 public static function task_4_2_alpha1_createPriceSets(CRM_Queue_TaskContext $ctx, $rev) {
6a488035 396 $upgrade = new CRM_Upgrade_Form();
9d72cede 397 $daoName = array(
353ffa53
TO
398 'civicrm_contribution_page' => array(
399 'CRM_Contribute_BAO_ContributionPage',
400 CRM_Core_Component::getComponentID('CiviContribute'),
401 ),
402 'civicrm_event' => array(
403 'CRM_Event_BAO_Event',
404 CRM_Core_Component::getComponentID('CiviEvent'),
405 ),
406 );
6a488035
TO
407
408 // get all option group used for event and contribution page
409 $query = "
410SELECT id, name
411FROM civicrm_option_group
412WHERE name LIKE '%.amount.%' ";
413 $dao = CRM_Core_DAO::executeQuery($query);
414 while ($dao->fetch()) {
415 $addTo = explode('.', $dao->name);
a7488080 416 if (!empty($addTo[2])) {
e418776c 417 $options = array('optionGroup' => $dao->name);
6a488035
TO
418 self::createPriceSet($daoName, $addTo, $options);
419 }
420 CRM_Core_OptionGroup::deleteAssoc($dao->name);
421 }
422
423 //create pricesets for contribution with only other amount
424 $query = "
425SELECT ccp.id as contribution_page_id, ccp.is_allow_other_amount, cmb.id as membership_block_id
426FROM civicrm_contribution_page ccp
427LEFT JOIN civicrm_membership_block cmb ON cmb.entity_id = ccp.id AND cmb.entity_table = 'civicrm_contribution_page'
428LEFT JOIN civicrm_price_set_entity cpse ON cpse.entity_id = ccp.id and cpse.entity_table = 'civicrm_contribution_page'
429WHERE cpse.price_set_id IS NULL";
430 $dao = CRM_Core_DAO::executeQuery($query);
431 $addTo = array('civicrm_contribution_page');
432 while ($dao->fetch()) {
433 $addTo[2] = $dao->contribution_page_id;
e418776c 434 $options = array(
353ffa53 435 'otherAmount' => $dao->is_allow_other_amount,
7c550ca0 436 'membership' => $dao->membership_block_id,
353ffa53 437 );
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 463 $query = "SELECT title FROM {$addTo[0]} where id =%1";
353ffa53 464 $setParams['title'] = CRM_Core_DAO::singleValueQuery($query,
6a488035
TO
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
353ffa53 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'])) {
353ffa53 533 $dao = new CRM_Member_DAO_MembershipBlock();
6a488035 534 $dao->entity_table = 'civicrm_contribution_page';
353ffa53 535 $dao->entity_id = $addTo[2];
6a488035
TO
536
537 if ($dao->find(TRUE)) {
538 if ($dao->membership_types) {
539 $fieldParams = array(
353ffa53
TO
540 'name' => strtolower(CRM_Utils_String::munge("Membership Amount", '_', 245)),
541 'label' => "Membership Amount",
542 'is_required' => $dao->is_required,
6a488035 543 'is_display_amounts' => $dao->display_min_fee,
353ffa53
TO
544 'is_active' => $dao->is_active,
545 'price_set_id' => $priceSet->id,
546 'html_type' => 'Radio',
547 'weight' => 1,
6a488035
TO
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++;
353ffa53 554 $fieldParams['option_label'][$rowcount] = $membershipTypeDetail['name'];
6a488035
TO
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(
353ffa53
TO
565 'id' => $priceSet->id,
566 'extends' => CRM_Core_Component::getComponentID('CiviMember'),
6a488035
TO
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(
353ffa53
TO
576 'name' => strtolower(CRM_Utils_String::munge("Other Amount", '_', 245)),
577 'label' => "Other Amount",
578 'is_required' => 0,
6a488035 579 'is_display_amounts' => 0,
353ffa53
TO
580 'is_active' => 1,
581 'price_set_id' => $priceSet->id,
582 'html_type' => 'Text',
583 'weight' => 3,
6a488035 584 );
353ffa53 585 $fieldParams['option_label'][1] = "Other Amount";
6a488035
TO
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'),
353ffa53
TO
656 '3' => array(
657 CRM_Core_DAO::getFieldValue('CRM_Member_DAO_Membership', $result->membership_id, 'membership_type_id'),
7c550ca0 658 'Integer',
353ffa53 659 ),
6a488035
TO
660 );
661 $res = CRM_Core_DAO::executeQuery($sql, $params);
662 if ($res->fetch()) {
663 $lineParams += array(
664 'price_field_id' => $res->id,
665 'label' => $res->label,
666 'qty' => 1,
667 'unit_price' => $res->amount,
668 'line_total' => $res->amount,
669 'participant_count' => $res->count ? $res->count : 0,
670 'price_field_value_id' => $res->price_field_value_id,
671 );
672 }
673 else {
674 $lineParams['price_field_id'] = CRM_Core_DAO::getFieldValue('CRM_Upgrade_Snapshot_V4p2_Price_DAO_Field', $result->price_set_id, 'id', 'price_set_id');
675 $lineParams['label'] = 'Membership Amount';
676 $lineParams['qty'] = 1;
677 $lineParams['unit_price'] = $lineParams['line_total'] = $result->total_amount;
678 $lineParams['participant_count'] = 0;
679 }
680 }
681 else {
682 $sql .= "AND cpfv.amount = %2";
ab44179e
PJ
683
684 //CRM-12273
685 //check if price_set_id is exist, if not use the default contribution amount
9b873358 686 if (isset($result->price_set_id)) {
ab44179e
PJ
687 $priceSetId = $result->price_set_id;
688 }
92e4c2a5 689 else {
9da8dc8c 690 $defaultPriceSets = CRM_Price_BAO_PriceSet::getDefaultPriceSet();
ab44179e 691 foreach ($defaultPriceSets as $key => $pSet) {
9b873358 692 if ($pSet['name'] == 'contribution_amount') {
ab44179e
PJ
693 $priceSetId = $pSet['setID'];
694 }
695 }
696 }
697
6a488035 698 $params = array(
ab44179e 699 '1' => array($priceSetId, 'Integer'),
6a488035
TO
700 '2' => array($result->total_amount, 'String'),
701 );
702 $res = CRM_Core_DAO::executeQuery($sql, $params);
703 if ($res->fetch()) {
704 $lineParams += array(
705 'price_field_id' => $res->id,
706 'label' => $res->label,
707 'qty' => 1,
708 'unit_price' => $res->amount,
709 'line_total' => $res->amount,
710 'participant_count' => $res->count ? $res->count : 0,
711 'price_field_value_id' => $res->price_field_value_id,
712 );
713 }
714 else {
715 $params = array(
ab44179e 716 'price_set_id' => $priceSetId,
6a488035
TO
717 'name' => 'other_amount',
718 );
719 $defaults = array();
720 CRM_Upgrade_Snapshot_V4p2_Price_BAO_Field::retrieve($params, $defaults);
721 if (!empty($defaults)) {
722 $lineParams['price_field_id'] = $defaults['id'];
723 $lineParams['label'] = $defaults['label'];
7c550ca0
WA
724 $lineParams['price_field_value_id']
725 = CRM_Core_DAO::getFieldValue('CRM_Upgrade_Snapshot_V4p2_Price_DAO_FieldValue', $defaults['id'], 'id', 'price_field_id');
6a488035
TO
726 }
727 else {
7c550ca0
WA
728 $lineParams['price_field_id']
729 = CRM_Core_DAO::getFieldValue('CRM_Upgrade_Snapshot_V4p2_Price_DAO_Field', $priceSetId, 'id', 'price_set_id');
6a488035
TO
730 $lineParams['label'] = 'Contribution Amount';
731 }
732 $lineParams['qty'] = 1;
733 $lineParams['participant_count'] = 0;
734 $lineParams['unit_price'] = $lineParams['line_total'] = $result->total_amount;
735 }
736 }
737 CRM_Upgrade_Snapshot_V4p2_Price_BAO_LineItem::create($lineParams);
738 }
739
740 return TRUE;
741 }
742
743 /**
744 * (Queue Task Callback)
745 *
746 * Find any participant records and create corresponding line-item
747 * records.
748 *
77b97be7 749 * @param CRM_Queue_TaskContext $ctx
5a4f6742
CW
750 * @param int $startId
751 * the first/lowest participant ID to convert.
752 * @param int $endId
753 * the last/highest participant ID to convert.
77b97be7
EM
754 *
755 * @return bool
6a488035 756 */
00be9182 757 public static function task_4_2_alpha1_convertParticipants(CRM_Queue_TaskContext $ctx, $startId, $endId) {
6a488035
TO
758 $upgrade = new CRM_Upgrade_Form();
759 //create lineitems for participant in edge cases using default price set for contribution.
760 $query = "
761SELECT cp.id as participant_id, cp.fee_amount, cp.fee_level,ce.is_monetary,
762 cpse.price_set_id, cpf.id as price_field_id, cpfv.id as price_field_value_id
763FROM civicrm_participant cp
764LEFT JOIN civicrm_line_item cli ON cli.entity_id=cp.id and cli.entity_table = 'civicrm_participant'
765LEFT JOIN civicrm_event ce ON ce.id=cp.event_id
766LEFT JOIN civicrm_price_set_entity cpse ON cp.event_id = cpse.entity_id and cpse.entity_table = 'civicrm_event'
767LEFT JOIN civicrm_price_field cpf ON cpf.price_set_id = cpse.price_set_id
768LEFT JOIN civicrm_price_field_value cpfv ON cpfv.price_field_id = cpf.id AND cpfv.label = cp.fee_level
769WHERE (cp.id BETWEEN %1 AND %2)
770AND cli.entity_id IS NULL AND cp.fee_amount IS NOT NULL";
771 $sqlParams = array(
772 1 => array($startId, 'Integer'),
773 2 => array($endId, 'Integer'),
774 );
775 $dao = CRM_Core_DAO::executeQuery($query, $sqlParams);
776 if ($dao->N) {
777 $defaultPriceSetId = CRM_Core_DAO::getFieldValue('CRM_Upgrade_Snapshot_V4p2_Price_DAO_Set', 'default_contribution_amount', 'id', 'name');
778 $priceSets = current(CRM_Upgrade_Snapshot_V4p2_Price_BAO_Set::getSetDetail($defaultPriceSetId));
779 $fieldID = key($priceSets['fields']);
780 }
781
782 while ($dao->fetch()) {
783 $lineParams = array(
784 'entity_table' => 'civicrm_participant',
785 'entity_id' => $dao->participant_id,
786 'label' => $dao->fee_level ? $dao->fee_level : ts('Default'),
787 'qty' => 1,
788 'unit_price' => $dao->fee_amount,
789 'line_total' => $dao->fee_amount,
790 'participant_count' => 1,
791 );
792 if ($dao->is_monetary && $dao->price_field_id) {
793 $lineParams += array(
794 'price_field_id' => $dao->price_field_id,
795 'price_field_value_id' => $dao->price_field_value_id,
796 );
797 $priceSetId = $dao->price_set_id;
0db6c3e1
TO
798 }
799 else {
6a488035
TO
800 $lineParams['price_field_id'] = $fieldID;
801 $priceSetId = $defaultPriceSetId;
802 }
803 CRM_Upgrade_Snapshot_V4p2_Price_BAO_LineItem::create($lineParams);
804 }
805 return TRUE;
806 }
807
808 /**
809 * (Queue Task Callback)
810 *
811 * Create an event registration profile with a single email field CRM-9587
812 */
00be9182 813 public static function task_4_2_alpha1_eventProfile(CRM_Queue_TaskContext $ctx) {
6a488035
TO
814 $upgrade = new CRM_Upgrade_Form();
815 $profileTitle = ts('Your Registration Info');
37044cde 816
6a488035
TO
817 $sql = "
818INSERT INTO civicrm_uf_group
819 (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)
820VALUES
37044cde 821 (1, 'Individual, Contact', %1, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0, NULL, 0, NULL, 0, 'event_registration', NULL, NULL, 0);
6a488035 822";
37044cde
ML
823
824 $params = array(
825 1 => array($profileTitle, 'String'),
826 );
827
828 CRM_Core_DAO::executeQuery($sql, $params);
6a488035
TO
829
830 $eventRegistrationId = CRM_Core_DAO::singleValueQuery('SELECT LAST_INSERT_ID()');
831 $sql = "
832INSERT INTO civicrm_uf_field
833 (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)
834VALUES
835 ({$eventRegistrationId}, 'email', 1, 0, 1, 1, NULL, NULL, 'User and User Admin Only', 0, 0, NULL, NULL, 'Email Address', 'Contact', 0);
836";
837 CRM_Core_DAO::executeQuery($sql);
838
839 $sql = "SELECT * FROM civicrm_event WHERE is_online_registration = 1;";
840 $events = CRM_Core_DAO::executeQuery($sql);
841 while ($events->fetch()) {
842 // Get next weights for the event registration profile
843 $nextMainWeight = $nextAdditionalWeight = 1;
844 $sql = "
845SELECT weight
846FROM civicrm_uf_join
847WHERE entity_id = {$events->id} AND module = 'CiviEvent'
848ORDER BY weight DESC LIMIT 1";
353ffa53 849 $weights = CRM_Core_DAO::executeQuery($sql);
6a488035
TO
850 $weights->fetch();
851 if (isset($weights->weight)) {
852 $nextMainWeight += $weights->weight;
853 }
854 $sql = "
855SELECT weight
856FROM civicrm_uf_join
857WHERE entity_id = {$events->id} AND module = 'CiviEvent_Additional'
858ORDER BY weight DESC LIMIT 1";
859 $weights = CRM_Core_DAO::executeQuery($sql);
860 $weights->fetch();
861 if (isset($weights->weight)) {
862 $nextAdditionalWeight += $weights->weight;
863 }
864 // Add an event registration profile to the event
865 $sql = "
866INSERT INTO civicrm_uf_join
867 (is_active, module, entity_table, entity_id, weight, uf_group_id)
868VALUES
869 (1, 'CiviEvent', 'civicrm_event', {$events->id}, {$nextMainWeight}, {$eventRegistrationId});
870";
871 CRM_Core_DAO::executeQuery($sql);
872 $sql = "
873INSERT INTO civicrm_uf_join
874 (is_active, module, entity_table, entity_id, weight, uf_group_id)
875VALUES
876 (1, 'CiviEvent_Additional', 'civicrm_event', {$events->id}, {$nextAdditionalWeight}, {$eventRegistrationId});";
877 CRM_Core_DAO::executeQuery($sql);
878 }
879 return TRUE;
880 }
881
882 /**
883 * Syntatic sugar for adding a task which (a) is in this class and (b) has
884 * a high priority.
885 *
886 * After passing the $funcName, you can also pass parameters that will go to
887 * the function. Note that all params must be serializable.
888 */
889 protected function addTask($title, $funcName) {
890 $queue = CRM_Queue_Service::singleton()->load(array(
891 'type' => 'Sql',
892 'name' => CRM_Upgrade_Form::QUEUE_NAME,
893 ));
894
895 $args = func_get_args();
896 $title = array_shift($args);
897 $funcName = array_shift($args);
898 $task = new CRM_Queue_Task(
899 array(get_class($this), $funcName),
900 $args,
901 $title
902 );
903 $queue->createItem($task, array('weight' => -1));
904 }
905
624e56fa
EM
906 /**
907 * @return array
908 */
6a488035
TO
909 public static function deleteInvalidPairs() {
910 require_once 'CRM/Member/PseudoConstant.php';
911 require_once 'CRM/Contribute/PseudoConstant.php';
912 $processedRecords = array();
913
914 $tempTableName1 = CRM_Core_DAO::createTempTableName();
915 // 1. collect all duplicates
916 $sql = "
917 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
918 FROM civicrm_membership_payment mp
919 INNER JOIN ( SELECT cmp.contribution_id
920 FROM civicrm_membership_payment cmp
921 LEFT JOIN civicrm_line_item cli ON cmp.contribution_id=cli.entity_id and cli.entity_table = 'civicrm_contribution'
922 WHERE cli.entity_id IS NULL
923 GROUP BY cmp.contribution_id
924 HAVING COUNT(cmp.membership_id) > 1) submp ON submp.contribution_id = mp.contribution_id
925 INNER JOIN civicrm_membership mem ON mem.id = mp.membership_id
926 INNER JOIN civicrm_contribution con ON con.id = mp.contribution_id
927 ORDER BY mp.contribution_id, mp.membership_id";
928 $dao = CRM_Core_DAO::executeQuery($sql);
929
930 $tempTableName2 = CRM_Core_DAO::createTempTableName();
931 // 2. collect all records that are going to be retained
932 $sql = "
933 CREATE TEMPORARY TABLE {$tempTableName2}
934 SELECT MAX(payment_id) as payment_id FROM {$tempTableName1} GROUP BY contribution_id HAVING COUNT(*) > 1";
935 CRM_Core_DAO::executeQuery($sql);
936
937 // 3. do the un-linking
938 $sql = "
939 DELETE cmp.*
940 FROM civicrm_membership_payment cmp
941 INNER JOIN $tempTableName1 temp1 ON temp1.payment_id = cmp.id
942 LEFT JOIN $tempTableName2 temp2 ON temp1.payment_id = temp2.payment_id
943 WHERE temp2.payment_id IS NULL";
944 CRM_Core_DAO::executeQuery($sql);
945
946 // 4. show all records that were Processed, i.e Retained vs Un-linked
947 $sql = "
948 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
949 FROM $tempTableName1 temp1
950 LEFT JOIN $tempTableName2 temp2 ON temp1.payment_id = temp2.payment_id";
951 $dao = CRM_Core_DAO::executeQuery($sql);
952 if ($dao->N) {
353ffa53 953 $membershipType = CRM_Member_PseudoConstant::membershipType();
6a488035
TO
954 $membershipStatus = CRM_Member_PseudoConstant::membershipStatus();
955 $contributionStatus = CRM_Contribute_PseudoConstant::contributionStatus();
956 while ($dao->fetch()) {
353ffa53
TO
957 $status = $dao->retain_id ? 'Retained' : 'Un-linked';
958 $memType = CRM_Utils_Array::value($dao->membership_type_id, $membershipType);
959 $memStatus = CRM_Utils_Array::value($dao->status_id, $membershipStatus);
960 $contribStatus = CRM_Utils_Array::value($dao->contribution_status_id, $contributionStatus);
961 $processedRecords[] = array(
962 $dao->contact_id,
963 $dao->contribution_id,
964 $contribStatus,
965 $dao->membership_id,
966 $memType,
967 $dao->start_date,
968 $dao->end_date,
969 $memStatus,
7c550ca0 970 $status,
353ffa53 971 );
e418776c 972 }
6a488035
TO
973 }
974
481a74f4 975 if (!empty($processedRecords)) {
6a488035 976 CRM_Core_Error::debug_log_message("deleteInvalidPairs() - The following records have been processed. Membership records with action:");
481a74f4
TO
977 CRM_Core_Error::debug_log_message("Contact ID, ContributionID, Contribution Status, MembershipID, Membership Type, Start Date, End Date, Membership Status, Action");
978 foreach ($processedRecords as $record) {
6a488035
TO
979 CRM_Core_Error::debug_log_message(implode(', ', $record));
980 }
0db6c3e1
TO
981 }
982 else {
6a488035
TO
983 CRM_Core_Error::debug_log_message("deleteInvalidPairs() - Could not find any records to process.");
984 }
985 return $processedRecords;
986 }
987
988}