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 extends Nette\Object implements Nette\DI\Config\IAdapter
20: {
21:
22: const INHERITING_SEPARATOR = '<',
23: PREVENT_MERGING = '!';
24:
25: 26: 27: 28: 29:
30: public function load($file)
31: {
32: return $this->process((array) Neon\Neon::decode(file_get_contents($file)));
33: }
34:
35:
36: private function process(array $arr)
37: {
38: $res = array();
39: foreach ($arr as $key => $val) {
40: if (substr($key, -1) === self::PREVENT_MERGING) {
41: if (!is_array($val) && $val !== NULL) {
42: throw new Nette\InvalidStateException("Replacing operator is available only for arrays, item '$key' is not array.");
43: }
44: $key = substr($key, 0, -1);
45: $val[Helpers::EXTENDS_KEY] = Helpers::OVERWRITE;
46:
47: } elseif (preg_match('#^(\S+)\s+' . self::INHERITING_SEPARATOR . '\s+(\S+)\z#', $key, $matches)) {
48: if (!is_array($val) && $val !== NULL) {
49: throw new Nette\InvalidStateException("Inheritance operator is available only for arrays, item '$key' is not array.");
50: }
51: list(, $key, $val[Helpers::EXTENDS_KEY]) = $matches;
52: if (isset($res[$key])) {
53: throw new Nette\InvalidStateException("Duplicated key '$key'.");
54: }
55: }
56:
57: if (is_array($val)) {
58: $val = $this->process($val);
59:
60: } elseif ($val instanceof Neon\Entity) {
61: if ($val->value === Neon\Neon::CHAIN) {
62: $tmp = NULL;
63: foreach ($this->process($val->attributes) as $st) {
64: $tmp = new Statement(
65: $tmp === NULL ? $st->getEntity() : array($tmp, ltrim($st->getEntity(), ':')),
66: $st->arguments
67: );
68: }
69: $val = $tmp;
70: } else {
71: $tmp = $this->process(array($val->value));
72: $val = new Statement($tmp[0], $this->process($val->attributes));
73: }
74: }
75: $res[$key] = $val;
76: }
77: return $res;
78: }
79:
80:
81: 82: 83: 84:
85: public function dump(array $data)
86: {
87: $tmp = array();
88: foreach ($data as $name => $secData) {
89: if ($parent = Helpers::takeParent($secData)) {
90: $name .= ' ' . self::INHERITING_SEPARATOR . ' ' . $parent;
91: }
92: $tmp[$name] = $secData;
93: }
94: array_walk_recursive(
95: $tmp,
96: function (& $val) {
97: if ($val instanceof Statement) {
98: $val = NeonAdapter::statementToEntity($val);
99: }
100: }
101: );
102:
103: return "# generated by Nette\n\n" . Neon\Neon::encode($tmp, Neon\Neon::BLOCK);
104: }
105:
106:
107: 108: 109: 110:
111: public static function statementToEntity(Statement $val)
112: {
113: array_walk_recursive(
114: $val->arguments,
115: function (& $val) {
116: if ($val instanceof Statement) {
117: $val = NeonAdapter::statementToEntity($val);
118: }
119: }
120: );
121: if (is_array($val->entity) && $val->entity[0] instanceof Statement) {
122: return new Neon\Entity(
123: Neon\Neon::CHAIN,
124: array(
125: self::statementToEntity($val->entity[0]),
126: new Neon\Entity('::' . $val->entity[1], $val->arguments)
127: )
128: );
129: } else {
130: return new Neon\Entity($val->entity, $val->arguments);
131: }
132: }
133:
134: }
135: