Skip to content
This repository has been archived by the owner on Nov 16, 2022. It is now read-only.

Commit

Permalink
fix(glpi): manage pagination in object lists (#131)
Browse files Browse the repository at this point in the history
Refs: MON-6258

Co-authored-by: Tanguy Charles <tcharles@centreon.com>
  • Loading branch information
kduret and tanguyvda committed Nov 19, 2020
1 parent 70221ce commit a2cac15
Showing 1 changed file with 56 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ class GlpiRestApiProvider extends AbstractProvider {
const ARG_USER_ROLE = 12;
const ARG_REQUESTER = 13;

private const PAGE_SIZE = 20;

protected $_internal_arg_name = array(
self::ARG_CONTENT => 'content',
self::ARG_ENTITY => 'entity',
Expand Down Expand Up @@ -713,7 +715,7 @@ protected function assignGlpiGroups($entry, &$groups_order, &$groups) {

// try to get groups
try {
// $listGroups = $this->getCache($entry['Id']);
$listGroups = $this->getCache($entry['Id']);
if (is_null($listGroups)) {
$listGroups = $this->getGroups();
$this->setCache($entry['Id'], $listGroups, 8 * 3600);
Expand Down Expand Up @@ -1015,19 +1017,24 @@ protected function initSession() {
* handle every query that we need to do
*
* @param {array} $info required information to reach the glpi api
* @param int|null $offset pagination offset
*
* @return {array} $curlResult the json decoded data gathered from glpi
*
* throw \Exception 10 if php-curl is not installed
* throw \Exception if we can't get a session token
* throw \Exception 11 if glpi api fails
*/
protected function curlQuery($info) {
protected function curlQuery($info, int $offset = null) {
// check if php curl is installed
if (!extension_loaded("curl")) {
throw new \Exception("couldn't find php curl", 10);
}

if ($offset !== null && $offset < 0) {
throw new \InvalidArgumentException('offset must be positive');
}

// if we aren't trying to initiate the session, we try to get the session token from the cache
if ($info['query_endpoint'] != '/initSession') {
$sessionToken = $this->getCache('session_token');
Expand All @@ -1040,7 +1047,7 @@ protected function curlQuery($info) {
} catch (\Exception $e) {
throw new \Exception($e->getMessage(), $e->getCode());
}
} else {
} elseif (!preg_grep('/^Session-Token\:/', $info['headers'])) {
array_push($info['headers'], 'Session-Token: ' . $sessionToken);
}
}
Expand All @@ -1050,6 +1057,11 @@ protected function curlQuery($info) {
$apiAddress = $this->_getFormValue('protocol') . '://' . $this->_getFormValue('address') .
$this->_getFormValue('api_path') . $info['query_endpoint'];

if ($offset !== null) {
$apiAddress .= preg_match('/.+\?/', $apiAddress) ? '&' : '?';
$apiAddress .= 'range=' . $offset . '-' . ($offset + self::PAGE_SIZE);
}

// initiate our curl options
curl_setopt($curl, CURLOPT_URL, $apiAddress);
curl_setopt($curl, CURLOPT_HTTPHEADER, $info['headers']);
Expand All @@ -1076,21 +1088,52 @@ protected function curlQuery($info) {
}
}

// parse headers to manage pagination
if ($offset !== null) {
$curlHeaders = [];
curl_setopt($curl, CURLOPT_HEADERFUNCTION, function ($curlResource, $curlHeader) use (&$curlHeaders) {
$length = strlen($curlHeader);
$curlHeader = explode(':', $curlHeader, 2);

if (count($curlHeader) < 2) {
return $length;
}

$curlHeaders[strtolower(trim($curlHeader[0]))][] = trim($curlHeader[1]);

return $length;
});
}

// execute curl and get status information
$curlResult = json_decode(curl_exec($curl), true);
$httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);

// if http is 401 and message is about token, perhaps the token has expired, so we get a new one
if ($httpCode == 401 && $curlResult[0] == 'ERROR_SESSION_TOKEN_INVALID') {
if ($httpCode === 206 && $offset !== null) {
// If partial content, get next page
if (preg_match('/\/(\d+)/', $curlHeaders['content-range'][0], $matches)) {
$total = $matches[1];

$offset = $offset + self::PAGE_SIZE;

if ($offset <= $total) {
$curlResult = array_merge_recursive(
$curlResult,
$this->curlQuery($info, $offset)
);
}
}
} elseif ($httpCode == 401 && $curlResult[0] == 'ERROR_SESSION_TOKEN_INVALID') {
// if http is 401 and message is about token, perhaps the token has expired, so we get a new one
try {
$this->initSession();
$this->curlQuery($info);
$this->curlQuery($info, $offset);
} catch (\Exception $e) {
throw new \Exception($e->getMessage(), $e->getCode());
}
// for any other issue, we throw an exception
} elseif ($httpCode >= 400) {
// for any other issue, we throw an exception
throw new Exception('ENDPOINT: ' . $apiAddress . ' || GLPI ERROR : ' . $curlResult[0] .
' || GLPI MESSAGE: ' . $curlResult[1] . ' || HTTP ERROR: ' . $httpCode, 11);
}
Expand All @@ -1107,7 +1150,7 @@ protected function curlQuery($info) {
*/
protected function getEntities() {
// add the api endpoint and method to our info array
$info['query_endpoint'] = '/getMyEntities/?is_recursive=1';
$info['query_endpoint'] = '/getMyEntities?is_recursive=1';
$info['method'] = 0;
// set headers
$info['headers'] = array(
Expand All @@ -1117,7 +1160,7 @@ protected function getEntities() {
// try to get entities from Glpi
try {
// the variable is going to be used outside of this method.
$this->glpiCallResult['response'] = $this->curlQuery($info);
$this->glpiCallResult['response'] = $this->curlQuery($info, 0);
} catch (\Exception $e) {
throw new \Exception($e->getMessage(), $e->getCode());
}
Expand Down Expand Up @@ -1181,7 +1224,7 @@ protected function getGroups() {
// try to get groups from Glpi
try {
// the variable is going to be used outside of this method.
$this->glpiCallResult['response'] = $this->curlQuery($info);
$this->glpiCallResult['response'] = $this->curlQuery($info, 0);
} catch (\Exception $e) {
throw new \Exception($e->getMessage(), $e->getCode());
}
Expand All @@ -1208,7 +1251,7 @@ protected function getSuppliers() {
// try to get suppliers from Glpi
try {
// the variable is going to be used outside of this method.
$this->glpiCallResult['response'] = $this->curlQuery($info);
$this->glpiCallResult['response'] = $this->curlQuery($info, 0);
} catch (\Exception $e) {
throw new \Exception($e->getMessage(), $e->getCode());
}
Expand All @@ -1235,7 +1278,7 @@ protected function getItilCategories() {
// try to get itil categories from Glpi
try {
// the variable is going to be used outside of this method.
$this->glpiCallResult['response'] = $this->curlQuery($info);
$this->glpiCallResult['response'] = $this->curlQuery($info, 0);
} catch (\Exception $e) {
throw new \Exception($e->getMessage(), $e->getCode());
}
Expand All @@ -1262,7 +1305,7 @@ protected function getUsers() {
// try to get users from Glpi
try {
// the variable is going to be used outside of this method.
$this->glpiCallResult['response'] = $this->curlQuery($info);
$this->glpiCallResult['response'] = $this->curlQuery($info, 0);
} catch (\Exception $e) {
throw new \Exception($e->getMessage(), $e->getCode());
}
Expand Down

0 comments on commit a2cac15

Please sign in to comment.