X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=CRM%2FEvent%2FImport%2FParser%2FParticipant.php;h=7c555dececdeec9d21aaeea5991ab231092f48a1;hb=d60cd664d3c04e2dffa6df5e2cd16ce1e5564d18;hp=6c9cf49cb9ffc126fb925aaa68994c19c825d3fd;hpb=583e0c4b9ff82c7d058ffa23aaed4d2d0d73f272;p=civicrm-core.git diff --git a/CRM/Event/Import/Parser/Participant.php b/CRM/Event/Import/Parser/Participant.php index 6c9cf49cb9..7c555decec 100644 --- a/CRM/Event/Import/Parser/Participant.php +++ b/CRM/Event/Import/Parser/Participant.php @@ -20,7 +20,7 @@ require_once 'CRM/Utils/DeprecatedUtils.php'; /** * class to parse membership csv files */ -class CRM_Event_Import_Parser_Participant extends CRM_Event_Import_Parser { +class CRM_Event_Import_Parser_Participant extends CRM_Import_Parser { protected $_mapperKeys; private $_contactIdIndex; @@ -36,6 +36,37 @@ class CRM_Event_Import_Parser_Participant extends CRM_Event_Import_Parser { */ protected $_newParticipants; + + protected $_fileName; + + /** + * Imported file size. + * + * @var int + */ + protected $_fileSize; + + /** + * Separator being used. + * + * @var string + */ + protected $_separator; + + /** + * Total number of lines in file. + * + * @var int + */ + protected $_lineCount; + + /** + * Whether the file has a column header or not + * + * @var bool + */ + protected $_haveColumnHeader; + /** * Class constructor. * @@ -294,11 +325,9 @@ class CRM_Event_Import_Parser_Participant extends CRM_Event_Import_Parser { } else { $eventTitle = $params['event_title']; - $qParams = []; - $dao = new CRM_Core_DAO(); - $params['participant_role_id'] = $dao->singleValueQuery("SELECT default_role_id FROM civicrm_event WHERE title = '$eventTitle' ", - $qParams - ); + $params['participant_role_id'] = CRM_Core_DAO::singleValueQuery('SELECT default_role_id FROM civicrm_event WHERE title = %1', [ + 1 => [$eventTitle, 'String'], + ]); } } @@ -552,11 +581,9 @@ class CRM_Event_Import_Parser_Participant extends CRM_Event_Import_Parser { if (!CRM_Utils_Rule::integer($value)) { return civicrm_api3_create_error("Event ID is not valid: $value"); } - $dao = new CRM_Core_DAO(); - $qParams = []; - $svq = $dao->singleValueQuery("SELECT id FROM civicrm_event WHERE id = $value", - $qParams - ); + $svq = CRM_Core_DAO::singleValueQuery('SELECT id FROM civicrm_event WHERE id = %1', [ + 1 => [$value, 'Integer'], + ]); if (!$svq) { return civicrm_api3_create_error("Invalid Event ID: There is no event record with event_id = $value."); } @@ -703,4 +730,360 @@ class CRM_Event_Import_Parser_Participant extends CRM_Event_Import_Parser { return TRUE; } + /** + * @param string $fileName + * @param string $separator + * @param $mapper + * @param bool $skipColumnHeader + * @param int $mode + * @param int $contactType + * @param int $onDuplicate + * + * @return mixed + * @throws Exception + */ + public function run( + $fileName, + $separator, + $mapper, + $skipColumnHeader = FALSE, + $mode = self::MODE_PREVIEW, + $contactType = self::CONTACT_INDIVIDUAL, + $onDuplicate = self::DUPLICATE_SKIP + ) { + if (!is_array($fileName)) { + throw new CRM_Core_Exception('Unable to determine import file'); + } + $fileName = $fileName['name']; + + switch ($contactType) { + case self::CONTACT_INDIVIDUAL: + $this->_contactType = 'Individual'; + break; + + case self::CONTACT_HOUSEHOLD: + $this->_contactType = 'Household'; + break; + + case self::CONTACT_ORGANIZATION: + $this->_contactType = 'Organization'; + } + + $this->init(); + + $this->_haveColumnHeader = $skipColumnHeader; + + $this->_separator = $separator; + + $fd = fopen($fileName, "r"); + if (!$fd) { + return FALSE; + } + + $this->_lineCount = $this->_warningCount = 0; + $this->_invalidRowCount = $this->_validCount = 0; + $this->_totalCount = $this->_conflictCount = 0; + + $this->_errors = []; + $this->_warnings = []; + $this->_conflicts = []; + + $this->_fileSize = number_format(filesize($fileName) / 1024.0, 2); + + if ($mode == self::MODE_MAPFIELD) { + $this->_rows = []; + } + else { + $this->_activeFieldCount = count($this->_activeFields); + } + + while (!feof($fd)) { + $this->_lineCount++; + + $values = fgetcsv($fd, 8192, $separator); + if (!$values) { + continue; + } + + self::encloseScrub($values); + + // skip column header if we're not in mapfield mode + if ($mode != self::MODE_MAPFIELD && $skipColumnHeader) { + $skipColumnHeader = FALSE; + continue; + } + + /* trim whitespace around the values */ + + $empty = TRUE; + foreach ($values as $k => $v) { + $values[$k] = trim($v, " \t\r\n"); + } + + if (CRM_Utils_System::isNull($values)) { + continue; + } + + $this->_totalCount++; + + if ($mode == self::MODE_MAPFIELD) { + $returnCode = $this->mapField($values); + } + elseif ($mode == self::MODE_PREVIEW) { + $returnCode = $this->preview($values); + } + elseif ($mode == self::MODE_SUMMARY) { + $returnCode = $this->summary($values); + } + elseif ($mode == self::MODE_IMPORT) { + $returnCode = $this->import($onDuplicate, $values); + } + else { + $returnCode = self::ERROR; + } + + // note that a line could be valid but still produce a warning + if ($returnCode & self::VALID) { + $this->_validCount++; + if ($mode == self::MODE_MAPFIELD) { + $this->_rows[] = $values; + $this->_activeFieldCount = max($this->_activeFieldCount, count($values)); + } + } + + if ($returnCode & self::WARNING) { + $this->_warningCount++; + if ($this->_warningCount < $this->_maxWarningCount) { + $this->_warningCount[] = $line; + } + } + + if ($returnCode & self::ERROR) { + $this->_invalidRowCount++; + $recordNumber = $this->_lineCount; + if ($this->_haveColumnHeader) { + $recordNumber--; + } + array_unshift($values, $recordNumber); + $this->_errors[] = $values; + } + + if ($returnCode & self::CONFLICT) { + $this->_conflictCount++; + $recordNumber = $this->_lineCount; + if ($this->_haveColumnHeader) { + $recordNumber--; + } + array_unshift($values, $recordNumber); + $this->_conflicts[] = $values; + } + + if ($returnCode & self::DUPLICATE) { + $this->_duplicateCount++; + $recordNumber = $this->_lineCount; + if ($this->_haveColumnHeader) { + $recordNumber--; + } + array_unshift($values, $recordNumber); + $this->_duplicates[] = $values; + if ($onDuplicate != self::DUPLICATE_SKIP) { + $this->_validCount++; + } + } + + // we give the derived class a way of aborting the process + // note that the return code could be multiple code or'ed together + if ($returnCode & self::STOP) { + break; + } + + // if we are done processing the maxNumber of lines, break + if ($this->_maxLinesToProcess > 0 && $this->_validCount >= $this->_maxLinesToProcess) { + break; + } + } + + fclose($fd); + + if ($mode == self::MODE_PREVIEW || $mode == self::MODE_IMPORT) { + $customHeaders = $mapper; + + $customfields = CRM_Core_BAO_CustomField::getFields('Participant'); + foreach ($customHeaders as $key => $value) { + if ($id = CRM_Core_BAO_CustomField::getKeyID($value)) { + $customHeaders[$key] = $customfields[$id][0]; + } + } + + if ($this->_invalidRowCount) { + // removed view url for invlaid contacts + $headers = array_merge([ + ts('Line Number'), + ts('Reason'), + ], $customHeaders); + $this->_errorFileName = self::errorFileName(self::ERROR); + self::exportCSV($this->_errorFileName, $headers, $this->_errors); + } + if ($this->_conflictCount) { + $headers = array_merge([ + ts('Line Number'), + ts('Reason'), + ], $customHeaders); + $this->_conflictFileName = self::errorFileName(self::CONFLICT); + self::exportCSV($this->_conflictFileName, $headers, $this->_conflicts); + } + if ($this->_duplicateCount) { + $headers = array_merge([ + ts('Line Number'), + ts('View Participant URL'), + ], $customHeaders); + + $this->_duplicateFileName = self::errorFileName(self::DUPLICATE); + self::exportCSV($this->_duplicateFileName, $headers, $this->_duplicates); + } + } + return $this->fini(); + } + + /** + * Given a list of the importable field keys that the user has selected + * set the active fields array to this list + * + * @param array $fieldKeys mapped array of values + * + * @return void + */ + public function setActiveFields($fieldKeys) { + $this->_activeFieldCount = count($fieldKeys); + foreach ($fieldKeys as $key) { + if (empty($this->_fields[$key])) { + $this->_activeFields[] = new CRM_Event_Import_Field('', ts('- do not import -')); + } + else { + $this->_activeFields[] = clone($this->_fields[$key]); + } + } + } + + /** + * @param string $name + * @param $title + * @param int $type + * @param string $headerPattern + * @param string $dataPattern + */ + public function addField($name, $title, $type = CRM_Utils_Type::T_INT, $headerPattern = '//', $dataPattern = '//') { + if (empty($name)) { + $this->_fields['doNotImport'] = new CRM_Event_Import_Field($name, $title, $type, $headerPattern, $dataPattern); + } + else { + + //$tempField = CRM_Contact_BAO_Contact::importableFields('Individual', null ); + $tempField = CRM_Contact_BAO_Contact::importableFields('All', NULL); + if (!array_key_exists($name, $tempField)) { + $this->_fields[$name] = new CRM_Event_Import_Field($name, $title, $type, $headerPattern, $dataPattern); + } + else { + $this->_fields[$name] = new CRM_Contact_Import_Field($name, $title, $type, $headerPattern, $dataPattern, + CRM_Utils_Array::value('hasLocationType', $tempField[$name]) + ); + } + } + } + + /** + * Store parser values. + * + * @param CRM_Core_Session $store + * + * @param int $mode + * + * @return void + */ + public function set($store, $mode = self::MODE_SUMMARY) { + $store->set('fileSize', $this->_fileSize); + $store->set('lineCount', $this->_lineCount); + $store->set('separator', $this->_separator); + $store->set('fields', $this->getSelectValues()); + $store->set('fieldTypes', $this->getSelectTypes()); + + $store->set('headerPatterns', $this->getHeaderPatterns()); + $store->set('dataPatterns', $this->getDataPatterns()); + $store->set('columnCount', $this->_activeFieldCount); + + $store->set('totalRowCount', $this->_totalCount); + $store->set('validRowCount', $this->_validCount); + $store->set('invalidRowCount', $this->_invalidRowCount); + $store->set('conflictRowCount', $this->_conflictCount); + + switch ($this->_contactType) { + case 'Individual': + $store->set('contactType', CRM_Import_Parser::CONTACT_INDIVIDUAL); + break; + + case 'Household': + $store->set('contactType', CRM_Import_Parser::CONTACT_HOUSEHOLD); + break; + + case 'Organization': + $store->set('contactType', CRM_Import_Parser::CONTACT_ORGANIZATION); + } + + if ($this->_invalidRowCount) { + $store->set('errorsFileName', $this->_errorFileName); + } + if ($this->_conflictCount) { + $store->set('conflictsFileName', $this->_conflictFileName); + } + if (isset($this->_rows) && !empty($this->_rows)) { + $store->set('dataValues', $this->_rows); + } + + if ($mode == self::MODE_IMPORT) { + $store->set('duplicateRowCount', $this->_duplicateCount); + if ($this->_duplicateCount) { + $store->set('duplicatesFileName', $this->_duplicateFileName); + } + } + } + + /** + * Export data to a CSV file. + * + * @param string $fileName + * @param array $header + * @param array $data + * + * @return void + */ + public static function exportCSV($fileName, $header, $data) { + $output = []; + $fd = fopen($fileName, 'w'); + + foreach ($header as $key => $value) { + $header[$key] = "\"$value\""; + } + $config = CRM_Core_Config::singleton(); + $output[] = implode($config->fieldSeparator, $header); + + foreach ($data as $datum) { + foreach ($datum as $key => $value) { + if (is_array($value)) { + foreach ($value[0] as $k1 => $v1) { + if ($k1 == 'location_type_id') { + continue; + } + $datum[$k1] = $v1; + } + } + else { + $datum[$key] = "\"$value\""; + } + } + $output[] = implode($config->fieldSeparator, $datum); + } + fwrite($fd, implode("\n", $output)); + fclose($fd); + } + }