mirror of
https://github.com/Universal-Omega/PortableInfobox.git
synced 2024-11-15 20:09:44 +00:00
Merge pull request #7364 from Wikia/DAT-2845
DAT-2845 add infobox parser api
This commit is contained in:
commit
07dfc765d2
|
@ -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';
|
||||
|
|
79
controllers/ApiPortableInfobox.class.php
Normal file
79
controllers/ApiPortableInfobox.class.php
Normal file
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
|
||||
class ApiPortableInfobox extends ApiBase {
|
||||
|
||||
public function __construct( $main, $action ) {
|
||||
parent:: __construct( $main, $action );
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
$text = $this->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=<infobox><data><default>{{PAGENAME}}</default></data></infobox>&title=Test',
|
||||
'api.php?action=infobox&text=<infobox><data source="test" /></infobox>&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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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 );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue