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