mirror of
https://github.com/Universal-Omega/PortableInfobox.git
synced 2024-11-15 11:59:56 +00:00
DAT-3621 Unified tests for hero image and regular caption
* Disable sanitization on Oasis * Handle previously unsupported case of nested tag ( <b><a></a></b> ) * Unify test formatting * Change list handling (yes, I am not proud of that)
This commit is contained in:
parent
e68ce57c7a
commit
168bf09348
|
@ -173,7 +173,6 @@ class PortableInfoboxRenderService extends WikiaService {
|
|||
for ( $i = 0; $i < count($data); $i++ ) {
|
||||
$data[$i][ 'context' ] = self::MEDIA_CONTEXT_INFOBOX;
|
||||
$data[$i] = $helper->extendImageData( $data[$i] );
|
||||
$data[$i] = SanitizerBuilder::createFromType( $type )->sanitize( $data[$i] );
|
||||
|
||||
if ( !!$data[$i] ) {
|
||||
$images[] = $data[$i];
|
||||
|
@ -198,6 +197,9 @@ class PortableInfoboxRenderService extends WikiaService {
|
|||
$templateName = $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Currently, based on business decision, sanitization happens ONLY on Mercury
|
||||
*/
|
||||
if ( $helper->isWikiaMobile() ) {
|
||||
$data = SanitizerBuilder::createFromType( $type )->sanitize( $data );
|
||||
}
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
<?php
|
||||
|
||||
class NodeHeroImageSanitizer extends NodeSanitizer {
|
||||
protected $allowedTags = [ 'a' ];
|
||||
protected $selectorsWrappingTextToPad = [ 'li' ];
|
||||
protected $selectorsWrappingAllowedFeatures = [ 'sup[@class="reference"]' ];
|
||||
protected $selectorsForFullRemoval = [ 'script', 'span[@itemprop="duration"]' ];
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
* @return mixed
|
||||
|
@ -9,6 +14,9 @@ class NodeHeroImageSanitizer extends NodeSanitizer {
|
|||
if ( !empty( $data[ 'title' ][ 'value' ] ) ) {
|
||||
$data[ 'title' ][ 'value' ] = $this->sanitizeElementData( $data[ 'title' ][ 'value' ] );
|
||||
}
|
||||
if ( !empty( $data[ 'image' ][ 'caption' ] ) ) {
|
||||
$data[ 'image' ]['caption'] = $this->sanitizeElementData( $data[ 'image' ]['caption'] );
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
class NodeImageSanitizer extends NodeSanitizer {
|
||||
protected $allowedTags = [ 'a' ];
|
||||
protected $selectorsWrappingTextToPad = [ 'li' ];
|
||||
protected $selectorsWrappingAllowedFeatures = [ 'sup[@class="reference"]' ];
|
||||
protected $selectorsForFullRemoval = [ 'script', 'span[@itemprop="duration"]' ];
|
||||
|
||||
|
|
|
@ -9,9 +9,15 @@ abstract class NodeSanitizer implements NodeTypeSanitizerInterface {
|
|||
* Sanitizer configuration
|
||||
* Can be overridden by child classes
|
||||
*/
|
||||
// these are selectors for explicitly allowed tags, like 'a'
|
||||
protected $allowedTags = [ ];
|
||||
// these are valid 'internal' node names (per libxml convention, i.e. a, #text, etc)
|
||||
protected $validNodeNames = [ '#text' ];
|
||||
// these are selectors that describe nodes containing text that should be padded with whitespace
|
||||
protected $selectorsWrappingTextToPad = [ ];
|
||||
// these are selectors that describe root nodes of known features that should not be sanitized
|
||||
protected $selectorsWrappingAllowedFeatures = [ ];
|
||||
// these are selectors that describe nodes for full removal
|
||||
protected $selectorsForFullRemoval = [ ];
|
||||
|
||||
/**
|
||||
|
@ -20,8 +26,8 @@ abstract class NodeSanitizer implements NodeTypeSanitizerInterface {
|
|||
* @param $elementText
|
||||
* @return string
|
||||
*/
|
||||
protected function sanitizeElementData( $elementText ) {
|
||||
$dom = new \DOMDocument( );
|
||||
protected function sanitizeElementData( $elementText ) {
|
||||
$dom = new \DOMDocument();
|
||||
$dom->loadHTML( $this->prepareValidXML( $elementText ) );
|
||||
|
||||
$elementTextAfterTrim = trim( $this->cleanUpDOM( $dom ) );
|
||||
|
@ -65,6 +71,7 @@ abstract class NodeSanitizer implements NodeTypeSanitizerInterface {
|
|||
protected function cleanUpDOM( $dom ) {
|
||||
$xpath = new \DOMXPath( $dom );
|
||||
$this->removeNodesBySelector( $xpath, $this->selectorsForFullRemoval );
|
||||
|
||||
$nodes = $this->extractNeededNodes( $xpath );
|
||||
|
||||
return $this->normalizeWhitespace( $this->generateHTML( $nodes, $dom ) );
|
||||
|
@ -78,15 +85,22 @@ abstract class NodeSanitizer implements NodeTypeSanitizerInterface {
|
|||
* @return string
|
||||
*/
|
||||
protected function generateHTML( $nodes, $dom ) {
|
||||
$result = [];
|
||||
$result = [ ];
|
||||
foreach ( $nodes as $node ) {
|
||||
/*
|
||||
* store the result; As the input text is already escaped, we make sure that
|
||||
* our output will be escaped too
|
||||
*/
|
||||
$result[] = ( $node->nodeName === '#text' ) ? htmlspecialchars( $dom->saveHTML( $node ), ENT_QUOTES ) : $dom->saveHTML( $node );
|
||||
$outputHtml = $rawHtml = $dom->saveHTML( $node );
|
||||
if ( $node->nodeName === '#text' ) {
|
||||
// As the input text is already escaped, we make sure that our output will be escaped too
|
||||
$outputHtml = htmlspecialchars( $rawHtml, ENT_QUOTES );
|
||||
}
|
||||
if ( $node->parentNode && in_array( $node->parentNode->nodeName, $this->selectorsWrappingTextToPad ) ) {
|
||||
$outputHtml = sprintf( ' %s ', $rawHtml );
|
||||
}
|
||||
|
||||
$result[] = $outputHtml;
|
||||
|
||||
|
||||
}
|
||||
return implode( ' ', $result );
|
||||
return implode( '', $result );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -105,7 +119,16 @@ abstract class NodeSanitizer implements NodeTypeSanitizerInterface {
|
|||
* @return string
|
||||
*/
|
||||
protected function getAllNodesXPath() {
|
||||
return sprintf('//%s/* | //%s//text()', $this->rootNodeTag, $this->rootNodeTag);
|
||||
$xpathExpressions = [ ];
|
||||
foreach ( $this->selectorsWrappingAllowedFeatures as $selector ) {
|
||||
$xpathExpressions [] = sprintf( '//%s//%s', $this->rootNodeTag, $selector );
|
||||
}
|
||||
foreach ( $this->allowedTags as $selector ) {
|
||||
$xpathExpressions [] = sprintf( '//%s//%s', $this->rootNodeTag, $selector );
|
||||
}
|
||||
$xpathExpressions [] = sprintf( '//%s//text()', $this->rootNodeTag );
|
||||
|
||||
return implode( ' | ', $xpathExpressions );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -135,7 +158,7 @@ abstract class NodeSanitizer implements NodeTypeSanitizerInterface {
|
|||
* @param $xpath DOMXPath
|
||||
* @param $selectorsToRemove array
|
||||
*/
|
||||
protected function removeNodesBySelector( $xpath, $selectorsToRemove = [] ) {
|
||||
protected function removeNodesBySelector( $xpath, $selectorsToRemove = [ ] ) {
|
||||
foreach ( $selectorsToRemove as $selector ) {
|
||||
$nodesToRemove = $xpath->query( sprintf( '//%s//%s', $this->rootNodeTag, $selector ) );
|
||||
foreach ( $nodesToRemove as $node ) {
|
||||
|
|
|
@ -572,7 +572,7 @@ class PortableInfoboxRenderServiceTest extends WikiaBaseTest {
|
|||
'output' => '<aside class="portable-infobox pi-background">
|
||||
<div class="pi-item pi-hero">
|
||||
<hgroup class="pi-hero-title-wrapper pi-item-spacing">
|
||||
<h2 class="pi-hero-title">Test Title</h2>
|
||||
<h2 class="pi-hero-title">Test <a href="example.com">Title</a></h2>
|
||||
</hgroup>
|
||||
<img
|
||||
src="data:image/gif;base64,R0lGODlhAQABAIABAAAAAP///yH5BAEAAAEALAAAAAABAAEAQAICTAEAOw%3D%3D" data-src="thumbnail.jpg" class="pi-image-thumbnail lazy media article-media" alt="" data-image-key="test1" data-image-name="test1" data-ref="44" data-params=\'[{"name":"test1", "full":"http://image.jpg"}]\'/>
|
||||
|
|
|
@ -25,13 +25,118 @@ class NodeHeroImageSanitizerTest extends WikiaBaseTest {
|
|||
function testSanitizeDataProvider() {
|
||||
return [
|
||||
[
|
||||
['title' => ['value' => 'Test Title'] ],
|
||||
['title' => ['value' => 'Test Title'] ]
|
||||
[ 'title' => [ 'value' => 'Test Title' ] ],
|
||||
[ 'title' => [ 'value' => 'Test Title' ] ]
|
||||
],
|
||||
[
|
||||
['title' => ['value' => 'Real world <a href="http://vignette-poz.wikia-dev.com/mediawiki116/images/b/b6/DBGT_Logo.svg/revision/latest?cb=20150601155347" class="image image-thumbnail" ><img src="http://vignette-poz.wikia-dev.com/mediawiki116/images/b/b6/DBGT_Logo.svg/revision/latest/scale-to-width-down/30?cb=20150601155347" alt="DBGT Logo" class="" data-image-key="DBGT_Logo.svg" data-image-name="DBGT Logo.svg" width="30" height="18" ></a>title example'] ] ,
|
||||
['title' => ['value' => 'Real world title example'] ]
|
||||
[ 'title' => [ 'value' => 'Real world <a href="http://vignette-poz.wikia-dev.com/mediawiki116/images/b/b6/DBGT_Logo.svg/revision/latest?cb=20150601155347" class="image image-thumbnail" ><img src="http://vignette-poz.wikia-dev.com/mediawiki116/images/b/b6/DBGT_Logo.svg/revision/latest/scale-to-width-down/30?cb=20150601155347" alt="DBGT Logo" class="" data-image-key="DBGT_Logo.svg" data-image-name="DBGT Logo.svg" width="30" height="18" ></a>title example' ] ] ,
|
||||
[ 'title' => [ 'value' => 'Real world title example' ] ]
|
||||
],
|
||||
[
|
||||
[ 'title' => [ 'value' => 'Test <a>Title with</a> <span><small>small</small></span> tag, span tag and <img src="sfefes"/>tag' ] ],
|
||||
[ 'title' => [ 'value' => 'Test <a>Title with</a> small tag, span tag and tag' ] ]
|
||||
],
|
||||
[
|
||||
[ 'title' => [ 'value' => '<a href="http://vignette-poz.wikia-dev.com//images/9/95/All_Stats_%2B2.png/revision/latest?cb=20151222111955" class="image image-thumbnail"><img src="abc" alt="All Stats +2" class="thumbimage" /></a>' ] ],
|
||||
[ 'title' => [ 'value' => '' ] ],
|
||||
],
|
||||
[
|
||||
[ 'title' => [ 'value' => '<figure class="article-thumb tright show-info-icon" style="width: 335px"> <a href="http://mediawiki119.marzjan.wikia-dev.com/wiki/File:AMERICA%27S_TEST_KITCHEN_SEASON_9" class="video video-thumbnail image lightbox medium " itemprop=\'video\' itemscope itemtype="http://schema.org/VideoObject" ><img src="http://vignette-poz.wikia-dev.com//images/6/6e/AMERICA%27S_TEST_KITCHEN_SEASON_9/revision/latest/scale-to-width-down/335?cb=20130904003328" alt="AMERICA'S TEST KITCHEN SEASON 9" class="thumbimage " data-video-key="AMERICA'S_TEST_KITCHEN_SEASON_9" data-video-name="AMERICA'S TEST KITCHEN SEASON 9" width="335" height="187" itemprop="thumbnail" ><span class="duration" itemprop="duration">01:00</span><span class="play-circle"></span><meta itemprop="duration" content="PT01M00S"></a> <figcaption> <a href="/wiki/File:AMERICA%27S_TEST_KITCHEN_SEASON_9" class="sprite info-icon"></a> <p class="title">AMERICA'S TEST KITCHEN SEASON 9</p> </figcaption> </figure>' ] ],
|
||||
[ 'title' => [ 'value' => 'AMERICA'S TEST KITCHEN SEASON 9' ] ]
|
||||
],
|
||||
[
|
||||
[ 'title' => [ 'value' => '<sup id="cite_ref-0" class="reference"><a href="#cite_note-0">[1]</a></sup>' ] ],
|
||||
[ 'title' => [ 'value' => '<sup id="cite_ref-0" class="reference"><a href="#cite_note-0">[1]</a></sup>' ] ]
|
||||
],
|
||||
[
|
||||
[ 'title' => [ 'value' => '<script>JSSnippetsStack.push({dependencies:[{"url":"http://i3.marzjan.wikia-dev.com/__am/1451462348/group/-/wikia_photo_gallery_js","type":"js"},{"url":"http://i2.marzjan.wikia-dev.com/__am/1451462348/sass/background-dynamic%3D1%26background-image%3D%26background-image-height%3D1185%26background-image-width%3D1600%26color-body%3D%2523bacdd8%26color-body-middle%3D%2523bacdd8%26color-buttons%3D%2523006cb0%26color-header%3D%25233a5766%26color-links%3D%2523006cb0%26color-page%3D%2523ffffff%26oasisTypography%3D1%26page-opacity%3D100%26widthType%3D0/extensions/wikia/WikiaPhotoGallery/css/gallery.scss","type":"css"}],callback:function(json){WikiaPhotoGalleryView.init(json)},id:"WikiaPhotoGalleryView.init"})</script>' ] ],
|
||||
[ 'title' => [ 'value' => '' ] ]
|
||||
],
|
||||
[
|
||||
[ 'title' => [ 'value' => '<ul><li>1
|
||||
</li><li>2
|
||||
</li><li>3
|
||||
</li></ul>' ] ],
|
||||
[ 'title' => [ 'value' => '1 2 3' ] ]
|
||||
],
|
||||
[
|
||||
[ 'title' => [ 'value' => '<ol><li>1
|
||||
</li><li>2
|
||||
<ol><li>2.1
|
||||
</li></ol>
|
||||
</li></ol>' ] ],
|
||||
[ 'title' => [ 'value' => '1 2 2.1' ] ]
|
||||
],
|
||||
[
|
||||
[ 'title' => [ 'value' => 'Próxima' ] ],
|
||||
[ 'title' => [ 'value' => 'Próxima' ] ]
|
||||
],
|
||||
[
|
||||
[ 'title' => [ 'value' => 'Música de' ] ],
|
||||
[ 'title' => [ 'value' => 'Música de' ] ]
|
||||
],
|
||||
[
|
||||
[ 'title' => [ 'value' => 'A <b>Kuruma</b> in <i><a href="/wiki/Grand_Theft_Auto_Online" title="Grand Theft Auto Online">Grand Theft Auto Online</a></i>.' ] ],
|
||||
[ 'title' => [ 'value' => 'A Kuruma in <a href="/wiki/Grand_Theft_Auto_Online" title="Grand Theft Auto Online">Grand Theft Auto Online</a>.' ] ]
|
||||
],
|
||||
[
|
||||
[ 'title' => [ 'value' => '<a href="/wiki/User:Idradm" class="new" title="User:Idradm (page does not exist)">Idradm</a> (<a href="/wiki/User_talk:Idradm" title="User talk:Idradm (page does not exist)">talk</a>) 15:34, January 4, 2016 (UTC)' ] ],
|
||||
[ 'title' => [ 'value' => '<a href="/wiki/User:Idradm" class="new" title="User:Idradm (page does not exist)">Idradm</a> (<a href="/wiki/User_talk:Idradm" title="User talk:Idradm (page does not exist)">talk</a>) 15:34, January 4, 2016 (UTC)' ] ]
|
||||
],
|
||||
[
|
||||
[ 'image' => [ 'caption' => 'Test Title' ] ],
|
||||
[ 'image' => [ 'caption' => 'Test Title' ] ]
|
||||
],
|
||||
[
|
||||
[ 'image' => [ 'caption' => 'Real world <a href="http://vignette-poz.wikia-dev.com/mediawiki116/images/b/b6/DBGT_Logo.svg/revision/latest?cb=20150601155347" class="image image-thumbnail" ><img src="http://vignette-poz.wikia-dev.com/mediawiki116/images/b/b6/DBGT_Logo.svg/revision/latest/scale-to-width-down/30?cb=20150601155347" alt="DBGT Logo" class="" data-image-key="DBGT_Logo.svg" data-image-name="DBGT Logo.svg" width="30" height="18" ></a>title example' ] ] ,
|
||||
[ 'image' => [ 'caption' => 'Real world title example' ] ]
|
||||
],
|
||||
[
|
||||
[ 'image' => [ 'caption' => 'Test <a>Title with</a> <span><small>small</small></span> tag, span tag and <img src="sfefes"/>tag' ] ],
|
||||
[ 'image' => [ 'caption' => 'Test <a>Title with</a> small tag, span tag and tag' ] ]
|
||||
],
|
||||
[
|
||||
[ 'image' => [ 'caption' => '<a href="http://vignette-poz.wikia-dev.com//images/9/95/All_Stats_%2B2.png/revision/latest?cb=20151222111955" class="image image-thumbnail"><img src="abc" alt="All Stats +2" class="thumbimage" /></a>' ] ],
|
||||
[ 'image' => [ 'caption' => '' ] ],
|
||||
],
|
||||
[
|
||||
[ 'image' => [ 'caption' => '<figure class="article-thumb tright show-info-icon" style="width: 335px"> <a href="http://mediawiki119.marzjan.wikia-dev.com/wiki/File:AMERICA%27S_TEST_KITCHEN_SEASON_9" class="video video-thumbnail image lightbox medium " itemprop=\'video\' itemscope itemtype="http://schema.org/VideoObject" ><img src="http://vignette-poz.wikia-dev.com//images/6/6e/AMERICA%27S_TEST_KITCHEN_SEASON_9/revision/latest/scale-to-width-down/335?cb=20130904003328" alt="AMERICA'S TEST KITCHEN SEASON 9" class="thumbimage " data-video-key="AMERICA'S_TEST_KITCHEN_SEASON_9" data-video-name="AMERICA'S TEST KITCHEN SEASON 9" width="335" height="187" itemprop="thumbnail" ><span class="duration" itemprop="duration">01:00</span><span class="play-circle"></span><meta itemprop="duration" content="PT01M00S"></a> <figcaption> <a href="/wiki/File:AMERICA%27S_TEST_KITCHEN_SEASON_9" class="sprite info-icon"></a> <p class="title">AMERICA'S TEST KITCHEN SEASON 9</p> </figcaption> </figure>' ] ],
|
||||
[ 'image' => [ 'caption' => 'AMERICA'S TEST KITCHEN SEASON 9' ] ]
|
||||
],
|
||||
[
|
||||
[ 'image' => [ 'caption' => '<sup id="cite_ref-0" class="reference"><a href="#cite_note-0">[1]</a></sup>' ] ],
|
||||
[ 'image' => [ 'caption' => '<sup id="cite_ref-0" class="reference"><a href="#cite_note-0">[1]</a></sup>' ] ]
|
||||
],
|
||||
[
|
||||
[ 'image' => [ 'caption' => '<script>JSSnippetsStack.push({dependencies:[{"url":"http://i3.marzjan.wikia-dev.com/__am/1451462348/group/-/wikia_photo_gallery_js","type":"js"},{"url":"http://i2.marzjan.wikia-dev.com/__am/1451462348/sass/background-dynamic%3D1%26background-image%3D%26background-image-height%3D1185%26background-image-width%3D1600%26color-body%3D%2523bacdd8%26color-body-middle%3D%2523bacdd8%26color-buttons%3D%2523006cb0%26color-header%3D%25233a5766%26color-links%3D%2523006cb0%26color-page%3D%2523ffffff%26oasisTypography%3D1%26page-opacity%3D100%26widthType%3D0/extensions/wikia/WikiaPhotoGallery/css/gallery.scss","type":"css"}],callback:function(json){WikiaPhotoGalleryView.init(json)},id:"WikiaPhotoGalleryView.init"})</script>' ] ],
|
||||
[ 'image' => [ 'caption' => '' ] ]
|
||||
],
|
||||
[
|
||||
[ 'image' => [ 'caption' => '<ul><li>1</li><li>2</li><li>3</li></ul>' ] ],
|
||||
[ 'image' => [ 'caption' => '1 2 3' ] ]
|
||||
],
|
||||
[
|
||||
[ 'image' => [ 'caption' => '<ol><li>1</li><li>2<ol><li>2.1</li></ol></li></ol>' ] ],
|
||||
[ 'image' => [ 'caption' => '1 2 2.1' ] ]
|
||||
],
|
||||
[
|
||||
[ 'image' => [ 'caption' => 'Próxima' ] ],
|
||||
[ 'image' => [ 'caption' => 'Próxima' ] ]
|
||||
],
|
||||
[
|
||||
[ 'image' => [ 'caption' => 'Música de' ] ],
|
||||
[ 'image' => [ 'caption' => 'Música de' ] ]
|
||||
],
|
||||
[
|
||||
[ 'image' => [ 'caption' => 'A <b>Kuruma</b> in <i><a href="/wiki/Grand_Theft_Auto_Online" title="Grand Theft Auto Online">Grand Theft Auto Online</a></i>.' ] ],
|
||||
[ 'image' => [ 'caption' => 'A Kuruma in <a href="/wiki/Grand_Theft_Auto_Online" title="Grand Theft Auto Online">Grand Theft Auto Online</a>.' ] ]
|
||||
],
|
||||
[
|
||||
[ 'image' => [ 'caption' => '<a href="/wiki/User:Idradm" class="new" title="User:Idradm (page does not exist)">Idradm</a> (<a href="/wiki/User_talk:Idradm" title="User talk:Idradm (page does not exist)">talk</a>) 15:34, January 4, 2016 (UTC)' ] ],
|
||||
[ 'image' => [ 'caption' => '<a href="/wiki/User:Idradm" class="new" title="User:Idradm (page does not exist)">Idradm</a> (<a href="/wiki/User_talk:Idradm" title="User talk:Idradm (page does not exist)">talk</a>) 15:34, January 4, 2016 (UTC)' ] ]
|
||||
]
|
||||
];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -45,18 +45,11 @@ class NodeImageSanitizerTest extends WikiaBaseTest {
|
|||
[ 'caption' => '' ]
|
||||
],
|
||||
[
|
||||
[ 'caption' => '<ul><li>1
|
||||
</li><li>2
|
||||
</li><li>3
|
||||
</li></ul>' ],
|
||||
[ 'caption' => '<ul><li>1</li><li>2</li><li>3</li></ul>' ],
|
||||
[ 'caption' => '1 2 3' ]
|
||||
],
|
||||
[
|
||||
[ 'caption' => '<ol><li>1
|
||||
</li><li>2
|
||||
<ol><li>2.1
|
||||
</li></ol>
|
||||
</li></ol>' ],
|
||||
[ 'caption' => '<ol><li>1</li><li>2<ol><li>2.1</li></ol></li></ol>' ],
|
||||
[ 'caption' => '1 2 2.1' ]
|
||||
],
|
||||
[
|
||||
|
@ -66,6 +59,14 @@ class NodeImageSanitizerTest extends WikiaBaseTest {
|
|||
[
|
||||
[ 'caption' => 'Música de' ],
|
||||
[ 'caption' => 'Música de' ]
|
||||
],
|
||||
[
|
||||
[ 'caption' => 'A <b>Kuruma</b> in <i><a href="/wiki/Grand_Theft_Auto_Online" title="Grand Theft Auto Online">Grand Theft Auto Online</a></i>.' ],
|
||||
[ 'caption' => 'A Kuruma in <a href="/wiki/Grand_Theft_Auto_Online" title="Grand Theft Auto Online">Grand Theft Auto Online</a>.' ]
|
||||
],
|
||||
[
|
||||
[ 'caption' => '<a href="/wiki/User:Idradm" class="new" title="User:Idradm (page does not exist)">Idradm</a> (<a href="/wiki/User_talk:Idradm" title="User talk:Idradm (page does not exist)">talk</a>) 15:34, January 4, 2016 (UTC)' ],
|
||||
[ 'caption' => '<a href="/wiki/User:Idradm" class="new" title="User:Idradm (page does not exist)">Idradm</a> (<a href="/wiki/User_talk:Idradm" title="User talk:Idradm (page does not exist)">talk</a>) 15:34, January 4, 2016 (UTC)' ]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue