depage-fs
Toggle main menu visibility
Loading...
Searching...
No Matches
Fs.php
Go to the documentation of this file.
1
<?php
2
3
namespace
Depage\Fs;
4
5
class
Fs
6
{
7
protected
$currentPath
;
8
protected
$base
;
9
protected
$url
;
10
protected
$hidden
;
11
protected
$streamContextOptions
= array();
12
protected
$streamContext
;
13
protected
$path
;
14
protected
$errorHandlerDepth
= 0;
15
public
function
__construct
($params = array())
16
{
17
if
(isset($params[
'scheme'
])) $this->url[
'scheme'
] = $params[
'scheme'
];
18
if
(isset($params[
'user'
])) $this->url[
'user'
] = $params[
'user'
];
19
if
(isset($params[
'pass'
])) $this->url[
'pass'
] = $params[
'pass'
];
20
if
(isset($params[
'host'
])) $this->url[
'host'
] = $params[
'host'
];
21
if
(isset($params[
'port'
])) $this->url[
'port'
] = $params[
'port'
];
22
23
$this->hidden = (isset($params[
'hidden'
])) ? $params[
'hidden'
] :
false
;
24
$this->path = (isset($params[
'path'
])) ? $params[
'path'
] :
'.'
;
25
26
$this->streamContext = stream_context_create($this->streamContextOptions);
27
}
28
public
static
function
factory
(
$url
, $params = array())
29
{
30
$parsed =
self::parseUrl
(
$url
);
31
if
(is_array($parsed)) {
32
$params = array_merge($parsed, $params);
33
}
34
$scheme = $params[
'scheme'
] ??
''
;
35
$alias =
self::schemeAlias
($scheme);
36
37
$schemeClass =
'\Depage\Fs\Fs'
. ucfirst($alias[
'class'
]);
38
$params[
'scheme'
] = $alias[
'scheme'
];
39
40
return
new
$schemeClass($params);
41
}
42
protected
static
function
schemeAlias
($alias =
''
)
43
{
44
// null would be deprecated as an array key in php 8.5
45
$alias = (string) $alias;
46
47
$aliases = array(
48
''
=> array(
'class'
=>
'file'
,
'scheme'
=>
'file'
),
49
'file'
=> array(
'class'
=>
'file'
,
'scheme'
=>
'file'
),
50
'ftp'
=> array(
'class'
=>
'ftp'
,
'scheme'
=>
'ftp'
),
51
'ftps'
=> array(
'class'
=>
'ftp'
,
'scheme'
=>
'ftps'
),
52
'ssh2.sftp'
=> array(
'class'
=>
'ssh'
,
'scheme'
=>
'ssh2.sftp'
),
53
'ssh'
=> array(
'class'
=>
'ssh'
,
'scheme'
=>
'ssh2.sftp'
),
54
'sftp'
=> array(
'class'
=>
'ssh'
,
'scheme'
=>
'ssh2.sftp'
),
55
);
56
57
if
(array_key_exists($alias, $aliases)) {
58
$translation = $aliases[$alias];
59
}
else
{
60
$translation = array(
'class'
=>
''
,
'scheme'
=> $alias);
61
}
62
63
return
$translation;
64
}
65
66
public
function
pwd
()
67
{
68
$this->
preCommandHook
();
69
70
try
{
71
$url
=
$this->url
;
72
$url
[
'path'
] = $this->base .
$this->currentPath
;
73
$pwd = $this->
buildUrl
(
$url
);
74
75
return
$pwd;
76
}
finally
{
77
$this->
postCommandHook
();
78
}
79
}
80
public
function
ls
(
$url
)
81
{
82
$this->
preCommandHook
();
83
84
try
{
85
$cleanUrl = $this->
cleanUrl
(
$url
);
86
$path
= str_replace($this->
pwd
(),
''
, $cleanUrl);
87
$ls = $this->
lsRecursive
(
$path
,
''
);
88
89
return
$ls;
90
}
finally
{
91
$this->
postCommandHook
();
92
}
93
}
94
public
function
lsDir
(
$path
=
''
)
95
{
96
$this->
preCommandHook
();
97
98
try
{
99
$lsDir = $this->
lsFilter
(
$path
,
'is_dir'
);
100
101
return
$lsDir;
102
}
finally
{
103
$this->
postCommandHook
();
104
}
105
}
106
public
function
lsFiles
(
$path
=
''
)
107
{
108
$this->
preCommandHook
();
109
110
try
{
111
$lsFiles = $this->
lsFilter
(
$path
,
'is_file'
);
112
113
return
$lsFiles;
114
}
finally
{
115
$this->
postCommandHook
();
116
}
117
}
118
public
function
exists
($remotePath)
119
{
120
$this->
preCommandHook
();
121
122
try
{
123
$remote = $this->
cleanUrl
($remotePath);
124
$exists = file_exists($remote);
125
126
return
$exists;
127
}
finally
{
128
$this->
postCommandHook
();
129
}
130
}
131
public
function
fileInfo
($remotePath)
132
{
133
$this->
preCommandHook
();
134
135
try
{
136
$remote = $this->
cleanUrl
($remotePath);
137
$fileInfo = new \SplFileInfo($remote);
138
139
return
$fileInfo;
140
}
finally
{
141
$this->
postCommandHook
();
142
}
143
}
144
145
public
function
cd
(
$url
)
146
{
147
$this->
preCommandHook
();
148
149
try
{
150
$cleanUrl = $this->
cleanUrl
(
$url
);
151
152
if
(is_dir($cleanUrl) && is_readable($cleanUrl .
'/.'
)) {
153
$this->currentPath = str_replace($this->
pwd
(),
''
, $cleanUrl) .
'/'
;
154
}
else
{
155
throw
new
Exceptions\FsException
(
'Directory not accessible "'
. $this->
cleanUrl
(
$url
,
false
) .
'".'
);
156
}
157
158
}
finally
{
159
$this->
postCommandHook
();
160
}
161
}
162
public
function
mkdir
($pathName, $mode = 0777, $recursive =
true
)
163
{
164
$this->
preCommandHook
();
165
166
try
{
167
$cleanUrl = $this->
cleanUrl
($pathName);
168
if
(!is_dir($cleanUrl)) {
169
$success =
mkdir
($cleanUrl, $mode, $recursive, $this->streamContext);
170
171
if
(!$success && !is_dir($cleanUrl)) {
172
throw
new
Exceptions\FsException
(
'Error while creating directory "'
. $pathName .
'".'
);
173
}
174
}
175
176
}
finally
{
177
$this->
postCommandHook
();
178
}
179
}
180
public
function
rm
(
$url
)
181
{
182
$this->
preCommandHook
();
183
184
try
{
185
$cleanUrl = $this->
cleanUrl
(
$url
);
186
$pwd = $this->
pwd
();
187
188
if
(preg_match(
'/^'
. preg_quote($cleanUrl,
'/'
) .
'\//'
, $pwd .
'/'
)) {
189
throw
new
Exceptions\FsException
(
'Cannot delete current or parent directory "'
. $this->
cleanUrl
($pwd,
false
) .
'".'
);
190
}
191
$this->
rmRecursive
($cleanUrl);
192
193
}
finally
{
194
$this->
postCommandHook
();
195
}
196
}
197
public
function
copy
($sourcePath, $targetPath)
198
{
199
$this->
preCommandHook
();
200
201
try
{
202
$source = $this->
cleanUrl
($sourcePath);
203
$target = $this->
cleanUrl
($targetPath);
204
205
if
(file_exists($source)) {
206
if
(file_exists($target) && is_dir($target)) {
207
$target .=
'/'
. $this->
extractFileName
($source);
208
}
209
\copy
($source, $target, $this->streamContext);
210
}
else
{
211
throw
new
Exceptions\FsException
(
'Cannot copy "'
. $this->
cleanUrl
($sourcePath,
false
) .
'" to "'
. $this->
cleanUrl
($targetPath,
false
) .
'" - source doesn\'t exist.'
);
212
}
213
214
}
finally
{
215
$this->
postCommandHook
();
216
}
217
}
218
public
function
mv
($sourcePath, $targetPath)
219
{
220
$this->
preCommandHook
();
221
222
try
{
223
$source = $this->
cleanUrl
($sourcePath);
224
$target = $this->
cleanUrl
($targetPath);
225
226
if
(file_exists($source)) {
227
if
(file_exists($target) && is_dir($target)) {
228
$target .=
'/'
. $this->
extractFileName
($source);
229
}
230
$this->
rename
($source, $target);
231
}
else
{
232
throw
new
Exceptions\FsException
(
'Cannot move "'
. $this->
cleanUrl
($sourcePath,
false
) .
'" to "'
. $this->
cleanUrl
($targetPath,
false
) .
'" - source doesn\'t exist.'
);
233
}
234
235
}
finally
{
236
$this->
postCommandHook
();
237
}
238
}
239
240
public
function
get
($remotePath, $local =
null
)
241
{
242
$this->
preCommandHook
();
243
244
try
{
245
if
($local ===
null
) {
246
$local = $this->
extractFileName
($remotePath);
247
}
248
249
$remote = $this->
cleanUrl
($remotePath);
250
copy
($remote, $local, $this->streamContext);
251
252
}
finally
{
253
$this->
postCommandHook
();
254
}
255
}
256
public
function
put
($local, $remotePath)
257
{
258
$this->
preCommandHook
();
259
260
try
{
261
$remote = $this->
cleanUrl
($remotePath);
262
copy
($local, $remote, $this->streamContext);
263
264
}
finally
{
265
$this->
postCommandHook
();
266
}
267
}
268
public
function
getString
($remotePath)
269
{
270
$this->
preCommandHook
();
271
272
try
{
273
$remote = $this->
cleanUrl
($remotePath);
274
$string = file_get_contents($remote,
false
, $this->streamContext);
275
276
return
$string;
277
}
finally
{
278
$this->
postCommandHook
();
279
}
280
}
281
public
function
putString
($remotePath, $string)
282
{
283
$this->
preCommandHook
();
284
285
try
{
286
$remote = $this->
cleanUrl
($remotePath);
287
$this->
file_put_contents
($remote, $string, 0, $this->streamContext);
288
289
}
finally
{
290
$this->
postCommandHook
();
291
}
292
}
293
294
public
function
test
(&$error =
null
)
295
{
296
$testFile =
'depage-fs-test-file.tmp'
;
297
$testString =
'depage-fs-test-string'
;
298
$success =
false
;
299
300
try
{
301
if
(!$this->
exists
($testFile)) {
302
$this->
putString
($testFile, $testString);
303
if
($this->
getString
($testFile) === $testString) {
304
$this->
rm
($testFile);
305
$success = !$this->
exists
($testFile);
306
}
307
}
308
}
catch
(
Exceptions
\
FsException
$exception) {
309
$error = $exception->getMessage();
310
}
311
312
return
$success;
313
}
314
315
protected
function
preCommandHook
()
316
{
317
$this->
lateConnect
();
318
$this->
setErrorHandler
(
true
);
319
}
320
protected
function
postCommandHook
()
321
{
322
$this->
setErrorHandler
(
false
);
323
}
324
protected
function
lateConnect
()
325
{
326
if
(!isset($this->base)) {
327
$this->
setBase
($this->path);
328
}
329
}
330
protected
function
setBase
(
$path
)
331
{
332
$cleanPath = $this->
cleanPath
(
'/'
.
$path
);
333
$this->base = (substr($cleanPath, -1) ==
'/'
) ? $cleanPath : $cleanPath .
'/'
;
334
}
335
336
public
function
depageFsErrorHandler
($errno, $errstr, $errfile, $errline)
337
{
338
if
($this->errorHandlerDepth > 0) {
339
$this->errorHandlerDepth = 0;
340
restore_error_handler();
341
}
342
throw
new
Exceptions\FsException
($errstr);
343
}
344
protected
function
setErrorHandler
($start)
345
{
346
if
($start) {
347
if
($this->errorHandlerDepth++ === 0) {
348
set_error_handler(array($this,
'depageFsErrorHandler'
));
349
}
350
} elseif ($this->errorHandlerDepth > 0 && --$this->errorHandlerDepth === 0) {
351
restore_error_handler();
352
}
353
}
354
355
public
static
function
parseUrl
(
$url
)
356
{
357
$parsed = parse_url(
$url
);
358
359
// hack, parse_url (PHP 5.6.29) won't handle resource name strings
360
if
(isset($parsed[
'fragment'
])) {
361
$urlParts = explode(
'/'
,
$url
);
362
363
if
(isset($urlParts[2]) && preg_match(
'/^Resource id \#([0-9]+)$/'
, $urlParts[2], $matches)) {
364
$urlParts[2] = $matches[1];
365
$parsed = parse_url(implode(
'/'
, $urlParts));
366
$parsed[
'host'
] =
'Resource id #'
. $parsed[
'host'
];
367
}
368
}
369
370
// hack, parse_url matches anything after the first question mark as "query"
371
$path
= (isset($parsed[
'path'
])) ? $parsed[
'path'
] :
''
;
372
$query = (isset($parsed[
'query'
])) ? $parsed[
'query'
] :
''
;
373
if
(!empty($query) || preg_match(
'/\?$/'
,
$url
)) {
374
$parsed[
'path'
] =
$path
.
'?'
. $query;
375
unset($parsed[
'query'
]);
376
}
377
378
return
$parsed;
379
}
380
protected
function
cleanUrl
(
$url
, $showPass =
true
)
381
{
382
$parsed =
self::parseUrl
(
$url
);
383
$scheme = (isset($parsed[
'scheme'
])) ? $parsed[
'scheme'
] :
null
;
384
$path
= (isset($parsed[
'path'
])) ? $parsed[
'path'
] :
null
;
385
386
if
($scheme) {
387
$newUrl = $parsed;
388
$newPath =
$path
;
389
}
else
{
390
$newUrl =
$this->url
;
391
if
(substr(
$url
, 0, 1) ==
'/'
) {
392
$newPath =
$url
;
393
}
else
{
394
$newPath = $this->base .
$this->currentPath
;
395
$newPath .= (substr(
$path
, 0, 1) ==
'/'
) ?
''
:
'/'
;
396
$newPath .=
$path
;
397
}
398
}
399
400
$newUrl[
'path'
] = $this->
cleanPath
($newPath);
401
402
if
(!preg_match(
';^'
. preg_quote($this->
cleanPath
($this->base)) .
'(.*)$;'
, $newUrl[
'path'
])) {
403
throw
new
Exceptions\FsException
(
'Cannot leave base directory "'
. $this->base .
'".'
);
404
}
405
406
return
$this->
buildUrl
($newUrl, $showPass);
407
}
408
protected
function
cleanPath
(
$path
)
409
{
410
$dirs = explode(
'/'
,
$path
);
411
$newDirs = array();
412
413
foreach
($dirs as $dir) {
414
if
($dir ==
'..'
) {
415
array_pop($newDirs);
416
} elseif ($dir !=
'.'
&& $dir !=
''
) {
417
$newDirs[] = $dir;
418
}
419
}
420
421
$newPath = (substr(
$path
, 0, 1) ==
'/'
) ?
'/'
:
''
;
422
$newPath .= implode(
'/'
, $newDirs);
423
424
return
$newPath;
425
}
426
protected
function
buildUrl
($parsed, $showPass =
true
)
427
{
428
$path
= $parsed[
'scheme'
] .
'://'
;
429
$path
.= !empty($parsed[
'user'
]) ? rawurlencode($parsed[
'user'
]) :
''
;
430
431
if
(!empty($parsed[
'pass'
])) {
432
$path
.= ($showPass) ?
':'
. rawurlencode($parsed[
'pass'
]) :
':...'
;
433
}
434
435
$path
.= !empty($parsed[
'user'
]) ?
'@'
:
''
;
436
$path
.= !empty($parsed[
'host'
]) ? $parsed[
'host'
] :
''
;
437
$path
.= !empty($parsed[
'port'
]) ?
':'
. $parsed[
'port'
] :
''
;
438
$path
.= !empty($parsed[
'path'
]) ? $parsed[
'path'
] :
'/'
;
439
440
return
$path
;
441
}
442
protected
function
extractFileName
(
$path
)
443
{
444
$pathInfo = pathinfo(
$path
);
445
$fileName = $pathInfo[
'filename'
];
446
447
if
(isset($pathInfo[
'extension'
])) {
448
$fileName .=
'.'
. $pathInfo[
'extension'
];
449
}
450
451
return
$fileName;
452
}
453
454
protected
function
lsFilter
(
$path
, $function)
455
{
456
$ls = $this->
ls
(
$path
);
457
$pwd = $this->
pwd
();
458
$lsFiltered = array_filter(
459
$ls,
460
function
($element) use ($function, $pwd) {
461
return
$function($pwd . $element);
462
}
463
);
464
natcasesort($lsFiltered);
465
$sorted = array_values($lsFiltered);
466
467
return
$sorted;
468
}
469
protected
function
matchNodesInPath
(
$path
, $pattern)
470
{
471
if
(preg_match(
'/['
. preg_quote(
'*?[]'
) .
']/'
, $pattern)) {
472
$matches = array_filter(
473
$this->
scandir
(
$path
),
474
function
($node) use ($pattern) {
return
fnmatch($pattern, $node); }
475
);
476
}
else
{
477
$matches = array($pattern);
478
}
479
return
$matches;
480
}
481
protected
function
lsRecursive
(
$path
, $current)
482
{
483
$nodes = array();
484
$patterns = explode(
'/'
,
$path
);
485
$count = count($patterns);
486
$pwd = $this->
pwd
();
487
488
if
($count) {
489
$pattern = array_shift($patterns);
490
$matches = $this->
matchNodesInPath
($pwd . $current, $pattern);
491
492
foreach
($matches as $match) {
493
$next = ($current) ? $current .
'/'
. $match : $match;
494
495
if
($count === 1) {
496
$nodes[] = $next;
497
} elseif (is_dir($pwd . $next)) {
498
$nodes = array_merge(
499
$nodes,
500
$this->
lsRecursive
(implode(
'/'
, $patterns), $next)
501
);
502
}
503
}
504
}
505
506
return
$nodes;
507
}
508
protected
function
rmRecursive
($cleanUrl)
509
{
510
if
(!file_exists($cleanUrl)) {
511
throw
new
Exceptions\FsException
(
'"'
. $this->
cleanUrl
($cleanUrl,
false
) .
'" doesn\'t exist.'
);
512
} elseif (is_dir($cleanUrl)) {
513
foreach
($this->
scandir
($cleanUrl,
true
) as $nested) {
514
$this->
rmRecursive
($cleanUrl .
'/'
. $nested);
515
}
516
$this->
rmdir
($cleanUrl);
517
} elseif (is_file($cleanUrl)) {
518
unlink($cleanUrl, $this->streamContext);
519
}
520
521
clearstatcache(
true
, $cleanUrl);
522
}
523
524
protected
function
scandir
($cleanUrl =
''
,
$hidden
=
null
)
525
{
526
if
(
$hidden
===
null
) {
527
$hidden
=
$this->hidden
;
528
}
529
530
$scanDir =
\scandir
($cleanUrl, 0, $this->streamContext);
531
$filtered = array_diff($scanDir, array(
'.'
,
'..'
));
532
533
if
(!
$hidden
) {
534
$filtered = array_filter(
535
$filtered,
536
function
($node) {
return
($node[0] !=
'.'
); }
537
);
538
}
539
540
natcasesort($filtered);
541
$sorted = array_values($filtered);
542
543
return
$sorted;
544
}
545
548
protected
function
rmdir
(
$url
)
549
{
550
return \rmdir(
$url
, $this->streamContext);
551
}
552
555
protected
function
rename
($source, $target)
556
{
557
return \rename($source, $target, $this->streamContext);
558
}
559
562
public
function
file_put_contents
($filename, $data, $flags = 0, $context =
null
)
563
{
564
return \file_put_contents($filename, $data, $flags, $context);
565
}
566
}
567
568
/* vim:set ft=php sw=4 sts=4 fdm=marker : */
Depage\Fs\Exceptions\FsException
Definition
FsException.php:5
Depage\Fs\Fs
Definition
Fs.php:6
Depage\Fs\Fs\extractFileName
extractFileName($path)
Definition
Fs.php:442
Depage\Fs\Fs\$streamContextOptions
$streamContextOptions
Definition
Fs.php:11
Depage\Fs\Fs\rmRecursive
rmRecursive($cleanUrl)
Definition
Fs.php:508
Depage\Fs\Fs\$path
$path
Definition
Fs.php:13
Depage\Fs\Fs\buildUrl
buildUrl($parsed, $showPass=true)
Definition
Fs.php:426
Depage\Fs\Fs\preCommandHook
preCommandHook()
Definition
Fs.php:315
Depage\Fs\Fs\pwd
pwd()
Definition
Fs.php:66
Depage\Fs\Fs\fileInfo
fileInfo($remotePath)
Definition
Fs.php:131
Depage\Fs\Fs\schemeAlias
static schemeAlias($alias='')
Definition
Fs.php:42
Depage\Fs\Fs\cd
cd($url)
Definition
Fs.php:145
Depage\Fs\Fs\putString
putString($remotePath, $string)
Definition
Fs.php:281
Depage\Fs\Fs\cleanPath
cleanPath($path)
Definition
Fs.php:408
Depage\Fs\Fs\$hidden
$hidden
Definition
Fs.php:10
Depage\Fs\Fs\ls
ls($url)
Definition
Fs.php:80
Depage\Fs\Fs\__construct
__construct($params=array())
Definition
Fs.php:15
Depage\Fs\Fs\lateConnect
lateConnect()
Definition
Fs.php:324
Depage\Fs\Fs\rename
rename($source, $target)
Hook, allows overriding of rename function.
Definition
Fs.php:555
Depage\Fs\Fs\factory
static factory($url, $params=array())
Definition
Fs.php:28
Depage\Fs\Fs\lsRecursive
lsRecursive($path, $current)
Definition
Fs.php:481
Depage\Fs\Fs\$streamContext
$streamContext
Definition
Fs.php:12
Depage\Fs\Fs\$currentPath
$currentPath
Definition
Fs.php:7
Depage\Fs\Fs\copy
copy($sourcePath, $targetPath)
Definition
Fs.php:197
Depage\Fs\Fs\rmdir
rmdir($url)
Hook, allows overriding of rmdir function.
Definition
Fs.php:548
Depage\Fs\Fs\file_put_contents
file_put_contents($filename, $data, $flags=0, $context=null)
Hook, allows overriding of file_put_contents function.
Definition
Fs.php:562
Depage\Fs\Fs\scandir
scandir($cleanUrl='', $hidden=null)
Definition
Fs.php:524
Depage\Fs\Fs\lsDir
lsDir($path='')
Definition
Fs.php:94
Depage\Fs\Fs\$errorHandlerDepth
$errorHandlerDepth
Definition
Fs.php:14
Depage\Fs\Fs\mkdir
mkdir($pathName, $mode=0777, $recursive=true)
Definition
Fs.php:162
Depage\Fs\Fs\depageFsErrorHandler
depageFsErrorHandler($errno, $errstr, $errfile, $errline)
Definition
Fs.php:336
Depage\Fs\Fs\getString
getString($remotePath)
Definition
Fs.php:268
Depage\Fs\Fs\postCommandHook
postCommandHook()
Definition
Fs.php:320
Depage\Fs\Fs\$base
$base
Definition
Fs.php:8
Depage\Fs\Fs\mv
mv($sourcePath, $targetPath)
Definition
Fs.php:218
Depage\Fs\Fs\$url
$url
Definition
Fs.php:9
Depage\Fs\Fs\lsFiles
lsFiles($path='')
Definition
Fs.php:106
Depage\Fs\Fs\exists
exists($remotePath)
Definition
Fs.php:118
Depage\Fs\Fs\setErrorHandler
setErrorHandler($start)
Definition
Fs.php:344
Depage\Fs\Fs\put
put($local, $remotePath)
Definition
Fs.php:256
Depage\Fs\Fs\lsFilter
lsFilter($path, $function)
Definition
Fs.php:454
Depage\Fs\Fs\test
test(&$error=null)
Definition
Fs.php:294
Depage\Fs\Fs\cleanUrl
cleanUrl($url, $showPass=true)
Definition
Fs.php:380
Depage\Fs\Fs\matchNodesInPath
matchNodesInPath($path, $pattern)
Definition
Fs.php:469
Depage\Fs\Fs\setBase
setBase($path)
Definition
Fs.php:330
Depage\Fs\Fs\rm
rm($url)
Definition
Fs.php:180
Depage\Fs\Fs\parseUrl
static parseUrl($url)
Definition
Fs.php:355
Depage\Fs\Exceptions
Definition
FsException.php:3
Fs.php
Generated on
for depage-fs by
doxygen
1.18.0
For an overview of all docs, go to
docs.depage.net