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