Aggiornamento API

This commit is contained in:
Thomas Zilio 2019-07-19 15:23:00 +02:00
parent 1dbaf0bed5
commit 7b589c530c
58 changed files with 1366 additions and 1202 deletions

View File

@ -5,7 +5,7 @@ function serverError()
$error = error_get_last();
if ($error['type'] == E_ERROR) {
ob_end_clean();
echo API::error('serverError');
echo Response::error('serverError');
}
}
@ -22,61 +22,21 @@ session_write_close();
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, PUT, DELETE, OPTIONS');
// Attenzione: al momento l'API permette la lettura di tutte le tabelle presenti nel database (non limitate a quelle del progetto)
use API\Response;
try {
// Controlli sulla chiave di accesso
$api = new API();
// Lettura delle informazioni
$request = API::getRequest();
// Gestione della richiesta
$method = $_SERVER['REQUEST_METHOD'];
switch ($method) {
// Richiesta PUT (modifica elementi)
case 'PUT':
$response = $api->update($request);
break;
// Richiesta POST (creazione elementi)
case 'POST':
$response = $api->create($request);
break;
// Richiesta GET (ottenimento elementi)
case 'GET':
// Risorsa specificata
if (count($request) > 1) {
$response = $api->retrieve($request);
}
// Risorsa non specificata (lista delle risorse disponibili)
else {
$response = API::response([
'resources' => array_keys(API::getResources()['retrieve']),
]);
}
break;
// Richiesta DELETE (eliminazione elementi)
case 'DELETE':
$response = $api->delete($request);
break;
}
} catch (InvalidArgumentException $e) {
$response = API::error('unauthorized');
$response = Response::manage();
} catch (Exception $e) {
// Log dell'errore
$logger = logger();
$logger->addRecord(\Monolog\Logger::ERROR, $e);
$response = API::error('serverError');
$response = Response::error('serverError');
}
// Richiesta OPTIONS (controllo da parte del dispositivo)
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
$response = API::error('ok');
$response = Response::error('ok');
}
json_decode($response);

View File

