3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.7 |
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;
190 public $_contactSubType;
195 public function __construct() {
196 $this->_maxLinesToProcess
= 0;
197 $this->_maxErrorCount
= self
::MAX_ERRORS
;
201 * Abstract function definitions.
203 abstract protected function init();
208 abstract protected function fini();
215 abstract protected function mapField(&$values);
222 abstract protected function preview(&$values);
229 abstract protected function summary(&$values);
232 * @param $onDuplicate
237 abstract protected function import($onDuplicate, &$values);
240 * Set and validate field values.
242 * @param array $elements
244 * @param $erroneousField
249 public function setActiveFieldValues($elements, &$erroneousField) {
250 $maxCount = count($elements) < $this->_activeFieldCount ?
count($elements) : $this->_activeFieldCount
;
251 for ($i = 0; $i < $maxCount; $i++
) {
252 $this->_activeFields
[$i]->setValue($elements[$i]);
255 // reset all the values that we did not have an equivalent import element
256 for (; $i < $this->_activeFieldCount
; $i++
) {
257 $this->_activeFields
[$i]->resetValue();
260 // now validate the fields and return false if error
261 $valid = self
::VALID
;
262 for ($i = 0; $i < $this->_activeFieldCount
; $i++
) {
263 if (!$this->_activeFields
[$i]->validate()) {
264 // no need to do any more validation
265 $erroneousField = $i;
266 $valid = self
::ERROR
;
274 * Format the field values for input to the api.
277 * (reference) associative array of name/value pairs
279 public function &getActiveFieldParams() {
281 for ($i = 0; $i < $this->_activeFieldCount
; $i++
) {
282 if (isset($this->_activeFields
[$i]->_value
)
283 && !isset($params[$this->_activeFields
[$i]->_name
])
284 && !isset($this->_activeFields
[$i]->_related
)
287 $params[$this->_activeFields
[$i]->_name
] = $this->_activeFields
[$i]->_value
;
296 public function getSelectValues() {
298 foreach ($this->_fields
as $name => $field) {
299 $values[$name] = $field->_title
;
307 public function getSelectTypes() {
309 foreach ($this->_fields
as $name => $field) {
310 if (isset($field->_hasLocationType
)) {
311 $values[$name] = $field->_hasLocationType
;
320 public function getHeaderPatterns() {
322 foreach ($this->_fields
as $name => $field) {
323 if (isset($field->_headerPattern
)) {
324 $values[$name] = $field->_headerPattern
;
333 public function getDataPatterns() {
335 foreach ($this->_fields
as $name => $field) {
336 $values[$name] = $field->_dataPattern
;
342 * Remove single-quote enclosures from a value array (row)
344 * @param array $values
345 * @param string $enclosure
349 public static function encloseScrub(&$values, $enclosure = "'") {
350 if (empty($values)) {
354 foreach ($values as $k => $v) {
355 $values[$k] = preg_replace("/^$enclosure(.*)$enclosure$/", '$1', $v);
366 public function setMaxLinesToProcess($max) {
367 $this->_maxLinesToProcess
= $max;
371 * Determines the file extension based on error code.
373 * @var $type error code constant
376 public static function errorFileName($type) {
382 $config = CRM_Core_Config
::singleton();
383 $fileName = $config->uploadDir
. "sqlImport";
386 $fileName .= '.errors';
390 $fileName .= '.conflicts';
393 case self
::DUPLICATE
:
394 $fileName .= '.duplicates';
398 $fileName .= '.mismatch';
401 case self
::UNPARSED_ADDRESS_WARNING
:
402 $fileName .= '.unparsedAddress';
410 * Determines the file name based on error code.
412 * @var $type error code constant
415 public static function saveFileName($type) {
422 $fileName = 'Import_Errors.csv';
426 $fileName = 'Import_Conflicts.csv';
429 case self
::DUPLICATE
:
430 $fileName = 'Import_Duplicates.csv';
434 $fileName = 'Import_Mismatch.csv';
437 case self
::UNPARSED_ADDRESS_WARNING
:
438 $fileName = 'Import_Unparsed_Address.csv';