Skip to content

Commit

Permalink
Merge pull request civicrm#27902 from eileenmcnaughton/supports
Browse files Browse the repository at this point in the history
Use api to get price set metadata - Online Contribution Page
  • Loading branch information
colemanw authored Oct 24, 2023
2 parents 2f33e85 + 039a435 commit 0172313
Show file tree
Hide file tree
Showing 10 changed files with 118 additions and 59 deletions.
6 changes: 3 additions & 3 deletions CRM/Contribute/Form/Contribution/Main.php
Original file line number Diff line number Diff line change
Expand Up @@ -491,8 +491,8 @@ private function buildPriceSet(&$form, $component = NULL) {
$adminFieldVisible = CRM_Core_Permission::check('administer CiviCRM');
$checklifetime = FALSE;
foreach ($this->getPriceFieldMetaData() as $id => $field) {
if ($field['visibility'] === 'public' ||
($field['visibility'] === 'admin' && $adminFieldVisible)
if ($field['visibility_id:name'] === 'public' ||
($field['visibility_id:name'] === 'admin' && $adminFieldVisible)
) {
$options = $field['options'] ?? NULL;
if ($this->_membershipContactID && $options) {
Expand All @@ -508,7 +508,7 @@ private function buildPriceSet(&$form, $component = NULL) {
}
if (!CRM_Core_Permission::check('edit contributions')) {
foreach ($options as $key => $currentOption) {
if ($currentOption['visibility_id'] == CRM_Price_BAO_PriceField::getVisibilityOptionID('admin')) {
if ($currentOption['visibility_id:name'] === 'admin') {
unset($options[$key]);
}
}
Expand Down
2 changes: 1 addition & 1 deletion CRM/Contribute/Form/ContributionBase.php
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,7 @@ private function initSet($form) {
if ($form->_action & CRM_Core_Action::UPDATE) {
$form->_values['line_items'] = CRM_Price_BAO_LineItem::getLineItems($form->_id, 'contribution');
}
$form->_priceSet = [$this->getPriceSetID() => $this->order->getPriceSetMetadata()];
$form->_priceSet = $this->order->getPriceSetMetadata();
$this->setPriceFieldMetaData($this->order->getPriceFieldsMetadata());
$form->set('priceSet', $form->_priceSet);
}
Expand Down
10 changes: 4 additions & 6 deletions CRM/Financial/BAO/Order.php
Original file line number Diff line number Diff line change
Expand Up @@ -683,10 +683,10 @@ protected function setPriceFieldMetadata(array $metadata): void {
if (!empty($option['membership_type_id'])) {
$membershipType = CRM_Member_BAO_MembershipType::getMembershipType((int) $option['membership_type_id']);
$metadata[$index]['options'][$optionID]['auto_renew'] = (int) $membershipType['auto_renew'];
if ($membershipType['auto_renew'] && empty($this->priceSetMetadata['auto_renew_membership_type'])) {
if ($membershipType['auto_renew'] && empty($this->priceSetMetadata['auto_renew_membership_field'])) {
// Quick form layer supports one auto-renew membership type per price set. If we
// want more for any reason we can add another array property.
$this->priceSetMetadata['auto_renew_membership_type'] = (int) $option['membership_type_id'];
$this->priceSetMetadata['auto_renew_membership_field'] = (int) $option['membership_type_id'];
}
}
}
Expand All @@ -711,8 +711,7 @@ public function getPriceSetMetadata(): array {
if (empty($this->priceSetMetadata)) {
$this->priceSetMetadata = CRM_Price_BAO_PriceSet::getCachedPriceSetDetail($this->getPriceSetID());
$this->priceSetMetadata['id'] = $this->getPriceSetID();
// @todo - make sure this is an array - commented out for now as this PR is against the rc.
// $priceSetMetadata['extends'] = explode(CRM_Core_DAO::VALUE_SEPARATOR, $priceSetMetadata['extends']);
$this->priceSetMetadata['auto_renew_membership_field'] = NULL;
$this->setPriceFieldMetadata($this->priceSetMetadata['fields']);
unset($this->priceSetMetadata['fields']);
}
Expand All @@ -725,8 +724,7 @@ public function isMembershipPriceSet() {
}
// Access the property if set, to avoid a potential loop when the hook is called.
$priceSetMetadata = $this->priceSetMetadata ?: $this->getPriceSetMetadata();
$extends = explode(CRM_Core_DAO::VALUE_SEPARATOR, $priceSetMetadata['extends']);
return in_array(CRM_Core_Component::getComponentID('CiviMember'), $extends, FALSE);
return in_array(CRM_Core_Component::getComponentID('CiviMember'), $priceSetMetadata['extends'], FALSE);
}

/**
Expand Down
14 changes: 7 additions & 7 deletions CRM/Price/BAO/PriceField.php
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ public static function addQuickFormElement(

if (!empty($fieldOptions[$optionKey]['label'])) {
//check for label.
$label = $fieldOptions[$optionKey]['label'];
$label = CRM_Utils_String::purifyHTML($fieldOptions[$optionKey]['label']);
}
// @todo - move this back to the only calling function on Contribution_Form_Main.php
if ($isQuickConfig && $field->name === 'other_amount') {
Expand Down Expand Up @@ -383,7 +383,7 @@ public static function addQuickFormElement(
$qf->assign('membershipFieldID', $field->id);
}

$choice[$opt['id']] = $priceOptionText['label'];
$choice[$opt['id']] = CRM_Utils_String::purifyHTML($priceOptionText['label']);
$choiceAttrs[$opt['id']] = $extra;
if ($is_pay_later) {
$qf->add('text', 'txt-' . $elementName, $label, ['size' => '4']);
Expand Down Expand Up @@ -771,12 +771,12 @@ public static function priceSetValidation($priceSetId, $fields, &$error, $allowN
*/
public static function buildPriceOptionText($opt, $isDisplayAmounts, $valueFieldName) {
$preHelpText = $postHelpText = '';
$optionLabel = !empty($opt['label']) ? '<span class="crm-price-amount-label">' . $opt['label'] . '</span>' : '';
if (!empty($opt['help_pre'])) {
$preHelpText = '<span class="crm-price-amount-help-pre description">' . $opt['help_pre'] . '</span><span class="crm-price-amount-help-pre-separator">:&nbsp;</span>';
$optionLabel = !empty($opt['label']) ? '<span class="crm-price-amount-label">' . CRM_Utils_String::purifyHTML($opt['label']) . '</span>' : '';
if (CRM_Utils_String::purifyHTML($opt['help_pre'] ?? '')) {
$preHelpText = '<span class="crm-price-amount-help-pre description">' . CRM_Utils_String::purifyHTML($opt['help_pre']) . '</span><span class="crm-price-amount-help-pre-separator">:&nbsp;</span>';
}
if (!empty($opt['help_post'])) {
$postHelpText = '<span class="crm-price-amount-help-post-separator">:&nbsp;</span><span class="crm-price-amount-help-post description">' . $opt['help_post'] . '</span>';
if (CRM_Utils_String::purifyHTML($opt['help_post'] ?? '')) {
$postHelpText = '<span class="crm-price-amount-help-post-separator">:&nbsp;</span><span class="crm-price-amount-help-post description">' . CRM_Utils_String::purifyHTML($opt['help_post']) . '</span>';
}

$invoicing = Civi::settings()->get('invoicing');
Expand Down
50 changes: 37 additions & 13 deletions CRM/Price/BAO/PriceSet.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
* @copyright CiviCRM LLC https://civicrm.org/licensing
*/

use Civi\Api4\PriceField;
use Civi\Api4\PriceFieldValue;
use Civi\Api4\PriceSet;

/**
* Business object for managing price sets.
*
Expand Down Expand Up @@ -757,30 +761,50 @@ public static function filterPriceFieldsFromParams($priceSetID, $params) {
}

/**
* Wrapper for getSetDetail with caching.
* Get PriceSet + Fields + FieldValues nested, with caching.
*
* This gets the same values as getSet but uses apiv4 for more
* predictability & better variable typing.
*
* We seem to be passing this array around in a painful way - presumably to avoid the hit
* of loading it - so lets make it callable with caching.
*
* Why not just add caching to the other function? We could do - it just seemed a bit unclear the best caching pattern
* & the function was already pretty fugly. Also, I feel like we need to migrate the interaction with price-sets into
* a more granular interaction - ie. retrieve specific data using specific functions on this class & have the form
* think less about the price sets.
*
* @param int $priceSetID
*
* @return array
*
* @noinspection PhpUnhandledExceptionInspection
*/
public static function getCachedPriceSetDetail($priceSetID) {
public static function getCachedPriceSetDetail(int $priceSetID): array {
$cacheKey = __CLASS__ . __FUNCTION__ . '_' . $priceSetID;
$cache = CRM_Utils_Cache::singleton();
$values = $cache->get($cacheKey);
if (empty($values)) {
$data = self::getSetDetail($priceSetID);
$values = $data[$priceSetID];
$cache->set($cacheKey, $values);
$data = $cache->get($cacheKey);
if (empty($data)) {
$data = PriceSet::get(FALSE)
->addWhere('id', '=', $priceSetID)
->addSelect('*', 'visibility_id:name', 'extends:name')
->execute()->first();
$data['fields'] = (array) PriceField::get(FALSE)
->addWhere('price_set_id', '=', $priceSetID)
->addSelect('*', 'visibility_id:name')
->execute()->indexBy('id');
foreach ($data['fields'] as &$field) {
$field['options'] = [];
// Add in visibility because Smarty templates expect it and it is hard to adjust them to colon format.
$field['visibility'] = $field['visibility_id:name'];
}
$options = PriceFieldValue::get(FALSE)
->addWhere('price_field_id', 'IN', array_keys($data['fields']))
->addSelect('*', 'membership_type_id.name', 'visibility_id:name')
->execute();
foreach ($options as $option) {
// Add in visibility because Smarty templates expect it and it is hard to adjust them to colon format.
$option['visibility'] = $option['visibility_id:name'];
$data['fields'][$option['price_field_id']]['options'][$option['id']] = $option;
}
$cache->set($cacheKey, $data);
}
return $values;
return $data;
}

/**
Expand Down
18 changes: 9 additions & 9 deletions templates/CRM/Price/Form/Field.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,12 @@
<div class="crm-block crm-form-block crm-price-field-form-block">
<table class="form-layout">
<tr class="crm-price-field-form-block-label">
<td class="label">{$form.label.label}</td>
<td class="label">{$form.label.label|escape}</td>
<td>{if $action == 2}{include file='CRM/Core/I18n/Dialog.tpl' table='civicrm_price_field' field='label' id=$fid}{/if}{$form.label.html}
</td>
</tr>
<tr class="crm-price-field-form-block-html_type">
<td class="label">{$form.html_type.label}</td>
<td class="label">{$form.html_type.label|escape}</td>
<td>{$form.html_type.html}
</td>
</tr>
Expand All @@ -103,33 +103,33 @@
<div id="price-block" {if $action eq 2 && $form.html_type.value.0 eq 'Text'} class="show-block" {else} class="hiddenElement" {/if}>
<table class="form-layout">
<tr class="crm-price-field-form-block-price">
<td class="label">{$form.price.label} <span class="crm-marker" title="{ts}This field is required.{/ts}">*</span></td>
<td class="label">{$form.price.label|escape} <span class="crm-marker" title="{ts}This field is required.{/ts}">*</span></td>
<td>{$form.price.html}
{if $action neq 4}
<br /><span class="description">{ts}Unit price.{/ts}</span> {help id="id-negative"}
{/if}
</td>
</tr>
<tr class="crm-price-field-form-block-non-deductible-amount">
<td class="label">{$form.non_deductible_amount.label}</td>
<td class="label">{$form.non_deductible_amount.label|escape}</td>
<td>{$form.non_deductible_amount.html}</td>
</tr>
{if $useForEvent}
<tr class="crm-price-field-form-block-count">
<td class="label">{$form.count.label}</td>
<td class="label">{$form.count.label|escape}</td>
<td>{$form.count.html}<br />
<span class="description">{ts}Enter a value here if you want to increment the number of registered participants per unit against the maximum number of participants allowed for this event.{/ts}</span>
{help id="id-participant-count"}
</td>
</tr>
<tr class="crm-price-field-form-block-max_value">
<td class="label">{$form.max_value.label}</td>
<td class="label">{$form.max_value.label|escape}</td>
<td>{$form.max_value.html}
</td>
</tr>
{/if}
<tr class="crm-price-field-form-block-financial_type">
<td class="label">{$form.financial_type_id.label}<span class="crm-marker" title="{ts}This field is required.{/ts}">*</span></td></td>
<td class="label">{$form.financial_type_id.label|escape}<span class="crm-marker" title="{ts}This field is required.{/ts}">*</span></td></td>
<td>
{if !$financialType}
{capture assign=ftUrl}{crmURL p='civicrm/admin/financial/financialType' q="reset=1"}{/capture}
Expand Down Expand Up @@ -169,7 +169,7 @@
</tr>

<tr class="crm-price-field-form-block-help_pre">
<td class="label">{$form.help_pre.label}</td>
<td class="label">{$form.help_pre.label|escape}</td>
<td>{if $action == 2}{include file='CRM/Core/I18n/Dialog.tpl' table='civicrm_price_field' field='help_pre' id=$fid}{/if}{$form.help_pre.html|crmAddClass:huge}&nbsp;
{if $action neq 4}
<div class="description">{ts}Explanatory text displayed to users at the beginning of this field.{/ts}</div>
Expand All @@ -178,7 +178,7 @@
</tr>

<tr class="crm-price-field-form-block-help_post">
<td class="label">{$form.help_post.label}</td>
<td class="label">{$form.help_post.label|escape}</td>
<td>{if $action == 2}{include file='CRM/Core/I18n/Dialog.tpl' table='civicrm_price_field' field='help_post' id=$fid}{/if}{$form.help_post.html|crmAddClass:huge}&nbsp;
{if $action neq 4}
<div class="description">{ts}Explanatory text displayed to users below this field.{/ts}</div>
Expand Down
8 changes: 4 additions & 4 deletions templates/CRM/Price/Form/Option.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@
</tr>
{/if}
<tr class="crm-price-option-form-block-label">
<td class="label">{$form.label.label}</td>
<td class="label">{$form.label.label|escape}</td>
<td>{if $action == 2}{include file='CRM/Core/I18n/Dialog.tpl' table='civicrm_price_field_value' field='label' id=$optionId}{/if}{$form.label.html}</td>
</tr>
<tr class="crm-price-option-form-block-amount">
<td class="label">{$form.amount.label}</td>
<td class="label">{$form.amount.label|escape}</td>
<td>{$form.amount.html}</td>
</tr>
<tr class="crm-price-option-form-block-non-deductible-amount">
Expand All @@ -44,11 +44,11 @@
<td>{if $action == 2}{include file='CRM/Core/I18n/Dialog.tpl' table='civicrm_price_field_value' field='description' id=$optionId}{/if}{$form.description.html}</td>
</tr>
<tr class="crm-price-option-form-block-help-pre">
<td class="label">{$form.help_pre.label}</td>
<td class="label">{$form.help_pre.label|escape}</td>
<td>{if $action == 2}{include file='CRM/Core/I18n/Dialog.tpl' table='civicrm_price_field_value' field='help_pre' id=$optionId}{/if}{$form.help_pre.html}</td>
</tr>
<tr class="crm-price-option-form-block-help-post">
<td class="label">{$form.help_post.label}</td>
<td class="label">{$form.help_post.label|escape}</td>
<td>{if $action == 2}{include file='CRM/Core/I18n/Dialog.tpl' table='civicrm_price_field_value' field='help_post' id=$optionId}{/if}{$form.help_post.html}</td>
</tr>
<tr class="crm-price-option-form-block-financial-type">
Expand Down
24 changes: 12 additions & 12 deletions templates/CRM/Price/Form/PriceSet.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
{crmRegion name="price-set-1"}
<div id="priceset" class="crm-section price_set-section">
{if $priceSet.help_pre}
<div class="messages help">{$priceSet.help_pre}</div>
<div class="messages help">{$priceSet.help_pre|escape}</div>
{/if}

{assign var='adminFld' value=false}
Expand All @@ -28,12 +28,12 @@
{foreach from=$priceSet.fields item=element key=field_id}
{* Skip 'Admin' visibility price fields WHEN this tpl is used in online registration unless user has administer CiviCRM permission. *}
{if $element.visibility EQ 'public' || ($element.visibility EQ 'admin' && $adminFld EQ true) || $context eq 'standalone' || $context eq 'advanced' || $context eq 'search' || $context eq 'participant' || $context eq 'dashboard'}
{if $element.help_pre}<span class="content description">{$element.help_pre}</span><br />{/if}
<div class="crm-section {$element.name}-section crm-price-field-id-{$field_id}">
{if $element.help_pre}<span class="content description">{$element.help_pre|escape}</span><br />{/if}
<div class="crm-section {$element.name|escape}-section crm-price-field-id-{$field_id}">
{if ($element.html_type eq 'CheckBox' || $element.html_type == 'Radio') && $element.options_per_line}
{assign var="element_name" value="price_`$field_id`"}
<div class="label">{$form.$element_name.label}</div>
<div class="content {$element.name}-content">
<div class="label">{$form.$element_name.label|purify}</div>
<div class="content {$element.name|escape}-content">
{assign var="elementCount" value="0"}
{assign var="optionCount" value="0"}
{assign var="rowCount" value="0"}
Expand All @@ -43,7 +43,7 @@
{assign var="optionCount" value=$optionCount+1}
{if $optionCount == 1}
{assign var="rowCount" value=$rowCount+1}
<div class="price-set-row {$element.name}-row{$rowCount}">
<div class="price-set-row {$element.name|escape}-row{$rowCount}">
{/if}
<span class="price-set-option-content">{$form.$element_name.$key.html}</span>
{if $optionCount == $element.options_per_line || $elementCount == $form.$element_name|@count}
Expand All @@ -53,15 +53,15 @@
{/if}
{/foreach}
{if $element.help_post}
<div class="description">{$element.help_post}</div>
<div class="description">{$element.help_post|escape}</div>
{/if}
</div>
{else}

{assign var="element_name" value="price_"|cat:$field_id}

<div class="label">{$form.$element_name.label}</div>
<div class="content {$element.name}-content">
<div class="label">{$form.$element_name.label|escape}</div>
<div class="content {$element.name|escape}-content">
{$form.$element_name.html}
{if $element.html_type eq 'Text'}
{if $element.is_display_amounts}
Expand Down Expand Up @@ -91,7 +91,7 @@
{/if}
{/if}
{/if}
{if $element.help_post}<br /><span class="description">{$element.help_post}</span>{/if}
{if $element.help_post}<br /><span class="description">{$element.help_post|escape}</span>{/if}
</div>

{/if}
Expand All @@ -102,7 +102,7 @@
<div class='label'></div>
<div class='content' id="auto_renew_section">
{if $form.auto_renew}
{$form.auto_renew.html}&nbsp;{$form.auto_renew.label}
{$form.auto_renew.html}&nbsp;{$form.auto_renew.label|escape}
{/if}
</div>
<div class='content' id="force_renew" style='display: none'>{ts}Membership will renew automatically.{/ts}</div>
Expand All @@ -116,7 +116,7 @@
{/foreach}

{if $priceSet.help_post}
<div class="messages help">{$priceSet.help_post}</div>
<div class="messages help">{$priceSet.help_post|escape}</div>
{/if}

{include file="CRM/Price/Form/Calculate.tpl"}
Expand Down
Loading

0 comments on commit 0172313

Please sign in to comment.