89% of 1434OPs |
93% of 261Lines |
80% of 269Branches |
7% of 842Paths |
# | |
---|---|
1 |
<?php |
2 |
|
3 |
namespace mageekguy\atoum\mock\streams\fs\file; |
4 |
|
5 |
use |
6 |
mageekguy\atoum\exceptions, |
7 |
mageekguy\atoum\mock\streams\fs |
8 |
; |
9 |
|
10 |
class controller extends fs\controller |
11 |
{ |
12 |
protected $exists = true; |
13 |
protected $read = false; |
14 |
protected $write = false; |
15 |
protected $eof = false; |
16 |
protected $pointer = 0; |
17 |
protected $offset = null; |
18 |
protected $append = false; |
19 |
protected $contents = ''; |
20 |
|
21 |
public function __construct($path)100% |
22 |
{ |
23 |
parent::__construct($path); |
24 |
|
25 |
$this->setPermissions('644'); |
26 |
} |
27 |
|
28 |
public function __set($method, $value)100% |
29 |
{ |
30 |
switch ($method = static::mapMethod($method)) |
31 |
{ |
32 |
case 'mkdir': |
33 |
case 'rmdir': |
34 |
case 'dir_closedir': |
35 |
case 'dir_opendir': |
36 |
case 'dir_readdir': |
37 |
case 'dir_rewinddir': |
38 |
throw new exceptions\logic\invalidArgument('Unable to override streamWrapper::' . $method . '() for file'); |
39 |
|
40 |
default: |
41 |
return parent::__set($method, $value); |
42 |
} |
43 |
} |
44 |
|
45 |
public function duplicate()100% |
46 |
{ |
47 |
$controller = parent::duplicate(); |
48 |
|
49 |
$controller->contents = & $this->contents; |
50 |
|
51 |
return $controller; |
52 |
} |
53 |
|
54 |
public function setPermissions($permissions)100% |
55 |
{ |
56 |
return parent::setPermissions(0100000 | octdec($permissions)); |
57 |
} |
58 |
|
59 |
public function getPointer()100% |
60 |
{ |
61 |
return $this->pointer; |
62 |
} |
63 |
|
64 |
public function setContents($contents)100% |
65 |
{ |
66 |
$this->contents = $contents; |
67 |
|
68 |
return $this->setStat('size', strlen($this->contents)); |
69 |
} |
70 |
|
71 |
public function getContents()100% |
72 |
{ |
73 |
return $this->contents; |
74 |
} |
75 |
|
76 |
public function contains($contents)100% |
77 |
{ |
78 |
return $this |
79 |
->setContents($contents) |
80 |
->setPointer(0) |
81 |
; |
82 |
} |
83 |
|
84 |
public function isEmpty()100% |
85 |
{ |
86 |
return $this->contains(''); |
87 |
} |
88 |
|
89 |
public function stream_open($path, $mode, $options, & $openedPath = null)100% |
90 |
{ |
91 |
if ($this->nextCallIsOverloaded(__FUNCTION__) === true) |
92 |
{ |
93 |
return $this->invoke(__FUNCTION__, func_get_args()); |
94 |
} |
95 |
else |
96 |
{ |
97 |
$this->addCall(__FUNCTION__, func_get_args()); |
98 |
|
99 |
$this->offset = null; |
100 |
$this->append = false; |
101 |
|
102 |
$isOpened = false; |
103 |
|
104 |
$reportErrors = ($options & STREAM_REPORT_ERRORS) == STREAM_REPORT_ERRORS; |
105 |
|
106 |
if (self::checkOpenMode($mode) === false) |
107 |
{ |
108 |
if ($reportErrors === true) |
109 |
{ |
110 |
trigger_error('Operation timed out', E_USER_WARNING); |
111 |
} |
112 |
} |
113 |
else |
114 |
{ |
115 |
$this->setOpenMode($mode); |
116 |
|
117 |
switch (true) |
118 |
{ |
119 |
case $this->read === true && $this->write === false: |
120 |
$isOpened = $this->checkIfReadable(); |
121 |
break; |
122 |
|
123 |
case $this->read === false && $this->write === true: |
124 |
$isOpened = $this->checkIfWritable(); |
125 |
break; |
126 |
|
127 |
default: |
128 |
$isOpened = $this->checkIfReadable() && $this->checkIfWritable(); |
129 |
} |
130 |
|
131 |
if ($isOpened === false) |
132 |
{ |
133 |
if ($reportErrors === true) |
134 |
{ |
135 |
trigger_error('Permission denied', E_USER_WARNING); |
136 |
} |
137 |
} |
138 |
else |
139 |
{ |
140 |
switch (self::getRawOpenMode($mode)) |
141 |
{ |
142 |
case 'w': |
143 |
$this->exists = true; |
144 |
$this->truncate(0); |
145 |
$this->seek(0); |
146 |
break; |
147 |
|
148 |
case 'r': |
149 |
$isOpened = $this->exists; |
150 |
|
151 |
if ($isOpened === true) |
152 |
{ |
153 |
$this->seek(0); |
154 |
} |
155 |
else if ($reportErrors === true) |
156 |
{ |
157 |
trigger_error('No such file or directory', E_USER_WARNING); |
158 |
} |
159 |
break; |
160 |
|
161 |
case 'c': |
162 |
$this->exists = true; |
163 |
$this->seek(0); |
164 |
break; |
165 |
|
166 |
case 'x': |
167 |
if ($this->exists === false) |
168 |
{ |
169 |
$this->seek(0); |
170 |
} |
171 |
else |
172 |
{ |
173 |
$isOpened = false; |
174 |
|
175 |
if ($reportErrors === true) |
176 |
{ |
177 |
trigger_error('File exists', E_USER_WARNING); |
178 |
} |
179 |
} |
180 |
break; |
181 |
|
182 |
case 'a': |
183 |
$this->exists = true; |
184 |
|
185 |
if ($this->read === true) |
186 |
{ |
187 |
$this->seek(0); |
188 |
} |
189 |
else |
190 |
{ |
191 |
$this->seek(0, SEEK_END); |
192 |
$this->offset = $this->pointer; |
193 |
} |
194 |
|
195 |
$this->append = true; |
196 |
break; |
197 |
} |
198 |
} |
199 |
} |
200 |
|
201 |
$openedPath = null; |
202 |
|
203 |
if ($isOpened === true && ($options & STREAM_USE_PATH)) |
204 |
{ |
205 |
$openedPath = $this->getPath(); |
206 |
} |
207 |
|
208 |
return $isOpened; |
209 |
} |
210 |
} |
211 |
|
212 |
public function stream_seek($offset, $whence = SEEK_SET)80% |
213 |
{ |
214 |
if ($this->nextCallIsOverloaded(__FUNCTION__) === true) |
215 |
{ |
216 |
return $this->invoke(__FUNCTION__, func_get_args()); |
217 |
} |
218 |
else |
219 |
{ |
220 |
$this->addCall(__FUNCTION__, func_get_args()); |
221 |
|
222 |
return $this->seek($offset, $whence); |
223 |
} |
224 |
} |
225 |
|
226 |
public function stream_eof()83% |
227 |
{ |
228 |
if ($this->nextCallIsOverloaded(__FUNCTION__) === true) |
229 |
{ |
230 |
return $this->invoke(__FUNCTION__, func_get_args()); |
231 |
} |
232 |
else |
233 |
{ |
234 |
$this->addCall(__FUNCTION__, array()); |
235 | |
236 |
return $this->eof; |
237 |
} |
238 |
} |
239 |
|
240 |
public function stream_tell()80% |
241 |
{ |
242 |
if ($this->nextCallIsOverloaded(__FUNCTION__) === true) |
243 |
{ |
244 |
return $this->invoke(__FUNCTION__, array()); |
245 |
} |
246 |
else |
247 |
{ |
248 |
$this->addCall(__FUNCTION__, array()); |
249 |
|
250 |
return ($this->offset === null ? $this->pointer : $this->pointer - $this->offset); |
251 |
} |
252 |
} |
253 |
|
254 |
public function stream_read($count)92% |
255 |
{ |
256 |
if ($this->nextCallIsOverloaded(__FUNCTION__) === true) |
257 |
{ |
258 |
return $this->invoke(__FUNCTION__, func_get_args()); |
259 |
} |
260 |
else |
261 |
{ |
262 |
$this->addCall(__FUNCTION__, func_get_args()); |
263 |
|
264 |
$data = ''; |
265 |
|
266 |
$this->eof = ($this->pointer < 0 || $this->pointer >= $this->stat['size']); |
267 |
|
268 |
if ($this->read === true && $this->pointer >= 0 && $this->eof === false) |
269 |
{ |
270 |
$data = substr($this->contents, $this->pointer, $count) ?: ''; |
271 |
|
272 |
$this->movePointer(strlen($data) ?: $count); |
273 |
} |
274 |
|
275 |
return $data; |
276 |
} |
277 |
} |
278 |
|
279 |
public function stream_write($data)95% |
280 |
{ |
281 |
if ($this->nextCallIsOverloaded(__FUNCTION__) === true) |
282 |
{ |
283 |
return $this->invoke(__FUNCTION__, func_get_args()); |
284 |
} |
285 |
else |
286 |
{ |
287 |
$this->addCall(__FUNCTION__, func_get_args()); |
288 |
|
289 |
$bytesWrited = 0; |
290 |
|
291 |
if ($this->write === true) |
292 |
{ |
293 |
$contents = $this->getContents(); |
294 |
|
295 |
if ($this->append === true) |
296 |
{ |
297 |
if ($contents !== '') |
298 |
{ |
299 |
$contents .= PHP_EOL; |
300 |
$this->movePointer(1); |
301 |
} |
302 |
|
303 |
$this->append = false; |
304 |
} |
305 |
|
306 |
$this |
307 |
->setContents($contents . $data) |
308 |
->movePointer($bytesWrited = strlen($data)) |
309 |
; |
310 |
} |
311 |
|
312 |
return $bytesWrited; |
313 |
} |
314 |
} |
315 |
|
316 |
public function stream_flush()0% |
317 |
{ |
318 |
return true; |
319 |
} |
320 |
|
321 |
public function stream_metadata($path, $option, $value)69% |
322 |
{ |
323 |
if ($this->nextCallIsOverloaded(__FUNCTION__) === true) |
324 |
{ |
325 |
return $this->invoke(__FUNCTION__, func_get_args()); |
326 |
} |
327 |
else |
328 |
{ |
329 |
$this->addCall(__FUNCTION__, func_get_args()); |
330 |
|
331 |
switch ($option) |
332 |
{ |
333 |
case STREAM_META_TOUCH: |
334 |
case STREAM_META_OWNER_NAME: |
335 |
case STREAM_META_OWNER: |
336 |
case STREAM_META_GROUP_NAME: |
337 |
case STREAM_META_GROUP: |
338 |
return true; |
339 |
|
340 |
case STREAM_META_ACCESS: |
341 |
$this->setPermissions($value); |
342 |
return true; |
343 |
|
344 |
default: |
345 |
return false; |
346 |
} |
347 |
} |
348 |
} |
349 |
|
350 |
public function stream_truncate($newSize)80% |
351 |
{ |
352 |
if ($this->nextCallIsOverloaded(__FUNCTION__) === true) |
353 |
{ |
354 |
return $this->invoke(__FUNCTION__, func_get_args()); |
355 |
} |
356 |
else |
357 |
{ |
358 |
$this->addCall(__FUNCTION__, func_get_args()); |
359 |
|
360 |
return $this->truncate($newSize); |
361 |
} |
362 |
} |
363 |
|
364 |
public function stream_lock($mode)100% |
365 |
{ |
366 |
if ($this->nextCallIsOverloaded(__FUNCTION__) === true) |
367 |
{ |
368 |
return $this->invoke(__FUNCTION__, func_get_args()); |
369 |
} |
370 |
else |
371 |
{ |
372 |
$this->addCall(__FUNCTION__, func_get_args()); |
373 |
|
374 |
return true; |
375 |
} |
376 |
} |
377 |
|
378 |
public function stream_close()100% |
379 |
{ |
380 |
if ($this->nextCallIsOverloaded(__FUNCTION__) === true) |
381 |
{ |
382 |
return $this->invoke(__FUNCTION__, array()); |
383 |
} |
384 |
else |
385 |
{ |
386 |
$this->addCall(__FUNCTION__, array()); |
387 |
|
388 |
return true; |
389 |
} |
390 |
} |
391 |
|
392 |
public function unlink($path)89% |
393 |
{ |
394 |
if ($this->nextCallIsOverloaded(__FUNCTION__) === true) |
395 |
{ |
396 |
return $this->invoke(__FUNCTION__, func_get_args()); |
397 |
} |
398 |
else |
399 |
{ |
400 |
$this->addCall(__FUNCTION__, func_get_args()); |
401 |
|
402 |
if ($this->exists === false || $this->checkIfWritable() === false) |
403 |
{ |
404 |
return false; |
405 |
} |
406 |
else |
407 |
{ |
408 |
$this->exists = false; |
409 |
|
410 |
return true; |
411 |
} |
412 |
} |
413 |
} |
414 |
|
415 |
public function rename($from, $to)100% |
416 |
{ |
417 |
if ($this->nextCallIsOverloaded(__FUNCTION__) === true) |
418 |
{ |
419 |
return $this->invoke(__FUNCTION__, func_get_args()); |
420 |
} |
421 |
else |
422 |
{ |
423 |
$this->addCall(__FUNCTION__, func_get_args()); |
424 |
$this->setPath($to); |
425 |
|
426 |
return true; |
427 |
} |
428 |
} |
429 |
|
430 |
public function mkdir($path, $mode, $options)100% |
431 |
{ |
432 |
return false; |
433 |
} |
434 |
|
435 |
public function dir_opendir($path, $options)100% |
436 |
{ |
437 |
return false; |
438 |
} |
439 |
|
440 |
public function dir_readdir()100% |
441 |
{ |
442 |
return false; |
443 |
} |
444 |
|
445 |
public function dir_rewinddir()100% |
446 |
{ |
447 |
return false; |
448 |
} |
449 |
|
450 |
public function dir_closedir()100% |
451 |
{ |
452 |
return false; |
453 |
} |
454 |
|
455 |
public function rmdir($path, $options)100% |
456 |
{ |
457 |
return false; |
458 |
} |
459 |
|
460 |
protected function truncate($newSize)100% |
461 |
{ |
462 |
$this->setContents(str_pad(substr($this->contents, 0, $newSize), $newSize, "\0")); |
463 |
|
464 |
return true; |
465 |
} |
466 |
|
467 |
protected function seek($offset, $whence = SEEK_SET)67% |
468 |
{ |
469 |
switch ($whence) |
470 |
{ |
471 |
case SEEK_CUR: |
472 |
$offset = $this->pointer + $offset; |
473 |
break; |
474 |
|
475 |
case SEEK_END: |
476 |
$offset = strlen($this->getContents()) + $offset; |
477 |
} |
478 |
|
479 |
if ($this->offset !== null && $offset < $this->offset) |
480 |
{ |
481 |
$offset = $this->offset; |
482 |
} |
483 |
|
484 |
$this->setPointer($offset); |
485 |
|
486 |
return true; |
487 |
} |
488 |
|
489 |
protected function setOpenMode($mode)100% |
490 |
{ |
491 |
$this->read = false; |
492 |
$this->write = false; |
493 |
|
494 |
switch (str_replace(array('b', 't'), '', $mode)) |
495 |
{ |
496 |
case 'r': |
497 |
case 'x': |
498 |
$this->read = true; |
499 |
break; |
500 |
|
501 |
case 'w': |
502 |
case 'a': |
503 |
case 'c': |
504 |
$this->write = true; |
505 |
break; |
506 |
|
507 |
case 'r+': |
508 |
case 'x+': |
509 |
case 'w+': |
510 |
case 'a+': |
511 |
case 'c+': |
512 |
$this->read = $this->write = true; |
513 |
} |
514 |
|
515 |
return $this; |
516 |
} |
517 |
|
518 |
protected function setPointer($pointer)100% |
519 |
{ |
520 |
$this->pointer = $pointer; |
521 |
$this->eof = false; |
522 |
|
523 |
return $this; |
524 |
} |
525 |
|
526 |
protected function movePointer($offset)100% |
527 |
{ |
528 |
return $this->setPointer($this->pointer + $offset); |
529 |
} |
530 |
|
531 |
protected static function getRawOpenMode($mode)100% |
532 |
{ |
533 |
return str_replace(array('b', 't', '+'), '', $mode); |
534 |
} |
535 |
|
536 |
protected static function checkOpenMode($mode)100% |
537 |
{ |
538 |
switch (self::getRawOpenMode($mode)) |
539 |
{ |
540 |
case 'r': |
541 |
case 'w': |
542 |
case 'a': |
543 |
case 'x': |
544 |
case 'c': |
545 |
return true; |
546 |
|
547 |
default: |
548 |
return false; |
549 |
} |
550 |
} |
551 |
} |