2012-02-29 10:50:36 +00:00
|
|
|
<?php
|
|
|
|
|
2015-11-16 14:59:34 +00:00
|
|
|
/**
|
|
|
|
* @license WTFPL 2.0
|
2015-11-17 08:54:24 +00:00
|
|
|
* @author Max Semenik
|
2015-11-16 14:59:34 +00:00
|
|
|
* @author Brad Jorsch
|
2017-11-24 07:33:49 +00:00
|
|
|
* @author Thiemo Kreuz
|
2015-11-16 14:59:34 +00:00
|
|
|
*/
|
2012-02-29 10:50:36 +00:00
|
|
|
class PageImages {
|
2015-11-16 14:59:34 +00:00
|
|
|
|
2013-11-04 22:00:38 +00:00
|
|
|
/**
|
2016-11-10 00:02:00 +00:00
|
|
|
* Page property used to store the best page image information.
|
|
|
|
* If the best image is the same as the best image with free license,
|
|
|
|
* then nothing is stored under this property.
|
2017-01-23 21:53:05 +00:00
|
|
|
* Note changing this value is not advised as it will invalidate all
|
|
|
|
* existing page property names on a production instance
|
|
|
|
* and cause them to be regenerated.
|
2016-11-10 00:02:00 +00:00
|
|
|
* @see PageImages::PROP_NAME_FREE
|
2013-11-04 22:00:38 +00:00
|
|
|
*/
|
|
|
|
const PROP_NAME = 'page_image';
|
2017-01-31 12:59:16 +00:00
|
|
|
|
2016-11-10 00:02:00 +00:00
|
|
|
/**
|
|
|
|
* Page property used to store the best free page image information
|
2017-01-23 21:53:05 +00:00
|
|
|
* Note changing this value is not advised as it will invalidate all
|
|
|
|
* existing page property names on a production instance
|
|
|
|
* and cause them to be regenerated.
|
2016-11-10 00:02:00 +00:00
|
|
|
*/
|
|
|
|
const PROP_NAME_FREE = 'page_image_free';
|
|
|
|
|
|
|
|
/**
|
2017-01-23 21:53:05 +00:00
|
|
|
* Get property name used in page_props table. When a page image
|
|
|
|
* is stored it will be stored under this property name on the corresponding
|
|
|
|
* article.
|
2016-11-10 00:02:00 +00:00
|
|
|
*
|
|
|
|
* @param bool $isFree Whether the image is a free-license image
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
public static function getPropName( $isFree ) {
|
|
|
|
return $isFree ? self::PROP_NAME_FREE : self::PROP_NAME;
|
|
|
|
}
|
2013-11-04 22:00:38 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns page image for a given title
|
|
|
|
*
|
2017-09-01 04:54:58 +00:00
|
|
|
* @param Title $title Title to get page image for
|
2013-11-04 22:00:38 +00:00
|
|
|
*
|
2014-06-18 19:58:12 +00:00
|
|
|
* @return File|bool
|
2013-11-04 22:00:38 +00:00
|
|
|
*/
|
|
|
|
public static function getPageImage( Title $title ) {
|
2017-09-24 05:30:58 +00:00
|
|
|
$dbr = wfGetDB( DB_REPLICA );
|
2016-12-03 01:57:30 +00:00
|
|
|
$fileName = $dbr->selectField( 'page_props',
|
|
|
|
[ 'pp_value' ],
|
2017-05-30 19:49:44 +00:00
|
|
|
[
|
|
|
|
'pp_page' => $title->getArticleID(),
|
|
|
|
'pp_propname' => [ self::PROP_NAME, self::PROP_NAME_FREE ]
|
|
|
|
],
|
2016-12-03 01:57:30 +00:00
|
|
|
__METHOD__,
|
|
|
|
[ 'ORDER BY' => 'pp_propname' ]
|
2013-11-04 22:00:38 +00:00
|
|
|
);
|
2015-11-16 14:59:34 +00:00
|
|
|
|
2014-06-18 19:58:12 +00:00
|
|
|
$file = false;
|
2016-12-03 01:57:30 +00:00
|
|
|
if ( $fileName ) {
|
|
|
|
$file = wfFindFile( $fileName );
|
2013-11-04 22:00:38 +00:00
|
|
|
}
|
2015-11-16 14:59:34 +00:00
|
|
|
|
2013-11-04 22:00:38 +00:00
|
|
|
return $file;
|
|
|
|
}
|
|
|
|
|
2014-05-02 06:29:28 +00:00
|
|
|
/**
|
|
|
|
* InfoAction hook handler, adds the page image to the info=action page
|
2015-10-26 10:41:13 +00:00
|
|
|
*
|
2014-05-02 06:29:28 +00:00
|
|
|
* @see https://www.mediawiki.org/wiki/Manual:Hooks/InfoAction
|
2015-10-26 10:41:13 +00:00
|
|
|
*
|
2014-05-02 06:29:28 +00:00
|
|
|
* @param IContextSource $context
|
2015-10-26 10:41:13 +00:00
|
|
|
* @param array[] &$pageInfo
|
2014-05-02 06:29:28 +00:00
|
|
|
*/
|
|
|
|
public static function onInfoAction( IContextSource $context, &$pageInfo ) {
|
2016-01-26 18:07:39 +00:00
|
|
|
global $wgThumbLimits;
|
2014-05-02 06:29:28 +00:00
|
|
|
|
|
|
|
$imageFile = self::getPageImage( $context->getTitle() );
|
2014-06-18 19:58:12 +00:00
|
|
|
if ( !$imageFile ) {
|
2014-05-02 06:29:28 +00:00
|
|
|
// The page has no image
|
2016-03-07 08:47:51 +00:00
|
|
|
return;
|
2014-05-02 06:29:28 +00:00
|
|
|
}
|
|
|
|
|
2016-01-26 18:07:39 +00:00
|
|
|
$thumbSetting = $context->getUser()->getOption( 'thumbsize' );
|
2014-05-02 06:29:28 +00:00
|
|
|
$thumbSize = $wgThumbLimits[$thumbSetting];
|
|
|
|
|
2016-11-21 23:29:28 +00:00
|
|
|
$thumb = $imageFile->transform( [ 'width' => $thumbSize ] );
|
2014-06-18 19:58:12 +00:00
|
|
|
if ( !$thumb ) {
|
2016-03-07 08:47:51 +00:00
|
|
|
return;
|
2014-06-18 19:58:12 +00:00
|
|
|
}
|
|
|
|
$imageHtml = $thumb->toHtml(
|
2016-11-21 23:29:28 +00:00
|
|
|
[
|
2014-05-02 06:29:28 +00:00
|
|
|
'alt' => $imageFile->getTitle()->getText(),
|
|
|
|
'desc-link' => true,
|
2016-11-21 23:29:28 +00:00
|
|
|
]
|
2014-05-02 06:29:28 +00:00
|
|
|
);
|
|
|
|
|
2016-11-21 23:29:28 +00:00
|
|
|
$pageInfo['header-basic'][] = [
|
2014-05-02 06:29:28 +00:00
|
|
|
$context->msg( 'pageimages-info-label' ),
|
|
|
|
$imageHtml
|
2016-11-21 23:29:28 +00:00
|
|
|
];
|
2014-05-02 06:29:28 +00:00
|
|
|
}
|
|
|
|
|
2012-05-08 21:42:07 +00:00
|
|
|
/**
|
2014-11-05 22:18:30 +00:00
|
|
|
* ApiOpenSearchSuggest hook handler, enhances ApiOpenSearch results with this extension's data
|
2015-10-26 10:41:13 +00:00
|
|
|
*
|
|
|
|
* @param array[] &$results
|
2012-05-08 21:42:07 +00:00
|
|
|
*/
|
2015-10-31 01:30:18 +00:00
|
|
|
public static function onApiOpenSearchSuggest( array &$results ) {
|
2012-03-08 14:01:00 +00:00
|
|
|
global $wgPageImagesExpandOpenSearchXml;
|
2015-01-20 23:37:08 +00:00
|
|
|
|
2012-03-08 14:01:00 +00:00
|
|
|
if ( !$wgPageImagesExpandOpenSearchXml || !count( $results ) ) {
|
2016-03-07 08:47:51 +00:00
|
|
|
return;
|
2012-03-08 14:01:00 +00:00
|
|
|
}
|
2015-10-26 10:41:13 +00:00
|
|
|
|
2012-03-08 14:01:00 +00:00
|
|
|
$pageIds = array_keys( $results );
|
2014-09-19 18:41:48 +00:00
|
|
|
$data = self::getImages( $pageIds, 50 );
|
2012-03-08 14:01:00 +00:00
|
|
|
foreach ( $pageIds as $id ) {
|
2014-09-19 18:41:48 +00:00
|
|
|
if ( isset( $data[$id]['thumbnail'] ) ) {
|
|
|
|
$results[$id]['image'] = $data[$id]['thumbnail'];
|
2012-03-08 14:01:00 +00:00
|
|
|
} else {
|
|
|
|
$results[$id]['image'] = null;
|
|
|
|
}
|
|
|
|
}
|
2012-05-08 21:42:07 +00:00
|
|
|
}
|
|
|
|
|
2014-09-19 18:41:48 +00:00
|
|
|
/**
|
|
|
|
* SpecialMobileEditWatchlist::images hook handler, adds images to mobile watchlist A-Z view
|
|
|
|
*
|
|
|
|
* @param IContextSource $context
|
2015-10-26 10:41:13 +00:00
|
|
|
* @param array[] $watchlist
|
|
|
|
* @param array[] &$images
|
2014-09-19 18:41:48 +00:00
|
|
|
*/
|
2016-11-21 23:29:28 +00:00
|
|
|
public static function onSpecialMobileEditWatchlist_images(
|
|
|
|
IContextSource $context, array $watchlist, array &$images
|
2014-09-19 18:41:48 +00:00
|
|
|
) {
|
2016-11-21 23:29:28 +00:00
|
|
|
$ids = [];
|
2014-09-19 18:41:48 +00:00
|
|
|
foreach ( $watchlist as $ns => $pages ) {
|
|
|
|
foreach ( array_keys( $pages ) as $dbKey ) {
|
|
|
|
$title = Title::makeTitle( $ns, $dbKey );
|
|
|
|
// Getting page ID here is safe because SpecialEditWatchlist::getWatchlistInfo()
|
|
|
|
// uses LinkBatch
|
|
|
|
$id = $title->getArticleID();
|
|
|
|
if ( $id ) {
|
|
|
|
$ids[$id] = $dbKey;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-10-26 10:41:13 +00:00
|
|
|
|
2014-09-19 18:41:48 +00:00
|
|
|
$data = self::getImages( array_keys( $ids ) );
|
|
|
|
foreach ( $data as $id => $page ) {
|
|
|
|
if ( isset( $page['pageimage'] ) ) {
|
|
|
|
$images[ $page['ns'] ][ $ids[$id] ] = $page['pageimage'];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns image information for pages with given ids
|
|
|
|
*
|
2015-10-26 10:41:13 +00:00
|
|
|
* @param int[] $pageIds
|
|
|
|
* @param int $size
|
2015-11-16 14:59:34 +00:00
|
|
|
*
|
2015-10-26 10:41:13 +00:00
|
|
|
* @return array[]
|
2014-09-19 18:41:48 +00:00
|
|
|
*/
|
|
|
|
private static function getImages( array $pageIds, $size = 0 ) {
|
2017-05-26 21:23:42 +00:00
|
|
|
$ret = [];
|
|
|
|
foreach ( array_chunk( $pageIds, ApiBase::LIMIT_SML1 ) as $chunk ) {
|
|
|
|
$request = [
|
|
|
|
'action' => 'query',
|
|
|
|
'prop' => 'pageimages',
|
|
|
|
'piprop' => 'name',
|
|
|
|
'pageids' => implode( '|', $chunk ),
|
|
|
|
'pilimit' => 'max',
|
|
|
|
];
|
|
|
|
|
|
|
|
if ( $size ) {
|
|
|
|
$request['piprop'] = 'thumbnail';
|
|
|
|
$request['pithumbsize'] = $size;
|
|
|
|
}
|
2015-11-16 14:59:34 +00:00
|
|
|
|
2017-05-26 21:23:42 +00:00
|
|
|
$api = new ApiMain( new FauxRequest( $request ) );
|
|
|
|
$api->execute();
|
2015-11-16 14:59:34 +00:00
|
|
|
|
2017-05-26 21:23:42 +00:00
|
|
|
if ( defined( 'ApiResult::META_CONTENT' ) ) {
|
|
|
|
$ret += (array)$api->getResult()->getResultData( [ 'query', 'pages' ],
|
|
|
|
[ 'Strip' => 'base' ] );
|
|
|
|
} else {
|
|
|
|
$data = $api->getResultData();
|
|
|
|
if ( isset( $data['query']['pages'] ) ) {
|
|
|
|
$ret += $data['query']['pages'];
|
|
|
|
}
|
2014-12-30 22:20:55 +00:00
|
|
|
}
|
2014-09-19 18:41:48 +00:00
|
|
|
}
|
2017-05-26 21:23:42 +00:00
|
|
|
return $ret;
|
2014-09-19 18:41:48 +00:00
|
|
|
}
|
|
|
|
|
2017-12-06 22:44:34 +00:00
|
|
|
/**
|
|
|
|
* Hook function called after the extension is loaded to define PAGE_IMAGES_INSTALLED
|
|
|
|
* @return null
|
|
|
|
*/
|
2016-09-16 20:57:33 +00:00
|
|
|
public static function onRegistration() {
|
|
|
|
define( 'PAGE_IMAGES_INSTALLED', true );
|
|
|
|
}
|
2017-01-28 15:43:55 +00:00
|
|
|
|
2017-01-31 12:59:16 +00:00
|
|
|
/**
|
|
|
|
* @param OutputPage &$out
|
|
|
|
* @param Skin &$skin
|
|
|
|
*/
|
2017-01-28 15:43:55 +00:00
|
|
|
public static function onBeforePageDisplay( OutputPage &$out, Skin &$skin ) {
|
|
|
|
$imageFile = self::getPageImage( $out->getContext()->getTitle() );
|
|
|
|
if ( !$imageFile ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// See https://developers.facebook.com/docs/sharing/best-practices?locale=en_US#tags
|
2017-02-01 15:37:25 +00:00
|
|
|
$thumb = $imageFile->transform( [ 'width' => 1200 ] );
|
2017-01-28 15:43:55 +00:00
|
|
|
if ( !$thumb ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
$out->addMeta( 'og:image', wfExpandUrl( $thumb->getUrl(), PROTO_CANONICAL ) );
|
|
|
|
}
|
|
|
|
|
2012-02-29 10:50:36 +00:00
|
|
|
}
|