forked from acquia/blt
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathFileStore.php
158 lines (142 loc) · 3.54 KB
/
FileStore.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
<?php
namespace Acquia\Blt\Robo\Datastore;
/**
* Class FileStore.
*/
class FileStore implements DataStoreInterface {
/**
* @var stringThedirectorytostorethedatafilesin
*/
protected $directory;
/**
*
*/
public function __construct($directory) {
$this->directory = $directory;
}
/**
* Reads retrieves data from the store.
*
* @param string $key
* A key.
*
* @return mixed The value fpr the given key or null.
*/
public function get($key) {
$out = NULL;
// Read the json encoded value from disk if it exists.
$path = $this->getFileName($key);
if (file_exists($path)) {
$out = file_get_contents($path);
$out = json_decode($out, TRUE);
}
return $out;
}
/**
* Saves a value with the given key.
*
* @param string $key
* A key.
* @param mixed $data
* Data to save to the store.
*/
public function set($key, $data) {
$path = $this->getFileName($key, TRUE);
file_put_contents($path, json_encode($data));
}
/**
* Checks if a key is in the store.
*
* @param string $key
* A key.
*
* @return bool Whether a value exists with the given key.
*/
public function has($key) {
$path = $this->getFileName($key);
return file_exists($path);
}
/**
* Remove value from the store.
*
* @param string $key
* A key.
*/
public function remove($key) {
$path = $this->getFileName($key, TRUE);
if (file_exists($path)) {
unlink($path);
}
}
/**
* Remove all values from the store.
*/
public function removeAll() {
foreach ($this->keys() as $key) {
$this->remove($key);
}
}
/**
* Return a list of all keys in the store.
*
* @return array A list of keys
*/
public function keys() {
$root = $this->directory;
if (file_exists($root) && is_readable($root)) {
return array_diff(scandir($root), array('..', '.'));
}
return [];
}
/**
* Get a valid file name for the given key.
*
* @param string $key
* The data key to be written or read.
*
* @return string A file path
*
* @throws \Exception
*/
protected function getFileName($key, $writable = FALSE) {
$key = $this->cleanKey($key);
if ($writable) {
$this->ensureDirectoryWritable();
}
if (!$key) {
throw new BltException('Could not save data to a file because it is missing an ID');
}
return $this->directory . '/' . $key;
}
/**
* Make the file path safe by whitelisting characters.
*
* This is a very naive approach to hashing but in practice this doesn't
* matter since this is only used for a few already safe keys.
*
* @param $key
*
* @return mixed
*/
protected function cleanKey($key) {
return preg_replace('/[^a-zA-Z0-9\-\_\@\.]/', '-', $key);
}
/**
* Check that the directory is writable and create it if we can.
*/
protected function ensureDirectoryWritable() {
// Reality check to prevent stomping on the local filesystem if there is
// something wrong with the config.
if (!$this->directory) {
throw new BltException('Could not save data to a file because the path setting is mis-configured.');
}
$writable = is_dir($this->directory) || (!file_exists($this->directory) && @mkdir($this->directory, 0777, TRUE));
$writable = $writable && is_writable($this->directory);
if (!$writable) {
throw new BltException(
'Could not save data to a file because the path {path} cannot be written to.',
['path' => $this->directory]
);
}
}
}