1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11:
12:
13:
14:
15: 16: 17: 18: 19: 20: 21: 22:
23: class ConfigLoader extends Object
24: {
25:
26: const INCLUDES_KEY = 'includes';
27:
28: private $adapters = array(
29: 'php' => 'ConfigPhpAdapter',
30: 'ini' => 'ConfigIniAdapter',
31: 'neon' => 'ConfigNeonAdapter',
32: );
33:
34: private $dependencies = array();
35:
36:
37: 38: 39: 40: 41: 42:
43: public function load($file, $section = NULL)
44: {
45: if (!is_file($file) || !is_readable($file)) {
46: throw new FileNotFoundException("File '$file' is missing or is not readable.");
47: }
48: $this->dependencies[] = $file = realpath($file);
49: $data = $this->getAdapter($file)->load($file);
50:
51: if ($section) {
52: if (isset($data[self::INCLUDES_KEY])) {
53: throw new InvalidStateException("Section 'includes' must be placed under some top section in file '$file'.");
54: }
55: $data = $this->getSection($data, $section, $file);
56: }
57:
58:
59: $merged = array();
60: if (isset($data[self::INCLUDES_KEY])) {
61: Validators::assert($data[self::INCLUDES_KEY], 'list', "section 'includes' in file '$file'");
62: foreach ($data[self::INCLUDES_KEY] as $include) {
63: $merged = ConfigHelpers::merge($this->load(dirname($file) . '/' . $include), $merged);
64: }
65: }
66: unset($data[self::INCLUDES_KEY]);
67:
68: return ConfigHelpers::merge($data, $merged);
69: }
70:
71:
72: 73: 74: 75: 76: 77:
78: public function save($data, $file)
79: {
80: if (file_put_contents($file, $this->getAdapter($file)->dump($data)) === FALSE) {
81: throw new IOException("Cannot write file '$file'.");
82: }
83: }
84:
85:
86: 87: 88: 89:
90: public function getDependencies()
91: {
92: return array_unique($this->dependencies);
93: }
94:
95:
96: 97: 98: 99: 100: 101:
102: public function addAdapter($extension, $adapter)
103: {
104: $this->adapters[strtolower($extension)] = $adapter;
105: return $this;
106: }
107:
108:
109:
110: private function getAdapter($file)
111: {
112: $extension = strtolower(pathinfo($file, PATHINFO_EXTENSION));
113: if (!isset($this->adapters[$extension])) {
114: throw new InvalidArgumentException("Unknown file extension '$file'.");
115: }
116: return is_object($this->adapters[$extension]) ? $this->adapters[$extension] : new $this->adapters[$extension];
117: }
118:
119:
120: private function getSection(array $data, $key, $file)
121: {
122: Validators::assertField($data, $key, 'array|null', "section '%' in file '$file'");
123: $item = $data[$key];
124: if ($parent = ConfigHelpers::takeParent($item)) {
125: $item = ConfigHelpers::merge($item, $this->getSection($data, $parent, $file));
126: }
127: return $item;
128: }
129:
130: }
131: