Subversion Repositories Applications.framework

Rev

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

Rev 253 Rev 269
1
<?php
1
<?php
2
class CacheFichier {
2
class CacheFichier {
3
	/**
3
	/**
4
	 * Available options
4
	 * Available options
5
	 *
5
	 *
6
	 * =====> (string) cache_dir :
6
	 * =====> (string) cache_dir :
7
	 * - Directory where to put the cache files
7
	 * - Directory where to put the cache files
8
	 *
8
	 *
9
	 * =====> (boolean) file_locking :
9
	 * =====> (boolean) file_locking :
10
	 * - Enable / disable file_locking
10
	 * - Enable / disable file_locking
11
	 * - Can avoid cache corruption under bad circumstances but it doesn't work on multithread
11
	 * - Can avoid cache corruption under bad circumstances but it doesn't work on multithread
12
	 * webservers and on NFS filesystems for example
12
	 * webservers and on NFS filesystems for example
13
	 *
13
	 *
14
	 * =====> (boolean) read_control :
14
	 * =====> (boolean) read_control :
15
	 * - Enable / disable read control
15
	 * - Enable / disable read control
16
	 * - If enabled, a control key is embeded in cache file and this key is compared with the one
16
	 * - If enabled, a control key is embeded in cache file and this key is compared with the one
17
	 * calculated after the reading.
17
	 * calculated after the reading.
18
	 *
18
	 *
19
	 * =====> (string) read_control_type :
19
	 * =====> (string) read_control_type :
20
	 * - Type of read control (only if read control is enabled). Available values are :
20
	 * - Type of read control (only if read control is enabled). Available values are :
21
	 *   'md5' for a md5 hash control (best but slowest)
21
	 *   'md5' for a md5 hash control (best but slowest)
22
	 *   'crc32' for a crc32 hash control (lightly less safe but faster, better choice)
22
	 *   'crc32' for a crc32 hash control (lightly less safe but faster, better choice)
23
	 *   'adler32' for an adler32 hash control (excellent choice too, faster than crc32)
23
	 *   'adler32' for an adler32 hash control (excellent choice too, faster than crc32)
24
	 *   'strlen' for a length only test (fastest)
24
	 *   'strlen' for a length only test (fastest)
25
	 *
25
	 *
26
	 * =====> (int) hashed_directory_level :
26
	 * =====> (int) hashed_directory_level :
27
	 * - Hashed directory level
27
	 * - Hashed directory level
28
	 * - Set the hashed directory structure level. 0 means "no hashed directory
28
	 * - Set the hashed directory structure level. 0 means "no hashed directory
29
	 * structure", 1 means "one level of directory", 2 means "two levels"...
29
	 * structure", 1 means "one level of directory", 2 means "two levels"...
30
	 * This option can speed up the cache only when you have many thousands of
30
	 * This option can speed up the cache only when you have many thousands of
31
	 * cache file. Only specific benchs can help you to choose the perfect value
31
	 * cache file. Only specific benchs can help you to choose the perfect value
32
	 * for you. Maybe, 1 or 2 is a good start.
32
	 * for you. Maybe, 1 or 2 is a good start.
33
	 *
33
	 *
34
	 * =====> (int) hashed_directory_umask :
34
	 * =====> (int) hashed_directory_umask :
35
	 * - Umask for hashed directory structure
35
	 * - Umask for hashed directory structure
36
	 *
36
	 *
37
	 * =====> (string) file_name_prefix :
37
	 * =====> (string) file_name_prefix :
38
	 * - prefix for cache files
38
	 * - prefix for cache files
39
	 * - be really carefull with this option because a too generic value in a system cache dir
39
	 * - be really carefull with this option because a too generic value in a system cache dir
40
	 *   (like /tmp) can cause disasters when cleaning the cache
40
	 *   (like /tmp) can cause disasters when cleaning the cache
41
	 *
41
	 *
42
	 * =====> (int) cache_file_umask :
42
	 * =====> (int) cache_file_umask :
43
	 * - Umask for cache files
43
	 * - Umask for cache files
44
	 *
44
	 *
45
	 * =====> (int) metatadatas_array_max_size :
45
	 * =====> (int) metatadatas_array_max_size :
46
	 * - max size for the metadatas array (don't change this value unless you
46
	 * - max size for the metadatas array (don't change this value unless you
47
	 *   know what you are doing)
47
	 *   know what you are doing)
48
	 *
48
	 *
49
	 * @var array available options
49
	 * @var array available options
50
	 */
50
	 */
51
	protected $options = array(
51
	protected $options = array(
52
		'stockage_chemin' => null,
52
		'stockage_chemin' => null,
53
		'fichier_verrou' => true,
53
		'fichier_verrou' => true,
54
		'controle_lecture' => true,
54
		'controle_lecture' => true,
55
		'controle_lecture_type' => 'crc32',
55
		'controle_lecture_type' => 'crc32',
56
		'dossier_niveau' => 0,
56
		'dossier_niveau' => 0,
57
		'dossier_umask' => 0700,
57
		'dossier_umask' => 0700,
58
		'fichier_prefixe' => 'tbf',
58
		'fichier_prefixe' => 'tbf',
59
		'fichier_umask' => 0600,
59
		'fichier_umask' => 0600,
60
		'metadonnees_max_taille' => 100
60
		'metadonnees_max_taille' => 100
61
	);
61
	);
62
 
62
 
63
	/**
63
	/**
64
	 * Array of metadatas (each item is an associative array)
64
	 * Array of metadatas (each item is an associative array)
65
	 *
65
	 *
66
	 * @var array
66
	 * @var array
67
	 */
67
	 */
68
	protected $metadonnees = array();
68
	protected $metadonnees = array();
-
 
69
 
69
 
70
	private $Cache = null;
70
 
71
	
71
	/**
72
	/**
72
	 * Constructor
73
	 * Constructor
73
	 *
74
	 *
74
	 * @param  array $options associative array of options
75
	 * @param  array $options associative array of options
75
	 * @throws Zend_Cache_Exception
76
	 * @throws Zend_Cache_Exception
76
	 * @return void
77
	 * @return void
77
	 */
78
	 */
78
	public function __construct(array $options = array()) {
79
	public function __construct(array $options = array(), Cache $cache) {
-
 
80
		$this->Cache = $cache;
79
		$this->setOptions($options);
81
		$this->setOptions($options);
80
 
82
 
81
		if (isset($this->options['prefixe_fichier'])) {
83
		if (isset($this->options['prefixe_fichier'])) {
82
			if (!preg_match('~^[a-zA-Z0-9_]+$~D', $this->options['prefixe_fichier'])) {
84
			if (!preg_match('~^[a-zA-Z0-9_]+$~D', $this->options['prefixe_fichier'])) {
83
				trigger_error("Préfixe de nom de fichier invalide : doit contenir seulement [a-zA-Z0-9_]", E_USER_WARNING);
85
				trigger_error("Préfixe de nom de fichier invalide : doit contenir seulement [a-zA-Z0-9_]", E_USER_WARNING);
84
			}
86
			}
85
		}
87
		}
86
		if ($this->options['metadonnees_max_taille'] < 10) {
88
		if ($this->options['metadonnees_max_taille'] < 10) {
87
			trigger_error("Taille du tableau des méta-données invalide, elle doit être > 10", E_USER_WARNING);
89
			trigger_error("Taille du tableau des méta-données invalide, elle doit être > 10", E_USER_WARNING);
88
		}
90
		}
89
		if (isset($options['dossier_umask']) && is_string($options['dossier_umask'])) {
91
		if (isset($options['dossier_umask']) && is_string($options['dossier_umask'])) {
90
			// See #ZF-4422
92
			// See #ZF-4422
91
			$this->options['dossier_umask'] = octdec($this->options['dossier_umask']);
93
			$this->options['dossier_umask'] = octdec($this->options['dossier_umask']);
92
		}
94
		}
93
		if (isset($options['fichier_umask']) && is_string($options['fichier_umask'])) {
95
		if (isset($options['fichier_umask']) && is_string($options['fichier_umask'])) {
94
			// See #ZF-4422
96
			// See #ZF-4422
95
			$this->options['fichier_umask'] = octdec($this->options['fichier_umask']);
97
			$this->options['fichier_umask'] = octdec($this->options['fichier_umask']);
96
		}
98
		}
97
	}
99
	}
98
	
100
	
99
	private function setOptions($options) {
101
	private function setOptions($options) {
100
		while (list($nom, $valeur) = each($options)) {
102
		while (list($nom, $valeur) = each($options)) {
101
			if (!is_string($nom)) {
103
			if (!is_string($nom)) {
102
				trigger_error("Nom d'option incorecte : $nom", E_USER_WARNING);
104
				trigger_error("Nom d'option incorecte : $nom", E_USER_WARNING);
103
			}
105
			}
104
			$nom = strtolower($nom);
106
			$nom = strtolower($nom);
105
			if (array_key_exists($nom, $this->options)) {
107
			if (array_key_exists($nom, $this->options)) {
106
				$this->options[$nom] = $valeur;
108
				$this->options[$nom] = $valeur;
107
			}
109
			}
108
		}
110
		}
109
	}
111
	}
110
 
112
 
111
   	public function setEmplacement($emplacement) {
113
   	public function setEmplacement($emplacement) {
112
		if (!is_dir($emplacement)) {
114
		if (!is_dir($emplacement)) {
113
			trigger_error("L'emplacement doit être un dossier.", E_USER_WARNING);
115
			trigger_error("L'emplacement doit être un dossier.", E_USER_WARNING);
114
		}
116
		}
115
		if (!is_writable($emplacement)) {
117
		if (!is_writable($emplacement)) {
116
			trigger_error("Le dossier de stockage du cache n'est pas accessible en écriture", E_USER_WARNING);
118
			trigger_error("Le dossier de stockage du cache n'est pas accessible en écriture", E_USER_WARNING);
117
		}
119
		}
118
		$emplacement = rtrim(realpath($emplacement), '\\/').DS;
120
		$emplacement = rtrim(realpath($emplacement), '\\/').DS;
119
		$this->options['stockage_chemin'] = $emplacement;
121
		$this->options['stockage_chemin'] = $emplacement;
120
	}
122
	}
121
 
123
 
122
	/**
124
	/**
123
	 * Test if a cache is available for the given id and (if yes) return it (false else)
125
	 * Test if a cache is available for the given id and (if yes) return it (false else)
124
	 *
126
	 *
125
	 * @param string $id cache id
127
	 * @param string $id cache id
126
	 * @param boolean $doNotTestCacheValidity if set to true, the cache validity won't be tested
128
	 * @param boolean $doNotTestCacheValidity if set to true, the cache validity won't be tested
127
	 * @return string|false cached datas
129
	 * @return string|false cached datas
128
	 */
130
	 */
129
	public function charger($id, $ne_pas_tester_validiter_du_cache = false) {
131
	public function charger($id, $ne_pas_tester_validiter_du_cache = false) {
130
		$donnees = false;
132
		$donnees = false;
131
		if ($this->tester($id, $ne_pas_tester_validiter_du_cache)) {
133
		if ($this->tester($id, $ne_pas_tester_validiter_du_cache)) {
132
			$metadonnees = $this->getMetadonneesFichier($id);
134
			$metadonnees = $this->getMetadonneesFichier($id);
133
			$fichier = $this->getFichierNom($id);
135
			$fichier = $this->getFichierNom($id);
134
			$donnees = $this->getContenuFichier($fichier);
136
			$donnees = $this->getContenuFichier($fichier);
135
			if ($this->options['controle_lecture']) {
137
			if ($this->options['controle_lecture']) {
136
				$cle_secu_donnees = $this->genererCleSecu($donnees, $this->options['controle_lecture_type']);
138
				$cle_secu_donnees = $this->genererCleSecu($donnees, $this->options['controle_lecture_type']);
137
				$cle_secu_controle = $metadonnees['hash'];
139
				$cle_secu_controle = $metadonnees['hash'];
138
				if ($cle_secu_donnees != $cle_secu_controle) {
140
				if ($cle_secu_donnees != $cle_secu_controle) {
139
					// Probléme détecté par le contrôle de lecture !
141
					// Probléme détecté par le contrôle de lecture !
140
					// TODO : loguer le pb de sécu
142
					// TODO : loguer le pb de sécu
141
					$this->supprimer($id);
143
					$this->supprimer($id);
142
					$donnees = false;
144
					$donnees = false;
143
				}
145
				}
144
			}
146
			}
145
		}
147
		}
146
		return $donnees;
148
		return $donnees;
147
	}
149
	}
148
 
150
 
149
	/**
151
	/**
150
	 * Teste si un enregistrement en cache est disponible ou pas (pour l'id passé en paramètre).
152
	 * Teste si un enregistrement en cache est disponible ou pas (pour l'id passé en paramètre).
151
	 *
153
	 *
152
	 * @param string $id identifiant de cache.
154
	 * @param string $id identifiant de cache.
153
	 * @return mixed false (le cache n'est pas disponible) ou timestamp (int) "de dernière modification" de l'enregistrement en cache
155
	 * @return mixed false (le cache n'est pas disponible) ou timestamp (int) "de dernière modification" de l'enregistrement en cache
154
	 */
156
	 */
155
	public function tester($id) {
157
	public function tester($id) {
156
		clearstatcache();
158
		clearstatcache();
157
		return $this->testerExistenceCache($id, false);
159
		return $this->testerExistenceCache($id, false);
158
	}
160
	}
159
 
161
 
160
	/**
162
	/**
161
	 * Save some string datas into a cache record
163
	 * Save some string datas into a cache record
162
	 *
164
	 *
163
	 * Note : $data is always "string" (serialization is done by the
165
	 * Note : $data is always "string" (serialization is done by the
164
	 * core not by the backend)
166
	 * core not by the backend)
165
	 *
167
	 *
166
	 * @param  string $data			 Datas to cache
168
	 * @param  string $data			 Datas to cache
167
	 * @param  string $id			   Cache id
169
	 * @param  string $id			   Cache id
168
	 * @param  array  $tags			 Array of strings, the cache record will be tagged by each string entry
170
	 * @param  array  $tags			 Array of strings, the cache record will be tagged by each string entry
169
	 * @param  int	$specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime)
171
	 * @param  int	$specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime)
170
	 * @return boolean true if no problem
172
	 * @return boolean true if no problem
171
	 */
173
	 */
172
	public function sauver($donnees, $id, $tags = array(), $duree_vie_specifique = false) {
174
	public function sauver($donnees, $id, $tags = array(), $duree_vie_specifique = false) {
173
		clearstatcache();
175
		clearstatcache();
174
		$fichier = $this->getFichierNom($id);
176
		$fichier = $this->getFichierNom($id);
175
		$chemin = $this->getChemin($id);
177
		$chemin = $this->getChemin($id);
176
		
178
		
177
		$resultat = true;
179
		$resultat = true;
178
		if ($this->options['dossier_niveau'] > 0) {
180
		if ($this->options['dossier_niveau'] > 0) {
179
			if (!is_writable($chemin)) {
181
			if (!is_writable($chemin)) {
180
				// maybe, we just have to build the directory structure
182
				// maybe, we just have to build the directory structure
181
				$this->lancerMkdirEtChmodRecursif($id);
183
				$this->lancerMkdirEtChmodRecursif($id);
182
			}
184
			}
183
			if (!is_writable($chemin)) {
185
			if (!is_writable($chemin)) {
184
				$resultat = false;
186
				$resultat = false;
185
			}
187
			}
186
		}
188
		}
187
		
189
		
188
		if ($resultat === true) {
190
		if ($resultat === true) {
189
			if ($this->options['controle_lecture']) {
191
			if ($this->options['controle_lecture']) {
190
				$cle_secu = $this->genererCleSecu($donnees, $this->options['controle_lecture_type']);
192
				$cle_secu = $this->genererCleSecu($donnees, $this->options['controle_lecture_type']);
191
			} else {
193
			} else {
192
				$cle_secu = '';
194
				$cle_secu = '';
193
			}
195
			}
194
			
196
			
195
			$metadonnees = array(
197
			$metadonnees = array(
196
				'hash' => $cle_secu,
198
				'hash' => $cle_secu,
197
				'mtime' => time(),
199
				'mtime' => time(),
198
				'expiration' => $this->getTimestampExpiration($duree_vie_specifique),
200
				'expiration' => $this->Cache->getTimestampExpiration($duree_vie_specifique),
199
				'tags' => $tags
201
				'tags' => $tags
200
			);
202
			);
201
 
203
 
202
			if (! $resultat = $this->setMetadonnees($id, $metadonnees)) {
204
			if (! $resultat = $this->setMetadonnees($id, $metadonnees)) {
203
				// TODO : ajouter un log
205
				// TODO : ajouter un log
204
			} else {
206
			} else {
205
				$resultat = $this->setContenuFichier($fichier, $donnees);
207
				$resultat = $this->setContenuFichier($fichier, $donnees);
206
			}
208
			}
207
		}
209
		}
208
		return $resultat;
210
		return $resultat;
209
	}
211
	}
210
 
212
 
211
	/**
213
	/**
212
	 * Remove a cache record
214
	 * Remove a cache record
213
	 *
215
	 *
214
	 * @param  string $id cache id
216
	 * @param  string $id cache id
215
	 * @return boolean true if no problem
217
	 * @return boolean true if no problem
216
	 */
218
	 */
217
	public function supprimer($id) {
219
	public function supprimer($id) {
218
		$fichier = $this->getFichierNom($id);
220
		$fichier = $this->getFichierNom($id);
219
		$suppression_fichier = $this->supprimerFichier($fichier);
221
		$suppression_fichier = $this->supprimerFichier($fichier);
220
		$suppression_metadonnees = $this->supprimerMetadonnees($id);
222
		$suppression_metadonnees = $this->supprimerMetadonnees($id);
221
		return $suppression_metadonnees && $suppression_fichier;
223
		return $suppression_metadonnees && $suppression_fichier;
222
	}
224
	}
223
 
225
 
224
	/**
226
	/**
225
	 * Clean some cache records
227
	 * Clean some cache records
226
	 *
228
	 *
227
	 * Available modes are :
229
	 * Available modes are :
228
	 * 'all' (default)  => remove all cache entries ($tags is not used)
230
	 * 'all' (default)  => remove all cache entries ($tags is not used)
229
	 * 'old'			=> remove too old cache entries ($tags is not used)
231
	 * 'old'			=> remove too old cache entries ($tags is not used)
230
	 * 'matchingTag'	=> remove cache entries matching all given tags
232
	 * 'matchingTag'	=> remove cache entries matching all given tags
231
	 *					 ($tags can be an array of strings or a single string)
233
	 *					 ($tags can be an array of strings or a single string)
232
	 * 'notMatchingTag' => remove cache entries not matching one of the given tags
234
	 * 'notMatchingTag' => remove cache entries not matching one of the given tags
233
	 *					 ($tags can be an array of strings or a single string)
235
	 *					 ($tags can be an array of strings or a single string)
234
	 * 'matchingAnyTag' => remove cache entries matching any given tags
236
	 * 'matchingAnyTag' => remove cache entries matching any given tags
235
	 *					 ($tags can be an array of strings or a single string)
237
	 *					 ($tags can be an array of strings or a single string)
236
	 *
238
	 *
237
	 * @param string $mode clean mode
239
	 * @param string $mode clean mode
238
	 * @param tags array $tags array of tags
240
	 * @param tags array $tags array of tags
239
	 * @return boolean true if no problem
241
	 * @return boolean true if no problem
240
	 */
242
	 */
241
	public function nettoyer($mode = Cache::NETTOYAGE_MODE_TOUS, $tags = array()) {
243
	public function nettoyer($mode = Cache::NETTOYAGE_MODE_TOUS, $tags = array()) {
242
		// We use this protected method to hide the recursive stuff
244
		// We use this protected method to hide the recursive stuff
243
		clearstatcache();
245
		clearstatcache();
244
		return $this->nettoyerFichiers($this->options['stockage_chemin'], $mode, $tags);
246
		return $this->nettoyerFichiers($this->options['stockage_chemin'], $mode, $tags);
245
	}
247
	}
246
 
248
 
247
	/**
249
	/**
248
	 * Return an array of stored cache ids
250
	 * Return an array of stored cache ids
249
	 *
251
	 *
250
	 * @return array array of stored cache ids (string)
252
	 * @return array array of stored cache ids (string)
251
	 */
253
	 */
252
	public function getIds() {
254
	public function getIds() {
253
		return $this->analyserCache($this->options['stockage_chemin'], 'ids', array());
255
		return $this->analyserCache($this->options['stockage_chemin'], 'ids', array());
254
	}
256
	}
255
 
257
 
256
	/**
258
	/**
257
	 * Return an array of stored tags
259
	 * Return an array of stored tags
258
	 *
260
	 *
259
	 * @return array array of stored tags (string)
261
	 * @return array array of stored tags (string)
260
	 */
262
	 */
261
	public function getTags() {
263
	public function getTags() {
262
		return $this->analyserCache($this->options['stockage_chemin'], 'tags', array());
264
		return $this->analyserCache($this->options['stockage_chemin'], 'tags', array());
263
	}
265
	}
264
 
266
 
265
	/**
267
	/**
266
	 * Return an array of stored cache ids which match given tags
268
	 * Return an array of stored cache ids which match given tags
267
	 *
269
	 *
268
	 * In case of multiple tags, a logical AND is made between tags
270
	 * In case of multiple tags, a logical AND is made between tags
269
	 *
271
	 *
270
	 * @param array $tags array of tags
272
	 * @param array $tags array of tags
271
	 * @return array array of matching cache ids (string)
273
	 * @return array array of matching cache ids (string)
272
	 */
274
	 */
273
	public function getIdsAvecLesTags($tags = array()) {
275
	public function getIdsAvecLesTags($tags = array()) {
274
		return $this->analyserCache($this->options['stockage_chemin'], 'matching', $tags);
276
		return $this->analyserCache($this->options['stockage_chemin'], 'matching', $tags);
275
	}
277
	}
276
 
278
 
277
	/**
279
	/**
278
	 * Return an array of stored cache ids which don't match given tags
280
	 * Return an array of stored cache ids which don't match given tags
279
	 *
281
	 *
280
	 * In case of multiple tags, a logical OR is made between tags
282
	 * In case of multiple tags, a logical OR is made between tags
281
	 *
283
	 *
282
	 * @param array $tags array of tags
284
	 * @param array $tags array of tags
283
	 * @return array array of not matching cache ids (string)
285
	 * @return array array of not matching cache ids (string)
284
	 */
286
	 */
285
	public function getIdsSansLesTags($tags = array()) {
287
	public function getIdsSansLesTags($tags = array()) {
286
		return $this->analyserCache($this->options['stockage_chemin'], 'notMatching', $tags);
288
		return $this->analyserCache($this->options['stockage_chemin'], 'notMatching', $tags);
287
	}
289
	}
288
 
290
 
289
	/**
291
	/**
290
	 * Return an array of stored cache ids which match any given tags
292
	 * Return an array of stored cache ids which match any given tags
291
	 *
293
	 *
292
	 * In case of multiple tags, a logical AND is made between tags
294
	 * In case of multiple tags, a logical AND is made between tags
293
	 *
295
	 *
294
	 * @param array $tags array of tags
296
	 * @param array $tags array of tags
295
	 * @return array array of any matching cache ids (string)
297
	 * @return array array of any matching cache ids (string)
296
	 */
298
	 */
297
	public function getIdsAvecUnTag($tags = array()) {
299
	public function getIdsAvecUnTag($tags = array()) {
298
		return $this->analyserCache($this->options['stockage_chemin'], 'matchingAny', $tags);
300
		return $this->analyserCache($this->options['stockage_chemin'], 'matchingAny', $tags);
299
	}
301
	}
300
 
302
 
301
	/**
303
	/**
302
	 * Return the filling percentage of the backend storage
304
	 * Return the filling percentage of the backend storage
303
	 *
305
	 *
304
	 * @throws Zend_Cache_Exception
306
	 * @throws Zend_Cache_Exception
305
	 * @return int integer between 0 and 100
307
	 * @return int integer between 0 and 100
306
	 */
308
	 */
307
	public function getPourcentageRemplissage() {
309
	public function getPourcentageRemplissage() {
308
		$libre = disk_free_space($this->options['stockage_chemin']);
310
		$libre = disk_free_space($this->options['stockage_chemin']);
309
		$total = disk_total_space($this->options['stockage_chemin']);
311
		$total = disk_total_space($this->options['stockage_chemin']);
310
		
312
		
311
		$pourcentage = 0;
313
		$pourcentage = 0;
312
		if ($total == 0) {
314
		if ($total == 0) {
313
			trigger_error("Impossible d'utiliser la fonction disk_total_space", E_USER_WARNING);
315
			trigger_error("Impossible d'utiliser la fonction disk_total_space", E_USER_WARNING);
314
		} else {
316
		} else {
315
			$pourcentage = ($libre >= $total) ? 100 : ((int) (100. * ($total - $libre) / $total));
317
			$pourcentage = ($libre >= $total) ? 100 : ((int) (100. * ($total - $libre) / $total));
316
		}
318
		}
317
		return $pourcentage;
319
		return $pourcentage;
318
	}
320
	}
319
 
321
 
320
	/**
322
	/**
321
	 * Return an array of metadatas for the given cache id
323
	 * Return an array of metadatas for the given cache id
322
	 *
324
	 *
323
	 * The array must include these keys :
325
	 * The array must include these keys :
324
	 * - expire : the expire timestamp
326
	 * - expire : the expire timestamp
325
	 * - tags : a string array of tags
327
	 * - tags : a string array of tags
326
	 * - mtime : timestamp of last modification time
328
	 * - mtime : timestamp of last modification time
327
	 *
329
	 *
328
	 * @param string $id cache id
330
	 * @param string $id cache id
329
	 * @return array array of metadatas (false if the cache id is not found)
331
	 * @return array array of metadatas (false if the cache id is not found)
330
	 */
332
	 */
331
	public function getMetadonnees($id) {
333
	public function getMetadonnees($id) {
332
		if ($metadonnees = $this->getMetadonneesFichier($id)) {
334
		if ($metadonnees = $this->getMetadonneesFichier($id)) {
333
			if (time() > $metadonnees['expiration']) {
335
			if (time() > $metadonnees['expiration']) {
334
				$metadonnees = false;
336
				$metadonnees = false;
335
			} else {
337
			} else {
336
				$metadonnees = array(
338
				$metadonnees = array(
337
					'expiration' => $metadonnees['expiration'],
339
					'expiration' => $metadonnees['expiration'],
338
					'tags' => $metadonnees['tags'],
340
					'tags' => $metadonnees['tags'],
339
					'mtime' => $metadonnees['mtime']
341
					'mtime' => $metadonnees['mtime']
340
				);
342
				);
341
			}
343
			}
342
		}
344
		}
343
		
345
		
344
		return $metadonnees;
346
		return $metadonnees;
345
	}
347
	}
346
 
348
 
347
	/**
349
	/**
348
	 * Give (if possible) an extra lifetime to the given cache id
350
	 * Give (if possible) an extra lifetime to the given cache id
349
	 *
351
	 *
350
	 * @param string $id cache id
352
	 * @param string $id cache id
351
	 * @param int $extraLifetime
353
	 * @param int $extraLifetime
352
	 * @return boolean true if ok
354
	 * @return boolean true if ok
353
	 */
355
	 */
354
	public function ajouterSupplementDureeDeVie($id, $supplement_duree_de_vie) {
356
	public function ajouterSupplementDureeDeVie($id, $supplement_duree_de_vie) {
355
		$augmentation = true;
357
		$augmentation = true;
356
		if ($metadonnees = $this->getMetadonneesFichier($id)) {
358
		if ($metadonnees = $this->getMetadonneesFichier($id)) {
357
			if (time() > $metadonnees['expiration']) {
359
			if (time() > $metadonnees['expiration']) {
358
				$augmentation = false;
360
				$augmentation = false;
359
			} else {
361
			} else {
360
				$metadonnees_nouvelle = array(
362
				$metadonnees_nouvelle = array(
361
					'hash' => $metadonnees['hash'],
363
					'hash' => $metadonnees['hash'],
362
					'mtime' => time(),
364
					'mtime' => time(),
363
					'expiration' => $metadonnees['expiration'] + $supplement_duree_de_vie,
365
					'expiration' => $metadonnees['expiration'] + $supplement_duree_de_vie,
364
					'tags' => $metadonnees['tags']
366
					'tags' => $metadonnees['tags']
365
				);
367
				);
366
				$augmentation = $this->setMetadonnees($id, $metadonnees_nouvelle);
368
				$augmentation = $this->setMetadonnees($id, $metadonnees_nouvelle);
367
			}
369
			}
368
		}
370
		}
369
		return $augmentation;
371
		return $augmentation;
370
	}
372
	}
371
 
373
 
372
	/**
374
	/**
373
	 * Get a metadatas record
375
	 * Get a metadatas record
374
	 *
376
	 *
375
	 * @param  string $id  Cache id
377
	 * @param  string $id  Cache id
376
	 * @return array|false Associative array of metadatas
378
	 * @return array|false Associative array of metadatas
377
	 */
379
	 */
378
	protected function getMetadonneesFichier($id) {
380
	protected function getMetadonneesFichier($id) {
379
		$metadonnees = false;
381
		$metadonnees = false;
380
		if (isset($this->metadonnees[$id])) {
382
		if (isset($this->metadonnees[$id])) {
381
			$metadonnees = $this->metadonnees[$id];
383
			$metadonnees = $this->metadonnees[$id];
382
		} else {
384
		} else {
383
			if ($metadonnees = $this->chargerMetadonnees($id)) {
385
			if ($metadonnees = $this->chargerMetadonnees($id)) {
384
				$this->setMetadonnees($id, $metadonnees, false);
386
				$this->setMetadonnees($id, $metadonnees, false);
385
			}
387
			}
386
		}
388
		}
387
		return $metadonnees;
389
		return $metadonnees;
388
	}
390
	}
389
 
391
 
390
	/**
392
	/**
391
	 * Set a metadatas record
393
	 * Set a metadatas record
392
	 *
394
	 *
393
	 * @param  string $id		Cache id
395
	 * @param  string $id		Cache id
394
	 * @param  array  $metadatas Associative array of metadatas
396
	 * @param  array  $metadatas Associative array of metadatas
395
	 * @param  boolean $save	 optional pass false to disable saving to file
397
	 * @param  boolean $save	 optional pass false to disable saving to file
396
	 * @return boolean True if no problem
398
	 * @return boolean True if no problem
397
	 */
399
	 */
398
	protected function setMetadonnees($id, $metadonnees, $sauvegarde = true) {
400
	protected function setMetadonnees($id, $metadonnees, $sauvegarde = true) {
399
		if (count($this->metadonnees) >= $this->options['metadonnees_max_taille']) {
401
		if (count($this->metadonnees) >= $this->options['metadonnees_max_taille']) {
400
			$n = (int) ($this->options['metadonnees_max_taille'] / 10);
402
			$n = (int) ($this->options['metadonnees_max_taille'] / 10);
401
			$this->metadonnees = array_slice($this->metadonnees, $n);
403
			$this->metadonnees = array_slice($this->metadonnees, $n);
402
		}
404
		}
403
		
405
		
404
		$resultat = true;
406
		$resultat = true;
405
		if ($sauvegarde) {
407
		if ($sauvegarde) {
406
			$resultat = $this->sauverMetadonnees($id, $metadonnees);
408
			$resultat = $this->sauverMetadonnees($id, $metadonnees);
407
		}
409
		}
408
		if ($resultat == true) {
410
		if ($resultat == true) {
409
			$this->metadonnees[$id] = $metadonnees;
411
			$this->metadonnees[$id] = $metadonnees;
410
		}
412
		}
411
		return $resultat;
413
		return $resultat;
412
	}
414
	}
413
 
415
 
414
	/**
416
	/**
415
	 * Drop a metadata record
417
	 * Drop a metadata record
416
	 *
418
	 *
417
	 * @param  string $id Cache id
419
	 * @param  string $id Cache id
418
	 * @return boolean True if no problem
420
	 * @return boolean True if no problem
419
	 */
421
	 */
420
	protected function supprimerMetadonnees($id) {
422
	protected function supprimerMetadonnees($id) {
421
		if (isset($this->metadonnees[$id])) {
423
		if (isset($this->metadonnees[$id])) {
422
			unset($this->metadonnees[$id]);
424
			unset($this->metadonnees[$id]);
423
		}
425
		}
424
		$fichier_meta = $this->getNomFichierMeta($id);
426
		$fichier_meta = $this->getNomFichierMeta($id);
425
		return $this->supprimerFichier($fichier_meta);
427
		return $this->supprimerFichier($fichier_meta);
426
	}
428
	}
427
 
429
 
428
	/**
430
	/**
429
	 * Clear the metadatas array
431
	 * Clear the metadatas array
430
	 *
432
	 *
431
	 * @return void
433
	 * @return void
432
	 */
434
	 */
433
	protected function nettoyerMetadonnees() {
435
	protected function nettoyerMetadonnees() {
434
		$this->metadonnees = array();
436
		$this->metadonnees = array();
435
	}
437
	}
436
 
438
 
437
	/**
439
	/**
438
	 * Load metadatas from disk
440
	 * Load metadatas from disk
439
	 *
441
	 *
440
	 * @param  string $id Cache id
442
	 * @param  string $id Cache id
441
	 * @return array|false Metadatas associative array
443
	 * @return array|false Metadatas associative array
442
	 */
444
	 */
443
	protected function chargerMetadonnees($id) {
445
	protected function chargerMetadonnees($id) {
444
		$fichier = $this->getNomFichierMeta($id);
446
		$fichier = $this->getNomFichierMeta($id);
445
		if ($resultat = $this->getContenuFichier($fichier)) {
447
		if ($resultat = $this->getContenuFichier($fichier)) {
446
			$resultat = @unserialize($resultat);
448
			$resultat = @unserialize($resultat);
447
		}
449
		}
448
		return $resultat;
450
		return $resultat;
449
	}
451
	}
450
 
452
 
451
	/**
453
	/**
452
	 * Save metadatas to disk
454
	 * Save metadatas to disk
453
	 *
455
	 *
454
	 * @param  string $id		Cache id
456
	 * @param  string $id		Cache id
455
	 * @param  array  $metadatas Associative array
457
	 * @param  array  $metadatas Associative array
456
	 * @return boolean True if no problem
458
	 * @return boolean True if no problem
457
	 */
459
	 */
458
	protected function sauverMetadonnees($id, $metadonnees) {
460
	protected function sauverMetadonnees($id, $metadonnees) {
459
		$fichier = $this->getNomFichierMeta($id);
461
		$fichier = $this->getNomFichierMeta($id);
460
		$resultat = $this->setContenuFichier($fichier, serialize($metadonnees));
462
		$resultat = $this->setContenuFichier($fichier, serialize($metadonnees));
461
		return $resultat;
463
		return $resultat;
462
	}
464
	}
463
 
465
 
464
	/**
466
	/**
465
	 * Make and return a file name (with path) for metadatas
467
	 * Make and return a file name (with path) for metadatas
466
	 *
468
	 *
467
	 * @param  string $id Cache id
469
	 * @param  string $id Cache id
468
	 * @return string Metadatas file name (with path)
470
	 * @return string Metadatas file name (with path)
469
	 */
471
	 */
470
	protected function getNomFichierMeta($id) {
472
	protected function getNomFichierMeta($id) {
471
		$chemin = $this->getChemin($id);
473
		$chemin = $this->getChemin($id);
472
		$fichier_nom = $this->transformaterIdEnNomFichier('interne-meta---'.$id);
474
		$fichier_nom = $this->transformaterIdEnNomFichier('interne-meta---'.$id);
473
		return $chemin.$fichier_nom;
475
		return $chemin.$fichier_nom;
474
	}
476
	}
475
 
477
 
476
	/**
478
	/**
477
	 * Check if the given filename is a metadatas one
479
	 * Check if the given filename is a metadatas one
478
	 *
480
	 *
479
	 * @param  string $fileName File name
481
	 * @param  string $fileName File name
480
	 * @return boolean True if it's a metadatas one
482
	 * @return boolean True if it's a metadatas one
481
	 */
483
	 */
482
	protected function etreFichierMeta($fichier_nom) {
484
	protected function etreFichierMeta($fichier_nom) {
483
		$id = $this->transformerNomFichierEnId($fichier_nom);
485
		$id = $this->transformerNomFichierEnId($fichier_nom);
484
		return (substr($id, 0, 21) == 'interne-meta---') ? true : false;
486
		return (substr($id, 0, 21) == 'interne-meta---') ? true : false;
485
	}
487
	}
486
 
488
 
487
	/**
489
	/**
488
	 * Remove a file
490
	 * Remove a file
489
	 *
491
	 *
490
	 * If we can't remove the file (because of locks or any problem), we will touch
492
	 * If we can't remove the file (because of locks or any problem), we will touch
491
	 * the file to invalidate it
493
	 * the file to invalidate it
492
	 *
494
	 *
493
	 * @param  string $file Complete file path
495
	 * @param  string $file Complete file path
494
	 * @return boolean True if ok
496
	 * @return boolean True if ok
495
	 */
497
	 */
496
	protected function supprimerFichier($fichier) {
498
	protected function supprimerFichier($fichier) {
497
		$resultat = false;
499
		$resultat = false;
498
		if (is_file($fichier)) {
500
		if (is_file($fichier)) {
499
			if ($resultat = @unlink($fichier)) {
501
			if ($resultat = @unlink($fichier)) {
500
				// TODO : ajouter un log
502
				// TODO : ajouter un log
501
			}
503
			}
502
		}
504
		}
503
		return $resultat;
505
		return $resultat;
504
	}
506
	}
505
 
507
 
506
	/**
508
	/**
507
	 * Clean some cache records (protected method used for recursive stuff)
509
	 * Clean some cache records (protected method used for recursive stuff)
508
	 *
510
	 *
509
	 * Available modes are :
511
	 * Available modes are :
510
	 * Zend_Cache::CLEANING_MODE_ALL (default)	=> remove all cache entries ($tags is not used)
512
	 * Zend_Cache::CLEANING_MODE_ALL (default)	=> remove all cache entries ($tags is not used)
511
	 * Zend_Cache::CLEANING_MODE_OLD			  => remove too old cache entries ($tags is not used)
513
	 * Zend_Cache::CLEANING_MODE_OLD			  => remove too old cache entries ($tags is not used)
512
	 * Zend_Cache::CLEANING_MODE_MATCHING_TAG	 => remove cache entries matching all given tags
514
	 * Zend_Cache::CLEANING_MODE_MATCHING_TAG	 => remove cache entries matching all given tags
513
	 *											   ($tags can be an array of strings or a single string)
515
	 *											   ($tags can be an array of strings or a single string)
514
	 * Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG => remove cache entries not {matching one of the given tags}
516
	 * Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG => remove cache entries not {matching one of the given tags}
515
	 *											   ($tags can be an array of strings or a single string)
517
	 *											   ($tags can be an array of strings or a single string)
516
	 * Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG => remove cache entries matching any given tags
518
	 * Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG => remove cache entries matching any given tags
517
	 *											   ($tags can be an array of strings or a single string)
519
	 *											   ($tags can be an array of strings or a single string)
518
	 *
520
	 *
519
	 * @param  string $dir  Directory to clean
521
	 * @param  string $dir  Directory to clean
520
	 * @param  string $mode Clean mode
522
	 * @param  string $mode Clean mode
521
	 * @param  array  $tags Array of tags
523
	 * @param  array  $tags Array of tags
522
	 * @throws Zend_Cache_Exception
524
	 * @throws Zend_Cache_Exception
523
	 * @return boolean True if no problem
525
	 * @return boolean True if no problem
524
	 */
526
	 */
525
	protected function nettoyerFichiers($dossier, $mode = Cache::NETTOYAGE_MODE_TOUS, $tags = array()) {
527
	protected function nettoyerFichiers($dossier, $mode = Cache::NETTOYAGE_MODE_TOUS, $tags = array()) {
526
		if (!is_dir($dossier)) {
528
		if (!is_dir($dossier)) {
527
			return false;
529
			return false;
528
		}
530
		}
529
		$resultat = true;
531
		$resultat = true;
530
		$prefixe = $this->options['fichier_prefixe'];
532
		$prefixe = $this->options['fichier_prefixe'];
531
		$glob = @glob($dossier.$prefixe.'--*');
533
		$glob = @glob($dossier.$prefixe.'--*');
532
		if ($glob === false) {
534
		if ($glob === false) {
533
			// On some systems it is impossible to distinguish between empty match and an error.
535
			// On some systems it is impossible to distinguish between empty match and an error.
534
			return true;
536
			return true;
535
		}
537
		}
536
		foreach ($glob as $fichier)  {
538
		foreach ($glob as $fichier)  {
537
			if (is_file($fichier)) {
539
			if (is_file($fichier)) {
538
				$fichier_nom = basename($fichier);
540
				$fichier_nom = basename($fichier);
539
				if ($this->etreFichierMeta($fichier_nom)) {
541
				if ($this->etreFichierMeta($fichier_nom)) {
540
					// Pour le mode Cache::NETTOYAGE_MODE_TOUS, nous essayons de tous supprimer même les vieux fichiers méta
542
					// Pour le mode Cache::NETTOYAGE_MODE_TOUS, nous essayons de tous supprimer même les vieux fichiers méta
541
					if ($mode != Cache::NETTOYAGE_MODE_TOUS) {
543
					if ($mode != Cache::NETTOYAGE_MODE_TOUS) {
542
						continue;
544
						continue;
543
					}
545
					}
544
				}
546
				}
545
				$id = $this->transformerNomFichierEnId($fichier_nom);
547
				$id = $this->transformerNomFichierEnId($fichier_nom);
546
				$metadonnees = $this->getMetadonneesFichier($id);
548
				$metadonnees = $this->getMetadonneesFichier($id);
547
				if ($metadonnees === FALSE) {
549
				if ($metadonnees === FALSE) {
548
					$metadonnees = array('expiration' => 1, 'tags' => array());
550
					$metadonnees = array('expiration' => 1, 'tags' => array());
549
				}
551
				}
550
				switch ($mode) {
552
				switch ($mode) {
551
					case Cache::NETTOYAGE_MODE_TOUS :
553
					case Cache::NETTOYAGE_MODE_TOUS :
552
						if ($resultat_suppression = $this->supprimer($id)) {
554
						if ($resultat_suppression = $this->supprimer($id)) {
553
							// Dans ce cas seulement, nous acception qu'il y ait un problème avec la suppresssion du fichier meta
555
							// Dans ce cas seulement, nous acception qu'il y ait un problème avec la suppresssion du fichier meta
554
							$resultat_suppression = $this->supprimerFichier($fichier);
556
							$resultat_suppression = $this->supprimerFichier($fichier);
555
						}
557
						}
556
						$resultat = $resultat && $resultat_suppression;
558
						$resultat = $resultat && $resultat_suppression;
557
						break;
559
						break;
558
					case Cache::NETTOYAGE_MODE_EXPIRATION :
560
					case Cache::NETTOYAGE_MODE_EXPIRATION :
559
						if (time() > $metadonnees['expiration']) {
561
						if (time() > $metadonnees['expiration']) {
560
							$resultat = $this->supprimer($id) && $resultat;
562
							$resultat = $this->supprimer($id) && $resultat;
561
						}
563
						}
562
						break;
564
						break;
563
					case Cache::NETTOYAGE_MODE_AVEC_LES_TAGS :
565
					case Cache::NETTOYAGE_MODE_AVEC_LES_TAGS :
564
						$correspondance = true;
566
						$correspondance = true;
565
						foreach ($tags as $tag) {
567
						foreach ($tags as $tag) {
566
							if (!in_array($tag, $metadonnees['tags'])) {
568
							if (!in_array($tag, $metadonnees['tags'])) {
567
								$correspondance = false;
569
								$correspondance = false;
568
								break;
570
								break;
569
							}
571
							}
570
						}
572
						}
571
						if ($correspondance) {
573
						if ($correspondance) {
572
							$resultat = $this->supprimer($id) && $resultat;
574
							$resultat = $this->supprimer($id) && $resultat;
573
						}
575
						}
574
						break;
576
						break;
575
					case Cache::NETTOYAGE_MODE_SANS_LES_TAGS :
577
					case Cache::NETTOYAGE_MODE_SANS_LES_TAGS :
576
						$correspondance = false;
578
						$correspondance = false;
577
						foreach ($tags as $tag) {
579
						foreach ($tags as $tag) {
578
							if (in_array($tag, $metadonnees['tags'])) {
580
							if (in_array($tag, $metadonnees['tags'])) {
579
								$correspondance = true;
581
								$correspondance = true;
580
								break;
582
								break;
581
							}
583
							}
582
						}
584
						}
583
						if (!$correspondance) {
585
						if (!$correspondance) {
584
							$resultat = $this->supprimer($id) && $resultat;
586
							$resultat = $this->supprimer($id) && $resultat;
585
						}
587
						}
586
						break;
588
						break;
587
					case Cache::NETTOYAGE_MODE_AVEC_UN_TAG :
589
					case Cache::NETTOYAGE_MODE_AVEC_UN_TAG :
588
						$correspondance = false;
590
						$correspondance = false;
589
						foreach ($tags as $tag) {
591
						foreach ($tags as $tag) {
590
							if (in_array($tag, $metadonnees['tags'])) {
592
							if (in_array($tag, $metadonnees['tags'])) {
591
								$correspondance = true;
593
								$correspondance = true;
592
								break;
594
								break;
593
							}
595
							}
594
						}
596
						}
595
						if ($correspondance) {
597
						if ($correspondance) {
596
							$resultat = $this->supprimer($id) && $resultat;
598
							$resultat = $this->supprimer($id) && $resultat;
597
						}
599
						}
598
						break;
600
						break;
599
					default:
601
					default:
600
						trigger_error("Mode de nettoyage invalide pour la méthode nettoyer()", E_USER_WARNING);
602
						trigger_error("Mode de nettoyage invalide pour la méthode nettoyer()", E_USER_WARNING);
601
						break;
603
						break;
602
				}
604
				}
603
			}
605
			}
604
			if ((is_dir($fichier)) and ($this->options['dossier_niveau'] > 0)) {
606
			if ((is_dir($fichier)) and ($this->options['dossier_niveau'] > 0)) {
605
				// Appel récursif
607
				// Appel récursif
606
				$resultat = $this->nettoyerFichiers($fichier.DS, $mode, $tags) && $resultat;
608
				$resultat = $this->nettoyerFichiers($fichier.DS, $mode, $tags) && $resultat;
607
				if ($mode == Cache::NETTOYAGE_MODE_TOUS) {
609
				if ($mode == Cache::NETTOYAGE_MODE_TOUS) {
608
					// Si mode == Cache::NETTOYAGE_MODE_TOUS, nous essayons de supprimer la structure aussi
610
					// Si mode == Cache::NETTOYAGE_MODE_TOUS, nous essayons de supprimer la structure aussi
609
					@rmdir($fichier);
611
					@rmdir($fichier);
610
				}
612
				}
611
			}
613
			}
612
		}
614
		}
613
		return $resultat;
615
		return $resultat;
614
	}
616
	}
615
 
617
 
616
	protected function analyserCache($dossier, $mode, $tags = array()) {
618
	protected function analyserCache($dossier, $mode, $tags = array()) {
617
		if (!is_dir($dossier)) {
619
		if (!is_dir($dossier)) {
618
			return false;
620
			return false;
619
		}
621
		}
620
		$resultat = array();
622
		$resultat = array();
621
		$prefixe = $this->options['fichier_prefixe'];
623
		$prefixe = $this->options['fichier_prefixe'];
622
		$glob = @glob($dossier.$prefixe.'--*');
624
		$glob = @glob($dossier.$prefixe.'--*');
623
		if ($glob === false) {
625
		if ($glob === false) {
624
			// On some systems it is impossible to distinguish between empty match and an error.
626
			// On some systems it is impossible to distinguish between empty match and an error.
625
			return array();
627
			return array();
626
		}
628
		}
627
		foreach ($glob as $fichier)  {
629
		foreach ($glob as $fichier)  {
628
			if (is_file($fichier)) {
630
			if (is_file($fichier)) {
629
				$nom_fichier = basename($fichier);
631
				$nom_fichier = basename($fichier);
630
				$id = $this->transformerNomFichierEnId($nom_fichier);
632
				$id = $this->transformerNomFichierEnId($nom_fichier);
631
				$metadonnees = $this->getMetadonneesFichier($id);
633
				$metadonnees = $this->getMetadonneesFichier($id);
632
				if ($metadonnees === FALSE) {
634
				if ($metadonnees === FALSE) {
633
					continue;
635
					continue;
634
				}
636
				}
635
				if (time() > $metadonnees['expiration']) {
637
				if (time() > $metadonnees['expiration']) {
636
					continue;
638
					continue;
637
				}
639
				}
638
				switch ($mode) {
640
				switch ($mode) {
639
					case 'ids':
641
					case 'ids':
640
						$resultat[] = $id;
642
						$resultat[] = $id;
641
						break;
643
						break;
642
					case 'tags':
644
					case 'tags':
643
						$resultat = array_unique(array_merge($resultat, $metadonnees['tags']));
645
						$resultat = array_unique(array_merge($resultat, $metadonnees['tags']));
644
						break;
646
						break;
645
					case 'matching':
647
					case 'matching':
646
						$correspondance = true;
648
						$correspondance = true;
647
						foreach ($tags as $tag) {
649
						foreach ($tags as $tag) {
648
							if (!in_array($tag, $metadonnees['tags'])) {
650
							if (!in_array($tag, $metadonnees['tags'])) {
649
								$correspondance = false;
651
								$correspondance = false;
650
								break;
652
								break;
651
							}
653
							}
652
						}
654
						}
653
						if ($correspondance) {
655
						if ($correspondance) {
654
							$resultat[] = $id;
656
							$resultat[] = $id;
655
						}
657
						}
656
						break;
658
						break;
657
					case 'notMatching':
659
					case 'notMatching':
658
						$correspondance = false;
660
						$correspondance = false;
659
						foreach ($tags as $tag) {
661
						foreach ($tags as $tag) {
660
							if (in_array($tag, $metadonnees['tags'])) {
662
							if (in_array($tag, $metadonnees['tags'])) {
661
								$correspondance = true;
663
								$correspondance = true;
662
								break;
664
								break;
663
							}
665
							}
664
						}
666
						}
665
						if (!$correspondance) {
667
						if (!$correspondance) {
666
							$resultat[] = $id;
668
							$resultat[] = $id;
667
						}
669
						}
668
						break;
670
						break;
669
					case 'matchingAny':
671
					case 'matchingAny':
670
						$correspondance = false;
672
						$correspondance = false;
671
						foreach ($tags as $tag) {
673
						foreach ($tags as $tag) {
672
							if (in_array($tag, $metadonnees['tags'])) {
674
							if (in_array($tag, $metadonnees['tags'])) {
673
								$correspondance = true;
675
								$correspondance = true;
674
								break;
676
								break;
675
							}
677
							}
676
						}
678
						}
677
						if ($correspondance) {
679
						if ($correspondance) {
678
							$resultat[] = $id;
680
							$resultat[] = $id;
679
						}
681
						}
680
						break;
682
						break;
681
					default:
683
					default:
682
						trigger_error("Mode invalide pour la méthode analyserCache()", E_USER_WARNING);
684
						trigger_error("Mode invalide pour la méthode analyserCache()", E_USER_WARNING);
683
						break;
685
						break;
684
				}
686
				}
685
			}
687
			}
686
			if ((is_dir($fichier)) and ($this->options['dossier_niveau'] > 0)) {
688
			if ((is_dir($fichier)) and ($this->options['dossier_niveau'] > 0)) {
687
				// Appel récursif
689
				// Appel récursif
688
				$resultat_analyse_recursive = $this->analyserCache($fichier.DS, $mode, $tags);
690
				$resultat_analyse_recursive = $this->analyserCache($fichier.DS, $mode, $tags);
689
				if ($resultat_analyse_recursive === false) {
691
				if ($resultat_analyse_recursive === false) {
690
					// TODO : ajoute un log
692
					// TODO : ajoute un log
691
				} else {
693
				} else {
692
					$resultat = array_unique(array_merge($resultat, $resultat_analyse_recursive));
694
					$resultat = array_unique(array_merge($resultat, $resultat_analyse_recursive));
693
				}
695
				}
694
			}
696
			}
695
		}
697
		}
696
		return array_unique($resultat);
698
		return array_unique($resultat);
697
	}
699
	}
698
 
-
 
699
	/**
-
 
700
	 * Compute & return the expire time
-
 
701
	 *
-
 
702
	 * @return int expire time (unix timestamp)
-
 
703
	 */
-
 
704
	protected function getTimestampExpiration($duree_de_vie) {
-
 
705
		if ($duree_de_vie === false) {
-
 
706
			$duree_de_vie = 3600;
-
 
707
		}
-
 
708
		$timestamp = ($duree_de_vie === null) ? 9999999999 : (time() + $duree_de_vie);
-
 
709
		return $timestamp;
-
 
710
	}
-
 
711
 
700
 
712
	/**
701
	/**
713
	 * Make a control key with the string containing datas
702
	 * Make a control key with the string containing datas
714
	 *
703
	 *
715
	 * @param  string $data		Data
704
	 * @param  string $data		Data
716
	 * @param  string $controlType Type of control 'md5', 'crc32' or 'strlen'
705
	 * @param  string $controlType Type of control 'md5', 'crc32' or 'strlen'
717
	 * @throws Zend_Cache_Exception
706
	 * @throws Zend_Cache_Exception
718
	 * @return string Control key
707
	 * @return string Control key
719
	 */
708
	 */
720
	protected function genererCleSecu($donnees, $type_de_controle) {
709
	protected function genererCleSecu($donnees, $type_de_controle) {
721
		switch ($type_de_controle) {
710
		switch ($type_de_controle) {
722
		case 'md5':
711
		case 'md5':
723
			return md5($donnees);
712
			return md5($donnees);
724
		case 'crc32':
713
		case 'crc32':
725
			return crc32($donnees);
714
			return crc32($donnees);
726
		case 'strlen':
715
		case 'strlen':
727
			return strlen($donnees);
716
			return strlen($donnees);
728
		case 'adler32':
717
		case 'adler32':
729
			return hash('adler32', $donnees);
718
			return hash('adler32', $donnees);
730
		default:
719
		default:
731
			trigger_error("Fonction de génération de clé de sécurité introuvable : $type_de_controle", E_USER_WARNING);
720
			trigger_error("Fonction de génération de clé de sécurité introuvable : $type_de_controle", E_USER_WARNING);
732
		}
721
		}
733
	}
722
	}
734
 
723
 
735
	/**
724
	/**
736
	 * Transform a cache id into a file name and return it
725
	 * Transform a cache id into a file name and return it
737
	 *
726
	 *
738
	 * @param  string $id Cache id
727
	 * @param  string $id Cache id
739
	 * @return string File name
728
	 * @return string File name
740
	 */
729
	 */
741
	protected function transformaterIdEnNomFichier($id) {
730
	protected function transformaterIdEnNomFichier($id) {
742
		$prefixe = $this->options['fichier_prefixe'];
731
		$prefixe = $this->options['fichier_prefixe'];
743
		$resultat = $prefixe.'---'.$id;
732
		$resultat = $prefixe.'---'.$id;
744
		return $resultat;
733
		return $resultat;
745
	}
734
	}
746
 
735
 
747
	/**
736
	/**
748
	 * Make and return a file name (with path)
737
	 * Make and return a file name (with path)
749
	 *
738
	 *
750
	 * @param  string $id Cache id
739
	 * @param  string $id Cache id
751
	 * @return string File name (with path)
740
	 * @return string File name (with path)
752
	 */
741
	 */
753
	protected function getFichierNom($id) {
742
	protected function getFichierNom($id) {
754
		$path = $this->getChemin($id);
743
		$path = $this->getChemin($id);
755
		$fileName = $this->transformaterIdEnNomFichier($id);
744
		$fileName = $this->transformaterIdEnNomFichier($id);
756
		return $path . $fileName;
745
		return $path . $fileName;
757
	}
746
	}
758
 
747
 
759
	/**
748
	/**
760
	 * Return the complete directory path of a filename (including hashedDirectoryStructure)
749
	 * Return the complete directory path of a filename (including hashedDirectoryStructure)
761
	 *
750
	 *
762
	 * @param  string $id Cache id
751
	 * @param  string $id Cache id
763
	 * @param  boolean $decoupage if true, returns array of directory parts instead of single string
752
	 * @param  boolean $decoupage if true, returns array of directory parts instead of single string
764
	 * @return string Complete directory path
753
	 * @return string Complete directory path
765
	 */
754
	 */
766
	protected function getChemin($id, $decoupage = false) {
755
	protected function getChemin($id, $decoupage = false) {
767
		$morceaux = array();
756
		$morceaux = array();
768
		$chemin = $this->options['stockage_chemin'];
757
		$chemin = $this->options['stockage_chemin'];
769
		$prefixe = $this->options['fichier_prefixe'];
758
		$prefixe = $this->options['fichier_prefixe'];
770
		if ($this->options['dossier_niveau'] > 0) {
759
		if ($this->options['dossier_niveau'] > 0) {
771
			$hash = hash('adler32', $id);
760
			$hash = hash('adler32', $id);
772
			for ($i = 0 ; $i < $this->options['dossier_niveau'] ; $i++) {
761
			for ($i = 0 ; $i < $this->options['dossier_niveau'] ; $i++) {
773
				$chemin .= $prefixe.'--'.substr($hash, 0, $i + 1).DS;
762
				$chemin .= $prefixe.'--'.substr($hash, 0, $i + 1).DS;
774
				$morceaux[] = $chemin;
763
				$morceaux[] = $chemin;
775
			}
764
			}
776
		}
765
		}
777
		return ($decoupage) ? 	$morceaux : $chemin;
766
		return ($decoupage) ? 	$morceaux : $chemin;
778
	}
767
	}
779
 
768
 
780
	/**
769
	/**
781
	 * Make the directory strucuture for the given id
770
	 * Make the directory strucuture for the given id
782
	 *
771
	 *
783
	 * @param string $id cache id
772
	 * @param string $id cache id
784
	 * @return boolean true
773
	 * @return boolean true
785
	 */
774
	 */
786
	protected function lancerMkdirEtChmodRecursif($id) {
775
	protected function lancerMkdirEtChmodRecursif($id) {
787
		$resultat = true;
776
		$resultat = true;
788
		if ($this->options['dossier_niveau'] > 0) {
777
		if ($this->options['dossier_niveau'] > 0) {
789
			$chemins = $this->getChemin($id, true);
778
			$chemins = $this->getChemin($id, true);
790
			foreach ($chemins as $chemin) {
779
			foreach ($chemins as $chemin) {
791
				if (!is_dir($chemin)) {
780
				if (!is_dir($chemin)) {
792
					@mkdir($chemin, $this->options['dossier_umask']);
781
					@mkdir($chemin, $this->options['dossier_umask']);
793
					@chmod($chemin, $this->options['dossier_umask']); // see #ZF-320 (this line is required in some configurations)
782
					@chmod($chemin, $this->options['dossier_umask']); // see #ZF-320 (this line is required in some configurations)
794
				}
783
				}
795
			}
784
			}
796
		}
785
		}
797
		return $resultat;
786
		return $resultat;
798
	}
787
	}
799
 
788
 
800
	/**
789
	/**
801
	 * Test if the given cache id is available (and still valid as a cache record)
790
	 * Test if the given cache id is available (and still valid as a cache record)
802
	 *
791
	 *
803
	 * @param  string  $id					 Cache id
792
	 * @param  string  $id					 Cache id
804
	 * @param  boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested
793
	 * @param  boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested
805
	 * @return boolean|mixed false (a cache is not available) or "last modified" timestamp (int) of the available cache record
794
	 * @return boolean|mixed false (a cache is not available) or "last modified" timestamp (int) of the available cache record
806
	 */
795
	 */
807
	protected function testerExistenceCache($id, $ne_pas_tester_validiter_du_cache) {
796
	protected function testerExistenceCache($id, $ne_pas_tester_validiter_du_cache) {
808
		$resultat = false;
797
		$resultat = false;
809
		if ($metadonnees = $this->getMetadonnees($id)) {
798
		if ($metadonnees = $this->getMetadonnees($id)) {
810
			if ($ne_pas_tester_validiter_du_cache || (time() <= $metadonnees['expiration'])) {
799
			if ($ne_pas_tester_validiter_du_cache || (time() <= $metadonnees['expiration'])) {
811
				$resultat =  $metadonnees['mtime'];
800
				$resultat =  $metadonnees['mtime'];
812
			}
801
			}
813
		}
802
		}
814
		return $resultat;
803
		return $resultat;
815
	}
804
	}
816
 
805
 
817
	/**
806
	/**
818
	 * Return the file content of the given file
807
	 * Return the file content of the given file
819
	 *
808
	 *
820
	 * @param  string $file File complete path
809
	 * @param  string $file File complete path
821
	 * @return string File content (or false if problem)
810
	 * @return string File content (or false if problem)
822
	 */
811
	 */
823
	protected function getContenuFichier($fichier) {
812
	protected function getContenuFichier($fichier) {
824
		$resultat = false;
813
		$resultat = false;
825
		if (is_file($fichier)) {
814
		if (is_file($fichier)) {
826
			$f = @fopen($fichier, 'rb');
815
			$f = @fopen($fichier, 'rb');
827
			if ($f) {
816
			if ($f) {
828
				if ($this->options['fichier_verrou']) @flock($f, LOCK_SH);
817
				if ($this->options['fichier_verrou']) @flock($f, LOCK_SH);
829
				$resultat = stream_get_contents($f);
818
				$resultat = stream_get_contents($f);
830
				if ($this->options['fichier_verrou']) @flock($f, LOCK_UN);
819
				if ($this->options['fichier_verrou']) @flock($f, LOCK_UN);
831
				@fclose($f);
820
				@fclose($f);
832
			}
821
			}
833
		}
822
		}
834
		return $resultat;
823
		return $resultat;
835
	}
824
	}
836
 
825
 
837
	/**
826
	/**
838
	 * Put the given string into the given file
827
	 * Put the given string into the given file
839
	 *
828
	 *
840
	 * @param  string $file   File complete path
829
	 * @param  string $file   File complete path
841
	 * @param  string $string String to put in file
830
	 * @param  string $string String to put in file
842
	 * @return boolean true if no problem
831
	 * @return boolean true if no problem
843
	 */
832
	 */
844
	protected function setContenuFichier($fichier, $chaine) {
833
	protected function setContenuFichier($fichier, $chaine) {
845
		$resultat = false;
834
		$resultat = false;
846
		$f = @fopen($fichier, 'ab+');
835
		$f = @fopen($fichier, 'ab+');
847
		if ($f) {
836
		if ($f) {
848
			if ($this->options['fichier_verrou']) @flock($f, LOCK_EX);
837
			if ($this->options['fichier_verrou']) @flock($f, LOCK_EX);
849
			fseek($f, 0);
838
			fseek($f, 0);
850
			ftruncate($f, 0);
839
			ftruncate($f, 0);
851
			$tmp = @fwrite($f, $chaine);
840
			$tmp = @fwrite($f, $chaine);
852
			if (!($tmp === FALSE)) {
841
			if (!($tmp === FALSE)) {
853
				$resultat = true;
842
				$resultat = true;
854
			}
843
			}
855
			@fclose($f);
844
			@fclose($f);
856
		}
845
		}
857
		@chmod($fichier, $this->options['fichier_umask']);
846
		@chmod($fichier, $this->options['fichier_umask']);
858
		return $resultat;
847
		return $resultat;
859
	}
848
	}
860
 
849
 
861
	/**
850
	/**
862
	 * Transform a file name into cache id and return it
851
	 * Transform a file name into cache id and return it
863
	 *
852
	 *
864
	 * @param  string $fileName File name
853
	 * @param  string $fileName File name
865
	 * @return string Cache id
854
	 * @return string Cache id
866
	 */
855
	 */
867
	protected function transformerNomFichierEnId($nom_de_fichier) {
856
	protected function transformerNomFichierEnId($nom_de_fichier) {
868
		$prefixe = $this->options['fichier_prefixe'];
857
		$prefixe = $this->options['fichier_prefixe'];
869
		return preg_replace('~^' . $prefixe . '---(.*)$~', '$1', $nom_de_fichier);
858
		return preg_replace('~^' . $prefixe . '---(.*)$~', '$1', $nom_de_fichier);
870
	}
859
	}
871
}
860
}
872
?>
861
?>