1
|
|
|
<?php |
|
|
|
|
2
|
|
|
/** |
3
|
|
|
* @title File Class |
4
|
|
|
* @desc Useful methods for handling files. |
5
|
|
|
* |
6
|
|
|
* @author Pierre-Henry Soria <[email protected]> |
7
|
|
|
* @copyright (c) 2012-2017, Pierre-Henry Soria. All Rights Reserved. |
8
|
|
|
* @license GNU General Public License; See PH7.LICENSE.txt and PH7.COPYRIGHT.txt in the root directory. |
9
|
|
|
* @package PH7 / Framework / File |
10
|
|
|
*/ |
11
|
|
|
|
12
|
|
|
namespace PH7\Framework\File; |
13
|
|
|
|
14
|
|
|
defined('PH7') or exit('Restricted access'); |
15
|
|
|
|
16
|
|
|
use PH7\Framework\Server\Server; |
17
|
|
|
use PH7\Framework\Url\Url; |
18
|
|
|
use PH7\Framework\Parse\Url as ParseUrl; |
19
|
|
|
use PH7\Framework\Navigation\Browser; |
20
|
|
|
use PH7\Framework\Registry\Registry; |
21
|
|
|
use PH7\Framework\Error\CException\PH7InvalidArgumentException; |
22
|
|
|
|
23
|
|
|
class File |
24
|
|
|
{ |
25
|
|
|
// End Of Line relative to the operating system |
26
|
|
|
const EOL = PHP_EOL; |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* Mime Types list. |
30
|
|
|
* |
31
|
|
|
* @staticvar array $_aMimeTypes |
32
|
|
|
*/ |
33
|
|
|
private static $_aMimeTypes = [ |
34
|
|
|
'pdf' => 'application/pdf', |
35
|
|
|
'txt' => 'text/plain', |
36
|
|
|
'html' => 'text/html', |
37
|
|
|
'htm' => 'text/html', |
38
|
|
|
'exe' => 'application/octet-stream', |
39
|
|
|
'zip' => 'application/zip', |
40
|
|
|
'doc' => 'application/msword', |
41
|
|
|
'xls' => 'application/vnd.ms-excel', |
42
|
|
|
'ppt' => 'application/vnd.ms-powerpoint', |
43
|
|
|
'gif' => 'image/gif', |
44
|
|
|
'png' => 'image/png', |
45
|
|
|
'jpeg' => 'image/jpg', |
46
|
|
|
'jpg' => 'image/jpg', |
47
|
|
|
'ico' => 'image/x-icon', |
48
|
|
|
'eot' => 'application/vnd.ms-fontobject', |
49
|
|
|
'otf' => 'application/octet-stream', |
50
|
|
|
'ttf' => 'application/octet-stream', |
51
|
|
|
'woff' => 'application/octet-stream', |
52
|
|
|
'svg' => 'application/octet-stream', |
53
|
|
|
'swf' => 'application/x-shockwave-flash', |
54
|
|
|
'mp3' => 'audio/mpeg', |
55
|
|
|
'mp4' => 'video/mp4', |
56
|
|
|
'mov' => 'video/quicktime', |
57
|
|
|
'avi' => 'video/x-msvideo', |
58
|
|
|
'php' => 'text/plain', |
59
|
|
|
]; |
60
|
|
|
|
61
|
|
|
/** |
62
|
|
|
* @param string $sExt Extension File. |
63
|
|
|
* @return string (string | null) Returns the "mime type" if it is found, otherwise "null" |
64
|
|
|
*/ |
65
|
|
|
public function getMimeType($sExt) |
66
|
|
|
{ |
67
|
|
|
return (array_key_exists($sExt, static::$_aMimeTypes)) ? static::$_aMimeTypes[$sExt] : null; |
|
|
|
|
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
/** |
71
|
|
|
* Get Extension file without the dot. |
72
|
|
|
* |
73
|
|
|
* @param string $sFile The File Name. |
74
|
|
|
* @return string |
75
|
|
|
*/ |
76
|
|
|
public function getFileExt($sFile) |
77
|
|
|
{ |
78
|
|
|
return strtolower(substr(strrchr($sFile, PH7_DOT), 1)); |
79
|
|
|
} |
80
|
|
|
|
81
|
|
|
/** |
82
|
|
|
* Get File without Extension and dot. |
83
|
|
|
* This function is smarter than just a code like this, substr($sFile,0,strpos($sFile,'.')) |
84
|
|
|
* Just look at the example below for you to realize that the function removes only the extension and nothing else! |
85
|
|
|
* Example 1 "my_file.pl" The return value is "my_file" |
86
|
|
|
* Example 2 "my_file.inc.pl" The return value is "my_file.inc" |
87
|
|
|
* Example 3 "my_file.class.html.php" The return value is "my_file.class.html" |
88
|
|
|
* |
89
|
|
|
* @see File::getFileExt() To see the method that retrieves the file extension. |
90
|
|
|
* @param string $sFile |
91
|
|
|
* @return string |
92
|
|
|
*/ |
93
|
|
|
public function getFileWithoutExt($sFile) |
94
|
|
|
{ |
95
|
|
|
$sExt = $this->getFileExt($sFile); |
96
|
|
|
return str_replace(PH7_DOT . $sExt, '', $sFile); |
97
|
|
|
} |
98
|
|
|
|
99
|
|
|
/** |
100
|
|
|
* Get File Contents. |
101
|
|
|
* |
102
|
|
|
* @param string $sFile File name. |
103
|
|
|
* @param boolean $bIncPath Default FALSE |
104
|
|
|
* @return mixed (string | boolean) Returns the read data or FALSE on failure. |
105
|
|
|
*/ |
106
|
|
|
public function getFile($sFile, $bIncPath = false) |
107
|
|
|
{ |
108
|
|
|
return @file_get_contents($sFile, $bIncPath); |
109
|
|
|
} |
110
|
|
|
|
111
|
|
|
/** |
112
|
|
|
* Put File Contents. |
113
|
|
|
* |
114
|
|
|
* @param string $sFile File name. |
115
|
|
|
* @param string $sContents Contents file. |
116
|
|
|
* @param integer $iFlag Constant (see http://php.net/manual/function.file-put-contents.php). Default 0 |
117
|
|
|
* @return mixed (integer | boolean) Returns the number of bytes that were written to the file, or FALSE on failure. |
118
|
|
|
*/ |
119
|
|
|
public function putFile($sFile, $sContents, $iFlag = 0) |
120
|
|
|
{ |
121
|
|
|
return @file_put_contents($sFile, $sContents, $iFlag); |
122
|
|
|
} |
123
|
|
|
|
124
|
|
|
/** |
125
|
|
|
* Check if file exists. |
126
|
|
|
* |
127
|
|
|
* @param mixed (array | string) $mFile |
128
|
|
|
* @return boolean TRUE if file exists, FALSE otherwise. |
129
|
|
|
*/ |
130
|
|
|
public function existFile($mFile) |
131
|
|
|
{ |
132
|
|
|
$bExists = false; // Default value |
133
|
|
|
|
134
|
|
|
if (is_array($mFile)) |
135
|
|
|
{ |
136
|
|
|
foreach ($mFile as $sFile) { |
137
|
|
|
if (!$bExists = $this->existFile($sFile)) { |
138
|
|
|
return false; |
139
|
|
|
} |
140
|
|
|
} |
141
|
|
|
} |
142
|
|
|
else |
143
|
|
|
{ |
144
|
|
|
$bExists = is_file($mFile); |
145
|
|
|
} |
146
|
|
|
|
147
|
|
|
return $bExists; |
148
|
|
|
} |
149
|
|
|
|
150
|
|
|
/** |
151
|
|
|
* Check if directory exists. |
152
|
|
|
* |
153
|
|
|
* @param mixed (array | string) $mDir |
154
|
|
|
* @return boolean TRUE if file exists, FALSE otherwise. |
155
|
|
|
*/ |
156
|
|
|
public function existDir($mDir) |
157
|
|
|
{ |
158
|
|
|
$bExists = false; // Default value |
159
|
|
|
|
160
|
|
|
if (is_array($mDir)) |
161
|
|
|
{ |
162
|
|
|
foreach ($mDir as $sDir) { |
163
|
|
|
if (!$bExists = $this->existDir($sDir)) { |
164
|
|
|
return false; |
165
|
|
|
} |
166
|
|
|
} |
167
|
|
|
} |
168
|
|
|
else |
169
|
|
|
{ |
170
|
|
|
$bExists = is_dir($mDir); |
171
|
|
|
} |
172
|
|
|
|
173
|
|
|
return $bExists; |
174
|
|
|
} |
175
|
|
|
|
176
|
|
|
/** |
177
|
|
|
* @param string $sDir The directory. |
178
|
|
|
* @return array The list of the folder that is in the directory. |
179
|
|
|
*/ |
180
|
|
|
public function getDirList($sDir) |
181
|
|
|
{ |
182
|
|
|
$aDirList = array(); |
183
|
|
|
|
184
|
|
|
if ($rHandle = opendir($sDir)) |
185
|
|
|
{ |
186
|
|
|
while (false !== ($sFile = readdir($rHandle))) |
187
|
|
|
{ |
188
|
|
|
if ($sFile != '.' && $sFile != '..' && is_dir($sDir . PH7_DS . $sFile)) |
189
|
|
|
$aDirList[] = $sFile; |
190
|
|
|
} |
191
|
|
|
asort($aDirList); |
192
|
|
|
reset($aDirList); |
193
|
|
|
} |
194
|
|
|
closedir($rHandle); |
195
|
|
|
return $aDirList; |
196
|
|
|
} |
197
|
|
|
|
198
|
|
|
/** |
199
|
|
|
* Get file size. |
200
|
|
|
* |
201
|
|
|
* @param string $sFile |
202
|
|
|
* @return integer The size of the file in bytes. |
203
|
|
|
*/ |
204
|
|
|
public function size($sFile) |
205
|
|
|
{ |
206
|
|
|
return (int) @filesize($sFile); |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
/** |
210
|
|
|
* @param string $sDir |
211
|
|
|
* @param mixed (string | array) $mExt Optional, retrieves only files with specific extensions. Default value is NULL. |
212
|
|
|
* @return array List of files sorted alphabetically. |
213
|
|
|
*/ |
214
|
|
|
public function getFileList($sDir, $mExt = null) |
215
|
|
|
{ |
216
|
|
|
$aTree = array(); |
217
|
|
|
$sDir = $this->checkExtDir($sDir); |
218
|
|
|
|
219
|
|
|
if (is_dir($sDir) && $rHandle = opendir($sDir)) |
220
|
|
|
{ |
221
|
|
|
while (false !== ($sF = readdir($rHandle))) |
222
|
|
|
{ |
223
|
|
|
if ($sF !== '.' && $sF !== '..') |
224
|
|
|
{ |
225
|
|
|
if (is_dir($sDir . $sF)) |
226
|
|
|
{ |
227
|
|
|
$aTree = array_merge($aTree, $this->getFileList($sDir . $sF, $mExt)); |
228
|
|
|
} |
229
|
|
|
else |
230
|
|
|
{ |
231
|
|
|
if (!empty($mExt)) |
232
|
|
|
{ |
233
|
|
|
$aExt = (array) $mExt; |
234
|
|
|
|
235
|
|
|
foreach ($aExt as $sExt) |
236
|
|
|
{ |
237
|
|
|
if (substr($sF, -strlen($sExt)) === $sExt) |
238
|
|
|
$aTree[] = $sDir . $sF; |
239
|
|
|
} |
240
|
|
|
} |
241
|
|
|
else |
242
|
|
|
{ |
243
|
|
|
$aTree[] = $sDir . $sF; |
244
|
|
|
} |
245
|
|
|
} |
246
|
|
|
} |
247
|
|
|
} |
248
|
|
|
sort($aTree); |
249
|
|
|
} |
250
|
|
|
closedir($rHandle); |
|
|
|
|
251
|
|
|
return $aTree; |
252
|
|
|
} |
253
|
|
|
|
254
|
|
|
/** |
255
|
|
|
* Make sure that folder names have a trailing. |
256
|
|
|
* |
257
|
|
|
* @param string $sDir The directory. |
258
|
|
|
* @param bool $bStart for check extension directory start. Default FALSE |
259
|
|
|
* @param bool $bEnd for check extension end. Default TRUE |
260
|
|
|
* @return string $sDir Directory |
261
|
|
|
*/ |
262
|
|
|
public function checkExtDir($sDir, $bStart = false, $bEnd = true) |
263
|
|
|
{ |
264
|
|
|
$bIsWindows = Server::isWindows(); |
265
|
|
|
|
266
|
|
|
if (!$bIsWindows && $bStart === true && substr($sDir, 0, 1) !== PH7_DS) |
267
|
|
|
$sDir = PH7_DS . $sDir; |
268
|
|
|
|
269
|
|
|
if ($bEnd === true && substr($sDir, -1) !== PH7_DS) |
270
|
|
|
$sDir .= PH7_DS; |
271
|
|
|
|
272
|
|
|
return $sDir; |
273
|
|
|
} |
274
|
|
|
|
275
|
|
|
/** |
276
|
|
|
* Creates a directory if they are in an array. If it does not exist and |
277
|
|
|
* allows the creation of nested directories specified in the pathname. |
278
|
|
|
* |
279
|
|
|
* @param mixed (string | array) $mDir |
280
|
|
|
* @param integer (octal) $iMode Default: 0777 |
281
|
|
|
* @return void |
282
|
|
|
* @throws Exception If the file cannot be created. |
283
|
|
|
*/ |
284
|
|
|
public function createDir($mDir, $iMode = 0777) |
285
|
|
|
{ |
286
|
|
|
if (is_array($mDir)) |
287
|
|
|
{ |
288
|
|
|
foreach ($mDir as $sD) $this->createDir($sD); |
289
|
|
|
} |
290
|
|
|
else |
291
|
|
|
{ |
292
|
|
|
if (!is_dir($mDir)) |
293
|
|
|
if (!@mkdir($mDir, $iMode, true)) |
294
|
|
|
throw new Exception('Error to create file: \'' . $mDir . '\'<br /> Please verify that the directory permission is in writing mode.'); |
295
|
|
|
} |
296
|
|
|
} |
297
|
|
|
|
298
|
|
|
/** |
299
|
|
|
* Copy files and checks if the "from file" exists. |
300
|
|
|
* |
301
|
|
|
* @param string $sFrom File. |
302
|
|
|
* @param string $sTo File. |
303
|
|
|
* @return boolean |
304
|
|
|
*/ |
305
|
|
|
public function copy($sFrom, $sTo) |
306
|
|
|
{ |
307
|
|
|
if (!is_file($sFrom)) return false; |
308
|
|
|
|
309
|
|
|
return @copy($sFrom, $sTo); |
310
|
|
|
} |
311
|
|
|
|
312
|
|
|
/** |
313
|
|
|
* Copy the contents of a directory into another. |
314
|
|
|
* |
315
|
|
|
* @param string $sFrom Old directory. |
316
|
|
|
* @param string $sTo New directory. |
317
|
|
|
* @return boolean TRUE if everything went well, otherwise FALSE if the "from directory" couldn't be found or if it couldn't be copied. |
318
|
|
|
*/ |
319
|
|
|
public function copyDir($sFrom, $sTo) |
320
|
|
|
{ |
321
|
|
|
return $this->_recursiveDirIterator($sFrom, $sTo, 'copy'); |
322
|
|
|
} |
323
|
|
|
|
324
|
|
|
/** |
325
|
|
|
* Copy a file or directory with the Unix cp command. |
326
|
|
|
* |
327
|
|
|
* @param string $sFrom File or directory. |
328
|
|
|
* @param string $sTo File or directory. |
329
|
|
|
* @return mixed (integer | boolean) Returns the last line on success, and FALSE on failure. |
330
|
|
|
*/ |
331
|
|
|
public function systemCopy($sFrom, $sTo) |
332
|
|
|
{ |
333
|
|
|
if (file_exists($sFrom)) |
334
|
|
|
return system("cp -r $sFrom $sTo"); |
335
|
|
|
|
336
|
|
|
return false; |
337
|
|
|
} |
338
|
|
|
|
339
|
|
|
/** |
340
|
|
|
* Rename a file or directory and checks if the "from file" or directory exists with file_exists() function |
341
|
|
|
* since it checks the existance of a file or directory (because, as in the Unix OS, a directory is a file). |
342
|
|
|
* |
343
|
|
|
* @param string $sFrom File or directory. |
344
|
|
|
* @param string $sTo File or directory. |
345
|
|
|
* @return boolean |
346
|
|
|
*/ |
347
|
|
|
public function rename($sFrom, $sTo) |
348
|
|
|
{ |
349
|
|
|
if (!file_exists($sFrom)) return false; |
350
|
|
|
|
351
|
|
|
return @rename($sFrom, $sTo); |
352
|
|
|
} |
353
|
|
|
|
354
|
|
|
/** |
355
|
|
|
* Rename the contents of a directory into another. |
356
|
|
|
* |
357
|
|
|
* @param string $sFrom Old directory. |
358
|
|
|
* @param string $sTo New directory. |
359
|
|
|
* @return boolean TRUE if everything went well, otherwise FALSE if the "from directory" couldn't be found or if it couldn't be renamed. |
360
|
|
|
*/ |
361
|
|
|
public function renameDir($sFrom, $sTo) |
362
|
|
|
{ |
363
|
|
|
return $this->_recursiveDirIterator($sFrom, $sTo, 'rename'); |
364
|
|
|
} |
365
|
|
|
|
366
|
|
|
/** |
367
|
|
|
* Rename a file or directory with the Unix mv command. |
368
|
|
|
* |
369
|
|
|
* @param string $sFrom File or directory. |
370
|
|
|
* @param string $sTo File or directory. |
371
|
|
|
* @return mixed (integer | boolean) Returns the last line on success, and FALSE on failure. |
372
|
|
|
*/ |
373
|
|
|
public function systemRename($sFrom, $sTo) |
374
|
|
|
{ |
375
|
|
|
if (file_exists($sFrom)) |
376
|
|
|
return system("mv $sFrom $sTo"); |
377
|
|
|
|
378
|
|
|
return false; |
379
|
|
|
} |
380
|
|
|
|
381
|
|
|
/** |
382
|
|
|
* Deletes a file or files if they are in an array. |
383
|
|
|
* If the file does not exist, the function does nothing. |
384
|
|
|
* |
385
|
|
|
* @param mixed (string | array) $mFile |
386
|
|
|
* @return void |
387
|
|
|
*/ |
388
|
|
|
public function deleteFile($mFile) |
389
|
|
|
{ |
390
|
|
|
if (is_array($mFile)) |
391
|
|
|
foreach ($mFile as $sF) $this->deleteFile($sF); |
392
|
|
|
else |
393
|
|
|
if (is_file($mFile)) @unlink($mFile); |
|
|
|
|
394
|
|
|
} |
395
|
|
|
|
396
|
|
|
/** |
397
|
|
|
* For deleting Directory and files! |
398
|
|
|
* A "rmdir" function improved PHP which also delete files in a directory. |
399
|
|
|
* |
400
|
|
|
* @param string $sPath The path |
401
|
|
|
* @return boolean |
402
|
|
|
*/ |
403
|
|
|
public function deleteDir($sPath) |
404
|
|
|
{ |
405
|
|
|
return (is_file($sPath) ? unlink($sPath) : (is_dir($sPath) ? array_map(array($this, 'deleteDir'), glob($sPath . '/*')) === @rmdir($sPath) : false)); |
406
|
|
|
} |
407
|
|
|
|
408
|
|
|
/** |
409
|
|
|
* Remove the contents of a directory. |
410
|
|
|
* |
411
|
|
|
* @param string $sDir |
412
|
|
|
* @return void |
413
|
|
|
*/ |
414
|
|
|
public function remove($sDir) |
415
|
|
|
{ |
416
|
|
|
$oIterator = new \RecursiveIteratorIterator($this->getDirIterator($sDir), \RecursiveIteratorIterator::CHILD_FIRST); |
417
|
|
|
foreach ($oIterator as $sPath) ($sPath->isFile()) ? unlink($sPath) : @rmdir($sPath); |
418
|
|
|
@rmdir($sDir); |
|
|
|
|
419
|
|
|
} |
420
|
|
|
|
421
|
|
|
/** |
422
|
|
|
* Get the creation/modification time of a file in the Unix timestamp. |
423
|
|
|
* |
424
|
|
|
* @param string Full path of the file. |
425
|
|
|
* @return mixed (integer | boolean) Returns the time the file was last modified, or FALSE if it not found. |
426
|
|
|
*/ |
427
|
|
|
public function getModifTime($sFile) |
428
|
|
|
{ |
429
|
|
|
return (is_file($sFile)) ? filemtime($sFile) : false; |
430
|
|
|
} |
431
|
|
|
|
432
|
|
|
/** |
433
|
|
|
* Get the version of a file based on the its latest modification. |
434
|
|
|
* Shortened form of self::getModifTime() |
435
|
|
|
* |
436
|
|
|
* @param string Full path of the file. |
437
|
|
|
* @return integer Returns the latest modification time of the file in Unix timestamp. |
438
|
|
|
*/ |
439
|
|
|
public static function version($sFile) |
440
|
|
|
{ |
441
|
|
|
return @filemtime($sFile); |
442
|
|
|
} |
443
|
|
|
|
444
|
|
|
/** |
445
|
|
|
* Delay script execution. |
446
|
|
|
* |
447
|
|
|
* @param integer $iSleep Halt time in seconds. Optional parameter, default value is 5. |
448
|
|
|
* @return mixed (integer | boolean) Returns "0" on success, or "false" on error. |
449
|
|
|
*/ |
450
|
|
|
public function sleep($iSleep = null) |
451
|
|
|
{ |
452
|
|
|
$iSleep = (!empty($iSleep)) ? $iSleep : 5; |
453
|
|
|
return sleep($iSleep); |
454
|
|
|
} |
455
|
|
|
|
456
|
|
|
/** |
457
|
|
|
* Changes permission on a file or directory. |
458
|
|
|
* |
459
|
|
|
* @param string $sFile |
460
|
|
|
* @param integer $iMode Octal Permission for the file. |
461
|
|
|
* @return boolean |
462
|
|
|
*/ |
463
|
|
|
public function chmod($sFile, $iMode) |
464
|
|
|
{ |
465
|
|
|
// file_exists function verify the existence of a "file" or "folder"! |
466
|
|
|
if (file_exists($sFile) && $this->getOctalAccess($sFile) !== $iMode) |
|
|
|
|
467
|
|
|
return @chmod($sFile, $iMode); |
468
|
|
|
|
469
|
|
|
return false; |
470
|
|
|
} |
471
|
|
|
|
472
|
|
|
/** |
473
|
|
|
* @param string $sFile |
474
|
|
|
* @return string Octal Permissions. |
475
|
|
|
*/ |
476
|
|
|
public function getOctalAccess($sFile) |
477
|
|
|
{ |
478
|
|
|
clearstatcache(); |
479
|
|
|
return substr(sprintf('%o', fileperms($sFile)), -4); |
480
|
|
|
} |
481
|
|
|
|
482
|
|
|
/** |
483
|
|
|
* @param string $sData |
484
|
|
|
* @return string |
485
|
|
|
*/ |
486
|
|
|
public function pack($sData) |
487
|
|
|
{ |
488
|
|
|
return urlencode(serialize($sData)); |
489
|
|
|
} |
490
|
|
|
|
491
|
|
|
/** |
492
|
|
|
* Get the size of a directory. |
493
|
|
|
* |
494
|
|
|
* @param string $sPath |
495
|
|
|
* @return integer The size of the file in bytes. |
496
|
|
|
*/ |
497
|
|
|
public function getDirSize($sPath) |
498
|
|
|
{ |
499
|
|
|
if (!is_dir($sPath)) return 0; |
500
|
|
|
if (!($rHandle = opendir($sPath))) return 0; |
501
|
|
|
|
502
|
|
|
$iSize = 0; |
503
|
|
|
while (false !== ($sFile = readdir($rHandle))) |
504
|
|
|
{ |
505
|
|
|
if ($sFile != '.' && $sFile != '..') |
506
|
|
|
{ |
507
|
|
|
$sFullPath = $sPath . PH7_DS . $sFile; |
508
|
|
|
|
509
|
|
|
if (is_dir($sFullPath)) |
510
|
|
|
$iSize = $this->getDirSize($sFullPath); |
511
|
|
|
else |
512
|
|
|
$iSize += $this->size($sFullPath); |
513
|
|
|
} |
514
|
|
|
} |
515
|
|
|
closedir($rHandle); |
516
|
|
|
|
517
|
|
|
return $iSize; |
518
|
|
|
} |
519
|
|
|
|
520
|
|
|
/** |
521
|
|
|
* Get free space of a directory. |
522
|
|
|
* |
523
|
|
|
* @param string $sPath |
524
|
|
|
* @return float The number of available bytes as a float. |
525
|
|
|
*/ |
526
|
|
|
public function getDirFreeSpace($sPath) |
527
|
|
|
{ |
528
|
|
|
return disk_free_space($sPath); |
529
|
|
|
} |
530
|
|
|
|
531
|
|
|
/** |
532
|
|
|
* @param string $sData |
533
|
|
|
* @return mixed (boolean, integer, float, string, array or object) |
534
|
|
|
*/ |
535
|
|
|
public function unpack($sData) |
536
|
|
|
{ |
537
|
|
|
return unserialize(urldecode($sData)); |
538
|
|
|
} |
539
|
|
|
|
540
|
|
|
/** |
541
|
|
|
* For download file. |
542
|
|
|
* |
543
|
|
|
* @param string $sFile File to download. |
544
|
|
|
* @param string $sName A name for the file to download. |
545
|
|
|
* @param string $sMimeType Optional, default value is NULL. |
546
|
|
|
* @return void |
547
|
|
|
*/ |
548
|
|
|
public function download($sFile, $sName, $sMimeType = null) |
549
|
|
|
{ |
550
|
|
|
/* |
551
|
|
|
This function takes a path to a file to output ($sFile), |
552
|
|
|
the filename that the browser will see ($sName) and |
553
|
|
|
the MIME type of the file ($sMimeType, optional). |
554
|
|
|
|
555
|
|
|
If you want to do something on download abort/finish, |
556
|
|
|
register_shutdown_function('function_name'); |
557
|
|
|
*/ |
558
|
|
|
|
559
|
|
|
//if (!is_readable($sFile)) exit('File not found or inaccessible!'); |
|
|
|
|
560
|
|
|
|
561
|
|
|
$sName = Url::decode($sName); // Clean the name file |
562
|
|
|
|
563
|
|
|
/* Figure out the MIME type (if not specified) */ |
564
|
|
|
|
565
|
|
|
|
566
|
|
|
if (empty($sMimeType)) |
567
|
|
|
{ |
568
|
|
|
$sFileExtension = $this->getFileExt($sFile); |
569
|
|
|
|
570
|
|
|
$mGetMimeType = $this->getMimeType($sFileExtension); |
571
|
|
|
|
572
|
|
|
if (!empty($mGetMimeType)) |
573
|
|
|
$sMimeType = $mGetMimeType; |
574
|
|
|
else |
575
|
|
|
$sMimeType = 'application/force-download'; |
576
|
|
|
} |
577
|
|
|
|
578
|
|
|
@ob_end_clean(); // Turn off output buffering to decrease CPU usage |
|
|
|
|
579
|
|
|
|
580
|
|
|
(new Browser)->nocache(); // No cache |
581
|
|
|
|
582
|
|
|
$sPrefix = Registry::getInstance()->site_name . '_'; // the prefix |
583
|
|
|
header('Content-Type: ' . $sMimeType); |
584
|
|
|
header('Content-Disposition: attachment; filename=' . ParseUrl::clean($sPrefix) . $sName); |
585
|
|
|
header('Content-Transfer-Encoding: binary'); |
586
|
|
|
header('Accept-Ranges: bytes'); |
587
|
|
|
header('Content-Length: ' . $this->size($sFile)); |
588
|
|
|
readfile($sFile); |
589
|
|
|
} |
590
|
|
|
|
591
|
|
|
/** |
592
|
|
|
* Write Header Contents. |
593
|
|
|
* |
594
|
|
|
* @param string $sHeader Text to be shown in the headers |
595
|
|
|
* @param array $aFile |
596
|
|
|
* @return void |
597
|
|
|
*/ |
598
|
|
|
public function writeHeader($sHeader, $aFile = array()) |
599
|
|
|
{ |
600
|
|
|
for ($i = 0, $iCountFiles = count($aFile); $i < $iCountFiles; $i++) |
601
|
|
|
{ |
602
|
|
|
$rHandle = fopen($aFile[$i], 'wb+'); |
603
|
|
|
$sData = ''; |
604
|
|
|
if ($this->size($aFile[$i]) > 0) |
605
|
|
|
{ |
606
|
|
|
$aData = fread($rHandle, $this->size($aFile[$i])); |
|
|
|
|
607
|
|
|
fwrite($rHandle, $sHeader . static::EOL . $sData); |
608
|
|
|
} |
609
|
|
|
fclose($rHandle); |
610
|
|
|
} |
611
|
|
|
} |
612
|
|
|
|
613
|
|
|
/** |
614
|
|
|
* Writes and saves the contents to a file. |
615
|
|
|
* It also creates a temporary file to not delete the original file if something goes wrong during the recording file. |
616
|
|
|
* |
617
|
|
|
* @param string $sFile |
618
|
|
|
* @param string $sData |
619
|
|
|
* @return integer Returns the number of bytes written, or NULL on error. |
620
|
|
|
*/ |
621
|
|
|
public function save($sFile, $sData) |
622
|
|
|
{ |
623
|
|
|
$sTmpFile = $this->getFileWithoutExt($sFile) . '.tmp.' . $this->getFileExt($sFile); |
624
|
|
|
$iWritten = (new \SplFileObject($sTmpFile, 'wb'))->fwrite($sData); |
625
|
|
|
|
626
|
|
|
if ($iWritten !== null) { |
627
|
|
|
// Copy of the temporary file to the original file if no problem occurred. |
628
|
|
|
copy($sTmpFile, $sFile); |
629
|
|
|
} |
630
|
|
|
|
631
|
|
|
// Deletes the temporary file. |
632
|
|
|
$this->deleteFile($sTmpFile); |
633
|
|
|
|
634
|
|
|
return $iWritten; |
635
|
|
|
} |
636
|
|
|
|
637
|
|
|
/** |
638
|
|
|
* Reading Files. |
639
|
|
|
* |
640
|
|
|
* @param string $sPath |
641
|
|
|
* @param mixed (array | string) $mFiles |
642
|
|
|
* @return mixed (array | string) The Files. |
643
|
|
|
*/ |
644
|
|
|
public function readFiles($sPath = './', &$mFiles) |
645
|
|
|
{ |
646
|
|
|
if (!($rHandle = opendir($sPath))) |
647
|
|
|
return false; |
648
|
|
|
|
649
|
|
|
while (false !== ($sFile = readdir($rHandle))) |
650
|
|
|
{ |
651
|
|
|
if ($sFile != '.' && $sFile != '..') |
652
|
|
|
{ |
653
|
|
|
if (strpos($sFile, '.') === false) |
654
|
|
|
$this->readFiles($sPath . PH7_DS . $sFile, $mFiles); |
655
|
|
|
else |
656
|
|
|
$mFiles[] = $sPath . PH7_DS . $sFile; |
657
|
|
|
} |
658
|
|
|
} |
659
|
|
|
closedir($rHandle); |
660
|
|
|
|
661
|
|
|
return $mFiles; |
662
|
|
|
} |
663
|
|
|
|
664
|
|
|
/** |
665
|
|
|
* Reading Directories. |
666
|
|
|
* |
667
|
|
|
* @param string $sPath |
668
|
|
|
* @return mixed (array | boolean) Returns an ARRAY with the folders or FALSE if the folder could not be opened. |
669
|
|
|
*/ |
670
|
|
|
public function readDirs($sPath = './') |
671
|
|
|
{ |
672
|
|
|
if (!($rHandle = opendir($sPath))) return false; // Return when yield is used will be OK with PHP 7 |
673
|
|
|
$aRet = array();//remove it for yield |
674
|
|
|
|
675
|
|
|
while (false !== ($sFolder = readdir($rHandle))) |
676
|
|
|
{ |
677
|
|
|
if ('.' == $sFolder || '..' == $sFolder || !is_dir($sPath . $sFolder)) |
678
|
|
|
continue; |
679
|
|
|
|
680
|
|
|
//yield $sFolder; // PHP 7 |
681
|
|
|
$aRet[] = $sFolder;//remove it for yield |
682
|
|
|
} |
683
|
|
|
closedir($rHandle); |
684
|
|
|
|
685
|
|
|
return $aRet;//remove it for yield |
686
|
|
|
} |
687
|
|
|
|
688
|
|
|
/** |
689
|
|
|
* Get the URL contents (For URLs, it is better to use CURL because it is faster than file_get_contents function). |
690
|
|
|
* |
691
|
|
|
* @param string $sUrl URL to be read contents. |
692
|
|
|
* @return mixed (string | boolean) Return the result content on success, FALSE on failure. |
693
|
|
|
*/ |
694
|
|
|
public function getUrlContents($sUrl) |
695
|
|
|
{ |
696
|
|
|
$rCh = curl_init(); |
697
|
|
|
curl_setopt($rCh, CURLOPT_URL, $sUrl); |
698
|
|
|
curl_setopt($rCh, CURLOPT_HEADER, 0); |
699
|
|
|
curl_setopt($rCh, CURLOPT_RETURNTRANSFER, 1); |
700
|
|
|
curl_setopt($rCh, CURLOPT_FOLLOWLOCATION, 1); |
701
|
|
|
$mRes = curl_exec($rCh); |
702
|
|
|
curl_close($rCh); |
703
|
|
|
unset($rCh); |
704
|
|
|
|
705
|
|
|
return $mRes; |
706
|
|
|
} |
707
|
|
|
|
708
|
|
|
/** |
709
|
|
|
* Extract Zip archive. |
710
|
|
|
* |
711
|
|
|
* @param string $sFile Zip file. |
712
|
|
|
* @param string $sDir Destination to extract the file. |
713
|
|
|
* @return boolean |
714
|
|
|
*/ |
715
|
|
|
public function zipExtract($sFile, $sDir) |
716
|
|
|
{ |
717
|
|
|
$oZip = new \ZipArchive; |
718
|
|
|
$mRes = $oZip->open($sFile); |
719
|
|
|
|
720
|
|
|
if ($mRes === true) { |
721
|
|
|
$oZip->extractTo($sDir); |
722
|
|
|
$oZip->close(); |
723
|
|
|
return true; |
724
|
|
|
} |
725
|
|
|
|
726
|
|
|
return false; // Return error value |
727
|
|
|
} |
728
|
|
|
|
729
|
|
|
/** |
730
|
|
|
* Check if the file is binary. |
731
|
|
|
* |
732
|
|
|
* @param string $sFile |
733
|
|
|
* @return boolean |
734
|
|
|
*/ |
735
|
|
|
public function isBinary($sFile) |
736
|
|
|
{ |
737
|
|
|
if (file_exists($sFile)) |
738
|
|
|
{ |
739
|
|
|
if (!is_file($sFile)) |
740
|
|
|
return false; |
741
|
|
|
|
742
|
|
|
if (preg_match('/^(.*?)\.(gif|jpg|jpeg|png|ico|mp3|mp4|mov|avi|flv|mpg|mpeg|wmv|ogg|ogv|webm|pdf|ttf|eot|woff|svg|swf)$/i', $sFile)) |
743
|
|
|
return true; |
744
|
|
|
|
745
|
|
|
$rHandle = fopen($sFile, 'r'); |
746
|
|
|
$sContents = fread($rHandle, 512); // Get 512 bytes of the file. |
747
|
|
|
fclose($rHandle); |
748
|
|
|
clearstatcache(); |
749
|
|
|
|
750
|
|
|
if (!function_exists('is_binary')) // PHP 6 |
751
|
|
|
return is_binary($sContents); |
752
|
|
|
|
753
|
|
|
return ( |
754
|
|
|
0 or substr_count($sContents, "^ -~", "^\r\n")/512 > 0.3 |
755
|
|
|
or substr_count($sContents, "\x00") > 0 |
756
|
|
|
); |
757
|
|
|
} |
758
|
|
|
|
759
|
|
|
return false; |
760
|
|
|
} |
761
|
|
|
|
762
|
|
|
/** |
763
|
|
|
* Create a recurive directory iterator for a given directory. |
764
|
|
|
* |
765
|
|
|
* @param string $sPath |
766
|
|
|
* @return string The directory. |
767
|
|
|
*/ |
768
|
|
|
public function getDirIterator($sPath) |
769
|
|
|
{ |
770
|
|
|
return (new \RecursiveDirectoryIterator($sPath)); |
771
|
|
|
} |
772
|
|
|
|
773
|
|
|
/** |
774
|
|
|
* Recursive Directory Iterator. |
775
|
|
|
* |
776
|
|
|
* @param string $sFuncName The function name. Choose between 'copy' and 'rename'. |
777
|
|
|
* @param string $sFrom Directory. |
778
|
|
|
* @param string $sTo Directory. |
779
|
|
|
* |
780
|
|
|
* @return boolean |
781
|
|
|
* |
782
|
|
|
* @throws PH7InvalidArgumentException If the type is bad. |
783
|
|
|
*/ |
784
|
|
|
private function _recursiveDirIterator($sFrom, $sTo, $sFuncName) |
785
|
|
|
{ |
786
|
|
|
if ($sFuncName !== 'copy' && $sFuncName !== 'rename') { |
787
|
|
|
throw new PH7InvalidArgumentException('Bad function name: \'' . $sFuncName . '\''); |
788
|
|
|
} |
789
|
|
|
|
790
|
|
|
if (!is_dir($sFrom)) { |
791
|
|
|
return false; |
792
|
|
|
} |
793
|
|
|
|
794
|
|
|
$bRet = false; // Default value |
795
|
|
|
$oIterator = new \RecursiveIteratorIterator($this->getDirIterator($sFrom), \RecursiveIteratorIterator::SELF_FIRST); |
796
|
|
|
|
797
|
|
|
foreach ($oIterator as $sFromFile) { |
798
|
|
|
$sDest = $sTo . PH7_DS . $oIterator->getSubPathName(); |
799
|
|
|
|
800
|
|
|
if ($sFromFile->isDir()) { |
801
|
|
|
$this->createDir($sDest); |
802
|
|
|
} else { |
803
|
|
|
if (!$bRet = $this->$sFuncName($sFromFile, $sDest)) { |
804
|
|
|
return false; |
805
|
|
|
} |
806
|
|
|
} |
807
|
|
|
} |
808
|
|
|
|
809
|
|
|
return $bRet; |
810
|
|
|
} |
811
|
|
|
} |
812
|
|
|
|
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.