From 4f96e2d29c9f2434bc3c3815e790beebca38e054 Mon Sep 17 00:00:00 2001 From: Eileen McNaughton Date: Tue, 16 Aug 2022 20:13:06 +1200 Subject: [PATCH] Add Saved searches to view import jobs: --- .../Event/Subscriber/ImportSubscriber.php | 21 +- .../Spec/Provider/ImportSpecProvider.php | 6 +- ext/civiimport/Civi/BAO/Import.php | 12 ++ ext/civiimport/Managed/ImportSearches.mgd.php | 182 ++++++++++++++++++ 4 files changed, 213 insertions(+), 8 deletions(-) create mode 100644 ext/civiimport/Managed/ImportSearches.mgd.php diff --git a/ext/civiimport/Civi/Api4/Event/Subscriber/ImportSubscriber.php b/ext/civiimport/Civi/Api4/Event/Subscriber/ImportSubscriber.php index 598d8b45ba..4643a24a7e 100644 --- a/ext/civiimport/Civi/Api4/Event/Subscriber/ImportSubscriber.php +++ b/ext/civiimport/Civi/Api4/Event/Subscriber/ImportSubscriber.php @@ -10,6 +10,8 @@ namespace Civi\Api4\Event\Subscriber; use Civi; use Civi\API\Event\AuthorizeEvent; use Civi\API\Events; +use Civi\Api4\Entity; +use Civi\Api4\Managed; use Civi\Api4\UserJob; use Civi\Core\Event\PostEvent; use Civi\Core\Event\GenericHookEvent; @@ -72,10 +74,21 @@ class ImportSubscriber implements EventSubscriberInterface { * Callback for hook_civicrm_post(). */ public function on_hook_civicrm_post(PostEvent $event): void { - if ($event->entity === 'UserJob' && $event->action === 'create') { - // Flush entities cache key so our new Import will load as an entity. - Civi::cache('metadata')->set('api4.entities.info', NULL); - CRM_Core_DAO_AllCoreTables::flush(); + if ($event->entity === 'UserJob') { + try { + $exists = Entity::get(FALSE)->addWhere('name', '=', 'Import_' . $event->id)->selectRowCount()->execute()->count(); + if (!$exists || $event->action === 'delete') { + // Flush entities cache key so our new Import will load as an entity. + Civi::cache('metadata')->set('api4.entities.info', NULL); + CRM_Core_DAO_AllCoreTables::flush(); + Managed::reconcile(FALSE)->setModules(['civiimport'])->execute(); + } + } + catch (\CRM_Core_Exception $e) { + // Log & move on. + \Civi::log()->warning('Failed to flush cache on UserJob clear', ['exception' => $e]); + return; + } } } diff --git a/ext/civiimport/Civi/Api4/Service/Spec/Provider/ImportSpecProvider.php b/ext/civiimport/Civi/Api4/Service/Spec/Provider/ImportSpecProvider.php index 61480f8d25..e81e4108c4 100644 --- a/ext/civiimport/Civi/Api4/Service/Spec/Provider/ImportSpecProvider.php +++ b/ext/civiimport/Civi/Api4/Service/Spec/Provider/ImportSpecProvider.php @@ -32,17 +32,15 @@ class ImportSpecProvider implements Generic\SpecProviderInterface { $userJobID = substr($spec->getEntity(), (strpos($spec->getEntity(), '_') + 1)); $userJob = UserJob::get(FALSE)->addWhere('id', '=', $userJobID)->addSelect('metadata', 'job_type', 'created_id')->execute()->first(); - $headers = $userJob['metadata']['DataSource']['column_headers'] ?? []; foreach ($columns as $column) { $isInternalField = strpos($column['name'], '_') === 0; $exists = $isInternalField && $spec->getFieldByName($column['name']); if ($exists) { continue; } - $header = $isInternalField ? $column['name'] : array_shift($headers); $field = new FieldSpec($column['name'], $spec->getEntity(), 'String'); - $field->setTitle(ts('Import field') . ':' . $header); - $field->setLabel($header); + $field->setTitle(ts('Import field') . ':' . $column['label']); + $field->setLabel($column['label']); $field->setReadonly($isInternalField); $field->setDescription(ts('Data being imported into the field.')); $field->setColumnName($column['name']); diff --git a/ext/civiimport/Civi/BAO/Import.php b/ext/civiimport/Civi/BAO/Import.php index a83e69295c..4e44659efd 100644 --- a/ext/civiimport/Civi/BAO/Import.php +++ b/ext/civiimport/Civi/BAO/Import.php @@ -69,13 +69,17 @@ class Import extends CRM_Core_DAO { if (!CRM_Utils_Rule::alphanumeric($tableName) || !CRM_Core_DAO::singleValueQuery('SHOW TABLES LIKE %1', [1 => [$tableName, 'String']])) { continue; } + $createdBy = $tables->display_name ? '' : ' (' . E::ts('Created by %1', [$tables->display_name, 'String']) . ')'; $importEntities[$tables->id] = [ 'table_name' => $tableName, 'created_by' => $tables->display_name, 'created_id' => $tables->created_id ? (int) $tables->created_id : NULL, 'job_type' => $tables->job_type, + 'user_job_id' => (int) $tables->id, 'created_date' => $tables->created_date, 'expires_date' => $tables->expires_date, + 'title' => ts('Import Job') . (int) $tables->id, + 'description' => $tables->created_date . $createdBy, ]; } return $importEntities; @@ -221,9 +225,17 @@ class Import extends CRM_Core_DAO { throw new CRM_Core_Exception('Invalid import table'); } $columns = []; + $headers = UserJob::get(FALSE) + ->addWhere('metadata', 'LIKE', '%' . $tableName . '%') + ->addSelect('metadata')->execute()->first()['metadata']['DataSource']['column_headers'] ?? []; $result = CRM_Core_DAO::executeQuery("SHOW COLUMNS FROM $tableName"); + $userFieldIndex = 0; while ($result->fetch()) { $columns[$result->Field] = ['name' => $result->Field, 'table_name' => $tableName]; + if (substr($result->Field, 1) !== '_') { + $columns[$result->Field]['label'] = $headers[$userFieldIndex] ?? $result->Field; + $userFieldIndex++; + } } return $columns; } diff --git a/ext/civiimport/Managed/ImportSearches.mgd.php b/ext/civiimport/Managed/ImportSearches.mgd.php new file mode 100644 index 0000000000..862aea8e93 --- /dev/null +++ b/ext/civiimport/Managed/ImportSearches.mgd.php @@ -0,0 +1,182 @@ +addWhere('name', '=', 'SearchDisplay') + ->selectRowCount() + ->execute()->count()) { + return []; + } +} +catch (CRM_Core_Exception $e) { + return []; +} + +$managedEntities = []; +$importEntities = Import::getImportTables(); +foreach ($importEntities as $importEntity) { + try { + $fields = array_merge(['_id' => TRUE, '_status' => TRUE, '_status_message' => TRUE], Import::getFieldsForUserJobID($importEntity['user_job_id'], FALSE)); + } + catch (CRM_Core_Exception $e) { + continue; + } + $createdBy = empty($importEntity['created_by']) ? '' : ' (' . E::ts('Created by %1', [$importEntity['created_by'], 'String']) . ')'; + $managedEntities[] = [ + 'name' => 'SavedSearch_Import' . $importEntity['user_job_id'], + 'entity' => 'SavedSearch', + 'cleanup' => 'always', + 'update' => 'unmodified', + 'params' => [ + 'version' => 4, + 'values' => [ + 'name' => 'Import' . '_' . $importEntity['user_job_id'], + 'label' => $importEntity['title'] . ' ' . $importEntity['description'], + 'api_entity' => 'Import' . '_' . $importEntity['user_job_id'], + 'api_params' => [ + 'version' => 4, + 'select' => array_keys($fields), + 'orderBy' => [], + 'where' => [], + 'groupBy' => [], + 'join' => [], + 'having' => [], + ], + 'expires_date' => $importEntity['expires_date'], + 'created_date' => $importEntity['created_date'], + 'created_id' => $importEntity['created_id'], + 'description' => ts('Temporary import data'), + 'mapping_id' => NULL, + ], + ], + ]; + $managedEntities[] = [ + 'name' => 'SavedSearch_Import_Summary' . $importEntity['user_job_id'], + 'entity' => 'SavedSearch', + 'cleanup' => 'always', + 'update' => 'unmodified', + 'params' => [ + 'version' => 4, + 'values' => [ + 'name' => 'Import_Summary' . '_' . $importEntity['user_job_id'], + 'label' => E::ts('Import Summary') . ' ' . $importEntity['description'], + 'api_entity' => 'Import' . '_' . $importEntity['user_job_id'], + 'api_params' => [ + 'version' => 4, + 'select' => ['_status', 'COUNT(_id) AS COUNT__id'], + 'orderBy' => [], + 'where' => [], + 'groupBy' => ['_status'], + 'join' => [], + 'having' => [], + ], + 'expires_date' => $importEntity['expires_date'], + 'created_date' => $importEntity['created_date'], + 'created_id' => $importEntity['created_id'], + 'description' => ts('Temporary import data'), + 'mapping_id' => NULL, + ], + ], + ]; + $columns = []; + foreach ($fields as $field) { + $columns[] = [ + 'type' => 'field', + 'key' => $field['name'], + 'dataType' => $field['data_type'] ?? 'String', + 'label' => $field['title'] ?? $field['label'], + 'sortable' => TRUE, + 'editable' => strpos($field['name'], '_') !== 0, + ]; + } + $managedEntities[] = [ + 'name' => 'SavedSearchDisplay_Import' . $importEntity['user_job_id'], + 'entity' => 'SearchDisplay', + 'cleanup' => 'always', + 'update' => 'unmodified', + 'params' => [ + 'version' => 4, + 'values' => [ + 'name' => 'Import' . '_' . $importEntity['user_job_id'], + 'label' => E::ts('Import') . ' ' . $importEntity['user_job_id'] . $createdBy, + 'saved_search_id.name' => 'Import' . '_' . $importEntity['user_job_id'], + 'type' => 'table', + 'settings' => [ + 'actions' => TRUE, + 'limit' => 25, + 'classes' => [ + 'table', + 'table-striped', + ], + 'pager' => [ + 'show_count' => TRUE, + 'expose_limit' => TRUE, + ], + 'sort' => [], + 'columns' => $columns, + ], + 'acl_bypass' => FALSE, + ], + ], + ]; + + $managedEntities[] = [ + 'name' => 'SavedSearchDisplay_Import_Summary' . $importEntity['user_job_id'], + 'entity' => 'SearchDisplay', + 'cleanup' => 'always', + 'update' => 'unmodified', + 'params' => [ + 'version' => 4, + 'values' => [ + 'name' => 'Import_Summary' . '_' . $importEntity['user_job_id'], + 'label' => E::ts('Import Summary') . ' ' . $importEntity['user_job_id'] . $createdBy, + 'saved_search_id.name' => 'Import_Summary' . '_' . $importEntity['user_job_id'], + 'type' => 'table', + 'settings' => [ + 'actions' => FALSE, + 'limit' => 40, + 'classes' => [ + 'table', + 'table-striped', + ], + 'pager' => [ + 'show_count' => TRUE, + 'expose_limit' => TRUE, + ], + 'sort' => [], + 'columns' => [ + [ + 'type' => 'field', + 'key' => '_status', + 'dataType' => 'String', + 'label' => 'Row status', + 'sortable' => TRUE, + 'link' => [ + 'path' => 'civicrm/search#/display/Import_' . $importEntity['user_job_id'] . '/Import_' . $importEntity['user_job_id'] . '?_status=[_status]', + 'entity' => '', + 'action' => '', + 'join' => '', + 'target' => '', + ], + 'rewrite' => '[_status]', + ], + [ + 'type' => 'field', + 'key' => 'COUNT__id', + 'dataType' => 'Integer', + 'label' => '', + 'sortable' => TRUE, + ], + ], + ], + 'acl_bypass' => FALSE, + ], + ], + ]; +} +return $managedEntities; -- 2.25.1