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