Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
87.84% covered (warning)
87.84%
65 / 74
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
MediaFileTrait
89.04% covered (warning)
89.04%
65 / 73
0.00% covered (danger)
0.00%
0 / 3
20.53
0.00% covered (danger)
0.00%
0 / 1
 getFileInfo
89.13% covered (warning)
89.13%
41 / 46
0.00% covered (danger)
0.00%
0 / 1
10.13
 getTransformInfo
94.44% covered (success)
94.44%
17 / 18
0.00% covered (danger)
0.00%
0 / 1
7.01
 getImageLimitsFromOption
77.78% covered (warning)
77.78%
7 / 9
0.00% covered (danger)
0.00%
0 / 1
3.10
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
21namespace MediaWiki\FileRepo\File;
22
23use MediaWiki\MainConfigNames;
24use MediaWiki\MediaWikiServices;
25use MediaWiki\Permissions\Authority;
26use MediaWiki\User\UserIdentity;
27
28/**
29 * Trait for functionality related to media files
30 *
31 * @internal
32 * @ingroup FileRepo
33 */
34trait MediaFileTrait {
35    /**
36     * @param File $file
37     * @param Authority $performer for permissions check
38     * @param array $transforms array of transforms to include in the response
39     * @return array response data
40     */
41    private function getFileInfo( $file, Authority $performer, $transforms ) {
42        $urlUtils = MediaWikiServices::getInstance()->getUrlUtils();
43        // If there is a problem with the file, there is very little info we can reliably
44        // return (T228286, T239213), but we do what we can (T201205).
45        $responseFile = [
46            'title' => $file->getTitle()->getText(),
47            'file_description_url' => $urlUtils->expand( $file->getDescriptionUrl(), PROTO_RELATIVE ),
48            'latest' => null,
49            'preferred' => null,
50            'original' => null,
51        ];
52
53        foreach ( $transforms as $transformType => $_ ) {
54            $responseFile[$transformType] = null;
55        }
56
57        if ( $file->exists() ) {
58            $uploader = $file->getUploader( File::FOR_THIS_USER, $performer );
59            if ( $uploader ) {
60                $fileUser = [
61                    'id' => $uploader->getId(),
62                    'name' => $uploader->getName(),
63                ];
64            } else {
65                $fileUser = [
66                    'id' => null,
67                    'name' => null,
68                ];
69            }
70            $responseFile['latest'] = [
71                'timestamp' => wfTimestamp( TS_ISO_8601, $file->getTimestamp() ),
72                'user' => $fileUser,
73            ];
74
75            // If the file doesn't and shouldn't have a duration, return null instead of 0.
76            // Testing for 0 first, then checking mediatype, makes gifs behave as desired for
77            // both still and animated cases.
78            $duration = $file->getLength();
79            $mediaTypesWithDurations = [ MEDIATYPE_AUDIO, MEDIATYPE_VIDEO, MEDIATYPE_MULTIMEDIA ];
80            if ( $duration == 0 && !in_array( $file->getMediaType(), $mediaTypesWithDurations ) ) {
81                $duration = null;
82            }
83
84            if ( $file->allowInlineDisplay() ) {
85                foreach ( $transforms as $transformType => $transform ) {
86                    $responseFile[$transformType] = $this->getTransformInfo(
87                        $file,
88                        // @phan-suppress-next-line PhanTypeMismatchArgumentNullable False positive
89                        $duration,
90                        $transform['maxWidth'],
91                        $transform['maxHeight']
92                    );
93                }
94            }
95
96            $responseFile['original'] = [
97                'mediatype' => $file->getMediaType(),
98                'size' => $file->getSize(),
99                'width' => $file->getWidth() ?: null,
100                'height' => $file->getHeight() ?: null,
101                'duration' => $duration,
102                'url' => $urlUtils->expand( $file->getUrl(), PROTO_RELATIVE ),
103            ];
104        }
105
106        return $responseFile;
107    }
108
109    /**
110     * @param File $file
111     * @param int|null $duration File duration (if any)
112     * @param int $maxWidth Max width to display at
113     * @param int $maxHeight Max height to display at
114     * @return array|null Transform info ready to include in response, or null if unavailable
115     */
116    private function getTransformInfo( $file, $duration, $maxWidth, $maxHeight ) {
117        $transformInfo = null;
118
119        [ $width, $height ] = $file->getDisplayWidthHeight( $maxWidth, $maxHeight );
120        $transform = $file->transform( [ 'width' => $width, 'height' => $height ] );
121        if ( $transform && !$transform->isError() ) {
122            // $file->getSize() returns original size. Only include if dimensions match.
123            $size = null;
124            if ( $file->getWidth() == $transform->getWidth() &&
125                $file->getHeight() == $transform->getHeight()
126            ) {
127                $size = $file->getSize();
128            }
129
130            $transformInfo = [
131                'mediatype' => $transform->getFile()->getMediaType(),
132                'size' => $size,
133                'width' => $transform->getWidth() ?: null,
134                'height' => $transform->getHeight() ?: null,
135                'duration' => $duration,
136                'url' => MediaWikiServices::getInstance()->getUrlUtils()
137                    ->expand( $transform->getUrl(), PROTO_RELATIVE ),
138            ];
139        }
140
141        return $transformInfo;
142    }
143
144    /**
145     * Returns the corresponding $wgImageLimits entry for the selected user option
146     *
147     * @param UserIdentity $user
148     * @param string $optionName Name of a option to check, typically imagesize or thumbsize
149     * @return int[]
150     * @since 1.35
151     */
152    public static function getImageLimitsFromOption( UserIdentity $user, string $optionName ) {
153        $imageLimits = MediaWikiServices::getInstance()->getMainConfig()
154            ->get( MainConfigNames::ImageLimits );
155        $optionsLookup = MediaWikiServices::getInstance()->getUserOptionsLookup();
156        $option = $optionsLookup->getIntOption( $user, $optionName );
157        if ( !isset( $imageLimits[$option] ) ) {
158            $option = $optionsLookup->getDefaultOption( $optionName, $user );
159        }
160
161        // The user offset might still be incorrect, specially if
162        // $wgImageLimits got changed (see T10858).
163        if ( !isset( $imageLimits[$option] ) ) {
164            // Default to the first offset in $wgImageLimits
165            $option = 0;
166        }
167
168        // if nothing is set, fallback to a hardcoded default
169        return $imageLimits[$option] ?? [ 800, 600 ];
170    }
171}
172
173/** @deprecated class alias since 1.44 */
174class_alias( MediaFileTrait::class, 'MediaFileTrait' );