* @throws \Civi\API\Exception\UnauthorizedException
*/
public function preProcess() {
- $this->_mapperFields = $this->get('fields');
+ $this->_mapperFields = $this->getAvailableFields();
$this->_importTableName = $this->get('importTableName');
$this->_contactSubType = $this->get('contactSubType');
//format custom field names, CRM-2676
$contactType = $this->getContactType();
$this->_contactType = $contactType;
- if ($this->isSkipDuplicates()) {
- unset($this->_mapperFields['id']);
- }
if ($this->isIgnoreDuplicates()) {
//Mark Dedupe Rule Fields as required, since it's used in matching contact
$parser->run($this->_importTableName,
$mapper,
CRM_Import_Parser::MODE_PREVIEW,
- $this->get('contactType'),
+ NULL,
'_id',
'_status',
(int) $this->getSubmittedValue('onDuplicate'),
NULL, NULL, FALSE,
CRM_Contact_Import_Parser_Contact::DEFAULT_TIMEOUT,
- $this->get('contactSubType'),
+ $this->getSubmittedValue('contactSubType'),
$this->getSubmittedValue('dedupe_rule_id')
);
return $parser;
/**
* Process the mapped fields and map it into the uploaded file.
+ *
+ * @throws \API_Exception
*/
public function postProcess() {
'tag' => $this->controller->exportValue($this->_name, 'tag'),
'allTags' => $this->get('tag'),
'mapper' => $this->controller->exportValue('MapField', 'mapper'),
- 'mapFields' => $this->get('fields'),
+ 'mapFields' => $this->getAvailableFields(),
'contactType' => $this->get('contactType'),
'contactSubType' => $this->get('contactSubType'),
'primaryKeyName' => $this->get('primaryKeyName'),
$this->_mapperRelatedContactWebsiteType = $mapperRelatedContactWebsiteType;
// get IM service provider type id for related contact
$this->_mapperRelatedContactImProvider = &$mapperRelatedContactImProvider;
- $this->setFieldMetadata();
- foreach ($this->getImportableFieldsMetadata() as $name => $field) {
- $this->addField($name, $field['title'], CRM_Utils_Array::value('type', $field), CRM_Utils_Array::value('headerPattern', $field), CRM_Utils_Array::value('dataPattern', $field), CRM_Utils_Array::value('hasLocationType', $field));
- }
}
/**
* The initializer code, called before processing.
*/
public function init() {
+ $this->setFieldMetadata();
+ foreach ($this->getImportableFieldsMetadata() as $name => $field) {
+ $this->addField($name, $field['title'], CRM_Utils_Array::value('type', $field), CRM_Utils_Array::value('headerPattern', $field), CRM_Utils_Array::value('dataPattern', $field), CRM_Utils_Array::value('hasLocationType', $field));
+ }
$this->_newContacts = [];
$this->setActiveFields($this->_mapperKeys);
}
/**
- * Get configured contact type.
+ * Gets the fields available for importing in a key-name, title format.
+ *
+ * @return array
+ * eg. ['first_name' => 'First Name'.....]
+ *
+ * @throws \API_Exception
+ *
+ * @todo - we are constructing the metadata before we
+ * have set the contact type so we re-do it here.
+ *
+ * Once we have cleaned up the way the mapper is handled
+ * we can ditch all the existing _construct parameters in favour
+ * of just the userJobID - there are current open PRs towards this end.
*/
- protected function getContactType() {
- return $this->_contactType ?? 'Individual';
+ public function getAvailableFields(): array {
+ $this->setFieldMetadata();
+ $return = [];
+ foreach ($this->getImportableFieldsMetadata() as $name => $field) {
+ if ($name === 'id' && $this->isSkipDuplicates()) {
+ // Duplicates are being skipped so id matching is not availble.
+ continue;
+ }
+ $return[$name] = $field['title'];
+ }
+ return $return;
+ }
+
+ /**
+ * Did the user specify duplicates should be skipped and not imported.
+ *
+ * @return bool
+ *
+ * @throws \API_Exception
+ */
+ private function isSkipDuplicates(): bool {
+ return ((int) $this->getSubmittedValue('onDuplicate')) === CRM_Import_Parser::DUPLICATE_SKIP;
}
/**
// TODO: Make the timeout actually work
$this->_onDuplicate = $onDuplicate;
$this->_dedupeRuleGroupID = $dedupeRuleGroupID;
-
- switch ($contactType) {
- case CRM_Import_Parser::CONTACT_INDIVIDUAL:
- $this->_contactType = 'Individual';
- break;
-
- case CRM_Import_Parser::CONTACT_HOUSEHOLD:
- $this->_contactType = 'Household';
- break;
-
- case CRM_Import_Parser::CONTACT_ORGANIZATION:
- $this->_contactType = 'Organization';
- }
+ // Since $this->_contactType is still being called directly do a get call
+ // here to make sure it is instantiated.
+ $this->getContactType();
$this->_contactSubType = $contactSubType;
$returnCode = $this->summary($values);
}
elseif ($mode == self::MODE_IMPORT) {
- //print "Running parser in import mode<br/>\n";
- $returnCode = $this->import($onDuplicate, $values, $doGeocodeAddress);
+ try {
+ $returnCode = $this->import($onDuplicate, $values, $doGeocodeAddress);
+ }
+ catch (CiviCRM_API3_Exception $e) {
+ // When we catch errors here we are not adding to the errors array - mostly
+ // because that will become obsolete once https://github.com/civicrm/civicrm-core/pull/23292
+ // is merged and this will replace it as the main way to handle errors (ie. update the table
+ // and move on).
+ $this->setImportStatus((int) $values[count($values) - 1], 'ERROR', $e->getMessage());
+ }
if ($statusID && (($this->_rowCount % 50) == 0)) {
$prevTimestamp = $this->progressImport($statusID, FALSE, $startTimestamp, $prevTimestamp, $totalRowCount);
}
*/
public function set($store, $mode = self::MODE_SUMMARY) {
$store->set('rowCount', $this->_rowCount);
- $store->set('fields', $this->getSelectValues());
$store->set('fieldTypes', $this->getSelectTypes());
$store->set('columnCount', $this->_activeFieldCount);
return $this->getDataSourceObject()->getRows($limit);
}
+ /**
+ * Get the fields available for import selection.
+ *
+ * @return array
+ * e.g ['first_name' => 'First Name', 'last_name' => 'Last Name'....
+ *
+ * @throws \API_Exception
+ */
+ protected function getAvailableFields(): array {
+ $parser = new CRM_Contact_Import_Parser_Contact();
+ $parser->setUserJobID($this->getUserJobID());
+ return $parser->getAvailableFields();
+ }
+
}
*/
protected $metadata = [];
+ /**
+ * Id of the created user job.
+ *
+ * @var int
+ */
+ protected $userJobID;
+
+ /**
+ * @return int
+ */
+ public function getUserJobID(): int {
+ return $this->userJobID;
+ }
+
+ /**
+ * @param int $userJobID
+ */
+ public function setUserJobID(int $userJobID): void {
+ $this->userJobID = $userJobID;
+ }
+
/**
* Metadata keyed by field title.
*
$this->getFieldWebsiteTypes()
// $mapperRelatedContactWebsiteType = []
);
+ $importer->setUserJobID($this->getUserJobID());
$importer->init();
- $importer->_contactType = $this->getContactType();
return $importer;
}
->first();
}
+ /**
+ * Get the submitted value, as stored on the user job.
+ *
+ * @param string $fieldName
+ *
+ * @return mixed
+ *
+ * @throws \API_Exception
+ */
+ protected function getSubmittedValue(string $fieldName) {
+ return $this->getUserJob()['metadata']['submitted_values'][$fieldName];
+ }
+
+ /**
+ * Get configured contact type.
+ *
+ * @throws \API_Exception
+ */
+ protected function getContactType() {
+ if (!$this->_contactType) {
+ $contactTypeMapping = [
+ CRM_Import_Parser::CONTACT_INDIVIDUAL => 'Individual',
+ CRM_Import_Parser::CONTACT_HOUSEHOLD => 'Household',
+ CRM_Import_Parser::CONTACT_ORGANIZATION => 'Organization',
+ ];
+ $this->_contactType = $contactTypeMapping[$this->getSubmittedValue('contactType')];
+ }
+ return $this->_contactType;
+ }
+
/**
* Total number of non empty lines
* @var int
/**
* Contact type
*
- * @var int
+ * @var string
*/
public $_contactType;
/**
$sqlFormValues = [
'dataSource' => 'CRM_Import_DataSource_SQL',
'sqlQuery' => 'SELECT "bob" as first_name FROM civicrm_option_value LIMIT 5',
+ 'contactType' => CRM_Import_Parser::CONTACT_INDIVIDUAL,
];
$form = $this->submitDataSourceForm($sqlFormValues);
$userJobID = $form->getUserJobID();
$csvFormValues = [
'dataSource' => 'CRM_Import_DataSource_CSV',
'skipColumnHeader' => 1,
+ 'contactType' => CRM_Import_Parser::CONTACT_INDIVIDUAL,
'uploadFile' => [
'name' => __DIR__ . '/data/yogi.csv',
'type' => 'text/csv',
'contactType' => CRM_Import_Parser::CONTACT_INDIVIDUAL,
'dataSource' => 'CRM_Import_DataSource_SQL',
'sqlQuery' => 'SELECT * FROM civicrm_tmp_d_import_job_xxx',
+ 'onDuplicate' => CRM_Import_Parser::DUPLICATE_UPDATE,
], $submittedValues);
$userJobID = UserJob::create()->setValues([
'metadata' => [
* File for the CRM_Contact_Imports_Parser_ContactTest class.
*/
+use Civi\Api4\UserJob;
+
/**
* Test contact import parser.
*
*
* There is an expectation that you can import by label here.
*
+ * @throws \API_Exception
* @throws \CRM_Core_Exception
* @throws \CiviCRM_API3_Exception
*/
['name' => 'prefix_id', 'column_number' => 3],
['name' => 'suffix_id', 'column_number' => 4],
];
+
$processor = new CRM_Import_ImportProcessor();
$processor->setMappingFields($mapping);
$processor->setContactType('Individual');
+ $processor->setUserJobID($this->getUserJobID());
$importer = $processor->getImporterObject();
$contactValues = [
/**
* Test importing 2 phones of different types.
*
+ * @throws \API_Exception
* @throws \CRM_Core_Exception
* @throws \CiviCRM_API3_Exception
*/
- public function testImportTwoPhonesDifferentTypes() {
+ public function testImportTwoPhonesDifferentTypes(): void {
$processor = new CRM_Import_ImportProcessor();
- $processor->setContactType('Individual');
+ $processor->setUserJobID($this->getUserJobID());
$processor->setMappingFields(
[
['name' => 'first_name'],
* Ensure we can import multiple preferred_communication_methods, single
* gender, and single preferred language using both labels and values.
*
- * @throws \CRM_Core_Exception @throws \CiviCRM_API3_Exception
+ * @throws \API_Exception
+ * @throws \CRM_Core_Exception
+ * @throws \CiviCRM_API3_Exception
*/
- public function testImportFieldsWithVariousOptions() {
+ public function testImportFieldsWithVariousOptions(): void {
$processor = new CRM_Import_ImportProcessor();
- $processor->setContactType('Individual');
+ $processor->setUserJobID($this->getUserJobID());
$processor->setMappingFields(
[
['name' => 'first_name'],
]
);
$importer = $processor->getImporterObject();
- $fields = ['Ima', 'Texter', "SMS,Phone", "Female", "Danish"];
+ $fields = ['Ima', 'Texter', 'SMS,Phone', 'Female', 'Danish'];
$importer->import(CRM_Import_Parser::DUPLICATE_NOCHECK, $fields);
$contact = $this->callAPISuccessGetSingle('Contact', ['last_name' => 'Texter']);
return [$originalValues, $result];
}
+ /**
+ * @return mixed
+ * @throws \API_Exception
+ * @throws \Civi\API\Exception\UnauthorizedException
+ */
+ protected function getUserJobID() {
+ $userJobID = UserJob::create()->setValues([
+ 'metadata' => [
+ 'submitted_values' => ['contactType' => CRM_Import_Parser::CONTACT_INDIVIDUAL],
+ ],
+ 'status_id:name' => 'draft',
+ 'type_id:name' => 'contact_import',
+ ])->execute()->first()['id'];
+ return $userJobID;
+ }
+
}
'name' => __DIR__ . '/' . $csvFileName,
],
'skipColumnHeader' => TRUE,
+ 'contactType' => CRM_Import_Parser::CONTACT_INDIVIDUAL,
]);
$form->buildForm();
$form->postProcess();