X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=CRM%2FMember%2FBAO%2FMembership.php;h=a204dd9dafa048b6bad1946f96d5a4e831374176;hb=7e179a1d16c36e5121068378030cfef95b75852b;hp=bd9daf1219bf2bd1db6d5722fbbb2bab99c98245;hpb=0829c6977408ac4bca633cf1ea20f1914d059037;p=civicrm-core.git diff --git a/CRM/Member/BAO/Membership.php b/CRM/Member/BAO/Membership.php index bd9daf1219..a204dd9daf 100644 --- a/CRM/Member/BAO/Membership.php +++ b/CRM/Member/BAO/Membership.php @@ -29,8 +29,6 @@ * * @package CRM * @copyright CiviCRM LLC (c) 2004-2015 - * $Id$ - * */ class CRM_Member_BAO_Membership extends CRM_Member_DAO_Membership { @@ -47,10 +45,6 @@ class CRM_Member_BAO_Membership extends CRM_Member_DAO_Membership { /** * Class constructor. - * - * @return \CRM_Member_DAO_Membership - */ - /** */ public function __construct() { parent::__construct(); @@ -184,8 +178,7 @@ class CRM_Member_BAO_Membership extends CRM_Member_DAO_Membership { } /** - * Given the list of params in the params array, fetch the object - * and store the values in the values array + * Fetch the object and store the values in the values array. * * @param array $params * Input parameters to find object. @@ -194,10 +187,12 @@ class CRM_Member_BAO_Membership extends CRM_Member_DAO_Membership { * @param bool $active * Do you want only active memberships to. * be returned + * @param bool $relatedMemberships * - * @return CRM_Member_BAO_Membership|null the found object or null + * @return CRM_Member_BAO_Membership|null + * The found object or null */ - public static function &getValues(&$params, &$values, $active = FALSE) { + public static function &getValues(&$params, &$values, $active = FALSE, $relatedMemberships = FALSE) { if (empty($params)) { return NULL; } @@ -218,6 +213,9 @@ class CRM_Member_BAO_Membership extends CRM_Member_DAO_Membership { CRM_Core_DAO::storeValues($membership, $values[$membership->id]); $memberships[$membership->id] = $membership; + if ($relatedMemberships && !empty($membership->owner_membership_id)) { + $values['owner_membership_ids'][] = $membership->owner_membership_id; + } } return $memberships; @@ -246,7 +244,8 @@ class CRM_Member_BAO_Membership extends CRM_Member_DAO_Membership { if (empty($params['is_override']) && empty($params['skipStatusCal'])) { $dates = array('start_date', 'end_date', 'join_date'); - $start_date = $end_date = $join_date = NULL; // declare these out of courtesy as IDEs don't pick up the setting of them below + // Declare these out of courtesy as IDEs don't pick up the setting of them below. + $start_date = $end_date = $join_date = NULL; foreach ($dates as $date) { $$date = $params[$date] = CRM_Utils_Date::processDate(CRM_Utils_Array::value($date, $params), NULL, TRUE, 'Ymd'); } @@ -279,8 +278,8 @@ class CRM_Member_BAO_Membership extends CRM_Member_DAO_Membership { } // data cleanup only: all verifications on number of related memberships are done upstream in: - // CRM_Member_BAO_Membership::createRelatedMemberships() - // CRM_Contact_BAO_Relationship::relatedMemberships() + // CRM_Member_BAO_Membership::createRelatedMemberships() + // CRM_Contact_BAO_Relationship::relatedMemberships() if (isset($params['owner_membership_id'])) { unset($params['max_related']); } @@ -404,7 +403,8 @@ class CRM_Member_BAO_Membership extends CRM_Member_DAO_Membership { $url = CRM_Utils_System::url('civicrm/contact/view/membership', "action=view&reset=1&id={$membership->id}&cid={$membership->contact_id}&context=home" ); - if (empty($membership->membership_type_id)) {// ie in an update situation + if (empty($membership->membership_type_id)) { + // ie in an update situation. $membership->find(TRUE); } $membershipTypes = CRM_Member_PseudoConstant::membershipType(); @@ -544,8 +544,7 @@ class CRM_Member_BAO_Membership extends CRM_Member_DAO_Membership { } /** - * - * get membership status and membership type values + * Get membership status and membership type values. * * @param int $membershipId * Membership id of values to return. @@ -590,13 +589,14 @@ INNER JOIN civicrm_membership_type type ON ( type.id = membership.membership_ty /** * Delete membership. + * * Wrapper for most delete calls. Use this unless you JUST want to delete related memberships w/o deleting the parent. * * @param int $membershipId * Membership id that needs to be deleted. * - * - * @return int $results id of deleted Membership on success, false otherwise + * @return int + * Id of deleted Membership on success, false otherwise. */ public static function del($membershipId) { //delete related first and then delete parent. @@ -610,8 +610,8 @@ INNER JOIN civicrm_membership_type type ON ( type.id = membership.membership_ty * @param int $membershipId * Membership id that needs to be deleted. * - * - * @return int $results id of deleted Membership on success, false otherwise + * @return int + * Id of deleted Membership on success, false otherwise. */ public static function deleteMembership($membershipId) { // CRM-12147, retrieve membership data before we delete it for hooks @@ -745,7 +745,6 @@ INNER JOIN civicrm_membership_type type ON ( type.id = membership.membership_ty * * @return bool * Is this a separate membership payment - * */ public static function buildMembershipBlock( &$form, @@ -939,7 +938,6 @@ INNER JOIN civicrm_membership_type type ON ( type.id = membership.membership_ty * Contribution page id. * * @return array|null - * */ public static function getMembershipBlock($pageID) { $membershipBlock = array(); @@ -972,6 +970,7 @@ INNER JOIN civicrm_membership_type type ON ( type.id = membership.membership_ty /** * Return a current membership of given contact. + * * NB: if more than one membership meets criteria, a randomly selected one is returned. * * @param int $contactID @@ -1163,7 +1162,7 @@ INNER JOIN civicrm_membership_type type ON ( type.id = membership.membership_ty /** * Get all exportable fields. * - * @retun array return array of all exportable fields + * @return array return array of all exportable fields */ public static function &exportableFields() { $expFieldMembership = CRM_Member_DAO_Membership::export(); @@ -1185,8 +1184,9 @@ INNER JOIN civicrm_membership_type type ON ( type.id = membership.membership_ty } /** - * Get membership joins/renewals for a specified membership - * type. Specifically, retrieves a count of memberships whose "Membership + * Get membership joins/renewals for a specified membership type. + * + * Specifically, retrieves a count of memberships whose "Membership * Signup" or "Membership Renewal" activity falls in the given date range. * Dates match the pattern "yyyy-mm-dd". * @@ -1241,8 +1241,9 @@ INNER JOIN civicrm_contact contact ON ( contact.id = membership.contact_id AND } /** - * Get a count of membership for a specified membership type, - * optionally for a specified date. The date must have the form yyyy-mm-dd. + * Get a count of membership for a specified membership type, optionally for a specified date. + * + * The date must have the form yyyy-mm-dd. * * If $date is omitted, this function counts as a member anyone whose * membership status_id indicates they're a current member. @@ -1324,12 +1325,12 @@ AND civicrm_membership.is_test = %2"; * @param bool $isPaidMembership * @param array $membershipID * - * @param $isProcessSeparateMembershipTransaction + * @param bool $isProcessSeparateMembershipTransaction * * @param int $defaultContributionTypeID * @param array $membershipLineItems * Line items specific to membership payment that is separate to contribution. - * @param $isPayLater + * @param bool $isPayLater * * @throws \CRM_Core_Exception */ @@ -1339,7 +1340,7 @@ AND civicrm_membership.is_test = %2"; $isProcessSeparateMembershipTransaction, $defaultContributionTypeID, $membershipLineItems, $isPayLater) { $result = $membershipContribution = NULL; $isTest = CRM_Utils_Array::value('is_test', $membershipParams, FALSE); - $errors = $createdMemberships = array(); + $errors = $createdMemberships = $paymentResult = array(); //@todo move this into the calling function & pass in the correct financialTypeID if (isset($paymentParams['financial_type'])) { @@ -1354,7 +1355,12 @@ AND civicrm_membership.is_test = %2"; } if ($isPaidMembership) { - $result = CRM_Contribute_BAO_Contribution_Utils::processConfirm($form, $membershipParams, + 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', @@ -1363,20 +1369,27 @@ AND civicrm_membership.is_test = %2"; $isPayLater ); if (is_a($result[1], 'CRM_Core_Error')) { - $errors[1] = CRM_Core_Error::getMessages($result[1]); + $errors[1] = CRM_Core_Error::getMessages($paymentResult[1]); } - elseif (!empty($result[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'] = $result[1]->id; - //note that this will be over-written if we are using a separate membership transaction. Otherwise there is only one - $membershipContribution = $result[1]; + $form->_values['contribution_other_id'] = $membershipContribution->id; } } if ($isProcessSeparateMembershipTransaction) { try { - $lineItems = $form->_lineItem = $membershipLineItems; + $form->_lineItem = $membershipLineItems; + if (empty($form->_params['auto_renew']) && !empty($membershipParams['is_recur'])) { + unset($membershipParams['is_recur']); + } $membershipContribution = self::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) { @@ -1430,7 +1443,6 @@ AND civicrm_membership.is_test = %2"; foreach ($createdMemberships as $createdMembership) { CRM_Core_BAO_CustomValueTable::postProcess( $form->_params, - CRM_Core_DAO::$_nullArray, 'civicrm_membership', $createdMembership->id, 'Membership' @@ -1443,7 +1455,7 @@ AND civicrm_membership.is_test = %2"; } //CRM-15232: Check if membership is created and on the basis of it use - //membership reciept template to send payment reciept + //membership receipt template to send payment receipt if (count($createdMemberships)) { $form->_values['isMembership'] = TRUE; } @@ -1461,14 +1473,13 @@ AND civicrm_membership.is_test = %2"; $form->_values['contribution_id'] = $membershipContributionID; } - // Do not send an email if Recurring transaction is done via Direct Mode - // Email will we sent when the IPN is received. - if (!empty($form->_params['is_recur']) && $form->_contributeMode == 'direct') { - if (!empty($membershipContribution->trxn_id)) { + if ($form->_contributeMode == 'direct') { + if (CRM_Utils_Array::value('contribution_status_id', $paymentResult) == 1) { try { civicrm_api3('contribution', 'completetransaction', array( - 'id' => $membershipContribution->id, - 'trxn_id' => $membershipContribution->trxn_id, + 'id' => $paymentResult['contribution']->id, + 'trxn_id' => $paymentResult['contribution']->trxn_id, + 'is_transactional' => FALSE, )); } catch (CiviCRM_API3_Exception $e) { @@ -1489,12 +1500,10 @@ AND civicrm_membership.is_test = %2"; } /** - * Function for updating a membership record's contribution_recur_id + * Function for updating a membership record's contribution_recur_id. * * @param CRM_Member_DAO_Membership $membership * @param \CRM_Contribute_BAO_Contribution|\CRM_Contribute_DAO_Contribution $contribution - * - * @return void */ static public function updateRecurMembership(CRM_Member_DAO_Membership $membership, CRM_Contribute_BAO_Contribution $contribution) { @@ -1512,8 +1521,10 @@ AND civicrm_membership.is_test = %2"; } /** + * A wrapper for renewing memberships from a form. + * * @deprecated - * A wrapper for renewing memberships from a form - including the form in the membership processing adds complexity + * - including the form in the membership processing adds complexity * as the forms are being forced to pretend similarity * Try to call the renewMembership directly * @todo - this form method needs to have the interaction with the form layer removed from it @@ -1541,19 +1552,24 @@ AND civicrm_membership.is_test = %2"; * @param int $membershipID * Membership ID, this should always be passed in & optionality should be removed. * - * @throws CRM_Core_Exception + * @param bool $isPending + * Is the transaction pending. We are working towards this ALWAYS being true and completion being done + * in the complete transaction function, called by all types of payment processor (removing assumptions + * about what they do & always doing a pending + a complete at the appropriate time). * + * @return CRM_Member_BAO_Membership|CRM_Core_Error */ public static function renewMembershipFormWrapper( $contactID, $membershipTypeID, $is_test, &$form, - $changeToday = NULL, - $modifiedID = NULL, - $customFieldsFormatted = NULL, - $numRenewTerms = 1, - $membershipID = NULL + $changeToday, + $modifiedID, + $customFieldsFormatted, + $numRenewTerms, + $membershipID, + $isPending ) { $statusFormat = '%Y-%m-%d'; $format = '%Y%m%d'; @@ -1569,8 +1585,10 @@ AND civicrm_membership.is_test = %2"; $membershipTypeDetails = CRM_Member_BAO_MembershipType::getMembershipTypeDetails($membershipTypeID); // check is it pending. - CRM-4555 - list($pending, $contributionRecurID, $changeToday, $membershipSource, $isPayLater, $campaignId) = self::extractFormValues($form, $changeToday, $membershipTypeDetails); - list($membership, $renewalMode, $dates) = self::renewMembership($contactID, $membershipTypeID, $is_test, $changeToday, $modifiedID, $customFieldsFormatted, $numRenewTerms, $membershipID, $pending, $allStatus, $membershipTypeDetails, $contributionRecurID, $format, $membershipSource, $ids, $statusFormat, $isPayLater, $campaignId); + list($contributionRecurID, $changeToday, $membershipSource, $isPayLater, $campaignId) = self::extractFormValues($form, $changeToday); + list($membership, $renewalMode, $dates) = self::renewMembership($contactID, $membershipTypeID, $is_test, + $changeToday, $modifiedID, $customFieldsFormatted, $numRenewTerms, $membershipID, $isPending, $allStatus, + $membershipTypeDetails, $contributionRecurID, $format, $membershipSource, $ids, $statusFormat, $isPayLater, $campaignId); $form->set('renewal_mode', $renewalMode); if (!empty($dates)) { $form->assign('mem_start_date', @@ -1599,8 +1617,6 @@ AND civicrm_membership.is_test = %2"; * Array of month, day, year. * values in case today needs * to be customised, null otherwise - * - * @return void */ public static function fixMembershipStatusBeforeRenew(&$currentMembership, $changeToday) { $today = NULL; @@ -1662,7 +1678,7 @@ AND civicrm_membership.is_test = %2"; $format ), 'membership_type_id' => $currentMembership['membership_type_id'], - 'max_related' => $currentMembership['max_related'], + 'max_related' => CRM_Utils_Array::value('max_related', $currentMembership, 0), ); $session = CRM_Core_Session::singleton(); @@ -1725,6 +1741,7 @@ SELECT c.contribution_page_id as pageID /** * Get list of membership fields for profile. + * * For now we only allow custom membership fields to be in * profile * @@ -1771,16 +1788,19 @@ WHERE civicrm_membership.contact_id = civicrm_contact.id } /** - * Create memberships for related contacts. - * takes into account the maximum related memberships + * Create memberships for related contacts, taking into account the maximum related memberships. * * @param array $params * Array of key - value pairs. * @param CRM_Core_DAO $dao * Membership object. * - * @return null|array - * array of memberships if created + * @param bool $reset + * + * @return array|null + * Membership details, if created. + * + * @throws \CRM_Core_Exception */ public static function createRelatedMemberships(&$params, &$dao, $reset = FALSE) { static $relatedContactIds = array(); @@ -1872,7 +1892,8 @@ WHERE civicrm_membership.contact_id = civicrm_contact.id unset($params['max_related']); // Number of inherited memberships available - NULL is interpreted as unlimited, '0' as none $available = ($membership->max_related == NULL ? PHP_INT_MAX : $membership->max_related); - $queue = array(); // will be used to queue potential memberships to be created + // will be used to queue potential memberships to be created. + $queue = array(); foreach ($relatedContacts as $contactId => $relationshipStatus) { //use existing membership record. @@ -2050,8 +2071,7 @@ FROM civicrm_membership_type } /** - * Check whether payment processor supports - * cancellation of membership subscription + * Check whether payment processor supports cancellation of membership subscription. * * @param int $mid * Membership id. @@ -2107,8 +2127,9 @@ LEFT JOIN civicrm_membership mem ON ( cr.id = mem.contribution_recur_id ) } /** - * Get membership joins for a specified membership - * type. Specifically, retrieves a count of still current memberships whose + * Get membership joins for a specified membership type. + * + * Specifically, retrieves a count of still current memberships whose * join_date and start_date are within a specified date range. Dates match * the pattern "yyyy-mm-dd". * @@ -2159,8 +2180,9 @@ INNER JOIN civicrm_contact contact ON ( contact.id = membership.contact_id AND } /** - * Get membership renewals for a specified membership - * type. Specifically, retrieves a count of still current memberships + * Get membership renewals for a specified membership type. + * + * Specifically, retrieves a count of still current memberships * whose join_date is before and start_date is within a specified date * range. Dates match the pattern "yyyy-mm-dd". * @@ -2215,7 +2237,7 @@ INNER JOIN civicrm_contact contact ON ( contact.id = membership.contact_id AND * @param int $contactID * @param CRM_Contribute_Form_Contribution_Confirm $form * @param array $tempParams - * @param $isTest + * @param bool $isTest * @param array $lineItems * @param $minimumFee * @param int $financialTypeID @@ -2268,14 +2290,18 @@ INNER JOIN civicrm_contact contact ON ( contact.id = membership.contact_id AND // irrespective of the value, CRM-2888 $tempParams['cms_create_account'] = 0; - $pending = $form->_params['is_pay_later'] ? (($minimumFee > 0.0) ? TRUE : FALSE) : FALSE; + //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::processContribution($form, + $membershipContribution = CRM_Contribute_Form_Contribution_Confirm::processFormContribution($form, $tempParams, $result, $contactID, @@ -2283,7 +2309,8 @@ INNER JOIN civicrm_contact contact ON ( contact.id = membership.contact_id AND $pending, TRUE, $isTest, - $lineItems + $lineItems, + $form->_bltID ); return $membershipContribution; } @@ -2307,19 +2334,24 @@ INNER JOIN civicrm_contact contact ON ( contact.id = membership.contact_id AND * @param $customFieldsFormatted * @param int $membershipID * @param $memType - * @param $isTest - * @param $numTerms + * @param bool $isTest + * @param int $numTerms * @param $membershipContribution * @param CRM_Core_Form $form * * @return array */ public static function createOrRenewMembership($membershipParams, $contactID, $customFieldsFormatted, $membershipID, $memType, $isTest, $numTerms, $membershipContribution, &$form) { + if (!empty($membershipContribution)) { + $pendingStatus = CRM_Core_OptionGroup::getValue('contribution_status', 'Pending', 'name'); + $pending = ($membershipContribution->contribution_status_id == $pendingStatus) ? TRUE : FALSE; + } $membership = self::renewMembershipFormWrapper($contactID, $memType, $isTest, $form, NULL, CRM_Utils_Array::value('cms_contactID', $membershipParams), $customFieldsFormatted, $numTerms, - $membershipID + $membershipID, + self::extractPendingFormValue($form, $memType, $pending) ); if (!empty($membershipContribution)) { @@ -2348,30 +2380,43 @@ INNER JOIN civicrm_contact contact ON ( contact.id = membership.contact_id AND } /** - * Extract relevant values from the form so we can separate form logic from BAO logcis. + * Determine if the form has a pending status. + * + * This is an interim refactoring step. This information should be extracted at the form layer. + * + * @deprecated * * @param CRM_Core_Form $form - * @param $changeToday - * @param $membershipTypeDetails + * @param int $membershipID * - * @return array + * @return bool */ - public static function extractFormValues($form, $changeToday, $membershipTypeDetails) { - $pending = FALSE; + public static function extractPendingFormValue($form, $membershipID, $pending = FALSE) { + $membershipTypeDetails = CRM_Member_BAO_MembershipType::getMembershipTypeDetails($membershipID); //@todo this is a BAO function & should not inspect the form - the form should do this // & pass required params to the BAO if (CRM_Utils_Array::value('minimum_fee', $membershipTypeDetails) > 0.0) { - if (((isset($form->_contributeMode) && $form->_contributeMode == 'notify') || !empty($form->_params['is_pay_later']) || - (!empty($form->_params['is_recur']) && $form->_contributeMode == 'direct' - ) + if (((isset($form->_contributeMode) && $form->_contributeMode == 'notify') || !empty($form->_params['is_pay_later']) ) && - (($form->_values['is_monetary'] && $form->_amount > 0.0) || !empty($form->_params['separate_membership_payment']) || + (($form->_values['is_monetary'] && $form->_amount > 0.0) || CRM_Utils_Array::value('record_contribution', $form->_params) ) ) { $pending = TRUE; } } + return $pending; + } + + /** + * Extract relevant values from the form so we can separate form logic from BAO logcis. + * + * @param CRM_Core_Form $form + * @param $changeToday + * + * @return array + */ + public static function extractFormValues($form, $changeToday) { $contributionRecurID = isset($form->_params['contributionRecurID']) ? $form->_params['contributionRecurID'] : NULL; //we renew expired membership, CRM-6277 @@ -2402,7 +2447,7 @@ INNER JOIN civicrm_contact contact ON ( contact.id = membership.contact_id AND $campaignId = CRM_Utils_Array::value('campaign_id', $form->_values); } } - return array($pending, $contributionRecurID, $changeToday, $membershipSource, $isPayLater, $campaignId); + return array($contributionRecurID, $changeToday, $membershipSource, $isPayLater, $campaignId); } /** @@ -2661,9 +2706,7 @@ INNER JOIN civicrm_contact contact ON ( contact.id = membership.contact_id AND * Process price set and line items. * * @param int $membershipId - * @param $lineItem - * - * @return void + * @param array $lineItem */ public function processPriceSet($membershipId, $lineItem) { //FIXME : need to move this too