source: spip-zone/_plugins_/cachelab/trunk/inc/cachelab.php @ 111924

Last change on this file since 111924 was 111924, checked in by jluc@…, 14 months ago

une fois inclure suffit

File size: 7.2 KB
Line 
1<?php
2if (!defined('_ECRIRE_INC_VERSION')) {
3        return;
4}
5
6if (!function_exists('plugin_est_actif')) {
7        function plugin_est_actif($prefixe) {
8                $f = chercher_filtre('info_plugin');
9                return $f($prefixe, 'est_actif');
10        }
11}
12
13function cachelab_applique ($action, $cle, $data=null, $options='') {
14global $Memoization;
15static $len_prefix;
16        if (!$len_prefix)
17                $len_prefix = strlen(_CACHE_NAMESPACE);
18        $joliecle = substr($cle, $len_prefix);
19
20        switch ($action) {
21        case 'del' :
22                $del = $Memoization->del($joliecle);
23                if (!$del) {
24                        spip_log ("Échec 'del' $joliecle", 'cachelab');
25                        return false;
26                };
27                break;
28
29        case 'echo_cache' :
30                if (!$data)
31                        $data = $Memoization->get($joliecle);
32                echo "«<xmp>".substr(print_r($data,1), 0,2000)."</xmp>»";
33                break;
34
35        case 'echo_html' :
36                if (!$data)
37                        $data = $Memoization->get($joliecle);
38                echo "<p>«<xmp>".print_r($data,1)."</xmp>»</p>";
39                break;
40
41        case 'pass' :
42        case 'list' :
43                break;
44
45        default :
46                // on pourrait appeler cachelab_applique_$action(...)
47                break;
48        }
49        return true;
50}
51
52// $chemin : liste de chaines à tester dans le chemin du squelette, séparées par |
53//      OU une regexp (hors délimiteurs et modificateurs) si la méthode est 'regexp'
54function cachelab_filtre ($action, $conditions, $options=array()) {
55global $Memoization;
56        if (!$Memoization or !in_array($Memoization->methode(), array('apc', 'apcu')))
57                die ("Il faut mémoization avec APC ou APCu");
58
59        // filtrage
60        $session = (isset($conditions['session']) ? $conditions['session'] : null);
61        if ($session=='courante')
62                $session = spip_session();
63        $chemin = (isset($conditions['chemin']) ? $conditions['chemin'] : null);
64        $chemins = explode('|', $chemin); // sert seulement pour methode_chemin == strpos
65        $cle_objet = (isset($conditions['cle_objet']) ? $conditions['cle_objet'] : null);
66        $id_objet = (isset($conditions['id_objet']) ? $conditions['id_objet'] : null);
67        if ($cle_objet and !$id_objet)
68                die ("$cle_objet est inconnu : passez le en argument d'url ou définissez XRAY_ID_OBJET_SPECIAL en php");
69        // pour 'contexte' on simule un 'more' pour donner un exemple d'extension
70        if (isset($conditions['contexte']) and $conditions['contexte'] and !isset($conditions['more']))
71                $conditions['more'] = 'contexte';
72        if ($more = (isset($conditions['more']) ? (string)$conditions['more'] : '')) {
73                $morefunc='cachelab_filtrecache_'.$more;
74                // Signature nécessaire : $morefunc ($action, $conditions, $options, &$stats)
75                if (!function_exists($morefunc))
76                        die ("La fonction '$morefunc' n'est pas définie");
77        }
78
79        // options
80        // explode+strpos par défaut pour les chemins
81        $methode_chemin = (isset ($options['methode_chemin']) ? $options['methode_chemin'] : 'strpos');
82        // clean par défaut
83        $do_clean = (isset ($options['clean']) ? $options['clean'] : (!defined('CACHELAB_CLEAN') or CACHELAB_CLEAN)); 
84        // pas de listes par défaut
85        $do_lists = ($action == 'list') or (isset ($options['list']) and $options['list']);
86        // pas de chrono par défaut sauf si CACHELAB_CHRONO
87        $do_chrono = (isset ($options['chrono']) ? $options['chrono'] : (defined('CACHELAB_CHRONO') and CACHELAB_CHRONO)); 
88        if ($do_chrono) {
89                include_spip ('lib/microtime.inc');
90                microtime_do ('begin');
91        }
92
93        // retours
94        $stats=array();
95        $stats['nb_alien']=$stats['nb_candidats']=$stats['nb_clean']=$stats['nb_no_data']=$stats['nb_not_array']=$stats['nb_cible']=0;
96        $stats['l_no_data'] = $stats['l_not_array'] = $stats['l_cible'] = array();
97
98        // On y va
99        $cache = apcu_cache_info();
100        $meta_derniere_modif = lire_meta('derniere_modif');
101        $len_prefix = strlen(_CACHE_NAMESPACE);
102
103        foreach($cache['cache_list'] as $i => $d) {
104                // on "continue=passe au suivant" dés qu'on sait que le cache n'est pas cible
105
106                $cle = $d['info'];
107                $data=null;
108
109                // on saute les caches d'autres origines
110                // (et les caches d'un précédent _CACHE_NAMESPACE pour ce même site)
111                if (strpos ($cle, _CACHE_NAMESPACE) !== 0) {
112                        $stats['nb_alien']++;
113                        continue;
114                }
115
116                // on ne veut examiner que les caches de squelettes SPIP
117                if ((substr($cle, $len_prefix-1, 7) != ':cache:')
118                        or !apcu_exists($cle))
119                        continue;
120
121                // effacer ou au moins sauter les caches périmés
122                if ($meta_derniere_modif > $d['creation_time']) {
123                        if ($do_clean) {
124                                $del=$Memoization->del(substr($cle,$len_prefix));
125                                if (!$del)
126                                        spip_log ("Echec du clean du cache périmé cle=$cle (création : {$d['creation_time']}, invalidation : $meta_derniere_modif)", "cachelab");
127                                $stats['nb_clean']++;
128                        };
129                        continue;
130                }
131
132                // caches SPIP véritablement candidats
133                $stats['nb_candidats']++;
134
135                if ($session) {
136                        if (substr ($cle, -9) != "_$session")
137                                continue;
138                }
139
140                if ($chemin) {
141                        // mémo php : « continue resumes execution just before the closing curly bracket ( } ), and break resumes execution just after the closing curly bracket. »
142                        switch ($methode_chemin) {
143                        case 'strpos' :
144                                foreach ($chemins as $unchemin)
145                                        if ($unchemin and (strpos ($cle, $unchemin) !== false))
146                                                break 2;        // trouvé : sort du foreach et du switch et poursuit le test des autres conditions
147                                continue 2;      // échec : passe à la $cle suivante
148                        case 'regexp' :
149                                if ($chemin and ($danslechemin = preg_match(",$chemin,i", $cle)))
150                                        break;  // trouvé : poursuit le test des autres conditions
151                                continue 2;     // échec : passe à la clé suivante
152                        default :
153                                die("Méthode '$methode_chemin' pas prévue pour le filtrage par le chemin");
154                        };
155                }
156                // récupérer le contenu du cache
157                if (($cle_objet and $id_objet) or $morefunc) {
158                        global $Memoization;
159                        $data = $Memoization->get(substr($cle, $len_prefix));
160                        if (!$data) {
161                                $stats['nb_no_data']++;
162                                continue;
163                        }
164                        if (!is_array($data)) {
165                                spip_log ("clé=$cle : data n'est pas un tableau : ".print_r($data,1), 'cachelab');
166                                $stats['nb_not_array']++;
167                                if ($do_lists)
168                                        $stats['l_not_array'][] = $cle;
169                                continue;
170                        };
171                };
172
173                if ($cle_objet
174                        and (!isset ($data['contexte'][$cle_objet])
175                                or ($data['contexte'][$cle_objet]!=$id_objet)))
176                        continue;
177
178                if ($morefunc
179                        and !$morefunc ($action, $conditions, $options, $cle, $data, $stats))
180                        continue;
181
182                // restent les cibles
183                $stats['nb_cible']++;
184                if ($do_lists) 
185                        $stats['l_cible'][] = $cle;
186
187                cachelab_applique ($action, $cle, $data, $options);
188        }
189
190
191        if ($do_chrono) {
192                $stats['chrono'] = microtime_do ('end', 'ms');
193                spip_log ("cachelab_filtre ($action) avec session=$session, objet $cle_objet=$id_objet, chemin=$chemin) : {$stats['nb_cible']} caches ciblés en {$stats['chrono']} ms", 'cachelab');
194        }
195
196        return $stats;
197}
198
199function controler_invalideur($action, $objets_invalidants=array()) {
200static $prev_derniere_modif_invalide;
201        switch($action) {
202        case 'stop' :
203                $objets_invalidants = array();
204                // nobreak;
205        case 'select' :
206                $prev_derniere_modif_invalide = $GLOBALS['derniere_modif_invalide'];
207                if (is_array($objets_invalidants))
208                        $GLOBALS['derniere_modif_invalide'] = $objets_invalidants;
209                break;
210        case 'go' :
211                $GLOBALS['derniere_modif_invalide'] = $prev_derniere_modif_invalide;
212                break;
213        }
214}
215
216function cachelab_filtrecache_contexte($action, $conditions, $options, $cle, &$data, &$stats) {
217        if (!isset ($data['contexte'])
218                or !isset($conditions['contexte'])
219                or !is_array($conditions['contexte']))
220                return false;
221        $diff = array_diff_assoc($conditions['contexte'], $data['contexte']);
222        return empty($diff);
223}
Note: See TracBrowser for help on using the repository browser.