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