2015-04-27 14:05:31 +00:00
|
|
|
<?php
|
|
|
|
namespace Wikia\PortableInfobox\Parser\Nodes;
|
|
|
|
|
2016-01-12 09:50:24 +00:00
|
|
|
use HtmlHelper;
|
2017-01-25 11:18:20 +00:00
|
|
|
use Wikia\PortableInfobox\Helpers\PortableInfoboxDataBag;
|
2015-07-21 14:29:14 +00:00
|
|
|
use WikiaFileHelper;
|
2015-05-07 12:37:13 +00:00
|
|
|
|
2015-04-27 14:05:31 +00:00
|
|
|
class NodeImage extends Node {
|
2017-01-25 11:18:20 +00:00
|
|
|
const GALLERY = 'GALLERY';
|
|
|
|
const TABBER = 'TABBER';
|
|
|
|
|
2015-04-27 14:05:31 +00:00
|
|
|
const ALT_TAG_NAME = 'alt';
|
2015-05-19 07:56:57 +00:00
|
|
|
const CAPTION_TAG_NAME = 'caption';
|
2015-07-21 14:29:14 +00:00
|
|
|
const MEDIA_TYPE_VIDEO = 'VIDEO';
|
2015-04-27 14:05:31 +00:00
|
|
|
|
2015-10-20 22:42:36 +00:00
|
|
|
public static function getMarkers( $value, $ext ) {
|
2018-07-28 13:59:24 +00:00
|
|
|
if ( preg_match_all('/' . \Parser::MARKER_PREFIX . '-' . $ext . '-[A-F0-9]{8}' . \Parser::MARKER_SUFFIX . '/is', $value, $out ) ) {
|
2015-10-20 22:42:36 +00:00
|
|
|
return $out[0];
|
|
|
|
} else {
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-25 11:18:20 +00:00
|
|
|
public static function getGalleryData( $marker ) {
|
|
|
|
$galleryData = PortableInfoboxDataBag::getInstance()->getGallery( $marker );
|
2017-02-22 15:56:13 +00:00
|
|
|
return isset( $galleryData['images'] ) ? array_map( function ( $image ) {
|
2017-01-25 11:18:20 +00:00
|
|
|
return [
|
2017-02-22 15:56:13 +00:00
|
|
|
'label' => $image['caption'],
|
|
|
|
'title' => $image['name']
|
2017-01-25 11:18:20 +00:00
|
|
|
];
|
2017-02-22 15:56:13 +00:00
|
|
|
}, $galleryData['images'] ) : [ ];
|
2015-10-20 22:42:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public static function getTabberData( $html ) {
|
2015-10-21 00:03:06 +00:00
|
|
|
global $wgArticleAsJson;
|
2015-10-20 22:42:36 +00:00
|
|
|
$data = array();
|
2016-01-12 09:50:24 +00:00
|
|
|
$doc = HtmlHelper::createDOMDocumentFromText( $html );
|
2015-10-20 22:42:36 +00:00
|
|
|
$sxml = simplexml_import_dom( $doc );
|
|
|
|
$divs = $sxml->xpath( '//div[@class=\'tabbertab\']' );
|
|
|
|
foreach ( $divs as $div ) {
|
|
|
|
if ( $wgArticleAsJson ) {
|
2015-10-27 20:02:58 +00:00
|
|
|
if ( preg_match( '/data-ref="([^"]+)"/', $div->asXML(), $out ) ) {
|
2015-10-20 22:42:36 +00:00
|
|
|
$data[] = array( 'label' => (string) $div['title'], 'title' => \ArticleAsJson::$media[$out[1]]['title'] );
|
|
|
|
}
|
|
|
|
} else {
|
2015-10-27 20:02:58 +00:00
|
|
|
if ( preg_match( '/data-(video|image)-key="([^"]+)"/', $div->asXML(), $out ) ) {
|
2015-10-21 00:48:37 +00:00
|
|
|
$data[] = array( 'label' => (string) $div['title'], 'title' => $out[2] );
|
2015-10-20 22:42:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return $data;
|
|
|
|
}
|
|
|
|
|
2015-04-27 14:05:31 +00:00
|
|
|
public function getData() {
|
2015-06-11 09:34:28 +00:00
|
|
|
if ( !isset( $this->data ) ) {
|
2015-10-16 01:15:52 +00:00
|
|
|
$this->data = array();
|
2015-06-19 10:31:22 +00:00
|
|
|
|
2015-10-16 01:15:52 +00:00
|
|
|
// value passed to source parameter (or default)
|
|
|
|
$value = $this->getRawValueWithDefault( $this->xmlNode );
|
2015-06-19 10:31:22 +00:00
|
|
|
|
2015-10-16 01:15:52 +00:00
|
|
|
if ( $this->containsTabberOrGallery( $value ) ) {
|
|
|
|
$this->data = $this->getImagesData( $value );
|
|
|
|
} else {
|
|
|
|
$this->data = array( $this->getImageData(
|
|
|
|
$value,
|
|
|
|
$this->getValueWithDefault( $this->xmlNode->{self::ALT_TAG_NAME} ),
|
|
|
|
$this->getValueWithDefault( $this->xmlNode->{self::CAPTION_TAG_NAME} )
|
|
|
|
) );
|
2015-08-31 11:53:06 +00:00
|
|
|
}
|
2015-10-16 01:15:52 +00:00
|
|
|
}
|
|
|
|
return $this->data;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @desc Checks if parser preprocessed string containg Tabber or Gallery extension
|
|
|
|
* @param string $str String to check
|
|
|
|
* @return bool
|
|
|
|
*/
|
|
|
|
private function containsTabberOrGallery( $str ) {
|
2017-01-25 11:18:20 +00:00
|
|
|
return !empty( self::getMarkers( $str, self::TABBER ) ) || !empty( self::getMarkers( $str, self::GALLERY ) );
|
2015-10-16 01:15:52 +00:00
|
|
|
}
|
|
|
|
|
2015-10-20 01:19:49 +00:00
|
|
|
private function getImagesData( $value ) {
|
|
|
|
$data = array();
|
|
|
|
$items = array_merge( $this->getGalleryItems( $value ), $this->getTabberItems( $value ) );
|
2017-01-25 11:18:20 +00:00
|
|
|
foreach( $items as $item ) {
|
|
|
|
$data[] = $this->getImageData( $item['title'], $item['label'], $item['label'] );
|
2015-10-16 01:15:52 +00:00
|
|
|
}
|
2015-10-20 01:19:49 +00:00
|
|
|
return $data;
|
2015-10-19 23:56:20 +00:00
|
|
|
}
|
2015-10-16 01:15:52 +00:00
|
|
|
|
2015-10-20 01:19:49 +00:00
|
|
|
private function getGalleryItems( $value ) {
|
2017-01-25 11:18:20 +00:00
|
|
|
$galleryItems = [];
|
|
|
|
$galleryMarkers = self::getMarkers( $value, self::GALLERY );
|
|
|
|
foreach ( $galleryMarkers as $marker ) {
|
|
|
|
$galleryItems = array_merge( $galleryItems, self::getGalleryData( $marker ) );
|
|
|
|
|
2015-06-11 09:34:28 +00:00
|
|
|
}
|
2015-10-20 01:19:49 +00:00
|
|
|
return $galleryItems;
|
2015-10-16 01:15:52 +00:00
|
|
|
}
|
2015-06-10 09:28:33 +00:00
|
|
|
|
2015-10-20 23:09:23 +00:00
|
|
|
private function getTabberItems( $value ) {
|
2015-10-19 23:56:20 +00:00
|
|
|
$tabberItems = array();
|
2017-01-25 11:18:20 +00:00
|
|
|
$tabberMarkers = self::getMarkers( $value, self::TABBER );
|
|
|
|
foreach ( $tabberMarkers as $marker ) {
|
|
|
|
$tabberHtml = $this->getExternalParser()->parseRecursive( $marker );
|
2015-10-20 22:42:36 +00:00
|
|
|
$tabberItems = array_merge( $tabberItems, self::getTabberData( $tabberHtml ) );
|
2015-10-19 23:56:20 +00:00
|
|
|
}
|
2015-10-20 01:19:49 +00:00
|
|
|
return $tabberItems;
|
|
|
|
}
|
|
|
|
|
2015-12-23 10:20:39 +00:00
|
|
|
/**
|
|
|
|
* @desc prepare infobox image node data.
|
2015-12-23 12:20:55 +00:00
|
|
|
*
|
2015-12-23 10:20:39 +00:00
|
|
|
* @param $title
|
|
|
|
* @param $alt
|
|
|
|
* @param $caption
|
|
|
|
* @return array
|
|
|
|
*/
|
2015-10-16 01:15:52 +00:00
|
|
|
private function getImageData( $title, $alt, $caption ) {
|
|
|
|
$titleObj = $this->getImageAsTitleObject( $title );
|
|
|
|
$fileObj = $this->getFilefromTitle( $titleObj );
|
|
|
|
|
|
|
|
if ( $titleObj instanceof \Title ) {
|
|
|
|
$this->getExternalParser()->addImage( $titleObj->getDBkey() );
|
|
|
|
}
|
|
|
|
|
|
|
|
$image = [
|
|
|
|
'url' => $this->resolveImageUrl( $fileObj ),
|
|
|
|
'name' => $titleObj ? $titleObj->getText() : '',
|
|
|
|
'key' => $titleObj ? $titleObj->getDBKey() : '',
|
|
|
|
'alt' => $alt,
|
2017-10-03 08:52:40 +00:00
|
|
|
'caption' => \SanitizerBuilder::createFromType( 'image' )
|
|
|
|
->sanitize( [ 'caption' => $caption ] )['caption'],
|
2016-04-20 08:38:44 +00:00
|
|
|
'isVideo' => false
|
2015-10-16 01:15:52 +00:00
|
|
|
];
|
|
|
|
|
|
|
|
if ( $this->isVideo( $fileObj ) ) {
|
|
|
|
$image = $this->videoDataDecorator( $image, $fileObj );
|
|
|
|
}
|
|
|
|
|
|
|
|
return $image;
|
2015-04-27 14:05:31 +00:00
|
|
|
}
|
|
|
|
|
2015-06-10 09:28:33 +00:00
|
|
|
public function isEmpty() {
|
2015-06-11 09:34:28 +00:00
|
|
|
$data = $this->getData();
|
2015-10-16 01:15:52 +00:00
|
|
|
foreach ( $data as $dataItem ) {
|
|
|
|
if ( !empty( $dataItem[ 'url' ] ) ) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
2015-05-06 14:11:04 +00:00
|
|
|
}
|
|
|
|
|
2016-12-09 13:01:49 +00:00
|
|
|
public function getSources() {
|
|
|
|
$sources = $this->extractSourcesFromNode( $this->xmlNode );
|
2015-06-11 09:48:32 +00:00
|
|
|
if ( $this->xmlNode->{self::ALT_TAG_NAME} ) {
|
|
|
|
$sources = array_merge( $sources,
|
2016-12-09 13:01:49 +00:00
|
|
|
$this->extractSourcesFromNode( $this->xmlNode->{self::ALT_TAG_NAME} ) );
|
2015-06-11 09:48:32 +00:00
|
|
|
}
|
|
|
|
if ( $this->xmlNode->{self::CAPTION_TAG_NAME} ) {
|
|
|
|
$sources = array_merge( $sources,
|
2016-12-09 13:01:49 +00:00
|
|
|
$this->extractSourcesFromNode( $this->xmlNode->{self::CAPTION_TAG_NAME} ) );
|
2015-06-11 09:48:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return array_unique( $sources );
|
|
|
|
}
|
|
|
|
|
2015-05-11 12:36:23 +00:00
|
|
|
private function getImageAsTitleObject( $imageName ) {
|
2015-05-04 15:43:09 +00:00
|
|
|
global $wgContLang;
|
2015-08-31 11:53:06 +00:00
|
|
|
$title = \Title::makeTitleSafe(
|
|
|
|
NS_FILE,
|
2015-11-25 10:00:39 +00:00
|
|
|
\FileNamespaceSanitizeHelper::getInstance()->sanitizeImageFileName( $imageName, $wgContLang )
|
2015-05-07 12:37:13 +00:00
|
|
|
);
|
2015-06-03 14:53:31 +00:00
|
|
|
|
2015-05-11 12:36:23 +00:00
|
|
|
return $title;
|
|
|
|
}
|
|
|
|
|
2015-07-21 14:29:14 +00:00
|
|
|
/**
|
|
|
|
* @desc get file object from title object
|
|
|
|
* @param Title|null $title
|
|
|
|
* @return File|null
|
|
|
|
*/
|
|
|
|
private function getFilefromTitle( $title ) {
|
|
|
|
return $title ? WikiaFileHelper::getFileFromTitle( $title ) : null;
|
|
|
|
}
|
|
|
|
|
2015-05-22 15:27:20 +00:00
|
|
|
/**
|
|
|
|
* @desc returns image url for given image title
|
2015-07-21 14:29:14 +00:00
|
|
|
* @param File|null $file
|
2015-05-22 15:27:20 +00:00
|
|
|
* @return string url or '' if image doesn't exist
|
|
|
|
*/
|
2015-07-21 14:29:14 +00:00
|
|
|
public function resolveImageUrl( $file ) {
|
|
|
|
return $file ? $file->getUrl() : '';
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @desc checks if file media type is VIDEO
|
|
|
|
* @param File|null $file
|
|
|
|
* @return bool
|
|
|
|
*/
|
|
|
|
private function isVideo( $file ) {
|
|
|
|
return $file ? $file->getMediaType() === self::MEDIA_TYPE_VIDEO : false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @desc add addtional data required for video media type
|
|
|
|
* @param array $data
|
|
|
|
* @param File $file
|
|
|
|
* @return array
|
|
|
|
*/
|
2015-09-09 11:23:34 +00:00
|
|
|
private function videoDataDecorator( $data, $file ) {
|
|
|
|
$title = $file->getTitle();
|
|
|
|
|
|
|
|
if ( $title ) {
|
|
|
|
$data[ 'url' ] = $title->getFullURL();
|
|
|
|
}
|
|
|
|
|
2015-09-07 15:38:17 +00:00
|
|
|
$data[ 'isVideo' ] = true;
|
|
|
|
$data[ 'duration' ] = WikiaFileHelper::formatDuration( $file->getMetadataDuration());
|
2015-06-03 14:53:31 +00:00
|
|
|
|
2015-07-21 14:29:14 +00:00
|
|
|
return $data;
|
2015-04-27 14:05:31 +00:00
|
|
|
}
|
|
|
|
}
|