diff --git a/PortableInfobox.setup.php b/PortableInfobox.setup.php
index e37b187..1c70812 100644
--- a/PortableInfobox.setup.php
+++ b/PortableInfobox.setup.php
@@ -45,6 +45,7 @@ $wgAutoloadClasses[ 'Wikia\PortableInfobox\Helpers\SimpleXmlUtil' ] = $dir . 'se
// controller classes
$wgAutoloadClasses[ 'PortableInfoboxParserTagController' ] = $dir . 'controllers/PortableInfoboxParserTagController.class.php';
+$wgAutoloadClasses[ 'ApiPortableInfobox' ] = $dir . 'controllers/ApiPortableInfobox.class.php';
$wgAutoloadClasses[ 'PortableInfoboxHooks' ] = $dir . 'PortableInfoboxHooks.class.php';
// hooks
@@ -54,3 +55,6 @@ $wgHooks['ParserAfterTidy'][] = 'PortableInfoboxParserTagController::replaceInfo
// i18n mapping
$wgExtensionMessagesFiles[ 'PortableInfobox' ] = $dir . 'PortableInfobox.i18n.php';
+
+// MW API
+$wgAPIModules['infobox'] = 'ApiPortableInfobox';
diff --git a/controllers/ApiPortableInfobox.class.php b/controllers/ApiPortableInfobox.class.php
new file mode 100644
index 0000000..614e94b
--- /dev/null
+++ b/controllers/ApiPortableInfobox.class.php
@@ -0,0 +1,79 @@
+getParameter( "text" );
+ $title = $this->getParameter( "title" );
+ $arguments = $this->getFrameArguments();
+ if ( $arguments === null ) {
+ $this->getResult()->setWarning( "Arguments json format incorect or empty" );
+ }
+ $parser = new Parser();
+ $parser->startExternalParse( Title::newFromText( $title ), new ParserOptions(), 'text', true );
+ $frame = $parser->getPreprocessor()->newCustomFrame( $arguments );
+
+ try {
+ $output = PortableInfoboxParserTagController::getInstance()->render( $text, $parser, $frame );
+ $this->getResult()->addValue( null, $this->getModuleName(), [ 'text' => [ '*' => $output ] ] );
+ } catch ( \Wikia\PortableInfobox\Parser\Nodes\UnimplementedNodeException $e ) {
+ $this->dieUsage( wfMessage( 'unimplemented-infobox-tag', [ $e->getMessage() ] )->escaped(), "notimplemented" );
+ } catch ( \Wikia\PortableInfobox\Parser\XmlMarkupParseErrorException $e ) {
+ $this->dieUsage( wfMessage( 'xml-parse-error' )->text(), "badxml" );
+ }
+ }
+
+ public function getAllowedParams() {
+ return array(
+ 'text' => array(
+ ApiBase :: PARAM_TYPE => 'string'
+ ),
+ 'title' => array(
+ ApiBase :: PARAM_TYPE => 'string'
+ ),
+ 'args' => array(
+ ApiBase :: PARAM_TYPE => 'string'
+ )
+ );
+ }
+
+ public function getParamDescription() {
+ return array(
+ 'text' => 'Infobox to parse (xml string)',
+ 'title' => 'Title of page the text belongs to',
+ 'args' => 'Variable list to use during parse (json format)',
+ );
+ }
+
+ public function getDescription() {
+ return array( 'This module provides infobox parser' );
+ }
+
+ /**
+ * Examples
+ */
+ public function getExamples() {
+ return array(
+ 'api.php?action=infobox',
+ 'api.php?action=infobox&text={{PAGENAME}}&title=Test',
+ 'api.php?action=infobox&text=&args={"test": "test value"}',
+ );
+ }
+
+ public function getVersion() {
+ return __CLASS__ . '$Id$';
+ }
+
+ /**
+ * @return mixed
+ */
+ protected function getFrameArguments() {
+ $arguments = $this->getParameter( "args" );
+ return isset( $arguments ) ? json_decode( $arguments, true ) : false;
+ }
+
+}
\ No newline at end of file
diff --git a/controllers/PortableInfoboxParserTagController.class.php b/controllers/PortableInfoboxParserTagController.class.php
index b7f5d9b..324e761 100644
--- a/controllers/PortableInfoboxParserTagController.class.php
+++ b/controllers/PortableInfoboxParserTagController.class.php
@@ -42,6 +42,30 @@ class PortableInfoboxParserTagController extends WikiaController {
return true;
}
+ /**
+ * @param $markup
+ * @param Parser $parser
+ * @param PPFrame $frame
+ * @return string
+ * @throws UnimplementedNodeException when node used in markup does not exists
+ * @throws XmlMarkupParseErrorException xml not well formatted
+ */
+ public function render( $markup, Parser $parser, PPFrame $frame, $params = null ) {
+ $infoboxParser = new Wikia\PortableInfobox\Parser\XmlParser( $this->getFrameParams( $frame ) );
+ $infoboxParser->setExternalParser( new Wikia\PortableInfobox\Parser\MediaWikiParserService( $parser, $frame ) );
+
+ //get params if not overridden
+ if ( !isset( $params ) ) {
+ $params = $infoboxParser->getInfoboxParams( $markup );
+ }
+ $data = $infoboxParser->getDataFromXmlString( $markup );
+ //save for later api usage
+ $this->saveToParserOutput( $parser->getOutput(), $data );
+
+ $theme = $this->getThemeWithDefault( $params, $frame );
+ return ( new PortableInfoboxRenderService() )->renderInfobox( $data, $theme );
+ }
+
/**
* @desc Renders Infobox
*
@@ -56,23 +80,14 @@ class PortableInfoboxParserTagController extends WikiaController {
$this->markerNumber++;
$markup = '<' . self::PARSER_TAG_NAME . '>' . $text . '' . self::PARSER_TAG_NAME . '>';
- $infoboxParser = new Wikia\PortableInfobox\Parser\XmlParser( $frame->getNamedArguments() );
- $infoboxParser->setExternalParser( ( new Wikia\PortableInfobox\Parser\MediaWikiParserService( $parser, $frame ) ) );
-
try {
- $data = $infoboxParser->getDataFromXmlString( $markup );
+ $renderedValue = $this->render( $markup, $parser, $frame, $params );
} catch ( \Wikia\PortableInfobox\Parser\Nodes\UnimplementedNodeException $e ) {
return $this->handleError( wfMessage( 'unimplemented-infobox-tag', [ $e->getMessage() ] )->escaped() );
} catch ( \Wikia\PortableInfobox\Parser\XmlMarkupParseErrorException $e ) {
return $this->handleError( wfMessage( 'xml-parse-error' ) );
}
- //save for later api usage
- $this->saveToParserOutput( $parser->getOutput(), $data );
-
- $renderer = new PortableInfoboxRenderService();
- $theme = $this->getThemeWithDefault( $params, $frame );
- $renderedValue = $renderer->renderInfobox( $data, $theme );
if ( $wgArticleAsJson ) {
// (wgArticleAsJson == true) it means that we need to encode output for use inside JSON
$renderedValue = trim( json_encode( $renderedValue ), '"' );
@@ -113,4 +128,19 @@ class PortableInfoboxParserTagController extends WikiaController {
( isset( $params[ 'theme' ] ) ? $params[ 'theme' ] : self::DEFAULT_THEME_NAME );
}
+ /**
+ * Function ensures that arrays are used for merging
+ * @param PPFrame $frame
+ * @return array
+ */
+ protected function getFrameParams( PPFrame $frame ) {
+ //we use both getNamedArguments and getArguments to ensure we acquire variables no matter what frame is used
+ $namedArgs = $frame->getNamedArguments();
+ $namedArgs = isset( $namedArgs ) ? ( is_array( $namedArgs ) ? $namedArgs : [ $namedArgs ] ) : [ ];
+ $args = $frame->getArguments();
+ $args = isset( $args ) ? ( is_array( $args ) ? $args : [ $args ] ) : [ ];
+
+ return array_merge( $namedArgs, $args );
+ }
+
}
diff --git a/services/Parser/XmlParser.php b/services/Parser/XmlParser.php
index 28a49d9..1b6be05 100644
--- a/services/Parser/XmlParser.php
+++ b/services/Parser/XmlParser.php
@@ -55,25 +55,22 @@ class XmlParser {
public function getDataFromXmlString( $xmlString ) {
wfProfileIn( __METHOD__ );
- $global_libxml_setting = libxml_use_internal_errors();
- libxml_use_internal_errors( true );
- $xml = simplexml_load_string( $xmlString );
- $errors = libxml_get_errors();
- libxml_use_internal_errors( $global_libxml_setting );
-
- if ( $xml === false ) {
- foreach ( $errors as $xmlerror ) {
- $this->logXmlParseError( $xmlerror->level, $xmlerror->code, trim( $xmlerror->message ) );
- }
- libxml_clear_errors();
- throw new XmlMarkupParseErrorException();
- }
+ $xml = $this->parseXmlString( $xmlString );
$data = $this->getDataFromNodes( $xml );
wfProfileOut( __METHOD__ );
return $data;
}
+ public function getInfoboxParams( $xmlString ) {
+ $xml = $this->parseXmlString( $xmlString );
+ $result = [];
+ foreach ( $xml->attributes() as $k => $v ) {
+ $result[$k] = (string) $v;
+ }
+ return $result;
+ }
+
protected function logXmlParseError( $level, $code, $message ) {
\Wikia\Logger\WikiaLogger::instance()->info( "PortableInfobox XML Parser problem", [
"level" => $level,
@@ -106,6 +103,28 @@ class XmlParser {
return new Nodes\NodeUnimplemented( $xmlNode, $this->infoboxData );
}
+ /**
+ * @param $xmlString
+ * @return \SimpleXMLElement
+ * @throws XmlMarkupParseErrorException
+ */
+ protected function parseXmlString( $xmlString ) {
+ $global_libxml_setting = libxml_use_internal_errors();
+ libxml_use_internal_errors( true );
+ $xml = simplexml_load_string( $xmlString );
+ $errors = libxml_get_errors();
+ libxml_use_internal_errors( $global_libxml_setting );
+
+ if ( $xml === false ) {
+ foreach ( $errors as $xmlerror ) {
+ $this->logXmlParseError( $xmlerror->level, $xmlerror->code, trim( $xmlerror->message ) );
+ }
+ libxml_clear_errors();
+ throw new XmlMarkupParseErrorException();
+ }
+ return $xml;
+ }
+
}
class XmlMarkupParseErrorException extends \Exception {
diff --git a/tests/PortableInfoboxParserTagControllerTest.php b/tests/PortableInfoboxParserTagControllerTest.php
index 9fb8f96..dc69567 100644
--- a/tests/PortableInfoboxParserTagControllerTest.php
+++ b/tests/PortableInfoboxParserTagControllerTest.php
@@ -2,6 +2,11 @@
class PortableInfoboxParserTagControllerTest extends WikiaBaseTest {
+ /** @var PortableInfoboxParserTagController */
+ protected $parser;
+ /** @var Parser */
+ protected $controller;
+
protected function setUp() {
$this->setupFile = dirname( __FILE__ ) . '/../PortableInfobox.setup.php';
parent::setUp();