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