Subversion Repositories Applications.framework

Rev

Rev 269 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 269 Rev 282
1
<?php
1
<?php
2
// declare(encoding='UTF-8');
2
// declare(encoding='UTF-8');
3
/**
3
/**
4
 * Classe Cache permettant de mettre en cache des données.
4
 * Classe Cache permettant de mettre en cache des données.
5
 * Basée sur les principes de Zend_Cache (Copyright (c) 2005-2010, Zend Technologies USA, Inc. All rights reserved.)
5
 * Basée sur les principes de Zend_Cache (Copyright (c) 2005-2010, Zend Technologies USA, Inc. All rights reserved.)
6
 *
6
 *
7
 * @category	php 5.2
7
 * @category	php 5.2
8
 * @package	Framework
8
 * @package	Framework
9
 * @author		Jean-Pascal MILCENT <jpm@tela-botanica.org>
9
 * @author		Jean-Pascal MILCENT <jpm@tela-botanica.org>
10
 * @copyright	Copyright (c) 2010, Tela Botanica (accueil@tela-botanica.org)
10
 * @copyright	Copyright (c) 2010, Tela Botanica (accueil@tela-botanica.org)
11
 * @license	http://framework.zend.com/license/new-bsd Licence New BSD
11
 * @license	http://framework.zend.com/license/new-bsd Licence New BSD
12
 * @license	http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
12
 * @license	http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
13
 * @license	http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
13
 * @license	http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
14
 * @version	$Id$
14
 * @version	$Id$
15
 * @link		/doc/framework/
15
 * @link		/doc/framework/
16
 */
16
 */
