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