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