2020-07-15 16:58:01 +02:00
< ? php
2020-09-07 15:04:06 +02:00
/*
* OpenSTAManager : il software gestionale open source per l ' assistenza tecnica e la fatturazione
2021-01-20 15:08:51 +01:00
* Copyright ( C ) DevCode s . r . l .
2020-09-07 15:04:06 +02:00
*
* This program 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 3 of the License , or
* ( at your option ) any later version .
*
* This program 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 this program . If not , see < https :// www . gnu . org / licenses />.
*/
2020-07-15 16:58:01 +02:00
2020-07-24 10:20:42 +02:00
namespace API\App ;
2020-07-15 16:58:01 +02:00
2020-07-24 10:20:42 +02:00
use API\Interfaces\CreateInterface ;
use API\Interfaces\DeleteInterface ;
2020-07-15 16:58:01 +02:00
use API\Interfaces\RetrieveInterface ;
2020-07-24 10:20:42 +02:00
use API\Interfaces\UpdateInterface ;
use API\Resource ;
2020-07-28 09:42:05 +02:00
use Carbon\Carbon ;
2021-02-24 11:48:38 +01:00
use Illuminate\Support\Collection ;
2020-07-15 16:58:01 +02:00
/**
* Risorsa di base per la gestione delle operazioni standard di comunicazione con l ' applicazione .
2020-07-28 09:42:05 +02:00
* Implementa le operazioni di * retrieve * in tre fasi , e rende disponibile l ' espansione per operazioni di * create * , * update * e * delete *.
2020-07-15 16:58:01 +02:00
*/
2020-07-24 10:20:42 +02:00
abstract class AppResource extends Resource implements RetrieveInterface , CreateInterface , UpdateInterface , DeleteInterface
2020-07-15 16:58:01 +02:00
{
2020-07-28 09:42:05 +02:00
/**
* Gestisce le operazioni di * retrieve * in tre fasi :
* - Cleanup ( elenco di record da rimuovere nell ' applicazione );
* - Record modificati ( elenco di record che sono stati aggiornati nel gestionale );
* - Dettagli del record .
*
* @ return array []
*/
2020-07-15 16:58:01 +02:00
public function retrieve ( $request )
{
$id = $request [ 'id' ];
2020-07-28 09:42:05 +02:00
$last_sync_at = $request [ 'last_sync_at' ] && $request [ 'last_sync_at' ] != 'undefined' ? new Carbon ( $request [ 'last_sync_at' ]) : null ;
2020-07-15 16:58:01 +02:00
// Gestione delle operazioni di cleanup
if ( strpos ( $request [ 'resource' ], 'cleanup' ) !== false ) {
2020-07-28 12:12:27 +02:00
$list = [];
if ( ! empty ( $last_sync_at )) {
$list = $this -> getCleanupData ( $last_sync_at );
}
2020-07-24 11:13:50 +02:00
$list = $this -> forceToString ( $list );
2020-07-15 16:58:01 +02:00
return [
'records' => $list ,
];
}
// Gestione dell'enumerazione dei record modificati
if ( ! isset ( $id )) {
2020-07-28 09:42:05 +02:00
$list = $this -> getModifiedRecords ( $last_sync_at );
2020-07-24 11:13:50 +02:00
$list = $this -> forceToString ( $list );
2020-07-15 16:58:01 +02:00
return [
'records' => $list ,
];
}
// Gestione della visualizzazione dei dettagli del record
2020-07-24 10:20:42 +02:00
$details = $this -> retrieveRecord ( $id );
2020-07-24 11:13:50 +02:00
$details = $this -> forceToString ( $details );
2020-07-22 10:52:18 +02:00
2020-07-15 16:58:01 +02:00
return [
'record' => $details ,
];
}
2020-07-28 09:42:05 +02:00
/**
* Gestisce la richiesta di creazione di un record , delegando le operazioni relative a * createRecord * e forzando i risultati in formato stringa .
*
* @ return array
*/
2020-07-24 10:20:42 +02:00
public function create ( $request )
{
$data = $request [ 'data' ];
$response_data = $this -> createRecord ( $data );
2020-07-24 15:13:36 +02:00
$response_data = $this -> forceToString ( $response_data );
2020-07-24 10:20:42 +02:00
return [
'id' => $response_data [ 'id' ],
'data' => $response_data ,
];
}
2020-07-28 09:42:05 +02:00
/**
* Gestisce la richiesta di modifica di un record , delegando le operazioni relative a * updateRecord * e forzando i risultati in formato stringa .
*
* @ return array
*/
2020-07-24 10:20:42 +02:00
public function update ( $request )
{
$data = $request [ 'data' ];
$response_data = $this -> updateRecord ( $data );
2020-07-24 15:13:36 +02:00
$response_data = $this -> forceToString ( $response_data );
2020-07-24 10:20:42 +02:00
return [
'data' => $response_data ,
];
}
2020-07-28 09:42:05 +02:00
/**
* Gestisce la richiesta di eliminazione di un record , delegando le operazioni relative a * deleteRecord *.
*/
2020-07-24 10:20:42 +02:00
public function delete ( $request )
{
$id = $request [ 'id' ];
$this -> deleteRecord ( $id );
}
2020-07-28 12:12:27 +02:00
/**
* Restituisce un array contenente gli ID dei record eliminati .
*
* @ return array
*/
abstract public function getCleanupData ( $last_sync );
/**
* Restituisce un array contenente gli ID dei record modificati e da sincronizzare .
*
* @ param string $last_sync_at
*
2021-02-24 11:48:38 +01:00
* @ return array < number , array >
2020-07-28 12:12:27 +02:00
*/
abstract public function getModifiedRecords ( $last_sync_at );
/**
* Restituisce i dettagli relativi a un singolo record identificato tramite ID .
*
* @ param string $id
*
* @ return array
*/
abstract public function retrieveRecord ( $id );
/**
* Crea un nuovo record relativo alla risorsa , restituendo l ' ID relativo ed eventuali campi da aggiornare in remoto .
*
* @ param array $data
*
* @ return array
*/
public function createRecord ( $data )
{
return [];
}
/**
* Aggiorna un record relativo alla risorsa , restituendo eventuali campi da aggiornare in remoto .
*
* @ param array $data
*
* @ return array
*/
public function updateRecord ( $data )
{
return [];
}
/**
* Elimina un record relativo alla risorsa .
*
* @ param string $id
*
* @ return void
*/
public function deleteRecord ( $id )
{
}
2021-02-24 11:48:38 +01:00
/**
* Genera la mappatura id => updated_at necessaria per la gestione dei record modificati .
*
* @ return array []
*/
protected function mapModifiedRecords ( $records )
{
2021-02-24 16:27:04 +01:00
if ( $records instanceof Collection ) {
2024-04-09 12:18:08 +02:00
return $records -> mapToGroups ( fn ( $item , $key ) => [ $item [ 'id' ] => $item ]) -> toArray ();
2021-02-24 11:48:38 +01:00
}
return array_reduce ( $records , function ( $accumulator , $item ) {
$accumulator [ $item [ 'id' ]] = $item ;
return $accumulator ;
2021-02-24 16:27:04 +01:00
}) ? : [];
2021-02-24 11:48:38 +01:00
}
2020-07-28 09:42:05 +02:00
/**
* Converte i valori numerici in stringhe .
*
* @ return array
*/
2020-07-24 11:13:50 +02:00
protected function forceToString ( $list )
{
$result = [];
// Fix per la gestione dei contenuti numerici
foreach ( $list as $key => $value ) {
if ( is_numeric ( $value )) {
$result [ $key ] = ( string ) $value ;
2020-07-24 15:13:36 +02:00
} elseif ( is_array ( $value )) {
$result [ $key ] = $this -> forceToString ( $value );
2020-07-24 11:13:50 +02:00
} else {
$result [ $key ] = $value ;
}
}
return $result ;
}
2020-07-15 16:58:01 +02:00
/**
2020-07-28 09:42:05 +02:00
* Restituisce gli ID dei potenziali record mancanti , sulla base della colonna indicata e a partire da * last_sync_at *.
*
* @ param string $table_name Tabella da analizzare
* @ param string $column Colonna di tipo AUTO_INCREMENT della tabella
* @ param null $last_sync_at
2020-07-15 16:58:01 +02:00
*
2024-01-15 15:30:45 +01:00
* @ throws \Exception
2020-07-15 16:58:01 +02:00
*
* @ return array
*/
2020-07-28 09:42:05 +02:00
protected function getMissingIDs ( $table_name , $column , $last_sync_at = null )
2020-07-15 16:58:01 +02:00
{
$database = database ();
$db_name = $database -> getDatabaseName ();
// Ottiene il valore successivo della colonna di tipo AUTO_INCREMENT
2022-04-22 10:18:37 +02:00
$database -> query ( 'ANALYZE TABLE ' . $table_name );
2020-07-28 09:42:05 +02:00
$next_autoincrement = $database -> fetchOne ( 'SELECT AUTO_INCREMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = ' . prepare ( $table_name ) . ' AND TABLE_SCHEMA = ' . prepare ( $db_name ))[ 'AUTO_INCREMENT' ];
2020-08-06 16:22:32 +02:00
/*
2020-07-28 09:42:05 +02:00
// Ottiene l'ultimo record con data precedente a quella impostata
$last_id = null ;
if ( $last_sync_at ) {
$last_record = $database -> fetchOne ( 'SELECT ' . $column . ' AS id FROM ' . $table_name . ' WHERE created_at <= ' . prepare ( $last_sync_at ) . ' ORDER BY ' . $column . ' DESC' );
$last_id = $last_record [ 'id' ];
}
2020-08-06 16:22:32 +02:00
*/
2020-07-15 16:58:01 +02:00
// Ottiene i vuoti all'interno della sequenza AUTO_INCREMENT
2020-07-28 09:42:05 +02:00
$query = '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)' ;
2020-08-06 16:22:32 +02:00
/*
2020-07-28 09:42:05 +02:00
if ( $last_id ) {
$query .= ' AND t1.' . $column . ' >= ' . prepare ( $last_id );
}
2020-08-06 16:22:32 +02:00
*/
2020-07-28 09:42:05 +02:00
$query .= ' ORDER BY start' ;
$steps = $database -> fetchArray ( $query );
2020-07-15 16:58:01 +02:00
2020-08-06 16:22:32 +02:00
// Gestione dell'eliminazione dei primi record della tabella
$exists_first = $database -> fetchNum ( 'SELECT * FROM ' . $table_name . ' WHERE ' . $column . ' = 1' );
if ( ! $exists_first ) {
$first = $database -> fetchOne ( 'SELECT MIN(' . $column . ') AS min FROM ' . $table_name );
$steps [] = [
'start' => 1 ,
'end' => $first [ 'min' ] - 1 ,
];
}
2020-07-15 16:58:01 +02:00
$total = [];
foreach ( $steps as $step ) {
if ( $step [ 'end' ] == null ) {
2020-07-28 09:42:05 +02:00
$step [ 'end' ] = $next_autoincrement - 1 ;
2020-07-15 16:58:01 +02:00
}
2022-04-20 15:45:46 +02:00
if ( $step [ 'end' ] == '-1' ) {
$step [ 'end' ] = $next_autoincrement ;
}
2020-07-15 16:58:01 +02:00
if ( $step [ 'end' ] >= $step [ 'start' ]) {
$total = array_merge ( $total , range ( $step [ 'start' ], $step [ 'end' ]));
}
}
return $total ;
}
/**
2020-07-28 09:42:05 +02:00
* Restituisce gli ID dei record con campo * deleted_at * maggiore di * last_sync_at *.
*
* @ param string $table_name Tabella da analizzare
* @ param string $column Colonna di tipo AUTO_INCREMENT della tabella
* @ param null $last_sync_at
2020-07-15 16:58:01 +02:00
*
2024-01-15 15:30:45 +01:00
* @ throws \Exception
2020-07-15 16:58:01 +02:00
*
* @ return array
*/
2020-07-28 09:42:05 +02:00
protected function getDeleted ( $table_name , $column , $last_sync_at = null )
2020-07-15 16:58:01 +02:00
{
2020-07-28 09:42:05 +02:00
$query = 'SELECT ' . $column . ' AS id FROM ' . $table_name . ' WHERE deleted_at' ;
if ( $last_sync_at ) {
$query .= ' > ' . prepare ( $last_sync_at );
} else {
$query .= ' IS NOT NULL' ;
}
2020-07-15 16:58:01 +02:00
2020-07-28 09:42:05 +02:00
$results = database () -> fetchArray ( $query );
2020-07-15 16:58:01 +02:00
return array_column ( $results , 'id' );
}
}