jenkins-bot has submitted this change and it was merged.

Change subject: SMW\MessageFormatter class (deprecates smwfEncodeMessages())
......................................................................


SMW\MessageFormatter class (deprecates smwfEncodeMessages())

Code coverage: 100%
CRAP: 26

smwfEncodeMessages() deprecated in 1.9 with a removal in 1.11

## Narative

Invoke message objects instead of string/text representation during
processing and only transform messages before the actual output.

Instead of doing  wfMessage( '...' )->inContentLanguage()->text()
just invoked a Message( '...' ) object and let the MessageFormatter
resolve the text/html representation based on the language used for
the output.

It means a class only has to return a Message object without the need
to know the language.

Change-Id: Id252311eedc9855c961f5b1dfd02ade1ed8d3079
---
M includes/ParserData.php
M includes/RecurringEvents.php
M includes/Setup.php
A includes/formatters/MessageFormatter.php
M includes/parserhooks/AskParserFunction.php
M includes/parserhooks/ConceptParserFunction.php
M includes/parserhooks/RecurringEventsParserFunction.php
M includes/parserhooks/SetParserFunction.php
M includes/parserhooks/ShowParserFunction.php
M includes/parserhooks/SubobjectParserFunction.php
M tests/phpunit/SemanticMediaWikiTestCase.php
A tests/phpunit/includes/formatters/MessageFormatterTest.php
M tests/phpunit/includes/parserhooks/AskParserFunctionTest.php
M tests/phpunit/includes/parserhooks/ConceptParserFunctionTest.php
M tests/phpunit/includes/parserhooks/RecurringEventsParserFunctionTest.php
M tests/phpunit/includes/parserhooks/SetParserFunctionTest.php
M tests/phpunit/includes/parserhooks/ShowParserFunctionTest.php
M tests/phpunit/includes/parserhooks/SubobjectParserFunctionTest.php
18 files changed, 776 insertions(+), 134 deletions(-)

Approvals:
  Mwjames: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/includes/ParserData.php b/includes/ParserData.php
index d35d307..c914958 100644
--- a/includes/ParserData.php
+++ b/includes/ParserData.php
@@ -99,13 +99,13 @@
        public function updateStore();
 
        /**
-        * Returns an report about activities that occurred during processing
+        * Returns errors that occurred during processing
         *
         * @since 1.9
         *
         * @return string
         */
-       public function getReport();
+       public function getErrors();
 
 }
 
