00001 <?php 00027 require_once 'Zend/Cache/Core.php'; 00028 00029 00036 class Zend_Cache_Frontend_Page extends Zend_Cache_Core 00037 { 00084 protected $_specificOptions = array( 00085 'http_conditional' => false, 00086 'debug_header' => false, 00087 'content_type_memorization' => false, 00088 'memorize_headers' => array(), 00089 'default_options' => array( 00090 'cache_with_get_variables' => false, 00091 'cache_with_post_variables' => false, 00092 'cache_with_session_variables' => false, 00093 'cache_with_files_variables' => false, 00094 'cache_with_cookie_variables' => false, 00095 'make_id_with_get_variables' => true, 00096 'make_id_with_post_variables' => true, 00097 'make_id_with_session_variables' => true, 00098 'make_id_with_files_variables' => true, 00099 'make_id_with_cookie_variables' => true, 00100 'cache' => true, 00101 'specific_lifetime' => false, 00102 'tags' => array(), 00103 'priority' => null 00104 ), 00105 'regexps' => array() 00106 ); 00107 00113 protected $_activeOptions = array(); 00114 00120 protected $_cancel = false; 00121 00130 public function __construct(array $options = array()) 00131 { 00132 while (list($name, $value) = each($options)) { 00133 $name = strtolower($name); 00134 switch ($name) { 00135 case 'regexps': 00136 $this->_setRegexps($value); 00137 break; 00138 case 'default_options': 00139 $this->_setDefaultOptions($value); 00140 break; 00141 case 'content_type_memorization': 00142 $this->_setContentTypeMemorization($value); 00143 break; 00144 default: 00145 $this->setOption($name, $value); 00146 } 00147 } 00148 if (isset($this->_specificOptions['http_conditional'])) { 00149 if ($this->_specificOptions['http_conditional']) { 00150 Zend_Cache::throwException('http_conditional is not implemented for the moment !'); 00151 } 00152 } 00153 $this->setOption('automatic_serialization', true); 00154 } 00155 00163 protected function _setDefaultOptions($options) 00164 { 00165 if (!is_array($options)) { 00166 Zend_Cache::throwException('default_options must be an array !'); 00167 } 00168 foreach ($options as $key=>$value) { 00169 if (!is_string($key)) { 00170 Zend_Cache::throwException("invalid option [$key] !"); 00171 } 00172 $key = strtolower($key); 00173 if (isset($this->_specificOptions['default_options'][$key])) { 00174 $this->_specificOptions['default_options'][$key] = $value; 00175 } 00176 } 00177 } 00178 00186 protected function _setContentTypeMemorization($value) 00187 { 00188 $found = null; 00189 foreach ($this->_specificOptions['memorize_headers'] as $key => $value) { 00190 if (strtolower($value) == 'content-type') { 00191 $found = $key; 00192 } 00193 } 00194 if ($value) { 00195 if (!$found) { 00196 $this->_specificOptions['memorize_headers'][] = 'Content-Type'; 00197 } 00198 } else { 00199 if ($found) { 00200 unset($this->_specificOptions['memorize_headers'][$found]); 00201 } 00202 } 00203 } 00204 00212 protected function _setRegexps($regexps) 00213 { 00214 if (!is_array($regexps)) { 00215 Zend_Cache::throwException('regexps option must be an array !'); 00216 } 00217 foreach ($regexps as $regexp=>$conf) { 00218 if (!is_array($conf)) { 00219 Zend_Cache::throwException('regexps option must be an array of arrays !'); 00220 } 00221 $validKeys = array_keys($this->_specificOptions['default_options']); 00222 foreach ($conf as $key=>$value) { 00223 if (!is_string($key)) { 00224 Zend_Cache::throwException("unknown option [$key] !"); 00225 } 00226 $key = strtolower($key); 00227 if (!in_array($key, $validKeys)) { 00228 unset($regexps[$regexp][$key]); 00229 } 00230 } 00231 } 00232 $this->setOption('regexps', $regexps); 00233 } 00234 00242 public function start($id = false, $doNotDie = false) 00243 { 00244 $this->_cancel = false; 00245 $lastMatchingRegexp = null; 00246 foreach ($this->_specificOptions['regexps'] as $regexp => $conf) { 00247 if (preg_match("`$regexp`", $_SERVER['REQUEST_URI'])) { 00248 $lastMatchingRegexp = $regexp; 00249 } 00250 } 00251 $this->_activeOptions = $this->_specificOptions['default_options']; 00252 if ($lastMatchingRegexp !== null) { 00253 $conf = $this->_specificOptions['regexps'][$lastMatchingRegexp]; 00254 foreach ($conf as $key=>$value) { 00255 $this->_activeOptions[$key] = $value; 00256 } 00257 } 00258 if (!($this->_activeOptions['cache'])) { 00259 return false; 00260 } 00261 if (!$id) { 00262 $id = $this->_makeId(); 00263 if (!$id) { 00264 return false; 00265 } 00266 } 00267 $array = $this->load($id); 00268 if ($array !== false) { 00269 $data = $array['data']; 00270 $headers = $array['headers']; 00271 if (!headers_sent()) { 00272 foreach ($headers as $key=>$headerCouple) { 00273 $name = $headerCouple[0]; 00274 $value = $headerCouple[1]; 00275 header("$name: $value"); 00276 } 00277 } 00278 if ($this->_specificOptions['debug_header']) { 00279 echo 'DEBUG HEADER : This is a cached page !'; 00280 } 00281 echo $data; 00282 if ($doNotDie) { 00283 return true; 00284 } 00285 die(); 00286 } 00287 ob_start(array($this, '_flush')); 00288 ob_implicit_flush(false); 00289 return false; 00290 } 00291 00295 public function cancel() 00296 { 00297 $this->_cancel = true; 00298 } 00299 00307 public function _flush($data) 00308 { 00309 if ($this->_cancel) { 00310 return $data; 00311 } 00312 $contentType = null; 00313 $storedHeaders = array(); 00314 $headersList = headers_list(); 00315 foreach($this->_specificOptions['memorize_headers'] as $key=>$headerName) { 00316 foreach ($headersList as $headerSent) { 00317 $tmp = explode(':', $headerSent); 00318 $headerSentName = trim(array_shift($tmp)); 00319 if (strtolower($headerName) == strtolower($headerSentName)) { 00320 $headerSentValue = trim(implode(':', $tmp)); 00321 $storedHeaders[] = array($headerSentName, $headerSentValue); 00322 } 00323 } 00324 } 00325 $array = array( 00326 'data' => $data, 00327 'headers' => $storedHeaders 00328 ); 00329 $this->save($array, null, $this->_activeOptions['tags'], $this->_activeOptions['specific_lifetime'], $this->_activeOptions['priority']); 00330 return $data; 00331 } 00332 00338 protected function _makeId() 00339 { 00340 $tmp = $_SERVER['REQUEST_URI']; 00341 $array = explode('?', $tmp, 2); 00342 $tmp = $array[0]; 00343 foreach (array('Get', 'Post', 'Session', 'Files', 'Cookie') as $arrayName) { 00344 $tmp2 = $this->_makePartialId($arrayName, $this->_activeOptions['cache_with_' . strtolower($arrayName) . '_variables'], $this->_activeOptions['make_id_with_' . strtolower($arrayName) . '_variables']); 00345 if ($tmp2===false) { 00346 return false; 00347 } 00348 $tmp = $tmp . $tmp2; 00349 } 00350 return md5($tmp); 00351 } 00352 00361 protected function _makePartialId($arrayName, $bool1, $bool2) 00362 { 00363 switch ($arrayName) { 00364 case 'Get': 00365 $var = $_GET; 00366 break; 00367 case 'Post': 00368 $var = $_POST; 00369 break; 00370 case 'Session': 00371 if (isset($_SESSION)) { 00372 $var = $_SESSION; 00373 } else { 00374 $var = null; 00375 } 00376 break; 00377 case 'Cookie': 00378 if (isset($_COOKIE)) { 00379 $var = $_COOKIE; 00380 } else { 00381 $var = null; 00382 } 00383 break; 00384 case 'Files': 00385 $var = $_FILES; 00386 break; 00387 default: 00388 return false; 00389 } 00390 if ($bool1) { 00391 if ($bool2) { 00392 return serialize($var); 00393 } 00394 return ''; 00395 } 00396 if (count($var) > 0) { 00397 return false; 00398 } 00399 return ''; 00400 } 00401 00402 }