1<?php 2/** 3 * Implements Special:Wantedfiles 4 * 5 * Copyright © 2008 Soxred93 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License along 18 * with this program; if not, write to the Free Software Foundation, Inc., 19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 * http://www.gnu.org/copyleft/gpl.html 21 * 22 * @file 23 * @ingroup SpecialPage 24 * @author Soxred93 <soxred93@gmail.com> 25 */ 26 27use MediaWiki\Cache\LinkBatchFactory; 28use MediaWiki\MediaWikiServices; 29use Wikimedia\Rdbms\ILoadBalancer; 30 31/** 32 * Querypage that lists the most wanted files 33 * 34 * @ingroup SpecialPage 35 */ 36class WantedFilesPage extends WantedQueryPage { 37 38 /** @var RepoGroup */ 39 private $repoGroup; 40 41 /** 42 * @param RepoGroup|string $repoGroup 43 * @param ILoadBalancer|null $loadBalancer 44 * @param LinkBatchFactory|null $linkBatchFactory 45 */ 46 public function __construct( 47 $repoGroup, 48 ILoadBalancer $loadBalancer = null, 49 LinkBatchFactory $linkBatchFactory = null 50 ) { 51 parent::__construct( is_string( $repoGroup ) ? $repoGroup : 'Wantedfiles' ); 52 // This class is extended and therefor fallback to global state - T265301 53 $services = MediaWikiServices::getInstance(); 54 $this->repoGroup = $repoGroup instanceof RepoGroup 55 ? $repoGroup 56 : $services->getRepoGroup(); 57 $this->setDBLoadBalancer( $loadBalancer ?? $services->getDBLoadBalancer() ); 58 $this->setLinkBatchFactory( $linkBatchFactory ?? $services->getLinkBatchFactory() ); 59 } 60 61 protected function getPageHeader() { 62 # Specifically setting to use "Wanted Files" (NS_MAIN) as title, so as to get what 63 # category would be used on main namespace pages, for those tricky wikipedia 64 # admins who like to do {{#ifeq:{{NAMESPACE}}|foo|bar|....}}. 65 $catMessage = $this->msg( 'broken-file-category' ) 66 ->title( Title::newFromText( "Wanted Files", NS_MAIN ) ) 67 ->inContentLanguage(); 68 69 if ( !$catMessage->isDisabled() ) { 70 $category = Title::makeTitleSafe( NS_CATEGORY, $catMessage->text() ); 71 } else { 72 $category = false; 73 } 74 75 $noForeign = ''; 76 if ( !$this->likelyToHaveFalsePositives() ) { 77 // Additional messages for grep: 78 // wantedfiletext-cat-noforeign, wantedfiletext-nocat-noforeign 79 $noForeign = '-noforeign'; 80 } 81 82 if ( $category ) { 83 return $this 84 ->msg( 'wantedfiletext-cat' . $noForeign ) 85 ->params( $category->getFullText() ) 86 ->parseAsBlock(); 87 } else { 88 return $this 89 ->msg( 'wantedfiletext-nocat' . $noForeign ) 90 ->parseAsBlock(); 91 } 92 } 93 94 /** 95 * Whether foreign repos are likely to cause false positives 96 * 97 * In its own function to allow subclasses to override. 98 * @see SpecialWantedFilesGUOverride in GlobalUsage extension. 99 * @since 1.24 100 * @return bool 101 */ 102 protected function likelyToHaveFalsePositives() { 103 return $this->repoGroup->hasForeignRepos(); 104 } 105 106 /** 107 * KLUGE: The results may contain false positives for files 108 * that exist e.g. in a shared repo. Setting this at least 109 * keeps them from showing up as redlinks in the output, even 110 * if it doesn't fix the real problem (T8220). 111 * 112 * @note could also have existing links here from broken file 113 * redirects. 114 * @return bool 115 */ 116 protected function forceExistenceCheck() { 117 return true; 118 } 119 120 /** 121 * Does the file exist? 122 * 123 * Use findFile() so we still think file namespace pages without files 124 * are missing, but valid file redirects and foreign files are ok. 125 * 126 * @param Title $title 127 * @return bool 128 */ 129 protected function existenceCheck( Title $title ) { 130 return (bool)$this->repoGroup->findFile( $title ); 131 } 132 133 public function getQueryInfo() { 134 return [ 135 'tables' => [ 136 'imagelinks', 137 'page', 138 'redirect', 139 'img1' => 'image', 140 'img2' => 'image', 141 ], 142 'fields' => [ 143 'namespace' => NS_FILE, 144 'title' => 'il_to', 145 'value' => 'COUNT(*)' 146 ], 147 'conds' => [ 148 'img1.img_name' => null, 149 // We also need to exclude file redirects 150 'img2.img_name' => null, 151 ], 152 'options' => [ 'GROUP BY' => 'il_to' ], 153 'join_conds' => [ 154 'img1' => [ 'LEFT JOIN', 155 'il_to = img1.img_name' 156 ], 157 'page' => [ 'LEFT JOIN', [ 158 'il_to = page_title', 159 'page_namespace' => NS_FILE, 160 ] ], 161 'redirect' => [ 'LEFT JOIN', [ 162 'page_id = rd_from', 163 'rd_namespace' => NS_FILE, 164 'rd_interwiki' => '' 165 ] ], 166 'img2' => [ 'LEFT JOIN', 167 'rd_title = img2.img_name' 168 ] 169 ] 170 ]; 171 } 172 173 protected function getGroupName() { 174 return 'maintenance'; 175 } 176} 177