merge with dev

This commit is contained in:
Diana 2015-05-26 10:51:41 +00:00
parent 8e1834c810
commit 01ccae3e79
14 changed files with 187 additions and 37 deletions

View file

@ -104,7 +104,7 @@ class PortableInfoboxParserTagController extends WikiaController {
$value = isset( $params[ 'theme-source' ] ) ? $frame->getArgument( $params[ 'theme-source' ] ) : false;
$themeName = $this->getThemeName( $params, $value );
//make sure no whitespaces, prevents side effects
return self::INFOBOX_THEME_PREFIX . preg_replace( '|\s+|s', '-', $themeName );
return Sanitizer::escapeClass( self::INFOBOX_THEME_PREFIX . preg_replace( '|\s+|s', '-', $themeName ) );
}
private function getThemeName( $params, $value ) {

View file

@ -12,6 +12,7 @@ class Node {
const LABEL_TAG_NAME = 'label';
protected $xmlNode;
protected $parent = null;
/* @var $externalParser ExternalParser */
protected $externalParser;
@ -21,6 +22,24 @@ class Node {
$this->infoboxData = $infoboxData;
}
/**
* @return mixed
*/
public function getParent() {
return $this->parent;
}
/**
* @param mixed $parent
*/
public function setParent( Node $parent ) {
$this->parent = $parent;
}
public function ignoreNodeWhenEmpty() {
return true;
}
/**
* @return ExternalParser
*/
@ -39,7 +58,13 @@ class Node {
}
public function getType() {
return $this->xmlNode->getName();
/*
* Node type generation is based on XML tag name.
* It's worth to remember that SimpleXMLElement::getName method is
* case - sensitive ( "<Data>" != "<data>" ), so we need to sanitize Node Type
* by using strtolower function
*/
return strtolower( $this->xmlNode->getName() );
}
public function getData() {

View file

@ -10,7 +10,7 @@ class NodeComparison extends Node {
if ( $this->externalParser ) {
$nodeFactory->setExternalParser( $this->externalParser );
}
return [ 'value' => $nodeFactory->getDataFromNodes( $this->xmlNode ) ];
return [ 'value' => $nodeFactory->getDataFromNodes( $this->xmlNode, $this ) ];
}
public function isEmpty( $data ) {

View file

@ -3,6 +3,17 @@ namespace Wikia\PortableInfobox\Parser\Nodes;
class NodeData extends Node {
public function ignoreNodeWhenEmpty() {
$parent = $this->getParent();
if ( $parent instanceof NodeSet ) {
if ( $parent->getParent() instanceof NodeComparison ) {
// data tag inside comparison tag can not be ignored
return false;
}
}
return true;
}
public function getData() {
return [
'label' => $this->getExternalParser()->parseRecursive(

View file

@ -10,7 +10,7 @@ class NodeGroup extends Node {
if ( $this->externalParser ) {
$nodeFactory->setExternalParser( $this->externalParser );
}
return [ 'value' => $nodeFactory->getDataFromNodes( $this->xmlNode ) ];
return [ 'value' => $nodeFactory->getDataFromNodes( $this->xmlNode, $this ) ];
}
public function isEmpty( $data ) {

View file

@ -5,18 +5,22 @@ use Wikia\PortableInfobox\Helpers\ImageFilenameSanitizer;
class NodeImage extends Node {
const ALT_TAG_NAME = 'alt';
const CAPTION_TAG_NAME = 'caption';
public function getData() {
$title = $this->getImageAsTitleObject( $this->getRawValueWithDefault( $this->xmlNode ) );
$ref = null;
$alt = $this->getValueWithDefault( $this->xmlNode->{self::ALT_TAG_NAME} );
$caption = $this->getValueWithDefault( $this->xmlNode->{self::CAPTION_TAG_NAME} );
wfRunHooks( 'PortableInfoboxNodeImage::getData', [ $title, &$ref, $alt ] );
return [
'url' => $this->resolveImageUrl( $title ),
'name' => ( $title ) ? $title->getDBkey() : '',
'name' => ( $title ) ? $title->getText() : '',
'key' => ( $title ) ? $title->getDBKey() : '',
'alt' => $alt,
'caption' => $caption,
'ref' => $ref
];
}

View file

@ -10,7 +10,7 @@ class NodeSet extends Node {
if ( $this->externalParser ) {
$nodeFactory->setExternalParser( $this->externalParser );
}
return [ 'value' => $nodeFactory->getDataFromNodes( $this->xmlNode ) ];
return [ 'value' => $nodeFactory->getDataFromNodes( $this->xmlNode, $this ) ];
}
public function isEmpty( $data ) {

View file

@ -28,16 +28,18 @@ class XmlParser {
* @param \SimpleXMLElement $xmlIterable
* @return array
*/
public function getDataFromNodes( \SimpleXMLElement $xmlIterable ) {
public function getDataFromNodes( \SimpleXMLElement $xmlIterable, $parentNode = null ) {
wfProfileIn(__METHOD__);
$data = [ ];
foreach ( $xmlIterable as $node ) {
$nodeHandler = $this->getNode( $node );
$nodeHandler = $this->getNode( $node, $parentNode );
$nodeData = $nodeHandler->getData();
if ( !$nodeHandler->isEmpty( $nodeData ) ) {
// add data if node is not empty or - when node can not be ignored when empty
if ( !$nodeHandler->isEmpty( $nodeData ) || !$nodeHandler->ignoreNodeWhenEmpty() ) {
$data[ ] = [
'type' => $nodeHandler->getType(),
'data' => $nodeData
'data' => $nodeData,
'isEmpty' => $nodeHandler->isEmpty( $nodeData )
];
}
}
@ -81,9 +83,10 @@ class XmlParser {
/**
* @param \SimpleXMLElement $xmlNode
* @param Node $parent
* @return \Wikia\PortableInfobox\Parser\Nodes\Node
*/
public function getNode( \SimpleXMLElement $xmlNode ) {
public function getNode( \SimpleXMLElement $xmlNode, $parent = null ) {
wfProfileIn(__METHOD__);
$tagType = $xmlNode->getName();
$className = 'Wikia\\PortableInfobox\\Parser\\Nodes\\' . 'Node' . ucfirst( strtolower( $tagType ) );
@ -93,6 +96,9 @@ class XmlParser {
if ( !empty( $this->externalParser ) ) {
$instance->setExternalParser( $this->externalParser );
}
if ( $parent ) {
$instance->setParent( $parent );
}
wfProfileOut( __METHOD__ );
return $instance;
}

View file

@ -150,8 +150,9 @@ class PortableInfoboxRenderService extends WikiaService {
// it modular) While doing this we also need to move this logic to appropriate image render class
if ( $type === 'image' ) {
$data[ 'thumbnail' ] = $this->getThumbnailUrl( $data );
$data[ 'key' ] = urlencode( $data[ 'key' ] );
if ( F::app()->checkSkin( 'wikiamobile' ) ) {
if ( $this->isWikiaMobile() ) {
$type = $type . self::MOBILE_TEMPLATE_POSTFIX;
}
}
@ -185,7 +186,7 @@ class PortableInfoboxRenderService extends WikiaService {
private function createVignetteThumbnail( $url ) {
return VignetteRequest::fromUrl( $url )
->thumbnailDown()
->width( F::app()->checkSkin( 'wikiamobile' ) ?
->width( $this->isWikiaMobile() ?
self::MOBILE_THUMBNAIL_WIDTH :
self::DESKTOP_THUMBNAIL_WIDTH
)
@ -211,6 +212,12 @@ class PortableInfoboxRenderService extends WikiaService {
);
}
return '';
/**
* required for testing mobile template rendering
* @return bool
*/
protected function isWikiaMobile() {
return F::app()->checkSkin( 'wikiamobile' );
}
/**

View file

@ -3,5 +3,6 @@
<a href="{{url}}" class="image image-thumbnail" title="{{alt}}">
<img src="{{thumbnail}}" class="portable-infobox-image" alt="{{alt}}" data-image-key="{{name}}" data-image-name="{{name}}"/>
</a>
{{#caption}}<figcaption class="portable-infobox-item-margins portable-infobox-image-caption">{{{caption}}}</figcaption>{{/caption}}
</figure>
</div>

View file

@ -1 +1 @@
<aside class="portable-infobox{{#theme}} {{{theme}}}{{/theme}}">{{{content}}}</aside>
<aside class="portable-infobox{{#theme}} {{theme}}{{/theme}}">{{{content}}}</aside>

View file

@ -28,17 +28,27 @@ class PortableInfoboxParserNodesTest extends WikiaBaseTest {
}
public function testNodeImage() {
$string = '<image source="image2"><alt source="alt-source"><default>default-alt</default></alt></image>';
$string = '<image source="image2">
<alt source="alt-source"><default>default-alt</default></alt>
<caption source="caption"><default>default caption</default></caption>
</image>';
$xml = simplexml_load_string( $string );
$nodeDefault = new Wikia\PortableInfobox\Parser\Nodes\NodeImage( $xml, [ ] );
$node = $this->getMockBuilder( 'Wikia\PortableInfobox\Parser\Nodes\NodeImage' )->setConstructorArgs( [ $xml, [ 'image2' => 'aaa.jpg', 'alt-source' => 'bbb' ] ] )->setMethods( [ 'resolveImageUrl' ] )->getMock();
$node = $this->getMockBuilder( 'Wikia\PortableInfobox\Parser\Nodes\NodeImage' )
->setConstructorArgs( [ $xml, [ 'image2' => 'aaa.jpg',
'alt-source' => 'bbb',
'caption' => 'capt' ] ] )
->setMethods( [ 'resolveImageUrl' ] )
->getMock();
$node->expects( $this->any() )->method( 'resolveImageUrl' )->will( $this->returnValue( 'aaa.jpg' ) );
$this->assertTrue( $node->getData()[ 'url' ] == 'aaa.jpg', 'value is not aaa.jpg' );
$this->assertTrue( $node->getData()[ 'name' ] == 'Aaa.jpg', 'value is not aaa.jpg' );
$this->assertTrue( $node->getData()[ 'alt' ] == 'bbb', 'alt is not bbb' );
$this->assertTrue( $node->getData()[ 'caption' ] == 'capt', 'caption is not "capt"' );
$this->assertTrue( $nodeDefault->getData()[ 'alt' ] == 'default-alt', 'default alt' );
$this->assertTrue( $nodeDefault->getData()[ 'caption' ] == 'default caption', 'default caption' );
}
public function testNodeHeader() {

View file

@ -13,6 +13,11 @@ class PortableInfoboxRenderServiceTest extends PHPUnit_Framework_TestCase {
$this->infoboxRenderService = $mock;
}
private function setWikiaMobileSkin($bool) {
$this->infoboxRenderService->expects( $this->any() )->method( 'isWikiaMobile' )->will( $this->returnValue
($bool) );
}
/**
* @param $input
* @param $expectedOutput
@ -20,6 +25,7 @@ class PortableInfoboxRenderServiceTest extends PHPUnit_Framework_TestCase {
* @dataProvider testRenderInfoboxDataProvider
*/
public function testRenderInfobox( $input, $expectedOutput, $description ) {
$this->setWikiaMobileSkin(false);
$actualOutput = $this->infoboxRenderService->renderInfobox( $input );
@ -38,6 +44,31 @@ class PortableInfoboxRenderServiceTest extends PHPUnit_Framework_TestCase {
$this->assertEquals( $expectedHtml, $actualHtml, $description );
}
/**
* @param $input
* @param $expectedOutput
* @param $description
* @dataProvider testRenderInfoboxDataProvider
*/
public function testRenderMobileInfobox( $input, $expectedOutput, $description ) {
$this->setWikiaMobileSkin(true);
$actualOutput = $this->infoboxRenderService->renderInfobox( $input );
$actualDOM = new DOMDocument('1.0');
$expectedDOM = new DOMDocument('1.0');
$actualDOM->formatOutput = true;
$actualDOM->preserveWhiteSpace = false;
$expectedDOM->formatOutput = true;
$expectedDOM->preserveWhiteSpace = false;
$actualDOM->loadXML($actualOutput);
$expectedDOM->loadXML($expectedOutput);
$expectedHtml = $expectedDOM->saveXML();
$actualHtml = $actualDOM->saveXML();
$this->assertEquals( $expectedHtml, $actualHtml, $description );
}
public function testRenderInfoboxDataProvider() {
return [
[
@ -61,6 +92,29 @@ class PortableInfoboxRenderServiceTest extends PHPUnit_Framework_TestCase {
</aside>',
'description' => 'Only title'
],
[
'input' => [
[
'type' => 'image',
'data' => [
'alt' => 'image alt',
'url' => 'http://image.jpg',
'caption' => 'Lorem ipsum dolor'
]
]
],
'output' => '<aside class="portable-infobox">
<div class="portable-infobox-item item-type-image no-margins">
<figure class="portable-infobox-image-wrapper">
<a href="http://image.jpg" class="image image-thumbnail" title="image alt">
<img src="http://image.jpg" class="portable-infobox-image" alt="image alt" data-image-key="" data-image-name=""/>
</a>
<figcaption class="portable-infobox-item-margins portable-infobox-image-caption">Lorem ipsum dolor</figcaption>
</figure>
</div>
</aside>',
'description' => 'Only image'
],
[
'input' => [
[
@ -75,27 +129,6 @@ class PortableInfoboxRenderServiceTest extends PHPUnit_Framework_TestCase {
</aside>',
'description' => 'Footer only'
],
[
'input' => [
[
'type' => 'image',
'data' => [
'alt' => 'image alt',
'url' => 'http://image.jpg'
]
]
],
'output' => '<aside class="portable-infobox">
<div class="portable-infobox-item item-type-image no-margins">
<figure class="portable-infobox-image-wrapper">
<a href="http://image.jpg" class="image image-thumbnail" title="image alt">
<img src="http://image.jpg" class="portable-infobox-image" alt="image alt" data-image-key="" data-image-name=""/>
</a>
</figure>
</div>
</aside>',
'description' => 'Only image'
],
[
'input' => [
[
@ -322,4 +355,29 @@ class PortableInfoboxRenderServiceTest extends PHPUnit_Framework_TestCase {
]
];
}
public function testRenderMobileInfoboxDataProvider() {
return [
[
'input' => [
[
'type' => 'image',
'data' => [
'alt' => 'image alt',
'url' => 'http://image.jpg',
'thumbnail' => 'thumbnail.jpg',
'ref' => 1,
'name' => 'test1'
]
]
],
'output' => '<aside class="portable-infobox">
<div class="portable-infobox-item item-type-image no-margins">
<img src="data:image/gif;base64,R0lGODlhAQABAIABAAAAAP///yH5BAEAAAEALAAAAAABAAEAQAICTAEAOw%3D%3D" class="portable-infobox-image lazy media article-media" alt="image alt" data-image-key="test1" data-image-name="test1" data-ref="1" data-src="thumbnail.jpg" data-params=\'[{"name":"test1", "full":"http://image.jpg"}]\' />
</div>
</aside>',
'description' => 'Only image for mobile'
]
];
}
}

View file

@ -59,6 +59,34 @@ class XmlParserTest extends WikiaBaseTest {
$this->assertTrue( $data[1]['data']['value'][0]['data']['value'][2]['data']['value'] == 'parseRecursive(LALALA)' );
}
public function testNotProvidingDataSource() {
$xmlParser = new \Wikia\PortableInfobox\Parser\XmlParser( ['a'=>'1'] );
$data1 = $xmlParser->getDataFromXmlString('<infobox><data source="b" /><data source="a" /></infobox>');
$this->assertTrue( $data1[0]['data']['value'] == '1', 'Data with empty source "b" should be ignored' );
}
public function testNotProvidingDataSourceInsideComparison() {
$xmlParser = new \Wikia\PortableInfobox\Parser\XmlParser( ['a'=>'1'] );
$data1 = $xmlParser->getDataFromXmlString( '<infobox>
<comparison>
<set>
<data source="b" />
<data source="a" />
</set>
</comparison>
</infobox>' );
$setElement = $data1[0]['data']['value'][0]['data']['value'];
//Data with empty source "b" should not be ignored inside comparison:
$this->assertTrue( $setElement[0]['data']['value'] == '', 'Data with empty source "b" inside comparison' );
$this->assertTrue( $setElement[0]['isEmpty'] == true );
$this->assertTrue( $setElement[1]['data']['value'] == '1', '' );
}
/**
* @dataProvider errorHandlingDataProvider
*/