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:
13:
14: 15: 16:
17: class IniAdapter implements Nette\DI\Config\IAdapter
18: {
19: use Nette\SmartObject;
20:
21:
22: const INHERITING_SEPARATOR = '<',
23: KEY_SEPARATOR = '.',
24: ESCAPED_KEY_SEPARATOR = '..',
25: RAW_SECTION = '!';
26:
27:
28: 29: 30: 31: 32: 33:
34: public function load($file)
35: {
36: $ini = @parse_ini_file($file, true);
37: if ($ini === false) {
38: $error = error_get_last();
39: throw new Nette\InvalidStateException("parse_ini_file(): $error[message]");
40: }
41: return $this->process($ini);
42: }
43:
44:
45: 46: 47: 48:
49: public function process(array $arr)
50: {
51: $data = [];
52: foreach ($arr as $secName => $secData) {
53: if (is_array($secData)) {
54: if (substr($secName, -1) === self::RAW_SECTION) {
55: $secName = substr($secName, 0, -1);
56: } else {
57: $tmp = [];
58: foreach ($secData as $key => $val) {
59: $cursor = &$tmp;
60: $key = str_replace(self::ESCAPED_KEY_SEPARATOR, "\xFF", $key);
61: foreach (explode(self::KEY_SEPARATOR, $key) as $part) {
62: $part = str_replace("\xFF", self::KEY_SEPARATOR, $part);
63: if (!isset($cursor[$part]) || is_array($cursor[$part])) {
64: $cursor = &$cursor[$part];
65: } else {
66: throw new Nette\InvalidStateException("Invalid key '$key' in section [$secName].");
67: }
68: }
69: $cursor = $val;
70: }
71: $secData = $tmp;
72: }
73:
74: $parts = explode(self::INHERITING_SEPARATOR, $secName);
75: if (count($parts) > 1) {
76: $secName = trim($parts[0]);
77: $secData[Helpers::EXTENDS_KEY] = trim($parts[1]);
78: }
79: }
80:
81: $cursor = &$data;
82: foreach (explode(self::KEY_SEPARATOR, $secName) as $part) {
83: if (!isset($cursor[$part]) || is_array($cursor[$part])) {
84: $cursor = &$cursor[$part];
85: } else {
86: throw new Nette\InvalidStateException("Invalid section [$secName].");
87: }
88: }
89:
90: if (is_array($secData) && is_array($cursor)) {
91: $secData = Helpers::merge($secData, $cursor);
92: }
93:
94: $cursor = $secData;
95: }
96:
97: return $data;
98: }
99:
100:
101: 102: 103: 104:
105: public function dump(array $data)
106: {
107: $output = [];
108: foreach ($data as $name => $secData) {
109: if (!is_array($secData)) {
110: $output = [];
111: self::build($data, $output, '');
112: break;
113: }
114: if ($parent = Helpers::takeParent($secData)) {
115: $output[] = "[$name " . self::INHERITING_SEPARATOR . " $parent]";
116: } else {
117: $output[] = "[$name]";
118: }
119: self::build($secData, $output, '');
120: $output[] = '';
121: }
122: return "; generated by Nette\n\n" . implode(PHP_EOL, $output);
123: }
124:
125:
126: 127: 128: 129:
130: private static function build($input, &$output, $prefix)
131: {
132: foreach ($input as $key => $val) {
133: $key = str_replace(self::KEY_SEPARATOR, self::ESCAPED_KEY_SEPARATOR, $key);
134: if (is_array($val)) {
135: self::build($val, $output, $prefix . $key . self::KEY_SEPARATOR);
136:
137: } elseif (is_bool($val)) {
138: $output[] = "$prefix$key = " . ($val ? 'true' : 'false');
139:
140: } elseif (is_numeric($val)) {
141: $output[] = "$prefix$key = $val";
142:
143: } elseif (is_string($val)) {
144: $output[] = "$prefix$key = \"$val\"";
145:
146: } else {
147: throw new Nette\InvalidArgumentException(sprintf("The '%s' item must be scalar or array, %s given.", $prefix . $key, gettype($val)));
148: }
149: }
150: }
151: }
152: