Conditions | 56 |
Paths | > 20000 |
Total Lines | 283 |
Code Lines | 177 |
Lines | 9 |
Ratio | 3.18 % |
Changes | 0 |
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
1 | <?php |
||
91 | function wfStreamThumb( array $params ) { |
||
92 | global $wgVaryOnXFP; |
||
93 | |||
94 | $headers = []; // HTTP headers to send |
||
95 | |||
96 | $fileName = isset( $params['f'] ) ? $params['f'] : ''; |
||
97 | |||
98 | // Backwards compatibility parameters |
||
99 | if ( isset( $params['w'] ) ) { |
||
100 | $params['width'] = $params['w']; |
||
101 | unset( $params['w'] ); |
||
102 | } |
||
103 | if ( isset( $params['width'] ) && substr( $params['width'], -2 ) == 'px' ) { |
||
104 | // strip the px (pixel) suffix, if found |
||
105 | $params['width'] = substr( $params['width'], 0, -2 ); |
||
106 | } |
||
107 | if ( isset( $params['p'] ) ) { |
||
108 | $params['page'] = $params['p']; |
||
109 | } |
||
110 | |||
111 | // Is this a thumb of an archived file? |
||
112 | $isOld = ( isset( $params['archived'] ) && $params['archived'] ); |
||
113 | unset( $params['archived'] ); // handlers don't care |
||
114 | |||
115 | // Is this a thumb of a temp file? |
||
116 | $isTemp = ( isset( $params['temp'] ) && $params['temp'] ); |
||
117 | unset( $params['temp'] ); // handlers don't care |
||
118 | |||
119 | // Some basic input validation |
||
120 | $fileName = strtr( $fileName, '\\/', '__' ); |
||
121 | |||
122 | // Actually fetch the image. Method depends on whether it is archived or not. |
||
123 | if ( $isTemp ) { |
||
124 | $repo = RepoGroup::singleton()->getLocalRepo()->getTempRepo(); |
||
125 | $img = new UnregisteredLocalFile( null, $repo, |
||
126 | # Temp files are hashed based on the name without the timestamp. |
||
127 | # The thumbnails will be hashed based on the entire name however. |
||
128 | # @todo fix this convention to actually be reasonable. |
||
129 | $repo->getZonePath( 'public' ) . '/' . $repo->getTempHashPath( $fileName ) . $fileName |
||
130 | ); |
||
131 | } elseif ( $isOld ) { |
||
132 | // Format is <timestamp>!<name> |
||
133 | $bits = explode( '!', $fileName, 2 ); |
||
134 | if ( count( $bits ) != 2 ) { |
||
135 | wfThumbError( 404, wfMessage( 'badtitletext' )->parse() ); |
||
136 | return; |
||
137 | } |
||
138 | $title = Title::makeTitleSafe( NS_FILE, $bits[1] ); |
||
139 | if ( !$title ) { |
||
140 | wfThumbError( 404, wfMessage( 'badtitletext' )->parse() ); |
||
141 | return; |
||
142 | } |
||
143 | $img = RepoGroup::singleton()->getLocalRepo()->newFromArchiveName( $title, $fileName ); |
||
144 | } else { |
||
145 | $img = wfLocalFile( $fileName ); |
||
146 | } |
||
147 | |||
148 | // Check the source file title |
||
149 | if ( !$img ) { |
||
150 | wfThumbError( 404, wfMessage( 'badtitletext' )->parse() ); |
||
151 | return; |
||
152 | } |
||
153 | |||
154 | // Check permissions if there are read restrictions |
||
155 | $varyHeader = []; |
||
156 | if ( !in_array( 'read', User::getGroupPermissions( [ '*' ] ), true ) ) { |
||
157 | if ( !$img->getTitle() || !$img->getTitle()->userCan( 'read' ) ) { |
||
158 | wfThumbError( 403, 'Access denied. You do not have permission to access ' . |
||
159 | 'the source file.' ); |
||
160 | return; |
||
161 | } |
||
162 | $headers[] = 'Cache-Control: private'; |
||
163 | $varyHeader[] = 'Cookie'; |
||
164 | } |
||
165 | |||
166 | // Check if the file is hidden |
||
167 | if ( $img->isDeleted( File::DELETED_FILE ) ) { |
||
168 | wfThumbErrorText( 404, "The source file '$fileName' does not exist." ); |
||
169 | return; |
||
170 | } |
||
171 | |||
172 | // Do rendering parameters extraction from thumbnail name. |
||
173 | if ( isset( $params['thumbName'] ) ) { |
||
174 | $params = wfExtractThumbParams( $img, $params ); |
||
175 | } |
||
176 | if ( $params == null ) { |
||
177 | wfThumbError( 400, 'The specified thumbnail parameters are not recognized.' ); |
||
178 | return; |
||
179 | } |
||
180 | |||
181 | // Check the source file storage path |
||
182 | if ( !$img->exists() ) { |
||
183 | $redirectedLocation = false; |
||
184 | if ( !$isTemp ) { |
||
185 | // Check for file redirect |
||
186 | // Since redirects are associated with pages, not versions of files, |
||
187 | // we look for the most current version to see if its a redirect. |
||
188 | $possRedirFile = RepoGroup::singleton()->getLocalRepo()->findFile( $img->getName() ); |
||
189 | if ( $possRedirFile && !is_null( $possRedirFile->getRedirected() ) ) { |
||
190 | $redirTarget = $possRedirFile->getName(); |
||
191 | $targetFile = wfLocalFile( Title::makeTitleSafe( NS_FILE, $redirTarget ) ); |
||
192 | if ( $targetFile->exists() ) { |
||
193 | $newThumbName = $targetFile->thumbName( $params ); |
||
194 | if ( $isOld ) { |
||
195 | /** @var array $bits */ |
||
196 | $newThumbUrl = $targetFile->getArchiveThumbUrl( |
||
197 | $bits[0] . '!' . $targetFile->getName(), $newThumbName ); |
||
198 | } else { |
||
199 | $newThumbUrl = $targetFile->getThumbUrl( $newThumbName ); |
||
200 | } |
||
201 | $redirectedLocation = wfExpandUrl( $newThumbUrl, PROTO_CURRENT ); |
||
202 | } |
||
203 | } |
||
204 | } |
||
205 | |||
206 | if ( $redirectedLocation ) { |
||
207 | // File has been moved. Give redirect. |
||
208 | $response = RequestContext::getMain()->getRequest()->response(); |
||
209 | $response->statusHeader( 302 ); |
||
210 | $response->header( 'Location: ' . $redirectedLocation ); |
||
211 | $response->header( 'Expires: ' . |
||
212 | gmdate( 'D, d M Y H:i:s', time() + 12 * 3600 ) . ' GMT' ); |
||
213 | if ( $wgVaryOnXFP ) { |
||
214 | $varyHeader[] = 'X-Forwarded-Proto'; |
||
215 | } |
||
216 | if ( count( $varyHeader ) ) { |
||
217 | $response->header( 'Vary: ' . implode( ', ', $varyHeader ) ); |
||
218 | } |
||
219 | $response->header( 'Content-Length: 0' ); |
||
220 | return; |
||
221 | } |
||
222 | |||
223 | // If its not a redirect that has a target as a local file, give 404. |
||
224 | wfThumbErrorText( 404, "The source file '$fileName' does not exist." ); |
||
225 | return; |
||
226 | } elseif ( $img->getPath() === false ) { |
||
227 | wfThumbErrorText( 400, "The source file '$fileName' is not locally accessible." ); |
||
228 | return; |
||
229 | } |
||
230 | |||
231 | // Check IMS against the source file |
||
232 | // This means that clients can keep a cached copy even after it has been deleted on the server |
||
233 | if ( !empty( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) ) { |
||
234 | // Fix IE brokenness |
||
235 | $imsString = preg_replace( '/;.*$/', '', $_SERVER["HTTP_IF_MODIFIED_SINCE"] ); |
||
236 | // Calculate time |
||
237 | MediaWiki\suppressWarnings(); |
||
238 | $imsUnix = strtotime( $imsString ); |
||
239 | MediaWiki\restoreWarnings(); |
||
240 | if ( wfTimestamp( TS_UNIX, $img->getTimestamp() ) <= $imsUnix ) { |
||
241 | HttpStatus::header( 304 ); |
||
242 | return; |
||
243 | } |
||
244 | } |
||
245 | |||
246 | $rel404 = isset( $params['rel404'] ) ? $params['rel404'] : null; |
||
247 | unset( $params['r'] ); // ignore 'r' because we unconditionally pass File::RENDER |
||
248 | unset( $params['f'] ); // We're done with 'f' parameter. |
||
249 | unset( $params['rel404'] ); // moved to $rel404 |
||
250 | |||
251 | // Get the normalized thumbnail name from the parameters... |
||
252 | try { |
||
253 | $thumbName = $img->thumbName( $params ); |
||
254 | if ( !strlen( $thumbName ) ) { // invalid params? |
||
255 | throw new MediaTransformInvalidParametersException( |
||
256 | 'Empty return from File::thumbName' |
||
257 | ); |
||
258 | } |
||
259 | $thumbName2 = $img->thumbName( $params, File::THUMB_FULL_NAME ); // b/c; "long" style |
||
260 | } catch ( MediaTransformInvalidParametersException $e ) { |
||
261 | wfThumbError( |
||
262 | 400, |
||
263 | 'The specified thumbnail parameters are not valid: ' . $e->getMessage() |
||
264 | ); |
||
265 | return; |
||
266 | } catch ( MWException $e ) { |
||
267 | wfThumbError( 500, $e->getHTML(), 'Exception caught while extracting thumb name', |
||
268 | [ 'exception' => $e ] ); |
||
269 | return; |
||
270 | } |
||
271 | |||
272 | // For 404 handled thumbnails, we only use the base name of the URI |
||
273 | // for the thumb params and the parent directory for the source file name. |
||
274 | // Check that the zone relative path matches up so squid caches won't pick |
||
275 | // up thumbs that would not be purged on source file deletion (bug 34231). |
||
276 | if ( $rel404 !== null ) { // thumbnail was handled via 404 |
||
277 | if ( rawurldecode( $rel404 ) === $img->getThumbRel( $thumbName ) ) { |
||
278 | // Request for the canonical thumbnail name |
||
279 | } elseif ( rawurldecode( $rel404 ) === $img->getThumbRel( $thumbName2 ) ) { |
||
280 | // Request for the "long" thumbnail name; redirect to canonical name |
||
281 | $response = RequestContext::getMain()->getRequest()->response(); |
||
282 | $response->statusHeader( 301 ); |
||
283 | $response->header( 'Location: ' . |
||
284 | wfExpandUrl( $img->getThumbUrl( $thumbName ), PROTO_CURRENT ) ); |
||
285 | $response->header( 'Expires: ' . |
||
286 | gmdate( 'D, d M Y H:i:s', time() + 7 * 86400 ) . ' GMT' ); |
||
287 | if ( $wgVaryOnXFP ) { |
||
288 | $varyHeader[] = 'X-Forwarded-Proto'; |
||
289 | } |
||
290 | if ( count( $varyHeader ) ) { |
||
291 | $response->header( 'Vary: ' . implode( ', ', $varyHeader ) ); |
||
292 | } |
||
293 | return; |
||
294 | } else { |
||
295 | wfThumbErrorText( 404, "The given path of the specified thumbnail is incorrect; |
||
296 | expected '" . $img->getThumbRel( $thumbName ) . "' but got '" . |
||
297 | rawurldecode( $rel404 ) . "'." ); |
||
298 | return; |
||
299 | } |
||
300 | } |
||
301 | |||
302 | $dispositionType = isset( $params['download'] ) ? 'attachment' : 'inline'; |
||
303 | |||
304 | // Suggest a good name for users downloading this thumbnail |
||
305 | $headers[] = |
||
306 | "Content-Disposition: {$img->getThumbDisposition( $thumbName, $dispositionType )}"; |
||
307 | |||
308 | if ( count( $varyHeader ) ) { |
||
309 | $headers[] = 'Vary: ' . implode( ', ', $varyHeader ); |
||
310 | } |
||
311 | |||
312 | // Stream the file if it exists already... |
||
313 | $thumbPath = $img->getThumbPath( $thumbName ); |
||
314 | if ( $img->getRepo()->fileExists( $thumbPath ) ) { |
||
315 | $starttime = microtime( true ); |
||
316 | $status = $img->getRepo()->streamFileWithStatus( $thumbPath, $headers ); |
||
317 | $streamtime = microtime( true ) - $starttime; |
||
318 | |||
319 | if ( $status->isOK() ) { |
||
320 | RequestContext::getMain()->getStats()->timing( 'media.thumbnail.stream', $streamtime ); |
||
321 | View Code Duplication | } else { |
|
322 | wfThumbError( 500, 'Could not stream the file', null, [ 'file' => $thumbName, |
||
323 | 'path' => $thumbPath, 'error' => $status->getWikiText( false, false, 'en' ) ] ); |
||
324 | } |
||
325 | return; |
||
326 | } |
||
327 | |||
328 | $user = RequestContext::getMain()->getUser(); |
||
329 | if ( !wfThumbIsStandard( $img, $params ) && $user->pingLimiter( 'renderfile-nonstandard' ) ) { |
||
330 | wfThumbError( 429, wfMessage( 'actionthrottledtext' )->parse() ); |
||
331 | return; |
||
332 | } elseif ( $user->pingLimiter( 'renderfile' ) ) { |
||
333 | wfThumbError( 429, wfMessage( 'actionthrottledtext' )->parse() ); |
||
334 | return; |
||
335 | } |
||
336 | |||
337 | list( $thumb, $errorMsg ) = wfGenerateThumbnail( $img, $params, $thumbName, $thumbPath ); |
||
338 | |||
339 | /** @var MediaTransformOutput|MediaTransformError|bool $thumb */ |
||
340 | |||
341 | // Check for thumbnail generation errors... |
||
342 | $msg = wfMessage( 'thumbnail_error' ); |
||
343 | $errorCode = 500; |
||
344 | if ( !$thumb ) { |
||
345 | $errorMsg = $errorMsg ?: $msg->rawParams( 'File::transform() returned false' )->escaped(); |
||
346 | if ( $errorMsg instanceof MessageSpecifier && |
||
347 | $errorMsg->getKey() === 'thumbnail_image-failure-limit' |
||
348 | ) { |
||
349 | $errorCode = 429; |
||
350 | } |
||
351 | } elseif ( $thumb->isError() ) { |
||
352 | $errorMsg = $thumb->getHtmlMsg(); |
||
353 | } elseif ( !$thumb->hasFile() ) { |
||
354 | $errorMsg = $msg->rawParams( 'No path supplied in thumbnail object' )->escaped(); |
||
355 | } elseif ( $thumb->fileIsSource() ) { |
||
356 | $errorMsg = $msg |
||
357 | ->rawParams( 'Image was not scaled, is the requested width bigger than the source?' ) |
||
358 | ->escaped(); |
||
359 | $errorCode = 400; |
||
360 | } |
||
361 | |||
362 | if ( $errorMsg !== false ) { |
||
363 | wfThumbError( $errorCode, $errorMsg, null, [ 'file' => $thumbName, 'path' => $thumbPath ] ); |
||
364 | } else { |
||
365 | // Stream the file if there were no errors |
||
366 | $status = $thumb->streamFileWithStatus( $headers ); |
||
367 | View Code Duplication | if ( !$status->isOK() ) { |
|
368 | wfThumbError( 500, 'Could not stream the file', null, [ |
||
369 | 'file' => $thumbName, 'path' => $thumbPath, |
||
370 | 'error' => $status->getWikiText( false, false, 'en' ) ] ); |
||
371 | } |
||
372 | } |
||
373 | } |
||
374 | |||
635 |
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.