From 668ddfc2c3b8502c4370c43b2097efa4f9b839f4 Mon Sep 17 00:00:00 2001 From: Eileen McNaughton Date: Fri, 10 Jul 2015 20:49:12 +1200 Subject: [PATCH] CRM-16829 move form functions to form --- CRM/Contribute/Form/Contribution/Confirm.php | 339 ++++++++++++++++++- CRM/Member/BAO/Membership.php | 98 ------ 2 files changed, 338 insertions(+), 99 deletions(-) diff --git a/CRM/Contribute/Form/Contribution/Confirm.php b/CRM/Contribute/Form/Contribution/Confirm.php index 863e8ef56b..dcd9cce58f 100644 --- a/CRM/Contribute/Form/Contribution/Confirm.php +++ b/CRM/Contribute/Form/Contribution/Confirm.php @@ -1551,7 +1551,7 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr $membershipParams['contribution_source'] = $this->_params['membership_source']; } - CRM_Member_BAO_Membership::postProcessMembership($membershipParams, $contactID, + $this->postProcessMembership($membershipParams, $contactID, $this, $premiumParams, $customFieldsFormatted, $fieldTypes, $membershipType, $membershipTypeIDs, $isPaidMembership, $this->_membershipId, $isProcessSeparateMembershipTransaction, $financialTypeID, $membershipLineItems, $isPayLater, $isPending); @@ -1564,6 +1564,343 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr } } + /** + * Process the Memberships. + * + * @param array $membershipParams + * Array of membership fields. + * @param int $contactID + * Contact id. + * @param CRM_Contribute_Form_Contribution_Confirm $form + * Confirmation form object. + * + * @param array $premiumParams + * @param null $customFieldsFormatted + * @param null $includeFieldTypes + * + * @param array $membershipDetails + * + * @param array $membershipTypeIDs + * + * @param bool $isPaidMembership + * @param array $membershipID + * + * @param bool $isProcessSeparateMembershipTransaction + * + * @param int $financialTypeID + * @param array $membershipLineItems + * Line items specific to membership payment that is separate to contribution. + * @param bool $isPayLater + * @param bool $isPending + * + * @throws \CRM_Core_Exception + */ + protected function postProcessMembership( + $membershipParams, $contactID, &$form, $premiumParams, + $customFieldsFormatted = NULL, $includeFieldTypes = NULL, $membershipDetails, $membershipTypeIDs, $isPaidMembership, $membershipID, + $isProcessSeparateMembershipTransaction, $financialTypeID, $membershipLineItems, $isPayLater, $isPending) { + $result = $membershipContribution = NULL; + $isTest = CRM_Utils_Array::value('is_test', $membershipParams, FALSE); + $errors = $createdMemberships = $paymentResult = array(); + + if ($isPaidMembership) { + if ($isProcessSeparateMembershipTransaction) { + // If we have 2 transactions only one can use the invoice id. + $membershipParams['invoiceID'] .= '-2'; + } + + $paymentResult = CRM_Contribute_BAO_Contribution_Utils::processConfirm($form, $membershipParams, + $premiumParams, $contactID, + $financialTypeID, + 'membership', + array(), + $isTest, + $isPayLater + ); + if (is_a($result[1], 'CRM_Core_Error')) { + $errors[1] = CRM_Core_Error::getMessages($paymentResult[1]); + } + + if (is_a($paymentResult, 'CRM_Core_Error')) { + $errors[1] = CRM_Core_Error::getMessages($paymentResult); + } + elseif (!empty($paymentResult['contribution'])) { + //note that this will be over-written if we are using a separate membership transaction. Otherwise there is only one + $membershipContribution = $paymentResult['contribution']; + // Save the contribution ID so that I can be used in email receipts + // For example, if you need to generate a tax receipt for the donation only. + $form->_values['contribution_other_id'] = $membershipContribution->id; + } + } + + if ($isProcessSeparateMembershipTransaction) { + try { + $form->_lineItem = $membershipLineItems; + if (empty($form->_params['auto_renew']) && !empty($membershipParams['is_recur'])) { + unset($membershipParams['is_recur']); + } + $membershipContribution = $this->processSecondaryFinancialTransaction($contactID, $form, $membershipParams, + $isTest, $membershipLineItems, CRM_Utils_Array::value('minimum_fee', $membershipDetails, 0), CRM_Utils_Array::value('financial_type_id', $membershipDetails)); + } + catch (CRM_Core_Exception $e) { + $errors[2] = $e->getMessage(); + $membershipContribution = NULL; + } + } + + $membership = NULL; + if (!empty($membershipContribution) && !is_a($membershipContribution, 'CRM_Core_Error')) { + $membershipContributionID = $membershipContribution->id; + } + + //@todo - why is this nested so deep? it seems like it could be just set on the calling function on the form layer + if (isset($membershipParams['onbehalf']) && !empty($membershipParams['onbehalf']['member_campaign_id'])) { + $form->_params['campaign_id'] = $membershipParams['onbehalf']['member_campaign_id']; + } + //@todo it should no longer be possible for it to get to this point & membership to not be an array + if (is_array($membershipTypeIDs) && !empty($membershipContributionID)) { + $typesTerms = CRM_Utils_Array::value('types_terms', $membershipParams, array()); + foreach ($membershipTypeIDs as $memType) { + $numTerms = CRM_Utils_Array::value($memType, $typesTerms, 1); + if (!empty($membershipContribution)) { + $pendingStatus = CRM_Core_OptionGroup::getValue('contribution_status', 'Pending', 'name'); + $pending = ($membershipContribution->contribution_status_id == $pendingStatus) ? TRUE : FALSE; + } + else { + $pending = $isPending; + } + $contributionRecurID = isset($form->_params['contributionRecurID']) ? $form->_params['contributionRecurID'] : NULL; + + $membershipSource = NULL; + if (!empty($form->_params['membership_source'])) { + $membershipSource = $form->_params['membership_source']; + } + elseif (isset($form->_values['title']) && !empty($form->_values['title'])) { + $membershipSource = ts('Online Contribution:') . ' ' . $form->_values['title']; + } + $isPayLater = NULL; + if (isset($form->_params)) { + $isPayLater = CRM_Utils_Array::value('is_pay_later', $form->_params); + } + $campaignId = NULL; + if (isset($form->_values) && is_array($form->_values) && !empty($form->_values)) { + $campaignId = CRM_Utils_Array::value('campaign_id', $form->_params); + if (!array_key_exists('campaign_id', $form->_params)) { + $campaignId = CRM_Utils_Array::value('campaign_id', $form->_values); + } + } + + list($membership, $renewalMode, $dates) = CRM_Member_BAO_Membership::renewMembership( + $contactID, $memType, $isTest, + date('YmdHis'), CRM_Utils_Array::value('cms_contactID', $membershipParams), + $customFieldsFormatted, + $numTerms, $membershipID, $pending, + $contributionRecurID, $membershipSource, $isPayLater, $campaignId + ); + $form->set('renewal_mode', $renewalMode); + if (!empty($dates)) { + $form->assign('mem_start_date', + CRM_Utils_Date::customFormat($dates['start_date'], '%Y%m%d') + ); + $form->assign('mem_end_date', + CRM_Utils_Date::customFormat($dates['end_date'], '%Y%m%d') + ); + } + + if (!empty($membershipContribution)) { + // update recurring id for membership record + CRM_Member_BAO_Membership::updateRecurMembership($membership, $membershipContribution); + CRM_Member_BAO_Membership::linkMembershipPayment($membership, $membershipContribution); + } + } + if ($form->_priceSetId && !empty($form->_useForMember) && !empty($form->_lineItem)) { + foreach ($form->_lineItem[$form->_priceSetId] as & $priceFieldOp) { + if (!empty($priceFieldOp['membership_type_id']) && + isset($createdMemberships[$priceFieldOp['membership_type_id']]) + ) { + $membershipOb = $createdMemberships[$priceFieldOp['membership_type_id']]; + $priceFieldOp['start_date'] = $membershipOb->start_date ? CRM_Utils_Date::customFormat($membershipOb->start_date, '%B %E%f, %Y') : '-'; + $priceFieldOp['end_date'] = $membershipOb->end_date ? CRM_Utils_Date::customFormat($membershipOb->end_date, '%B %E%f, %Y') : '-'; + } + else { + $priceFieldOp['start_date'] = $priceFieldOp['end_date'] = 'N/A'; + } + } + $form->_values['lineItem'] = $form->_lineItem; + $form->assign('lineItem', $form->_lineItem); + } + } + + if (!empty($errors)) { + $message = $this->compileErrorMessage($errors); + throw new CRM_Core_Exception($message); + } + $form->_params['createdMembershipIDs'] = array(); + + // CRM-7851 - Moved after processing Payment Errors + //@todo - the reasoning for this being here seems a little outdated + foreach ($createdMemberships as $createdMembership) { + CRM_Core_BAO_CustomValueTable::postProcess( + $form->_params, + 'civicrm_membership', + $createdMembership->id, + 'Membership' + ); + $form->_params['createdMembershipIDs'][] = $createdMembership->id; + } + if (count($createdMemberships) == 1) { + //presumably this is only relevant for exactly 1 membership + $form->_params['membershipID'] = $createdMembership->id; + } + + //CRM-15232: Check if membership is created and on the basis of it use + //membership receipt template to send payment receipt + if (count($createdMemberships)) { + $form->_values['isMembership'] = TRUE; + } + if ($form->_contributeMode == 'notify') { + if ($form->_values['is_monetary'] && $form->_amount > 0.0 && !$form->_params['is_pay_later']) { + // call postProcess hook before leaving + $form->postProcessHook(); + // this does not return + $payment = CRM_Core_Payment::singleton($form->_mode, $form->_paymentProcessor, $form); + $payment->doTransferCheckout($form->_params, 'contribute'); + } + } + + if (isset($membershipContributionID)) { + $form->_values['contribution_id'] = $membershipContributionID; + } + + if ($form->_contributeMode == 'direct') { + if (CRM_Utils_Array::value('payment_status_id', $paymentResult) == 1) { + // Refer to CRM-16737. Payment processors 'should' return payment_status_id + // to denote the outcome of the transaction. + try { + civicrm_api3('contribution', 'completetransaction', array( + 'id' => $paymentResult['contribution']->id, + 'trxn_id' => $paymentResult['contribution']->trxn_id, + 'is_transactional' => FALSE, + )); + } + catch (CiviCRM_API3_Exception $e) { + // if for any reason it is already completed this will fail - e.g extensions hacking around core not completing transactions prior to CRM-15296 + // so let's be gentle here + CRM_Core_Error::debug_log_message('contribution ' . $membershipContribution->id . ' not completed with trxn_id ' . $membershipContribution->trxn_id . ' and message ' . $e->getMessage()); + } + } + // Do not send an email if Recurring transaction is done via Direct Mode + // Email will we sent when the IPN is received. + return; + } + + //finally send an email receipt + CRM_Contribute_BAO_ContributionPage::sendMail($contactID, + $form->_values, + $isTest, FALSE, + $includeFieldTypes + ); + } + + /** + * Turn array of errors into message string. + * + * @param array $errors + * + * @return string + */ + protected function compileErrorMessage($errors) { + foreach ($errors as $error) { + if (is_string($error)) { + $message[] = $error; + } + } + return ts('Payment Processor Error message') . ': ' . implode('
', $message); + } + + /** + * Where a second separate financial transaction is supported we will process it here. + * + * @param int $contactID + * @param CRM_Contribute_Form_Contribution_Confirm $form + * @param array $tempParams + * @param bool $isTest + * @param array $lineItems + * @param $minimumFee + * @param int $financialTypeID + * + * @throws CRM_Core_Exception + * @throws Exception + * @return CRM_Contribute_BAO_Contribution + */ + protected function processSecondaryFinancialTransaction($contactID, &$form, $tempParams, $isTest, $lineItems, $minimumFee, + $financialTypeID) { + $financialType = new CRM_Financial_DAO_FinancialType(); + $financialType->id = $financialTypeID; + $financialType->find(TRUE); + $tempParams['amount'] = $minimumFee; + $tempParams['invoiceID'] = md5(uniqid(rand(), TRUE)); + + $result = NULL; + if ($form->_values['is_monetary'] && !$form->_params['is_pay_later'] && $minimumFee > 0.0) { + $payment = CRM_Core_Payment::singleton($form->_mode, $form->_paymentProcessor, $form); + + if ($form->_contributeMode == 'express') { + $result = $payment->doExpressCheckout($tempParams); + if (is_a($result, 'CRM_Core_Error')) { + throw new CRM_Core_Exception(CRM_Core_Error::getMessages($result)); + } + } + else { + $result = $payment->doPayment($tempParams, 'contribute'); + } + } + + //assign receive date when separate membership payment + //and contribution amount not selected. + if ($form->_amount == 0) { + $now = date('YmdHis'); + $form->_params['receive_date'] = $now; + $receiveDate = CRM_Utils_Date::mysqlToIso($now); + $form->set('params', $form->_params); + $form->assign('receive_date', $receiveDate); + } + + $form->set('membership_trx_id', $result['trxn_id']); + $form->set('membership_amount', $minimumFee); + + $form->assign('membership_trx_id', $result['trxn_id']); + $form->assign('membership_amount', $minimumFee); + + // we don't need to create the user twice, so lets disable cms_create_account + // irrespective of the value, CRM-2888 + $tempParams['cms_create_account'] = 0; + + //CRM-16165, scenarios are + // 1) If contribution is_pay_later and if contribution amount is > 0.0 we set pending = TRUE, vice-versa FALSE + // 2) If not pay later but auto-renewal membership is chosen then pending = TRUE as it later triggers + // pending recurring contribution, vice-versa FALSE + $pending = $form->_params['is_pay_later'] ? (($minimumFee > 0.0) ? TRUE : FALSE) : (!empty($form->_params['auto_renew']) ? TRUE : FALSE); + + //set this variable as we are not creating pledge for + //separate membership payment contribution. + //so for differentiating membership contribution from + //main contribution. + $form->_params['separate_membership_payment'] = 1; + $membershipContribution = CRM_Contribute_Form_Contribution_Confirm::processFormContribution($form, + $tempParams, + $result, + $contactID, + $financialType, + $pending, + TRUE, + $isTest, + $lineItems, + $form->_bltID + ); + return $membershipContribution; + } + /** * Is the payment a pending payment. * diff --git a/CRM/Member/BAO/Membership.php b/CRM/Member/BAO/Membership.php index bc4b216bda..7cec76f1cb 100644 --- a/CRM/Member/BAO/Membership.php +++ b/CRM/Member/BAO/Membership.php @@ -1998,88 +1998,6 @@ INNER JOIN civicrm_contact contact ON ( contact.id = membership.contact_id AND return (int) $memberCount; } - /** - * Where a second separate financial transaction is supported we will process it here. - * - * @param int $contactID - * @param CRM_Contribute_Form_Contribution_Confirm $form - * @param array $tempParams - * @param bool $isTest - * @param array $lineItems - * @param $minimumFee - * @param int $financialTypeID - * - * @throws CRM_Core_Exception - * @throws Exception - * @return CRM_Contribute_BAO_Contribution - */ - public static function processSecondaryFinancialTransaction($contactID, &$form, $tempParams, $isTest, $lineItems, $minimumFee, $financialTypeID) { - $financialType = new CRM_Financial_DAO_FinancialType(); - $financialType->id = $financialTypeID; - $financialType->find(TRUE); - $tempParams['amount'] = $minimumFee; - $tempParams['invoiceID'] = md5(uniqid(rand(), TRUE)); - - $result = NULL; - if ($form->_values['is_monetary'] && !$form->_params['is_pay_later'] && $minimumFee > 0.0) { - $payment = CRM_Core_Payment::singleton($form->_mode, $form->_paymentProcessor, $form); - - if ($form->_contributeMode == 'express') { - $result = $payment->doExpressCheckout($tempParams); - if (is_a($result, 'CRM_Core_Error')) { - throw new CRM_Core_Exception(CRM_Core_Error::getMessages($result)); - } - } - else { - $result = $payment->doPayment($tempParams, 'contribute'); - } - } - - //assign receive date when separate membership payment - //and contribution amount not selected. - if ($form->_amount == 0) { - $now = date('YmdHis'); - $form->_params['receive_date'] = $now; - $receiveDate = CRM_Utils_Date::mysqlToIso($now); - $form->set('params', $form->_params); - $form->assign('receive_date', $receiveDate); - } - - $form->set('membership_trx_id', $result['trxn_id']); - $form->set('membership_amount', $minimumFee); - - $form->assign('membership_trx_id', $result['trxn_id']); - $form->assign('membership_amount', $minimumFee); - - // we don't need to create the user twice, so lets disable cms_create_account - // irrespective of the value, CRM-2888 - $tempParams['cms_create_account'] = 0; - - //CRM-16165, scenarios are - // 1) If contribution is_pay_later and if contribution amount is > 0.0 we set pending = TRUE, vice-versa FALSE - // 2) If not pay later but auto-renewal membership is chosen then pending = TRUE as it later triggers - // pending recurring contribution, vice-versa FALSE - $pending = $form->_params['is_pay_later'] ? (($minimumFee > 0.0) ? TRUE : FALSE) : (!empty($form->_params['auto_renew']) ? TRUE : FALSE); - - //set this variable as we are not creating pledge for - //separate membership payment contribution. - //so for differentiating membership contribution from - //main contribution. - $form->_params['separate_membership_payment'] = 1; - $membershipContribution = CRM_Contribute_Form_Contribution_Confirm::processFormContribution($form, - $tempParams, - $result, - $contactID, - $financialType, - $pending, - TRUE, - $isTest, - $lineItems, - $form->_bltID - ); - return $membershipContribution; - } - /** * Create linkages between membership & contribution - note this is the wrong place for this code but this is a * refactoring step. This should be BAO functionality @@ -2093,22 +2011,6 @@ INNER JOIN civicrm_contact contact ON ( contact.id = membership.contact_id AND )); } - /** - * Turn array of errors into message string. - * - * @param array $errors - * - * @return string - */ - public static function compileErrorMessage($errors) { - foreach ($errors as $error) { - if (is_string($error)) { - $message[] = $error; - } - } - return ts('Payment Processor Error message') . ': ' . implode('
', $message); - } - /** * @param int $contactID * @param int $membershipTypeID -- 2.25.1