CRM-21050, fixed code to set receive date with correct timestamp
[civicrm-core.git] / CRM / Member / Form / Membership.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.7 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2017 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26 */
27
28 /**
29 *
30 * @package CRM
31 * @copyright CiviCRM LLC (c) 2004-2017
32 */
33
34 /**
35 * This class generates form components for offline membership form.
36 */
37 class CRM_Member_Form_Membership extends CRM_Member_Form {
38
39 protected $_memType = NULL;
40
41 protected $_onlinePendingContributionId;
42
43 public $_mode;
44
45 public $_contributeMode = 'direct';
46
47 protected $_recurMembershipTypes;
48
49 protected $_memTypeSelected;
50
51 /**
52 * Display name of the member.
53 *
54 * @var string
55 */
56 protected $_memberDisplayName = NULL;
57
58 /**
59 * email of the person paying for the membership (used for receipts)
60 */
61 protected $_memberEmail = NULL;
62
63 /**
64 * Contact ID of the member.
65 *
66 * @var int
67 */
68 public $_contactID = NULL;
69
70 /**
71 * Display name of the person paying for the membership (used for receipts)
72 *
73 * @var string
74 */
75 protected $_contributorDisplayName = NULL;
76
77 /**
78 * email of the person paying for the membership (used for receipts)
79 */
80 protected $_contributorEmail = NULL;
81
82 /**
83 * email of the person paying for the membership (used for receipts)
84 *
85 * @var int
86 */
87 protected $_contributorContactID = NULL;
88
89 /**
90 * ID of the person the receipt is to go to.
91 *
92 * @var int
93 */
94 protected $_receiptContactId = NULL;
95
96 /**
97 * Keep a class variable for ALL membership IDs so
98 * postProcess hook function can do something with it
99 *
100 * @var array
101 */
102 protected $_membershipIDs = array();
103
104 /**
105 * An array to hold a list of date fields on the form
106 * so that they can be converted to ISO in a consistent manner
107 *
108 * @var array
109 */
110 protected $_dateFields = array(
111 'receive_date' => array('default' => 'now'),
112 );
113
114 /**
115 * Get selected membership type from the form values.
116 *
117 * @param array $priceSet
118 * @param array $params
119 *
120 * @return array
121 */
122 public static function getSelectedMemberships($priceSet, $params) {
123 $memTypeSelected = array();
124 $priceFieldIDS = self::getPriceFieldIDs($params, $priceSet);
125 if (isset($params['membership_type_id']) && !empty($params['membership_type_id'][1])) {
126 $memTypeSelected = array($params['membership_type_id'][1] => $params['membership_type_id'][1]);
127 }
128 else {
129 foreach ($priceFieldIDS as $priceFieldId) {
130 if ($id = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceFieldValue', $priceFieldId, 'membership_type_id')) {
131 $memTypeSelected[$id] = $id;
132 }
133 }
134 }
135 return $memTypeSelected;
136 }
137
138 /**
139 * Extract price set fields and values from $params.
140 *
141 * @param array $params
142 * @param array $priceSet
143 *
144 * @return array
145 */
146 public static function getPriceFieldIDs($params, $priceSet) {
147 $priceFieldIDS = array();
148 if (isset($priceSet['fields']) && is_array($priceSet['fields'])) {
149 foreach ($priceSet['fields'] as $fieldId => $field) {
150 if (!empty($params['price_' . $fieldId])) {
151 if (is_array($params['price_' . $fieldId])) {
152 foreach ($params['price_' . $fieldId] as $priceFldVal => $isSet) {
153 if ($isSet) {
154 $priceFieldIDS[] = $priceFldVal;
155 }
156 }
157 }
158 elseif (!$field['is_enter_qty']) {
159 $priceFieldIDS[] = $params['price_' . $fieldId];
160 }
161 }
162 }
163 }
164 return $priceFieldIDS;
165 }
166
167 /**
168 * Form preProcess function.
169 *
170 * @throws \Exception
171 */
172 public function preProcess() {
173 // This string makes up part of the class names, differentiating them (not sure why) from the membership fields.
174 $this->assign('formClass', 'membership');
175 parent::preProcess();
176 // get price set id.
177 $this->_priceSetId = CRM_Utils_Array::value('priceSetId', $_GET);
178 $this->set('priceSetId', $this->_priceSetId);
179 $this->assign('priceSetId', $this->_priceSetId);
180
181 if ($this->_action & CRM_Core_Action::DELETE) {
182 $contributionID = CRM_Member_BAO_Membership::getMembershipContributionId($this->_id);
183 // check delete permission for contribution
184 if ($this->_id && $contributionID && !CRM_Core_Permission::checkActionPermission('CiviContribute', $this->_action)) {
185 CRM_Core_Error::fatal(ts("This Membership is linked to a contribution. You must have 'delete in CiviContribute' permission in order to delete this record."));
186 }
187 }
188
189 if ($this->_action & CRM_Core_Action::ADD) {
190 if ($this->_contactID) {
191 //check whether contact has a current membership so we can alert user that they may want to do a renewal instead
192 $contactMemberships = array();
193 $memParams = array('contact_id' => $this->_contactID);
194 CRM_Member_BAO_Membership::getValues($memParams, $contactMemberships, TRUE);
195 $cMemTypes = array();
196 foreach ($contactMemberships as $mem) {
197 $cMemTypes[] = $mem['membership_type_id'];
198 }
199 if (count($cMemTypes) > 0) {
200 $memberorgs = CRM_Member_BAO_MembershipType::getMemberOfContactByMemTypes($cMemTypes);
201 $mems_by_org = array();
202 foreach ($contactMemberships as $mem) {
203 $mem['member_of_contact_id'] = CRM_Utils_Array::value($mem['membership_type_id'], $memberorgs);
204 if (!empty($mem['membership_end_date'])) {
205 $mem['membership_end_date'] = CRM_Utils_Date::customformat($mem['membership_end_date']);
206 }
207 $mem['membership_type'] = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_MembershipType',
208 $mem['membership_type_id'],
209 'name', 'id'
210 );
211 $mem['membership_status'] = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_MembershipStatus',
212 $mem['status_id'],
213 'label', 'id'
214 );
215 $mem['renewUrl'] = CRM_Utils_System::url('civicrm/contact/view/membership',
216 "reset=1&action=renew&cid={$this->_contactID}&id={$mem['id']}&context=membership&selectedChild=member"
217 . ($this->_mode ? '&mode=live' : '')
218 );
219 $mem['membershipTab'] = CRM_Utils_System::url('civicrm/contact/view',
220 "reset=1&force=1&cid={$this->_contactID}&selectedChild=member"
221 );
222 $mems_by_org[$mem['member_of_contact_id']] = $mem;
223 }
224 $this->assign('existingContactMemberships', $mems_by_org);
225 }
226 }
227 else {
228 // In standalone mode we don't have a contact id yet so lookup will be done client-side with this script:
229 $resources = CRM_Core_Resources::singleton();
230 $resources->addScriptFile('civicrm', 'templates/CRM/Member/Form/MembershipStandalone.js');
231 $passthru = array(
232 'typeorgs' => CRM_Member_BAO_MembershipType::getMembershipTypeOrganization(),
233 'memtypes' => CRM_Core_PseudoConstant::get('CRM_Member_BAO_Membership', 'membership_type_id'),
234 'statuses' => CRM_Core_PseudoConstant::get('CRM_Member_BAO_Membership', 'status_id'),
235 );
236 $resources->addSetting(array('existingMems' => $passthru));
237 }
238 }
239
240 if (!$this->_memType) {
241 $params = CRM_Utils_Request::exportValues();
242 if (!empty($params['membership_type_id'][1])) {
243 $this->_memType = $params['membership_type_id'][1];
244 }
245 }
246 // when custom data is included in this page
247 if (!empty($_POST['hidden_custom'])) {
248 CRM_Custom_Form_CustomData::preProcess($this, NULL, $this->_memType, 1, 'Membership', $this->_id);
249 CRM_Custom_Form_CustomData::buildQuickForm($this);
250 CRM_Custom_Form_CustomData::setDefaultValues($this);
251 }
252
253 // CRM-4395, get the online pending contribution id.
254 $this->_onlinePendingContributionId = NULL;
255 if (!$this->_mode && $this->_id && ($this->_action & CRM_Core_Action::UPDATE)) {
256 $this->_onlinePendingContributionId = CRM_Contribute_BAO_Contribution::checkOnlinePendingContribution($this->_id,
257 'Membership'
258 );
259 }
260 $this->assign('onlinePendingContributionId', $this->_onlinePendingContributionId);
261
262 $this->setPageTitle(ts('Membership'));
263 }
264
265 /**
266 * Set default values for the form.
267 */
268 public function setDefaultValues() {
269
270 if ($this->_priceSetId) {
271 return CRM_Price_BAO_PriceSet::setDefaultPriceSet($this, $defaults);
272 }
273
274 $defaults = parent::setDefaultValues();
275
276 //setting default join date and receive date
277 list($now, $currentTime) = CRM_Utils_Date::setDateDefaults();
278 if ($this->_action == CRM_Core_Action::ADD) {
279 $defaults['receive_date'] = $now;
280 $defaults['receive_date_time'] = $currentTime;
281 }
282
283 $defaults['num_terms'] = 1;
284
285 if (!empty($defaults['id'])) {
286 if ($this->_onlinePendingContributionId) {
287 $defaults['record_contribution'] = $this->_onlinePendingContributionId;
288 }
289 else {
290 $contributionId = CRM_Core_DAO::singleValueQuery("
291 SELECT contribution_id
292 FROM civicrm_membership_payment
293 WHERE membership_id = $this->_id
294 ORDER BY contribution_id
295 DESC limit 1");
296
297 if ($contributionId) {
298 $defaults['record_contribution'] = $contributionId;
299 }
300 }
301 }
302
303 //set Soft Credit Type to Gift by default
304 $scTypes = CRM_Core_OptionGroup::values("soft_credit_type");
305 $defaults['soft_credit_type_id'] = CRM_Utils_Array::value(ts('Gift'), array_flip($scTypes));
306
307 if (!empty($defaults['record_contribution']) && !$this->_mode) {
308 $contributionParams = array('id' => $defaults['record_contribution']);
309 $contributionIds = array();
310
311 //keep main object campaign in hand.
312 $memberCampaignId = CRM_Utils_Array::value('campaign_id', $defaults);
313
314 CRM_Contribute_BAO_Contribution::getValues($contributionParams, $defaults, $contributionIds);
315
316 //get back original object campaign id.
317 $defaults['campaign_id'] = $memberCampaignId;
318
319 if (!empty($defaults['receive_date'])) {
320 list($defaults['receive_date']) = CRM_Utils_Date::setDateDefaults($defaults['receive_date']);
321 }
322
323 // Contribution::getValues() over-writes the membership record's source field value - so we need to restore it.
324 if (!empty($defaults['membership_source'])) {
325 $defaults['source'] = $defaults['membership_source'];
326 }
327 }
328 //CRM-13420
329 if (empty($defaults['payment_instrument_id'])) {
330 $defaults['payment_instrument_id'] = key(CRM_Core_OptionGroup::values('payment_instrument', FALSE, FALSE, FALSE, 'AND is_default = 1'));
331 }
332
333 // User must explicitly choose to send a receipt in both add and update mode.
334 $defaults['send_receipt'] = 0;
335
336 if ($this->_action & CRM_Core_Action::UPDATE) {
337 // in this mode by default uncheck this checkbox
338 unset($defaults['record_contribution']);
339 }
340
341 $subscriptionCancelled = FALSE;
342 if (!empty($defaults['id'])) {
343 $subscriptionCancelled = CRM_Member_BAO_Membership::isSubscriptionCancelled($this->_id);
344 }
345
346 $alreadyAutoRenew = FALSE;
347 if (!empty($defaults['contribution_recur_id']) && !$subscriptionCancelled) {
348 $defaults['auto_renew'] = 1;
349 $alreadyAutoRenew = TRUE;
350 }
351 $this->assign('alreadyAutoRenew', $alreadyAutoRenew);
352
353 $this->assign('member_is_test', CRM_Utils_Array::value('member_is_test', $defaults));
354
355 $this->assign('membership_status_id', CRM_Utils_Array::value('status_id', $defaults));
356
357 if (!empty($defaults['is_pay_later'])) {
358 $this->assign('is_pay_later', TRUE);
359 }
360 if ($this->_mode) {
361 $defaults = $this->getBillingDefaults($defaults);
362 // hack to simplify credit card entry for testing
363 // $defaults['credit_card_type'] = 'Visa';
364 // $defaults['credit_card_number'] = '4807731747657838';
365 // $defaults['cvv2'] = '000';
366 // $defaults['credit_card_exp_date'] = array( 'Y' => '2012', 'M' => '05' );
367 }
368
369 $dates = array('join_date', 'start_date', 'end_date');
370 foreach ($dates as $key) {
371 if (!empty($defaults[$key])) {
372 list($defaults[$key]) = CRM_Utils_Date::setDateDefaults(CRM_Utils_Array::value($key, $defaults));
373 }
374 }
375
376 //setting default join date if there is no join date
377 if (empty($defaults['join_date'])) {
378 $defaults['join_date'] = $now;
379 }
380
381 if (!empty($defaults['membership_end_date'])) {
382 $this->assign('endDate', $defaults['membership_end_date']);
383 }
384
385 return $defaults;
386 }
387
388 /**
389 * Build the form object.
390 */
391 public function buildQuickForm() {
392
393 $this->assign('taxRates', json_encode(CRM_Core_PseudoConstant::getTaxRates()));
394
395 $this->assign('currency', CRM_Core_Config::singleton()->defaultCurrencySymbol);
396 $invoiceSettings = Civi::settings()->get('contribution_invoice_settings');
397 $invoicing = CRM_Utils_Array::value('invoicing', $invoiceSettings);
398 if (isset($invoicing)) {
399 $this->assign('taxTerm', CRM_Utils_Array::value('tax_term', $invoiceSettings));
400 }
401 // build price set form.
402 $buildPriceSet = FALSE;
403 if ($this->_priceSetId || !empty($_POST['price_set_id'])) {
404 if (!empty($_POST['price_set_id'])) {
405 $buildPriceSet = TRUE;
406 }
407 $getOnlyPriceSetElements = TRUE;
408 if (!$this->_priceSetId) {
409 $this->_priceSetId = $_POST['price_set_id'];
410 $getOnlyPriceSetElements = FALSE;
411 }
412
413 $this->set('priceSetId', $this->_priceSetId);
414 CRM_Price_BAO_PriceSet::buildPriceSet($this);
415
416 $optionsMembershipTypes = array();
417 foreach ($this->_priceSet['fields'] as $pField) {
418 if (empty($pField['options'])) {
419 continue;
420 }
421 foreach ($pField['options'] as $opId => $opValues) {
422 $optionsMembershipTypes[$opId] = CRM_Utils_Array::value('membership_type_id', $opValues, 0);
423 }
424 }
425
426 $this->assign('autoRenewOption', CRM_Price_BAO_PriceSet::checkAutoRenewForPriceSet($this->_priceSetId));
427
428 $this->assign('optionsMembershipTypes', $optionsMembershipTypes);
429 $this->assign('contributionType', CRM_Utils_Array::value('financial_type_id', $this->_priceSet));
430
431 // get only price set form elements.
432 if ($getOnlyPriceSetElements) {
433 return;
434 }
435 }
436
437 // use to build form during form rule.
438 $this->assign('buildPriceSet', $buildPriceSet);
439
440 if ($this->_action & CRM_Core_Action::ADD) {
441 $buildPriceSet = FALSE;
442 $priceSets = CRM_Price_BAO_PriceSet::getAssoc(FALSE, 'CiviMember');
443 if (!empty($priceSets)) {
444 $buildPriceSet = TRUE;
445 }
446
447 if ($buildPriceSet) {
448 $this->add('select', 'price_set_id', ts('Choose price set'),
449 array(
450 '' => ts('Choose price set'),
451 ) + $priceSets,
452 NULL, array('onchange' => "buildAmount( this.value );")
453 );
454 }
455 $this->assign('hasPriceSets', $buildPriceSet);
456 }
457
458 //need to assign custom data type and subtype to the template
459 $this->assign('customDataType', 'Membership');
460 $this->assign('customDataSubType', $this->_memType);
461 $this->assign('entityID', $this->_id);
462
463 if ($this->_action & CRM_Core_Action::DELETE) {
464 $this->addButtons(array(
465 array(
466 'type' => 'next',
467 'name' => ts('Delete'),
468 'spacing' => '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;',
469 'isDefault' => TRUE,
470 ),
471 array(
472 'type' => 'cancel',
473 'name' => ts('Cancel'),
474 ),
475 ));
476 return;
477 }
478
479 if ($this->_context == 'standalone') {
480 $this->addEntityRef('contact_id', ts('Contact'), array(
481 'create' => TRUE,
482 'api' => array('extra' => array('email')),
483 ), TRUE);
484 }
485
486 $selOrgMemType[0][0] = $selMemTypeOrg[0] = ts('- select -');
487
488 // Throw status bounce when no Membership type or priceset is present
489 if (CRM_Financial_BAO_FinancialType::isACLFinancialTypeStatus()
490 && empty($this->allMembershipTypeDetails) && empty($priceSets)
491 ) {
492 CRM_Core_Error::statusBounce(ts('You do not have all the permissions needed for this page.'));
493 }
494 // retrieve all memberships
495 $allMembershipInfo = array();
496 foreach ($this->allMembershipTypeDetails as $key => $values) {
497 if ($this->_mode && empty($values['minimum_fee'])) {
498 continue;
499 }
500 else {
501 $memberOfContactId = CRM_Utils_Array::value('member_of_contact_id', $values);
502 if (empty($selMemTypeOrg[$memberOfContactId])) {
503 $selMemTypeOrg[$memberOfContactId] = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact',
504 $memberOfContactId,
505 'display_name',
506 'id'
507 );
508
509 $selOrgMemType[$memberOfContactId][0] = ts('- select -');
510 }
511 if (empty($selOrgMemType[$memberOfContactId][$key])) {
512 $selOrgMemType[$memberOfContactId][$key] = CRM_Utils_Array::value('name', $values);
513 }
514 }
515 $totalAmount = CRM_Utils_Array::value('minimum_fee', $values);
516 //CRM-18827 - override the default value if total_amount is submitted
517 if (!empty($this->_submitValues['total_amount'])) {
518 $totalAmount = $this->_submitValues['total_amount'];
519 }
520 // build membership info array, which is used when membership type is selected to:
521 // - set the payment information block
522 // - set the max related block
523 $allMembershipInfo[$key] = array(
524 'financial_type_id' => CRM_Utils_Array::value('financial_type_id', $values),
525 'total_amount' => CRM_Utils_Money::format($totalAmount, NULL, '%a'),
526 'total_amount_numeric' => $totalAmount,
527 'auto_renew' => CRM_Utils_Array::value('auto_renew', $values),
528 'has_related' => isset($values['relationship_type_id']),
529 'max_related' => CRM_Utils_Array::value('max_related', $values),
530 );
531 }
532
533 $this->assign('allMembershipInfo', json_encode($allMembershipInfo));
534
535 // show organization by default, if only one organization in
536 // the list
537 if (count($selMemTypeOrg) == 2) {
538 unset($selMemTypeOrg[0], $selOrgMemType[0][0]);
539 }
540 //sort membership organization and type, CRM-6099
541 natcasesort($selMemTypeOrg);
542 foreach ($selOrgMemType as $index => $orgMembershipType) {
543 natcasesort($orgMembershipType);
544 $selOrgMemType[$index] = $orgMembershipType;
545 }
546
547 $memTypeJs = array(
548 'onChange' => "buildMaxRelated(this.value,true); CRM.buildCustomData('Membership', this.value);",
549 );
550
551 if (!empty($this->_recurPaymentProcessors)) {
552 $memTypeJs['onChange'] = "" . $memTypeJs['onChange'] . "buildAutoRenew(this.value, null, '{$this->_mode}');";
553 }
554
555 $this->add('text', 'max_related', ts('Max related'),
556 CRM_Core_DAO::getAttribute('CRM_Member_DAO_Membership', 'max_related')
557 );
558
559 $sel = &$this->addElement('hierselect',
560 'membership_type_id',
561 ts('Membership Organization and Type'),
562 $memTypeJs
563 );
564
565 $sel->setOptions(array($selMemTypeOrg, $selOrgMemType));
566 $elements = array();
567 if ($sel) {
568 $elements[] = $sel;
569 }
570
571 $this->applyFilter('__ALL__', 'trim');
572
573 if ($this->_action & CRM_Core_Action::ADD) {
574 $this->add('text', 'num_terms', ts('Number of Terms'), array('size' => 6));
575 }
576
577 $this->addDate('join_date', ts('Member Since'), FALSE, array('formatType' => 'activityDate'));
578 $this->addDate('start_date', ts('Start Date'), FALSE, array('formatType' => 'activityDate'));
579 $endDate = $this->addDate('end_date', ts('End Date'), FALSE, array('formatType' => 'activityDate'));
580 if ($endDate) {
581 $elements[] = $endDate;
582 }
583
584 $this->add('text', 'source', ts('Source'),
585 CRM_Core_DAO::getAttribute('CRM_Member_DAO_Membership', 'source')
586 );
587
588 //CRM-7362 --add campaigns.
589 $campaignId = NULL;
590 if ($this->_id) {
591 $campaignId = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_Membership', $this->_id, 'campaign_id');
592 }
593 CRM_Campaign_BAO_Campaign::addCampaign($this, $campaignId);
594
595 if (!$this->_mode) {
596 $this->add('select', 'status_id', ts('Membership Status'),
597 array('' => ts('- select -')) + CRM_Member_PseudoConstant::membershipStatus(NULL, NULL, 'label')
598 );
599 $statusOverride = $this->addElement('checkbox', 'is_override',
600 ts('Status Override?'), NULL,
601 array('onClick' => 'showHideMemberStatus()')
602 );
603 if ($statusOverride) {
604 $elements[] = $statusOverride;
605 }
606
607 $this->addElement('checkbox', 'record_contribution', ts('Record Membership Payment?'));
608
609 $this->add('text', 'total_amount', ts('Amount'));
610 $this->addRule('total_amount', ts('Please enter a valid amount.'), 'money');
611
612 $this->addDate('receive_date', ts('Received'), FALSE, array('formatType' => 'activityDateTime'));
613
614 $this->add('select', 'payment_instrument_id',
615 ts('Payment Method'),
616 array('' => ts('- select -')) + CRM_Contribute_PseudoConstant::paymentInstrument(),
617 FALSE, array('onChange' => "return showHideByValue('payment_instrument_id','4','checkNumber','table-row','select',false);")
618 );
619 $this->add('text', 'trxn_id', ts('Transaction ID'));
620 $this->addRule('trxn_id', ts('Transaction ID already exists in Database.'),
621 'objectExists', array(
622 'CRM_Contribute_DAO_Contribution',
623 $this->_id,
624 'trxn_id',
625 )
626 );
627
628 $this->add('select', 'contribution_status_id',
629 ts('Payment Status'), CRM_Contribute_BAO_Contribution_Utils::getContributionStatuses('membership')
630 );
631 $this->add('text', 'check_number', ts('Check Number'),
632 CRM_Core_DAO::getAttribute('CRM_Contribute_DAO_Contribution', 'check_number')
633 );
634 }
635 else {
636 //add field for amount to allow an amount to be entered that differs from minimum
637 $this->add('text', 'total_amount', ts('Amount'));
638 }
639 $this->add('select', 'financial_type_id',
640 ts('Financial Type'),
641 array('' => ts('- select -')) + CRM_Financial_BAO_FinancialType::getAvailableFinancialTypes($financialTypes, $this->_action)
642 );
643
644 $this->addElement('checkbox', 'is_different_contribution_contact', ts('Record Payment from a Different Contact?'));
645
646 $this->addSelect('soft_credit_type_id', array('entity' => 'contribution_soft'));
647 $this->addEntityRef('soft_credit_contact_id', ts('Payment From'), array('create' => TRUE));
648
649 $this->addElement('checkbox',
650 'send_receipt',
651 ts('Send Confirmation and Receipt?'), NULL,
652 array('onclick' => "showEmailOptions()")
653 );
654
655 $this->add('select', 'from_email_address', ts('Receipt From'), $this->_fromEmails);
656
657 $this->add('textarea', 'receipt_text', ts('Receipt Message'));
658
659 // Retrieve the name and email of the contact - this will be the TO for receipt email
660 if ($this->_contactID) {
661 list($this->_memberDisplayName,
662 $this->_memberEmail
663 ) = CRM_Contact_BAO_Contact_Location::getEmailDetails($this->_contactID);
664
665 $this->assign('emailExists', $this->_memberEmail);
666 $this->assign('displayName', $this->_memberDisplayName);
667 }
668
669 $isRecur = FALSE;
670 if ($this->_action & CRM_Core_Action::UPDATE) {
671 $recurContributionId = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_Membership', $this->_id,
672 'contribution_recur_id'
673 );
674 if ($recurContributionId && !CRM_Member_BAO_Membership::isSubscriptionCancelled($this->_id)) {
675 $isRecur = TRUE;
676 if (CRM_Member_BAO_Membership::isCancelSubscriptionSupported($this->_id)) {
677 $this->assign('cancelAutoRenew',
678 CRM_Utils_System::url('civicrm/contribute/unsubscribe', "reset=1&mid={$this->_id}")
679 );
680 }
681 foreach ($elements as $elem) {
682 $elem->freeze();
683 }
684 }
685 }
686 $this->assign('isRecur', $isRecur);
687
688 $this->addFormRule(array('CRM_Member_Form_Membership', 'formRule'), $this);
689 $mailingInfo = Civi::settings()->get('mailing_backend');
690 $this->assign('isEmailEnabledForSite', ($mailingInfo['outBound_option'] != 2));
691
692 parent::buildQuickForm();
693 }
694
695 /**
696 * Validation.
697 *
698 * @param array $params
699 * (ref.) an assoc array of name/value pairs.
700 *
701 * @param array $files
702 * @param CRM_Member_Form_Membership $self
703 *
704 * @throws CiviCRM_API3_Exception
705 * @return bool|array
706 * mixed true or array of errors
707 */
708 public static function formRule($params, $files, $self) {
709 $errors = array();
710
711 $priceSetId = self::getPriceSetID($params);
712 $priceSetDetails = self::getPriceSetDetails($params);
713
714 $selectedMemberships = self::getSelectedMemberships($priceSetDetails[$priceSetId], $params);
715
716 if (!empty($params['price_set_id'])) {
717 CRM_Price_BAO_PriceField::priceSetValidation($priceSetId, $params, $errors);
718
719 $priceFieldIDS = self::getPriceFieldIDs($params, $priceSetDetails[$priceSetId]);
720
721 if (!empty($priceFieldIDS)) {
722 $ids = implode(',', $priceFieldIDS);
723
724 $count = CRM_Price_BAO_PriceSet::getMembershipCount($ids);
725 foreach ($count as $occurrence) {
726 if ($occurrence > 1) {
727 $errors['_qf_default'] = ts('Select at most one option associated with the same membership type.');
728 }
729 }
730 }
731 // Return error if empty $self->_memTypeSelected
732 if (empty($errors) && empty($selectedMemberships)) {
733 $errors['_qf_default'] = ts('Select at least one membership option.');
734 }
735 if (!$self->_mode && empty($params['record_contribution'])) {
736 $errors['record_contribution'] = ts('Record Membership Payment is required when you use a price set.');
737 }
738 }
739 else {
740 if (empty($params['membership_type_id'][1])) {
741 $errors['membership_type_id'] = ts('Please select a membership type.');
742 }
743 $numterms = CRM_Utils_Array::value('num_terms', $params);
744 if ($numterms && intval($numterms) != $numterms) {
745 $errors['num_terms'] = ts('Please enter an integer for the number of terms.');
746 }
747
748 if (($self->_mode || isset($params['record_contribution'])) && empty($params['financial_type_id'])) {
749 $errors['financial_type_id'] = ts('Please enter the financial Type.');
750 }
751 }
752
753 if (!empty($errors) && (count($selectedMemberships) > 1)) {
754 $memberOfContacts = CRM_Member_BAO_MembershipType::getMemberOfContactByMemTypes($selectedMemberships);
755 $duplicateMemberOfContacts = array_count_values($memberOfContacts);
756 foreach ($duplicateMemberOfContacts as $countDuplicate) {
757 if ($countDuplicate > 1) {
758 $errors['_qf_default'] = ts('Please do not select more than one membership associated with the same organization.');
759 }
760 }
761 }
762
763 if (!empty($errors)) {
764 return $errors;
765 }
766
767 if (!empty($params['record_contribution']) && empty($params['payment_instrument_id'])) {
768 $errors['payment_instrument_id'] = ts('Payment Method is a required field.');
769 }
770
771 if (!empty($params['is_different_contribution_contact'])) {
772 if (empty($params['soft_credit_type_id'])) {
773 $errors['soft_credit_type_id'] = ts('Please Select a Soft Credit Type');
774 }
775 if (empty($params['soft_credit_contact_id'])) {
776 $errors['soft_credit_contact_id'] = ts('Please select a contact');
777 }
778 }
779
780 if (!empty($params['payment_processor_id'])) {
781 // validate payment instrument (e.g. credit card number)
782 CRM_Core_Payment_Form::validatePaymentInstrument($params['payment_processor_id'], $params, $errors, NULL);
783 }
784
785 $joinDate = NULL;
786 if (!empty($params['join_date'])) {
787
788 $joinDate = CRM_Utils_Date::processDate($params['join_date']);
789
790 foreach ($selectedMemberships as $memType) {
791 $startDate = NULL;
792 if (!empty($params['start_date'])) {
793 $startDate = CRM_Utils_Date::processDate($params['start_date']);
794 }
795
796 // if end date is set, ensure that start date is also set
797 // and that end date is later than start date
798 $endDate = NULL;
799 if (!empty($params['end_date'])) {
800 $endDate = CRM_Utils_Date::processDate($params['end_date']);
801 }
802
803 $membershipDetails = CRM_Member_BAO_MembershipType::getMembershipTypeDetails($memType);
804
805 if ($startDate && CRM_Utils_Array::value('period_type', $membershipDetails) == 'rolling') {
806 if ($startDate < $joinDate) {
807 $errors['start_date'] = ts('Start date must be the same or later than Member since.');
808 }
809 }
810
811 if ($endDate) {
812 if ($membershipDetails['duration_unit'] == 'lifetime') {
813 // Check if status is NOT cancelled or similar. For lifetime memberships, there is no automated
814 // process to update status based on end-date. The user must change the status now.
815 $result = civicrm_api3('MembershipStatus', 'get', array(
816 'sequential' => 1,
817 'is_current_member' => 0,
818 ));
819 $tmp_statuses = $result['values'];
820 $status_ids = array();
821 foreach ($tmp_statuses as $cur_stat) {
822 $status_ids[] = $cur_stat['id'];
823 }
824 if (empty($params['status_id']) || in_array($params['status_id'], $status_ids) == FALSE) {
825 $errors['status_id'] = ts('Please enter a status that does NOT represent a current membership status.');
826 $errors['is_override'] = ts('This must be checked because you set an End Date for a lifetime membership');
827 }
828 }
829 else {
830 if (!$startDate) {
831 $errors['start_date'] = ts('Start date must be set if end date is set.');
832 }
833 if ($endDate < $startDate) {
834 $errors['end_date'] = ts('End date must be the same or later than start date.');
835 }
836 }
837 }
838
839 // Default values for start and end dates if not supplied on the form.
840 $defaultDates = CRM_Member_BAO_MembershipType::getDatesForMembershipType($memType,
841 $joinDate,
842 $startDate,
843 $endDate
844 );
845
846 if (!$startDate) {
847 $startDate = CRM_Utils_Array::value('start_date',
848 $defaultDates
849 );
850 }
851 if (!$endDate) {
852 $endDate = CRM_Utils_Array::value('end_date',
853 $defaultDates
854 );
855 }
856
857 //CRM-3724, check for availability of valid membership status.
858 if (empty($params['is_override']) && !isset($errors['_qf_default'])) {
859 $calcStatus = CRM_Member_BAO_MembershipStatus::getMembershipStatusByDate($startDate,
860 $endDate,
861 $joinDate,
862 'today',
863 TRUE,
864 $memType,
865 $params
866 );
867 if (empty($calcStatus)) {
868 $url = CRM_Utils_System::url('civicrm/admin/member/membershipStatus', 'reset=1&action=browse');
869 $errors['_qf_default'] = ts('There is no valid Membership Status available for selected membership dates.');
870 $status = ts('Oops, it looks like there is no valid membership status available for the given membership dates. You can <a href="%1">Configure Membership Status Rules</a>.', array(1 => $url));
871 if (!$self->_mode) {
872 $status .= ' ' . ts('OR You can sign up by setting Status Override? to true.');
873 }
874 CRM_Core_Session::setStatus($status, ts('Membership Status Error'), 'error');
875 }
876 }
877 }
878 }
879 else {
880 $errors['join_date'] = ts('Please enter the Member Since.');
881 }
882
883 if (isset($params['is_override']) &&
884 $params['is_override'] && empty($params['status_id'])
885 ) {
886 $errors['status_id'] = ts('Please enter the status.');
887 }
888
889 //total amount condition arise when membership type having no
890 //minimum fee
891 if (isset($params['record_contribution'])) {
892 if (CRM_Utils_System::isNull($params['total_amount'])) {
893 $errors['total_amount'] = ts('Please enter the contribution.');
894 }
895 }
896
897 // validate contribution status for 'Failed'.
898 if ($self->_onlinePendingContributionId && !empty($params['record_contribution']) &&
899 (CRM_Utils_Array::value('contribution_status_id', $params) ==
900 array_search('Failed', CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name'))
901 )
902 ) {
903 $errors['contribution_status_id'] = ts('Please select a valid payment status before updating.');
904 }
905
906 return empty($errors) ? TRUE : $errors;
907 }
908
909 /**
910 * Process the form submission.
911 */
912 public function postProcess() {
913 if ($this->_action & CRM_Core_Action::DELETE) {
914 CRM_Member_BAO_Membership::del($this->_id);
915 return;
916 }
917 // get the submitted form values.
918 $this->_params = $this->controller->exportValues($this->_name);
919
920 $this->submit();
921
922 $this->setUserContext();
923 }
924
925 /**
926 * Send email receipt.
927 *
928 * @param CRM_Core_Form $form
929 * Form object.
930 * @param array $formValues
931 * @param object $membership
932 * Object.
933 *
934 * @return bool
935 * true if mail was sent successfully
936 */
937 public static function emailReceipt(&$form, &$formValues, &$membership) {
938 // retrieve 'from email id' for acknowledgement
939 $receiptFrom = $formValues['from_email_address'];
940
941 if (!empty($formValues['payment_instrument_id'])) {
942 $paymentInstrument = CRM_Contribute_PseudoConstant::paymentInstrument();
943 $formValues['paidBy'] = $paymentInstrument[$formValues['payment_instrument_id']];
944 }
945
946 // retrieve custom data
947 $customFields = $customValues = array();
948 if (property_exists($form, '_groupTree')
949 && !empty($form->_groupTree)
950 ) {
951 foreach ($form->_groupTree as $groupID => $group) {
952 if ($groupID == 'info') {
953 continue;
954 }
955 foreach ($group['fields'] as $k => $field) {
956 $field['title'] = $field['label'];
957 $customFields["custom_{$k}"] = $field;
958 }
959 }
960 }
961
962 $members = array(array('member_id', '=', $membership->id, 0, 0));
963 // check whether its a test drive
964 if ($form->_mode == 'test') {
965 $members[] = array('member_test', '=', 1, 0, 0);
966 }
967
968 CRM_Core_BAO_UFGroup::getValues($formValues['contact_id'], $customFields, $customValues, FALSE, $members);
969 $form->assign('customValues', $customValues);
970
971 if ($form->_mode) {
972 $form->assign('address', CRM_Utils_Address::getFormattedBillingAddressFieldsFromParameters(
973 $form->_params,
974 $form->_bltID
975 ));
976
977 $date = CRM_Utils_Date::format($form->_params['credit_card_exp_date']);
978 $date = CRM_Utils_Date::mysqlToIso($date);
979 $form->assign('credit_card_exp_date', $date);
980 $form->assign('credit_card_number',
981 CRM_Utils_System::mungeCreditCard($form->_params['credit_card_number'])
982 );
983 $form->assign('credit_card_type', $form->_params['credit_card_type']);
984 $form->assign('contributeMode', 'direct');
985 $form->assign('isAmountzero', 0);
986 $form->assign('is_pay_later', 0);
987 $form->assign('isPrimary', 1);
988 }
989
990 $form->assign('module', 'Membership');
991 $form->assign('contactID', $formValues['contact_id']);
992
993 $form->assign('membershipID', CRM_Utils_Array::value('membership_id', $form->_params, CRM_Utils_Array::value('membership_id', $form->_defaultValues)));
994
995 if (!empty($formValues['contribution_id'])) {
996 $form->assign('contributionID', $formValues['contribution_id']);
997 }
998 elseif (isset($form->_onlinePendingContributionId)) {
999 $form->assign('contributionID', $form->_onlinePendingContributionId);
1000 }
1001
1002 if (!empty($formValues['contribution_status_id'])) {
1003 $form->assign('contributionStatusID', $formValues['contribution_status_id']);
1004 $form->assign('contributionStatus', CRM_Contribute_PseudoConstant::contributionStatus($formValues['contribution_status_id'], 'name'));
1005 }
1006
1007 if (!empty($formValues['is_renew'])) {
1008 $form->assign('receiptType', 'membership renewal');
1009 }
1010 else {
1011 $form->assign('receiptType', 'membership signup');
1012 }
1013 $form->assign('receive_date', CRM_Utils_Date::processDate(CRM_Utils_Array::value('receive_date', $formValues)));
1014 $form->assign('formValues', $formValues);
1015
1016 if (empty($lineItem)) {
1017 $form->assign('mem_start_date', CRM_Utils_Date::customFormat($membership->start_date, '%B %E%f, %Y'));
1018 if (!CRM_Utils_System::isNull($membership->end_date)) {
1019 $form->assign('mem_end_date', CRM_Utils_Date::customFormat($membership->end_date, '%B %E%f, %Y'));
1020 }
1021 $form->assign('membership_name', CRM_Member_PseudoConstant::membershipType($membership->membership_type_id));
1022 }
1023
1024 $isBatchProcess = is_a($form, 'CRM_Batch_Form_Entry');
1025 if ((empty($form->_contributorDisplayName) || empty($form->_contributorEmail)) || $isBatchProcess) {
1026 // in this case the form is being called statically from the batch editing screen
1027 // having one class in the form layer call another statically is not greate
1028 // & we should aim to move this function to the BAO layer in future.
1029 // however, we can assume that the contact_id passed in by the batch
1030 // function will be the recipient
1031 list($form->_contributorDisplayName, $form->_contributorEmail)
1032 = CRM_Contact_BAO_Contact_Location::getEmailDetails($formValues['contact_id']);
1033 if (empty($form->_receiptContactId) || $isBatchProcess) {
1034 $form->_receiptContactId = $formValues['contact_id'];
1035 }
1036 }
1037 $template = CRM_Core_Smarty::singleton();
1038 $taxAmt = $template->get_template_vars('dataArray');
1039 $eventTaxAmt = $template->get_template_vars('totalTaxAmount');
1040 $prefixValue = Civi::settings()->get('contribution_invoice_settings');
1041 $invoicing = CRM_Utils_Array::value('invoicing', $prefixValue);
1042 if ((!empty($taxAmt) || isset($eventTaxAmt)) && (isset($invoicing) && isset($prefixValue['is_email_pdf']))) {
1043 $isEmailPdf = TRUE;
1044 }
1045 else {
1046 $isEmailPdf = FALSE;
1047 }
1048
1049 list($mailSend, $subject, $message, $html) = CRM_Core_BAO_MessageTemplate::sendTemplate(
1050 array(
1051 'groupName' => 'msg_tpl_workflow_membership',
1052 'valueName' => 'membership_offline_receipt',
1053 'contactId' => $form->_receiptContactId,
1054 'from' => $receiptFrom,
1055 'toName' => $form->_contributorDisplayName,
1056 'toEmail' => $form->_contributorEmail,
1057 'PDFFilename' => ts('receipt') . '.pdf',
1058 'isEmailPdf' => $isEmailPdf,
1059 'contributionId' => $formValues['contribution_id'],
1060 'isTest' => (bool) ($form->_action & CRM_Core_Action::PREVIEW),
1061 )
1062 );
1063
1064 return TRUE;
1065 }
1066
1067 /**
1068 * Submit function.
1069 *
1070 * This is also accessed by unit tests.
1071 *
1072 * @return array
1073 */
1074 public function submit() {
1075 $isTest = ($this->_mode == 'test') ? 1 : 0;
1076 $this->storeContactFields($this->_params);
1077 $this->beginPostProcess();
1078 $formValues = $this->_params;
1079 $joinDate = $startDate = $endDate = NULL;
1080 $membershipTypes = $membership = $calcDate = array();
1081 $membershipType = NULL;
1082 $paymentInstrumentID = $this->_paymentProcessor['object']->getPaymentInstrumentID();
1083
1084 $mailSend = FALSE;
1085 $formValues = $this->setPriceSetParameters($formValues);
1086 $params = $softParams = $ids = array();
1087
1088 $allMemberStatus = CRM_Member_PseudoConstant::membershipStatus();
1089 $allContributionStatus = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name');
1090 $this->processBillingAddress();
1091
1092 if ($this->_id) {
1093 $ids['membership'] = $params['id'] = $this->_id;
1094 }
1095 $ids['userId'] = CRM_Core_Session::singleton()->get('userID');
1096
1097 // Set variables that we normally get from context.
1098 // In form mode these are set in preProcess.
1099 //TODO: set memberships, fixme
1100 $this->setContextVariables($formValues);
1101
1102 $this->_memTypeSelected = self::getSelectedMemberships(
1103 $this->_priceSet,
1104 $formValues
1105 );
1106 if (empty($formValues['financial_type_id'])) {
1107 $formValues['financial_type_id'] = $this->_priceSet['financial_type_id'];
1108 }
1109
1110 $config = CRM_Core_Config::singleton();
1111
1112 // @todo this is no longer required if we convert some date fields.
1113 $this->convertDateFieldsToMySQL($formValues);
1114
1115 $membershipTypeValues = array();
1116 foreach ($this->_memTypeSelected as $memType) {
1117 $membershipTypeValues[$memType]['membership_type_id'] = $memType;
1118 }
1119
1120 //take the required membership recur values.
1121 if ($this->_mode && !empty($formValues['auto_renew'])) {
1122 $params['is_recur'] = $formValues['is_recur'] = TRUE;
1123 $mapping = array(
1124 'frequency_interval' => 'duration_interval',
1125 'frequency_unit' => 'duration_unit',
1126 );
1127
1128 $count = 0;
1129 foreach ($this->_memTypeSelected as $memType) {
1130 $recurMembershipTypeValues = CRM_Utils_Array::value($memType,
1131 $this->_recurMembershipTypes, array()
1132 );
1133 foreach ($mapping as $mapVal => $mapParam) {
1134 $membershipTypeValues[$memType][$mapVal] = CRM_Utils_Array::value($mapParam,
1135 $recurMembershipTypeValues
1136 );
1137 if (!$count) {
1138 $formValues[$mapVal] = CRM_Utils_Array::value($mapParam,
1139 $recurMembershipTypeValues
1140 );
1141 }
1142 }
1143 $count++;
1144 }
1145 }
1146
1147 $isQuickConfig = $this->_priceSet['is_quick_config'];
1148
1149 $termsByType = array();
1150
1151 $lineItem = array($this->_priceSetId => array());
1152
1153 CRM_Price_BAO_PriceSet::processAmount($this->_priceSet['fields'],
1154 $formValues, $lineItem[$this->_priceSetId], NULL, $this->_priceSetId);
1155
1156 if (CRM_Utils_Array::value('tax_amount', $formValues)) {
1157 $params['tax_amount'] = $formValues['tax_amount'];
1158 }
1159 $params['total_amount'] = CRM_Utils_Array::value('amount', $formValues);
1160 $submittedFinancialType = CRM_Utils_Array::value('financial_type_id', $formValues);
1161 if (!empty($lineItem[$this->_priceSetId])) {
1162 foreach ($lineItem[$this->_priceSetId] as &$li) {
1163 if (!empty($li['membership_type_id'])) {
1164 if (!empty($li['membership_num_terms'])) {
1165 $termsByType[$li['membership_type_id']] = $li['membership_num_terms'];
1166 }
1167 }
1168
1169 ///CRM-11529 for quick config backoffice transactions
1170 //when financial_type_id is passed in form, update the
1171 //lineitems with the financial type selected in form
1172 if ($isQuickConfig && $submittedFinancialType) {
1173 $li['financial_type_id'] = $submittedFinancialType;
1174 }
1175 }
1176 }
1177
1178 $params['contact_id'] = $this->_contactID;
1179
1180 $fields = array(
1181 'status_id',
1182 'source',
1183 'is_override',
1184 'campaign_id',
1185 );
1186
1187 foreach ($fields as $f) {
1188 $params[$f] = CRM_Utils_Array::value($f, $formValues);
1189 }
1190
1191 // fix for CRM-3724
1192 // when is_override false ignore is_admin statuses during membership
1193 // status calculation. similarly we did fix for import in CRM-3570.
1194 if (empty($params['is_override'])) {
1195 $params['exclude_is_admin'] = TRUE;
1196 }
1197
1198 // process date params to mysql date format.
1199 $dateTypes = array(
1200 'join_date' => 'joinDate',
1201 'start_date' => 'startDate',
1202 'end_date' => 'endDate',
1203 );
1204 foreach ($dateTypes as $dateField => $dateVariable) {
1205 $$dateVariable = CRM_Utils_Date::processDate($formValues[$dateField]);
1206 }
1207
1208 $memTypeNumTerms = empty($termsByType) ? CRM_Utils_Array::value('num_terms', $formValues) : NULL;
1209
1210 $calcDates = array();
1211 foreach ($this->_memTypeSelected as $memType) {
1212 if (empty($memTypeNumTerms)) {
1213 $memTypeNumTerms = CRM_Utils_Array::value($memType, $termsByType, 1);
1214 }
1215 $calcDates[$memType] = CRM_Member_BAO_MembershipType::getDatesForMembershipType($memType,
1216 $joinDate, $startDate, $endDate, $memTypeNumTerms
1217 );
1218 }
1219
1220 foreach ($calcDates as $memType => $calcDate) {
1221 foreach (array_keys($dateTypes) as $d) {
1222 //first give priority to form values then calDates.
1223 $date = CRM_Utils_Array::value($d, $formValues);
1224 if (!$date) {
1225 $date = CRM_Utils_Array::value($d, $calcDate);
1226 }
1227
1228 $membershipTypeValues[$memType][$d] = CRM_Utils_Date::processDate($date);
1229 }
1230 }
1231
1232 // max related memberships - take from form or inherit from membership type
1233 foreach ($this->_memTypeSelected as $memType) {
1234 if (array_key_exists('max_related', $formValues)) {
1235 $membershipTypeValues[$memType]['max_related'] = CRM_Utils_Array::value('max_related', $formValues);
1236 }
1237 $membershipTypeValues[$memType]['custom'] = CRM_Core_BAO_CustomField::postProcess($formValues,
1238 $this->_id,
1239 'Membership'
1240 );
1241 $membershipTypes[$memType] = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_MembershipType',
1242 $memType
1243 );
1244 }
1245
1246 $membershipType = implode(', ', $membershipTypes);
1247
1248 // Retrieve the name and email of the current user - this will be the FROM for the receipt email
1249 list($userName) = CRM_Contact_BAO_Contact_Location::getEmailDetails($ids['userId']);
1250
1251 //CRM-13981, allow different person as a soft-contributor of chosen type
1252 if ($this->_contributorContactID != $this->_contactID) {
1253 $params['contribution_contact_id'] = $this->_contributorContactID;
1254 if (!empty($formValues['soft_credit_type_id'])) {
1255 $softParams['soft_credit_type_id'] = $formValues['soft_credit_type_id'];
1256 $softParams['contact_id'] = $this->_contactID;
1257 }
1258 }
1259 if (!empty($formValues['record_contribution'])) {
1260 $recordContribution = array(
1261 'total_amount',
1262 'financial_type_id',
1263 'payment_instrument_id',
1264 'trxn_id',
1265 'contribution_status_id',
1266 'check_number',
1267 'campaign_id',
1268 'receive_date',
1269 'card_type_id',
1270 'pan_truncation',
1271 );
1272
1273 foreach ($recordContribution as $f) {
1274 $params[$f] = CRM_Utils_Array::value($f, $formValues);
1275 }
1276
1277 if (!$this->_onlinePendingContributionId) {
1278 if (empty($formValues['source'])) {
1279 $params['contribution_source'] = ts('%1 Membership: Offline signup (by %2)', array(
1280 1 => $membershipType,
1281 2 => $userName,
1282 ));
1283 }
1284 else {
1285 $params['contribution_source'] = $formValues['source'];
1286 }
1287 }
1288
1289 if (empty($params['is_override']) &&
1290 CRM_Utils_Array::value('contribution_status_id', $params) != array_search('Completed', $allContributionStatus)
1291 ) {
1292 $params['status_id'] = array_search('Pending', $allMemberStatus);
1293 $params['skipStatusCal'] = TRUE;
1294 $params['is_pay_later'] = 1;
1295 $this->assign('is_pay_later', 1);
1296 }
1297
1298 if (!empty($formValues['send_receipt'])) {
1299 $params['receipt_date'] = CRM_Utils_Array::value('receive_date', $formValues);
1300 }
1301
1302 //insert financial type name in receipt.
1303 $formValues['contributionType_name'] = CRM_Core_DAO::getFieldValue('CRM_Financial_DAO_FinancialType',
1304 $formValues['financial_type_id']
1305 );
1306 }
1307
1308 // process line items, until no previous line items.
1309 if (!empty($lineItem)) {
1310 $params['lineItems'] = $lineItem;
1311 $params['processPriceSet'] = TRUE;
1312 }
1313 $createdMemberships = array();
1314 if ($this->_mode) {
1315 $params['total_amount'] = CRM_Utils_Array::value('total_amount', $formValues, 0);
1316
1317 //CRM-20264 : Store CC type and number (last 4 digit) during backoffice or online payment
1318 $params['card_type_id'] = CRM_Utils_Array::value('card_type_id', $this->_params);
1319 $params['pan_truncation'] = CRM_Utils_Array::value('pan_truncation', $this->_params);
1320
1321 if (!$isQuickConfig) {
1322 $params['financial_type_id'] = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet',
1323 $this->_priceSetId,
1324 'financial_type_id'
1325 );
1326 }
1327 else {
1328 $params['financial_type_id'] = CRM_Utils_Array::value('financial_type_id', $formValues);
1329 }
1330
1331 //get the payment processor id as per mode. Try removing in favour of beginPostProcess.
1332 $params['payment_processor_id'] = $formValues['payment_processor_id'] = $this->_paymentProcessor['id'];
1333 $params['register_date'] = date('YmdHis');
1334
1335 // add all the additional payment params we need
1336 // @todo the country & state values should be set by the call to $this->assignBillingAddress.
1337 $formValues["state_province-{$this->_bltID}"] = $formValues["billing_state_province-{$this->_bltID}"]
1338 = CRM_Core_PseudoConstant::stateProvinceAbbreviation($formValues["billing_state_province_id-{$this->_bltID}"]);
1339 $formValues["country-{$this->_bltID}"] = $formValues["billing_country-{$this->_bltID}"] = CRM_Core_PseudoConstant::countryIsoCode($formValues["billing_country_id-{$this->_bltID}"]);
1340
1341 $formValues['amount'] = $params['total_amount'];
1342 // @todo this is a candidate for beginPostProcessFunction.
1343 $formValues['currencyID'] = $config->defaultCurrency;
1344 $formValues['description'] = ts("Contribution submitted by a staff person using member's credit card for signup");
1345 $formValues['invoiceID'] = md5(uniqid(rand(), TRUE));
1346 $formValues['financial_type_id'] = $params['financial_type_id'];
1347
1348 // at this point we've created a contact and stored its address etc
1349 // all the payment processors expect the name and address to be in the
1350 // so we copy stuff over to first_name etc.
1351 $paymentParams = $formValues;
1352 $paymentParams['contactID'] = $this->_contributorContactID;
1353 //CRM-10377 if payment is by an alternate contact then we need to set that person
1354 // as the contact in the payment params
1355 if ($this->_contributorContactID != $this->_contactID) {
1356 if (!empty($formValues['soft_credit_type_id'])) {
1357 $softParams['contact_id'] = $params['contact_id'];
1358 $softParams['soft_credit_type_id'] = $formValues['soft_credit_type_id'];
1359 }
1360 }
1361 if (!empty($formValues['send_receipt'])) {
1362 $paymentParams['email'] = $this->_contributorEmail;
1363 }
1364
1365 // This is a candidate for shared beginPostProcess function.
1366 CRM_Core_Payment_Form::mapParams($this->_bltID, $formValues, $paymentParams, TRUE);
1367 // CRM-7137 -for recurring membership,
1368 // we do need contribution and recurring records.
1369 $result = NULL;
1370 if (!empty($paymentParams['is_recur'])) {
1371 $financialType = new CRM_Financial_DAO_FinancialType();
1372 $financialType->id = $params['financial_type_id'];
1373 $financialType->find(TRUE);
1374 $this->_params = $formValues;
1375
1376 $contribution = CRM_Contribute_Form_Contribution_Confirm::processFormContribution($this,
1377 $paymentParams,
1378 NULL,
1379 array(
1380 'contact_id' => $this->_contributorContactID,
1381 'line_item' => $lineItem,
1382 'is_test' => $isTest,
1383 'campaign_id' => CRM_Utils_Array::value('campaign_id', $paymentParams),
1384 'contribution_page_id' => CRM_Utils_Array::value('contribution_page_id', $formValues),
1385 'source' => CRM_Utils_Array::value('source', $paymentParams, CRM_Utils_Array::value('description', $paymentParams)),
1386 'thankyou_date' => CRM_Utils_Array::value('thankyou_date', $paymentParams),
1387 'payment_instrument_id' => $paymentInstrumentID,
1388 ),
1389 $financialType,
1390 FALSE,
1391 $this->_bltID,
1392 TRUE
1393 );
1394
1395 //create new soft-credit record, CRM-13981
1396 if ($softParams) {
1397 $softParams['contribution_id'] = $contribution->id;
1398 $softParams['currency'] = $contribution->currency;
1399 $softParams['amount'] = $contribution->total_amount;
1400 CRM_Contribute_BAO_ContributionSoft::add($softParams);
1401 }
1402
1403 $paymentParams['contactID'] = $this->_contactID;
1404 $paymentParams['contributionID'] = $contribution->id;
1405 $paymentParams['contributionTypeID'] = $contribution->financial_type_id;
1406 $paymentParams['contributionPageID'] = $contribution->contribution_page_id;
1407 $paymentParams['contributionRecurID'] = $contribution->contribution_recur_id;
1408 $ids['contribution'] = $contribution->id;
1409 $params['contribution_recur_id'] = $paymentParams['contributionRecurID'];
1410 }
1411
1412 if ($params['total_amount'] > 0.0) {
1413 $payment = $this->_paymentProcessor['object'];
1414 try {
1415 $result = $payment->doPayment($paymentParams);
1416 $formValues = array_merge($formValues, $result);
1417 // Assign amount to template if payment was successful.
1418 $this->assign('amount', $params['total_amount']);
1419 }
1420 catch (PaymentProcessorException $e) {
1421 if (!empty($paymentParams['contributionID'])) {
1422 CRM_Contribute_BAO_Contribution::failPayment($paymentParams['contributionID'], $this->_contactID,
1423 $e->getMessage());
1424 }
1425 if (!empty($paymentParams['contributionRecurID'])) {
1426 CRM_Contribute_BAO_ContributionRecur::deleteRecurContribution($paymentParams['contributionRecurID']);
1427 }
1428
1429 CRM_Core_Error::displaySessionError($result);
1430 CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/contact/view/membership',
1431 "reset=1&action=add&cid={$this->_contactID}&context=&mode={$this->_mode}"
1432 ));
1433
1434 }
1435 }
1436
1437 if ($formValues['payment_status_id'] != array_search('Completed', $allContributionStatus)) {
1438 $params['status_id'] = array_search('Pending', $allMemberStatus);
1439 $params['skipStatusCal'] = TRUE;
1440 // unset send-receipt option, since receipt will be sent when ipn is received.
1441 unset($formValues['send_receipt'], $formValues['send_receipt']);
1442 //as membership is pending set dates to null.
1443 $memberDates = array(
1444 'join_date' => 'joinDate',
1445 'start_date' => 'startDate',
1446 'end_date' => 'endDate',
1447 );
1448 foreach ($memberDates as $dv) {
1449 $$dv = NULL;
1450 foreach ($this->_memTypeSelected as $memType) {
1451 $membershipTypeValues[$memType][$dv] = NULL;
1452 }
1453 }
1454 }
1455 $now = date('YmdHis');
1456 $params['receive_date'] = $now;
1457 $params['invoice_id'] = $formValues['invoiceID'];
1458 $params['contribution_source'] = ts('%1 Membership Signup: Credit card or direct debit (by %2)',
1459 array(1 => $membershipType, 2 => $userName)
1460 );
1461 $params['source'] = $formValues['source'] ? $formValues['source'] : $params['contribution_source'];
1462 $params['trxn_id'] = CRM_Utils_Array::value('trxn_id', $result);
1463 $params['is_test'] = ($this->_mode == 'live') ? 0 : 1;
1464 if (!empty($formValues['send_receipt'])) {
1465 $params['receipt_date'] = $now;
1466 }
1467 else {
1468 $params['receipt_date'] = NULL;
1469 }
1470
1471 $this->set('params', $formValues);
1472 $this->assign('trxn_id', CRM_Utils_Array::value('trxn_id', $result));
1473 $this->assign('receive_date',
1474 CRM_Utils_Date::mysqlToIso($params['receive_date'])
1475 );
1476
1477 // required for creating membership for related contacts
1478 $params['action'] = $this->_action;
1479
1480 //create membership record.
1481 $count = 0;
1482 foreach ($this->_memTypeSelected as $memType) {
1483 if ($count &&
1484 ($relateContribution = CRM_Member_BAO_Membership::getMembershipContributionId($membership->id))
1485 ) {
1486 $membershipTypeValues[$memType]['relate_contribution_id'] = $relateContribution;
1487 }
1488
1489 $membershipParams = array_merge($membershipTypeValues[$memType], $params);
1490 //CRM-15366
1491 if (!empty($softParams) && empty($paymentParams['is_recur'])) {
1492 $membershipParams['soft_credit'] = $softParams;
1493 }
1494 if (isset($result['fee_amount'])) {
1495 $membershipParams['fee_amount'] = $result['fee_amount'];
1496 }
1497 // This is required to trigger the recording of the membership contribution in the
1498 // CRM_Member_BAO_Membership::Create function.
1499 // @todo stop setting this & 'teach' the create function to respond to something
1500 // appropriate as part of our 2-step always create the pending contribution & then finally add the payment
1501 // process -
1502 // @see http://wiki.civicrm.org/confluence/pages/viewpage.action?pageId=261062657#Payments&AccountsRoadmap-Movetowardsalwaysusinga2-steppaymentprocess
1503 $membershipParams['contribution_status_id'] = CRM_Utils_Array::value('payment_status_id', $result);
1504 if (!empty($paymentParams['is_recur'])) {
1505 // The earlier process created the line items (although we want to get rid of the earlier one in favour
1506 // of a single path!
1507 unset($membershipParams['lineItems']);
1508 }
1509 $membershipParams['payment_instrument_id'] = $paymentInstrumentID;
1510 $membership = CRM_Member_BAO_Membership::create($membershipParams, $ids);
1511 $params['contribution'] = CRM_Utils_Array::value('contribution', $membershipParams);
1512 unset($params['lineItems']);
1513 $this->_membershipIDs[] = $membership->id;
1514 $createdMemberships[$memType] = $membership;
1515 $count++;
1516 }
1517
1518 }
1519 else {
1520 $params['action'] = $this->_action;
1521 if ($this->_onlinePendingContributionId && !empty($formValues['record_contribution'])) {
1522
1523 // update membership as well as contribution object, CRM-4395
1524 $params['contribution_id'] = $this->_onlinePendingContributionId;
1525 $params['componentId'] = $params['id'];
1526 $params['componentName'] = 'contribute';
1527 $result = CRM_Contribute_BAO_Contribution::transitionComponents($params, TRUE);
1528 if (!empty($result) && !empty($params['contribution_id'])) {
1529 $lineItem = array();
1530 $lineItems = CRM_Price_BAO_LineItem::getLineItemsByContributionID($params['contribution_id']);
1531 $itemId = key($lineItems);
1532 $priceSetId = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceField', $lineItems[$itemId]['price_field_id'], 'price_set_id');
1533
1534 $lineItems[$itemId]['unit_price'] = $params['total_amount'];
1535 $lineItems[$itemId]['line_total'] = $params['total_amount'];
1536 $lineItems[$itemId]['id'] = $itemId;
1537 $lineItem[$priceSetId] = $lineItems;
1538 $contributionBAO = new CRM_Contribute_BAO_Contribution();
1539 $contributionBAO->id = $params['contribution_id'];
1540 $contributionBAO->contact_id = $params['contact_id'];
1541 $contributionBAO->find();
1542 CRM_Price_BAO_LineItem::processPriceSet($params['contribution_id'], $lineItem, $contributionBAO, 'civicrm_membership');
1543
1544 //create new soft-credit record, CRM-13981
1545 if ($softParams) {
1546 $softParams['contribution_id'] = $params['contribution_id'];
1547 while ($contributionBAO->fetch()) {
1548 $softParams['currency'] = $contributionBAO->currency;
1549 $softParams['amount'] = $contributionBAO->total_amount;
1550 }
1551 CRM_Contribute_BAO_ContributionSoft::add($softParams);
1552 }
1553 }
1554
1555 //carry updated membership object.
1556 $membership = new CRM_Member_DAO_Membership();
1557 $membership->id = $this->_id;
1558 $membership->find(TRUE);
1559
1560 $cancelled = TRUE;
1561 if ($membership->end_date) {
1562 //display end date w/ status message.
1563 $endDate = $membership->end_date;
1564
1565 if (!in_array($membership->status_id, array(
1566 // CRM-15475
1567 array_search('Cancelled', CRM_Member_PseudoConstant::membershipStatus(NULL, " name = 'Cancelled' ", 'name', FALSE, TRUE)),
1568 array_search('Expired', CRM_Member_PseudoConstant::membershipStatus()),
1569 ))
1570 ) {
1571 $cancelled = FALSE;
1572 }
1573 }
1574 // suppress form values in template.
1575 $this->assign('cancelled', $cancelled);
1576
1577 $createdMemberships[] = $membership;
1578 }
1579 else {
1580 $count = 0;
1581 foreach ($this->_memTypeSelected as $memType) {
1582 if ($count && !empty($formValues['record_contribution']) &&
1583 ($relateContribution = CRM_Member_BAO_Membership::getMembershipContributionId($membership->id))
1584 ) {
1585 $membershipTypeValues[$memType]['relate_contribution_id'] = $relateContribution;
1586 }
1587
1588 $membershipParams = array_merge($params, $membershipTypeValues[$memType]);
1589 if (!empty($formValues['int_amount'])) {
1590 $init_amount = array();
1591 foreach ($formValues as $key => $value) {
1592 if (strstr($key, 'txt-price')) {
1593 $init_amount[$key] = $value;
1594 }
1595 }
1596 $membershipParams['init_amount'] = $init_amount;
1597 }
1598
1599 if (!empty($softParams)) {
1600 $membershipParams['soft_credit'] = $softParams;
1601 }
1602
1603 $membership = CRM_Member_BAO_Membership::create($membershipParams, $ids);
1604 $params['contribution'] = CRM_Utils_Array::value('contribution', $membershipParams);
1605 unset($params['lineItems']);
1606 // skip line item creation for next interation since line item(s) are already created.
1607 $params['skipLineItem'] = TRUE;
1608
1609 $this->_membershipIDs[] = $membership->id;
1610 $createdMemberships[$memType] = $membership;
1611 $count++;
1612 }
1613 }
1614 }
1615
1616 if (!empty($lineItem[$this->_priceSetId])) {
1617 $invoiceSettings = Civi::settings()->get('contribution_invoice_settings');
1618 $invoicing = CRM_Utils_Array::value('invoicing', $invoiceSettings);
1619 $taxAmount = FALSE;
1620 $totalTaxAmount = 0;
1621 foreach ($lineItem[$this->_priceSetId] as & $priceFieldOp) {
1622 if (!empty($priceFieldOp['membership_type_id'])) {
1623 $priceFieldOp['start_date'] = $membershipTypeValues[$priceFieldOp['membership_type_id']]['start_date'] ? CRM_Utils_Date::customFormat($membershipTypeValues[$priceFieldOp['membership_type_id']]['start_date'], '%B %E%f, %Y') : '-';
1624 $priceFieldOp['end_date'] = $membershipTypeValues[$priceFieldOp['membership_type_id']]['end_date'] ? CRM_Utils_Date::customFormat($membershipTypeValues[$priceFieldOp['membership_type_id']]['end_date'], '%B %E%f, %Y') : '-';
1625 }
1626 else {
1627 $priceFieldOp['start_date'] = $priceFieldOp['end_date'] = 'N/A';
1628 }
1629 if ($invoicing && isset($priceFieldOp['tax_amount'])) {
1630 $taxAmount = TRUE;
1631 $totalTaxAmount += $priceFieldOp['tax_amount'];
1632 }
1633 }
1634 if ($invoicing) {
1635 $dataArray = array();
1636 foreach ($lineItem[$this->_priceSetId] as $key => $value) {
1637 if (isset($value['tax_amount']) && isset($value['tax_rate'])) {
1638 if (isset($dataArray[$value['tax_rate']])) {
1639 $dataArray[$value['tax_rate']] = $dataArray[$value['tax_rate']] + CRM_Utils_Array::value('tax_amount', $value);
1640 }
1641 else {
1642 $dataArray[$value['tax_rate']] = CRM_Utils_Array::value('tax_amount', $value);
1643 }
1644 }
1645 }
1646 if ($taxAmount) {
1647 $this->assign('totalTaxAmount', $totalTaxAmount);
1648 $this->assign('taxTerm', CRM_Utils_Array::value('tax_term', $invoiceSettings));
1649 }
1650 $this->assign('dataArray', $dataArray);
1651 }
1652 }
1653 $this->assign('lineItem', !empty($lineItem) && !$isQuickConfig ? $lineItem : FALSE);
1654
1655 $receiptSend = FALSE;
1656 $contributionId = CRM_Member_BAO_Membership::getMembershipContributionId($membership->id);
1657 $membershipIds = $this->_membershipIDs;
1658 if ($contributionId && !empty($membershipIds)) {
1659 $contributionDetails = CRM_Contribute_BAO_Contribution::getContributionDetails(
1660 CRM_Export_Form_Select::MEMBER_EXPORT, $this->_membershipIDs);
1661 if ($contributionDetails[$membership->id]['contribution_status'] == 'Completed') {
1662 $receiptSend = TRUE;
1663 }
1664 }
1665
1666 $receiptSent = FALSE;
1667 if (!empty($formValues['send_receipt']) && $receiptSend) {
1668 $formValues['contact_id'] = $this->_contactID;
1669 $formValues['contribution_id'] = $contributionId;
1670 // We really don't need a distinct receipt_text_signup vs receipt_text_renewal as they are
1671 // handled in the receipt. But by setting one we avoid breaking templates for now
1672 // although at some point we should switch in the templates.
1673 $formValues['receipt_text_signup'] = $formValues['receipt_text'];
1674 // send email receipt
1675 $this->assignBillingName();
1676 $mailSend = self::emailReceipt($this, $formValues, $membership);
1677 $receiptSent = TRUE;
1678 }
1679
1680 // finally set membership id if already not set
1681 if (!$this->_id) {
1682 $this->_id = $membership->id;
1683 }
1684
1685 $isRecur = CRM_Utils_Array::value('is_recur', $params);
1686 $this->updateContributionOnMembershipTypeChange($params, $membership);
1687 $this->setStatusMessage($membership, $endDate, $receiptSent, $membershipTypes, $createdMemberships, $isRecur, $calcDates, $mailSend);
1688 return $createdMemberships;
1689 }
1690
1691 /**
1692 * Update related contribution of a membership if update_contribution_on_membership_type_change
1693 * contribution setting is enabled and type is changed on edit
1694 *
1695 * @param array $inputParams
1696 * submitted form values
1697 * @param CRM_Member_DAO_Membership $membership
1698 * Updated membership object
1699 *
1700 */
1701 protected function updateContributionOnMembershipTypeChange($inputParams, $membership) {
1702 if (Civi::settings()->get('update_contribution_on_membership_type_change') &&
1703 ($this->_action & CRM_Core_Action::UPDATE) && // on update
1704 $this->_id && // if ID is present
1705 !in_array($this->_memType, $this->_memTypeSelected) // if selected membership doesn't match with earlier membership
1706 ) {
1707 if (CRM_Utils_Array::value('is_recur', $inputParams)) {
1708 CRM_Core_Session::setStatus(ts('Associated recurring contribution cannot be updated on membership type change.', ts('Error'), 'error'));
1709 return;
1710 }
1711
1712 // fetch lineitems by updated membership ID
1713 $lineItems = CRM_Price_BAO_LineItem::getLineItems($membership->id, 'membership');
1714 // retrieve the related contribution ID
1715 $contributionID = CRM_Core_DAO::getFieldValue(
1716 'CRM_Member_DAO_MembershipPayment',
1717 $membership->id,
1718 'contribution_id',
1719 'membership_id'
1720 );
1721 // get price fields of chosen price-set
1722 $priceSetDetails = CRM_Utils_Array::value(
1723 $this->_priceSetId,
1724 CRM_Price_BAO_PriceSet::getSetDetail(
1725 $this->_priceSetId,
1726 TRUE,
1727 TRUE
1728 )
1729 );
1730
1731 // add price field information in $inputParams
1732 self::addPriceFieldByMembershipType($inputParams, $priceSetDetails['fields'], $membership->membership_type_id);
1733
1734 // update related contribution and financial records
1735 CRM_Price_BAO_LineItem::changeFeeSelections(
1736 $inputParams,
1737 $membership->id,
1738 'membership',
1739 $contributionID,
1740 $priceSetDetails['fields'],
1741 $lineItems
1742 );
1743 CRM_Core_Session::setStatus(ts('Associated contribution is updated on membership type change.'), ts('Success'), 'success');
1744 }
1745 }
1746
1747 /**
1748 * Add selected price field information in $formValues
1749 *
1750 * @param array $formValues
1751 * submitted form values
1752 * @param array $priceFields
1753 * Price fields of selected Priceset ID
1754 * @param int $membershipTypeID
1755 * Selected membership type ID
1756 *
1757 */
1758 public static function addPriceFieldByMembershipType(&$formValues, $priceFields, $membershipTypeID) {
1759 foreach ($priceFields as $priceFieldID => $priceField) {
1760 if (isset($priceField['options']) && count($priceField['options'])) {
1761 foreach ($priceField['options'] as $option) {
1762 if ($option['membership_type_id'] == $membershipTypeID) {
1763 $formValues["price_{$priceFieldID}"] = $option['id'];
1764 break;
1765 }
1766 }
1767 }
1768 }
1769 }
1770 /**
1771 * Set context in session.
1772 */
1773 protected function setUserContext() {
1774 $buttonName = $this->controller->getButtonName();
1775 $session = CRM_Core_Session::singleton();
1776
1777 if ($this->_context == 'standalone') {
1778 if ($buttonName == $this->getButtonName('upload', 'new')) {
1779 $session->replaceUserContext(CRM_Utils_System::url('civicrm/member/add',
1780 'reset=1&action=add&context=standalone'
1781 ));
1782 }
1783 else {
1784 $session->replaceUserContext(CRM_Utils_System::url('civicrm/contact/view',
1785 "reset=1&cid={$this->_contactID}&selectedChild=member"
1786 ));
1787 }
1788 }
1789 elseif ($buttonName == $this->getButtonName('upload', 'new')) {
1790 $session->replaceUserContext(CRM_Utils_System::url('civicrm/contact/view/membership',
1791 "reset=1&action=add&context=membership&cid={$this->_contactID}"
1792 ));
1793 }
1794 }
1795
1796 /**
1797 * Get status message for updating membership.
1798 *
1799 * @param CRM_Member_BAO_Membership $membership
1800 * @param string $endDate
1801 * @param bool $receiptSend
1802 *
1803 * @return string
1804 */
1805 protected function getStatusMessageForUpdate($membership, $endDate, $receiptSend) {
1806 // End date can be modified by hooks, so if end date is set then use it.
1807 $endDate = ($membership->end_date) ? $membership->end_date : $endDate;
1808
1809 $statusMsg = ts('Membership for %1 has been updated.', array(1 => $this->_memberDisplayName));
1810 if ($endDate && $endDate !== 'null') {
1811 $endDate = CRM_Utils_Date::customFormat($endDate);
1812 $statusMsg .= ' ' . ts('The membership End Date is %1.', array(1 => $endDate));
1813 }
1814
1815 if ($receiptSend) {
1816 $statusMsg .= ' ' . ts('A confirmation and receipt has been sent to %1.', array(1 => $this->_contributorEmail));
1817 }
1818 return $statusMsg;
1819 }
1820
1821 /**
1822 * Get status message for create action.
1823 *
1824 * @param string $endDate
1825 * @param bool $receiptSend
1826 * @param array $membershipTypes
1827 * @param array $createdMemberships
1828 * @param bool $isRecur
1829 * @param array $calcDates
1830 * @param bool $mailSent
1831 *
1832 * @return array|string
1833 */
1834 protected function getStatusMessageForCreate($endDate, $receiptSend, $membershipTypes, $createdMemberships,
1835 $isRecur, $calcDates, $mailSent) {
1836 // FIX ME: fix status messages
1837
1838 $statusMsg = array();
1839 foreach ($membershipTypes as $memType => $membershipType) {
1840 $statusMsg[$memType] = ts('%1 membership for %2 has been added.', array(
1841 1 => $membershipType,
1842 2 => $this->_memberDisplayName,
1843 ));
1844
1845 $membership = $createdMemberships[$memType];
1846 $memEndDate = ($membership->end_date) ? $membership->end_date : $endDate;
1847
1848 //get the end date from calculated dates.
1849 if (!$memEndDate && !$isRecur) {
1850 $memEndDate = CRM_Utils_Array::value('end_date', $calcDates[$memType]);
1851 }
1852
1853 if ($memEndDate && $memEndDate !== 'null') {
1854 $memEndDate = CRM_Utils_Date::customFormat($memEndDate);
1855 $statusMsg[$memType] .= ' ' . ts('The new membership End Date is %1.', array(1 => $memEndDate));
1856 }
1857 }
1858 $statusMsg = implode('<br/>', $statusMsg);
1859 if ($receiptSend && !empty($mailSent)) {
1860 $statusMsg .= ' ' . ts('A membership confirmation and receipt has been sent to %1.', array(1 => $this->_contributorEmail));
1861 }
1862 return $statusMsg;
1863 }
1864
1865 /**
1866 * @param $membership
1867 * @param $endDate
1868 * @param $receiptSend
1869 * @param $membershipTypes
1870 * @param $createdMemberships
1871 * @param $isRecur
1872 * @param $calcDates
1873 * @param $mailSend
1874 */
1875 protected function setStatusMessage($membership, $endDate, $receiptSend, $membershipTypes, $createdMemberships, $isRecur, $calcDates, $mailSend) {
1876 $statusMsg = '';
1877 if (($this->_action & CRM_Core_Action::UPDATE)) {
1878 $statusMsg = $this->getStatusMessageForUpdate($membership, $endDate, $receiptSend);
1879 }
1880 elseif (($this->_action & CRM_Core_Action::ADD)) {
1881 $statusMsg = $this->getStatusMessageForCreate($endDate, $receiptSend, $membershipTypes, $createdMemberships,
1882 $isRecur, $calcDates, $mailSend);
1883 }
1884
1885 CRM_Core_Session::setStatus($statusMsg, ts('Complete'), 'success');
1886 //CRM-15187
1887 // display message when membership type is changed
1888 if (($this->_action & CRM_Core_Action::UPDATE) && $this->_id && !in_array($this->_memType, $this->_memTypeSelected)) {
1889 $lineItem = CRM_Price_BAO_LineItem::getLineItems($this->_id, 'membership');
1890 $maxID = max(array_keys($lineItem));
1891 $lineItem = $lineItem[$maxID];
1892 $membershipTypeDetails = $this->allMembershipTypeDetails[$membership->membership_type_id];
1893 if ($membershipTypeDetails['financial_type_id'] != $lineItem['financial_type_id']) {
1894 CRM_Core_Session::setStatus(
1895 ts('The financial types associated with the old and new membership types are different. You may want to edit the contribution associated with this membership to adjust its financial type.'),
1896 ts('Warning')
1897 );
1898 }
1899 if ($membershipTypeDetails['minimum_fee'] != $lineItem['line_total']) {
1900 CRM_Core_Session::setStatus(
1901 ts('The cost of the old and new membership types are different. You may want to edit the contribution associated with this membership to adjust its amount.'),
1902 ts('Warning')
1903 );
1904 }
1905 }
1906 }
1907
1908 }