Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 37 |
|
0.00% |
0 / 11 |
CRAP | |
0.00% |
0 / 1 |
SpecialMostGloballyLinkedFiles | |
0.00% |
0 / 37 |
|
0.00% |
0 / 11 |
240 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
execute | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
isExpensive | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
isSyndicated | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
isCacheable | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getQueryInfo | |
0.00% |
0 / 13 |
|
0.00% |
0 / 1 |
2 | |||
getCellHtml | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
assertOnSharedRepo | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
isListed | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getRecacheDB | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
12 | |||
getGroupName | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | /** |
3 | * Special page to list files with most global usages |
4 | * |
5 | * @file |
6 | * @ingroup SpecialPage |
7 | * @author Brian Wolff <bawolff+wn@gmail.com> |
8 | */ |
9 | |
10 | namespace MediaWiki\Extension\GlobalUsage; |
11 | |
12 | use MediaWiki\Cache\LinkBatchFactory; |
13 | use MediaWiki\SpecialPage\ImageQueryPage; |
14 | use MediaWiki\WikiMap\WikiMap; |
15 | use RuntimeException; |
16 | use Wikimedia\Rdbms\IConnectionProvider; |
17 | use Wikimedia\Rdbms\IDatabase; |
18 | |
19 | class SpecialMostGloballyLinkedFiles extends ImageQueryPage { |
20 | |
21 | public function __construct( |
22 | IConnectionProvider $dbProvider, |
23 | LinkBatchFactory $linkBatchFactory |
24 | ) { |
25 | parent::__construct( 'MostGloballyLinkedFiles' ); |
26 | $this->setDatabaseProvider( $dbProvider ); |
27 | $this->setLinkBatchFactory( $linkBatchFactory ); |
28 | } |
29 | |
30 | /** |
31 | * Main execution function. Use the parent if we're on the right wiki. |
32 | * If we're not on a shared repo, try to redirect there. |
33 | * @param string $par |
34 | */ |
35 | public function execute( $par ) { |
36 | if ( GlobalUsage::onSharedRepo() ) { |
37 | parent::execute( $par ); |
38 | } else { |
39 | GlobalUsage::redirectSpecialPageToSharedRepo( $this->getContext() ); |
40 | } |
41 | } |
42 | |
43 | /** @inheritDoc */ |
44 | public function isExpensive() { |
45 | return true; |
46 | } |
47 | |
48 | /** @inheritDoc */ |
49 | public function isSyndicated() { |
50 | return false; |
51 | } |
52 | |
53 | /** |
54 | * Don't want to do cached handling on non-shared repo, since we only redirect. |
55 | * @return bool |
56 | */ |
57 | public function isCacheable() { |
58 | return GlobalUsage::onSharedRepo(); |
59 | } |
60 | |
61 | /** |
62 | * What query to do. |
63 | * @return array |
64 | */ |
65 | public function getQueryInfo() { |
66 | $this->assertOnSharedRepo(); |
67 | return [ |
68 | 'tables' => [ 'globalimagelinks' ], |
69 | 'fields' => [ |
70 | 'namespace' => NS_FILE, |
71 | 'title' => 'gil_to', |
72 | 'value' => 'COUNT(*)' |
73 | ], |
74 | 'options' => [ |
75 | 'GROUP BY' => 'gil_to', |
76 | 'HAVING' => 'COUNT(*) > 1' |
77 | ] |
78 | ]; |
79 | } |
80 | |
81 | /** @inheritDoc */ |
82 | protected function getCellHtml( $row ) { |
83 | return $this->msg( 'nimagelinks' )->numParams( $row->value )->escaped() . '<br />'; |
84 | } |
85 | |
86 | /** |
87 | * Make sure we are on the shared repo. |
88 | * |
89 | * This function should only be used as a paranoia check, and should never actually be hit. |
90 | * There should be actual error handling for any code path a user could hit. |
91 | */ |
92 | protected function assertOnSharedRepo() { |
93 | if ( !GlobalUsage::onSharedRepo() ) { |
94 | throw new RuntimeException( |
95 | 'Special:MostGloballyLinkedFiles should only be processed on the shared repo' |
96 | ); |
97 | } |
98 | } |
99 | |
100 | /** |
101 | * Only list this special page on the wiki that is the shared repo. |
102 | * |
103 | * @return bool Should this be listed in Special:SpecialPages |
104 | */ |
105 | public function isListed() { |
106 | return GlobalUsage::onSharedRepo(); |
107 | } |
108 | |
109 | /** |
110 | * In most common configs (including WMF's), this wouldn't be needed. However |
111 | * for completeness support having the shared repo db be separate from the |
112 | * globalimagelinks db. |
113 | * @return IDatabase |
114 | */ |
115 | public function getRecacheDB() { |
116 | // There's no reason why we couldn't make this special page work on all wikis, |
117 | // it just doesn't really make sense to. We should be prevented from getting |
118 | // to this point by $this->isCachable(), but just to be safe: |
119 | $this->assertOnSharedRepo(); |
120 | |
121 | $globalUsageDatabase = $this->getConfig()->get( 'GlobalUsageDatabase' ); |
122 | if ( $globalUsageDatabase === false || $globalUsageDatabase === WikiMap::getCurrentWikiId() ) { |
123 | // We are using the local wiki |
124 | return parent::getRecacheDB(); |
125 | } else { |
126 | // The global usage db could be on a different db |
127 | return GlobalUsage::getGlobalDB( |
128 | DB_REPLICA, |
129 | [ $this->getName(), 'QueryPage::recache', 'vslow' ] |
130 | ); |
131 | } |
132 | } |
133 | |
134 | /** @inheritDoc */ |
135 | protected function getGroupName() { |
136 | return 'highuse'; |
137 | } |
138 | } |