486 lines
18 KiB
PHP
486 lines
18 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Classe generica che si interfaccia con le varie classi di risorsa da utilizzare con le funzione generiche delle query
|
|
*
|
|
* Versione: 1.0.2
|
|
* Data Update: 16/02/2021
|
|
*
|
|
* Elenco Funzionalità implementate:
|
|
*
|
|
* - countTotal
|
|
* - getList con paginazione
|
|
* - getList con ricerche complete di parametri ORWHERE e ANDORWHERE
|
|
* - getList con gestione completa dell'ordinamento in base alla stringa passata anche con valori multipli | array (rimane intatto)
|
|
* - getList con selectList (opzionele) | '*'
|
|
* - getList con joinData (opzionale) inclusa anche la possibilità di inserire join multipli nell'array
|
|
* - getList con groupBy (opzionale)
|
|
* # Per utilizzare getList e groupBy bisogna fare l'overload delle funzioni checkIfSetJoinData | checkIfSetGroupBy nel controller della risorsa
|
|
* - countFiltered() non utilizza il getList
|
|
* - getByColumnName()
|
|
* - customQuery()
|
|
* - inserito l'overload della funzione getList che ora è utilizzabile con due intestazioni di metodo "classica" o "con array di parametri"
|
|
* - inserita la gestione dell'having per la getList
|
|
*
|
|
* Class App_Model_AbstractGeneric
|
|
*/
|
|
abstract class App_Model_AbstractGeneric
|
|
{
|
|
protected $_resources = array();
|
|
|
|
const JOIN_TABLE_NAME = "JOIN_TABLE_NAME";
|
|
const JOIN_CONDITION_NAME = "JOIN_CONDITION_NAME";
|
|
const JOIN_COLUMNS_NAME = "JOIN_COLUMNS_NAME";
|
|
const JOIN_TYPE = "JOIN_TYPE";
|
|
const JOIN_FUNCTION_NAME_ALLOWED = array('join', 'joinInner', 'joinLeft', 'joinRight', 'joinFull', 'joinCross', 'joinNatural');
|
|
|
|
const ALLOWED_GETLIST_ARRAY_OPTIONS = array('page', 'count', 'where', 'order', 'selectList', 'joinOptions', 'groupBy', 'fetchRow', 'having');
|
|
|
|
/**
|
|
* @param $name
|
|
* @return App_Model_Resource_Abstract
|
|
* @throws App_Controller_Errors_WebServiceError
|
|
*/
|
|
public function getResource($name)
|
|
{
|
|
|
|
if (!isset($this->_resources[$name])) {
|
|
$class = implode('_', array(
|
|
$this->_getNamespace(),
|
|
'Model_Resources',
|
|
ucfirst($name)));
|
|
|
|
//Controllo l'esistenza della classe
|
|
if (!class_exists($class)) {
|
|
throw new App_Controller_Errors_WebServiceError("Errore generazione la classe risorsa '$class' potrebbe non esistere");
|
|
}
|
|
|
|
$this->_resources[$name] = new $class();
|
|
}
|
|
|
|
return $this->_resources[$name];
|
|
}
|
|
|
|
private function _getNamespace()
|
|
{
|
|
$ns = explode('_', get_class($this));
|
|
return $ns[0];
|
|
}
|
|
|
|
/*====================================================================================================
|
|
*======================= FUNZIONI GENERICHE PER OGNI TABELLA ==========================
|
|
*====================================================================================================*/
|
|
|
|
/**
|
|
* @param $resourceName
|
|
* @param $info
|
|
* @return mixed
|
|
* @throws App_Controller_Errors_WebServiceError
|
|
*/
|
|
public function insert($resourceName, $info)
|
|
{
|
|
|
|
return $this->getResource($resourceName)->insert($info);
|
|
}
|
|
|
|
public function update($resourceName, $id, $info)
|
|
{
|
|
|
|
$resource = $this->getResource($resourceName);
|
|
$idString = (is_int($id)) ? " = $id" : " = '$id'";
|
|
return $resource->update($info, $resource->getPrimaryKey() . $idString);
|
|
}
|
|
|
|
public function updateWhere($resourceName, $condition, $info)
|
|
{
|
|
//Se passo un array di condizioni viene construita la stringa
|
|
if (is_array($condition)) {
|
|
$last_key = key(array_slice($condition, -1, 1, TRUE));
|
|
$str = "";
|
|
foreach ($condition as $key => $val) {
|
|
$str .= str_replace('?', $val, $key);
|
|
if ($key != $last_key) $str .= " AND ";
|
|
}
|
|
$condition = $str;
|
|
}
|
|
|
|
$resource = $this->getResource($resourceName);
|
|
return $resource->update($info, $condition);
|
|
}
|
|
|
|
public function delete($resourceName, $id)
|
|
{
|
|
$resource = $this->getResource($resourceName);
|
|
$idString = (is_int($id)) ? " = $id" : " = '$id'";
|
|
return $resource->delete($resource->getPrimaryKey() . $idString);
|
|
}
|
|
|
|
public function deleteWhere($resourceName, $condition)
|
|
{
|
|
//Se passo un array di condizioni viene construita la stringa
|
|
if (is_array($condition)) {
|
|
$last_key = key(array_slice($condition, -1, 1, TRUE));
|
|
$str = "";
|
|
foreach ($condition as $key => $val) {
|
|
$str .= str_replace('?', $val, $key);
|
|
if ($key != $last_key) $str .= " AND ";
|
|
}
|
|
$condition = $str;
|
|
}
|
|
|
|
$resource = $this->getResource($resourceName);
|
|
return $resource->delete($condition);
|
|
}
|
|
|
|
public function getById($resourceName, $id)
|
|
{
|
|
|
|
$resource = $this->getResource($resourceName);
|
|
return $resource->getAdapter()->query('SELECT * FROM ' . $resource->getTableName() . ' WHERE ' . $resource->getPrimaryKey() . ' = ?', array($id))->fetch();
|
|
}
|
|
|
|
public function getLastId($resourceName)
|
|
{
|
|
|
|
$resource = $this->getResource($resourceName);
|
|
return $resource->getAdapter()->query('SELECT id FROM ' . $resource->getTableName() . ' ORDER BY ' . $resource->getPrimaryKey() . ' DESC LIMIT 1')->fetchColumn(0);
|
|
}
|
|
|
|
public function getCountTotal($resourceName)
|
|
{
|
|
|
|
$resource = $this->getResource($resourceName);
|
|
return $resource->getAdapter()->query('SELECT COUNT(*) as num FROM ' . $resource->getTableName())->fetchColumn(0);
|
|
}
|
|
|
|
// FUNZIONE GET LIST CON OVERLOAD
|
|
|
|
public function getList()
|
|
{
|
|
$args = func_get_args();
|
|
$functionName = (func_num_args() === 2 && is_array($args[1])) ? 'getListOptions' : 'getListDefault';
|
|
return call_user_func_array(array(&$this, $functionName), $args);
|
|
}
|
|
|
|
/**
|
|
* #Overload
|
|
* Funzione get list che accetta i parametri inseriti in un array in modo da non dover più rispettare l'ordine di inserimento
|
|
*
|
|
* @param $resourceName
|
|
* @param array $options
|
|
* @return Zend_Paginator
|
|
* @throws Zend_Exception
|
|
* @throws Zend_Paginator_Exception
|
|
*/
|
|
public function getListOptions($resourceName, array $options = [])
|
|
{
|
|
foreach ($options as $optionKey => $val) {
|
|
if (!in_array($optionKey, self::ALLOWED_GETLIST_ARRAY_OPTIONS)) {
|
|
throw new App_Controller_Errors_WebServiceError("'$optionKey' non e' una opzione valida per la funzione getList()");
|
|
}
|
|
}
|
|
|
|
return $this->getListDefault($resourceName,
|
|
$options['page'], $options['count'], $options['where'],
|
|
$options['order'], $options['selectList'], $options['joinOptions'],
|
|
$options['groupBy'], $options['fetchRow'], $options['having']);
|
|
}
|
|
|
|
/**
|
|
* Funzione getList completa (può sostituire anche la funzione getFilteredList)
|
|
*
|
|
* @param $resourceName
|
|
* @param null $paged
|
|
* @param null $count
|
|
* @param array $where
|
|
* @param null $order
|
|
* @param string $selectList
|
|
* @param null $joinData
|
|
* @param null $groupBy
|
|
* @param bool $fetchRow
|
|
* @return Zend_Paginator
|
|
* @throws Zend_Exception
|
|
* @throws Zend_Paginator_Exception
|
|
*/
|
|
public function getListDefault($resourceName, $paged = null, $count = null, $where = array(), $order = null, $selectList = '*', $joinData = null, $groupBy = null, $fetchRow = false, $having = false)
|
|
{
|
|
$resource = $this->getResource($resourceName);
|
|
|
|
// definizione della select list
|
|
$selectList = (!is_null($selectList)) ? $selectList : $resource->getDefaultSelectColumns();
|
|
if (is_string($selectList)) {
|
|
$selectList = explode(',', $selectList);
|
|
}
|
|
$select = $resource->getAdapter()->select()->from($resource->getTableName(), $selectList);
|
|
|
|
//Gestione dell'eventuale Join
|
|
$joinData = (!is_null($joinData)) ? $joinData : $resource->getDefaultJoinData();
|
|
if (is_array($joinData)) {
|
|
$select = $this->applicateJoinData($select, $joinData);
|
|
}
|
|
|
|
//gestione dei parametri di ricerca
|
|
if (is_array($where)) {
|
|
foreach ($where as $key => $value) {
|
|
// se trovo l'operatore '#OR' o '#ANDOR' significa che devo applicare l'or per gli elementi passati nel campo value, NB: il value deve essere una string separata da virgole
|
|
if (preg_match("/#OR/", $key)) { // #ANDOR accoda la query es: WHERE ... OR (nome_campo = ?)
|
|
$select = $this->applicateOrWhere($select, $key, $value, '#OR');
|
|
} else if (preg_match("/#ANDOR/", $key)) { // #ANDOR compone la query es: WHERE ... AND ( campo1 = ? OR campo2 = ?)
|
|
|
|
//salvo le condizioni presenti e resetto temporaneamente le condizini
|
|
$oldWhereConditions = $select->getPart(Zend_Db_Select::WHERE);
|
|
$select->reset(Zend_Db_Select::WHERE);
|
|
|
|
// genero le condizioni or
|
|
$select = $this->applicateOrWhere($select, $key, $value, '#ANDOR');
|
|
|
|
// recupero le condizioni or generate e resetto di nuovo tutte le condizioni
|
|
$orWhereConditions = $select->getPart(Zend_Db_Select::WHERE);
|
|
$select->reset(Zend_Db_Select::WHERE);
|
|
|
|
// reimposto le vecchie condizioni e accodo le nuove condizioni or
|
|
if ($oldWhereConditions) $select->where(implode(' ', $oldWhereConditions));
|
|
$select->where(implode(' ', $orWhereConditions));
|
|
|
|
} else {
|
|
//Di default utilizzo where con la AND
|
|
$select->where($key, $value);
|
|
}
|
|
}
|
|
}
|
|
|
|
//Gestione dell'eventuale grouBy
|
|
if ($groupBy) {
|
|
$select->group($groupBy);
|
|
}
|
|
|
|
//gestione dell'ordinamento
|
|
$order = (!$order) ? $resource->getDefaultOrder() : $order;
|
|
if (is_string($order)) {
|
|
$tmpOrder = explode(',', $order);
|
|
foreach ($tmpOrder as &$ord) {
|
|
// il '.' serve a definire il nome della tabella altrimenti imposto quella di default della risorsa che chiama la query
|
|
if (!preg_match("/\./", $ord)) {
|
|
$ord = $resource->getTableName() . "." . trim($ord);
|
|
}
|
|
|
|
// Se non esiste un verso di ordinamento assegno quello di default della risorsa per ogni campo ordinamento passato
|
|
if (!preg_match("/(ASC|DESC|desc|asc)$/", $ord)) {
|
|
$ord = explode(' ', trim($ord))[0] . ' ' . strtoupper($resource->getDefaultTipoOrder());
|
|
}
|
|
}
|
|
|
|
$order = $tmpOrder;
|
|
}
|
|
|
|
$select->order($order);
|
|
|
|
//Gestione dell'eventuale grouBy
|
|
if ($having && is_array($having)) {
|
|
foreach (array_keys($having) as $key) {
|
|
$select->having($key, $having[$key]);
|
|
}
|
|
}
|
|
|
|
// Zend_Registry::get('log')->info(print_r($select->__toString(), true));
|
|
|
|
//Esecuzione della query di ricerca
|
|
if (null !== $paged && null !== $count) {
|
|
$adapter = new Zend_Paginator_Adapter_DbSelect($select);
|
|
$paginator = new Zend_Paginator($adapter);
|
|
$paginator->setItemCountPerPage($count)->setCurrentPageNumber((int)$paged);
|
|
|
|
return $paginator;
|
|
}
|
|
$stmt = $resource->getAdapter()->query($select->__toString());
|
|
|
|
//Gestione del Fetch
|
|
if ($fetchRow)
|
|
return $stmt->fetch();
|
|
else
|
|
return $stmt->fetchAll();
|
|
}
|
|
|
|
/**
|
|
* @param $resourceName
|
|
* @param $where
|
|
* @param null $order
|
|
* @param null $selectList
|
|
* @param null $joinData
|
|
* @param null $groupBy
|
|
* @return Zend_Paginator
|
|
* @throws Zend_Exception
|
|
* @throws Zend_Paginator_Exception
|
|
*/
|
|
public function getFiltered($resourceName, $where, $order = null, $selectList = null, $joinData = null, $groupBy = null)
|
|
{
|
|
return $this->getList($resourceName, null, null, $where, $order, $selectList, $joinData, $groupBy, true);
|
|
}
|
|
|
|
/**
|
|
* Con questa funzione posso recuperare il numero di elementi di una tabella in base a parametri
|
|
* @param $resourceName
|
|
* @param $where
|
|
*
|
|
* @return Zend_Paginator
|
|
*/
|
|
public function countFiltered($resourceName, $where)
|
|
{
|
|
//Definizione della risorsa
|
|
$resource = $this->getResource($resourceName);
|
|
$select = $resource->getAdapter()->select()->from($resource->getTableName(), 'COUNT(*) as num');
|
|
|
|
//Applico le eventuali condizioni di ricerca
|
|
foreach ($where as $key => $value) {
|
|
$select->where($key, $value);
|
|
}
|
|
|
|
$stmt = $resource->getAdapter()->query($select->__toString());
|
|
|
|
return $stmt->fetchColumn(0);
|
|
}
|
|
|
|
/**
|
|
* Questa funzione passato il nome della colonna su cui cercare cerca il valore scelto;
|
|
* l'operatore di default è 'uguale'
|
|
* altriemnti è possibile specificarne un altro trimete il parametro @op
|
|
*
|
|
* @param $resourceName
|
|
* @param $columnName
|
|
* @param $value
|
|
* @param $fetchRow | Se impostato a true ritorna la riga come oggetto
|
|
* @param $op
|
|
* @param $joinData | per eseguire un join con altre tabelle
|
|
*
|
|
* @return mixed
|
|
*/
|
|
public function getByColumnName($resourceName, $columnName, $value, $op = "=", $fetchRow = false, $order = null, $joinData = null)
|
|
{
|
|
|
|
$resource = $this->getResource($resourceName);
|
|
|
|
//GESTIONE OPERATORI
|
|
switch ($op) {
|
|
case'LIKE':
|
|
$value = "%" . $value . "%";
|
|
break;
|
|
case'LIKEPRE':
|
|
$value = "%" . $value;
|
|
break;
|
|
case'LIKEPOST':
|
|
$value = $value . "%";
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
$select = $resource->getAdapter()->select()->from($resource->getTableName());
|
|
|
|
//Gestione dell'eventuale Join
|
|
if (is_array($joinData)) {
|
|
$select = $this->applicateJoinData($select, $joinData);
|
|
}
|
|
|
|
$select->where($columnName . ' ' . $op . ' ?', $value);
|
|
|
|
if ($order != null && (is_array($order) || is_string($order))) {
|
|
$select->order($order);
|
|
}
|
|
|
|
if ($fetchRow) {
|
|
if ($order != null && (is_array($order) || is_string($order))) {
|
|
return $resource->fetchRow($resource->select()->where($columnName . ' ' . $op . ' ?', $value)->order($order));
|
|
} else {
|
|
return $resource->fetchRow($resource->select()->where($columnName . ' ' . $op . ' ?', $value));
|
|
}
|
|
} else {
|
|
return $resource->getAdapter()->query($select->__toString())->fetch();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param $query
|
|
* @param null $params
|
|
* @param bool $fetchRow
|
|
* @return mixed
|
|
*
|
|
* @throws App_Controller_Errors_WebServiceError
|
|
*/
|
|
public function customQuery($query, $params = null, $fetchRow = false)
|
|
{
|
|
|
|
$resource = $this->getResource('Abstract');
|
|
$stmt = $resource->getAdapter()->query($query, $params);
|
|
|
|
//Gestione del Fetch
|
|
if ($fetchRow)
|
|
return $stmt->fetch();
|
|
else
|
|
return $stmt->fetchAll();
|
|
}
|
|
|
|
/**
|
|
* @param $select
|
|
* @param $joinData
|
|
* @return mixed
|
|
*
|
|
* @throws App_Controller_Errors_WebServiceError
|
|
*/
|
|
private function applicateJoinData($select, $joinData)
|
|
{
|
|
|
|
if (!isset($joinData[0])) {
|
|
if (!array_key_exists(self::JOIN_TABLE_NAME, $joinData))
|
|
throw new App_Controller_Errors_WebServiceError("Nome tabella per il join non trovato");
|
|
|
|
if (!array_key_exists(self::JOIN_CONDITION_NAME, $joinData))
|
|
throw new App_Controller_Errors_WebServiceError("Nome del campo di condizione per il join non trovato");
|
|
|
|
$colonne = (!$joinData[self::JOIN_COLUMNS_NAME]) ? array('*') : $joinData[self::JOIN_COLUMNS_NAME];
|
|
$joinFunctionName = (in_array($joinData[self::JOIN_TYPE], self::JOIN_FUNCTION_NAME_ALLOWED)) ? $joinData[self::JOIN_TYPE] : 'join';
|
|
|
|
return $select->$joinFunctionName($joinData[self::JOIN_TABLE_NAME], $joinData[self::JOIN_CONDITION_NAME], $colonne);
|
|
} else { // Gestione di più join contemporanei
|
|
foreach ($joinData as $key => $join) {
|
|
if (!array_key_exists(self::JOIN_TABLE_NAME, $join))
|
|
throw new App_Controller_Errors_WebServiceError("Nome tabella per il join non trovato per il join index: [$key]");
|
|
|
|
if (!array_key_exists(self::JOIN_CONDITION_NAME, $join))
|
|
throw new App_Controller_Errors_WebServiceError("Nome del campo di condizione per il join non trovato per il join index: [$key]");
|
|
|
|
$colonne = (!$join[self::JOIN_COLUMNS_NAME]) ? array('*') : $join[self::JOIN_COLUMNS_NAME];
|
|
$joinFunctionName = (in_array($join[self::JOIN_TYPE], self::JOIN_FUNCTION_NAME_ALLOWED)) ? $join[self::JOIN_TYPE] : 'join';
|
|
|
|
$select->$joinFunctionName($join[self::JOIN_TABLE_NAME], $join[self::JOIN_CONDITION_NAME], $colonne);
|
|
}
|
|
return $select;
|
|
}
|
|
|
|
}
|
|
|
|
private function applicateOrWhere($select, string $keyNomeCampo, $valoriOr, string $op = '#OR')
|
|
{
|
|
|
|
$valueOrDaApplicare = null;
|
|
if (is_string($valoriOr))
|
|
$valueOrDaApplicare = explode(',', $valoriOr);
|
|
elseif (is_array($valoriOr))
|
|
$valueOrDaApplicare = $valoriOr;
|
|
|
|
if (!$valueOrDaApplicare) {
|
|
throw new App_Controller_Errors_WebServiceError("Valori per la condizione '$op' non validi per generare la query", App_Controller_Errors_WebServiceError::WEBSERVICE_GENERIC_ERROR);
|
|
}
|
|
|
|
$keyDaApplicare = str_replace($op, '=', $keyNomeCampo);
|
|
|
|
if (is_array($valueOrDaApplicare) && count($valueOrDaApplicare) > 0) {
|
|
foreach ($valueOrDaApplicare as $val) {
|
|
$select->orwhere($keyDaApplicare, $val);
|
|
}
|
|
}
|
|
|
|
return $select;
|
|
}
|
|
|
|
}
|