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