Completed
Push — master ( 14072a...b74bfb )
by cam
07:13 queued 03:15
created

invalideur.php ➔ purger_repertoire()   D

Complexity

Conditions 18
Paths 18

Size

Total Lines 45

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 18
nc 18
nop 2
dl 0
loc 45
rs 4.8666
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/***************************************************************************\
4
 *  SPIP, Systeme de publication pour l'internet                           *
5
 *                                                                         *
6
 *  Copyright (c) 2001-2019                                                *
7
 *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
8
 *                                                                         *
9
 *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
10
 *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
11
\***************************************************************************/
12
13
/**
14
 * Gestion du cache et des invalidations de cache
15
 *
16
 * @package SPIP\Core\Cache
17
 **/
18
19
if (!defined('_ECRIRE_INC_VERSION')) {
20
	return;
21
}
22
23
include_spip('base/serial');
24
25
/** Estime la taille moyenne d'un fichier cache, pour ne pas les regarder (10ko) */
26
if (!defined('_TAILLE_MOYENNE_FICHIER_CACHE')) {
27
	define('_TAILLE_MOYENNE_FICHIER_CACHE', 1024 * 10);
28
}
29
/**
30
 * Si un fichier n'a pas été servi (fileatime) depuis plus d'une heure, on se sent
31
 * en droit de l'éliminer
32
 */
33
if (!defined('_AGE_CACHE_ATIME')) {
34
	define('_AGE_CACHE_ATIME', 3600);
35
}
36
37
/**
38
 * Calcul le nombre de fichiers à la racine d'un répertoire ainsi qu'une
39
 * approximation de la taille du répertoire
40
 *
41
 * On ne calcule que la racine pour pour aller vite.
42
 *
43
 * @param string $dir Chemin du répertoire
44
 * @param string $nb_estim_taille Nombre de fichiers maximum pour estimer la taille
0 ignored issues
show
Documentation introduced by
Should the type for parameter $nb_estim_taille not be integer?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
45
 * @return bool|array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use false|integer[].

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
46
 *
47
 *     - false si le répertoire ne peut pas être ouvert
48
 *     - array(nombre de fichiers, approximation de la taille en octet) sinon
49
 **/
50
function nombre_de_fichiers_repertoire($dir, $nb_estim_taille = 20) {
51
	$taille = 0; // mesurer la taille de N fichiers au hasard dans le repertoire
52
	$nb = $nb_estim_taille;
53
	if (!$h = opendir($dir)) {
54
		return false;
55
	}
56
	$total = 0;
57
	while (($fichier = @readdir($h)) !== false) {
58
		if ($fichier[0] != '.' and !is_dir("$dir/$fichier")) {
59
			$total++;
60
			if ($nb and rand(1, 10) == 1) {
61
				$taille += filesize("$dir/$fichier");
62
				$nb--;
63
			}
64
		}
65
	}
66
	closedir($h);
67
68
	return array($total, $taille ? $taille / ($nb_estim_taille - $nb) : _TAILLE_MOYENNE_FICHIER_CACHE);
69
}
70
71
72
/**
73
 * Évalue approximativement la taille du cache
74
 *
75
 * Pour de gros volumes, impossible d'ouvrir chaque fichier,
76
 * on y va donc à l'estime !
77
 *
78
 * @return int Taille approximative en octets
0 ignored issues
show
Documentation introduced by
Should the return type not be integer|double?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
79
 **/
