File   A
last analyzed

Complexity

Total Complexity 19

Size/Duplication

Total Lines 79
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Test Coverage

Coverage 93.02%

Importance

Changes 0
Metric Value
dl 0
loc 79
ccs 40
cts 43
cp 0.9302
rs 10
c 0
b 0
f 0
wmc 19
lcom 1
cbo 1

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 12 5
A isPathUnderDocRoot() 0 3 2
A initFileHandler() 0 10 3
A getKeysData() 0 3 2
A saveKeysData() 0 4 2
A closeFileHandler() 0 7 2
A pop() 0 6 1
A push() 0 5 1
A __destruct() 0 3 1
1
<?php
2
3
namespace PhpConsole\Storage;
4
5
/**
6
 * File storage for postponed response data. Use it if session handler in your project is overridden.
7
 *
8
 * @package PhpConsole
9
 * @version 3.1
10
 * @link http://consle.com
11
 * @author Sergey Barbushin http://linkedin.com/in/barbushin
12
 * @copyright © Sergey Barbushin, 2011-2013. All rights reserved.
13
 * @license http://www.opensource.org/licenses/BSD-3-Clause "The BSD 3-Clause License"
14
 */
15
class File extends AllKeysList {
16
17
	protected $filePath;
18
	protected $fileHandler;
19
20
	/**
21
	 * @param string $filePath Writable path for postponed data storage (should not be under DOCUMENT_ROOT)
22
	 * @param bool $validatePathNotUnderDocRoot Throw \Exception if $filePath is not under DOCUMENT_ROOT
23
	 * @throws \Exception
24
	 */
25 5
	public function __construct($filePath, $validatePathNotUnderDocRoot = true) {
26 5
		if(!file_exists($filePath)) {
27 5
			if(file_put_contents($filePath, '') === false) {
28
				throw new \Exception('Unable to write file ' . $filePath);
29
			}
30
		}
31 5
		$this->filePath = realpath($filePath);
32
33 5
		if($validatePathNotUnderDocRoot && $this->isPathUnderDocRoot()) {
34 1
			throw new \Exception('Path ' . $this->filePath . ' is under DOCUMENT_ROOT. It\'s insecure!');
35
		}
36 5
	}
37
38 2
	protected function isPathUnderDocRoot() {
39 2
		return !empty($_SERVER['DOCUMENT_ROOT']) && strpos($this->filePath, $_SERVER['DOCUMENT_ROOT']) === 0;
40
	}
41
42 3
	protected function initFileHandler() {
43 3
		$this->fileHandler = fopen($this->filePath, 'a+b');
44 3
		if(!$this->fileHandler) {
45
			throw new \Exception('Unable to read/write file ' . $this->filePath);
46
		}
47 3
		while(!flock($this->fileHandler, LOCK_EX | LOCK_NB)) {
48
			usleep(10000);
49
		}
50 3
		fseek($this->fileHandler, 0);
51 3
	}
52
53
	/**
54
	 * @throws \Exception
55
	 * @return array
56
	 */
57 3
	protected function getKeysData() {
58 3
		return json_decode(fgets($this->fileHandler), true) ? : array();
59
	}
60
61
	/**
62
	 * @param array $keysData
63
	 */
64 3
	protected function saveKeysData(array $keysData) {
65 3
		ftruncate($this->fileHandler, 0);
66 3
		fwrite($this->fileHandler, json_encode($keysData, defined('JSON_UNESCAPED_UNICODE') ? JSON_UNESCAPED_UNICODE : null));
67 3
	}
68
69 4
	protected function closeFileHandler() {
70 4
		if($this->fileHandler) {
71 3
			flock($this->fileHandler, LOCK_UN);
72 3
			fclose($this->fileHandler);
73 3
			$this->fileHandler = null;
74
		}
75 4
	}
76
77 3
	public function pop($key) {
78 3
		$this->initFileHandler();
79 3
		$result = parent::pop($key);
80 3
		$this->closeFileHandler();
81 3
		return $result;
82
	}
83
84 3
	public function push($key, $data) {
85 3
		$this->initFileHandler();
86 3
		parent::push($key, $data);
87 3
		$this->closeFileHandler();
88 3
	}
89
90 1
	public function __destruct() {
91 1
		$this->closeFileHandler();
92 1
	}
93
}
94