From 75637f227b3268f2f9ecc119f86e0051b425dbc6 Mon Sep 17 00:00:00 2001 From: Eileen McNaughton Date: Thu, 25 Jun 2015 00:19:16 +1200 Subject: [PATCH] CRM-16417 extract main processing into testable function --- CRM/Contribute/Form/Contribution/Confirm.php | 1921 +++++++++--------- 1 file changed, 969 insertions(+), 952 deletions(-) diff --git a/CRM/Contribute/Form/Contribution/Confirm.php b/CRM/Contribute/Form/Contribution/Confirm.php index 5e38c9fde0..8ec906cc3b 100644 --- a/CRM/Contribute/Form/Contribution/Confirm.php +++ b/CRM/Contribute/Form/Contribution/Confirm.php @@ -726,1074 +726,706 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr */ public function postProcess() { $contactID = $this->getContactID(); - $isPayLater = $this->_params['is_pay_later']; - if (isset($this->_params['payment_processor_id']) && $this->_params['payment_processor_id'] == 0) { - $this->_params['is_pay_later'] = $isPayLater = TRUE; + $result = $this->processFormSubmission($contactID); + if (is_array($result) && !empty($result['is_payment_failure'])) { + CRM_Core_Error::displaySessionError($result); + CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/contribute/transact', + "_qf_Main_display=true&qfKey={$this->_params['qfKey']}" + )); } - // add a description field at the very beginning - $this->_params['description'] = ts('Online Contribution') . ': ' . (($this->_pcpInfo['title']) ? $this->_pcpInfo['title'] : $this->_values['title']); - - $this->_params['accountingCode'] = CRM_Utils_Array::value('accountingCode', $this->_values); - - // fix currency ID - $this->_params['currencyID'] = CRM_Core_Config::singleton()->defaultCurrency; + } - //carry payment processor id. - if (CRM_Utils_Array::value('id', $this->_paymentProcessor)) { - $this->_params['payment_processor_id'] = $this->_paymentProcessor['id']; + /** + * Wrangle financial type ID. + * + * This wrangling of the financialType ID was happening in a shared function rather than in the form it relates to & hence has been moved to that form + * Pledges are not relevant to the membership code so that portion will not go onto the membership form. + * + * Comments from previous refactor indicate doubt as to what was going on. + * + * @param int $contributionTypeId + * + * @return null|string + */ + public function wrangleFinancialTypeID($contributionTypeId) { + if (isset($paymentParams['financial_type'])) { + $contributionTypeId = $paymentParams['financial_type']; } - if (!empty($params['image_URL'])) { - CRM_Contact_BAO_Contact::processImageParams($params); + elseif (!empty($this->_values['pledge_id'])) { + $contributionTypeId = CRM_Core_DAO::getFieldValue('CRM_Pledge_DAO_Pledge', + $this->_values['pledge_id'], + 'financial_type_id' + ); } - $premiumParams = $membershipParams = $params = $this->_params; - $fields = array('email-Primary' => 1); - - // get the add to groups - $addToGroups = array(); + return $contributionTypeId; + } - // now set the values for the billing location. - foreach ($this->_fields as $name => $value) { - $fields[$name] = 1; + /** + * Process the form. + * + * @param array $premiumParams + * @param CRM_Contribute_BAO_Contribution $contribution + */ + public function postProcessPremium($premiumParams, $contribution) { + $hour = $minute = $second = 0; + // assigning Premium information to receipt tpl + $selectProduct = CRM_Utils_Array::value('selectProduct', $premiumParams); + if ($selectProduct && + $selectProduct != 'no_thanks' + ) { + $startDate = $endDate = ""; + $this->assign('selectPremium', TRUE); + $productDAO = new CRM_Contribute_DAO_Product(); + $productDAO->id = $selectProduct; + $productDAO->find(TRUE); + $this->assign('product_name', $productDAO->name); + $this->assign('price', $productDAO->price); + $this->assign('sku', $productDAO->sku); + $this->assign('option', CRM_Utils_Array::value('options_' . $premiumParams['selectProduct'], $premiumParams)); - // get the add to groups for uf fields - if (!empty($value['add_to_group_id'])) { - $addToGroups[$value['add_to_group_id']] = $value['add_to_group_id']; - } - } + $periodType = $productDAO->period_type; - if (!array_key_exists('first_name', $fields)) { - $nameFields = array('first_name', 'middle_name', 'last_name'); - foreach ($nameFields as $name) { - $fields[$name] = 1; - if (array_key_exists("billing_$name", $params)) { - $params[$name] = $params["billing_{$name}"]; - $params['preserveDBName'] = TRUE; + if ($periodType) { + $fixed_period_start_day = $productDAO->fixed_period_start_day; + $duration_unit = $productDAO->duration_unit; + $duration_interval = $productDAO->duration_interval; + if ($periodType == 'rolling') { + $startDate = date('Y-m-d'); + } + elseif ($periodType == 'fixed') { + if ($fixed_period_start_day) { + $date = explode('-', date('Y-m-d')); + $month = substr($fixed_period_start_day, 0, strlen($fixed_period_start_day) - 2); + $day = substr($fixed_period_start_day, -2) . "
"; + $year = $date[0]; + $startDate = $year . '-' . $month . '-' . $day; + } + else { + $startDate = date('Y-m-d'); + } } - } - } - // billing email address - $fields["email-{$this->_bltID}"] = 1; + $date = explode('-', $startDate); + $year = $date[0]; + $month = $date[1]; + $day = $date[2]; - //unset the billing parameters if it is pay later mode - //to avoid creation of billing location - if ($isPayLater && !$this->_isBillingAddressRequiredForPayLater) { - $billingFields = array( - 'billing_first_name', - 'billing_middle_name', - 'billing_last_name', - "billing_street_address-{$this->_bltID}", - "billing_city-{$this->_bltID}", - "billing_state_province-{$this->_bltID}", - "billing_state_province_id-{$this->_bltID}", - "billing_postal_code-{$this->_bltID}", - "billing_country-{$this->_bltID}", - "billing_country_id-{$this->_bltID}", - ); + switch ($duration_unit) { + case 'year': + $year = $year + $duration_interval; + break; - foreach ($billingFields as $value) { - unset($params[$value]); - unset($fields[$value]); - } - } + case 'month': + $month = $month + $duration_interval; + break; - // if onbehalf-of-organization contribution, take out - // organization params in a separate variable, to make sure - // normal behavior is continued. And use that variable to - // process on-behalf-of functionality. - if (!empty($this->_params['hidden_onbehalf_profile'])) { - $behalfOrganization = array(); - $orgFields = array('organization_name', 'organization_id', 'org_option'); - foreach ($orgFields as $fld) { - if (array_key_exists($fld, $params)) { - $behalfOrganization[$fld] = $params[$fld]; - unset($params[$fld]); - } - } + case 'day': + $day = $day + $duration_interval; + break; - if (is_array($params['onbehalf']) && !empty($params['onbehalf'])) { - foreach ($params['onbehalf'] as $fld => $values) { - if (strstr($fld, 'custom_')) { - $behalfOrganization[$fld] = $values; - } - elseif (!(strstr($fld, '-'))) { - if (in_array($fld, array( - 'contribution_campaign_id', - 'member_campaign_id', - ))) { - $fld = 'campaign_id'; - } - else { - $behalfOrganization[$fld] = $values; - } - $this->_params[$fld] = $values; - } + case 'week': + $day = $day + ($duration_interval * 7); } + $endDate = date('Y-m-d H:i:s', mktime($hour, $minute, $second, $month, $day, $year)); + $this->assign('start_date', $startDate); + $this->assign('end_date', $endDate); } - if (array_key_exists('onbehalf_location', $params) && is_array($params['onbehalf_location'])) { - foreach ($params['onbehalf_location'] as $block => $vals) { - //fix for custom data (of type checkbox, multi-select) - if (substr($block, 0, 7) == 'custom_') { - continue; - } - // fix the index of block elements - if (is_array($vals)) { - foreach ($vals as $key => $val) { - //dont adjust the index of address block as - //it's index is WRT to location type - $newKey = ($block == 'address') ? $key : ++$key; - $behalfOrganization[$block][$newKey] = $val; - } - } - } - unset($params['onbehalf_location']); + $dao = new CRM_Contribute_DAO_Premium(); + $dao->entity_table = 'civicrm_contribution_page'; + $dao->entity_id = $this->_id; + $dao->find(TRUE); + $this->assign('contact_phone', $dao->premiums_contact_phone); + $this->assign('contact_email', $dao->premiums_contact_email); + + //create Premium record + $params = array( + 'product_id' => $premiumParams['selectProduct'], + 'contribution_id' => $contribution->id, + 'product_option' => CRM_Utils_Array::value('options_' . $premiumParams['selectProduct'], $premiumParams), + 'quantity' => 1, + 'start_date' => CRM_Utils_Date::customFormat($startDate, '%Y%m%d'), + 'end_date' => CRM_Utils_Date::customFormat($endDate, '%Y%m%d'), + ); + if (!empty($premiumParams['selectProduct'])) { + $daoPremiumsProduct = new CRM_Contribute_DAO_PremiumsProduct(); + $daoPremiumsProduct->product_id = $premiumParams['selectProduct']; + $daoPremiumsProduct->premiums_id = $dao->id; + $daoPremiumsProduct->find(TRUE); + $params['financial_type_id'] = $daoPremiumsProduct->financial_type_id; } - if (!empty($params['onbehalf[image_URL]'])) { - $behalfOrganization['image_URL'] = $params['onbehalf[image_URL]']; + //Fixed For CRM-3901 + $daoContrProd = new CRM_Contribute_DAO_ContributionProduct(); + $daoContrProd->contribution_id = $contribution->id; + if ($daoContrProd->find(TRUE)) { + $params['id'] = $daoContrProd->id; } - } - // check for profile double opt-in and get groups to be subscribed - $subscribeGroupIds = CRM_Core_BAO_UFGroup::getDoubleOptInGroupIds($params, $contactID); - - // since we are directly adding contact to group lets unset it from mailing - if (!empty($addToGroups)) { - foreach ($addToGroups as $groupId) { - if (isset($subscribeGroupIds[$groupId])) { - unset($subscribeGroupIds[$groupId]); - } + CRM_Contribute_BAO_Contribution::addPremium($params); + if ($productDAO->cost && !empty($params['financial_type_id'])) { + $trxnParams = array( + 'cost' => $productDAO->cost, + 'currency' => $productDAO->currency, + 'financial_type_id' => $params['financial_type_id'], + 'contributionId' => $contribution->id, + ); + CRM_Core_BAO_FinancialTrxn::createPremiumTrxn($trxnParams); } } - - foreach ($addToGroups as $k) { - if (array_key_exists($k, $subscribeGroupIds)) { - unset($addToGroups[$k]); + elseif ($selectProduct == 'no_thanks') { + //Fixed For CRM-3901 + $daoContrProd = new CRM_Contribute_DAO_ContributionProduct(); + $daoContrProd->contribution_id = $contribution->id; + if ($daoContrProd->find(TRUE)) { + $daoContrProd->delete(); } } + } - if (empty($contactID)) { - $dupeParams = $params; - if (!empty($dupeParams['onbehalf'])) { - unset($dupeParams['onbehalf']); - } - if (!empty($dupeParams['honor'])) { - unset($dupeParams['honor']); - } - - $dedupeParams = CRM_Dedupe_Finder::formatParams($dupeParams, 'Individual'); - $dedupeParams['check_permission'] = FALSE; - $ids = CRM_Dedupe_Finder::dupesByParams($dedupeParams, 'Individual'); - - // if we find more than one contact, use the first one - $contactID = CRM_Utils_Array::value(0, $ids); - - // Fetch default greeting id's if creating a contact - if (!$contactID) { - foreach (CRM_Contact_BAO_Contact::$_greetingTypes as $greeting) { - if (!isset($params[$greeting])) { - $params[$greeting] = CRM_Contact_BAO_Contact_Utils::defaultGreeting('Individual', $greeting); - } - } - } - $contactType = NULL; + /** + * Process the contribution. + * + * @param CRM_Core_Form $form + * @param array $params + * @param array $result + * @param int $contactID + * @param CRM_Financial_DAO_FinancialType $financialType + * @param bool $pending + * @param bool $online + * + * @param bool $isTest + * @param array $lineItems + * + * @param int $billingLocationID + * ID of billing location type. + * + * @return \CRM_Contribute_DAO_Contribution + * @throws \Exception + */ + public static function processFormContribution( + &$form, + $params, + $result, + $contactID, + $financialType, + $pending, + $online, + $isTest, + $lineItems, + $billingLocationID + ) { + $transaction = new CRM_Core_Transaction(); + $contribSoftContactId = $addressID = NULL; + $contributeMode = $form->_contributeMode; + $isMonetary = !empty($form->_values['is_monetary']); + $isEmailReceipt = !empty($form->_values['is_email_receipt']); + // How do these vary from params? These are currently passed to + // - custom data function.... + $formParams = $form->_params; + $isSeparateMembershipPayment = empty($formParams['separate_membership_payment']) ? FALSE : TRUE; + $pledgeID = empty($formParams['pledge_id']) ? NULL : $formParams['pledge_id']; + if (!$isSeparateMembershipPayment && !empty($form->_values['pledge_block_id']) && + (!empty($formParams['is_pledge']) || $pledgeID)) { + $isPledge = TRUE; } else { - $contactType = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $contactID, 'contact_type'); + $isPledge = FALSE; } - $contactID = CRM_Contact_BAO_Contact::createProfileContact( - $params, - $fields, - $contactID, - $addToGroups, - NULL, - $contactType, - TRUE - ); - // Make the contact ID associated with the contribution available at the Class level. - // Also make available to the session. - //@todo consider handling this in $this->getContactID(); - $this->set('contactID', $contactID); - $this->_contactID = $contactID; + // add these values for the recurringContrib function ,CRM-10188 + $params['financial_type_id'] = $financialType->id; - //get email primary first if exist - $subscriptionEmail = array('email' => CRM_Utils_Array::value('email-Primary', $params)); - if (!$subscriptionEmail['email']) { - $subscriptionEmail['email'] = CRM_Utils_Array::value("email-{$this->_bltID}", $params); - } - // subscribing contact to groups - if (!empty($subscribeGroupIds) && $subscriptionEmail['email']) { - CRM_Mailing_Event_BAO_Subscribe::commonSubscribe($subscribeGroupIds, $subscriptionEmail, $contactID); + //create an contribution address + if ($contributeMode != 'notify' && empty($params['is_pay_later']) && $isMonetary) { + $addressID = CRM_Contribute_BAO_Contribution::createAddress($params, $billingLocationID); } - // If onbehalf-of-organization contribution / signup, add organization - // and it's location. - if (isset($params['hidden_onbehalf_profile']) && isset($behalfOrganization['organization_name'])) { - $ufFields = array(); - foreach ($this->_fields['onbehalf'] as $name => $value) { - $ufFields[$name] = 1; - } - self::processOnBehalfOrganization($behalfOrganization, $contactID, $this->_values, - $this->_params, $ufFields - ); - } - elseif (!empty($this->_membershipContactID) && $contactID != $this->_membershipContactID) { - // this is an onbehalf renew case for inherited membership. For e.g a permissioned member of household, - // store current user id as related contact for later use for mailing / activity.. - $this->_values['related_contact'] = $contactID; - $this->_params['related_contact'] = $contactID; - // swap contact like we do for on-behalf-org case, so parent/primary membership is affected - $contactID = $this->_membershipContactID; + //@todo - this is being set from the form to resolve CRM-10188 - an + // eNotice caused by it not being set @ the front end + // however, we then get it being over-written with null for backend contributions + // a better fix would be to set the values in the respective forms rather than require + // a function being shared by two forms to deal with their respective values + // moving it to the BAO & not taking the $form as a param would make sense here. + if (!isset($params['is_email_receipt']) && $isEmailReceipt) { + $params['is_email_receipt'] = $isEmailReceipt; } + $recurringContributionID = self::processRecurringContribution($form, $params, $contactID, $financialType, $online); + $nonDeductibleAmount = self::getNonDeductibleAmount($params, $financialType, $online); - // lets store the contactID in the session - // for things like tell a friend - $session = CRM_Core_Session::singleton(); - if (!$session->get('userID')) { - $session->set('transaction.userID', $contactID); - } - else { - $session->set('transaction.userID', NULL); + $now = date('YmdHis'); + $receiptDate = CRM_Utils_Array::value('receipt_date', $params); + if ($isEmailReceipt) { + $receiptDate = $now; } - $this->_useForMember = $this->get('useForMember'); - - // store the fact that this is a membership and membership type is selected - $processMembership = FALSE; - if ((!empty($membershipParams['selectMembership']) && - $membershipParams['selectMembership'] != 'no_thanks' - ) || - $this->_useForMember - ) { - $processMembership = TRUE; - - if (!$this->_useForMember) { - $this->assign('membership_assign', TRUE); - $this->set('membershipTypeID', $this->_params['selectMembership']); - } - - if ($this->_action & CRM_Core_Action::PREVIEW) { - $membershipParams['is_test'] = 1; - } - if ($this->_params['is_pay_later']) { - $membershipParams['is_pay_later'] = 1; + //get the contrib page id. + $contributionPageId = NULL; + if ($online) { + $contributionPageId = $form->_id; + $campaignId = CRM_Utils_Array::value('campaign_id', $params); + if (!array_key_exists('campaign_id', $params)) { + $campaignId = CRM_Utils_Array::value('campaign_id', $form->_values); } } + else { + //also for offline we do support - CRM-7290 + $contributionPageId = CRM_Utils_Array::value('contribution_page_id', $params); + $campaignId = CRM_Utils_Array::value('campaign_id', $params); + } - if ($processMembership) { - CRM_Core_Payment_Form::mapParams($this->_bltID, $this->_params, $membershipParams, TRUE); - - // added new parameter for cms user contact id, needed to distinguish behaviour for on behalf of sign-ups - if (isset($this->_params['related_contact'])) { - $membershipParams['cms_contactID'] = $this->_params['related_contact']; + // Prepare soft contribution due to pcp or Submit Credit / Debit Card Contribution by admin. + if (!empty($params['pcp_made_through_id']) || !empty($params['soft_credit_to'])) { + // if its due to pcp + if (!empty($params['pcp_made_through_id'])) { + $contribSoftContactId = CRM_Core_DAO::getFieldValue( + 'CRM_PCP_DAO_PCP', + $params['pcp_made_through_id'], + 'contact_id' + ); } else { - $membershipParams['cms_contactID'] = $contactID; + $contribSoftContactId = CRM_Utils_Array::value('soft_credit_to', $params); } - //inherit campaign from contribution page. - if (!array_key_exists('campaign_id', $membershipParams)) { - $membershipParams['campaign_id'] = CRM_Utils_Array::value('campaign_id', $this->_values); - } + // Pass these details onto with the contribution to make them + // available at hook_post_process, CRM-8908 + $params['soft_credit_to'] = $contribSoftContactId; + } - if (!empty($membershipParams['onbehalf']) && - is_array($membershipParams['onbehalf']) && !empty($membershipParams['onbehalf']['member_campaign_id']) - ) { - $this->_params['campaign_id'] = $membershipParams['onbehalf']['member_campaign_id']; - } + if (isset($params['amount'])) { + $contribParams = self::getContributionParams( + $params, $contactID, $financialType->id, $online, $contributionPageId, $nonDeductibleAmount, $campaignId, $isMonetary, $pending, $result, $receiptDate, + $recurringContributionID, $isTest, $addressID, $contribSoftContactId, $lineItems + ); + $contribution = CRM_Contribute_BAO_Contribution::add($contribParams); - $customFieldsFormatted = $fieldTypes = array(); - if (!empty($membershipParams['onbehalf']) && - is_array($membershipParams['onbehalf']) - ) { - foreach ($membershipParams['onbehalf'] as $key => $value) { - if (strstr($key, 'custom_')) { - $customFieldId = explode('_', $key); - CRM_Core_BAO_CustomField::formatCustomField( - $customFieldId[1], - $customFieldsFormatted, - $value, - 'Membership', - NULL, - $contactID - ); + $invoiceSettings = CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::CONTRIBUTE_PREFERENCES_NAME, 'contribution_invoice_settings'); + $invoicing = CRM_Utils_Array::value('invoicing', $invoiceSettings); + if ($invoicing) { + $dataArray = array(); + foreach ($form->_lineItem as $lineItemKey => $lineItemValue) { + foreach ($lineItemValue as $key => $value) { + if (isset($value['tax_amount']) && isset($value['tax_rate'])) { + if (isset($dataArray[$value['tax_rate']])) { + $dataArray[$value['tax_rate']] = $dataArray[$value['tax_rate']] + CRM_Utils_Array::value('tax_amount', $value); + } + else { + $dataArray[$value['tax_rate']] = CRM_Utils_Array::value('tax_amount', $value); + } + } } } - $fieldTypes = array('Contact', 'Organization', 'Membership'); + $smarty = CRM_Core_Smarty::singleton(); + $smarty->assign('dataArray', $dataArray); + $smarty->assign('totalTaxAmount', $params['tax_amount']); + } + if (is_a($contribution, 'CRM_Core_Error')) { + $message = CRM_Core_Error::getMessages($contribution); + CRM_Core_Error::fatal($message); } - $priceFieldIds = $this->get('memberPriceFieldIDS'); + // lets store it in the form variable so postProcess hook can get to this and use it + $form->_contributionID = $contribution->id; + } - if (!empty($priceFieldIds)) { - $contributionTypeID = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $priceFieldIds['id'], 'financial_type_id'); - unset($priceFieldIds['id']); - $membershipTypeIds = array(); - $membershipTypeTerms = array(); - foreach ($priceFieldIds as $priceFieldId) { - if ($id = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceFieldValue', $priceFieldId, 'membership_type_id')) { - $membershipTypeIds[] = $id; - //@todo the value for $term is immediately overwritten. It is unclear from the code whether it was intentional to - // do this or a double = was intended (this ambiguity is the reason many IDEs complain about 'assignment in condition' - $term = 1; - if ($term = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceFieldValue', $priceFieldId, 'membership_num_terms')) { - $membershipTypeTerms[$id] = ($term > 1) ? $term : 1; - } - else { - $membershipTypeTerms[$id] = 1; - } - } + //CRM-13981, processing honor contact into soft-credit contribution + CRM_Contact_Form_ProfileContact::postProcess($form); + + // process soft credit / pcp pages + CRM_Contribute_Form_Contribution_Confirm::processPcpSoft($params, $contribution); + + //handle pledge stuff. + if ($isPledge) { + if ($pledgeID) { + //when user doing pledge payments. + //update the schedule when payment(s) are made + foreach ($form->_params['pledge_amount'] as $paymentId => $dontCare) { + $scheduledAmount = CRM_Core_DAO::getFieldValue( + 'CRM_Pledge_DAO_PledgePayment', + $paymentId, + 'scheduled_amount', + 'id' + ); + + $pledgePaymentParams = array( + 'id' => $paymentId, + 'contribution_id' => $contribution->id, + 'status_id' => $contribution->contribution_status_id, + 'actual_amount' => $scheduledAmount, + ); + + CRM_Pledge_BAO_PledgePayment::add($pledgePaymentParams); } - $membershipParams['selectMembership'] = $membershipTypeIds; - $membershipParams['financial_type_id'] = $contributionTypeID; - $membershipParams['types_terms'] = $membershipTypeTerms; + + //update pledge status according to the new payment statuses + CRM_Pledge_BAO_PledgePayment::updatePledgePaymentStatus($pledgeID); } - if (!empty($membershipParams['selectMembership'])) { - // CRM-12233 - $membershipLineItems = array(); - if ($this->_separateMembershipPayment && $this->_values['amount_block_is_active']) { - foreach ($this->_values['fee'] as $key => $feeValues) { - if ($feeValues['name'] == 'membership_amount') { - $fieldId = $this->_params['price_' . $key]; - $membershipLineItems[$this->_priceSetId][$fieldId] = $this->_lineItem[$this->_priceSetId][$fieldId]; - unset($this->_lineItem[$this->_priceSetId][$fieldId]); - break; - } - } + else { + //when user creating pledge record. + $pledgeParams = array(); + $pledgeParams['contact_id'] = $contribution->contact_id; + $pledgeParams['installment_amount'] = $pledgeParams['actual_amount'] = $contribution->total_amount; + $pledgeParams['contribution_id'] = $contribution->id; + $pledgeParams['contribution_page_id'] = $contribution->contribution_page_id; + $pledgeParams['financial_type_id'] = $contribution->financial_type_id; + $pledgeParams['frequency_interval'] = $params['pledge_frequency_interval']; + $pledgeParams['installments'] = $params['pledge_installments']; + $pledgeParams['frequency_unit'] = $params['pledge_frequency_unit']; + if ($pledgeParams['frequency_unit'] == 'month') { + $pledgeParams['frequency_day'] = intval(date("d")); } - $this->processMembership($membershipParams, $contactID, $customFieldsFormatted, $fieldTypes, $premiumParams, $membershipLineItems, $isPayLater); - if (!$this->_amount > 0.0 || !$membershipParams['amount']) { - // we need to explicitly create a CMS user in case of free memberships - // since it is done under processConfirm for paid memberships - CRM_Contribute_BAO_Contribution_Utils::createCMSUser($membershipParams, - $membershipParams['cms_contactID'], - 'email-' . $this->_bltID - ); + else { + $pledgeParams['frequency_day'] = 1; + } + $pledgeParams['create_date'] = $pledgeParams['start_date'] = $pledgeParams['scheduled_date'] = date("Ymd"); + $pledgeParams['status_id'] = $contribution->contribution_status_id; + $pledgeParams['max_reminders'] = $form->_values['max_reminders']; + $pledgeParams['initial_reminder_day'] = $form->_values['initial_reminder_day']; + $pledgeParams['additional_reminder_day'] = $form->_values['additional_reminder_day']; + $pledgeParams['is_test'] = $contribution->is_test; + $pledgeParams['acknowledge_date'] = date('Ymd'); + $pledgeParams['original_installment_amount'] = $pledgeParams['installment_amount']; + + //inherit campaign from contirb page. + $pledgeParams['campaign_id'] = $campaignId; + + $pledge = CRM_Pledge_BAO_Pledge::create($pledgeParams); + + $form->_params['pledge_id'] = $pledge->id; + + //send acknowledgment email. only when pledge is created + if ($pledge->id) { + //build params to send acknowledgment. + $pledgeParams['id'] = $pledge->id; + $pledgeParams['receipt_from_name'] = $form->_values['receipt_from_name']; + $pledgeParams['receipt_from_email'] = $form->_values['receipt_from_email']; + + //scheduled amount will be same as installment_amount. + $pledgeParams['scheduled_amount'] = $pledgeParams['installment_amount']; + + //get total pledge amount. + $pledgeParams['total_pledge_amount'] = $pledge->amount; + + CRM_Pledge_BAO_Pledge::sendAcknowledgment($form, $pledgeParams); } } } - else { - // at this point we've created a contact and stored its address etc - // all the payment processors expect the name and address to be in the - // so we copy stuff over to first_name etc. - $paymentParams = $this->_params; - $contributionTypeId = $this->_values['financial_type_id']; - $fieldTypes = array(); - if (!empty($paymentParams['onbehalf']) && - is_array($paymentParams['onbehalf']) + if ($online && $contribution) { + CRM_Core_BAO_CustomValueTable::postProcess($form->_params, + 'civicrm_contribution', + $contribution->id, + 'Contribution' + ); + } + elseif ($contribution) { + //handle custom data. + $params['contribution_id'] = $contribution->id; + if (!empty($params['custom']) && + is_array($params['custom']) && + !is_a($contribution, 'CRM_Core_Error') ) { - foreach ($paymentParams['onbehalf'] as $key => $value) { - if (strstr($key, 'custom_')) { - $this->_params[$key] = $value; - } - } - $fieldTypes = array('Contact', 'Organization', 'Contribution'); + CRM_Core_BAO_CustomValueTable::store($params['custom'], 'civicrm_contribution', $contribution->id); } - $financialTypeID = $this->wrangleFinancialTypeID($contributionTypeId); - - CRM_Contribute_BAO_Contribution_Utils::processConfirm($this, $paymentParams, - $premiumParams, $contactID, - $financialTypeID, - 'contribution', - $fieldTypes, - ($this->_mode == 'test') ? 1 : 0, - $isPayLater + } + // Save note + if ($contribution && !empty($params['contribution_note'])) { + $noteParams = array( + 'entity_table' => 'civicrm_contribution', + 'note' => $params['contribution_note'], + 'entity_id' => $contribution->id, + 'contact_id' => $contribution->contact_id, + 'modified_date' => date('Ymd'), ); + + CRM_Core_BAO_Note::add($noteParams, array()); } - } - /** - * Wrangle financial type ID. - * - * This wrangling of the financialType ID was happening in a shared function rather than in the form it relates to & hence has been moved to that form - * Pledges are not relevant to the membership code so that portion will not go onto the membership form. - * - * Comments from previous refactor indicate doubt as to what was going on. - * - * @param int $contributionTypeId - * - * @return null|string - */ - public function wrangleFinancialTypeID($contributionTypeId) { - if (isset($paymentParams['financial_type'])) { - $contributionTypeId = $paymentParams['financial_type']; + if (isset($params['related_contact'])) { + $contactID = $params['related_contact']; } - elseif (!empty($this->_values['pledge_id'])) { - $contributionTypeId = CRM_Core_DAO::getFieldValue('CRM_Pledge_DAO_Pledge', - $this->_values['pledge_id'], - 'financial_type_id' - ); + elseif (isset($params['cms_contactID'])) { + $contactID = $params['cms_contactID']; } - return $contributionTypeId; + + //create contribution activity w/ individual and target + //activity w/ organisation contact id when onbelf, CRM-4027 + $targetContactID = NULL; + if (!empty($params['hidden_onbehalf_profile'])) { + $targetContactID = $contribution->contact_id; + $contribution->contact_id = $contactID; + } + + // create an activity record + if ($contribution) { + CRM_Activity_BAO_Activity::addActivity($contribution, NULL, $targetContactID); + } + + $transaction->commit(); + // CRM-13074 - create the CMSUser after the transaction is completed as it + // is not appropriate to delete a valid contribution if a user create problem occurs + CRM_Contribute_BAO_Contribution_Utils::createCMSUser($params, + $contactID, + 'email-' . $billingLocationID + ); + return $contribution; } /** - * Process the form. + * Create the recurring contribution record. * - * @param array $premiumParams - * @param CRM_Contribute_BAO_Contribution $contribution + * @param CRM_Core_Form $form + * @param array $params + * @param int $contactID + * @param string $contributionType + * @param bool $online + * + * @return mixed */ - public function postProcessPremium($premiumParams, $contribution) { - $hour = $minute = $second = 0; - // assigning Premium information to receipt tpl - $selectProduct = CRM_Utils_Array::value('selectProduct', $premiumParams); - if ($selectProduct && - $selectProduct != 'no_thanks' - ) { - $startDate = $endDate = ""; - $this->assign('selectPremium', TRUE); - $productDAO = new CRM_Contribute_DAO_Product(); - $productDAO->id = $selectProduct; - $productDAO->find(TRUE); - $this->assign('product_name', $productDAO->name); - $this->assign('price', $productDAO->price); - $this->assign('sku', $productDAO->sku); - $this->assign('option', CRM_Utils_Array::value('options_' . $premiumParams['selectProduct'], $premiumParams)); - - $periodType = $productDAO->period_type; + public static function processRecurringContribution(&$form, &$params, $contactID, $contributionType, $online = TRUE) { + // return if this page is not set for recurring + // or the user has not chosen the recurring option - if ($periodType) { - $fixed_period_start_day = $productDAO->fixed_period_start_day; - $duration_unit = $productDAO->duration_unit; - $duration_interval = $productDAO->duration_interval; - if ($periodType == 'rolling') { - $startDate = date('Y-m-d'); - } - elseif ($periodType == 'fixed') { - if ($fixed_period_start_day) { - $date = explode('-', date('Y-m-d')); - $month = substr($fixed_period_start_day, 0, strlen($fixed_period_start_day) - 2); - $day = substr($fixed_period_start_day, -2) . "
"; - $year = $date[0]; - $startDate = $year . '-' . $month . '-' . $day; - } - else { - $startDate = date('Y-m-d'); - } - } + //this is online case validation. + if ((empty($form->_values['is_recur']) && $online) || empty($params['is_recur'])) { + return NULL; + } - $date = explode('-', $startDate); - $year = $date[0]; - $month = $date[1]; - $day = $date[2]; - - switch ($duration_unit) { - case 'year': - $year = $year + $duration_interval; - break; - - case 'month': - $month = $month + $duration_interval; - break; + $recurParams = array('contact_id' => $contactID); + $recurParams['amount'] = CRM_Utils_Array::value('amount', $params); + $recurParams['auto_renew'] = CRM_Utils_Array::value('auto_renew', $params); + $recurParams['frequency_unit'] = CRM_Utils_Array::value('frequency_unit', $params); + $recurParams['frequency_interval'] = CRM_Utils_Array::value('frequency_interval', $params); + $recurParams['installments'] = CRM_Utils_Array::value('installments', $params); + $recurParams['financial_type_id'] = CRM_Utils_Array::value('financial_type_id', $params); + $recurParams['currency'] = CRM_Utils_Array::value('currency', $params); - case 'day': - $day = $day + $duration_interval; - break; + // CRM-14354: For an auto-renewing membership with an additional contribution, + // if separate payments is not enabled, make sure only the membership fee recurs + if (!empty($form->_membershipBlock) + && $form->_membershipBlock['is_separate_payment'] === '0' + && isset($params['selectMembership']) + && $form->_values['is_allow_other_amount'] == '1' + // CRM-16331 + && !empty($form->_membershipTypeValues) + && !empty($form->_membershipTypeValues[$params['selectMembership']]['minimum_fee']) + ) { + $recurParams['amount'] = $form->_membershipTypeValues[$params['selectMembership']]['minimum_fee']; + } - case 'week': - $day = $day + ($duration_interval * 7); - } - $endDate = date('Y-m-d H:i:s', mktime($hour, $minute, $second, $month, $day, $year)); - $this->assign('start_date', $startDate); - $this->assign('end_date', $endDate); - } + $recurParams['is_test'] = 0; + if (($form->_action & CRM_Core_Action::PREVIEW) || + (isset($form->_mode) && ($form->_mode == 'test')) + ) { + $recurParams['is_test'] = 1; + } - $dao = new CRM_Contribute_DAO_Premium(); - $dao->entity_table = 'civicrm_contribution_page'; - $dao->entity_id = $this->_id; - $dao->find(TRUE); - $this->assign('contact_phone', $dao->premiums_contact_phone); - $this->assign('contact_email', $dao->premiums_contact_email); + $recurParams['start_date'] = $recurParams['create_date'] = $recurParams['modified_date'] = date('YmdHis'); + if (!empty($params['receive_date'])) { + $recurParams['start_date'] = $params['receive_date']; + } + $recurParams['invoice_id'] = CRM_Utils_Array::value('invoiceID', $params); + $recurParams['contribution_status_id'] = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Pending'); + $recurParams['payment_processor_id'] = CRM_Utils_Array::value('payment_processor_id', $params); + $recurParams['is_email_receipt'] = CRM_Utils_Array::value('is_email_receipt', $params); + // we need to add a unique trxn_id to avoid a unique key error + // in paypal IPN we reset this when paypal sends us the real trxn id, CRM-2991 + $recurParams['trxn_id'] = CRM_Utils_Array::value('trxn_id', $params, $params['invoiceID']); + $recurParams['financial_type_id'] = $contributionType->id; - //create Premium record - $params = array( - 'product_id' => $premiumParams['selectProduct'], - 'contribution_id' => $contribution->id, - 'product_option' => CRM_Utils_Array::value('options_' . $premiumParams['selectProduct'], $premiumParams), - 'quantity' => 1, - 'start_date' => CRM_Utils_Date::customFormat($startDate, '%Y%m%d'), - 'end_date' => CRM_Utils_Date::customFormat($endDate, '%Y%m%d'), - ); - if (!empty($premiumParams['selectProduct'])) { - $daoPremiumsProduct = new CRM_Contribute_DAO_PremiumsProduct(); - $daoPremiumsProduct->product_id = $premiumParams['selectProduct']; - $daoPremiumsProduct->premiums_id = $dao->id; - $daoPremiumsProduct->find(TRUE); - $params['financial_type_id'] = $daoPremiumsProduct->financial_type_id; - } - //Fixed For CRM-3901 - $daoContrProd = new CRM_Contribute_DAO_ContributionProduct(); - $daoContrProd->contribution_id = $contribution->id; - if ($daoContrProd->find(TRUE)) { - $params['id'] = $daoContrProd->id; - } + if (!$online || $form->_values['is_monetary']) { + $recurParams['payment_instrument_id'] = 1; + } - CRM_Contribute_BAO_Contribution::addPremium($params); - if ($productDAO->cost && !empty($params['financial_type_id'])) { - $trxnParams = array( - 'cost' => $productDAO->cost, - 'currency' => $productDAO->currency, - 'financial_type_id' => $params['financial_type_id'], - 'contributionId' => $contribution->id, - ); - CRM_Core_BAO_FinancialTrxn::createPremiumTrxn($trxnParams); + $campaignId = CRM_Utils_Array::value('campaign_id', $params); + if ($online) { + if (!array_key_exists('campaign_id', $params)) { + $campaignId = CRM_Utils_Array::value('campaign_id', $form->_values); } } - elseif ($selectProduct == 'no_thanks') { - //Fixed For CRM-3901 - $daoContrProd = new CRM_Contribute_DAO_ContributionProduct(); - $daoContrProd->contribution_id = $contribution->id; - if ($daoContrProd->find(TRUE)) { - $daoContrProd->delete(); + $recurParams['campaign_id'] = $campaignId; + + $recurring = CRM_Contribute_BAO_ContributionRecur::add($recurParams); + if (is_a($recurring, 'CRM_Core_Error')) { + CRM_Core_Error::displaySessionError($recurring); + $urlString = 'civicrm/contribute/transact'; + $urlParams = '_qf_Main_display=true'; + if (get_class($form) == 'CRM_Contribute_Form_Contribution') { + $urlString = 'civicrm/contact/view/contribution'; + $urlParams = "action=add&cid={$form->_contactID}"; + if ($form->_mode) { + $urlParams .= "&mode={$form->_mode}"; + } } + CRM_Utils_System::redirect(CRM_Utils_System::url($urlString, $urlParams)); } + + return $recurring->id; } /** - * Process the contribution. - * - * @param CRM_Core_Form $form - * @param array $params - * @param array $result - * @param int $contactID - * @param CRM_Financial_DAO_FinancialType $financialType - * @param bool $pending - * @param bool $online + * Add on behalf of organization and it's location. * - * @param bool $isTest - * @param array $lineItems + * This situation occurs when on behalf of is enabled for the contribution page and the person + * signing up does so on behalf of an organization. * - * @param int $billingLocationID - * ID of billing location type. + * @param array $behalfOrganization + * array of organization info. + * @param int $contactID + * individual contact id. One. + * who is doing the process of signup / contribution. * - * @return \CRM_Contribute_DAO_Contribution - * @throws \Exception + * @param array $values + * form values array. + * @param array $params + * @param array $fields + * Array of fields from the onbehalf profile relevant to the organization. */ - public static function processFormContribution( - &$form, - $params, - $result, - $contactID, - $financialType, - $pending, - $online, - $isTest, - $lineItems, - $billingLocationID - ) { - $transaction = new CRM_Core_Transaction(); - $contribSoftContactId = $addressID = NULL; - $contributeMode = $form->_contributeMode; - $isMonetary = !empty($form->_values['is_monetary']); - $isEmailReceipt = !empty($form->_values['is_email_receipt']); - // How do these vary from params? These are currently passed to - // - custom data function.... - $formParams = $form->_params; - $isSeparateMembershipPayment = empty($formParams['separate_membership_payment']) ? FALSE : TRUE; - $pledgeID = empty($formParams['pledge_id']) ? NULL : $formParams['pledge_id']; - if (!$isSeparateMembershipPayment && !empty($form->_values['pledge_block_id']) && - (!empty($formParams['is_pledge']) || $pledgeID)) { - $isPledge = TRUE; - } - else { - $isPledge = FALSE; + public static function processOnBehalfOrganization(&$behalfOrganization, &$contactID, &$values, &$params, $fields = NULL) { + $isCurrentEmployer = FALSE; + $dupeIDs = array(); + $orgID = NULL; + if (!empty($behalfOrganization['organization_id']) && empty($behalfOrganization['org_option'])) { + $orgID = $behalfOrganization['organization_id']; + unset($behalfOrganization['organization_id']); + $isCurrentEmployer = TRUE; } - // add these values for the recurringContrib function ,CRM-10188 - $params['financial_type_id'] = $financialType->id; + // formalities for creating / editing organization. + $behalfOrganization['contact_type'] = 'Organization'; - //create an contribution address - if ($contributeMode != 'notify' && empty($params['is_pay_later']) && $isMonetary) { - $addressID = CRM_Contribute_BAO_Contribution::createAddress($params, $billingLocationID); - } + // get the relationship type id + $relType = new CRM_Contact_DAO_RelationshipType(); + $relType->name_a_b = 'Employee of'; + $relType->find(TRUE); + $relTypeId = $relType->id; - //@todo - this is being set from the form to resolve CRM-10188 - an - // eNotice caused by it not being set @ the front end - // however, we then get it being over-written with null for backend contributions - // a better fix would be to set the values in the respective forms rather than require - // a function being shared by two forms to deal with their respective values - // moving it to the BAO & not taking the $form as a param would make sense here. - if (!isset($params['is_email_receipt']) && $isEmailReceipt) { - $params['is_email_receipt'] = $isEmailReceipt; - } - $recurringContributionID = self::processRecurringContribution($form, $params, $contactID, $financialType, $online); - $nonDeductibleAmount = self::getNonDeductibleAmount($params, $financialType, $online); + // keep relationship params ready + $relParams['relationship_type_id'] = $relTypeId . '_a_b'; + $relParams['is_permission_a_b'] = 1; + $relParams['is_active'] = 1; - $now = date('YmdHis'); - $receiptDate = CRM_Utils_Array::value('receipt_date', $params); - if ($isEmailReceipt) { - $receiptDate = $now; - } + if (!$orgID) { + // check if matching organization contact exists + $dedupeParams = CRM_Dedupe_Finder::formatParams($behalfOrganization, 'Organization'); + $dedupeParams['check_permission'] = FALSE; + $dupeIDs = CRM_Dedupe_Finder::dupesByParams($dedupeParams, 'Organization', 'Unsupervised'); - //get the contrib page id. - $contributionPageId = NULL; - if ($online) { - $contributionPageId = $form->_id; - $campaignId = CRM_Utils_Array::value('campaign_id', $params); - if (!array_key_exists('campaign_id', $params)) { - $campaignId = CRM_Utils_Array::value('campaign_id', $form->_values); + // CRM-6243 says to pick the first org even if more than one match + if (count($dupeIDs) >= 1) { + $behalfOrganization['contact_id'] = $orgID = $dupeIDs[0]; + // don't allow name edit + unset($behalfOrganization['organization_name']); } } else { - //also for offline we do support - CRM-7290 - $contributionPageId = CRM_Utils_Array::value('contribution_page_id', $params); - $campaignId = CRM_Utils_Array::value('campaign_id', $params); + // if found permissioned related organization, allow location edit + $behalfOrganization['contact_id'] = $orgID; + // don't allow name edit + unset($behalfOrganization['organization_name']); } - // Prepare soft contribution due to pcp or Submit Credit / Debit Card Contribution by admin. - if (!empty($params['pcp_made_through_id']) || !empty($params['soft_credit_to'])) { - // if its due to pcp - if (!empty($params['pcp_made_through_id'])) { - $contribSoftContactId = CRM_Core_DAO::getFieldValue( - 'CRM_PCP_DAO_PCP', - $params['pcp_made_through_id'], - 'contact_id' - ); - } - else { - $contribSoftContactId = CRM_Utils_Array::value('soft_credit_to', $params); - } - - // Pass these details onto with the contribution to make them - // available at hook_post_process, CRM-8908 - $params['soft_credit_to'] = $contribSoftContactId; + // handling for image url + if (!empty($behalfOrganization['image_URL'])) { + CRM_Contact_BAO_Contact::processImageParams($behalfOrganization); } - if (isset($params['amount'])) { - $contribParams = self::getContributionParams( - $params, $contactID, $financialType->id, $online, $contributionPageId, $nonDeductibleAmount, $campaignId, $isMonetary, $pending, $result, $receiptDate, - $recurringContributionID, $isTest, $addressID, $contribSoftContactId, $lineItems - ); - $contribution = CRM_Contribute_BAO_Contribution::add($contribParams); - - $invoiceSettings = CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::CONTRIBUTE_PREFERENCES_NAME, 'contribution_invoice_settings'); - $invoicing = CRM_Utils_Array::value('invoicing', $invoiceSettings); - if ($invoicing) { - $dataArray = array(); - foreach ($form->_lineItem as $lineItemKey => $lineItemValue) { - foreach ($lineItemValue as $key => $value) { - if (isset($value['tax_amount']) && isset($value['tax_rate'])) { - if (isset($dataArray[$value['tax_rate']])) { - $dataArray[$value['tax_rate']] = $dataArray[$value['tax_rate']] + CRM_Utils_Array::value('tax_amount', $value); - } - else { - $dataArray[$value['tax_rate']] = CRM_Utils_Array::value('tax_amount', $value); - } - } - } - } - $smarty = CRM_Core_Smarty::singleton(); - $smarty->assign('dataArray', $dataArray); - $smarty->assign('totalTaxAmount', $params['tax_amount']); - } - if (is_a($contribution, 'CRM_Core_Error')) { - $message = CRM_Core_Error::getMessages($contribution); - CRM_Core_Error::fatal($message); - } + // create organization, add location + $orgID = CRM_Contact_BAO_Contact::createProfileContact($behalfOrganization, $fields, $orgID, + NULL, NULL, 'Organization' + ); + // create relationship + $relParams['contact_check'][$orgID] = 1; + $cid = array('contact' => $contactID); + CRM_Contact_BAO_Relationship::legacyCreateMultiple($relParams, $cid); - // lets store it in the form variable so postProcess hook can get to this and use it - $form->_contributionID = $contribution->id; + // if multiple match - send a duplicate alert + if ($dupeIDs && (count($dupeIDs) > 1)) { + $values['onbehalf_dupe_alert'] = 1; + // required for IPN + $params['onbehalf_dupe_alert'] = 1; } - //CRM-13981, processing honor contact into soft-credit contribution - CRM_Contact_Form_ProfileContact::postProcess($form); - - // process soft credit / pcp pages - CRM_Contribute_Form_Contribution_Confirm::processPcpSoft($params, $contribution); - - //handle pledge stuff. - if ($isPledge) { - if ($pledgeID) { - //when user doing pledge payments. - //update the schedule when payment(s) are made - foreach ($form->_params['pledge_amount'] as $paymentId => $dontCare) { - $scheduledAmount = CRM_Core_DAO::getFieldValue( - 'CRM_Pledge_DAO_PledgePayment', - $paymentId, - 'scheduled_amount', - 'id' - ); - - $pledgePaymentParams = array( - 'id' => $paymentId, - 'contribution_id' => $contribution->id, - 'status_id' => $contribution->contribution_status_id, - 'actual_amount' => $scheduledAmount, - ); + // make sure organization-contact-id is considered for recording + // contribution/membership etc.. + if ($contactID != $orgID) { + // take a note of contact-id, so we can send the + // receipt to individual contact as well. - CRM_Pledge_BAO_PledgePayment::add($pledgePaymentParams); - } + // required for mailing/template display ..etc + $values['related_contact'] = $contactID; + // required for IPN + $params['related_contact'] = $contactID; - //update pledge status according to the new payment statuses - CRM_Pledge_BAO_PledgePayment::updatePledgePaymentStatus($pledgeID); + //make this employee of relationship as current + //employer / employee relationship, CRM-3532 + if ($isCurrentEmployer && + ($orgID != CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $contactID, 'employer_id')) + ) { + $isCurrentEmployer = FALSE; } - else { - //when user creating pledge record. - $pledgeParams = array(); - $pledgeParams['contact_id'] = $contribution->contact_id; - $pledgeParams['installment_amount'] = $pledgeParams['actual_amount'] = $contribution->total_amount; - $pledgeParams['contribution_id'] = $contribution->id; - $pledgeParams['contribution_page_id'] = $contribution->contribution_page_id; - $pledgeParams['financial_type_id'] = $contribution->financial_type_id; - $pledgeParams['frequency_interval'] = $params['pledge_frequency_interval']; - $pledgeParams['installments'] = $params['pledge_installments']; - $pledgeParams['frequency_unit'] = $params['pledge_frequency_unit']; - if ($pledgeParams['frequency_unit'] == 'month') { - $pledgeParams['frequency_day'] = intval(date("d")); - } - else { - $pledgeParams['frequency_day'] = 1; - } - $pledgeParams['create_date'] = $pledgeParams['start_date'] = $pledgeParams['scheduled_date'] = date("Ymd"); - $pledgeParams['status_id'] = $contribution->contribution_status_id; - $pledgeParams['max_reminders'] = $form->_values['max_reminders']; - $pledgeParams['initial_reminder_day'] = $form->_values['initial_reminder_day']; - $pledgeParams['additional_reminder_day'] = $form->_values['additional_reminder_day']; - $pledgeParams['is_test'] = $contribution->is_test; - $pledgeParams['acknowledge_date'] = date('Ymd'); - $pledgeParams['original_installment_amount'] = $pledgeParams['installment_amount']; - - //inherit campaign from contirb page. - $pledgeParams['campaign_id'] = $campaignId; - $pledge = CRM_Pledge_BAO_Pledge::create($pledgeParams); - - $form->_params['pledge_id'] = $pledge->id; - - //send acknowledgment email. only when pledge is created - if ($pledge->id) { - //build params to send acknowledgment. - $pledgeParams['id'] = $pledge->id; - $pledgeParams['receipt_from_name'] = $form->_values['receipt_from_name']; - $pledgeParams['receipt_from_email'] = $form->_values['receipt_from_email']; - - //scheduled amount will be same as installment_amount. - $pledgeParams['scheduled_amount'] = $pledgeParams['installment_amount']; - - //get total pledge amount. - $pledgeParams['total_pledge_amount'] = $pledge->amount; - - CRM_Pledge_BAO_Pledge::sendAcknowledgment($form, $pledgeParams); - } + if (!$isCurrentEmployer && $orgID) { + //build current employer params + $currentEmpParams[$contactID] = $orgID; + CRM_Contact_BAO_Contact_Utils::setCurrentEmployer($currentEmpParams); } - } - if ($online && $contribution) { - CRM_Core_BAO_CustomValueTable::postProcess($form->_params, - 'civicrm_contribution', - $contribution->id, - 'Contribution' - ); + // contribution / signup will be done using this + // organization id. + $contactID = $orgID; } - elseif ($contribution) { - //handle custom data. - $params['contribution_id'] = $contribution->id; - if (!empty($params['custom']) && - is_array($params['custom']) && - !is_a($contribution, 'CRM_Core_Error') - ) { - CRM_Core_BAO_CustomValueTable::store($params['custom'], 'civicrm_contribution', $contribution->id); + } + + /** + * Function used to save pcp / soft credit entry. + * + * This is used by contribution and also event pcps + * + * @param array $params + * @param object $contribution + * Contribution object. + */ + public static function processPcpSoft(&$params, &$contribution) { + // Add soft contribution due to pcp or Submit Credit / Debit Card Contribution by admin. + if (!empty($params['soft_credit_to'])) { + $contributionSoftParams = array(); + foreach (array( + 'pcp_display_in_roll', + 'pcp_roll_nickname', + 'pcp_personal_note', + 'amount', + ) as $val) { + if (!empty($params[$val])) { + $contributionSoftParams[$val] = $params[$val]; + } } - } - // Save note - if ($contribution && !empty($params['contribution_note'])) { - $noteParams = array( - 'entity_table' => 'civicrm_contribution', - 'note' => $params['contribution_note'], - 'entity_id' => $contribution->id, - 'contact_id' => $contribution->contact_id, - 'modified_date' => date('Ymd'), - ); - CRM_Core_BAO_Note::add($noteParams, array()); - } + $contributionSoftParams['contact_id'] = $params['soft_credit_to']; + // add contribution id + $contributionSoftParams['contribution_id'] = $contribution->id; + // add pcp id + $contributionSoftParams['pcp_id'] = $params['pcp_made_through_id']; - if (isset($params['related_contact'])) { - $contactID = $params['related_contact']; - } - elseif (isset($params['cms_contactID'])) { - $contactID = $params['cms_contactID']; - } + $contributionSoftParams['soft_credit_type_id'] = CRM_Core_OptionGroup::getValue('soft_credit_type', 'pcp', 'name'); - //create contribution activity w/ individual and target - //activity w/ organisation contact id when onbelf, CRM-4027 - $targetContactID = NULL; - if (!empty($params['hidden_onbehalf_profile'])) { - $targetContactID = $contribution->contact_id; - $contribution->contact_id = $contactID; - } + $contributionSoft = CRM_Contribute_BAO_ContributionSoft::add($contributionSoftParams); - // create an activity record - if ($contribution) { - CRM_Activity_BAO_Activity::addActivity($contribution, NULL, $targetContactID); + //Send notification to owner for PCP + if ($contributionSoft->id && $contributionSoft->pcp_id) { + CRM_Contribute_Form_Contribution_Confirm::pcpNotifyOwner($contribution, $contributionSoft); + } } - - $transaction->commit(); - // CRM-13074 - create the CMSUser after the transaction is completed as it - // is not appropriate to delete a valid contribution if a user create problem occurs - CRM_Contribute_BAO_Contribution_Utils::createCMSUser($params, - $contactID, - 'email-' . $billingLocationID - ); - return $contribution; } /** - * Create the recurring contribution record. + * Function used to send notification mail to pcp owner. * - * @param CRM_Core_Form $form - * @param array $params - * @param int $contactID - * @param string $contributionType - * @param bool $online + * This is used by contribution and also event PCPs. * - * @return mixed - */ - public static function processRecurringContribution(&$form, &$params, $contactID, $contributionType, $online = TRUE) { - // return if this page is not set for recurring - // or the user has not chosen the recurring option - - //this is online case validation. - if ((empty($form->_values['is_recur']) && $online) || empty($params['is_recur'])) { - return NULL; - } - - $recurParams = array('contact_id' => $contactID); - $recurParams['amount'] = CRM_Utils_Array::value('amount', $params); - $recurParams['auto_renew'] = CRM_Utils_Array::value('auto_renew', $params); - $recurParams['frequency_unit'] = CRM_Utils_Array::value('frequency_unit', $params); - $recurParams['frequency_interval'] = CRM_Utils_Array::value('frequency_interval', $params); - $recurParams['installments'] = CRM_Utils_Array::value('installments', $params); - $recurParams['financial_type_id'] = CRM_Utils_Array::value('financial_type_id', $params); - $recurParams['currency'] = CRM_Utils_Array::value('currency', $params); - - // CRM-14354: For an auto-renewing membership with an additional contribution, - // if separate payments is not enabled, make sure only the membership fee recurs - if (!empty($form->_membershipBlock) - && $form->_membershipBlock['is_separate_payment'] === '0' - && isset($params['selectMembership']) - && $form->_values['is_allow_other_amount'] == '1' - // CRM-16331 - && !empty($form->_membershipTypeValues) - && !empty($form->_membershipTypeValues[$params['selectMembership']]['minimum_fee']) - ) { - $recurParams['amount'] = $form->_membershipTypeValues[$params['selectMembership']]['minimum_fee']; - } - - $recurParams['is_test'] = 0; - if (($form->_action & CRM_Core_Action::PREVIEW) || - (isset($form->_mode) && ($form->_mode == 'test')) - ) { - $recurParams['is_test'] = 1; - } - - $recurParams['start_date'] = $recurParams['create_date'] = $recurParams['modified_date'] = date('YmdHis'); - if (!empty($params['receive_date'])) { - $recurParams['start_date'] = $params['receive_date']; - } - $recurParams['invoice_id'] = CRM_Utils_Array::value('invoiceID', $params); - $recurParams['contribution_status_id'] = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Pending'); - $recurParams['payment_processor_id'] = CRM_Utils_Array::value('payment_processor_id', $params); - $recurParams['is_email_receipt'] = CRM_Utils_Array::value('is_email_receipt', $params); - // we need to add a unique trxn_id to avoid a unique key error - // in paypal IPN we reset this when paypal sends us the real trxn id, CRM-2991 - $recurParams['trxn_id'] = CRM_Utils_Array::value('trxn_id', $params, $params['invoiceID']); - $recurParams['financial_type_id'] = $contributionType->id; - - if (!$online || $form->_values['is_monetary']) { - $recurParams['payment_instrument_id'] = 1; - } - - $campaignId = CRM_Utils_Array::value('campaign_id', $params); - if ($online) { - if (!array_key_exists('campaign_id', $params)) { - $campaignId = CRM_Utils_Array::value('campaign_id', $form->_values); - } - } - $recurParams['campaign_id'] = $campaignId; - - $recurring = CRM_Contribute_BAO_ContributionRecur::add($recurParams); - if (is_a($recurring, 'CRM_Core_Error')) { - CRM_Core_Error::displaySessionError($recurring); - $urlString = 'civicrm/contribute/transact'; - $urlParams = '_qf_Main_display=true'; - if (get_class($form) == 'CRM_Contribute_Form_Contribution') { - $urlString = 'civicrm/contact/view/contribution'; - $urlParams = "action=add&cid={$form->_contactID}"; - if ($form->_mode) { - $urlParams .= "&mode={$form->_mode}"; - } - } - CRM_Utils_System::redirect(CRM_Utils_System::url($urlString, $urlParams)); - } - - return $recurring->id; - } - - /** - * Add on behalf of organization and it's location. - * - * This situation occurs when on behalf of is enabled for the contribution page and the person - * signing up does so on behalf of an organization. - * - * @param array $behalfOrganization - * array of organization info. - * @param int $contactID - * individual contact id. One. - * who is doing the process of signup / contribution. - * - * @param array $values - * form values array. - * @param array $params - * @param array $fields - * Array of fields from the onbehalf profile relevant to the organization. - */ - public static function processOnBehalfOrganization(&$behalfOrganization, &$contactID, &$values, &$params, $fields = NULL) { - $isCurrentEmployer = FALSE; - $dupeIDs = array(); - $orgID = NULL; - if (!empty($behalfOrganization['organization_id']) && empty($behalfOrganization['org_option'])) { - $orgID = $behalfOrganization['organization_id']; - unset($behalfOrganization['organization_id']); - $isCurrentEmployer = TRUE; - } - - // formalities for creating / editing organization. - $behalfOrganization['contact_type'] = 'Organization'; - - // get the relationship type id - $relType = new CRM_Contact_DAO_RelationshipType(); - $relType->name_a_b = 'Employee of'; - $relType->find(TRUE); - $relTypeId = $relType->id; - - // keep relationship params ready - $relParams['relationship_type_id'] = $relTypeId . '_a_b'; - $relParams['is_permission_a_b'] = 1; - $relParams['is_active'] = 1; - - if (!$orgID) { - // check if matching organization contact exists - $dedupeParams = CRM_Dedupe_Finder::formatParams($behalfOrganization, 'Organization'); - $dedupeParams['check_permission'] = FALSE; - $dupeIDs = CRM_Dedupe_Finder::dupesByParams($dedupeParams, 'Organization', 'Unsupervised'); - - // CRM-6243 says to pick the first org even if more than one match - if (count($dupeIDs) >= 1) { - $behalfOrganization['contact_id'] = $orgID = $dupeIDs[0]; - // don't allow name edit - unset($behalfOrganization['organization_name']); - } - } - else { - // if found permissioned related organization, allow location edit - $behalfOrganization['contact_id'] = $orgID; - // don't allow name edit - unset($behalfOrganization['organization_name']); - } - - // handling for image url - if (!empty($behalfOrganization['image_URL'])) { - CRM_Contact_BAO_Contact::processImageParams($behalfOrganization); - } - - // create organization, add location - $orgID = CRM_Contact_BAO_Contact::createProfileContact($behalfOrganization, $fields, $orgID, - NULL, NULL, 'Organization' - ); - // create relationship - $relParams['contact_check'][$orgID] = 1; - $cid = array('contact' => $contactID); - CRM_Contact_BAO_Relationship::legacyCreateMultiple($relParams, $cid); - - // if multiple match - send a duplicate alert - if ($dupeIDs && (count($dupeIDs) > 1)) { - $values['onbehalf_dupe_alert'] = 1; - // required for IPN - $params['onbehalf_dupe_alert'] = 1; - } - - // make sure organization-contact-id is considered for recording - // contribution/membership etc.. - if ($contactID != $orgID) { - // take a note of contact-id, so we can send the - // receipt to individual contact as well. - - // required for mailing/template display ..etc - $values['related_contact'] = $contactID; - // required for IPN - $params['related_contact'] = $contactID; - - //make this employee of relationship as current - //employer / employee relationship, CRM-3532 - if ($isCurrentEmployer && - ($orgID != CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $contactID, 'employer_id')) - ) { - $isCurrentEmployer = FALSE; - } - - if (!$isCurrentEmployer && $orgID) { - //build current employer params - $currentEmpParams[$contactID] = $orgID; - CRM_Contact_BAO_Contact_Utils::setCurrentEmployer($currentEmpParams); - } - - // contribution / signup will be done using this - // organization id. - $contactID = $orgID; - } - } - - /** - * Function used to save pcp / soft credit entry. - * - * This is used by contribution and also event pcps - * - * @param array $params - * @param object $contribution - * Contribution object. - */ - public static function processPcpSoft(&$params, &$contribution) { - // Add soft contribution due to pcp or Submit Credit / Debit Card Contribution by admin. - if (!empty($params['soft_credit_to'])) { - $contributionSoftParams = array(); - foreach (array( - 'pcp_display_in_roll', - 'pcp_roll_nickname', - 'pcp_personal_note', - 'amount', - ) as $val) { - if (!empty($params[$val])) { - $contributionSoftParams[$val] = $params[$val]; - } - } - - $contributionSoftParams['contact_id'] = $params['soft_credit_to']; - // add contribution id - $contributionSoftParams['contribution_id'] = $contribution->id; - // add pcp id - $contributionSoftParams['pcp_id'] = $params['pcp_made_through_id']; - - $contributionSoftParams['soft_credit_type_id'] = CRM_Core_OptionGroup::getValue('soft_credit_type', 'pcp', 'name'); - - $contributionSoft = CRM_Contribute_BAO_ContributionSoft::add($contributionSoftParams); - - //Send notification to owner for PCP - if ($contributionSoft->id && $contributionSoft->pcp_id) { - CRM_Contribute_Form_Contribution_Confirm::pcpNotifyOwner($contribution, $contributionSoft); - } - } - } - - /** - * Function used to send notification mail to pcp owner. - * - * This is used by contribution and also event PCPs. - * - * @param object $contribution - * @param object $contributionSoft - * Contribution object. + * @param object $contribution + * @param object $contributionSoft + * Contribution object. */ public static function pcpNotifyOwner($contribution, $contributionSoft) { $params = array('id' => $contributionSoft->pcp_id); @@ -2023,9 +1655,7 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr public static function submit($params) { $form = new CRM_Contribute_Form_Contribution_Confirm(); $form->_id = $params['id']; - if (!empty($params['contact_id'])) { - $form->_contactID = $params['contact_id']; - } + CRM_Contribute_BAO_ContributionPage::setValues($form->_id, $form->_values); $form->_separateMembershipPayment = CRM_Contribute_BAO_ContributionPage::getIsMembershipPayment($form->_id); //this way the mocked up controller ignores the session stuff @@ -2057,7 +1687,7 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr $priceFields = $priceFields[$priceSetID]['fields']; CRM_Price_BAO_PriceSet::processAmount($priceFields, $paramsProcessedForForm, $lineItems, 'civicrm_contribution'); $form->_lineItem = array($priceSetID => $lineItems); - $form->postProcess(); + $form->processFormSubmission(CRM_Utils_Array::value('contact_id', $params)); } /** @@ -2089,4 +1719,391 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr return $params; } + /** + * Post form submission handling. + * + * This is also called from the test suite. + * + * @param int $contactID + * + * @return array + */ + protected function processFormSubmission($contactID) { + $isPayLater = $this->_params['is_pay_later']; + if (isset($this->_params['payment_processor_id']) && $this->_params['payment_processor_id'] == 0) { + $this->_params['is_pay_later'] = $isPayLater = TRUE; + } + // add a description field at the very beginning + $this->_params['description'] = ts('Online Contribution') . ': ' . (($this->_pcpInfo['title']) ? $this->_pcpInfo['title'] : $this->_values['title']); + + $this->_params['accountingCode'] = CRM_Utils_Array::value('accountingCode', $this->_values); + + // fix currency ID + $this->_params['currencyID'] = CRM_Core_Config::singleton()->defaultCurrency; + + //carry payment processor id. + if (CRM_Utils_Array::value('id', $this->_paymentProcessor)) { + $this->_params['payment_processor_id'] = $this->_paymentProcessor['id']; + } + if (!empty($params['image_URL'])) { + CRM_Contact_BAO_Contact::processImageParams($params); + } + $premiumParams = $membershipParams = $params = $this->_params; + $fields = array('email-Primary' => 1); + + // get the add to groups + $addToGroups = array(); + + // now set the values for the billing location. + foreach ($this->_fields as $name => $value) { + $fields[$name] = 1; + + // get the add to groups for uf fields + if (!empty($value['add_to_group_id'])) { + $addToGroups[$value['add_to_group_id']] = $value['add_to_group_id']; + } + } + + if (!array_key_exists('first_name', $fields)) { + $nameFields = array('first_name', 'middle_name', 'last_name'); + foreach ($nameFields as $name) { + $fields[$name] = 1; + if (array_key_exists("billing_$name", $params)) { + $params[$name] = $params["billing_{$name}"]; + $params['preserveDBName'] = TRUE; + } + } + } + + // billing email address + $fields["email-{$this->_bltID}"] = 1; + + //unset the billing parameters if it is pay later mode + //to avoid creation of billing location + if ($isPayLater && !$this->_isBillingAddressRequiredForPayLater) { + $billingFields = array( + 'billing_first_name', + 'billing_middle_name', + 'billing_last_name', + "billing_street_address-{$this->_bltID}", + "billing_city-{$this->_bltID}", + "billing_state_province-{$this->_bltID}", + "billing_state_province_id-{$this->_bltID}", + "billing_postal_code-{$this->_bltID}", + "billing_country-{$this->_bltID}", + "billing_country_id-{$this->_bltID}", + ); + + foreach ($billingFields as $value) { + unset($params[$value]); + unset($fields[$value]); + } + } + + // if onbehalf-of-organization contribution, take out + // organization params in a separate variable, to make sure + // normal behavior is continued. And use that variable to + // process on-behalf-of functionality. + if (!empty($this->_params['hidden_onbehalf_profile'])) { + $behalfOrganization = array(); + $orgFields = array('organization_name', 'organization_id', 'org_option'); + foreach ($orgFields as $fld) { + if (array_key_exists($fld, $params)) { + $behalfOrganization[$fld] = $params[$fld]; + unset($params[$fld]); + } + } + + if (is_array($params['onbehalf']) && !empty($params['onbehalf'])) { + foreach ($params['onbehalf'] as $fld => $values) { + if (strstr($fld, 'custom_')) { + $behalfOrganization[$fld] = $values; + } + elseif (!(strstr($fld, '-'))) { + if (in_array($fld, array( + 'contribution_campaign_id', + 'member_campaign_id', + ))) { + $fld = 'campaign_id'; + } + else { + $behalfOrganization[$fld] = $values; + } + $this->_params[$fld] = $values; + } + } + } + + if (array_key_exists('onbehalf_location', $params) && is_array($params['onbehalf_location'])) { + foreach ($params['onbehalf_location'] as $block => $vals) { + //fix for custom data (of type checkbox, multi-select) + if (substr($block, 0, 7) == 'custom_') { + continue; + } + // fix the index of block elements + if (is_array($vals)) { + foreach ($vals as $key => $val) { + //dont adjust the index of address block as + //it's index is WRT to location type + $newKey = ($block == 'address') ? $key : ++$key; + $behalfOrganization[$block][$newKey] = $val; + } + } + } + unset($params['onbehalf_location']); + } + if (!empty($params['onbehalf[image_URL]'])) { + $behalfOrganization['image_URL'] = $params['onbehalf[image_URL]']; + } + } + + // check for profile double opt-in and get groups to be subscribed + $subscribeGroupIds = CRM_Core_BAO_UFGroup::getDoubleOptInGroupIds($params, $contactID); + + // since we are directly adding contact to group lets unset it from mailing + if (!empty($addToGroups)) { + foreach ($addToGroups as $groupId) { + if (isset($subscribeGroupIds[$groupId])) { + unset($subscribeGroupIds[$groupId]); + } + } + } + + foreach ($addToGroups as $k) { + if (array_key_exists($k, $subscribeGroupIds)) { + unset($addToGroups[$k]); + } + } + + if (empty($contactID)) { + $dupeParams = $params; + if (!empty($dupeParams['onbehalf'])) { + unset($dupeParams['onbehalf']); + } + if (!empty($dupeParams['honor'])) { + unset($dupeParams['honor']); + } + + $dedupeParams = CRM_Dedupe_Finder::formatParams($dupeParams, 'Individual'); + $dedupeParams['check_permission'] = FALSE; + $ids = CRM_Dedupe_Finder::dupesByParams($dedupeParams, 'Individual'); + + // if we find more than one contact, use the first one + $contactID = CRM_Utils_Array::value(0, $ids); + + // Fetch default greeting id's if creating a contact + if (!$contactID) { + foreach (CRM_Contact_BAO_Contact::$_greetingTypes as $greeting) { + if (!isset($params[$greeting])) { + $params[$greeting] = CRM_Contact_BAO_Contact_Utils::defaultGreeting('Individual', $greeting); + } + } + } + $contactType = NULL; + } + else { + $contactType = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $contactID, 'contact_type'); + } + $contactID = CRM_Contact_BAO_Contact::createProfileContact( + $params, + $fields, + $contactID, + $addToGroups, + NULL, + $contactType, + TRUE + ); + + // Make the contact ID associated with the contribution available at the Class level. + // Also make available to the session. + //@todo consider handling this in $this->getContactID(); + $this->set('contactID', $contactID); + $this->_contactID = $contactID; + + //get email primary first if exist + $subscriptionEmail = array('email' => CRM_Utils_Array::value('email-Primary', $params)); + if (!$subscriptionEmail['email']) { + $subscriptionEmail['email'] = CRM_Utils_Array::value("email-{$this->_bltID}", $params); + } + // subscribing contact to groups + if (!empty($subscribeGroupIds) && $subscriptionEmail['email']) { + CRM_Mailing_Event_BAO_Subscribe::commonSubscribe($subscribeGroupIds, $subscriptionEmail, $contactID); + } + + // If onbehalf-of-organization contribution / signup, add organization + // and it's location. + if (isset($params['hidden_onbehalf_profile']) && isset($behalfOrganization['organization_name'])) { + $ufFields = array(); + foreach ($this->_fields['onbehalf'] as $name => $value) { + $ufFields[$name] = 1; + } + self::processOnBehalfOrganization($behalfOrganization, $contactID, $this->_values, + $this->_params, $ufFields + ); + } + elseif (!empty($this->_membershipContactID) && $contactID != $this->_membershipContactID) { + // this is an onbehalf renew case for inherited membership. For e.g a permissioned member of household, + // store current user id as related contact for later use for mailing / activity.. + $this->_values['related_contact'] = $contactID; + $this->_params['related_contact'] = $contactID; + // swap contact like we do for on-behalf-org case, so parent/primary membership is affected + $contactID = $this->_membershipContactID; + } + + // lets store the contactID in the session + // for things like tell a friend + $session = CRM_Core_Session::singleton(); + if (!$session->get('userID')) { + $session->set('transaction.userID', $contactID); + } + else { + $session->set('transaction.userID', NULL); + } + + $this->_useForMember = $this->get('useForMember'); + + // store the fact that this is a membership and membership type is selected + $processMembership = FALSE; + if ((!empty($membershipParams['selectMembership']) && + $membershipParams['selectMembership'] != 'no_thanks' + ) || + $this->_useForMember + ) { + $processMembership = TRUE; + + if (!$this->_useForMember) { + $this->assign('membership_assign', TRUE); + $this->set('membershipTypeID', $this->_params['selectMembership']); + } + + if ($this->_action & CRM_Core_Action::PREVIEW) { + $membershipParams['is_test'] = 1; + } + if ($this->_params['is_pay_later']) { + $membershipParams['is_pay_later'] = 1; + } + } + + if ($processMembership) { + CRM_Core_Payment_Form::mapParams($this->_bltID, $this->_params, $membershipParams, TRUE); + + // added new parameter for cms user contact id, needed to distinguish behaviour for on behalf of sign-ups + if (isset($this->_params['related_contact'])) { + $membershipParams['cms_contactID'] = $this->_params['related_contact']; + } + else { + $membershipParams['cms_contactID'] = $contactID; + } + + //inherit campaign from contribution page. + if (!array_key_exists('campaign_id', $membershipParams)) { + $membershipParams['campaign_id'] = CRM_Utils_Array::value('campaign_id', $this->_values); + } + + if (!empty($membershipParams['onbehalf']) && + is_array($membershipParams['onbehalf']) && !empty($membershipParams['onbehalf']['member_campaign_id']) + ) { + $this->_params['campaign_id'] = $membershipParams['onbehalf']['member_campaign_id']; + } + + $customFieldsFormatted = $fieldTypes = array(); + if (!empty($membershipParams['onbehalf']) && + is_array($membershipParams['onbehalf']) + ) { + foreach ($membershipParams['onbehalf'] as $key => $value) { + if (strstr($key, 'custom_')) { + $customFieldId = explode('_', $key); + CRM_Core_BAO_CustomField::formatCustomField( + $customFieldId[1], + $customFieldsFormatted, + $value, + 'Membership', + NULL, + $contactID + ); + } + } + $fieldTypes = array('Contact', 'Organization', 'Membership'); + } + + $priceFieldIds = $this->get('memberPriceFieldIDS'); + + if (!empty($priceFieldIds)) { + $contributionTypeID = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $priceFieldIds['id'], 'financial_type_id'); + unset($priceFieldIds['id']); + $membershipTypeIds = array(); + $membershipTypeTerms = array(); + foreach ($priceFieldIds as $priceFieldId) { + if ($id = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceFieldValue', $priceFieldId, 'membership_type_id')) { + $membershipTypeIds[] = $id; + //@todo the value for $term is immediately overwritten. It is unclear from the code whether it was intentional to + // do this or a double = was intended (this ambiguity is the reason many IDEs complain about 'assignment in condition' + $term = 1; + if ($term = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceFieldValue', $priceFieldId, 'membership_num_terms')) { + $membershipTypeTerms[$id] = ($term > 1) ? $term : 1; + } + else { + $membershipTypeTerms[$id] = 1; + } + } + } + $membershipParams['selectMembership'] = $membershipTypeIds; + $membershipParams['financial_type_id'] = $contributionTypeID; + $membershipParams['types_terms'] = $membershipTypeTerms; + } + if (!empty($membershipParams['selectMembership'])) { + // CRM-12233 + $membershipLineItems = array(); + if ($this->_separateMembershipPayment && $this->_values['amount_block_is_active']) { + foreach ($this->_values['fee'] as $key => $feeValues) { + if ($feeValues['name'] == 'membership_amount') { + $fieldId = $this->_params['price_' . $key]; + $membershipLineItems[$this->_priceSetId][$fieldId] = $this->_lineItem[$this->_priceSetId][$fieldId]; + unset($this->_lineItem[$this->_priceSetId][$fieldId]); + break; + } + } + } + $this->processMembership($membershipParams, $contactID, $customFieldsFormatted, $fieldTypes, $premiumParams, $membershipLineItems, $isPayLater); + if (!$this->_amount > 0.0 || !$membershipParams['amount']) { + // we need to explicitly create a CMS user in case of free memberships + // since it is done under processConfirm for paid memberships + CRM_Contribute_BAO_Contribution_Utils::createCMSUser($membershipParams, + $membershipParams['cms_contactID'], + 'email-' . $this->_bltID + ); + } + } + } + else { + // at this point we've created a contact and stored its address etc + // all the payment processors expect the name and address to be in the + // so we copy stuff over to first_name etc. + $paymentParams = $this->_params; + $contributionTypeId = $this->_values['financial_type_id']; + + $fieldTypes = array(); + if (!empty($paymentParams['onbehalf']) && + is_array($paymentParams['onbehalf']) + ) { + foreach ($paymentParams['onbehalf'] as $key => $value) { + if (strstr($key, 'custom_')) { + $this->_params[$key] = $value; + } + } + $fieldTypes = array('Contact', 'Organization', 'Contribution'); + } + $financialTypeID = $this->wrangleFinancialTypeID($contributionTypeId); + + return CRM_Contribute_BAO_Contribution_Utils::processConfirm($this, $paymentParams, + $premiumParams, $contactID, + $financialTypeID, + 'contribution', + $fieldTypes, + ($this->_mode == 'test') ? 1 : 0, + $isPayLater + ); + } + } + } -- 2.25.1