CRM-16692 follow-up fix, move assumptions back to calling-form
[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 if ($this->_id) {
1161 $ids['membership'] = $params['id'] = $this->_id;
1162 }
1163 $ids['userId'] = CRM_Core_Session::singleton()->get('userID');
1164
1165 // Set variables that we normally get from context.
1166 // In form mode these are set in preProcess.
1167 //TODO: set memberships, fixme
1168 $this->setContextVariables($formValues);
1169 $this->_memTypeSelected = self::getSelectedMemberships($priceSetID, $formValues);
1170
1171 $config = CRM_Core_Config::singleton();
1172
1173 $this->convertDateFieldsToMySQL($formValues);
1174
1175 $membershipTypeValues = array();
1176 foreach ($this->_memTypeSelected as $memType) {
1177 $membershipTypeValues[$memType]['membership_type_id'] = $memType;
1178 }
1179
1180 //take the required membership recur values.
1181 if ($this->_mode && !empty($formValues['auto_renew'])) {
1182 $params['is_recur'] = $this->_params['is_recur'] = $formValues['is_recur'] = TRUE;
1183 $mapping = array(
1184 'frequency_interval' => 'duration_interval',
1185 'frequency_unit' => 'duration_unit',
1186 );
1187
1188 $count = 0;
1189 foreach ($this->_memTypeSelected as $memType) {
1190 $recurMembershipTypeValues = CRM_Utils_Array::value($memType,
1191 $this->_recurMembershipTypes, array()
1192 );
1193 foreach ($mapping as $mapVal => $mapParam) {
1194 $membershipTypeValues[$memType][$mapVal] = CRM_Utils_Array::value($mapParam,
1195 $recurMembershipTypeValues
1196 );
1197 if (!$count) {
1198 $this->_params[$mapVal] = $formValues[$mapVal] = CRM_Utils_Array::value($mapParam,
1199 $recurMembershipTypeValues
1200 );
1201 }
1202 }
1203 $count++;
1204 }
1205 }
1206
1207 // process price set and get total amount and line items.
1208 if (!$priceSetID) {
1209 $priceSetID = CRM_Member_BAO_Membership::createLineItems(
1210 $this,
1211 $formValues['membership_type_id'],
1212 NULL
1213 );
1214 }
1215 $isQuickConfig = FALSE;
1216 if (CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $priceSetID, 'is_quick_config')) {
1217 $isQuickConfig = 1;
1218 }
1219 $termsByType = array();
1220
1221 $lineItem = array();
1222 CRM_Price_BAO_PriceSet::processAmount($this->_priceSet['fields'],
1223 $this->_params, $lineItem[$priceSetID]);
1224 if (CRM_Utils_Array::value('tax_amount', $this->_params)) {
1225 $params['tax_amount'] = $this->_params['tax_amount'];
1226 }
1227 $params['total_amount'] = CRM_Utils_Array::value('amount', $this->_params);
1228 $submittedFinancialType = CRM_Utils_Array::value('financial_type_id', $formValues);
1229 if (!empty($lineItem[$priceSetID])) {
1230 foreach ($lineItem[$priceSetID] as &$li) {
1231 if (!empty($li['membership_type_id'])) {
1232 if (!empty($li['membership_num_terms'])) {
1233 $termsByType[$li['membership_type_id']] = $li['membership_num_terms'];
1234 }
1235 }
1236
1237 ///CRM-11529 for quick config backoffice transactions
1238 //when financial_type_id is passed in form, update the
1239 //lineitems with the financial type selected in form
1240 if ($isQuickConfig && $submittedFinancialType) {
1241 $li['financial_type_id'] = $submittedFinancialType;
1242 }
1243 }
1244 }
1245
1246 $this->storeContactFields($formValues);
1247
1248 $params['contact_id'] = $this->_contactID;
1249
1250 $fields = array(
1251 'status_id',
1252 'source',
1253 'is_override',
1254 'campaign_id',
1255 );
1256
1257 foreach ($fields as $f) {
1258 $params[$f] = CRM_Utils_Array::value($f, $formValues);
1259 }
1260
1261 // fix for CRM-3724
1262 // when is_override false ignore is_admin statuses during membership
1263 // status calculation. similarly we did fix for import in CRM-3570.
1264 if (empty($params['is_override'])) {
1265 $params['exclude_is_admin'] = TRUE;
1266 }
1267
1268 // process date params to mysql date format.
1269 $dateTypes = array(
1270 'join_date' => 'joinDate',
1271 'start_date' => 'startDate',
1272 'end_date' => 'endDate',
1273 );
1274 foreach ($dateTypes as $dateField => $dateVariable) {
1275 $$dateVariable = CRM_Utils_Date::processDate($formValues[$dateField]);
1276 }
1277
1278 $memTypeNumTerms = empty($termsByType) ? CRM_Utils_Array::value('num_terms', $formValues) : NULL;
1279
1280 $calcDates = array();
1281 foreach ($this->_memTypeSelected as $memType) {
1282 if (empty($memTypeNumTerms)) {
1283 $memTypeNumTerms = CRM_Utils_Array::value($memType, $termsByType, 1);
1284 }
1285 $calcDates[$memType] = CRM_Member_BAO_MembershipType::getDatesForMembershipType($memType,
1286 $joinDate, $startDate, $endDate, $memTypeNumTerms
1287 );
1288 }
1289
1290 foreach ($calcDates as $memType => $calcDate) {
1291 foreach (array_keys($dateTypes) as $d) {
1292 //first give priority to form values then calDates.
1293 $date = CRM_Utils_Array::value($d, $formValues);
1294 if (!$date) {
1295 $date = CRM_Utils_Array::value($d, $calcDate);
1296 }
1297
1298 $membershipTypeValues[$memType][$d] = CRM_Utils_Date::processDate($date);
1299 }
1300 }
1301
1302 // max related memberships - take from form or inherit from membership type
1303 foreach ($this->_memTypeSelected as $memType) {
1304 if (array_key_exists('max_related', $formValues)) {
1305 $membershipTypeValues[$memType]['max_related'] = CRM_Utils_Array::value('max_related', $formValues);
1306 }
1307 $membershipTypeValues[$memType]['custom'] = CRM_Core_BAO_CustomField::postProcess($formValues,
1308 $this->_id,
1309 'Membership'
1310 );
1311 $membershipTypes[$memType] = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_MembershipType',
1312 $memType
1313 );
1314 }
1315
1316 $membershipType = implode(', ', $membershipTypes);
1317
1318 // Retrieve the name and email of the current user - this will be the FROM for the receipt email
1319 list($userName) = CRM_Contact_BAO_Contact_Location::getEmailDetails($ids['userId']);
1320
1321 //CRM-13981, allow different person as a soft-contributor of chosen type
1322 if ($this->_contributorContactID != $this->_contactID) {
1323 $params['contribution_contact_id'] = $this->_contributorContactID;
1324 if (!empty($this->_params['soft_credit_type_id'])) {
1325 $softParams['soft_credit_type_id'] = $this->_params['soft_credit_type_id'];
1326 $softParams['contact_id'] = $this->_contactID;
1327 }
1328 }
1329 if (!empty($formValues['record_contribution'])) {
1330 $recordContribution = array(
1331 'total_amount',
1332 'financial_type_id',
1333 'payment_instrument_id',
1334 'trxn_id',
1335 'contribution_status_id',
1336 'check_number',
1337 'campaign_id',
1338 'receive_date',
1339 );
1340
1341 foreach ($recordContribution as $f) {
1342 $params[$f] = CRM_Utils_Array::value($f, $formValues);
1343 }
1344
1345 if (!$this->_onlinePendingContributionId) {
1346 if (empty($formValues['source'])) {
1347 $params['contribution_source'] = ts('%1 Membership: Offline signup (by %2)', array(
1348 1 => $membershipType,
1349 2 => $userName,
1350 ));
1351 }
1352 else {
1353 $params['contribution_source'] = $formValues['source'];
1354 }
1355 }
1356
1357 if (empty($params['is_override']) &&
1358 CRM_Utils_Array::value('contribution_status_id', $params) == array_search('Pending', CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name'))
1359 ) {
1360 $params['status_id'] = array_search('Pending', $allMemberStatus);
1361 $params['skipStatusCal'] = TRUE;
1362 $params['is_pay_later'] = 1;
1363 $this->assign('is_pay_later', 1);
1364 }
1365
1366 if (!empty($formValues['send_receipt'])) {
1367 $params['receipt_date'] = CRM_Utils_Array::value('receive_date', $formValues);
1368 }
1369
1370 //insert financial type name in receipt.
1371 $formValues['contributionType_name'] = CRM_Core_DAO::getFieldValue('CRM_Financial_DAO_FinancialType',
1372 $formValues['financial_type_id']
1373 );
1374 }
1375
1376 // process line items, until no previous line items.
1377 if (!empty($lineItem)) {
1378 $params['lineItems'] = $lineItem;
1379 $params['processPriceSet'] = TRUE;
1380 }
1381 $createdMemberships = array();
1382 if ($this->_mode) {
1383 if (empty($formValues['total_amount']) && !$priceSetID) {
1384 // if total amount not provided minimum for membership type is used
1385 $params['total_amount'] = $formValues['total_amount'] = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_MembershipType',
1386 $formValues['membership_type_id'][1], 'minimum_fee'
1387 );
1388 }
1389 else {
1390 $params['total_amount'] = CRM_Utils_Array::value('total_amount', $formValues, 0);
1391 }
1392
1393 if ($priceSetID && !$isQuickConfig) {
1394 $params['financial_type_id'] = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet',
1395 $priceSetID,
1396 'financial_type_id'
1397 );
1398 }
1399 else {
1400 $params['financial_type_id'] = CRM_Utils_Array::value('financial_type_id', $formValues);
1401 }
1402
1403 $this->_paymentProcessor = CRM_Financial_BAO_PaymentProcessor::getPayment($formValues['payment_processor_id'],
1404 $this->_mode
1405 );
1406
1407 //get the payment processor id as per mode.
1408 $params['payment_processor_id'] = $this->_params['payment_processor_id'] = $formValues['payment_processor_id'] = $this->_paymentProcessor['id'];
1409
1410 $now = date('YmdHis');
1411 $fields = array();
1412
1413 // set email for primary location.
1414 $fields['email-Primary'] = 1;
1415 $formValues['email-5'] = $formValues['email-Primary'] = $this->_memberEmail;
1416 $params['register_date'] = $now;
1417
1418 // now set the values for the billing location.
1419 foreach ($this->_fields as $name => $dontCare) {
1420 $fields[$name] = 1;
1421 }
1422
1423 // also add location name to the array
1424 $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);
1425
1426 $formValues["address_name-{$this->_bltID}"] = trim($formValues["address_name-{$this->_bltID}"]);
1427
1428 $fields["address_name-{$this->_bltID}"] = 1;
1429 //ensure we don't over-write the payer's email with the member's email
1430 if ($this->_contributorContactID == $this->_contactID) {
1431 $fields["email-{$this->_bltID}"] = 1;
1432 }
1433
1434 $nameFields = array('first_name', 'middle_name', 'last_name');
1435
1436 foreach ($nameFields as $name) {
1437 $fields[$name] = 1;
1438 if (array_key_exists("billing_$name", $formValues)) {
1439 $formValues[$name] = $formValues["billing_{$name}"];
1440 $formValues['preserveDBName'] = TRUE;
1441 }
1442 }
1443 if ($this->_contributorContactID == $this->_contactID) {
1444 //see CRM-12869 for discussion of why we don't do this for separate payee payments
1445 CRM_Contact_BAO_Contact::createProfileContact($formValues, $fields,
1446 $this->_contributorContactID, NULL, NULL,
1447 CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $this->_contactID, 'contact_type')
1448 );
1449 }
1450
1451 // add all the additional payment params we need
1452 $this->_params["state_province-{$this->_bltID}"] = $this->_params["billing_state_province-{$this->_bltID}"]
1453 = CRM_Core_PseudoConstant::stateProvinceAbbreviation($formValues["billing_state_province_id-{$this->_bltID}"]);
1454 $this->_params["country-{$this->_bltID}"] = $this->_params["billing_country-{$this->_bltID}"] = CRM_Core_PseudoConstant::countryIsoCode($formValues["billing_country_id-{$this->_bltID}"]);
1455
1456 $this->_params['year'] = CRM_Core_Payment_Form::getCreditCardExpirationYear($formValues);
1457 $this->_params['month'] = CRM_Core_Payment_Form::getCreditCardExpirationMonth($formValues);
1458 $this->_params['ip_address'] = CRM_Utils_System::ipAddress();
1459 $this->_params['amount'] = $params['total_amount'];
1460 $this->_params['currencyID'] = $config->defaultCurrency;
1461 $this->_params['description'] = ts("Contribution submitted by a staff person using member's credit card for signup");
1462 $this->_params['invoiceID'] = md5(uniqid(rand(), TRUE));
1463 $this->_params['financial_type_id'] = $params['financial_type_id'];
1464
1465 // at this point we've created a contact and stored its address etc
1466 // all the payment processors expect the name and address to be in the
1467 // so we copy stuff over to first_name etc.
1468 $paymentParams = $this->_params;
1469 $paymentParams['contactID'] = $this->_contributorContactID;
1470 //CRM-10377 if payment is by an alternate contact then we need to set that person
1471 // as the contact in the payment params
1472 if ($this->_contributorContactID != $this->_contactID) {
1473 if (!empty($this->_params['soft_credit_type_id'])) {
1474 $softParams['contact_id'] = $params['contact_id'];
1475 $softParams['soft_credit_type_id'] = $this->_params['soft_credit_type_id'];
1476 }
1477 }
1478 if (!empty($this->_params['send_receipt'])) {
1479 $paymentParams['email'] = $this->_contributorEmail;
1480 }
1481
1482 CRM_Core_Payment_Form::mapParams($this->_bltID, $this->_params, $paymentParams, TRUE);
1483
1484 // CRM-7137 -for recurring membership,
1485 // we do need contribution and recurring records.
1486 $result = NULL;
1487 if (!empty($paymentParams['is_recur'])) {
1488 $financialType = new CRM_Financial_DAO_FinancialType();
1489 $financialType->id = $params['financial_type_id'];
1490 $financialType->find(TRUE);
1491
1492 $contribution = CRM_Contribute_Form_Contribution_Confirm::processFormContribution($this,
1493 $paymentParams,
1494 NULL,
1495 array(
1496 'contact_id' => $this->_contributorContactID,
1497 'line_item' => $lineItem,
1498 'is_test' => $isTest,
1499 'campaign_id' => CRM_Utils_Array::value('campaign_id', $paymentParams),
1500 'contribution_page_id' => CRM_Utils_Array::value('contribution_page_id', $this->_params),
1501 'source' => CRM_Utils_Array::value('source', $paymentParams, CRM_Utils_Array::value('description', $paymentParams)),
1502 'thankyou_date' => CRM_Utils_Array::value('thankyou_date', $paymentParams),
1503 'payment_instrument_id' => $this->_paymentProcessor['payment_instrument_id'],
1504 ),
1505 $financialType,
1506 TRUE,
1507 FALSE,
1508 $this->_bltID
1509 );
1510
1511 //create new soft-credit record, CRM-13981
1512 if ($softParams) {
1513 $softParams['contribution_id'] = $contribution->id;
1514 $softParams['currency'] = $contribution->currency;
1515 $softParams['amount'] = $contribution->total_amount;
1516 CRM_Contribute_BAO_ContributionSoft::add($softParams);
1517 }
1518
1519 $paymentParams['contactID'] = $this->_contactID;
1520 $paymentParams['contributionID'] = $contribution->id;
1521 $paymentParams['contributionTypeID'] = $contribution->financial_type_id;
1522 $paymentParams['contributionPageID'] = $contribution->contribution_page_id;
1523 $paymentParams['contributionRecurID'] = $contribution->contribution_recur_id;
1524 $ids['contribution'] = $contribution->id;
1525 $params['contribution_recur_id'] = $paymentParams['contributionRecurID'];
1526 }
1527
1528 if ($params['total_amount'] > 0.0) {
1529 $payment = $this->_paymentProcessor['object'];
1530 try {
1531 $result = $payment->doPayment($paymentParams);
1532 $this->_params = array_merge($this->_params, $result);
1533 // Assign amount to template if payment was successful.
1534 $this->assign('amount', $params['total_amount']);
1535 }
1536 catch (PaymentProcessorException $e) {
1537 if (!empty($paymentParams['contributionID'])) {
1538 CRM_Contribute_BAO_Contribution::failPayment($paymentParams['contributionID'], $this->_contactID,
1539 $e->getMessage());
1540 }
1541 if (!empty($paymentParams['contributionRecurID'])) {
1542 CRM_Contribute_BAO_ContributionRecur::deleteRecurContribution($paymentParams['contributionRecurID']);
1543 }
1544
1545 CRM_Core_Error::displaySessionError($result);
1546 CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/contact/view/membership',
1547 "reset=1&action=add&cid={$this->_contactID}&context=&mode={$this->_mode}"
1548 ));
1549
1550 }
1551 }
1552
1553 if ($this->_params['payment_status_id'] != array_search('Completed', $allContributionStatus)) {
1554 $params['status_id'] = array_search('Pending', $allMemberStatus);
1555 $params['skipStatusCal'] = TRUE;
1556 // unset send-receipt option, since receipt will be sent when ipn is received.
1557 unset($this->_params['send_receipt'], $formValues['send_receipt']);
1558 //as membership is pending set dates to null.
1559 $memberDates = array(
1560 'join_date' => 'joinDate',
1561 'start_date' => 'startDate',
1562 'end_date' => 'endDate',
1563 );
1564 foreach ($memberDates as $dv) {
1565 $$dv = NULL;
1566 foreach ($this->_memTypeSelected as $memType) {
1567 $membershipTypeValues[$memType][$dv] = NULL;
1568 }
1569 }
1570 }
1571 $params['receive_date'] = $now;
1572 $params['invoice_id'] = $this->_params['invoiceID'];
1573 $params['contribution_source'] = ts('%1 Membership Signup: Credit card or direct debit (by %2)',
1574 array(1 => $membershipType, 2 => $userName)
1575 );
1576 $params['source'] = $formValues['source'] ? $formValues['source'] : $params['contribution_source'];
1577 $params['trxn_id'] = CRM_Utils_Array::value('trxn_id', $result);
1578 $params['payment_instrument_id'] = 1;
1579 $params['is_test'] = ($this->_mode == 'live') ? 0 : 1;
1580 if (!empty($this->_params['send_receipt'])) {
1581 $params['receipt_date'] = $now;
1582 }
1583 else {
1584 $params['receipt_date'] = NULL;
1585 }
1586
1587 $this->set('params', $this->_params);
1588 $this->assign('trxn_id', CRM_Utils_Array::value('trxn_id', $result));
1589 $this->assign('receive_date',
1590 CRM_Utils_Date::mysqlToIso($params['receive_date'])
1591 );
1592
1593 // required for creating membership for related contacts
1594 $params['action'] = $this->_action;
1595
1596 //create membership record.
1597 $count = 0;
1598 foreach ($this->_memTypeSelected as $memType) {
1599 if ($count &&
1600 ($relateContribution = CRM_Member_BAO_Membership::getMembershipContributionId($membership->id))
1601 ) {
1602 $membershipTypeValues[$memType]['relate_contribution_id'] = $relateContribution;
1603 }
1604
1605 $membershipParams = array_merge($membershipTypeValues[$memType], $params);
1606 //CRM-15366
1607 if (!empty($softParams) && empty($paymentParams['is_recur'])) {
1608 $membershipParams['soft_credit'] = $softParams;
1609 }
1610 // This is required to trigger the recording of the membership contribution in the
1611 // CRM_Member_BAO_Membership::Create function.
1612 // @todo stop setting this & 'teach' the create function to respond to something
1613 // appropriate as part of our 2-step always create the pending contribution & then finally add the payment
1614 // process -
1615 // @see http://wiki.civicrm.org/confluence/pages/viewpage.action?pageId=261062657#Payments&AccountsRoadmap-Movetowardsalwaysusinga2-steppaymentprocess
1616 $membershipParams['contribution_status_id'] = CRM_Utils_Array::value('payment_status_id', $result);
1617 $membership = CRM_Member_BAO_Membership::create($membershipParams, $ids);
1618 $params['contribution'] = CRM_Utils_Array::value('contribution', $membershipParams);
1619 unset($params['lineItems']);
1620 $this->_membershipIDs[] = $membership->id;
1621 $createdMemberships[$memType] = $membership;
1622 $count++;
1623 }
1624
1625 }
1626 else {
1627 $params['action'] = $this->_action;
1628 if ($this->_onlinePendingContributionId && !empty($formValues['record_contribution'])) {
1629
1630 // update membership as well as contribution object, CRM-4395
1631 $params['contribution_id'] = $this->_onlinePendingContributionId;
1632 $params['componentId'] = $params['id'];
1633 $params['componentName'] = 'contribute';
1634 $result = CRM_Contribute_BAO_Contribution::transitionComponents($params, TRUE);
1635 if (!empty($result) && !empty($params['contribution_id'])) {
1636 $lineItem = array();
1637 $lineItems = CRM_Price_BAO_LineItem::getLineItems($params['contribution_id'], 'contribution', NULL, TRUE, TRUE);
1638 $itemId = key($lineItems);
1639 $priceSetId = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceField', $lineItems[$itemId]['price_field_id'], 'price_set_id');
1640
1641 $lineItems[$itemId]['unit_price'] = $params['total_amount'];
1642 $lineItems[$itemId]['line_total'] = $params['total_amount'];
1643 $lineItems[$itemId]['id'] = $itemId;
1644 $lineItem[$priceSetId] = $lineItems;
1645 $contributionBAO = new CRM_Contribute_BAO_Contribution();
1646 $contributionBAO->id = $params['contribution_id'];
1647 $contributionBAO->contact_id = $params['contact_id'];
1648 $contributionBAO->find();
1649 CRM_Price_BAO_LineItem::processPriceSet($params['contribution_id'], $lineItem, $contributionBAO, 'civicrm_membership');
1650
1651 //create new soft-credit record, CRM-13981
1652 if ($softParams) {
1653 $softParams['contribution_id'] = $params['contribution_id'];
1654 while ($contributionBAO->fetch()) {
1655 $softParams['currency'] = $contributionBAO->currency;
1656 $softParams['amount'] = $contributionBAO->total_amount;
1657 }
1658 CRM_Contribute_BAO_ContributionSoft::add($softParams);
1659 }
1660 }
1661
1662 //carry updated membership object.
1663 $membership = new CRM_Member_DAO_Membership();
1664 $membership->id = $this->_id;
1665 $membership->find(TRUE);
1666
1667 $cancelled = TRUE;
1668 if ($membership->end_date) {
1669 //display end date w/ status message.
1670 $endDate = $membership->end_date;
1671
1672 if (!in_array($membership->status_id, array(
1673 // CRM-15475
1674 array_search('Cancelled', CRM_Member_PseudoConstant::membershipStatus(NULL, " name = 'Cancelled' ", 'name', FALSE, TRUE)),
1675 array_search('Expired', CRM_Member_PseudoConstant::membershipStatus()),
1676 ))
1677 ) {
1678 $cancelled = FALSE;
1679 }
1680 }
1681 // suppress form values in template.
1682 $this->assign('cancelled', $cancelled);
1683
1684 $createdMemberships[] = $membership;
1685 }
1686 else {
1687 $count = 0;
1688 foreach ($this->_memTypeSelected as $memType) {
1689 if ($count && !empty($formValues['record_contribution']) &&
1690 ($relateContribution = CRM_Member_BAO_Membership::getMembershipContributionId($membership->id))
1691 ) {
1692 $membershipTypeValues[$memType]['relate_contribution_id'] = $relateContribution;
1693 }
1694
1695 $membershipParams = array_merge($params, $membershipTypeValues[$memType]);
1696 if (!empty($formValues['int_amount'])) {
1697 $init_amount = array();
1698 foreach ($formValues as $key => $value) {
1699 if (strstr($key, 'txt-price')) {
1700 $init_amount[$key] = $value;
1701 }
1702 }
1703 $membershipParams['init_amount'] = $init_amount;
1704 }
1705
1706 if (!empty($softParams)) {
1707 $membershipParams['soft_credit'] = $softParams;
1708 }
1709
1710 $membership = CRM_Member_BAO_Membership::create($membershipParams, $ids);
1711 $params['contribution'] = CRM_Utils_Array::value('contribution', $membershipParams);
1712 unset($params['lineItems']);
1713
1714 $this->_membershipIDs[] = $membership->id;
1715 $createdMemberships[$memType] = $membership;
1716 $count++;
1717 }
1718 }
1719 }
1720
1721 if (!empty($lineItem[$priceSetID])) {
1722 $invoiceSettings = CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::CONTRIBUTE_PREFERENCES_NAME, 'contribution_invoice_settings');
1723 $invoicing = CRM_Utils_Array::value('invoicing', $invoiceSettings);
1724 $taxAmount = FALSE;
1725 $totalTaxAmount = 0;
1726 foreach ($lineItem[$priceSetID] as & $priceFieldOp) {
1727 if (!empty($priceFieldOp['membership_type_id'])) {
1728 $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') : '-';
1729 $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') : '-';
1730 }
1731 else {
1732 $priceFieldOp['start_date'] = $priceFieldOp['end_date'] = 'N/A';
1733 }
1734 if ($invoicing && isset($priceFieldOp['tax_amount'])) {
1735 $taxAmount = TRUE;
1736 $totalTaxAmount += $priceFieldOp['tax_amount'];
1737 }
1738 }
1739 if ($invoicing) {
1740 $dataArray = array();
1741 foreach ($lineItem[$priceSetID] as $key => $value) {
1742 if (isset($value['tax_amount']) && isset($value['tax_rate'])) {
1743 if (isset($dataArray[$value['tax_rate']])) {
1744 $dataArray[$value['tax_rate']] = $dataArray[$value['tax_rate']] + CRM_Utils_Array::value('tax_amount', $value);
1745 }
1746 else {
1747 $dataArray[$value['tax_rate']] = CRM_Utils_Array::value('tax_amount', $value);
1748 }
1749 }
1750 }
1751 if ($taxAmount) {
1752 $this->assign('totalTaxAmount', $totalTaxAmount);
1753 $this->assign('taxTerm', CRM_Utils_Array::value('tax_term', $invoiceSettings));
1754 }
1755 $this->assign('dataArray', $dataArray);
1756 }
1757 }
1758 $this->assign('lineItem', !empty($lineItem) && !$isQuickConfig ? $lineItem : FALSE);
1759
1760 $receiptSend = FALSE;
1761 $contributionId = CRM_Member_BAO_Membership::getMembershipContributionId($membership->id);
1762 $membershipIds = $this->_membershipIDs;
1763 if ($contributionId && !empty($membershipIds)) {
1764 $contributionDetails = CRM_Contribute_BAO_Contribution::getContributionDetails(
1765 CRM_Export_Form_Select::MEMBER_EXPORT, $this->_membershipIDs);
1766 if ($contributionDetails[$membership->id]['contribution_status'] == 'Completed') {
1767 $receiptSend = TRUE;
1768 }
1769 }
1770
1771 if (!empty($formValues['send_receipt']) && $receiptSend) {
1772 $formValues['contact_id'] = $this->_contactID;
1773 $formValues['contribution_id'] = $contributionId;
1774 // We really don't need a distinct receipt_text_signup vs receipt_text_renewal as they are
1775 // handled in the receipt. But by setting one we avoid breaking templates for now
1776 // although at some point we should switch in the templates.
1777 $formValues['receipt_text_signup'] = $formValues['receipt_text'];
1778 // send email receipt
1779 $mailSend = self::emailReceipt($this, $formValues, $membership);
1780 }
1781
1782 // finally set membership id if already not set
1783 if (!$this->_id) {
1784 $this->_id = $membership->id;
1785 }
1786
1787 $statusMsg = '';
1788 if (($this->_action & CRM_Core_Action::UPDATE)) {
1789 $statusMsg = $this->getStatusMessageForUpdate($membership, $endDate, $receiptSend);
1790 }
1791 elseif (($this->_action & CRM_Core_Action::ADD)) {
1792 $statusMsg = $this->getStatusMessageForCreate($endDate, $receiptSend, $membershipTypes, $createdMemberships,
1793 $params, $calcDates, $mailSend);
1794 }
1795
1796 CRM_Core_Session::setStatus($statusMsg, ts('Complete'), 'success');
1797 //CRM-15187
1798 // dusplay message when membership type is changed
1799 if (($this->_action & CRM_Core_Action::UPDATE) && $this->_id && !in_array($this->_memType, $this->_memTypeSelected)) {
1800 CRM_Core_Session::setStatus(
1801 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.'),
1802 ts('Warning')
1803 );
1804 CRM_Core_Session::setStatus(
1805 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.'),
1806 ts('Warning')
1807 );
1808 }
1809 return $createdMemberships;
1810 }
1811
1812 /**
1813 * Set context in session.
1814 */
1815 protected function setUserContext() {
1816 $buttonName = $this->controller->getButtonName();
1817 $session = CRM_Core_Session::singleton();
1818
1819 if ($this->_context == 'standalone') {
1820 if ($buttonName == $this->getButtonName('upload', 'new')) {
1821 $session->replaceUserContext(CRM_Utils_System::url('civicrm/member/add',
1822 'reset=1&action=add&context=standalone'
1823 ));
1824 }
1825 else {
1826 $session->replaceUserContext(CRM_Utils_System::url('civicrm/contact/view',
1827 "reset=1&cid={$this->_contactID}&selectedChild=member"
1828 ));
1829 }
1830 }
1831 elseif ($buttonName == $this->getButtonName('upload', 'new')) {
1832 $session->replaceUserContext(CRM_Utils_System::url('civicrm/contact/view/membership',
1833 "reset=1&action=add&context=membership&cid={$this->_contactID}"
1834 ));
1835 }
1836 }
1837
1838 /**
1839 * Get status message for updating membership.
1840 *
1841 * @param CRM_Member_BAO_Membership $membership
1842 * @param string $endDate
1843 * @param bool $receiptSend
1844 *
1845 * @return string
1846 */
1847 protected function getStatusMessageForUpdate($membership, $endDate, $receiptSend) {
1848 // End date can be modified by hooks, so if end date is set then use it.
1849 $endDate = ($membership->end_date) ? $membership->end_date : $endDate;
1850
1851 $statusMsg = ts('Membership for %1 has been updated.', array(1 => $this->_memberDisplayName));
1852 if ($endDate && $endDate !== 'null') {
1853 $endDate = CRM_Utils_Date::customFormat($endDate);
1854 $statusMsg .= ' ' . ts('The membership End Date is %1.', array(1 => $endDate));
1855 }
1856
1857 if ($receiptSend) {
1858 $statusMsg .= ' ' . ts('A confirmation and receipt has been sent to %1.', array(1 => $this->_contributorEmail));
1859 }
1860 return $statusMsg;
1861 }
1862
1863 /**
1864 * Get status message for create action.
1865 *
1866 * @param string $endDate
1867 * @param bool $receiptSend
1868 * @param array $membershipTypes
1869 * @param array $createdMemberships
1870 * @param array $params
1871 * @param array $calcDates
1872 * @param bool $mailSent
1873 *
1874 * @return array|string
1875 */
1876 protected function getStatusMessageForCreate($endDate, $receiptSend, $membershipTypes, $createdMemberships,
1877 $params, $calcDates, $mailSent) {
1878 // FIX ME: fix status messages
1879
1880 $statusMsg = array();
1881 foreach ($membershipTypes as $memType => $membershipType) {
1882 $statusMsg[$memType] = ts('%1 membership for %2 has been added.', array(
1883 1 => $membershipType,
1884 2 => $this->_memberDisplayName,
1885 ));
1886
1887 $membership = $createdMemberships[$memType];
1888 $memEndDate = ($membership->end_date) ? $membership->end_date : $endDate;
1889
1890 //get the end date from calculated dates.
1891 if (!$memEndDate && empty($params['is_recur'])) {
1892 $memEndDate = CRM_Utils_Array::value('end_date', $calcDates[$memType]);
1893 }
1894
1895 if ($memEndDate && $memEndDate !== 'null') {
1896 $memEndDate = CRM_Utils_Date::customFormat($memEndDate);
1897 $statusMsg[$memType] .= ' ' . ts('The new membership End Date is %1.', array(1 => $memEndDate));
1898 }
1899 }
1900 $statusMsg = implode('<br/>', $statusMsg);
1901 if ($receiptSend && !empty($mailSent)) {
1902 $statusMsg .= ' ' . ts('A membership confirmation and receipt has been sent to %1.', array(1 => $this->_contributorEmail));
1903 }
1904 return $statusMsg;
1905 }
1906
1907 }