Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HL API Integration #374

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 0 additions & 15 deletions hook.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
227 changes: 227 additions & 0 deletions inc/apicontroller.class.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
<?php

/**
* -------------------------------------------------------------------------
* DataInjection plugin for GLPI
* -------------------------------------------------------------------------
*
* LICENSE
*
* This file is part of DataInjection.
*
* DataInjection is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* DataInjection is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DataInjection. If not, see <http://www.gnu.org/licenses/>.
* -------------------------------------------------------------------------
* @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());
}
}
1 change: 1 addition & 0 deletions inc/backend.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -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) {

Expand Down
4 changes: 2 additions & 2 deletions inc/engine.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -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) {

Expand Down
35 changes: 8 additions & 27 deletions inc/model.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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"];
Expand All @@ -961,7 +961,7 @@ function readUploadedFile($options = []) {
if ($this->specific_model->checkFileName($original_filename)) {
$message = __('File format is wrong', 'datainjection');
$message .= "<br>".__('Extension csv required', 'datainjection');
if (!$webservice) {
if (!$from_api) {
Session::addMessageAfterRedirect($message, true, ERROR, false);
}
//unlink($temporary_uniquefilename);
Expand All @@ -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
Expand Down Expand Up @@ -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) {
Expand All @@ -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;
}
}

Expand Down
Loading