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