1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* File containing the {@see AppUtils\FileHelper} class. |
4
|
|
|
* |
5
|
|
|
* @package Application Utils |
6
|
|
|
* @subpackage FileHelper |
7
|
|
|
* @see FileHelper |
8
|
|
|
*/ |
9
|
|
|
|
10
|
|
|
declare(strict_types=1); |
11
|
|
|
|
12
|
|
|
namespace AppUtils; |
13
|
|
|
|
14
|
|
|
use AppUtils\FileHelper\AbstractPathInfo; |
15
|
|
|
use AppUtils\FileHelper\CLICommandChecker; |
16
|
|
|
use AppUtils\FileHelper\FileDownloader; |
17
|
|
|
use AppUtils\FileHelper\FileFinder; |
18
|
|
|
use AppUtils\FileHelper\FileInfo\NameFixer; |
19
|
|
|
use AppUtils\FileHelper\PathRelativizer; |
20
|
|
|
use AppUtils\FileHelper\PathsReducer; |
21
|
|
|
use AppUtils\FileHelper\FolderInfo; |
22
|
|
|
use AppUtils\FileHelper\FolderTree; |
23
|
|
|
use AppUtils\FileHelper\FileInfo; |
24
|
|
|
use AppUtils\FileHelper\JSONFile; |
25
|
|
|
use AppUtils\FileHelper\PathInfoInterface; |
26
|
|
|
use AppUtils\FileHelper\PHPFile; |
27
|
|
|
use AppUtils\FileHelper\SerializedFile; |
28
|
|
|
use AppUtils\FileHelper\UnicodeHandling; |
29
|
|
|
use AppUtils\FileHelper\UploadFileSizeInfo; |
30
|
|
|
use DateTime; |
31
|
|
|
use JsonException; |
32
|
|
|
use SplFileInfo; |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* Collection of file system related methods. |
36
|
|
|
* |
37
|
|
|
* @package Application Utils |
38
|
|
|
* @subpackage FileHelper |
39
|
|
|
* @author Sebastian Mordziol <[email protected]> |
40
|
|
|
*/ |
41
|
|
|
class FileHelper |
42
|
|
|
{ |
43
|
|
|
public const ERROR_CANNOT_FIND_JSON_FILE = 340001; |
44
|
|
|
public const ERROR_CANNOT_DECODE_JSON_FILE = 340003; |
45
|
|
|
public const ERROR_JSON_ENCODE_ERROR = 340005; |
46
|
|
|
public const ERROR_CANNOT_OPEN_URL = 340008; |
47
|
|
|
public const ERROR_CANNOT_CREATE_FOLDER = 340009; |
48
|
|
|
public const ERROR_FILE_NOT_READABLE = 340010; |
49
|
|
|
public const ERROR_CANNOT_COPY_FILE = 340011; |
50
|
|
|
public const ERROR_CANNOT_DELETE_FILE = 340012; |
51
|
|
|
public const ERROR_FIND_SUBFOLDERS_FOLDER_DOES_NOT_EXIST = 340014; |
52
|
|
|
public const ERROR_UNKNOWN_FILE_MIME_TYPE = 340015; |
53
|
|
|
public const ERROR_SERIALIZED_FILE_CANNOT_BE_READ = 340017; |
54
|
|
|
public const ERROR_SERIALIZED_FILE_UNSERIALZE_FAILED = 340018; |
55
|
|
|
public const ERROR_UNSUPPORTED_OS_CLI_COMMAND = 340019; |
56
|
|
|
public const ERROR_SOURCE_FILE_NOT_FOUND = 340020; |
57
|
|
|
public const ERROR_SOURCE_FILE_NOT_READABLE = 340021; |
58
|
|
|
public const ERROR_TARGET_COPY_FOLDER_NOT_WRITABLE = 340022; |
59
|
|
|
public const ERROR_SAVE_FOLDER_NOT_WRITABLE = 340023; |
60
|
|
|
public const ERROR_SAVE_FILE_NOT_WRITABLE = 340024; |
61
|
|
|
public const ERROR_SAVE_FILE_WRITE_FAILED = 340025; |
62
|
|
|
public const ERROR_FILE_DOES_NOT_EXIST = 340026; |
63
|
|
|
public const ERROR_CANNOT_OPEN_FILE_TO_READ_LINES = 340027; |
64
|
|
|
public const ERROR_CANNOT_READ_FILE_CONTENTS = 340028; |
65
|
|
|
public const ERROR_CURL_OUTPUT_NOT_STRING = 340031; |
66
|
|
|
public const ERROR_CANNOT_OPEN_FILE_TO_DETECT_BOM = 340032; |
67
|
|
|
public const ERROR_FOLDER_DOES_NOT_EXIST = 340033; |
68
|
|
|
public const ERROR_PATH_IS_NOT_A_FOLDER = 340034; |
69
|
|
|
public const ERROR_CANNOT_DELETE_FOLDER = 340036; |
70
|
|
|
public const ERROR_REAL_PATH_NOT_FOUND = 340037; |
71
|
|
|
public const ERROR_PATH_IS_NOT_A_FILE = 340038; |
72
|
|
|
public const ERROR_PATH_NOT_WRITABLE = 340039; |
73
|
|
|
public const ERROR_PATH_INVALID = 340040; |
74
|
|
|
public const ERROR_CANNOT_COPY_FILE_TO_FOLDER = 340041; |
75
|
|
|
|
76
|
|
|
/** |
77
|
|
|
* Opens a serialized file and returns the unserialized data. |
78
|
|
|
* |
79
|
|
|
* @param string|PathInfoInterface|SplFileInfo $file |
80
|
|
|
* @throws FileHelper_Exception |
81
|
|
|
* @return array<int|string,mixed> |
82
|
|
|
* @see SerializedFile::parse() |
83
|
|
|
* |
84
|
|
|
* @see FileHelper::ERROR_FILE_DOES_NOT_EXIST |
85
|
|
|
* @see FileHelper::ERROR_SERIALIZED_FILE_CANNOT_BE_READ |
86
|
|
|
* @see FileHelper::ERROR_SERIALIZED_FILE_UNSERIALZE_FAILED |
87
|
|
|
*/ |
88
|
|
|
public static function parseSerializedFile($file) : array |
89
|
|
|
{ |
90
|
|
|
return SerializedFile::factory($file)->parse(); |
91
|
|
|
} |
92
|
|
|
|
93
|
|
|
/** |
94
|
|
|
* Deletes a folder tree with all files therein, including |
95
|
|
|
* the specified folder itself. |
96
|
|
|
* |
97
|
|
|
* @param string|PathInfoInterface|SplFileInfo $rootFolder |
98
|
|
|
* @return bool |
99
|
|
|
* @throws FileHelper_Exception |
100
|
|
|
*/ |
101
|
|
|
public static function deleteTree($rootFolder) : bool |
102
|
|
|
{ |
103
|
|
|
return FolderTree::delete($rootFolder); |
104
|
|
|
} |
105
|
|
|
|
106
|
|
|
/** |
107
|
|
|
* Create a folder, if it does not exist yet. |
108
|
|
|
* |
109
|
|
|
* @param string|PathInfoInterface $path |
110
|
|
|
* @throws FileHelper_Exception |
111
|
|
|
* @see FileHelper::ERROR_CANNOT_CREATE_FOLDER |
112
|
|
|
*/ |
113
|
|
|
public static function createFolder($path) : FolderInfo |
114
|
|
|
{ |
115
|
|
|
return self::getFolderInfo($path)->create(); |
116
|
|
|
} |
117
|
|
|
|
118
|
|
|
/** |
119
|
|
|
* @param string|PathInfoInterface|SplFileInfo $path |
120
|
|
|
* @return FolderInfo |
121
|
|
|
* @throws FileHelper_Exception |
122
|
|
|
*/ |
123
|
|
|
public static function getFolderInfo($path) : FolderInfo |
124
|
|
|
{ |
125
|
|
|
return FolderInfo::factory($path); |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
/** |
129
|
|
|
* Copies a folder tree to the target folder. |
130
|
|
|
* |
131
|
|
|
* @param string|PathInfoInterface|SplFileInfo $source |
132
|
|
|
* @param string|PathInfoInterface|SplFileInfo $target |
133
|
|
|
* @throws FileHelper_Exception |
134
|
|
|
* @see FolderTree |
135
|
|
|
*/ |
136
|
|
|
public static function copyTree($source, $target) : void |
137
|
|
|
{ |
138
|
|
|
FolderTree::copy($source, $target); |
139
|
|
|
} |
140
|
|
|
|
141
|
|
|
/** |
142
|
|
|
* Copies a file to the target location. Includes checks |
143
|
|
|
* for most error sources, like the source file not being |
144
|
|
|
* readable. Automatically creates the target folder if it |
145
|
|
|
* does not exist yet. |
146
|
|
|
* |
147
|
|
|
* @param string|PathInfoInterface|SplFileInfo $sourcePath |
148
|
|
|
* @param string|PathInfoInterface|SplFileInfo $targetPath |
149
|
|
|
* @throws FileHelper_Exception |
150
|
|
|
* |
151
|
|
|
* @see FileHelper::ERROR_CANNOT_CREATE_FOLDER |
152
|
|
|
* @see FileHelper::ERROR_SOURCE_FILE_NOT_FOUND |
153
|
|
|
* @see FileHelper::ERROR_SOURCE_FILE_NOT_READABLE |
154
|
|
|
* @see FileHelper::ERROR_TARGET_COPY_FOLDER_NOT_WRITABLE |
155
|
|
|
* @see FileHelper::ERROR_CANNOT_COPY_FILE |
156
|
|
|
*/ |
157
|
|
|
public static function copyFile($sourcePath, $targetPath) : void |
158
|
|
|
{ |
159
|
|
|
self::getFileInfo($sourcePath)->copyTo($targetPath); |
160
|
|
|
} |
161
|
|
|
|
162
|
|
|
/** |
163
|
|
|
* Deletes the target file. Ignored if it cannot be found, |
164
|
|
|
* and throws an exception if it fails. |
165
|
|
|
* |
166
|
|
|
* @param string|PathInfoInterface|SplFileInfo $filePath |
167
|
|
|
* @throws FileHelper_Exception |
168
|
|
|
* |
169
|
|
|
* @see FileHelper::ERROR_CANNOT_DELETE_FILE |
170
|
|
|
*/ |
171
|
|
|
public static function deleteFile($filePath) : void |
172
|
|
|
{ |
173
|
|
|
self::getFileInfo($filePath)->delete(); |
174
|
|
|
} |
175
|
|
|
|
176
|
|
|
/** |
177
|
|
|
* Retrieves an instance of the file info class, which |
178
|
|
|
* allows file operations and accessing information on |
179
|
|
|
* the file. |
180
|
|
|
* |
181
|
|
|
* @param string|PathInfoInterface|SplFileInfo $path |
182
|
|
|
* @return FileInfo |
183
|
|
|
* @throws FileHelper_Exception |
184
|
|
|
*/ |
185
|
|
|
public static function getFileInfo($path) : FileInfo |
186
|
|
|
{ |
187
|
|
|
return FileInfo::factory($path); |
188
|
|
|
} |
189
|
|
|
|
190
|
|
|
/** |
191
|
|
|
* @param string|PathInfoInterface|SplFileInfo $path |
192
|
|
|
* @return PathInfoInterface |
193
|
|
|
* @throws FileHelper_Exception |
194
|
|
|
*/ |
195
|
|
|
public static function getPathInfo($path) : PathInfoInterface |
196
|
|
|
{ |
197
|
|
|
return AbstractPathInfo::resolveType($path); |
198
|
|
|
} |
199
|
|
|
|
200
|
|
|
/** |
201
|
|
|
* Detects the mime type for the specified file name/path. |
202
|
|
|
* Returns null if it is not a known file extension. |
203
|
|
|
* |
204
|
|
|
* @param string|PathInfoInterface|SplFileInfo $fileName |
205
|
|
|
* @return string|NULL |
206
|
|
|
* @throws FileHelper_Exception |
207
|
|
|
*/ |
208
|
|
|
public static function detectMimeType($fileName) : ?string |
209
|
|
|
{ |
210
|
|
|
$ext = self::getExtension($fileName); |
211
|
|
|
if(empty($ext)) { |
212
|
|
|
return null; |
213
|
|
|
} |
214
|
|
|
|
215
|
|
|
return FileHelper_MimeTypes::getMime($ext); |
216
|
|
|
} |
217
|
|
|
|
218
|
|
|
/** |
219
|
|
|
* Like `sendFile()`, but automatically determines whether |
220
|
|
|
* the browser can open the target file type, to either |
221
|
|
|
* send it directly to the browser, or force downloading |
222
|
|
|
* it instead. |
223
|
|
|
* |
224
|
|
|
* @param string|PathInfoInterface|SplFileInfo $filePath |
225
|
|
|
* @param string $fileName |
226
|
|
|
* @throws FileHelper_Exception |
227
|
|
|
*/ |
228
|
|
|
public static function sendFileAuto($filePath, string $fileName = '') : void |
229
|
|
|
{ |
230
|
|
|
$file = FileInfo::factory($filePath) |
231
|
|
|
->requireExists() |
232
|
|
|
->requireReadable(); |
233
|
|
|
|
234
|
|
|
self::sendFile( |
235
|
|
|
$file, |
236
|
|
|
$fileName, |
237
|
|
|
!FileHelper_MimeTypes::canBrowserDisplay($file->getExtension()) |
238
|
|
|
); |
239
|
|
|
} |
240
|
|
|
|
241
|
|
|
/** |
242
|
|
|
* Detects the mime type of the target file automatically, |
243
|
|
|
* sends the required headers to trigger a download and |
244
|
|
|
* outputs the file. Returns false if the mime type could |
245
|
|
|
* not be determined. |
246
|
|
|
* |
247
|
|
|
* @param string|PathInfoInterface|SplFileInfo $filePath |
248
|
|
|
* @param string|null $fileName The name of the file for the client. |
249
|
|
|
* @param bool $asAttachment Whether to force the client to download the file. |
250
|
|
|
* @throws FileHelper_Exception |
251
|
|
|
* |
252
|
|
|
* @see FileHelper::ERROR_FILE_DOES_NOT_EXIST |
253
|
|
|
* @see FileHelper::ERROR_UNKNOWN_FILE_MIME_TYPE |
254
|
|
|
*/ |
255
|
|
|
public static function sendFile($filePath, ?string $fileName = null, bool $asAttachment=true) : void |
256
|
|
|
{ |
257
|
|
|
self::getFileInfo($filePath)->getDownloader()->send($fileName, $asAttachment); |
258
|
|
|
} |
259
|
|
|
|
260
|
|
|
/** |
261
|
|
|
* Uses cURL to download the contents of the specified URL, |
262
|
|
|
* returns the content. |
263
|
|
|
* |
264
|
|
|
* @param string $url |
265
|
|
|
* @param int $timeout In seconds. Set to 0 to use the default. |
266
|
|
|
* @param bool $SSLEnabled Whether to enable HTTPs host verification. |
267
|
|
|
* @return string |
268
|
|
|
* |
269
|
|
|
* @throws FileHelper_Exception |
270
|
|
|
* @see FileHelper::ERROR_CANNOT_OPEN_URL |
271
|
|
|
*/ |
272
|
|
|
public static function downloadFile(string $url, int $timeout=0, bool $SSLEnabled=false) : string |
273
|
|
|
{ |
274
|
|
|
return FileDownloader::factory($url) |
275
|
|
|
->setTimeout($timeout) |
276
|
|
|
->setSSLEnabled($SSLEnabled) |
277
|
|
|
->download(); |
278
|
|
|
} |
279
|
|
|
|
280
|
|
|
/** |
281
|
|
|
* Verifies whether the target file is a PHP file. The path |
282
|
|
|
* to the file can be a path to a file as a string, or a |
283
|
|
|
* {@see SplFileInfo} object instance. |
284
|
|
|
* |
285
|
|
|
* @param string|PathInfoInterface|SplFileInfo $filePath |
286
|
|
|
* @return boolean |
287
|
|
|
* @throws FileHelper_Exception |
288
|
|
|
*/ |
289
|
|
|
public static function isPHPFile($filePath) : bool |
290
|
|
|
{ |
291
|
|
|
return self::getExtension($filePath) === 'php'; |
292
|
|
|
} |
293
|
|
|
|
294
|
|
|
/** |
295
|
|
|
* Retrieves the extension of the specified file. Can be a path |
296
|
|
|
* to a file as a string, or a {@see SplFileInfo} object instance. |
297
|
|
|
* |
298
|
|
|
* NOTE: A folder will return an empty string. |
299
|
|
|
* |
300
|
|
|
* @param string|PathInfoInterface|SplFileInfo $fileName |
301
|
|
|
* @param bool $lowercase |
302
|
|
|
* @return string |
303
|
|
|
* @throws FileHelper_Exception |
304
|
|
|
*/ |
305
|
|
|
public static function getExtension($fileName, bool $lowercase = true) : string |
306
|
|
|
{ |
307
|
|
|
return self::getPathInfo($fileName)->getExtension($lowercase); |
308
|
|
|
} |
309
|
|
|
|
310
|
|
|
/** |
311
|
|
|
* Retrieves the file name from a path, with or without extension. |
312
|
|
|
* The path to the file can be a string, or a {@see SplFileInfo} |
313
|
|
|
* object instance. |
314
|
|
|
* |
315
|
|
|
* In case of folders, behaves like the "pathinfo" function: returns |
316
|
|
|
* the name of the folder. |
317
|
|
|
* |
318
|
|
|
* @param string|PathInfoInterface|SplFileInfo $pathOrDirIterator |
319
|
|
|
* @param bool $extension |
320
|
|
|
* @return string |
321
|
|
|
* @throws FileHelper_Exception |
322
|
|
|
*/ |
323
|
|
|
public static function getFilename($pathOrDirIterator, bool $extension = true) : string |
324
|
|
|
{ |
325
|
|
|
$info = self::getPathInfo($pathOrDirIterator); |
326
|
|
|
|
327
|
|
|
if($extension === true || $info instanceof FolderInfo) |
328
|
|
|
{ |
329
|
|
|
return $info->getName(); |
330
|
|
|
} |
331
|
|
|
|
332
|
|
|
return $info->requireIsFile()->removeExtension(); |
333
|
|
|
} |
334
|
|
|
|
335
|
|
|
/** |
336
|
|
|
* Tries to read the contents of the target file and |
337
|
|
|
* treat it as JSON to return the decoded JSON data. |
338
|
|
|
* |
339
|
|
|
* @param string|PathInfoInterface|SplFileInfo $file |
340
|
|
|
* @param string $targetEncoding |
341
|
|
|
* @param string|string[]|null $sourceEncoding |
342
|
|
|
* @return array<int|string,mixed> |
343
|
|
|
* |
344
|
|
|
* @throws FileHelper_Exception |
345
|
|
|
* @throws JsonException |
346
|
|
|
* @see FileHelper::ERROR_CANNOT_FIND_JSON_FILE |
347
|
|
|
* @see FileHelper::ERROR_CANNOT_DECODE_JSON_FILE |
348
|
|
|
*/ |
349
|
|
|
public static function parseJSONFile($file, string $targetEncoding='', $sourceEncoding=null) : array |
350
|
|
|
{ |
351
|
|
|
return JSONFile::factory($file) |
352
|
|
|
->setTargetEncoding($targetEncoding) |
353
|
|
|
->setSourceEncodings($sourceEncoding) |
354
|
|
|
->parse(); |
355
|
|
|
} |
356
|
|
|
|
357
|
|
|
/** |
358
|
|
|
* Corrects common formatting mistakes when users enter |
359
|
|
|
* file names, like too many spaces, dots and the like. |
360
|
|
|
* |
361
|
|
|
* NOTE: if the file name contains a path, the path is |
362
|
|
|
* stripped, leaving only the file name. |
363
|
|
|
* |
364
|
|
|
* @param string $name |
365
|
|
|
* @return string |
366
|
|
|
*/ |
367
|
|
|
public static function fixFileName(string $name) : string |
368
|
|
|
{ |
369
|
|
|
return NameFixer::fixName($name); |
370
|
|
|
} |
371
|
|
|
|
372
|
|
|
/** |
373
|
|
|
* Creates an instance of the file finder, which is an easier |
374
|
|
|
* alternative to the other manual findFile methods, since all |
375
|
|
|
* options can be set by chaining. |
376
|
|
|
* |
377
|
|
|
* @param string|AbstractPathInfo|SplFileInfo $path |
378
|
|
|
* @return FileFinder |
379
|
|
|
* @throws FileHelper_Exception |
380
|
|
|
* |
381
|
|
|
* @see FileFinder::ERROR_PATH_DOES_NOT_EXIST |
382
|
|
|
*/ |
383
|
|
|
public static function createFileFinder($path) : FileFinder |
384
|
|
|
{ |
385
|
|
|
return new FileFinder($path); |
386
|
|
|
} |
387
|
|
|
|
388
|
|
|
/** |
389
|
|
|
* Searches for all HTML files in the target folder. |
390
|
|
|
* |
391
|
|
|
* NOTE: This method only exists for backwards compatibility. |
392
|
|
|
* Use the {@see FileHelper::createFileFinder()} method instead, |
393
|
|
|
* which offers an object-oriented interface that is much easier |
394
|
|
|
* to use. |
395
|
|
|
* |
396
|
|
|
* @param string|PathInfoInterface|SplFileInfo $targetFolder |
397
|
|
|
* @param array<string,mixed> $options |
398
|
|
|
* @return string[] An indexed array with files. |
399
|
|
|
* @throws FileHelper_Exception |
400
|
|
|
* @see FileHelper::createFileFinder() |
401
|
|
|
*/ |
402
|
|
|
public static function findHTMLFiles($targetFolder, array $options=array()) : array |
403
|
|
|
{ |
404
|
|
|
return self::findFiles($targetFolder, array('html'), $options); |
|
|
|
|
405
|
|
|
} |
406
|
|
|
|
407
|
|
|
/** |
408
|
|
|
* Searches for all PHP files in the target folder. |
409
|
|
|
* |
410
|
|
|
* NOTE: This method only exists for backwards compatibility. |
411
|
|
|
* Use the {@see FileHelper::createFileFinder()} method instead, |
412
|
|
|
* which offers an object-oriented interface that is much easier |
413
|
|
|
* to use. |
414
|
|
|
* |
415
|
|
|
* @param string|PathInfoInterface|SplFileInfo $targetFolder |
416
|
|
|
* @param array<string,mixed> $options |
417
|
|
|
* @return string[] An indexed array of PHP files. |
418
|
|
|
* @throws FileHelper_Exception |
419
|
|
|
* @see FileHelper::createFileFinder() |
420
|
|
|
*/ |
421
|
|
|
public static function findPHPFiles($targetFolder, array $options=array()) : array |
422
|
|
|
{ |
423
|
|
|
return self::findFiles($targetFolder, array('php'), $options); |
|
|
|
|
424
|
|
|
} |
425
|
|
|
|
426
|
|
|
/** |
427
|
|
|
* Finds files according to the specified options. |
428
|
|
|
* |
429
|
|
|
* NOTE: This method only exists for backwards compatibility. |
430
|
|
|
* Use the {@see FileHelper::createFileFinder()} method instead, |
431
|
|
|
* which offers an object-oriented interface that is much easier |
432
|
|
|
* to use. |
433
|
|
|
* |
434
|
|
|
* @param string|PathInfoInterface|SplFileInfo $targetFolder |
435
|
|
|
* @param string[] $extensions |
436
|
|
|
* @param array<string,mixed> $options |
437
|
|
|
* @throws FileHelper_Exception |
438
|
|
|
* @return string[] |
439
|
|
|
* |
440
|
|
|
* @see FileHelper::createFileFinder() |
441
|
|
|
* @deprecated Use the file finder instead. |
442
|
|
|
*/ |
443
|
|
|
public static function findFiles($targetFolder, array $extensions=array(), array $options=array()) : array |
444
|
|
|
{ |
445
|
|
|
$finder = self::createFileFinder($targetFolder); |
446
|
|
|
|
447
|
|
|
foreach ($extensions as $extension) { |
448
|
|
|
$finder->includeExtension($extension); |
449
|
|
|
} |
450
|
|
|
|
451
|
|
|
$finder->setPathmodeStrip(); |
452
|
|
|
|
453
|
|
|
if(isset($options['relative-path']) && $options['relative-path'] === true) |
454
|
|
|
{ |
455
|
|
|
$finder->setPathmodeRelative(); |
456
|
|
|
} |
457
|
|
|
else if(isset($options['absolute-path']) && $options['absolute-path'] === true) |
458
|
|
|
{ |
459
|
|
|
$finder->setPathmodeAbsolute(); |
460
|
|
|
} |
461
|
|
|
|
462
|
|
|
if(isset($options['strip-extension'])) |
463
|
|
|
{ |
464
|
|
|
$finder->stripExtensions(); |
465
|
|
|
} |
466
|
|
|
|
467
|
|
|
$finder->setOptions($options); |
468
|
|
|
|
469
|
|
|
return $finder->getAll(); |
470
|
|
|
} |
471
|
|
|
|
472
|
|
|
/** |
473
|
|
|
* Removes the extension from the specified path or file name, |
474
|
|
|
* if any, and returns the name without the extension. |
475
|
|
|
* |
476
|
|
|
* @param string|PathInfoInterface|SplFileInfo $filename |
477
|
|
|
* @param bool $keepPath Whether to keep the path component, if any. Default PHP pathinfo behavior is no. |
478
|
|
|
* @return string |
479
|
|
|
* @throws FileHelper_Exception |
480
|
|
|
*/ |
481
|
|
|
public static function removeExtension($filename, bool $keepPath=false) : string |
482
|
|
|
{ |
483
|
|
|
$path = self::getPathInfo($filename); |
484
|
|
|
|
485
|
|
|
if($path instanceof FileInfo) |
486
|
|
|
{ |
487
|
|
|
return $path->removeExtension($keepPath); |
488
|
|
|
} |
489
|
|
|
|
490
|
|
|
if($keepPath) |
491
|
|
|
{ |
492
|
|
|
return $filename; |
493
|
|
|
} |
494
|
|
|
|
495
|
|
|
return basename($filename); |
496
|
|
|
} |
497
|
|
|
|
498
|
|
|
/** |
499
|
|
|
* @var UnicodeHandling|NULL |
500
|
|
|
*/ |
501
|
|
|
private static ?UnicodeHandling $unicodeHandling = null; |
502
|
|
|
|
503
|
|
|
public static function createUnicodeHandling() : UnicodeHandling |
504
|
|
|
{ |
505
|
|
|
if(!isset(self::$unicodeHandling)) |
506
|
|
|
{ |
507
|
|
|
self::$unicodeHandling = new UnicodeHandling(); |
508
|
|
|
} |
509
|
|
|
|
510
|
|
|
return self::$unicodeHandling; |
|
|
|
|
511
|
|
|
} |
512
|
|
|
|
513
|
|
|
/** |
514
|
|
|
* Normalizes the slash style in a file or folder path, |
515
|
|
|
* by replacing any anti-slashes with forward slashes. |
516
|
|
|
* |
517
|
|
|
* @param string $path |
518
|
|
|
* @return string |
519
|
|
|
*/ |
520
|
|
|
public static function normalizePath(string $path) : string |
521
|
|
|
{ |
522
|
|
|
return str_replace(array('\\', '//'), array('/', '/'), $path); |
523
|
|
|
} |
524
|
|
|
|
525
|
|
|
/** |
526
|
|
|
* Saves the specified data to a file, JSON encoded. |
527
|
|
|
* |
528
|
|
|
* @param mixed $data |
529
|
|
|
* @param string|PathInfoInterface|SplFileInfo $file |
530
|
|
|
* @param bool $pretty |
531
|
|
|
* @return JSONFile |
532
|
|
|
* |
533
|
|
|
* @throws FileHelper_Exception |
534
|
|
|
* @see FileHelper::ERROR_JSON_ENCODE_ERROR |
535
|
|
|
* @see FileHelper::ERROR_SAVE_FOLDER_NOT_WRITABLE |
536
|
|
|
* @see FileHelper::ERROR_SAVE_FILE_NOT_WRITABLE |
537
|
|
|
* @see FileHelper::ERROR_SAVE_FILE_WRITE_FAILED |
538
|
|
|
*/ |
539
|
|
|
public static function saveAsJSON($data, $file, bool $pretty=false) : JSONFile |
540
|
|
|
{ |
541
|
|
|
return JSONFile::factory($file)->putData($data, $pretty); |
542
|
|
|
} |
543
|
|
|
|
544
|
|
|
/** |
545
|
|
|
* Saves the specified content to the target file, creating |
546
|
|
|
* the file and the folder as necessary. |
547
|
|
|
* |
548
|
|
|
* @param string|PathInfoInterface|SplFileInfo $filePath |
549
|
|
|
* @param string $content |
550
|
|
|
* @return FileInfo |
551
|
|
|
* |
552
|
|
|
* @throws FileHelper_Exception |
553
|
|
|
* @see FileHelper::ERROR_SAVE_FOLDER_NOT_WRITABLE |
554
|
|
|
* @see FileHelper::ERROR_SAVE_FILE_NOT_WRITABLE |
555
|
|
|
* @see FileHelper::ERROR_SAVE_FILE_WRITE_FAILED |
556
|
|
|
*/ |
557
|
|
|
public static function saveFile($filePath, string $content='') : FileInfo |
558
|
|
|
{ |
559
|
|
|
return self::getFileInfo($filePath)->putContents($content); |
560
|
|
|
} |
561
|
|
|
|
562
|
|
|
/** |
563
|
|
|
* Checks whether it is possible to run PHP command |
564
|
|
|
* line commands. |
565
|
|
|
* |
566
|
|
|
* @return boolean |
567
|
|
|
* @throws FileHelper_Exception |
568
|
|
|
*/ |
569
|
|
|
public static function canMakePHPCalls() : bool |
570
|
|
|
{ |
571
|
|
|
return self::cliCommandExists('php'); |
572
|
|
|
} |
573
|
|
|
|
574
|
|
|
/** |
575
|
|
|
* Determines if a command exists on the current environment's command line interface. |
576
|
|
|
* |
577
|
|
|
* @param string $command The name of the command to check, e.g. "php" |
578
|
|
|
* @return bool True if the command has been found, false otherwise. |
579
|
|
|
* @throws FileHelper_Exception |
580
|
|
|
* @see FileHelper::ERROR_UNSUPPORTED_OS_CLI_COMMAND |
581
|
|
|
*/ |
582
|
|
|
public static function cliCommandExists(string $command) : bool |
583
|
|
|
{ |
584
|
|
|
return CLICommandChecker::factory()->exists($command); |
585
|
|
|
} |
586
|
|
|
|
587
|
|
|
/** |
588
|
|
|
* Validates a PHP file's syntax. |
589
|
|
|
* |
590
|
|
|
* NOTE: This will fail silently if the PHP command line |
591
|
|
|
* is not available. Use {@link FileHelper::canMakePHPCalls()} |
592
|
|
|
* to check this beforehand as needed. |
593
|
|
|
* |
594
|
|
|
* @param string|PathInfoInterface|SplFileInfo $path |
595
|
|
|
* @return boolean|string[] A boolean true if the file is valid, an array with validation messages otherwise. |
596
|
|
|
* @throws FileHelper_Exception |
597
|
|
|
* @deprecated Use {@see PHPFile::checkSyntax()} instead. |
598
|
|
|
*/ |
599
|
|
|
public static function checkPHPFileSyntax($path) |
600
|
|
|
{ |
601
|
|
|
return PHPFile::factory($path)->checkSyntax(); |
602
|
|
|
} |
603
|
|
|
|
604
|
|
|
/** |
605
|
|
|
* Retrieves the last modified date for the specified file or folder. |
606
|
|
|
* |
607
|
|
|
* Note: If the target does not exist, returns null. |
608
|
|
|
* |
609
|
|
|
* @param string|PathInfoInterface|SplFileInfo $path |
610
|
|
|
* @return DateTime|NULL |
611
|
|
|
* @throws FileHelper_Exception |
612
|
|
|
*/ |
613
|
|
|
public static function getModifiedDate($path) : ?DateTime |
614
|
|
|
{ |
615
|
|
|
return self::getFileInfo($path)->getModifiedDate(); |
616
|
|
|
} |
617
|
|
|
|
618
|
|
|
/** |
619
|
|
|
* Retrieves the names of all sub-folders in the specified path. |
620
|
|
|
* |
621
|
|
|
* Available options: |
622
|
|
|
* |
623
|
|
|
* - recursive: true/false |
624
|
|
|
* Whether to search for sub-folders recursively. |
625
|
|
|
* |
626
|
|
|
* - absolute-paths: true/false |
627
|
|
|
* Whether to return a list of absolute paths. |
628
|
|
|
* |
629
|
|
|
* @param string|PathInfoInterface|SplFileInfo $targetFolder |
630
|
|
|
* @param array<string,mixed> $options |
631
|
|
|
* @return string[] |
632
|
|
|
* |
633
|
|
|
* @throws FileHelper_Exception |
634
|
|
|
* @see FileHelper::ERROR_FIND_SUBFOLDERS_FOLDER_DOES_NOT_EXIST |
635
|
|
|
*/ |
636
|
|
|
public static function getSubfolders($targetFolder, array $options = array()) : array |
637
|
|
|
{ |
638
|
|
|
return FolderInfo::factory($targetFolder) |
639
|
|
|
->createFolderFinder() |
640
|
|
|
->setOptions($options) |
641
|
|
|
->getPaths(); |
642
|
|
|
} |
643
|
|
|
|
644
|
|
|
/** |
645
|
|
|
* Retrieves the maximum allowed upload file size, in bytes. |
646
|
|
|
* Takes into account the PHP ini settings <code>post_max_size</code> |
647
|
|
|
* and <code>upload_max_filesize</code>. Since these cannot |
648
|
|
|
* be modified at runtime, they are the hard limits for uploads. |
649
|
|
|
* |
650
|
|
|
* NOTE: Based on binary values, where 1KB = 1024 Bytes. |
651
|
|
|
* |
652
|
|
|
* @return int Will return <code>-1</code> if no limit. |
653
|
|
|
*/ |
654
|
|
|
public static function getMaxUploadFilesize() : int |
655
|
|
|
{ |
656
|
|
|
return UploadFileSizeInfo::getFileSize(); |
657
|
|
|
} |
658
|
|
|
|
659
|
|
|
/** |
660
|
|
|
* Makes a path relative using a folder depth: will reduce the |
661
|
|
|
* length of the path so that only the amount of folders defined |
662
|
|
|
* in the <code>$depth</code> attribute are shown below the actual |
663
|
|
|
* folder or file in the path. |
664
|
|
|
* |
665
|
|
|
* @param string $path The absolute or relative path |
666
|
|
|
* @param int $depth The folder depth to reduce the path to |
667
|
|
|
* @return string |
668
|
|
|
*/ |
669
|
|
|
public static function relativizePathByDepth(string $path, int $depth=2) : string |
670
|
|
|
{ |
671
|
|
|
return PathRelativizer::relativizeByDepth($path, $depth); |
672
|
|
|
} |
673
|
|
|
|
674
|
|
|
/** |
675
|
|
|
* Makes the specified path relative to another path, |
676
|
|
|
* by removing one from the other if found. Also |
677
|
|
|
* normalizes the path to use forward slashes. |
678
|
|
|
* |
679
|
|
|
* Example: |
680
|
|
|
* |
681
|
|
|
* <pre> |
682
|
|
|
* relativizePath('c:\some\folder\to\file.txt', 'c:\some\folder'); |
683
|
|
|
* </pre> |
684
|
|
|
* |
685
|
|
|
* Result: <code>to/file.txt</code> |
686
|
|
|
* |
687
|
|
|
* @param string $path |
688
|
|
|
* @param string $relativeTo |
689
|
|
|
* @return string |
690
|
|
|
*/ |
691
|
|
|
public static function relativizePath(string $path, string $relativeTo) : string |
692
|
|
|
{ |
693
|
|
|
return PathRelativizer::relativize($path, $relativeTo); |
694
|
|
|
} |
695
|
|
|
|
696
|
|
|
/** |
697
|
|
|
* Checks that the target file exists, and throws an exception |
698
|
|
|
* if it does not. |
699
|
|
|
* |
700
|
|
|
* @param string|SplFileInfo $path |
701
|
|
|
* @param int|NULL $errorCode Optional custom error code |
702
|
|
|
* @throws FileHelper_Exception |
703
|
|
|
* @return string The real path to the file |
704
|
|
|
* |
705
|
|
|
* @see FileHelper::ERROR_FILE_DOES_NOT_EXIST |
706
|
|
|
* @see FileHelper::ERROR_REAL_PATH_NOT_FOUND |
707
|
|
|
*/ |
708
|
|
|
public static function requireFileExists($path, ?int $errorCode=null) : string |
709
|
|
|
{ |
710
|
|
|
return self::getPathInfo($path) |
711
|
|
|
->requireIsFile() |
712
|
|
|
->requireExists($errorCode) |
713
|
|
|
->getRealPath(); |
714
|
|
|
} |
715
|
|
|
|
716
|
|
|
/** |
717
|
|
|
* @param string|PathInfoInterface|SplFileInfo $path |
718
|
|
|
* @param int|NULL $errorCode |
719
|
|
|
* @return string |
720
|
|
|
* @throws FileHelper_Exception |
721
|
|
|
*/ |
722
|
|
|
public static function requireFileReadable($path, ?int $errorCode=null) : string |
723
|
|
|
{ |
724
|
|
|
return self::getPathInfo($path) |
725
|
|
|
->requireIsFile() |
726
|
|
|
->requireReadable($errorCode) |
727
|
|
|
->getPath(); |
728
|
|
|
} |
729
|
|
|
|
730
|
|
|
/** |
731
|
|
|
* Reads a specific line number from the target file and returns its |
732
|
|
|
* contents, if the file has such a line. Does so with little memory |
733
|
|
|
* usage, as the file is not read entirely into memory. |
734
|
|
|
* |
735
|
|
|
* @param string|PathInfoInterface|SplFileInfo $path |
736
|
|
|
* @param int $lineNumber Note: 1-based; the first line is number 1. |
737
|
|
|
* @return string|NULL Will return null if the requested line does not exist. |
738
|
|
|
* @throws FileHelper_Exception |
739
|
|
|
* |
740
|
|
|
* @see FileHelper::ERROR_FILE_DOES_NOT_EXIST |
741
|
|
|
*/ |
742
|
|
|
public static function getLineFromFile($path, int $lineNumber) : ?string |
743
|
|
|
{ |
744
|
|
|
return self::getFileInfo($path)->getLine($lineNumber); |
745
|
|
|
} |
746
|
|
|
|
747
|
|
|
/** |
748
|
|
|
* Retrieves the total amount of lines in the file, without |
749
|
|
|
* reading the whole file into memory. |
750
|
|
|
* |
751
|
|
|
* @param string|PathInfoInterface|SplFileInfo $path |
752
|
|
|
* @return int |
753
|
|
|
* @throws FileHelper_Exception |
754
|
|
|
*/ |
755
|
|
|
public static function countFileLines($path) : int |
756
|
|
|
{ |
757
|
|
|
return self::getFileInfo($path)->countLines(); |
758
|
|
|
} |
759
|
|
|
|
760
|
|
|
/** |
761
|
|
|
* Parses the target file to detect any PHP classes contained |
762
|
|
|
* within, and retrieve information on them. Does not use the |
763
|
|
|
* PHP reflection API. |
764
|
|
|
* |
765
|
|
|
* @param string|PathInfoInterface|SplFileInfo $filePath |
766
|
|
|
* @return FileHelper_PHPClassInfo |
767
|
|
|
* @throws FileHelper_Exception |
768
|
|
|
*/ |
769
|
|
|
public static function findPHPClasses($filePath) : FileHelper_PHPClassInfo |
770
|
|
|
{ |
771
|
|
|
return PHPFile::factory($filePath)->findClasses(); |
772
|
|
|
} |
773
|
|
|
|
774
|
|
|
/** |
775
|
|
|
* Detects the end of line style used in the target file, if any. |
776
|
|
|
* Can be used with large files, because it only reads part of it. |
777
|
|
|
* |
778
|
|
|
* @param string|PathInfoInterface|SplFileInfo $filePath The path to the file. |
779
|
|
|
* @return NULL|ConvertHelper_EOL The end of line character information, or NULL if none is found. |
780
|
|
|
* @throws FileHelper_Exception |
781
|
|
|
*/ |
782
|
|
|
public static function detectEOLCharacter($filePath) : ?ConvertHelper_EOL |
783
|
|
|
{ |
784
|
|
|
return self::getFileInfo($filePath)->detectEOLCharacter(); |
785
|
|
|
} |
786
|
|
|
|
787
|
|
|
/** |
788
|
|
|
* Reads the specified amount of lines from the target file. |
789
|
|
|
* Unicode BOM compatible: any byte order marker is stripped |
790
|
|
|
* from the resulting lines. |
791
|
|
|
* |
792
|
|
|
* @param string|PathInfoInterface|SplFileInfo $filePath |
793
|
|
|
* @param int $amount Set to 0 to read all lines. |
794
|
|
|
* @return string[] |
795
|
|
|
* |
796
|
|
|
* @throws FileHelper_Exception |
797
|
|
|
* @see FileHelper::ERROR_FILE_DOES_NOT_EXIST |
798
|
|
|
* @see FileHelper::ERROR_CANNOT_OPEN_FILE_TO_READ_LINES |
799
|
|
|
*/ |
800
|
|
|
public static function readLines($filePath, int $amount=0) : array |
801
|
|
|
{ |
802
|
|
|
return self::getFileInfo($filePath) |
803
|
|
|
->getLineReader() |
804
|
|
|
->getLines($amount); |
805
|
|
|
} |
806
|
|
|
|
807
|
|
|
/** |
808
|
|
|
* Reads all content from a file. |
809
|
|
|
* |
810
|
|
|
* @param string|PathInfoInterface|SplFileInfo $filePath |
811
|
|
|
* @throws FileHelper_Exception |
812
|
|
|
* @return string |
813
|
|
|
* |
814
|
|
|
* @see FileHelper::ERROR_FILE_DOES_NOT_EXIST |
815
|
|
|
* @see FileHelper::ERROR_CANNOT_READ_FILE_CONTENTS |
816
|
|
|
*/ |
817
|
|
|
public static function readContents($filePath) : string |
818
|
|
|
{ |
819
|
|
|
return self::getFileInfo($filePath)->getContents(); |
820
|
|
|
} |
821
|
|
|
|
822
|
|
|
/** |
823
|
|
|
* Ensures that the target path exists on disk, and is a folder. |
824
|
|
|
* |
825
|
|
|
* @param string|PathInfoInterface|SplFileInfo $path |
826
|
|
|
* @return string The real path, with normalized slashes. |
827
|
|
|
* @throws FileHelper_Exception |
828
|
|
|
* |
829
|
|
|
* @see FileHelper::normalizePath() |
830
|
|
|
* |
831
|
|
|
* @see FileHelper::ERROR_FOLDER_DOES_NOT_EXIST |
832
|
|
|
* @see FileHelper::ERROR_PATH_IS_NOT_A_FOLDER |
833
|
|
|
*/ |
834
|
|
|
public static function requireFolderExists($path) : string |
835
|
|
|
{ |
836
|
|
|
return self::getFolderInfo($path) |
837
|
|
|
->requireExists(self::ERROR_FOLDER_DOES_NOT_EXIST) |
838
|
|
|
->getRealPath(); |
839
|
|
|
} |
840
|
|
|
|
841
|
|
|
/** |
842
|
|
|
* Creates an instance of the path reducer tool, which can reduce |
843
|
|
|
* a list of paths to the closest common root folder. |
844
|
|
|
* |
845
|
|
|
* @param string[] $paths |
846
|
|
|
* @return PathsReducer |
847
|
|
|
* |
848
|
|
|
* @throws FileHelper_Exception |
849
|
|
|
*/ |
850
|
|
|
public static function createPathsReducer(array $paths=array()) : PathsReducer |
851
|
|
|
{ |
852
|
|
|
return new PathsReducer($paths); |
853
|
|
|
} |
854
|
|
|
} |
855
|
|
|
|
This function has been deprecated. The supplier of the function has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.