MediaWiki  REL1_24
AjaxResponse.php
Go to the documentation of this file.
00001 <?php
00030 class AjaxResponse {
00035     private $mCacheDuration;
00036 
00041     private $mContentType;
00042 
00047     private $mDisabled;
00048 
00053     private $mLastModified;
00054 
00059     private $mResponseCode;
00060 
00065     private $mVary;
00066 
00071     private $mText;
00072 
00076     private $mConfig;
00077 
00082     function __construct( $text = null, Config $config = null ) {
00083         $this->mCacheDuration = null;
00084         $this->mVary = null;
00085         $this->mConfig = $config ?: ConfigFactory::getDefaultInstance()->makeConfig( 'main' );
00086 
00087         $this->mDisabled = false;
00088         $this->mText = '';
00089         $this->mResponseCode = '200 OK';
00090         $this->mLastModified = false;
00091         $this->mContentType = 'application/x-wiki';
00092 
00093         if ( $text ) {
00094             $this->addText( $text );
00095         }
00096     }
00097 
00102     function setCacheDuration( $duration ) {
00103         $this->mCacheDuration = $duration;
00104     }
00105 
00110     function setVary( $vary ) {
00111         $this->mVary = $vary;
00112     }
00113 
00118     function setResponseCode( $code ) {
00119         $this->mResponseCode = $code;
00120     }
00121 
00126     function setContentType( $type ) {
00127         $this->mContentType = $type;
00128     }
00129 
00133     function disable() {
00134         $this->mDisabled = true;
00135     }
00136 
00141     function addText( $text ) {
00142         if ( !$this->mDisabled && $text ) {
00143             $this->mText .= $text;
00144         }
00145     }
00146 
00150     function printText() {
00151         if ( !$this->mDisabled ) {
00152             print $this->mText;
00153         }
00154     }
00155 
00159     function sendHeaders() {
00160         if ( $this->mResponseCode ) {
00161             $n = preg_replace( '/^ *(\d+)/', '\1', $this->mResponseCode );
00162             header( "Status: " . $this->mResponseCode, true, (int)$n );
00163         }
00164 
00165         header ( "Content-Type: " . $this->mContentType );
00166 
00167         if ( $this->mLastModified ) {
00168             header ( "Last-Modified: " . $this->mLastModified );
00169         } else {
00170             header ( "Last-Modified: " . gmdate( "D, d M Y H:i:s" ) . " GMT" );
00171         }
00172 
00173         if ( $this->mCacheDuration ) {
00174             # If squid caches are configured, tell them to cache the response,
00175             # and tell the client to always check with the squid. Otherwise,
00176             # tell the client to use a cached copy, without a way to purge it.
00177 
00178             if ( $this->mConfig->get( 'UseSquid' ) ) {
00179                 # Expect explicit purge of the proxy cache, but require end user agents
00180                 # to revalidate against the proxy on each visit.
00181                 # Surrogate-Control controls our Squid, Cache-Control downstream caches
00182 
00183                 if ( $this->mConfig->get( 'UseESI' ) ) {
00184                     header( 'Surrogate-Control: max-age=' . $this->mCacheDuration . ', content="ESI/1.0"' );
00185                     header( 'Cache-Control: s-maxage=0, must-revalidate, max-age=0' );
00186                 } else {
00187                     header( 'Cache-Control: s-maxage=' . $this->mCacheDuration . ', must-revalidate, max-age=0' );
00188                 }
00189 
00190             } else {
00191                 # Let the client do the caching. Cache is not purged.
00192                 header ( "Expires: " . gmdate( "D, d M Y H:i:s", time() + $this->mCacheDuration ) . " GMT" );
00193                 header ( "Cache-Control: s-maxage={$this->mCacheDuration}," .
00194                     "public,max-age={$this->mCacheDuration}" );
00195             }
00196 
00197         } else {
00198             # always expired, always modified
00199             header ( "Expires: Mon, 26 Jul 1997 05:00:00 GMT" );    // Date in the past
00200             header ( "Cache-Control: no-cache, must-revalidate" );  // HTTP/1.1
00201             header ( "Pragma: no-cache" );                          // HTTP/1.0
00202         }
00203 
00204         if ( $this->mVary ) {
00205             header ( "Vary: " . $this->mVary );
00206         }
00207     }
00208 
00217     function checkLastModified( $timestamp ) {
00218         global $wgCachePages, $wgCacheEpoch, $wgUser;
00219         $fname = 'AjaxResponse::checkLastModified';
00220 
00221         if ( !$timestamp || $timestamp == '19700101000000' ) {
00222             wfDebug( "$fname: CACHE DISABLED, NO TIMESTAMP\n", 'log' );
00223             return false;
00224         }
00225 
00226         if ( !$wgCachePages ) {
00227             wfDebug( "$fname: CACHE DISABLED\n", 'log' );
00228             return false;
00229         }
00230 
00231         $timestamp = wfTimestamp( TS_MW, $timestamp );
00232         $lastmod = wfTimestamp( TS_RFC2822, max( $timestamp, $wgUser->getTouched(), $wgCacheEpoch ) );
00233 
00234         if ( !empty( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) ) {
00235             # IE sends sizes after the date like this:
00236             # Wed, 20 Aug 2003 06:51:19 GMT; length=5202
00237             # this breaks strtotime().
00238             $modsince = preg_replace( '/;.*$/', '', $_SERVER["HTTP_IF_MODIFIED_SINCE"] );
00239             $modsinceTime = strtotime( $modsince );
00240             $ismodsince = wfTimestamp( TS_MW, $modsinceTime ? $modsinceTime : 1 );
00241             wfDebug( "$fname: -- client send If-Modified-Since: " . $modsince . "\n", 'log' );
00242             wfDebug( "$fname: --  we might send Last-Modified : $lastmod\n", 'log' );
00243 
00244             if ( ( $ismodsince >= $timestamp )
00245                 && $wgUser->validateCache( $ismodsince ) &&
00246                 $ismodsince >= $wgCacheEpoch
00247             ) {
00248                 ini_set( 'zlib.output_compression', 0 );
00249                 $this->setResponseCode( "304 Not Modified" );
00250                 $this->disable();
00251                 $this->mLastModified = $lastmod;
00252 
00253                 wfDebug( "$fname: CACHED client: $ismodsince ; user: {$wgUser->getTouched()} ; " .
00254                     "page: $timestamp ; site $wgCacheEpoch\n", 'log' );
00255 
00256                 return true;
00257             } else {
00258                 wfDebug( "$fname: READY  client: $ismodsince ; user: {$wgUser->getTouched()} ; " .
00259                     "page: $timestamp ; site $wgCacheEpoch\n", 'log' );
00260                 $this->mLastModified = $lastmod;
00261             }
00262         } else {
00263             wfDebug( "$fname: client did not send If-Modified-Since header\n", 'log' );
00264             $this->mLastModified = $lastmod;
00265         }
00266         return false;
00267     }
00268 
00274     function loadFromMemcached( $mckey, $touched ) {
00275         global $wgMemc;
00276 
00277         if ( !$touched ) {
00278             return false;
00279         }
00280 
00281         $mcvalue = $wgMemc->get( $mckey );
00282         if ( $mcvalue ) {
00283             # Check to see if the value has been invalidated
00284             if ( $touched <= $mcvalue['timestamp'] ) {
00285                 wfDebug( "Got $mckey from cache\n" );
00286                 $this->mText = $mcvalue['value'];
00287 
00288                 return true;
00289             } else {
00290                 wfDebug( "$mckey has expired\n" );
00291             }
00292         }
00293 
00294         return false;
00295     }
00296 
00302     function storeInMemcached( $mckey, $expiry = 86400 ) {
00303         global $wgMemc;
00304 
00305         $wgMemc->set( $mckey,
00306             array(
00307                 'timestamp' => wfTimestampNow(),
00308                 'value' => $this->mText
00309             ), $expiry
00310         );
00311 
00312         return true;
00313     }
00314 }