Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 197 |
|
0.00% |
0 / 9 |
CRAP | |
0.00% |
0 / 1 |
FileSelectQueryBuilder | |
0.00% |
0 / 197 |
|
0.00% |
0 / 9 |
600 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 15 |
|
0.00% |
0 / 1 |
42 | |||
newForFile | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
newForOldFile | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
newForArchivedFile | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
initFileOld | |
0.00% |
0 / 31 |
|
0.00% |
0 / 1 |
12 | |||
initFileNew | |
0.00% |
0 / 39 |
|
0.00% |
0 / 1 |
12 | |||
initOldFileOld | |
0.00% |
0 / 32 |
|
0.00% |
0 / 1 |
12 | |||
initOldFileNew | |
0.00% |
0 / 40 |
|
0.00% |
0 / 1 |
12 | |||
initArchivedFile | |
0.00% |
0 / 37 |
|
0.00% |
0 / 1 |
12 |
1 | <?php |
2 | /** |
3 | * This program is free software; you can redistribute it and/or modify |
4 | * it under the terms of the GNU General Public License as published by |
5 | * the Free Software Foundation; either version 2 of the License, or |
6 | * (at your option) any later version. |
7 | * |
8 | * This program is distributed in the hope that it will be useful, |
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
11 | * GNU General Public License for more details. |
12 | * |
13 | * You should have received a copy of the GNU General Public License along |
14 | * with this program; if not, write to the Free Software Foundation, Inc., |
15 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
16 | * http://www.gnu.org/copyleft/gpl.html |
17 | * |
18 | * @file |
19 | */ |
20 | |
21 | namespace MediaWiki\FileRepo\File; |
22 | |
23 | use InvalidArgumentException; |
24 | use MediaWiki\MainConfigNames; |
25 | use MediaWiki\MediaWikiServices; |
26 | use Wikimedia\Rdbms\IReadableDatabase; |
27 | use Wikimedia\Rdbms\SelectQueryBuilder; |
28 | |
29 | class FileSelectQueryBuilder extends SelectQueryBuilder { |
30 | |
31 | private int $migrationStage; |
32 | |
33 | /** |
34 | * @internal use ::newFor* instead. |
35 | * @param IReadableDatabase $db |
36 | * @param string $type either 'file', 'oldfile' or 'archivedfile' |
37 | * @param array $options |
38 | * - omit-lazy: Omit fields that are lazily cached. |
39 | */ |
40 | public function __construct( IReadableDatabase $db, string $type = 'file', array $options = [] ) { |
41 | parent::__construct( $db ); |
42 | $this->migrationStage = MediaWikiServices::getInstance()->getMainConfig()->get( |
43 | MainConfigNames::FileSchemaMigrationStage |
44 | ); |
45 | if ( $type === 'file' ) { |
46 | if ( $this->migrationStage & SCHEMA_COMPAT_READ_OLD ) { |
47 | $this->initFileOld( $options ); |
48 | } else { |
49 | $this->initFileNew( $options ); |
50 | } |
51 | } elseif ( $type === 'oldfile' ) { |
52 | if ( $this->migrationStage & SCHEMA_COMPAT_READ_OLD ) { |
53 | $this->initOldFileOld( $options ); |
54 | } else { |
55 | $this->initOldFileNew( $options ); |
56 | } |
57 | } elseif ( $type === 'archivedfile' ) { |
58 | $this->initArchivedFile( $options ); |
59 | } else { |
60 | throw new InvalidArgumentException( "Type $type is not among accepted values" ); |
61 | } |
62 | } |
63 | |
64 | public static function newForFile( IReadableDatabase $db, array $options = [] ): FileSelectQueryBuilder { |
65 | return new FileSelectQueryBuilder( $db, 'file', $options ); |
66 | } |
67 | |
68 | public static function newForOldFile( IReadableDatabase $db, array $options = [] ): FileSelectQueryBuilder { |
69 | return new FileSelectQueryBuilder( $db, 'oldfile', $options ); |
70 | } |
71 | |
72 | public static function newForArchivedFile( IReadableDatabase $db, array $options = [] ): FileSelectQueryBuilder { |
73 | return new FileSelectQueryBuilder( $db, 'archivedfile', $options ); |
74 | } |
75 | |
76 | private function initFileOld( array $options ) { |
77 | $this->table( 'image' ) |
78 | ->join( 'actor', 'image_actor', 'actor_id=img_actor' ) |
79 | ->join( |
80 | 'comment', |
81 | 'comment_img_description', |
82 | 'comment_img_description.comment_id = img_description_id' |
83 | ); |
84 | |
85 | if ( !in_array( 'omit-nonlazy', $options, true ) ) { |
86 | $this->fields( |
87 | [ |
88 | 'img_name', |
89 | 'img_size', |
90 | 'img_width', |
91 | 'img_height', |
92 | 'img_metadata', |
93 | 'img_bits', |
94 | 'img_media_type', |
95 | 'img_major_mime', |
96 | 'img_minor_mime', |
97 | 'img_timestamp', |
98 | 'img_sha1', |
99 | 'img_actor', |
100 | 'img_user' => 'image_actor.actor_user', |
101 | 'img_user_text' => 'image_actor.actor_name', |
102 | 'img_description_text' => 'comment_img_description.comment_text', |
103 | 'img_description_data' => 'comment_img_description.comment_data', |
104 | 'img_description_cid' => 'comment_img_description.comment_id' |
105 | ] |
106 | ); |
107 | } |
108 | if ( !in_array( 'omit-lazy', $options, true ) ) { |
109 | // Note: Keep this in sync with LocalFile::getLazyCacheFields() and |
110 | // LocalFile::loadExtraFromDB() |
111 | $this->field( 'img_metadata' ); |
112 | } |
113 | } |
114 | |
115 | private function initFileNew( array $options ) { |
116 | $subquery = $this->newSubquery(); |
117 | $subquery->table( 'file' ) |
118 | ->join( 'filerevision', null, 'file_latest = fr_id' ) |
119 | ->join( 'filetypes', null, 'file_type = ft_id' ) |
120 | ->join( 'actor', 'image_actor', 'actor_id=fr_actor' ) |
121 | ->join( |
122 | 'comment', |
123 | 'comment_img_description', |
124 | 'comment_img_description.comment_id = fr_description_id' |
125 | ); |
126 | |
127 | if ( !in_array( 'omit-nonlazy', $options, true ) ) { |
128 | $subquery->fields( |
129 | [ |
130 | 'img_file_id' => 'file_id', |
131 | 'img_filerevision_id' => 'fr_id', |
132 | 'img_name' => 'file_name', |
133 | 'img_size' => 'fr_size', |
134 | 'img_width' => 'fr_width', |
135 | 'img_height' => 'fr_height', |
136 | 'img_metadata' => 'fr_metadata', |
137 | 'img_bits' => 'fr_bits', |
138 | 'img_media_type' => 'ft_media_type', |
139 | 'img_major_mime' => 'ft_major_mime', |
140 | 'img_minor_mime' => 'ft_minor_mime', |
141 | 'img_timestamp' => 'fr_timestamp', |
142 | 'img_sha1' => 'fr_sha1', |
143 | 'img_actor' => 'fr_actor', |
144 | 'img_user' => 'image_actor.actor_user', |
145 | 'img_user_text' => 'image_actor.actor_name', |
146 | 'img_description_text' => 'comment_img_description.comment_text', |
147 | 'img_description_data' => 'comment_img_description.comment_data', |
148 | 'img_description_cid' => 'comment_img_description.comment_id' |
149 | ] |
150 | ); |
151 | } |
152 | if ( !in_array( 'omit-lazy', $options, true ) ) { |
153 | // Note: Keep this in sync with LocalFile::getLazyCacheFields() and |
154 | // LocalFile::loadExtraFromDB() |
155 | $subquery->field( 'fr_metadata', 'img_metadata' ); |
156 | } |
157 | |
158 | $subquery->where( [ 'file_deleted' => 0 ] ); |
159 | |
160 | // Without the wrapper, callers can't make conditions |
161 | // on the old field names so all of them would need updating. |
162 | // See https://stackoverflow.com/a/8370146 |
163 | $this->field( '*' ) |
164 | ->from( $subquery ); |
165 | } |
166 | |
167 | private function initOldFileOld( array $options ) { |
168 | $this->table( 'oldimage' ) |
169 | ->join( 'actor', 'oldimage_actor', 'actor_id=oi_actor' ) |
170 | ->join( |
171 | 'comment', |
172 | 'comment_oi_description', |
173 | 'comment_oi_description.comment_id = oi_description_id' |
174 | ); |
175 | |
176 | if ( !in_array( 'omit-nonlazy', $options, true ) ) { |
177 | $this->fields( |
178 | [ |
179 | 'oi_name', |
180 | 'oi_archive_name', |
181 | 'oi_size', |
182 | 'oi_width', |
183 | 'oi_height', |
184 | 'oi_bits', |
185 | 'oi_media_type', |
186 | 'oi_major_mime', |
187 | 'oi_minor_mime', |
188 | 'oi_timestamp', |
189 | 'oi_deleted', |
190 | 'oi_sha1', |
191 | 'oi_actor', |
192 | 'oi_user' => 'oldimage_actor.actor_user', |
193 | 'oi_user_text' => 'oldimage_actor.actor_name', |
194 | 'oi_description_text' => 'comment_oi_description.comment_text', |
195 | 'oi_description_data' => 'comment_oi_description.comment_data', |
196 | 'oi_description_cid' => 'comment_oi_description.comment_id' |
197 | ] |
198 | ); |
199 | } |
200 | if ( !in_array( 'omit-lazy', $options, true ) ) { |
201 | // Note: Keep this in sync with LocalFile::getLazyCacheFields() and |
202 | // LocalFile::loadExtraFromDB() |
203 | $this->field( 'oi_metadata' ); |
204 | } |
205 | } |
206 | |
207 | private function initOldFileNew( array $options ) { |
208 | $subquery = $this->newSubquery(); |
209 | $subquery->table( 'filerevision' ) |
210 | ->join( 'file', null, 'fr_file = file_id' ) |
211 | ->join( 'filetypes', null, 'file_type = ft_id' ) |
212 | ->join( 'actor', 'oldimage_actor', 'actor_id = fr_actor' ) |
213 | ->join( |
214 | 'comment', |
215 | 'comment_oi_description', |
216 | 'comment_oi_description.comment_id = fr_description_id' |
217 | ); |
218 | |
219 | if ( !in_array( 'omit-nonlazy', $options, true ) ) { |
220 | $subquery->fields( |
221 | [ |
222 | 'oi_file_id' => 'file_id', |
223 | 'oi_filerevision_id' => 'fr_id', |
224 | 'oi_name' => 'file_name', |
225 | 'oi_archive_name' => 'fr_archive_name', |
226 | 'oi_size' => 'fr_size', |
227 | 'oi_width' => 'fr_width', |
228 | 'oi_height' => 'fr_height', |
229 | 'oi_bits' => 'fr_bits', |
230 | 'oi_media_type' => 'ft_media_type', |
231 | 'oi_major_mime' => 'ft_major_mime', |
232 | 'oi_minor_mime' => 'ft_minor_mime', |
233 | 'oi_timestamp' => 'fr_timestamp', |
234 | 'oi_deleted' => 'fr_deleted', |
235 | 'oi_sha1' => 'fr_sha1', |
236 | 'oi_actor' => 'fr_actor', |
237 | 'oi_user' => 'oldimage_actor.actor_user', |
238 | 'oi_user_text' => 'oldimage_actor.actor_name', |
239 | 'oi_description_text' => 'comment_oi_description.comment_text', |
240 | 'oi_description_data' => 'comment_oi_description.comment_data', |
241 | 'oi_description_cid' => 'comment_oi_description.comment_id' |
242 | ] |
243 | ); |
244 | } |
245 | if ( !in_array( 'omit-lazy', $options, true ) ) { |
246 | // Note: Keep this in sync with LocalFile::getLazyCacheFields() and |
247 | // LocalFile::loadExtraFromDB() |
248 | $subquery->field( 'fr_metadata', 'oi_metadata' ); |
249 | } |
250 | |
251 | $subquery->where( 'file_latest != fr_id' ); |
252 | $this->field( '*' ) |
253 | ->from( $subquery ); |
254 | } |
255 | |
256 | private function initArchivedFile( array $options ) { |
257 | $this->table( 'filearchive' ) |
258 | ->join( 'actor', 'filearchive_actor', 'actor_id=fa_actor' ) |
259 | ->join( |
260 | 'comment', |
261 | 'comment_fa_description', |
262 | 'comment_fa_description.comment_id = fa_description_id' |
263 | ); |
264 | |
265 | if ( !in_array( 'omit-nonlazy', $options, true ) ) { |
266 | $this->fields( |
267 | [ |
268 | 'fa_id', |
269 | 'fa_name', |
270 | 'fa_archive_name', |
271 | 'fa_storage_key', |
272 | 'fa_storage_group', |
273 | 'fa_size', |
274 | 'fa_bits', |
275 | 'fa_width', |
276 | 'fa_height', |
277 | 'fa_metadata', |
278 | 'fa_media_type', |
279 | 'fa_major_mime', |
280 | 'fa_minor_mime', |
281 | 'fa_timestamp', |
282 | 'fa_deleted', |
283 | 'fa_deleted_timestamp', /* Used by LocalFileRestoreBatch */ |
284 | 'fa_sha1', |
285 | 'fa_actor', |
286 | 'fa_user' => 'filearchive_actor.actor_user', |
287 | 'fa_user_text' => 'filearchive_actor.actor_name', |
288 | 'fa_description_text' => 'comment_fa_description.comment_text', |
289 | 'fa_description_data' => 'comment_fa_description.comment_data', |
290 | 'fa_description_cid' => 'comment_fa_description.comment_id' |
291 | ] |
292 | ); |
293 | } |
294 | if ( !in_array( 'omit-lazy', $options, true ) ) { |
295 | // Note: Keep this in sync with LocalFile::getLazyCacheFields() and |
296 | // LocalFile::loadExtraFromDB() |
297 | $this->field( 'fa_metadata' ); |
298 | } |
299 | } |
300 | } |