Merge "Http::getProxy() method to get proxy configuration"
[lhc/web/wiklou.git] / includes / page / ImagePage.php
index 3638aed..106911c 100644 (file)
@@ -38,6 +38,11 @@ class ImagePage extends Article {
        /** @var bool */
        protected $mExtraDescription = false;
 
+       /**
+        * @var WikiFilePage
+        */
+       protected $mPage;
+
        /**
         * @param Title $title
         * @return WikiFilePage
@@ -76,7 +81,7 @@ class ImagePage extends Article {
                $this->fileLoaded = true;
 
                $this->displayImg = $img = false;
-               Hooks::run( 'ImagePageFindFile', array( $this, &$img, &$this->displayImg ) );
+               Hooks::run( 'ImagePageFindFile', [ $this, &$img, &$this->displayImg ] );
                if ( !$img ) { // not set by hook?
                        $img = wfFindFile( $this->getTitle() );
                        if ( !$img ) {
@@ -155,13 +160,13 @@ class ImagePage extends Article {
                }
 
                # No need to display noarticletext, we use our own message, output in openShowImage()
-               if ( $this->mPage->getID() ) {
+               if ( $this->mPage->getId() ) {
                        # NS_FILE is in the user language, but this section (the actual wikitext)
                        # should be in page content language
                        $pageLang = $this->getTitle()->getPageViewLanguage();
-                       $out->addHTML( Xml::openElement( 'div', array( 'id' => 'mw-imagepage-content',
+                       $out->addHTML( Xml::openElement( 'div', [ 'id' => 'mw-imagepage-content',
                                'lang' => $pageLang->getHtmlCode(), 'dir' => $pageLang->getDir(),
-                               'class' => 'mw-content-' . $pageLang->getDir() ) ) );
+                               'class' => 'mw-content-' . $pageLang->getDir() ] ) );
 
                        parent::view();
 
@@ -187,7 +192,7 @@ class ImagePage extends Article {
                // TODO: Cleanup the following
 
                $out->addHTML( Xml::element( 'h2',
-                       array( 'id' => 'filelinks' ),
+                       [ 'id' => 'filelinks' ],
                                $this->getContext()->msg( 'imagelinks' )->text() ) . "\n" );
                $this->imageDupes();
                # @todo FIXME: For some freaky reason, we can't redirect to foreign images.
@@ -196,7 +201,7 @@ class ImagePage extends Article {
 
                # Allow extensions to add something after the image links
                $html = '';
-               Hooks::run( 'ImagePageAfterImageLinks', array( $this, &$html ) );
+               Hooks::run( 'ImagePageAfterImageLinks', [ $this, &$html ] );
                if ( $html ) {
                        $out->addHTML( $html );
                }
@@ -204,10 +209,10 @@ class ImagePage extends Article {
                if ( $showmeta ) {
                        $out->addHTML( Xml::element(
                                'h2',
-                               array( 'id' => 'metadata' ),
+                               [ 'id' => 'metadata' ],
                                        $this->getContext()->msg( 'metadata' )->text() ) . "\n" );
                        $out->addWikiText( $this->makeMetadataTable( $formattedMetadata ) );
-                       $out->addModules( array( 'mediawiki.action.view.metadata' ) );
+                       $out->addModules( [ 'mediawiki.action.view.metadata' ] );
                }
 
                // Add remote Filepage.css
@@ -239,13 +244,13 @@ class ImagePage extends Article {
         * @return string
         */
        protected function showTOC( $metadata ) {
-               $r = array(
+               $r = [
                        '<li><a href="#file">' . $this->getContext()->msg( 'file-anchor-link' )->escaped() . '</a></li>',
                        '<li><a href="#filehistory">' . $this->getContext()->msg( 'filehist' )->escaped() . '</a></li>',
                        '<li><a href="#filelinks">' . $this->getContext()->msg( 'imagelinks' )->escaped() . '</a></li>',
-               );
+               ];
 
-               Hooks::run( 'ImagePageShowTOC', array( $this, &$r ) );
+               Hooks::run( 'ImagePageShowTOC', [ $this, &$r ] );
 
                if ( $metadata ) {
                        $r[] = '<li><a href="#metadata">' .
@@ -294,7 +299,7 @@ class ImagePage extends Article {
         */
        public function getContentObject() {
                $this->loadFile();
-               if ( $this->mPage->getFile() && !$this->mPage->getFile()->isLocal() && 0 == $this->getID() ) {
+               if ( $this->mPage->getFile() && !$this->mPage->getFile()->isLocal() && 0 == $this->getId() ) {
                        return null;
                }
                return parent::getContentObject();
@@ -318,10 +323,10 @@ class ImagePage extends Article {
                        # image
                        $page = $request->getIntOrNull( 'page' );
                        if ( is_null( $page ) ) {
-                               $params = array();
+                               $params = [];
                                $page = 1;
                        } else {
-                               $params = array( 'page' => $page );
+                               $params = [ 'page' => $page ];
                        }
 
                        $renderLang = $request->getVal( 'lang' );
@@ -342,7 +347,7 @@ class ImagePage extends Article {
                        $filename = wfEscapeWikiText( $this->displayImg->getName() );
                        $linktext = $filename;
 
-                       Hooks::run( 'ImageOpenShowImageInlineBefore', array( &$this, &$out ) );
+                       Hooks::run( 'ImageOpenShowImageInlineBefore', [ &$this, &$out ] );
 
                        if ( $this->displayImg->allowInlineDisplay() ) {
                                # image
@@ -358,7 +363,7 @@ class ImagePage extends Article {
 
                                        $thumbSizes = $this->getThumbSizes( $width_orig, $height_orig );
                                        # Generate thumbnails or thumbnail links as needed...
-                                       $otherSizes = array();
+                                       $otherSizes = [];
                                        foreach ( $thumbSizes as $size ) {
                                                // We include a thumbnail size in the list, if it is
                                                // less than or equal to the original size of the image
@@ -388,7 +393,7 @@ class ImagePage extends Article {
                                                $msgsmall .= ' ' .
                                                Html::rawElement(
                                                        'span',
-                                                       array( 'class' => 'mw-filepage-other-resolutions' ),
+                                                       [ 'class' => 'mw-filepage-other-resolutions' ],
                                                        $this->getContext()->msg( 'show-big-image-other' )
                                                                ->rawParams( $lang->pipeList( $otherSizes ) )
                                                                ->params( count( $otherSizes ) )
@@ -411,7 +416,7 @@ class ImagePage extends Article {
 
                                $anchorclose = Html::rawElement(
                                        'div',
-                                       array( 'class' => 'mw-filepage-resolutioninfo' ),
+                                       [ 'class' => 'mw-filepage-resolutioninfo' ],
                                        $msgsmall
                                );
 
@@ -422,10 +427,10 @@ class ImagePage extends Article {
                                }
 
                                if ( $thumbnail ) {
-                                       $options = array(
+                                       $options = [
                                                'alt' => $this->displayImg->getTitle()->getPrefixedText(),
                                                'file-link' => true,
-                                       );
+                                       ];
                                        $out->addHTML( '<div class="fullImageLink" id="file">' .
                                                $thumbnail->toHtml( $options ) .
                                                $anchorclose . "</div>\n" );
@@ -441,8 +446,8 @@ class ImagePage extends Article {
                                                $link = Linker::linkKnown(
                                                        $this->getTitle(),
                                                        $label,
-                                                       array(),
-                                                       array( 'page' => $page - 1 )
+                                                       [],
+                                                       [ 'page' => $page - 1 ]
                                                );
                                                $thumb1 = Linker::makeThumbLinkObj(
                                                        $this->getTitle(),
@@ -450,7 +455,7 @@ class ImagePage extends Article {
                                                        $link,
                                                        $label,
                                                        'none',
-                                                       array( 'page' => $page - 1 )
+                                                       [ 'page' => $page - 1 ]
                                                );
                                        } else {
                                                $thumb1 = '';
@@ -461,8 +466,8 @@ class ImagePage extends Article {
                                                $link = Linker::linkKnown(
                                                        $this->getTitle(),
                                                        $label,
-                                                       array(),
-                                                       array( 'page' => $page + 1 )
+                                                       [],
+                                                       [ 'page' => $page + 1 ]
                                                );
                                                $thumb2 = Linker::makeThumbLinkObj(
                                                        $this->getTitle(),
@@ -470,7 +475,7 @@ class ImagePage extends Article {
                                                        $link,
                                                        $label,
                                                        'none',
-                                                       array( 'page' => $page + 1 )
+                                                       [ 'page' => $page + 1 ]
                                                );
                                        } else {
                                                $thumb2 = '';
@@ -478,16 +483,16 @@ class ImagePage extends Article {
 
                                        global $wgScript;
 
-                                       $formParams = array(
+                                       $formParams = [
                                                'name' => 'pageselector',
                                                'action' => $wgScript,
-                                       );
-                                       $options = array();
+                                       ];
+                                       $options = [];
                                        for ( $i = 1; $i <= $count; $i++ ) {
                                                $options[] = Xml::option( $lang->formatNum( $i ), $i, $i == $page );
                                        }
                                        $select = Xml::tags( 'select',
-                                               array( 'id' => 'pageselector', 'name' => 'page' ),
+                                               [ 'id' => 'pageselector', 'name' => 'page' ],
                                                implode( "\n", $options ) );
 
                                        $out->addHTML(
@@ -505,7 +510,7 @@ class ImagePage extends Article {
                                $icon = $this->displayImg->iconThumb();
 
                                $out->addHTML( '<div class="fullImageLink" id="file">' .
-                                       $icon->toHtml( array( 'file-link' => true ) ) .
+                                       $icon->toHtml( [ 'file-link' => true ] ) .
                                        "</div>\n" );
                        }
 
@@ -560,7 +565,7 @@ EOT
                                if ( is_null( $currentLanguage ) ) {
                                        $currentLanguage = $defaultLang;
                                }
-                               $out->addHtml( $this->doRenderLangOpt( $renderLangOptions, $currentLanguage, $defaultLang ) );
+                               $out->addHTML( $this->doRenderLangOpt( $renderLangOptions, $currentLanguage, $defaultLang ) );
                        }
 
                        // Add cannot animate thumbnail warning
@@ -587,29 +592,29 @@ EOT
                        }
                } else {
                        # Image does not exist
-                       if ( !$this->getID() ) {
+                       if ( !$this->getId() ) {
                                # No article exists either
                                # Show deletion log to be consistent with normal articles
                                LogEventsList::showLogExtract(
                                        $out,
-                                       array( 'delete', 'move' ),
+                                       [ 'delete', 'move' ],
                                        $this->getTitle()->getPrefixedText(),
                                        '',
-                                       array( 'lim' => 10,
-                                               'conds' => array( "log_action != 'revision'" ),
+                                       [ 'lim' => 10,
+                                               'conds' => [ "log_action != 'revision'" ],
                                                'showIfEmpty' => false,
-                                               'msgKey' => array( 'moveddeleted-notice' )
-                                       )
+                                               'msgKey' => [ 'moveddeleted-notice' ]
+                                       ]
                                );
                        }
 
                        if ( $wgEnableUploads && $user->isAllowed( 'upload' ) ) {
                                // Only show an upload link if the user can upload
                                $uploadTitle = SpecialPage::getTitleFor( 'Upload' );
-                               $nofile = array(
+                               $nofile = [
                                        'filepage-nofile-link',
-                                       $uploadTitle->getFullURL( array( 'wpDestFile' => $this->mPage->getFile()->getName() ) )
-                               );
+                                       $uploadTitle->getFullURL( [ 'wpDestFile' => $this->mPage->getFile()->getName() ] )
+                               ];
                        } else {
                                $nofile = 'filepage-nofile';
                        }
@@ -618,7 +623,7 @@ EOT
                        // by Article::View().
                        $out->setRobotPolicy( 'noindex,nofollow' );
                        $out->wrapWikiMsg( "<div id='mw-imagepage-nofile' class='plainlinks'>\n$1\n</div>", $nofile );
-                       if ( !$this->getID() && $wgSend404Code ) {
+                       if ( !$this->getId() && $wgSend404Code ) {
                                // If there is no image, no shared image, and no description page,
                                // output a 404, to be consistent with Article::showMissingArticle.
                                $request->response()->statusHeader( 404 );
@@ -630,7 +635,7 @@ EOT
        /**
         * Make the text under the image to say what size preview
         *
-        * @param $params Array parameters for thumbnail
+        * @param $params array parameters for thumbnail
         * @param $sizeLinkBigImagePreview HTML for the current size
         * @return string HTML output
         */
@@ -677,10 +682,10 @@ EOT
                $params['height'] = $height;
                $thumbnail = $this->displayImg->transform( $params );
                if ( $thumbnail && !$thumbnail->isError() ) {
-                       return Html::rawElement( 'a', array(
+                       return Html::rawElement( 'a', [
                                'href' => $thumbnail->getUrl(),
                                'class' => 'mw-thumbnail-link'
-                               ), $this->getContext()->msg( 'show-big-image-size' )->numParams(
+                               ], $this->getContext()->msg( 'show-big-image-size' )->numParams(
                                        $thumbnail->getWidth(), $thumbnail->getHeight()
                                )->parse() );
                } else {
@@ -699,7 +704,7 @@ EOT
                $descText = $this->mPage->getFile()->getDescriptionText( $this->getContext()->getLanguage() );
 
                /* Add canonical to head if there is no local page for this shared file */
-               if ( $descUrl && $this->mPage->getID() == 0 ) {
+               if ( $descUrl && $this->mPage->getId() == 0 ) {
                        $out->setCanonicalUrl( $descUrl );
                }
 
@@ -710,13 +715,13 @@ EOT
                        $descText &&
                        $this->getContext()->msg( 'sharedupload-desc-here' )->plain() !== '-'
                ) {
-                       $out->wrapWikiMsg( $wrap, array( 'sharedupload-desc-here', $repo, $descUrl ) );
+                       $out->wrapWikiMsg( $wrap, [ 'sharedupload-desc-here', $repo, $descUrl ] );
                } elseif ( $descUrl &&
                        $this->getContext()->msg( 'sharedupload-desc-there' )->plain() !== '-'
                ) {
-                       $out->wrapWikiMsg( $wrap, array( 'sharedupload-desc-there', $repo, $descUrl ) );
+                       $out->wrapWikiMsg( $wrap, [ 'sharedupload-desc-there', $repo, $descUrl ] );
                } else {
-                       $out->wrapWikiMsg( $wrap, array( 'sharedupload', $repo ), ''/*BACKCOMPAT*/ );
+                       $out->wrapWikiMsg( $wrap, [ 'sharedupload', $repo ], ''/*BACKCOMPAT*/ );
                }
 
                if ( $descText ) {
@@ -727,10 +732,10 @@ EOT
        public function getUploadUrl() {
                $this->loadFile();
                $uploadTitle = SpecialPage::getTitleFor( 'Upload' );
-               return $uploadTitle->getFullURL( array(
+               return $uploadTitle->getFullURL( [
                        'wpDestFile' => $this->mPage->getFile()->getName(),
                        'wpForReUpload' => 1
-               ) );
+               ] );
        }
 
        /**
@@ -807,11 +812,11 @@ EOT
                $dbr = wfGetDB( DB_SLAVE );
 
                return $dbr->select(
-                       array( 'imagelinks', 'page' ),
-                       array( 'page_namespace', 'page_title', 'il_to' ),
-                       array( 'il_to' => $target, 'il_from = page_id' ),
+                       [ 'imagelinks', 'page' ],
+                       [ 'page_namespace', 'page_title', 'il_to' ],
+                       [ 'il_to' => $target, 'il_from = page_id' ],
                        __METHOD__,
-                       array( 'LIMIT' => $limit + 1, 'ORDER BY' => 'il_from', )
+                       [ 'LIMIT' => $limit + 1, 'ORDER BY' => 'il_from', ]
                );
        }
 
@@ -820,14 +825,14 @@ EOT
 
                $out = $this->getContext()->getOutput();
 
-               $rows = array();
-               $redirects = array();
+               $rows = [];
+               $redirects = [];
                foreach ( $this->getTitle()->getRedirectsHere( NS_FILE ) as $redir ) {
-                       $redirects[$redir->getDBkey()] = array();
-                       $rows[] = (object)array(
+                       $redirects[$redir->getDBkey()] = [];
+                       $rows[] = (object)[
                                'page_namespace' => NS_FILE,
                                'page_title' => $redir->getDBkey(),
-                       );
+                       ];
                }
 
                $res = $this->queryImageLinks( $this->getTitle()->getDBkey(), $limit + 1 );
@@ -850,7 +855,7 @@ EOT
                if ( $count == 0 ) {
                        $out->wrapWikiMsg(
                                Html::rawElement( 'div',
-                                       array( 'id' => 'mw-imagepage-nolinkstoimage' ), "\n$1\n" ),
+                                       [ 'id' => 'mw-imagepage-nolinkstoimage' ], "\n$1\n" ),
                                'nolinkstoimage'
                        );
                        return;
@@ -869,12 +874,12 @@ EOT
 
                $out->addHTML(
                        Html::openElement( 'ul',
-                               array( 'class' => 'mw-imagepage-linkstoimage' ) ) . "\n"
+                               [ 'class' => 'mw-imagepage-linkstoimage' ] ) . "\n"
                );
                $count = 0;
 
                // Sort the list by namespace:title
-               usort( $rows, array( $this, 'compare' ) );
+               usort( $rows, [ $this, 'compare' ] );
 
                // Create links for every element
                $currentCount = 0;
@@ -884,14 +889,14 @@ EOT
                                break;
                        }
 
-                       $query = array();
+                       $query = [];
                        # Add a redirect=no to make redirect pages reachable
                        if ( isset( $redirects[$element->page_title] ) ) {
                                $query['redirect'] = 'no';
                        }
                        $link = Linker::linkKnown(
                                Title::makeTitle( $element->page_namespace, $element->page_title ),
-                               null, array(), $query
+                               null, [], $query
                        );
                        if ( !isset( $redirects[$element->page_title] ) ) {
                                # No redirects
@@ -913,14 +918,14 @@ EOT
                                        $link2 = Linker::linkKnown( Title::makeTitle( $row->page_namespace, $row->page_title ) );
                                        $li .= Html::rawElement(
                                                'li',
-                                               array( 'class' => 'mw-imagepage-linkstoimage-ns' . $element->page_namespace ),
+                                               [ 'class' => 'mw-imagepage-linkstoimage-ns' . $element->page_namespace ],
                                                $link2
                                                ) . "\n";
                                }
 
                                $ul = Html::rawElement(
                                        'ul',
-                                       array( 'class' => 'mw-imagepage-redirectstofile' ),
+                                       [ 'class' => 'mw-imagepage-redirectstofile' ],
                                        $li
                                        ) . "\n";
                                $liContents = $this->getContext()->msg( 'linkstoimage-redirect' )->rawParams(
@@ -928,7 +933,7 @@ EOT
                        }
                        $out->addHTML( Html::rawElement(
                                        'li',
-                                       array( 'class' => 'mw-imagepage-linkstoimage-ns' . $element->page_namespace ),
+                                       [ 'class' => 'mw-imagepage-linkstoimage-ns' . $element->page_namespace ],
                                        $liContents
                                ) . "\n"
                        );
@@ -1049,7 +1054,7 @@ EOT
 
                return isset( $wgImageLimits[$option] )
                        ? $wgImageLimits[$option]
-                       : array( 800, 600 ); // if nothing is set, fallback to a hardcoded default
+                       : [ 800, 600 ]; // if nothing is set, fallback to a hardcoded default
        }
 
        /**
@@ -1112,7 +1117,7 @@ EOT
 
                $select = Html::rawElement(
                        'select',
-                       array( 'id' => 'mw-imglangselector', 'name' => 'lang' ),
+                       [ 'id' => 'mw-imglangselector', 'name' => 'lang' ],
                        $opts
                );
                $submit = Xml::submitButton( $this->getContext()->msg( 'img-lang-go' )->text() );
@@ -1122,8 +1127,8 @@ EOT
                        ->parse();
                $formContents .= Html::hidden( 'title', $this->getTitle()->getPrefixedDBkey() );
 
-               $langSelectLine = Html::rawElement( 'div', array( 'id' => 'mw-imglangselector-line' ),
-                       Html::rawElement( 'form', array( 'action' => $wgScript ), $formContents )
+               $langSelectLine = Html::rawElement( 'div', [ 'id' => 'mw-imglangselector-line' ],
+                       Html::rawElement( 'form', [ 'action' => $wgScript ], $formContents )
                );
                return $langSelectLine;
        }
@@ -1149,7 +1154,7 @@ EOT
                }
 
                if ( !$width || !$height ) {
-                       return array( 0, 0 );
+                       return [ 0, 0 ];
                }
 
                # Calculate the thumbnail size.
@@ -1167,7 +1172,7 @@ EOT
                        # Note that $height <= $maxHeight now, but might not be identical
                        # because of rounding.
                }
-               return array( $width, $height );
+               return [ $width, $height ];
        }
 
        /**
@@ -1188,514 +1193,52 @@ EOT
                        // that we mustRender, some users have indicated that they would
                        // find it useful to have the full size image in the rendered
                        // image format.
-                       $thumbSizes[] = array( $origWidth, $origHeight );
+                       $thumbSizes[] = [ $origWidth, $origHeight ];
                } else {
                        # Creating thumb links triggers thumbnail generation.
                        # Just generate the thumb for the current users prefs.
-                       $thumbSizes = array(
+                       $thumbSizes = [
                                $this->getImageLimitsFromOption( $this->getContext()->getUser(), 'thumbsize' )
-                       );
+                       ];
                        if ( !$this->displayImg->mustRender() ) {
                                // We can safely include a link to the "full-size" preview,
                                // without actually rendering.
-                               $thumbSizes[] = array( $origWidth, $origHeight );
+                               $thumbSizes[] = [ $origWidth, $origHeight ];
                        }
                }
                return $thumbSizes;
        }
 
-}
-
-/**
- * Builds the image revision log shown on image pages
- *
- * @ingroup Media
- */
-class ImageHistoryList extends ContextSource {
-
-       /**
-        * @var Title
-        */
-       protected $title;
-
-       /**
-        * @var File
-        */
-       protected $img;
-
-       /**
-        * @var ImagePage
-        */
-       protected $imagePage;
-
-       /**
-        * @var File
-        */
-       protected $current;
-
-       protected $repo, $showThumb;
-       protected $preventClickjacking = false;
-
-       /**
-        * @param ImagePage $imagePage
-        */
-       public function __construct( $imagePage ) {
-               global $wgShowArchiveThumbnails;
-               $this->current = $imagePage->getFile();
-               $this->img = $imagePage->getDisplayedFile();
-               $this->title = $imagePage->getTitle();
-               $this->imagePage = $imagePage;
-               $this->showThumb = $wgShowArchiveThumbnails && $this->img->canRender();
-               $this->setContext( $imagePage->getContext() );
-       }
-
-       /**
-        * @return ImagePage
-        */
-       public function getImagePage() {
-               return $this->imagePage;
-       }
-
        /**
-        * @return File
+        * @see WikiFilePage::getFile
+        * @return bool|File
         */
        public function getFile() {
-               return $this->img;
-       }
-
-       /**
-        * @param string $navLinks
-        * @return string
-        */
-       public function beginImageHistoryList( $navLinks = '' ) {
-               return Xml::element( 'h2', array( 'id' => 'filehistory' ), $this->msg( 'filehist' )->text() )
-                       . "\n"
-                       . "<div id=\"mw-imagepage-section-filehistory\">\n"
-                       . $this->msg( 'filehist-help' )->parseAsBlock()
-                       . $navLinks . "\n"
-                       . Xml::openElement( 'table', array( 'class' => 'wikitable filehistory' ) ) . "\n"
-                       . '<tr><th></th>'
-                       . ( $this->current->isLocal()
-                               && ( $this->getUser()->isAllowedAny( 'delete', 'deletedhistory' ) ) ? '<th></th>' : '' )
-                       . '<th>' . $this->msg( 'filehist-datetime' )->escaped() . '</th>'
-                       . ( $this->showThumb ? '<th>' . $this->msg( 'filehist-thumb' )->escaped() . '</th>' : '' )
-                       . '<th>' . $this->msg( 'filehist-dimensions' )->escaped() . '</th>'
-                       . '<th>' . $this->msg( 'filehist-user' )->escaped() . '</th>'
-                       . '<th>' . $this->msg( 'filehist-comment' )->escaped() . '</th>'
-                       . "</tr>\n";
-       }
-
-       /**
-        * @param string $navLinks
-        * @return string
-        */
-       public function endImageHistoryList( $navLinks = '' ) {
-               return "</table>\n$navLinks\n</div>\n";
-       }
-
-       /**
-        * @param bool $iscur
-        * @param File $file
-        * @return string
-        */
-       public function imageHistoryLine( $iscur, $file ) {
-               global $wgContLang;
-
-               $user = $this->getUser();
-               $lang = $this->getLanguage();
-               $timestamp = wfTimestamp( TS_MW, $file->getTimestamp() );
-               $img = $iscur ? $file->getName() : $file->getArchiveName();
-               $userId = $file->getUser( 'id' );
-               $userText = $file->getUser( 'text' );
-               $description = $file->getDescription( File::FOR_THIS_USER, $user );
-
-               $local = $this->current->isLocal();
-               $row = $selected = '';
-
-               // Deletion link
-               if ( $local && ( $user->isAllowedAny( 'delete', 'deletedhistory' ) ) ) {
-                       $row .= '<td>';
-                       # Link to remove from history
-                       if ( $user->isAllowed( 'delete' ) ) {
-                               $q = array( 'action' => 'delete' );
-                               if ( !$iscur ) {
-                                       $q['oldimage'] = $img;
-                               }
-                               $row .= Linker::linkKnown(
-                                       $this->title,
-                                       $this->msg( $iscur ? 'filehist-deleteall' : 'filehist-deleteone' )->escaped(),
-                                       array(), $q
-                               );
-                       }
-                       # Link to hide content. Don't show useless link to people who cannot hide revisions.
-                       $canHide = $user->isAllowed( 'deleterevision' );
-                       if ( $canHide || ( $user->isAllowed( 'deletedhistory' ) && $file->getVisibility() ) ) {
-                               if ( $user->isAllowed( 'delete' ) ) {
-                                       $row .= '<br />';
-                               }
-                               // If file is top revision or locked from this user, don't link
-                               if ( $iscur || !$file->userCan( File::DELETED_RESTRICTED, $user ) ) {
-                                       $del = Linker::revDeleteLinkDisabled( $canHide );
-                               } else {
-                                       list( $ts, ) = explode( '!', $img, 2 );
-                                       $query = array(
-                                               'type' => 'oldimage',
-                                               'target' => $this->title->getPrefixedText(),
-                                               'ids' => $ts,
-                                       );
-                                       $del = Linker::revDeleteLink( $query,
-                                               $file->isDeleted( File::DELETED_RESTRICTED ), $canHide );
-                               }
-                               $row .= $del;
-                       }
-                       $row .= '</td>';
-               }
-
-               // Reversion link/current indicator
-               $row .= '<td>';
-               if ( $iscur ) {
-                       $row .= $this->msg( 'filehist-current' )->escaped();
-               } elseif ( $local && $this->title->quickUserCan( 'edit', $user )
-                       && $this->title->quickUserCan( 'upload', $user )
-               ) {
-                       if ( $file->isDeleted( File::DELETED_FILE ) ) {
-                               $row .= $this->msg( 'filehist-revert' )->escaped();
-                       } else {
-                               $row .= Linker::linkKnown(
-                                       $this->title,
-                                       $this->msg( 'filehist-revert' )->escaped(),
-                                       array(),
-                                       array(
-                                               'action' => 'revert',
-                                               'oldimage' => $img,
-                                               'wpEditToken' => $user->getEditToken( $img )
-                                       )
-                               );
-                       }
-               }
-               $row .= '</td>';
-
-               // Date/time and image link
-               if ( $file->getTimestamp() === $this->img->getTimestamp() ) {
-                       $selected = "class='filehistory-selected'";
-               }
-               $row .= "<td $selected style='white-space: nowrap;'>";
-               if ( !$file->userCan( File::DELETED_FILE, $user ) ) {
-                       # Don't link to unviewable files
-                       $row .= '<span class="history-deleted">'
-                               . $lang->userTimeAndDate( $timestamp, $user ) . '</span>';
-               } elseif ( $file->isDeleted( File::DELETED_FILE ) ) {
-                       if ( $local ) {
-                               $this->preventClickjacking();
-                               $revdel = SpecialPage::getTitleFor( 'Revisiondelete' );
-                               # Make a link to review the image
-                               $url = Linker::linkKnown(
-                                       $revdel,
-                                       $lang->userTimeAndDate( $timestamp, $user ),
-                                       array(),
-                                       array(
-                                               'target' => $this->title->getPrefixedText(),
-                                               'file' => $img,
-                                               'token' => $user->getEditToken( $img )
-                                       )
-                               );
-                       } else {
-                               $url = $lang->userTimeAndDate( $timestamp, $user );
-                       }
-                       $row .= '<span class="history-deleted">' . $url . '</span>';
-               } elseif ( !$file->exists() ) {
-                       $row .= '<span class="mw-file-missing">'
-                               . $lang->userTimeAndDate( $timestamp, $user ) . '</span>';
-               } else {
-                       $url = $iscur ? $this->current->getUrl() : $this->current->getArchiveUrl( $img );
-                       $row .= Xml::element(
-                               'a',
-                               array( 'href' => $url ),
-                               $lang->userTimeAndDate( $timestamp, $user )
-                       );
-               }
-               $row .= "</td>";
-
-               // Thumbnail
-               if ( $this->showThumb ) {
-                       $row .= '<td>' . $this->getThumbForLine( $file ) . '</td>';
-               }
-
-               // Image dimensions + size
-               $row .= '<td>';
-               $row .= htmlspecialchars( $file->getDimensionsString() );
-               $row .= $this->msg( 'word-separator' )->escaped();
-               $row .= '<span style="white-space: nowrap;">';
-               $row .= $this->msg( 'parentheses' )->sizeParams( $file->getSize() )->escaped();
-               $row .= '</span>';
-               $row .= '</td>';
-
-               // Uploading user
-               $row .= '<td>';
-               // Hide deleted usernames
-               if ( $file->isDeleted( File::DELETED_USER ) ) {
-                       $row .= '<span class="history-deleted">'
-                               . $this->msg( 'rev-deleted-user' )->escaped() . '</span>';
-               } else {
-                       if ( $local ) {
-                               $row .= Linker::userLink( $userId, $userText );
-                               $row .= '<span style="white-space: nowrap;">';
-                               $row .= Linker::userToolLinks( $userId, $userText );
-                               $row .= '</span>';
-                       } else {
-                               $row .= htmlspecialchars( $userText );
-                       }
-               }
-               $row .= '</td>';
-
-               // Don't show deleted descriptions
-               if ( $file->isDeleted( File::DELETED_COMMENT ) ) {
-                       $row .= '<td><span class="history-deleted">' .
-                               $this->msg( 'rev-deleted-comment' )->escaped() . '</span></td>';
-               } else {
-                       $row .= '<td dir="' . $wgContLang->getDir() . '">' .
-                               Linker::formatComment( $description, $this->title ) . '</td>';
-               }
-
-               $rowClass = null;
-               Hooks::run( 'ImagePageFileHistoryLine', array( $this, $file, &$row, &$rowClass ) );
-               $classAttr = $rowClass ? " class='$rowClass'" : '';
-
-               return "<tr{$classAttr}>{$row}</tr>\n";
-       }
-
-       /**
-        * @param File $file
-        * @return string
-        */
-       protected function getThumbForLine( $file ) {
-               $lang = $this->getLanguage();
-               $user = $this->getUser();
-               if ( $file->allowInlineDisplay() && $file->userCan( File::DELETED_FILE, $user )
-                       && !$file->isDeleted( File::DELETED_FILE )
-               ) {
-                       $params = array(
-                               'width' => '120',
-                               'height' => '120',
-                       );
-                       $timestamp = wfTimestamp( TS_MW, $file->getTimestamp() );
-
-                       $thumbnail = $file->transform( $params );
-                       $options = array(
-                               'alt' => $this->msg( 'filehist-thumbtext',
-                                       $lang->userTimeAndDate( $timestamp, $user ),
-                                       $lang->userDate( $timestamp, $user ),
-                                       $lang->userTime( $timestamp, $user ) )->text(),
-                               'file-link' => true,
-                       );
-
-                       if ( !$thumbnail ) {
-                               return $this->msg( 'filehist-nothumb' )->escaped();
-                       }
-
-                       return $thumbnail->toHtml( $options );
-               } else {
-                       return $this->msg( 'filehist-nothumb' )->escaped();
-               }
-       }
-
-       /**
-        * @param bool $enable
-        */
-       protected function preventClickjacking( $enable = true ) {
-               $this->preventClickjacking = $enable;
+               return $this->mPage->getFile();
        }
 
        /**
+        * @see WikiFilePage::isLocal
         * @return bool
         */
-       public function getPreventClickjacking() {
-               return $this->preventClickjacking;
+       public function isLocal() {
+               return $this->mPage->isLocal();
        }
-}
-
-class ImageHistoryPseudoPager extends ReverseChronologicalPager {
-       protected $preventClickjacking = false;
-
-       /**
-        * @var File
-        */
-       protected $mImg;
-
-       /**
-        * @var Title
-        */
-       protected $mTitle;
 
        /**
-        * @param ImagePage $imagePage
+        * @see WikiFilePage::getDuplicates
+        * @return array|null
         */
-       function __construct( $imagePage ) {
-               parent::__construct( $imagePage->getContext() );
-               $this->mImagePage = $imagePage;
-               $this->mTitle = clone $imagePage->getTitle();
-               $this->mTitle->setFragment( '#filehistory' );
-               $this->mImg = null;
-               $this->mHist = array();
-               $this->mRange = array( 0, 0 ); // display range
+       public function getDuplicates() {
+               return $this->mPage->getDuplicates();
        }
 
        /**
-        * @return Title
-        */
-       function getTitle() {
-               return $this->mTitle;
-       }
-
-       function getQueryInfo() {
-               return false;
-       }
-
-       /**
-        * @return string
-        */
-       function getIndexField() {
-               return '';
-       }
-
-       /**
-        * @param object $row
-        * @return string
-        */
-       function formatRow( $row ) {
-               return '';
-       }
-
-       /**
-        * @return string
-        */
-       function getBody() {
-               $s = '';
-               $this->doQuery();
-               if ( count( $this->mHist ) ) {
-                       if ( $this->mImg->isLocal() ) {
-                               // Do a batch existence check for user pages and talkpages
-                               $linkBatch = new LinkBatch();
-                               for ( $i = $this->mRange[0]; $i <= $this->mRange[1]; $i++ ) {
-                                       $file = $this->mHist[$i];
-                                       $user = $file->getUser( 'text' );
-                                       $linkBatch->add( NS_USER, $user );
-                                       $linkBatch->add( NS_USER_TALK, $user );
-                               }
-                               $linkBatch->execute();
-                       }
-
-                       $list = new ImageHistoryList( $this->mImagePage );
-                       # Generate prev/next links
-                       $navLink = $this->getNavigationBar();
-                       $s = $list->beginImageHistoryList( $navLink );
-                       // Skip rows there just for paging links
-                       for ( $i = $this->mRange[0]; $i <= $this->mRange[1]; $i++ ) {
-                               $file = $this->mHist[$i];
-                               $s .= $list->imageHistoryLine( !$file->isOld(), $file );
-                       }
-                       $s .= $list->endImageHistoryList( $navLink );
-
-                       if ( $list->getPreventClickjacking() ) {
-                               $this->preventClickjacking();
-                       }
-               }
-               return $s;
-       }
-
-       function doQuery() {
-               if ( $this->mQueryDone ) {
-                       return;
-               }
-               $this->mImg = $this->mImagePage->getFile(); // ensure loading
-               if ( !$this->mImg->exists() ) {
-                       return;
-               }
-               $queryLimit = $this->mLimit + 1; // limit plus extra row
-               if ( $this->mIsBackwards ) {
-                       // Fetch the file history
-                       $this->mHist = $this->mImg->getHistory( $queryLimit, null, $this->mOffset, false );
-                       // The current rev may not meet the offset/limit
-                       $numRows = count( $this->mHist );
-                       if ( $numRows <= $this->mLimit && $this->mImg->getTimestamp() > $this->mOffset ) {
-                               $this->mHist = array_merge( array( $this->mImg ), $this->mHist );
-                       }
-               } else {
-                       // The current rev may not meet the offset
-                       if ( !$this->mOffset || $this->mImg->getTimestamp() < $this->mOffset ) {
-                               $this->mHist[] = $this->mImg;
-                       }
-                       // Old image versions (fetch extra row for nav links)
-                       $oiLimit = count( $this->mHist ) ? $this->mLimit : $this->mLimit + 1;
-                       // Fetch the file history
-                       $this->mHist = array_merge( $this->mHist,
-                               $this->mImg->getHistory( $oiLimit, $this->mOffset, null, false ) );
-               }
-               $numRows = count( $this->mHist ); // Total number of query results
-               if ( $numRows ) {
-                       # Index value of top item in the list
-                       $firstIndex = $this->mIsBackwards ?
-                               $this->mHist[$numRows - 1]->getTimestamp() : $this->mHist[0]->getTimestamp();
-                       # Discard the extra result row if there is one
-                       if ( $numRows > $this->mLimit && $numRows > 1 ) {
-                               if ( $this->mIsBackwards ) {
-                                       # Index value of item past the index
-                                       $this->mPastTheEndIndex = $this->mHist[0]->getTimestamp();
-                                       # Index value of bottom item in the list
-                                       $lastIndex = $this->mHist[1]->getTimestamp();
-                                       # Display range
-                                       $this->mRange = array( 1, $numRows - 1 );
-                               } else {
-                                       # Index value of item past the index
-                                       $this->mPastTheEndIndex = $this->mHist[$numRows - 1]->getTimestamp();
-                                       # Index value of bottom item in the list
-                                       $lastIndex = $this->mHist[$numRows - 2]->getTimestamp();
-                                       # Display range
-                                       $this->mRange = array( 0, $numRows - 2 );
-                               }
-                       } else {
-                               # Setting indexes to an empty string means that they will be
-                               # omitted if they would otherwise appear in URLs. It just so
-                               # happens that this  is the right thing to do in the standard
-                               # UI, in all the relevant cases.
-                               $this->mPastTheEndIndex = '';
-                               # Index value of bottom item in the list
-                               $lastIndex = $this->mIsBackwards ?
-                                       $this->mHist[0]->getTimestamp() : $this->mHist[$numRows - 1]->getTimestamp();
-                               # Display range
-                               $this->mRange = array( 0, $numRows - 1 );
-                       }
-               } else {
-                       $firstIndex = '';
-                       $lastIndex = '';
-                       $this->mPastTheEndIndex = '';
-               }
-               if ( $this->mIsBackwards ) {
-                       $this->mIsFirst = ( $numRows < $queryLimit );
-                       $this->mIsLast = ( $this->mOffset == '' );
-                       $this->mLastShown = $firstIndex;
-                       $this->mFirstShown = $lastIndex;
-               } else {
-                       $this->mIsFirst = ( $this->mOffset == '' );
-                       $this->mIsLast = ( $numRows < $queryLimit );
-                       $this->mLastShown = $lastIndex;
-                       $this->mFirstShown = $firstIndex;
-               }
-               $this->mQueryDone = true;
-       }
-
-       /**
-        * @param bool $enable
-        */
-       protected function preventClickjacking( $enable = true ) {
-               $this->preventClickjacking = $enable;
-       }
-
-       /**
-        * @return bool
+        * @see WikiFilePage::getForeignCategories
+        * @return TitleArray|Title[]
         */
-       public function getPreventClickjacking() {
-               return $this->preventClickjacking;
+       public function getForeignCategories() {
+               $this->mPage->getForeignCategories();
        }
 
 }