80
function taille_du_cache() {
81
	# check dirs until we reach > 500 files
82
	$t = 0;
83
	$n = 0;
84
	$time = isset($GLOBALS['meta']['cache_mark']) ? $GLOBALS['meta']['cache_mark'] : 0;
85
	for ($i=0; $i < 256; $i++) {
86
		$dir = _DIR_CACHE.sprintf('%02s', dechex($i));
87
		if (@is_dir($dir) and is_readable($dir) and $d = opendir($dir)) {
88
			while (($f = readdir($d)) !== false) {
89
				if (preg_match(',^[[0-9a-f]+\.cache$,S', $f) and $a = stat("$dir/$f")) {
90
					$n++;
91
					if ($a['mtime'] >= $time) {
92
						if ($a['blocks'] > 0) {
93
							$t += 512*$a['blocks'];
94
						} else {
95
							$t += $a['size'];
96
						}
97
					}
98
				}
99
			}
100
		}
101
		if ($n > 500) {
102
			return intval(256*$t/(1+$i));
103
		}
104
	}
105
	return $t;
106
}
107
108
109
/**
110
 * Invalider les caches liés à telle condition
111
 *
112
 * Les invalideurs sont de la forme 'objet/id_objet'.
113
 * La condition est géneralement "id='objet/id_objet'".
114
 *
115
 * Ici on se contente de noter la date de mise à jour dans les metas,
116
 * pour le type d'objet en question (non utilisé cependant) et pour
117
 * tout le site (sur la meta `derniere_modif`)
118
 *
119
 * @global derniere_modif_invalide
120
 *     Par défaut à `true`, la meta `derniere_modif` est systématiquement
121
 *     calculée dès qu'un invalideur se présente. Cette globale peut
122
 *     être mise à `false` (aucun changement sur `derniere_modif`) ou
123
 *     sur une liste de type d'objets (changements uniquement lorsqu'une
124
 *     modification d'un des objets se présente).
125
 *
126
 * @param string $cond
127
 *     Condition d'invalidation
128
 * @param bool $modif
129
 *     Inutilisé
130
 **/
131
function inc_suivre_invalideur_dist($cond, $modif = true) {
132
	if (!$modif) {
133
		return;
134
	}
135
136
	// determiner l'objet modifie : forum, article, etc
137
	if (preg_match(',["\']([a-z_]+)[/"\'],', $cond, $r)) {
138
		$objet = objet_type($r[1]);
139
	}
140
141
	// stocker la date_modif_$objet (ne sert a rien pour le moment)
142
	if (isset($objet)) {
143
		ecrire_meta('derniere_modif_' . $objet, time());
144
	}
145
146
	// si $derniere_modif_invalide est un array('article', 'rubrique')
147
	// n'affecter la meta que si un de ces objets est modifie
148
	if (is_array($GLOBALS['derniere_modif_invalide'])) {
149
		if (in_array($objet, $GLOBALS['derniere_modif_invalide'])) {
0 ignored issues
show
Bug introduced by
The variable $objet does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
150
			ecrire_meta('derniere_modif', time());
151
		}
152
	} // sinon, cas standard, toujours affecter la meta
153
	else {
154
		ecrire_meta('derniere_modif', time());
155
	}
156
}
157
158
159
/**
160
 * Purge un répertoire de ses fichiers
161
 *
162
 * Utilisée entre autres pour vider le cache depuis l'espace privé
163
 *
164
 * @uses supprimer_fichier()
165
 *
166
 * @param string $dir
167
 *     Chemin du répertoire à purger
168
 * @param array $options
169
 *     Tableau des options. Peut être :
170
 *
171
 *     - atime : timestamp pour ne supprimer que les fichiers antérieurs
172
 *       à cette date (via fileatime)
173
 *     - mtime : timestamp pour ne supprimer que les fichiers antérieurs
174
 *       à cette date (via filemtime)
175
 *     - limit : nombre maximum de suppressions
176
 * @return int
0 ignored issues
show
Documentation introduced by
Should the return type not be null|integer?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
177
 *     Nombre de fichiers supprimés
178
 **/
