Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 48
0.00% covered (danger)
0.00%
0 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
GlobalUsageImagePageHooks
0.00% covered (danger)
0.00%
0 / 48
0.00% covered (danger)
0.00%
0 / 4
240
0.00% covered (danger)
0.00%
0 / 1
 getImagePageQuery
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
12
 onImagePageAfterImageLinks
0.00% covered (danger)
0.00%
0 / 24
0.00% covered (danger)
0.00%
0 / 1
42
 onImagePageShowTOC
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 hasResults
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
20
1<?php
2
3namespace MediaWiki\Extension\GlobalUsage;
4
5use ImagePage;
6use MediaWiki\MediaWikiServices;
7use MediaWiki\Page\Hook\ImagePageAfterImageLinksHook;
8use MediaWiki\Page\Hook\ImagePageShowTOCHook;
9use MediaWiki\Parser\Sanitizer;
10use MediaWiki\Title\Title;
11use MediaWiki\WikiMap\WikiMap;
12
13class GlobalUsageImagePageHooks implements
14    ImagePageAfterImageLinksHook,
15    ImagePageShowTOCHook
16{
17    private static $queryCache = [];
18
19    /**
20     * Get an executed query for use on image pages
21     *
22     * @param Title $title File to query for
23     * @return GlobalUsageQuery Query object, already executed
24     */
25    private static function getImagePageQuery( $title ) {
26        $name = $title->getDBkey();
27        if ( !isset( self::$queryCache[$name] ) ) {
28            $query = new GlobalUsageQuery( $title );
29            $query->filterLocal();
30            $query->execute();
31
32            self::$queryCache[$name] = $query;
33
34            // Limit cache size to 100
35            if ( count( self::$queryCache ) > 100 ) {
36                array_shift( self::$queryCache );
37            }
38        }
39
40        return self::$queryCache[$name];
41    }
42
43    /**
44     * Show a global usage section on the image page
45     *
46     * @param ImagePage $imagePage
47     * @param string &$html HTML to add to the image page as global usage section
48     */
49    public function onImagePageAfterImageLinks( $imagePage, &$html ) {
50        if ( !self::hasResults( $imagePage ) ) {
51            return;
52        }
53
54        $context = $imagePage->getContext();
55        $title = $imagePage->getPage()->getFile()->getTitle();
56        $targetName = $title->getText();
57
58        $query = self::getImagePageQuery( $title );
59
60        $guHtml = '';
61        foreach ( $query->getSingleImageResult() as $wiki => $result ) {
62            $wikiName = WikiMap::getWikiName( $wiki );
63            $escWikiName = Sanitizer::escapeClass( $wikiName );
64            $guHtml .= "<li class='mw-gu-onwiki-$escWikiName'>" . $context->msg(
65                'globalusage-on-wiki',
66                $targetName, $wikiName )->parse() . "\n<ul>";
67            foreach ( $result as $item ) {
68                $guHtml .= "\t<li>" . SpecialGlobalUsage::formatItem( $item ) . "</li>\n";
69            }
70            $guHtml .= "</ul></li>\n";
71        }
72
73        if ( $guHtml ) {
74            $html .= '<h2 id="globalusage">' . $context->msg( 'globalusage' )->escaped() . "</h2>\n"
75                . '<div id="mw-imagepage-section-globalusage">'
76                . $context->msg( 'globalusage-of-file' )->parseAsBlock()
77                . "<ul>\n" . $guHtml . "</ul>\n";
78            if ( $query->hasMore() ) {
79                $html .= $context->msg( 'globalusage-more', $targetName )->parseAsBlock();
80            }
81            $html .= '</div>';
82        }
83    }
84
85    /**
86     * Show a link to the global image links in the TOC if there are any results available.
87     * @param ImagePage $imagePage
88     * @param array &$toc
89     */
90    public function onImagePageShowTOC( $imagePage, &$toc ) {
91        if ( self::hasResults( $imagePage ) ) {
92            # Insert a link after the 3rd entry in the TOC
93            array_splice( $toc, 3, 0, '<li><a href="#globalusage">'
94                . $imagePage->getContext()->msg( 'globalusage' )->escaped() . '</a></li>' );
95        }
96    }
97
98    /**
99     * Check whether there are results for an image page. Checks whether the
100     * file exists and is not local.
101     *
102     * @param ImagePage $imagePage
103     * @return bool
104     */
105    protected static function hasResults( $imagePage ) {
106        # Don't display links if the target file does not exist
107        $file = $imagePage->getPage()->getFile();
108        if ( !$file->exists() ) {
109            return false;
110        }
111
112        # Don't show global usage if the file is local.
113        # Do show it however if the current repo is the shared repo. The way
114        # we detect this is a bit hacky and less than ideal. See bug 23136 for
115        # a discussion.
116        global $wgGlobalUsageDatabase;
117        $dbr = MediaWikiServices::getInstance()
118            ->getConnectionProvider()
119            ->getReplicaDatabase();
120        if ( $file->getRepoName() == 'local'
121            && $dbr->getDBname() != $wgGlobalUsageDatabase
122        ) {
123            return false;
124        }
125
126        $query = self::getImagePageQuery( $file->getTitle() );
127        return (bool)$query->getResult();
128    }
129}