Skip to content

Commit

Permalink
Participant import fix - broken uniqueName fields, mapping saving, ev…
Browse files Browse the repository at this point in the history
…ent_id

This switches to using 'normal' field names
for all participant fields.
  • Loading branch information
eileenmcnaughton committed Jun 8, 2022
1 parent 7c4c1f6 commit 038104a
Show file tree
Hide file tree
Showing 10 changed files with 124 additions and 277 deletions.
4 changes: 4 additions & 0 deletions CRM/Event/BAO/Participant.php
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,10 @@ public static function pendingToConfirmSpaces($eventId) {
* @param bool $checkPermission
* Is this a permissioned retrieval?
*
* @deprecated only called from event search, but without most of the details
* returned. Event search should call stop using this & get the metadata
* a better way.
*
* @return array
* array of importable Fields
*/
Expand Down
17 changes: 0 additions & 17 deletions CRM/Event/Import/Form/DataSource.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ public function getUserJobType(): string {
public function buildQuickForm() {
parent::buildQuickForm();

$duplicateOptions = [];
$this->addRadio('onDuplicate', ts('On Duplicate Entries'), [
CRM_Import_Parser::DUPLICATE_SKIP => ts('Skip'),
CRM_Import_Parser::DUPLICATE_UPDATE => ts('Update'),
Expand All @@ -52,22 +51,6 @@ public function buildQuickForm() {
$this->addContactTypeSelector();
}

/**
* Process the uploaded file.
*
* @return void
*/
public function postProcess() {
$this->storeFormValues([
'onDuplicate',
'contactType',
'dateFormats',
'savedMapping',
]);

$this->submitFileForMapping('CRM_Event_Import_Parser_Participant');
}

/**
* @return CRM_Event_Import_Parser_Participant
*/
Expand Down
20 changes: 11 additions & 9 deletions CRM/Event/Import/Form/MapField.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,21 +85,21 @@ public static function formRule($fields, $files, $self) {
}
// FIXME: should use the schema titles, not redeclare them
$requiredFields = array(
'participant_contact_id' => ts('Contact ID'),
'contact_id' => ts('Contact ID'),
'event_id' => ts('Event ID'),
);

$contactFieldsBelowWeightMessage = self::validateRequiredContactMatchFields($self->getContactType(), $importKeys);

foreach ($requiredFields as $field => $title) {
if (!in_array($field, $importKeys)) {
if ($field == 'participant_contact_id') {
if ($field === 'contact_id') {
if (!$contactFieldsBelowWeightMessage || in_array('external_identifier', $importKeys) ||
in_array('participant_id', $importKeys)
) {
continue;
}
if ($self->_onDuplicate == CRM_Import_Parser::DUPLICATE_UPDATE) {
if ($self->isUpdateExisting()) {
$errors['_qf_default'] .= ts('Missing required field: Provide Participant ID') . '<br />';
}
else {
Expand Down Expand Up @@ -166,16 +166,15 @@ protected function getParser(): CRM_Event_Import_Parser_Participant {
* Get the fields to highlight.
*
* @return array
* @throws \CRM_Core_Exception
*/
protected function getHighlightedFields(): array {
$highlightedFields = [];
if ($this->getSubmittedValue('onDuplicate') == CRM_Import_Parser::DUPLICATE_UPDATE) {
if ($this->isUpdateExisting()) {
$highlightedFieldsArray = [
'participant_id',
'id',
'event_id',
'event_title',
'participant_status_id',
'status_id',
];
foreach ($highlightedFieldsArray as $name) {
$highlightedFields[] = $name;
Expand All @@ -184,14 +183,17 @@ protected function getHighlightedFields(): array {
elseif ($this->getSubmittedValue('onDuplicate') == CRM_Import_Parser::DUPLICATE_SKIP ||
$this->getSubmittedValue('onDuplicate') == CRM_Import_Parser::DUPLICATE_NOCHECK
) {
// this should be retrieved from the parser.
$highlightedFieldsArray = [
'participant_contact_id',
'contact_id',
'event_id',
'email',
'first_name',
'last_name',
'organization_name',
'household_name',
'external_identifier',
'participant_status_id',
'status_id',
];
foreach ($highlightedFieldsArray as $name) {
$highlightedFields[] = $name;
Expand Down
40 changes: 0 additions & 40 deletions CRM/Event/Import/Form/Preview.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,46 +21,6 @@
*/
class CRM_Event_Import_Form_Preview extends CRM_Import_Form_Preview {

/**
* Process the mapped fields and map it into the uploaded file
* preview the file and extract some summary statistics
*
* @return void
*/
public function postProcess() {
$fileName = $this->controller->exportValue('DataSource', 'uploadFile');
$separator = $this->controller->exportValue('DataSource', 'fieldSeparator');
$invalidRowCount = $this->get('invalidRowCount');
$onDuplicate = $this->get('onDuplicate');

$mapper = $this->controller->exportValue('MapField', 'mapper');
$mapperKeys = [];

foreach ($mapper as $key => $value) {
$mapperKeys[$key] = $mapper[$key][0];
}

$parser = new CRM_Event_Import_Parser_Participant($mapperKeys);
$parser->setUserJobID($this->getUserJobID());
$mapFields = $this->get('fields');

foreach ($mapper as $key => $value) {
$header = [];
if (isset($mapFields[$mapper[$key][0]])) {
$header[] = $mapFields[$mapper[$key][0]];
}
$mapperFields[] = implode(' - ', $header);
}
$parser->run($fileName, $separator,
$mapperFields,
$this->getSubmittedValue('skipColumnHeader'),
CRM_Import_Parser::MODE_IMPORT
);

// add all the necessary variables to the form
$parser->set($this, CRM_Import_Parser::MODE_IMPORT);
}

/**
* @return CRM_Event_Import_Parser_Participant
*/
Expand Down
207 changes: 27 additions & 180 deletions CRM/Event/Import/Parser/Participant.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,21 +85,6 @@ public function init() {
}
}

/**
* Get the metadata field for which importable fields does not key the actual field name.
*
* @return string[]
*/
protected function getOddlyMappedMetadataFields(): array {
$uniqueNames = ['participant_id', 'participant_campaign_id', 'participant_contact_id', 'participant_status_id', 'participant_role_id', 'participant_register_date', 'participant_source', 'participant_is_pay_later'];
$fields = [];
foreach ($uniqueNames as $name) {
$fields[$this->importableFieldsMetadata[$name]['name']] = $name;
}
// Include the parent fields as they could be present if required for matching ...in theory.
return array_merge($fields, parent::getOddlyMappedMetadataFields());
}

/**
* Handle the values in preview mode.
*
Expand Down Expand Up @@ -534,78 +519,6 @@ protected function deprecated_participant_check_params($params, $checkDuplicate
return TRUE;
}

/**
* @param string $fileName
* @param string $separator
* @param $mapper
* @param bool $skipColumnHeader
* @param int $mode
*
* @return mixed
* @throws Exception
*/
public function run(
$fileName,
$separator,
$mapper,
$skipColumnHeader = FALSE,
$mode = self::MODE_PREVIEW
) {
if (!is_array($fileName)) {
throw new CRM_Core_Exception('Unable to determine import file');
}
$fileName = $fileName['name'];
$this->getContactType();
$this->init();

$this->_haveColumnHeader = $skipColumnHeader;

$this->_separator = $separator;

$fd = fopen($fileName, "r");
if (!$fd) {
return FALSE;
}

$this->_lineCount = 0;
$this->_invalidRowCount = $this->_validCount = 0;
$this->_totalCount = 0;

$this->_errors = [];
$this->_warnings = [];

$this->_fileSize = number_format(filesize($fileName) / 1024.0, 2);

if ($mode == self::MODE_MAPFIELD) {
$this->_rows = [];
}
else {
$this->_activeFieldCount = count($this->_activeFields);
}

$dataSource = $this->getDataSourceObject();
$dataSource->setStatuses(['new']);
while ($row = $dataSource->getRow()) {
$this->_lineCount++;
$values = array_values($row);

$this->_totalCount++;

if ($mode == self::MODE_MAPFIELD) {
$returnCode = CRM_Import_Parser::VALID;
}
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($values);
}
}
}

/**
* Given a list of the importable field keys that the user has selected
* set the active fields array to this list
Expand Down Expand Up @@ -652,106 +565,40 @@ public function addField($name, $title, $type = CRM_Utils_Type::T_INT, $headerPa
}
}

/**
* 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('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);

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 (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);
}

/**
* Set up field metadata.
*
* @return void
*/
protected function setFieldMetadata(): void {
if (empty($this->importableFieldsMetadata)) {
$fields = CRM_Event_BAO_Participant::importableFields($this->getContactType(), FALSE);
// We can't import event type, the other two duplicate id fields that work fine.
unset($fields['participant_role'], $fields['participant_status'], $fields['event_type']);
$fields = array_merge(
[
'' => ['title' => ts('- do not import -')],
'participant_note' => [
'title' => ts('Participant Note'),
'name' => 'participant_note',
'headerPattern' => '/(participant.)?note$/i',
'data_type' => CRM_Utils_Type::T_TEXT,
'options' => FALSE,
],
],
CRM_Event_DAO_Participant::import(),
CRM_Core_BAO_CustomField::getFieldsForImport('Participant'),
$this->getContactMatchingFields()
);

$fields['participant_contact_id']['title'] .= ' (match to contact)';
$fields['participant_contact_id']['html']['select'] = $fields['participant_contact_id']['title'];
foreach ($fields as $index => $field) {
if (isset($field['name']) && $field['name'] !== $index) {
// undo unique names - participant is the primary
// entity and no others have conflicting unique names
// if we ever added them the should have unique names - v4api style
$fields[$field['name']] = $field;
unset($fields[$index]);
}
}
$this->importableFieldsMetadata = $fields;
}
}
Expand Down
Loading

0 comments on commit 038104a

Please sign in to comment.