In FileBackendBase/FileBackend:
[lhc/web/wiklou.git] / includes / filerepo / file / FSFile.php
1 <?php
2 /**
3 * @file
4 * @ingroup FileRepo
5 * @ingroup FileBackend
6 */
7
8 /**
9 * Class representing a non-directory file on the file system
10 *
11 * @ingroup FileRepo
12 * @ingroup FileBackend
13 */
14 class FSFile {
15 protected $path; // path to file
16
17 /**
18 * Sets up the file object
19 *
20 * @param String $path Path to temporary file on local disk
21 */
22 public function __construct( $path ) {
23 if ( FileBackend::isStoragePath( $path ) ) {
24 throw new MWException( __METHOD__ . " given storage path `$path`." );
25 }
26 $this->path = $path;
27 }
28
29 /**
30 * Returns the file system path
31 *
32 * @return String
33 */
34 public function getPath() {
35 return $this->path;
36 }
37
38 /**
39 * Checks if the file exists
40 *
41 * @return bool
42 */
43 public function exists() {
44 return is_file( $this->path );
45 }
46
47 /**
48 * Get the file size in bytes
49 *
50 * @return int|false
51 */
52 public function getSize() {
53 return filesize( $this->path );
54 }
55
56 /**
57 * Get the file's last-modified timestamp
58 *
59 * @return string|false TS_MW timestamp or false on failure
60 */
61 public function getTimestamp() {
62 wfSuppressWarnings();
63 $timestamp = filemtime( $this->path );
64 wfRestoreWarnings();
65 if ( $timestamp !== false ) {
66 $timestamp = wfTimestamp( TS_MW, $timestamp );
67 }
68 return $timestamp;
69 }
70
71 /**
72 * Get an associative array containing information about
73 * a file with the given storage path.
74 *
75 * @param $ext Mixed: the file extension, or true to extract it from the filename.
76 * Set it to false to ignore the extension.
77 *
78 * @return array
79 */
80 public function getProps( $ext = true ) {
81 wfProfileIn( __METHOD__ );
82 wfDebug( __METHOD__.": Getting file info for $this->path\n" );
83
84 $info = self::placeholderProps();
85 $info['fileExists'] = $this->exists();
86
87 if ( $info['fileExists'] ) {
88 $magic = MimeMagic::singleton();
89
90 # get the file extension
91 if ( $ext === true ) {
92 $i = strrpos( $this->path, '.' );
93 $ext = strtolower( $i ? substr( $this->path, $i + 1 ) : '' );
94 }
95
96 # mime type according to file contents
97 $info['file-mime'] = $magic->guessMimeType( $this->path, false );
98 # logical mime type
99 $info['mime'] = $magic->improveTypeFromExtension( $info['file-mime'], $ext );
100
101 list( $info['major_mime'], $info['minor_mime'] ) = File::splitMime( $info['mime'] );
102 $info['media_type'] = $magic->getMediaType( $this->path, $info['mime'] );
103
104 # Get size in bytes
105 $info['size'] = $this->getSize();
106
107 # Height, width and metadata
108 $handler = MediaHandler::getHandler( $info['mime'] );
109 if ( $handler ) {
110 $tempImage = (object)array();
111 $info['metadata'] = $handler->getMetadata( $tempImage, $this->path );
112 $gis = $handler->getImageSize( $tempImage, $this->path, $info['metadata'] );
113 if ( is_array( $gis ) ) {
114 $info = $this->extractImageSizeInfo( $gis ) + $info;
115 }
116 }
117 $info['sha1'] = $this->getSha1Base36();
118
119 wfDebug(__METHOD__.": $this->path loaded, {$info['size']} bytes, {$info['mime']}.\n");
120 } else {
121 wfDebug(__METHOD__.": $this->path NOT FOUND!\n");
122 }
123
124 wfProfileOut( __METHOD__ );
125 return $info;
126 }
127
128 /**
129 * Placeholder file properties to use for files that don't exist
130 *
131 * @return Array
132 */
133 public static function placeholderProps() {
134 $info = array();
135 $info['fileExists'] = false;
136 $info['mime'] = null;
137 $info['media_type'] = MEDIATYPE_UNKNOWN;
138 $info['metadata'] = '';
139 $info['sha1'] = '';
140 $info['width'] = 0;
141 $info['height'] = 0;
142 $info['bits'] = 0;
143 return $info;
144 }
145
146 protected function extractImageSizeInfo( array $gis ) {
147 $info = array();
148 # NOTE: $gis[2] contains a code for the image type. This is no longer used.
149 $info['width'] = $gis[0];
150 $info['height'] = $gis[1];
151 if ( isset( $gis['bits'] ) ) {
152 $info['bits'] = $gis['bits'];
153 } else {
154 $info['bits'] = 0;
155 }
156 return $info;
157 }
158
159 /**
160 * Get a SHA-1 hash of a file in the local filesystem, in base-36 lower case
161 * encoding, zero padded to 31 digits.
162 *
163 * 160 log 2 / log 36 = 30.95, so the 160-bit hash fills 31 digits in base 36
164 * fairly neatly.
165 *
166 * @return false|string False on failure
167 */
168 public function getSha1Base36() {
169 wfProfileIn( __METHOD__ );
170
171 wfSuppressWarnings();
172 $hash = sha1_file( $this->path );
173 wfRestoreWarnings();
174 if ( $hash !== false ) {
175 $hash = wfBaseConvert( $hash, 16, 36, 31 );
176 }
177
178 wfProfileOut( __METHOD__ );
179 return $hash;
180 }
181
182 /**
183 * Get an associative array containing information about a file in the local filesystem.
184 *
185 * @param $path String: absolute local filesystem path
186 * @param $ext Mixed: the file extension, or true to extract it from the filename.
187 * Set it to false to ignore the extension.
188 *
189 * @return array
190 */
191 static function getPropsFromPath( $path, $ext = true ) {
192 $fsFile = new self( $path );
193 return $fsFile->getProps( $ext );
194 }
195
196 /**
197 * Get a SHA-1 hash of a file in the local filesystem, in base-36 lower case
198 * encoding, zero padded to 31 digits.
199 *
200 * 160 log 2 / log 36 = 30.95, so the 160-bit hash fills 31 digits in base 36
201 * fairly neatly.
202 *
203 * @param $path string
204 *
205 * @return false|string False on failure
206 */
207 static function getSha1Base36FromPath( $path ) {
208 $fsFile = new self( $path );
209 return $fsFile->getSha1Base36();
210 }
211 }