<?php
    /**
    *
    * copyright (c) 2015-2024 Heliac Technologies
    * license http://opensource.org/licenses/gpl-license.php GNU GPL v3 
    *
    * Classe per eseguire le operazioni sul database. Prende in input un array con i
    * campi host, utente, password, nome e codifica del database e crea un'istanza del database
    * su cui possiamo eseguire le query. 
    * 
    * Dispone di metodi per eseguire più rapidamente le operazioni lettura, scrittura,
    * conteggio, esecuzione di più query e altro ancora
    * 
    * Modalità debug
    * 
     * tra i parametri in input c'è la possibilità di selezionare se siamo o meno in modalità debug
     * (debug=si per attivare tale modalità). A seconda se questa modalità è attiva o meno la classe
     * mostrerà l'errore oppure no 
    * 
    */

    class DbManager {
        public $db;
        public $nome;
        public $host;
        public $utente;
        public $password;
        public $debug;
        public $ultimaQueryEseguita;

        public function __construct($costantiDatabase) {
            $database = new mysqli($costantiDatabase["host"], $costantiDatabase["utenteDb"], $costantiDatabase["passwordDb"], $costantiDatabase["nomeDb"]);

            if (mysqli_connect_errno()) {
                echo "Errore durante la connessione al Database: ".mysqli_connect_error();
                exit();
            }
            $this->db = $database;
            $this->db->set_charset($costantiDatabase["codifica"]);
            $this->nome     = $costantiDatabase["nomeDb"];
            $this->host     = $costantiDatabase["host"];
            $this->utente   = $costantiDatabase["utenteDb"];
            $this->password = $costantiDatabase["passwordDb"];
            $this->debug    = $costantiDatabase["debug"];
            $this->ultimaQueryEseguita = "";
        }

        /*
         * metodo che consente di eseguire l'escape string di una stringa
        *  @param la $stringa su cui eseguire l'escape
        */
        public function escapeString($stringa) {
            return $this->db->real_escape_string($stringa);
        }

        /*
         * metodo che consente di eseguire una query in lettura
        *  @param la $query la query da eseguire
        */
        public function eseguiQueryLettura($query) {
            if(!$risQuery = $this->db->query($query)) {
                if($this->debug=="si") {	//stampa l'errore solo se questi sono abilitati		
                    echo "Errore durante l'esecuzione della query: ".$this->db->error;
                    echo "<br>$query";
                }
                exit();
            }
            else {
                $this->ultimaQueryEseguita = $query; // la query viene memorizzata come ultima query eseguita solo se non ci sono errori
                return $risQuery;
            }
        }

        /*
         * metodo per eseguire una query in cui viene creato un elemento. 
         * Restituisce l'id dell'elemento creato
         * @param la $query la query da eseguire
        */
        public function eseguiQueryCreazione($query) {
            if(!$risQuery = $this->db->query($query)) {
                if($this->debug=="si") {	//stampa l'errore solo se questi sono abilitati		
                    echo "Errore durante l'esecuzione della query: ".$this->db->error;
                    echo "<br>$query";
                }
                exit();
            }
            else {
                $this->ultimaQueryEseguita = $query; // la query viene memorizzata come ultima query eseguita solo se non ci sono errori
                return $this->idUltimoElemento();
            }
        }

        /*
         * metodo che consente di eseguire una query in scrittura
         * @param la $query la query da eseguire
         */
        public function eseguiQueryScrittura($query) {
            if(!$risQuery = $this->db->query($query)) {
                if($this->debug=="si") {	//stampa l'errore solo se questi sono abilitati		
                    echo "Errore durante l'esecuzione della query: ".$this->db->error;
                    echo "<br>$query";
                }
                exit();
            }
            $this->ultimaQueryEseguita = $query; // la query viene memorizzata come ultima query eseguita solo se non ci sono errori
        }
        
        /*
         * metodo che consente di eseguire la cancellazione di un elemento dalla tabella
         * passata in input. La query viene costruita con i parametri passati in input
         * @param $tabella la tabella sulla quale eseguire la query
         * @param $id l'id dell'oggetto da eliminare
         */
        public function eseguiQueryCancellazione($tabella,$id) {
            $query = "DELETE FROM $tabella WHERE id=$id";
            if(!$risQuery = $this->db->query($query)) {
                if($this->debug=="si") {	//stampa l'errore solo se questi sono abilitati		
                    echo "Errore durante l'esecuzione della query: ".$this->db->error;
                    echo "<br>$query";
                }
                exit();
            }
            $this->ultimaQueryEseguita = $query; // la query viene memorizzata come ultima query eseguita solo se non ci sono errori
        }
        
       /*
        * metodo che consente di eseguire una query in lettura con la parola chiave DISTINCT
        *  @param $colonna la colonna argomento di DISTINCT
        *  @param $tabella la tabella su cui eseguire la query
        *  @param $parametri è  un array associativo che contiene caratteri opzionali
        */
        public function eseguiQueryDistinct($colonna,$tabella,$parametri = null) {
            $query = "SELECT DISTINCT($colonna) FROM $tabella";
            if($parametri!=null) {
                $query = "SELECT DISTINCT(*) FROM $tabella WHERE ";
                foreach($parametri as $parametro=>$valore) {
                    if(is_numeric($valore)) {
                        $query .= " $parametro = $valore AND ";
                    }
                    else {
                        $query .= " $parametro LIKE '$valore' AND ";
                    }
                }
                $query = substr($query,0,strlen($query)-5);
            }
            
            return $this->eseguiQueryLettura($query);
        }

        /*
         * legge una singola riga del database, restituendo l'array associativo contenente 
         * tutti i suoi elementi, false se non trova l'elemento corrispondente
         * 
         * @param $tabella la tabella sulla quale eseguire la query
         * @param $valoreDaCercare contiene il valore della colonna da cercare
         * @param $colonnaDaCercare contiene il nome della colonna da cercare. È un campo opzionale,
         * se non viene inserito usa il valore di default che è id
         * 
         */
        public function leggiSingolaRiga($tabella,$valoreDaCercare,$colonnaDaCercare = "id") {
            if(is_numeric($valoreDaCercare)) {
                $query = "SELECT * FROM $tabella  WHERE $colonnaDaCercare = $valoreDaCercare";
            }
            else {
                $query = "SELECT * FROM $tabella  WHERE $colonnaDaCercare LIKE '$valoreDaCercare'";
            }
            
            $risQuery = $this->eseguiQueryLettura($query);
            if($risQuery->num_rows>0) {           
                return $risQuery->fetch_assoc();
            }
            else {
                return false;
            }
        }
        
        /*
         * restituisce l'ultima occorrenza inserita nella tabella selezionata, restituendo l'array associativo contenente 
         * tutti i suoi elementi, false se la tabella è vuota
         * 
         * @param $tabella la tabella sulla quale eseguire la query
         * @param $colonnaOrdinamento contiene il nome della colonna con cui effettuare l'ordinamento. È un campo opzionale,
         * se non viene inserito usa il valore di default che è id
         * 
         */
        public function ultimaRigaTabella($tabella,$colonnaOrdinamento = "id") {
           
            $query = "SELECT * FROM $tabella  ORDER  BY $colonnaOrdinamento DESC";
            $risQuery = $this->eseguiQueryLettura($query);
            if($risQuery->num_rows>0) {                    
                return $risQuery->fetch_assoc();
            }
            else {
                return false;
            }
        }
        
        /*
         * metodo per eseguire più query in scrittura, 
         * @param $arrayQuery prende in input un array di query
         */
        public function eseguiInsiemeDiQuery($arrayQuery) {
            foreach($arrayQuery as $query) {
                if(!$this->db->query($query) && $this->debug=="si") {
                    echo "Errore durante l'esecuzione della query: ".$this->db->error;
                    echo "<br>$query";
                    exit();
                }
            }
        }

        /*
         * metodo che restituisce il numero di elementi  della tabella passata come parametro
         * @parametri 		è un array associativo che contiene caratteri opzionali 
         * @colonnaDistinct 	se presente, la query verrà eseguita con la clausola DISTINCT e il valore di questa colonna nel COUNT
         */
        public function contaRigheTabella($tabella,$parametri=null,$colonnaDistinct="") {
            if($colonnaDistinct!="") {
                $query = "SELECT COUNT(DISTINCT $colonnaDistinct) FROM $tabella";
            }
            else {
                $query = "SELECT COUNT(*) FROM $tabella";
            }
            
            if($parametri!=null) {
                $query = "SELECT COUNT(*) FROM $tabella WHERE ";
                foreach($parametri as $parametro=>$valore) {
                    if(is_numeric($valore)) {
                        $query .= " $parametro = $valore AND ";
                    }
                    else if($valore == null) {
                        $query .= "$parametro IS NULL AND ";
                    }
                    else if($valore[0]==="<" || $valore[0]===">") {
                        $query .= "$parametro $valore AND ";
                    }
                    else {
                        $query .= " $parametro LIKE '$valore' AND ";
                    }
                }
                $query = substr($query,0,strlen($query)-5);
            }
            $ris = $this->eseguiQueryLettura($query);
            $arrayConteggio = $ris->fetch_array(MYSQLI_NUM);
            return $arrayConteggio[0];
        }
        
        /*
         * metodo che restituisce la somma dei valori di una colonna della tabella passata come parametro
         * @parametri è  un array associativo che contiene caratteri opzionali
         * se vengono inseriti il metodo esegue
         */        
        public function sommaValoriColonna($elemento,$tabella,$parametri=null) {
            if($parametri==null) {
                $query = "SELECT SUM($elemento) FROM $tabella";
            }
            else {
                $query = "SELECT SUM($elemento) FROM $tabella WHERE ";
                foreach($parametri as $parametro=>$valore) {
                    if(is_numeric($valore)) {
                        $query .= " $parametro = $valore AND ";
                    }
                    else if($valore[0]==="<" || $valore[0]===">") {
                        $query .= "$parametro $valore AND ";
                    }
                    else {
                        $query .= " $parametro LIKE '$valore' AND ";
                    }
                }
                $query = substr($query,0,strlen($query)-5);
            }

            $ris = $this->eseguiQueryLettura($query);
            $arrayConteggio = $ris->fetch_array(MYSQLI_NUM);
            return (is_numeric($arrayConteggio[0])) ? $arrayConteggio[0] : 0;
        }
        
        /*
         * Questo metodo esegue il dump del database in un determinato file
         */
        public function esportaDatabaseSuFile($percorso) {
            $nomeFile = date("d-m-Y")."$this->nome.sql";
            exec("mysqldump --user={$this->utente} --password={$this->password} --host={$this->host} {$this->nome} --result -file='$percorso/$nomeFile' 2>&1");
            return ($percorso."/$nomeFile");
        }
        
        /*
         * Questo metodo esegue il dump del database in un determinato file
         */
        public function importaDatabaseDaFile($percorso) {
            $sql = file_get_contents($percorso);
            $this->db->multi_query($sql);
        }
        
        /*
         * metodo che restituisce le tabelle del database in uso
         */
        public function elencoTabelle() {
            $query = "SHOW tables";
            return $this->eseguiQueryLettura($query);
        }

        /*
         * metodo che restituisce le colonne della tabella passata come parametro
         */      
        public function elencoColonneTabella($tabella) {
            $query = "SHOW COLUMNS FROM $tabella";
            return $this->eseguiQueryLettura($query);
        }
        
        /*
         * metodo che consente di ottenere l'id dell'ultimo elemento memorizzato nel db
         */
        public function idUltimoElemento() {
            return $this->db->insert_id;
        }
        
        public function getUltimaQueryEseguita() {
            return $this->ultimaQueryEseguita;
        }
        
        public function getInformazioniServer() {
            $query  = "SELECT VERSION()";
            $ris    = $this->eseguiQueryLettura($query);
            $versione = $ris->fetch_array(MYSQLI_NUM);
            return $versione[0];
        }
    }
