| [ Index ] |
|
Code source de Plume CMS 1.2.2 |
1 <?php 2 /* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 3 /* 4 # ***** BEGIN LICENSE BLOCK ***** 5 # This file is part of Plume CMS, a website management application. 6 # Copyright (C) 2001-2005 Loic d'Anterroches and contributors. 7 # 8 # Plume CMS is free software; you can redistribute it and/or modify 9 # it under the terms of the GNU General Public License as published by 10 # the Free Software Foundation; either version 2 of the License, or 11 # (at your option) any later version. 12 # 13 # Copyright (C) 2003 KDO / VWT (The Virtual Web Team) 14 # 15 # Plume CMS is distributed in the hope that it will be useful, 16 # but WITHOUT ANY WARRANTY; without even the implied warranty of 17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 # GNU General Public License for more details. 19 # 20 # You should have received a copy of the GNU General Public License 21 # along with this program; if not, write to the Free Software 22 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 23 # 24 # ***** END LICENSE BLOCK ***** */ 25 26 /** 27 * Cache: Gestion de cache pages dynamiques 28 * 29 * Utilise l'output buffering: fonctions type ob_xxx de PHP 30 * Sample usage-1: 31 * $cc = new Cache('cacheFileName', 300); 32 * if($cc->processPage()) { 33 * .... // Ce que vous voulez cacher 34 * $cc->endCache(); 35 * } 36 * Sample usage-2: 37 * $cc = new Cache('basfilename'); 38 * if($cc->processSegment(200)) { 39 * .... // Ce que vous voulez cacher 40 * $cc->endCache(); 41 * } 42 * .... // Suite non cachée 43 * if($cc->processSegment(600)) { 44 * .... // Autre partie à cacher 45 * $cc->endCache(); 46 * } 47 * 48 */ 49 class Cache 50 { 51 var $data; /**< Data to cache. */ 52 var $cacheDir = '/tmp/'; /**< Cache folder. */ 53 var $file; /**< Cache file. */ 54 var $Fname; /**< Cache file name. */ 55 var $FnameOrig; /**< Original cache file name, use for segmented cache. */ 56 var $segmentId = 1; /**< Segment id, used to generate the cache file. */ 57 var $refreshTime; /**< Cache validity timestamp. */ 58 var $needUpdate = 0; /**< Need to update the cache. */ 59 var $isActive = false; /**< Are we in a processcache/processsegment loop */ 60 var $isSegment = false; /**< In a segment or not. */ 61 var $timeout; /**< Validity of a cache in seconds. */ 62 var $headers = array(); /**< Extra headers to send. */ 63 var $debug = false; /**< Debug mode (no caching). */ 64 65 /** 66 * Init the cache 67 * 68 * @param string Cache file name 69 * @param int Timeout in minutes (180) 70 */ 71 function Cache($fname, $timeout=180) 72 { 73 $fname = md5($fname); 74 $this->Fname = $fname; 75 $this->FnameOrig = $fname; 76 $this->file = $this->cacheDir.$fname; 77 $this->setTimeout($timeout); 78 } 79 80 /** 81 * Set the cache directory. 82 * 83 * @param string Full path to cache directory with trailing slash 84 */ 85 function setCacheDirectory($dir) 86 { 87 $this->cacheDir = $dir; 88 $this->file = $dir.$this->Fname; 89 } 90 91 /** 92 * Set the timeout. 93 * 94 * @param int Timeout in minutes (180) 95 */ 96 function setTimeout($timeout=180) 97 { 98 $this->refreshTime = time() - ($timeout * 60); 99 $this->timeout = $timeout * 60; 100 } 101 102 /** 103 * Set extra header to send. 104 * 105 * @param string Extra header. 106 */ 107 function setHeader($header) { 108 if (0 != strlen($header)) { 109 $this->headers[] = $header; 110 } 111 } 112 113 /** 114 * Send the extra headers. 115 */ 116 function sendHeaders() 117 { 118 foreach ($this->headers as $header) { 119 header($header); 120 } 121 } 122 123 /** 124 * Process the cache 125 * 126 * @param int Timeout in minutes (false) if false use the one at construct 127 * @return boolean false if cache content is valid 128 */ 129 function processPage($timeout=false) 130 { 131 if ($timeout !== false) { 132 $this->setTimeout($timeout); 133 } 134 if(!$this->isActive ) { 135 $this->isActive = true; 136 ob_start(); 137 ob_implicit_flush(0); 138 if (!$this->debug 139 && file_exists($this->file) 140 && (@filemtime(config::getMassUpdateFile())-10 < @filemtime($this->file)) 141 && (@filemtime($this->file) > $this->refreshTime) 142 ) { 143 if (!$this->isSegment) { 144 if (isset($_SERVER["HTTP_IF_MODIFIED_SINCE"])) { 145 $gmtime = gmdate('D, d M Y H:i:s', filemtime($this->file)).' GMT'; 146 $usertime = substr($_SERVER["HTTP_IF_MODIFIED_SINCE"], 0, strpos($_SERVER["HTTP_IF_MODIFIED_SINCE"], 'GMT') + 3); 147 if ($usertime == $gmtime) { 148 header("HTTP/1.1 304 Not Modified"); 149 ob_end_flush(); 150 exit; 151 } 152 } 153 } 154 $this->read(); 155 if (empty($gmtime)) 156 $gmtime = gmdate('D, d M Y H:i:s', 157 filemtime($this->file)).' GMT'; 158 if (!$this->isSegment) 159 header("Last-Modified: ".$gmtime); 160 echo $this->data; 161 ob_end_flush(); 162 $this->isActive = false; 163 return false; 164 165 } else { 166 if (!$this->isSegment) { 167 header('Cache-Control: no-cache'); 168 header('Pragma: no-cache'); 169 $time = gmdate('D, d M Y H:i:s', 123456).' GMT'; 170 header("Last-Modified: ".$time); 171 } 172 $this->needUpdate = 1; 173 return true; 174 } 175 } 176 } 177 178 /** 179 * Réalise le cache pour un segment donné 180 * 181 * @since 2002-02-21 182 * @return boolean false si le contenu du cache est valide 183 * @access public 184 */ 185 function processSegment($timeout=180) 186 { 187 if (!$this->isActive) { 188 $this->isSegment = true; 189 $this->Fname = $this->FnameOrig.'%%'.$this->segmentId; 190 $this->segmentId += 1; 191 $this->file = $this->cacheDir.$this->Fname; 192 return $this->processPage($timeout); 193 } 194 return true; 195 } 196 197 /** 198 * End of cache block. 199 */ 200 function endCache() 201 { 202 $this->isActive = false; 203 if ($this->needUpdate) { 204 $this->data = ob_get_contents(); 205 $this->write(); 206 if (!$this->isSegment) { 207 clearstatcache(); 208 $FT = @filemtime($this->file); 209 $gnow = gmdate('D, d M Y H:i:s', $FT+$this->timeout).' GMT'; 210 if ($this->timeout != -1) 211 header('Expires: '.$gnow); 212 $gnow = gmdate('D, d M Y H:i:s', $FT).' GMT'; 213 header('Last-Modified: '.$gnow); 214 } 215 ob_end_flush(); 216 $this->isSegment = false; 217 } 218 } 219 220 /** 221 * Ecrit les données dans le fichier de cache 222 * 223 * @return true si l'on a pu ecrire dans le fichier, false sinon 224 * @access private 225 */ 226 function write() 227 { 228 // mode "a" pour ne pas tronquer avant d'avoir le lock 229 $fp = @fopen($this->file, 'a'); 230 if ($fp) { 231 // lock exclusif pour l'écriture 232 flock($fp, LOCK_EX); 233 // maintenant qu'on a le seul pointeur on tronque 234 ftruncate($fp,0); 235 // on se replace, comme si on avait ouvert en +w 236 rewind($fp); 237 fwrite($fp, $this->data, strlen($this->data)); 238 // lock relaché, on peut acceder en lecture 239 flock($fp, LOCK_UN); 240 fclose($fp); 241 @chmod($this->file, 0666); 242 return true; 243 } 244 return false; 245 } 246 247 /** 248 * Lit les données dans le cache 249 * 250 * @return boolean - true si l'on a pu lire le cache, false sinon 251 * @access private 252 */ 253 function read() 254 { 255 $fp = @fopen($this->file, 'r'); 256 if ($fp) { 257 flock($fp, LOCK_SH); 258 $this->data = ''; 259 while ($tmp=fread($fp, 4096)) { 260 $this->data .= $tmp; 261 } 262 // un ralachement du lock, même si normalement ca marche sans 263 flock($fp, LOCK_UN); 264 fclose($fp); 265 return true; 266 } 267 return false; 268 } 269 } 270 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Mon Nov 26 11:57:01 2007 | par Balluche grâce à PHPXref 0.7 |
|