X-Git-Url: https://git.cyclocoop.org/%27.WWW_URL.%27admin/?a=blobdiff_plain;f=includes%2FMessage.php;h=7dd14e15c478d5fb4874dede119bcdcd4fbcf115;hb=195eafd6ef664c2f7a238eb553f5653fd04a246e;hp=b8d77a15cbd8da67b5fcaca938e1013788c31b62;hpb=77c882769c38d642fc10a84b4b639292005e7f5c;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/Message.php b/includes/Message.php index b8d77a15cb..7dd14e15c4 100644 --- a/includes/Message.php +++ b/includes/Message.php @@ -1,7 +1,5 @@ text() ); + * $button = Xml::button( wfMessage( 'submit' )->text() ); + * * Messages can have parameters: - * Message::key( 'welcome-to' )->params( $wgSitename )->text(); + * wfMessage( 'welcome-to' )->params( $wgSitename )->text(); * {{GRAMMAR}} and friends work correctly - * Message::key( 'are-friends' )->params( $user, $friend ); - * Message::key( 'bad-message' )->rawParams( '' )->escaped() + * wfMessage( 'are-friends', $user, $friend ); + * wfMessage( 'bad-message' )->rawParams( '' )->escaped(); + * * Sometimes the message text ends up in the database, so content language is needed. - * Message::key( 'file-log' )->params( $user, $filename )->inContentLanguage()->text() + * wfMessage( 'file-log', $user, $filename )->inContentLanguage()->text() + * * Checking if message exists: - * Message::key( 'mysterious-message' )->exists() + * wfMessage( 'mysterious-message' )->exists() + * * If you want to use a different language: - * Message::key( 'email-header' )->language( $user->getOption( 'language' ) )->plain() + * wfMessage( 'email-header' )->inLanguage( $user->getOption( 'language' ) )->plain() * Note that you cannot parse the text except in the content or interface * languages + * * * * Comparison with old wfMsg* functions: * * Use full parsing. * wfMsgExt( 'key', array( 'parseinline' ), 'apple' ); - * === Message::key( 'key' )->params( 'apple' )->parse(); + * === wfMessage( 'key', 'apple' )->parse(); + * * Parseinline is used because it is more useful when pre-building html. * In normal use it is better to use OutputPage::(add|wrap)WikiMsg. * * Places where html cannot be used. {{-transformation is done. * wfMsgExt( 'key', array( 'parsemag' ), 'apple', 'pear' ); - * === Message::key( 'key' )->params( 'apple', 'pear' )->text(); + * === wfMessage( 'key', 'apple', 'pear' )->text(); + * * * Shortcut for escaping the message too, similar to wfMsgHTML, but * parameters are not replaced after escaping by default. - * $escaped = Message::key( 'key' )->rawParams( 'apple' )->escaped(); + * $escaped = wfMessage( 'key' )->rawParams( 'apple' )->escaped(); + * * * TODO: - * * test, can we have tests? - * * sort out the details marked with fixme - * * should we have _m() or similar global wrapper? + * - test, can we have tests? + * - sort out the details marked with fixme * * @since 1.17 + * @author Niklas Laxström */ class Message { /** @@ -71,60 +77,88 @@ class Message { * List of parameters which will be substituted into the message. */ protected $parameters = array(); - + + /** + * Format for the message. + * Supported formats are: + * * text (transform) + * * escaped (transform+htmlspecialchars) + * * block-parse + * * parse (default) + * * plain + */ + protected $format = 'parse'; + + /** + * Whether database can be used. + */ + protected $useDatabase = true; + /** - * Some situations need exotic combinations of options to the - * underlying Language modules; which can be specified here. - * Dependencies: - * 'parse' implies 'transform', 'escape' + * Title object to use as context */ - protected $options = array( - # Don't wrap the output in a block-level element - 'inline' => true, - # Expand {{ constructs - 'transform' => true, - # Output will be safe HTML - 'escape' => true, - # Parse the text with the full parser - 'parse' => true, - # Access the database when getting the message text - 'usedb' => true, - ); + protected $title = null; /** * Constructor. - * @param $key String: message key + * @param $key: message key, or array of message keys to try and use the first non-empty message for + * @param $params Array message parameters * @return Message: $this */ - public function __construct( $key, $params=array(), $options=array() ) { + public function __construct( $key, $params = array() ) { + global $wgLang; $this->key = $key; - if( $params ){ - $this->params( $params ); - } - if( $options ){ - $this->options( $options ); - } + $this->parameters = array_values( $params ); + $this->language = $wgLang; } /** * Factory function that is just wrapper for the real constructor. It is * intented to be used instead of the real constructor, because it allows * chaining method calls, while new objects don't. - * //FIXME: key or get or something else? * @param $key String: message key + * @param Varargs: parameters as Strings + * @return Message: $this + */ + public static function newFromKey( $key /*...*/ ) { + $params = func_get_args(); + array_shift( $params ); + return new self( $key, $params ); + } + + /** + * Factory function accepting multiple message keys and returning a message instance + * for the first message which is non-empty. If all messages are empty then an + * instance of the first message key is returned. + * @param Varargs: message keys * @return Message: $this */ - public function key( $key ) { - return new Message( $key ); + public static function newFallbackSequence( /*...*/ ) { + $keys = func_get_args(); + if ( func_num_args() == 1 ) { + if ( is_array($keys[0]) ) { + // Allow an array to be passed as the first argument instead + $keys = array_values($keys[0]); + } else { + // Optimize a single string to not need special fallback handling + $keys = $keys[0]; + } + } + return new self( $keys ); } /** * Adds parameters to the parameter list of this message. - * @params Vargars: parameters as Strings + * @param Varargs: parameters as Strings * @return Message: $this */ public function params( /*...*/ ) { - $this->parameters += array_values( func_get_args() ); + $args = func_get_args(); + if ( isset( $args[0] ) && is_array( $args[0] ) ) { + $args = $args[0]; + } + $args_values = array_values( $args ); + $this->parameters = array_merge( $this->parameters, $args_values ); return $this; } @@ -133,47 +167,54 @@ class Message { * In other words the parsing process cannot access the contents * of this type of parameter, and you need to make sure it is * sanitized beforehand. The parser will see "$n", instead. - * @param $value Varargs: raw parameters as Strings + * @param Varargs: raw parameters as Strings * @return Message: $this */ public function rawParams( /*...*/ ) { $params = func_get_args(); - foreach( $params as $param ){ - $this->parameters[] = array( 'raw' => $param ); + if ( isset( $params[0] ) && is_array( $params[0] ) ) { + $params = $params[0]; + } + foreach( $params as $param ) { + $this->parameters[] = self::rawParam( $param ); } return $this; } /** - * Set some of the individual options, if you need to use some - * funky combination of them. - * @param $options Array $option => $value - * @return Message $this + * Add parameters that are numeric and will be passed through + * Language::formatNum before substitution + * @param Varargs: numeric parameters + * @return Message: $this */ - public function options( array $options ){ - foreach( $options as $key => $value ){ - if( in_array( $key, $this->options ) ){ - $this->options[$key] = (bool)$value; - } + public function numParams( /*...*/ ) { + $params = func_get_args(); + if ( isset( $params[0] ) && is_array( $params[0] ) ) { + $params = $params[0]; + } + foreach( $params as $param ) { + $this->parameters[] = self::numParam( $param ); } return $this; } - + /** * Request the message in any language that is supported. * As a side effect interface message status is unconditionally * turned off. - * @param $lang Mixed: langauge code or language object. + * @param $lang Mixed: language code or Language object. * @return Message: $this */ - public function language( $lang ) { + public function inLanguage( $lang ) { if( $lang instanceof Language ){ $this->language = $lang; } elseif ( is_string( $lang ) ) { - $this->language = Language::factory( $lang ); + if( $this->language->getCode() != $lang ) { + $this->language = Language::factory( $lang ); + } } else { $type = gettype( $lang ); - throw new MWException( "Message::langauge() must be " + throw new MWException( __METHOD__ . " must be " . "passed a String or Language object; $type given" ); } @@ -186,8 +227,30 @@ class Message { * @return Message: $this */ public function inContentLanguage() { + global $wgContLang; $this->interface = false; - $this->language = null; + $this->language = $wgContLang; + return $this; + } + + /** + * Enable or disable database use. + * @param $value Boolean + * @return Message: $this + */ + public function useDatabase( $value ) { + $this->useDatabase = (bool) $value; + return $this; + } + + /** + * Set the Title object to use as context when transforming the message + * + * @param $title Title object + * @return Message: $this + */ + public function title( $title ) { + $this->title = $title; return $this; } @@ -208,28 +271,20 @@ class Message { $string = $this->replaceParameters( $string, 'before' ); # Maybe transform using the full parser - if( $this->options['parse'] ){ + if( $this->format === 'parse' ) { $string = $this->parseText( $string ); - } else { - - # Transform {{ constructs - if( $this->options['transform'] ){ - $string = $this->transformText( $string ); - } - - # Sanitise - if( $this->options['escape'] ){ - # FIXME: Sanitizer method here? - $string = htmlspecialchars( $string ); - } - } - - # Strip the block element - if( !$this->options['inline'] ){ $m = array(); if( preg_match( '/^

