Subversion Repositories Applications.framework

Compare Revisions

Ignore whitespace Rev 247 → Rev 248

/trunk/framework/CacheFichier.php
50,8 → 50,8
*/
protected $options = array(
'stockage_chemin' => null,
'fichier_verrou' => true,// file_locking
'controle_lecture' => true,// controle de lecture
'fichier_verrou' => true,
'controle_lecture' => true,
'controle_lecture_type' => 'crc32',
'dossier_niveau' => 0,
'dossier_umask' => 0700,
65,7 → 65,7
*
* @var array
*/
protected $metadonnees = array(); // metadatasArray
protected $metadonnees = array();
 
 
/**
76,12 → 76,14
* @return void
*/
public function __construct(array $options = array()) {
$this->setOptions($options);
 
if (isset($this->options['prefixe_fichier'])) {
if (!preg_match('~^[a-zA-Z0-9_]+$~D', $this->options['prefixe_fichier'])) {
trigger_error("Préfixe de nom de fichier invalide : doit contenir seulement [a-zA-Z0-9_]", E_USER_WARNING);
}
}
if ($this->_options['metadonnees_max_taille'] < 10) {
if ($this->options['metadonnees_max_taille'] < 10) {
trigger_error("Taille du tableau des méta-données invalide, elle doit être > 10", E_USER_WARNING);
}
if (isset($options['dossier_umask']) && is_string($options['dossier_umask'])) {
93,8 → 95,20
$this->options['fichier_umask'] = octdec($this->options['fichier_umask']);
}
}
private function setOptions($options) {
while (list($nom, $valeur) = each($options)) {
if (!is_string($nom)) {
trigger_error("Nom d'option incorecte : $nom", E_USER_WARNING);
}
$nom = strtolower($nom);
if (array_key_exists($nom, $this->options)) {
$this->options[$nom] = $valeur;
}
}
}
 
private function setEmplacement($emplacement) {
public function setEmplacement($emplacement) {
if (!is_dir($emplacement)) {
trigger_error("L'emplacement doit être un dossier.", E_USER_WARNING);
}
155,37 → 169,43
* @param int $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime)
* @return boolean true if no problem
*/
public function save($data, $id, $tags = array(), $specificLifetime = false) {
public function sauver($donnees, $id, $tags = array(), $duree_vie_specifique = false) {
clearstatcache();
$file = $this->getFichierNom($id);
$path = $this->getChemin($id);
if ($this->_options['hashed_directory_level'] > 0) {
if (!is_writable($path)) {
$fichier = $this->getFichierNom($id);
$chemin = $this->getChemin($id);
$resultat = true;
if ($this->options['dossier_niveau'] > 0) {
if (!is_writable($chemin)) {
// maybe, we just have to build the directory structure
$this->lancerMkdirEtChmodRecursif($id);
}
if (!is_writable($path)) {
return false;
if (!is_writable($chemin)) {
$resultat = false;
}
}
if ($this->_options['read_control']) {
$hash = $this->genererCleSecu($data, $this->_options['read_control_type']);
} else {
$hash = '';
if ($resultat === true) {
if ($this->options['controle_lecture']) {
$cle_secu = $this->genererCleSecu($donnees, $this->options['controle_lecture_type']);
} else {
$cle_secu = '';
}
$metadonnees = array(
'hash' => $cle_secu,
'mtime' => time(),
'expiration' => $this->getTimestampExpiration($duree_vie_specifique),
'tags' => $tags
);
 
if (! $resultat = $this->setMetadonnees($id, $metadonnees)) {
// TODO : ajouter un log
} else {
$resultat = $this->setContenuFichier($fichier, $donnees);
}
}
$metadatas = array(
'hash' => $hash,
'mtime' => time(),
'expire' => $this->_expireTime($this->getLifetime($specificLifetime)),
'tags' => $tags
);
$res = $this->_setMetadatas($id, $metadatas);
if (!$res) {
$this->_log('Zend_Cache_Backend_File::save() / error on saving metadata');
return false;
}
$res = $this->setContenuFichier($file, $data);
return $res;
return $resultat;
}
 
/**
221,7 → 241,7
public function nettoyer($mode = Cache::NETTOYAGE_MODE_TOUS, $tags = array()) {
// We use this protected method to hide the recursive stuff
clearstatcache();
return $this->nettoyerFichiers($this->options['stockage_dossier'], $mode, $tags);
return $this->nettoyerFichiers($this->options['stockage_chemin'], $mode, $tags);
}
 
/**
229,9 → 249,8
*
* @return array array of stored cache ids (string)
*/
public function getIds()
{
return $this->_get($this->_options['cache_dir'], 'ids', array());
public function getIds() {
return $this->analyserCache($this->options['stockage_chemin'], 'ids', array());
}
 
/**
239,9 → 258,8
*
* @return array array of stored tags (string)
*/
public function getTags()
{
return $this->_get($this->_options['cache_dir'], 'tags', array());
public function getTags() {
return $this->analyserCache($this->options['stockage_chemin'], 'tags', array());
}
 
/**
252,9 → 270,8
* @param array $tags array of tags
* @return array array of matching cache ids (string)
*/
public function getIdsMatchingTags($tags = array())
{
return $this->_get($this->_options['cache_dir'], 'matching', $tags);
public function getIdsAvecLesTags($tags = array()) {
return $this->analyserCache($this->options['stockage_chemin'], 'matching', $tags);
}
 
/**
265,9 → 282,8
* @param array $tags array of tags
* @return array array of not matching cache ids (string)
*/
public function getIdsNotMatchingTags($tags = array())
{
return $this->_get($this->_options['cache_dir'], 'notMatching', $tags);
public function getIdsSansLesTags($tags = array()) {
return $this->analyserCache($this->options['stockage_chemin'], 'notMatching', $tags);
}
 
/**
278,9 → 294,8
* @param array $tags array of tags
* @return array array of any matching cache ids (string)
*/
public function getIdsMatchingAnyTags($tags = array())
{
return $this->_get($this->_options['cache_dir'], 'matchingAny', $tags);
public function getIdsAvecUnTag($tags = array()) {
return $this->analyserCache($this->options['stockage_chemin'], 'matchingAny', $tags);
}
 
/**
289,18 → 304,17
* @throws Zend_Cache_Exception
* @return int integer between 0 and 100
*/
public function getFillingPercentage()
{
$free = disk_free_space($this->_options['cache_dir']);
$total = disk_total_space($this->_options['cache_dir']);
public function getPourcentageRemplissage() {
$libre = disk_free_space($this->options['sotckage_chemin']);
$total = disk_total_space($this->options['sotckage_chemin']);
$pourcentage = 0;
if ($total == 0) {
Zend_Cache::throwException('can\'t get disk_total_space');
trigger_error("Impossible d'utiliser la fonction disk_total_space", E_USER_WARNING);
} else {
if ($free >= $total) {
return 100;
}
return ((int) (100. * ($total - $free) / $total));
$pourcentage = ($libre >= $total) ? 100 : ((int) (100. * ($total - $libre) / $total));
}
return $pourcentage;
}
 
/**
314,20 → 328,20
* @param string $id cache id
* @return array array of metadatas (false if the cache id is not found)
*/
public function getMetadatas($id)
{
$metadatas = $this->getMetadonneesFichier($id);
if (!$metadatas) {
return false;
public function getMetadonnees($id) {
if ($metadonnees = $this->getMetadonneesFichier($id)) {
if (time() > $metadonnees['expiration']) {
$metadonnees = false;
} else {
$metadonnees = array(
'expiration' => $metadonnees['expiration'],
'tags' => $metadonnees['tags'],
'mtime' => $metadonnees['mtime']
);
}
}
if (time() > $metadatas['expire']) {
return false;
}
return array(
'expire' => $metadatas['expire'],
'tags' => $metadatas['tags'],
'mtime' => $metadatas['mtime']
);
return $metadonnees;
}
 
/**
337,26 → 351,22
* @param int $extraLifetime
* @return boolean true if ok
*/
public function touch($id, $extraLifetime)
{
$metadatas = $this->getMetadonneesFichier($id);
if (!$metadatas) {
return false;
public function ajouterSupplementDureeDeVie($id, $supplement_duree_de_vie) {
$augmentation = true;
if ($metadonnees = $this->getMetadonneesFichier($id)) {
if (time() > $metadonnees['expiration']) {
$augmentation = false;
} else {
$metadonnees_nouvelle = array(
'hash' => $metadonnees['hash'],
'mtime' => time(),
'expiration' => $metadonnees['expiration'] + $supplement_duree_de_vie,
'tags' => $metadonnees['tags']
);
$augmentation = $this->setMetadonnees($id, $metadonnees_nouvelle);
}
}
if (time() > $metadatas['expire']) {
return false;
}
$newMetadatas = array(
'hash' => $metadatas['hash'],
'mtime' => time(),
'expire' => $metadatas['expire'] + $extraLifetime,
'tags' => $metadatas['tags']
);
$res = $this->_setMetadatas($id, $newMetadatas);
if (!$res) {
return false;
}
return true;
return $augmentation;
}
 
/**
527,77 → 537,76
if (is_file($fichier)) {
$fichier_nom = basename($fichier);
if ($this->etreFichierMeta($fichier_nom)) {
// in CLEANING_MODE_ALL, we drop anything, even remainings old metadatas files
// Pour le mode Cache::NETTOYAGE_MODE_TOUS, nous essayons de tous supprimer même les vieux fichiers méta
if ($mode != Cache::NETTOYAGE_MODE_TOUS) {
continue;
}
}
$id = $this->transformerNomFichierEnId($fichier_nom);
$metadatas = $this->getMetadonneesFichier($id);
if ($metadatas === FALSE) {
$metadatas = array('expire' => 1, 'tags' => array());
$metadonnees = $this->getMetadonneesFichier($id);
if ($metadonnees === FALSE) {
$metadonnees = array('expiration' => 1, 'tags' => array());
}
switch ($mode) {
case Zend_Cache::CLEANING_MODE_ALL:
$res = $this->remove($id);
if (!$res) {
// in this case only, we accept a problem with the metadatas file drop
$res = $this->supprimerFichier($file);
case Cache::NETTOYAGE_MODE_TOUS :
if ($resultat_suppression = $this->supprimer($id)) {
// Dans ce cas seulement, nous acception qu'il y ait un problème avec la suppresssion du fichier meta
$resultat_suppression = $this->supprimerFichier($fichier);
}
$resultat = $resultat && $res;
$resultat = $resultat && $resultat_suppression;
break;
case Zend_Cache::CLEANING_MODE_OLD:
if (time() > $metadatas['expire']) {
$resultat = $this->remove($id) && $resultat;
case Cache::NETTOYAGE_MODE_EXPIRATION :
if (time() > $metadonnees['expiration']) {
$resultat = $this->supprimer($id) && $resultat;
}
break;
case Zend_Cache::CLEANING_MODE_MATCHING_TAG:
$matching = true;
case Cache::NETTOYAGE_MODE_AVEC_LES_TAGS :
$correspondance = true;
foreach ($tags as $tag) {
if (!in_array($tag, $metadatas['tags'])) {
$matching = false;
if (!in_array($tag, $metadonnees['tags'])) {
$correspondance = false;
break;
}
}
if ($matching) {
$resultat = $this->remove($id) && $resultat;
if ($correspondance) {
$resultat = $this->supprimer($id) && $resultat;
}
break;
case Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG:
$matching = false;
case Cache::NETTOYAGE_MODE_SANS_LES_TAGS :
$correspondance = false;
foreach ($tags as $tag) {
if (in_array($tag, $metadatas['tags'])) {
$matching = true;
if (in_array($tag, $metadonnees['tags'])) {
$correspondance = true;
break;
}
}
if (!$matching) {
$resultat = $this->remove($id) && $resultat;
if (!$correspondance) {
$resultat = $this->supprimer($id) && $resultat;
}
break;
case Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG:
$matching = false;
case Cache::NETTOYAGE_MODE_AVEC_UN_TAG :
$correspondance = false;
foreach ($tags as $tag) {
if (in_array($tag, $metadatas['tags'])) {
$matching = true;
if (in_array($tag, $metadonnees['tags'])) {
$correspondance = true;
break;
}
}
if ($matching) {
$resultat = $this->remove($id) && $resultat;
if ($correspondance) {
$resultat = $this->supprimer($id) && $resultat;
}
break;
default:
Zend_Cache::throwException('Invalid mode for clean() method');
trigger_error("Mode de nettoyage invalide pour la méthode nettoyer()", E_USER_WARNING);
break;
}
}
if ((is_dir($file)) and ($this->_options['hashed_directory_level']>0)) {
// Recursive call
$resultat = $this->nettoyerFichiers($file . DIRECTORY_SEPARATOR, $mode, $tags) && $resultat;
if ($mode=='all') {
// if mode=='all', we try to drop the structure too
@rmdir($file);
if ((is_dir($fichier)) and ($this->options['dossier_niveau'] > 0)) {
// Appel récursif
$resultat = $this->nettoyerFichiers($fichier.DS, $mode, $tags) && $resultat;
if ($mode == Cache::NETTOYAGE_MODE_TOUS) {
// Si mode == Cache::NETTOYAGE_MODE_TOUS, nous essayons de supprimer la structure aussi
@rmdir($fichier);
}
}
}
604,87 → 613,87
return $resultat;
}
 
protected function _get($dir, $mode, $tags = array()) {
if (!is_dir($dir)) {
protected function analyserCache($dossier, $mode, $tags = array()) {
if (!is_dir($dossier)) {
return false;
}
$result = array();
$prefix = $this->_options['file_name_prefix'];
$glob = @glob($dir . $prefix . '--*');
$resultat = array();
$prefixe = $this->options['fichier_prefixe'];
$glob = @glob($dossier.$prefixe.'--*');
if ($glob === false) {
// On some systems it is impossible to distinguish between empty match and an error.
return array();
}
foreach ($glob as $file) {
if (is_file($file)) {
$fileName = basename($file);
$id = $this->transformerNomFichierEnId($fileName);
$metadatas = $this->getMetadonneesFichier($id);
if ($metadatas === FALSE) {
foreach ($glob as $fichier) {
if (is_file($fichier)) {
$nom_fichier = basename($fichier);
$id = $this->transformerNomFichierEnId($nom_fichier);
$metadonnees = $this->getMetadonneesFichier($id);
if ($metadonnees === FALSE) {
continue;
}
if (time() > $metadatas['expire']) {
if (time() > $metadonnees['expiration']) {
continue;
}
switch ($mode) {
case 'ids':
$result[] = $id;
$resultat[] = $id;
break;
case 'tags':
$result = array_unique(array_merge($result, $metadatas['tags']));
$resultat = array_unique(array_merge($resultat, $metadonnees['tags']));
break;
case 'matching':
$matching = true;
$correspondance = true;
foreach ($tags as $tag) {
if (!in_array($tag, $metadatas['tags'])) {
$matching = false;
if (!in_array($tag, $metadonnees['tags'])) {
$correspondance = false;
break;
}
}
if ($matching) {
$result[] = $id;
if ($correspondance) {
$resultat[] = $id;
}
break;
case 'notMatching':
$matching = false;
$correspondance = false;
foreach ($tags as $tag) {
if (in_array($tag, $metadatas['tags'])) {
$matching = true;
if (in_array($tag, $metadonnees['tags'])) {
$correspondance = true;
break;
}
}
if (!$matching) {
$result[] = $id;
if (!$correspondance) {
$resultat[] = $id;
}
break;
case 'matchingAny':
$matching = false;
$correspondance = false;
foreach ($tags as $tag) {
if (in_array($tag, $metadatas['tags'])) {
$matching = true;
if (in_array($tag, $metadonnees['tags'])) {
$correspondance = true;
break;
}
}
if ($matching) {
$result[] = $id;
if ($correspondance) {
$resultat[] = $id;
}
break;
default:
Zend_Cache::throwException('Invalid mode for _get() method');
trigger_error("Mode invalide pour la méthode analyserCache()", E_USER_WARNING);
break;
}
}
if ((is_dir($file)) and ($this->_options['hashed_directory_level']>0)) {
// Recursive call
$recursiveRs = $this->_get($file . DIRECTORY_SEPARATOR, $mode, $tags);
if ($recursiveRs === false) {
$this->_log('Zend_Cache_Backend_File::_get() / recursive call : can\'t list entries of "'.$file.'"');
if ((is_dir($fichier)) and ($this->options['dossier_niveau'] > 0)) {
// Appel récursif
$resultat_analyse_recursive = $this->analyserCache($fichier.DS, $mode, $tags);
if ($resultat_analyse_recursive === false) {
// TODO : ajoute un log
} else {
$result = array_unique(array_merge($result, $recursiveRs));
$resultat = array_unique(array_merge($resultat, $resultat_analyse_recursive));
}
}
}
return array_unique($result);
return array_unique($resultat);
}
 
/**
692,11 → 701,12
*
* @return int expire time (unix timestamp)
*/
protected function _expireTime($lifetime) {
if ($lifetime === null) {
return 9999999999;
protected function getTimestampExpiration($duree_de_vie) {
if ($duree_de_vie === false) {
$duree_de_vie = 3600;
}
return time() + $lifetime;
$timestamp = ($duree_de_vie === null) ? 9999999999 : (time() + $duree_de_vie);
return $timestamp;
}
 
/**
730,7 → 740,7
*/
protected function transformaterIdEnNomFichier($id) {
$prefixe = $this->options['fichier_prefixe'];
$resulta = $prefixe.'---'.$id;
$resultat = $prefixe.'---'.$id;
return $resultat;
}
 
760,7 → 770,7
if ($this->options['dossier_niveau'] > 0) {
$hash = hash('adler32', $id);
for ($i = 0 ; $i < $this->options['dossier_niveau'] ; $i++) {
$chemin .= $prefix.'--'.substr($hash, 0, $i + 1).DS;
$chemin .= $prefixe.'--'.substr($hash, 0, $i + 1).DS;
$morceaux[] = $chemin;
}
}