-
Notifications
You must be signed in to change notification settings - Fork 102
/
vfsStream.php
389 lines (364 loc) · 12.6 KB
/
vfsStream.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
<?php
/**
* This file is part of vfsStream.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @package org\bovigo\vfs
*/
namespace org\bovigo\vfs;
use org\bovigo\vfs\visitor\vfsStreamVisitor;
/**
* Some utility methods for vfsStream.
*
* @api
*/
class vfsStream
{
/**
* url scheme
*/
const SCHEME = 'vfs';
/**
* owner: root
*/
const OWNER_ROOT = 0;
/**
* owner: user 1
*/
const OWNER_USER_1 = 1;
/**
* owner: user 2
*/
const OWNER_USER_2 = 2;
/**
* group: root
*/
const GROUP_ROOT = 0;
/**
* group: user 1
*/
const GROUP_USER_1 = 1;
/**
* group: user 2
*/
const GROUP_USER_2 = 2;
/**
* initial umask setting
*
* @type int
*/
protected static $umask = 0000;
/**
* prepends the scheme to the given URL
*
* @param string $path path to translate to vfsStream url
* @return string
*/
public static function url($path)
{
return self::SCHEME . '://' . str_replace('\\', '/', $path);
}
/**
* restores the path from the url
*
* @param string $url vfsStream url to translate into path
* @return string
*/
public static function path($url)
{
// remove line feeds and trailing whitespaces
$path = trim($url, " \t\r\n\0\x0B/");
$path = substr($path, strlen(self::SCHEME . '://'));
$path = str_replace('\\', '/', $path);
// replace double slashes with single slashes
$path = str_replace('//', '/', $path);
return $path;
}
/**
* sets new umask setting and returns previous umask setting
*
* If no value is given only the current umask setting is returned.
*
* @param int $umask new umask setting
* @return int
* @since 0.8.0
*/
public static function umask($umask = null)
{
$oldUmask = self::$umask;
if (null !== $umask) {
self::$umask = $umask;
}
return $oldUmask;
}
/**
* helper method for setting up vfsStream in unit tests
*
* Instead of
* vfsStreamWrapper::register();
* vfsStreamWrapper::setRoot(vfsStream::newDirectory('root'));
* you can simply do
* vfsStream::setup()
* which yields the same result. Additionally, the method returns the
* freshly created root directory which you can use to make further
* adjustments to it.
*
* Assumed $structure contains an array like this:
* <code>
* array('Core' = array('AbstractFactory' => array('test.php' => 'some text content',
* 'other.php' => 'Some more text content',
* 'Invalid.csv' => 'Something else',
* ),
* 'AnEmptyFolder' => array(),
* 'badlocation.php' => 'some bad content',
* )
* )
* </code>
* the resulting directory tree will look like this:
* <pre>
* root
* \- Core
* |- badlocation.php
* |- AbstractFactory
* | |- test.php
* | |- other.php
* | \- Invalid.csv
* \- AnEmptyFolder
* </pre>
* Arrays will become directories with their key as directory name, and
* strings becomes files with their key as file name and their value as file
* content.
*
* @param string $rootDirName name of root directory
* @param int $permissions file permissions of root directory
* @param array $structure directory structure to add under root directory
* @return \org\bovigo\vfs\vfsStreamDirectory
* @since 0.7.0
* @see https://github.com/mikey179/vfsStream/issues/14
* @see https://github.com/mikey179/vfsStream/issues/20
*/
public static function setup($rootDirName = 'root', $permissions = null, array $structure = array())
{
vfsStreamWrapper::register();
return self::create($structure, vfsStreamWrapper::setRoot(self::newDirectory($rootDirName, $permissions)));
}
/**
* creates vfsStream directory structure from an array and adds it to given base dir
*
* Assumed $structure contains an array like this:
* <code>
* array('Core' = array('AbstractFactory' => array('test.php' => 'some text content',
* 'other.php' => 'Some more text content',
* 'Invalid.csv' => 'Something else',
* ),
* 'AnEmptyFolder' => array(),
* 'badlocation.php' => 'some bad content',
* )
* )
* </code>
* the resulting directory tree will look like this:
* <pre>
* baseDir
* \- Core
* |- badlocation.php
* |- AbstractFactory
* | |- test.php
* | |- other.php
* | \- Invalid.csv
* \- AnEmptyFolder
* </pre>
* Arrays will become directories with their key as directory name, and
* strings becomes files with their key as file name and their value as file
* content.
*
* If no baseDir is given it will try to add the structure to the existing
* root directory without replacing existing childs except those with equal
* names.
*
* @param array $structure directory structure to add under root directory
* @param vfsStreamDirectory $baseDir base directory to add structure to
* @return vfsStreamDirectory
* @throws \InvalidArgumentException
* @since 0.10.0
* @see https://github.com/mikey179/vfsStream/issues/14
* @see https://github.com/mikey179/vfsStream/issues/20
*/
public static function create(array $structure, vfsStreamDirectory $baseDir = null)
{
if (null === $baseDir) {
$baseDir = vfsStreamWrapper::getRoot();
}
if (null === $baseDir) {
throw new \InvalidArgumentException('No baseDir given and no root directory set.');
}
return self::addStructure($structure, $baseDir);
}
/**
* helper method to create subdirectories recursively
*
* @param array $structure subdirectory structure to add
* @param vfsStreamDirectory $baseDir directory to add the structure to
* @return vfsStreamDirectory
*/
protected static function addStructure(array $structure, vfsStreamDirectory $baseDir)
{
foreach ($structure as $name => $data) {
$name = (string) $name;
if (is_array($data) === true) {
self::addStructure($data, self::newDirectory($name)->at($baseDir));
} elseif (is_string($data) === true) {
self::newFile($name)->withContent($data)->at($baseDir);
}
}
return $baseDir;
}
/**
* copies the file system structure from given path into the base dir
*
* If no baseDir is given it will try to add the structure to the existing
* root directory without replacing existing childs except those with equal
* names.
* File permissions are copied as well.
* Please note that file contents will only be copied if their file size
* does not exceed the given $maxFileSize which is 1024 KB.
*
* @param string $path path to copy the structure from
* @param vfsStreamDirectory $baseDir directory to add the structure to
* @param int $maxFileSize maximum file size of files to copy content from
* @return vfsStreamDirectory
* @throws \InvalidArgumentException
* @since 0.11.0
* @see https://github.com/mikey179/vfsStream/issues/4
*/
public static function copyFromFileSystem($path, vfsStreamDirectory $baseDir = null, $maxFileSize = 1048576)
{
if (null === $baseDir) {
$baseDir = vfsStreamWrapper::getRoot();
}
if (null === $baseDir) {
throw new \InvalidArgumentException('No baseDir given and no root directory set.');
}
$dir = new \DirectoryIterator($path);
foreach ($dir as $fileinfo) {
if ($fileinfo->isFile() === true) {
if ($fileinfo->getSize() <= $maxFileSize) {
$content = file_get_contents($fileinfo->getPathname());
} else {
$content = '';
}
self::newFile($fileinfo->getFilename(),
octdec(substr(sprintf('%o', $fileinfo->getPerms()), -4))
)
->withContent($content)
->at($baseDir);
} elseif ($fileinfo->isDir() === true && $fileinfo->isDot() === false) {
self::copyFromFileSystem($fileinfo->getPathname(),
self::newDirectory($fileinfo->getFilename(),
octdec(substr(sprintf('%o', $fileinfo->getPerms()), -4))
)
->at($baseDir),
$maxFileSize
);
}
}
return $baseDir;
}
/**
* returns a new file with given name
*
* @param string $name name of file to create
* @param int $permissions permissions of file to create
* @return vfsStreamFile
*/
public static function newFile($name, $permissions = null)
{
return new vfsStreamFile($name, $permissions);
}
/**
* returns a new directory with given name
*
* If the name contains slashes, a new directory structure will be created.
* The returned directory will always be the parent directory of this
* directory structure.
*
* @param string $name name of directory to create
* @param int $permissions permissions of directory to create
* @return vfsStreamDirectory
*/
public static function newDirectory($name, $permissions = null)
{
if ('/' === $name{0}) {
$name = substr($name, 1);
}
$firstSlash = strpos($name, '/');
if (false === $firstSlash) {
return new vfsStreamDirectory($name, $permissions);
}
$ownName = substr($name, 0, $firstSlash);
$subDirs = substr($name, $firstSlash + 1);
$directory = new vfsStreamDirectory($ownName, $permissions);
self::newDirectory($subDirs, $permissions)->at($directory);
return $directory;
}
/**
* returns current user
*
* If the system does not support posix_getuid() the current user will be root (0).
*
* @return int
*/
public static function getCurrentUser()
{
return function_exists('posix_getuid') ? posix_getuid() : self::OWNER_ROOT;
}
/**
* returns current group
*
* If the system does not support posix_getgid() the current group will be root (0).
*
* @return int
*/
public static function getCurrentGroup()
{
return function_exists('posix_getgid') ? posix_getgid() : self::GROUP_ROOT;
}
/**
* use visitor to inspect a content structure
*
* If the given content is null it will fall back to use the current root
* directory of the stream wrapper.
*
* Returns given visitor for method chaining comfort.
*
* @param vfsStreamVisitor $visitor the visitor who inspects
* @param vfsStreamContent $content directory structure to inspect
* @return vfsStreamVisitor
* @throws \InvalidArgumentException
* @since 0.10.0
* @see https://github.com/mikey179/vfsStream/issues/10
*/
public static function inspect(vfsStreamVisitor $visitor, vfsStreamContent $content = null)
{
if (null !== $content) {
return $visitor->visit($content);
}
$root = vfsStreamWrapper::getRoot();
if (null === $root) {
throw new \InvalidArgumentException('No content given and no root directory set.');
}
return $visitor->visitDirectory($root);
}
/**
* sets quota to given amount of bytes
*
* @param int $bytes
* @since 1.1.0
*/
public static function setQuota($bytes)
{
vfsStreamWrapper::setQuota(new Quota($bytes));
}
}
?>