(.*)\n?<\/p>\n?$/sU', $string, $m ) ) { $string = $m[1]; } + } elseif( $this->format === 'block-parse' ){ + $string = $this->parseText( $string ); + } elseif( $this->format === 'text' ){ + $string = $this->transformText( $string ); + } elseif( $this->format === 'escaped' ){ + # FIXME: Sanitizer method here? + $string = $this->transformText( $string ); + $string = htmlspecialchars( $string ); } # Raw parameter replacement @@ -238,17 +293,13 @@ class Message { return $string; } - public function __tostring(){ return $this->toString(); } - /** * Fully parse the text from wikitext to HTML * @return String parsed HTML */ - public function parse(){ - $this->options( array( - 'parse' => true, - )); - return $this->tostring(); + public function parse() { + $this->format = 'parse'; + return $this->toString(); } /** @@ -256,12 +307,8 @@ class Message { * @return String: Unescaped message text. */ public function text() { - $this->options( array( - 'parse' => false, - 'transform' => true, - 'escape' => false, - )); - return $this->tostring(); + $this->format = 'text'; + return $this->toString(); } /** @@ -269,13 +316,8 @@ class Message { * @return String: Unescaped untransformed message text. */ public function plain() { - $this->options( array( - 'parse' => false, - 'transform' => false, - 'escape' => false, - 'inline' => false, - )); - return $this->tostring(); + $this->format = 'plain'; + return $this->toString(); } /** @@ -283,26 +325,18 @@ class Message { * @return String: HTML */ public function parseAsBlock() { - $this->options( array( - 'parse' => true, - 'inline' => true, - )); - return $this->tostring(); + $this->format = 'block-parse'; + return $this->toString(); } /** * Returns the message text. {{-transformation is done and the result - * is excaped excluding any raw parameters. + * is escaped excluding any raw parameters. * @return String: Escaped message text. */ public function escaped() { - $this->options( array( - 'parse' => false, - 'transform' => true, - 'escape' => true, - 'inline' => false, - )); - return $this->tostring(); + $this->format = 'escaped'; + return $this->toString(); } /** @@ -310,12 +344,33 @@ class Message { * @return Bool: true if it is and false if not. */ public function exists() { - global $wgMessageCache; - return $wgMessageCache->get( - $this->key, - $this->options['usedb'], - $this->language - ) !== false; + return $this->fetchMessage() !== false; + } + + /** + * Check whether a message does not exist, or is an empty string + * @return Bool: true if is is and false if not + */ + public function isBlank() { + $message = $this->fetchMessage(); + return $message === false || $message === ''; + } + + /** + * Check whether a message does not exist, is an empty string, or is "-" + * @return Bool: true if is is and false if not + */ + public function isDisabled() { + $message = $this->fetchMessage(); + return $message === false || $message === '' || $message === '-'; + } + + public static function rawParam( $value ) { + return array( 'raw' => $value ); + } + + public static function numParam( $value ) { + return array( 'num' => $value ); } /** @@ -331,6 +386,9 @@ class Message { $replacementKeys['$' . ($n + 1)] = $param; } elseif ( $type === 'after' && isset( $param['raw'] ) ) { $replacementKeys['$' . ($n + 1)] = $param['raw']; + } elseif ( isset( $param['num'] ) ) { + $replacementKeys['$' . ($n + 1)] = + $this->language->formatNum( $param['num'] ); } } $message = strtr( $message, $replacementKeys ); @@ -344,11 +402,7 @@ class Message { */ protected function parseText( $string ) { global $wgOut; - if ( $this->language !== null ) { - # FIXME: remove this limitation - throw new MWException( 'Can only parse in interface or content language' ); - } - return $wgOut->parse( $string, /*linestart*/true, $this->interface ); + return $wgOut->parse( $string, /*linestart*/true, $this->interface, $this->language ); } /** @@ -357,20 +411,41 @@ class Message { * @return Wikitext with {{-constructs replaced with their values. */ protected function transformText( $string ) { - global $wgMessageCache; - return $wgMessageCache->transform( $string, $this->interface, $this->language ); + return MessageCache::singleton()->transform( $string, $this->interface, $this->language, $this->title ); } /** - * Wrapper for what ever method we use to get message contents - * @return Unmodified message contents + * Returns the textual value for the message. + * @return Message contents or placeholder */ protected function getMessageText() { - global $wgMessageCache; - $message = $wgMessageCache->get( $this->key, $this->options['usedb'], $this->language ); - return $message === false - ? '<' . htmlspecialchars( $this->key ) . '>' - : $message; + $message = $this->fetchMessage(); + if ( $message === false ) { + return '<' . htmlspecialchars( is_array($this->key) ? $this->key[0] : $this->key ) . '>'; + } else { + return $message; + } + } + + /** + * Wrapper for what ever method we use to get message contents + */ + protected function fetchMessage() { + if ( !isset( $this->message ) ) { + $cache = MessageCache::singleton(); + if ( is_array($this->key) ) { + foreach ( $this->key as $key ) { + $message = $cache->get( $key, $this->useDatabase, $this->language ); + if ( $message !== false && $message !== '' ) { + break; + } + } + $this->message = $message; + } else { + $this->message = $cache->get( $this->key, $this->useDatabase, $this->language ); + } + } + return $this->message; } -} \ No newline at end of file +}