NxTIC/manager/lightdb.php

265 lines
7.0 KiB
PHP
Executable File
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace manager;
class lightdb{
// REPERTOIRE RACINE DE TOUTES LES BDD
public static $default_root = __ROOT__.'/';
// ATTRIBUTS
private $root;
private $dbname;
private $dir;
private $index;
private $driver;
private $line;
private $tmp;
/* CONSTRUCTEUR -> CREER LES FICHIERS S'ILS N'EXISTENT PAS SINON, RECUPERE LES DONNES
*
* @dbname<String> Nom de la base de données
*
*/
public function __construct($dbname, $root=null){
/* [0] On récupère les attributs
=========================================================*/
$this->root = is_null($root) ? self::$default_root : $root;
$this->dbname = $dbname;
$this->dir = $this->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<String> Index pour lequel on veut la ligne et le hash
*
* @return Index<Array> 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<String> Clé qui permettra l'accès direct
* @data<mixed*> Objet qui sera enregistré dans la base
*
* @return status<Boolean> 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<String> Clé associée à la valeur à récupérer
*
* @return data<mixed*> 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<String> Clé de l'entrée à supprimer
*
* @return status<Boolean> 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<typeParam> Description du param
*
* @return nomRetour<typeRetour> 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; }
}