openstamanager/lib/classes/API.php

229 lines
6.7 KiB
PHP

<?php
/**
* Classe per la gestione delle API del progetto.
*
* @since 2.3
*/
class API extends \Util\Singleton
{
protected static $resources;
protected static $status = [
'ok' => [
'code' => 200,
'message' => 'OK',
],
'internalError' => [
'code' => 400,
'message' => "Errore interno dell'API",
],
'unauthorized' => [
'code' => 401,
'message' => 'Non autorizzato',
],
'notFound' => [
'code' => 404,
'message' => 'Non trovato',
],
'serverError' => [
'code' => 500,
'message' => 'Errore del server',
],
];
public function __construct($token)
{
$user = Auth::user();
if (!self::isAPIRequest() || empty($user)) {
throw new InvalidArgumentException();
}
}
public function retrieve($resource)
{
$table = '';
$select = '*';
// Selezione personalizzata
$display = filter('display');
$select = !empty($display) ? explode(',', substr($display, 1, -1)) : $select;
$where = [];
// Ricerca personalizzata
$filter = (array) filter('filter');
foreach ($filter as $key => $value) {
$value = substr($value, 1, -1);
$result = [];
if (str_contains($value, ',')) {
$or = [];
$temp = explode(',', $value);
foreach ($temp as $value) {
$or[] = [$key => $value];
}
$result[] = ['OR' => $or];
} else {
$result[$key] = $value;
}
$where[] = $result;
}
$order = [];
// Ordinamento personalizzato
$order_request = (array) filter('order');
foreach ($order_request as $value) {
$pieces = explode('|', $value);
$order[] = empty($pieces[1]) ? $pieces[0] : [$pieces[0] => $pieces[1]];
}
// Date di interesse
$updated = filter('upd');
$created = filter('crd');
$dbo = Database::getConnection();
$kind = 'retrieve';
$resources = self::getResources()[$kind];
if (!in_array($resource, $resources)) {
$excluded = explode(',', Settings::get('Tabelle escluse per la sincronizzazione API automatica'));
if (!in_array($resource, $excluded)) {
$table = $resource;
if (empty($order)) {
$order[] = $dbo->fetchArray('SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '.prepare($table)." AND EXTRA LIKE '%AUTO_INCREMENT%' AND TABLE_SCHEMA = ".prepare($dbo->getDatabaseName()))[0]['COLUMN_NAME'];
}
}
} else {
$filename = DOCROOT.'/modules/'.$resources[$resource].'/api/'.$kind.'.php';
include $filename;
}
// Paginazione dell'API
$page = (int) filter('page') ?: 0;
$length = Settings::get('Lunghezza pagine per API');
// Generazione automatica delle query
if (empty($results) && !empty($table)) {
try {
// Query per ottenere le informazioni
$results = $dbo->select($table, $select, $where, $order, [$page * $length, $length]);
// Informazioni aggiuntive
$query = $dbo->select($table, $select, $where, $order, [], true);
$cont = $dbo->fetchArray('SELECT COUNT(*) as `records`, CEIL(COUNT(*) / '.$length.') as `pages` FROM ('.$query.') AS `count`');
if (!empty($cont)) {
$results['records'] = $cont[0]['records'];
$results['pages'] = $cont[0]['pages'];
}
} catch (PDOException $e) {
return self::error('internalError');
}
}
return self::response($results);
}
public function create($resource)
{
return $this->fileRequest($resource, 'create');
}
public function update($resource)
{
return $this->fileRequest($resource, 'generate');
}
public function delete($resource)
{
return $this->fileRequest($resource, 'delete');
}
protected function fileRequest($resource, $kind)
{
$resources = self::getResources()[$kind];
if (!in_array($resource, $resources)) {
return self::error('notFound');
}
$dbo = Database::getConnection();
$filename = DOCROOT.'/modules/'.$resources[$resource].'/api/'.$kind.'.php';
include $filename;
return self::response($results);
}
public static function error($error)
{
$keys = array_keys(self::$status);
$error = (in_array($error, $keys)) ? $error : end($keys);
return self::response([
'status' => self::$status[$error]['code'],
'message' => self::$status[$error]['message'],
]);
}
public static function getResources()
{
if (!is_array(self::$resources)) {
$resources = [];
$operations = glob(DOCROOT.'/modules/*/api/{retrieve,create,update,delete}.php', GLOB_BRACE);
if (!empty($operations)) {
foreach ($operations as $operation) {
$module = basename(dirname(dirname($operation)));
$kind = basename($operation, '.php');
$temp = str_replace('/api/', '/custom/api/', $operation);
$operation = file_exists($temp) ? $temp : $operation;
$api = include $operation;
$api = array_unique($api);
$keys = array_keys($resources[$kind]);
$results = [];
foreach ($api as $value) {
$value .= in_array($value, $keys) ? $module : '';
$results[$value] = $module;
}
$resources[$kind] = array_merge((array) $resources[$kind], $results);
}
}
self::$resources = $resources;
}
return self::$resources;
}
public static function response($array)
{
if (empty($array['status'])) {
$array['status'] = self::$status['ok']['code'];
$array['message'] = self::$status['ok']['message'];
}
$flags = JSON_FORCE_OBJECT;
if (filter('beautify') !== null) {
$flags |= JSON_PRETTY_PRINT;
}
return json_encode($array, $flags);
}
public static function isAPIRequest()
{
return slashes($_SERVER['SCRIPT_FILENAME']) == slashes(DOCROOT.'/api/index.php');
}
}