MediaWiki  REL1_22
Message.php
Go to the documentation of this file.
00001 <?php
00159 class Message {
00164     protected $interface = true;
00165 
00172     protected $language = null;
00173 
00177     protected $key;
00178 
00182     protected $parameters = array();
00183 
00193     protected $format = 'parse';
00194 
00198     protected $useDatabase = true;
00199 
00203     protected $title = null;
00204 
00208     protected $content = null;
00209 
00213     protected $message;
00214 
00222     public function __construct( $key, $params = array() ) {
00223         global $wgLang;
00224         $this->key = $key;
00225         $this->parameters = array_values( $params );
00226         $this->language = $wgLang;
00227     }
00228 
00236     public function getKey() {
00237         if ( is_array( $this->key ) ) {
00238             // May happen if some kind of fallback is applied.
00239             // For now, just use the first key. We really need a better solution.
00240             return $this->key[0];
00241         } else {
00242             return $this->key;
00243         }
00244     }
00245 
00253     public function getParams() {
00254         return $this->parameters;
00255     }
00256 
00264     public function getFormat() {
00265         return $this->format;
00266     }
00267 
00277     public static function newFromKey( $key /*...*/ ) {
00278         $params = func_get_args();
00279         array_shift( $params );
00280         return new self( $key, $params );
00281     }
00282 
00291     public static function newFallbackSequence( /*...*/ ) {
00292         $keys = func_get_args();
00293         if ( func_num_args() == 1 ) {
00294             if ( is_array( $keys[0] ) ) {
00295                 // Allow an array to be passed as the first argument instead
00296                 $keys = array_values( $keys[0] );
00297             } else {
00298                 // Optimize a single string to not need special fallback handling
00299                 $keys = $keys[0];
00300             }
00301         }
00302         return new self( $keys );
00303     }
00304 
00311     public function params( /*...*/ ) {
00312         $args = func_get_args();
00313         if ( isset( $args[0] ) && is_array( $args[0] ) ) {
00314             $args = $args[0];
00315         }
00316         $args_values = array_values( $args );
00317         $this->parameters = array_merge( $this->parameters, $args_values );
00318         return $this;
00319     }
00320 
00330     public function rawParams( /*...*/ ) {
00331         $params = func_get_args();
00332         if ( isset( $params[0] ) && is_array( $params[0] ) ) {
00333             $params = $params[0];
00334         }
00335         foreach ( $params as $param ) {
00336             $this->parameters[] = self::rawParam( $param );
00337         }
00338         return $this;
00339     }
00340 
00348     public function numParams( /*...*/ ) {
00349         $params = func_get_args();
00350         if ( isset( $params[0] ) && is_array( $params[0] ) ) {
00351             $params = $params[0];
00352         }
00353         foreach ( $params as $param ) {
00354             $this->parameters[] = self::numParam( $param );
00355         }
00356         return $this;
00357     }
00358 
00366     public function durationParams( /*...*/ ) {
00367         $params = func_get_args();
00368         if ( isset( $params[0] ) && is_array( $params[0] ) ) {
00369             $params = $params[0];
00370         }
00371         foreach ( $params as $param ) {
00372             $this->parameters[] = self::durationParam( $param );
00373         }
00374         return $this;
00375     }
00376 
00384     public function expiryParams( /*...*/ ) {
00385         $params = func_get_args();
00386         if ( isset( $params[0] ) && is_array( $params[0] ) ) {
00387             $params = $params[0];
00388         }
00389         foreach ( $params as $param ) {
00390             $this->parameters[] = self::expiryParam( $param );
00391         }
00392         return $this;
00393     }
00394 
00402     public function timeperiodParams( /*...*/ ) {
00403         $params = func_get_args();
00404         if ( isset( $params[0] ) && is_array( $params[0] ) ) {
00405             $params = $params[0];
00406         }
00407         foreach ( $params as $param ) {
00408             $this->parameters[] = self::timeperiodParam( $param );
00409         }
00410         return $this;
00411     }
00412 
00420     public function sizeParams( /*...*/ ) {
00421         $params = func_get_args();
00422         if ( isset( $params[0] ) && is_array( $params[0] ) ) {
00423             $params = $params[0];
00424         }
00425         foreach ( $params as $param ) {
00426             $this->parameters[] = self::sizeParam( $param );
00427         }
00428         return $this;
00429     }
00430 
00438     public function bitrateParams( /*...*/ ) {
00439         $params = func_get_args();
00440         if ( isset( $params[0] ) && is_array( $params[0] ) ) {
00441             $params = $params[0];
00442         }
00443         foreach ( $params as $param ) {
00444             $this->parameters[] = self::bitrateParam( $param );
00445         }
00446         return $this;
00447     }
00448 
00455     public function setContext( IContextSource $context ) {
00456         $this->inLanguage( $context->getLanguage() );
00457         $this->title( $context->getTitle() );
00458         $this->interface = true;
00459 
00460         return $this;
00461     }
00462 
00472     public function inLanguage( $lang ) {
00473         if ( $lang instanceof Language || $lang instanceof StubUserLang ) {
00474             $this->language = $lang;
00475         } elseif ( is_string( $lang ) ) {
00476             if ( $this->language->getCode() != $lang ) {
00477                 $this->language = Language::factory( $lang );
00478             }
00479         } else {
00480             $type = gettype( $lang );
00481             throw new MWException( __METHOD__ . " must be "
00482                 . "passed a String or Language object; $type given"
00483             );
00484         }
00485         $this->interface = false;
00486         return $this;
00487     }
00488 
00496     public function inContentLanguage() {
00497         global $wgForceUIMsgAsContentMsg;
00498         if ( in_array( $this->key, (array)$wgForceUIMsgAsContentMsg ) ) {
00499             return $this;
00500         }
00501 
00502         global $wgContLang;
00503         $this->interface = false;
00504         $this->language = $wgContLang;
00505         return $this;
00506     }
00507 
00515     public function setInterfaceMessageFlag( $value ) {
00516         $this->interface = (bool)$value;
00517         return $this;
00518     }
00519 
00526     public function useDatabase( $value ) {
00527         $this->useDatabase = (bool)$value;
00528         return $this;
00529     }
00530 
00537     public function title( $title ) {
00538         $this->title = $title;
00539         return $this;
00540     }
00541 
00546     public function content() {
00547         if ( !$this->content ) {
00548             $this->content = new MessageContent( $this );
00549         }
00550 
00551         return $this->content;
00552     }
00553 
00559     public function toString() {
00560         $string = $this->fetchMessage();
00561 
00562         if ( $string === false ) {
00563             $key = htmlspecialchars( is_array( $this->key ) ? $this->key[0] : $this->key );
00564             if ( $this->format === 'plain' ) {
00565                 return '<' . $key . '>';
00566             }
00567             return '&lt;' . $key . '&gt;';
00568         }
00569 
00570         # Replace $* with a list of parameters for &uselang=qqx.
00571         if ( strpos( $string, '$*' ) !== false ) {
00572             $paramlist = '';
00573             if ( $this->parameters !== array() ) {
00574                 $paramlist = ': $' . implode( ', $', range( 1, count( $this->parameters ) ) );
00575             }
00576             $string = str_replace( '$*', $paramlist, $string );
00577         }
00578 
00579         # Replace parameters before text parsing
00580         $string = $this->replaceParameters( $string, 'before' );
00581 
00582         # Maybe transform using the full parser
00583         if ( $this->format === 'parse' ) {
00584             $string = $this->parseText( $string );
00585             $m = array();
00586             if ( preg_match( '/^<p>(.*)\n?<\/p>\n?$/sU', $string, $m ) ) {
00587                 $string = $m[1];
00588             }
00589         } elseif ( $this->format === 'block-parse' ) {
00590             $string = $this->parseText( $string );
00591         } elseif ( $this->format === 'text' ) {
00592             $string = $this->transformText( $string );
00593         } elseif ( $this->format === 'escaped' ) {
00594             $string = $this->transformText( $string );
00595             $string = htmlspecialchars( $string, ENT_QUOTES, 'UTF-8', false );
00596         }
00597 
00598         # Raw parameter replacement
00599         $string = $this->replaceParameters( $string, 'after' );
00600 
00601         return $string;
00602     }
00603 
00611     public function __toString() {
00612         // PHP doesn't allow __toString to throw exceptions and will
00613         // trigger a fatal error if it does. So, catch any exceptions.
00614 
00615         try {
00616             return $this->toString();
00617         } catch ( Exception $ex ) {
00618             try {
00619                 trigger_error( "Exception caught in " . __METHOD__ . " (message " . $this->key . "): "
00620                     . $ex, E_USER_WARNING );
00621             } catch ( Exception $ex ) {
00622                 // Doh! Cause a fatal error after all?
00623             }
00624 
00625             if ( $this->format === 'plain' ) {
00626                 return '<' . $this->key . '>';
00627             }
00628             return '&lt;' . $this->key . '&gt;';
00629         }
00630     }
00631 
00637     public function parse() {
00638         $this->format = 'parse';
00639         return $this->toString();
00640     }
00641 
00647     public function text() {
00648         $this->format = 'text';
00649         return $this->toString();
00650     }
00651 
00657     public function plain() {
00658         $this->format = 'plain';
00659         return $this->toString();
00660     }
00661 
00667     public function parseAsBlock() {
00668         $this->format = 'block-parse';
00669         return $this->toString();
00670     }
00671 
00678     public function escaped() {
00679         $this->format = 'escaped';
00680         return $this->toString();
00681     }
00682 
00688     public function exists() {
00689         return $this->fetchMessage() !== false;
00690     }
00691 
00698     public function isBlank() {
00699         $message = $this->fetchMessage();
00700         return $message === false || $message === '';
00701     }
00702 
00708     public function isDisabled() {
00709         $message = $this->fetchMessage();
00710         return $message === false || $message === '' || $message === '-';
00711     }
00712 
00718     public static function rawParam( $value ) {
00719         return array( 'raw' => $value );
00720     }
00721 
00727     public static function numParam( $value ) {
00728         return array( 'num' => $value );
00729     }
00730 
00736     public static function durationParam( $value ) {
00737         return array( 'duration' => $value );
00738     }
00739 
00745     public static function expiryParam( $value ) {
00746         return array( 'expiry' => $value );
00747     }
00748 
00754     public static function timeperiodParam( $value ) {
00755         return array( 'period' => $value );
00756     }
00757 
00763     public static function sizeParam( $value ) {
00764         return array( 'size' => $value );
00765     }
00766 
00772     public static function bitrateParam( $value ) {
00773         return array( 'bitrate' => $value );
00774     }
00775 
00783     protected function replaceParameters( $message, $type = 'before' ) {
00784         $replacementKeys = array();
00785         foreach ( $this->parameters as $n => $param ) {
00786             list( $paramType, $value ) = $this->extractParam( $param );
00787             if ( $type === $paramType ) {
00788                 $replacementKeys['$' . ( $n + 1 )] = $value;
00789             }
00790         }
00791         $message = strtr( $message, $replacementKeys );
00792         return $message;
00793     }
00794 
00801     protected function extractParam( $param ) {
00802         if ( is_array( $param ) ) {
00803             if ( isset( $param['raw'] ) ) {
00804                 return array( 'after', $param['raw'] );
00805             } elseif ( isset( $param['num'] ) ) {
00806                 // Replace number params always in before step for now.
00807                 // No support for combined raw and num params
00808                 return array( 'before', $this->language->formatNum( $param['num'] ) );
00809             } elseif ( isset( $param['duration'] ) ) {
00810                 return array( 'before', $this->language->formatDuration( $param['duration'] ) );
00811             } elseif ( isset( $param['expiry'] ) ) {
00812                 return array( 'before', $this->language->formatExpiry( $param['expiry'] ) );
00813             } elseif ( isset( $param['period'] ) ) {
00814                 return array( 'before', $this->language->formatTimePeriod( $param['period'] ) );
00815             } elseif ( isset( $param['size'] ) ) {
00816                 return array( 'before', $this->language->formatSize( $param['size'] ) );
00817             } elseif ( isset( $param['bitrate'] ) ) {
00818                 return array( 'before', $this->language->formatBitrate( $param['bitrate'] ) );
00819             } else {
00820                 trigger_error(
00821                     "Invalid message parameter: " . htmlspecialchars( serialize( $param ) ),
00822                     E_USER_WARNING
00823                 );
00824                 return array( 'before', '[INVALID]' );
00825             }
00826         } elseif ( $param instanceof Message ) {
00827             // Message objects should not be before parameters because
00828             // then they'll get double escaped. If the message needs to be
00829             // escaped, it'll happen right here when we call toString().
00830             return array( 'after', $param->toString() );
00831         } else {
00832             return array( 'before', $param );
00833         }
00834     }
00835 
00842     protected function parseText( $string ) {
00843         $out = MessageCache::singleton()->parse( $string, $this->title, /*linestart*/true, $this->interface, $this->language );
00844         return is_object( $out ) ? $out->getText() : $out;
00845     }
00846 
00853     protected function transformText( $string ) {
00854         return MessageCache::singleton()->transform( $string, $this->interface, $this->language, $this->title );
00855     }
00856 
00863     protected function fetchMessage() {
00864         if ( !isset( $this->message ) ) {
00865             $cache = MessageCache::singleton();
00866             if ( is_array( $this->key ) ) {
00867                 if ( !count( $this->key ) ) {
00868                     throw new MWException( "Given empty message key array." );
00869                 }
00870                 foreach ( $this->key as $key ) {
00871                     $message = $cache->get( $key, $this->useDatabase, $this->language );
00872                     if ( $message !== false && $message !== '' ) {
00873                         break;
00874                     }
00875                 }
00876                 $this->message = $message;
00877             } else {
00878                 $this->message = $cache->get( $this->key, $this->useDatabase, $this->language );
00879             }
00880         }
00881         return $this->message;
00882     }
00883 
00884 }
00885 
00899 class RawMessage extends Message {
00908     public function __construct( $key, $params = array() ) {
00909         parent::__construct( $key, $params );
00910         // The key is the message.
00911         $this->message = $key;
00912     }
00913 
00919     public function fetchMessage() {
00920         // Just in case the message is unset somewhere.
00921         if ( !isset( $this->message ) ) {
00922             $this->message = $this->key;
00923         }
00924         return $this->message;
00925     }
00926 }