CRM-16425 Added CiviCRM Licensing Exception in header
[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 +--------------------------------------------------------------------+
e7112fa7 6 | Copyright CiviCRM LLC (c) 2004-2015 |
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 |
c73475ea 12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
6a488035
TO
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 |
c73475ea
WA
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
6a488035
TO
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 +--------------------------------------------------------------------+
d25dd0ee 26 */
6a488035
TO
27
28/**
29 *
30 * @package CRM
e7112fa7 31 * @copyright CiviCRM LLC (c) 2004-2015
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 /**
fe482240 50 * Compute any messages which should be displayed beforeupgrade.
6a488035
TO
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(
353ffa53
TO
111 1 => self::SETTINGS_SNIPPET,
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 118 $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
119 1 => CIVICRM_SETTINGS_PATH,
120 2 => self::SETTINGS_SNIPPET,
121 ));
6a488035
TO
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 /**
fe482240 150 * Compute any messages which should be displayed after upgrade.
6a488035 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(
353ffa53
TO
163 1 => CRM_Utils_System::url('civicrm/admin/setting/url', 'reset=1'),
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 179 $tables = array(
353ffa53
TO
180 'civicrm_contribution_page' => 'FK_civicrm_contribution_page_payment_processor_id',
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
7c550ca0 192 $domain = new CRM_Core_DAO_Domain();
6a488035
TO
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) {
7c550ca0 289 $domain = new CRM_Core_DAO_Domain();
6a488035
TO
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 398 $daoName = array(
353ffa53
TO
399 'civicrm_contribution_page' => array(
400 'CRM_Contribute_BAO_ContributionPage',
401 CRM_Core_Component::getComponentID('CiviContribute'),
402 ),
403 'civicrm_event' => array(
404 'CRM_Event_BAO_Event',
405 CRM_Core_Component::getComponentID('CiviEvent'),
406 ),
407 );
6a488035
TO
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 435 $options = array(
353ffa53 436 'otherAmount' => $dao->is_allow_other_amount,
7c550ca0 437 'membership' => $dao->membership_block_id,
353ffa53 438 );
6a488035
TO
439 self::createPriceSet($daoName, $addTo, $options);
440 }
441
442 return TRUE;
443 }
444
445 /**
446 * (Queue Task Callback)
447 */
00be9182 448 public static function task_4_2_x_runSql(CRM_Queue_TaskContext $ctx, $rev) {
e418776c
TO
449 $upgrade = new CRM_Upgrade_Form();
450 $upgrade->processSQL($rev);
6a488035 451
e418776c
TO
452 // now rebuild all the triggers
453 // CRM-9716
454 // FIXME // CRM_Core_DAO::triggerRebuild();
6a488035 455
e418776c 456 return TRUE;
6a488035
TO
457 }
458
459 /**
460 *
c490a46a 461 * create price sets
6a488035 462 */
e418776c 463 public static function createPriceSet($daoName, $addTo, $options = array()) {
6a488035 464 $query = "SELECT title FROM {$addTo[0]} where id =%1";
353ffa53 465 $setParams['title'] = CRM_Core_DAO::singleValueQuery($query,
6a488035
TO
466 array(1 => array($addTo[2], 'Integer'))
467 );
468 $pageTitle = strtolower(CRM_Utils_String::munge($setParams['title'], '_', 245));
469
470 // an event or contrib page has been deleted but left the option group behind - (this may be fixed in later versions?)
471 // we should probably delete the option group - but at least early exit here as the code following it does not fatal
472 // CRM-10298
481a74f4 473 if (empty($pageTitle)) {
6a488035
TO
474 return;
475 }
476
477 $optionValue = array();
a7488080 478 if (!empty($options['optionGroup'])) {
6a488035 479 CRM_Core_OptionGroup::getAssoc($options['optionGroup'], $optionValue);
e418776c 480 if (empty($optionValue)) {
6a488035 481 return;
e418776c 482 }
6a488035 483 }
8cc574cf 484 elseif (empty($options['otherAmount']) && empty($options['membership'])) {
ab44179e
PJ
485 //CRM-12273
486 //if options group, otherAmount, membersip is empty then return, contribution should be default price set
487 return;
488 }
6a488035 489
353ffa53 490 if (!CRM_Core_DAO::getFieldValue('CRM_Upgrade_Snapshot_V4p2_Price_BAO_Set', $pageTitle, 'id', 'name', TRUE)) {
6a488035
TO
491 $setParams['name'] = $pageTitle;
492 }
493 else {
e418776c 494 $timeSec = explode(".", microtime(TRUE));
6a488035
TO
495 $setParams['name'] = $pageTitle . '_' . date('is', $timeSec[0]) . $timeSec[1];
496 }
497 $setParams['extends'] = $daoName[$addTo[0]][1];
498 $setParams['is_quick_config'] = 1;
499 $priceSet = CRM_Upgrade_Snapshot_V4p2_Price_BAO_Set::create($setParams);
500 CRM_Upgrade_Snapshot_V4p2_Price_BAO_Set::addTo($addTo[0], $addTo[2], $priceSet->id, 1);
501
502 $fieldParams['price_set_id'] = $priceSet->id;
a7488080 503 if (!empty($options['optionGroup'])) {
6a488035
TO
504 $fieldParams['html_type'] = 'Radio';
505 $fieldParams['is_required'] = 1;
506 if ($addTo[0] == 'civicrm_event') {
507 $query = "SELECT fee_label FROM civicrm_event where id =%1";
508 $fieldParams['name'] = $fieldParams['label'] = CRM_Core_DAO::singleValueQuery($query,
509 array(1 => array($addTo[2], 'Integer'))
510 );
511 $defaultAmountColumn = 'default_fee_id';
512 }
513 else {
514 $options['membership'] = 1;
515 $fieldParams['name'] = strtolower(CRM_Utils_String::munge("Contribution Amount", '_', 245));
516 $fieldParams['label'] = "Contribution Amount";
517 $defaultAmountColumn = 'default_amount_id';
518 $options['otherAmount'] = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_ContributionPage', $addTo[2], 'is_allow_other_amount');
a7488080 519 if (!empty($options['otherAmount'])) {
6a488035
TO
520 $fieldParams['is_required'] = 0;
521 }
522 }
523 $fieldParams['option_label'] = $optionValue['label'];
524 $fieldParams['option_amount'] = $optionValue['value'];
525 $fieldParams['option_weight'] = $optionValue['weight'];
f813f78e 526 $fieldParams['is_quick_config'] = $setParams['is_quick_config'];
6a488035
TO
527 if ($defaultAmount = CRM_Core_DAO::getFieldValue($daoName[$addTo[0]][0], $addTo[2], $defaultAmountColumn)) {
528 $fieldParams['default_option'] = array_search($defaultAmount, $optionValue['amount_id']);
529 }
530 $priceField = CRM_Upgrade_Snapshot_V4p2_Price_BAO_Field::create($fieldParams);
531
532 }
a7488080 533 if (!empty($options['membership'])) {
353ffa53 534 $dao = new CRM_Member_DAO_MembershipBlock();
6a488035 535 $dao->entity_table = 'civicrm_contribution_page';
353ffa53 536 $dao->entity_id = $addTo[2];
6a488035
TO
537
538 if ($dao->find(TRUE)) {
539 if ($dao->membership_types) {
540 $fieldParams = array(
353ffa53
TO
541 'name' => strtolower(CRM_Utils_String::munge("Membership Amount", '_', 245)),
542 'label' => "Membership Amount",
543 'is_required' => $dao->is_required,
6a488035 544 'is_display_amounts' => $dao->display_min_fee,
353ffa53
TO
545 'is_active' => $dao->is_active,
546 'price_set_id' => $priceSet->id,
547 'html_type' => 'Radio',
548 'weight' => 1,
6a488035
TO
549 );
550 $membershipTypes = unserialize($dao->membership_types);
551 $rowcount = 0;
552 foreach ($membershipTypes as $membershipType => $autoRenew) {
553 $membershipTypeDetail = CRM_Member_BAO_MembershipType::getMembershipTypeDetails($membershipType);
554 $rowcount++;
353ffa53 555 $fieldParams['option_label'][$rowcount] = $membershipTypeDetail['name'];
6a488035
TO
556 $fieldParams['option_amount'][$rowcount] = $membershipTypeDetail['minimum_fee'];
557 $fieldParams['option_weight'][$rowcount] = $rowcount;
558 $fieldParams['membership_type_id'][$rowcount] = $membershipType;
559 if ($membershipType == $dao->membership_type_default) {
560 $fieldParams['default_option'] = $rowcount;
561 }
562 }
563 $priceField = CRM_Upgrade_Snapshot_V4p2_Price_BAO_Field::create($fieldParams);
564
565 $setParams = array(
353ffa53
TO
566 'id' => $priceSet->id,
567 'extends' => CRM_Core_Component::getComponentID('CiviMember'),
6a488035
TO
568 'contribution_type_id' => CRM_Core_DAO::getFieldValue($daoName[$addTo[0]][0], $addTo[2], 'contribution_type_id'),
569 );
570 CRM_Upgrade_Snapshot_V4p2_Price_BAO_Set::create($setParams);
571 }
572 }
573 }
a7488080 574 if (!empty($options['otherAmount'])) {
6a488035
TO
575
576 $fieldParams = array(
353ffa53
TO
577 'name' => strtolower(CRM_Utils_String::munge("Other Amount", '_', 245)),
578 'label' => "Other Amount",
579 'is_required' => 0,
6a488035 580 'is_display_amounts' => 0,
353ffa53
TO
581 'is_active' => 1,
582 'price_set_id' => $priceSet->id,
583 'html_type' => 'Text',
584 'weight' => 3,
6a488035 585 );
353ffa53 586 $fieldParams['option_label'][1] = "Other Amount";
6a488035
TO
587 $fieldParams['option_amount'][1] = 1;
588 $fieldParams['option_weight'][1] = 1;
589 $priceField = CRM_Upgrade_Snapshot_V4p2_Price_BAO_Field::create($fieldParams);
590 }
591 }
592
593 /**
594 * (Queue Task Callback)
595 *
596 * Find any contribution records and create corresponding line-item
597 * records.
598 *
77b97be7 599 * @param CRM_Queue_TaskContext $ctx
5a4f6742
CW
600 * @param int $startId
601 * the first/lowest contribution ID to convert.
602 * @param int $endId
603 * the last/highest contribution ID to convert.
77b97be7
EM
604 *
605 * @return bool
6a488035 606 */
00be9182 607 public static function task_4_2_alpha1_convertContributions(CRM_Queue_TaskContext $ctx, $startId, $endId) {
6a488035
TO
608 $upgrade = new CRM_Upgrade_Form();
609 $query = "
610 INSERT INTO civicrm_line_item(`entity_table` ,`entity_id` ,`price_field_id` ,`label` , `qty` ,`unit_price` ,`line_total` ,`participant_count` ,`price_field_value_id`)
611 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
612 FROM civicrm_membership_payment cmp
613 LEFT JOIN `civicrm_contribution` cc ON cc.id = cmp.contribution_id
614 LEFT JOIN civicrm_line_item cli ON cc.id=cli.entity_id and cli.entity_table = 'civicrm_contribution'
615 LEFT JOIN civicrm_membership cm ON cm.id=cmp.membership_id
616 LEFT JOIN civicrm_membership_type cmt ON cmt.id = cm.membership_type_id
617 LEFT JOIN civicrm_price_field cpf ON BINARY cpf.name = cmt.member_of_contact_id
618 LEFT JOIN civicrm_price_field_value cpfv ON cpfv.membership_type_id = cm.membership_type_id AND cpf.id = cpfv.price_field_id
619 WHERE (cc.id BETWEEN %1 AND %2) AND cli.entity_id IS NULL ;
620 ";
621 $sqlParams = array(
622 1 => array($startId, 'Integer'),
623 2 => array($endId, 'Integer'),
624 );
625 CRM_Core_DAO::executeQuery($query, $sqlParams);
626
627 // create lineitems for contribution done for membership
628 $sql = "
629SELECT cc.id, cmp.membership_id, cpse.price_set_id, cc.total_amount
630FROM civicrm_contribution cc
631LEFT JOIN civicrm_line_item cli ON cc.id=cli.entity_id AND cli.entity_table = 'civicrm_contribution'
632LEFT JOIN civicrm_membership_payment cmp ON cc.id = cmp.contribution_id
633LEFT JOIN civicrm_participant_payment cpp ON cc.id = cpp.contribution_id
634LEFT JOIN civicrm_price_set_entity cpse on cpse.entity_table = 'civicrm_contribution_page' AND cpse.entity_id = cc.contribution_page_id
635WHERE (cc.id BETWEEN %1 AND %2)
636AND cli.entity_id IS NULL AND cc.contribution_page_id IS NOT NULL AND cpp.contribution_id IS NULL
637GROUP BY cc.id
638";
639 $result = CRM_Core_DAO::executeQuery($sql, $sqlParams);
640
641 while ($result->fetch()) {
642 $sql = "
643SELECT cpf.id, cpfv.id as price_field_value_id, cpfv.label, cpfv.amount, cpfv.count
644FROM civicrm_price_field cpf
645LEFT JOIN civicrm_price_field_value cpfv ON cpf.id = cpfv.price_field_id
646WHERE cpf.price_set_id = %1
647";
648 $lineParams = array(
649 'entity_table' => 'civicrm_contribution',
650 'entity_id' => $result->id,
651 );
652 if ($result->membership_id) {
653 $sql .= " AND cpf.name = %2 AND cpfv.membership_type_id = %3 ";
654 $params = array(
655 '1' => array($result->price_set_id, 'Integer'),
656 '2' => array('membership_amount', 'String'),
353ffa53
TO
657 '3' => array(
658 CRM_Core_DAO::getFieldValue('CRM_Member_DAO_Membership', $result->membership_id, 'membership_type_id'),
7c550ca0 659 'Integer',
353ffa53 660 ),
6a488035
TO
661 );
662 $res = CRM_Core_DAO::executeQuery($sql, $params);
663 if ($res->fetch()) {
664 $lineParams += array(
665 'price_field_id' => $res->id,
666 'label' => $res->label,
667 'qty' => 1,
668 'unit_price' => $res->amount,
669 'line_total' => $res->amount,
670 'participant_count' => $res->count ? $res->count : 0,
671 'price_field_value_id' => $res->price_field_value_id,
672 );
673 }
674 else {
675 $lineParams['price_field_id'] = CRM_Core_DAO::getFieldValue('CRM_Upgrade_Snapshot_V4p2_Price_DAO_Field', $result->price_set_id, 'id', 'price_set_id');
676 $lineParams['label'] = 'Membership Amount';
677 $lineParams['qty'] = 1;
678 $lineParams['unit_price'] = $lineParams['line_total'] = $result->total_amount;
679 $lineParams['participant_count'] = 0;
680 }
681 }
682 else {
683 $sql .= "AND cpfv.amount = %2";
ab44179e
PJ
684
685 //CRM-12273
686 //check if price_set_id is exist, if not use the default contribution amount
9b873358 687 if (isset($result->price_set_id)) {
ab44179e
PJ
688 $priceSetId = $result->price_set_id;
689 }
92e4c2a5 690 else {
9da8dc8c 691 $defaultPriceSets = CRM_Price_BAO_PriceSet::getDefaultPriceSet();
ab44179e 692 foreach ($defaultPriceSets as $key => $pSet) {
9b873358 693 if ($pSet['name'] == 'contribution_amount') {
ab44179e
PJ
694 $priceSetId = $pSet['setID'];
695 }
696 }
697 }
698
6a488035 699 $params = array(
ab44179e 700 '1' => array($priceSetId, 'Integer'),
6a488035
TO
701 '2' => array($result->total_amount, 'String'),
702 );
703 $res = CRM_Core_DAO::executeQuery($sql, $params);
704 if ($res->fetch()) {
705 $lineParams += array(
706 'price_field_id' => $res->id,
707 'label' => $res->label,
708 'qty' => 1,
709 'unit_price' => $res->amount,
710 'line_total' => $res->amount,
711 'participant_count' => $res->count ? $res->count : 0,
712 'price_field_value_id' => $res->price_field_value_id,
713 );
714 }
715 else {
716 $params = array(
ab44179e 717 'price_set_id' => $priceSetId,
6a488035
TO
718 'name' => 'other_amount',
719 );
720 $defaults = array();
721 CRM_Upgrade_Snapshot_V4p2_Price_BAO_Field::retrieve($params, $defaults);
722 if (!empty($defaults)) {
723 $lineParams['price_field_id'] = $defaults['id'];
724 $lineParams['label'] = $defaults['label'];
7c550ca0
WA
725 $lineParams['price_field_value_id']
726 = CRM_Core_DAO::getFieldValue('CRM_Upgrade_Snapshot_V4p2_Price_DAO_FieldValue', $defaults['id'], 'id', 'price_field_id');
6a488035
TO
727 }
728 else {
7c550ca0
WA
729 $lineParams['price_field_id']
730 = CRM_Core_DAO::getFieldValue('CRM_Upgrade_Snapshot_V4p2_Price_DAO_Field', $priceSetId, 'id', 'price_set_id');
6a488035
TO
731 $lineParams['label'] = 'Contribution Amount';
732 }
733 $lineParams['qty'] = 1;
734 $lineParams['participant_count'] = 0;
735 $lineParams['unit_price'] = $lineParams['line_total'] = $result->total_amount;
736 }
737 }
738 CRM_Upgrade_Snapshot_V4p2_Price_BAO_LineItem::create($lineParams);
739 }
740
741 return TRUE;
742 }
743
744 /**
745 * (Queue Task Callback)
746 *
747 * Find any participant records and create corresponding line-item
748 * records.
749 *
77b97be7 750 * @param CRM_Queue_TaskContext $ctx
5a4f6742
CW
751 * @param int $startId
752 * the first/lowest participant ID to convert.
753 * @param int $endId
754 * the last/highest participant ID to convert.
77b97be7
EM
755 *
756 * @return bool
6a488035 757 */
00be9182 758 public static function task_4_2_alpha1_convertParticipants(CRM_Queue_TaskContext $ctx, $startId, $endId) {
6a488035
TO
759 $upgrade = new CRM_Upgrade_Form();
760 //create lineitems for participant in edge cases using default price set for contribution.
761 $query = "
762SELECT cp.id as participant_id, cp.fee_amount, cp.fee_level,ce.is_monetary,
763 cpse.price_set_id, cpf.id as price_field_id, cpfv.id as price_field_value_id
764FROM civicrm_participant cp
765LEFT JOIN civicrm_line_item cli ON cli.entity_id=cp.id and cli.entity_table = 'civicrm_participant'
766LEFT JOIN civicrm_event ce ON ce.id=cp.event_id
767LEFT JOIN civicrm_price_set_entity cpse ON cp.event_id = cpse.entity_id and cpse.entity_table = 'civicrm_event'
768LEFT JOIN civicrm_price_field cpf ON cpf.price_set_id = cpse.price_set_id
769LEFT JOIN civicrm_price_field_value cpfv ON cpfv.price_field_id = cpf.id AND cpfv.label = cp.fee_level
770WHERE (cp.id BETWEEN %1 AND %2)
771AND cli.entity_id IS NULL AND cp.fee_amount IS NOT NULL";
772 $sqlParams = array(
773 1 => array($startId, 'Integer'),
774 2 => array($endId, 'Integer'),
775 );
776 $dao = CRM_Core_DAO::executeQuery($query, $sqlParams);
777 if ($dao->N) {
778 $defaultPriceSetId = CRM_Core_DAO::getFieldValue('CRM_Upgrade_Snapshot_V4p2_Price_DAO_Set', 'default_contribution_amount', 'id', 'name');
779 $priceSets = current(CRM_Upgrade_Snapshot_V4p2_Price_BAO_Set::getSetDetail($defaultPriceSetId));
780 $fieldID = key($priceSets['fields']);
781 }
782
783 while ($dao->fetch()) {
784 $lineParams = array(
785 'entity_table' => 'civicrm_participant',
786 'entity_id' => $dao->participant_id,
787 'label' => $dao->fee_level ? $dao->fee_level : ts('Default'),
788 'qty' => 1,
789 'unit_price' => $dao->fee_amount,
790 'line_total' => $dao->fee_amount,
791 'participant_count' => 1,
792 );
793 if ($dao->is_monetary && $dao->price_field_id) {
794 $lineParams += array(
795 'price_field_id' => $dao->price_field_id,
796 'price_field_value_id' => $dao->price_field_value_id,
797 );
798 $priceSetId = $dao->price_set_id;
0db6c3e1
TO
799 }
800 else {
6a488035
TO
801 $lineParams['price_field_id'] = $fieldID;
802 $priceSetId = $defaultPriceSetId;
803 }
804 CRM_Upgrade_Snapshot_V4p2_Price_BAO_LineItem::create($lineParams);
805 }
806 return TRUE;
807 }
808
809 /**
810 * (Queue Task Callback)
811 *
812 * Create an event registration profile with a single email field CRM-9587
813 */
00be9182 814 public static function task_4_2_alpha1_eventProfile(CRM_Queue_TaskContext $ctx) {
6a488035
TO
815 $upgrade = new CRM_Upgrade_Form();
816 $profileTitle = ts('Your Registration Info');
37044cde 817
6a488035
TO
818 $sql = "
819INSERT INTO civicrm_uf_group
820 (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)
821VALUES
37044cde 822 (1, 'Individual, Contact', %1, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0, NULL, 0, NULL, 0, 'event_registration', NULL, NULL, 0);
6a488035 823";
37044cde
ML
824
825 $params = array(
826 1 => array($profileTitle, 'String'),
827 );
828
829 CRM_Core_DAO::executeQuery($sql, $params);
6a488035
TO
830
831 $eventRegistrationId = CRM_Core_DAO::singleValueQuery('SELECT LAST_INSERT_ID()');
832 $sql = "
833INSERT INTO civicrm_uf_field
834 (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)
835VALUES
836 ({$eventRegistrationId}, 'email', 1, 0, 1, 1, NULL, NULL, 'User and User Admin Only', 0, 0, NULL, NULL, 'Email Address', 'Contact', 0);
837";
838 CRM_Core_DAO::executeQuery($sql);
839
840 $sql = "SELECT * FROM civicrm_event WHERE is_online_registration = 1;";
841 $events = CRM_Core_DAO::executeQuery($sql);
842 while ($events->fetch()) {
843 // Get next weights for the event registration profile
844 $nextMainWeight = $nextAdditionalWeight = 1;
845 $sql = "
846SELECT weight
847FROM civicrm_uf_join
848WHERE entity_id = {$events->id} AND module = 'CiviEvent'
849ORDER BY weight DESC LIMIT 1";
353ffa53 850 $weights = CRM_Core_DAO::executeQuery($sql);
6a488035
TO
851 $weights->fetch();
852 if (isset($weights->weight)) {
853 $nextMainWeight += $weights->weight;
854 }
855 $sql = "
856SELECT weight
857FROM civicrm_uf_join
858WHERE entity_id = {$events->id} AND module = 'CiviEvent_Additional'
859ORDER BY weight DESC LIMIT 1";
860 $weights = CRM_Core_DAO::executeQuery($sql);
861 $weights->fetch();
862 if (isset($weights->weight)) {
863 $nextAdditionalWeight += $weights->weight;
864 }
865 // Add an event registration profile to the event
866 $sql = "
867INSERT INTO civicrm_uf_join
868 (is_active, module, entity_table, entity_id, weight, uf_group_id)
869VALUES
870 (1, 'CiviEvent', 'civicrm_event', {$events->id}, {$nextMainWeight}, {$eventRegistrationId});
871";
872 CRM_Core_DAO::executeQuery($sql);
873 $sql = "
874INSERT INTO civicrm_uf_join
875 (is_active, module, entity_table, entity_id, weight, uf_group_id)
876VALUES
877 (1, 'CiviEvent_Additional', 'civicrm_event', {$events->id}, {$nextAdditionalWeight}, {$eventRegistrationId});";
878 CRM_Core_DAO::executeQuery($sql);
879 }
880 return TRUE;
881 }
882
883 /**
884 * Syntatic sugar for adding a task which (a) is in this class and (b) has
885 * a high priority.
886 *
887 * After passing the $funcName, you can also pass parameters that will go to
888 * the function. Note that all params must be serializable.
889 */
890 protected function addTask($title, $funcName) {
891 $queue = CRM_Queue_Service::singleton()->load(array(
892 'type' => 'Sql',
893 'name' => CRM_Upgrade_Form::QUEUE_NAME,
894 ));
895
896 $args = func_get_args();
897 $title = array_shift($args);
898 $funcName = array_shift($args);
899 $task = new CRM_Queue_Task(
900 array(get_class($this), $funcName),
901 $args,
902 $title
903 );
904 $queue->createItem($task, array('weight' => -1));
905 }
906
624e56fa
EM
907 /**
908 * @return array
909 */
6a488035
TO
910 public static function deleteInvalidPairs() {
911 require_once 'CRM/Member/PseudoConstant.php';
912 require_once 'CRM/Contribute/PseudoConstant.php';
913 $processedRecords = array();
914
915 $tempTableName1 = CRM_Core_DAO::createTempTableName();
916 // 1. collect all duplicates
917 $sql = "
918 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
919 FROM civicrm_membership_payment mp
920 INNER JOIN ( SELECT cmp.contribution_id
921 FROM civicrm_membership_payment cmp
922 LEFT JOIN civicrm_line_item cli ON cmp.contribution_id=cli.entity_id and cli.entity_table = 'civicrm_contribution'
923 WHERE cli.entity_id IS NULL
924 GROUP BY cmp.contribution_id
925 HAVING COUNT(cmp.membership_id) > 1) submp ON submp.contribution_id = mp.contribution_id
926 INNER JOIN civicrm_membership mem ON mem.id = mp.membership_id
927 INNER JOIN civicrm_contribution con ON con.id = mp.contribution_id
928 ORDER BY mp.contribution_id, mp.membership_id";
929 $dao = CRM_Core_DAO::executeQuery($sql);
930
931 $tempTableName2 = CRM_Core_DAO::createTempTableName();
932 // 2. collect all records that are going to be retained
933 $sql = "
934 CREATE TEMPORARY TABLE {$tempTableName2}
935 SELECT MAX(payment_id) as payment_id FROM {$tempTableName1} GROUP BY contribution_id HAVING COUNT(*) > 1";
936 CRM_Core_DAO::executeQuery($sql);
937
938 // 3. do the un-linking
939 $sql = "
940 DELETE cmp.*
941 FROM civicrm_membership_payment cmp
942 INNER JOIN $tempTableName1 temp1 ON temp1.payment_id = cmp.id
943 LEFT JOIN $tempTableName2 temp2 ON temp1.payment_id = temp2.payment_id
944 WHERE temp2.payment_id IS NULL";
945 CRM_Core_DAO::executeQuery($sql);
946
947 // 4. show all records that were Processed, i.e Retained vs Un-linked
948 $sql = "
949 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
950 FROM $tempTableName1 temp1
951 LEFT JOIN $tempTableName2 temp2 ON temp1.payment_id = temp2.payment_id";
952 $dao = CRM_Core_DAO::executeQuery($sql);
953 if ($dao->N) {
353ffa53 954 $membershipType = CRM_Member_PseudoConstant::membershipType();
6a488035
TO
955 $membershipStatus = CRM_Member_PseudoConstant::membershipStatus();
956 $contributionStatus = CRM_Contribute_PseudoConstant::contributionStatus();
957 while ($dao->fetch()) {
353ffa53
TO
958 $status = $dao->retain_id ? 'Retained' : 'Un-linked';
959 $memType = CRM_Utils_Array::value($dao->membership_type_id, $membershipType);
960 $memStatus = CRM_Utils_Array::value($dao->status_id, $membershipStatus);
961 $contribStatus = CRM_Utils_Array::value($dao->contribution_status_id, $contributionStatus);
962 $processedRecords[] = array(
963 $dao->contact_id,
964 $dao->contribution_id,
965 $contribStatus,
966 $dao->membership_id,
967 $memType,
968 $dao->start_date,
969 $dao->end_date,
970 $memStatus,
7c550ca0 971 $status,
353ffa53 972 );
e418776c 973 }
6a488035
TO
974 }
975
481a74f4 976 if (!empty($processedRecords)) {
6a488035 977 CRM_Core_Error::debug_log_message("deleteInvalidPairs() - The following records have been processed. Membership records with action:");
481a74f4
TO
978 CRM_Core_Error::debug_log_message("Contact ID, ContributionID, Contribution Status, MembershipID, Membership Type, Start Date, End Date, Membership Status, Action");
979 foreach ($processedRecords as $record) {
6a488035
TO
980 CRM_Core_Error::debug_log_message(implode(', ', $record));
981 }
0db6c3e1
TO
982 }
983 else {
6a488035
TO
984 CRM_Core_Error::debug_log_message("deleteInvalidPairs() - Could not find any records to process.");
985 }
986 return $processedRecords;
987 }
988
989}