First commit
This commit is contained in:
commit
c6e2478c40
13918 changed files with 2303184 additions and 0 deletions
463
sites/all/modules/civicrm/CRM/Import/Parser.php
Normal file
463
sites/all/modules/civicrm/CRM/Import/Parser.php
Normal file
|
@ -0,0 +1,463 @@
|
|||
<?php
|
||||
/*
|
||||
+--------------------------------------------------------------------+
|
||||
| CiviCRM version 4.7 |
|
||||
+--------------------------------------------------------------------+
|
||||
| Copyright CiviCRM LLC (c) 2004-2017 |
|
||||
+--------------------------------------------------------------------+
|
||||
| This file is a part of CiviCRM. |
|
||||
| |
|
||||
| CiviCRM is free software; you can copy, modify, and distribute it |
|
||||
| under the terms of the GNU Affero General Public License |
|
||||
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
|
||||
| |
|
||||
| CiviCRM is distributed in the hope that it will be useful, but |
|
||||
| WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
|
||||
| See the GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| You should have received a copy of the GNU Affero General Public |
|
||||
| License and the CiviCRM Licensing Exception along |
|
||||
| with this program; if not, contact CiviCRM LLC |
|
||||
| at info[AT]civicrm[DOT]org. If you have questions about the |
|
||||
| GNU Affero General Public License or the licensing of CiviCRM, |
|
||||
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
|
||||
+--------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @package CRM
|
||||
* @copyright CiviCRM LLC (c) 2004-2017
|
||||
*/
|
||||
abstract class CRM_Import_Parser {
|
||||
/**
|
||||
* Settings
|
||||
*/
|
||||
const MAX_ERRORS = 250, MAX_WARNINGS = 25, DEFAULT_TIMEOUT = 30;
|
||||
|
||||
/**
|
||||
* Return codes
|
||||
*/
|
||||
const VALID = 1, WARNING = 2, ERROR = 4, CONFLICT = 8, STOP = 16, DUPLICATE = 32, MULTIPLE_DUPE = 64, NO_MATCH = 128, UNPARSED_ADDRESS_WARNING = 256;
|
||||
|
||||
/**
|
||||
* Parser modes
|
||||
*/
|
||||
const MODE_MAPFIELD = 1, MODE_PREVIEW = 2, MODE_SUMMARY = 4, MODE_IMPORT = 8;
|
||||
|
||||
/**
|
||||
* Codes for duplicate record handling
|
||||
*/
|
||||
const DUPLICATE_SKIP = 1, DUPLICATE_REPLACE = 2, DUPLICATE_UPDATE = 4, DUPLICATE_FILL = 8, DUPLICATE_NOCHECK = 16;
|
||||
|
||||
/**
|
||||
* Contact types
|
||||
*/
|
||||
const CONTACT_INDIVIDUAL = 1, CONTACT_HOUSEHOLD = 2, CONTACT_ORGANIZATION = 4;
|
||||
|
||||
|
||||
/**
|
||||
* Total number of non empty lines
|
||||
*/
|
||||
protected $_totalCount;
|
||||
|
||||
/**
|
||||
* Running total number of valid lines
|
||||
*/
|
||||
protected $_validCount;
|
||||
|
||||
/**
|
||||
* Running total number of invalid rows
|
||||
*/
|
||||
protected $_invalidRowCount;
|
||||
|
||||
/**
|
||||
* Maximum number of non-empty/comment lines to process
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $_maxLinesToProcess;
|
||||
|
||||
/**
|
||||
* Maximum number of invalid rows to store
|
||||
*/
|
||||
protected $_maxErrorCount;
|
||||
|
||||
/**
|
||||
* Array of error lines, bounded by MAX_ERROR
|
||||
*/
|
||||
protected $_errors;
|
||||
|
||||
/**
|
||||
* Total number of conflict lines
|
||||
*/
|
||||
protected $_conflictCount;
|
||||
|
||||
/**
|
||||
* Array of conflict lines
|
||||
*/
|
||||
protected $_conflicts;
|
||||
|
||||
/**
|
||||
* Total number of duplicate (from database) lines
|
||||
*/
|
||||
protected $_duplicateCount;
|
||||
|
||||
/**
|
||||
* Array of duplicate lines
|
||||
*/
|
||||
protected $_duplicates;
|
||||
|
||||
/**
|
||||
* Running total number of warnings
|
||||
*/
|
||||
protected $_warningCount;
|
||||
|
||||
/**
|
||||
* Maximum number of warnings to store
|
||||
*/
|
||||
protected $_maxWarningCount = self::MAX_WARNINGS;
|
||||
|
||||
/**
|
||||
* Array of warning lines, bounded by MAX_WARNING
|
||||
*/
|
||||
protected $_warnings;
|
||||
|
||||
/**
|
||||
* Array of all the fields that could potentially be part
|
||||
* of this import process
|
||||
* @var array
|
||||
*/
|
||||
protected $_fields;
|
||||
|
||||
/**
|
||||
* Array of the fields that are actually part of the import process
|
||||
* the position in the array also dictates their position in the import
|
||||
* file
|
||||
* @var array
|
||||
*/
|
||||
protected $_activeFields;
|
||||
|
||||
/**
|
||||
* Cache the count of active fields
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $_activeFieldCount;
|
||||
|
||||
/**
|
||||
* Cache of preview rows
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_rows;
|
||||
|
||||
/**
|
||||
* Filename of error data
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_errorFileName;
|
||||
|
||||
/**
|
||||
* Filename of conflict data
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_conflictFileName;
|
||||
|
||||
/**
|
||||
* Filename of duplicate data
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_duplicateFileName;
|
||||
|
||||
/**
|
||||
* Contact type
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $_contactType;
|
||||
/**
|
||||
* Contact sub-type
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $_contactSubType;
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->_maxLinesToProcess = 0;
|
||||
$this->_maxErrorCount = self::MAX_ERRORS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract function definitions.
|
||||
*/
|
||||
abstract protected function init();
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
abstract protected function fini();
|
||||
|
||||
/**
|
||||
* Map field.
|
||||
*
|
||||
* @param array $values
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
abstract protected function mapField(&$values);
|
||||
|
||||
/**
|
||||
* Preview.
|
||||
*
|
||||
* @param array $values
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
abstract protected function preview(&$values);
|
||||
|
||||
/**
|
||||
* @param $values
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
abstract protected function summary(&$values);
|
||||
|
||||
/**
|
||||
* @param $onDuplicate
|
||||
* @param $values
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
abstract protected function import($onDuplicate, &$values);
|
||||
|
||||
/**
|
||||
* Set and validate field values.
|
||||
*
|
||||
* @param array $elements
|
||||
* array.
|
||||
* @param $erroneousField
|
||||
* reference.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function setActiveFieldValues($elements, &$erroneousField) {
|
||||
$maxCount = count($elements) < $this->_activeFieldCount ? count($elements) : $this->_activeFieldCount;
|
||||
for ($i = 0; $i < $maxCount; $i++) {
|
||||
$this->_activeFields[$i]->setValue($elements[$i]);
|
||||
}
|
||||
|
||||
// reset all the values that we did not have an equivalent import element
|
||||
for (; $i < $this->_activeFieldCount; $i++) {
|
||||
$this->_activeFields[$i]->resetValue();
|
||||
}
|
||||
|
||||
// now validate the fields and return false if error
|
||||
$valid = self::VALID;
|
||||
for ($i = 0; $i < $this->_activeFieldCount; $i++) {
|
||||
if (!$this->_activeFields[$i]->validate()) {
|
||||
// no need to do any more validation
|
||||
$erroneousField = $i;
|
||||
$valid = self::ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $valid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the field values for input to the api.
|
||||
*
|
||||
* @return array
|
||||
* (reference) associative array of name/value pairs
|
||||
*/
|
||||
public function &getActiveFieldParams() {
|
||||
$params = array();
|
||||
for ($i = 0; $i < $this->_activeFieldCount; $i++) {
|
||||
if (isset($this->_activeFields[$i]->_value)
|
||||
&& !isset($params[$this->_activeFields[$i]->_name])
|
||||
&& !isset($this->_activeFields[$i]->_related)
|
||||
) {
|
||||
|
||||
$params[$this->_activeFields[$i]->_name] = $this->_activeFields[$i]->_value;
|
||||
}
|
||||
}
|
||||
return $params;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getSelectValues() {
|
||||
$values = array();
|
||||
foreach ($this->_fields as $name => $field) {
|
||||
$values[$name] = $field->_title;
|
||||
}
|
||||
return $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getSelectTypes() {
|
||||
$values = array();
|
||||
foreach ($this->_fields as $name => $field) {
|
||||
if (isset($field->_hasLocationType)) {
|
||||
$values[$name] = $field->_hasLocationType;
|
||||
}
|
||||
}
|
||||
return $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getHeaderPatterns() {
|
||||
$values = array();
|
||||
foreach ($this->_fields as $name => $field) {
|
||||
if (isset($field->_headerPattern)) {
|
||||
$values[$name] = $field->_headerPattern;
|
||||
}
|
||||
}
|
||||
return $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getDataPatterns() {
|
||||
$values = array();
|
||||
foreach ($this->_fields as $name => $field) {
|
||||
$values[$name] = $field->_dataPattern;
|
||||
}
|
||||
return $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove single-quote enclosures from a value array (row).
|
||||
*
|
||||
* @param array $values
|
||||
* @param string $enclosure
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function encloseScrub(&$values, $enclosure = "'") {
|
||||
if (empty($values)) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($values as $k => $v) {
|
||||
$values[$k] = preg_replace("/^$enclosure(.*)$enclosure$/", '$1', $v);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter function.
|
||||
*
|
||||
* @param int $max
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setMaxLinesToProcess($max) {
|
||||
$this->_maxLinesToProcess = $max;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the file extension based on error code.
|
||||
*
|
||||
* @var $type error code constant
|
||||
* @return string
|
||||
*/
|
||||
public static function errorFileName($type) {
|
||||
$fileName = NULL;
|
||||
if (empty($type)) {
|
||||
return $fileName;
|
||||
}
|
||||
|
||||
$config = CRM_Core_Config::singleton();
|
||||
$fileName = $config->uploadDir . "sqlImport";
|
||||
switch ($type) {
|
||||
case self::ERROR:
|
||||
$fileName .= '.errors';
|
||||
break;
|
||||
|
||||
case self::CONFLICT:
|
||||
$fileName .= '.conflicts';
|
||||
break;
|
||||
|
||||
case self::DUPLICATE:
|
||||
$fileName .= '.duplicates';
|
||||
break;
|
||||
|
||||
case self::NO_MATCH:
|
||||
$fileName .= '.mismatch';
|
||||
break;
|
||||
|
||||
case self::UNPARSED_ADDRESS_WARNING:
|
||||
$fileName .= '.unparsedAddress';
|
||||
break;
|
||||
}
|
||||
|
||||
return $fileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the file name based on error code.
|
||||
*
|
||||
* @var $type error code constant
|
||||
* @return string
|
||||
*/
|
||||
public static function saveFileName($type) {
|
||||
$fileName = NULL;
|
||||
if (empty($type)) {
|
||||
return $fileName;
|
||||
}
|
||||
switch ($type) {
|
||||
case self::ERROR:
|
||||
$fileName = 'Import_Errors.csv';
|
||||
break;
|
||||
|
||||
case self::CONFLICT:
|
||||
$fileName = 'Import_Conflicts.csv';
|
||||
break;
|
||||
|
||||
case self::DUPLICATE:
|
||||
$fileName = 'Import_Duplicates.csv';
|
||||
break;
|
||||
|
||||
case self::NO_MATCH:
|
||||
$fileName = 'Import_Mismatch.csv';
|
||||
break;
|
||||
|
||||
case self::UNPARSED_ADDRESS_WARNING:
|
||||
$fileName = 'Import_Unparsed_Address.csv';
|
||||
break;
|
||||
}
|
||||
|
||||
return $fileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if contact is a duplicate .
|
||||
*
|
||||
* @param array $formatValues
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function checkContactDuplicate(&$formatValues) {
|
||||
//retrieve contact id using contact dedupe rule
|
||||
$formatValues['contact_type'] = $this->_contactType;
|
||||
$formatValues['version'] = 3;
|
||||
require_once 'CRM/Utils/DeprecatedUtils.php';
|
||||
$error = _civicrm_api3_deprecated_check_contact_dedupe($formatValues);
|
||||
return $error;
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue