3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.6 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2015 |
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-2015
35 abstract class CRM_Import_Parser
{
39 const MAX_ERRORS
= 250, MAX_WARNINGS
= 25, DEFAULT_TIMEOUT
= 30;
44 const VALID
= 1, WARNING
= 2, ERROR
= 4, CONFLICT
= 8, STOP
= 16, DUPLICATE
= 32, MULTIPLE_DUPE
= 64, NO_MATCH
= 128, UNPARSED_ADDRESS_WARNING
= 256;
49 const MODE_MAPFIELD
= 1, MODE_PREVIEW
= 2, MODE_SUMMARY
= 4, MODE_IMPORT
= 8;
52 * Codes for duplicate record handling
54 const DUPLICATE_SKIP
= 1, DUPLICATE_REPLACE
= 2, DUPLICATE_UPDATE
= 4, DUPLICATE_FILL
= 8, DUPLICATE_NOCHECK
= 16;
59 const CONTACT_INDIVIDUAL
= 1, CONTACT_HOUSEHOLD
= 2, CONTACT_ORGANIZATION
= 4;
63 * Total number of non empty lines
65 protected $_totalCount;
68 * Running total number of valid lines
70 protected $_validCount;
73 * Running total number of invalid rows
75 protected $_invalidRowCount;
78 * Maximum number of non-empty/comment lines to process
82 protected $_maxLinesToProcess;
85 * Maximum number of invalid rows to store
87 protected $_maxErrorCount;
90 * Array of error lines, bounded by MAX_ERROR
95 * Total number of conflict lines
97 protected $_conflictCount;
100 * Array of conflict lines
102 protected $_conflicts;
105 * Total number of duplicate (from database) lines
107 protected $_duplicateCount;
110 * Array of duplicate lines
112 protected $_duplicates;
115 * Running total number of warnings
117 protected $_warningCount;
120 * Maximum number of warnings to store
122 protected $_maxWarningCount = self
::MAX_WARNINGS
;
125 * Array of warning lines, bounded by MAX_WARNING
127 protected $_warnings;
130 * Array of all the fields that could potentially be part
131 * of this import process
137 * Array of the fields that are actually part of the import process
138 * the position in the array also dictates their position in the import
142 protected $_activeFields;
145 * Cache the count of active fields
149 protected $_activeFieldCount;
152 * Cache of preview rows
159 * Filename of error data
163 protected $_errorFileName;
166 * Filename of conflict data
170 protected $_conflictFileName;
173 * Filename of duplicate data
177 protected $_duplicateFileName;
184 public $_contactType;
189 public function __construct() {
190 $this->_maxLinesToProcess
= 0;
191 $this->_maxErrorCount
= self
::MAX_ERRORS
;
195 * Abstract function definitions.
197 abstract protected function init();
202 abstract protected function fini();
209 abstract protected function mapField(&$values);
216 abstract protected function preview(&$values);
223 abstract protected function summary(&$values);
226 * @param $onDuplicate
231 abstract protected function import($onDuplicate, &$values);
234 * Set and validate field values.
236 * @param array $elements
238 * @param $erroneousField
243 public 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.
271 * (reference) associative array of name/value pairs
273 public 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 public function getSelectValues() {
292 foreach ($this->_fields
as $name => $field) {
293 $values[$name] = $field->_title
;
301 public function getSelectTypes() {
303 foreach ($this->_fields
as $name => $field) {
304 if (isset($field->_hasLocationType
)) {
305 $values[$name] = $field->_hasLocationType
;
314 public function getHeaderPatterns() {
316 foreach ($this->_fields
as $name => $field) {
317 if (isset($field->_headerPattern
)) {
318 $values[$name] = $field->_headerPattern
;
327 public 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
343 public static function encloseScrub(&$values, $enclosure = "'") {
344 if (empty($values)) {
348 foreach ($values as $k => $v) {
349 $values[$k] = preg_replace("/^$enclosure(.*)$enclosure$/", '$1', $v);
360 public function setMaxLinesToProcess($max) {
361 $this->_maxLinesToProcess
= $max;
365 * Determines the file extension based on error code.
367 * @var $type error code constant
370 public static function errorFileName($type) {
376 $config = CRM_Core_Config
::singleton();
377 $fileName = $config->uploadDir
. "sqlImport";
380 $fileName .= '.errors';
384 $fileName .= '.conflicts';
387 case self
::DUPLICATE
:
388 $fileName .= '.duplicates';
392 $fileName .= '.mismatch';
395 case self
::UNPARSED_ADDRESS_WARNING
:
396 $fileName .= '.unparsedAddress';
404 * Determines the file name based on error code.
406 * @var $type error code constant
409 public static function saveFileName($type) {
416 $fileName = 'Import_Errors.csv';
420 $fileName = 'Import_Conflicts.csv';
423 case self
::DUPLICATE
:
424 $fileName = 'Import_Duplicates.csv';
428 $fileName = 'Import_Mismatch.csv';
431 case self
::UNPARSED_ADDRESS_WARNING
:
432 $fileName = 'Import_Unparsed_Address.csv';