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