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