Merge pull request #4622 from civicrm/4.5
[civicrm-core.git] / CRM / Contact / Import / Form / Preview.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
06b69b18 4 | CiviCRM version 4.5 |
6a488035 5 +--------------------------------------------------------------------+
06b69b18 6 | Copyright CiviCRM LLC (c) 2004-2014 |
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 +--------------------------------------------------------------------+
26*/
27
28/**
29 *
30 * @package CRM
06b69b18 31 * @copyright CiviCRM LLC (c) 2004-2014
6a488035
TO
32 * $Id$
33 *
34 */
35
36/**
37 * This class previews the uploaded file and returns summary
38 * statistics
39 */
f532671f 40class CRM_Contact_Import_Form_Preview extends CRM_Import_Form_Preview {
6a488035
TO
41
42 /**
43 * Function to set variables up before form is built
44 *
45 * @return void
46 * @access public
47 */
48 public function preProcess() {
49 //get the data from the session
50 $dataValues = $this->get('dataValues');
51 $mapper = $this->get('mapper');
52 $invalidRowCount = $this->get('invalidRowCount');
53 $conflictRowCount = $this->get('conflictRowCount');
54 $mismatchCount = $this->get('unMatchCount');
55 $columnNames = $this->get('columnNames');
56
57 //assign column names
58 $this->assign('columnNames', $columnNames);
59
60 //get the mapping name displayed if the mappingId is set
61 $mappingId = $this->get('loadMappingId');
62 if ($mappingId) {
63 $mapDAO = new CRM_Core_DAO_Mapping();
64 $mapDAO->id = $mappingId;
65 $mapDAO->find(TRUE);
66 $this->assign('loadedMapping', $mappingId);
67 $this->assign('savedName', $mapDAO->name);
68 }
69
70 $this->assign('rowDisplayCount', 2);
71
24431f7b 72 $groups = CRM_Core_PseudoConstant::nestedGroup();
6a488035
TO
73 $this->set('groups', $groups);
74
cd43c5e3 75 $tag = CRM_Core_PseudoConstant::get('CRM_Core_DAO_EntityTag', 'tag_id', array('onlyActive' => FALSE));
6a488035
TO
76 if ($tag) {
77 $this->set('tag', $tag);
78 }
79
80 if ($invalidRowCount) {
a05662ef 81 $urlParams = 'type=' . CRM_Import_Parser::ERROR . '&parser=CRM_Contact_Import_Parser';
6a488035
TO
82 $this->set('downloadErrorRecordsUrl', CRM_Utils_System::url('civicrm/export', $urlParams));
83 }
84
85 if ($conflictRowCount) {
a05662ef 86 $urlParams = 'type=' . CRM_Import_Parser::CONFLICT . '&parser=CRM_Contact_Import_Parser';
6a488035
TO
87 $this->set('downloadConflictRecordsUrl', CRM_Utils_System::url('civicrm/export', $urlParams));
88 }
89
90 if ($mismatchCount) {
a05662ef 91 $urlParams = 'type=' . CRM_Import_Parser::NO_MATCH . '&parser=CRM_Contact_Import_Parser';
6a488035
TO
92 $this->set('downloadMismatchRecordsUrl', CRM_Utils_System::url('civicrm/export', $urlParams));
93 }
94
95 $properties = array(
96 'mapper', 'locations', 'phones', 'ims',
97 'dataValues', 'columnCount',
98 'totalRowCount', 'validRowCount',
99 'invalidRowCount', 'conflictRowCount',
100 'downloadErrorRecordsUrl',
101 'downloadConflictRecordsUrl',
102 'downloadMismatchRecordsUrl',
103 'related', 'relatedContactDetails', 'relatedContactLocType',
104 'relatedContactPhoneType', 'relatedContactImProvider', 'websites',
105 'relatedContactWebsiteType',
106 );
107
108 foreach ($properties as $property) {
109 $this->assign($property, $this->get($property));
110 }
111
112 $statusID = $this->get('statusID');
113 if (!$statusID) {
114 $statusID = md5(uniqid(rand(), TRUE));
115 $this->set('statusID', $statusID);
116 }
117 $statusUrl = CRM_Utils_System::url('civicrm/ajax/status', "id={$statusID}", FALSE, NULL, FALSE);
118 $this->assign('statusUrl', $statusUrl);
119
120 $showColNames = TRUE;
121 if ('CRM_Import_DataSource_CSV' == $this->get('dataSource') &&
122 !$this->get('skipColumnHeader')
123 ) {
124 $showColNames = FALSE;
125 }
126 $this->assign('showColNames', $showColNames);
127 }
128
129 /**
130 * Function to actually build the form
131 *
355ba699 132 * @return void
6a488035
TO
133 * @access public
134 */
135 public function buildQuickForm() {
136 $this->addElement('text', 'newGroupName', ts('Name for new group'));
137 $this->addElement('text', 'newGroupDesc', ts('Description of new group'));
138
139 $groups = $this->get('groups');
140
141 if (!empty($groups)) {
24431f7b 142 $this->addElement('select', 'groups', ts('Add imported records to existing group(s)'), $groups, array('multiple' => "multiple", 'class' => 'crm-select2'));
6a488035
TO
143 }
144
145 //display new tag
146 $this->addElement('text', 'newTagName', ts('Tag'));
147 $this->addElement('text', 'newTagDesc', ts('Description'));
148
149 $tag = $this->get('tag');
150 if (!empty($tag)) {
151 foreach ($tag as $tagID => $tagName) {
152 $this->addElement('checkbox', "tag[$tagID]", NULL, $tagName);
153 }
154 }
155
156 $path = "_qf_MapField_display=true";
157 $qfKey = CRM_Utils_Request::retrieve('qfKey', 'String', $form);
158 if (CRM_Utils_Rule::qfKey($qfKey)) {
159 $path .= "&qfKey=$qfKey";
160 }
161
162 $previousURL = CRM_Utils_System::url('civicrm/import/contact', $path, FALSE, NULL, FALSE);
163 $cancelURL = CRM_Utils_System::url('civicrm/import/contact', 'reset=1');
164
165 $buttons = array(
166 array(
167 'type' => 'back',
168 'name' => ts('<< Previous'),
169 'js' => array('onclick' => "location.href='{$previousURL}'; return false;"),
170 ),
171 array(
172 'type' => 'next',
173 'name' => ts('Import Now >>'),
174 'spacing' => '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;',
175 'isDefault' => TRUE,
176 'js' => array('onclick' => "return verify( );"),
177 ),
178 array(
179 'type' => 'cancel',
180 'name' => ts('Cancel'),
181 'js' => array('onclick' => "location.href='{$cancelURL}'; return false;"),
182 ),
183 );
184
185 $this->addButtons($buttons);
186
719a6fec 187 $this->addFormRule(array('CRM_Contact_Import_Form_Preview', 'formRule'), $this);
6a488035
TO
188 }
189
190 /**
191 * global validation rules for the form
192 *
193 * @param array $fields posted values of the form
194 *
da6b46f4
EM
195 * @param $files
196 * @param $self
197 *
6a488035
TO
198 * @return array list of errors to be posted back to the form
199 * @static
200 * @access public
201 */
202 static function formRule($fields, $files, $self) {
203 $errors = array();
204 $invalidTagName = $invalidGroupName = FALSE;
205
a7488080 206 if (!empty($fields['newTagName'])) {
6a488035
TO
207 if (!CRM_Utils_Rule::objectExists(trim($fields['newTagName']),
208 array('CRM_Core_DAO_Tag')
209 )) {
210 $errors['newTagName'] = ts('Tag \'%1\' already exists.',
211 array(1 => $fields['newTagName'])
212 );
213 $invalidTagName = TRUE;
214 }
215 }
216
a7488080 217 if (!empty($fields['newGroupName'])) {
6a488035
TO
218 $title = trim($fields['newGroupName']);
219 $name = CRM_Utils_String::titleToVar($title);
220 $query = 'select count(*) from civicrm_group where name like %1 OR title like %2';
0e6e8724
DL
221 $grpCnt = CRM_Core_DAO::singleValueQuery(
222 $query,
223 array(
224 1 => array($name, 'String'),
6a488035 225 2 => array($title, 'String'),
0e6e8724
DL
226 )
227 );
6a488035
TO
228 if ($grpCnt) {
229 $invalidGroupName = TRUE;
230 $errors['newGroupName'] = ts('Group \'%1\' already exists.', array(1 => $fields['newGroupName']));
231 }
232 }
233
234 $self->assign('invalidTagName', $invalidTagName);
235 $self->assign('invalidGroupName', $invalidGroupName);
236
237 return empty($errors) ? TRUE : $errors;
238 }
239
6a488035
TO
240 /**
241 * Process the mapped fields and map it into the uploaded file
242 * preview the file and extract some summary statistics
243 *
244 * @return void
245 * @access public
246 */
247 public function postProcess() {
248
249 $importJobParams = array(
250 'doGeocodeAddress' => $this->controller->exportValue('DataSource', 'doGeocodeAddress'),
251 'invalidRowCount' => $this->get('invalidRowCount'),
252 'conflictRowCount' => $this->get('conflictRowCount'),
253 'onDuplicate' => $this->get('onDuplicate'),
254 'dedupe' => $this->get('dedupe'),
255 'newGroupName' => $this->controller->exportValue($this->_name, 'newGroupName'),
256 'newGroupDesc' => $this->controller->exportValue($this->_name, 'newGroupDesc'),
257 'groups' => $this->controller->exportValue($this->_name, 'groups'),
258 'allGroups' => $this->get('groups'),
259 'newTagName' => $this->controller->exportValue($this->_name, 'newTagName'),
260 'newTagDesc' => $this->controller->exportValue($this->_name, 'newTagDesc'),
261 'tag' => $this->controller->exportValue($this->_name, 'tag'),
262 'allTags' => $this->get('tag'),
263 'mapper' => $this->controller->exportValue('MapField', 'mapper'),
264 'mapFields' => $this->get('fields'),
265 'contactType' => $this->get('contactType'),
266 'contactSubType' => $this->get('contactSubType'),
267 'primaryKeyName' => $this->get('primaryKeyName'),
268 'statusFieldName' => $this->get('statusFieldName'),
269 'statusID' => $this->get('statusID'),
270 'totalRowCount' => $this->get('totalRowCount'),
271 );
272
273 $tableName = $this->get('importTableName');
719a6fec 274 $importJob = new CRM_Contact_Import_ImportJob($tableName);
6a488035
TO
275 $importJob->setJobParams($importJobParams);
276
277 // If ACL applies to the current user, update cache before running the import.
278 if (!CRM_Core_Permission::check('view all contacts')) {
279 $session = CRM_Core_Session::singleton();
280 $userID = $session->get('userID');
281 CRM_ACL_BAO_Cache::updateEntry($userID);
282 }
283
284 // run the import
285 $importJob->runImport($this);
286
287 // update cache after we done with runImport
288 if (!CRM_Core_Permission::check('view all contacts')) {
289 CRM_ACL_BAO_Cache::updateEntry($userID);
290 }
291
292 // clear all caches
293 CRM_Contact_BAO_Contact_Utils::clearContactCaches();
294
295 // add all the necessary variables to the form
296 $importJob->setFormVariables($this);
297
298 // check if there is any error occured
299 $errorStack = CRM_Core_Error::singleton();
300 $errors = $errorStack->getErrors();
301 $errorMessage = array();
302
303 if (is_array($errors)) {
304 foreach ($errors as $key => $value) {
305 $errorMessage[] = $value['message'];
306 }
307
308 // there is no fileName since this is a sql import
309 // so fudge it
310 $config = CRM_Core_Config::singleton();
311 $errorFile = $config->uploadDir . "sqlImport.error.log";
312 if ($fd = fopen($errorFile, 'w')) {
313 fwrite($fd, implode('\n', $errorMessage));
314 }
315 fclose($fd);
316
317 $this->set('errorFile', $errorFile);
318
a05662ef 319 $urlParams = 'type=' . CRM_Import_Parser::ERROR . '&parser=CRM_Contact_Import_Parser';
6a488035
TO
320 $this->set('downloadErrorRecordsUrl', CRM_Utils_System::url('civicrm/export', $urlParams));
321
a05662ef 322 $urlParams = 'type=' . CRM_Import_Parser::CONFLICT . '&parser=CRM_Contact_Import_Parser';
6a488035
TO
323 $this->set('downloadConflictRecordsUrl', CRM_Utils_System::url('civicrm/export', $urlParams));
324
a05662ef 325 $urlParams = 'type=' . CRM_Import_Parser::NO_MATCH . '&parser=CRM_Contact_Import_Parser';
6a488035
TO
326 $this->set('downloadMismatchRecordsUrl', CRM_Utils_System::url('civicrm/export', $urlParams));
327 }
328
329 //hack to clean db
330 //if job complete drop table.
331 $importJob->isComplete(TRUE);
332 }
333
334 /**
335 * Process the mapped fields and map it into the uploaded file
336 * preview the file and extract some summary statistics
337 *
338 * @return void
339 * @access public
340 */
341 public function postProcessOld() {
342
343 $doGeocodeAddress = $this->controller->exportValue('DataSource', 'doGeocodeAddress');
344 $invalidRowCount = $this->get('invalidRowCount');
345 $conflictRowCount = $this->get('conflictRowCount');
346 $onDuplicate = $this->get('onDuplicate');
347 $newGroupName = $this->controller->exportValue($this->_name, 'newGroupName');
348 $newGroupDesc = $this->controller->exportValue($this->_name, 'newGroupDesc');
349 $groups = $this->controller->exportValue($this->_name, 'groups');
350 $allGroups = $this->get('groups');
351 $newTagName = $this->controller->exportValue($this->_name, 'newTagName');
352 $newTagDesc = $this->controller->exportValue($this->_name, 'newTagDesc');
353 $tag = $this->controller->exportValue($this->_name, 'tag');
354 $allTags = $this->get('tag');
355
356 $mapper = $this->controller->exportValue('MapField', 'mapper');
357
358 $mapperKeys = array();
359 $mapperLocTypes = array();
360 $mapperPhoneTypes = array();
361 $mapperRelated = array();
362 $mapperRelatedContactType = array();
363 $mapperRelatedContactDetails = array();
364 $mapperRelatedContactLocType = array();
365 $mapperRelatedContactPhoneType = array();
366
367 foreach ($mapper as $key => $value) {
368 $mapperKeys[$key] = $mapper[$key][0];
369 if (is_numeric($mapper[$key][1])) {
370 $mapperLocTypes[$key] = $mapper[$key][1];
371 }
372 else {
373 $mapperLocTypes[$key] = NULL;
374 }
375
376 if (CRM_Utils_Array::value($key, $mapperKeys) == 'phone') {
377 $mapperPhoneTypes[$key] = $mapper[$key][2];
378 }
379 else {
380 $mapperPhoneTypes[$key] = NULL;
381 }
382
383 list($id, $first, $second) = explode('_', $mapper[$key][0]);
384 if (($first == 'a' && $second == 'b') || ($first == 'b' && $second == 'a')) {
385 $relationType = new CRM_Contact_DAO_RelationshipType();
386 $relationType->id = $id;
387 $relationType->find(TRUE);
0e6e8724
DL
388 $fieldName = "contact_type_$second";
389 $mapperRelatedContactType[$key] = $relationType->$fieldName;
6a488035
TO
390 $mapperRelated[$key] = $mapper[$key][0];
391 $mapperRelatedContactDetails[$key] = $mapper[$key][1];
392 $mapperRelatedContactLocType[$key] = $mapper[$key][2];
393 $mapperRelatedContactPhoneType[$key] = $mapper[$key][3];
394 }
395 else {
396 $mapperRelated[$key] = NULL;
397 $mapperRelatedContactType[$key] = NULL;
398 $mapperRelatedContactDetails[$key] = NULL;
399 $mapperRelatedContactLocType[$key] = NULL;
400 $mapperRelatedContactPhoneType[$key] = NULL;
401 }
402 }
403
719a6fec 404 $parser = new CRM_Contact_Import_Parser_Contact($mapperKeys, $mapperLocTypes,
6a488035
TO
405 $mapperPhoneTypes, $mapperRelated, $mapperRelatedContactType,
406 $mapperRelatedContactDetails, $mapperRelatedContactLocType,
407 $mapperRelatedContactPhoneType
408 );
409
410 $mapFields = $this->get('fields');
411
b2b0530a 412 $locationTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Address', 'location_type_id');
b4f964d9 413 $phoneTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Phone', 'phone_type_id');
6a488035
TO
414
415 foreach ($mapper as $key => $value) {
416 $header = array();
417 list($id, $first, $second) = explode('_', $mapper[$key][0]);
418 if (($first == 'a' && $second == 'b') || ($first == 'b' && $second == 'a')) {
419 $relationType = new CRM_Contact_DAO_RelationshipType();
420 $relationType->id = $id;
421 $relationType->find(TRUE);
422
423 $header[] = $relationType->name_a_b;
424 $header[] = ucwords(str_replace("_", " ", $mapper[$key][1]));
425
426 if (isset($mapper[$key][2])) {
427 $header[] = $locationTypes[$mapper[$key][2]];
428 }
429 if (isset($mapper[$key][3])) {
430 $header[] = $phoneTypes[$mapper[$key][3]];
431 }
432 }
433 else {
434 if (isset($mapFields[$mapper[$key][0]])) {
435 $header[] = $mapFields[$mapper[$key][0]];
436 if (isset($mapper[$key][1])) {
437 $header[] = $locationTypes[$mapper[$key][1]];
438 }
439 if (isset($mapper[$key][2])) {
440 $header[] = $phoneTypes[$mapper[$key][2]];
441 }
442 }
443 }
444 $mapperFields[] = implode(' - ', $header);
445 }
446
447 $tableName = $this->get('importTableName');
448 //print "Running parser on table: $tableName<br/>";
449 $parser->run($tableName, $mapperFields,
a05662ef 450 CRM_Import_Parser::MODE_IMPORT,
6a488035
TO
451 $this->get('contactType'),
452 $this->get('primaryKeyName'),
453 $this->get('statusFieldName'),
454 $onDuplicate,
455 $this->get('statusID'),
456 $this->get('totalRowCount'),
457 $doGeocodeAddress,
719a6fec 458 CRM_Contact_Import_Parser::DEFAULT_TIMEOUT,
6a488035
TO
459 $this->get('contactSubType'),
460 $this->get('dedupe')
461 );
462
463 // add the new contacts to selected groups
464 $contactIds = &$parser->getImportedContacts();
465
466 // add the new related contacts to selected groups
467 $relatedContactIds = &$parser->getRelatedImportedContacts();
468
469 $this->set('relatedCount', count($relatedContactIds));
470 $newGroupId = NULL;
471
472 //changed below if-statement "if ($newGroup) {" to "if ($newGroupName) {"
473 if ($newGroupName) {
474 /* Create a new group */
475
476 $gParams = array(
477 'name' => $newGroupName,
478 'title' => $newGroupName,
479 'description' => $newGroupDesc,
480 'is_active' => TRUE,
481 );
482 $group = CRM_Contact_BAO_Group::create($gParams);
483 $groups[] = $newGroupId = $group->id;
484 }
485
486 if (is_array($groups)) {
487 $groupAdditions = array();
488 foreach ($groups as $groupId) {
489 $addCount = CRM_Contact_BAO_GroupContact::addContactsToGroup($contactIds, $groupId);
490 if (!empty($relatedContactIds)) {
491 $addRelCount = CRM_Contact_BAO_GroupContact::addContactsToGroup($relatedContactIds, $groupId);
492 }
493 $totalCount = $addCount[1] + $addRelCount[1];
494 if ($groupId == $newGroupId) {
495 $name = $newGroupName;
496 $new = TRUE;
497 }
498 else {
499 $name = $allGroups[$groupId];
500 $new = FALSE;
501 }
502 $groupAdditions[] = array(
503 'url' => CRM_Utils_System::url('civicrm/group/search',
504 'reset=1&force=1&context=smog&gid=' . $groupId
505 ),
506 'name' => $name,
507 'added' => $totalCount,
508 'notAdded' => $addCount[2] + $addRelCount[2],
509 'new' => $new,
510 );
511 }
512 $this->set('groupAdditions', $groupAdditions);
513 }
514
515 $newTagId = NULL;
516 if ($newTagName) {
517 /* Create a new Tag */
518
519 $tagParams = array(
520 'name' => $newTagName,
521 'title' => $newTagName,
522 'description' => $newTagDesc,
523 'is_active' => TRUE,
524 );
525 $id = array();
526 $addedTag = CRM_Core_BAO_Tag::add($tagParams, $id);
527 $tag[$addedTag->id] = 1;
528 }
529 //add Tag to Import
530
531 if (is_array($tag)) {
532
533 $tagAdditions = array();
534 foreach ($tag as $tagId => $val) {
535 $addTagCount = CRM_Core_BAO_EntityTag::addContactsToTag($contactIds, $tagId);
536 if (!empty($relatedContactIds)) {
537 $addRelTagCount = CRM_Core_BAO_EntityTag::addContactsToTag($relatedContactIds, $tagId);
538 }
539 $totalTagCount = $addTagCount[1] + $addRelTagCount[1];
540 if ($tagId == $addedTag->id) {
541 $tagName = $newTagName;
542 $new = TRUE;
543 }
544 else {
545 $tagName = $allTags[$tagId];
546 $new = FALSE;
547 }
548 $tagAdditions[] = array(
549 'url' => CRM_Utils_System::url('civicrm/contact/search',
550 'reset=1&force=1&context=smog&id=' . $tagId
551 ),
552 'name' => $tagName,
553 'added' => $totalTagCount,
554 'notAdded' => $addTagCount[2] + $addRelTagCount[2],
555 'new' => $new,
556 );
557 }
558 $this->set('tagAdditions', $tagAdditions);
559 }
560
561 // add all the necessary variables to the form
a05662ef 562 $parser->set($this, CRM_Import_Parser::MODE_IMPORT);
6a488035
TO
563
564 // check if there is any error occured
565
566 $errorStack = CRM_Core_Error::singleton();
567 $errors = $errorStack->getErrors();
568 $errorMessage = array();
569
570 if (is_array($errors)) {
571 foreach ($errors as $key => $value) {
572 $errorMessage[] = $value['message'];
573 }
574
575 // there is no fileName since this is a sql import
576 // so fudge it
577 $config = CRM_Core_Config::singleton();
578 $errorFile = $config->uploadDir . "sqlImport.error.log";
579 if ($fd = fopen($errorFile, 'w')) {
580 fwrite($fd, implode('\n', $errorMessage));
581 }
582 fclose($fd);
583
584 $this->set('errorFile', $errorFile);
585
a05662ef 586 $urlParams = 'type=' . CRM_Import_Parser::ERROR . '&parser=CRM_Contact_Import_Parser';
6a488035
TO
587 $this->set('downloadErrorRecordsUrl', CRM_Utils_System::url('civicrm/export', $urlparams));
588
a05662ef 589 $urlParams = 'type=' . CRM_Import_Parser::CONFLICT . '&parser=CRM_Contact_Import_Parser';
6a488035
TO
590 $this->set('downloadConflictRecordsUrl', CRM_Utils_System::url('civicrm/export', $urlParams));
591
a05662ef 592 $urlParams = 'type=' . CRM_Import_Parser::NO_MATCH . '&parser=CRM_Contact_Import_Parser';
6a488035
TO
593 $this->set('downloadMismatchRecordsUrl', CRM_Utils_System::url('civicrm/export', $urlParams));
594 }
595 }
596}
597