3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2014 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
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. |
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. |
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 +--------------------------------------------------------------------+
31 * @copyright CiviCRM LLC (c) 2004-2014
37 abstract class CRM_Import_Parser
{
41 CONST MAX_ERRORS
= 250, MAX_WARNINGS
= 25, DEFAULT_TIMEOUT
= 30;
46 CONST VALID
= 1, WARNING
= 2, ERROR
= 4, CONFLICT
= 8, STOP
= 16, DUPLICATE
= 32, MULTIPLE_DUPE
= 64, NO_MATCH
= 128, UNPARSED_ADDRESS_WARNING
= 256;
51 CONST MODE_MAPFIELD
= 1, MODE_PREVIEW
= 2, MODE_SUMMARY
= 4, MODE_IMPORT
= 8;
54 * Codes for duplicate record handling
56 CONST DUPLICATE_SKIP
= 1, DUPLICATE_REPLACE
= 2, DUPLICATE_UPDATE
= 4, DUPLICATE_FILL
= 8, DUPLICATE_NOCHECK
= 16;
61 CONST CONTACT_INDIVIDUAL
= 1, CONTACT_HOUSEHOLD
= 2, CONTACT_ORGANIZATION
= 4;
65 * total number of non empty lines
67 protected $_totalCount;
70 * running total number of valid lines
72 protected $_validCount;
75 * running total number of invalid rows
77 protected $_invalidRowCount;
80 * maximum number of non-empty/comment lines to process
84 protected $_maxLinesToProcess;
87 * maximum number of invalid rows to store
89 protected $_maxErrorCount;
92 * array of error lines, bounded by MAX_ERROR
97 * total number of conflict lines
99 protected $_conflictCount;
102 * array of conflict lines
104 protected $_conflicts;
107 * total number of duplicate (from database) lines
109 protected $_duplicateCount;
112 * array of duplicate lines
114 protected $_duplicates;
117 * running total number of warnings
119 protected $_warningCount;
122 * maximum number of warnings to store
124 protected $_maxWarningCount = self
::MAX_WARNINGS
;
127 * array of warning lines, bounded by MAX_WARNING
129 protected $_warnings;
132 * array of all the fields that could potentially be part
133 * of this import process
139 * array of the fields that are actually part of the import process
140 * the position in the array also dictates their position in the import
144 protected $_activeFields;
147 * cache the count of active fields
151 protected $_activeFieldCount;
154 * cache of preview rows
161 * filename of error data
165 protected $_errorFileName;
168 * filename of conflict data
172 protected $_conflictFileName;
175 * filename of duplicate data
179 protected $_duplicateFileName;
186 public $_contactType;
191 function __construct() {
192 $this->_maxLinesToProcess
= 0;
193 $this->_maxErrorCount
= self
::MAX_ERRORS
;
197 * Abstract function definitions
199 abstract function init();
204 abstract function fini();
211 abstract function mapField(&$values);
218 abstract function preview(&$values);
225 abstract function summary(&$values);
228 * @param $onDuplicate
233 abstract function import($onDuplicate, &$values);
236 * Set and validate field values
238 * @param $elements : array
239 * @param $erroneousField : reference
243 function setActiveFieldValues($elements, &$erroneousField) {
244 $maxCount = count($elements) < $this->_activeFieldCount ?
count($elements) : $this->_activeFieldCount
;
245 for ($i = 0; $i < $maxCount; $i++
) {
246 $this->_activeFields
[$i]->setValue($elements[$i]);
249 // reset all the values that we did not have an equivalent import element
250 for (; $i < $this->_activeFieldCount
; $i++
) {
251 $this->_activeFields
[$i]->resetValue();
254 // now validate the fields and return false if error
255 $valid = self
::VALID
;
256 for ($i = 0; $i < $this->_activeFieldCount
; $i++
) {
257 if (!$this->_activeFields
[$i]->validate()) {
258 // no need to do any more validation
259 $erroneousField = $i;
260 $valid = self
::ERROR
;
268 * Format the field values for input to the api
270 * @return array (reference) associative array of name/value pairs
273 function &getActiveFieldParams() {
275 for ($i = 0; $i < $this->_activeFieldCount
; $i++
) {
276 if (isset($this->_activeFields
[$i]->_value
)
277 && !isset($params[$this->_activeFields
[$i]->_name
])
278 && !isset($this->_activeFields
[$i]->_related
)
281 $params[$this->_activeFields
[$i]->_name
] = $this->_activeFields
[$i]->_value
;
290 function getSelectValues() {
292 foreach ($this->_fields
as $name => $field) {
293 $values[$name] = $field->_title
;
301 function getSelectTypes() {
303 foreach ($this->_fields
as $name => $field) {
304 if (isset($field->_hasLocationType
)) {
305 $values[$name] = $field->_hasLocationType
;
314 function getHeaderPatterns() {
316 foreach ($this->_fields
as $name => $field) {
317 if (isset($field->_headerPattern
)) {
318 $values[$name] = $field->_headerPattern
;
327 function getDataPatterns() {
329 foreach ($this->_fields
as $name => $field) {
330 $values[$name] = $field->_dataPattern
;
336 * Remove single-quote enclosures from a value array (row)
338 * @param array $values
339 * @param string $enclosure
345 static function encloseScrub(&$values, $enclosure = "'") {
346 if (empty($values)) {
350 foreach ($values as $k => $v) {
351 $values[$k] = preg_replace("/^$enclosure(.*)$enclosure$/", '$1', $v);
363 function setMaxLinesToProcess($max) {
364 $this->_maxLinesToProcess
= $max;
368 * Determines the file extension based on error code
370 * @var $type error code constant
374 static function errorFileName($type) {
380 $config = CRM_Core_Config
::singleton();
381 $fileName = $config->uploadDir
. "sqlImport";
384 $fileName .= '.errors';
388 $fileName .= '.conflicts';
391 case self
::DUPLICATE
:
392 $fileName .= '.duplicates';
396 $fileName .= '.mismatch';
399 case self
::UNPARSED_ADDRESS_WARNING
:
400 $fileName .= '.unparsedAddress';
408 * Determines the file name based on error code
410 * @var $type error code constant
414 static function saveFileName($type) {
421 $fileName = 'Import_Errors.csv';
425 $fileName = 'Import_Conflicts.csv';
428 case self
::DUPLICATE
:
429 $fileName = 'Import_Duplicates.csv';
433 $fileName = 'Import_Mismatch.csv';
436 case self
::UNPARSED_ADDRESS_WARNING
:
437 $fileName = 'Import_Unparsed_Address.csv';