diff --git a/CRM/Contact/Import/Form/DataSource.php b/CRM/Contact/Import/Form/DataSource.php index b39b67401094..443bf956b896 100644 --- a/CRM/Contact/Import/Form/DataSource.php +++ b/CRM/Contact/Import/Form/DataSource.php @@ -176,6 +176,7 @@ public function postProcess() { $this->createUserJob(); } else { + $this->flushDataSource(); $this->updateUserJobMetadata('submitted_values', $this->getSubmittedValues()); } // Setup the params array @@ -199,11 +200,6 @@ public function postProcess() { CRM_Core_Session::singleton()->set('dateTypes', $storeParams['dateFormats']); - //hack to prevent multiple tables. - $this->_params['import_table_name'] = $this->get('importTableName'); - if (!$this->_params['import_table_name']) { - $this->_params['import_table_name'] = 'civicrm_import_job_' . md5(uniqid(rand(), TRUE)); - } $this->instantiateDataSource(); // We should have the data in the DB now, parse it diff --git a/CRM/Import/DataSource.php b/CRM/Import/DataSource.php index 1fce11a312fe..66e80574af57 100644 --- a/CRM/Import/DataSource.php +++ b/CRM/Import/DataSource.php @@ -300,4 +300,37 @@ protected function updateUserJobMetadata(string $key, array $data): void { $this->userJob['metadata'] = $metaData; } + /** + * Purge any datasource related assets when the datasource is dropped. + * + * This is the datasource's chance to delete any tables etc that it created + * which will now not be used. + * + * @param array $newParams + * If the dataSource is being updated to another variant of the same + * class (eg. the csv upload was set to no column headers and they + * have resubmitted WITH skipColumnHeader (first row is a header) then + * the dataSource is still CSV and the params for the new intance + * are passed in. When changing from csv to SQL (for example) newParams is + * empty. + * + * @return array + * The details to update the DataSource key in the userJob metadata to. + * Generally and empty array but it the datasource decided (for example) + * that the table it created earlier is still consistent with the new params + * then it might decided not to drop the table and would want to retain + * some metadata. + * + * @throws \API_Exception + * @throws \CRM_Core_Exception + */ + public function purge(array $newParams = []) :array { + // The old name is still stored... + $oldTableName = $this->getTableName(); + if ($oldTableName) { + CRM_Core_DAO::executeQuery('DROP TABLE IF EXISTS ' . $oldTableName); + } + return []; + } + } diff --git a/CRM/Import/DataSource/CSV.php b/CRM/Import/DataSource/CSV.php index a21a4f01f691..43c6120c9483 100644 --- a/CRM/Import/DataSource/CSV.php +++ b/CRM/Import/DataSource/CSV.php @@ -93,7 +93,7 @@ public function postProcess(&$params, &$db, &$form) { $result = self::_CsvToTable( $file, $firstRowIsColumnHeader, - CRM_Utils_Array::value('import_table_name', $params), + NULL, CRM_Utils_Array::value('fieldSeparator', $params, ',') ); diff --git a/CRM/Import/DataSource/SQL.php b/CRM/Import/DataSource/SQL.php index 3d123ce6a900..1d3e7c8d4ae4 100644 --- a/CRM/Import/DataSource/SQL.php +++ b/CRM/Import/DataSource/SQL.php @@ -94,7 +94,7 @@ public static function formRule($fields, $files, $form) { */ public function postProcess(&$params, &$db, &$form) { $importJob = new CRM_Contact_Import_ImportJob( - CRM_Utils_Array::value('import_table_name', $params), + NULL, $params['sqlQuery'], TRUE ); diff --git a/CRM/Import/Forms.php b/CRM/Import/Forms.php index 938f8f5f6d58..4181a43869c9 100644 --- a/CRM/Import/Forms.php +++ b/CRM/Import/Forms.php @@ -235,6 +235,35 @@ protected function buildDataSourceFields(): void { } } + /** + * Flush datasource on re-submission of the form. + * + * If the form has been re-submitted the datasource might have changed. + * We tell the dataSource class to remove any tables (and potentially files) + * created last form submission. + * + * If the DataSource in use is unchanged (ie still CSV or still SQL) + * we also pass in the new variables. In theory it could decide that they + * have not actually changed and it doesn't need to do any cleanup. + * + * In practice the datasource classes blast away as they always have for now + * - however, the sql class, for example, might realise the fields it cares + * about are unchanged and not flush the table. + * + * @throws \API_Exception + * @throws \CRM_Core_Exception + */ + protected function flushDataSource(): void { + // If the form has been resubmitted the datasource might have changed. + // We give the datasource a chance to clean up any tables it might have + // created. If we are still using the same type of datasource (e.g still + // an sql query + $oldDataSource = $this->getUserJobSubmittedValues()['dataSource']; + $oldDataSourceObject = new $oldDataSource($this->getUserJobID()); + $newParams = $this->getSubmittedValue('dataSource') === $oldDataSource ? $this->getSubmittedValues() : []; + $oldDataSourceObject->purge($newParams); + } + /** * Get the relevant datasource object. * diff --git a/tests/phpunit/CRM/Contact/Import/Form/DataSourceTest.php b/tests/phpunit/CRM/Contact/Import/Form/DataSourceTest.php index 2d096185abe9..4c71051c4f25 100644 --- a/tests/phpunit/CRM/Contact/Import/Form/DataSourceTest.php +++ b/tests/phpunit/CRM/Contact/Import/Form/DataSourceTest.php @@ -52,7 +52,6 @@ public function testBuildForm(): void { * * @throws \API_Exception * @throws \CRM_Core_Exception - * @throws \Civi\API\Exception\UnauthorizedException */ public function testDataSources(): void { $this->createLoggedInUser();