CREER LES FICHIERS S'ILS N'EXISTENT PAS SINON, RECUPERE LES DONNES * * @dbname Nom de la base de données * */ public function __construct($dbname){ /* [0] On récupère les attributs =========================================================*/ $this->dbname = $dbname; $this->dir = self::$root.$dbname.'/'; /* [1] Création du répertoire s'il n'existe pas =========================================================*/ if( !is_dir($this->dir) ) mkdir($this->dir); /* [2] Création du fichier d'index ou récupération =========================================================*/ /* (1) Si le fichier n'existe pas, on le crée */ if( !file_exists($this->dir.'index') ){ $fIndex = new \SplFileObject($this->dir.'index', 'w'); $fIndex->fwrite('[]'); $fIndex = null; } /* (2) On récupère le contenu du fichier */ $fIndex = new \SplFileObject($this->dir.'index'); $fIndex->seek(0); $index = json_decode( $fIndex->fgets(), true ); // Si erreur de parsage, on retourne une erreur if( is_null($index) ) return; $this->index = $index; /* [3] Initialisation du gestionnaire d'acces (SplFileObject) =========================================================*/ /* (1) Si le fichier n'existe pas, on le crée */ if( !file_exists($this->dir.'data') ) file_put_contents($this->dir.'data', '' ); /* (2) On place un 'driver' sur le fichier */ $this->driver = new \SplFileObject($this->dir.'data', 'r+'); // $this->driver->setFlags( \SplFileObject::SKIP_EMPTY ); /* (3) On récupère le nombre de lignes */ $this->line = -1; while( !$this->driver->eof() ){ $this->line++; $this->driver->fgetcsv(); } } public function close(){ $this->driver = null; } /* RETOURNE LA LISTE DES INDEX * * @i Index pour lequel on veut la ligne et le hash * * @return Index Tableau associatif contenant le hash et la ligne * */ public function index($i=null){ return is_numeric($i) ? $this->index : $this->index; } /* INSERTION D'UNE ENTREE DANS LA BASE DE DONNEES * * @key Clé qui permettra l'accès direct * @data Objet qui sera enregistré dans la base * * @return status Retourne TRUE si tout s'est bien passé, sinon FALSE * */ public function insert($key, $data){ /* (1) On vérifie que la clé est unique */ if( array_key_exists($key, $this->index) ) return true; $key = (string) $key; /* (2) On ajoute les données aux fichier */ $json_data = json_encode($data); $this->driver->seek($this->line); $this->line++; $written = $this->driver->fwrite( $json_data.PHP_EOL ); // Si erreur d'écriture, on retourne FALSE if( is_null($written) ) return false; /* (3) On enregistre l'index */ $this->index[$key] = array( 'line' => $this->line - 1, 'hash' => sha1($json_data) ); /* (4) On enregistre le fichier index */ $fIndex = new \SplFileObject($this->dir.'index', 'w'); $fIndex->fwrite( json_encode($this->index) ); $fIndex = null; return true; } /* RENVOIE LES DONNEES ASSOCIEES A UNE CLE DONNEE * * @key Clé associée à la valeur à récupérer * * @return data Renvoie la valeur associée à la clé, FALSE si erreur * */ public function fetch($key){ /* (1) On vérifie que la clé existe bien */ if( !array_key_exists($key, $this->index) ) return false; /* (2) On récupère la ligne */ $line = $this->index[$key]['line']; /* (3) On récupère le contenu */ $this->driver->seek($line); $json = json_decode( $this->driver->current(), true ); // Si erreur de parsage if( is_null($json) ) return false; return $json; } /* SUPPRIME UNE ENTREE DE CLE DONNEE DE LA BASE DE DONNEES * * @key Clé de l'entrée à supprimer * * @return status Retourne TRUE si tout s'est bien passé, sinon FALSE * */ public function delete($key){ /* (1) On vérifie l'existence de la clé */ if( !array_key_exists($key, $this->index) ) return true; // On considère que l'action souhaitée est effectuée $line = $this->index[$key]['line']; /* (2) On réarrange la bd pour supprimer la ligne */ $tmpfilename = __ROOT__.'/tmp/'.uniqid().'.dat'; $tmpfile = new \SplFileObject($tmpfilename, 'w'); $this->driver->seek(0); // On recopie toutes les lignes sauf celle à supprimer dans un fichier temporaire while( $this->driver->key() < $this->line ){ if( $this->driver->key() != $line ) $tmpfile->fwrite( $this->driver->current() ); $this->driver->next(); } // On décrémente le nb de lignes $this->line--; $tmpfile = null; /* (3) On remplace le fichier original par le fichier temporaire */ $this->driver = null; rename($tmpfilename, $this->dir.'data'); $this->driver = new \SplFileObject($this->dir.'data', 'r+'); /* (3) On supprime la ligne de l'index */ unset( $this->index[$key] ); /* (4) On met à jour les index des lignes déplacées */ foreach($this->index as $i=>$indexData) if( $indexData['line'] > $line ) $this->index[$i]['line']--; // on décrémente les lignes au dessus de la ligne supprimée /* (5) On enregistre le fichier index */ $fIndex = new \SplFileObject($this->dir.'index', 'w'); $fIndex->fwrite( json_encode($this->index) ); $fIndex = null; return true; } /* RENVOIE LES DONNEES ASSOCIEES A UN CHAMP DE RECHERCHE * * @nomParam Description du param * * @return nomRetour Description du retour * */ public function filter($data){ /* (1) Si @data est un tableau associatif */ if( is_array($data) ){ $filtered = array(); foreach($this->index as $i=>$indexData){ $this->driver->seek( $indexData['line'] ); $dbData = json_decode( $this->driver->fgets(), true ); foreach($data as $key=>$value) if( isset($dbData[$key]) && preg_match("#$value#", $dbData[$key]) ){ $filtered[$i] = $dbData; break; } } return $filtered; /* (2) Sinon on compare @data en tant que valeur simple */ }else{ $this->tmp = sha1( json_encode($data) ); return array_filter($this->index, array($this, 'simpleFilter')); } } protected function simpleFilter($e){ return $e['hash'] == $this->tmp; } }