Merge pull request #9746 from vedantrathore/master
[civicrm-core.git] / CRM / Member / Import / Parser / Membership.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.7 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2017 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26 */
27
28 /**
29 *
30 * @package CRM
31 * @copyright CiviCRM LLC (c) 2004-2017
32 * $Id$
33 *
34 */
35
36
37 require_once 'api/api.php';
38
39 /**
40 * class to parse membership csv files
41 */
42 class CRM_Member_Import_Parser_Membership extends CRM_Member_Import_Parser {
43
44 protected $_mapperKeys;
45
46 private $_contactIdIndex;
47 private $_totalAmountIndex;
48 private $_membershipTypeIndex;
49 private $_membershipStatusIndex;
50
51 /**
52 * Array of successfully imported membership id's
53 *
54 * @array
55 */
56 protected $_newMemberships;
57
58 /**
59 * Class constructor.
60 *
61 * @param $mapperKeys
62 * @param null $mapperLocType
63 * @param null $mapperPhoneType
64 */
65 public function __construct(&$mapperKeys, $mapperLocType = NULL, $mapperPhoneType = NULL) {
66 parent::__construct();
67 $this->_mapperKeys = &$mapperKeys;
68 }
69
70 /**
71 * The initializer code, called before the processing
72 *
73 * @return void
74 */
75 public function init() {
76 $fields = CRM_Member_BAO_Membership::importableFields($this->_contactType, FALSE);
77
78 foreach ($fields as $name => $field) {
79 $field['type'] = CRM_Utils_Array::value('type', $field, CRM_Utils_Type::T_INT);
80 $field['dataPattern'] = CRM_Utils_Array::value('dataPattern', $field, '//');
81 $field['headerPattern'] = CRM_Utils_Array::value('headerPattern', $field, '//');
82 $this->addField($name, $field['title'], $field['type'], $field['headerPattern'], $field['dataPattern']);
83 }
84
85 $this->_newMemberships = array();
86
87 $this->setActiveFields($this->_mapperKeys);
88
89 // FIXME: we should do this in one place together with Form/MapField.php
90 $this->_contactIdIndex = -1;
91 $this->_membershipTypeIndex = -1;
92 $this->_membershipStatusIndex = -1;
93
94 $index = 0;
95 foreach ($this->_mapperKeys as $key) {
96 switch ($key) {
97 case 'membership_contact_id':
98 $this->_contactIdIndex = $index;
99 break;
100
101 case 'membership_type_id':
102 $this->_membershipTypeIndex = $index;
103 break;
104
105 case 'status_id':
106 $this->_membershipStatusIndex = $index;
107 break;
108 }
109 $index++;
110 }
111 }
112
113 /**
114 * Handle the values in mapField mode.
115 *
116 * @param array $values
117 * The array of values belonging to this line.
118 *
119 * @return bool
120 */
121 public function mapField(&$values) {
122 return CRM_Import_Parser::VALID;
123 }
124
125 /**
126 * Handle the values in preview mode.
127 *
128 * @param array $values
129 * The array of values belonging to this line.
130 *
131 * @return bool
132 * the result of this processing
133 */
134 public function preview(&$values) {
135 return $this->summary($values);
136 }
137
138 /**
139 * Handle the values in summary mode.
140 *
141 * @param array $values
142 * The array of values belonging to this line.
143 *
144 * @return bool
145 * the result of this processing
146 */
147 public function summary(&$values) {
148 $erroneousField = NULL;
149 $response = $this->setActiveFieldValues($values, $erroneousField);
150
151 $errorRequired = FALSE;
152
153 if ($this->_membershipTypeIndex < 0) {
154 $errorRequired = TRUE;
155 }
156 else {
157 $errorRequired = !CRM_Utils_Array::value($this->_membershipTypeIndex, $values);
158 }
159
160 if ($errorRequired) {
161 array_unshift($values, ts('Missing required fields'));
162 return CRM_Import_Parser::ERROR;
163 }
164
165 $params = $this->getActiveFieldParams();
166 $errorMessage = NULL;
167
168 //To check whether start date or join date is provided
169 if (empty($params['membership_start_date']) && empty($params['join_date'])) {
170 $errorMessage = 'Membership Start Date is required to create a memberships.';
171 CRM_Contact_Import_Parser_Contact::addToErrorMsg('Start Date', $errorMessage);
172 }
173
174 //for date-Formats
175 $session = CRM_Core_Session::singleton();
176 $dateType = $session->get('dateTypes');
177 foreach ($params as $key => $val) {
178
179 if ($val) {
180 switch ($key) {
181 case 'join_date':
182 if (CRM_Utils_Date::convertToDefaultDate($params, $dateType, $key)) {
183 if (!CRM_Utils_Rule::date($params[$key])) {
184 CRM_Contact_Import_Parser_Contact::addToErrorMsg('Member Since', $errorMessage);
185 }
186 }
187 else {
188 CRM_Contact_Import_Parser_Contact::addToErrorMsg('Member Since', $errorMessage);
189 }
190 break;
191
192 case 'membership_start_date':
193 if (CRM_Utils_Date::convertToDefaultDate($params, $dateType, $key)) {
194 if (!CRM_Utils_Rule::date($params[$key])) {
195 CRM_Contact_Import_Parser_Contact::addToErrorMsg('Start Date', $errorMessage);
196 }
197 }
198 else {
199 CRM_Contact_Import_Parser_Contact::addToErrorMsg('Start Date', $errorMessage);
200 }
201 break;
202
203 case 'membership_end_date':
204 if (CRM_Utils_Date::convertToDefaultDate($params, $dateType, $key)) {
205 if (!CRM_Utils_Rule::date($params[$key])) {
206 CRM_Contact_Import_Parser_Contact::addToErrorMsg('End date', $errorMessage);
207 }
208 }
209 else {
210 CRM_Contact_Import_Parser_Contact::addToErrorMsg('End date', $errorMessage);
211 }
212 break;
213
214 case 'membership_type_id':
215 $membershipTypes = CRM_Member_PseudoConstant::membershipType();
216 if (!CRM_Utils_Array::crmInArray($val, $membershipTypes) &&
217 !array_key_exists($val, $membershipTypes)
218 ) {
219 CRM_Contact_Import_Parser_Contact::addToErrorMsg('Membership Type', $errorMessage);
220 }
221 break;
222
223 case 'status_id':
224 if (!CRM_Utils_Array::crmInArray($val, CRM_Member_PseudoConstant::membershipStatus())) {
225 CRM_Contact_Import_Parser_Contact::addToErrorMsg('Membership Status', $errorMessage);
226 }
227 break;
228
229 case 'email':
230 if (!CRM_Utils_Rule::email($val)) {
231 CRM_Contact_Import_Parser_Contact::addToErrorMsg('Email Address', $errorMessage);
232 }
233 }
234 }
235 }
236 //date-Format part ends
237
238 $params['contact_type'] = 'Membership';
239
240 //checking error in custom data
241 CRM_Contact_Import_Parser_Contact::isErrorInCustomData($params, $errorMessage);
242
243 if ($errorMessage) {
244 $tempMsg = "Invalid value for field(s) : $errorMessage";
245 array_unshift($values, $tempMsg);
246 $errorMessage = NULL;
247 return CRM_Import_Parser::ERROR;
248 }
249
250 return CRM_Import_Parser::VALID;
251 }
252
253 /**
254 * Handle the values in import mode.
255 *
256 * @param int $onDuplicate
257 * The code for what action to take on duplicates.
258 * @param array $values
259 * The array of values belonging to this line.
260 *
261 * @return bool
262 * the result of this processing
263 */
264 public function import($onDuplicate, &$values) {
265 try {
266 // first make sure this is a valid line
267 $response = $this->summary($values);
268 if ($response != CRM_Import_Parser::VALID) {
269 return $response;
270 }
271
272 $params = $this->getActiveFieldParams();
273
274 //assign join date equal to start date if join date is not provided
275 if (empty($params['join_date']) && !empty($params['membership_start_date'])) {
276 $params['join_date'] = $params['membership_start_date'];
277 }
278
279 $session = CRM_Core_Session::singleton();
280 $dateType = $session->get('dateTypes');
281 $formatted = array();
282 $customDataType = !empty($params['contact_type']) ? $params['contact_type'] : 'Membership';
283 $customFields = CRM_Core_BAO_CustomField::getFields($customDataType);
284
285 // don't add to recent items, CRM-4399
286 $formatted['skipRecentView'] = TRUE;
287 $dateLabels = array(
288 'join_date' => ts('Member Since'),
289 'membership_start_date' => ts('Start Date'),
290 'membership_end_date' => ts('End Date'),
291 );
292 foreach ($params as $key => $val) {
293 if ($val) {
294 switch ($key) {
295 case 'join_date':
296 case 'membership_start_date':
297 case 'membership_end_date':
298 if (CRM_Utils_Date::convertToDefaultDate($params, $dateType, $key)) {
299 if (!CRM_Utils_Rule::date($params[$key])) {
300 CRM_Contact_Import_Parser_Contact::addToErrorMsg($dateLabels[$key], $errorMessage);
301 }
302 }
303 else {
304 CRM_Contact_Import_Parser_Contact::addToErrorMsg($dateLabels[$key], $errorMessage);
305 }
306 break;
307
308 case 'membership_type_id':
309 if (!is_numeric($val)) {
310 unset($params['membership_type_id']);
311 $params['membership_type'] = $val;
312 }
313 break;
314
315 case 'status_id':
316 if (!is_numeric($val)) {
317 unset($params['status_id']);
318 $params['membership_status'] = $val;
319 }
320 break;
321
322 case 'is_override':
323 $params[$key] = CRM_Utils_String::strtobool($val);
324 break;
325 }
326 if ($customFieldID = CRM_Core_BAO_CustomField::getKeyID($key)) {
327 if ($customFields[$customFieldID]['data_type'] == 'Date') {
328 CRM_Contact_Import_Parser_Contact::formatCustomDate($params, $formatted, $dateType, $key);
329 unset($params[$key]);
330 }
331 elseif ($customFields[$customFieldID]['data_type'] == 'Boolean') {
332 $params[$key] = CRM_Utils_String::strtoboolstr($val);
333 }
334 }
335 }
336 }
337 //date-Format part ends
338
339 static $indieFields = NULL;
340 if ($indieFields == NULL) {
341 $tempIndieFields = CRM_Member_DAO_Membership::import();
342 $indieFields = $tempIndieFields;
343 }
344
345 $formatValues = array();
346 foreach ($params as $key => $field) {
347 if ($field == NULL || $field === '') {
348 continue;
349 }
350
351 $formatValues[$key] = $field;
352 }
353
354 //format params to meet api v2 requirements.
355 //@todo find a way to test removing this formatting
356 $formatError = $this->membership_format_params($formatValues, $formatted, TRUE);
357
358 if ($onDuplicate != CRM_Import_Parser::DUPLICATE_UPDATE) {
359 $formatted['custom'] = CRM_Core_BAO_CustomField::postProcess($formatted,
360 NULL,
361 'Membership'
362 );
363 }
364 else {
365 //fix for CRM-2219 Update Membership
366 // onDuplicate == CRM_Import_Parser::DUPLICATE_UPDATE
367 if (!empty($formatted['is_override']) && empty($formatted['status_id'])) {
368 array_unshift($values, 'Required parameter missing: Status');
369 return CRM_Import_Parser::ERROR;
370 }
371
372 if (!empty($formatValues['membership_id'])) {
373 $dao = new CRM_Member_BAO_Membership();
374 $dao->id = $formatValues['membership_id'];
375 $dates = array('join_date', 'start_date', 'end_date');
376 foreach ($dates as $v) {
377 if (empty($formatted[$v])) {
378 $formatted[$v] = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_Membership', $formatValues['membership_id'], $v);
379 }
380 }
381
382 $formatted['custom'] = CRM_Core_BAO_CustomField::postProcess($formatted,
383 $formatValues['membership_id'],
384 'Membership'
385 );
386 if ($dao->find(TRUE)) {
387 $ids = array(
388 'membership' => $formatValues['membership_id'],
389 'userId' => $session->get('userID'),
390 );
391
392 if (empty($params['line_item']) && !empty($formatted['membership_type_id'])) {
393 CRM_Price_BAO_LineItem::getLineItemArray($formatted, NULL, 'membership', $formatted['membership_type_id']);
394 }
395
396 $newMembership = CRM_Member_BAO_Membership::create($formatted, $ids, TRUE);
397 if (civicrm_error($newMembership)) {
398 array_unshift($values, $newMembership['is_error'] . ' for Membership ID ' . $formatValues['membership_id'] . '. Row was skipped.');
399 return CRM_Import_Parser::ERROR;
400 }
401 else {
402 $this->_newMemberships[] = $newMembership->id;
403 return CRM_Import_Parser::VALID;
404 }
405 }
406 else {
407 array_unshift($values, 'Matching Membership record not found for Membership ID ' . $formatValues['membership_id'] . '. Row was skipped.');
408 return CRM_Import_Parser::ERROR;
409 }
410 }
411 }
412
413 //Format dates
414 $startDate = CRM_Utils_Date::customFormat(CRM_Utils_Array::value('start_date', $formatted), '%Y-%m-%d');
415 $endDate = CRM_Utils_Date::customFormat(CRM_Utils_Array::value('end_date', $formatted), '%Y-%m-%d');
416 $joinDate = CRM_Utils_Date::customFormat(CRM_Utils_Array::value('join_date', $formatted), '%Y-%m-%d');
417
418 if ($this->_contactIdIndex < 0) {
419 $error = $this->checkContactDuplicate($formatValues);
420
421 if (CRM_Core_Error::isAPIError($error, CRM_Core_ERROR::DUPLICATE_CONTACT)) {
422 $matchedIDs = explode(',', $error['error_message']['params'][0]);
423 if (count($matchedIDs) > 1) {
424 array_unshift($values, 'Multiple matching contact records detected for this row. The membership was not imported');
425 return CRM_Import_Parser::ERROR;
426 }
427 else {
428 $cid = $matchedIDs[0];
429 $formatted['contact_id'] = $cid;
430
431 //fix for CRM-1924
432 $calcDates = CRM_Member_BAO_MembershipType::getDatesForMembershipType($formatted['membership_type_id'],
433 $joinDate,
434 $startDate,
435 $endDate
436 );
437 self::formattedDates($calcDates, $formatted);
438
439 //fix for CRM-3570, exclude the statuses those having is_admin = 1
440 //now user can import is_admin if is override is true.
441 $excludeIsAdmin = FALSE;
442 if (empty($formatted['is_override'])) {
443 $formatted['exclude_is_admin'] = $excludeIsAdmin = TRUE;
444 }
445 $calcStatus = CRM_Member_BAO_MembershipStatus::getMembershipStatusByDate($startDate,
446 $endDate,
447 $joinDate,
448 'today',
449 $excludeIsAdmin,
450 $formatted['membership_type_id'],
451 $formatted
452 );
453
454 if (empty($formatted['status_id'])) {
455 $formatted['status_id'] = $calcStatus['id'];
456 }
457 elseif (empty($formatted['is_override'])) {
458 if (empty($calcStatus)) {
459 array_unshift($values, 'Status in import row (' . $formatValues['status_id'] . ') does not match calculated status based on your configured Membership Status Rules. Record was not imported.');
460 return CRM_Import_Parser::ERROR;
461 }
462 elseif ($formatted['status_id'] != $calcStatus['id']) {
463 //Status Hold" is either NOT mapped or is FALSE
464 array_unshift($values, 'Status in import row (' . $formatValues['status_id'] . ') does not match calculated status based on your configured Membership Status Rules (' . $calcStatus['name'] . '). Record was not imported.');
465 return CRM_Import_Parser::ERROR;
466 }
467 }
468
469 $newMembership = civicrm_api3('membership', 'create', $formatted);
470
471 $this->_newMemberships[] = $newMembership['id'];
472 return CRM_Import_Parser::VALID;
473 }
474 }
475 else {
476 // Using new Dedupe rule.
477 $ruleParams = array(
478 'contact_type' => $this->_contactType,
479 'used' => 'Unsupervised',
480 );
481 $fieldsArray = CRM_Dedupe_BAO_Rule::dedupeRuleFields($ruleParams);
482 $disp = '';
483
484 foreach ($fieldsArray as $value) {
485 if (array_key_exists(trim($value), $params)) {
486 $paramValue = $params[trim($value)];
487 if (is_array($paramValue)) {
488 $disp .= $params[trim($value)][0][trim($value)] . " ";
489 }
490 else {
491 $disp .= $params[trim($value)] . " ";
492 }
493 }
494 }
495
496 if (!empty($params['external_identifier'])) {
497 if ($disp) {
498 $disp .= "AND {$params['external_identifier']}";
499 }
500 else {
501 $disp = $params['external_identifier'];
502 }
503 }
504
505 array_unshift($values, 'No matching Contact found for (' . $disp . ')');
506 return CRM_Import_Parser::ERROR;
507 }
508 }
509 else {
510 if (!empty($formatValues['external_identifier'])) {
511 $checkCid = new CRM_Contact_DAO_Contact();
512 $checkCid->external_identifier = $formatValues['external_identifier'];
513 $checkCid->find(TRUE);
514 if ($checkCid->id != $formatted['contact_id']) {
515 array_unshift($values, 'Mismatch of External ID:' . $formatValues['external_identifier'] . ' and Contact Id:' . $formatted['contact_id']);
516 return CRM_Import_Parser::ERROR;
517 }
518 }
519
520 //to calculate dates
521 $calcDates = CRM_Member_BAO_MembershipType::getDatesForMembershipType($formatted['membership_type_id'],
522 $joinDate,
523 $startDate,
524 $endDate
525 );
526 self::formattedDates($calcDates, $formatted);
527 //end of date calculation part
528
529 //fix for CRM-3570, exclude the statuses those having is_admin = 1
530 //now user can import is_admin if is override is true.
531 $excludeIsAdmin = FALSE;
532 if (empty($formatted['is_override'])) {
533 $formatted['exclude_is_admin'] = $excludeIsAdmin = TRUE;
534 }
535 $calcStatus = CRM_Member_BAO_MembershipStatus::getMembershipStatusByDate($startDate,
536 $endDate,
537 $joinDate,
538 'today',
539 $excludeIsAdmin,
540 $formatted['membership_type_id'],
541 $formatted
542 );
543 if (empty($formatted['status_id'])) {
544 $formatted['status_id'] = CRM_Utils_Array::value('id', $calcStatus);
545 }
546 elseif (empty($formatted['is_override'])) {
547 if (empty($calcStatus)) {
548 array_unshift($values, 'Status in import row (' . CRM_Utils_Array::value('status_id', $formatValues) . ') does not match calculated status based on your configured Membership Status Rules. Record was not imported.');
549 return CRM_Import_Parser::ERROR;
550 }
551 elseif ($formatted['status_id'] != $calcStatus['id']) {
552 //Status Hold" is either NOT mapped or is FALSE
553 array_unshift($values, 'Status in import row (' . CRM_Utils_Array::value('status_id', $formatValues) . ') does not match calculated status based on your configured Membership Status Rules (' . $calcStatus['name'] . '). Record was not imported.');
554 return CRM_Import_Parser::ERROR;
555 }
556 }
557
558 $newMembership = civicrm_api3('membership', 'create', $formatted);
559
560 $this->_newMemberships[] = $newMembership['id'];
561 return CRM_Import_Parser::VALID;
562 }
563 }
564 catch (Exception $e) {
565 array_unshift($values, $e->getMessage());
566 return CRM_Import_Parser::ERROR;
567 }
568 }
569
570 /**
571 * Get the array of successfully imported membership id's
572 *
573 * @return array
574 */
575 public function &getImportedMemberships() {
576 return $this->_newMemberships;
577 }
578
579 /**
580 * The initializer code, called before the processing
581 *
582 * @return void
583 */
584 public function fini() {
585 }
586
587 /**
588 * to calculate join, start and end dates
589 *
590 * @param array $calcDates
591 * Array of dates returned by getDatesForMembershipType().
592 *
593 * @param $formatted
594 *
595 */
596 public function formattedDates($calcDates, &$formatted) {
597 $dates = array(
598 'join_date',
599 'start_date',
600 'end_date',
601 );
602
603 foreach ($dates as $d) {
604 if (isset($formatted[$d]) &&
605 !CRM_Utils_System::isNull($formatted[$d])
606 ) {
607 $formatted[$d] = CRM_Utils_Date::isoToMysql($formatted[$d]);
608 }
609 elseif (isset($calcDates[$d])) {
610 $formatted[$d] = CRM_Utils_Date::isoToMysql($calcDates[$d]);
611 }
612 }
613 }
614
615 /**
616 * @deprecated - this function formats params according to v2 standards but
617 * need to be sure about the impact of not calling it so retaining on the import class
618 * take the input parameter list as specified in the data model and
619 * convert it into the same format that we use in QF and BAO object
620 *
621 * @param array $params
622 * Associative array of property name/value.
623 * pairs to insert in new contact.
624 * @param array $values
625 * The reformatted properties that we can use internally.
626 *
627 * @param array|bool $create Is the formatted Values array going to
628 * be used for CRM_Member_BAO_Membership:create()
629 *
630 * @throws Exception
631 * @return array|error
632 */
633 public function membership_format_params($params, &$values, $create = FALSE) {
634 require_once 'api/v3/utils.php';
635 $fields = CRM_Member_DAO_Membership::fields();
636 _civicrm_api3_store_values($fields, $params, $values);
637
638 $customFields = CRM_Core_BAO_CustomField::getFields('Membership');
639
640 foreach ($params as $key => $value) {
641 // ignore empty values or empty arrays etc
642 if (CRM_Utils_System::isNull($value)) {
643 continue;
644 }
645
646 //Handling Custom Data
647 if ($customFieldID = CRM_Core_BAO_CustomField::getKeyID($key)) {
648 $values[$key] = $value;
649 $type = $customFields[$customFieldID]['html_type'];
650 if ($type == 'CheckBox' || $type == 'Multi-Select' || $type == 'AdvMulti-Select') {
651 $mulValues = explode(',', $value);
652 $customOption = CRM_Core_BAO_CustomOption::getCustomOption($customFieldID, TRUE);
653 $values[$key] = array();
654 foreach ($mulValues as $v1) {
655 foreach ($customOption as $customValueID => $customLabel) {
656 $customValue = $customLabel['value'];
657 if ((strtolower($customLabel['label']) == strtolower(trim($v1))) ||
658 (strtolower($customValue) == strtolower(trim($v1)))
659 ) {
660 if ($type == 'CheckBox') {
661 $values[$key][$customValue] = 1;
662 }
663 else {
664 $values[$key][] = $customValue;
665 }
666 }
667 }
668 }
669 }
670 }
671
672 switch ($key) {
673 case 'membership_contact_id':
674 if (!CRM_Utils_Rule::integer($value)) {
675 throw new Exception("contact_id not valid: $value");
676 }
677 $dao = new CRM_Core_DAO();
678 $qParams = array();
679 $svq = $dao->singleValueQuery("SELECT id FROM civicrm_contact WHERE id = $value",
680 $qParams
681 );
682 if (!$svq) {
683 throw new Exception("Invalid Contact ID: There is no contact record with contact_id = $value.");
684 }
685 $values['contact_id'] = $values['membership_contact_id'];
686 unset($values['membership_contact_id']);
687 break;
688
689 case 'membership_type_id':
690 if (!CRM_Utils_Array::value($value, CRM_Member_PseudoConstant::membershipType())) {
691 throw new Exception('Invalid Membership Type Id');
692 }
693 $values[$key] = $value;
694 break;
695
696 case 'membership_type':
697 $membershipTypeId = CRM_Utils_Array::key(ucfirst($value),
698 CRM_Member_PseudoConstant::membershipType()
699 );
700 if ($membershipTypeId) {
701 if (!empty($values['membership_type_id']) &&
702 $membershipTypeId != $values['membership_type_id']
703 ) {
704 throw new Exception('Mismatched membership Type and Membership Type Id');
705 }
706 }
707 else {
708 throw new Exception('Invalid Membership Type');
709 }
710 $values['membership_type_id'] = $membershipTypeId;
711 break;
712
713 case 'status_id':
714 if (!CRM_Utils_Array::value($value, CRM_Member_PseudoConstant::membershipStatus())) {
715 throw new Exception('Invalid Membership Status Id');
716 }
717 $values[$key] = $value;
718 break;
719
720 case 'membership_status':
721 $membershipStatusId = CRM_Utils_Array::key(ucfirst($value),
722 CRM_Member_PseudoConstant::membershipStatus()
723 );
724 if ($membershipStatusId) {
725 if (!empty($values['status_id']) &&
726 $membershipStatusId != $values['status_id']
727 ) {
728 throw new Exception('Mismatched membership Status and Membership Status Id');
729 }
730 }
731 else {
732 throw new Exception('Invalid Membership Status');
733 }
734 $values['status_id'] = $membershipStatusId;
735 break;
736
737 default:
738 break;
739 }
740 }
741
742 _civicrm_api3_custom_format_params($params, $values, 'Membership');
743
744 if ($create) {
745 // CRM_Member_BAO_Membership::create() handles membership_start_date,
746 // membership_end_date and membership_source. So, if $values contains
747 // membership_start_date, membership_end_date or membership_source,
748 // convert it to start_date, end_date or source
749 $changes = array(
750 'membership_start_date' => 'start_date',
751 'membership_end_date' => 'end_date',
752 'membership_source' => 'source',
753 );
754
755 foreach ($changes as $orgVal => $changeVal) {
756 if (isset($values[$orgVal])) {
757 $values[$changeVal] = $values[$orgVal];
758 unset($values[$orgVal]);
759 }
760 }
761 }
762
763 return NULL;
764 }
765
766 }