17
class Cache {
17
class Cache {
18
	/** Socke les enregistrements du cache dans des fichiers textes. */
18
	/** Socke les enregistrements du cache dans des fichiers textes. */
19
	const STOCKAGE_MODE_FICHIER = "Fichier";
19
	const STOCKAGE_MODE_FICHIER = "Fichier";
20
	/** Socke les enregistrements du cache dans une base de données SQLite. */
20
	/** Socke les enregistrements du cache dans une base de données SQLite. */
21
	const STOCKAGE_MODE_SQLITE = "Sqlite";
21
	const STOCKAGE_MODE_SQLITE = "Sqlite";
22
	
22
	
23
	/** 'tous' (par défaut) : supprime tous les enregistrements. */
23
	/** 'tous' (par défaut) : supprime tous les enregistrements. */
24
	const NETTOYAGE_MODE_TOUS = "tous";
24
	const NETTOYAGE_MODE_TOUS = "tous";
25
	/** 'expiration' : supprime tous les enregistrements dont la date d'expériration est dépassée. */
25
	/** 'expiration' : supprime tous les enregistrements dont la date d'expériration est dépassée. */
26
	const NETTOYAGE_MODE_EXPIRATION = "expiration";
26
	const NETTOYAGE_MODE_EXPIRATION = "expiration";
27
	/** 'avecLesTags' : supprime tous les enregistrements contenant tous les tags indiqués. */
27
	/** 'avecLesTags' : supprime tous les enregistrements contenant tous les tags indiqués. */
28
	const NETTOYAGE_MODE_AVEC_LES_TAGS = "avecLesTags";
28
	const NETTOYAGE_MODE_AVEC_LES_TAGS = "avecLesTags";
29
	/** 'sansLesTags' : supprime tous les enregistrements contenant aucun des tags indiqués. */
29
	/** 'sansLesTags' : supprime tous les enregistrements contenant aucun des tags indiqués. */
30
	const NETTOYAGE_MODE_SANS_LES_TAGS = "sansLesTags";
30
	const NETTOYAGE_MODE_SANS_LES_TAGS = "sansLesTags";
31
	/** 'avecUnTag' : supprime tous les enregistrements contenant au moins un des tags indiqués. */
31
	/** 'avecUnTag' : supprime tous les enregistrements contenant au moins un des tags indiqués. */
32
	const NETTOYAGE_MODE_AVEC_UN_TAG = "avecUnTag";
32
	const NETTOYAGE_MODE_AVEC_UN_TAG = "avecUnTag";
33
	
33
	
34
	/**
34
	/**
35
	 * Dernier identifiant de cache utilisé.
35
	 * Dernier identifiant de cache utilisé.
36
	 *
36
	 *
37
	 * @var string $dernier_id
37
	 * @var string $dernier_id
38
	 */
38
	 */
39
	private $dernier_id = null;
39
	private $dernier_id = null;
40
	
40
	
41
	/**
41
	/**
42
	 * Les options disponibles pour le cache :
42
	 * Les options disponibles pour le cache :
-
 
43
	 * ====> (string) stockage_mode :
-
 
44
	 * Indique le mode de stockage du cache à utiliser parmis :
-
 
45
	 * - Cache::STOCKAGE_MODE_FICHIER : sous forme d'une arborescence de fichiers et dossier
-
 
46
	 * - Cache::STOCKAGE_MODE_SQLITE : sous forme d'une base de données SQLite
43
	 *
47
	 * 
-
 
48
	 * ====> (string) stockage_chemin :
-
 
49
	 * Chemin vers :
-
 
50
	 * - Cache::STOCKAGE_MODE_FICHIER : le dossier devant contenir l'arborescence.
-
 
51
	 * - Cache::STOCKAGE_MODE_SQLITE : le fichier contenant la base SQLite.
-
 
52
	 * 
44
	 * ====> (boolean) controle_ecriture : [write_control]
53
	 * ====> (boolean) controle_ecriture :
45
	 * - Enable / disable write control (the cache is read just after writing to detect corrupt entries)
54
	 * - Active / Désactive le controle d'écriture (le cache est lue jute après l'écriture du fichier pour détecter sa corruption)
46
	 * - Enable write control will lightly slow the cache writing but not the cache reading
55
	 * - Activer le controle d'écriture ralentira légèrement l'écriture du fichier de cache mais pas sa lecture
47
	 * Write control can detect some corrupt cache files but maybe it's not a perfect control
56
	 * Le controle d'écriture peut détecter la corruption de fichier mais ce n'est pas un système de controle parfait.
48
	 *
57
	 *
49
	 * ====> (boolean) mise_en_cache : [caching]
58
	 * ====> (boolean) mise_en_cache :
50
	 * - Enable / disable caching
59
	 * - Active / Désactive la mise en cache
51
	 * (can be very useful for the debug of cached scripts)
60
	 * (peut être très utile pour le débogage des scripts utilisant le cache
52
	 *
61
	 *
53
	 * =====> (string) cache_id_prefixe : [cache_id_prefix]
62
	 * =====> (string) cache_id_prefixe :
54
	 * - prefix for cache ids (namespace)
63
	 * - préfixe pour les identifiant de cache ( = espace de nom)
55
	 *
64
	 *
56
	 * ====> (boolean) serialisation_auto : [automatic_serialization]
65
	 * ====> (boolean) serialisation_auto :
57
	 * - Enable / disable automatic serialization
66
	 * - Active / Désactive la sérialisation automatique
58
	 * - It can be used to save directly datas which aren't strings (but it's slower)
67
	 * - Peut être utilisé pour sauver directement des données qui ne sont pas des chaines (mais c'est plus lent)
59
	 *
68
	 *
60
	 * ====> (int) nettoyage_auto : [automatic_cleaning_factor]
69
	 * ====> (int) nettoyage_auto :
61
	 * - Disable / Tune the automatic cleaning process
70
	 * - Désactive / Régler le processus de nettoyage automatique
62
	 * - The automatic cleaning process destroy too old (for the given life time)
71
	 * - Le processus de nettoyage automatiques détruit les fichier trop vieux (pour la durée de vie donnée)
63
	 *   cache files when a new cache file is written :
72
	 *   quand un nouveau fichier de cache est écrit :
64
	 *	 0			   => no automatic cache cleaning
73
	 *	 0			   => pas de nettoyage automatique
65
	 *	 1			   => systematic cache cleaning
74
	 *	 1			   => nettoyage automatique systématique
66
	 *	 x (integer) > 1 => automatic cleaning randomly 1 times on x cache write
75
	 *	 x (integer) > 1 => nettoyage automatique toutes les 1 fois (au hasard) sur x écriture de fichier de cache
67
	 *
76
	 *
68
	 * ====> (int) duree_de_vie : [lifetime]
77
	 * ====> (int) duree_de_vie :
69
	 * - Cache lifetime (in seconds)
78
	 * - Durée de vie du cache (en secondes)
70
	 * - If null, the cache is valid forever.
79
	 * - Si null, le cache est valide indéfiniment.
71
	 *
80
	 *
72
	 * @var array $options les options disponibles pour le cache .
81
	 * @var array $options les options disponibles pour le cache .
73
	 */
82
	 */
74
	protected $options = array(
83
	protected $options = array(
75
		'stockage_mode'				 => self::STOCKAGE_MODE_FICHIER,
84
		'stockage_mode'				 => self::STOCKAGE_MODE_FICHIER,
76
		'stockage_chemin'				 => null,	
85
		'stockage_chemin'				 => null,	
77
		'controle_ecriture'			 => true,
86
		'controle_ecriture'			 => true,
78
		'mise_en_cache'		  		 => true,
87
		'mise_en_cache'		  		 => true,
79
		'cache_id_prefixe'		  		 => null,
88
		'cache_id_prefixe'		  		 => null,
80
		'serialisation_auto'		  	 => false,
89
		'serialisation_auto'		  	 => false,
81
		'nettoyage_auto'				 => 10,
90
		'nettoyage_auto'				 => 10,
82
		'duree_de_vie'			 		 => 3600,
91
		'duree_de_vie'			 		 => 3600,
83
	);
92
	);
84
	
93
	
85
	protected $stockage = null;
94
	protected $stockage = null;
86
	
95
	
-
 
96
	public function __construct($options = array(), $options_stockage = array()) {
87
	public function __construct($options, $options_stockage = array()) {
97
		$this->initialiserOptionsParConfig();
88
		$this->setOptions($options);
98
		$this->setOptions($options);
89
		if ($this->options['stockage_mode'] == self::STOCKAGE_MODE_FICHIER) {
99
		if ($this->options['stockage_mode'] == self::STOCKAGE_MODE_FICHIER) {
90
			$this->stockage = new CacheFichier($options_stockage, $this);
100
			$this->stockage = new CacheFichier($options_stockage, $this);
91
		} else if ($this->options['stockage_mode'] == self::STOCKAGE_MODE_SQLITE) {
101
		} else if ($this->options['stockage_mode'] == self::STOCKAGE_MODE_SQLITE) {
92
			$this->stockage = new CacheSqlite($options_stockage, $this);
102
			$this->stockage = new CacheSqlite($options_stockage, $this);
93
		}
103
		}
94
		$this->stockage->setEmplacement($this->options['stockage_chemin']);
104
		$this->stockage->setEmplacement($this->options['stockage_chemin']);
95
	}
105
	}
-
 
106
	
-
 
107
	private function initialiserOptionsParConfig() {
-
 
108
		while (list($nom, $valeur) = each($this->options)) {
-
 
109
			if (Config::existe($nom)) {
-
 
110
				$this->options[$nom] = Config::get($nom);
-
 
111
			}
-
 
112
		}
-
 
113
	}
96
	
114
	
97
	private function setOptions($options) {
115
	private function setOptions($options) {
98
		while (list($nom, $valeur) = each($options)) {
116
		while (list($nom, $valeur) = each($options)) {
99
			if (!is_string($nom)) {
117
			if (!is_string($nom)) {
100
				trigger_error("Nom d'option incorecte : $nom", E_USER_WARNING);
118
				trigger_error("Nom d'option incorecte : $nom", E_USER_WARNING);
101
			}
119
			}
102
			$nom = strtolower($nom);
120
			$nom = strtolower($nom);
103
			if (array_key_exists($nom, $this->options)) {
121
			if (array_key_exists($nom, $this->options)) {
104
				$this->options[$nom] = $valeur;
122
				$this->options[$nom] = $valeur;
105
			}
123
			}
106
		}
124
		}
107
	}
125
	}
108
	
126
	
109
	/**
127
	/**
110
	 * Permet de (re-)définir l'emplacement pour le stockage du cache.
128
	 * Permet de (re-)définir l'emplacement pour le stockage du cache.
111
	 * En fonction du mode de stockage utilisé , l'emplacement indiqué correspondra au chemin du :
129
	 * En fonction du mode de stockage utilisé , l'emplacement indiqué correspondra au chemin du :
112
	 *  - dossier où stocker les fichiers pour le mode "fichier".
130
	 *  - dossier où stocker les fichiers pour le mode "fichier".
113
	 *  - fichier de la base de données pour le mode "sqlite". 
131
	 *  - fichier de la base de données pour le mode "sqlite". 
114
	 * @param string $emplacement chemin vers dossier (Cache::STOCKAGE_MODE_FICHIER) ou fichier base Sqlite (Cache::STOCKAGE_MODE_SQLITE)
132
	 * @param string $emplacement chemin vers dossier (Cache::STOCKAGE_MODE_FICHIER) ou fichier base Sqlite (Cache::STOCKAGE_MODE_SQLITE)
115
	 * @return void 
133
	 * @return void 
116
	 */
134
	 */
117
	public function setEmplacement($emplacement) {
135
	public function setEmplacement($emplacement) {
118
		if ($emplacement != null) {
136
		if ($emplacement != null) {
119
			$this->executerMethodeStockage('setEmplacement', array($emplacement));
137
			$this->executerMethodeStockage('setEmplacement', array($emplacement));
120
		} else {
138
		} else {
121
			trigger_error("L'emplacement ne peut pas être null.", E_USER_WARNING);
139
			trigger_error("L'emplacement ne peut pas être null.", E_USER_WARNING);
122
		}
140
		}
123
	}
141
	}
124
	
142
	
125
	/**
143
	/**
126
	 * Teste si un cache est disponible pour l'identifiant donné et (si oui) le retourne (false dans le cas contraire)
144
	 * Teste si un cache est disponible pour l'identifiant donné et (si oui) le retourne (false dans le cas contraire)
127
	 *
145
	 *
128
	 * @param  string  $id Identifiant de cache.
146
	 * @param  string  $id Identifiant de cache.
129
	 * @param  boolean $ne_pas_tester_validiter_du_cache Si mis à true, la validité du cache n'est pas testée
147
	 * @param  boolean $ne_pas_tester_validiter_du_cache Si mis à true, la validité du cache n'est pas testée
130
	 * @return mixed|false Cached datas
148
	 * @return mixed|false Cached datas
131
	 */
149
	 */
132
	public function charger($id, $ne_pas_tester_validiter_du_cache = false) {
150
	public function charger($id, $ne_pas_tester_validiter_du_cache = false) {
133
		$donnees = false;
151
		$donnees = false;
134
		if ($this->options['mise_en_cache'] === true) {
152
		if ($this->options['mise_en_cache'] === true) {
135
			$id = $this->prefixerId($id);
153
			$id = $this->prefixerId($id);
136
			$this->dernier_id = $id;
154
			$this->dernier_id = $id;
137
			self::validerIdOuTag($id);
155
			self::validerIdOuTag($id);
138
			$donnees = $this->executerMethodeStockage('charger', array($id, $ne_pas_tester_validiter_du_cache));
156
			$donnees = $this->executerMethodeStockage('charger', array($id, $ne_pas_tester_validiter_du_cache));
139
			$donnees = $this->deserialiserAutomatiquement($donnees);
157
			$donnees = $this->deserialiserAutomatiquement($donnees);
140
		}
158
		}
141
		return $donnees;
159
		return $donnees;
142
	}
160
	}
143
	
161
	
144
	/**
162
	/**
145
	 * Test if a cache is available for the given id
163
	 * Test if a cache is available for the given id
146
	 *
164
	 *
147
	 * @param  string $id Cache id
165
	 * @param  string $id Cache id
148
	 * @return int|false Last modified time of cache entry if it is available, false otherwise
166
	 * @return int|false Last modified time of cache entry if it is available, false otherwise
149
	 */
167
	 */
150
	public function tester($id) {
168
	public function tester($id) {
151
		$resultat = false;
169
		$resultat = false;
152
		if ($this->options['mise_en_cache'] === true) {
170
		if ($this->options['mise_en_cache'] === true) {
153
		  	$id = $this->prefixerId($id);
171
		  	$id = $this->prefixerId($id);
154
			self::validerIdOuTag($id);
172
			self::validerIdOuTag($id);
155
			$this->dernier_id = $id;
173
			$this->dernier_id = $id;
156
			$resultat = $this->executerMethodeStockage('tester', array($id));
174
			$resultat = $this->executerMethodeStockage('tester', array($id));
157
		}
175
		}
158
		return $resultat;
176
		return $resultat;
159
	}
177
	}
160
	
178
	
161
	/**
179
	/**
162
	 * Sauvegarde en cache les données passées en paramètre.
180
	 * Sauvegarde en cache les données passées en paramètre.
163
	 *
181
	 *
164
	 * @param  mixed $donnees Données à mettre en cache (peut être différent d'une chaine si serialisation_auto vaut true).
182
	 * @param  mixed $donnees Données à mettre en cache (peut être différent d'une chaine si serialisation_auto vaut true).
165
	 * @param  string $id	 Identifiant du cache (s'il n'est pas définit, le dernier identifiant sera utilisé).
183
	 * @param  string $id	 Identifiant du cache (s'il n'est pas définit, le dernier identifiant sera utilisé).
166
	 * @param  array $tags Mots-clés du cache.
184
	 * @param  array $tags Mots-clés du cache.
167
	 * @param  int $duree_de_vie_specifique Si != false, indique une durée de vie spécifique pour cet enregistrement en cache (null => durée de vie infinie)
185
	 * @param  int $duree_de_vie_specifique Si != false, indique une durée de vie spécifique pour cet enregistrement en cache (null => durée de vie infinie)
168
	 * @return boolean True si aucun problème n'est survenu.
186
	 * @return boolean True si aucun problème n'est survenu.
169
	 */
187
	 */
170
	public function sauver($donnees, $id = null, $tags = array(), $duree_de_vie_specifique = false) {
188
	public function sauver($donnees, $id = null, $tags = array(), $duree_de_vie_specifique = false) {
171
		$resultat = true;
189
		$resultat = true;
172
		if ($this->options['mise_en_cache'] === true) {
190
		if ($this->options['mise_en_cache'] === true) {
173
			$id = ($id === null) ? $this->dernier_id : $this->prefixerId($id);
191
			$id = ($id === null) ? $this->dernier_id : $this->prefixerId($id);
174
	
192
	
175
			self::validerIdOuTag($id);
193
			self::validerIdOuTag($id);
176
			self::validerTableauDeTags($tags);
194
			self::validerTableauDeTags($tags);
177
			$donnees = $this->serialiserAutomatiquement($donnees);
195
			$donnees = $this->serialiserAutomatiquement($donnees);
178
			$this->nettoyerAutomatiquement();
196
			$this->nettoyerAutomatiquement();
179
			
197
			
180
			$resultat = $this->executerMethodeStockage('sauver', array($donnees, $id, $tags, $duree_de_vie_specifique));
198
			$resultat = $this->executerMethodeStockage('sauver', array($donnees, $id, $tags, $duree_de_vie_specifique));
181
			
199
			
182
			if ($resultat == false) {
200
			if ($resultat == false) {
183
				// Le cache étant peut être corrompu, nous le supprimons
201
				// Le cache étant peut être corrompu, nous le supprimons
184
				$this->supprimer($id);
202
				$this->supprimer($id);
185
			} else {
203
			} else {
186
				$resultat = $this->controlerEcriture($id, $donnees);
204
				$resultat = $this->controlerEcriture($id, $donnees);
187
			}
205
			}
188
		}
206
		}
189
		return $resultat;
207
		return $resultat;
190
	}
208
	}
191
	
209
	
192
	/**
210
	/**
193
	 * Supprime un enregistrement en cache.
211
	 * Supprime un enregistrement en cache.
194
	 *
212
	 *
195
	 * @param  string $id Identificant du cache à supprimer.
213
	 * @param  string $id Identificant du cache à supprimer.
196
	 * @return boolean True si ok
214
	 * @return boolean True si ok
197
	 */
215
	 */
198
	public function supprimer($id) {
216
	public function supprimer($id) {
199
		$resultat = true;
217
		$resultat = true;
200
		if ($this->options['mise_en_cache'] === true) {
218
		if ($this->options['mise_en_cache'] === true) {
201
			$id = $this->prefixerId($id);
219
			$id = $this->prefixerId($id);
202
			self::validerIdOuTag($id);
220
			self::validerIdOuTag($id);
203
		   $resultat = $this->executerMethodeStockage('supprimer', array($id));
221
		   $resultat = $this->executerMethodeStockage('supprimer', array($id));
204
		}
222
		}
205
		return $resultat;
223
		return $resultat;
206
	}
224
	}
207
	
225
	
208
	/**
226
	/**
209
	 * Nettoyage des enregistrements en cache
227
	 * Nettoyage des enregistrements en cache
210
	 * 
228
	 * 
211
	 * Mode de nettoyage disponibles :
229
	 * Mode de nettoyage disponibles :
212
	 * 'tous' (défaut)	=> supprime tous les enregistrements ($tags n'est pas utilisé)
230
	 * 'tous' (défaut)	=> supprime tous les enregistrements ($tags n'est pas utilisé)
213
	 * 'expiration'		=> supprime tous les enregistrements dont la date d'expériration est dépassée ($tags n'est pas utilisé)
231
	 * 'expiration'		=> supprime tous les enregistrements dont la date d'expériration est dépassée ($tags n'est pas utilisé)
214
	 * 'avecLesTag'		=> supprime tous les enregistrements contenant tous les tags indiqués
232
	 * 'avecLesTag'		=> supprime tous les enregistrements contenant tous les tags indiqués
215
	 * 'sansLesTag'		=> supprime tous les enregistrements contenant aucun des tags indiqués
233
	 * 'sansLesTag'		=> supprime tous les enregistrements contenant aucun des tags indiqués
216
	 * 'avecUnTag'			=> supprime tous les enregistrements contenant au moins un des tags indiqués
234
	 * 'avecUnTag'			=> supprime tous les enregistrements contenant au moins un des tags indiqués
217
	 *
235
	 *
218
	 * @param string $mode mode de nettoyage
236
	 * @param string $mode mode de nettoyage
219
	 * @param array|string $tags peut être un tableau de chaîne ou une simple chaine.
237
	 * @param array|string $tags peut être un tableau de chaîne ou une simple chaine.
220
	 * @return boolean True si ok
238
	 * @return boolean True si ok
221
	 */
239
	 */
222
	public function nettoyer($mode = self::NETTOYAGE_MODE_TOUS, $tags = array()) {
240
	public function nettoyer($mode = self::NETTOYAGE_MODE_TOUS, $tags = array()) {
223
		$resultat = true;
241
		$resultat = true;
224
		if ($this->options['mise_en_cache'] === true) {
242
		if ($this->options['mise_en_cache'] === true) {
225
			if (!in_array($mode, array(Cache::NETTOYAGE_MODE_TOUS,
243
			if (!in_array($mode, array(Cache::NETTOYAGE_MODE_TOUS,
226
				Cache::NETTOYAGE_MODE_EXPIRATION,
244
				Cache::NETTOYAGE_MODE_EXPIRATION,
227
				Cache::NETTOYAGE_MODE_AVEC_LES_TAGS,
245
				Cache::NETTOYAGE_MODE_AVEC_LES_TAGS,
228
				Cache::NETTOYAGE_MODE_SANS_LES_TAGS,
246
				Cache::NETTOYAGE_MODE_SANS_LES_TAGS,
229
				Cache::NETTOYAGE_MODE_AVEC_UN_TAG))) {
247
				Cache::NETTOYAGE_MODE_AVEC_UN_TAG))) {
230
				trigger_error("Le mode de nettoyage du cache indiqué n'est pas valide", E_USER_WARNING);
248
				trigger_error("Le mode de nettoyage du cache indiqué n'est pas valide", E_USER_WARNING);
231
			}
249
			}
232
			self::validerTableauDeTags($tags);
250
			self::validerTableauDeTags($tags);
233
			
251
			
234
			$resultat = $this->executerMethodeStockage('nettoyer', array($mode, $tags));
252
			$resultat = $this->executerMethodeStockage('nettoyer', array($mode, $tags));
235
		}
253
		}
236
		return $resultat;
254
		return $resultat;
237
	}
255
	}
238
 
256
 
239
	/**
257
	/**
240
	 * Return an array of stored cache ids
258
	 * Return an array of stored cache ids
241
	 *
259
	 *
242
	 * @return array array of stored cache ids (string)
260
	 * @return array array of stored cache ids (string)
243
	 */
261
	 */
244
	public function getIds() {
262
	public function getIds() {
245
		$ids = $this->executerMethodeStockage('getIds');
263
		$ids = $this->executerMethodeStockage('getIds');
246
		$ids = $this->supprimerPrefixe($ids);
264
		$ids = $this->supprimerPrefixe($ids);
247
		return $ids;
265
		return $ids;
248
	}
266
	}
249
 
267
 
250
	/**
268
	/**
251
	 * Return an array of stored tags
269
	 * Return an array of stored tags
252
	 *
270
	 *
253
	 * @return array array of stored tags (string)
271
	 * @return array array of stored tags (string)
254
	 */
272
	 */
255
	public function getTags() {
273
	public function getTags() {
256
		return $this->executerMethodeStockage('getTags');
274
		return $this->executerMethodeStockage('getTags');
257
	}
275
	}
258
	
276
	
259
	/**
277
	/**
260
	 * Return an array of stored cache ids which match given tags
278
	 * Return an array of stored cache ids which match given tags
261
	 *
279
	 *
262
	 * In case of multiple tags, a logical AND is made between tags
280
	 * In case of multiple tags, a logical AND is made between tags
263
	 *
281
	 *
264
	 * @param array $tags array of tags
282
	 * @param array $tags array of tags
265
	 * @return array array of matching cache ids (string)
283
	 * @return array array of matching cache ids (string)
266
	 */
284
	 */
267
	public function getIdsAvecLesTags($tags = array()) {
285
	public function getIdsAvecLesTags($tags = array()) {
268
		$ids = $this->executerMethodeStockage('getIdsAvecLesTags', array($tags));
286
		$ids = $this->executerMethodeStockage('getIdsAvecLesTags', array($tags));
269
		$ids = $this->supprimerPrefixe($ids);
287
		$ids = $this->supprimerPrefixe($ids);
270
		return $ids;
288
		return $ids;
271
	}
289
	}
272
 
290
 
273
	/**
291
	/**
274
	 * Return an array of stored cache ids which don't match given tags
292
	 * Return an array of stored cache ids which don't match given tags
275
	 *
293
	 *
276
	 * In case of multiple tags, a logical OR is made between tags
294
	 * In case of multiple tags, a logical OR is made between tags
277
	 *
295
	 *
278
	 * @param array $tags array of tags
296
	 * @param array $tags array of tags
279
	 * @return array array of not matching cache ids (string)
297
	 * @return array array of not matching cache ids (string)
280
	 */
298
	 */
281
	public function getIdsSansLesTags($tags = array()) {
299
	public function getIdsSansLesTags($tags = array()) {
282
	   	$ids = $this->executerMethodeStockage('getIdsSansLesTags', array($tags));
300
	   	$ids = $this->executerMethodeStockage('getIdsSansLesTags', array($tags));
283
		$ids = $this->supprimerPrefixe($ids);
301
		$ids = $this->supprimerPrefixe($ids);
284
		return $ids;
302
		return $ids;
285
	}
303
	}
286
 
304
 
287
	/**
305
	/**
288
	 * Return an array of stored cache ids which match any given tags
306
	 * Return an array of stored cache ids which match any given tags
289
	 *
307
	 *
290
	 * In case of multiple tags, a logical OR is made between tags
308
	 * In case of multiple tags, a logical OR is made between tags
291
	 *
309
	 *
292
	 * @param array $tags array of tags
310
	 * @param array $tags array of tags
293
	 * @return array array of matching any cache ids (string)
311
	 * @return array array of matching any cache ids (string)
294
	 */
312
	 */
295
	public function getIdsAvecUnTag($tags = array()) {
313
	public function getIdsAvecUnTag($tags = array()) {
296
		$ids = $this->executerMethodeStockage('getIdsAvecUnTag', array($tags));
314
		$ids = $this->executerMethodeStockage('getIdsAvecUnTag', array($tags));
297
		$ids = $this->supprimerPrefixe($ids);
315
		$ids = $this->supprimerPrefixe($ids);
298
		return $ids;
316
		return $ids;
299
	}
317
	}
300
 
318
 
301
	/**
319
	/**
302
	 * Return the filling percentage of the backend storage
320
	 * Return the filling percentage of the backend storage
303
	 *
321
	 *
304
	 * @return int integer between 0 and 100
322
	 * @return int integer between 0 and 100
305
	 */
323
	 */
306
	public function getPourcentageRemplissage() {
324
	public function getPourcentageRemplissage() {
307
		return $this->executerMethodeStockage('getPourcentageRemplissage');
325
		return $this->executerMethodeStockage('getPourcentageRemplissage');
308
	}
326
	}
309
 
327
 
310
	/**
328
	/**
311
	 * Return an array of metadatas for the given cache id
329
	 * Return an array of metadatas for the given cache id
312
	 *
330
	 *
313
	 * The array will include these keys :
331
	 * The array will include these keys :
314
	 * - expire : the expire timestamp
332
	 * - expire : the expire timestamp
315
	 * - tags : a string array of tags
333
	 * - tags : a string array of tags
316
	 * - mtime : timestamp of last modification time
334
	 * - mtime : timestamp of last modification time
317
	 *
335
	 *
318
	 * @param string $id cache id
336
	 * @param string $id cache id
319
	 * @return array array of metadatas (false if the cache id is not found)
337
	 * @return array array of metadatas (false if the cache id is not found)
320
	 */
338
	 */
321
	public function getMetadonnees($id) {
339
	public function getMetadonnees($id) {
322
		$id = $this->prefixerId($id);
340
		$id = $this->prefixerId($id);
323
		return $this->executerMethodeStockage('getMetadonnees', array($id));
341
		return $this->executerMethodeStockage('getMetadonnees', array($id));
324
	}
342
	}
325
 
343
 
326
	/**
344
	/**
327
	 * Give (if possible) an extra lifetime to the given cache id
345
	 * Give (if possible) an extra lifetime to the given cache id
328
	 *
346
	 *
329
	 * @param string $id cache id
347
	 * @param string $id cache id
330
	 * @param int $extraLifetime
348
	 * @param int $extraLifetime
331
	 * @return boolean true if ok
349
	 * @return boolean true if ok
332
	 */
350
	 */
333
	public function ajouterSupplementDureeDeVie($id, $supplement_duree_de_vie) {
351
	public function ajouterSupplementDureeDeVie($id, $supplement_duree_de_vie) {
334
		$id = $this->prefixerId($id);
352
		$id = $this->prefixerId($id);
335
		return $this->executerMethodeStockage('ajouterSupplementDureeDeVie', array($id, $supplement_duree_de_vie));
353
		return $this->executerMethodeStockage('ajouterSupplementDureeDeVie', array($id, $supplement_duree_de_vie));
336
	}
354
	}
337
	
355
	
338
 
356
 
339
	/**
357
	/**
340
	 * Fabrique et retourne l'identifiant du cache avec son préfixe.
358
	 * Fabrique et retourne l'identifiant du cache avec son préfixe.
341
	 *
359
	 *
342
	 * Vérifie l'option 'cache_id_prefixe' et retourne le nouvel id avec préfixe ou simplement l'id lui même si elle vaut null.
360
	 * Vérifie l'option 'cache_id_prefixe' et retourne le nouvel id avec préfixe ou simplement l'id lui même si elle vaut null.
343
	 *
361
	 *
344
	 * @param  string $id Identifiant du cache.
362
	 * @param  string $id Identifiant du cache.
345
	 * @return string Identifiant du cache avec ou sans préfixe.
363
	 * @return string Identifiant du cache avec ou sans préfixe.
346
	 */
364
	 */
347
	private function prefixerId($id) {
365
	private function prefixerId($id) {
348
		$nouvel_id = $id;
366
		$nouvel_id = $id;
349
		if (($id !== null) && isset($this->options['cache_id_prefixe'])) {
367
		if (($id !== null) && isset($this->options['cache_id_prefixe'])) {
350
			$nouvel_id = $this->options['cache_id_prefixe'].$id;
368
			$nouvel_id = $this->options['cache_id_prefixe'].$id;
351
		}
369
		}
352
		return $nouvel_id;
370
		return $nouvel_id;
353
	}
371
	}
354
	
372
	
355
	private function executerMethodeStockage($methode, $params = null) {
373
	private function executerMethodeStockage($methode, $params = null) {
356
		if (method_exists($this->stockage, $methode)) {
374
		if (method_exists($this->stockage, $methode)) {
357
			if ($params == null) {
375
			if ($params == null) {
358
				$resultat = call_user_func(array($this->stockage, $methode));
376
				$resultat = call_user_func(array($this->stockage, $methode));
359
			} else {
377
			} else {
360
				$resultat = call_user_func_array(array($this->stockage, $methode), $params);
378
				$resultat = call_user_func_array(array($this->stockage, $methode), $params);
361
			}
379
			}
362
		} else {
380
		} else {
363
			$resultat = false;
381
			$resultat = false;
364
			trigger_error("La méthode '$methode' n'existe pas dans la classe '".get_class($this)."'.", E_USER_WARNING);
382
			trigger_error("La méthode '$methode' n'existe pas dans la classe '".get_class($this)."'.", E_USER_WARNING);
365
		}
383
		}
366
		return $resultat;
384
		return $resultat;
367
	}
385
	}
368
	
386
	
369
	private function supprimerPrefixe($ids) {
387
	private function supprimerPrefixe($ids) {
370
		// Il est nécessaire de retirer les cache_id_prefixe des ids (voir #ZF-6178, #ZF-7600)
388
		// Il est nécessaire de retirer les cache_id_prefixe des ids (voir #ZF-6178, #ZF-7600)
371
		if (isset($this->options['cache_id_prefixe']) && $this->options['cache_id_prefixe'] !== '') {
389
		if (isset($this->options['cache_id_prefixe']) && $this->options['cache_id_prefixe'] !== '') {
372
			$prefixe =& $this->options['cache_id_prefixe'];
390
			$prefixe =& $this->options['cache_id_prefixe'];
373
			$prefixe_longueur = strlen($prefixe);
391
			$prefixe_longueur = strlen($prefixe);
374
			foreach ($ids as &$id) {
392
			foreach ($ids as &$id) {
375
				if (strpos($id, $prefixe) === 0) {
393
				if (strpos($id, $prefixe) === 0) {
376
					$id = substr($id, $prefixe_longueur);
394
					$id = substr($id, $prefixe_longueur);
377
				}
395
				}
378
			}
396
			}
379
		}
397
		}
380
		return $ids;
398
		return $ids;
381
	}
399
	}
382
	
400
	
383
	private function controlerEcriture($id, $donnees_avant_ecriture) {
401
	private function controlerEcriture($id, $donnees_avant_ecriture) {
384
		$resultat = true;
402
		$resultat = true;
385
		if ($this->options['controle_ecriture']) {
403
		if ($this->options['controle_ecriture']) {
386
			$donnees_apres_ecriture = $this->executerMethodeStockage('charger', array($id, true));
404
			$donnees_apres_ecriture = $this->executerMethodeStockage('charger', array($id, true));
387
			if ($donnees_avant_ecriture != $donnees_apres_ecriture) {
405
			if ($donnees_avant_ecriture != $donnees_apres_ecriture) {
388
				$this->executerMethodeStockage('supprimer', array($id));
406
				$this->executerMethodeStockage('supprimer', array($id));
389
				$resultat = false;
407
				$resultat = false;
390
			}
408
			}
391
		}
409
		}
392
		return $resultat;
410
		return $resultat;
393
	}
411
	}
394
	
412
	
395
	private function deserialiserAutomatiquement($donnees) {
413
	private function deserialiserAutomatiquement($donnees) {
396
		if ($donnees !== false && $this->options['serialisation_auto']) {
414
		if ($donnees !== false && $this->options['serialisation_auto']) {
397
				// we need to unserialize before sending the result
415
				// we need to unserialize before sending the result
398
				$donnees = unserialize($donnees);
416
				$donnees = unserialize($donnees);
399
		}
417
		}
400
		return $donnees;
418
		return $donnees;
401
	}
419
	}
402
	
420
	
403
	private function serialiserAutomatiquement($donnees) {
421
	private function serialiserAutomatiquement($donnees) {
404
		if ($this->options['serialisation_auto']) {
422
		if ($this->options['serialisation_auto']) {
405
			// we need to serialize datas before storing them
423
			// we need to serialize datas before storing them
406
			$donnees = serialize($donnees);
424
			$donnees = serialize($donnees);
407
		} else {
425
		} else {
408
			if (!is_string($donnees)) {
426
			if (!is_string($donnees)) {
409
				trigger_error("Les données doivent être une chaîne de caractères ou vous devez activez l'option serialisation_auto = true", E_USER_WARNING);
427
				trigger_error("Les données doivent être une chaîne de caractères ou vous devez activez l'option serialisation_auto = true", E_USER_WARNING);
410
			}
428
			}
411
		}
429
		}
412
		return $donnees;
430
		return $donnees;
413
	}
431
	}
414
	
432
	
415
	private function nettoyerAutomatiquement() {
433
	private function nettoyerAutomatiquement() {
416
		if ($this->options['nettoyage_auto'] > 0) {
434
		if ($this->options['nettoyage_auto'] > 0) {
417
			$rand = rand(1, $this->options['nettoyage_auto']);
435
			$rand = rand(1, $this->options['nettoyage_auto']);
418
			if ($rand == 1) {
436
			if ($rand == 1) {
419
				$this->nettoyer(self::NETTOYAGE_MODE_EXPIRATION);
437
				$this->nettoyer(self::NETTOYAGE_MODE_EXPIRATION);
420
			}
438
			}
421
		}
439
		}
422
	}
440
	}
423
	
441
	
424
	/**
442
	/**
425
	 * Valide un identifiant de cache ou un tag (securité, nom de fichiers fiables, préfixes réservés...)
443
	 * Valide un identifiant de cache ou un tag (securité, nom de fichiers fiables, préfixes réservés...)
426
	 *
444
	 *
427
	 * @param  string $chaine Identificant de cache ou tag
445
	 * @param  string $chaine Identificant de cache ou tag
428
	 * @return void
446
	 * @return void
429
	 */
447
	 */
430
	protected static function validerIdOuTag($chaine) {
448
	protected static function validerIdOuTag($chaine) {
431
		if (!is_string($chaine)) {
449
		if (!is_string($chaine)) {
432
			trigger_error('Id ou tag invalide : doit être une chaîne de caractères', E_USER_ERROR);
450
			trigger_error('Id ou tag invalide : doit être une chaîne de caractères', E_USER_ERROR);
433
		}
451
		}
434
		if (substr($chaine, 0, 9) == 'internal-') {
452
		if (substr($chaine, 0, 9) == 'internal-') {
435
			trigger_error('"internal-*" identifiants ou tags sont réservés', E_USER_WARNING);
453
			trigger_error('"internal-*" identifiants ou tags sont réservés', E_USER_WARNING);
436
		}
454
		}
437
		if (!preg_match('~^[a-zA-Z0-9_]+$~D', $chaine)) {
455
		if (!preg_match('~^[a-zA-Z0-9_]+$~D', $chaine)) {
438
			trigger_error("Id ou tag invalide '$chaine' : doit contenir seulement [a-zA-Z0-9_]", E_USER_WARNING);
456
			trigger_error("Id ou tag invalide '$chaine' : doit contenir seulement [a-zA-Z0-9_]", E_USER_WARNING);
439
		}
457
		}
440
	}
458
	}
441
 
459
 
442
	/**
460
	/**
443
	 * Valide un tableau de tags  (securité, nom de fichiers fiables, préfixes réservés...)
461
	 * Valide un tableau de tags  (securité, nom de fichiers fiables, préfixes réservés...)
444
	 *
462
	 *
445
	 * @param  array $tags tableau de tags
463
	 * @param  array $tags tableau de tags
446
	 * @return void
464
	 * @return void
447
	 */
465
	 */
448
	protected static function validerTableauDeTags($tags) {
466
	protected static function validerTableauDeTags($tags) {
449
		if (!is_array($tags)) {
467
		if (!is_array($tags)) {
450
			trigger_error("Tableau de tags invalide : doit être un tableau 'array'", E_USER_WARNING);
468
			trigger_error("Tableau de tags invalide : doit être un tableau 'array'", E_USER_WARNING);
451
		}
469
		}
452
		foreach ($tags as $tag) {
470
		foreach ($tags as $tag) {
453
			self::validerIdOuTag($tag);
471
			self::validerIdOuTag($tag);
454
		}
472
		}
455
		reset($tags);
473
		reset($tags);
456
	}
474
	}
457
	
475
	
458
	/**
476
	/**
459
	 * Calcule et retourne le timestamp d'expiration
477
	 * Calcule et retourne le timestamp d'expiration
460
	 *
478
	 *
461
	 * @return int timestamp d'expiration (unix timestamp)
479
	 * @return int timestamp d'expiration (unix timestamp)
462
	 */
480
	 */
463
	public function getTimestampExpiration($duree_de_vie) {
481
	public function getTimestampExpiration($duree_de_vie) {
464
		if ($duree_de_vie === false) {
482
		if ($duree_de_vie === false) {
465
			if (isset($this->options['duree_de_vie']) && is_int($this->options['duree_de_vie'])) {
483
			if (isset($this->options['duree_de_vie']) && is_int($this->options['duree_de_vie'])) {
466
				$duree_de_vie = (int) $this->options['duree_de_vie'];
484
				$duree_de_vie = (int) $this->options['duree_de_vie'];
467
			} else {
485
			} else {
468
				$duree_de_vie = 3600;
486
				$duree_de_vie = 3600;
469
			}
487
			}
470
		}
488
		}
471
		$timestamp = ($duree_de_vie === null) ? 9999999999 : (time() + $duree_de_vie);
489
		$timestamp = ($duree_de_vie === null) ? 9999999999 : (time() + $duree_de_vie);
472
		return $timestamp;
490
		return $timestamp;
473
	}
491
	}
474
	
492
	
475
}
493
}