Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
70.43% |
81 / 115 |
|
53.85% |
7 / 13 |
CRAP | |
0.00% |
0 / 1 |
SpecialMIMESearch | |
71.05% |
81 / 114 |
|
53.85% |
7 / 13 |
31.70 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 | |||
isExpensive | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
isSyndicated | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
isCacheable | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
linkParameters | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getQueryInfo | |
100.00% |
35 / 35 |
|
100.00% |
1 / 1 |
2 | |||
getOrderFields | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getPageHeader | |
100.00% |
17 / 17 |
|
100.00% |
1 / 1 |
1 | |||
getSuggestionsForTypes | |
68.42% |
13 / 19 |
|
0.00% |
0 / 1 |
3.28 | |||
execute | |
66.67% |
8 / 12 |
|
0.00% |
0 / 1 |
7.33 | |||
formatResult | |
0.00% |
0 / 20 |
|
0.00% |
0 / 1 |
2 | |||
preprocessResults | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getGroupName | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | /** |
3 | * Implements Special:MIMESearch |
4 | * |
5 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published by |
7 | * the Free Software Foundation; either version 2 of the License, or |
8 | * (at your option) any later version. |
9 | * |
10 | * This program is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | * GNU General Public License for more details. |
14 | * |
15 | * You should have received a copy of the GNU General Public License along |
16 | * with this program; if not, write to the Free Software Foundation, Inc., |
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
18 | * http://www.gnu.org/copyleft/gpl.html |
19 | * |
20 | * @file |
21 | * @ingroup SpecialPage |
22 | * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com> |
23 | */ |
24 | |
25 | namespace MediaWiki\Specials; |
26 | |
27 | use File; |
28 | use HtmlArmor; |
29 | use ILanguageConverter; |
30 | use LocalFile; |
31 | use MediaWiki\Cache\LinkBatchFactory; |
32 | use MediaWiki\HTMLForm\HTMLForm; |
33 | use MediaWiki\Languages\LanguageConverterFactory; |
34 | use MediaWiki\Linker\Linker; |
35 | use MediaWiki\MediaWikiServices; |
36 | use MediaWiki\SpecialPage\QueryPage; |
37 | use MediaWiki\Title\Title; |
38 | use Skin; |
39 | use stdClass; |
40 | use Wikimedia\Rdbms\IConnectionProvider; |
41 | |
42 | /** |
43 | * Searches the database for files of the requested MIME type, comparing this with the |
44 | * 'img_major_mime' and 'img_minor_mime' fields in the image table. |
45 | * @ingroup SpecialPage |
46 | */ |
47 | class SpecialMIMESearch extends QueryPage { |
48 | protected $major; |
49 | protected $minor; |
50 | protected $mime; |
51 | |
52 | private ILanguageConverter $languageConverter; |
53 | |
54 | /** |
55 | * @param IConnectionProvider $dbProvider |
56 | * @param LinkBatchFactory $linkBatchFactory |
57 | * @param LanguageConverterFactory $languageConverterFactory |
58 | */ |
59 | public function __construct( |
60 | IConnectionProvider $dbProvider, |
61 | LinkBatchFactory $linkBatchFactory, |
62 | LanguageConverterFactory $languageConverterFactory |
63 | ) { |
64 | parent::__construct( 'MIMEsearch' ); |
65 | $this->setDatabaseProvider( $dbProvider ); |
66 | $this->setLinkBatchFactory( $linkBatchFactory ); |
67 | $this->languageConverter = $languageConverterFactory->getLanguageConverter( $this->getContentLanguage() ); |
68 | } |
69 | |
70 | public function isExpensive() { |
71 | return false; |
72 | } |
73 | |
74 | public function isSyndicated() { |
75 | return false; |
76 | } |
77 | |
78 | public function isCacheable() { |
79 | return false; |
80 | } |
81 | |
82 | protected function linkParameters() { |
83 | return [ 'mime' => "{$this->major}/{$this->minor}" ]; |
84 | } |
85 | |
86 | public function getQueryInfo() { |
87 | $minorType = []; |
88 | if ( $this->minor !== '*' ) { |
89 | // Allow wildcard searching |
90 | $minorType['img_minor_mime'] = $this->minor; |
91 | } |
92 | $imgQuery = LocalFile::getQueryInfo(); |
93 | $qi = [ |
94 | 'tables' => $imgQuery['tables'], |
95 | 'fields' => [ |
96 | 'namespace' => NS_FILE, |
97 | 'title' => 'img_name', |
98 | // Still have a value field just in case, |
99 | // but it isn't actually used for sorting. |
100 | 'value' => 'img_name', |
101 | 'img_size', |
102 | 'img_width', |
103 | 'img_height', |
104 | 'img_user_text' => $imgQuery['fields']['img_user_text'], |
105 | 'img_timestamp' |
106 | ], |
107 | 'conds' => [ |
108 | 'img_major_mime' => $this->major, |
109 | // This is in order to trigger using |
110 | // the img_media_mime index in "range" mode. |
111 | // @todo how is order defined? use MimeAnalyzer::getMediaTypes? |
112 | 'img_media_type' => [ |
113 | MEDIATYPE_BITMAP, |
114 | MEDIATYPE_DRAWING, |
115 | MEDIATYPE_AUDIO, |
116 | MEDIATYPE_VIDEO, |
117 | MEDIATYPE_MULTIMEDIA, |
118 | MEDIATYPE_UNKNOWN, |
119 | MEDIATYPE_OFFICE, |
120 | MEDIATYPE_TEXT, |
121 | MEDIATYPE_EXECUTABLE, |
122 | MEDIATYPE_ARCHIVE, |
123 | MEDIATYPE_3D, |
124 | ], |
125 | ] + $minorType, |
126 | 'join_conds' => $imgQuery['joins'], |
127 | ]; |
128 | |
129 | return $qi; |
130 | } |
131 | |
132 | /** |
133 | * The index is on (img_media_type, img_major_mime, img_minor_mime) |
134 | * which unfortunately doesn't have img_name at the end for sorting. |
135 | * So tell db to sort it however it wishes (Its not super important |
136 | * that this report gives results in a logical order). As an additional |
137 | * note, mysql seems to by default order things by img_name ASC, which |
138 | * is what we ideally want, so everything works out fine anyhow. |
139 | * @return array |
140 | */ |
141 | protected function getOrderFields() { |
142 | return []; |
143 | } |
144 | |
145 | /** |
146 | * Generate and output the form |
147 | * @return string |
148 | */ |
149 | protected function getPageHeader() { |
150 | $formDescriptor = [ |
151 | 'mime' => [ |
152 | 'type' => 'combobox', |
153 | 'options' => $this->getSuggestionsForTypes(), |
154 | 'name' => 'mime', |
155 | 'label-message' => 'mimetype', |
156 | 'required' => true, |
157 | 'default' => $this->mime, |
158 | ], |
159 | ]; |
160 | |
161 | HTMLForm::factory( 'ooui', $formDescriptor, $this->getContext() ) |
162 | ->setSubmitTextMsg( 'ilsubmit' ) |
163 | ->setTitle( $this->getPageTitle() ) |
164 | ->setMethod( 'get' ) |
165 | ->prepareForm() |
166 | ->displayForm( false ); |
167 | return ''; |
168 | } |
169 | |
170 | protected function getSuggestionsForTypes() { |
171 | $queryBuilder = $this->getDatabaseProvider()->getReplicaDatabase()->newSelectQueryBuilder(); |
172 | $queryBuilder |
173 | // We ignore img_media_type, but using it in the query is needed for MySQL to choose a |
174 | // sensible execution plan |
175 | ->select( [ 'img_media_type', 'img_major_mime', 'img_minor_mime' ] ) |
176 | ->from( 'image' ) |
177 | ->groupBy( [ 'img_media_type', 'img_major_mime', 'img_minor_mime' ] ); |
178 | $result = $queryBuilder->caller( __METHOD__ )->fetchResultSet(); |
179 | |
180 | $lastMajor = null; |
181 | $suggestions = []; |
182 | foreach ( $result as $row ) { |
183 | $major = $row->img_major_mime; |
184 | $minor = $row->img_minor_mime; |
185 | $suggestions[ "$major/$minor" ] = "$major/$minor"; |
186 | if ( $lastMajor === $major ) { |
187 | // If there are at least two with the same major mime type, also include the wildcard |
188 | $suggestions[ "$major/*" ] = "$major/*"; |
189 | } |
190 | $lastMajor = $major; |
191 | } |
192 | ksort( $suggestions ); |
193 | return $suggestions; |
194 | } |
195 | |
196 | public function execute( $par ) { |
197 | $this->addHelpLink( 'Help:Managing_files' ); |
198 | $this->mime = $par ?: $this->getRequest()->getText( 'mime' ); |
199 | $this->mime = trim( $this->mime ); |
200 | [ $this->major, $this->minor ] = File::splitMime( $this->mime ); |
201 | $mimeAnalyzer = MediaWikiServices::getInstance()->getMimeAnalyzer(); |
202 | |
203 | if ( $this->major == '' || $this->minor == '' || $this->minor == 'unknown' || |
204 | !$mimeAnalyzer->isValidMajorMimeType( $this->major ) |
205 | ) { |
206 | $this->setHeaders(); |
207 | $this->outputHeader(); |
208 | $this->getPageHeader(); |
209 | return; |
210 | } |
211 | |
212 | parent::execute( $par ); |
213 | } |
214 | |
215 | /** |
216 | * @param Skin $skin |
217 | * @param stdClass $result Result row |
218 | * @return string |
219 | */ |
220 | public function formatResult( $skin, $result ) { |
221 | $linkRenderer = $this->getLinkRenderer(); |
222 | $nt = Title::makeTitle( $result->namespace, $result->title ); |
223 | |
224 | $text = $this->languageConverter->convertHtml( $nt->getText() ); |
225 | $plink = $linkRenderer->makeLink( |
226 | Title::newFromText( $nt->getPrefixedText() ), |
227 | new HtmlArmor( $text ) |
228 | ); |
229 | |
230 | $download = Linker::makeMediaLinkObj( $nt, $this->msg( 'download' )->escaped() ); |
231 | $download = $this->msg( 'parentheses' )->rawParams( $download )->escaped(); |
232 | $lang = $this->getLanguage(); |
233 | $bytes = htmlspecialchars( $lang->formatSize( $result->img_size ) ); |
234 | $dimensions = $this->msg( 'widthheight' )->numParams( $result->img_width, |
235 | $result->img_height )->escaped(); |
236 | $user = $linkRenderer->makeLink( |
237 | Title::makeTitle( NS_USER, $result->img_user_text ), |
238 | $result->img_user_text |
239 | ); |
240 | |
241 | $time = $lang->userTimeAndDate( $result->img_timestamp, $this->getUser() ); |
242 | $time = htmlspecialchars( $time ); |
243 | |
244 | return "$download $plink . . $dimensions . . $bytes . . $user . . $time"; |
245 | } |
246 | |
247 | public function preprocessResults( $db, $res ) { |
248 | $this->executeLBFromResultWrapper( $res ); |
249 | } |
250 | |
251 | protected function getGroupName() { |
252 | return 'media'; |
253 | } |
254 | } |
255 | |
256 | /** |
257 | * Retain the old class name for backwards compatibility. |
258 | * @deprecated since 1.41 |
259 | */ |
260 | class_alias( SpecialMIMESearch::class, 'SpecialMIMESearch' ); |