3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.4 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2013 |
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-2013
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();
200 abstract function fini();
201 abstract function mapField(&$values);
202 abstract function preview(&$values);
203 abstract function summary(&$values);
204 abstract function import($onDuplicate, &$values);
207 * Set and validate field values
209 * @param $elements: array
210 * @param $erroneousField: reference
212 function setActiveFieldValues($elements, &$erroneousField) {
213 $maxCount = count($elements) < $this->_activeFieldCount ?
count($elements) : $this->_activeFieldCount
;
214 for ($i = 0; $i < $maxCount; $i++
) {
215 $this->_activeFields
[$i]->setValue($elements[$i]);
218 // reset all the values that we did not have an equivalent import element
219 for (; $i < $this->_activeFieldCount
; $i++
) {
220 $this->_activeFields
[$i]->resetValue();
223 // now validate the fields and return false if error
224 $valid = self
::VALID
;
225 for ($i = 0; $i < $this->_activeFieldCount
; $i++
) {
226 if (!$this->_activeFields
[$i]->validate()) {
227 // no need to do any more validation
228 $erroneousField = $i;
229 $valid = self
::ERROR
;
237 * Format the field values for input to the api
239 * @return array (reference) associative array of name/value pairs
242 function &getActiveFieldParams() {
244 for ($i = 0; $i < $this->_activeFieldCount
; $i++
) {
245 if (isset($this->_activeFields
[$i]->_value
)
246 && !isset($params[$this->_activeFields
[$i]->_name
])
247 && !isset($this->_activeFields
[$i]->_related
)
250 $params[$this->_activeFields
[$i]->_name
] = $this->_activeFields
[$i]->_value
;
256 function getSelectValues() {
258 foreach ($this->_fields
as $name => $field) {
259 $values[$name] = $field->_title
;
264 function getSelectTypes() {
266 foreach ($this->_fields
as $name => $field) {
267 if (isset($field->_hasLocationType
)) {
268 $values[$name] = $field->_hasLocationType
;
274 function getHeaderPatterns() {
276 foreach ($this->_fields
as $name => $field) {
277 if (isset($field->_headerPattern
)) {
278 $values[$name] = $field->_headerPattern
;
284 function getDataPatterns() {
286 foreach ($this->_fields
as $name => $field) {
287 $values[$name] = $field->_dataPattern
;
293 * Remove single-quote enclosures from a value array (row)
295 * @param array $values
296 * @param string $enclosure
302 static function encloseScrub(&$values, $enclosure = "'") {
303 if (empty($values)) {
307 foreach ($values as $k => $v) {
308 $values[$k] = preg_replace("/^$enclosure(.*)$enclosure$/", '$1', $v);
320 function setMaxLinesToProcess($max) {
321 $this->_maxLinesToProcess
= $max;
325 * Determines the file extension based on error code
327 * @var $type error code constant
331 static function errorFileName($type) {
337 $config = CRM_Core_Config
::singleton();
338 $fileName = $config->uploadDir
. "sqlImport";
341 $fileName .= '.errors';
345 $fileName .= '.conflicts';
348 case self
::DUPLICATE
:
349 $fileName .= '.duplicates';
353 $fileName .= '.mismatch';
356 case self
::UNPARSED_ADDRESS_WARNING
:
357 $fileName .= '.unparsedAddress';
365 * Determines the file name based on error code
367 * @var $type error code constant
371 static function saveFileName($type) {
378 $fileName = 'Import_Errors.csv';
382 $fileName = 'Import_Conflicts.csv';
385 case self
::DUPLICATE
:
386 $fileName = 'Import_Duplicates.csv';
390 $fileName = 'Import_Mismatch.csv';
393 case self
::UNPARSED_ADDRESS_WARNING
:
394 $fileName = 'Import_Unparsed_Address.csv';