Вход Регистрация
Файл: framework/web/filters/CHttpCacheFilter.php
Строк: 242
<?php
/**
 * CHttpCacheFilter class file.
 *
 * @author Da:Sourcerer <webmaster@dasourcerer.net>
 * @link http://www.yiiframework.com/
 * @copyright 2008-2013 Yii Software LLC
 * @license http://www.yiiframework.com/license/
 */

/**
 * CHttpCacheFilter implements http caching. It works a lot like {@link COutputCache}
 * as a filter, except that content caching is being done on the client side.
 *
 * @author Da:Sourcerer <webmaster@dasourcerer.net>
 * @package system.web.filters
 * @since 1.1.11
 */
class CHttpCacheFilter extends CFilter
{
    
/**
     * @var string|integer Timestamp for the last modification date.
     * Must be either a string parsable by {@link http://php.net/strtotime strtotime()}
     * or an integer representing a unix timestamp.
     */
    
public $lastModified;
    
/**
     * @var string|callback PHP Expression for the last modification date.
     * If set, this takes precedence over {@link lastModified}.
     *
     * The PHP expression will be evaluated using {@link evaluateExpression}.
     *
     * A PHP expression can be any PHP code that has a value. To learn more about what an expression is,
     * please refer to the {@link http://www.php.net/manual/en/language.expressions.php php manual}.
     */
    
public $lastModifiedExpression;
    
/**
     * @var mixed Seed for the ETag.
     * Can be anything that passes through {@link http://php.net/serialize serialize()}.
     */
    
public $etagSeed;
    
/**
     * @var string|callback Expression for the ETag seed.
     * If set, this takes precedence over {@link etagSeed}.
     *
     * The PHP expression will be evaluated using {@link evaluateExpression}.
     *
     * A PHP expression can be any PHP code that has a value. To learn more about what an expression is,
     * please refer to the {@link http://www.php.net/manual/en/language.expressions.php php manual}.
     */
    
public $etagSeedExpression;
    
/**
     * @var string Http cache control headers. Set this to an empty string in order to keep this
     * header from being sent entirely.
     */
    
public $cacheControl='max-age=3600, public';

    
/**
     * Performs the pre-action filtering.
     * @param CFilterChain $filterChain the filter chain that the filter is on.
     * @return boolean whether the filtering process should continue and the action should be executed.
     */
    
public function preFilter($filterChain)
    {
        
// Only cache GET and HEAD requests
        
if(!in_array(Yii::app()->getRequest()->getRequestType(), array('GET''HEAD')))
            return 
true;

        
$lastModified=$this->getLastModifiedValue();
        
$etag=$this->getEtagValue();

        if(
$etag===false&&$lastModified===false)
            return 
true;

        if(
$etag)
            
header('ETag: '.$etag);

        if(isset(
$_SERVER['HTTP_IF_MODIFIED_SINCE'])&&isset($_SERVER['HTTP_IF_NONE_MATCH']))
        {
            if(
$this->checkLastModified($lastModified)&&$this->checkEtag($etag))
            {
                
$this->send304Header();
                
$this->sendCacheControlHeader();
                return 
false;
            }
        }
        elseif(isset(
$_SERVER['HTTP_IF_MODIFIED_SINCE']))
        {
            if(
$this->checkLastModified($lastModified))
            {
                
$this->send304Header();
                
$this->sendCacheControlHeader();
                return 
false;
            }
        }
        elseif(isset(
$_SERVER['HTTP_IF_NONE_MATCH']))
        {
            if(
$this->checkEtag($etag))
            {
                
$this->send304Header();
                
$this->sendCacheControlHeader();
                return 
false;
            }

        }

        if(
$lastModified)
            
header('Last-Modified: '.gmdate('D, d M Y H:i:s'$lastModified).' GMT');

        
$this->sendCacheControlHeader();
        return 
true;
    }

    
/**
     * Gets the last modified value from either {@link lastModifiedExpression} or {@link lastModified}
     * and converts it into a unix timestamp if necessary
     * @throws CException
     * @return integer|boolean A unix timestamp or false if neither lastModified nor
     * lastModifiedExpression have been set
     */
    
protected function getLastModifiedValue()
    {
        if(
$this->lastModifiedExpression)
        {
            
$value=$this->evaluateExpression($this->lastModifiedExpression);
            if(
is_numeric($value)&&$value==(int)$value)
                return 
$value;
            elseif((
$lastModified=strtotime($value))===false)
                throw new 
CException(Yii::t('yii','Invalid expression for CHttpCacheFilter.lastModifiedExpression: The evaluation result "{value}" could not be understood by strtotime()',
                    array(
'{value}'=>$value)));
            return 
$lastModified;
        }

        if(
$this->lastModified)
        {
            if(
is_numeric($this->lastModified)&&$this->lastModified==(int)$this->lastModified)
                return 
$this->lastModified;
            elseif((
$lastModified=strtotime($this->lastModified))===false)
                throw new 
CException(Yii::t('yii','CHttpCacheFilter.lastModified contained a value that could not be understood by strtotime()'));
            return 
$lastModified;
        }
        return 
false;
    }

    
/**
     *  Gets the ETag out of either {@link etagSeedExpression} or {@link etagSeed}
     *  @return string|boolean Either a quoted string serving as ETag or false if neither etagSeed nor etagSeedExpression have been set
     */
    
protected function getEtagValue()
    {
        if(
$this->etagSeedExpression)
            return 
$this->generateEtag($this->evaluateExpression($this->etagSeedExpression));
        elseif(
$this->etagSeed)
            return 
$this->generateEtag($this->etagSeed);
        return 
false;
    }

    
/**
     * Check if the etag supplied by the client matches our generated one
     * @param string $etag the supplied etag
     * @return boolean true if the supplied etag matches $etag
     */
    
protected function checkEtag($etag)
    {
        return isset(
$_SERVER['HTTP_IF_NONE_MATCH'])&&$_SERVER['HTTP_IF_NONE_MATCH']==$etag;
    }

    
/**
     * Checks if the last modified date supplied by the client is still up to date
     * @param integer $lastModified the last modified date
     * @return boolean true if the last modified date sent by the client is newer or equal to $lastModified
     */
    
protected function checkLastModified($lastModified)
    {
        return isset(
$_SERVER['HTTP_IF_MODIFIED_SINCE'])&&@strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])>=$lastModified;
    }

    
/**
     * Sends the 304 HTTP status code to the client
     */
    
protected function send304Header()
    {
        
$httpVersion=Yii::app()->request->getHttpVersion();
        
header("HTTP/$httpVersion 304 Not Modified");
    }

    
/**
     * Sends the cache control header to the client
     * @see cacheControl
     * @since 1.1.12
     */
    
protected function sendCacheControlHeader()
    {
        if(
Yii::app()->session->isStarted)
        {
            
session_cache_limiter('public');
            
header('Pragma:',true);
        }
        
header('Cache-Control: '.$this->cacheControl,true);
    }

    
/**
     * Generates a quoted string out of the seed
     * @param mixed $seed Seed for the ETag
     * @return string Quoted string serving as ETag
     */
    
protected function generateEtag($seed)
    {
        return 
'"'.base64_encode(sha1(serialize($seed),true)).'"';
    }
}
Онлайн: 2
Реклама