[ Index ] |
PHP Cross Reference of MediaWiki-1.24.0 |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Fetching and processing of interface messages. 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 * @author Niklas Laxström 22 */ 23 24 /** 25 * The Message class provides methods which fulfil two basic services: 26 * - fetching interface messages 27 * - processing messages into a variety of formats 28 * 29 * First implemented with MediaWiki 1.17, the Message class is intended to 30 * replace the old wfMsg* functions that over time grew unusable. 31 * @see https://www.mediawiki.org/wiki/Manual:Messages_API for equivalences 32 * between old and new functions. 33 * 34 * You should use the wfMessage() global function which acts as a wrapper for 35 * the Message class. The wrapper let you pass parameters as arguments. 36 * 37 * The most basic usage cases would be: 38 * 39 * @code 40 * // Initialize a Message object using the 'some_key' message key 41 * $message = wfMessage( 'some_key' ); 42 * 43 * // Using two parameters those values are strings 'value1' and 'value2': 44 * $message = wfMessage( 'some_key', 45 * 'value1', 'value2' 46 * ); 47 * @endcode 48 * 49 * @section message_global_fn Global function wrapper: 50 * 51 * Since wfMessage() returns a Message instance, you can chain its call with 52 * a method. Some of them return a Message instance too so you can chain them. 53 * You will find below several examples of wfMessage() usage. 54 * 55 * Fetching a message text for interface message: 56 * 57 * @code 58 * $button = Xml::button( 59 * wfMessage( 'submit' )->text() 60 * ); 61 * @endcode 62 * 63 * A Message instance can be passed parameters after it has been constructed, 64 * use the params() method to do so: 65 * 66 * @code 67 * wfMessage( 'welcome-to' ) 68 * ->params( $wgSitename ) 69 * ->text(); 70 * @endcode 71 * 72 * {{GRAMMAR}} and friends work correctly: 73 * 74 * @code 75 * wfMessage( 'are-friends', 76 * $user, $friend 77 * ); 78 * wfMessage( 'bad-message' ) 79 * ->rawParams( '<script>...</script>' ) 80 * ->escaped(); 81 * @endcode 82 * 83 * @section message_language Changing language: 84 * 85 * Messages can be requested in a different language or in whatever current 86 * content language is being used. The methods are: 87 * - Message->inContentLanguage() 88 * - Message->inLanguage() 89 * 90 * Sometimes the message text ends up in the database, so content language is 91 * needed: 92 * 93 * @code 94 * wfMessage( 'file-log', 95 * $user, $filename 96 * )->inContentLanguage()->text(); 97 * @endcode 98 * 99 * Checking whether a message exists: 100 * 101 * @code 102 * wfMessage( 'mysterious-message' )->exists() 103 * // returns a boolean whether the 'mysterious-message' key exist. 104 * @endcode 105 * 106 * If you want to use a different language: 107 * 108 * @code 109 * $userLanguage = $user->getOption( 'language' ); 110 * wfMessage( 'email-header' ) 111 * ->inLanguage( $userLanguage ) 112 * ->plain(); 113 * @endcode 114 * 115 * @note You can parse the text only in the content or interface languages 116 * 117 * @section message_compare_old Comparison with old wfMsg* functions: 118 * 119 * Use full parsing: 120 * 121 * @code 122 * // old style: 123 * wfMsgExt( 'key', array( 'parseinline' ), 'apple' ); 124 * // new style: 125 * wfMessage( 'key', 'apple' )->parse(); 126 * @endcode 127 * 128 * Parseinline is used because it is more useful when pre-building HTML. 129 * In normal use it is better to use OutputPage::(add|wrap)WikiMsg. 130 * 131 * Places where HTML cannot be used. {{-transformation is done. 132 * @code 133 * // old style: 134 * wfMsgExt( 'key', array( 'parsemag' ), 'apple', 'pear' ); 135 * // new style: 136 * wfMessage( 'key', 'apple', 'pear' )->text(); 137 * @endcode 138 * 139 * Shortcut for escaping the message too, similar to wfMsgHTML(), but 140 * parameters are not replaced after escaping by default. 141 * @code 142 * $escaped = wfMessage( 'key' ) 143 * ->rawParams( 'apple' ) 144 * ->escaped(); 145 * @endcode 146 * 147 * @section message_appendix Appendix: 148 * 149 * @todo 150 * - test, can we have tests? 151 * - this documentation needs to be extended 152 * 153 * @see https://www.mediawiki.org/wiki/WfMessage() 154 * @see https://www.mediawiki.org/wiki/New_messages_API 155 * @see https://www.mediawiki.org/wiki/Localisation 156 * 157 * @since 1.17 158 */ 159 class Message { 160 161 /** 162 * In which language to get this message. True, which is the default, 163 * means the current interface language, false content language. 164 * 165 * @var bool 166 */ 167 protected $interface = true; 168 169 /** 170 * In which language to get this message. Overrides the $interface 171 * variable. 172 * 173 * @var Language 174 */ 175 protected $language = null; 176 177 /** 178 * @var string The message key. If $keysToTry has more than one element, 179 * this may change to one of the keys to try when fetching the message text. 180 */ 181 protected $key; 182 183 /** 184 * @var string[] List of keys to try when fetching the message. 185 */ 186 protected $keysToTry; 187 188 /** 189 * @var array List of parameters which will be substituted into the message. 190 */ 191 protected $parameters = array(); 192 193 /** 194 * Format for the message. 195 * Supported formats are: 196 * * text (transform) 197 * * escaped (transform+htmlspecialchars) 198 * * block-parse 199 * * parse (default) 200 * * plain 201 * 202 * @var string 203 */ 204 protected $format = 'parse'; 205 206 /** 207 * @var bool Whether database can be used. 208 */ 209 protected $useDatabase = true; 210 211 /** 212 * @var Title Title object to use as context. 213 */ 214 protected $title = null; 215 216 /** 217 * @var Content Content object representing the message. 218 */ 219 protected $content = null; 220 221 /** 222 * @var string 223 */ 224 protected $message; 225 226 /** 227 * @since 1.17 228 * 229 * @param string|string[] $key Message key or array of message keys to try and use the first 230 * non-empty message for. 231 * @param array $params Message parameters. 232 * @param Language $language Optional language of the message, defaults to $wgLang. 233 * 234 * @throws InvalidArgumentException 235 */ 236 public function __construct( $key, $params = array(), Language $language = null ) { 237 global $wgLang; 238 239 if ( !is_string( $key ) && !is_array( $key ) ) { 240 throw new InvalidArgumentException( '$key must be a string or an array' ); 241 } 242 243 $this->keysToTry = (array)$key; 244 245 if ( empty( $this->keysToTry ) ) { 246 throw new InvalidArgumentException( '$key must not be an empty list' ); 247 } 248 249 $this->key = reset( $this->keysToTry ); 250 251 $this->parameters = array_values( $params ); 252 $this->language = $language ? $language : $wgLang; 253 } 254 255 /** 256 * @since 1.24 257 * 258 * @return bool True if this is a multi-key message, that is, if the key provided to the 259 * constructor was a fallback list of keys to try. 260 */ 261 public function isMultiKey() { 262 return count( $this->keysToTry ) > 1; 263 } 264 265 /** 266 * @since 1.24 267 * 268 * @return string[] The list of keys to try when fetching the message text, 269 * in order of preference. 270 */ 271 public function getKeysToTry() { 272 return $this->keysToTry; 273 } 274 275 /** 276 * Returns the message key. 277 * 278 * If a list of multiple possible keys was supplied to the constructor, this method may 279 * return any of these keys. After the message ahs been fetched, this method will return 280 * the key that was actually used to fetch the message. 281 * 282 * @since 1.21 283 * 284 * @return string 285 */ 286 public function getKey() { 287 return $this->key; 288 } 289 290 /** 291 * Returns the message parameters. 292 * 293 * @since 1.21 294 * 295 * @return array 296 */ 297 public function getParams() { 298 return $this->parameters; 299 } 300 301 /** 302 * Returns the message format. 303 * 304 * @since 1.21 305 * 306 * @return string 307 */ 308 public function getFormat() { 309 return $this->format; 310 } 311 312 /** 313 * Returns the Language of the Message. 314 * 315 * @since 1.23 316 * 317 * @return Language 318 */ 319 public function getLanguage() { 320 return $this->language; 321 } 322 323 /** 324 * Factory function that is just wrapper for the real constructor. It is 325 * intended to be used instead of the real constructor, because it allows 326 * chaining method calls, while new objects don't. 327 * 328 * @since 1.17 329 * 330 * @param string|string[] $key Message key or array of keys. 331 * @param mixed $param,... Parameters as strings. 332 * 333 * @return Message 334 */ 335 public static function newFromKey( $key /*...*/ ) { 336 $params = func_get_args(); 337 array_shift( $params ); 338 return new self( $key, $params ); 339 } 340 341 /** 342 * Factory function accepting multiple message keys and returning a message instance 343 * for the first message which is non-empty. If all messages are empty then an 344 * instance of the first message key is returned. 345 * 346 * @since 1.18 347 * 348 * @param string|string[] $keys,... Message keys, or first argument as an array of all the 349 * message keys. 350 * 351 * @return Message 352 */ 353 public static function newFallbackSequence( /*...*/ ) { 354 $keys = func_get_args(); 355 if ( func_num_args() == 1 ) { 356 if ( is_array( $keys[0] ) ) { 357 // Allow an array to be passed as the first argument instead 358 $keys = array_values( $keys[0] ); 359 } else { 360 // Optimize a single string to not need special fallback handling 361 $keys = $keys[0]; 362 } 363 } 364 return new self( $keys ); 365 } 366 367 /** 368 * Adds parameters to the parameter list of this message. 369 * 370 * @since 1.17 371 * 372 * @param mixed $params,... Parameters as strings, or a single argument that is 373 * an array of strings. 374 * 375 * @return Message $this 376 */ 377 public function params( /*...*/ ) { 378 $args = func_get_args(); 379 if ( isset( $args[0] ) && is_array( $args[0] ) ) { 380 $args = $args[0]; 381 } 382 $args_values = array_values( $args ); 383 $this->parameters = array_merge( $this->parameters, $args_values ); 384 return $this; 385 } 386 387 /** 388 * Add parameters that are substituted after parsing or escaping. 389 * In other words the parsing process cannot access the contents 390 * of this type of parameter, and you need to make sure it is 391 * sanitized beforehand. The parser will see "$n", instead. 392 * 393 * @since 1.17 394 * 395 * @param mixed $params,... Raw parameters as strings, or a single argument that is 396 * an array of raw parameters. 397 * 398 * @return Message $this 399 */ 400 public function rawParams( /*...*/ ) { 401 $params = func_get_args(); 402 if ( isset( $params[0] ) && is_array( $params[0] ) ) { 403 $params = $params[0]; 404 } 405 foreach ( $params as $param ) { 406 $this->parameters[] = self::rawParam( $param ); 407 } 408 return $this; 409 } 410 411 /** 412 * Add parameters that are numeric and will be passed through 413 * Language::formatNum before substitution 414 * 415 * @since 1.18 416 * 417 * @param mixed $param,... Numeric parameters, or a single argument that is 418 * an array of numeric parameters. 419 * 420 * @return Message $this 421 */ 422 public function numParams( /*...*/ ) { 423 $params = func_get_args(); 424 if ( isset( $params[0] ) && is_array( $params[0] ) ) { 425 $params = $params[0]; 426 } 427 foreach ( $params as $param ) { 428 $this->parameters[] = self::numParam( $param ); 429 } 430 return $this; 431 } 432 433 /** 434 * Add parameters that are durations of time and will be passed through 435 * Language::formatDuration before substitution 436 * 437 * @since 1.22 438 * 439 * @param int|int[] $param,... Duration parameters, or a single argument that is 440 * an array of duration parameters. 441 * 442 * @return Message $this 443 */ 444 public function durationParams( /*...*/ ) { 445 $params = func_get_args(); 446 if ( isset( $params[0] ) && is_array( $params[0] ) ) { 447 $params = $params[0]; 448 } 449 foreach ( $params as $param ) { 450 $this->parameters[] = self::durationParam( $param ); 451 } 452 return $this; 453 } 454 455 /** 456 * Add parameters that are expiration times and will be passed through 457 * Language::formatExpiry before substitution 458 * 459 * @since 1.22 460 * 461 * @param string|string[] $param,... Expiry parameters, or a single argument that is 462 * an array of expiry parameters. 463 * 464 * @return Message $this 465 */ 466 public function expiryParams( /*...*/ ) { 467 $params = func_get_args(); 468 if ( isset( $params[0] ) && is_array( $params[0] ) ) { 469 $params = $params[0]; 470 } 471 foreach ( $params as $param ) { 472 $this->parameters[] = self::expiryParam( $param ); 473 } 474 return $this; 475 } 476 477 /** 478 * Add parameters that are time periods and will be passed through 479 * Language::formatTimePeriod before substitution 480 * 481 * @since 1.22 482 * 483 * @param int|int[] $param,... Time period parameters, or a single argument that is 484 * an array of time period parameters. 485 * 486 * @return Message $this 487 */ 488 public function timeperiodParams( /*...*/ ) { 489 $params = func_get_args(); 490 if ( isset( $params[0] ) && is_array( $params[0] ) ) { 491 $params = $params[0]; 492 } 493 foreach ( $params as $param ) { 494 $this->parameters[] = self::timeperiodParam( $param ); 495 } 496 return $this; 497 } 498 499 /** 500 * Add parameters that are file sizes and will be passed through 501 * Language::formatSize before substitution 502 * 503 * @since 1.22 504 * 505 * @param int|int[] $param,... Size parameters, or a single argument that is 506 * an array of size parameters. 507 * 508 * @return Message $this 509 */ 510 public function sizeParams( /*...*/ ) { 511 $params = func_get_args(); 512 if ( isset( $params[0] ) && is_array( $params[0] ) ) { 513 $params = $params[0]; 514 } 515 foreach ( $params as $param ) { 516 $this->parameters[] = self::sizeParam( $param ); 517 } 518 return $this; 519 } 520 521 /** 522 * Add parameters that are bitrates and will be passed through 523 * Language::formatBitrate before substitution 524 * 525 * @since 1.22 526 * 527 * @param int|int[] $param,... Bit rate parameters, or a single argument that is 528 * an array of bit rate parameters. 529 * 530 * @return Message $this 531 */ 532 public function bitrateParams( /*...*/ ) { 533 $params = func_get_args(); 534 if ( isset( $params[0] ) && is_array( $params[0] ) ) { 535 $params = $params[0]; 536 } 537 foreach ( $params as $param ) { 538 $this->parameters[] = self::bitrateParam( $param ); 539 } 540 return $this; 541 } 542 543 /** 544 * Set the language and the title from a context object 545 * 546 * @since 1.19 547 * 548 * @param IContextSource $context 549 * 550 * @return Message $this 551 */ 552 public function setContext( IContextSource $context ) { 553 $this->inLanguage( $context->getLanguage() ); 554 $this->title( $context->getTitle() ); 555 $this->interface = true; 556 557 return $this; 558 } 559 560 /** 561 * Request the message in any language that is supported. 562 * As a side effect interface message status is unconditionally 563 * turned off. 564 * 565 * @since 1.17 566 * 567 * @param Language|string $lang Language code or Language object. 568 * 569 * @return Message $this 570 * @throws MWException 571 */ 572 public function inLanguage( $lang ) { 573 if ( $lang instanceof Language || $lang instanceof StubUserLang ) { 574 $this->language = $lang; 575 } elseif ( is_string( $lang ) ) { 576 if ( $this->language->getCode() != $lang ) { 577 $this->language = Language::factory( $lang ); 578 } 579 } else { 580 $type = gettype( $lang ); 581 throw new MWException( __METHOD__ . " must be " 582 . "passed a String or Language object; $type given" 583 ); 584 } 585 $this->message = null; 586 $this->interface = false; 587 return $this; 588 } 589 590 /** 591 * Request the message in the wiki's content language, 592 * unless it is disabled for this message. 593 * 594 * @since 1.17 595 * @see $wgForceUIMsgAsContentMsg 596 * 597 * @return Message $this 598 */ 599 public function inContentLanguage() { 600 global $wgForceUIMsgAsContentMsg; 601 if ( in_array( $this->key, (array)$wgForceUIMsgAsContentMsg ) ) { 602 return $this; 603 } 604 605 global $wgContLang; 606 $this->inLanguage( $wgContLang ); 607 return $this; 608 } 609 610 /** 611 * Allows manipulating the interface message flag directly. 612 * Can be used to restore the flag after setting a language. 613 * 614 * @since 1.20 615 * 616 * @param bool $interface 617 * 618 * @return Message $this 619 */ 620 public function setInterfaceMessageFlag( $interface ) { 621 $this->interface = (bool)$interface; 622 return $this; 623 } 624 625 /** 626 * Enable or disable database use. 627 * 628 * @since 1.17 629 * 630 * @param bool $useDatabase 631 * 632 * @return Message $this 633 */ 634 public function useDatabase( $useDatabase ) { 635 $this->useDatabase = (bool)$useDatabase; 636 return $this; 637 } 638 639 /** 640 * Set the Title object to use as context when transforming the message 641 * 642 * @since 1.18 643 * 644 * @param Title $title 645 * 646 * @return Message $this 647 */ 648 public function title( $title ) { 649 $this->title = $title; 650 return $this; 651 } 652 653 /** 654 * Returns the message as a Content object. 655 * 656 * @return Content 657 */ 658 public function content() { 659 if ( !$this->content ) { 660 $this->content = new MessageContent( $this ); 661 } 662 663 return $this->content; 664 } 665 666 /** 667 * Returns the message parsed from wikitext to HTML. 668 * 669 * @since 1.17 670 * 671 * @return string HTML 672 */ 673 public function toString() { 674 $string = $this->fetchMessage(); 675 676 if ( $string === false ) { 677 $key = htmlspecialchars( $this->key ); 678 if ( $this->format === 'plain' ) { 679 return '<' . $key . '>'; 680 } 681 return '<' . $key . '>'; 682 } 683 684 # Replace $* with a list of parameters for &uselang=qqx. 685 if ( strpos( $string, '$*' ) !== false ) { 686 $paramlist = ''; 687 if ( $this->parameters !== array() ) { 688 $paramlist = ': $' . implode( ', $', range( 1, count( $this->parameters ) ) ); 689 } 690 $string = str_replace( '$*', $paramlist, $string ); 691 } 692 693 # Replace parameters before text parsing 694 $string = $this->replaceParameters( $string, 'before' ); 695 696 # Maybe transform using the full parser 697 if ( $this->format === 'parse' ) { 698 $string = $this->parseText( $string ); 699 $string = Parser::stripOuterParagraph( $string ); 700 } elseif ( $this->format === 'block-parse' ) { 701 $string = $this->parseText( $string ); 702 } elseif ( $this->format === 'text' ) { 703 $string = $this->transformText( $string ); 704 } elseif ( $this->format === 'escaped' ) { 705 $string = $this->transformText( $string ); 706 $string = htmlspecialchars( $string, ENT_QUOTES, 'UTF-8', false ); 707 } 708 709 # Raw parameter replacement 710 $string = $this->replaceParameters( $string, 'after' ); 711 712 return $string; 713 } 714 715 /** 716 * Magic method implementation of the above (for PHP >= 5.2.0), so we can do, eg: 717 * $foo = Message::get( $key ); 718 * $string = "<abbr>$foo</abbr>"; 719 * 720 * @since 1.18 721 * 722 * @return string 723 */ 724 public function __toString() { 725 // PHP doesn't allow __toString to throw exceptions and will 726 // trigger a fatal error if it does. So, catch any exceptions. 727 728 try { 729 return $this->toString(); 730 } catch ( Exception $ex ) { 731 try { 732 trigger_error( "Exception caught in " . __METHOD__ . " (message " . $this->key . "): " 733 . $ex, E_USER_WARNING ); 734 } catch ( Exception $ex ) { 735 // Doh! Cause a fatal error after all? 736 } 737 738 if ( $this->format === 'plain' ) { 739 return '<' . $this->key . '>'; 740 } 741 return '<' . $this->key . '>'; 742 } 743 } 744 745 /** 746 * Fully parse the text from wikitext to HTML. 747 * 748 * @since 1.17 749 * 750 * @return string Parsed HTML. 751 */ 752 public function parse() { 753 $this->format = 'parse'; 754 return $this->toString(); 755 } 756 757 /** 758 * Returns the message text. {{-transformation is done. 759 * 760 * @since 1.17 761 * 762 * @return string Unescaped message text. 763 */ 764 public function text() { 765 $this->format = 'text'; 766 return $this->toString(); 767 } 768 769 /** 770 * Returns the message text as-is, only parameters are substituted. 771 * 772 * @since 1.17 773 * 774 * @return string Unescaped untransformed message text. 775 */ 776 public function plain() { 777 $this->format = 'plain'; 778 return $this->toString(); 779 } 780 781 /** 782 * Returns the parsed message text which is always surrounded by a block element. 783 * 784 * @since 1.17 785 * 786 * @return string HTML 787 */ 788 public function parseAsBlock() { 789 $this->format = 'block-parse'; 790 return $this->toString(); 791 } 792 793 /** 794 * Returns the message text. {{-transformation is done and the result 795 * is escaped excluding any raw parameters. 796 * 797 * @since 1.17 798 * 799 * @return string Escaped message text. 800 */ 801 public function escaped() { 802 $this->format = 'escaped'; 803 return $this->toString(); 804 } 805 806 /** 807 * Check whether a message key has been defined currently. 808 * 809 * @since 1.17 810 * 811 * @return bool 812 */ 813 public function exists() { 814 return $this->fetchMessage() !== false; 815 } 816 817 /** 818 * Check whether a message does not exist, or is an empty string 819 * 820 * @since 1.18 821 * @todo FIXME: Merge with isDisabled()? 822 * 823 * @return bool 824 */ 825 public function isBlank() { 826 $message = $this->fetchMessage(); 827 return $message === false || $message === ''; 828 } 829 830 /** 831 * Check whether a message does not exist, is an empty string, or is "-". 832 * 833 * @since 1.18 834 * 835 * @return bool 836 */ 837 public function isDisabled() { 838 $message = $this->fetchMessage(); 839 return $message === false || $message === '' || $message === '-'; 840 } 841 842 /** 843 * @since 1.17 844 * 845 * @param mixed $raw 846 * 847 * @return array Array with a single "raw" key. 848 */ 849 public static function rawParam( $raw ) { 850 return array( 'raw' => $raw ); 851 } 852 853 /** 854 * @since 1.18 855 * 856 * @param mixed $num 857 * 858 * @return array Array with a single "num" key. 859 */ 860 public static function numParam( $num ) { 861 return array( 'num' => $num ); 862 } 863 864 /** 865 * @since 1.22 866 * 867 * @param int $duration 868 * 869 * @return int[] Array with a single "duration" key. 870 */ 871 public static function durationParam( $duration ) { 872 return array( 'duration' => $duration ); 873 } 874 875 /** 876 * @since 1.22 877 * 878 * @param string $expiry 879 * 880 * @return string[] Array with a single "expiry" key. 881 */ 882 public static function expiryParam( $expiry ) { 883 return array( 'expiry' => $expiry ); 884 } 885 886 /** 887 * @since 1.22 888 * 889 * @param number $period 890 * 891 * @return number[] Array with a single "period" key. 892 */ 893 public static function timeperiodParam( $period ) { 894 return array( 'period' => $period ); 895 } 896 897 /** 898 * @since 1.22 899 * 900 * @param int $size 901 * 902 * @return int[] Array with a single "size" key. 903 */ 904 public static function sizeParam( $size ) { 905 return array( 'size' => $size ); 906 } 907 908 /** 909 * @since 1.22 910 * 911 * @param int $bitrate 912 * 913 * @return int[] Array with a single "bitrate" key. 914 */ 915 public static function bitrateParam( $bitrate ) { 916 return array( 'bitrate' => $bitrate ); 917 } 918 919 /** 920 * Substitutes any parameters into the message text. 921 * 922 * @since 1.17 923 * 924 * @param string $message The message text. 925 * @param string $type Either "before" or "after". 926 * 927 * @return string 928 */ 929 protected function replaceParameters( $message, $type = 'before' ) { 930 $replacementKeys = array(); 931 foreach ( $this->parameters as $n => $param ) { 932 list( $paramType, $value ) = $this->extractParam( $param ); 933 if ( $type === $paramType ) { 934 $replacementKeys['$' . ( $n + 1 )] = $value; 935 } 936 } 937 $message = strtr( $message, $replacementKeys ); 938 return $message; 939 } 940 941 /** 942 * Extracts the parameter type and preprocessed the value if needed. 943 * 944 * @since 1.18 945 * 946 * @param mixed $param Parameter as defined in this class. 947 * 948 * @return array Array with the parameter type (either "before" or "after") and the value. 949 */ 950 protected function extractParam( $param ) { 951 if ( is_array( $param ) ) { 952 if ( isset( $param['raw'] ) ) { 953 return array( 'after', $param['raw'] ); 954 } elseif ( isset( $param['num'] ) ) { 955 // Replace number params always in before step for now. 956 // No support for combined raw and num params 957 return array( 'before', $this->language->formatNum( $param['num'] ) ); 958 } elseif ( isset( $param['duration'] ) ) { 959 return array( 'before', $this->language->formatDuration( $param['duration'] ) ); 960 } elseif ( isset( $param['expiry'] ) ) { 961 return array( 'before', $this->language->formatExpiry( $param['expiry'] ) ); 962 } elseif ( isset( $param['period'] ) ) { 963 return array( 'before', $this->language->formatTimePeriod( $param['period'] ) ); 964 } elseif ( isset( $param['size'] ) ) { 965 return array( 'before', $this->language->formatSize( $param['size'] ) ); 966 } elseif ( isset( $param['bitrate'] ) ) { 967 return array( 'before', $this->language->formatBitrate( $param['bitrate'] ) ); 968 } else { 969 $warning = 'Invalid parameter for message "' . $this->getKey() . '": ' . 970 htmlspecialchars( serialize( $param ) ); 971 trigger_error( $warning, E_USER_WARNING ); 972 $e = new Exception; 973 wfDebugLog( 'Bug58676', $warning . "\n" . $e->getTraceAsString() ); 974 975 return array( 'before', '[INVALID]' ); 976 } 977 } elseif ( $param instanceof Message ) { 978 // Message objects should not be before parameters because 979 // then they'll get double escaped. If the message needs to be 980 // escaped, it'll happen right here when we call toString(). 981 return array( 'after', $param->toString() ); 982 } else { 983 return array( 'before', $param ); 984 } 985 } 986 987 /** 988 * Wrapper for what ever method we use to parse wikitext. 989 * 990 * @since 1.17 991 * 992 * @param string $string Wikitext message contents. 993 * 994 * @return string Wikitext parsed into HTML. 995 */ 996 protected function parseText( $string ) { 997 $out = MessageCache::singleton()->parse( 998 $string, 999 $this->title, 1000 /*linestart*/true, 1001 $this->interface, 1002 $this->language 1003 ); 1004 1005 return $out instanceof ParserOutput ? $out->getText() : $out; 1006 } 1007 1008 /** 1009 * Wrapper for what ever method we use to {{-transform wikitext. 1010 * 1011 * @since 1.17 1012 * 1013 * @param string $string Wikitext message contents. 1014 * 1015 * @return string Wikitext with {{-constructs replaced with their values. 1016 */ 1017 protected function transformText( $string ) { 1018 return MessageCache::singleton()->transform( 1019 $string, 1020 $this->interface, 1021 $this->language, 1022 $this->title 1023 ); 1024 } 1025 1026 /** 1027 * Wrapper for what ever method we use to get message contents. 1028 * 1029 * @since 1.17 1030 * 1031 * @return string 1032 * @throws MWException If message key array is empty. 1033 */ 1034 protected function fetchMessage() { 1035 if ( $this->message === null ) { 1036 $cache = MessageCache::singleton(); 1037 1038 foreach ( $this->keysToTry as $key ) { 1039 $message = $cache->get( $key, $this->useDatabase, $this->language ); 1040 if ( $message !== false && $message !== '' ) { 1041 break; 1042 } 1043 } 1044 1045 // NOTE: The constructor makes sure keysToTry isn't empty, 1046 // so we know that $key and $message are initialized. 1047 $this->key = $key; 1048 $this->message = $message; 1049 } 1050 return $this->message; 1051 } 1052 1053 } 1054 1055 /** 1056 * Variant of the Message class. 1057 * 1058 * Rather than treating the message key as a lookup 1059 * value (which is passed to the MessageCache and 1060 * translated as necessary), a RawMessage key is 1061 * treated as the actual message. 1062 * 1063 * All other functionality (parsing, escaping, etc.) 1064 * is preserved. 1065 * 1066 * @since 1.21 1067 */ 1068 class RawMessage extends Message { 1069 1070 /** 1071 * Call the parent constructor, then store the key as 1072 * the message. 1073 * 1074 * @see Message::__construct 1075 * 1076 * @param string $text Message to use. 1077 * @param array $params Parameters for the message. 1078 * 1079 * @throws InvalidArgumentException 1080 */ 1081 public function __construct( $text, $params = array() ) { 1082 if ( !is_string( $text ) ) { 1083 throw new InvalidArgumentException( '$text must be a string' ); 1084 } 1085 1086 parent::__construct( $text, $params ); 1087 1088 // The key is the message. 1089 $this->message = $text; 1090 } 1091 1092 /** 1093 * Fetch the message (in this case, the key). 1094 * 1095 * @return string 1096 */ 1097 public function fetchMessage() { 1098 // Just in case the message is unset somewhere. 1099 if ( $this->message === null ) { 1100 $this->message = $this->key; 1101 } 1102 1103 return $this->message; 1104 } 1105 1106 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 14:03:12 2014 | Cross-referenced by PHPXref 0.7.1 |