Merge pull request #11578 from jitendrapurohit/CRM-20697
[civicrm-core.git] / CRM / Activity / Import / Parser / Activity.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
fee14197 4 | CiviCRM version 5 |
6a488035 5 +--------------------------------------------------------------------+
8c9251b3 6 | Copyright CiviCRM LLC (c) 2004-2018 |
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
8c9251b3 31 * @copyright CiviCRM LLC (c) 2004-2018
6a488035
TO
32 */
33
6a488035
TO
34
35/**
b6c94f42 36 * Class to parse activity csv files.
6a488035
TO
37 */
38class CRM_Activity_Import_Parser_Activity extends CRM_Activity_Import_Parser {
39
40 protected $_mapperKeys;
41
42 private $_contactIdIndex;
43 private $_activityTypeIndex;
44 private $_activityLabelIndex;
45 private $_activityDateIndex;
46
47 /**
ceb10dc7 48 * Array of successfully imported activity id's
6a488035
TO
49 *
50 * @array
51 */
52 protected $_newActivity;
53
54 /**
fe482240 55 * Class constructor.
b6c94f42 56 *
57 * @param array $mapperKeys
1ae8fc42 58 * @param int $mapperLocType
59 * @param int $mapperPhoneType
6a488035 60 */
00be9182 61 public function __construct(&$mapperKeys, $mapperLocType = NULL, $mapperPhoneType = NULL) {
6a488035
TO
62 parent::__construct();
63 $this->_mapperKeys = &$mapperKeys;
64 }
65
1ae8fc42 66 /**
67 * Function of undocumented functionality required by the interface.
68 */
69 protected function fini() {}
70
6a488035 71 /**
b6c94f42 72 * The initializer code, called before the processing.
6a488035 73 */
00be9182 74 public function init() {
cc6f3942 75 $activityContact = CRM_Activity_BAO_ActivityContact::import();
76 $activityTarget['target_contact_id'] = $activityContact['contact_id'];
6a488035 77 $fields = array_merge(CRM_Activity_BAO_Activity::importableFields(),
cc6f3942 78 $activityTarget
6a488035
TO
79 );
80
cc6f3942 81 $fields = array_merge($fields, array(
4039effc
JP
82 'source_contact_id' => array(
83 'title' => ts('Source Contact'),
84 'headerPattern' => '/Source.Contact?/i',
85 ),
cc6f3942 86 'activity_label' => array(
87 'title' => ts('Activity Type Label'),
88 'headerPattern' => '/(activity.)?type label?/i',
21dfd5f5 89 ),
cc6f3942 90 ));
6a488035
TO
91
92 foreach ($fields as $name => $field) {
93 $field['type'] = CRM_Utils_Array::value('type', $field, CRM_Utils_Type::T_INT);
94 $field['dataPattern'] = CRM_Utils_Array::value('dataPattern', $field, '//');
95 $field['headerPattern'] = CRM_Utils_Array::value('headerPattern', $field, '//');
96 $this->addField($name, $field['title'], $field['type'], $field['headerPattern'], $field['dataPattern']);
97 }
98
99 $this->_newActivity = array();
100
101 $this->setActiveFields($this->_mapperKeys);
102
103 // FIXME: we should do this in one place together with Form/MapField.php
104 $this->_contactIdIndex = -1;
105 $this->_activityTypeIndex = -1;
106 $this->_activityLabelIndex = -1;
107 $this->_activityDateIndex = -1;
108
109 $index = 0;
110 foreach ($this->_mapperKeys as $key) {
111 switch ($key) {
112 case 'target_contact_id':
113 case 'external_identifier':
114 $this->_contactIdIndex = $index;
115 break;
116
117 case 'activity_label':
118 $this->_activityLabelIndex = $index;
119 break;
120
121 case 'activity_type_id':
122 $this->_activityTypeIndex = $index;
123 break;
124
125 case 'activity_date_time':
126 $this->_activityDateIndex = $index;
127 break;
128 }
129 $index++;
130 }
131 }
132
133 /**
fe482240 134 * Handle the values in mapField mode.
6a488035 135 *
041ab3d1
TO
136 * @param array $values
137 * The array of values belonging to this line.
6a488035 138 *
408b79bf 139 * @return bool
6a488035 140 */
00be9182 141 public function mapField(&$values) {
a05662ef 142 return CRM_Import_Parser::VALID;
6a488035
TO
143 }
144
145 /**
fe482240 146 * Handle the values in preview mode.
6a488035 147 *
041ab3d1
TO
148 * @param array $values
149 * The array of values belonging to this line.
6a488035 150 *
408b79bf 151 * @return bool
a6c01b45 152 * the result of this processing
6a488035 153 */
00be9182 154 public function preview(&$values) {
6a488035
TO
155 return $this->summary($values);
156 }
157
158 /**
fe482240 159 * Handle the values in summary mode.
6a488035 160 *
041ab3d1
TO
161 * @param array $values
162 * The array of values belonging to this line.
6a488035 163 *
408b79bf 164 * @return bool
a6c01b45 165 * the result of this processing
6a488035 166 */
00be9182 167 public function summary(&$values) {
6a488035 168 $erroneousField = NULL;
1ae8fc42 169 $this->setActiveFieldValues($values, $erroneousField);
353ffa53 170 $index = -1;
6a488035
TO
171
172 if ($this->_activityTypeIndex > -1 && $this->_activityLabelIndex > -1) {
173 array_unshift($values, ts('Please select either Activity Type ID OR Activity Type Label.'));
a05662ef 174 return CRM_Import_Parser::ERROR;
6a488035
TO
175 }
176 elseif ($this->_activityLabelIndex > -1) {
177 $index = $this->_activityLabelIndex;
178 }
179 elseif ($this->_activityTypeIndex > -1) {
180 $index = $this->_activityTypeIndex;
181 }
182
183 if ($index < 0 or $this->_activityDateIndex < 0) {
184 $errorRequired = TRUE;
185 }
186 else {
187 $errorRequired = !CRM_Utils_Array::value($index, $values) || !CRM_Utils_Array::value($this->_activityDateIndex, $values);
188 }
189
190 if ($errorRequired) {
191 array_unshift($values, ts('Missing required fields'));
a05662ef 192 return CRM_Import_Parser::ERROR;
6a488035
TO
193 }
194
195 $params = &$this->getActiveFieldParams();
196
197 $errorMessage = NULL;
198
7808aae6 199 // For date-Formats
6a488035
TO
200 $session = CRM_Core_Session::singleton();
201 $dateType = $session->get('dateTypes');
202 if (!isset($params['source_contact_id'])) {
203 $params['source_contact_id'] = $session->get('userID');
204 }
205 foreach ($params as $key => $val) {
206 if ($key == 'activity_date_time') {
207 if ($val) {
208 $dateValue = CRM_Utils_Date::formatDate($val, $dateType);
209 if ($dateValue) {
210 $params[$key] = $dateValue;
211 }
212 else {
719a6fec 213 CRM_Contact_Import_Parser_Contact::addToErrorMsg('Activity date', $errorMessage);
6a488035
TO
214 }
215 }
216 }
217 elseif ($key == 'activity_engagement_level' && $val &&
218 !CRM_Utils_Rule::positiveInteger($val)
219 ) {
719a6fec 220 CRM_Contact_Import_Parser_Contact::addToErrorMsg('Activity Engagement Index', $errorMessage);
6a488035
TO
221 }
222 }
7808aae6 223 // Date-Format part ends.
6a488035 224
7808aae6 225 // Checking error in custom data.
6a488035
TO
226 $params['contact_type'] = isset($this->_contactType) ? $this->_contactType : 'Activity';
227
719a6fec 228 CRM_Contact_Import_Parser_Contact::isErrorInCustomData($params, $errorMessage);
6a488035
TO
229
230 if ($errorMessage) {
231 $tempMsg = "Invalid value for field(s) : $errorMessage";
232 array_unshift($values, $tempMsg);
233 $errorMessage = NULL;
a05662ef 234 return CRM_Import_Parser::ERROR;
6a488035
TO
235 }
236
a05662ef 237 return CRM_Import_Parser::VALID;
6a488035
TO
238 }
239
240 /**
fe482240 241 * Handle the values in import mode.
6a488035 242 *
041ab3d1
TO
243 * @param int $onDuplicate
244 * The code for what action to take on duplicates.
245 * @param array $values
246 * The array of values belonging to this line.
6a488035 247 *
408b79bf 248 * @return bool
a6c01b45 249 * the result of this processing
6a488035 250 */
00be9182 251 public function import($onDuplicate, &$values) {
7808aae6 252 // First make sure this is a valid line
6a488035
TO
253 $response = $this->summary($values);
254
a05662ef 255 if ($response != CRM_Import_Parser::VALID) {
6a488035
TO
256 return $response;
257 }
258 $params = &$this->getActiveFieldParams();
259 $activityLabel = array_search('activity_label', $this->_mapperKeys);
260 if ($activityLabel) {
261 $params = array_merge($params, array('activity_label' => $values[$activityLabel]));
262 }
7808aae6 263 // For date-Formats.
6a488035
TO
264 $session = CRM_Core_Session::singleton();
265 $dateType = $session->get('dateTypes');
266 if (!isset($params['source_contact_id'])) {
267 $params['source_contact_id'] = $session->get('userID');
268 }
1ae8fc42 269
127f50ce 270 $customFields = CRM_Core_BAO_CustomField::getFields('Activity');
6a488035
TO
271
272 foreach ($params as $key => $val) {
273 if ($customFieldID = CRM_Core_BAO_CustomField::getKeyID($key)) {
8bc84e3c 274 if ($key == 'activity_date_time' && $val) {
2272a067
BS
275 $params[$key] = CRM_Utils_Date::formatDate($val, $dateType);
276 }
8bc84e3c 277 elseif (!empty($customFields[$customFieldID]) && $customFields[$customFieldID]['data_type'] == 'Date') {
719a6fec 278 CRM_Contact_Import_Parser_Contact::formatCustomDate($params, $params, $dateType, $key);
6a488035 279 }
8bc84e3c 280 elseif (!empty($customFields[$customFieldID]) && $customFields[$customFieldID]['data_type'] == 'Boolean') {
6a488035
TO
281 $params[$key] = CRM_Utils_String::strtoboolstr($val);
282 }
283 }
7cad3e54
C
284 elseif ($key == 'activity_date_time') {
285 $params[$key] = CRM_Utils_Date::formatDate($val, $dateType);
286 }
6a488035
TO
287 elseif ($key == 'activity_subject') {
288 $params['subject'] = $val;
289 }
290 }
7808aae6 291 // Date-Format part ends.
6a488035
TO
292 require_once 'CRM/Utils/DeprecatedUtils.php';
293 $formatError = _civicrm_api3_deprecated_activity_formatted_param($params, $params, TRUE);
294
295 if ($formatError) {
296 array_unshift($values, $formatError['error_message']);
a05662ef 297 return CRM_Import_Parser::ERROR;
6a488035
TO
298 }
299
300 $params['custom'] = CRM_Core_BAO_CustomField::postProcess($params,
6a488035
TO
301 NULL,
302 'Activity'
303 );
304
305 if ($this->_contactIdIndex < 0) {
306
7808aae6
SB
307 // Retrieve contact id using contact dedupe rule.
308 // Since we are supporting only individual's activity import.
6a488035
TO
309 $params['contact_type'] = 'Individual';
310 $params['version'] = 3;
311 $error = _civicrm_api3_deprecated_duplicate_formatted_contact($params);
312
313 if (CRM_Core_Error::isAPIError($error, CRM_Core_ERROR::DUPLICATE_CONTACT)) {
314 $matchedIDs = explode(',', $error['error_message']['params'][0]);
315 if (count($matchedIDs) > 1) {
316 array_unshift($values, 'Multiple matching contact records detected for this row. The activity was not imported');
a05662ef 317 return CRM_Import_Parser::ERROR;
6a488035
TO
318 }
319 else {
320 $cid = $matchedIDs[0];
321 $params['target_contact_id'] = $cid;
322 $params['version'] = 3;
323 $newActivity = civicrm_api('activity', 'create', $params);
a7488080 324 if (!empty($newActivity['is_error'])) {
6a488035 325 array_unshift($values, $newActivity['error_message']);
a05662ef 326 return CRM_Import_Parser::ERROR;
6a488035
TO
327 }
328
329 $this->_newActivity[] = $newActivity['id'];
a05662ef 330 return CRM_Import_Parser::VALID;
6a488035
TO
331 }
332 }
333 else {
334 // Using new Dedupe rule.
335 $ruleParams = array(
336 'contact_type' => 'Individual',
353ffa53 337 'used' => 'Unsupervised',
6a488035
TO
338 );
339 $fieldsArray = CRM_Dedupe_BAO_Rule::dedupeRuleFields($ruleParams);
340
341 $disp = NULL;
342 foreach ($fieldsArray as $value) {
343 if (array_key_exists(trim($value), $params)) {
344 $paramValue = $params[trim($value)];
345 if (is_array($paramValue)) {
346 $disp .= $params[trim($value)][0][trim($value)] . " ";
347 }
348 else {
349 $disp .= $params[trim($value)] . " ";
350 }
351 }
352 }
353
a7488080 354 if (!empty($params['external_identifier'])) {
6a488035
TO
355 if ($disp) {
356 $disp .= "AND {$params['external_identifier']}";
357 }
358 else {
359 $disp = $params['external_identifier'];
360 }
361 }
362
363 array_unshift($values, 'No matching Contact found for (' . $disp . ')');
a05662ef 364 return CRM_Import_Parser::ERROR;
6a488035
TO
365 }
366 }
367 else {
a7488080 368 if (!empty($params['external_identifier'])) {
6a488035
TO
369 $targetContactId = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact',
370 $params['external_identifier'], 'id', 'external_identifier'
371 );
372
a7488080 373 if (!empty($params['target_contact_id']) &&
6a488035
TO
374 $params['target_contact_id'] != $targetContactId
375 ) {
d79be26c 376 array_unshift($values, 'Mismatch of External ID:' . $params['external_identifier'] . ' and Contact Id:' . $params['target_contact_id']);
a05662ef 377 return CRM_Import_Parser::ERROR;
6a488035
TO
378 }
379 elseif ($targetContactId) {
380 $params['target_contact_id'] = $targetContactId;
381 }
382 else {
d79be26c 383 array_unshift($values, 'No Matching Contact for External ID:' . $params['external_identifier']);
a05662ef 384 return CRM_Import_Parser::ERROR;
6a488035
TO
385 }
386 }
387
388 $params['version'] = 3;
389 $newActivity = civicrm_api('activity', 'create', $params);
a7488080 390 if (!empty($newActivity['is_error'])) {
6a488035 391 array_unshift($values, $newActivity['error_message']);
a05662ef 392 return CRM_Import_Parser::ERROR;
6a488035
TO
393 }
394
395 $this->_newActivity[] = $newActivity['id'];
a05662ef 396 return CRM_Import_Parser::VALID;
6a488035
TO
397 }
398 }
399
6a488035 400}