@@ -223,18 +223,7 @@
         * @return array
         */
        public function getErrors() {
-               return array_unique( $this->errors );
-       }
-
-       /**
-        * Returns boolean to indicate if an error appeared during processing
-        *
-        * @since 1.9
-        *
-        * @return boolean
-        */
-       public function hasError() {
-               return $this->errors !== array();
+               return $this->errors;
        }
 
        /**
@@ -246,17 +235,6 @@
         */
        public function addError( array $errors ) {
                return $this->errors = array_merge ( $errors, $this->errors );
-       }
-
-       /**
-        * Encode and report errors that appeared during processing
-        *
-        * @since  1.9
-        *
-        * @return string
-        */
-       public function getReport() {
-               return smwfEncodeMessages( $this->getErrors() );
        }
 
        /**
diff --git a/includes/RecurringEvents.php b/includes/RecurringEvents.php
index 2ad4c5f..cce01b3 100644
--- a/includes/RecurringEvents.php
+++ b/includes/RecurringEvents.php
@@ -2,6 +2,8 @@
 
 namespace SMW;
 
+use Message;
+
 use SMWDITime;
 use SMWTimeValue;
 
@@ -226,7 +228,7 @@
                }
 
                if ( $start_date === null ) {
-                       $this->setError( array( 'The start date is missing') );
+                       $this->errors[] = new Message( 
'smw-events-start-date-missing' );
                        return;
                } else if ( !( $start_date->getDataItem() instanceof SMWDITime 
) ) {
                        $this->setError( $start_date->getErrors() );
@@ -235,8 +237,7 @@
 
                // Check property
                if ( is_null( $this->property ) ) {
-                       $this->setError( array( 'The property is missing') );
-                       // $this->setError( $this->msg( 'smw-missing-property' 
)->inContentLanguage()->text() );
+                       $this->errors[] = new Message( 
'smw-events-property-missing' );
                        return;
                }
 
diff --git a/includes/Setup.php b/includes/Setup.php
index a761fc2..49ef38d 100644
--- a/includes/Setup.php
+++ b/includes/Setup.php
@@ -145,8 +145,10 @@
        $wgAutoloadClasses['SMW\Subobject']             = $incDir . 
'Subobject.php';
        $wgAutoloadClasses['SMW\RecurringEvents']       = $incDir . 
'RecurringEvents.php';
 
+       // Formatters
        $wgAutoloadClasses['SMW\ArrayFormatter']           = $incDir . 
'formatters/ArrayFormatter.php';
        $wgAutoloadClasses['SMW\ParserParameterFormatter'] = $incDir . 
'formatters/ParserParameterFormatter.php';
+       $wgAutoloadClasses['SMW\MessageFormatter']         = $incDir . 
'formatters/MessageFormatter.php';
 
        $wgAutoloadClasses['SMW\Settings']               = $incDir . 
'Settings.php';
 
diff --git a/includes/formatters/MessageFormatter.php 
b/includes/formatters/MessageFormatter.php
new file mode 100644
index 0000000..6ae41ff
--- /dev/null
+++ b/includes/formatters/MessageFormatter.php
@@ -0,0 +1,302 @@
+<?php
+
+namespace SMW;
+
+use Html;
+use Message;
+use Language;
+
+/**
+ * Class implementing message output formatting
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @since 1.9
+ *
+ * @file
+ * @ingroup Formatter
+ *
+ * @licence GNU GPL v2+
+ * @author mwjames
+ */
+
+/**
+ * This class is implementing message output formatting to avoid having
+ * classes to invoke a language object that is not a direct dependency (which
+ * means that context relevant information is mostly missing from the invoking
+ * class) therefore it is more appropriate to collect Message objects from the
+ * source and initiate an output formatting only when necessary and requested.
+ *
+ * @ingroup Formatter
+ */
+class MessageFormatter {
+
+       /** @var array */
+       protected $messages = array();
+
+       /** @var string */
+       protected $type = 'warning';
+
+       /** @var string */
+       protected $separator = ' <!--br-->';
+
+       /** @var boolean */
+       protected $escape = true;
+
+       /**
+        * @since 1.9
+        *
+        * @param Language $language
+        */
+       public function __construct( Language $language ) {
+               $this->language = $language;
+       }
+
+       /**
+        * Convenience factory method to invoke a message array together with
+        * a language object
+        *
+        * @par Example:
+        * @code
+        *  MessageFormatter::newFromArray( $language, array( 'Foo' ) 
)->getHtml();
+        * @endcode
+        *
+        * @since 1.9
+        *
+        * @param Language $language
+        * @param array|null $messages
+        *
+        * @return MessageFormatter
+        */
+       public static function newFromArray( Language $language, array 
$messages = array () ) {
+               $instance = new self( $language );
+               return $instance->addFromArray( $messages );
+       }
+
+       /**
+        * Creates a Message object from a key and adds it to an internal array
+        *
+        * @since 1.9
+        *
+        * @param string $key message key
+        *
+        * @return MessageFormatter
+        */
+       public function addFromKey( $key /*...*/ ) {
+               $params = func_get_args();
+               array_shift( $params );
+               $this->addFromArray( array( new Message( $key, $params ) ) );
+               return $this;
+       }
+
+       /**
+        * Adds an arbitrary array of messages which can either contain text
+        * or/and Message objects
+        *
+        * @par Example:
+        * @code
+        *  $msgFormatter = new MessageFormatter( $language );
+        *  $msgFormatter->addFromArray( array( 'Foo', new Message( 'Bar' ) ) 
)->getHtml()
+        * @endcode
+        *
+        * @since 1.9
+        *
+        * @param array $messages
+        *
+        * @return MessageFormatter
+        */
+       public function addFromArray( array $messages ) {
+               $this->messages = array_merge ( $messages, $this->messages );
+               return $this;
+       }
+
+       /**
+        * Returns unformatted invoked messages
+        *
+        * @since 1.9
+        *
+        * @return array
+        */
+       public function getMessages() {
+               return $this->messages;
+       }
+
+       /**
+        * Used in connection with the html output to invoke a specific display
+        * type
+        *
+        * @see Highlighter::getTypeId
+        *
+        * @since 1.9
+        *
+        * @return MessageFormatter
+        */
+       public function setType( $type ) {
+               $this->type = $type;
+               return $this;
+       }
+
+       /**
+        * Enables/disables escaping for the output representation
+        *
+        * @note Escaping is generally enabled but in cases of special pages or
+        * with messages already being escaped this option can be circumvent by
+        * invoking escape( false )
+        *
+        * @since 1.9
+        *
+        * @param boolean $escape
+        *
+        * @return MessageFormatter
+        */
+       public function escape( $escape ) {
+               $this->escape = (bool)$escape;
+               return $this;
+       }
+
+       /**
+        * Clears the internal message array
+        *
+        * @since 1.9
+        *
+        * @return MessageFormatter
+        */
+       public function clear() {
+               $this->messages = array();
+               return $this;
+       }
+
+       /**
+        * Returns if the internal message array does contain messages
+        *
+        * @since 1.9
+        *
+        * @return boolean
+        */
+       public function exists() {
+               return $this->messages !== array();
+       }
+
+       /**
+        * Overrides invoked language object
+        *
+        * @since 1.9
+        *
+        * @param Language $language
+        *
+        * @return MessageFormatter
+        */
+       public function setLanguage( Language $language ) {
+               $this->language = $language;
+               return $this;
+       }
+
+       /**
+        * Formatting and normalization of an array
+        *
+        * @note The array is being recursively resolved in order to ensure that
+        * the returning representation is a 1-n array where duplicate entries
+        * have been eliminated already while Message objects being transformed
+        * into a simple text representation using the invoked language
+        *
+        * @since 1.9
+        *
+        * @param array $messages
+        *
+        * @return array
+        */
+       protected function doFormat( array $messages ) {
+               $newArray = array();
+
+               foreach ( $messages as $msg ) {
+
+                       if ( $msg instanceof Message ) {
+                               $newArray[] = $msg->inLanguage( $this->language 
)->text();
+                       } else if ( is_array( $msg ) ) {
+                               foreach ( $this->doFormat( $msg ) as $m ) {
+                                       $newArray[] = $m;
+                               }
+                       } else if ( is_string( $msg ) ) {
+                               $newArray[] = $msg;
+                       }
+               }
+
+               return array_unique( $newArray );
+       }
+
+       /**
+        * Converts the message array into a string representation
+        *
+        * @since 1.9
+        *
+        * @param boolean $escape
+        * @param boolean $html
+        *
+        * @return string
+        */
+       protected function getString( $html = true ) {
+
+               if ( $this->escape ) {
+                       $messages = array_map( 'htmlspecialchars', 
$this->doFormat( $this->messages ) );
+               } else {
+                       $messages = $this->doFormat( $this->messages );
+               }
+
+               if ( count( $messages ) == 1 ) {
+                       $messageString = $messages[0];
+               } else {
+                       foreach ( $messages as &$message ) {
+                               $message = $html ? Html::rawElement( 'li' , 
array(), $message ) : $message ;
+                       }
+
+                       $messageString = implode( $this->separator, $messages );
+                       $messageString = $html ? Html::rawElement( 'ul' , 
array(), $messageString ) : $messageString;
+               }
+
+               return $messageString;
+       }
+
+       /**
+        * Returns html representation of the formatted messages
+        *
+        * @since 1.9
+        *
+        * @return string
+        */
+       public function getHtml() {
+
+               if ( $this->exists() ) {
+
+                       $highlighter = Highlighter::factory( $this->type );
+                       $highlighter->setContent( array( 'content' => 
$this->getString( true ) ) );
+
+                       return $highlighter->getHtml();
+               }
+
+               return '';
+       }
+
+       /**
+        * Returns plain text representation of the formatted messages
+        *
+        * @since 1.9
+        *
+        * @return string
+        */
+       public function getPlain() {
+               return $this->exists() ? $this->getString( false ) : '';
+       }
+}
diff --git a/includes/parserhooks/AskParserFunction.php 
b/includes/parserhooks/AskParserFunction.php
index 346edcb..a2104f3 100644
--- a/includes/parserhooks/AskParserFunction.php
+++ b/includes/parserhooks/AskParserFunction.php
@@ -45,22 +45,16 @@
  */
 class AskParserFunction {
 
-       /**
-        * Represents IParserData object
-        * @var QueryData
-        */
+       /** @var IParserData */
        protected $parserData;
 
-       /**
-        * Represents QueryData object
-        * @var IParserData
-        */
+       /** @var QueryData */
        protected $queryData;
 
-       /**
-        * SMWQueryProcessor showMode indicator
-        * @var boolean
-        */
+       /** @var MessageFormatter */
+       protected $msgFormatter;
+
+       /** @var boolean */
        protected $showMode = false;
 
        /**
@@ -68,15 +62,30 @@
         *
         * @param IParserData $parserData
         * @param QueryData $queryData
+        * @param MessageFormatter $msgFormatter
         */
-       public function __construct( IParserData $parserData, QueryData 
$queryData ) {
+       public function __construct( IParserData $parserData, QueryData 
$queryData, MessageFormatter $msgFormatter ) {
                $this->parserData = $parserData;
                $this->queryData = $queryData;
+               $this->msgFormatter = $msgFormatter;
+       }
+
+       /**
+        * {{#ask}} is disabled (see $smwgQEnabled)
+        *
+        * @since 1.9
+        *
+        * @return string|null
+        */
+       protected function disabled() {
+               return $this->msgFormatter->addFromKey( 'smw_iq_disabled' 
)->getHtml();
        }
 
        /**
         * After some discussion IQueryProcessor/QueryProcessor is not being
         * used in 1.9 and instead rely on SMWQueryProcessor
+        *
+        * @todo Static class SMWQueryProcessor, please fixme
         */
        private function initQueryProcessor( array $rawParams ) {
                list( $this->query, $this->params ) = 
SMWQueryProcessor::getQueryAndParamsFromFunctionParams(
@@ -92,21 +101,6 @@
                        SMW_OUTPUT_WIKI,
                        SMWQueryProcessor::INLINE_QUERY
                );
-       }
-
-       /**
-        * Returns a message about inline queries being disabled
-        *
-        * @see $smwgQEnabled
-        *
-        * FIXME Replace with IMessageFormatter -> ErrorMessageFormatter class
-        *
-        * @since 1.9
-        *
-        * @return string
-        */
-       protected function disabled() {
-               return smwfEncodeMessages( array( wfMessage( 'smw_iq_disabled' 
)->inContentLanguage()->text() ) );
        }
 
        /**
@@ -126,6 +120,11 @@
         * ParserOutput with meta data from the query
         *
         * FIXME $rawParams use IParameterFormatter -> QueryParameterFormatter 
class
+        * Parse parameters and return query results to the ParserOutput
+        * object and output result data from the SMWQueryProcessor
+        *
+        * @todo $rawParams should be of IParameterFormatter
+        * QueryParameterFormatter class
         *
         * @since 1.9
         *
@@ -134,9 +133,8 @@
         * @return string|null
         */
        public function parse( array $rawParams ) {
-               global $smwgIQRunningNumber;
-
                // Counter for what? Where and for what is it used?
+               global $smwgIQRunningNumber;
                $smwgIQRunningNumber++;
 
                // Remove parser object from parameters array
@@ -179,7 +177,8 @@
        public static function render( Parser &$parser ) {
                $ask = new self(
                        new ParserData( $parser->getTitle(), 
$parser->getOutput() ),
-                       new QueryData( $parser->getTitle() )
+                       new QueryData( $parser->getTitle() ),
+                       new MessageFormatter( $parser->getTargetLanguage() )
                );
                return $GLOBALS['smwgQEnabled'] ? $ask->parse( func_get_args() 
) : $ask->disabled();
        }
diff --git a/includes/parserhooks/ConceptParserFunction.php 
b/includes/parserhooks/ConceptParserFunction.php
index 4f822c6..5c2820d 100644
--- a/includes/parserhooks/ConceptParserFunction.php
+++ b/includes/parserhooks/ConceptParserFunction.php
@@ -48,19 +48,21 @@
  */
 class ConceptParserFunction {
 
-       /**
-        * Represents IParserData object
-        * @var IParserData
-        */
+       /** @var IParserData */
        protected $parserData;
+
+       /** @var MessageFormatter */
+       protected $msgFormatter;
 
        /**
         * @since 1.9
         *
         * @param IParserData $parserData
+        * @param MessageFormatter $msgFormatter
         */
-       public function __construct( IParserData $parserData ) {
+       public function __construct( IParserData $parserData, MessageFormatter 
$msgFormatter ) {
                $this->parserData = $parserData;
+               $this->msgFormatter = $msgFormatter;
        }
 
        /**
@@ -105,6 +107,8 @@
        /**
         * After some discussion IQueryProcessor/QueryProcessor is not being
         * used in 1.9 and instead rely on SMWQueryProcessor
+        *
+        * @todo Static class SMWQueryProcessor, please fixme
         */
        private function initQueryProcessor( array $rawParams, $showMode = 
false ) {
                list( $this->query, $this->params ) = 
SMWQueryProcessor::getQueryAndParamsFromFunctionParams(
@@ -139,9 +143,9 @@
                $property = new SMWDIProperty( '_CONC' );
 
                if ( !( $title->getNamespace() === SMW_NS_CONCEPT ) ) {
-                       return smwfEncodeMessages( array( wfMessage( 
'smw_no_concept_namespace' )->inContentLanguage()->text() ) );
+                       return $this->msgFormatter->addFromKey( 
'smw_no_concept_namespace' )->getHtml();
                } elseif ( count( 
$this->parserData->getData()->getPropertyValues( $property ) ) > 0 ) {
-                       return smwfEncodeMessages( array( wfMessage( 
'smw_multiple_concepts' )->inContentLanguage()->text() ) );
+                       return $this->msgFormatter->addFromKey( 
'smw_multiple_concepts' )->getHtml();
                }
 
                // Remove parser object from parameters array
@@ -172,13 +176,13 @@
                        )
                );
 
-               // Handling errors from the query
-               $this->parserData->addError( $this->query->getErrors() );
+               // Collect possible errors
+               $this->msgFormatter->addFromArray( $this->query->getErrors() 
)->addFromArray( $this->parserData->getErrors() );
 
                // Update ParserOutput
                $this->parserData->updateOutput();
 
-               return $this->parserData->hasError() ? 
$this->parserData->getReport() : $this->getHtml( $title, $conceptQueryString, 
$conceptDocu );
+               return $this->msgFormatter->exists() ? 
$this->msgFormatter->getHtml() : $this->getHtml( $title, $conceptQueryString, 
$conceptDocu );
        }
 
        /**
@@ -191,10 +195,10 @@
         * @return string
         */
        public static function render( Parser &$parser ) {
-               $instance = new self( new ParserData(
-                       $parser->getTitle(),
-                       $parser->getOutput() )
+               $concept = new self(
+                       new ParserData( $parser->getTitle(), 
$parser->getOutput() ),
+                       new MessageFormatter( $parser->getTargetLanguage() )
                );
-               return $instance->parse( func_get_args() );
+               return $concept->parse( func_get_args() );
        }
 }
diff --git a/includes/parserhooks/RecurringEventsParserFunction.php 
b/includes/parserhooks/RecurringEventsParserFunction.php
index f3ee241..9a868d1 100644
--- a/includes/parserhooks/RecurringEventsParserFunction.php
+++ b/includes/parserhooks/RecurringEventsParserFunction.php
@@ -74,7 +74,7 @@
 
                // Get recurring events
                $events = new RecurringEvents( $parameters->toArray(), 
$this->getSettings() );
-               $this->parserData->addError( $events->getErrors() );
+               $this->msgFormatter->addFromArray( $events->getErrors() );
 
                foreach ( $events->getDates() as $date_str ) {
 
@@ -110,13 +110,13 @@
                        );
 
                        // Collect errors that occurred during processing
-                       $this->parserData->addError( 
$this->subobject->getErrors() );
+                       $this->msgFormatter->addFromArray( 
$this->subobject->getErrors() );
                }
 
                // Update ParserOutput
                $this->parserData->updateOutput();
 
-               return $this->parserData->getReport();
+               return $this->msgFormatter->getHtml();
        }
 
        /**
@@ -129,7 +129,8 @@
        public static function render( Parser &$parser ) {
                $instance = new self(
                        new ParserData( $parser->getTitle(), 
$parser->getOutput() ),
-                       new Subobject( $parser->getTitle() )
+                       new Subobject( $parser->getTitle() ),
+                       new MessageFormatter( $parser->getTargetLanguage() )
                );
                return $instance->parse( new ParserParameterFormatter( 
func_get_args() ) );
        }
diff --git a/includes/parserhooks/SetParserFunction.php 
b/includes/parserhooks/SetParserFunction.php
index 7ee8441..41ea33f 100644
--- a/includes/parserhooks/SetParserFunction.php
+++ b/includes/parserhooks/SetParserFunction.php
@@ -45,19 +45,21 @@
  */
 class SetParserFunction {
 
-       /**
-        * Represents IParserData object
-        * @var IParserData
-        */
+       /** @var IParserDate */
        protected $parserData;
+
+       /** @var MessageFormatter */
+       protected $msgFormatter;
 
        /**
         * @since 1.9
         *
         * @param IParserData $parserData
+        * @param MessageFormatter $msgFormatter
         */
-       public function __construct( IParserData $parserData ) {
+       public function __construct( IParserData $parserData, MessageFormatter 
$msgFormatter ) {
                $this->parserData = $parserData;
+               $this->msgFormatter = $msgFormatter;
        }
 
        /**
@@ -86,7 +88,7 @@
                // Update ParserOutput
                $this->parserData->updateOutput();
 
-               return $this->parserData->getReport();
+               return $this->msgFormatter->addFromArray( 
$this->parserData->getErrors() )->getHtml();
        }
 
        /**
@@ -97,7 +99,10 @@
         * @return string|null
         */
        public static function render( Parser &$parser ) {
-               $set = new self( new ParserData( $parser->getTitle(), 
$parser->getOutput() ) );
+               $set = new self(
+                       new ParserData( $parser->getTitle(), 
$parser->getOutput() ),
+                       new MessageFormatter( $parser->getTargetLanguage() )
+               );
                return $set->parse( new ParserParameterFormatter( 
func_get_args() ) );
        }
 }
diff --git a/includes/parserhooks/ShowParserFunction.php 
b/includes/parserhooks/ShowParserFunction.php
index 291494e..c354a33 100644
--- a/includes/parserhooks/ShowParserFunction.php
+++ b/includes/parserhooks/ShowParserFunction.php
@@ -42,40 +42,38 @@
  */
 class ShowParserFunction {
 
-       /**
-        * Represents a IParserData object
-        * @var IParserData
-        */
+       /** @var IParserData */
        protected $parserData;
 
-       /**
-        * Represents a QueryData object
-        * @var QueryData
-        */
+       /** @var QueryData */
        protected $queryData;
+
+       /** @var MessageFormatter */
+       protected $msgFormatter;
 
        /**
         * @since 1.9
         *
         * @param IParserData $parserData
         * @param QueryData $queryData
+        * @param MessageFormatter $messageList
         */
-       public function __construct( IParserData $parserData, QueryData 
$queryData ) {
+       public function __construct( IParserData $parserData, QueryData 
$queryData, MessageFormatter $msgFormatter ) {
                $this->parserData = $parserData;
                $this->queryData = $queryData;
+               $this->msgFormatter = $msgFormatter;
        }
 
        /**
         * Returns a message about inline queries being disabled
-        *
         * @see $smwgQEnabled
         *
         * @since 1.9
         *
-        * @return string
+        * @return string|null
         */
        protected function disabled() {
-               return smwfEncodeMessages( array( wfMessage( 'smw_iq_disabled' 
)->inContentLanguage()->text() ) );
+               return $this->msgFormatter->addFromKey( 'smw_iq_disabled' 
)->getHtml();
        }
 
        /**
@@ -93,7 +91,7 @@
         * @return string|null
         */
        public function parse( array $rawParams ) {
-               $ask = new AskParserFunction( $this->parserData, 
$this->queryData );
+               $ask = new AskParserFunction( $this->parserData, 
$this->queryData, $this->msgFormatter );
                return $ask->useShowMode()->parse( $rawParams );
        }
 
@@ -109,7 +107,8 @@
        public static function render( Parser &$parser ) {
                $show = new self(
                        new ParserData( $parser->getTitle(), 
$parser->getOutput() ),
-                       new QueryData( $parser->getTitle() )
+                       new QueryData( $parser->getTitle() ),
+                       new MessageFormatter( $parser->getTargetLanguage() )
                );
                return $GLOBALS['smwgQEnabled'] ? $show->parse( func_get_args() 
) : $show->disabled();
        }
diff --git a/includes/parserhooks/SubobjectParserFunction.php 
b/includes/parserhooks/SubobjectParserFunction.php
index eb544c3..47d23a7 100644
--- a/includes/parserhooks/SubobjectParserFunction.php
+++ b/includes/parserhooks/SubobjectParserFunction.php
@@ -40,27 +40,26 @@
  */
 class SubobjectParserFunction {
 
-       /**
-        * Represents a IParserData object
-        * @var IParserData
-        */
+       /** @var IParserData */
        protected $parserData;
 
-       /**
-        * Represents a Subobject object
-        * @var Subobject
-        */
+       /** @var Subobject */
        protected $subobject;
+
+       /** @var MessageFormatter */
+       protected $msgFormatter;
 
        /**
         * @since 1.9
         *
         * @param IParserData $parserData
         * @param Subobject $subobject
+        * @param MessageFormatter $msgFormatter
         */
-       public function __construct( IParserData $parserData, Subobject 
$subobject ) {
+       public function __construct( IParserData $parserData, Subobject 
$subobject, MessageFormatter $msgFormatter ) {
                $this->parserData = $parserData;
                $this->subobject = $subobject;
+               $this->msgFormatter = $msgFormatter;
        }
 
        /**
@@ -130,12 +129,12 @@
                        $this->subobject->getContainer()
                );
 
-               $this->parserData->addError( $this->subobject->getErrors() );
-
                // Update ParserOutput
                $this->parserData->updateOutput();
 
-               return $this->parserData->getReport();
+               return $this->msgFormatter->addFromArray( 
$this->subobject->getErrors() )
+                       ->addFromArray( $this->parserData->getErrors() )
+                       ->getHtml();
        }
 
        /**
@@ -148,7 +147,8 @@
        public static function render( Parser &$parser ) {
                $instance = new self(
                        new ParserData( $parser->getTitle(), 
$parser->getOutput() ),
-                       new Subobject( $parser->getTitle() )
+                       new Subobject( $parser->getTitle() ),
+                       new MessageFormatter( $parser->getTargetLanguage() )
                );
                return $instance->parse( new ParserParameterFormatter( 
func_get_args() ) );
        }
diff --git a/tests/phpunit/SemanticMediaWikiTestCase.php 
b/tests/phpunit/SemanticMediaWikiTestCase.php
index 90428cc..c4be5e5 100644
--- a/tests/phpunit/SemanticMediaWikiTestCase.php
+++ b/tests/phpunit/SemanticMediaWikiTestCase.php
@@ -6,6 +6,7 @@
 use SMW\Settings;
 
 use Title;
+use Language;
 
 use SMWDIWikiPage;
 use SMWSemanticData;
@@ -83,6 +84,17 @@
        }
 
        /**
+        * Helper method that returns a Language object
+        *
+        * @since 1.9
+        *
+        * @return Language
+        */
+       protected function getLanguage( $langCode = 'en' ) {
+               return Language::factory( $langCode );
+       }
+
+       /**
         * Helper method that returns a randomized SMWDIWikiPage object
         *
         * @since 1.9
diff --git a/tests/phpunit/includes/formatters/MessageFormatterTest.php 
b/tests/phpunit/includes/formatters/MessageFormatterTest.php
new file mode 100644
index 0000000..2275e77
--- /dev/null
+++ b/tests/phpunit/includes/formatters/MessageFormatterTest.php
@@ -0,0 +1,300 @@
+<?php
+
+namespace SMW\Test;
+
+use SMW\MessageFormatter;
+use Message;
+use ReflectionClass;
+
+/**
+ * Tests for the MessageFormatter class
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @since 1.9
+ *
+ * @file
+ * @ingroup Test
+ *
+ * @licence GNU GPL v2+
+ * @author mwjames
+ */
+
+/**
+ * Tests for the MessageFormatter class
+ * @covers \SMW\MessageFormatter
+ *
+ * @ingroup Test
+ *
+ * @group SMW
+ * @group SMWExtension
+ */
+class MessageFormatterTest extends SemanticMediaWikiTestCase {
+
+       /**
+        * Returns the name of the class to be tested
+        *
+        * @return string
+        */
+       public function getClass() {
+               return '\SMW\MessageFormatter';
+       }
+
+       /**
+        * Helper method that returns an MessageFormatter instance
+        *
+        * @since 1.9
+        *
+        * @return MessageFormatter
+        */
+       private function getInstance() {
+               return new MessageFormatter( $this->getLanguage() );
+       }
+
+       /**
+        * @test MessageFormatter::__construct
+        * @dataProvider getDataProvider
+        *
+        * @since 1.9
+        */
+       public function testConstructor() {
+               $instance = $this->getInstance();
+               $this->assertInstanceOf( $this->getClass(), $instance );
+       }
+
+       /**
+        * @test MessageFormatter::newFromArray
+        * @test MessageFormatter::setType
+        * @test MessageFormatter::getHtml
+        * @dataProvider getDataProvider
+        *
+        * @since  1.9
+        *
+        * @param array $messages
+        */
+       public function testNewFromArray( array $messages ) {
+               $instance = MessageFormatter::newFromArray(
+                       $this->getLanguage(),
+                       $messages
+               );
+
+               $instance->setType( 'error' );
+               $this->assertInternalType( 'string', $instance->getHtml() );
+
+               $instance->setType( 'warning' );
+               $this->assertInternalType( 'string', $instance->getHtml() );
+
+               $instance->setType( 'info' );
+               $this->assertInternalType( 'string', $instance->getHtml() );
+
+       }
+
+       /**
+        * @test MessageFormatter::addFromKey
+        * @test MessageFormatter::getMessages
+        *
+        * @since 1.9
+        */
+       public function testAddFromKey() {
+               $instance = $this->getInstance();
+               $param = '1001';
+
+               $instance->addFromKey( 'Foo', $param )
+                       ->addFromKey( 'Bar', $param )
+                       ->addFromKey( 'Foo', $param );
+
+               $messages = $instance->getMessages();
+
+               // Returns count of existing with duplicates, elimination is
+               // applied only during output (getHtml/getPlain)
+               $this->assertCount( 3, $messages );
+
+               foreach ( $messages as $msg ) {
+                       $this->assertInstanceOf( '\Message', $msg );
+
+                       // getParams() only got added in MW 1.21
+                       if ( method_exists( $msg, 'getParams' ) ) {
+                               foreach ( $msg->getParams() as $result ) {
+                                       $this->assertEquals( $param, $result );
+                               }
+                       }
+               }
+       }
+
+       /**
+        * @test MessageFormatter::setLanguage
+        * @test MessageFormatter::getPlain
+        *
+        * @since 1.9
+        */
+       public function testSetLanguage() {
+               $key = 'properties';
+               $msg = new Message( $key );
+               $instance = $this->getInstance();
+
+               $instance->addFromKey( $key );
+               $instance->setLanguage( $this->getLanguage( 'zh-tw' ) );
+
+               $this->assertEquals(
+                       $msg->inLanguage( $this->getLanguage( 'zh-tw' ) 
)->text(),
+                       $instance->getPlain()
+               );
+
+               $instance->clear();
+               $this->assertEmpty( $instance->getPlain() );
+
+       }
+
+       /**
+        * @test MessageFormatter::format
+        * @dataProvider getDataProvider
+        *
+        * @since  1.9
+        *
+        * @param array $messages
+        * @param integer $count
+        */
+       public function testFormat( array $messages, $count ) {
+               $instance = $this->getInstance();
+               $instance->addFromArray( $messages );
+
+               // Access protected method
+               $reflection = new ReflectionClass( $this->getClass() );
+               $method = $reflection->getMethod( 'doFormat' );
+               $method->setAccessible( true );
+
+               // Test array normalization and deletion of duplicates
+               $result = $method->invoke( $instance, $instance->getMessages() 
);
+               $this->assertCount( $count, $result );
+
+       }
+
+       /**
+        * @test MessageFormatter::getHtml
+        * @dataProvider getDataProvider
+        *
+        * @since  1.9
+        *
+        * @param array $messages
+        */
+       public function testGetHtml( array $messages ) {
+               $instance = $this->getInstance();
+               $instance->addFromArray( $messages );
+
+               $this->assertInternalType( 'string', $instance->getHtml() );
+       }
+
+       /**
+        * @test MessageFormatter::getPlain
+        * @dataProvider getDataProvider
+        *
+        * @since  1.9
+        *
+        * @param array $messages
+        */
+       public function testGetPlain( array $messages ) {
+               $instance = $this->getInstance();
+               $instance->addFromArray( $messages );
+
+               $this->assertInternalType( 'string', $instance->getPlain() );
+       }
+
+       /**
+        * @test MessageFormatter::escape
+        * @test MessageFormatter::getPlain
+        *
+        * @since  1.9
+        */
+       public function testEscapedUnescaped() {
+               $instance = $this->getInstance();
+               $instance->addFromArray( array(  '<Foo>' ) );
+
+               $this->assertEquals( '&lt;Foo&gt;', $instance->escape( true 
)->getPlain() );
+               $this->assertEquals( '<Foo>', $instance->escape( false 
)->getPlain() );
+
+       }
+
+       /**
+        * Message from different sources could have different depth therefore
+        * objects need to be resolved recursively in order to ensure a 1-n 
array
+        *
+        */
+       public function getDataProvider() {
+               return array(
+
+                       // #0 Empty array
+                       array( array(), 0 ),
+
+                       // #1 Simple string elements 5 elements (one duplicate) 
= 4
+                       array(
+                               array(
+                                       'Foo', 'Bar', array( 'FooBar', array( 
'barFoo', 'Foo' ) )
+                               ),
+                               4
+                       ),
+
+                       // #2 A duplicate Message object = 1
+                       array(
+                               array(
+                                       new Message( 'smw_iq_disabled' ),
+                                       new Message( 'smw_iq_disabled' )
+                               ),
+                               1
+                       ),
+
+                       // #3 Different Message objects
+                       array(
+                               array(
+                                       new Message( 'smw_iq_disabled' ),
+                                       new Message( 'smw_multiple_concepts' )
+                               ),
+                               2
+                       ),
+
+                       // #4 Invoked MessageFormatter object (recursive test)
+                       array(
+                               array(
+                                       new Message( 'smw_iq_disabled' ),
+                                       array( new Message( 'smw_iq_disabled' ),
+                                                       new Message( 
'smw_multiple_concepts' )
+                                       )
+                               ),
+                               2
+                       ),
+
+                       // #5 Combine different objects (recursive test) 
containing 7 messages
+                       // where two of them are duplicates resulting in 5 
objects
+                       array(
+                               array(
+                                       new Message( 'smw_iq_disabled' ),
+                                       new Message( 'smw_multiple_concepts' ),
+                                       array(
+                                               new Message( 'smw_iq_disabled' 
),
+                                               'Foo'
+                                       ),
+                                       array(
+                                               array(
+                                                       new Message( 
'smw_no_concept_namespace' ),
+                                                       new Message( 'foo' ),
+                                                       'Foo'
+                                               )
+                                       )
+                               ),
+                               5
+                       ),
+               );
+       }
+}
diff --git a/tests/phpunit/includes/parserhooks/AskParserFunctionTest.php 
b/tests/phpunit/includes/parserhooks/AskParserFunctionTest.php
index b87c408..adf35df 100644
--- a/tests/phpunit/includes/parserhooks/AskParserFunctionTest.php
+++ b/tests/phpunit/includes/parserhooks/AskParserFunctionTest.php
@@ -3,6 +3,9 @@
 namespace SMW\Test;
 
 use SMW\AskParserFunction;
+
+use SMW\MessageFormatter;
+use SMW\ParserData;
 use SMW\QueryData;
 
 use Title;
@@ -181,7 +184,8 @@
        private function getInstance( Title $title, ParserOutput $parserOutput 
= null ) {
                return new AskParserFunction(
                        $this->getParserData( $title, $parserOutput ),
-                       new QueryData( $title )
+                       new QueryData( $title ),
+                       new MessageFormatter( $title->getPageLanguage() )
                );
        }
 
@@ -226,8 +230,11 @@
         * @since 1.9
         */
        public function testParseDisabledsmwgQEnabled() {
-               $expected = smwfEncodeMessages( array( wfMessage( 
'smw_iq_disabled' )->inContentLanguage()->text() ) );
-               $instance = $this->getInstance( $this->getTitle(), 
$this->getParserOutput() );
+               $title = $this->getTitle();
+               $message = new MessageFormatter( $title->getPageLanguage() );
+               $expected = $message->addFromKey( 'smw_iq_disabled' 
)->getHtml();
+
+               $instance = $this->getInstance( $title , 
$this->getParserOutput() );
 
                // Make protected method accessible
                $reflection = new ReflectionClass( $this->getClass() );
@@ -253,7 +260,7 @@
 
                // Initialize and parse
                $instance = $this->getInstance( $title, $parserOutput );
-               $instance->parse( $params, true );
+               $instance->parse( $params );
 
                // Get semantic data from the ParserOutput
                $parserData = $this->getParserData( $title, $parserOutput );
diff --git a/tests/phpunit/includes/parserhooks/ConceptParserFunctionTest.php 
b/tests/phpunit/includes/parserhooks/ConceptParserFunctionTest.php
index 9246fa4..89720dc 100644
--- a/tests/phpunit/includes/parserhooks/ConceptParserFunctionTest.php
+++ b/tests/phpunit/includes/parserhooks/ConceptParserFunctionTest.php
@@ -3,6 +3,7 @@
 namespace SMW\Test;
 
 use SMW\ConceptParserFunction;
+use SMW\MessageFormatter;
 use SMW\ParserData;
 
 use Title;
@@ -115,18 +116,25 @@
        }
 
        /**
-        * Helper method that returns a ConceptParserFunction object
-        *
-        * @since 1.9
-        *
-        * @param Title $title
-        * @param ParserOutput $parserOutput
+        * Helper method that returns a instance
         *
         * @return ConceptParserFunction
         */
        private function getInstance( Title $title, ParserOutput $parserOutput 
= null ) {
                return new ConceptParserFunction(
-                       $this->getParserData( $title, $parserOutput ) );
+                       $this->getParserData( $title, $parserOutput ),
+                       new MessageFormatter( $title->getPageLanguage() )
+               );
+       }
+
+       /**
+        * Helper method that returns a text
+        *
+        * @return string
+        */
+       private function getMessageText( Title $title, $error ) {
+               $message = new MessageFormatter( $title->getPageLanguage() );
+               return $message->addFromKey( $error )->getHtml();
        }
 
        /**
@@ -161,9 +169,10 @@
         * @param $namespace
         */
        public function testErrorOnNamespace( $namespace ) {
-               $errorMessage = smwfEncodeMessages( array( wfMessage( 
'smw_no_concept_namespace' )->inContentLanguage()->text() ) );
+               $title = $this->getTitle( $namespace );
+               $errorMessage = $this->getMessageText( $title, 
'smw_no_concept_namespace' );
+               $instance = $this->getInstance( $title, 
$this->getParserOutput() );
 
-               $instance = $this->getInstance( $this->getTitle( $namespace ), 
$this->getParserOutput() );
                $this->assertEquals( $errorMessage, $instance->parse( array() ) 
);
        }
 
@@ -173,14 +182,19 @@
         *
         * @since 1.9
         *
-        * @param $namespace
+        * @param $params
         */
        public function testErrorOnDoubleParse( array $params ) {
-               $errorMessage = smwfEncodeMessages( array( wfMessage( 
'smw_multiple_concepts' )->inContentLanguage()->text() ) );
+               $title = $this->getTitle( SMW_NS_CONCEPT );
+               $errorMessage = $this->getMessageText( $title, 
'smw_multiple_concepts' );
 
-               $instance = $this->getInstance( $this->getTitle( SMW_NS_CONCEPT 
), $this->getParserOutput() );
+               $instance = $this->getInstance( $title, 
$this->getParserOutput() );
                $instance->parse( $params );
 
+               // First call
+               $instance->parse( $params );
+
+               // Second call raises the error
                $this->assertEquals( $errorMessage, $instance->parse( $params ) 
);
        }
 
diff --git 
a/tests/phpunit/includes/parserhooks/RecurringEventsParserFunctionTest.php 
b/tests/phpunit/includes/parserhooks/RecurringEventsParserFunctionTest.php
index 44d1f15..c14e028 100644
--- a/tests/phpunit/includes/parserhooks/RecurringEventsParserFunctionTest.php
+++ b/tests/phpunit/includes/parserhooks/RecurringEventsParserFunctionTest.php
@@ -4,6 +4,8 @@
 
 use SMW\RecurringEventsParserFunction;
 use SMW\Subobject;
+use SMW\ParserParameterFormatter;
+use SMW\MessageFormatter;
 
 use Title;
 use ParserOutput;
@@ -382,7 +384,8 @@
        private function getInstance( Title $title, ParserOutput $parserOutput 
= null ) {
                return new RecurringEventsParserFunction(
                        $this->getParserData( $title, $parserOutput ),
-                       new Subobject( $title )
+                       new Subobject( $title ),
+                       new MessageFormatter( $title->getPageLanguage() )
                );
        }
 
@@ -445,5 +448,4 @@
                $result = RecurringEventsParserFunction::render( $parser );
                $this->assertInternalType( 'string', $result );
        }
-
 }
diff --git a/tests/phpunit/includes/parserhooks/SetParserFunctionTest.php 
b/tests/phpunit/includes/parserhooks/SetParserFunctionTest.php
index 361aaea..e833683 100644
--- a/tests/phpunit/includes/parserhooks/SetParserFunctionTest.php
+++ b/tests/phpunit/includes/parserhooks/SetParserFunctionTest.php
@@ -3,7 +3,12 @@
 namespace SMW\Test;
 
 use SMW\SetParserFunction;
+use SMW\ParserData;
+use SMW\ParserParameterFormatter;
+use SMW\MessageFormatter;
 
+use SMWDIWikiPage;
+use SMWDataItem;
 use Title;
 use ParserOutput;
 
@@ -132,7 +137,10 @@
         * @return  SetParserFunction
         */
        private function getInstance( Title $title, ParserOutput $parserOutput 
= null ) {
-               return new SetParserFunction( $this->getParserData( $title, 
$parserOutput ) );
+               return new SetParserFunction(
+                       $this->getParserData( $title, $parserOutput ),
+                       new MessageFormatter( $title->getPageLanguage() )
+               );
        }
 
        /**
@@ -167,6 +175,7 @@
        public function testParse( array $params, array $expected ) {
                $instance = $this->getInstance( $this->getTitle(), 
$this->getParserOutput() );
                $result = $instance->parse( $this->getParserParameterFormatter( 
$params ) );
+
                $this->assertInternalType( 'string', $result );
        }
 
diff --git a/tests/phpunit/includes/parserhooks/ShowParserFunctionTest.php 
b/tests/phpunit/includes/parserhooks/ShowParserFunctionTest.php
index 43a2a9c..04f4663 100644
--- a/tests/phpunit/includes/parserhooks/ShowParserFunctionTest.php
+++ b/tests/phpunit/includes/parserhooks/ShowParserFunctionTest.php
@@ -4,6 +4,7 @@
 
 use SMW\ShowParserFunction;
 use SMW\QueryData;
+use SMW\MessageFormatter;
 
 use Title;
 use ParserOutput;
@@ -139,7 +140,8 @@
        private function getInstance( Title $title, ParserOutput $parserOutput 
= null ) {
                return new ShowParserFunction(
                        $this->getParserData( $title, $parserOutput ),
-                       new QueryData( $title )
+                       new QueryData( $title ),
+                       new MessageFormatter( $title->getPageLanguage() )
                 );
        }
 
@@ -190,8 +192,11 @@
         * @since 1.9
         */
        public function testParseDisabledsmwgQEnabled() {
-               $expected = smwfEncodeMessages( array( wfMessage( 
'smw_iq_disabled' )->inContentLanguage()->text() ) );
-               $instance = $this->getInstance( $this->getTitle(), 
$this->getParserOutput() );
+               $title = $this->getTitle();
+               $message = new MessageFormatter( $title->getPageLanguage() );
+               $expected = $message->addFromKey( 'smw_iq_disabled' 
)->getHtml();
+
+               $instance = $this->getInstance( $title, 
$this->getParserOutput() );
 
                // Make protected method accessible
                $reflection = new ReflectionClass( $this->getClass() );
diff --git a/tests/phpunit/includes/parserhooks/SubobjectParserFunctionTest.php 
b/tests/phpunit/includes/parserhooks/SubobjectParserFunctionTest.php
index d88bf68..12c4aa4 100644
--- a/tests/phpunit/includes/parserhooks/SubobjectParserFunctionTest.php
+++ b/tests/phpunit/includes/parserhooks/SubobjectParserFunctionTest.php
@@ -5,6 +5,7 @@
 use SMW\SubobjectParserFunction;
 use SMW\Subobject;
 use SMW\ParserParameterFormatter;
+use SMW\MessageFormatter;
 
 use SMWDIProperty;
 use SMWDataItem;
@@ -71,7 +72,8 @@
        private function getInstance( Title $title, ParserOutput $parserOutput 
= null ) {
                return new SubobjectParserFunction(
                        $this->getParserData( $title, $parserOutput ),
-                       new Subobject( $title )
+                       new Subobject( $title ),
+                       new MessageFormatter( $title->getPageLanguage() )
                );
        }
 

-- 
To view, visit https://gerrit.wikimedia.org/r/58040
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Id252311eedc9855c961f5b1dfd02ade1ed8d3079
Gerrit-PatchSet: 6
Gerrit-Project: mediawiki/extensions/SemanticMediaWiki
Gerrit-Branch: master
Gerrit-Owner: Mwjames <[email protected]>
Gerrit-Reviewer: Jeroen De Dauw <[email protected]>
Gerrit-Reviewer: Mwjames <[email protected]>
Gerrit-Reviewer: jenkins-bot

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to