CRM-19953 refactor getUsedFor to break down & comment heavily.
[civicrm-core.git] / CRM / Price / BAO / PriceSet.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
7e9e8871 4 | CiviCRM version 4.7 |
6a488035 5 +--------------------------------------------------------------------+
0f03f337 6 | Copyright CiviCRM LLC (c) 2004-2017 |
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 and the CiviCRM Licensing Exception. |
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 and the CiviCRM Licensing Exception along |
21 | 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 +--------------------------------------------------------------------+
e70a7fc0 26 */
6a488035
TO
27
28/**
29 *
30 * @package CRM
0f03f337 31 * @copyright CiviCRM LLC (c) 2004-2017
6a488035
TO
32 */
33
34/**
1bde39c7 35 * Business object for managing price sets.
6a488035
TO
36 *
37 */
9da8dc8c 38class CRM_Price_BAO_PriceSet extends CRM_Price_DAO_PriceSet {
6a488035 39
71ba92c4 40 /**
fe482240 41 * Static field for default price set details.
71ba92c4
PN
42 *
43 * @var array
71ba92c4
PN
44 */
45 static $_defaultPriceSet = NULL;
46
6a488035 47 /**
fe482240 48 * Class constructor.
6a488035 49 */
00be9182 50 public function __construct() {
6a488035
TO
51 parent::__construct();
52 }
53
54 /**
fe482240 55 * Takes an associative array and creates a price set object.
6a488035 56 *
414c1420
TO
57 * @param array $params
58 * (reference) an assoc array of name/value pairs.
6a488035 59 *
16b10e64 60 * @return CRM_Price_DAO_PriceSet
6a488035 61 */
00be9182 62 public static function create(&$params) {
22e263ad 63 if (empty($params['id']) && empty($params['name'])) {
e0c1764e
EM
64 $params['name'] = CRM_Utils_String::munge($params['title'], '_', 242);
65 }
e68e1c9a
PN
66 $priceSetID = NULL;
67 $validatePriceSet = TRUE;
e10ac060 68 if (!empty($params['extends']) && is_array($params['extends'])) {
e68e1c9a
PN
69 if (!array_key_exists(CRM_Core_Component::getComponentID('CiviEvent'), $params['extends'])
70 || !array_key_exists(CRM_Core_Component::getComponentID('CiviMember'), $params['extends'])
71 ) {
72 $validatePriceSet = FALSE;
73 }
076809e3
JV
74 $params['extends'] = CRM_Utils_Array::implodePadded($params['extends']);
75 }
e68e1c9a
PN
76 else {
77 $priceSetID = CRM_Utils_Array::value('id', $params);
78 }
79 // CRM-16189
f7e2bf47
PN
80 if ($validatePriceSet && !empty($params['financial_type_id'])) {
81 CRM_Financial_BAO_FinancialAccount::validateFinancialType(
82 $params['financial_type_id'],
e68e1c9a
PN
83 $priceSetID
84 );
e68e1c9a 85 }
9da8dc8c 86 $priceSetBAO = new CRM_Price_BAO_PriceSet();
6a488035
TO
87 $priceSetBAO->copyValues($params);
88 if (self::eventPriceSetDomainID()) {
89 $priceSetBAO->domain_id = CRM_Core_Config::domainID();
90 }
91 return $priceSetBAO->save();
92 }
93
94 /**
fe482240 95 * Fetch object based on array of properties.
6a488035 96 *
414c1420
TO
97 * @param array $params
98 * (reference ) an assoc array of name/value pairs.
99 * @param array $defaults
100 * (reference ) an assoc array to hold the flattened values.
6a488035 101 *
16b10e64 102 * @return CRM_Price_DAO_PriceSet
6a488035 103 */
00be9182 104 public static function retrieve(&$params, &$defaults) {
9da8dc8c 105 return CRM_Core_DAO::commonRetrieve('CRM_Price_DAO_PriceSet', $params, $defaults);
6a488035
TO
106 }
107
108 /**
fe482240 109 * Update the is_active flag in the db.
6a488035 110 *
414c1420
TO
111 * @param int $id
112 * Id of the database record.
6c8f6e67
EM
113 * @param $isActive
114 *
115 * @internal param bool $is_active value we want to set the is_active field
6a488035 116 *
a6c01b45 117 * @return Object
b44e3f84 118 * DAO object on success, null otherwise
6a488035 119 */
00be9182 120 public static function setIsActive($id, $isActive) {
9da8dc8c 121 return CRM_Core_DAO::setFieldValue('CRM_Price_DAO_PriceSet', $id, 'is_active', $isActive);
6a488035
TO
122 }
123
124 /**
125 * Calculate the default price set id
126 * assigned to the contribution/membership etc
127 *
128 * @param string $entity
129 *
a6c01b45
CW
130 * @return array
131 * default price set
6a488035 132 *
6a488035
TO
133 */
134 public static function getDefaultPriceSet($entity = 'contribution') {
71ba92c4
PN
135 if (!empty(self::$_defaultPriceSet[$entity])) {
136 return self::$_defaultPriceSet[$entity];
137 }
e0c1764e
EM
138 $entityName = 'default_contribution_amount';
139 if ($entity == 'membership') {
6a488035
TO
140 $entityName = 'default_membership_type_amount';
141 }
142
143 $sql = "
82cc6775 144SELECT ps.id AS setID, pfv.price_field_id AS priceFieldID, pfv.id AS priceFieldValueID, pfv.name, pfv.label, pfv.membership_type_id, pfv.amount, pfv.financial_type_id
6a488035
TO
145FROM civicrm_price_set ps
146LEFT JOIN civicrm_price_field pf ON pf.`price_set_id` = ps.id
147LEFT JOIN civicrm_price_field_value pfv ON pfv.price_field_id = pf.id
148WHERE ps.name = '{$entityName}'
149";
150
151 $dao = CRM_Core_DAO::executeQuery($sql);
71ba92c4 152 self::$_defaultPriceSet[$entity] = array();
6a488035 153 while ($dao->fetch()) {
71ba92c4 154 self::$_defaultPriceSet[$entity][$dao->priceFieldValueID] = array(
353ffa53
TO
155 'setID' => $dao->setID,
156 'priceFieldID' => $dao->priceFieldID,
157 'name' => $dao->name,
158 'label' => $dao->label,
159 'priceFieldValueID' => $dao->priceFieldValueID,
160 'membership_type_id' => $dao->membership_type_id,
161 'amount' => $dao->amount,
162 'financial_type_id' => $dao->financial_type_id,
71ba92c4 163 );
6a488035
TO
164 }
165
71ba92c4 166 return self::$_defaultPriceSet[$entity];
6a488035
TO
167 }
168
169 /**
170 * Get the price set title.
171 *
414c1420
TO
172 * @param int $id
173 * Id of price set.
6a488035 174 *
a6c01b45
CW
175 * @return string
176 * title
6a488035 177 *
6a488035
TO
178 */
179 public static function getTitle($id) {
9da8dc8c 180 return CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $id, 'title');
6a488035
TO
181 }
182
183 /**
184 * Return a list of all forms which use this price set.
185 *
414c1420
TO
186 * @param int $id
187 * Id of price set.
e0c1764e 188 * @param bool|string $simpleReturn - get raw data. Possible values: 'entity', 'table'
6a488035
TO
189 *
190 * @return array
191 */
1bde39c7 192 public static function getUsedBy($id, $simpleReturn = FALSE) {
f5b8da4b 193 $usedBy = array();
194 $forms = self::getFormsUsingPriceSet($id);
195 $tables = array_keys($forms);
196 // @todo - this is really clumsy overloading the signature like this. Instead
197 // move towards having a function that does not call reformatUsedByFormsWithEntityData
198 // and call that when that data is not used.
6a488035
TO
199 if ($simpleReturn == 'table') {
200 return $tables;
201 }
f5b8da4b 202 // @todo - this is painfully slow in some cases.
6a488035
TO
203 if (empty($forms)) {
204 $queryString = "
205SELECT cli.entity_table, cli.entity_id
206FROM civicrm_line_item cli
207LEFT JOIN civicrm_price_field cpf ON cli.price_field_id = cpf.id
208WHERE cpf.price_set_id = %1";
209 $params = array(1 => array($id, 'Integer'));
210 $crmFormDAO = CRM_Core_DAO::executeQuery($queryString, $params);
211 while ($crmFormDAO->fetch()) {
212 $forms[$crmFormDAO->entity_table][] = $crmFormDAO->entity_id;
213 $tables[] = $crmFormDAO->entity_table;
214 }
215 if (empty($forms)) {
216 return $usedBy;
217 }
218 }
f5b8da4b 219 // @todo - this is really clumsy overloading the signature like this. See above.
6a488035
TO
220 if ($simpleReturn == 'entity') {
221 return $forms;
222 }
f5b8da4b 223 $usedBy = self::reformatUsedByFormsWithEntityData($forms, $usedBy);
6a488035
TO
224
225 return $usedBy;
226 }
227
228 /**
fe482240 229 * Delete the price set.
6a488035 230 *
414c1420
TO
231 * @param int $id
232 * Price Set id.
6a488035 233 *
acb1052e 234 * @return bool
a6c01b45 235 * false if fields exist for this set, true if the
16b10e64 236 * set could be deleted
6a488035 237 *
6a488035
TO
238 */
239 public static function deleteSet($id) {
240 // remove from all inactive forms
241 $usedBy = self::getUsedBy($id);
242 if (isset($usedBy['civicrm_event'])) {
243 foreach ($usedBy['civicrm_event'] as $eventId => $unused) {
244 $eventDAO = new CRM_Event_DAO_Event();
245 $eventDAO->id = $eventId;
246 $eventDAO->find();
247 while ($eventDAO->fetch()) {
248 self::removeFrom('civicrm_event', $eventDAO->id);
249 }
250 }
251 }
252
253 // delete price fields
9da8dc8c 254 $priceField = new CRM_Price_DAO_PriceField();
6a488035
TO
255 $priceField->price_set_id = $id;
256 $priceField->find();
257 while ($priceField->fetch()) {
258 // delete options first
9da8dc8c 259 CRM_Price_BAO_PriceField::deleteField($priceField->id);
6a488035
TO
260 }
261
9da8dc8c 262 $set = new CRM_Price_DAO_PriceSet();
6a488035
TO
263 $set->id = $id;
264 return $set->delete();
265 }
266
267 /**
fe482240 268 * Link the price set with the specified table and id.
6a488035
TO
269 *
270 * @param string $entityTable
414c1420
TO
271 * @param int $entityId
272 * @param int $priceSetId
6a488035
TO
273 *
274 * @return bool
275 */
276 public static function addTo($entityTable, $entityId, $priceSetId) {
277 // verify that the price set exists
9da8dc8c 278 $dao = new CRM_Price_DAO_PriceSet();
6a488035
TO
279 $dao->id = $priceSetId;
280 if (!$dao->find()) {
281 return FALSE;
282 }
283 unset($dao);
284
9da8dc8c 285 $dao = new CRM_Price_DAO_PriceSetEntity();
6a488035
TO
286 // find if this already exists
287 $dao->entity_id = $entityId;
288 $dao->entity_table = $entityTable;
289 $dao->find(TRUE);
290
291 // add or update price_set_id
292 $dao->price_set_id = $priceSetId;
293 return $dao->save();
294 }
295
296 /**
fe482240 297 * Delete price set for the given entity and id.
6a488035
TO
298 *
299 * @param string $entityTable
414c1420 300 * @param int $entityId
77b97be7
EM
301 *
302 * @return mixed
6a488035
TO
303 */
304 public static function removeFrom($entityTable, $entityId) {
353ffa53 305 $dao = new CRM_Price_DAO_PriceSetEntity();
6a488035 306 $dao->entity_table = $entityTable;
353ffa53 307 $dao->entity_id = $entityId;
6a488035
TO
308 return $dao->delete();
309 }
310
311 /**
1bde39c7 312 * Find a price_set_id associated with the given table, id and usedFor
6a488035
TO
313 * Used For value for events:1, contribution:2, membership:3
314 *
315 * @param string $entityTable
77b97be7 316 * @param int $entityId
414c1420
TO
317 * @param int $usedFor
318 * ( price set that extends/used for particular component ).
77b97be7
EM
319 *
320 * @param null $isQuickConfig
321 * @param null $setName
6a488035 322 *
df8d3074 323 * @return int|false
72b3a70c 324 * price_set_id, or false if none found
6a488035
TO
325 */
326 public static function getFor($entityTable, $entityId, $usedFor = NULL, $isQuickConfig = NULL, &$setName = NULL) {
327 if (!$entityTable || !$entityId) {
328 return FALSE;
329 }
330
331 $sql = 'SELECT ps.id as price_set_id, ps.name as price_set_name
332 FROM civicrm_price_set ps
333 INNER JOIN civicrm_price_set_entity pse ON ps.id = pse.price_set_id
334 WHERE pse.entity_table = %1 AND pse.entity_id = %2 ';
335 if ($isQuickConfig) {
336 $sql .= ' AND ps.is_quick_config = 0 ';
337 }
ba1dcfda 338 $params = array(
353ffa53
TO
339 1 => array($entityTable, 'String'),
340 2 => array($entityId, 'Integer'),
6a488035
TO
341 );
342 if ($usedFor) {
343 $sql .= " AND ps.extends LIKE '%%3%' ";
344 $params[3] = array($usedFor, 'Integer');
345 }
346
347 $dao = CRM_Core_DAO::executeQuery($sql, $params);
348 $dao->fetch();
349 $setName = (isset($dao->price_set_name)) ? $dao->price_set_name : FALSE;
350 return (isset($dao->price_set_id)) ? $dao->price_set_id : FALSE;
351 }
352
353 /**
fe482240 354 * Find a price_set_id associated with the given option value or field ID.
6a488035 355 *
414c1420
TO
356 * @param array $params
357 * (reference) an assoc array of name/value pairs.
6a488035
TO
358 * array may contain either option id or
359 * price field id
360 *
df8d3074 361 * @return int|NULL
72b3a70c 362 * price set id on success, null otherwise
6a488035
TO
363 */
364 public static function getSetId(&$params) {
365 $fid = NULL;
366
367 if ($oid = CRM_Utils_Array::value('oid', $params)) {
9da8dc8c 368 $fieldValue = new CRM_Price_DAO_PriceFieldValue();
6a488035
TO
369 $fieldValue->id = $oid;
370 if ($fieldValue->find(TRUE)) {
371 $fid = $fieldValue->price_field_id;
372 }
373 }
374 else {
375 $fid = CRM_Utils_Array::value('fid', $params);
376 }
377
378 if (isset($fid)) {
9da8dc8c 379 return CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceField', $fid, 'price_set_id');
6a488035
TO
380 }
381
382 return NULL;
383 }
384
385 /**
fe482240 386 * Return an associative array of all price sets.
6a488035 387 *
414c1420
TO
388 * @param bool $withInactive
389 * Whether or not to include inactive entries.
77b97be7 390 * @param bool|string $extendComponentName name of the component like 'CiviEvent','CiviContribute'
6a3d8d2d 391 * @param string $column name of the column.
6a488035 392 *
a6c01b45
CW
393 * @return array
394 * associative array of id => name
6a488035 395 */
6a3d8d2d
WA
396 public static function getAssoc($withInactive = FALSE, $extendComponentName = FALSE, $column = 'title') {
397 $query = "
6a488035 398 SELECT
75d6d479 399 DISTINCT ( price_set_id ) as id, s.{$column}
6a488035 400 FROM
53df1142
E
401 civicrm_price_set s
402 INNER JOIN civicrm_price_field f ON f.price_set_id = s.id
403 INNER JOIN civicrm_price_field_value v ON v.price_field_id = f.id
6a488035 404 WHERE
75d6d479 405 is_quick_config = 0 ";
6a488035
TO
406
407 if (!$withInactive) {
53df1142 408 $query .= ' AND s.is_active = 1 ';
6a488035
TO
409 }
410
411 if (self::eventPriceSetDomainID()) {
53df1142 412 $query .= ' AND s.domain_id = ' . CRM_Core_Config::domainID();
6a488035
TO
413 }
414
415 $priceSets = array();
416
417 if ($extendComponentName) {
418 $componentId = CRM_Core_Component::getComponentID($extendComponentName);
419 if (!$componentId) {
420 return $priceSets;
421 }
53df1142 422 $query .= " AND s.extends LIKE '%$componentId%' ";
6a488035 423 }
53df1142 424 // Check permissioned financial types
573fd305 425 CRM_Financial_BAO_FinancialType::getAvailableFinancialTypes($financialType, CRM_Core_Action::ADD);
53df1142 426 if ($financialType) {
40c655aa 427 $types = implode(',', array_keys($financialType));
53df1142
E
428 $query .= ' AND s.financial_type_id IN (' . $types . ') AND v.financial_type_id IN (' . $types . ') ';
429 }
430 else {
c5c263ca
AH
431 // Do not display any price sets
432 $query .= " AND 0 ";
53df1142
E
433 }
434 $query .= " GROUP BY s.id";
6a488035
TO
435 $dao = CRM_Core_DAO::executeQuery($query);
436 while ($dao->fetch()) {
6a3d8d2d 437 $priceSets[$dao->id] = $dao->$column;
6a488035
TO
438 }
439 return $priceSets;
440 }
441
442 /**
fe482240 443 * Get price set details.
6a488035
TO
444 *
445 * An array containing price set details (including price fields) is returned
446 *
100fef9d 447 * @param int $setID
003ca729 448 * Price Set ID.
2a6da8d7 449 * @param bool $required
003ca729 450 * Appears to have no effect based on reading the code.
2a6da8d7 451 * @param bool $validOnly
003ca729 452 * Should only fields where today's date falls within the valid range be returned?
2a6da8d7 453 *
a6c01b45 454 * @return array
003ca729 455 * Array consisting of field details
6a488035
TO
456 */
457 public static function getSetDetail($setID, $required = TRUE, $validOnly = FALSE) {
458 // create a new tree
459 $setTree = array();
6a488035
TO
460
461 $priceFields = array(
462 'id',
463 'name',
464 'label',
465 'html_type',
466 'is_enter_qty',
467 'help_pre',
468 'help_post',
469 'weight',
470 'is_display_amounts',
471 'options_per_line',
472 'is_active',
473 'active_on',
474 'expire_on',
475 'javascript',
476 'visibility_id',
477 'is_required',
478 );
479 if ($required == TRUE) {
480 $priceFields[] = 'is_required';
481 }
482
483 // create select
484 $select = 'SELECT ' . implode(',', $priceFields);
485 $from = ' FROM civicrm_price_field';
486
353ffa53 487 $params = array();
6a488035 488 $params[1] = array($setID, 'Integer');
353ffa53 489 $where = '
6a488035
TO
490WHERE price_set_id = %1
491AND is_active = 1
492';
493 $dateSelect = '';
494 if ($validOnly) {
495 $currentTime = date('YmdHis');
496 $dateSelect = "
497AND ( active_on IS NULL OR active_on <= {$currentTime} )
498AND ( expire_on IS NULL OR expire_on >= {$currentTime} )
499";
500 }
501
502 $orderBy = ' ORDER BY weight';
503
504 $sql = $select . $from . $where . $dateSelect . $orderBy;
505
506 $dao = CRM_Core_DAO::executeQuery($sql, $params);
507
265807d1
PN
508 $isDefaultContributionPriceSet = FALSE;
509 if ('default_contribution_amount' == CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $setID)) {
510 $isDefaultContributionPriceSet = TRUE;
511 }
512
6a488035
TO
513 $visibility = CRM_Core_PseudoConstant::visibility('name');
514 while ($dao->fetch()) {
515 $fieldID = $dao->id;
516
517 $setTree[$setID]['fields'][$fieldID] = array();
518 $setTree[$setID]['fields'][$fieldID]['id'] = $fieldID;
519
520 foreach ($priceFields as $field) {
521 if ($field == 'id' || is_null($dao->$field)) {
522 continue;
523 }
524
525 if ($field == 'visibility_id') {
526 $setTree[$setID]['fields'][$fieldID]['visibility'] = $visibility[$dao->$field];
527 }
528 $setTree[$setID]['fields'][$fieldID][$field] = $dao->$field;
529 }
265807d1 530 $setTree[$setID]['fields'][$fieldID]['options'] = CRM_Price_BAO_PriceField::getOptions($fieldID, FALSE, FALSE, $isDefaultContributionPriceSet);
6a488035
TO
531 }
532
533 // also get the pre and post help from this price set
534 $sql = "
601c7a24 535SELECT extends, financial_type_id, help_pre, help_post, is_quick_config, min_amount
6a488035
TO
536FROM civicrm_price_set
537WHERE id = %1";
538 $dao = CRM_Core_DAO::executeQuery($sql, $params);
539 if ($dao->fetch()) {
540 $setTree[$setID]['extends'] = $dao->extends;
157b21d8 541 $setTree[$setID]['financial_type_id'] = $dao->financial_type_id;
6a488035
TO
542 $setTree[$setID]['help_pre'] = $dao->help_pre;
543 $setTree[$setID]['help_post'] = $dao->help_post;
544 $setTree[$setID]['is_quick_config'] = $dao->is_quick_config;
601c7a24 545 $setTree[$setID]['min_amount'] = $dao->min_amount;
6a488035
TO
546 }
547 return $setTree;
548 }
549
85020e43 550 /**
003ca729
EM
551 * Get the Price Field ID.
552 *
553 * We call this function when more than one being present would represent an error
85020e43
EM
554 * starting format derived from current(CRM_Price_BAO_PriceSet::getSetDetail($priceSetId))
555 * @param array $priceSet
556 *
557 * @throws CRM_Core_Exception
558 * @return int
559 */
00be9182 560 public static function getOnlyPriceFieldID(array $priceSet) {
22e263ad 561 if (count($priceSet['fields']) > 1) {
1bde39c7 562 throw new CRM_Core_Exception(ts('expected only one price field to be in price set but multiple are present'));
85020e43
EM
563 }
564 return (int) implode('_', array_keys($priceSet['fields']));
565 }
566
567 /**
568 * Get the Price Field Value ID. We call this function when more than one being present would represent an error
569 * current(CRM_Price_BAO_PriceSet::getSetDetail($priceSetId))
570 * @param array $priceSet
571 *
572 * @throws CRM_Core_Exception
573 * @return int
574 */
00be9182 575 public static function getOnlyPriceFieldValueID(array $priceSet) {
85020e43 576 $priceFieldID = self::getOnlyPriceFieldID($priceSet);
22e263ad 577 if (count($priceSet['fields'][$priceFieldID]['options']) > 1) {
1bde39c7 578 throw new CRM_Core_Exception(ts('expected only one price field to be in price set but multiple are present'));
85020e43
EM
579 }
580 return (int) implode('_', array_keys($priceSet['fields'][$priceFieldID]['options']));
581 }
582
583
ffd93213 584 /**
003ca729
EM
585 * Initiate price set such that various non-BAO things are set on the form.
586 *
587 * This function is not really a BAO function so the location is misleading.
588 *
e0c1764e 589 * @param CRM_Core_Form $form
100fef9d 590 * @param int $id
003ca729 591 * Form entity id.
ffd93213
EM
592 * @param string $entityTable
593 * @param bool $validOnly
100fef9d 594 * @param int $priceSetId
003ca729 595 * Price Set ID
ffd93213
EM
596 *
597 * @return bool|false|int|null
598 */
00be9182 599 public static function initSet(&$form, $id, $entityTable = 'civicrm_event', $validOnly = FALSE, $priceSetId = NULL) {
6a488035
TO
600 if (!$priceSetId) {
601 $priceSetId = self::getFor($entityTable, $id);
602 }
603
1bde39c7 604 //check if price set is is_config
6a488035 605 if (is_numeric($priceSetId)) {
9da8dc8c 606 if (CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $priceSetId, 'is_quick_config') && $form->getVar('_name') != 'Participant') {
6a488035
TO
607 $form->assign('quickConfig', 1);
608 }
609 }
610 // get price info
611 if ($priceSetId) {
612 if ($form->_action & CRM_Core_Action::UPDATE) {
613 $entityId = $entity = NULL;
614
615 switch ($entityTable) {
616 case 'civicrm_event':
617 $entity = 'participant';
618 if (CRM_Utils_System::getClassName($form) == 'CRM_Event_Form_Participant') {
619 $entityId = $form->_id;
620 }
621 else {
622 $entityId = $form->_participantId;
623 }
624 break;
625
626 case 'civicrm_contribution_page':
627 case 'civicrm_contribution':
628 $entity = 'contribution';
629 $entityId = $form->_id;
630 break;
631 }
632
633 if ($entityId && $entity) {
634 $form->_values['line_items'] = CRM_Price_BAO_LineItem::getLineItems($entityId, $entity);
635 }
636 $required = FALSE;
637 }
638 else {
639 $required = TRUE;
640 }
641
642 $form->_priceSetId = $priceSetId;
643 $priceSet = self::getSetDetail($priceSetId, $required, $validOnly);
644 $form->_priceSet = CRM_Utils_Array::value($priceSetId, $priceSet);
645 $form->_values['fee'] = CRM_Utils_Array::value('fields', $form->_priceSet);
646
647 //get the price set fields participant count.
648 if ($entityTable == 'civicrm_event') {
649 //get option count info.
650 $form->_priceSet['optionsCountTotal'] = self::getPricesetCount($priceSetId);
651 if ($form->_priceSet['optionsCountTotal']) {
1bde39c7 652 $optionsCountDetails = array();
6a488035
TO
653 if (!empty($form->_priceSet['fields'])) {
654 foreach ($form->_priceSet['fields'] as $field) {
655 foreach ($field['options'] as $option) {
656 $count = CRM_Utils_Array::value('count', $option, 0);
1bde39c7 657 $optionsCountDetails['fields'][$field['id']]['options'][$option['id']] = $count;
6a488035
TO
658 }
659 }
660 }
1bde39c7 661 $form->_priceSet['optionsCountDetails'] = $optionsCountDetails;
6a488035
TO
662 }
663
664 //get option max value info.
665 $optionsMaxValueTotal = 0;
666 $optionsMaxValueDetails = array();
667
668 if (!empty($form->_priceSet['fields'])) {
669 foreach ($form->_priceSet['fields'] as $field) {
670 foreach ($field['options'] as $option) {
671 $maxVal = CRM_Utils_Array::value('max_value', $option, 0);
672 $optionsMaxValueDetails['fields'][$field['id']]['options'][$option['id']] = $maxVal;
673 $optionsMaxValueTotal += $maxVal;
674 }
675 }
676 }
677
678 $form->_priceSet['optionsMaxValueTotal'] = $optionsMaxValueTotal;
679 if ($optionsMaxValueTotal) {
680 $form->_priceSet['optionsMaxValueDetails'] = $optionsMaxValueDetails;
681 }
682 }
683 $form->set('priceSetId', $form->_priceSetId);
684 $form->set('priceSet', $form->_priceSet);
685
686 return $priceSetId;
687 }
688 return FALSE;
689 }
690
ffd93213 691 /**
003ca729
EM
692 * Get line item purchase information.
693 *
694 * This function takes the input parameters and interprets out of it what has been purchased.
695 *
ffd93213 696 * @param $fields
003ca729
EM
697 * This is the output of the function CRM_Price_BAO_PriceSet::getSetDetail($priceSetID, FALSE, FALSE);
698 * And, it would make sense to introduce caching into that function and call it from here rather than
699 * require the $fields array which is passed from pillar to post around the form in order to pass it in here.
c490a46a 700 * @param array $params
003ca729 701 * Params reflecting form input e.g with fields 'price_5' => 7, 'price_8' => array(7, 8)
ffd93213 702 * @param $lineItem
003ca729 703 * Line item array to be altered.
ffd93213 704 * @param string $component
003ca729
EM
705 * This parameter appears to only be relevant to determining whether memberships should be auto-renewed.
706 * (and is effectively a boolean for 'is_membership' which could be calculated from the line items.)
1bde39c7 707 * @param int $priceSetID
ffd93213 708 */
1a1a2f4f 709 public static function processAmount($fields, &$params, &$lineItem, $component = '', $priceSetID = NULL) {
6a488035 710 // using price set
dc428161 711 $totalPrice = $totalTax = 0;
1a1a2f4f 712 // CRM-18701 Sometimes the amount in the price set is overridden by the amount on the form.
713 // This is notably the case with memberships and we need to put this amount
714 // on the line item rather than the calculated amount.
715 // This seems to only affect radio link items as that is the use case for the 'quick config'
716 // set up (which allows a free form field).
717 $amount_override = NULL;
0be991f0 718
6a488035
TO
719 if ($component) {
720 $autoRenew = array();
721 $autoRenew[0] = $autoRenew[1] = $autoRenew[2] = 0;
722 }
1a1a2f4f 723 if ($priceSetID) {
724 $priceFields = self::filterPriceFieldsFromParams($priceSetID, $params);
725 if (count($priceFields) == 1 && !empty($params['total_amount'])) {
726 $amount_override = $params['total_amount'];
727 }
728 }
6a488035 729 foreach ($fields as $id => $field) {
a7488080 730 if (empty($params["price_{$id}"]) ||
6a488035
TO
731 (empty($params["price_{$id}"]) && $params["price_{$id}"] == NULL)
732 ) {
733 // skip if nothing was submitted for this field
734 continue;
735 }
736
737 switch ($field['html_type']) {
738 case 'Text':
be45c8b4
EM
739 $firstOption = reset($field['options']);
740 $params["price_{$id}"] = array($firstOption['id'] => $params["price_{$id}"]);
6a488035 741 CRM_Price_BAO_LineItem::format($id, $params, $field, $lineItem);
83e1baa3
PN
742 $optionValueId = key($field['options']);
743
744 if (CRM_Utils_Array::value('name', $field['options'][$optionValueId]) == 'contribution_amount') {
049db839 745 $taxRates = CRM_Core_PseudoConstant::getTaxRates();
746 if (array_key_exists($params['financial_type_id'], $taxRates)) {
747 $field['options'][key($field['options'])]['tax_rate'] = $taxRates[$params['financial_type_id']];
83e1baa3
PN
748 $taxAmount = CRM_Contribute_BAO_Contribution_Utils::calculateTaxAmount($field['options'][$optionValueId]['amount'], $field['options'][$optionValueId]['tax_rate']);
749 $field['options'][$optionValueId]['tax_amount'] = round($taxAmount['tax_amount'], 2);
049db839 750 }
751 }
83e1baa3
PN
752 if (CRM_Utils_Array::value('tax_rate', $field['options'][$optionValueId])) {
753 $lineItem = self::setLineItem($field, $lineItem, $optionValueId, $totalTax);
754 }
3b5db8ce 755 $totalPrice += $lineItem[$firstOption['id']]['line_total'] + CRM_Utils_Array::value('tax_amount', $lineItem[key($field['options'])]);
6a488035
TO
756 break;
757
758 case 'Radio':
759 //special case if user select -none-
760 if ($params["price_{$id}"] <= 0) {
761 continue;
762 }
763 $params["price_{$id}"] = array($params["price_{$id}"] => 1);
764 $optionValueId = CRM_Utils_Array::key(1, $params["price_{$id}"]);
0be991f0 765
1a1a2f4f 766 CRM_Price_BAO_LineItem::format($id, $params, $field, $lineItem, $amount_override);
dc428161 767 if (CRM_Utils_Array::value('tax_rate', $field['options'][$optionValueId])) {
83e1baa3 768 $lineItem = self::setLineItem($field, $lineItem, $optionValueId, $totalTax);
c40e1ff4 769 if (CRM_Utils_Array::value('field_title', $lineItem[$optionValueId]) == 'Membership Amount') {
770 $lineItem[$optionValueId]['line_total'] = $lineItem[$optionValueId]['unit_price'] = CRM_Utils_Rule::cleanMoney($lineItem[$optionValueId]['line_total'] - $lineItem[$optionValueId]['tax_amount']);
771 }
dc428161 772 }
c40e1ff4 773 $totalPrice += $lineItem[$optionValueId]['line_total'] + CRM_Utils_Array::value('tax_amount', $lineItem[$optionValueId]);
cde484fd
DL
774 if (
775 $component &&
a6c4ca20 776 // auto_renew exists and is empty in some workflows, which php treat as a 0
28156120 777 // and hence we explicitly check to see if auto_renew is numeric
cde484fd
DL
778 isset($lineItem[$optionValueId]['auto_renew']) &&
779 is_numeric($lineItem[$optionValueId]['auto_renew'])
780 ) {
6a488035
TO
781 $autoRenew[$lineItem[$optionValueId]['auto_renew']] += $lineItem[$optionValueId]['line_total'];
782 }
783 break;
784
785 case 'Select':
786 $params["price_{$id}"] = array($params["price_{$id}"] => 1);
787 $optionValueId = CRM_Utils_Array::key(1, $params["price_{$id}"]);
0be991f0 788
6a488035 789 CRM_Price_BAO_LineItem::format($id, $params, $field, $lineItem);
dc428161 790 if (CRM_Utils_Array::value('tax_rate', $field['options'][$optionValueId])) {
83e1baa3 791 $lineItem = self::setLineItem($field, $lineItem, $optionValueId, $totalTax);
dc428161 792 }
c40e1ff4 793 $totalPrice += $lineItem[$optionValueId]['line_total'] + CRM_Utils_Array::value('tax_amount', $lineItem[$optionValueId]);
cde484fd
DL
794 if (
795 $component &&
796 isset($lineItem[$optionValueId]['auto_renew']) &&
797 is_numeric($lineItem[$optionValueId]['auto_renew'])
798 ) {
6a488035
TO
799 $autoRenew[$lineItem[$optionValueId]['auto_renew']] += $lineItem[$optionValueId]['line_total'];
800 }
801 break;
802
803 case 'CheckBox':
0be991f0 804
6a488035 805 CRM_Price_BAO_LineItem::format($id, $params, $field, $lineItem);
0be991f0 806 foreach ($params["price_{$id}"] as $optionId => $option) {
dc428161 807 if (CRM_Utils_Array::value('tax_rate', $field['options'][$optionId])) {
83e1baa3 808 $lineItem = self::setLineItem($field, $lineItem, $optionId, $totalTax);
dc428161 809 }
c40e1ff4 810 $totalPrice += $lineItem[$optionId]['line_total'] + CRM_Utils_Array::value('tax_amount', $lineItem[$optionId]);
cde484fd
DL
811 if (
812 $component &&
813 isset($lineItem[$optionId]['auto_renew']) &&
814 is_numeric($lineItem[$optionId]['auto_renew'])
815 ) {
6a488035
TO
816 $autoRenew[$lineItem[$optionId]['auto_renew']] += $lineItem[$optionId]['line_total'];
817 }
818 }
819 break;
820 }
821 }
822
823 $amount_level = array();
824 $totalParticipant = 0;
825 if (is_array($lineItem)) {
826 foreach ($lineItem as $values) {
827 $totalParticipant += $values['participant_count'];
2b308818
DG
828 // This is a bit nasty. The logic of 'quick config' was because price set configuration was
829 // (and still is) too difficult to replace the 'quick config' price set configuration on the contribution
830 // page.
831 //
832 // However, because the quick config concept existed all sorts of logic was hung off it
833 // and function behaviour sometimes depends on whether 'price set' is set - although actually it
834 // is always set at the functional level. In this case we are dealing with the default 'quick config'
835 // price set having a label of 'Contribution Amount' which could wind up creating a 'funny looking' label.
836 // The correct answer is probably for it to have an empty label in the DB - the label is never shown so it is a
837 // place holder.
838 //
839 // But, in the interests of being careful when capacity is low - avoiding the known default value
840 // will get us by.
841 // Crucially a test has been added so a better solution can be implemented later with some comfort.
c039f658 842 // @todo - stop setting amount level in this function & call the getAmountLevel function to retrieve it.
2b308818
DG
843 if ($values['label'] != ts('Contribution Amount')) {
844 $amount_level[] = $values['label'] . ' - ' . (float) $values['qty'];
845 }
6a488035
TO
846 }
847 }
848
849 $displayParticipantCount = '';
850 if ($totalParticipant > 0) {
851 $displayParticipantCount = ' Participant Count -' . $totalParticipant;
852 }
c039f658 853 // @todo - stop setting amount level in this function & call the getAmountLevel function to retrieve it.
c0214b81 854 if (!empty($amount_level)) {
0aa9b939 855 $params['amount_level'] = CRM_Utils_Array::implodePadded($amount_level);
c0214b81 856 if (!empty($displayParticipantCount)) {
d7a867a8 857 $params['amount_level'] = CRM_Core_DAO::VALUE_SEPARATOR . implode(CRM_Core_DAO::VALUE_SEPARATOR, $amount_level) . $displayParticipantCount . CRM_Core_DAO::VALUE_SEPARATOR;
c0214b81 858 }
2b308818 859 }
85d3367a 860 $params['amount'] = CRM_Utils_Money::format($totalPrice, NULL, NULL, TRUE);
dc428161 861 $params['tax_amount'] = $totalTax;
6a488035
TO
862 if ($component) {
863 foreach ($autoRenew as $dontCare => $eachAmount) {
864 if (!$eachAmount) {
cde484fd 865 unset($autoRenew[$dontCare]);
6a488035
TO
866 }
867 }
481a74f4 868 if (count($autoRenew) > 1) {
6a488035
TO
869 $params['autoRenew'] = $autoRenew;
870 }
871 }
872 }
873
c039f658 874 /**
875 * Get the text to record for amount level.
876 *
877 * @param array $params
878 * Submitted parameters
879 * - priceSetId is required to be set in the calling function
880 * (we don't e-notice check it to enforce that - all payments DO have a price set - even if it is the
881 * default one & this function asks that be set if it is the case).
882 *
883 * @return string
884 * Text for civicrm_contribution.amount_level field.
885 */
886 public static function getAmountLevelText($params) {
887 $priceSetID = $params['priceSetId'];
888 $priceFieldSelection = self::filterPriceFieldsFromParams($priceSetID, $params);
889 $priceFieldMetadata = self::getCachedPriceSetDetail($priceSetID);
8c632a5d 890 $displayParticipantCount = NULL;
0f8a0349 891
c039f658 892 $amount_level = array();
893 foreach ($priceFieldMetadata['fields'] as $field) {
894 if (!empty($priceFieldSelection[$field['id']])) {
0f8a0349 895 $qtyString = '';
c039f658 896 if ($field['is_enter_qty']) {
897 $qtyString = ' - ' . (float) $params['price_' . $field['id']];
898 }
899 // We deliberately & specifically exclude contribution amount as it has a specific meaning.
900 // ie. it represents the default price field for a contribution. Another approach would be not
901 // to give it a label if we don't want it to show.
902 if ($field['label'] != ts('Contribution Amount')) {
903 $amount_level[] = $field['label'] . $qtyString;
904 }
905 }
906 }
907 return CRM_Core_DAO::VALUE_SEPARATOR . implode(CRM_Core_DAO::VALUE_SEPARATOR, $amount_level) . $displayParticipantCount . CRM_Core_DAO::VALUE_SEPARATOR;
908 }
909
910 /**
911 * Get the fields relevant to the price field from the parameters.
912 *
913 * E.g we are looking for price_5 => 7 out of a big array of input parameters.
914 *
915 * @param int $priceSetID
916 * @param array $params
917 *
918 * @return array
919 * Price fields found in the params array
920 */
921 public static function filterPriceFieldsFromParams($priceSetID, $params) {
922 $priceSet = self::getCachedPriceSetDetail($priceSetID);
923 $return = array();
924 foreach ($priceSet['fields'] as $field) {
925 if (!empty($params['price_' . $field['id']])) {
926 $return[$field['id']] = $params['price_' . $field['id']];
927 }
928 }
929 return $return;
930 }
931
932 /**
933 * Wrapper for getSetDetail with caching.
934 *
935 * We seem to be passing this array around in a painful way - presumably to avoid the hit
936 * of loading it - so lets make it callable with caching.
937 *
938 * Why not just add caching to the other function? We could do - it just seemed a bit unclear the best caching pattern
939 * & the function was already pretty fugly. Also, I feel like we need to migrate the interaction with price-sets into
940 * a more granular interaction - ie. retrieve specific data using specific functions on this class & have the form
941 * think less about the price sets.
942 *
943 * @param int $priceSetID
944 *
945 * @return array
946 */
947 public static function getCachedPriceSetDetail($priceSetID) {
948 $cacheKey = __CLASS__ . __FUNCTION__ . '_' . $priceSetID;
949 $cache = CRM_Utils_Cache::singleton();
982f1e47 950 $values = $cache->get($cacheKey);
c039f658 951 if (empty($values)) {
952 $data = self::getSetDetail($priceSetID);
953 $values = $data[$priceSetID];
954 $cache->set($cacheKey, $values);
955 }
956 return $values;
957 }
958
6a488035 959 /**
100fef9d 960 * Build the price set form.
6a488035 961 *
e0c1764e 962 * @param CRM_Core_Form $form
dd244018 963 *
355ba699 964 * @return void
6a488035 965 */
00be9182 966 public static function buildPriceSet(&$form) {
6a488035 967 $priceSetId = $form->get('priceSetId');
6a488035
TO
968 if (!$priceSetId) {
969 return;
970 }
971
972 $validFieldsOnly = TRUE;
973 $className = CRM_Utils_System::getClassName($form);
974 if (in_array($className, array(
353ffa53 975 'CRM_Contribute_Form_Contribution',
acb1052e 976 'CRM_Member_Form_Membership',
353ffa53 977 ))) {
6a488035
TO
978 $validFieldsOnly = FALSE;
979 }
980
353ffa53
TO
981 $priceSet = self::getSetDetail($priceSetId, TRUE, $validFieldsOnly);
982 $form->_priceSet = CRM_Utils_Array::value($priceSetId, $priceSet);
883e4763 983 $validPriceFieldIds = array_keys($form->_priceSet['fields']);
6a488035 984 $form->_quickConfig = $quickConfig = 0;
9da8dc8c 985 if (CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $priceSetId, 'is_quick_config')) {
6a488035
TO
986 $quickConfig = 1;
987 }
988
989 $form->assign('quickConfig', $quickConfig);
990 if ($className == 'CRM_Contribute_Form_Contribution_Main') {
991 $form->_quickConfig = $quickConfig;
992 }
ee7f71d9
AS
993
994 // Mark which field should have the auto-renew checkbox, if any. CRM-18305
f4fd225b 995 if (!empty($form->_membershipTypeValues) && is_array($form->_membershipTypeValues)) {
ee7f71d9
AS
996 $autoRenewMembershipTypes = array();
997 foreach ($form->_membershipTypeValues as $membershiptTypeValue) {
998 if ($membershiptTypeValue['auto_renew']) {
999 $autoRenewMembershipTypes[] = $membershiptTypeValue['id'];
1000 }
1001 }
1002 foreach ($form->_priceSet['fields'] as &$field) {
1003 if (array_key_exists('options', $field) && is_array($field['options'])) {
1004 foreach ($field['options'] as $option) {
b3460c23 1005 if (!empty($option['membership_type_id'])) {
ee7f71d9
AS
1006 if (in_array($option['membership_type_id'], $autoRenewMembershipTypes)) {
1007 $form->_priceSet['auto_renew_membership_field'] = $field['id'];
1008 // Only one field can offer auto_renew memberships, so break here.
1009 break;
1010 }
1011 }
1012 }
1013 }
1014 }
1015 }
6a488035
TO
1016 $form->assign('priceSet', $form->_priceSet);
1017
1018 $component = 'contribution';
1019 if ($className == 'CRM_Member_Form_Membership') {
1020 $component = 'membership';
1021 }
1022
1023 if ($className == 'CRM_Contribute_Form_Contribution_Main') {
1024 $feeBlock = &$form->_values['fee'];
1025 if (!empty($form->_useForMember)) {
1026 $component = 'membership';
1027 }
1028 }
1029 else {
1030 $feeBlock = &$form->_priceSet['fields'];
1031 }
66af7c48
PN
1032 if (CRM_Financial_BAO_FinancialType::isACLFinancialTypeStatus()) {
1033 foreach ($feeBlock as $key => $value) {
1034 foreach ($value['options'] as $k => $options) {
1035 if (!CRM_Core_Permission::check('add contributions of type ' . CRM_Contribute_PseudoConstant::financialType($options['financial_type_id']))) {
1036 unset($feeBlock[$key]['options'][$k]);
1037 }
1038 }
1039 if (empty($feeBlock[$key]['options'])) {
1040 unset($feeBlock[$key]);
e1a89dfd 1041 }
4a695b27 1042 }
e1a89dfd 1043 }
6a488035
TO
1044 // call the hook.
1045 CRM_Utils_Hook::buildAmount($component, $form, $feeBlock);
1046
c7b3d063 1047 // CRM-14492 Admin price fields should show up on event registration if user has 'administer CiviCRM' permissions
ba1dcfda 1048 $adminFieldVisible = FALSE;
c7b3d063 1049 if (CRM_Core_Permission::check('administer CiviCRM')) {
ba1dcfda 1050 $adminFieldVisible = TRUE;
c7b3d063 1051 }
77b97be7 1052
883e4763 1053 foreach ($feeBlock as $id => $field) {
6a488035 1054 if (CRM_Utils_Array::value('visibility', $field) == 'public' ||
ba1dcfda 1055 (CRM_Utils_Array::value('visibility', $field) == 'admin' && $adminFieldVisible == TRUE) ||
6a488035
TO
1056 !$validFieldsOnly
1057 ) {
1058 $options = CRM_Utils_Array::value('options', $field);
1059 if ($className == 'CRM_Contribute_Form_Contribution_Main' && $component = 'membership') {
cc509891 1060 $userid = $form->getVar('_membershipContactID');
6a488035
TO
1061 $checklifetime = self::checkCurrentMembership($options, $userid);
1062 if ($checklifetime) {
1063 $form->assign('ispricelifetime', TRUE);
1064 }
1065 }
883e4763 1066 if (!is_array($options) || !in_array($id, $validPriceFieldIds)) {
6a488035
TO
1067 continue;
1068 }
9da8dc8c 1069 CRM_Price_BAO_PriceField::addQuickFormElement($form,
6a488035
TO
1070 'price_' . $field['id'],
1071 $field['id'],
1072 FALSE,
1073 CRM_Utils_Array::value('is_required', $field, FALSE),
1074 NULL,
1075 $options
1076 );
1077 }
1078 }
1079 }
1080
1081 /**
003ca729
EM
1082 * Check the current Membership having end date null.
1083 *
1084 * @param array $options
1085 * @param int $userid
1086 * Probably actually contact ID.
1087 *
1088 * @return bool
6a488035 1089 */
00be9182 1090 public static function checkCurrentMembership(&$options, $userid) {
6a488035 1091 if (!$userid || empty($options)) {
925157c5 1092 return FALSE;
6a488035
TO
1093 }
1094 static $_contact_memberships = array();
003ca729 1095 $checkLifetime = FALSE;
6a488035 1096 foreach ($options as $key => $value) {
a7488080 1097 if (!empty($value['membership_type_id'])) {
6a488035
TO
1098 if (!isset($_contact_memberships[$userid][$value['membership_type_id']])) {
1099 $_contact_memberships[$userid][$value['membership_type_id']] = CRM_Member_BAO_Membership::getContactMembership($userid, $value['membership_type_id'], FALSE);
1100 }
1101 $currentMembership = $_contact_memberships[$userid][$value['membership_type_id']];
8cc574cf 1102 if (!empty($currentMembership) && empty($currentMembership['end_date'])) {
6a488035 1103 unset($options[$key]);
003ca729 1104 $checkLifetime = TRUE;
6a488035
TO
1105 }
1106 }
1107 }
003ca729 1108 if ($checkLifetime) {
6a488035
TO
1109 return TRUE;
1110 }
1111 else {
1112 return FALSE;
1113 }
1114 }
1115
1116 /**
100fef9d 1117 * Set daefult the price set fields.
6a488035 1118 *
c490a46a 1119 * @param CRM_Core_Form $form
fd31fa4c
EM
1120 * @param $defaults
1121 *
a6c01b45 1122 * @return array
6a488035 1123 */
00be9182 1124 public static function setDefaultPriceSet(&$form, &$defaults) {
6a488035
TO
1125 if (!isset($form->_priceSet) || empty($form->_priceSet['fields'])) {
1126 return $defaults;
1127 }
1128
1bde39c7 1129 foreach ($form->_priceSet['fields'] as $val) {
6a488035 1130 foreach ($val['options'] as $keys => $values) {
cb063506
KJ
1131 // build price field index which is passed via URL
1132 // url format will be appended by "&price_5=11"
1133 $priceFieldName = 'price_' . $values['price_field_id'];
1134 $priceFieldValue = self::getPriceFieldValueFromURL($form, $priceFieldName);
1135 if (!empty($priceFieldValue)) {
034b5cb6 1136 self::setDefaultPriceSetField($priceFieldName, $priceFieldValue, $val['html_type'], $defaults);
cb063506
KJ
1137 // break here to prevent overwriting of default due to 'is_default'
1138 // option configuration. The value sent via URL get's higher priority.
1139 break;
1140 }
1141 elseif ($values['is_default']) {
034b5cb6 1142 self::setDefaultPriceSetField($priceFieldName, $keys, $val['html_type'], $defaults);
6a488035
TO
1143 }
1144 }
1145 }
1146 return $defaults;
1147 }
1148
034b5cb6
KJ
1149 /**
1150 * Get the value of price field if passed via url
1151 *
1152 * @param string $priceFieldName
1153 * @param string $priceFieldValue
1154 * @param string $priceFieldType
1155 * @param array $defaults
1156 *
1157 * @return void
1158 */
1159 public static function setDefaultPriceSetField($priceFieldName, $priceFieldValue, $priceFieldType, &$defaults) {
1160 if ($priceFieldType == 'CheckBox') {
1161 $defaults[$priceFieldName][$priceFieldValue] = 1;
1162 }
1163 else {
1164 $defaults[$priceFieldName] = $priceFieldValue;
1165 }
1166 }
1167
cb063506
KJ
1168 /**
1169 * Get the value of price field if passed via url
1170 *
1171 * @param CRM_Core_Form $form
1172 * @param string $priceFieldName
1173 *
1174 * @return mixed $priceFieldValue
1175 */
1176 public static function getPriceFieldValueFromURL(&$form, $priceFieldName) {
1177 $priceFieldValue = CRM_Utils_Request::retrieve($priceFieldName, 'String', $form, FALSE, NULL, 'GET');
1178 if (!empty($priceFieldValue)) {
1179 return $priceFieldValue;
1180 }
1181 }
1182
b2cdd843
EM
1183 /**
1184 * Supports event create function by setting up required price sets, not tested but expect
1185 * it will work for contribution page
414c1420
TO
1186 * @param array $params
1187 * As passed to api/bao create fn.
1188 * @param CRM_Core_DAO $entity
1189 * Object for given entity.
1190 * @param string $entityName
1191 * Name of entity - e.g event.
b2cdd843 1192 */
00be9182 1193 public static function setPriceSets(&$params, $entity, $entityName) {
22e263ad 1194 if (empty($params['price_set_id']) || !is_array($params['price_set_id'])) {
b2cdd843
EM
1195 return;
1196 }
1197 // CRM-14069 note that we may as well start by assuming more than one.
1198 // currently the form does not pass in as an array & will be skipped
1199 // test is passing in as an array but I feel the api should have a metadata that allows
1200 // transform of single to array - seems good for managing transitions - in which case all api
1201 // calls that set price_set_id will hit this
1202 // e.g in getfields 'price_set_id' => array('blah', 'bao_type' => 'array') - causing
1203 // all separated values, strings, json half-separated values (in participant we hit this)
1204 // to be converted to json @ api layer
1205 $pse = new CRM_Price_DAO_PriceSetEntity();
1206 $pse->entity_table = 'civicrm_' . $entityName;
1207 $pse->entity_id = $entity->id;
1208 while ($pse->fetch()) {
22e263ad 1209 if (!in_array($pse->price_set_id, $params['price_set_id'])) {
b2cdd843
EM
1210 // note an even more aggressive form of this deletion currently happens in event form
1211 // past price sets discounts are made inaccessible by this as the discount_id is set to NULL
1212 // on the participant record
1213 if (CRM_Price_BAO_PriceSet::removeFrom('civicrm_' . $entityName, $entity->id)) {
ba1dcfda 1214 CRM_Core_BAO_Discount::del($entity->id, 'civicrm_' . $entityName);
b2cdd843
EM
1215 }
1216 }
1217 }
1218 foreach ($params['price_set_id'] as $priceSetID) {
1219 CRM_Price_BAO_PriceSet::addTo('civicrm_' . $entityName, $entity->id, $priceSetID);
1220 //@todo - how should we do this - copied from form
b53cbfbc 1221 //if (!empty($params['price_field_id'])) {
b2cdd843
EM
1222 // $priceSetID = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceField', $params['price_field_id'], 'price_set_id');
1223 // CRM_Price_BAO_PriceSet::setIsQuickConfig($priceSetID, 0);
1224 //}
1225 }
1226 }
353ffa53 1227
6a488035 1228 /**
fe482240 1229 * Get field ids of a price set.
6a488035 1230 *
414c1420
TO
1231 * @param int $id
1232 * Price Set id.
6a488035 1233 *
a6c01b45 1234 * @return array
16b10e64 1235 * Array of the field ids
6a488035 1236 *
6a488035
TO
1237 */
1238 public static function getFieldIds($id) {
9da8dc8c 1239 $priceField = new CRM_Price_DAO_PriceField();
6a488035
TO
1240 $priceField->price_set_id = $id;
1241 $priceField->find();
1242 while ($priceField->fetch()) {
1243 $var[] = $priceField->id;
1244 }
1245 return $var;
1246 }
1247
1248 /**
72b3a70c 1249 * Copy a price set, including all the fields
6a488035 1250 *
414c1420
TO
1251 * @param int $id
1252 * The price set id to copy.
6a488035 1253 *
72b3a70c 1254 * @return CRM_Price_DAO_PriceSet
6a488035 1255 */
00be9182 1256 public static function copy($id) {
6a488035
TO
1257 $maxId = CRM_Core_DAO::singleValueQuery("SELECT max(id) FROM civicrm_price_set");
1258
1259 $title = ts('[Copy id %1]', array(1 => $maxId + 1));
1260 $fieldsFix = array(
ba1dcfda 1261 'suffix' => array(
353ffa53
TO
1262 'title' => ' ' . $title,
1263 'name' => '__Copy_id_' . ($maxId + 1) . '_',
6a488035
TO
1264 ),
1265 );
1266
9da8dc8c 1267 $copy = &CRM_Core_DAO::copyGeneric('CRM_Price_DAO_PriceSet',
353ffa53
TO
1268 array('id' => $id),
1269 NULL,
1270 $fieldsFix
6a488035
TO
1271 );
1272
1273 //copying all the blocks pertaining to the price set
9da8dc8c 1274 $copyPriceField = &CRM_Core_DAO::copyGeneric('CRM_Price_DAO_PriceField',
353ffa53
TO
1275 array('price_set_id' => $id),
1276 array('price_set_id' => $copy->id)
6a488035
TO
1277 );
1278 if (!empty($copyPriceField)) {
1279 $price = array_combine(self::getFieldIds($id), self::getFieldIds($copy->id));
1280
1281 //copy option group and values
1282 foreach ($price as $originalId => $copyId) {
9da8dc8c 1283 CRM_Core_DAO::copyGeneric('CRM_Price_DAO_PriceFieldValue',
6a488035
TO
1284 array('price_field_id' => $originalId),
1285 array('price_field_id' => $copyId)
1286 );
1287 }
1288 }
1289 $copy->save();
1290
1291 CRM_Utils_Hook::copy('Set', $copy);
1292 return $copy;
1293 }
1294
1295 /**
fe482240 1296 * check price set permission.
6a488035 1297 *
414c1420
TO
1298 * @param int $sid
1299 * The price set id.
77b97be7
EM
1300 *
1301 * @return bool
6a488035 1302 */
00be9182 1303 public static function checkPermission($sid) {
44c8822b 1304 if ($sid && self::eventPriceSetDomainID()) {
9da8dc8c 1305 $domain_id = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $sid, 'domain_id', 'id');
6a488035 1306 if (CRM_Core_Config::domainID() != $domain_id) {
0499b0ad 1307 CRM_Core_Error::fatal(ts('You do not have permission to access this page.'));
6a488035
TO
1308 }
1309 }
1310 return TRUE;
1311 }
1312
1313 /**
1314 * Get the sum of participant count
1315 * for all fields of given price set.
1316 *
414c1420
TO
1317 * @param int $sid
1318 * The price set id.
6a488035 1319 *
77b97be7
EM
1320 * @param bool $onlyActive
1321 *
1322 * @return int|null|string
6a488035
TO
1323 */
1324 public static function getPricesetCount($sid, $onlyActive = TRUE) {
1325 $count = 0;
1326 if (!$sid) {
1327 return $count;
1328 }
1329
1330 $where = NULL;
1331 if ($onlyActive) {
1332 $where = 'AND value.is_active = 1 AND field.is_active = 1';
1333 }
1334
1335 static $pricesetFieldCount = array();
1336 if (!isset($pricesetFieldCount[$sid])) {
1337 $sql = "
1338 SELECT sum(value.count) as totalCount
1339 FROM civicrm_price_field_value value
1340INNER JOIN civicrm_price_field field ON ( field.id = value.price_field_id )
1341INNER JOIN civicrm_price_set pset ON ( pset.id = field.price_set_id )
1342 WHERE pset.id = %1
1343 $where";
1344
1345 $count = CRM_Core_DAO::singleValueQuery($sql, array(1 => array($sid, 'Positive')));
1346 $pricesetFieldCount[$sid] = ($count) ? $count : 0;
1347 }
1348
1349 return $pricesetFieldCount[$sid];
1350 }
1351
ffd93213
EM
1352 /**
1353 * @param $ids
1354 *
1355 * @return array
1356 */
6a488035
TO
1357 public static function getMembershipCount($ids) {
1358 $queryString = "
1359SELECT count( pfv.id ) AS count, pfv.id AS id
1360FROM civicrm_price_field_value pfv
1361INNER JOIN civicrm_membership_type mt ON mt.id = pfv.membership_type_id
1362WHERE pfv.id IN ( $ids )
1363GROUP BY mt.member_of_contact_id";
1364
1365 $crmDAO = CRM_Core_DAO::executeQuery($queryString);
1366 $count = array();
1367
1368 while ($crmDAO->fetch()) {
1369 $count[$crmDAO->id] = $crmDAO->count;
1370 }
1371
1372 return $count;
1373 }
1374
1375 /**
fe482240 1376 * Check if auto renew option should be shown.
6a488035 1377 *
8eb1503b 1378 * The auto-renew option should be visible if membership types associated with all the fields has
1379 * been set for auto-renew option.
1380 *
1381 * Auto renew checkbox should be frozen if for all the membership type auto renew is required
1382 *
414c1420
TO
1383 * @param int $priceSetId
1384 * Price set id.
6a488035 1385 *
a6c01b45
CW
1386 * @return int
1387 * $autoRenewOption ( 0:hide, 1:optional 2:required )
6a488035
TO
1388 */
1389 public static function checkAutoRenewForPriceSet($priceSetId) {
8eb1503b 1390 $query = 'SELECT DISTINCT mt.auto_renew, mt.duration_interval, mt.duration_unit,
1391 pf.html_type, pf.id as price_field_id
6a488035
TO
1392 FROM civicrm_price_field_value pfv
1393 INNER JOIN civicrm_membership_type mt ON pfv.membership_type_id = mt.id
1394 INNER JOIN civicrm_price_field pf ON pfv.price_field_id = pf.id
1395 WHERE pf.price_set_id = %1
1396 AND pf.is_active = 1
8eb1503b 1397 AND pfv.is_active = 1
1398 ORDER BY price_field_id';
6a488035
TO
1399
1400 $params = array(1 => array($priceSetId, 'Integer'));
1401
353ffa53 1402 $dao = CRM_Core_DAO::executeQuery($query, $params);
8eb1503b 1403
88089d21 1404 //CRM-18050: Check count of price set fields which has been set with auto-renew option.
137d1fac
WA
1405 //If price set field is already present with auto-renew option then, it will restrict for adding another price set field with auto-renew option.
1406 if ($dao->N == 0) {
1407 return 0;
1408 }
1409
6a488035 1410 $autoRenewOption = 2;
8eb1503b 1411 $priceFields = array();
6a488035
TO
1412 while ($dao->fetch()) {
1413 if (!$dao->auto_renew) {
8eb1503b 1414 // If any one can't be renewed none can.
1415 return 0;
6a488035
TO
1416 }
1417 if ($dao->auto_renew == 1) {
1418 $autoRenewOption = 1;
1419 }
1420
8eb1503b 1421 if ($dao->html_type == 'Checkbox' && !in_array($dao->duration_interval . $dao->duration_unit, $priceFields[$dao->price_field_id])) {
1422 // Checkbox fields cannot support auto-renew if they have more than one duration configuration
1423 // as more than one can be selected. Radio and select are either-or so they can have more than one duration.
1424 return 0;
1425 }
1426 $priceFields[$dao->price_field_id][] = $dao->duration_interval . $dao->duration_unit;
1427 foreach ($priceFields as $priceFieldID => $durations) {
1428 if ($priceFieldID != $dao->price_field_id && !in_array($dao->duration_interval . $dao->duration_unit, $durations)) {
1429 // Another price field has a duration configuration that differs so we can't offer auto-renew.
1430 return 0;
1431 }
1432 }
6a488035
TO
1433 }
1434
8eb1503b 1435 return $autoRenewOption;
6a488035
TO
1436 }
1437
1438 /**
fe482240 1439 * Retrieve auto renew frequency and interval.
6a488035 1440 *
414c1420
TO
1441 * @param int $priceSetId
1442 * Price set id.
6a488035 1443 *
a6c01b45
CW
1444 * @return array
1445 * associate array of frequency interval and unit
6a488035
TO
1446 */
1447 public static function getRecurDetails($priceSetId) {
1448 $query = 'SELECT mt.duration_interval, mt.duration_unit
1449 FROM civicrm_price_field_value pfv
1450 INNER JOIN civicrm_membership_type mt ON pfv.membership_type_id = mt.id
1451 INNER JOIN civicrm_price_field pf ON pfv.price_field_id = pf.id
1452 WHERE pf.price_set_id = %1 LIMIT 1';
1453
1454 $params = array(1 => array($priceSetId, 'Integer'));
1455 $dao = CRM_Core_DAO::executeQuery($query, $params);
1456 $dao->fetch();
1457 return array($dao->duration_interval, $dao->duration_unit);
1458 }
1459
ffd93213
EM
1460 /**
1461 * @return object
1462 */
00be9182 1463 public static function eventPriceSetDomainID() {
d356cdeb 1464 return Civi::settings()->get('event_price_set_domain_id');
6a488035
TO
1465 }
1466
1467 /**
fe482240 1468 * Update the is_quick_config flag in the db.
6a488035 1469 *
414c1420
TO
1470 * @param int $id
1471 * Id of the database record.
acb1052e 1472 * @param bool $isQuickConfig we want to set the is_quick_config field.
414c1420 1473 * Value we want to set the is_quick_config field.
6a488035 1474 *
a6c01b45 1475 * @return Object
b44e3f84 1476 * DAO object on success, null otherwise
6a488035 1477 */
00be9182 1478 public static function setIsQuickConfig($id, $isQuickConfig) {
9da8dc8c 1479 return CRM_Core_DAO::setFieldValue('CRM_Price_DAO_PriceSet', $id, 'is_quick_config', $isQuickConfig);
6a488035
TO
1480 }
1481
1482 /**
f72e6e2c 1483 * Check if price set id provides option for user to select both auto-renew and non-auto-renew memberships
6a488035 1484 *
003ca729
EM
1485 * @param int $id
1486 *
1487 * @return bool
6a488035 1488 */
f72e6e2c
EM
1489 public static function isMembershipPriceSetContainsMixOfRenewNonRenew($id) {
1490 $membershipTypes = self::getMembershipTypesFromPriceSet($id);
1491 if (!empty($membershipTypes['autorenew']) && !empty($membershipTypes['non_renew'])) {
1492 return TRUE;
6a488035 1493 }
ba1dcfda 1494 return FALSE;
6a488035
TO
1495 }
1496
37b11065
EM
1497 /**
1498 * Get an array of the membership types in a price set.
1499 *
1500 * @param int $id
1501 *
1502 * @return array(
1503 * Membership types in the price set
1504 */
1505 public static function getMembershipTypesFromPriceSet($id) {
1506 $query
1507 = "SELECT pfv.id, pfv.price_field_id, pfv.name, pfv.membership_type_id, pf.html_type, mt.auto_renew
1508FROM civicrm_price_field_value pfv
1509LEFT JOIN civicrm_price_field pf ON pf.id = pfv.price_field_id
1510LEFT JOIN civicrm_price_set ps ON ps.id = pf.price_set_id
1511LEFT JOIN civicrm_membership_type mt ON mt.id = pfv.membership_type_id
1512WHERE ps.id = %1
1513";
1514
1515 $params = array(1 => array($id, 'Integer'));
1516 $dao = CRM_Core_DAO::executeQuery($query, $params);
1517
1518 $membershipTypes = array(
1519 'all' => array(),
1520 'autorenew' => array(),
1521 'autorenew_required' => array(),
1522 'autorenew_optional' => array(),
1523 );
1524 while ($dao->fetch()) {
1525 if (empty($dao->membership_type_id)) {
1526 continue;
1527 }
1528 $membershipTypes['all'][] = $dao->membership_type_id;
1529 if (!empty($dao->auto_renew)) {
1530 $membershipTypes['autorenew'][] = $dao->membership_type_id;
1531 if ($dao->auto_renew == 2) {
1532 $membershipTypes['autorenew_required'][] = $dao->membership_type_id;
1533 }
1534 else {
1535 $membershipTypes['autorenew_optional'][] = $dao->membership_type_id;
1536 }
1537 }
1538 else {
1539 $membershipTypes['non_renew'][] = $dao->membership_type_id;
1540 }
1541 }
1542 return $membershipTypes;
1543 }
1544
e0c1764e 1545 /**
c6914066
PN
1546 * Copy priceSet when event/contibution page is copied
1547 *
414c1420
TO
1548 * @param string $baoName
1549 * BAO name.
1550 * @param int $id
1551 * Old event/contribution page id.
1552 * @param int $newId
1553 * Newly created event/contribution page id.
c6914066 1554 */
00be9182 1555 public static function copyPriceSet($baoName, $id, $newId) {
9da8dc8c 1556 $priceSetId = CRM_Price_BAO_PriceSet::getFor($baoName, $id);
c6914066 1557 if ($priceSetId) {
9da8dc8c 1558 $isQuickConfig = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $priceSetId, 'is_quick_config');
22e263ad 1559 if ($isQuickConfig) {
37326fa1 1560 $copyPriceSet = CRM_Price_BAO_PriceSet::copy($priceSetId);
9da8dc8c 1561 CRM_Price_BAO_PriceSet::addTo($baoName, $newId, $copyPriceSet->id);
44c8822b 1562 }
c6914066 1563 else {
9da8dc8c 1564 $copyPriceSet = &CRM_Core_DAO::copyGeneric('CRM_Price_DAO_PriceSetEntity',
c6914066
PN
1565 array(
1566 'entity_id' => $id,
1567 'entity_table' => $baoName,
1568 ),
1569 array('entity_id' => $newId)
1570 );
1571 }
1572 // copy event discount
1573 if ($baoName == 'civicrm_event') {
1574 $discount = CRM_Core_BAO_Discount::getOptionGroup($id, 'civicrm_event');
1575 foreach ($discount as $discountId => $setId) {
1576
9da8dc8c 1577 $copyPriceSet = &CRM_Price_BAO_PriceSet::copy($setId);
44c8822b 1578
28156120 1579 CRM_Core_DAO::copyGeneric(
c6914066
PN
1580 'CRM_Core_DAO_Discount',
1581 array(
1582 'id' => $discountId,
1583 ),
1584 array(
1585 'entity_id' => $newId,
1586 'price_set_id' => $copyPriceSet->id,
1587 )
1588 );
1589 }
1590 }
1591 }
1592 }
dc428161 1593
d424ffde 1594 /**
fe482240 1595 * Function to set tax_amount and tax_rate in LineItem.
d424ffde
CW
1596 *
1597 * @param array $field
1598 * @param array $lineItem
1599 * @param int $optionValueId
83e1baa3 1600 * @param float $totalTax
d424ffde
CW
1601 *
1602 * @return array
dc428161 1603 */
83e1baa3 1604 public static function setLineItem($field, $lineItem, $optionValueId, &$totalTax) {
dc428161 1605 if ($field['html_type'] == 'Text') {
1606 $taxAmount = $field['options'][$optionValueId]['tax_amount'] * $lineItem[$optionValueId]['qty'];
1607 }
1608 else {
1609 $taxAmount = $field['options'][$optionValueId]['tax_amount'];
1610 }
1611 $taxRate = $field['options'][$optionValueId]['tax_rate'];
dc428161 1612 $lineItem[$optionValueId]['tax_amount'] = $taxAmount;
1613 $lineItem[$optionValueId]['tax_rate'] = $taxRate;
83e1baa3 1614 $totalTax += $taxAmount;
dc428161 1615 return $lineItem;
1616 }
96025800 1617
362bd1b7 1618 /**
1619 * Get the first price set value IDs from a parameters array.
1620 *
1621 * In practice this is really used when we only expect one to exist.
1622 *
1623 * @param array $params
1624 *
1625 * @return array
1626 * Array of the ids of the price set values.
1627 */
1628 public static function parseFirstPriceSetValueIDFromParams($params) {
1629 $priceSetValueIDs = self::parsePriceSetValueIDsFromParams($params);
1630 return reset($priceSetValueIDs);
1631 }
1632
1633 /**
1634 * Get the price set value IDs from a set of parameters
1635 *
1636 * @param array $params
1637 *
1638 * @return array
1639 * Array of the ids of the price set values.
1640 */
1641 public static function parsePriceSetValueIDsFromParams($params) {
1642 $priceSetParams = self::parsePriceSetArrayFromParams($params);
1643 $priceSetValueIDs = array();
1644 foreach ($priceSetParams as $priceSetParam) {
1645 foreach (array_keys($priceSetParam) as $priceValueID) {
1646 $priceSetValueIDs[] = $priceValueID;
1647 }
1648 }
1649 return $priceSetValueIDs;
1650 }
1651
1652 /**
1653 * Get the price set value IDs from a set of parameters
1654 *
1655 * @param array $params
1656 *
1657 * @return array
1658 * Array of price fields filtered from the params.
1659 */
1660 public static function parsePriceSetArrayFromParams($params) {
1661 $priceSetParams = array();
1662 foreach ($params as $field => $value) {
1663 $parts = explode('_', $field);
0b34e9a4 1664 if (count($parts) == 2 && $parts[0] == 'price' && is_numeric($parts[1]) && is_array($value)) {
362bd1b7 1665 $priceSetParams[$field] = $value;
1666 }
1667 }
1668 return $priceSetParams;
1669 }
1670
05465712 1671 /**
1672 * Get non-deductible amount from price options
1673 *
1674 * @param int $priceSetId
1675 * @param array $lineItem
1676 *
1677 * @return int
1678 * calculated non-deductible amount.
1679 */
1680 public static function getNonDeductibleAmountFromPriceSet($priceSetId, $lineItem) {
1681 $nonDeductibleAmount = 0;
1682 if (!empty($lineItem[$priceSetId])) {
1bde39c7 1683 foreach ($lineItem[$priceSetId] as $options) {
05465712 1684 $nonDeductibleAmount += $options['non_deductible_amount'] * $options['qty'];
1685 }
1686 }
1687
1688 return $nonDeductibleAmount;
1689 }
1690
f5b8da4b 1691 /**
1692 * Get an array of all forms using a given price set.
1693 *
1694 * @param int $id
1695 *
1696 * @return array
1697 * Pages using the price set, keyed by type. e.g
1698 * array('
1699 * 'civicrm_contribution_page' => array(2,5,6),
1700 * 'civicrm_event' => array(5,6),
1701 * 'civicrm_event_template' => array(7),
1702 * )
1703 */
1704 public static function getFormsUsingPriceSet($id) {
1705 $forms = array();
1706 $queryString = "
1707SELECT entity_table, entity_id
1708FROM civicrm_price_set_entity
1709WHERE price_set_id = %1";
1710 $params = array(1 => array($id, 'Integer'));
1711 $crmFormDAO = CRM_Core_DAO::executeQuery($queryString, $params);
1712
1713 while ($crmFormDAO->fetch()) {
1714 $forms[$crmFormDAO->entity_table][] = $crmFormDAO->entity_id;
1715 }
1716 return $forms;
1717 }
1718
1719 /**
1720 * @param array $forms
1721 * Array of forms that use a price set keyed by entity. e.g
1722 * array('
1723 * 'civicrm_contribution_page' => array(2,5,6),
1724 * 'civicrm_event' => array(5,6),
1725 * 'civicrm_event_template' => array(7),
1726 * )
1727 *
1728 * @return mixed
1729 * Array of entities suppliemented with per entity information.
1730 * e.g
1731 * array('civicrm_event' => array(7 => array('title' => 'x'...))
1732 *
1733 * @throws \Exception
1734 */
1735 protected static function reformatUsedByFormsWithEntityData($forms) {
1736 $usedBy = array();
1737 foreach ($forms as $table => $entities) {
1738 switch ($table) {
1739 case 'civicrm_event':
1740 $ids = implode(',', $entities);
1741 $queryString = "SELECT ce.id as id, ce.title as title, ce.is_public as isPublic, ce.start_date as startDate, ce.end_date as endDate, civicrm_option_value.label as eventType, ce.is_template as isTemplate, ce.template_title as templateTitle
1742FROM civicrm_event ce
1743LEFT JOIN civicrm_option_value ON
1744 ( ce.event_type_id = civicrm_option_value.value )
1745LEFT JOIN civicrm_option_group ON
1746 ( civicrm_option_group.id = civicrm_option_value.option_group_id )
1747WHERE
1748 civicrm_option_group.name = 'event_type' AND
1749 ce.id IN ($ids) AND
1750 ce.is_active = 1;";
1751 $crmDAO = CRM_Core_DAO::executeQuery($queryString);
1752 while ($crmDAO->fetch()) {
1753 if ($crmDAO->isTemplate) {
1754 $usedBy['civicrm_event_template'][$crmDAO->id]['title'] = $crmDAO->templateTitle;
1755 $usedBy['civicrm_event_template'][$crmDAO->id]['eventType'] = $crmDAO->eventType;
1756 $usedBy['civicrm_event_template'][$crmDAO->id]['isPublic'] = $crmDAO->isPublic;
1757 }
1758 else {
1759 $usedBy[$table][$crmDAO->id]['title'] = $crmDAO->title;
1760 $usedBy[$table][$crmDAO->id]['eventType'] = $crmDAO->eventType;
1761 $usedBy[$table][$crmDAO->id]['startDate'] = $crmDAO->startDate;
1762 $usedBy[$table][$crmDAO->id]['endDate'] = $crmDAO->endDate;
1763 $usedBy[$table][$crmDAO->id]['isPublic'] = $crmDAO->isPublic;
1764 }
1765 }
1766 break;
1767
1768 case 'civicrm_contribution_page':
1769 $ids = implode(',', $entities);
1770 $queryString = "SELECT cp.id as id, cp.title as title, cp.start_date as startDate, cp.end_date as endDate,ct.name as type
1771FROM civicrm_contribution_page cp, civicrm_financial_type ct
1772WHERE ct.id = cp.financial_type_id AND
1773 cp.id IN ($ids) AND
1774 cp.is_active = 1;";
1775 $crmDAO = CRM_Core_DAO::executeQuery($queryString);
1776 while ($crmDAO->fetch()) {
1777 $usedBy[$table][$crmDAO->id]['title'] = $crmDAO->title;
1778 $usedBy[$table][$crmDAO->id]['type'] = $crmDAO->type;
1779 $usedBy[$table][$crmDAO->id]['startDate'] = $crmDAO->startDate;
1780 $usedBy[$table][$crmDAO->id]['endDate'] = $crmDAO->endDate;
1781 }
1782 break;
1783
1784 case 'civicrm_contribution':
1785 case 'civicrm_membership':
1786 case 'civicrm_participant':
1787 $usedBy[$table] = 1;
1788 break;
1789
1790 default:
1791 CRM_Core_Error::fatal("$table is not supported in PriceSet::usedBy()");
1792 break;
1793 }
1794 }
1795 return $usedBy;
1796 }
1797
6a488035 1798}