From 638a0140965d3044bb5870e5ba50de15f9eb7a20 Mon Sep 17 00:00:00 2001 From: Eileen McNaughton <emcnaughton@wikimedia.org> Date: Fri, 3 Jun 2022 15:23:29 +1200 Subject: [PATCH 1/4] Add import labels fixes that I figured out doing memberhsip Importantly do_not_import should be added --- CRM/Contribute/Import/Form/MapField.php | 2 +- CRM/Upgrade/Incremental/php/FiveFiftyOne.php | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CRM/Contribute/Import/Form/MapField.php b/CRM/Contribute/Import/Form/MapField.php index 78e6a869d8b1..8c24947a2bd4 100644 --- a/CRM/Contribute/Import/Form/MapField.php +++ b/CRM/Contribute/Import/Form/MapField.php @@ -433,7 +433,7 @@ public function postProcess() { if (isset($mapperKeys[$i][0]) && $mapperKeys[$i][0] == 'soft_credit') { $mapperSoftCredit[$i] = $mapperKeys[$i][1]; if (strpos($mapperSoftCredit[$i], '_') !== FALSE) { - list($first, $second) = explode('_', $mapperSoftCredit[$i]); + [$first, $second] = explode('_', $mapperSoftCredit[$i]); $softCreditFields[$i] = ucwords($first . " " . $second); } else { diff --git a/CRM/Upgrade/Incremental/php/FiveFiftyOne.php b/CRM/Upgrade/Incremental/php/FiveFiftyOne.php index fe10b78e6330..3de256e0ff4b 100644 --- a/CRM/Upgrade/Incremental/php/FiveFiftyOne.php +++ b/CRM/Upgrade/Incremental/php/FiveFiftyOne.php @@ -71,6 +71,7 @@ public static function fillQueueColumns($ctx): bool { * @throws \API_Exception */ public static function convertMappingFieldLabelsToNames(): bool { + // Contribution fields.... $mappings = MappingField::get(FALSE) ->setSelect(['id', 'name']) ->addWhere('mapping_id.mapping_type_id:name', '=', 'Import Contribution') @@ -79,12 +80,16 @@ public static function convertMappingFieldLabelsToNames(): bool { $fieldMap = []; foreach ($fields as $fieldName => $field) { $fieldMap[$field['title']] = $fieldName; + if (!empty($field['html']['label'])) { + $fieldMap[$field['html']['label']] = $fieldName; + } } $fieldMap[ts('Soft Credit')] = 'soft_credit'; $fieldMap[ts('Pledge Payment')] = 'pledge_payment'; $fieldMap[ts(ts('Pledge ID'))] = 'pledge_id'; $fieldMap[ts(ts('Financial Type'))] = 'financial_type_id'; $fieldMap[ts(ts('Payment Method'))] = 'payment_instrument_id'; + $fieldMap[ts('- do not import -')] = 'do_not_import'; foreach ($mappings as $mapping) { if (!empty($fieldMap[$mapping['name']])) { From 82cf0710d4b7a0807d8b53dfe463ef0c07cdce14 Mon Sep 17 00:00:00 2001 From: Eileen McNaughton <emcnaughton@wikimedia.org> Date: Fri, 3 Jun 2022 15:24:14 +1200 Subject: [PATCH 2/4] Fix fatal when going back from MapField due to no dataSource --- CRM/Import/Form/DataSource.php | 5 ++++- CRM/Import/Forms.php | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CRM/Import/Form/DataSource.php b/CRM/Import/Form/DataSource.php index 19fea5947c19..a5e53ad43fd8 100644 --- a/CRM/Import/Form/DataSource.php +++ b/CRM/Import/Form/DataSource.php @@ -63,7 +63,10 @@ protected function getTranslatedEntities(): string { */ public function buildQuickForm() { $config = CRM_Core_Config::singleton(); - + // When we switch to using the DataSource.tpl used by Contact we can remove this in + // favour of the one used by Contact - I was trying to consolidate + // first & got stuck on https://github.com/civicrm/civicrm-core/pull/23458 + $this->add('hidden', 'hidden_dataSource', 'CRM_Import_DataSource_CSV'); $uploadFileSize = CRM_Utils_Number::formatUnitSize($config->maxFileSize . 'm', TRUE); //Fetch uploadFileSize from php_ini when $config->maxFileSize is set to "no limit". diff --git a/CRM/Import/Forms.php b/CRM/Import/Forms.php index c3f364600213..e87bc5acb747 100644 --- a/CRM/Import/Forms.php +++ b/CRM/Import/Forms.php @@ -137,7 +137,10 @@ public function getSubmittedValue(string $fieldName) { if ($fieldName === 'dataSource') { // Hard-coded handling for DataSource as it affects the contents of // getSubmittableFields and can cause a loop. - return $this->controller->exportValue('DataSource', 'dataSource'); + // Note that the non-contact imports are not currently sharing the DataSource.tpl + // that adds the CSV/SQL options & hence fall back on this hidden field. + // - todo - switch to the same DataSource.tpl for all. + return $this->controller->exportValue('DataSource', 'dataSource') ?? $this->controller->exportValue('DataSource', 'hidden_dataSource'); } $mappedValues = $this->getSubmittableFields(); if (array_key_exists($fieldName, $mappedValues)) { From 8daa4f362f8b1d0a3a79f23827b7740786d1822e Mon Sep 17 00:00:00 2001 From: Eileen McNaughton <emcnaughton@wikimedia.org> Date: Fri, 3 Jun 2022 17:12:05 +1200 Subject: [PATCH 3/4] Cleanup templates & form variables, following contact pattern --- CRM/Contribute/Import/Form/MapField.php | 37 ++---- CRM/Contribute/Import/Form/Preview.php | 32 +---- CRM/Contribute/Import/Parser/Contribution.php | 113 +++++++----------- .../CRM/Contribute/Import/Form/MapTable.tpl | 93 +------------- .../CRM/Contribute/Import/Form/Preview.tpl | 2 +- 5 files changed, 61 insertions(+), 216 deletions(-) diff --git a/CRM/Contribute/Import/Form/MapField.php b/CRM/Contribute/Import/Form/MapField.php index 8c24947a2bd4..b45767d8b141 100644 --- a/CRM/Contribute/Import/Form/MapField.php +++ b/CRM/Contribute/Import/Form/MapField.php @@ -72,27 +72,15 @@ protected static function checkRequiredFields($self, string $contactORContributi * Set variables up before form is built. */ public function preProcess() { + parent::preProcess(); $this->_mapperFields = $this->getAvailableFields(); asort($this->_mapperFields); $this->_columnCount = $this->get('columnCount'); - $this->assign('columnCount', $this->_columnCount); - $this->_dataValues = $this->get('dataValues'); - $this->assign('dataValues', $this->_dataValues); + $skipColumnHeader = $this->getSubmittedValue('skipColumnHeader'); + $this->_onDuplicate = $this->getSubmittedValue('onDuplicate'); + $this->assign('skipColumnHeader', $skipColumnHeader); - $skipColumnHeader = $this->controller->exportValue('DataSource', 'skipColumnHeader'); - $this->_onDuplicate = $this->get('onDuplicate', $onDuplicate ?? ""); - - if ($skipColumnHeader) { - $this->assign('skipColumnHeader', $skipColumnHeader); - $this->assign('rowDisplayCount', 3); - // If we had a column header to skip, stash it for later - - $this->_columnHeaders = $this->_dataValues[0]; - } - else { - $this->assign('rowDisplayCount', 2); - } $highlightedFields = ['financial_type_id', 'total_amount']; //CRM-2219 removing other required fields since for updation only //invoice id or trxn id or contribution id is required. @@ -157,10 +145,11 @@ public function buildQuickForm() { $defaults = []; $mapperKeys = array_keys($this->_mapperFields); - $hasHeaders = !empty($this->_columnHeaders); - $headerPatterns = $this->get('headerPatterns'); - $dataPatterns = $this->get('dataPatterns'); - $mapperKeysValues = $this->controller->exportValue($this->_name, 'mapper'); + $hasHeaders = $this->getSubmittedValue('skipColumnHeader'); + $headerPatterns = $this->getHeaderPatterns(); + $dataPatterns = $this->getDataPatterns(); + $mapperKeysValues = $this->getSubmittedValue('mapper'); + $columnHeaders = $this->getColumnHeaders(); /* Initialize all field usages to false */ foreach ($mapperKeys as $key) { @@ -188,7 +177,7 @@ public function buildQuickForm() { //used to warn for mismatch column count or mismatch mapping $warning = 0; - for ($i = 0; $i < $this->_columnCount; $i++) { + foreach ($columnHeaders as $i => $columnHeader) { $sel = &$this->addElement('hierselect', "mapper[$i]", ts('Mapper for Field %1', [1 => $i]), NULL); $jsSet = FALSE; if ($this->get('savedMapping')) { @@ -228,7 +217,7 @@ public function buildQuickForm() { $js .= "swapOptions($formName, 'mapper[$i]', 0, 3, 'hs_mapper_0_');\n"; if ($hasHeaders) { - $defaults["mapper[$i]"] = [$this->defaultFromHeader($this->_columnHeaders[$i], $headerPatterns)]; + $defaults["mapper[$i]"] = [$this->defaultFromHeader($columnHeader, $headerPatterns)]; } else { $defaults["mapper[$i]"] = [$this->defaultFromData($dataPatterns, $i)]; @@ -240,7 +229,7 @@ public function buildQuickForm() { $js .= "swapOptions($formName, 'mapper[$i]', 0, 3, 'hs_mapper_0_');\n"; if ($hasHeaders) { // do array search first to see if has mapped key - $columnKey = array_search($this->_columnHeaders[$i], $this->_mapperFields); + $columnKey = array_search($columnHeader, $this->_mapperFields); if (isset($this->_fieldUsed[$columnKey])) { $defaults["mapper[$i]"] = $columnKey; $this->_fieldUsed[$key] = TRUE; @@ -248,7 +237,7 @@ public function buildQuickForm() { else { // Infer the default from the column names if we have them $defaults["mapper[$i]"] = [ - $this->defaultFromHeader($this->_columnHeaders[$i], $headerPatterns), + $this->defaultFromHeader($columnHeader, $headerPatterns), 0, ]; } diff --git a/CRM/Contribute/Import/Form/Preview.php b/CRM/Contribute/Import/Form/Preview.php index 46d77feedb0e..bce405c8e8a7 100644 --- a/CRM/Contribute/Import/Form/Preview.php +++ b/CRM/Contribute/Import/Form/Preview.php @@ -25,38 +25,16 @@ class CRM_Contribute_Import_Form_Preview extends CRM_Import_Form_Preview { */ public function preProcess() { parent::preProcess(); - //get the data from the session - $dataValues = $this->get('dataValues'); - $invalidRowCount = $this->get('invalidRowCount'); - - //get the mapping name displayed if the mappingId is set - $mappingId = $this->get('loadMappingId'); - if ($mappingId) { - $mapDAO = new CRM_Core_DAO_Mapping(); - $mapDAO->id = $mappingId; - $mapDAO->find(TRUE); - } - $this->assign('savedMappingName', $mappingId ? $mapDAO->name : NULL); + $invalidRowCount = $this->getRowCount(CRM_Import_Parser::VALID); + $downloadURL = ''; if ($invalidRowCount) { $urlParams = 'type=' . CRM_Import_Parser::ERROR . '&parser=CRM_Contribute_Import_Parser_Contribution'; - $this->set('downloadErrorRecordsUrl', CRM_Utils_System::url('civicrm/export', $urlParams)); + $downloadURL = CRM_Utils_System::url('civicrm/export', $urlParams); } - $properties = [ - 'dataValues', - 'columnCount', - 'totalRowCount', - 'validRowCount', - 'invalidRowCount', - 'downloadErrorRecordsUrl', - ]; $this->setStatusUrl(); - $this->assign('mapper', $this->getMappedFieldLabels()); - - foreach ($properties as $property) { - $this->assign($property, $this->get($property)); - } + $this->assign('downloadErrorRecordsUrl', $downloadURL); } /** @@ -105,7 +83,7 @@ public function postProcess() { $mapperFields, $this->getSubmittedValue('skipColumnHeader'), CRM_Import_Parser::MODE_IMPORT, - $this->get('contactType'), + $this->getSubmittedValue('contactType'), $onDuplicate, $this->get('statusID'), $this->get('totalRowCount') diff --git a/CRM/Contribute/Import/Parser/Contribution.php b/CRM/Contribute/Import/Parser/Contribution.php index c818b09475fd..239180da6546 100644 --- a/CRM/Contribute/Import/Parser/Contribution.php +++ b/CRM/Contribute/Import/Parser/Contribution.php @@ -48,17 +48,6 @@ public function __construct($mapperKeys = []) { */ const SOFT_CREDIT = 512, SOFT_CREDIT_ERROR = 1024, PLEDGE_PAYMENT = 2048, PLEDGE_PAYMENT_ERROR = 4096; - /** - * @var string - */ - protected $_fileName; - - /** - * Imported file size - * @var int - */ - protected $_fileSize; - /** * Separator being used * @var string @@ -137,7 +126,6 @@ public function __construct($mapperKeys = []) { * @param int $contactType * @param int $onDuplicate * @param int $statusID - * @param int $totalRowCount * * @return mixed * @throws Exception @@ -150,13 +138,8 @@ public function run( $mode = self::MODE_PREVIEW, $contactType = self::CONTACT_INDIVIDUAL, $onDuplicate = self::DUPLICATE_SKIP, - $statusID = NULL, - $totalRowCount = NULL + $statusID = NULL ) { - if (!is_array($fileName)) { - throw new CRM_Core_Exception('Unable to determine import file'); - } - $fileName = $fileName['name']; // Since $this->_contactType is still being called directly do a get call // here to make sure it is instantiated. $this->getContactType(); @@ -165,13 +148,6 @@ public function run( $this->_haveColumnHeader = $skipColumnHeader; - $this->_separator = $separator; - - $fd = fopen($fileName, "r"); - if (!$fd) { - return FALSE; - } - $this->_lineCount = $this->_validSoftCreditRowCount = $this->_validPledgePaymentRowCount = 0; $this->_invalidRowCount = $this->_validCount = $this->_invalidSoftCreditRowCount = $this->_invalidPledgePaymentRowCount = 0; $this->_totalCount = 0; @@ -185,8 +161,6 @@ public function run( $startTimestamp = $currTimestamp = $prevTimestamp = time(); } - $this->_fileSize = number_format(filesize($fileName) / 1024.0, 2); - if ($mode == self::MODE_MAPFIELD) { $this->_rows = []; } @@ -194,32 +168,13 @@ public function run( $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"); - } + $dataSource = $this->getDataSourceObject(); + $totalRowCount = $dataSource->getRowCount(['new']); + $dataSource->setStatuses(['new']); - if (CRM_Utils_System::isNull($values)) { - continue; - } + while ($row = $dataSource->getRow()) { + $values = array_values($row); + $this->_lineCount++; $this->_totalCount++; @@ -309,15 +264,8 @@ public function run( $this->_validCount++; } } - - // 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; @@ -470,18 +418,10 @@ public function addField($name, $title, $type = CRM_Utils_Type::T_INT, $headerPa * @param int $mode */ 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); + $store->set('invalidSoftCreditRowCount', $this->_invalidSoftCreditRowCount); $store->set('validSoftCreditRowCount', $this->_validSoftCreditRowCount); $store->set('invalidPledgePaymentRowCount', $this->_invalidPledgePaymentRowCount); @@ -692,6 +632,7 @@ protected function setFieldMetadata() { * CRM_Import_Parser::VALID or CRM_Import_Parser::ERROR */ public function summary(&$values) { + $rowNumber = (int) ($values[array_key_last($values)]); $params = $this->getMappedRow($values); //for date-Formats @@ -707,6 +648,7 @@ public function summary(&$values) { $tempMsg = "Invalid value for field(s) : $errorMessage"; array_unshift($values, $tempMsg); $errorMessage = NULL; + $this->setImportStatus($rowNumber, 'ERROR', $tempMsg); return CRM_Import_Parser::ERROR; } @@ -732,6 +674,7 @@ public function summary(&$values) { * - CRM_Import_Parser::PLEDGE_PAYMENT (successful creation) */ public function import($onDuplicate, &$values) { + $rowNumber = (int) ($values[array_key_last($values)]); // first make sure this is a valid line $response = $this->summary($values); if ($response != CRM_Import_Parser::VALID) { @@ -779,6 +722,7 @@ public function import($onDuplicate, &$values) { catch (CRM_Core_Exception $e) { array_unshift($values, $e->getMessage()); $errorMapping = ['soft_credit' => self::SOFT_CREDIT_ERROR, 'pledge_payment' => self::PLEDGE_PAYMENT_ERROR]; + $this->setImportStatus($rowNumber, $errorMapping[$e->getErrorCode()] ?? CRM_Import_Parser::ERROR, $e->getMessage()); return $errorMapping[$e->getErrorCode()] ?? CRM_Import_Parser::ERROR; } @@ -790,6 +734,7 @@ public function import($onDuplicate, &$values) { if (CRM_Utils_Array::value('error_data', $formatError) == 'pledge_payment') { return self::PLEDGE_PAYMENT_ERROR; } + $this->setImportStatus($rowNumber, 'ERROR', ''); return CRM_Import_Parser::ERROR; } @@ -873,6 +818,7 @@ public function import($onDuplicate, &$values) { } $errorMsg = implode(' AND ', $errorMsg); array_unshift($values, 'Matching Contribution record not found for ' . $errorMsg . '. Row was skipped.'); + $this->setImportStatus($rowNumber, 'ERROR', 'Matching Contribution record not found for ' . $errorMsg . '. Row was skipped.'); return CRM_Import_Parser::ERROR; } } @@ -885,6 +831,7 @@ public function import($onDuplicate, &$values) { $matchedIDs = explode(',', $error['error_message']['params'][0]); if (count($matchedIDs) > 1) { array_unshift($values, 'Multiple matching contact records detected for this row. The contribution was not imported'); + $this->setImportStatus($rowNumber, 'ERROR', 'Multiple matching contact records detected for this row. The contribution was not imported'); return CRM_Import_Parser::ERROR; } $cid = $matchedIDs[0]; @@ -895,11 +842,13 @@ public function import($onDuplicate, &$values) { if (is_array($newContribution['error_message'])) { array_unshift($values, $newContribution['error_message']['message']); if ($newContribution['error_message']['params'][0]) { + $this->setImportStatus($rowNumber, 'DUPLICATE', $newContribution['error_message']['message']); return CRM_Import_Parser::DUPLICATE; } } else { array_unshift($values, $newContribution['error_message']); + $this->setImportStatus($rowNumber, 'ERROR', $newContribution['error_message']); return CRM_Import_Parser::ERROR; } } @@ -943,8 +892,9 @@ public function import($onDuplicate, &$values) { $disp = $params['external_identifier']; } } - - array_unshift($values, 'No matching Contact found for (' . $disp . ')'); + $errorMessage = 'No matching Contact found for (' . $disp . ')'; + $this->setImportStatus($rowNumber, 'ERROR', $errorMessage); + array_unshift($values, $errorMessage); return CRM_Import_Parser::ERROR; } @@ -953,7 +903,9 @@ public function import($onDuplicate, &$values) { $checkCid->external_identifier = $paramValues['external_identifier']; $checkCid->find(TRUE); if ($checkCid->id != $formatted['contact_id']) { - array_unshift($values, 'Mismatch of External ID:' . $paramValues['external_identifier'] . ' and Contact Id:' . $formatted['contact_id']); + $errorMessage = 'Mismatch of External ID:' . $paramValues['external_identifier'] . ' and Contact Id:' . $formatted['contact_id']; + array_unshift($values, $errorMessage); + $this->setImportStatus($rowNumber, 'ERROR', $errorMessage); return CRM_Import_Parser::ERROR; } } @@ -962,11 +914,13 @@ public function import($onDuplicate, &$values) { if (is_array($newContribution['error_message'])) { array_unshift($values, $newContribution['error_message']['message']); if ($newContribution['error_message']['params'][0]) { + $this->setImportStatus($rowNumber, 'DUPLICATE', ''); return CRM_Import_Parser::DUPLICATE; } } else { array_unshift($values, $newContribution['error_message']); + $this->setImportStatus($rowNumber, 'ERROR', $newContribution['error_message']); return CRM_Import_Parser::ERROR; } } @@ -1509,7 +1463,7 @@ private function lookupMatchingContact(array $params): int { $lookupField = !empty($params['contact_id']) ? 'contact_id' : (!empty($params['external_identifier']) ? 'external_identifier' : 'email'); if (empty($params['email'])) { $contact = Contact::get(FALSE)->addSelect('id') - ->addWhere($lookupField, '=', $params[$lookupField]) + ->addWhere($lookupField === 'contact_id' ? 'id' : $lookupField, '=', $params[$lookupField]) ->execute(); if (count($contact) !== 1) { throw new CRM_Core_Exception(ts("Soft Credit %1 - %2 doesn't exist. Row was skipped.", @@ -1562,4 +1516,19 @@ public function getMappedFieldLabel(array $mappedField): string { return implode(' - ', $title); } + /** + * Get the metadata field for which importable fields does not key the actual field name. + * + * @return string[] + */ + protected function getOddlyMappedMetadataFields(): array { + $uniqueNames = ['contribution_id', 'contribution_contact_id', 'contribution_cancel_date', 'contribution_source', 'contribution_check_number']; + $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()); + } + } diff --git a/templates/CRM/Contribute/Import/Form/MapTable.tpl b/templates/CRM/Contribute/Import/Form/MapTable.tpl index 458bf3b4fe76..3b9bab32282d 100644 --- a/templates/CRM/Contribute/Import/Form/MapTable.tpl +++ b/templates/CRM/Contribute/Import/Form/MapTable.tpl @@ -8,95 +8,4 @@ +--------------------------------------------------------------------+ *} {* Contribution Import Wizard - Data Mapping table used by MapFields.tpl and Preview.tpl *} - - <div id="map-field"> - {strip} - <table> - {if $savedMappingName} - <tr class="columnheader-dark"><th colspan="4">{ts 1=$savedMappingName}Saved Field Mapping: %1{/ts}</th></tr> - {/if} - <tr class="columnheader"> - {section name=rows loop=$rowDisplayCount} - {if $skipColumnHeader } - {if $smarty.section.rows.iteration == 1} - <th>{ts}Column Headers{/ts}</th> - {else} - <th>{ts 1=$smarty.section.rows.iteration}Import Data (row %1){/ts}</th> - {/if} - {else} - <th>{ts 1=$smarty.section.rows.iteration}Import Data (row %1){/ts}</th> - {/if} - {/section} - - <th>{ts}Matching CiviCRM Field{/ts}</th> - </tr> - - {*Loop on columns parsed from the import data rows*} - {section name=cols loop=$columnCount} - {assign var="i" value=$smarty.section.cols.index} - <tr style="border-bottom: 1px solid #92B6EC;"> - - {section name=rows loop=$rowDisplayCount} - {assign var="j" value=$smarty.section.rows.index} - <td class="{if $skipColumnHeader AND $smarty.section.rows.iteration == 1}even-row labels{else}odd-row{/if}">{$dataValues[$j][$i]|escape}</td> - {/section} - - {* Display mapper <select> field for 'Map Fields', and mapper value for 'Preview' *} - <td class="form-item even-row{if $wizard.currentStepName == 'Preview'} labels{/if}"> - {if $wizard.currentStepName == 'Preview'} - {$mapper[$i]} - {else} - {$form.mapper[$i].html|smarty:nodefaults} - {/if} - </td> - - </tr> - {/section} - - </table> - {/strip} - - {if $wizard.currentStepName != 'Preview'} - <div> - - {if $savedMappingName} - <span>{$form.updateMapping.html} {$form.updateMapping.label}</span> - {/if} - <span>{$form.saveMapping.html} {$form.saveMapping.label}</span> - <div id="saveDetails" class="form-item"> - <table class="form-layout-compressed"> - <tr> - <td class="label">{$form.saveMappingName.label}</td> - <td class="html-adjust">{$form.saveMappingName.html}</td> - </tr> - <tr> - <td class="label">{$form.saveMappingDesc.label}</td> - <td class="html-adjust">{$form.saveMappingDesc.html}</td> - </tr> - </table> - </div> - <script type="text/javascript"> - {if $mappingDetailsError } - cj('#saveDetails').show(); - {else} - cj('#saveDetails').hide(); - {/if} - - {literal} - function showSaveDetails(chkbox) { - if (chkbox.checked) { - document.getElementById("saveDetails").style.display = "block"; - document.getElementById("saveMappingName").disabled = false; - document.getElementById("saveMappingDesc").disabled = false; - } else { - document.getElementById("saveDetails").style.display = "none"; - document.getElementById("saveMappingName").disabled = true; - document.getElementById("saveMappingDesc").disabled = true; - } - } - {/literal} - {include file="CRM/common/highLightImport.tpl"} - </script> - </div> - {/if} - </div> +{include file="CRM/Import/Form/MapTableCommon.tpl" mapper=$form.mapper} diff --git a/templates/CRM/Contribute/Import/Form/Preview.tpl b/templates/CRM/Contribute/Import/Form/Preview.tpl index bf4557bcf0c0..61f1d14e11f9 100644 --- a/templates/CRM/Contribute/Import/Form/Preview.tpl +++ b/templates/CRM/Contribute/Import/Form/Preview.tpl @@ -54,6 +54,6 @@ {* Table for mapping preview *} - {include file="CRM/Contribute/Import/Form/MapTable.tpl"} +{include file="CRM/Import/Form/MapTableCommon.tpl"} <div class="crm-submit-buttons">{include file="CRM/common/formButtons.tpl" location="bottom"}</div> </div> From 1c82489babc4981ba9b99f48abe0a1e0d3d496a7 Mon Sep 17 00:00:00 2001 From: Eileen McNaughton <emcnaughton@wikimedia.org> Date: Fri, 3 Jun 2022 18:34:50 +1200 Subject: [PATCH 4/4] Use getTransformedValue more & really old code less --- CRM/Contribute/Import/Parser/Contribution.php | 67 +------------------ CRM/Import/Parser.php | 2 +- 2 files changed, 4 insertions(+), 65 deletions(-) diff --git a/CRM/Contribute/Import/Parser/Contribution.php b/CRM/Contribute/Import/Parser/Contribution.php index 239180da6546..96aa3cc236e1 100644 --- a/CRM/Contribute/Import/Parser/Contribution.php +++ b/CRM/Contribute/Import/Parser/Contribution.php @@ -380,7 +380,7 @@ public function getMappedRow(array $values): array { $params['soft_credit'][$i] = ['soft_credit_type_id' => $mappedField['soft_credit_type_id'], $mappedField['soft_credit_match_field'] => $values[$i]]; } else { - $params[$this->getFieldMetadata($mappedField['name'])['name']] = $values[$i]; + $params[$this->getFieldMetadata($mappedField['name'])['name']] = $this->getTransformedFieldValue($mappedField['name'], $values[$i]); } } return $params; @@ -634,16 +634,9 @@ protected function setFieldMetadata() { public function summary(&$values) { $rowNumber = (int) ($values[array_key_last($values)]); $params = $this->getMappedRow($values); - - //for date-Formats - $errorMessage = implode('; ', $this->formatDateFields($params)); - //date-Format part ends - + $errorMessage = implode(';', $this->getInvalidValues($params)); $params['contact_type'] = 'Contribution'; - //checking error in custom data - $this->isErrorInCustomData($params, $errorMessage); - if ($errorMessage) { $tempMsg = "Invalid value for field(s) : $errorMessage"; array_unshift($values, $tempMsg); @@ -682,7 +675,7 @@ public function import($onDuplicate, &$values) { } $params = $this->getMappedRow($values); - $formatted = ['version' => 3, 'skipRecentView' => TRUE, 'skipCleanMoney' => FALSE, 'contribution_id' => $params['id'] ?? NULL]; + $formatted = array_merge(['version' => 3, 'skipRecentView' => TRUE, 'skipCleanMoney' => FALSE, 'contribution_id' => $params['id'] ?? NULL], $params); //CRM-10994 if (isset($params['total_amount']) && $params['total_amount'] == 0) { $params['total_amount'] = '0.00'; @@ -1095,11 +1088,6 @@ private function deprecatedFormatParams($params, &$values, $create = FALSE, $onD require_once 'CRM/Utils/DeprecatedUtils.php'; // copy all the contribution fields as is require_once 'api/v3/utils.php'; - $fields = CRM_Core_DAO::getExportableFieldsWithPseudoConstants('CRM_Contribute_BAO_Contribution'); - - _civicrm_api3_store_values($fields, $params, $values); - - $customFields = CRM_Core_BAO_CustomField::getFields('Contribution', FALSE, FALSE, NULL, NULL, FALSE, FALSE, FALSE); foreach ($params as $key => $value) { // ignore empty values or empty arrays etc @@ -1107,32 +1095,6 @@ private function deprecatedFormatParams($params, &$values, $create = FALSE, $onD continue; } - // Handling Custom Data - if ($customFieldID = CRM_Core_BAO_CustomField::getKeyID($key)) { - $values[$key] = $value; - $type = $customFields[$customFieldID]['html_type']; - if (CRM_Core_BAO_CustomField::isSerialized($customFields[$customFieldID])) { - $values[$key] = self::unserializeCustomValue($customFieldID, $value, $type); - } - elseif ($type == 'Select' || $type == 'Radio' || - ($type == 'Autocomplete-Select' && - $customFields[$customFieldID]['data_type'] == 'String' - ) - ) { - $customOption = CRM_Core_BAO_CustomOption::getCustomOption($customFieldID, TRUE); - foreach ($customOption as $customFldID => $customValue) { - $val = $customValue['value'] ?? NULL; - $label = $customValue['label'] ?? NULL; - $label = strtolower($label); - $value = strtolower(trim($value)); - if (($value == $label) || ($value == strtolower($val))) { - $values[$key] = $val; - } - } - } - continue; - } - switch ($key) { case 'contact_id': if (!CRM_Utils_Rule::integer($value)) { @@ -1221,15 +1183,6 @@ private function deprecatedFormatParams($params, &$values, $create = FALSE, $onD } break; - case 'receive_date': - case 'cancel_date': - case 'receipt_date': - case 'thankyou_date': - if (!CRM_Utils_Rule::dateTime($value)) { - return civicrm_api3_create_error("$key not a valid date: $value"); - } - break; - case 'non_deductible_amount': case 'total_amount': case 'fee_amount': @@ -1374,20 +1327,6 @@ private function deprecatedFormatParams($params, &$values, $create = FALSE, $onD $values['contribution_campaign_id'] = $params['contribution_campaign_id']; break; - default: - // Hande name or label for fields with options. - if (isset($fields[$key]) && - // Yay - just for a surprise we are inconsistent on whether we pass the pseudofield (payment_instrument) - // or the field name (contribution_status_id) - // @todo - payment_instrument is goneburger - now payment_instrument_id - how - // can we simplify. - (!empty($fields[$key]['is_pseudofield_for']) || !empty($fields[$key]['pseudoconstant'])) - ) { - $realField = $fields[$key]['is_pseudofield_for'] ?? $key; - $realFieldSpec = $fields[$realField]; - $values[$key] = $this->parsePseudoConstantField($value, $realFieldSpec); - } - break; } } diff --git a/CRM/Import/Parser.php b/CRM/Import/Parser.php index 8a12340f48fb..93c5260ff197 100644 --- a/CRM/Import/Parser.php +++ b/CRM/Import/Parser.php @@ -1537,7 +1537,7 @@ public function validate(): void { * @return array * @throws \API_Exception */ - protected function getInvalidValues($value, string $key, string $prefixString = ''): array { + protected function getInvalidValues($value, string $key = '', string $prefixString = ''): array { $errors = []; if ($value === 'invalid_import_value') { $errors[] = $prefixString . $this->getFieldMetadata($key)['title'];