179
function purger_repertoire($dir, $options = array()) {
180
	if (!is_dir($dir) or !is_readable($dir)) {
181
		return;
182
	}
183
	$handle = opendir($dir);
184
	if (!$handle) {
185
		return;
186
	}
187
188
	$total = 0;
189
190
	while (($fichier = @readdir($handle)) !== false) {
191
		// Eviter ".", "..", ".htaccess", ".svn" etc & CACHEDIR.TAG
192
		if ($fichier[0] == '.' or $fichier == 'CACHEDIR.TAG') {
193
			continue;
194
		}
195
		$chemin = "$dir/$fichier";
196
		if (is_file($chemin)) {
197
			if ((!isset($options['atime']) or (@fileatime($chemin) < $options['atime']))
198
				and (!isset($options['mtime']) or (@filemtime($chemin) < $options['mtime']))
199
			) {
200
				supprimer_fichier($chemin);
201
				$total++;
202
			}
203
		} else {
204
			if (is_dir($chemin)) {
205
				$opts = $options;
206
				if (isset($options['limit'])) {
207
					$opts['limit'] = $options['limit'] - $total;
208
				}
209
				$total += purger_repertoire($chemin, $opts);
210
				if (isset($options['subdir']) && $options['subdir']) {
211
					spip_unlink($chemin);
212
				}
213
			}
214
		}
215
216
		if (isset($options['limit']) and $total >= $options['limit']) {
217
			break;
218
		}
219
	}
220
	closedir($handle);
221
222
	return $total;
223
}
224
225
226
//
227
// Destruction des fichiers caches invalides
228
//
229
230
// Securite : est sur que c'est un cache
231
// http://code.spip.net/@retire_cache
232
function retire_cache($cache) {
233
234
	if (preg_match(
235
		',^([0-9a-f]/)?([0-9]+/)?[0-9a-f]+\.cache(\.gz)?$,i',
236
		$cache
237
	)) {
238
		// supprimer le fichier (de facon propre)
239
		supprimer_fichier(_DIR_CACHE . $cache);
240
	} else {
241
		spip_log("Nom de fichier cache incorrect : $cache");
242
	}
243
}
244
245
// Supprimer les caches marques "x"
246
// A priori dans cette version la fonction ne sera pas appelee, car
247
// la meta est toujours false ; mais evitons un bug si elle est appellee
248
// http://code.spip.net/@retire_caches
249
function inc_retire_caches_dist($chemin = '') {
0 ignored issues
show
Unused Code introduced by
The parameter $chemin is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
250
	if (isset($GLOBALS['meta']['invalider_caches'])) {
251
		effacer_meta('invalider_caches');
252
	} # concurrence
253
}
254
255
#######################################################################
256
##
257
## Ci-dessous les fonctions qui restent appellees dans le core
258
## pour pouvoir brancher le plugin invalideur ;
259
## mais ici elles ne font plus rien
260
##
261
262
function retire_caches($chemin = '') {
263
	if ($retire_caches = charger_fonction('retire_caches', 'inc', true)) {
264
		return $retire_caches($chemin);
265
	}
266
}
267
268
269
// Fonction permettant au compilo de calculer les invalideurs d'une page
270
// (note: si absente, n'est pas appellee)
271
272
// http://code.spip.net/@calcul_invalideurs
273
function calcul_invalideurs($corps, $primary, &$boucles, $id_boucle) {
274
	if ($calcul_invalideurs = charger_fonction('calcul_invalideurs', 'inc', true)) {
275
		return $calcul_invalideurs($corps, $primary, $boucles, $id_boucle);
276
	}
277
	return $corps;
278
}
279
280
281
// Cette fonction permet de supprimer tous les invalideurs
282
// Elle ne touche pas aux fichiers cache eux memes ; elle est
283
// invoquee quand on vide tout le cache en bloc (action/purger)
284
//
285
// http://code.spip.net/@supprime_invalideurs
286
function supprime_invalideurs() {
287
	if ($supprime_invalideurs = charger_fonction('supprime_invalideurs', 'inc', true)) {
288
		return $supprime_invalideurs();
289
	}
290
}
291
292
293
// Calcul des pages : noter dans la base les liens d'invalidation
294
// http://code.spip.net/@maj_invalideurs
295
function maj_invalideurs($fichier, &$page) {
296
	if ($maj_invalideurs = charger_fonction('maj_invalideurs', 'inc', true)) {
297
		return $maj_invalideurs($fichier, $page);
298
	}
299
}
300
301
302
// les invalideurs sont de la forme "objet/id_objet"
303
// http://code.spip.net/@insere_invalideur
304
function insere_invalideur($inval, $fichier) {
305
	if ($insere_invalideur = charger_fonction('insere_invalideur', 'inc', true)) {
306
		return $insere_invalideur($inval, $fichier);
307
	}
308
}
309
310
//
311
// Marquer les fichiers caches invalides comme etant a supprimer
312
//
313
// http://code.spip.net/@applique_invalideur
314
function applique_invalideur($depart) {
315
	if ($applique_invalideur = charger_fonction('applique_invalideur', 'inc', true)) {
316
		return $applique_invalideur($depart);
317
	}
318
}
319
320
//
321
// Invalider les caches liés à telle condition
322
//
323
function suivre_invalideur($cond, $modif = true) {
324
	if ($suivre_invalideur = charger_fonction('suivre_invalideur', 'inc', true)) {
325
		return $suivre_invalideur($cond, $modif);
326
	}
327
}