@ -17,6 +17,12 @@ return [
'modules/interventi' => 'Modules\Interventi',
'modules/pagamenti' => 'Modules\Pagamenti',
'modules/statistiche' => 'Modules\Statistiche',
'modules/utenti' => 'Modules\Utenti',
'modules/stato_servizi' => 'Modules\StatoServizi',
'modules/stati_intervento' => 'Modules\StatiIntervento',
'modules/stati_preventivo' => 'Modules\StatiPreventivo',
'modules/stati_contratto' => 'Modules\StatiContratto',
'modules/stato_servizi' => 'Modules\StatoServizi',
'modules/tipi_intervento' => 'Modules\TipiIntervento',
'plugins/exportFE' => 'Plugins\ExportFE',
'plugins/importFE' => 'Plugins\ImportFE',

View File

@ -28,6 +28,9 @@ $namespaces = require_once __DIR__.'/config/namespaces.php';
foreach ($namespaces as $path => $namespace) {
$loader->addPsr4($namespace.'\\', __DIR__.'/'.$path.'/custom/src');
$loader->addPsr4($namespace.'\\', __DIR__.'/'.$path.'/src');
$loader->addPsr4($namespace.'\\API\\', __DIR__.'/'.$path.'/custom/api');
$loader->addPsr4($namespace.'\\API\\', __DIR__.'/'.$path.'/api');
}
// Individuazione dei percorsi di base
@ -60,7 +63,7 @@ use Monolog\Handler\RotatingFileHandler;
use Monolog\Handler\StreamHandler;
$handlers = [];
if (!API::isAPIRequest()) {
if (!API\Response::isAPIRequest()) {
// File di log di base (logs/error.log, logs/setup.log)
$handlers[] = new StreamHandler($docroot.'/logs/error.log', Monolog\Logger::ERROR);
$handlers[] = new StreamHandler($docroot.'/logs/setup.log', Monolog\Logger::EMERGENCY);
@ -124,7 +127,7 @@ Monolog\ErrorHandler::register($logger, [], Monolog\Logger::ERROR, Monolog\Logge
$dbo = $database = database();
/* SESSIONE */
if (!API::isAPIRequest()) {
if (!API\Response::isAPIRequest()) {
// Sicurezza della sessioni
ini_set('session.use_trans_sid', '0');
ini_set('session.use_only_cookies', '1');
@ -162,7 +165,7 @@ $revision = Update::getRevision();
/* ACCESSO E INSTALLAZIONE */
// Controllo sulla presenza dei permessi di accesso basilari
$continue = $dbo->isInstalled() && !Update::isUpdateAvailable() && (Auth::check() || API::isAPIRequest());
$continue = $dbo->isInstalled() && !Update::isUpdateAvailable() && (Auth::check() || API\Response::isAPIRequest());
if (!empty($skip_permissions)) {
Permissions::skip();
@ -179,7 +182,7 @@ if (!$continue && getURLPath() != slashes(ROOTDIR.'/index.php') && !Permissions:
/* INIZIALIZZAZIONE GENERALE */
// Operazione aggiuntive (richieste non API)
if (!API::isAPIRequest()) {
if (!API\Response::isAPIRequest()) {
// Impostazioni di Content-Type e Charset Header
header('Content-Type: text/html; charset=UTF-8');

View File

@ -1,64 +0,0 @@
<?php
switch ($resource) {
case 'updates':
$custom_where = !empty($updated) ? ' WHERE updated_at >= '.prepare($updated) : '';
$excluded = explode(',', setting('Tabelle escluse per la sincronizzazione API automatica'));
// Attenzione: query specifica per MySQL
$datas = $dbo->fetchArray("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_SCHEMA=".prepare($db_name));
if (!empty($datas)) {
foreach ($datas as $data) {
if (!in_array($data['TABLE_NAME'], $excluded)) {
$response[$data['TABLE_NAME']] = $dbo->fetchArray('SELECT * FROM '.$data['TABLE_NAME'].$custom_where);
}
}
}
break;
// Attualmente vengono considerate solo le tabelle che eseguono l'eliminazione fisica della riga
case 'deleted':
$excluded = explode(',', setting('Tabelle escluse per la sincronizzazione API automatica'));
// Attenzione: query specifica per MySQL
$datas = $dbo->fetchArray("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_SCHEMA=".prepare($db_name));
if (!empty($datas)) {
foreach ($datas as $data) {
$table_name = $data['TABLE_NAME'];
// Ottiene il nome della colonna di tipo AUTO_INCREMENT della tabella
$column = $dbo->fetchArray('SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '.prepare($table_name)." AND EXTRA LIKE '%AUTO_INCREMENT%' AND TABLE_SCHEMA = ".prepare($db_name))[0]['COLUMN_NAME'];
if (!in_array($table_name, $excluded) && !empty($column)) {
// Ottiene il valore successivo della colonna di tipo AUTO_INCREMENT
$auto_inc = $dbo->fetchArray('SELECT AUTO_INCREMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '.prepare($table_name).' AND TABLE_SCHEMA = '.prepare($db_name))[0]['AUTO_INCREMENT'];
// Ottiene i vuoti all'interno della sequenza AUTO_INCREMENT
$steps = $dbo->fetchArray('SELECT (t1.'.$column.' + 1) as start, (SELECT MIN(t3.'.$column.') - 1 FROM '.$table_name.' t3 WHERE t3.'.$column.' > t1.'.$column.') as end FROM '.$table_name.' t1 WHERE NOT EXISTS (SELECT t2.'.$column.' FROM '.$table_name.' t2 WHERE t2.'.$column.' = t1.'.$column.' + 1) ORDER BY start');
$total = [];
foreach ($steps as $step) {
if ($step['end'] == null) {
$step['end'] = $auto_inc - 1;
}
if ($step['end'] >= $step['start']) {
$total = array_merge($total, range($step['start'], $step['end']));
}
}
$response[$table_name] = $total;
}
}
}
break;
}
/*
return [
'updates',
'deleted',
];
*/

View File

@ -1,22 +0,0 @@
<?php
switch ($resource) {
case 'add_anagrafica':
$rs = $dbo->fetchArray('SELECT codice FROM an_anagrafiche ORDER BY CAST(codice AS SIGNED) DESC LIMIT 0, 1');
$codice = Util\Generator::generate(setting('Formato codice anagrafica'), $rs[0]['codice']);
// Inserisco l'anagrafica
$dbo->insert('an_anagrafiche', [
'ragione_sociale' => $request['data']['ragione_sociale'],
'codice' => $codice,
]);
// Inserisco il rapporto dell'anagrafica (cliente, tecnico, ecc)
$dbo->sync('an_tipianagrafiche_anagrafiche', ['idanagrafica' => $dbo->lastInsertedID()], ['idtipoanagrafica' => (array) $request['data']['tipi']]);
break;
}
return [
'add_anagrafica',
];

View File

@ -1,20 +0,0 @@
<?php
switch ($resource) {
case 'delete_anagrafica':
$id_azienda = $dbo->fetchArray("SELECT idtipoanagrafica FROM an_tipianagrafiche WHERE descrizione='Azienda'")[0]['idtipoanagrafica'];
$anagrafica = $dbo->fetchArray('SELECT an_tipianagrafiche.idtipoanagrafica FROM an_tipianagrafiche INNER JOIN an_tipianagrafiche_anagrafiche ON an_tipianagrafiche.idtipoanagrafica=an_tipianagrafiche_anagrafiche.idtipoanagrafica WHERE idanagrafica='.prepare($request['id']));
$tipi = array_column($anagrafica, 'idtipoanagrafica');
// Se l'anagrafica non è l'azienda principale, la disattivo
if (!in_array($id_azienda, $tipi)) {
$dbo->query('UPDATE an_anagrafiche SET deleted_at = NOW() WHERE idanagrafica = '.prepare($request['id']));
}
break;
}
return [
'delete_anagrafica',
];

View File

@ -1,63 +0,0 @@
<?php
switch ($resource) {
case 'an_anagrafiche':
$table = 'an_anagrafiche';
if (empty($order)) {
$order[] = 'idanagrafica';
}
if (empty($where['deleted_at'])) {
$where['deleted_at'] = null;
}
break;
// Elenco clienti per l'applicazione
case 'clienti':
$query = "SELECT an_anagrafiche.idanagrafica AS id,
an_anagrafiche.ragione_sociale,
an_anagrafiche.piva,
an_anagrafiche.codice_fiscale,
an_anagrafiche.indirizzo,
an_anagrafiche.indirizzo2,
an_anagrafiche.citta,
an_anagrafiche.cap,
an_anagrafiche.provincia,
an_anagrafiche.km,
IFNULL(an_anagrafiche.lat, 0.00) AS latitudine,
IFNULL(an_anagrafiche.lng, 0.00) AS longitudine,
an_nazioni.nome AS nazione,
an_anagrafiche.telefono,
an_anagrafiche.fax,
an_anagrafiche.cellulare,
an_anagrafiche.email,
an_anagrafiche.sitoweb,
an_anagrafiche.note,
an_anagrafiche.idzona,
an_anagrafiche.deleted_at
FROM an_anagrafiche
LEFT OUTER JOIN an_nazioni ON an_anagrafiche.id_nazione=an_nazioni.id
WHERE
an_anagrafiche.deleted_at IS NULL AND
an_anagrafiche.idanagrafica IN (SELECT idanagrafica FROM an_tipianagrafiche_anagrafiche WHERE idtipoanagrafica = (SELECT idtipoanagrafica FROM an_tipianagrafiche WHERE descrizione = 'Cliente'))
ORDER BY an_anagrafiche.ragione_sociale";
break;
// Elenco sedi per l'applicazione
case 'sedi':
$table = 'an_sedi';
if (empty($order)) {
$order[] = 'id';
}
break;
}
return [
'an_anagrafiche',
'clienti',
'sedi',
];

View File

@ -1,28 +0,0 @@
<?php
switch ($resource) {
case 'update_anagrafica':
// Inserisco l'anagrafica
$dbo->update('an_anagrafiche', [
'ragione_sociale' => $request['data']['ragione_sociale'],
'piva' => $request['data']['piva'],
'codice_fiscale' => $request['data']['codice_fiscale'],
'indirizzo' => $request['data']['indirizzo'],
'citta' => $request['data']['citta'],
'provincia' => $request['data']['provincia'],
'id_nazione' => $request['data']['id_nazione'],
'telefono' => $request['data']['telefono'],
'fax' => $request['data']['fax'],
'cellulare' => $request['data']['cellulare'],
'email' => $request['data']['email'],
], ['idanagrafica' => $request['id']]);
// Inserisco il rapporto dell'anagrafica (cliente, tecnico, ecc)
$dbo->sync('an_tipianagrafiche_anagrafiche', ['idanagrafica' => $request['id']], ['idtipoanagrafica' => (array) $request['data']['tipi']]);
break;
}
return [
'update_anagrafica',
];

View File

@ -0,0 +1,106 @@
<?php
namespace Modules\Anagrafiche\API\v1;
use API\Interfaces\CreateInterface;
use API\Interfaces\DeleteInterface;
use API\Interfaces\RetrieveInterface;
use API\Interfaces\UpdateInterface;
use Modules;
use Modules\Anagrafiche\Anagrafica;
class Anagrafiche implements RetrieveInterface, CreateInterface, UpdateInterface, DeleteInterface
{
public function retrieve($request)
{
$query = 'SELECT an_anagrafiche.idanagrafica AS id,
an_anagrafiche.ragione_sociale,
an_anagrafiche.piva,
an_anagrafiche.codice_fiscale,
an_anagrafiche.indirizzo,
an_anagrafiche.indirizzo2,
an_anagrafiche.citta,
an_anagrafiche.cap,
an_anagrafiche.provincia,
an_anagrafiche.km,
IFNULL(an_anagrafiche.lat, 0.00) AS latitudine,
IFNULL(an_anagrafiche.lng, 0.00) AS longitudine,
an_nazioni.nome AS nazione,
an_anagrafiche.telefono,
an_anagrafiche.fax,
an_anagrafiche.cellulare,
an_anagrafiche.email,
an_anagrafiche.sitoweb,
an_anagrafiche.note,
an_anagrafiche.idzona,
an_anagrafiche.deleted_at
FROM an_anagrafiche
LEFT OUTER JOIN an_nazioni ON an_anagrafiche.id_nazione=an_nazioni.id
WHERE
1=1 AND an_anagrafiche.deleted_at IS NULL';
$types = $request['filter']['type'];
$types = explode(',', $types);
$types = array_clean($types);
$filters = [];
foreach ($types as $type) {
$filters[] = 'an_anagrafiche.idanagrafica IN (SELECT idanagrafica FROM an_tipianagrafiche_anagrafiche WHERE idtipoanagrafica = (SELECT idtipoanagrafica FROM an_tipianagrafiche WHERE descrizione = '.prepare($type).'))';
}
$query .= !empty($filters) ? ' AND ('.implode('OR ', $filters).')' : '';
$query .= '
HAVING 2=2
ORDER BY an_anagrafiche.ragione_sociale';
$module = Modules::get('Anagrafiche');
$query = Modules::replaceAdditionals($module->id, $query);
return [
'query' => $query,
];
}
public function create($request)
{
$ragione_sociale = $request['data']['ragione_sociale'];
$id_tipo = (array) $request['data']['tipi'];
$anagrafica = Anagrafica::build($ragione_sociale, null, null, $id_tipo);
$id_record = $anagrafica->id;
return [
'id' => $id_record,
];
}
public function delete($request)
{
$anagrafica = Anagrafica::find($request['id']);
$result = $anagrafica->delete();
}
public function update($request)
{
$data = $request['data'];
$anagrafica = Anagrafica::find($request['id']);
$anagrafica->ragione_sociale = $data['ragione_sociale'];
$anagrafica->piva = $data['piva'];
$anagrafica->codice_fiscale = $data['codice_fiscale'];
$anagrafica->indirizzo = $data['indirizzo'];
$anagrafica->citta = $data['citta'];
$anagrafica->provincia = $data['provincia'];
$anagrafica->id_nazione = $data['id_nazione'];
$anagrafica->telefono = $data['telefono'];
$anagrafica->fax = $data['fax'];
$anagrafica->cellulare = $data['cellulare'];
$anagrafica->email = $data['email'];
$anagrafica->tipologie = (array) $data['tipi'];
$anagrafica->save();
}
}

View File

@ -261,6 +261,13 @@ class Anagrafica extends Model
return $this;
}
public function delete()
{
if (!$this->isAzienda()) {
return parent::delete();
}
}
// Metodi statici
/**

View File

@ -1,12 +0,0 @@
<?php
switch ($resource) {
case 'articoli':
$query = 'SELECT *, (SELECT nome FROM mg_categorie WHERE id = mg_articoli.id_categoria) AS categoria, (SELECT nome FROM mg_categorie WHERE id = mg_articoli.id_sottocategoria) AS sottocategoria FROM mg_articoli WHERE attivo = 1';
break;
}
return [
'articoli',
];

View File

@ -0,0 +1,20 @@
<?php
namespace Modules\Articoli\API\v1;
use API\Interfaces\RetrieveInterface;
class Articoli implements RetrieveInterface
{
public function retrieve($request)
{
$query = 'SELECT *,
(SELECT nome FROM mg_categorie WHERE id = mg_articoli.id_categoria) AS categoria,
(SELECT nome FROM mg_categorie WHERE id = mg_articoli.id_sottocategoria) AS sottocategoria
FROM mg_articoli WHERE attivo = 1';
return [
'query' => $query,
];
}
}

View File

@ -1,17 +1,17 @@
<?php
namespace Modules\Articoli\API\v1;
use API\Interfaces\CreateInterface;
use Modules\Articoli\Articolo;
switch ($resource) {
case 'movimento_articolo':
class Movimenti implements CreateInterface
{
public function create($request)
{
$data = $request['data'];
$articolo = Articolo::find($data['id_articolo']);
$articolo->movimenta($data['qta'], $data['descrizione'], $data['data'], true);
break;
}
return [
'movimento_articolo',
];
}

View File

@ -126,7 +126,7 @@ if (empty($record['is_fiscale'])) {
<?php
if ($dir == 'entrata') {
?>
{[ "type": "select", "label": "<?php echo tr('Stato FE'); ?>", "name": "codice_stato_fe", "required": 0, "values": "query=SELECT codice as id, CONCAT_WS(' - ',codice,descrizione) as text FROM fe_stati_documento", "value": "$codice_stato_fe$", "disabled": <?php echo intval(Plugins\ExportFE\Connection::isEnabled()); ?>, "class": "unblockable", "help": "<?php echo (!empty($record['data_stato_fe'])) ? Translator::timestampToLocale($record['data_stato_fe']) : ''; ?>" ]}
{[ "type": "select", "label": "<?php echo tr('Stato FE'); ?>", "name": "codice_stato_fe", "required": 0, "values": "query=SELECT codice as id, CONCAT_WS(' - ',codice,descrizione) as text FROM fe_stati_documento", "value": "$codice_stato_fe$", "disabled": <?php echo intval(API\Services::isEnabled()); ?>, "class": "unblockable", "help": "<?php echo (!empty($record['data_stato_fe'])) ? Translator::timestampToLocale($record['data_stato_fe']) : ''; ?>" ]}
<?php
}
?>

View File

@ -1,79 +0,0 @@
<?php
use Modules\Articoli\Articolo as ArticoloOriginale;
use Modules\Interventi\Components\Articolo;
use Modules\Interventi\Intervento;
switch ($resource) {
case 'intervento':
$data = $request['data'];
// Se l'idintervento non esiste, creo un nuovo intervento
$formato = setting('Formato codice intervento');
$template = str_replace('#', '%', $formato);
$rs = $dbo->fetchArray('SELECT codice FROM in_interventi WHERE codice=(SELECT MAX(CAST(codice AS SIGNED)) FROM in_interventi) AND codice LIKE '.prepare($template).' ORDER BY codice DESC LIMIT 0,1');
$codice = Util\Generator::generate($formato, $rs[0]['codice']);
if (empty($codice)) {
$rs = $dbo->fetchArray('SELECT codice FROM in_interventi WHERE codice LIKE '.prepare($template).' ORDER BY codice DESC LIMIT 0,1');
$codice = Util\Generator::generate($formato, $rs[0]['codice']);
}
if (!empty($codice) && !empty($data['id_anagrafica']) && !empty($data['id_tipo_intervento'])) {
// Salvataggio modifiche intervento
$dbo->insert('in_interventi', [
'idanagrafica' => $data['id_anagrafica'],
'idclientefinale' => 0,
'idstatointervento' => $data['id_stato_intervento'],
'idtipointervento' => $data['id_tipo_intervento'],
'idsede' => 0,
'codice' => $codice,
'data_richiesta' => $data['data_richiesta'],
'richiesta' => $data['richiesta'],
'descrizione' => $data['descrizione'],
'informazioniaggiuntive' => $data['informazioni_aggiuntive'],
]);
$response['id'] = $dbo->lastInsertedID();
$response['codice'] = $codice;
/*
$start = date('Y-m-d H:i:s');
$end = date('Y-m-d H:i:s', strtotime('+1 hour', strtotime($start)));
add_tecnico($response['id'], $user['idanagrafica'], $start, $end);
*/
}
break;
case 'sessione':
$data = $request['data'];
add_tecnico($data['id_intervento'], $user['idanagrafica'], $data['orario_inizio'], $data['orario_fine']);
break;
case 'articolo_intervento':
$data = $request['data'];
$originale = ArticoloOriginale::find($data['id_articolo']);
$intervento = Intervento::find($data['id_intervento']);
$articolo = Articolo::build($intervento, $originale);
$articolo->qta = $data['qta'];
$articolo->um = $data['um'];
$articolo->save();
break;
}
return [
'intervento',
'sessione',
'articolo_intervento',
];

View File

@ -1,26 +0,0 @@
<?php
switch ($resource) {
case 'sessioni_intervento':
$dbo->query('DELETE FROM `in_interventi_tecnici` WHERE `idintervento` = :id_intervento AND `idtecnico` = :id_tecnico', [
':id_intervento' => $request['id_intervento'],
':id_tecnico' => $user['idanagrafica'],
]);
break;
case 'articoli_intervento':
$dbo->query('DELETE FROM `mg_articoli_interventi` WHERE `idintervento` = :id_intervento', [
':id_intervento' => $request['id_intervento'],
]);
// TODO: prevedere la modifica di quantità!
// TODO: prevedere causali
break;
}
return [
'sessioni_intervento',
//'articoli_intervento',
];

View File

@ -1,130 +0,0 @@
<?php
switch ($resource) {
case 'sync':
// Normalizzazione degli interventi a database
$dbo->query('UPDATE in_interventi_tecnici SET summary = (SELECT ragione_sociale FROM an_anagrafiche INNER JOIN in_interventi ON an_anagrafiche.idanagrafica=in_interventi.idanagrafica WHERE in_interventi.id=in_interventi_tecnici.idintervento) WHERE summary IS NULL');
$dbo->query('UPDATE in_interventi_tecnici SET uid = id WHERE uid IS NULL');
// Individuazione degli interventi
$query = 'SELECT in_interventi_tecnici.id AS idriga, in_interventi_tecnici.idintervento, (SELECT ragione_sociale FROM an_anagrafiche WHERE idanagrafica=in_interventi.idanagrafica) AS cliente, richiesta, orario_inizio, orario_fine, (SELECT ragione_sociale FROM an_anagrafiche WHERE idanagrafica=idtecnico) AS nome_tecnico, summary FROM in_interventi_tecnici INNER JOIN in_interventi ON in_interventi_tecnici.idintervento=in_interventi.id WHERE DATE(orario_inizio) BETWEEN CURDATE() - INTERVAL 7 DAY AND CURDATE() + INTERVAL 3 MONTH AND deleted_at IS NULL';
if (!empty($user['idanagrafica'])) {
$query .= ' AND in_interventi_tecnici.idtecnico = '.prepare($user['idanagrafica']);
}
$rs = $dbo->fetchArray($query);
$response['custom'] = '';
$response['custom'] .= "BEGIN:VCALENDAR\n";
$response['custom'] .= 'VERSION:'.Update::getVersion()."\n";
$response['custom'] .= "PRODID:-// OpenSTAManager\n";
foreach ($rs as $r) {
$richiesta = str_replace("\r\n", "\n", $r['richiesta']);
$richiesta = str_replace("\r", "\n", $richiesta);
$richiesta = str_replace("\n", '\\n', $richiesta);
$r['summary'] = str_replace("\r\n", "\n", $r['summary']);
$response['custom'] .= "BEGIN:VEVENT\n";
$response['custom'] .= 'UID:'.$r['idriga']."\n";
$response['custom'] .= 'DTSTAMP:'.date('Ymd').'T'.date('His')."\n";
//$response['custom'] .= 'ORGANIZER;CN='.$azienda.':MAILTO:'.$email."\n";
$response['custom'] .= 'DTSTART:'.date('Ymd', strtotime($r['orario_inizio'])).'T'.date('His', strtotime($r['orario_inizio']))."\n";
$response['custom'] .= 'DTEND:'.date('Ymd', strtotime($r['orario_fine'])).'T'.date('His', strtotime($r['orario_fine']))."\n";
$response['custom'] .= 'SUMMARY:'.html_entity_decode($r['summary'])."\n";
$response['custom'] .= 'DESCRIPTION:'.html_entity_decode($richiesta, ENT_QUOTES, 'UTF-8')."\n";
$response['custom'] .= "END:VEVENT\n";
}
$response['custom'] .= "END:VCALENDAR\n";
break;
// Elenco interventi per l'applicazione (recupero sempre tutti gli interventi che non vengono chiusi)
case 'interventi':
// Periodo per selezionare interventi
$today = date('Y-m-d');
$period_end = date('Y-m-d', strtotime($today.' +7 days'));
$period_start = date('Y-m-d', strtotime($today.' -2 months'));
$query = "SELECT `in_interventi`.`id`,
`in_interventi`.`codice`,
`in_interventi`.`data_richiesta`,
`in_interventi`.`richiesta`,
`in_interventi`.`descrizione`,
`in_interventi`.`idtipointervento`,
`in_interventi`.`idanagrafica`,
`in_interventi`.`idsede`,
`in_interventi`.`idstatointervento`,
`in_interventi`.`informazioniaggiuntive`,
`in_interventi`.`idclientefinale`,
`in_interventi`.`firma_file`,
IF(firma_data = '0000-00-00 00:00:00', '', firma_data) AS `firma_data`,
`in_interventi`.firma_nome,
(SELECT GROUP_CONCAT(CONCAT(my_impianti.matricola, ' - ', my_impianti.nome) SEPARATOR ', ') FROM (my_impianti_interventi INNER JOIN my_impianti ON my_impianti_interventi.idimpianto=my_impianti.id) WHERE my_impianti_interventi.idintervento = `in_interventi`.`id`) AS `impianti`,
(SELECT MAX(`orario_fine`) FROM `in_interventi_tecnici` WHERE `in_interventi_tecnici`.`idintervento` = `in_interventi`.`id`) AS `data`,
(SELECT GROUP_CONCAT(DISTINCT ragione_sociale SEPARATOR ', ') FROM `in_interventi_tecnici` INNER JOIN `an_anagrafiche` ON `in_interventi_tecnici`.`idtecnico` = `an_anagrafiche`.`idanagrafica` WHERE `in_interventi_tecnici`.`idintervento` = `in_interventi`.`id`) AS `tecnici`,
`in_statiintervento`.`colore` AS `bgcolor`,
`in_statiintervento`.`descrizione` AS `stato`,
`in_interventi`.`idtipointervento` AS `tipo`
FROM `in_interventi`
INNER JOIN `in_statiintervento` ON `in_interventi`.`idstatointervento` = `in_statiintervento`.`idstatointervento`
INNER JOIN `an_anagrafiche` ON `in_interventi`.`idanagrafica` = `an_anagrafiche`.`idanagrafica`
LEFT JOIN `an_sedi` ON `in_interventi`.`idsede` = `an_sedi`.`id`
WHERE EXISTS(SELECT `orario_fine` FROM `in_interventi_tecnici` WHERE `in_interventi_tecnici`.`idintervento` = `in_interventi`.`id` AND `orario_fine` BETWEEN :period_start AND :period_end)";
// TODO: rimosse le seguenti clausole
// WHERE `in_interventi`.idstatointervento IN(SELECT idstatointervento FROM in_statiintervento WHERE app_download=1)
// nel database ufficiale manca in_statiintervento.app_download
// AND `in_interventi_tecnici`.`idtecnico`='".$tecnico[0]['idanagrafica']."'
// nell'inner join con in_interventi_tecnici -> ad oggi 16-05-2018 non gestisco ancora idtecnico
$parameters = [
':period_end' => $period_end,
':period_start' => $period_start,
];
break;
// Elenco sessioni dell'intervento per l'applicazione
case 'sessioni_intervento':
$query = 'SELECT id, idintervento AS id_intervento, orario_inizio, orario_fine FROM in_interventi_tecnici WHERE `idintervento` = :id_intervento';
// TODO: rimosse seguenti clausole:
// WHERE `in_interventi`.idstatointervento IN(SELECT idstatointervento FROM in_statiintervento WHERE app_download=1)
// nel database ufficiale manca in_statiintervento.app_download
$parameters = [
':id_intervento' => $request['id_intervento'],
];
if ($user['gruppo'] == 'Tecnici') {
$query .= ' AND `idtecnico` = :id_tecnico';
$parameters[':id_tecnico'] = $user['idanagrafica'];
}
break;
// Elenco articoli dell'intervento per l'applicazione
case 'articoli_intervento':
$query = 'SELECT id, idarticolo AS id_articolo, idintervento AS id_intervento, qta, created_at as data FROM mg_articoli_interventi WHERE `idintervento` = :id_intervento';
$parameters = [
':id_intervento' => $request['id_intervento'],
];
break;
}
return [
'sync',
'interventi',
'sessioni_intervento',
'articoli_intervento',
];

View File

@ -1,135 +0,0 @@
<?php
use Carbon\Carbon;
switch ($resource) {
case 'sync':
// Normalizzazione degli interventi a database
$dbo->query('UPDATE in_interventi_tecnici SET summary = (SELECT ragione_sociale FROM an_anagrafiche INNER JOIN in_interventi ON an_anagrafiche.idanagrafica=in_interventi.idanagrafica WHERE in_interventi.id=in_interventi_tecnici.idintervento) WHERE summary IS NULL');
$dbo->query('UPDATE in_interventi_tecnici SET uid = id WHERE uid IS NULL');
// Interpretazione degli eventi
$idtecnico = $user['idanagrafica'];
$response = API::getRequest(true);
$ical = new iCalEasyReader();
$events = $ical->load($response);
foreach ($events['VEVENT'] as $event) {
$description = $event['DESCRIPTION'];
// Individuazione idriga di in_interventi_tecnici
if (str_contains($event['UID'], '-')) {
$idriga = 'NEW';
} else {
$idriga = $event['UID'];
}
// Timestamp di inizio
$orario_inizio = DateTime::createFromFormat('Ymd\\THi', $event['DTSTART'])->format(Intl\Formatter::getStandardFormats()['timestamp']);
// Timestamp di fine
$orario_fine = DateTime::createFromFormat('Ymd\\THi', $event['DTEND'])->format(Intl\Formatter::getStandardFormats()['timestamp']);
// Descrizione
$richiesta = $event['DESCRIPTION'];
$richiesta = str_replace('\\r\\n', "\n", $richiesta);
$richiesta = str_replace('\\n', "\n", $richiesta);
$summary = trim($event['SUMMARY']);
$summary = str_replace('\\r\\n', "\n", $summary);
$summary = str_replace('\\n', "\n", $summary);
// Nuova attività
if ($idriga == 'NEW') {
$rs_copie = $dbo->fetchArray('SELECT * FROM in_interventi_tecnici WHERE uid = '.prepare($event['UID']));
if (!empty($rs_copie)) {
$idintervento = $rs_copie[0]['idintervento'];
$dbo->update('in_interventi_tecnici', [
'orario_inizio' => $orario_inizio,
'orario_fine' => $orario_fine,
'summary' => $summary,
], [
'uid' => $event['UID'],
'idtecnico' => $idtecnico,
]);
$dbo->query('UPDATE in_interventi SET richiesta='.prepare($richiesta).', oggetto='.prepare($summary).' WHERE idintervento = (SELECT idintervento FROM in_interventi_tecnici WHERE idintervento = '.prepare($idintervento).' AND idtecnico = '.prepare($idtecnico).' LIMIT 0,1)');
$idriga = $rs_copie[0]['id'];
} else {
$idintervento = get_new_idintervento();
$stato = $dbo->fetchArray("SELECT * FROM in_statiintervento WHERE descrizione = 'Chiamata'");
$dbo->insert('in_interventi', [
'idintervento' => $idintervento,
'idanagrafica' => setting('Azienda predefinita'),
'data_richiesta' => Carbon::now(),
'richiesta' => $richiesta,
'idtipointervento' => 0,
'idstatointervento' => $stato['idstatointerventoWIP'],
'oggetto' => $summary,
]);
$dbo->insert('in_interventi', [
'idintervento' => $idintervento,
'idtecnico' => $idtecnico,
'orario_inizio' => $orario_inizio,
'orario_fine' => $orario_fine,
'summary' => $summary,
'uid' => $event['UID'],
]);
$idriga = $dbo->lastInsertedID();
}
}
// Modifica attività esistente
else {
$dbo->update('in_interventi_tecnici', [
'orario_inizio' => $orario_inizio,
'orario_fine' => $orario_fine,
'summary' => $summary,
], [
'id' => $idriga,
'idtecnico' => $idtecnico,
]);
$query = 'UPDATE in_interventi SET richiesta='.prepare($richiesta).', oggetto='.prepare($summary).' WHERE idintervento = (SELECT idintervento FROM in_interventi_tecnici WHERE id = '.prepare($idriga).' AND idtecnico = '.prepare($idtecnico).' LIMIT 0,1)';
$dbo->query($query);
}
}
break;
case 'intervento':
$data = $request['data'];
$dbo->update('in_interventi', [
'idstatointervento' => $data['id_stato_intervento'],
'descrizione' => $data['descrizione'],
'informazioniaggiuntive' => $data['informazioni_aggiuntive'],
], ['id' => $data['id']]);
break;
case 'firma_intervento':
$data = $request['data'];
$dbo->update('in_interventi', [
'firma_file' => $data['firma_file'],
'firma_data' => $data['firma_data'],
'firma_nome' => $data['firma_nome'],
], ['id' => $data['id']]);
break;
}
return [
'sync',
'intervento',
'firma_intervento',
];

View File

@ -0,0 +1,49 @@
<?php
namespace Modules\Interventi\API\v1;
use API\Interfaces\CreateInterface;
use API\Interfaces\RetrieveInterface;
use Modules\Articoli\Articolo as ArticoloOriginale;
use Modules\Interventi\Components\Articolo;
use Modules\Interventi\Intervento;
class Articoli implements RetrieveInterface, CreateInterface
{
public function retrieve($request)
{
$query = 'SELECT id, idarticolo AS id_articolo, idintervento AS id_intervento, qta, created_at as data FROM mg_articoli_interventi WHERE `idintervento` = :id_intervento';
$parameters = [
':id_intervento' => $request['id_intervento'],
];
return [
'query' => $query,
'parameters' => $parameters,
];
}
public function create($request)
{
$data = $request['data'];
$originale = ArticoloOriginale::find($data['id_articolo']);
$intervento = Intervento::find($data['id_intervento']);
$articolo = Articolo::build($intervento, $originale);
$articolo->qta = $data['qta'];
$articolo->um = $data['um'];
$articolo->save();
}
public function delete($request)
{
$database = database();
$database->query('DELETE FROM `mg_articoli_interventi` WHERE `idintervento` = :id_intervento', [
':id_intervento' => $request['id_intervento'],
]);
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace Modules\Interventi\API\v1;
use API\Interfaces\UpdateInterface;
class Firma implements UpdateInterface
{
public function update($request)
{
$database = database();
$data = $request['data'];
$database->update('in_interventi', [
'firma_file' => $data['firma_file'],
'firma_data' => $data['firma_data'],
'firma_nome' => $data['firma_nome'],
], ['id' => $data['id']]);
}
}

View File

@ -0,0 +1,91 @@
<?php
namespace Modules\Interventi\API\v1;
use API\Interfaces\CreateInterface;
use API\Interfaces\RetrieveInterface;
use API\Interfaces\UpdateInterface;
use Modules\Anagrafiche\Anagrafica;
use Modules\Interventi\Intervento;
use Modules\Interventi\Stato;
use Modules\TipiIntervento\Tipo as TipoSessione;
class Interventi implements RetrieveInterface, CreateInterface, UpdateInterface
{
public function retrieve($request)
{
// Periodo per selezionare interventi
$today = date('Y-m-d');
$period_end = date('Y-m-d', strtotime($today.' +7 days'));
$period_start = date('Y-m-d', strtotime($today.' -2 months'));
$query = "SELECT `in_interventi`.`id`,
`in_interventi`.`codice`,
`in_interventi`.`data_richiesta`,
`in_interventi`.`richiesta`,
`in_interventi`.`descrizione`,
`in_interventi`.`idtipointervento`,
`in_interventi`.`idanagrafica`,
`in_interventi`.`idsede_destinazione`,
`in_interventi`.`idstatointervento`,
`in_interventi`.`informazioniaggiuntive`,
`in_interventi`.`idclientefinale`,
`in_interventi`.`firma_file`,
IF(firma_data = '0000-00-00 00:00:00', '', firma_data) AS `firma_data`,
`in_interventi`.firma_nome,
(SELECT GROUP_CONCAT(CONCAT(my_impianti.matricola, ' - ', my_impianti.nome) SEPARATOR ', ') FROM (my_impianti_interventi INNER JOIN my_impianti ON my_impianti_interventi.idimpianto=my_impianti.id) WHERE my_impianti_interventi.idintervento = `in_interventi`.`id`) AS `impianti`,
(SELECT MAX(`orario_fine`) FROM `in_interventi_tecnici` WHERE `in_interventi_tecnici`.`idintervento` = `in_interventi`.`id`) AS `data`,
(SELECT GROUP_CONCAT(DISTINCT ragione_sociale SEPARATOR ', ') FROM `in_interventi_tecnici` INNER JOIN `an_anagrafiche` ON `in_interventi_tecnici`.`idtecnico` = `an_anagrafiche`.`idanagrafica` WHERE `in_interventi_tecnici`.`idintervento` = `in_interventi`.`id`) AS `tecnici`,
`in_statiintervento`.`colore` AS `bgcolor`,
`in_statiintervento`.`descrizione` AS `stato`,
`in_interventi`.`idtipointervento` AS `tipo`
FROM `in_interventi`
INNER JOIN `in_statiintervento` ON `in_interventi`.`idstatointervento` = `in_statiintervento`.`idstatointervento`
INNER JOIN `an_anagrafiche` ON `in_interventi`.`idanagrafica` = `an_anagrafiche`.`idanagrafica`
LEFT JOIN `an_sedi` ON `in_interventi`.`idsede_destinazione` = `an_sedi`.`id`
WHERE EXISTS(SELECT `orario_fine` FROM `in_interventi_tecnici` WHERE `in_interventi_tecnici`.`idintervento` = `in_interventi`.`id` AND `orario_fine` BETWEEN :period_start AND :period_end)";
$parameters = [
':period_end' => $period_end,
':period_start' => $period_start,
];
return [
'query' => $query,
'parameters' => $parameters,
];
}
public function create($request)
{
$data = $request['data'];
$anagrafica = Anagrafica::find($data['id_anagrafica']);
$tipo = TipoSessione::find($data['id_tipo_intervento']);
$stato = Stato::find($data['id_stato_intervento']);
$intervento = Intervento::build($anagrafica, $tipo, $stato, $data['data_richiesta']);
$intervento->richiesta = $data['richiesta'];
$intervento->descrizione = $data['descrizione'];
$intervento->informazioniaggiuntive = $data['informazioni_aggiuntive'];
$intervento->save();
return [
'id' => $intervento->id,
'codice' => $intervento->codice,
];
}
public function update($request)
{
$data = $request['data'];
$intervento = Intervento::find($data['id']);
$intervento->idstatointervento = $data['id_stato_intervento'];
$intervento->descrizione = $data['descrizione'];
$intervento->informazioniaggiuntive = $data['informazioni_aggiuntive'];
$intervento->save();
}
}

View File

@ -0,0 +1,50 @@
<?php
namespace Modules\Interventi\API\v1;
use API\Interfaces\CreateInterface;
use API\Interfaces\DeleteInterface;
use API\Interfaces\RetrieveInterface;
class Sessioni implements RetrieveInterface, CreateInterface, DeleteInterface
{
public function retrieve($request)
{
$user = auth()->getUser();
$query = 'SELECT id, idtecnico AS id_tecnico, idintervento AS id_intervento, orario_inizio, orario_fine FROM in_interventi_tecnici WHERE `idintervento` = :id_intervento';
$parameters = [
':id_intervento' => $request['id_intervento'],
];
if ($user['gruppo'] == 'Tecnici') {
$query .= ' AND `idtecnico` = :id_tecnico';
$parameters[':id_tecnico'] = $user['idanagrafica'];
}
return [
'query' => $query,
'parameters' => $parameters,
];
}
public function create($request)
{
$user = auth()->getUser();
$data = $request['data'];
add_tecnico($data['id_intervento'], $user['idanagrafica'], $data['orario_inizio'], $data['orario_fine']);
}
public function delete($request)
{
$database = database();
$user = auth()->getUser();
$database->query('DELETE FROM `in_interventi_tecnici` WHERE `idintervento` = :id_intervento AND `idtecnico` = :id_tecnico', [
':id_intervento' => $request['id_intervento'],
':id_tecnico' => $user['idanagrafica'],
]);
}
}

View File

@ -0,0 +1,167 @@
<?php
namespace Modules\Interventi\API\v1;
use API\Interfaces\RetrieveInterface;
use API\Interfaces\UpdateInterface;
use Carbon\Carbon;
use DateTime;
use iCalEasyReader;
use Update;
class Sync implements RetrieveInterface, UpdateInterface
{
public function retrieve($request)
{
$database = database();
$user = auth()->getUser();
// Normalizzazione degli interventi a database
$database->query('UPDATE in_interventi_tecnici SET summary = (SELECT ragione_sociale FROM an_anagrafiche INNER JOIN in_interventi ON an_anagrafiche.idanagrafica=in_interventi.idanagrafica WHERE in_interventi.id=in_interventi_tecnici.idintervento) WHERE summary IS NULL');
$database->query('UPDATE in_interventi_tecnici SET uid = id WHERE uid IS NULL');
// Individuazione degli interventi
$query = 'SELECT in_interventi_tecnici.id AS idriga, in_interventi_tecnici.idintervento, (SELECT ragione_sociale FROM an_anagrafiche WHERE idanagrafica=in_interventi.idanagrafica) AS cliente, richiesta, orario_inizio, orario_fine, (SELECT ragione_sociale FROM an_anagrafiche WHERE idanagrafica=idtecnico) AS nome_tecnico, summary FROM in_interventi_tecnici INNER JOIN in_interventi ON in_interventi_tecnici.idintervento=in_interventi.id WHERE DATE(orario_inizio) BETWEEN CURDATE() - INTERVAL 7 DAY AND CURDATE() + INTERVAL 3 MONTH AND deleted_at IS NULL';
if ($user->anagrafica->isTipo('Tecnico')) {
$query .= ' AND in_interventi_tecnici.idtecnico = '.prepare($user['idanagrafica']);
}
$rs = $database->fetchArray($query);
$result = '';
$result .= "BEGIN:VCALENDAR\n";
$result .= 'VERSION:'.Update::getVersion()."\n";
$result .= "PRODID:-// OpenSTAManager\n";
foreach ($rs as $r) {
$richiesta = str_replace("\r\n", "\n", $r['richiesta']);
$richiesta = str_replace("\r", "\n", $richiesta);
$richiesta = str_replace("\n", '\\n', $richiesta);
$r['summary'] = str_replace("\r\n", "\n", $r['summary']);
$result .= "BEGIN:VEVENT\n";
$result .= 'UID:'.$r['idriga']."\n";
$result .= 'DTSTAMP:'.date('Ymd').'T'.date('His')."\n";
//$result .= 'ORGANIZER;CN='.$azienda.':MAILTO:'.$email."\n";
$result .= 'DTSTART:'.date('Ymd', strtotime($r['orario_inizio'])).'T'.date('His', strtotime($r['orario_inizio']))."\n";
$result .= 'DTEND:'.date('Ymd', strtotime($r['orario_fine'])).'T'.date('His', strtotime($r['orario_fine']))."\n";
$result .= 'SUMMARY:'.html_entity_decode($r['summary'])."\n";
$result .= 'DESCRIPTION:'.html_entity_decode($richiesta, ENT_QUOTES, 'UTF-8')."\n";
$result .= "END:VEVENT\n";
}
$result .= "END:VCALENDAR\n";
return [
'custom' => $result,
];
}
public function update($request)
{
$database = database();
$user = auth()->getUser();
// Normalizzazione degli interventi a database
$database->query('UPDATE in_interventi_tecnici SET summary = (SELECT ragione_sociale FROM an_anagrafiche INNER JOIN in_interventi ON an_anagrafiche.idanagrafica=in_interventi.idanagrafica WHERE in_interventi.id=in_interventi_tecnici.idintervento) WHERE summary IS NULL');
$database->query('UPDATE in_interventi_tecnici SET uid = id WHERE uid IS NULL');
// Interpretazione degli eventi
$idtecnico = $user['idanagrafica'];
$response = API\Response::getRequest(true);
$ical = new iCalEasyReader();
$events = $ical->load($response);
foreach ($events['VEVENT'] as $event) {
$description = $event['DESCRIPTION'];
// Individuazione idriga di in_interventi_tecnici
if (str_contains($event['UID'], '-')) {
$idriga = 'NEW';
} else {
$idriga = $event['UID'];
}
// Timestamp di inizio
$orario_inizio = DateTime::createFromFormat('Ymd\\THi', $event['DTSTART'])->format(Intl\Formatter::getStandardFormats()['timestamp']);
// Timestamp di fine
$orario_fine = DateTime::createFromFormat('Ymd\\THi', $event['DTEND'])->format(Intl\Formatter::getStandardFormats()['timestamp']);
// Descrizione
$richiesta = $event['DESCRIPTION'];
$richiesta = str_replace('\\r\\n', "\n", $richiesta);
$richiesta = str_replace('\\n', "\n", $richiesta);
$summary = trim($event['SUMMARY']);
$summary = str_replace('\\r\\n', "\n", $summary);
$summary = str_replace('\\n', "\n", $summary);
// Nuova attività
if ($idriga == 'NEW') {
$rs_copie = $database->fetchArray('SELECT * FROM in_interventi_tecnici WHERE uid = '.prepare($event['UID']));
if (!empty($rs_copie)) {
$idintervento = $rs_copie[0]['idintervento'];
$database->update('in_interventi_tecnici', [
'orario_inizio' => $orario_inizio,
'orario_fine' => $orario_fine,
'summary' => $summary,
], [
'uid' => $event['UID'],
'idtecnico' => $idtecnico,
]);
$database->query('UPDATE in_interventi SET richiesta='.prepare($richiesta).', oggetto='.prepare($summary).' WHERE idintervento = (SELECT idintervento FROM in_interventi_tecnici WHERE idintervento = '.prepare($idintervento).' AND idtecnico = '.prepare($idtecnico).' LIMIT 0,1)');
$idriga = $rs_copie[0]['id'];
} else {
$idintervento = get_new_idintervento();
$stato = $database->fetchArray("SELECT * FROM in_statiintervento WHERE descrizione = 'Chiamata'");
$database->insert('in_interventi', [
'idintervento' => $idintervento,
'idanagrafica' => setting('Azienda predefinita'),
'data_richiesta' => Carbon::now(),
'richiesta' => $richiesta,
'idtipointervento' => 0,
'idstatointervento' => $stato['idstatointerventoWIP'],
'oggetto' => $summary,
]);
$database->insert('in_interventi', [
'idintervento' => $idintervento,
'idtecnico' => $idtecnico,
'orario_inizio' => $orario_inizio,
'orario_fine' => $orario_fine,
'summary' => $summary,
'uid' => $event['UID'],
]);
$idriga = $database->lastInsertedID();
}
}
// Modifica attività esistente
else {
$database->update('in_interventi_tecnici', [
'orario_inizio' => $orario_inizio,
'orario_fine' => $orario_fine,
'summary' => $summary,
], [
'id' => $idriga,
'idtecnico' => $idtecnico,
]);
$query = 'UPDATE in_interventi SET richiesta='.prepare($richiesta).', oggetto='.prepare($summary).' WHERE idintervento = (SELECT idintervento FROM in_interventi_tecnici WHERE id = '.prepare($idriga).' AND idtecnico = '.prepare($idtecnico).' LIMIT 0,1)';
$database->query($query);
}
}
}
}

View File

@ -1,22 +0,0 @@
<?php
switch ($resource) {
// Elenco stati contratti
case 'stati_contratto':
$table = 'co_staticontratti';
$select = [
'*',
'id' => 'id',
];
if (empty($where['deleted_at'])) {
$where['deleted_at'] = null;
}
break;
}
return [
'stati_contratto',
];

View File

@ -0,0 +1,27 @@
<?php
namespace Modules\StatiContratto\API\v1;
use API\Interfaces\RetrieveInterface;
class StatiContratti implements RetrieveInterface
{
public function retrieve($request)
{
$table = 'co_staticontratti';
$select = [
'*',
];
$where = $request['where'];
if (empty($where['deleted_at'])) {
$where['deleted_at'] = null;
}
return [
'select' => $select,
'table' => $table,
];
}
}

View File

@ -1,22 +0,0 @@
<?php
switch ($resource) {
// Elenco stati intervento per l'applicazione
case 'stati_intervento':
$table = 'in_statiintervento';
$select = [
'*',
'id' => 'idstatointervento',
];
if (empty($where['deleted_at'])) {
$where['deleted_at'] = null;
}
break;
}
return [
'stati_intervento',
];

View File

@ -0,0 +1,28 @@
<?php
namespace Modules\StatiIntervento\API\v1;
use API\Interfaces\RetrieveInterface;
class StatiInterventi implements RetrieveInterface
{
public function retrieve($request)
{
$table = 'in_statiintervento';
$select = [
'*',
'id' => 'idstatointervento',
];
$where = $request['where'];
if (empty($where['deleted_at'])) {
$where['deleted_at'] = null;
}
return [
'select' => $select,
'table' => $table,
];
}
}

View File

@ -1,22 +0,0 @@
<?php
switch ($resource) {
// Elenco stati preventivi
case 'stati_preventivo':
$table = 'co_statipreventivi';
$select = [
'*',
'id' => 'id',
];
if (empty($where['deleted_at'])) {
$where['deleted_at'] = null;
}
break;
}
return [
'stati_preventivo',
];

View File

@ -0,0 +1,27 @@
<?php
namespace Modules\StatiPreventivo\API\v1;
use API\Interfaces\RetrieveInterface;
class StatiPreventivi implements RetrieveInterface
{
public function retrieve($request)
{
$table = 'co_statipreventivi';
$select = [
'*',
];
$where = $request['where'];
if (empty($where['deleted_at'])) {
$where['deleted_at'] = null;
}
return [
'select' => $select,
'table' => $table,
];
}
}

View File

@ -155,12 +155,13 @@ switch (filter('op')) {
$dirs = [
$backup_dir => tr('Backup'),
'files' => tr('Allegati'),
'logs' => tr('Logs'),
DOCROOT.'/files' => tr('Allegati'),
DOCROOT.'/logs' => tr('Logs'),
];
foreach ($dirs as $dir => $description) {
$size = FileSystem::folderSize($dir);
$results[] = [
'description' => $description,
'size' => $size,

View File

@ -1,29 +1,36 @@
<?php
namespace Modules\StatoServizi\API\v1;
use API\Interfaces\RetrieveInterface;
use App;
use Util\FileSystem;
switch ($resource) {
case 'folder_size':
$dirs = $_GET['dirs'];
class FolderSize implements RetrieveInterface
{
public function retrieve($request)
{
$dirs = $request['dirs'];
if (empty($dirs)) {
$backup_dir = App::getConfig()['backup_dir'];
$dirs = [
$backup_dir => tr('Backup'),
'files' => tr('Allegati'),
'logs' => tr('Logs'),
DOCROOT.'/files' => tr('Allegati'),
DOCROOT.'/logs' => tr('Logs'),
];
} else {
$array = explode(',', $dirs);
foreach ($array as $key => $value) {
$dirs = [
$value => $key,
DOCROOT.'/'.$value => $key,
];
}
}
$tot_byte_size = 0;
$results = [];
$total = 0;
foreach ($dirs as $dir => $description) {
$size = FileSystem::folderSize($dir);
@ -33,16 +40,15 @@ switch ($resource) {
'formattedSize' => FileSystem::formatBytes($size),
];
$tot_byte_size += $size;
$total += $size;
}
$results[count($dirs)]['totalbyte'] = $tot_byte_size;
$response = $results;
break;
}
return [
'folder_size',
$response = [
'dirs' => $results,
'size' => $total,
'formattedSize' => FileSystem::formatBytes($total),
];
return $response;
}
}

View File

@ -0,0 +1,23 @@
<?php
namespace Modules\TipiIntervento\API\v1;
use API\Interfaces\RetrieveInterface;
class TipiInterventi implements RetrieveInterface
{
public function retrieve($request)
{
$table = 'in_tipiintervento';
$select = [
'*',
'id' => 'idtipointervento',
];
return [
'select' => $select,
'table' => $table,
];
}
}

View File

@ -1,50 +0,0 @@
<?php
switch ($resource) {
case 'login':
// Controllo sulle credenziali
if (auth()->attempt($request['username'], $request['password'])) {
$user = auth()->getUser();
$token = auth()->getToken();
// Informazioni da restituire tramite l'API
$response['user'] = $dbo->fetchOne('SELECT `ragione_sociale`, `codice`, `piva`, `codice_fiscale`, `indirizzo`, `citta`, `provincia`, (SELECT `nome` FROM `an_nazioni` WHERE `an_nazioni`.`id` = `an_anagrafiche`.`id_nazione`) AS nazione, `telefono`, `fax`, `cellulare`, `an_anagrafiche`.`email` FROM `zz_users` LEFT JOIN `an_anagrafiche` ON `an_anagrafiche`.`idanagrafica` = `zz_users`.`idanagrafica` WHERE `id` = :id', [
':id' => $user['id'],
]);
$response['token'] = $token;
$response['group'] = $user['gruppo'];
$response['google_maps_token'] = setting('Google Maps API key');
$response['version'] = Update::getVersion();
} else {
$response = [
'status' => API::getStatus()['unauthorized']['code'],
];
// Se è in corso un brute-force, aggiunge il timeout
if (Auth::isBrute()) {
$response['timeout'] = Auth::getBruteTimeout();
}
}
break;
// Operazione di logout
case 'logout':
if (!empty($request['token']) && !empty($user)) {
// Cancellazione della chiave
$database->query('DELETE FROM `zz_tokens` WHERE `token` = '.prepare($request['token']).' AND `id_utente` = '.prepare($user['id']));
} else {
$response = [
'status' => API::getStatus()['unauthorized']['code'],
];
}
break;
}
return [
'login',
'logout',
];

View File

@ -0,0 +1,43 @@
<?php
namespace Modules\Utenti\API\v1;
use API\Interfaces\CreateInterface;
use Auth;
use Update;
class Login implements CreateInterface
{
public function create($request)
{
$database = database();
// Controllo sulle credenziali
if (auth()->attempt($request['username'], $request['password'])) {
$user = auth()->getUser();
$token = auth()->getToken();
// Informazioni da restituire tramite l'API
$response['user'] = $database->fetchOne('SELECT `ragione_sociale`, `codice`, `piva`, `codice_fiscale`, `indirizzo`, `citta`, `provincia`, (SELECT `nome` FROM `an_nazioni` WHERE `an_nazioni`.`id` = `an_anagrafiche`.`id_nazione`) AS nazione, `telefono`, `fax`, `cellulare`, `an_anagrafiche`.`email` FROM `zz_users` LEFT JOIN `an_anagrafiche` ON `an_anagrafiche`.`idanagrafica` = `zz_users`.`idanagrafica` WHERE `id` = :id', [
':id' => $user['id'],
]);
$response['token'] = $token;
$response['group'] = $user['gruppo'];
$response['google_maps_token'] = setting('Google Maps API key');
$response['version'] = Update::getVersion();
} else {
$response = [
'status' => API\Response::getStatus()['unauthorized']['code'],
];
// Se è in corso un brute-force, aggiunge il timeout
if (Auth::isBrute()) {
$response['timeout'] = Auth::getBruteTimeout();
}
}
return $response;
}
}

View File

@ -0,0 +1,25 @@
<?php
namespace Modules\Utenti\API\v1;
use API\Interfaces\CreateInterface;
class Logout implements CreateInterface
{
public function create($request)
{
$database = database();
$user = auth()->getUser();
if (!empty($request['token']) && !empty($user)) {
// Cancellazione della chiave
$database->query('DELETE FROM `zz_tokens` WHERE `token` = '.prepare($request['token']).' AND `id_utente` = '.prepare($user['id']));
} else {
$response = [
'status' => API\Response::getStatus()['unauthorized']['code'],
];
}
return $response;
}
}

View File

@ -2,12 +2,14 @@
namespace Plugins\ExportFE;
use API\Services;
/**
* Classe per l'interazione con API esterne.
*
* @since 2.4.3
*/
class Interaction extends Connection
class Interaction extends Services
{
public static function sendXML($id_record)
{

View File

@ -2,14 +2,14 @@
namespace Plugins\ImportFE;
use Plugins\ExportFE\Connection;
use API\Services;
/**
* Classe per l'interazione con API esterne.
*
* @since 2.4.3
*/
class Interaction extends Connection
class Interaction extends Services
{
public static function listToImport()
{

View File

@ -2,14 +2,14 @@
namespace Plugins\ReceiptFE;
use Plugins\ExportFE\Connection;
use API\Services;
/**
* Classe per l'interazione con API esterne.
*
* @since 2.4.3
*/
class Interaction extends Connection
class Interaction extends Services
{
public static function getReceiptList()
{

View File

@ -1,410 +0,0 @@
<?php
/**
* Classe per la gestione delle API del progetto.
*
* @since 2.3
*/
class API extends \Util\Singleton
{
/** @var array Elenco delle risorse disponibili suddivise per categoria */
protected static $resources;
/** @var array Stati previsti dall'API */
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',
],
'externalError' => [
'code' => 409,
'message' => 'Errore in un servizio esterno',
],
'serverError' => [
'code' => 500,
'message' => 'Errore del server',
],
'incompatible' => [
'code' => 503,
'message' => 'Servizio non disponibile',
],
];
/**
* @throws InvalidArgumentException
*/
public function __construct()
{
if (!Auth::check() && self::getRequest()['resource'] != 'login') {
throw new InvalidArgumentException();
}
}
/**
* Gestisce le richieste di informazioni riguardanti gli elementi esistenti.
*
* @param array $request
*
* @return string
*/
public function retrieve($request)
{
$user = Auth::user();
// Controllo sulla compatibilità dell'API
if (!self::isCompatible()) {
return self::response([
'status' => self::$status['incompatible']['code'],
]);
}
$response = [];
$table = '';
$select = '*';
$where = [];
$order = [];
$parameters = [];
// Selezione personalizzata
$select = !empty($request['display']) ? explode(',', substr($request['display'], 1, -1)) : $select;
// Ricerca personalizzata
$values = isset($request['filter']) ? (array) $request['filter'] : [];
foreach ($values as $key => $value) {
// Rimozione delle parentesi
$value = substr($value, 1, -1);
// Individuazione della tipologia (array o string)
$where[$key] = str_contains($value, ',') ? explode(',', $value) : $value;
}
// Ordinamento personalizzato
$values = isset($request['order']) ? (array) $request['order'] : [];
foreach ($values as $value) {
$pieces = explode('|', $value);
$order[] = empty($pieces[1]) ? $pieces[0] : [$pieces[0] => $pieces[1]];
}
// Paginazione automatica dell'API
$page = isset($request['page']) ? (int) $request['page'] : 0;
$length = setting('Lunghezza pagine per API');
$dbo = $database = database();
$kind = 'retrieve';
$resources = self::getResources()[$kind];
$resource = $request['resource'];
try {
if (in_array($resource, array_keys($resources))) {
// Esecuzione delle operazioni personalizzate
$filename = DOCROOT.'/modules/'.$resources[$resource].'/api/'.$kind.'.php';
include $filename;
} elseif (
!in_array($resource, explode(',', setting('Tabelle escluse per la sincronizzazione API automatica')))
&& $database->tableExists($resource)
) {
$table = $resource;
// Individuazione della colonna AUTO_INCREMENT per l'ordinamento automatico
if (empty($order)) {
$column = $database->fetchArray('SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '.prepare($table)." AND EXTRA LIKE '%AUTO_INCREMENT%' AND TABLE_SCHEMA = ".prepare($database->getDatabaseName()));
if (!empty($column)) {
$order[] = $column[0]['COLUMN_NAME'];
}
}
} else {
return self::error('notFound');
}
// Generazione automatica delle query
if (!empty($table)) {
// Date di interesse
if (!empty($request['upd'])) {
$where['#updated_at'] = 'updated_at >= '.prepare($request['upd']);
}
if (!empty($request['crd'])) {
$where['#created_at'] = 'created_at >= '.prepare($request['crd']);
}
// Query per ottenere le informazioni
$query = $database->select($table, $select, $where, $order, [], true);
foreach ($where as $key => $value) {
$parameters[] = $value;
}
}
if (!empty($query)) {
$response['records'] = $database->fetchArray($query.' LIMIT '.($page * $length).', '.$length, $parameters);
$count = $database->fetchNum($query, $parameters);
$response['total-count'] = $count;
$response['pages'] = ceil($count / $length);
}
} catch (PDOException $e) {
// Log dell'errore
$logger = logger();
$logger->addRecord(\Monolog\Logger::ERROR, $e);
return self::error('internalError');
}
return self::response($response);
}
/**
* Gestisce le richieste di creazione nuovi elementi.
*
* @param array $request
*
* @return string
*/
public function create($request)
{
return $this->fileRequest($request, 'create');
}
/**
* Gestisce le richieste di aggiornamento di elementi esistenti.
*
* @param array $request
*
* @return string
*/
public function update($request)
{
return $this->fileRequest($request, 'update');
}
/**
* Gestisce le richieste di eliminazione di elementi esistenti.
*
* @param array $request
*
* @return string
*/
public function delete($request)
{
return $this->fileRequest($request, 'delete');
}
/**
* Genera i contenuti di risposta nel caso si verifichi un errore.
*
* @param string|int $error
*
* @return string
*/
public static function error($error)
{
$keys = array_keys(self::$status);
$error = (in_array($error, $keys)) ? $error : 'serverError';
$code = self::$status[$error]['code'];
http_response_code($code);
return self::response([
'status' => $code,
]);
}
/**
* Restituisce l'elenco delle risorse disponibili per l'API, suddivise per categoria.
*
* @return array
*/
public static function getResources()
{
if (!is_array(self::$resources)) {
$resources = [];
$operations = AJAX::find('api/{retrieve,create,update,delete}.php', false);
foreach ($operations as $operation) {
// Individua la tipologia e il modulo delle operazioni
$path = explode('/api/', $operation)[0];
$module = explode('modules/', $path)[1];
$kind = basename($operation, '.php');
$resources[$kind] = isset($resources[$kind]) ? (array) $resources[$kind] : [];
// Individuazione delle operazioni
$api = include $operation;
$api = is_array($api) ? array_unique($api) : [];
$keys = array_keys($resources[$kind]);
// Registrazione delle operazioni individuate
$results = [];
foreach ($api as $value) {
$value .= in_array($value, $keys) ? $module : '';
$results[$value] = $module;
}
// Salvataggio delle operazioni
$resources[$kind] = array_merge($resources[$kind], $results);
}
self::$resources = $resources;
}
return self::$resources;
}
/**
* Formatta i contenuti della risposta secondo il formato JSON.
*
* @param array $array
*
* @return string
*/
public static function response($array)
{
if (empty($array['custom'])) {
// Aggiunta dello status di default
if (empty($array['status'])) {
$array['status'] = self::$status['ok']['code'];
}
// Aggiunta del messaggio in base allo status
if (empty($array['message'])) {
$codes = array_column(self::$status, 'code');
$messages = array_column(self::$status, 'message');
$array['message'] = $messages[array_search($array['status'], $codes)];
}
$flags = JSON_FORCE_OBJECT;
// Beautify forzato dei risultati
if (get('beautify') !== null) {
$flags |= JSON_PRETTY_PRINT;
}
$result = json_encode($array, $flags);
} else {
$result = $array['custom'];
}
return $result;
}
/**
* Restituisce l'elenco degli stati dell'API.
*
* @return array
*/
public static function getStatus()
{
return self::$status;
}
/**
* Controlla se la richiesta effettuata è rivolta all'API.
*
* @return bool
*/
public static function isAPIRequest()
{
return getURLPath() == slashes(ROOTDIR.'/api/index.php');
}
/**
* Restituisce i parametri specificati dalla richiesta.
*
* @param bool $raw
*
* @return array
*/
public static function getRequest($raw = false)
{
$request = [];
if (self::isAPIRequest()) {
$request = file_get_contents('php://input');
if (empty($raw)) {
$request = (array) json_decode($request, true);
$request = Filter::sanitize($request);
// Fallback per input standard vuoto (richiesta da browser o upload file)
if (empty($request)) { // $_SERVER['REQUEST_METHOD'] == 'GET'
$request = Filter::getGET();
}
if (empty($request['token'])) {
$request['token'] = '';
}
}
}
return $request;
}
/**
* Controlla se il database è compatibile con l'API.
*
* @return bool
*/
public static function isCompatible()
{
$database = database();
return version_compare($database->getMySQLVersion(), '5.6.5') >= 0;
}
/**
* Gestisce le richieste in modo generalizzato, con il relativo richiamo ai file specifici responsabili dell'operazione.
*
* @param array $request
*
* @return string
*/
protected function fileRequest($request, $kind)
{
$user = Auth::user();
$response = [];
// Controllo sulla compatibilità dell'API
if (!self::isCompatible()) {
return self::response([
'status' => self::$status['incompatible']['code'],
]);
}
$resources = self::getResources()[$kind];
$resource = $request['resource'];
if (!in_array($resource, array_keys($resources))) {
return self::error('notFound');
}
// Database
$dbo = $database = database();
$database->beginTransaction();
// Esecuzione delle operazioni
$filename = DOCROOT.'/modules/'.$resources[$resource].'/api/'.$kind.'.php';
include $filename;
$database->commitTransaction();
return self::response($response);
}
}

View File

@ -1,7 +1,15 @@
<?php
switch ($resource) {
case 'allegato':
namespace Api\Common;
use API\Interfaces\CreateInterface;
use Modules;
use Uploads;
class Allegato implements CreateInterface
{
public function create($request)
{
$module = Modules::get($request['module']);
$upload = Uploads::upload($_FILES['upload'], [
@ -10,11 +18,8 @@ switch ($resource) {
'id_record' => $request['id'],
]);
$response['filename'] = $upload;
break;
}
return[
'allegato',
'filename' => $upload,
];
}
}

View File

@ -0,0 +1,9 @@
<?php
namespace API\Exceptions;
use Exception;
class InternalError extends Exception
{
}

View File

@ -0,0 +1,9 @@
<?php
namespace API\Exceptions;
use Exception;
class ResourceNotFound extends Exception
{
}

View File

@ -0,0 +1,9 @@
<?php
namespace API\Exceptions;
use Exception;
class ServiceError extends Exception
{
}

View File

@ -0,0 +1,9 @@
<?php
namespace API\Exceptions;
use Exception;
class Unauthorized extends Exception
{
}

View File

@ -0,0 +1,8 @@
<?php
namespace API\Interfaces;
interface CreateInterface
{
public function create($request);
}

View File

@ -0,0 +1,8 @@
<?php
namespace API\Interfaces;
interface DeleteInterface
{
public function delete($request);
}

View File

@ -0,0 +1,8 @@
<?php
namespace API\Interfaces;
interface RetrieveInterface
{
public function retrieve($request);
}

View File

@ -0,0 +1,8 @@
<?php
namespace API\Interfaces;
interface UpdateInterface
{
public function update($request);
}

193
src/API/Manager.php Normal file
View File

@ -0,0 +1,193 @@
<?php
namespace API;
use API\Exceptions\InternalError;
use API\Exceptions\ResourceNotFound;
use Auth;
use Models\ApiResource as Resource;
/**
* Classe per la gestione delle API del progetto.
*
* @since 2.4.11
*/
class Manager
{
protected $resource;
protected $type;
/**
* @throws InvalidArgumentException
*/
public function __construct($resource, $type, $version)
{
$resource = Resource::where('version', $version)
->where('type', $type)
->where('resource', $resource)
->first();
$this->resource = $resource;
$this->type = $type;
}
public function manage($request)
{
$type = $this->type;
$database = database();
$database->beginTransaction();
$response = $this->{$type}($request);
$database->commitTransaction();
return $response;
}
/**
* Gestisce le richieste di informazioni riguardanti gli elementi esistenti.
*
* @param array $request
*
* @return string
*/
public function retrieve($request)
{
$user = Auth::user();
$select = '*';
$where = [];
$order = [];
// Selezione personalizzata
$select = !empty($request['display']) ? explode(',', substr($request['display'], 1, -1)) : $select;
// Ricerca personalizzata
$values = isset($request['filter']) ? (array) $request['filter'] : [];
foreach ($values as $key => $value) {
// Rimozione delle parentesi
$value = substr($value, 1, -1);
// Individuazione della tipologia (array o string)
$where[$key] = str_contains($value, ',') ? explode(',', $value) : $value;
}
// Ordinamento personalizzato
$values = isset($request['order']) ? (array) $request['order'] : [];
foreach ($values as $value) {
$pieces = explode('|', $value);
$order[] = empty($pieces[1]) ? $pieces[0] : [$pieces[0] => $pieces[1]];
}
// Paginazione automatica dell'API
$page = isset($request['page']) ? (int) $request['page'] : 0;
$length = setting('Lunghezza pagine per API');
$data = array_merge($request, [
'user' => $user,
'select' => $select,
'where' => $where,
'order' => $order,
'page' => $page,
'length' => $length,
]);
$response = $this->getResponse($data);
$parameters = $response['parameters'];
$table = $response['table'];
$query = $response['query'];
try {
$database = database();
// Generazione automatica delle query
if (!empty($table)) {
// Date di interesse
if (!empty($request['upd'])) {
$where['#updated_at'] = 'updated_at >= '.prepare($request['upd']);
}
if (!empty($request['crd'])) {
$where['#created_at'] = 'created_at >= '.prepare($request['crd']);
}
// Query per ottenere le informazioni
$query = $database->select($table, $select, $where, $order, [], true);
foreach ($where as $key => $value) {
$parameters[] = $value;
}
}
if (!empty($query)) {
$response = [];
$response['records'] = $database->fetchArray($query.' LIMIT '.($page * $length).', '.$length, $parameters);
$count = $database->fetchNum($query, $parameters);
$response['total-count'] = $count;
$response['pages'] = intval(ceil($count / $length));
}
} catch (PDOException $e) {
// Log dell'errore
$logger = logger();
$logger->addRecord(\Monolog\Logger::ERROR, $e);
throw new InternalError();
}
return $response;
}
/**
* Gestisce le richieste di creazione nuovi elementi.
*
* @param array $request
*
* @return string
*/
public function create($request)
{
return $this->getResponse($request);
}
/**
* Gestisce le richieste di aggiornamento di elementi esistenti.
*
* @param array $request
*
* @return string
*/
public function update($request)
{
return $this->getResponse($request);
}
/**
* Gestisce le richieste di eliminazione di elementi esistenti.
*
* @param array $request
*
* @return string
*/
public function delete($request)
{
return $this->getResponse($request);
}
public function getResponse($request)
{
$class = $this->resource->class;
if (!class_exists($class)) {
throw new ResourceNotFound();
}
$object = new $class();
$method = $this->type;
$response = $object->{$method}($request);
return $response;
}
}

247
src/API/Response.php Normal file
View File

@ -0,0 +1,247 @@
<?php
namespace API;
use API\Exceptions\InternalError;
use API\Exceptions\ResourceNotFound;
use API\Exceptions\ServiceError;
use Auth;
use Filter;
use Models\ApiResource as Resource;
/**
* Classe per la gestione delle API del progetto.
*
* @since 2.4.11
*/
class Response
{
/** @var array Stati previsti dall'API */
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',
],
'externalError' => [
'code' => 409,
'message' => 'Errore in un servizio esterno',
],
'serverError' => [
'code' => 500,
'message' => 'Errore del server',
],
'incompatible' => [
'code' => 503,
'message' => 'Servizio non disponibile',
],
];
public static function manage()
{
// Gestione della richiesta
$method = $_SERVER['REQUEST_METHOD'];
$type = null;
switch ($method) {
// Richiesta PUT (modifica elementi)
case 'PUT':
$type = 'update';
break;
// Richiesta POST (creazione elementi)
case 'POST':
$type = 'create';
break;
// Richiesta GET (ottenimento elementi)
case 'GET':
$type = 'retrieve';
break;
// Richiesta DELETE (eliminazione elementi)
case 'DELETE':
$type = 'delete';
break;
}
$request = self::getRequest();
$version = $request['version'] ?: 'v1';
// Controllo sull'accesso
if (!Auth::check() && $request['resource'] != 'login') {
return self::response([
'status' => self::$status['unauthorized']['code'],
]);
}
// Controllo sulla compatibilità dell'API
if (!self::isCompatible()) {
return self::response([
'status' => self::$status['incompatible']['code'],
]);
}
try {
$manager = new Manager($request['resource'], $type, $version);
if ($type == 'retrieve' && empty($request['resource'])) {
$resources = self::getResources($type, $version)->toArray();
$list = array_column($resources, 'resource') ?: [];
return self::response([
'resources' => $list,
]);
}
$response = $manager->manage($request);
} catch (ResourceNotFound $e) {
return self::error('notFound');
} catch (InternalError $e) {
return self::error('internalError');
} catch (ServiceError $e) {
return self::error('externalError');
}
return self::response($response);
}
/**
* Genera i contenuti di risposta nel caso si verifichi un errore.
*
* @param string|int $error
*
* @return string
*/
public static function error($error)
{
$keys = array_keys(self::$status);
$error = (in_array($error, $keys)) ? $error : 'serverError';
$code = self::$status[$error]['code'];
http_response_code($code);
return self::response([
'status' => $code,
]);
}
/**
* Formatta i contenuti della risposta secondo il formato JSON.
*
* @param array $array
*
* @return string
*/
public static function response($array)
{
if (empty($array['custom'])) {
// Aggiunta dello status di default
if (empty($array['status'])) {
$array['status'] = self::$status['ok']['code'];
}
// Aggiunta del messaggio in base allo status
if (empty($array['message'])) {
$codes = array_column(self::$status, 'code');
$messages = array_column(self::$status, 'message');
$array['message'] = $messages[array_search($array['status'], $codes)];
}
$flags = JSON_FORCE_OBJECT;
// Beautify forzato dei risultati
if (get('beautify') !== null) {
$flags |= JSON_PRETTY_PRINT;
}
$result = json_encode($array, $flags);
} else {
$result = $array['custom'];
}
return $result;
}
/**
* Restituisce l'elenco degli stati dell'API.
*
* @return array
*/
public static function getStatus()
{
return self::$status;
}
/**
* Controlla se la richiesta effettuata è rivolta all'API.
*
* @return bool
*/
public static function isAPIRequest()
{
return getURLPath() == slashes(ROOTDIR.'/api/index.php');
}
/**
* Restituisce i parametri specificati dalla richiesta.
*
* @param bool $raw
*
* @return array
*/
public function getRequest($raw = false)
{
$request = [];
if (self::isAPIRequest()) {
$request = file_get_contents('php://input');
if (empty($raw)) {
$request = (array) json_decode($request, true);
$request = Filter::sanitize($request);
// Fallback per input standard vuoto (richiesta da browser o upload file)
if (empty($request)) { // $_SERVER['REQUEST_METHOD'] == 'GET'
$request = Filter::getGET();
}
if (empty($request['token'])) {
$request['token'] = '';
}
}
}
return $request;
}
/**
* Controlla se il database è compatibile con l'API.
*
* @return bool
*/
public static function isCompatible()
{
$database = database();
return version_compare($database->getMySQLVersion(), '5.6.5') >= 0;
}
protected static function getResources($type, $version)
{
$resources = Resource::where('version', $version)->where('type', $type)->get();
return $resources;
}
}

View File

@ -1,6 +1,6 @@
<?php
namespace Plugins\ExportFE;
namespace API;
use GuzzleHttp\Client;
@ -9,7 +9,7 @@ use GuzzleHttp\Client;
*
* @since 2.4.3
*/
class Connection
class Services
{
protected static $client = null;

View File

@ -56,8 +56,8 @@ class Auth extends \Util\Singleton
if ($database->isInstalled()) {
// Controllo dell'accesso da API
if (API::isAPIRequest()) {
$token = API::getRequest()['token'];
if (API\Response::isAPIRequest()) {
$token = API\Response::getRequest()['token'];
$user = $database->fetchArray('SELECT `id_utente` FROM `zz_tokens` WHERE `enabled` = 1 AND `token` = :token', [
':token' => $token,
@ -232,7 +232,7 @@ class Auth extends \Util\Singleton
session_unset();
session_regenerate_id();
if (!API::isAPIRequest()) {
if (!API\Response::isAPIRequest()) {
flash()->clearMessages();
}
}

View File

@ -0,0 +1,12 @@
<?php
namespace Models;
use Common\Model;
class ApiResource extends Model
{
protected $table = 'zz_api_resources';
/* Relazioni Eloquent */
}

View File

@ -4,6 +4,7 @@ namespace Models;
use Common\Model;
use Intervention\Image\ImageManagerStatic;
use Modules\Anagrafiche\Anagrafica;
class User extends Model
{
@ -171,6 +172,16 @@ class User extends Model
return $this->hasMany(Log::class, 'id_utente');
}
public function anagrafica()
{
return $this->belongsTo(Anagrafica::class, 'idanagrafica');
}
public function image()
{
return $this->belongsTo(Upload::class, 'image_file_id');
}
public function modules()
{
return $this->group->modules();

29
update/2_4_11.php Normal file
View File

@ -0,0 +1,29 @@
<?php
// File e cartelle deprecate
$files = [
'src\API.php',
'modules\utenti\api\create.php',
'modules\stato_servizi\api\retrieve.php',
'modules\stati_preventivo\api\retrieve.php',
'modules\stati_intervento\api\retrieve.php',
'modules\stati_contratto\api\retrieve.php',
'modules\articoli\api\retrieve.php',
'modules\anagrafiche\api\update.php',
'modules\anagrafiche\api\retrieve.php',
'modules\anagrafiche\api\delete.php',
'modules\anagrafiche\api\create.php',
'modules\interventi\api\update.php',
'modules\interventi\api\retrieve.php',
'modules\interventi\api\delete.php',
'modules\interventi\api\create.php',
'modules\aggiornamenti\api\retrieve.php',
'modules\aggiornamenti\api\create.php',
'plugins\exportFE\src\Connection.php',
];
foreach ($files as $key => $value) {
$files[$key] = realpath(DOCROOT.'/'.$value);
}
delete($files);

View File

@ -70,3 +70,45 @@ UPDATE `co_righe_documenti` INNER JOIN `co_righe_preventivi` ON `co_righe_docume
-- Aggiunta foto utente
ALTER TABLE `zz_users` ADD `image_file_id` int(11);
UPDATE `zz_modules` SET `enabled` = 1 WHERE `name` = 'Utenti e permessi';
-- Aggiornamento sistema API
CREATE TABLE IF NOT EXISTS `zz_api_resources` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`version` varchar(15) NOT NULL,
`type` ENUM('create', 'retrieve', 'update', 'delete'),
`resource` varchar(255) NOT NULL,
`class` varchar(255) NOT NULL,
`enabled` tinyint(1) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
DELETE FROM `zz_settings` WHERE `nome` = 'Tabelle escluse per la sincronizzazione API automatica';
INSERT INTO `zz_api_resources` (`id`, `version`, `type`, `resource`, `class`, `enabled`) VALUES
(NULL, 'v1', 'create', 'allegato', 'Api\\Common\\Allegato', '1'),
(NULL, 'v1', 'retrieve', 'anagrafiche', 'Modules\\Anagrafiche\\API\\v1\\Anagrafiche', '1'),
(NULL, 'v1', 'create', 'anagrafica', 'Modules\\Anagrafiche\\API\\v1\\Anagrafiche', '1'),
(NULL, 'v1', 'update', 'anagrafica', 'Modules\\Anagrafiche\\API\\v1\\Anagrafiche', '1'),
(NULL, 'v1', 'delete', 'anagrafica', 'Modules\\Anagrafiche\\API\\v1\\Anagrafiche', '1'),
(NULL, 'v1', 'create', 'movimento_articolo', 'Modules\\Articoli\\API\\v1\\Movimenti', '1'),
(NULL, 'v1', 'retrieve', 'articoli', 'Modules\\Articoli\\API\\v1\\Articoli', '1'),
(NULL, 'v1', 'create', 'login', 'Modules\\Utenti\\API\\v1\\Login', '1'),
(NULL, 'v1', 'create', 'logout', 'Modules\\Utenti\\API\\v1\\Logout', '1'),
(NULL, 'v1', 'retrieve', 'folder_size', 'Modules\\StatoServizi\\API\\v1\\FolderSize', '1'),
(NULL, 'v1', 'retrieve', 'tipi_intervento', 'Modules\\TipiIntervento\\API\\v1\\TipiInterventi', '1'),
(NULL, 'v1', 'retrieve', 'stati_intervento', 'Modules\\StatiIntervento\\API\\v1\\StatiInterventi', '1'),
(NULL, 'v1', 'retrieve', 'stati_preventivo', 'Modules\\StatiPreventivo\\API\\v1\\StatiPreventivi', '1'),
(NULL, 'v1', 'retrieve', 'stati_contratto', 'Modules\\StatiContratto\\API\\v1\\StatiContratti', '1'),
(NULL, 'v1', 'retrieve', 'tipi_intervento', 'Modules\\Interventi\\API\\v1\\Interventi', '1'),
(NULL, 'v1', 'retrieve', 'interventi', 'Modules\\Interventi\\API\\v1\\Interventi', '1'),
(NULL, 'v1', 'create', 'intervento', 'Modules\\Interventi\\API\\v1\\Interventi', '1'),
(NULL, 'v1', 'update', 'intervento', 'Modules\\Interventi\\API\\v1\\Interventi', '1'),
(NULL, 'v1', 'update', 'firma_intervento', 'Modules\\Interventi\\API\\v1\\Firma', '1'),
(NULL, 'v1', 'retrieve', 'sync', 'Modules\\Interventi\\API\\v1\\Sync', '1'),
(NULL, 'v1', 'update', 'sync', 'Modules\\Interventi\\API\\v1\\Sync', '1'),
(NULL, 'v1', 'retrieve', 'sessioni_intervento', 'Modules\\Interventi\\API\\v1\\Sessioni', '1'),
(NULL, 'v1', 'create', 'sessione_intervento', 'Modules\\Interventi\\API\\v1\\Sessioni', '1'),
(NULL, 'v1', 'update', 'sessione_intervento', 'Modules\\Interventi\\API\\v1\\Sessioni', '1'),
(NULL, 'v1', 'retrieve', 'articoli_intervento', 'Modules\\Interventi\\API\\v1\\Articoli', '1'),
(NULL, 'v1', 'create', 'articolo_intervento', 'Modules\\Interventi\\API\\v1\\Articoli', '1');

View File

@ -16,7 +16,7 @@ foreach ($tables as $table) {
$database->query('ALTER TABLE `'.$table.'` ADD `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP');
}
if (API::isCompatible()) {
if (API\Response::isCompatible()) {
$updated_at = $database->fetchArray(str_replace('|field|', 'updated_at', $query));
if (empty($updated_at)) {
$database->query('ALTER TABLE `'.$table.'` ADD `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP');

View File

@ -78,6 +78,7 @@ return [
'or_righe_ordini',
'or_statiordine',
'or_tipiordine',
'zz_api_resources',
'zz_currencies',
'zz_documenti',
'zz_documenti_categorie',