MediaWiki
REL1_22
|
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 '<' . $key . '>'; 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 '<' . $this->key . '>'; 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 }