* @author mwjames
* @author Rowan Rodrik van der Molen
*/
class Gallery extends ResultPrinter {
/**
* @see SMWResultPrinter::getName
*
* @return string
*/
public function getName() {
return $this->msg( 'srf_printername_gallery' )->text();
}
/**
* @see SMWResultPrinter::buildResult
*
* @since 1.8
*
* @param SMWQueryResult $results
*
* @return string
*/
protected function buildResult( SMWQueryResult $results ) {
// Intro/outro are not planned to work with the widget option
if ( ( $this->params['intro'] !== '' || $this->params['outro'] !== '' ) && $this->params['widget'] !== '' ) {
$results->addErrors(
[
$this->msg( 'srf-error-option-mix', 'widget' )->inContentLanguage()->text()
]
);
return '';
};
return $this->getResultText( $results, $this->outputMode );
}
/**
* @see SMWResultPrinter::getResultText
*
* @param $results SMWQueryResult
* @param $outputmode integer
*
* @return string | array
*/
public function getResultText( SMWQueryResult $results, $outputmode ) {
$ig = new TraditionalImageGallery();
$ig->setShowBytes( false );
$ig->setShowFilename( false );
if ( method_exists( $ig, 'setShowDimensions' ) ) {
$ig->setShowDimensions( false );
}
$ig->setCaption( $this->mIntro ); // set caption to IQ header
// No need for a special page to use the parser but for the "normal" page
// view we have to ensure caption text is parsed correctly through the parser
if ( !$this->isSpecialPage() ) {
$ig->setParser( $GLOBALS['wgParser'] );
}
$html = '';
$processing = '';
if ( $this->params['widget'] == 'carousel' ) {
// Carousel widget
$ig->setAttributes( $this->getCarouselWidget() );
} elseif ( $this->params['widget'] == 'slideshow' ) {
// Slideshow widget
$ig->setAttributes( $this->getSlideshowWidget() );
} else {
// Standard gallery attributes
$attribs = [
'id' => uniqid(),
'class' => $this->getImageOverlay(),
];
$ig->setAttributes( $attribs );
}
// Only use redirects where the overlay option is not used and redirect
// thumb images towards a different target
if ( $this->params['redirects'] !== '' && !$this->params['overlay'] ) {
SMWOutputs::requireResource( 'ext.srf.gallery.redirect' );
}
// For the carousel widget, the perrow option should not be set
if ( $this->params['perrow'] !== '' && $this->params['widget'] !== 'carousel' ) {
$ig->setPerRow( $this->params['perrow'] );
}
if ( $this->params['widths'] !== '' ) {
$ig->setWidths( $this->params['widths'] );
}
if ( $this->params['heights'] !== '' ) {
$ig->setHeights( $this->params['heights'] );
}
$printReqLabels = [];
$redirectType = '';
/**
* @var SMWPrintRequest $printReq
*/
foreach ( $results->getPrintRequests() as $printReq ) {
$printReqLabels[] = $printReq->getLabel();
// Get redirect type
if ( $this->params['redirects'] === $printReq->getLabel() ) {
$redirectType = $printReq->getTypeID();
}
}
if ( $this->params['imageproperty'] !== '' && in_array( $this->params['imageproperty'], $printReqLabels ) ||
$this->params['redirects'] !== '' && in_array( $this->params['redirects'], $printReqLabels ) ) {
$this->addImageProperties(
$results,
$ig,
$this->params['imageproperty'],
$this->params['captionproperty'],
$this->params['redirects'],
$outputmode
);
} else {
$this->addImagePages( $results, $ig );
}
// SRF Global settings
SRFUtils::addGlobalJSVariables();
// Display a processing image as long as the DOM is no ready
if ( $this->params['widget'] !== '' ) {
$processing = SRFUtils::htmlProcessingElement();
}
// Beautify the class selector
$class = $this->params['widget'] ? '-' . $this->params['widget'] . ' ' : '';
$class = $this->params['redirects'] !== '' && $this->params['overlay'] === false ? $class . ' srf-redirect' . ' ' : $class;
$class = $this->params['class'] ? $class . ' ' . $this->params['class'] : $class;
// Separate content from result output
if ( !$ig->isEmpty() ) {
$attribs = [
'class' => 'srf-gallery' . $class,
'data-redirect-type' => $redirectType,
'data-ns-text' => $this->getFileNsTextForPageLanguage()
];
$html = Html::rawElement( 'div', $attribs, $processing . $ig->toHTML() );
}
// If available, create a link that points to further results
if ( $this->linkFurtherResults( $results ) ) {
$html .= $this->getLink( $results, SMW_OUTPUT_HTML )->getText( SMW_OUTPUT_HTML, $this->mLinker );
}
return [ $html, 'nowiki' => true, 'isHTML' => true ];
}
/**
* Handles queries where the images (and optionally their captions) are specified as properties.
*
* @since 1.5.3
*
* @param SMWQueryResult $results
* @param TraditionalImageGallery $ig
* @param string $imageProperty
* @param string $captionProperty
* @param string $redirectProperty
* @param $outputMode
*/
protected function addImageProperties( SMWQueryResult $results, &$ig, $imageProperty, $captionProperty, $redirectProperty, $outputMode ) {
while ( /* array of SMWResultArray */
$rows = $results->getNext() ) { // Objects (pages)
$images = [];
$captions = [];
$redirects = [];
for ( $i = 0, $n = count( $rows ); $i < $n; $i++ ) { // Properties
/**
* @var \SMWResultArray $resultArray
* @var \SMWDataValue $dataValue
*/
$resultArray = $rows[$i];
$label = $resultArray->getPrintRequest()->getMode() == SMWPrintRequest::PRINT_THIS
? '-' : $resultArray->getPrintRequest()->getLabel();
// Make sure always use real label here otherwise it results in an empty array
if ( $resultArray->getPrintRequest()->getLabel() == $imageProperty ) {
while ( ( $dataValue = $resultArray->getNextDataValue() ) !== false ) { // Property values
if ( $dataValue->getTypeID() == '_wpg' ) {
$images[] = $dataValue->getDataItem()->getTitle();
}
}
} elseif ( $label == $captionProperty ) {
while ( ( $dataValue = $resultArray->getNextDataValue() ) !== false ) { // Property values
$captions[] = $dataValue->getShortText( $outputMode, $this->getLinker( true ) );
}
} elseif ( $label == $redirectProperty ) {
while ( ( $dataValue = $resultArray->getNextDataValue() ) !== false ) { // Property values
if ( $dataValue->getDataItem()->getDIType() == SMWDataItem::TYPE_WIKIPAGE ) {
$redirects[] = $dataValue->getTitle();
} elseif ( $dataValue->getDataItem()->getDIType() == SMWDataItem::TYPE_URI ) {
$redirects[] = $dataValue->getURL();
}
}
}
}
// Check available matches against captions
$amountMatches = count( $captions ) == count( $images );
$hasCaption = $amountMatches || count( $captions ) > 0;
// Check available matches against redirects
$amountRedirects = count( $redirects ) == count( $images );
$hasRedirect = $amountRedirects || count( $redirects ) > 0;
/**
* @var Title $imgTitle
*/
foreach ( $images as $imgTitle ) {
if ( $imgTitle->exists() ) {
$imgCaption = $hasCaption ? ( $amountMatches ? array_shift( $captions ) : $captions[0] ) : '';
$imgRedirect = $hasRedirect ? ( $amountRedirects ? array_shift( $redirects ) : $redirects[0] ) : '';
$this->addImageToGallery( $ig, $imgTitle, $imgCaption, $imgRedirect );
}
}
}
}
/**
* Handles queries where the result objects are image pages.
*
* @since 1.5.3
*
* @param SMWQueryResult $results
* @param TraditionalImageGallery $ig
*/
protected function addImagePages( SMWQueryResult $results, &$ig ) {
while ( $row = $results->getNext() ) {
/**
* @var \SMWResultArray $firstField
*/
$firstField = $row[0];
/** @var \SMWDataValue $nextObject */
$nextObject = $firstField->getNextDataValue();
if ( $nextObject !== false ) {
$dataItem = $nextObject->getDataItem();
$imgTitle = method_exists( $dataItem, 'getTitle' ) ? $dataItem->getTitle() : null;
// Ensure the title belongs to the image namespace
if ( $imgTitle instanceof Title && $imgTitle->getNamespace() === NS_FILE ) {
$imgCaption = '';
// Is there a property queried for display with ?property
if ( isset( $row[1] ) ) {
$imgCaption = $row[1]->getNextDataValue();
if ( is_object( $imgCaption ) ) {
$imgCaption = $imgCaption->getShortText( $this->outputMode, $this->getLinker( true ) );
}
}
$this->addImageToGallery( $ig, $imgTitle, $imgCaption );
}
}
}
}
/**
* Adds a single image to the gallery.
* Takes care of automatically adding a caption when none is provided and parsing it's wikitext.
*
* @since 1.5.3
*
* @param TraditionalImageGallery $ig The gallery to add the image to
* @param Title $imgTitle The title object of the page of the image
* @param string $imgCaption An optional caption for the image
* @param string $imgRedirect
*/
protected function addImageToGallery( &$ig, Title $imgTitle, $imgCaption, $imgRedirect = '' ) {
if ( empty( $imgCaption ) ) {
if ( $this->params['autocaptions'] ) {
$imgCaption = $imgTitle->getBaseText();
if ( !$this->params['fileextensions'] ) {
$imgCaption = preg_replace( '#\.[^.]+$#', '', $imgCaption );
}
} else {
$imgCaption = '';
}
} else {
if ( $imgTitle instanceof Title && $imgTitle->getNamespace() == NS_FILE && !$this->isSpecialPage() ) {
$imgCaption = $ig->mParser->recursiveTagParse( $imgCaption );
}
}
// Use image alt as helper for either text
$imgAlt = $this->params['redirects'] === '' ? $imgCaption : $imgRedirect !== '' ? $imgRedirect : '';
$ig->add( $imgTitle, $imgCaption, $imgAlt );
}
/**
* Returns the overlay setting
*
* @since 1.8
*
* @return string
*/
private function getImageOverlay() {
if ( array_key_exists( 'overlay', $this->params ) && $this->params['overlay'] == true ) {
SMWOutputs::requireResource( 'ext.srf.gallery.overlay' );
return ' srf-overlay';
} else {
return '';
}
}
/**
* Init carousel widget
*
* @since 1.8
*
* @return string[]
*/
private function getCarouselWidget() {
// Set attributes for jcarousel
$dataAttribs = [
'wrap' => 'both', // Whether to wrap at the first/last item (or both) and jump back to the start/end.
'vertical' => 'false', // Orientation: vertical = false means horizontal
'rtl' => 'false', // Directionality: rtl = false means ltr
];
// Use the perrow parameter to determine the scroll sequence.
if ( empty( $this->params['perrow'] ) ) {
$dataAttribs['scroll'] = 1; // default 1
} else {
$dataAttribs['scroll'] = $this->params['perrow'];
$dataAttribs['visible'] = $this->params['perrow'];
}
$attribs = [
'id' => uniqid(),
'class' => 'jcarousel jcarousel-skin-smw' . $this->getImageOverlay(),
'style' => 'display:none;',
];
foreach ( $dataAttribs as $name => $value ) {
$attribs['data-' . $name] = $value;
}
SMWOutputs::requireResource( 'ext.srf.gallery.carousel' );
return $attribs;
}
/**
* Init slideshow widget
*
* @since 1.8
*
* @return string[]
*/
private function getSlideshowWidget() {
$attribs = [
'id' => uniqid(),
'class' => $this->getImageOverlay(),
'style' => 'display:none;',
'data-nav-control' => $this->params['navigation']
];
SMWOutputs::requireResource( 'ext.srf.gallery.slideshow' );
return $attribs;
}
/**
* @see SMWResultPrinter::getParamDefinitions
*
* @since 1.8
*
* @param $definitions array of IParamDefinition
*
* @return array of IParamDefinition|array
*/
public function getParamDefinitions( array $definitions ) {
$params = parent::getParamDefinitions( $definitions );
$params['class'] = [
'type' => 'string',
'message' => 'srf-paramdesc-class',
'default' => ''
];
$params['widget'] = [
'type' => 'string',
'default' => '',
'message' => 'srf-paramdesc-widget',
'values' => [ 'carousel', 'slideshow', '' ]
];
$params['navigation'] = [
'type' => 'string',
'default' => 'nav',
'message' => 'srf-paramdesc-navigation',
'values' => [ 'nav', 'pager', 'auto' ]
];
$params['overlay'] = [
'type' => 'boolean',
'default' => false,
'message' => 'srf-paramdesc-overlay'
];
$params['perrow'] = [
'type' => 'integer',
'default' => '',
'message' => 'srf_paramdesc_perrow'
];
$params['widths'] = [
'type' => 'integer',
'default' => '',
'message' => 'srf_paramdesc_widths'
];
$params['heights'] = [
'type' => 'integer',
'default' => '',
'message' => 'srf_paramdesc_heights'
];
$params['autocaptions'] = [
'type' => 'boolean',
'default' => true,
'message' => 'srf_paramdesc_autocaptions'
];
$params['fileextensions'] = [
'type' => 'boolean',
'default' => false,
'message' => 'srf_paramdesc_fileextensions'
];
$params['captionproperty'] = [
'type' => 'string',
'default' => '',
'message' => 'srf_paramdesc_captionproperty'
];
$params['imageproperty'] = [
'type' => 'string',
'default' => '',
'message' => 'srf_paramdesc_imageproperty'
];
$params['redirects'] = [
'type' => 'string',
'default' => '',
'message' => 'srf-paramdesc-redirects'
];
return $params;
}
/**
* @return bool
*/
private function isSpecialPage() {
$title = $GLOBALS['wgTitle'];
return $title instanceof Title && $title->isSpecialPage();
}
/**
* @return bool|null|string
*/
private function getFileNsTextForPageLanguage() {
$title = $GLOBALS['wgTitle'];
return $title instanceof Title ? $title->getPageLanguage()->getNsText( NS_FILE ) : null;
}
}