Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 31 |
|
0.00% |
0 / 10 |
CRAP | |
0.00% |
0 / 1 |
SpecialGloballyWantedFiles | |
0.00% |
0 / 31 |
|
0.00% |
0 / 10 |
342 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
execute | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
forceExistenceCheck | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
existenceCheck | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getPageHeader | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
isCacheable | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
12 | |||
isListed | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getQueryInfo | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
formatResult | |
0.00% |
0 / 13 |
|
0.00% |
0 / 1 |
30 | |||
getGroupName | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | /** |
3 | * Implements Special:GloballyWantedFiles, the global equivalent to |
4 | * Special:WantedFiles |
5 | * |
6 | * @file |
7 | * @author Brian Wolff <bawolff+wn@gmail.com> |
8 | * @ingroup SpecialPage |
9 | */ |
10 | |
11 | namespace MediaWiki\Extension\GlobalUsage; |
12 | |
13 | use MediaWiki\Cache\LinkBatchFactory; |
14 | use MediaWiki\Html\Html; |
15 | use MediaWiki\SpecialPage\SpecialPage; |
16 | use MediaWiki\SpecialPage\WantedQueryPage; |
17 | use MediaWiki\Title\Title; |
18 | use MediaWiki\WikiMap\WikiMap; |
19 | use RepoGroup; |
20 | use Skin; |
21 | use stdClass; |
22 | use Wikimedia\Rdbms\IConnectionProvider; |
23 | |
24 | class SpecialGloballyWantedFiles extends WantedQueryPage { |
25 | |
26 | private RepoGroup $repoGroup; |
27 | |
28 | public function __construct( |
29 | IConnectionProvider $dbProvider, |
30 | LinkBatchFactory $linkBatchFactory, |
31 | RepoGroup $repoGroup |
32 | ) { |
33 | parent::__construct( 'GloballyWantedFiles' ); |
34 | $this->setDatabaseProvider( $dbProvider ); |
35 | $this->setLinkBatchFactory( $linkBatchFactory ); |
36 | $this->repoGroup = $repoGroup; |
37 | } |
38 | |
39 | /** |
40 | * Main execution function. Use the parent if we're on the right wiki. |
41 | * If we're not on a shared repo, try to redirect there. |
42 | * @param string $par |
43 | */ |
44 | public function execute( $par ) { |
45 | if ( GlobalUsage::onSharedRepo() ) { |
46 | parent::execute( $par ); |
47 | } else { |
48 | GlobalUsage::redirectSpecialPageToSharedRepo( $this->getContext() ); |
49 | } |
50 | } |
51 | |
52 | protected function forceExistenceCheck() { |
53 | // Same as MediaWiki core WantedFiles |
54 | return true; |
55 | } |
56 | |
57 | protected function existenceCheck( Title $title ) { |
58 | // Same as MediaWiki core WantedFiles |
59 | return (bool)$this->repoGroup->findFile( $title ); |
60 | } |
61 | |
62 | /** |
63 | * Output an extra header |
64 | * |
65 | * @return string html to output |
66 | */ |
67 | public function getPageHeader() { |
68 | if ( $this->repoGroup->hasForeignRepos() ) { |
69 | return $this->msg( 'globallywantedfiles-foreign-repo' )->parseAsBlock(); |
70 | } else { |
71 | return parent::getPageHeader(); |
72 | } |
73 | } |
74 | |
75 | /** |
76 | * Don't want to do cached handling on non-shared repo, since we only redirect. |
77 | * |
78 | * Also make sure that GlobalUsage db same as shared repo. |
79 | * (To catch the unlikely case where GlobalUsage db is different db from the |
80 | * shared repo db). |
81 | * @return bool |
82 | */ |
83 | public function isCacheable() { |
84 | global $wgGlobalUsageDatabase; |
85 | return GlobalUsage::onSharedRepo() |
86 | && ( !$wgGlobalUsageDatabase || $wgGlobalUsageDatabase === WikiMap::getCurrentWikiId() ); |
87 | } |
88 | |
89 | /** |
90 | * Only list this special page on the wiki that is the shared repo. |
91 | * |
92 | * @return bool Should this be listed in Special:SpecialPages |
93 | */ |
94 | public function isListed() { |
95 | return GlobalUsage::onSharedRepo(); |
96 | } |
97 | |
98 | public function getQueryInfo() { |
99 | return GlobalUsage::getWantedFilesQueryInfo(); |
100 | } |
101 | |
102 | /** |
103 | * Format a row of the results |
104 | * |
105 | * We need to override this in order to link to Special:GlobalUsage |
106 | * instead of Special:WhatLinksHere. |
107 | * |
108 | * @param Skin $skin |
109 | * @param stdClass $result A row from the database |
110 | * @return string HTML to output |
111 | */ |
112 | public function formatResult( $skin, $result ) { |
113 | // If some of the client wikis are $wgCapitalLinks = false |
114 | // but the shared repo is not, then we will get some false positives |
115 | // here. To avoid as much confusion as possible, use the raw (lowercase) version |
116 | // of the title for displaying, but the safe (properly cased) version of |
117 | // the title for any checks. (Bug 71359) |
118 | $title = Title::makeTitle( $result->namespace, $result->title ); |
119 | $safeTitle = Title::makeTitleSafe( $result->namespace, $result->title ); |
120 | if ( $title instanceof Title && $safeTitle instanceof Title ) { |
121 | $linkRenderer = $this->getLinkRenderer(); |
122 | $pageLink = $linkRenderer->makeLink( $title ); |
123 | if ( $safeTitle->isKnown() && |
124 | $this->repoGroup->findFile( $safeTitle ) |
125 | ) { |
126 | // If the title exists and is a file, than strike. |
127 | // The RepoGroup::findFile call should already be cached from LinkRenderer::makeLink call |
128 | // so it shouldn't be too expensive. However a future @todo would be |
129 | // to do preload existence checks for files all at once via RepoGroup::findFiles. |
130 | $pageLink = Html::rawElement( 'del', [], $pageLink ); |
131 | } |
132 | |
133 | $gu = SpecialPage::getTitleFor( 'GlobalUsage', $title->getDBKey() ); |
134 | $label = $this->msg( 'nlinks' )->numParams( $result->value )->text(); |
135 | $usages = $linkRenderer->makeLink( $gu, $label ); |
136 | |
137 | return $this->getLanguage()->specialList( $pageLink, $usages ); |
138 | } else { |
139 | return $this->msg( 'wantedpages-badtitle', $result->title )->escaped(); |
140 | } |
141 | } |
142 | |
143 | protected function getGroupName() { |
144 | return 'maintenance'; |
145 | } |
146 | } |