1: <?php
2:
3: 4: 5: 6:
7:
8: namespace Nette\DI\Config\Adapters;
9:
10: use Nette,
11: Nette\DI\Config\Helpers,
12: Nette\DI\Statement,
13: Nette\Neon;
14:
15:
16: 17: 18: 19: 20:
21: class NeonAdapter extends Nette\Object implements Nette\DI\Config\IAdapter
22: {
23:
24: const INHERITING_SEPARATOR = '<',
25: PREVENT_MERGING = '!';
26:
27: 28: 29: 30: 31:
32: public function load($file)
33: {
34: return $this->process((array) Neon\Neon::decode(file_get_contents($file)));
35: }
36:
37:
38: private function process(array $arr)
39: {
40: $res = array();
41: foreach ($arr as $key => $val) {
42: if (substr($key, -1) === self::PREVENT_MERGING) {
43: if (!is_array($val) && $val !== NULL) {
44: throw new Nette\InvalidStateException("Replacing operator is available only for arrays, item '$key' is not array.");
45: }
46: $key = substr($key, 0, -1);
47: $val[Helpers::EXTENDS_KEY] = Helpers::OVERWRITE;
48:
49: } elseif (preg_match('#^(\S+)\s+' . self::INHERITING_SEPARATOR . '\s+(\S+)\z#', $key, $matches)) {
50: if (!is_array($val) && $val !== NULL) {
51: throw new Nette\InvalidStateException("Inheritance operator is available only for arrays, item '$key' is not array.");
52: }
53: list(, $key, $val[Helpers::EXTENDS_KEY]) = $matches;
54: if (isset($res[$key])) {
55: throw new Nette\InvalidStateException("Duplicated key '$key'.");
56: }
57: }
58:
59: if (is_array($val)) {
60: $val = $this->process($val);
61:
62: } elseif ($val instanceof Neon\Entity) {
63: if ($val->value === Neon\Neon::CHAIN) {
64: $tmp = NULL;
65: foreach ($this->process($val->attributes) as $st) {
66: $tmp = new Statement(
67: $tmp === NULL ? $st->getEntity() : array($tmp, ltrim($st->getEntity(), ':')),
68: $st->arguments
69: );
70: }
71: $val = $tmp;
72: } else {
73: $tmp = $this->process(array($val->value));
74: $val = new Statement($tmp[0], $this->process($val->attributes));
75: }
76: }
77: $res[$key] = $val;
78: }
79: return $res;
80: }
81:
82:
83: 84: 85: 86:
87: public function dump(array $data)
88: {
89: $tmp = array();
90: foreach ($data as $name => $secData) {
91: if ($parent = Helpers::takeParent($secData)) {
92: $name .= ' ' . self::INHERITING_SEPARATOR . ' ' . $parent;
93: }
94: $tmp[$name] = $secData;
95: }
96: return "# generated by Nette\n\n" . Neon\Neon::encode($tmp, Neon\Neon::BLOCK);
97: }
98:
99: }
100: