MediaWiki  REL1_23
Message.php
Go to the documentation of this file.
00001 <?php
00159 class Message {
00160 
00167     protected $interface = true;
00168 
00175     protected $language = null;
00176 
00180     protected $key;
00181 
00185     protected $parameters = array();
00186 
00198     protected $format = 'parse';
00199 
00203     protected $useDatabase = true;
00204 
00208     protected $title = null;
00209 
00213     protected $content = null;
00214 
00218     protected $message;
00219 
00228     public function __construct( $key, $params = array(), Language $language = null ) {
00229         global $wgLang;
00230 
00231         $this->key = $key;
00232         $this->parameters = array_values( $params );
00233         $this->language = $language ? $language : $wgLang;
00234     }
00235 
00243     public function getKey() {
00244         if ( is_array( $this->key ) ) {
00245             // May happen if some kind of fallback is applied.
00246             // For now, just use the first key. We really need a better solution.
00247             return $this->key[0];
00248         } else {
00249             return $this->key;
00250         }
00251     }
00252 
00260     public function getParams() {
00261         return $this->parameters;
00262     }
00263 
00271     public function getFormat() {
00272         return $this->format;
00273     }
00274 
00282     public function getLanguage() {
00283         return $this->language;
00284     }
00285 
00298     public static function newFromKey( $key /*...*/ ) {
00299         $params = func_get_args();
00300         array_shift( $params );
00301         return new self( $key, $params );
00302     }
00303 
00316     public static function newFallbackSequence( /*...*/ ) {
00317         $keys = func_get_args();
00318         if ( func_num_args() == 1 ) {
00319             if ( is_array( $keys[0] ) ) {
00320                 // Allow an array to be passed as the first argument instead
00321                 $keys = array_values( $keys[0] );
00322             } else {
00323                 // Optimize a single string to not need special fallback handling
00324                 $keys = $keys[0];
00325             }
00326         }
00327         return new self( $keys );
00328     }
00329 
00340     public function params( /*...*/ ) {
00341         $args = func_get_args();
00342         if ( isset( $args[0] ) && is_array( $args[0] ) ) {
00343             $args = $args[0];
00344         }
00345         $args_values = array_values( $args );
00346         $this->parameters = array_merge( $this->parameters, $args_values );
00347         return $this;
00348     }
00349 
00363     public function rawParams( /*...*/ ) {
00364         $params = func_get_args();
00365         if ( isset( $params[0] ) && is_array( $params[0] ) ) {
00366             $params = $params[0];
00367         }
00368         foreach ( $params as $param ) {
00369             $this->parameters[] = self::rawParam( $param );
00370         }
00371         return $this;
00372     }
00373 
00385     public function numParams( /*...*/ ) {
00386         $params = func_get_args();
00387         if ( isset( $params[0] ) && is_array( $params[0] ) ) {
00388             $params = $params[0];
00389         }
00390         foreach ( $params as $param ) {
00391             $this->parameters[] = self::numParam( $param );
00392         }
00393         return $this;
00394     }
00395 
00407     public function durationParams( /*...*/ ) {
00408         $params = func_get_args();
00409         if ( isset( $params[0] ) && is_array( $params[0] ) ) {
00410             $params = $params[0];
00411         }
00412         foreach ( $params as $param ) {
00413             $this->parameters[] = self::durationParam( $param );
00414         }
00415         return $this;
00416     }
00417 
00429     public function expiryParams( /*...*/ ) {
00430         $params = func_get_args();
00431         if ( isset( $params[0] ) && is_array( $params[0] ) ) {
00432             $params = $params[0];
00433         }
00434         foreach ( $params as $param ) {
00435             $this->parameters[] = self::expiryParam( $param );
00436         }
00437         return $this;
00438     }
00439 
00451     public function timeperiodParams( /*...*/ ) {
00452         $params = func_get_args();
00453         if ( isset( $params[0] ) && is_array( $params[0] ) ) {
00454             $params = $params[0];
00455         }
00456         foreach ( $params as $param ) {
00457             $this->parameters[] = self::timeperiodParam( $param );
00458         }
00459         return $this;
00460     }
00461 
00473     public function sizeParams( /*...*/ ) {
00474         $params = func_get_args();
00475         if ( isset( $params[0] ) && is_array( $params[0] ) ) {
00476             $params = $params[0];
00477         }
00478         foreach ( $params as $param ) {
00479             $this->parameters[] = self::sizeParam( $param );
00480         }
00481         return $this;
00482     }
00483 
00495     public function bitrateParams( /*...*/ ) {
00496         $params = func_get_args();
00497         if ( isset( $params[0] ) && is_array( $params[0] ) ) {
00498             $params = $params[0];
00499         }
00500         foreach ( $params as $param ) {
00501             $this->parameters[] = self::bitrateParam( $param );
00502         }
00503         return $this;
00504     }
00505 
00515     public function setContext( IContextSource $context ) {
00516         $this->inLanguage( $context->getLanguage() );
00517         $this->title( $context->getTitle() );
00518         $this->interface = true;
00519 
00520         return $this;
00521     }
00522 
00535     public function inLanguage( $lang ) {
00536         if ( $lang instanceof Language || $lang instanceof StubUserLang ) {
00537             $this->language = $lang;
00538         } elseif ( is_string( $lang ) ) {
00539             if ( $this->language->getCode() != $lang ) {
00540                 $this->language = Language::factory( $lang );
00541             }
00542         } else {
00543             $type = gettype( $lang );
00544             throw new MWException( __METHOD__ . " must be "
00545                 . "passed a String or Language object; $type given"
00546             );
00547         }
00548         $this->interface = false;
00549         return $this;
00550     }
00551 
00561     public function inContentLanguage() {
00562         global $wgForceUIMsgAsContentMsg;
00563         if ( in_array( $this->key, (array)$wgForceUIMsgAsContentMsg ) ) {
00564             return $this;
00565         }
00566 
00567         global $wgContLang;
00568         $this->interface = false;
00569         $this->language = $wgContLang;
00570         return $this;
00571     }
00572 
00583     public function setInterfaceMessageFlag( $interface ) {
00584         $this->interface = (bool)$interface;
00585         return $this;
00586     }
00587 
00597     public function useDatabase( $useDatabase ) {
00598         $this->useDatabase = (bool)$useDatabase;
00599         return $this;
00600     }
00601 
00611     public function title( $title ) {
00612         $this->title = $title;
00613         return $this;
00614     }
00615 
00621     public function content() {
00622         if ( !$this->content ) {
00623             $this->content = new MessageContent( $this );
00624         }
00625 
00626         return $this->content;
00627     }
00628 
00636     public function toString() {
00637         $string = $this->fetchMessage();
00638 
00639         if ( $string === false ) {
00640             $key = htmlspecialchars( is_array( $this->key ) ? $this->key[0] : $this->key );
00641             if ( $this->format === 'plain' ) {
00642                 return '<' . $key . '>';
00643             }
00644             return '&lt;' . $key . '&gt;';
00645         }
00646 
00647         # Replace $* with a list of parameters for &uselang=qqx.
00648         if ( strpos( $string, '$*' ) !== false ) {
00649             $paramlist = '';
00650             if ( $this->parameters !== array() ) {
00651                 $paramlist = ': $' . implode( ', $', range( 1, count( $this->parameters ) ) );
00652             }
00653             $string = str_replace( '$*', $paramlist, $string );
00654         }
00655 
00656         # Replace parameters before text parsing
00657         $string = $this->replaceParameters( $string, 'before' );
00658 
00659         # Maybe transform using the full parser
00660         if ( $this->format === 'parse' ) {
00661             $string = $this->parseText( $string );
00662             $m = array();
00663             if ( preg_match( '/^<p>(.*)\n?<\/p>\n?$/sU', $string, $m ) ) {
00664                 $string = $m[1];
00665             }
00666         } elseif ( $this->format === 'block-parse' ) {
00667             $string = $this->parseText( $string );
00668         } elseif ( $this->format === 'text' ) {
00669             $string = $this->transformText( $string );
00670         } elseif ( $this->format === 'escaped' ) {
00671             $string = $this->transformText( $string );
00672             $string = htmlspecialchars( $string, ENT_QUOTES, 'UTF-8', false );
00673         }
00674 
00675         # Raw parameter replacement
00676         $string = $this->replaceParameters( $string, 'after' );
00677 
00678         return $string;
00679     }
00680 
00690     public function __toString() {
00691         // PHP doesn't allow __toString to throw exceptions and will
00692         // trigger a fatal error if it does. So, catch any exceptions.
00693 
00694         try {
00695             return $this->toString();
00696         } catch ( Exception $ex ) {
00697             try {
00698                 trigger_error( "Exception caught in " . __METHOD__ . " (message " . $this->key . "): "
00699                     . $ex, E_USER_WARNING );
00700             } catch ( Exception $ex ) {
00701                 // Doh! Cause a fatal error after all?
00702             }
00703 
00704             if ( $this->format === 'plain' ) {
00705                 return '<' . $this->key . '>';
00706             }
00707             return '&lt;' . $this->key . '&gt;';
00708         }
00709     }
00710 
00718     public function parse() {
00719         $this->format = 'parse';
00720         return $this->toString();
00721     }
00722 
00730     public function text() {
00731         $this->format = 'text';
00732         return $this->toString();
00733     }
00734 
00742     public function plain() {
00743         $this->format = 'plain';
00744         return $this->toString();
00745     }
00746 
00754     public function parseAsBlock() {
00755         $this->format = 'block-parse';
00756         return $this->toString();
00757     }
00758 
00767     public function escaped() {
00768         $this->format = 'escaped';
00769         return $this->toString();
00770     }
00771 
00779     public function exists() {
00780         return $this->fetchMessage() !== false;
00781     }
00782 
00791     public function isBlank() {
00792         $message = $this->fetchMessage();
00793         return $message === false || $message === '';
00794     }
00795 
00803     public function isDisabled() {
00804         $message = $this->fetchMessage();
00805         return $message === false || $message === '' || $message === '-';
00806     }
00807 
00815     public static function rawParam( $raw ) {
00816         return array( 'raw' => $raw );
00817     }
00818 
00826     public static function numParam( $num ) {
00827         return array( 'num' => $num );
00828     }
00829 
00837     public static function durationParam( $duration ) {
00838         return array( 'duration' => $duration );
00839     }
00840 
00848     public static function expiryParam( $expiry ) {
00849         return array( 'expiry' => $expiry );
00850     }
00851 
00859     public static function timeperiodParam( $period ) {
00860         return array( 'period' => $period );
00861     }
00862 
00870     public static function sizeParam( $size ) {
00871         return array( 'size' => $size );
00872     }
00873 
00881     public static function bitrateParam( $bitrate ) {
00882         return array( 'bitrate' => $bitrate );
00883     }
00884 
00895     protected function replaceParameters( $message, $type = 'before' ) {
00896         $replacementKeys = array();
00897         foreach ( $this->parameters as $n => $param ) {
00898             list( $paramType, $value ) = $this->extractParam( $param );
00899             if ( $type === $paramType ) {
00900                 $replacementKeys['$' . ( $n + 1 )] = $value;
00901             }
00902         }
00903         $message = strtr( $message, $replacementKeys );
00904         return $message;
00905     }
00906 
00916     protected function extractParam( $param ) {
00917         if ( is_array( $param ) ) {
00918             if ( isset( $param['raw'] ) ) {
00919                 return array( 'after', $param['raw'] );
00920             } elseif ( isset( $param['num'] ) ) {
00921                 // Replace number params always in before step for now.
00922                 // No support for combined raw and num params
00923                 return array( 'before', $this->language->formatNum( $param['num'] ) );
00924             } elseif ( isset( $param['duration'] ) ) {
00925                 return array( 'before', $this->language->formatDuration( $param['duration'] ) );
00926             } elseif ( isset( $param['expiry'] ) ) {
00927                 return array( 'before', $this->language->formatExpiry( $param['expiry'] ) );
00928             } elseif ( isset( $param['period'] ) ) {
00929                 return array( 'before', $this->language->formatTimePeriod( $param['period'] ) );
00930             } elseif ( isset( $param['size'] ) ) {
00931                 return array( 'before', $this->language->formatSize( $param['size'] ) );
00932             } elseif ( isset( $param['bitrate'] ) ) {
00933                 return array( 'before', $this->language->formatBitrate( $param['bitrate'] ) );
00934             } else {
00935                 $warning = 'Invalid parameter for message "' . $this->getKey() . '": ' .
00936                     htmlspecialchars( serialize( $param ) );
00937                 trigger_error( $warning, E_USER_WARNING );
00938                 $e = new Exception;
00939                 wfDebugLog( 'Bug58676', $warning . "\n" . $e->getTraceAsString() );
00940 
00941                 return array( 'before', '[INVALID]' );
00942             }
00943         } elseif ( $param instanceof Message ) {
00944             // Message objects should not be before parameters because
00945             // then they'll get double escaped. If the message needs to be
00946             // escaped, it'll happen right here when we call toString().
00947             return array( 'after', $param->toString() );
00948         } else {
00949             return array( 'before', $param );
00950         }
00951     }
00952 
00962     protected function parseText( $string ) {
00963         $out = MessageCache::singleton()->parse( $string, $this->title, /*linestart*/true, $this->interface, $this->language );
00964         return $out instanceof ParserOutput ? $out->getText() : $out;
00965     }
00966 
00976     protected function transformText( $string ) {
00977         return MessageCache::singleton()->transform( $string, $this->interface, $this->language, $this->title );
00978     }
00979 
00988     protected function fetchMessage() {
00989         if ( !isset( $this->message ) ) {
00990             $cache = MessageCache::singleton();
00991             if ( is_array( $this->key ) ) {
00992                 if ( !count( $this->key ) ) {
00993                     throw new MWException( "Given empty message key array." );
00994                 }
00995                 foreach ( $this->key as $key ) {
00996                     $message = $cache->get( $key, $this->useDatabase, $this->language );
00997                     if ( $message !== false && $message !== '' ) {
00998                         break;
00999                     }
01000                 }
01001                 $this->message = $message;
01002             } else {
01003                 $this->message = $cache->get( $this->key, $this->useDatabase, $this->language );
01004             }
01005         }
01006         return $this->message;
01007     }
01008 
01009 }
01010 
01024 class RawMessage extends Message {
01025 
01035     public function __construct( $key, $params = array() ) {
01036         parent::__construct( $key, $params );
01037         // The key is the message.
01038         $this->message = $key;
01039     }
01040 
01046     public function fetchMessage() {
01047         // Just in case the message is unset somewhere.
01048         if ( !isset( $this->message ) ) {
01049             $this->message = $this->key;
01050         }
01051         return $this->message;
01052     }
01053 
01054 }