From 9faf023919405283a52bba24ead59ff9c2d16895 Mon Sep 17 00:00:00 2001 From: Eileen McNaughton <emcnaughton@wikimedia.org> Date: Mon, 16 Oct 2023 10:58:32 +1300 Subject: [PATCH] Php8.x fixes on Main online contribution page --- CRM/Contribute/Form/Contribution/Main.php | 123 ++++++++++++++---- CRM/Contribute/Form/ContributionBase.php | 26 +++- CRM/Price/BAO/PriceField.php | 29 ++--- CRM/Profile/Form.php | 8 +- .../CRM/Contribute/Form/Contribution/Main.tpl | 23 ++-- 5 files changed, 139 insertions(+), 70 deletions(-) diff --git a/CRM/Contribute/Form/Contribution/Main.php b/CRM/Contribute/Form/Contribution/Main.php index e291f8c16cb7..897d29d78683 100644 --- a/CRM/Contribute/Form/Contribution/Main.php +++ b/CRM/Contribute/Form/Contribution/Main.php @@ -126,14 +126,14 @@ public function setDefaultValues() { // remove component related fields foreach ($this->_fields as $name => $fieldInfo) { //don't set custom data Used for Contribution (CRM-1344) - if (substr($name, 0, 7) == 'custom_') { + if (substr($name, 0, 7) === 'custom_') { $id = substr($name, 7); if (!CRM_Core_BAO_CustomGroup::checkCustomField($id, ['Contribution', 'Membership'])) { continue; } // ignore component fields } - elseif (array_key_exists($name, $contribFields) || (substr($name, 0, 11) == 'membership_') || (substr($name, 0, 13) == 'contribution_')) { + elseif (array_key_exists($name, $contribFields) || (substr($name, 0, 11) === 'membership_') || (substr($name, 0, 13) == 'contribution_')) { continue; } $fields[$name] = $fieldInfo; @@ -146,8 +146,9 @@ public function setDefaultValues() { $billingDefaults = $this->getProfileDefaults('Billing', $contactID); $this->_defaults = array_merge($this->_defaults, $billingDefaults); } - if (!empty($this->_ccid) && !empty($this->_pendingAmount)) { - $this->_defaults['total_amount'] = CRM_Utils_Money::formatLocaleNumericRoundedForDefaultCurrency($this->_pendingAmount); + $balance = $this->getContributionBalance(); + if ($balance) { + $this->_defaults['total_amount'] = CRM_Utils_Money::formatLocaleNumericRoundedForDefaultCurrency($balance); } /* @@ -401,10 +402,9 @@ public function buildQuickForm() { CRM_Core_BAO_CMSUser::buildForm($this, $profileID, TRUE); } } - if ($this->_pcpId && empty($this->_ccid)) { + if ($this->getPcpID() && empty($this->_ccid)) { if (CRM_PCP_BAO_PCP::displayName($this->_pcpId)) { $pcp_supporter_text = CRM_PCP_BAO_PCP::getPcpSupporterText($this->_pcpId, $this->_id, 'contribute'); - $this->assign('pcpSupporterText', $pcp_supporter_text); } $prms = ['id' => $this->_pcpId]; CRM_Core_DAO::commonRetrieve('CRM_PCP_DAO_PCP', $prms, $pcpInfo); @@ -420,6 +420,7 @@ public function buildQuickForm() { $this->addField('pcp_personal_note', ['entity' => 'ContributionSoft', 'context' => 'create', 'style' => 'height: 3em; width: 40em;']); } } + $this->assign('pcpSupporterText', $pcp_supporter_text ?? NULL); if (empty($this->_values['fee']) && empty($this->_ccid)) { throw new CRM_Core_Exception(ts('This page does not have any price fields configured or you may not have permission for them. Please contact the site administrator for more details.')); } @@ -542,13 +543,29 @@ private function buildPriceSet(&$form, $component = NULL) { } if (!empty($options)) { $label = (!empty($this->_membershipBlock) && $field['name'] === 'contribution_amount') ? ts('Additional Contribution') : $field['label']; + $extra = []; + $fieldID = (int) $field['id']; + if ($fieldID === $this->getPriceFieldOtherID()) { + $extra = [ + 'onclick' => 'useAmountOther("price_' . $this->getPriceFieldMainID() . '");', + 'autocomplete' => 'off', + ]; + } + if ($fieldID === $this->getPriceFieldMainID()) { + $extra = [ + 'onclick' => 'clearAmountOther("price_' . $this->getPriceFieldOtherID() . '");', + ]; + } + CRM_Price_BAO_PriceField::addQuickFormElement($form, - 'price_' . $field['id'], + 'price_' . $fieldID, $field['id'], FALSE, $field['is_required'] ?? FALSE, $label, - $options + $options, + [], + $extra ); } } @@ -556,6 +573,46 @@ private function buildPriceSet(&$form, $component = NULL) { $form->assign('ispricelifetime', $checklifetime); } + /** + * Get the idea of the other amount field if the form is configured to offer it. + * + * The other amount field is an alternative to the configured radio options, + * specific to this form. + * + * @return int|null + */ + private function getPriceFieldOtherID(): ?int { + if (!$this->isQuickConfig()) { + return NULL; + } + foreach ($this->order->getPriceFieldsMetadata() as $field) { + if ($field['name'] === 'other_amount') { + return (int) $field['id']; + } + } + return NULL; + } + + /** + * Get the idea of the other amount field if the form is configured to offer an other amount. + * + * The other amount field is an alternative to the configured radio options, + * specific to this form. + * + * @return int|null + */ + private function getPriceFieldMainID(): ?int { + if (!$this->isQuickConfig() || !$this->getPriceFieldOtherID()) { + return NULL; + } + foreach ($this->order->getPriceFieldsMetadata() as $field) { + if ($field['name'] !== 'other_amount') { + return (int) $field['id']; + } + } + return NULL; + } + /** * Build Membership Block in Contribution Pages. * @todo this was shared on CRM_Contribute_Form_ContributionBase but we are refactoring and simplifying for each @@ -1000,7 +1057,7 @@ public static function formRule($fields, $files, $self) { } if (isset($fields['selectProduct']) && - $fields['selectProduct'] != 'no_thanks' + $fields['selectProduct'] !== 'no_thanks' ) { $productDAO = new CRM_Contribute_DAO_Product(); $productDAO->id = $fields['selectProduct']; @@ -1223,9 +1280,9 @@ public function submit($params) { } } } - - if (!empty($this->_ccid) && !empty($this->_pendingAmount)) { - $params['amount'] = $this->_pendingAmount; + $balance = $this->getContributionBalance(); + if ($balance) { + $params['amount'] = $balance; } else { // from here on down, $params['amount'] holds a monetary value (or null) rather than an option ID @@ -1425,24 +1482,11 @@ public function assignFormVariablesByContributionID(): void { } } $this->assign('dummyTitle', $dummyTitle); - + $this->assign('pendingAmount', $this->getContributionBalance()); if (empty($this->getExistingContributionID())) { return; } - if (!$this->getContactID()) { - CRM_Core_Error::statusBounce(ts("Returning since there is no contact attached to this contribution id.")); - } - - $paymentBalance = CRM_Contribute_BAO_Contribution::getContributionBalance($this->_ccid); - //bounce if the contribution is not pending. - if ((float) $paymentBalance <= 0) { - CRM_Core_Error::statusBounce(ts("Returning since contribution has already been handled.")); - } - if (!empty($paymentBalance)) { - $this->_pendingAmount = $paymentBalance; - $this->assign('pendingAmount', $this->_pendingAmount); - } - + // @todo - all this stuff is likely obsolete. if ($taxAmount = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_Contribution', $this->_ccid, 'tax_amount')) { $this->assign('taxAmount', $taxAmount); } @@ -1453,6 +1497,29 @@ public function assignFormVariablesByContributionID(): void { $this->assign('priceSetID', $this->getPriceSetID()); } + /** + * Get the balance amount if an existing contribution is being paid. + * + * @return float|null + * + * @throws \CRM_Core_Exception + */ + private function getContributionBalance(): ?float { + if (empty($this->getExistingContributionID())) { + return NULL; + } + if (!$this->getContactID()) { + CRM_Core_Error::statusBounce(ts('Returning since there is no contact attached to this contribution id.')); + } + + $paymentBalance = CRM_Contribute_BAO_Contribution::getContributionBalance($this->_ccid); + //bounce if the contribution is not pending. + if ((float) $paymentBalance <= 0) { + CRM_Core_Error::statusBounce(ts('Returning since contribution has already been handled.')); + } + return $paymentBalance; + } + /** * Function for unit tests on the postProcess function. * @@ -1474,7 +1541,7 @@ public function testSubmit($params) { * * @param array $params * - * @return mixed + * @return bool * @throws \CRM_Core_Exception */ protected function hasSeparateMembershipPaymentAmount($params) { diff --git a/CRM/Contribute/Form/ContributionBase.php b/CRM/Contribute/Form/ContributionBase.php index 30e2bedca103..e937c547e457 100644 --- a/CRM/Contribute/Form/ContributionBase.php +++ b/CRM/Contribute/Form/ContributionBase.php @@ -114,6 +114,8 @@ class CRM_Contribute_Form_ContributionBase extends CRM_Core_Form { /** * Pcp id * + * @internal use getPcpID(). + * * @var int */ public $_pcpId; @@ -468,10 +470,9 @@ public function preProcess() { $this->set('membershipBlock', $this->getMembershipBlock()); // Handle PCP - $pcpId = CRM_Utils_Request::retrieve('pcpId', 'Positive', $this); - if ($pcpId) { + $pcpId = $this->getPcpID(); + if ($this->getPcpID()) { $pcp = CRM_PCP_BAO_PCP::handlePcp($pcpId, 'contribute', $this->_values); - $this->_pcpId = $pcp['pcpId']; $this->_pcpBlock = $pcp['pcpBlock']; $this->_pcpInfo = $pcp['pcpInfo']; } @@ -800,8 +801,6 @@ public function buildCustom($id, $name, $viewOnly = FALSE, $profileContactType = } } - $this->assign($name, $fields); - if ($profileContactType && count($viewOnlyFileValues[$profileContactType])) { $this->assign('viewOnlyPrefixFileValues', $viewOnlyFileValues); } @@ -810,6 +809,7 @@ public function buildCustom($id, $name, $viewOnly = FALSE, $profileContactType = } } } + $this->assign($name, $fields ?? NULL); } /** @@ -987,7 +987,6 @@ public function buildComponentForm($id, $form): void { ]; } $locDataURL = CRM_Utils_System::url('civicrm/ajax/permlocation', $args, FALSE, NULL, FALSE); - $form->assign('locDataURL', $locDataURL); } if (count($organizations) > 0) { $form->add('select', 'onbehalfof_id', '', CRM_Utils_Array::collect('name', $organizations)); @@ -1022,7 +1021,6 @@ public function buildComponentForm($id, $form): void { CRM_Core_Permission::CREATE, NULL ); - $form->assign('onBehalfOfFields', $profileFields); if (!empty($form->_submitValues['onbehalf'])) { if (!empty($form->_submitValues['onbehalfof_id'])) { $form->assign('submittedOnBehalf', $form->_submitValues['onbehalfof_id']); @@ -1055,6 +1053,8 @@ public function buildComponentForm($id, $form): void { } } } + $form->assign('locDataURL', $locDataURL ?? NULL); + $form->assign('onBehalfOfFields', $profileFields ?? NULL); } @@ -1406,4 +1406,16 @@ protected function getExistingContributionLineItems(): array { return $lineItems; } + /** + * Get the PCP ID being contributed to. + * + * @return int|null + */ + protected function getPcpID(): ?int { + if ($this->_pcpId === NULL) { + $this->_pcpId = CRM_Utils_Request::retrieve('pcpId', 'Positive', $this); + } + return $this->_pcpId ? (int) $this->_pcpId : NULL; + } + } diff --git a/CRM/Price/BAO/PriceField.php b/CRM/Price/BAO/PriceField.php index 7ed8a664fb53..a508653241d7 100644 --- a/CRM/Price/BAO/PriceField.php +++ b/CRM/Price/BAO/PriceField.php @@ -236,6 +236,8 @@ public static function getTitle($id) { * * @param null $fieldOptions * @param array $freezeOptions + * @param array $extra + * Passed through to the add element function, use to add js. * * @return null */ @@ -247,7 +249,8 @@ public static function addQuickFormElement( $useRequired = TRUE, $label = NULL, $fieldOptions = NULL, - $freezeOptions = [] + $freezeOptions = [], + array $extra = [] ) { $field = new CRM_Price_DAO_PriceField(); @@ -259,6 +262,7 @@ public static function addQuickFormElement( $label = $label ?: $field['label']; $is_pay_later = 0; $isQuickConfig = CRM_Price_BAO_PriceSet::isQuickConfig($field->price_set_id); + // @todo - pass is_pay_later in rather than checking form properties if (isset($qf->_mode) && empty($qf->_mode)) { $is_pay_later = 1; } @@ -274,6 +278,7 @@ public static function addQuickFormElement( // get currency name for price field and option attributes $currencyName = $config->defaultCurrency; + // @todo - pass useRequired in rather than checking form properties if (isset($qf->_online) && $qf->_online) { $useRequired = FALSE; } @@ -306,21 +311,16 @@ public static function addQuickFormElement( $max_value, ]); - $extra = []; if (!empty($fieldOptions[$optionKey]['label'])) { //check for label. $label = $fieldOptions[$optionKey]['label']; } + // @todo - move this back to the only calling function on Contribution_Form_Main.php if ($isQuickConfig && $field->name === 'other_amount') { if (!empty($qf->_membershipBlock)) { $useRequired = 0; } $label .= ' ' . $currencySymbol; - $qf->assign('priceset', $elementName); - $extra = [ - 'onclick' => 'useAmountOther();', - 'autocomplete' => 'off', - ]; } $element = &$qf->add('text', $elementName, $label, @@ -359,10 +359,6 @@ public static function addQuickFormElement( case 'Radio': $choice = []; - if ($isQuickConfig && $field->name === 'contribution_amount') { - $qf->assign('contriPriceset', $elementName); - } - foreach ($customOption as $opId => $opt) { $priceOptionText = self::buildPriceOptionText($opt, $field->is_display_amounts, $valueFieldName); if (isset($opt['visibility_id'])) { @@ -371,16 +367,14 @@ public static function addQuickFormElement( else { $visibility_id = self::getVisibilityOptionID('public'); } - $extra = [ + $extra += [ 'price' => json_encode([$elementName, $priceOptionText['priceVal']]), 'data-amount' => $opt[$valueFieldName], 'data-currency' => $currencyName, 'data-price-field-values' => json_encode($customOption), 'visibility' => $visibility_id, ]; - if ($isQuickConfig && $field->name == 'contribution_amount') { - $extra += ['onclick' => 'clearAmountOther();']; - } + // @todo - move this back to the only calling function on Contribution_Form_Main.php if ($field->name == 'membership_amount') { $extra += [ 'onclick' => "return showHideAutoRenew({$opt['membership_type_id']});", @@ -395,6 +389,7 @@ public static function addQuickFormElement( $qf->add('text', 'txt-' . $elementName, $label, ['size' => '4']); } } + // @todo - move this back to the only calling function on Contribution_Form_Main.php if (!empty($qf->_membershipBlock) && $field->name == 'contribution_amount') { $choice['-1'] = ts('No thank you'); $choiceAttrs['-1'] = [ @@ -431,6 +426,7 @@ public static function addQuickFormElement( } // make contribution field required for quick config when membership block is enabled + // @todo - move this back to the only calling function on Contribution_Form_Main.php if (($field->name == 'membership_amount' || $field->name == 'contribution_amount') && !empty($qf->_membershipBlock) && !$field->is_required ) { @@ -524,6 +520,7 @@ public static function addQuickFormElement( } break; } + // @todo - move this action back to the calling function if (isset($qf->_online) && $qf->_online) { $element->freeze(); } @@ -733,7 +730,7 @@ public static function priceSetValidation($priceSetId, $fields, &$error, $allowN } } - list($componentName) = explode(':', $fields['_qf_default']); + [$componentName] = explode(':', $fields['_qf_default']); // now we have all selected amount in hand. $totalAmount = array_sum($selectedAmounts); // The form offers a field to enter the amount paid. This may differ from the amount that is due to complete the purchase diff --git a/CRM/Profile/Form.php b/CRM/Profile/Form.php index 80605866ecbc..13b351e53ebe 100644 --- a/CRM/Profile/Form.php +++ b/CRM/Profile/Form.php @@ -889,13 +889,11 @@ public function buildQuickForm(): void { $this->setDefaultsValues(); $action = CRM_Utils_Request::retrieve('action', 'String', $this, FALSE, NULL); - - if ($this->_mode == self::MODE_CREATE || $this->_mode == self::MODE_EDIT) { + $isCreateOrEditMode = $this->_mode == self::MODE_CREATE || $this->_mode == self::MODE_EDIT; + if ($isCreateOrEditMode) { CRM_Core_BAO_CMSUser::buildForm($this, $this->_gid, $emailPresent, $action); } - else { - $this->assign('showCMS', FALSE); - } + $this->assign('showCMS', $isCreateOrEditMode); $this->assign('groupId', $this->_gid); diff --git a/templates/CRM/Contribute/Form/Contribution/Main.tpl b/templates/CRM/Contribute/Form/Contribution/Main.tpl index 08c54321bcc7..c6a322673b74 100644 --- a/templates/CRM/Contribute/Form/Contribution/Main.tpl +++ b/templates/CRM/Contribute/Form/Contribution/Main.tpl @@ -17,12 +17,10 @@ <script type="text/javascript"> // Putting these functions directly in template so they are available for standalone forms - function useAmountOther() { - var priceset = {/literal}{if $contriPriceset}'{$contriPriceset}'{else}0{/if}{literal}; - - for( i=0; i < document.Main.elements.length; i++ ) { + function useAmountOther(mainPriceFieldName) { + for( i=0; i < document.Main.elements.length; i++ ) { element = document.Main.elements[i]; - if ( element.type == 'radio' && element.name == priceset ) { + if ( element.type == 'radio' && element.name === mainPriceFieldName ) { if (element.value == '0' ) { element.click(); } @@ -33,12 +31,9 @@ } } - function clearAmountOther() { - var priceset = {/literal}{if $priceset}'#{$priceset}'{else}0{/if}{literal} - if( priceset ){ - cj(priceset).val(''); - cj(priceset).blur(); - } + function clearAmountOther(otherPriceFieldName) { + cj('#' + otherPriceFieldName).val(''); + cj('#' + otherPriceFieldName).blur(); if (document.Main.amount_other == null) return; // other_amt field not present; do nothing document.Main.amount_other.value = ""; } @@ -71,7 +66,7 @@ </div> {include file="CRM/common/cidzero.tpl"} - {if $islifetime or $ispricelifetime} + {if $isShowMembershipBlock && ($islifetime or $ispricelifetime)} <div class="help">{ts}You have a current Lifetime Membership which does not need to be renewed.{/ts}</div> {/if} @@ -118,13 +113,13 @@ {$form.pledge_frequency_unit.html}<span id="pledge_installments_num"> {ts}for{/ts} {$form.pledge_installments.html} {ts}installments.{/ts}</span> </div> <div class="clear"></div> - {if $start_date_editable} + {if array_key_exists('start_date', $form) && $start_date_editable} {if $is_date} <div class="label">{$form.start_date.label}</div><div class="content">{$form.start_date.html}</div> {else} <div class="label">{$form.start_date.label}</div><div class="content">{$form.start_date.html}</div> {/if} - {else} + {elseif array_key_exists('start_date', $form)} <div class="label">{$form.start_date.label}</div> <div class="content">{$start_date_display|crmDate:'%b %e, %Y'}</div> {/if}