diff --git a/hook.php b/hook.php
index 969fe791..5110626c 100644
--- a/hook.php
+++ b/hook.php
@@ -28,21 +28,6 @@
* -------------------------------------------------------------------------
*/
-function plugin_datainjection_registerMethods() {
-
- global $WEBSERVICES_METHOD;
-
- $methods = ['getModel' => 'methodGetModel',
- 'listModels' => 'methodListModels',
- 'inject' => 'methodInject',
- 'listItemtypes' => 'methodListItemtypes'];
-
- foreach ($methods as $code => $method) {
- $WEBSERVICES_METHOD['datainjection.'.$code] = ['PluginDatainjectionWebservice', $method];
- }
-}
-
-
function plugin_datainjection_install() {
global $DB;
diff --git a/inc/apicontroller.class.php b/inc/apicontroller.class.php
new file mode 100644
index 00000000..53a7a8a6
--- /dev/null
+++ b/inc/apicontroller.class.php
@@ -0,0 +1,227 @@
+.
+ * -------------------------------------------------------------------------
+ * @copyright Copyright (C) 2007-2023 by DataInjection plugin team.
+ * @license GPLv2 https://www.gnu.org/licenses/gpl-2.0.html
+ * @link https://github.com/pluginsGLPI/datainjection
+ * -------------------------------------------------------------------------
+ */
+
+use Glpi\Api\HL\Controller\AbstractController;
+use Glpi\Api\HL\Doc as Doc;
+use Glpi\Api\HL\Route;
+use Glpi\Api\HL\Search;
+use Glpi\Http\JSONResponse;
+use Glpi\Http\Request;
+use Glpi\Http\Response;
+use GuzzleHttp\Psr7\Utils;
+
+#[Route(path: '/Plugin/DataInjection', requirements: [
+ 'id' => '\d+'
+], priority: 1, tags: ['Data Injection'])]
+class PluginDatainjectionApiController extends AbstractController
+{
+ protected static function getRawKnownSchemas(): array
+ {
+ return [
+ 'DataInjectionModel' => [
+ 'type' => Doc\Schema::TYPE_OBJECT,
+ 'x-itemtype' => PluginDatainjectionModel::class,
+ 'properties' => [
+ 'id' => [
+ 'type' => Doc\Schema::TYPE_INTEGER,
+ 'format' => Doc\Schema::FORMAT_INTEGER_INT64,
+ ],
+ 'name' => ['type' => Doc\Schema::TYPE_STRING],
+ 'comment' => ['type' => Doc\Schema::TYPE_STRING],
+ 'itemtype' => ['type' => Doc\Schema::TYPE_STRING],
+ 'entity' => self::getDropdownTypeSchema(class: Entity::class, full_schema: 'Entity'),
+ 'date_creation' => ['type' => Doc\Schema::TYPE_STRING, 'format' => Doc\Schema::FORMAT_STRING_DATE_TIME],
+ 'date_mod' => ['type' => Doc\Schema::TYPE_STRING, 'format' => Doc\Schema::FORMAT_STRING_DATE_TIME],
+ 'allow_add' => [
+ 'type' => Doc\Schema::TYPE_BOOLEAN,
+ 'x-field' => 'behavior_add',
+ 'description' => 'Allow creation of new items'
+ ],
+ 'allow_update' => [
+ 'type' => Doc\Schema::TYPE_BOOLEAN,
+ 'x-field' => 'behavior_update',
+ 'description' => 'Allow update of existing items'
+ ],
+ 'allow_add_linked_items' => [
+ 'type' => Doc\Schema::TYPE_BOOLEAN,
+ 'x-field' => 'can_add_dropdown',
+ 'description' => 'Allow creation of dropdowns/linked items'
+ ],
+ 'allow_overwrite_fields' => [
+ 'type' => Doc\Schema::TYPE_BOOLEAN,
+ 'x-field' => 'can_overwrite_if_not_empty',
+ 'description' => 'Allow update of existing fields'
+ ],
+ 'is_private' => ['type' => Doc\Schema::TYPE_BOOLEAN],
+ 'user' => self::getDropdownTypeSchema(class: User::class, full_schema: 'User'),
+ 'date_format' => ['type' => Doc\Schema::TYPE_STRING],
+ 'float_format' => ['type' => Doc\Schema::TYPE_STRING],
+ 'unique_ports' => [
+ 'type' => Doc\Schema::TYPE_BOOLEAN,
+ 'x-field' => 'port_unicity',
+ ],
+ 'csv_options' => [
+ 'type' => Doc\Schema::TYPE_OBJECT,
+ 'x-join' => [
+ 'table' => 'glpi_plugin_datainjection_modelcsvs',
+ 'field' => 'models_id',
+ 'fkey' => 'id',
+ 'primary-property' => 'id',
+ ],
+ 'properties' => [
+ 'id' => [
+ 'type' => Doc\Schema::TYPE_INTEGER,
+ 'format' => Doc\Schema::FORMAT_INTEGER_INT64,
+ ],
+ 'model' => self::getDropdownTypeSchema(class: PluginDatainjectionModel::class, field: 'models_id'),
+ 'delimiter' => [
+ 'type' => Doc\Schema::TYPE_STRING,
+ ],
+ 'is_header_present' => [
+ 'type' => Doc\Schema::TYPE_BOOLEAN,
+ ],
+ ]
+ ]
+ ]
+ ]
+ ];
+ }
+
+ #[Route(path: '/Model', methods: ['GET'])]
+ #[Doc\Route(
+ description: 'List or search data injection models',
+ responses: [
+ ['schema' => 'DataInjectionModel[]']
+ ]
+ )]
+ public function getModels(Request $request): Response
+ {
+ $response = Search::searchBySchema($this->getKnownSchema('DataInjectionModel'), $request->getParameters());
+ $decoded = json_decode((string) $response->getBody(), true);
+ foreach ($decoded as &$model) {
+ // Keep only the id and name of the model
+ $model['csv_options']['model'] = [
+ 'id' => $model['csv_options']['model']['id'],
+ 'name' => $model['csv_options']['model']['name'],
+ ];
+ }
+ unset($model);
+ $response = $response->withBody(Utils::streamFor(json_encode($decoded)));
+ return $response;
+ }
+
+ #[Route(path: '/Model/{id}', methods: ['GET'])]
+ #[Doc\Route(
+ description: 'Get a data injection model',
+ responses: [
+ ['schema' => 'DataInjectionModel']
+ ]
+ )]
+ public function getModel(Request $request): Response
+ {
+ return Search::getOneBySchema($this->getKnownSchema('DataInjectionModel'), $request->getAttributes(), $request->getParameters());
+ }
+
+ #[Route(path: '/Model/{id}/Injection', methods: ['POST'])]
+ #[Doc\Route(
+ description: 'Inject data using the specified model',
+ parameters: [
+ [
+ 'name' => '_',
+ 'location' => Doc\Parameter::LOCATION_BODY,
+ 'schema' => [
+ 'type' => Doc\Schema::TYPE_OBJECT,
+ 'properties' => [
+ 'filename' => [
+ 'type' => Doc\Schema::TYPE_STRING,
+ 'format' => Doc\Schema::FORMAT_STRING_BINARY
+ ]
+ ]
+ ],
+ 'required' => false,
+ 'content_type' => 'multipart/form-data'
+ ],
+ ]
+ )]
+ public function inject(Request $request): Response
+ {
+ $model = new PluginDatainjectionModel();
+ if (!$model->getFromDB($request->getAttribute('id'))) {
+ return self::getNotFoundErrorResponse();
+ }
+
+ $results = [];
+ foreach ($request->getUploadedFiles() as $file) {
+ $options = [
+ 'file_encoding' => PluginDatainjectionBackend::ENCODING_AUTO,
+ 'from_api' => true,
+ 'original_filename' => $file['name'],
+ 'unique_filename' => $file['tmp_name'],
+ 'mode' => PluginDatainjectionModel::PROCESS,
+ 'delete_file' => true,
+ ];
+ $action_results = [];
+ $success = $model->processUploadedFile($options);
+ if (!$success) {
+ return new JSONResponse(
+ self::getErrorResponseBody(AbstractController::ERROR_GENERIC, 'Error processing file'),
+ 400
+ );
+ }
+ $engine = new PluginDatainjectionEngine($model, [], $_SESSION['glpiactive_entity'] ?? 0);
+ $first = true;
+ foreach ($model->injectionData->getData() as $id => $data) {
+ if ($first && $model->getSpecificModel()->isHeaderPresent()) {
+ $first = false;
+ } else {
+ $action_results[] = $engine->injectLine($data[0], $id);
+ }
+ }
+ $model->cleanData();
+ $results[] = [
+ 'filename' => $file['name'],
+ 'results' => $action_results
+ ];
+ }
+ return new JSONResponse($results);
+ }
+
+ #[Route(path: '/Itemtype', methods: ['GET'])]
+ #[Doc\Route(
+ description: 'List item types',
+ responses: [
+ ['schema' => 'string[]']
+ ]
+ )]
+ public function getItemtypes(Request $request): Response
+ {
+ return new JSONResponse(PluginDatainjectionInjectionType::getItemtypes());
+ }
+}
diff --git a/inc/backend.class.php b/inc/backend.class.php
index b68f4fdf..912953ef 100644
--- a/inc/backend.class.php
+++ b/inc/backend.class.php
@@ -71,6 +71,7 @@ static function getHeader(PluginDatainjectionData $injectionData, $header_presen
* Get the backend implementation by type
*
* @param $type
+ * @return PluginDatainjectionBackendInterface
**/
static function getInstance($type) {
diff --git a/inc/engine.class.php b/inc/engine.class.php
index 9a498658..a2081439 100644
--- a/inc/engine.class.php
+++ b/inc/engine.class.php
@@ -65,8 +65,8 @@ function __construct($model, $infos = [], $entity = 0) {
/**
* Inject one line of data
*
- * @param $line one line of data to import
- * @param $index the line number is the file
+ * @param string $line one line of data to import
+ * @param int $index the line number is the file
**/
function injectLine($line, $index) {
diff --git a/inc/model.class.php b/inc/model.class.php
index 041ff133..66d38876 100644
--- a/inc/model.class.php
+++ b/inc/model.class.php
@@ -932,7 +932,7 @@ function readUploadedFile($options = []) {
$file_encoding = (isset($options['file_encoding'])
?$options['file_encoding'] :PluginDatainjectionBackend::ENCODING_AUTO);
- $webservice = (isset($options['webservice'])?$options['webservice']:false);
+ $from_api = (isset($options['from_api'])?$options['from_api']:false);
$original_filename = (isset($options['original_filename'])?$options['original_filename']:false);
$unique_filename = (isset($options['unique_filename'])?$options['unique_filename']:false);
$injectionData = false;
@@ -942,7 +942,7 @@ function readUploadedFile($options = []) {
//Get model & model specific fields
$this->loadSpecificModel();
- if (!$webservice) {
+ if (!$from_api) {
//Get and store uploaded file
$original_filename = $_FILES['filename']['name'];
$temporary_uploaded_filename = $_FILES["filename"]["tmp_name"];
@@ -961,7 +961,7 @@ function readUploadedFile($options = []) {
if ($this->specific_model->checkFileName($original_filename)) {
$message = __('File format is wrong', 'datainjection');
$message .= "
".__('Extension csv required', 'datainjection');
- if (!$webservice) {
+ if (!$from_api) {
Session::addMessageAfterRedirect($message, true, ERROR, false);
}
//unlink($temporary_uniquefilename);
@@ -976,8 +976,8 @@ function readUploadedFile($options = []) {
$backend->setHeaderPresent($this->specific_model->fields['is_header_present']);
$backend->setDelimiter($this->specific_model->fields['delimiter']);
- if (!$webservice) {
- //Read n line from the CSV file if not webservice
+ if (!$from_api) {
+ //Read n line from the CSV file if not from API
$injectionData = $backend->read(20);
} else {
//Read the whole file
@@ -1029,19 +1029,7 @@ function processUploadedFile($options = []) {
$this->loadSpecificModel();
$response = $this->readUploadedFile($options);
if (!$this->injectionData) {
- if (!isset($options['webservice'])) {
- return false;
- }
- return PluginWebservicesMethodCommon::Error(
- $options['protocol'],
- WEBSERVICES_ERROR_FAILED,
- sprintf(
- __(
- 'Not data to import',
- 'datainjection'
- )
- )
- );
+ return false;
}
if ($mode == self::PROCESS) {
@@ -1055,15 +1043,8 @@ function processUploadedFile($options = []) {
if ($check['status']!= PluginDatainjectionCommonInjectionLib::SUCCESS) {
if ($mode == self::PROCESS) {
- if (!isset($options['webservice'])) {
- Session::addMessageAfterRedirect($check['error_message'], true, ERROR);
- return false;
- }
- return PluginWebservicesMethodCommon::Error(
- $options['protocol'],
- WEBSERVICES_ERROR_FAILED,
- $check['error_message']
- );
+ Session::addMessageAfterRedirect($check['error_message'], true, ERROR);
+ return false;
}
}
diff --git a/inc/webservice.class.php b/inc/webservice.class.php
deleted file mode 100644
index b1e5de1d..00000000
--- a/inc/webservice.class.php
+++ /dev/null
@@ -1,208 +0,0 @@
-.
- * -------------------------------------------------------------------------
- * @copyright Copyright (C) 2007-2023 by DataInjection plugin team.
- * @license GPLv2 https://www.gnu.org/licenses/gpl-2.0.html
- * @link https://github.com/pluginsGLPI/datainjection
- * -------------------------------------------------------------------------
- */
-
-class PluginDatainjectionWebservice
-{
-
-
- static function methodInject($params, $protocol) {
-
- if (isset($params['help'])) {
- return ['uri' => 'string,mandatory',
- 'base64' => 'string,optional',
- 'additional' => 'array,optional',
- 'models_id' => 'integer, mandatory',
- 'entities_id'=> 'integer,mandatory',
- 'mandatory' => 'array,optional',
- 'uri' => 'uri,mandatory',
- 'help' => 'bool,optional'];
- }
-
- $model = new PluginDatainjectionModel();
-
- //-----------------------------------------------------------------
- //-------------------------- Check parameters ---------------------
- //-----------------------------------------------------------------
- if (!isset($_SESSION['glpiID'])) {
- return PluginWebservicesMethodCommon::Error(
- $protocol,
- WEBSERVICES_ERROR_NOTAUTHENTICATED
- );
- }
-
- if (!isset($params['uri']) && !isset($params['base64'])) {
- return PluginWebservicesMethodCommon::Error(
- $protocol,
- WEBSERVICES_ERROR_MISSINGPARAMETER,
- '', 'uri or base64'
- );
- }
-
- if (!isset($params['models_id'])) {
- return PluginWebservicesMethodCommon::Error(
- $protocol,
- WEBSERVICES_ERROR_MISSINGPARAMETER,
- 'models_id'
- );
- }
- if (!$model->getFromDB($params['models_id'])) {
- return PluginWebservicesMethodCommon::Error(
- $protocol, WEBSERVICES_ERROR_NOTFOUND,
- __('Model unknown', 'datainjection')
- );
-
- }
- if (!$model->can($params['models_id'], READ)) {
- return PluginWebservicesMethodCommon::Error(
- $protocol, WEBSERVICES_ERROR_NOTALLOWED,
- __(
- 'You cannot access this model',
- 'datainjection'
- )
- );
- }
- if ($model->fields['step'] < PluginDatainjectionModel::READY_TO_USE_STEP) {
- return PluginWebservicesMethodCommon::Error(
- $protocol, WEBSERVICES_ERROR_NOTALLOWED,
- __(
- 'You cannot access this model',
- 'datainjection'
- )
- );
- }
-
- //Check entity
- if (!isset($params['entities_id'])) {
- return PluginWebservicesMethodCommon::Error(
- $protocol,
- WEBSERVICES_ERROR_MISSINGPARAMETER,
- 'entities_id'
- );
- }
- $entities_id = $params['entities_id'];
- if ($entities_id > 0) {
- $entity = new Entity();
- if (!$entity->getFromDB($entities_id)) {
- return PluginWebservicesMethodCommon::Error(
- $protocol, WEBSERVICES_ERROR_NOTFOUND,
- __('Entity unknown', 'datainjection')
- );
-
- }
- if (!Session::haveAccessToEntity($entities_id)) {
- return PluginWebservicesMethodCommon::Error(
- $protocol, WEBSERVICES_ERROR_NOTALLOWED,
- __(
- 'You cannot access this entity',
- 'datainjection'
- )
- );
- }
- }
-
- //Mandatory fields
- $additional_infos = [];
- if (isset($params['additional']) && is_array($params['additional'])) {
- $additional_infos = $params['additional'];
- }
-
- //Upload CSV file
- $document_name = basename($params['uri']);
- $filename = tempnam(PLUGIN_DATAINJECTION_UPLOAD_DIR, 'PWS');
- $response = PluginWebservicesMethodCommon::uploadDocument(
- $params, $protocol, $filename,
- $document_name
- );
-
- if (PluginWebservicesMethodCommon::isError($protocol, $response)) {
- return $response;
- }
-
- //Uploade successful : now perform import !
- $options = ['file_encoding' => PluginDatainjectionBackend::ENCODING_AUTO, //Detect automatically file encoding
- 'webservice' => true, //Use webservice CSV file import
- 'original_filename' => $params['uri'], //URI to the CSV file
- 'unique_filename' => $filename, //Unique filename
- 'mode' => PluginDatainjectionModel::PROCESS,
- 'delete_file' => false, //Do not delete file once imported
- 'protocol' => $protocol]; //The Webservice protocol used
-
- $results = [];
- $response = $model->processUploadedFile($options);
- if (!PluginWebservicesMethodCommon::isError($protocol, $response)) {
- $engine = new PluginDatainjectionEngine(
- $model,
- $additional_infos,
- $params['entities_id']
- );
- //Remove first line if header is present
- $first = true;
- foreach ($model->injectionData->getData() as $id => $data) {
- if ($first && $model->getSpecificModel()->isHeaderPresent()) {
- $first = false;
- } else {
- $results[] = $engine->injectLine($data[0], $id);
- }
- }
- $model->cleanData();
- return $results;
- }
- return $response;
- }
-
-
- static function methodGetModel($params, $protocol) {
-
- $params['itemtype'] = 'PluginDatainjectionModel';
- return PluginWebservicesMethodInventaire::methodGetObject($params, $protocol);
- }
-
-
- static function methodListModels($params, $protocol) {
-
- $params['itemtype'] = 'PluginDatainjectionModel';
- return PluginWebservicesMethodInventaire::methodListObjects($params, $protocol);
- }
-
-
- static function methodListItemtypes($params, $protocol) {
-
- if (isset($params['help'])) {
- return ['help' => 'bool,optional'];
- }
-
- if (!isset($_SESSION['glpiID'])) {
- return self::Error($protocol, WEBSERVICES_ERROR_NOTAUTHENTICATED);
- }
-
- return PluginDatainjectionInjectionType::getItemtypes();
- }
-
-}
diff --git a/setup.php b/setup.php
index 6f0f6ed6..69f472e0 100644
--- a/setup.php
+++ b/setup.php
@@ -79,11 +79,11 @@ function plugin_init_datainjection() {
// Javascript file
$PLUGIN_HOOKS['add_javascript']['datainjection'] = 'js/datainjection.js';
+ $PLUGIN_HOOKS[\Glpi\Plugin\Hooks::API_CONTROLLERS]['datainjection'] = [
+ PluginDatainjectionApiController::class
+ ];
- // Inbtegration with Webservices plugin
- $PLUGIN_HOOKS['webservices']['datainjection'] = 'plugin_datainjection_registerMethods';
$INJECTABLE_TYPES = [];
-
}
}
diff --git a/testwebservice.php b/testwebservice.php
deleted file mode 100644
index d03bb2c2..00000000
--- a/testwebservice.php
+++ /dev/null
@@ -1,125 +0,0 @@
-.
- * -------------------------------------------------------------------------
- * @copyright Copyright (C) 2007-2023 by DataInjection plugin team.
- * @license GPLv2 https://www.gnu.org/licenses/gpl-2.0.html
- * @link https://github.com/pluginsGLPI/datainjection
- * -------------------------------------------------------------------------
- */
-
-if (!extension_loaded("xmlrpc")) {
- die("Extension xmlrpc not loaded\n");
-}
-
-chdir(dirname($_SERVER["SCRIPT_FILENAME"]));
-chdir("../../..");
-$url = "/".basename(getcwd()).Plugin::getWebDir('webservices', false)."/xmlrpc.php";
-
-$args = [];
-if ($_SERVER['argc'] > 1) {
- for ($i=1; $i [
- 'method' => "POST",
- 'header' => $header,
- 'content' => $request
- ]
- ]
- );
-
- $file = file_get_contents("http://".$params['host']."/".$params['url'], false, $context);
- if (!$file) {
- die("+ No response\n");
- }
-
- $response = xmlrpc_decode($file);
- if (!is_array($response)) {
- echo $file;
- die ("+ Bad response\n");
- }
-
- if (xmlrpc_is_fault($response)) {
- echo("xmlrpc error(".$response['faultCode']."): ".$response['faultString']."\n");
- return false;
- }
- return $response;
-}