Merge pull request #17474 from eileenmcnaughton/processor_name
[civicrm-core.git] / CRM / Contact / Import / ImportJob.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
5 | |
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 |
9 +--------------------------------------------------------------------+
10 */
11
12 /**
13 *
14 * @package CRM
15 * @copyright CiviCRM LLC https://civicrm.org/licensing
16 * $Id$
17 *
18 */
19
20 /**
21 * This class acts like a psuedo-BAO for transient import job tables.
22 */
23 class CRM_Contact_Import_ImportJob {
24
25 protected $_tableName;
26 protected $_primaryKeyName;
27 protected $_statusFieldName;
28
29 protected $_doGeocodeAddress;
30 protected $_invalidRowCount;
31 protected $_conflictRowCount;
32 protected $_onDuplicate;
33 protected $_dedupe;
34 protected $_newGroupName;
35 protected $_newGroupDesc;
36 protected $_newGroupType;
37 protected $_groups;
38 protected $_allGroups;
39 protected $_newTagName;
40 protected $_newTagDesc;
41 protected $_tag;
42 protected $_allTags;
43
44 protected $_mapper;
45 protected $_mapperKeys = array();
46 protected $_mapFields;
47
48 protected $_parser;
49
50 /**
51 * @param null $tableName
52 * @param null $createSql
53 * @param bool $createTable
54 *
55 * @throws \CRM_Core_Exception
56 */
57 public function __construct($tableName = NULL, $createSql = NULL, $createTable = FALSE) {
58 $dao = new CRM_Core_DAO();
59 $db = $dao->getDatabaseConnection();
60
61 if ($createTable) {
62 if (!$createSql) {
63 throw new CRM_Core_Exception(ts('Either an existing table name or an SQL query to build one are required'));
64 }
65
66 // FIXME: we should regen this table's name if it exists rather than drop it
67 if (!$tableName) {
68 $tableName = 'civicrm_import_job_' . md5(uniqid(rand(), TRUE));
69 }
70 $db->query("DROP TABLE IF EXISTS $tableName");
71 $db->query("CREATE TABLE $tableName ENGINE=InnoDB DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci $createSql");
72 }
73
74 if (!$tableName) {
75 throw new CRM_Core_Exception(ts('Import Table is required.'));
76 }
77
78 $this->_tableName = $tableName;
79 }
80
81 /**
82 * @return null|string
83 */
84 public function getTableName() {
85 return $this->_tableName;
86 }
87
88 /**
89 * @param bool $dropIfComplete
90 *
91 * @return bool
92 * @throws Exception
93 */
94 public function isComplete($dropIfComplete = TRUE) {
95 if (!$this->_statusFieldName) {
96 CRM_Core_Error::fatal("Could not get name of the import status field");
97 }
98 $query = "SELECT * FROM $this->_tableName
99 WHERE $this->_statusFieldName = 'NEW' LIMIT 1";
100 $result = CRM_Core_DAO::executeQuery($query);
101 if ($result->fetch()) {
102 return FALSE;
103 }
104 if ($dropIfComplete) {
105 $query = "DROP TABLE $this->_tableName";
106 CRM_Core_DAO::executeQuery($query);
107 }
108 return TRUE;
109 }
110
111 /**
112 * @param array $params
113 */
114 public function setJobParams(&$params) {
115 foreach ($params as $param => $value) {
116 $fldName = "_$param";
117 $this->$fldName = $value;
118 }
119 }
120
121 /**
122 * @param CRM_Core_Form $form
123 * @param int $timeout
124 */
125 public function runImport(&$form, $timeout = 55) {
126 $mapper = $this->_mapper;
127 $mapperFields = array();
128 $parserParameters = CRM_Contact_Import_Parser_Contact::getParameterForParser(count($mapper));
129 $phoneTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Phone', 'phone_type_id');
130 $imProviders = CRM_Core_PseudoConstant::get('CRM_Core_DAO_IM', 'provider_id');
131 $websiteTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Website', 'website_type_id');
132 $locationTypes = array('Primary' => ts('Primary')) + CRM_Core_PseudoConstant::get('CRM_Core_DAO_Address', 'location_type_id');
133
134 foreach ($mapper as $key => $value) {
135
136 $fldName = $mapper[$key][0] ?? NULL;
137 $header = array($this->_mapFields[$fldName]);
138 $selOne = $mapper[$key][1] ?? NULL;
139 $selTwo = $mapper[$key][2] ?? NULL;
140 $selThree = $mapper[$key][3] ?? NULL;
141 $this->_mapperKeys[$key] = $fldName;
142
143 //need to differentiate non location elements.
144 // @todo merge this with duplicate code on MapField class.
145 if ($selOne && (is_numeric($selOne) || $selOne === 'Primary')) {
146 if ($fldName == 'url') {
147 $header[] = $websiteTypes[$selOne];
148 $parserParameters['mapperWebsiteType'][$key] = $selOne;
149 }
150 else {
151 $header[] = $locationTypes[$selOne];
152 $parserParameters['mapperLocType'][$key] = $selOne;
153 if ($selTwo && is_numeric($selTwo)) {
154 if ($fldName == 'phone') {
155 $header[] = $phoneTypes[$selTwo];
156 $parserParameters['mapperPhoneType'][$key] = $selTwo;
157 }
158 elseif ($fldName == 'im') {
159 $header[] = $imProviders[$selTwo];
160 $parserParameters['mapperImProvider'][$key] = $selTwo;
161 }
162 }
163 }
164 }
165
166 $fldNameParts = explode('_', $fldName, 3);
167 $id = $fldNameParts[0];
168 $first = $fldNameParts[1] ?? NULL;
169 $second = $fldNameParts[2] ?? NULL;
170 if (($first == 'a' && $second == 'b') ||
171 ($first == 'b' && $second == 'a')
172 ) {
173
174 $header[] = ucwords(str_replace("_", " ", $selOne));
175
176 $relationType = new CRM_Contact_DAO_RelationshipType();
177 $relationType->id = $id;
178 $relationType->find(TRUE);
179 $parserParameters['relatedContactType'][$key] = $relationType->{"contact_type_$second"};
180
181 $parserParameters['mapperRelated'][$key] = $fldName;
182 if ($selOne) {
183 $parserParameters['relatedContactDetails'][$key] = $selOne;
184 if ($selTwo) {
185 if ($selOne == 'url') {
186 $header[] = $websiteTypes[$selTwo];
187 $parserParameters[$key]['relatedContactWebsiteType'][$key] = $selTwo;
188 }
189 else {
190 $header[] = $locationTypes[$selTwo];
191 $parserParameters['relatedContactLocType'][$key] = $selTwo;
192 if ($selThree) {
193 if ($selOne == 'phone') {
194 $header[] = $phoneTypes[$selThree];
195 $parserParameters['relatedContactPhoneType'][$key] = $selThree;
196 }
197 elseif ($selOne == 'im') {
198 $header[] = $imProviders[$selThree];
199 $parserParameters['relatedContactImProvider'][$key] = $selThree;
200 }
201 }
202 }
203 }
204 }
205 }
206 $mapperFields[] = implode(' - ', $header);
207 }
208
209 $this->_parser = new CRM_Contact_Import_Parser_Contact(
210 $this->_mapperKeys,
211 $parserParameters['mapperLocType'],
212 $parserParameters['mapperPhoneType'],
213 $parserParameters['mapperImProvider'],
214 $parserParameters['mapperRelated'],
215 $parserParameters['relatedContactType'],
216 $parserParameters['relatedContactDetails'],
217 $parserParameters['relatedContactLocType'],
218 $parserParameters['relatedContactPhoneType'],
219 $parserParameters['relatedContactImProvider'],
220 $parserParameters['mapperWebsiteType'],
221 $parserParameters['relatedContactWebsiteType']
222 );
223
224 $this->_parser->run($this->_tableName, $mapperFields,
225 CRM_Import_Parser::MODE_IMPORT,
226 $this->_contactType,
227 $this->_primaryKeyName,
228 $this->_statusFieldName,
229 $this->_onDuplicate,
230 $this->_statusID,
231 $this->_totalRowCount,
232 $this->_doGeocodeAddress,
233 CRM_Contact_Import_Parser::DEFAULT_TIMEOUT,
234 $this->_contactSubType,
235 $this->_dedupe
236 );
237
238 $contactIds = $this->_parser->getImportedContacts();
239
240 //get the related contactIds. CRM-2926
241 $relatedContactIds = $this->_parser->getRelatedImportedContacts();
242 if ($relatedContactIds) {
243 $contactIds = array_merge($contactIds, $relatedContactIds);
244 if ($form) {
245 $form->set('relatedCount', count($relatedContactIds));
246 }
247 }
248
249 if ($this->_newGroupName || count($this->_groups)) {
250 $groupAdditions = $this->_addImportedContactsToNewGroup($contactIds,
251 $this->_newGroupName,
252 $this->_newGroupDesc,
253 $this->_newGroupType
254 );
255 if ($form) {
256 $form->set('groupAdditions', $groupAdditions);
257 }
258 }
259
260 if ($this->_newTagName || !empty($this->_tag)) {
261 $tagAdditions = $this->_tagImportedContactsWithNewTag($contactIds,
262 $this->_newTagName,
263 $this->_newTagDesc
264 );
265 if ($form) {
266 $form->set('tagAdditions', $tagAdditions);
267 }
268 }
269 }
270
271 /**
272 * @param $form
273 */
274 public function setFormVariables($form) {
275 $this->_parser->set($form, CRM_Import_Parser::MODE_IMPORT);
276 }
277
278 /**
279 * Add imported contacts.
280 *
281 * @param array $contactIds
282 * @param string $newGroupName
283 * @param string $newGroupDesc
284 * @param string $newGroupType
285 *
286 * @return array|bool
287 */
288 private function _addImportedContactsToNewGroup(
289 $contactIds,
290 $newGroupName, $newGroupDesc, $newGroupType
291 ) {
292
293 $newGroupId = NULL;
294
295 if ($newGroupName) {
296 /* Create a new group */
297 $newGroupType = $newGroupType ?? array();
298 $gParams = array(
299 'title' => $newGroupName,
300 'description' => $newGroupDesc,
301 'group_type' => $newGroupType,
302 'is_active' => TRUE,
303 );
304 $group = CRM_Contact_BAO_Group::create($gParams);
305 $this->_groups[] = $newGroupId = $group->id;
306 }
307
308 if (is_array($this->_groups)) {
309 $groupAdditions = array();
310 foreach ($this->_groups as $groupId) {
311 $addCount = CRM_Contact_BAO_GroupContact::addContactsToGroup($contactIds, $groupId);
312 $totalCount = $addCount[1];
313 if ($groupId == $newGroupId) {
314 $name = $newGroupName;
315 $new = TRUE;
316 }
317 else {
318 $name = $this->_allGroups[$groupId];
319 $new = FALSE;
320 }
321 $groupAdditions[] = array(
322 'url' => CRM_Utils_System::url('civicrm/group/search',
323 'reset=1&force=1&context=smog&gid=' . $groupId
324 ),
325 'name' => $name,
326 'added' => $totalCount,
327 'notAdded' => $addCount[2],
328 'new' => $new,
329 );
330 }
331 return $groupAdditions;
332 }
333 return FALSE;
334 }
335
336 /**
337 * @param $contactIds
338 * @param string $newTagName
339 * @param $newTagDesc
340 *
341 * @return array|bool
342 */
343 private function _tagImportedContactsWithNewTag(
344 $contactIds,
345 $newTagName, $newTagDesc
346 ) {
347
348 $newTagId = NULL;
349 if ($newTagName) {
350 /* Create a new Tag */
351
352 $tagParams = array(
353 'name' => $newTagName,
354 'description' => $newTagDesc,
355 'is_selectable' => TRUE,
356 'used_for' => 'civicrm_contact',
357 );
358 $addedTag = CRM_Core_BAO_Tag::add($tagParams);
359 $this->_tag[$addedTag->id] = 1;
360 }
361 //add Tag to Import
362
363 if (is_array($this->_tag)) {
364 $tagAdditions = array();
365 foreach ($this->_tag as $tagId => $val) {
366 $addTagCount = CRM_Core_BAO_EntityTag::addEntitiesToTag($contactIds, $tagId, 'civicrm_contact', FALSE);
367 $totalTagCount = $addTagCount[1];
368 if (isset($addedTag) && $tagId == $addedTag->id) {
369 $tagName = $newTagName;
370 $new = TRUE;
371 }
372 else {
373 $tagName = $this->_allTags[$tagId];
374 $new = FALSE;
375 }
376 $tagAdditions[] = array(
377 'url' => CRM_Utils_System::url('civicrm/contact/search',
378 'reset=1&force=1&context=smog&id=' . $tagId
379 ),
380 'name' => $tagName,
381 'added' => $totalTagCount,
382 'notAdded' => $addTagCount[2],
383 'new' => $new,
384 );
385 }
386 return $tagAdditions;
387 }
388 return FALSE;
389 }
390
391 }