1: <?php
2:
3: 4: 5: 6:
7:
8: namespace Nette\DI\Config\Adapters;
9:
10: use Nette;
11: use Nette\DI\Config\Helpers;
12: use Nette\DI\Statement;
13: use Nette\Neon;
14:
15:
16: 17: 18:
19: class NeonAdapter implements Nette\DI\Config\IAdapter
20: {
21: use Nette\SmartObject;
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: 39: 40: 41:
42: public function process(array $arr)
43: {
44: $res = [];
45: foreach ($arr as $key => $val) {
46: if (is_string($key) && substr($key, -1) === self::PREVENT_MERGING) {
47: if (!is_array($val) && $val !== NULL) {
48: throw new Nette\InvalidStateException("Replacing operator is available only for arrays, item '$key' is not array.");
49: }
50: $key = substr($key, 0, -1);
51: $val[Helpers::EXTENDS_KEY] = Helpers::OVERWRITE;
52:
53: } elseif (is_string($key) && preg_match('#^(\S+)\s+' . self::INHERITING_SEPARATOR . '\s+(\S+)\z#', $key, $matches)) {
54: if (!is_array($val) && $val !== NULL) {
55: throw new Nette\InvalidStateException("Inheritance operator is available only for arrays, item '$key' is not array.");
56: }
57: list(, $key, $val[Helpers::EXTENDS_KEY]) = $matches;
58: if (isset($res[$key])) {
59: throw new Nette\InvalidStateException("Duplicated key '$key'.");
60: }
61: }
62:
63: if (is_array($val)) {
64: $val = $this->process($val);
65:
66: } elseif ($val instanceof Neon\Entity) {
67: if ($val->value === Neon\Neon::CHAIN) {
68: $tmp = NULL;
69: foreach ($this->process($val->attributes) as $st) {
70: $tmp = new Statement(
71: $tmp === NULL ? $st->getEntity() : [$tmp, ltrim($st->getEntity(), ':')],
72: $st->arguments
73: );
74: }
75: $val = $tmp;
76: } else {
77: $tmp = $this->process([$val->value]);
78: $val = new Statement($tmp[0], $this->process($val->attributes));
79: }
80: }
81: $res[$key] = $val;
82: }
83: return $res;
84: }
85:
86:
87: 88: 89: 90:
91: public function dump(array $data)
92: {
93: $tmp = [];
94: foreach ($data as $name => $secData) {
95: if ($parent = Helpers::takeParent($secData)) {
96: $name .= ' ' . self::INHERITING_SEPARATOR . ' ' . $parent;
97: }
98: $tmp[$name] = $secData;
99: }
100: array_walk_recursive(
101: $tmp,
102: function (&$val) {
103: if ($val instanceof Statement) {
104: $val = self::statementToEntity($val);
105: }
106: }
107: );
108:
109: return "# generated by Nette\n\n" . Neon\Neon::encode($tmp, Neon\Neon::BLOCK);
110: }
111:
112:
113: 114: 115:
116: private static function statementToEntity(Statement $val)
117: {
118: array_walk_recursive(
119: $val->arguments,
120: function (&$val) {
121: if ($val instanceof Statement) {
122: $val = self::statementToEntity($val);
123: }
124: }
125: );
126: if (is_array($val->getEntity()) && $val->getEntity()[0] instanceof Statement) {
127: return new Neon\Entity(
128: Neon\Neon::CHAIN,
129: [
130: self::statementToEntity($val->getEntity()[0]),
131: new Neon\Entity('::' . $val->getEntity()[1], $val->arguments)
132: ]
133: );
134: } else {
135: return new Neon\Entity($val->getEntity(), $val->arguments);
136: }
137: }
138:
139: }
140: