Fix Parser classes to use ClassScanner
[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 21 */
8addbaf3 22class CRM_Activity_Import_Parser_Activity extends CRM_Import_Parser {
6a488035 23
3764aead
EM
24 /**
25 * Get information about the provided job.
26 * - name
27 * - id (generally the same as name)
28 * - label
29 *
30 * e.g. ['activity_import' => ['id' => 'activity_import', 'label' => ts('Activity Import'), 'name' => 'activity_import']]
31 *
32 * @return array
33 */
34 public static function getUserJobInfo(): array {
35 return [
36 'activity_import' => [
37 'id' => 'activity_import',
38 'name' => 'activity_import',
39 'label' => ts('Activity Import'),
40 ],
41 ];
42 }
43
6a488035 44 /**
b6c94f42 45 * The initializer code, called before the processing.
6a488035 46 */
00be9182 47 public function init() {
7eebbdaa
EM
48 $this->setFieldMetadata();
49
50 foreach ($this->importableFieldsMetadata as $name => $field) {
6a488035
TO
51 $field['type'] = CRM_Utils_Array::value('type', $field, CRM_Utils_Type::T_INT);
52 $field['dataPattern'] = CRM_Utils_Array::value('dataPattern', $field, '//');
53 $field['headerPattern'] = CRM_Utils_Array::value('headerPattern', $field, '//');
4245bf70
MM
54 if (!empty($field['custom_group_id'])) {
55 $field['title'] = $field["groupTitle"] . ' :: ' . $field["title"];
56 }
6a488035
TO
57 $this->addField($name, $field['title'], $field['type'], $field['headerPattern'], $field['dataPattern']);
58 }
6a488035
TO
59 }
60
61 /**
fe482240 62 * Handle the values in import mode.
6a488035 63 *
041ab3d1
TO
64 * @param array $values
65 * The array of values belonging to this line.
6a488035 66 */
7eebbdaa
EM
67 public function import($values) {
68 $rowNumber = (int) ($values[array_key_last($values)]);
7808aae6 69 // First make sure this is a valid line
3ac87609 70 try {
7eebbdaa 71 $params = $this->getMappedRow($values);
6a488035 72
945b79bf 73 if (empty($params['external_identifier']) && empty($params['target_contact_id'])) {
6a488035 74
945b79bf
EM
75 // Retrieve contact id using contact dedupe rule.
76 // Since we are supporting only individual's activity import.
77 $params['contact_type'] = 'Individual';
78 $params['version'] = 3;
79 $matchedIDs = CRM_Contact_BAO_Contact::getDuplicateContacts($params, 'Individual');
80
81 if (!empty($matchedIDs)) {
82 if (count($matchedIDs) > 1) {
7eebbdaa 83 throw new CRM_Core_Exception('Multiple matching contact records detected for this row. The activity was not imported');
945b79bf
EM
84 }
85 $cid = $matchedIDs[0];
86 $params['target_contact_id'] = $cid;
87 $params['version'] = 3;
88 $newActivity = civicrm_api('activity', 'create', $params);
89 if (!empty($newActivity['is_error'])) {
7eebbdaa 90 throw new CRM_Core_Exception($newActivity['error_message']);
945b79bf
EM
91 }
92
93 $this->_newActivity[] = $newActivity['id'];
7eebbdaa
EM
94 $this->setImportStatus($rowNumber, 'IMPORTED', '', $newActivity['id']);
95 return;
6a488035 96
6a488035 97 }
945b79bf
EM
98 // Using new Dedupe rule.
99 $ruleParams = [
100 'contact_type' => 'Individual',
101 'used' => 'Unsupervised',
102 ];
103 $fieldsArray = CRM_Dedupe_BAO_DedupeRule::dedupeRuleFields($ruleParams);
104
105 $disp = NULL;
106 foreach ($fieldsArray as $value) {
107 if (array_key_exists(trim($value), $params)) {
108 $paramValue = $params[trim($value)];
109 if (is_array($paramValue)) {
110 $disp .= $params[trim($value)][0][trim($value)] . " ";
111 }
112 else {
113 $disp .= $params[trim($value)] . " ";
114 }
115 }
6a488035
TO
116 }
117
945b79bf
EM
118 if (!empty($params['external_identifier'])) {
119 if ($disp) {
120 $disp .= "AND {$params['external_identifier']}";
6a488035
TO
121 }
122 else {
945b79bf 123 $disp = $params['external_identifier'];
6a488035
TO
124 }
125 }
81882fd1
EM
126 if (empty($params['id'])) {
127 throw new CRM_Core_Exception('No matching Contact found for (' . $disp . ')');
128 }
945b79bf 129 }
a7488080 130 if (!empty($params['external_identifier'])) {
945b79bf
EM
131 $targetContactId = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact',
132 $params['external_identifier'], 'id', 'external_identifier'
133 );
134
135 if (!empty($params['target_contact_id']) &&
136 $params['target_contact_id'] != $targetContactId
137 ) {
7eebbdaa 138 throw new CRM_Core_Exception('Mismatch of External ID:' . $params['external_identifier'] . ' and Contact Id:' . $params['target_contact_id']);
945b79bf
EM
139 }
140 if ($targetContactId) {
141 $params['target_contact_id'] = $targetContactId;
6a488035
TO
142 }
143 else {
7eebbdaa 144 throw new CRM_Core_Exception('No Matching Contact for External ID:' . $params['external_identifier']);
6a488035
TO
145 }
146 }
147
945b79bf
EM
148 $params['version'] = 3;
149 $newActivity = civicrm_api('activity', 'create', $params);
150 if (!empty($newActivity['is_error'])) {
7eebbdaa 151 throw new CRM_Core_Exception($newActivity['error_message']);
cb8bc3b6 152 }
153 }
945b79bf 154 catch (CRM_Core_Exception $e) {
7eebbdaa
EM
155 $this->setImportStatus($rowNumber, 'ERROR', $e->getMessage());
156 return;
6a488035 157 }
cb8bc3b6 158 $this->_newActivity[] = $newActivity['id'];
7eebbdaa
EM
159 $this->setImportStatus($rowNumber, 'IMPORTED', '', $newActivity['id']);
160 }
161
162 /**
163 * Get the row from the csv mapped to our parameters.
164 *
165 * @param array $values
166 *
167 * @return array
168 * @throws \API_Exception
169 */
170 public function getMappedRow(array $values): array {
171 $params = [];
172 foreach ($this->getFieldMappings() as $i => $mappedField) {
173 if ($mappedField['name'] === 'do_not_import') {
174 continue;
175 }
176 if ($mappedField['name']) {
177 $fieldName = $this->getFieldMetadata($mappedField['name'])['name'];
178 if (in_array($mappedField['name'], ['target_contact_id', 'source_contact_id'])) {
179 $fieldName = $mappedField['name'];
180 }
181 $params[$fieldName] = $this->getTransformedFieldValue($mappedField['name'], $values[$i]);
182 }
183 }
184 return $params;
6a488035
TO
185 }
186
7eebbdaa
EM
187 /**
188 * @return array
189 */
190 protected function getRequiredFields(): array {
191 return [['activity_type_id' => ts('Activity Type'), 'activity_date_time' => ts('Activity Date')]];
192 }
193
c5a8afa5 194 /**
37fe444e 195 * @deprecated - these are just used in a couple of parent class functions now.
8addbaf3
EM
196 * @param string $name
197 * @param $title
198 * @param int $type
199 * @param string $headerPattern
200 * @param string $dataPattern
201 */
202 public function addField($name, $title, $type = CRM_Utils_Type::T_INT, $headerPattern = '//', $dataPattern = '//') {
203 if (empty($name)) {
204 $this->_fields['doNotImport'] = new CRM_Activity_Import_Field($name, $title, $type, $headerPattern, $dataPattern);
205 }
206 else {
207
208 $tempField = CRM_Contact_BAO_Contact::importableFields('Individual', NULL);
209 if (!array_key_exists($name, $tempField)) {
210 $this->_fields[$name] = new CRM_Activity_Import_Field($name, $title, $type, $headerPattern, $dataPattern);
211 }
212 else {
213 $this->_fields[$name] = new CRM_Contact_Import_Field($name, $title, $type, $headerPattern, $dataPattern, CRM_Utils_Array::value('hasLocationType', $tempField[$name]));
214 }
215 }
216 }
217
7eebbdaa
EM
218 /**
219 * Ensure metadata is loaded.
220 */
221 protected function setFieldMetadata(): void {
222 if (empty($this->importableFieldsMetadata)) {
223 $activityContact = CRM_Activity_BAO_ActivityContact::import();
37fe444e
EM
224 $fields = ['' => ['title' => ts('- do not import -')]];
225
226 $tmpFields = CRM_Activity_DAO_Activity::import();
227 $contactFields = CRM_Contact_BAO_Contact::importableFields('Individual', NULL);
228
229 // Using new Dedupe rule.
230 $ruleParams = [
231 'contact_type' => 'Individual',
232 'used' => 'Unsupervised',
233 ];
234 $fieldsArray = CRM_Dedupe_BAO_DedupeRule::dedupeRuleFields($ruleParams);
235
236 $tmpConatctField = [];
237 if (is_array($fieldsArray)) {
238 foreach ($fieldsArray as $value) {
239 $customFieldId = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomField',
240 $value,
241 'id',
242 'column_name'
243 );
97b5d1ab
EM
244 $value = trim($customFieldId ? 'custom_' . $customFieldId : $value);
245 $tmpConatctField[$value] = $contactFields[$value];
246 $tmpConatctField[$value]['title'] = $tmpConatctField[$value]['title'] . " (match to contact)";
37fe444e
EM
247 }
248 }
249 $tmpConatctField['external_identifier'] = $contactFields['external_identifier'];
97b5d1ab 250 $tmpConatctField['external_identifier']['title'] = $contactFields['external_identifier']['title'] . ' (match to contact)';
37fe444e
EM
251 $fields = array_merge($fields, $tmpConatctField);
252 $fields = array_merge($fields, $tmpFields);
253 $fields = array_merge($fields, CRM_Core_BAO_CustomField::getFieldsForImport('Activity'));
7eebbdaa
EM
254
255 $fields = array_merge($fields, [
256 'source_contact_id' => [
257 'title' => ts('Source Contact'),
258 'headerPattern' => '/Source.Contact?/i',
37fe444e
EM
259 'name' => 'source_type_id',
260 'options' => FALSE,
261 'type' => CRM_Utils_Type::T_INT,
7eebbdaa 262 ],
97b5d1ab
EM
263 'target_contact_id' => [
264 'title' => ts('Target Contact'),
265 'headerPattern' => '/Target.Contact?/i',
266 'name' => 'target_type_id',
267 'options' => FALSE,
268 'type' => CRM_Utils_Type::T_INT,
269 ],
7eebbdaa
EM
270 ]);
271 $this->importableFieldsMetadata = $fields;
272 }
273 }
274
6a488035 275}