1: <?php
2:
3: namespace PHPixie\Config\Storages\Type;
4:
5: class Directory extends \PHPixie\Slice\Data\Implementation
6: implements \PHPixie\Config\Storages\Storage\Editable\Persistable
7: {
8: protected $storages;
9: protected $directory;
10: protected $name;
11: protected $defaultFormat;
12:
13: protected $storage;
14: protected $subdirs;
15:
16: public function __construct($storages, $sliceBuilder, $directory, $name, $defaultFormat = 'php')
17: {
18: $this->storages = $storages;
19: $this->directory = $directory;
20: $this->name = $name;
21: $this->defaultFormat = $defaultFormat;
22:
23: parent::__construct($sliceBuilder);
24: }
25:
26: public function getData($key = null, $isRequired = false, $default = null)
27: {
28: $this->requireSubdirs();
29:
30: if (!empty($key)) {
31: list($storage, $key) = $this->getStorageAndKey($key);
32:
33: return $storage->getData($key, $isRequired, $default);
34: }
35:
36: $data = $this->storage()->get();
37: foreach ($this->subdirs as $name => $subdir) {
38: $subdata = $subdir->get();
39: if (!empty($subdata)) {
40: $data[$name] = $subdata;
41: }
42: }
43:
44: if (empty($data)) {
45: if (!$isRequired)
46: return $default;
47:
48: throw new \PHPixie\Config\Exception("Configuration for {$key} not set.");
49: }
50:
51: return $data;
52: }
53:
54: public function keys($key = null, $isRequired = false)
55: {
56: $this->requireSubdirs();
57: if (!empty($key)) {
58: list($storage, $key) = $this->getStorageAndKey($key);
59:
60: return $storage->keys($key, $isRequired);
61: }
62:
63: $keys = array_fill_keys($this->storage()->keys(), true);
64:
65: foreach($this->subdirs as $name => $subdir) {
66: $keys[$name]=true;
67: }
68:
69: return array_keys($keys);
70: }
71:
72: public function slice($path = null)
73: {
74: return $this->sliceBuilder->editableSlice($this, $path);
75: }
76:
77: public function arraySlice($path = null)
78: {
79: $data = $this->get($path);
80: return $this->sliceBuilder->arraySlice($data, $path);
81: }
82:
83: public function getIterator()
84: {
85: return $this->sliceBuilder->iterator($this);
86: }
87:
88: protected function getStorageAndKey($key)
89: {
90: list($current, $subkey) = $this->splitKey($key);
91:
92: if (array_key_exists($current, $this->subdirs)) {
93: $storage = $this->subdirs[$current];
94: $key = $subkey;
95: }else {
96: $storage = $this->storage();
97: }
98:
99: return array($storage, $key);
100: }
101:
102: public function set($key, $value)
103: {
104: $this->requireSubdirs();
105: if (!empty($key)) {
106: list($current, $subkey) = $this->splitKey($key);
107: if (array_key_exists($current, $this->subdirs)) {
108: return $this->subdirs[$current]->set($subkey, $value);
109: }
110: } elseif (is_array($value)) {
111: foreach ($this->subdirs as $name => $subdir) {
112: if (array_key_exists($name, $value)) {
113: $subdir->set(null, $value[$name]);
114: unset($value[$name]);
115: }else
116: $subdir->remove(null);
117: }
118: }
119:
120: return $this->storage()->set($key, $value);
121: }
122:
123: public function remove($key = null)
124: {
125: $this->requireSubdirs();
126: if (empty($key)) {
127: $data = $this->storage()->remove(null);
128: foreach ($this->subdirs as $name => $subdir) {
129: $subdir->remove(null);
130: }
131:
132: return;
133: }
134:
135: list($current, $subkey) = $this->splitKey($key);
136: if (array_key_exists($current, $this->subdirs)) {
137: return $this->subdirs[$current]->remove($subkey);
138: }
139:
140: return $this->storage()->remove($key);
141: }
142:
143: public function persist($removeFilesIfEmpty = false)
144: {
145: $this->requireSubdirs();
146: foreach($this->subdirs as $subdir) {
147: $subdir->persist($removeFilesIfEmpty);
148: }
149:
150: $this->storage()->persist($removeFilesIfEmpty);
151: }
152:
153: protected function splitKey($key)
154: {
155: $splitKey = explode('.', $key, 2);
156: if (!array_key_exists(1, $splitKey)) {
157: $splitKey[1] = null;
158: }
159: return $splitKey;
160: }
161:
162: protected function requireSubdirs()
163: {
164: if (is_array($this->subdirs))
165: return;
166:
167: $this->subdirs = array();
168: $dirs = array();
169: $directory = $this->directory.'/'.$this->name.'/';
170: if (is_dir($directory)) {
171: foreach (scandir($directory) as $file) {
172: if ($file === '.' || $file === '..')
173: continue;
174:
175: $filePath = $directory.'/'.$file;
176: if (is_dir($filePath)) {
177: $dirs[] = $file;
178: continue;
179: }
180:
181: $fileInfo = pathinfo($filePath);
182: $fileName = $fileInfo['filename'];
183:
184: if (array_key_exists($fileName,$this->subdirs)) {
185: throw new \PHPixie\Config\Exception("More than one file for {$fileName} in {$directory}.");
186: }
187:
188: $this->subdirs[$fileName] = $this->storages->directory(
189: $directory,
190: $fileName,
191: $fileInfo['extension']
192: );
193: }
194:
195: foreach ($dirs as $dir) {
196: if (!array_key_exists($dir, $this->subdirs))
197: $this->subdirs[$dir] = $this->storages->directory(
198: $directory,
199: $dir,
200: $this->defaultFormat
201: );
202: }
203: }
204:
205: }
206:
207: protected function storage()
208: {
209: if ($this->storage === null) {
210: $file = $this->directory.'/'.$this->name.'.'.$this->defaultFormat;
211: $this->storage = $this->storages->file($file);
212: }
213:
214: return $this->storage;
215: }
216:
217: }
218: