1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10:
11:
12: namespace Nette\Config\Adapters;
13:
14: use Nette,
15: Nette\Config\Helpers;
16:
17:
18:
19: 20: 21: 22: 23:
24: class IniAdapter extends Nette\Object implements Nette\Config\IAdapter
25: {
26:
27: const INHERITING_SEPARATOR = '<',
28: KEY_SEPARATOR = '.',
29: ESCAPED_KEY_SEPARATOR = '..',
30: RAW_SECTION = '!';
31:
32:
33: 34: 35: 36: 37: 38:
39: public function load($file)
40: {
41: set_error_handler(function($severity, $message) {
42: restore_error_handler();
43: throw new Nette\InvalidStateException("parse_ini_file(): $message");
44: });
45: $ini = parse_ini_file($file, TRUE);
46: restore_error_handler();
47:
48: $data = array();
49: foreach ($ini as $secName => $secData) {
50: if (is_array($secData)) {
51: if (substr($secName, -1) === self::RAW_SECTION) {
52: $secName = substr($secName, 0, -1);
53: } else {
54: $tmp = array();
55: foreach ($secData as $key => $val) {
56: $cursor = & $tmp;
57: $key = str_replace(self::ESCAPED_KEY_SEPARATOR, "\xFF", $key);
58: foreach (explode(self::KEY_SEPARATOR, $key) as $part) {
59: $part = str_replace("\xFF", self::KEY_SEPARATOR, $part);
60: if (!isset($cursor[$part]) || is_array($cursor[$part])) {
61: $cursor = & $cursor[$part];
62: } else {
63: throw new Nette\InvalidStateException("Invalid key '$key' in section [$secName] in file '$file'.");
64: }
65: }
66: $cursor = $val;
67: }
68: $secData = $tmp;
69: }
70:
71: $parts = explode(self::INHERITING_SEPARATOR, $secName);
72: if (count($parts) > 1) {
73: $secName = trim($parts[0]);
74: $secData[Helpers::EXTENDS_KEY] = trim($parts[1]);
75: }
76: }
77:
78: $cursor = & $data;
79: foreach (explode(self::KEY_SEPARATOR, $secName) as $part) {
80: if (!isset($cursor[$part]) || is_array($cursor[$part])) {
81: $cursor = & $cursor[$part];
82: } else {
83: throw new Nette\InvalidStateException("Invalid section [$secName] in file '$file'.");
84: }
85: }
86:
87: if (is_array($secData) && is_array($cursor)) {
88: $secData = Helpers::merge($secData, $cursor);
89: }
90:
91: $cursor = $secData;
92: }
93:
94: return $data;
95: }
96:
97:
98:
99: 100: 101: 102: 103:
104: public function dump(array $data)
105: {
106: $output = array();
107: foreach ($data as $name => $secData) {
108: if (!is_array($secData)) {
109: $output = array();
110: self::build($data, $output, '');
111: break;
112: }
113: if ($parent = Helpers::takeParent($secData)) {
114: $output[] = "[$name " . self::INHERITING_SEPARATOR . " $parent]";
115: } else {
116: $output[] = "[$name]";
117: }
118: self::build($secData, $output, '');
119: $output[] = '';
120: }
121: return "; generated by Nette\n\n" . implode(PHP_EOL, $output);
122: }
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("The '$prefix$key' item must be scalar or array, " . gettype($val) ." given.");
148: }
149: }
150: }
151:
152: }
153: