From: Eileen McNaughton Date: Sat, 8 Nov 2014 07:42:10 +0000 (+1300) Subject: CRM-15555 fix QA bug on paylater when billing option is required X-Git-Url: https://vcs.fsf.org/?a=commitdiff_plain;h=dde5a0ef8c4fedd7ee474ddc9f0161293941ac06;p=civicrm-core.git CRM-15555 fix QA bug on paylater when billing option is required --- diff --git a/CRM/Contribute/Form/AbstractEditPayment.php b/CRM/Contribute/Form/AbstractEditPayment.php index 768730769f..1546dc51ee 100644 --- a/CRM/Contribute/Form/AbstractEditPayment.php +++ b/CRM/Contribute/Form/AbstractEditPayment.php @@ -142,7 +142,7 @@ class CRM_Contribute_Form_AbstractEditPayment extends CRM_Core_Form { public $_honorID = NULL; /** - * Store the contribution Type ID + * Store the financial Type ID * * @var array */ @@ -177,8 +177,23 @@ class CRM_Contribute_Form_AbstractEditPayment extends CRM_Core_Form { public $isBackOffice = TRUE; protected $_formType; + + /** + * @var mystery variable screaming out for documentation + */ protected $_cdType; + /** + * array of fields to display on billingBlock.tpl - this is not fully implemented but basically intent is the panes/fieldsets on this page should + * be all in this array in order like + * 'credit_card' => array('credit_card_number' ... + * 'billing_details' => array('first_name' ... + * + * such that both the fields and the order can be more easily altered by payment processors & other extensions + * @var array + */ + public $billingFieldSets = array(); + /** * @param $id */ diff --git a/CRM/Contribute/Form/Contribution/Main.php b/CRM/Contribute/Form/Contribution/Main.php index 056ca1d192..0266fb3522 100644 --- a/CRM/Contribute/Form/Contribution/Main.php +++ b/CRM/Contribute/Form/Contribution/Main.php @@ -56,6 +56,12 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu public $_useForMember; + /** + * array of payment related fields to potentially display on this form (generally credit card or debit card fields). Th + * @var array + */ + public $_paymentFields = array(); + protected $_ppType; protected $_snippet; diff --git a/CRM/Core/Payment/Form.php b/CRM/Core/Payment/Form.php index f5b4fbf08a..b163c3f026 100644 --- a/CRM/Core/Payment/Form.php +++ b/CRM/Core/Payment/Form.php @@ -36,46 +36,58 @@ class CRM_Core_Payment_Form { /** - * Add payment fields are depending on payment processor + * Add payment fields depending on payment processor. The payment processor can implement the following functions to override the built in fields. * - * @param CRM_Contribute_Form_Contribution| CRM_Contribute_Form_Contribution_Main $form - * @todo - add other forms specifically to the definition - since we don't have for $form - since we aren't adding the property to - * CRM_Core_Form (don't suppose we should?) + * - getPaymentFormFields() + * - getPaymentFormFieldsMetadata() + * (planned - getBillingDetailsFormFields(), getBillingDetailsFormFieldsMetadata() + * + * Note that this code is written to accommodate the possibility CiviCRM will switch to implementing pay later as a manual processor in future + * + * @param CRM_Contribute_Form_AbstractEditPayment|CRM_Contribute_Form_Contribution_Main $form * @param array $processor array of properties including 'object' as loaded from CRM_Financial_BAO_PaymentProcessor::getPaymentProcessors + * @param bool $forceBillingFieldsForPayLater display billing fields even for pay later */ - static public function setPaymentFieldsByProcessor(&$form, $processor) { + static public function setPaymentFieldsByProcessor(&$form, $processor, $forceBillingFieldsForPayLater = FALSE) { $form->billingFieldSets = array(); - $paymentFields = self::getPaymentFields($processor); - $paymentTypeName = self::getPaymentTypeName($processor); - $paymentTypeLabel = self::getPaymentTypeLabel($processor); - //@todo if we switch to iterating through the fieldsets we won't need to assign these directly - $form->assign('paymentTypeName', $paymentTypeName); - $form->assign('paymentTypeLabel', $paymentTypeLabel); - - $form->billingFieldSets[$paymentTypeName]['fields'] = $form->_paymentFields = array_intersect_key(self::getPaymentFieldMetadata($processor), array_flip($paymentFields)); - $form->billingPane = array($paymentTypeName => $paymentTypeLabel); - $form->assign('paymentFields', $paymentFields); - if ($processor['billing_mode'] != 4) { - //@todo setPaymentFields defines the billing fields - this should be moved to the processor class & renamed getBillingFields - // currently we just add the standard lot unless it's an off-site processor (& then add none) - //also set the billingFieldSet to hold all the details required to render the fieldset so we can iterate through the fieldset - making - // it easier to re-order. For not the billingFieldSets param is used to determine whether to show the billing pane - CRM_Core_Payment_Form::_setPaymentFields($form); - $form->billingFieldSets['billing_name_address-group']['fields'] = array(); + if ($processor != NULL) { + // ie it is pay later + $paymentFields = self::getPaymentFields($processor); + $paymentTypeName = self::getPaymentTypeName($processor); + $paymentTypeLabel = self::getPaymentTypeLabel($processor); + //@todo if we switch to iterating through $form->billingFieldSets we won't need to assign these directly + $form->assign('paymentTypeName', $paymentTypeName); + $form->assign('paymentTypeLabel', $paymentTypeLabel); + + $form->billingFieldSets[$paymentTypeName]['fields'] = $form->_paymentFields = array_intersect_key(self::getPaymentFieldMetadata($processor), array_flip($paymentFields)); + $form->billingPane = array($paymentTypeName => $paymentTypeLabel); + $form->assign('paymentFields', $paymentFields); + } + + // @todo - replace this section with one similar to above per discussion - probably use a manual processor shell class to stand in for that capability + //return without adding billing fields if billing_mode = 4 (@todo - more the ability to set that to the payment processor) + // or payment processor is NULL (pay later) + if (($processor == NULL && !$forceBillingFieldsForPayLater) || $processor['billing_mode'] == 4) { + return; } + //@todo setPaymentFields defines the billing fields - this should be moved to the processor class & renamed getBillingFields + // potentially pay later would also be a payment processor + //also set the billingFieldSet to hold all the details required to render the fieldset so we can iterate through the fieldset - making + // it easier to re-order in hooks etc. The billingFieldSets param is used to determine whether to show the billing pane + CRM_Core_Payment_Form::setBillingDetailsFields($form); + $form->billingFieldSets['billing_name_address-group']['fields'] = array(); } /** * add general billing fields * @todo set these like processor fields & let payment processors alter them * - * * @param $form * * @return void * @access protected */ - static protected function _setPaymentFields(&$form) { + static protected function setBillingDetailsFields(&$form) { $bltID = $form->_bltID; $form->_paymentFields['billing_first_name'] = array( @@ -173,7 +185,7 @@ class CRM_Core_Payment_Form { * @access public */ static function setCreditCardFields(&$form) { - CRM_Core_Payment_Form::_setPaymentFields($form); + CRM_Core_Payment_Form::setBillingDetailsFields($form); $form->_paymentFields['credit_card_number'] = array( 'htmlType' => 'text', @@ -255,7 +267,7 @@ class CRM_Core_Payment_Form { * @access public */ static function setDirectDebitFields(&$form) { - CRM_Core_Payment_Form::_setPaymentFields($form); + CRM_Core_Payment_Form::setBillingDetailsFields($form); $form->_paymentFields['account_holder'] = array( 'htmlType' => 'text', @@ -346,14 +358,29 @@ class CRM_Core_Payment_Form { } /** - * @param CRM_Contribute_Form_Contribution| CRM_Contribute_Form_Contribution_Main|CRM_Member_Form_Membership $form + * @param CRM_Contribute_Form_Contribution| CRM_Contribute_Form_Contribution_Main|CRM_Core_Payment_ProcessorForm $form * @param array $processor array of properties including 'object' as loaded from CRM_Financial_BAO_PaymentProcessor::getPaymentProcessors - * @param bool $isBillingDataOptional + * @param bool $isBillingDataOptional This manifests for 'NULL' (pay later) payment processor as the addition of billing fields to the form and + * for payment processors that gather payment data on site as rendering the fields as not being required. (not entirely sure why but this + * is implemented for back office forms) * * @return bool */ static function buildPaymentForm($form, $processor, $isBillingDataOptional){ - self::setPaymentFieldsByProcessor($form, $processor); + //if the form has address fields assign to the template so the js can decide what billing fields to show + $profileAddressFields = $form->get('profileAddressFields'); + if (!empty($profileAddressFields)) { + $form->assign('profileAddressFields', $profileAddressFields); + } + + // $processor->buildForm appears to be an undocumented (possibly unused) option for payment processors + // which was previously available only in some form flows + if (!empty($form->_paymentProcessor) && !empty($form->_paymentProcessor['object']) && $form->_paymentProcessor['object']->isSupported('buildForm')) { + $form->_paymentProcessor['object']->buildForm($form); + return; + } + + self::setPaymentFieldsByProcessor($form, $processor, empty($isBillingDataOptional)); self::addCommonFields($form, !$isBillingDataOptional, $form->_paymentFields); self::addRules($form, $form->_paymentFields); self::addPaypalExpressCode($form); @@ -483,40 +510,6 @@ class CRM_Core_Payment_Form { } } - /** - * Function to add address block - * - * @param $form - * @param bool $useRequired - * - * @return void - * @access public - */ - static function buildAddressBlock(&$form, $useRequired = FALSE) { - CRM_Core_Payment_Form::_setPaymentFields($form); - foreach ($form->_paymentFields as $name => $field) { - if (isset($field['cc_field']) && - $field['cc_field'] - ) { - $form->add($field['htmlType'], - $field['name'], - $field['title'], - $field['attributes'], - $useRequired ? $field['is_required'] : FALSE - ); - } - } - - // also take care of state country widget - $stateCountryMap = array( - 1 => array( - 'country' => "billing_country_id-{$form->_bltID}", - 'state_province' => "billing_state_province_id-{$form->_bltID}", - ) - ); - CRM_Core_BAO_Address::addStateCountryMap($stateCountryMap); - } - /** * Make sure that credit card number and cvv are valid * Called within the scope of a QF formRule function diff --git a/CRM/Core/Payment/ProcessorForm.php b/CRM/Core/Payment/ProcessorForm.php index 3f2394be24..50bfabbdbc 100644 --- a/CRM/Core/Payment/ProcessorForm.php +++ b/CRM/Core/Payment/ProcessorForm.php @@ -74,6 +74,7 @@ class CRM_Core_Payment_ProcessorForm { $form->assign_by_ref('paymentProcessor', $form->_paymentProcessor); // check if this is a paypal auto return and redirect accordingly + //@todo - determine if this is legacy and remove if (CRM_Core_Payment::paypalRedirect($form->_paymentProcessor)) { $url = CRM_Utils_System::url('civicrm/contribute/transact', "_qf_ThankYou_display=1&qfKey={$form->controller->_key}" @@ -104,34 +105,9 @@ class CRM_Core_Payment_ProcessorForm { * @param $form */ static function buildQuickform(&$form) { + //@todo document why this addHidden is here $form->addElement('hidden', 'hidden_processor', 1); - - $profileAddressFields = $form->get('profileAddressFields'); - if (!empty($profileAddressFields)) { - $form->assign('profileAddressFields', $profileAddressFields); - } - - // check if show billing setting is enabled - if ($form->getVar( '_ppType' ) == 0 && $form->_isBillingAddressRequiredForPayLater) { - CRM_Core_Payment_Form::buildAddressBlock($form); - return; - } - - // before we do this lets see if the payment processor has implemented a buildForm method - if (method_exists($form->_paymentProcessor['instance'], 'buildForm') && - is_callable(array($form->_paymentProcessor['instance'], 'buildForm'))) { - // the payment processor implements the buildForm function, let the payment - // processor do the work - $form->_paymentProcessor['instance']->buildForm($form); - return; - } - - if (($form->_paymentProcessor['payment_type'] & CRM_Core_Payment::PAYMENT_TYPE_DIRECT_DEBIT)) { - CRM_Core_Payment_Form::buildDirectDebit($form, TRUE); - } - elseif (($form->_paymentProcessor['payment_type'] & CRM_Core_Payment::PAYMENT_TYPE_CREDIT_CARD)) { - CRM_Core_Payment_Form::buildCreditCard($form, TRUE); - } + CRM_Core_Payment_Form::buildPaymentForm($form, $form->_paymentProcessor, empty($form->_isBillingAddressRequiredForPayLater)); } }