Subversion Repositories Applications.framework

Rev

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

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