[ Index ]

PHP Cross Reference of MediaWiki-1.24.0

title

Body

[close]

/includes/ -> AjaxResponse.php (source)

   1  <?php
   2  /**
   3   * Response handler for Ajax requests.
   4   *
   5   * This program is free software; you can redistribute it and/or modify
   6   * it under the terms of the GNU General Public License as published by
   7   * the Free Software Foundation; either version 2 of the License, or
   8   * (at your option) any later version.
   9   *
  10   * This program is distributed in the hope that it will be useful,
  11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13   * GNU General Public License for more details.
  14   *
  15   * You should have received a copy of the GNU General Public License along
  16   * with this program; if not, write to the Free Software Foundation, Inc.,
  17   * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  18   * http://www.gnu.org/copyleft/gpl.html
  19   *
  20   * @file
  21   * @ingroup Ajax
  22   */
  23  
  24  /**
  25   * Handle responses for Ajax requests (send headers, print
  26   * content, that sort of thing)
  27   *
  28   * @ingroup Ajax
  29   */
  30  class AjaxResponse {
  31      /**
  32       * Number of seconds to get the response cached by a proxy
  33       * @var int $mCacheDuration
  34       */
  35      private $mCacheDuration;
  36  
  37      /**
  38       * HTTP header Content-Type
  39       * @var string $mContentType
  40       */
  41      private $mContentType;
  42  
  43      /**
  44       * Disables output. Can be set by calling $AjaxResponse->disable()
  45       * @var bool $mDisabled
  46       */
  47      private $mDisabled;
  48  
  49      /**
  50       * Date for the HTTP header Last-modified
  51       * @var string|bool $mLastModified
  52       */
  53      private $mLastModified;
  54  
  55      /**
  56       * HTTP response code
  57       * @var string $mResponseCode
  58       */
  59      private $mResponseCode;
  60  
  61      /**
  62       * HTTP Vary header
  63       * @var string $mVary
  64       */
  65      private $mVary;
  66  
  67      /**
  68       * Content of our HTTP response
  69       * @var string $mText
  70       */
  71      private $mText;
  72  
  73      /**
  74       * @var Config
  75       */
  76      private $mConfig;
  77  
  78      /**
  79       * @param string|null $text
  80       * @param Config|null $config
  81       */
  82  	function __construct( $text = null, Config $config = null ) {
  83          $this->mCacheDuration = null;
  84          $this->mVary = null;
  85          $this->mConfig = $config ?: ConfigFactory::getDefaultInstance()->makeConfig( 'main' );
  86  
  87          $this->mDisabled = false;
  88          $this->mText = '';
  89          $this->mResponseCode = '200 OK';
  90          $this->mLastModified = false;
  91          $this->mContentType = 'application/x-wiki';
  92  
  93          if ( $text ) {
  94              $this->addText( $text );
  95          }
  96      }
  97  
  98      /**
  99       * Set the number of seconds to get the response cached by a proxy
 100       * @param int $duration
 101       */
 102  	function setCacheDuration( $duration ) {
 103          $this->mCacheDuration = $duration;
 104      }
 105  
 106      /**
 107       * Set the HTTP Vary header
 108       * @param string $vary
 109       */
 110  	function setVary( $vary ) {
 111          $this->mVary = $vary;
 112      }
 113  
 114      /**
 115       * Set the HTTP response code
 116       * @param string $code
 117       */
 118  	function setResponseCode( $code ) {
 119          $this->mResponseCode = $code;
 120      }
 121  
 122      /**
 123       * Set the HTTP header Content-Type
 124       * @param string $type
 125       */
 126  	function setContentType( $type ) {
 127          $this->mContentType = $type;
 128      }
 129  
 130      /**
 131       * Disable output.
 132       */
 133  	function disable() {
 134          $this->mDisabled = true;
 135      }
 136  
 137      /**
 138       * Add content to the response
 139       * @param string $text
 140       */
 141  	function addText( $text ) {
 142          if ( !$this->mDisabled && $text ) {
 143              $this->mText .= $text;
 144          }
 145      }
 146  
 147      /**
 148       * Output text
 149       */
 150  	function printText() {
 151          if ( !$this->mDisabled ) {
 152              print $this->mText;
 153          }
 154      }
 155  
 156      /**
 157       * Construct the header and output it
 158       */
 159  	function sendHeaders() {
 160          if ( $this->mResponseCode ) {
 161              $n = preg_replace( '/^ *(\d+)/', '\1', $this->mResponseCode );
 162              header( "Status: " . $this->mResponseCode, true, (int)$n );
 163          }
 164  
 165          header ( "Content-Type: " . $this->mContentType );
 166  
 167          if ( $this->mLastModified ) {
 168              header ( "Last-Modified: " . $this->mLastModified );
 169          } else {
 170              header ( "Last-Modified: " . gmdate( "D, d M Y H:i:s" ) . " GMT" );
 171          }
 172  
 173          if ( $this->mCacheDuration ) {
 174              # If squid caches are configured, tell them to cache the response,
 175              # and tell the client to always check with the squid. Otherwise,
 176              # tell the client to use a cached copy, without a way to purge it.
 177  
 178              if ( $this->mConfig->get( 'UseSquid' ) ) {
 179                  # Expect explicit purge of the proxy cache, but require end user agents
 180                  # to revalidate against the proxy on each visit.
 181                  # Surrogate-Control controls our Squid, Cache-Control downstream caches
 182  
 183                  if ( $this->mConfig->get( 'UseESI' ) ) {
 184                      header( 'Surrogate-Control: max-age=' . $this->mCacheDuration . ', content="ESI/1.0"' );
 185                      header( 'Cache-Control: s-maxage=0, must-revalidate, max-age=0' );
 186                  } else {
 187                      header( 'Cache-Control: s-maxage=' . $this->mCacheDuration . ', must-revalidate, max-age=0' );
 188                  }
 189  
 190              } else {
 191                  # Let the client do the caching. Cache is not purged.
 192                  header ( "Expires: " . gmdate( "D, d M Y H:i:s", time() + $this->mCacheDuration ) . " GMT" );
 193                  header ( "Cache-Control: s-maxage={$this->mCacheDuration}," .
 194                      "public,max-age={$this->mCacheDuration}" );
 195              }
 196  
 197          } else {
 198              # always expired, always modified
 199              header ( "Expires: Mon, 26 Jul 1997 05:00:00 GMT" );    // Date in the past
 200              header ( "Cache-Control: no-cache, must-revalidate" );  // HTTP/1.1
 201              header ( "Pragma: no-cache" );                          // HTTP/1.0
 202          }
 203  
 204          if ( $this->mVary ) {
 205              header ( "Vary: " . $this->mVary );
 206          }
 207      }
 208  
 209      /**
 210       * checkLastModified tells the client to use the client-cached response if
 211       * possible. If successful, the AjaxResponse is disabled so that
 212       * any future call to AjaxResponse::printText() have no effect.
 213       *
 214       * @param string $timestamp
 215       * @return bool Returns true if the response code was set to 304 Not Modified.
 216       */
 217  	function checkLastModified( $timestamp ) {
 218          global $wgCachePages, $wgCacheEpoch, $wgUser;
 219          $fname = 'AjaxResponse::checkLastModified';
 220  
 221          if ( !$timestamp || $timestamp == '19700101000000' ) {
 222              wfDebug( "$fname: CACHE DISABLED, NO TIMESTAMP\n", 'log' );
 223              return false;
 224          }
 225  
 226          if ( !$wgCachePages ) {
 227              wfDebug( "$fname: CACHE DISABLED\n", 'log' );
 228              return false;
 229          }
 230  
 231          $timestamp = wfTimestamp( TS_MW, $timestamp );
 232          $lastmod = wfTimestamp( TS_RFC2822, max( $timestamp, $wgUser->getTouched(), $wgCacheEpoch ) );
 233  
 234          if ( !empty( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) ) {
 235              # IE sends sizes after the date like this:
 236              # Wed, 20 Aug 2003 06:51:19 GMT; length=5202
 237              # this breaks strtotime().
 238              $modsince = preg_replace( '/;.*$/', '', $_SERVER["HTTP_IF_MODIFIED_SINCE"] );
 239              $modsinceTime = strtotime( $modsince );
 240              $ismodsince = wfTimestamp( TS_MW, $modsinceTime ? $modsinceTime : 1 );
 241              wfDebug( "$fname: -- client send If-Modified-Since: " . $modsince . "\n", 'log' );
 242              wfDebug( "$fname: --  we might send Last-Modified : $lastmod\n", 'log' );
 243  
 244              if ( ( $ismodsince >= $timestamp )
 245                  && $wgUser->validateCache( $ismodsince ) &&
 246                  $ismodsince >= $wgCacheEpoch
 247              ) {
 248                  ini_set( 'zlib.output_compression', 0 );
 249                  $this->setResponseCode( "304 Not Modified" );
 250                  $this->disable();
 251                  $this->mLastModified = $lastmod;
 252  
 253                  wfDebug( "$fname: CACHED client: $ismodsince ; user: {$wgUser->getTouched()} ; " .
 254                      "page: $timestamp ; site $wgCacheEpoch\n", 'log' );
 255  
 256                  return true;
 257              } else {
 258                  wfDebug( "$fname: READY  client: $ismodsince ; user: {$wgUser->getTouched()} ; " .
 259                      "page: $timestamp ; site $wgCacheEpoch\n", 'log' );
 260                  $this->mLastModified = $lastmod;
 261              }
 262          } else {
 263              wfDebug( "$fname: client did not send If-Modified-Since header\n", 'log' );
 264              $this->mLastModified = $lastmod;
 265          }
 266          return false;
 267      }
 268  
 269      /**
 270       * @param string $mckey
 271       * @param int $touched
 272       * @return bool
 273       */
 274  	function loadFromMemcached( $mckey, $touched ) {
 275          global $wgMemc;
 276  
 277          if ( !$touched ) {
 278              return false;
 279          }
 280  
 281          $mcvalue = $wgMemc->get( $mckey );
 282          if ( $mcvalue ) {
 283              # Check to see if the value has been invalidated
 284              if ( $touched <= $mcvalue['timestamp'] ) {
 285                  wfDebug( "Got $mckey from cache\n" );
 286                  $this->mText = $mcvalue['value'];
 287  
 288                  return true;
 289              } else {
 290                  wfDebug( "$mckey has expired\n" );
 291              }
 292          }
 293  
 294          return false;
 295      }
 296  
 297      /**
 298       * @param string $mckey
 299       * @param int $expiry
 300       * @return bool
 301       */
 302  	function storeInMemcached( $mckey, $expiry = 86400 ) {
 303          global $wgMemc;
 304  
 305          $wgMemc->set( $mckey,
 306              array(
 307                  'timestamp' => wfTimestampNow(),
 308                  'value' => $this->mText
 309              ), $expiry
 310          );
 311  
 312          return true;
 313      }
 314  }


Generated: Fri Nov 28 14:03:12 2014 Cross-referenced by PHPXref 0.7.1