Skip to content

Commit

Permalink
Add civiimport with Import api code for viewing import tables
Browse files Browse the repository at this point in the history
  • Loading branch information
eileenmcnaughton committed Aug 11, 2022
1 parent 95182b3 commit b7421e2
Show file tree
Hide file tree
Showing 11 changed files with 1,535 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
!/ext/payflowpro
!/ext/ckeditor4
!/ext/legacycustomsearches
!/ext/civiimport
backdrop/
bower_components
CRM/Case/xml/configuration
Expand Down
108 changes: 108 additions & 0 deletions ext/civiimport/Civi/Api4/Event/Subscriber/ImportSubscriber.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
<?php

/**
*
* @package CRM
* @copyright CiviCRM LLC https://civicrm.org/licensing
*/
namespace Civi\Api4\Event\Subscriber;

use Civi;
use Civi\Core\HookInterface;
use CRM_Core_DAO;
use Civi\Core\Event\GenericHookEvent;
use CRM_Utils_Rule;
use Civi\Api4\Import;

/**
* Listening class that registers each Import table as an entity.
*/
class ImportSubscriber implements HookInterface {

/**
* @return array
*/
public static function getImportTables(): array {
// We need to avoid the api here as it
$tables = CRM_Core_DAO::executeQuery('
Select `id`, `metadata`, `name`, `job_type`, `created_id`
FROM civicrm_user_job
-- As of writing expires date is probably not being managed
-- it is intended to be used to actually purge the record in
-- a cleanup job so it might not be relevant here & perhaps this will
-- be removed later
WHERE (expires_date IS NULL OR expires_date > NOW())
-- this is a short-cut for looking up if they are imports
-- it is a new convention, at best, to require anything
-- specific in the job_type, but it saves any onerous lookups
-- in a function which needs to avoid loops
AND job_type LIKE "%import"
-- also more of a feature than a specification - but we need a table
-- to do this pseudo-api
AND metadata LIKE "%table_name%"');
$importEntities = [];
while ($tables->fetch()) {
$tableName = json_decode($tables->metadata, TRUE)['DataSource']['table_name'];
if (!CRM_Utils_Rule::alphanumeric($tableName) || !CRM_Core_DAO::singleValueQuery('SHOW TABLES LIKE %1', [
1 => [
$tableName,
'String'
]
])) {
continue;
}
$importEntities[$tables->id] = $tableName;
}
return $importEntities;
}

/**
* Register each valid import as an entity
*
* @param GenericHookEvent $event
*
* @noinspection PhpUnused
* @noinspection PhpUndefinedFieldInspection
*/
public static function on_civi_api4_entityTypes(GenericHookEvent $event): void {
$importEntities = self::getImportTables();
foreach ($importEntities as $userJobID => $tableName) {
$event->entities['Import_' . $userJobID] = [
'name' => 'Import_' . $userJobID,
'title' => ts('Import') . '_' . $userJobID,
'title_plural' => ts('Import') . $userJobID,
'description' => ts('Import Job temporary data'),
'primary_key' => ['_id'],
'type' => ['Import'],
'table_name' => $tableName,
'class_args' => [$userJobID],
'label_field' => '_id',
'searchable' => 'secondary',
'paths' => [
// 'browse' => "civicrm/eck/entity/list/{$entity_type['name']}",
// 'view' => "civicrm/eck/entity?reset=1&action=view&type={$entity_type['name']}&id=[id]",
// 'update' => "civicrm/eck/entity/edit/{$entity_type['name']}/[subtype:name]#?{$entity_type['entity_name']}=[id]",
// 'add' => "civicrm/eck/entity/edit/{$entity_type['name']}/[subtype:name]",
],
'class' => Import::class,
'icon' => 'fa-cubes',
];
}
}

/**
* Callback for hook_civicrm_post().
*
* @param string $op
* @param string $objectName
*
* @noinspection PhpUnusedParameterInspection
*/
public static function hook_civicrm_post(string $op, string $objectName): void {
if ($objectName === 'UserJob') {
// Flush entities cache key so our new Import will load as an entity.
Civi::cache('metadata')->set('api4.entities.info', NULL);
}
}

}
138 changes: 138 additions & 0 deletions ext/civiimport/Civi/Api4/Import.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
<?php
/*
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC. All rights reserved. |
| |
| This work is published under the GNU AGPLv3 license with some |
| permitted exceptions and without any warranty. For full license |
| and copyright information, see https://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
namespace Civi\Api4;

use Civi\Api4\Generic\BasicReplaceAction;
use Civi\Api4\Generic\CheckAccessAction;
use Civi\Api4\Generic\DAOCreateAction;
use Civi\Api4\Generic\DAODeleteAction;
use Civi\Api4\Generic\DAOGetAction;
use Civi\Api4\Generic\DAOGetFieldsAction;
use Civi\Api4\Action\GetActions;
use Civi\Api4\Generic\DAOSaveAction;
use Civi\Api4\Generic\DAOUpdateAction;

/**
* Import entity.
*
* @searchable secondary
* @since 5.54
* @package Civi\Api4
*/
class Import {

/**
* @param int $userJobID
* @param bool $checkPermissions
*
* @return DAOGetFieldsAction
*/
public static function getFields(int $userJobID, bool $checkPermissions = TRUE): DAOGetFieldsAction {
return (new DAOGetFieldsAction('Import_' . $userJobID, __FUNCTION__))
->setCheckPermissions($checkPermissions);
}

/**
* @param int $userJobID
* @param bool $checkPermissions
* @return DAOGetAction
* @throws \CRM_Core_Exception
*/
public static function get(int $userJobID, bool $checkPermissions = TRUE): DAOGetAction {
return (new DAOGetAction('Import_' . $userJobID, __FUNCTION__))
->setCheckPermissions($checkPermissions);
}

/**
* @param int $userJobID
* @param bool $checkPermissions
* @return DAOSaveAction
* @throws \API_Exception
*/
public static function save(int $userJobID, bool $checkPermissions = TRUE): DAOSaveAction {
return (new DAOSaveAction('Import_' . $userJobID, __FUNCTION__))
->setCheckPermissions($checkPermissions);
}

/**
* @param int $userJobID
* @param bool $checkPermissions
* @return DAOCreateAction
* @throws \API_Exception
*/
public static function create(int $userJobID, bool $checkPermissions = TRUE): DAOCreateAction {
return (new DAOCreateAction('Import_' . $userJobID, __FUNCTION__))
->setCheckPermissions($checkPermissions);
}

/**
* @param int $userJobID
* @param bool $checkPermissions
* @return DAOUpdateAction
* @throws \API_Exception
*/
public static function update(int $userJobID, bool $checkPermissions = TRUE): DAOUpdateAction {
return (new DAOUpdateAction('Import_' . $userJobID, __FUNCTION__))
->setCheckPermissions($checkPermissions);
}

/**
* @param int $userJobID
* @param bool $checkPermissions
* @return DAODeleteAction
* @throws \API_Exception
*/
public static function delete(int $userJobID, bool $checkPermissions = TRUE): DAODeleteAction {
return (new DAODeleteAction('Import_' . $userJobID, __FUNCTION__))
->setCheckPermissions($checkPermissions);
}

/**
* @param int $userJobID
* @param bool $checkPermissions
* @return BasicReplaceAction
* @throws \API_Exception
*/
public static function replace(int $userJobID, bool $checkPermissions = TRUE): BasicReplaceAction {
return (new BasicReplaceAction('Import_' . $userJobID, __FUNCTION__))
->setCheckPermissions($checkPermissions);
}

/**
* @param int $userJobID
* @param bool $checkPermissions
* @return GetActions
*/
public static function getActions(int $userJobID, bool $checkPermissions = TRUE): GetActions {
return (new GetActions('Import_' . $userJobID, __FUNCTION__))
->setCheckPermissions($checkPermissions);
}

/**
* @param int $userJobID
* @return CheckAccessAction
* @throws \API_Exception
*/
public static function checkAccess(int $userJobID): CheckAccessAction {
return new CheckAccessAction('Import_' . $userJobID, __FUNCTION__);
}

/**
* We need to implement these elsewhere as we permit based on 'created_id'.
*
* @return array
*/
public static function permissions(): array {
return [];
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

/*
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC. All rights reserved. |
| |
| This work is published under the GNU AGPLv3 license with some |
| permitted exceptions and without any warranty. For full license |
| and copyright information, see https://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/

namespace Civi\Api4\Service\Spec\Provider;

use Civi\Api4\Service\Spec\FieldSpec;
use Civi\Api4\Service\Spec\RequestSpec;

class ImportSpecProvider implements Generic\SpecProviderInterface {

/**
* @inheritDoc
*/
public function modifySpec(RequestSpec $spec) {
// here we need to get the columns from the table & add them in...
// not being hit atm
return;
$action = $spec->getAction();

// The database default '1' is problematic as the option list is user-configurable,
// so activity type '1' doesn't necessarily exist. Best make the field required.
$spec->getFieldByName('activity_type_id')
->setDefaultValue(NULL)
->setRequired($action === 'create');

$field = new FieldSpec('source_contact_id', 'Activity', 'Integer');
$field->setTitle(ts('Source Contact'));
$field->setLabel(ts('Added by'));
$field->setDescription(ts('Contact who created this activity.'));
$field->setRequired($action === 'create');
$field->setFkEntity('Contact');
$field->setInputType('EntityRef');
$spec->addFieldSpec($field);

$field = new FieldSpec('target_contact_id', 'Activity', 'Array');
$field->setTitle(ts('Target Contacts'));
$field->setLabel(ts('With Contact(s)'));
$field->setDescription(ts('Contact(s) involved in this activity.'));
$field->setFkEntity('Contact');
$field->setInputType('EntityRef');
$field->setInputAttrs(['multiple' => TRUE]);
$spec->addFieldSpec($field);

$field = new FieldSpec('assignee_contact_id', 'Activity', 'Array');
$field->setTitle(ts('Assignee Contacts'));
$field->setLabel(ts('Assigned to'));
$field->setDescription(ts('Contact(s) assigned to this activity.'));
$field->setFkEntity('Contact');
$field->setInputType('EntityRef');
$field->setInputAttrs(['multiple' => TRUE]);
$spec->addFieldSpec($field);
}

/**
* @inheritDoc
*/
public function applies($entity, $action) {
// here we need to check the entity.
// not being hit atm
return $entity === 'Activity' && in_array($action, ['create', 'update'], TRUE);
}

}
68 changes: 68 additions & 0 deletions ext/civiimport/Civi/BAO/Import.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php
/*
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC. All rights reserved. |
| |
| This work is published under the GNU AGPLv3 license with some |
| permitted exceptions and without any warranty. For full license |
| and copyright information, see https://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/

namespace Civi\BAO;

use CRM_Civiimport_ExtensionUtil as E;

/**
*
* @package CRM
* @copyright CiviCRM LLC https://civicrm.org/licensing
*/
class Import {

public static function getSupportedFields(): array {
return [
'_id' => [
'type' => 'Field',
'required' => TRUE,
'nullable' => FALSE,
'readonly' => TRUE,
'name' => 'id',
'title' => E::ts('Import row ID'),
'data_type' => 'Integer',
'input_type' => 'Number',
'column_name' => '_id',
],
'_status' => [
'type' => 'Field',
'required' => TRUE,
'nullable' => FALSE,
'name' => '_status',
'title' => E::ts('Row status'),
'data_type' => 'String',
'column_name' => '_status_message',
],
'_status_message' => [
'type' => 'Field',
'nullable' => TRUE,
'name' => '_status_message',
'title' => E::ts('Row import message'),
'description' => '',
'data_type' => 'String',
'column_name' => '_status_message',
],
];
}

/**
* Checks if this DAO's table ought to exist.
*
* If there are pending DB updates, this function compares the CiviCRM version of the table to the current schema version.
*
* @return bool
*/
public static function tableHasBeenAdded(): bool {
return TRUE;
}

}
Loading

0 comments on commit b7421e2

Please sign in to comment.