1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10:
11:
12: namespace Nette\Config;
13:
14: use Nette;
15:
16:
17:
18: 19: 20: 21: 22:
23: final class IniAdapter implements IAdapter
24: {
25:
26:
27: public static $keySeparator = '.';
28:
29:
30: public static $sectionSeparator = ' < ';
31:
32:
33: public static $rawSection = '!';
34:
35:
36:
37: 38: 39:
40: final public function __construct()
41: {
42: throw new Nette\StaticClassException;
43: }
44:
45:
46:
47: 48: 49: 50: 51: 52:
53: public static function load($file)
54: {
55: if (!is_file($file) || !is_readable($file)) {
56: throw new Nette\FileNotFoundException("File '$file' is missing or is not readable.");
57: }
58:
59: Nette\Diagnostics\Debugger::tryError();
60: $ini = parse_ini_file($file, TRUE);
61: if (Nette\Diagnostics\Debugger::catchError($e)) {
62: throw new Nette\InvalidStateException('parse_ini_file(): ' . $e->getMessage(), 0, $e);
63: }
64:
65: $separator = trim(self::$sectionSeparator);
66: $data = array();
67: foreach ($ini as $secName => $secData) {
68:
69: if (is_array($secData)) {
70: if (substr($secName, -1) === self::$rawSection) {
71: $secName = substr($secName, 0, -1);
72:
73: } elseif (self::$keySeparator) {
74:
75: $tmp = array();
76: foreach ($secData as $key => $val) {
77: $cursor = & $tmp;
78: foreach (explode(self::$keySeparator, $key) as $part) {
79: if (!isset($cursor[$part]) || is_array($cursor[$part])) {
80: $cursor = & $cursor[$part];
81: } else {
82: throw new Nette\InvalidStateException("Invalid key '$key' in section [$secName] in file '$file'.");
83: }
84: }
85: $cursor = $val;
86: }
87: $secData = $tmp;
88: }
89:
90:
91: $parts = $separator ? explode($separator, strtr($secName, ':', $separator)) : array($secName);
92: if (count($parts) > 1) {
93: $parent = trim($parts[1]);
94: if (!isset($data[$parent]) || !is_array($data[$parent])) {
95: throw new Nette\InvalidStateException("Missing parent section [$parent] in file '$file'.");
96: }
97: $secData = array_reverse(Nette\Utils\Arrays::mergeTree(array_reverse($secData, TRUE), array_reverse($data[$parent], TRUE)), TRUE);
98: $secName = trim($parts[0]);
99: if ($secName === '') {
100: throw new Nette\InvalidStateException("Invalid empty section name in file '$file'.");
101: }
102: }
103: }
104:
105: if (self::$keySeparator) {
106: $cursor = & $data;
107: foreach (explode(self::$keySeparator, $secName) as $part) {
108: if (!isset($cursor[$part]) || is_array($cursor[$part])) {
109: $cursor = & $cursor[$part];
110: } else {
111: throw new Nette\InvalidStateException("Invalid section [$secName] in file '$file'.");
112: }
113: }
114: } else {
115: $cursor = & $data[$secName];
116: }
117:
118: if (is_array($secData) && is_array($cursor)) {
119: $secData = Nette\Utils\Arrays::mergeTree($secData, $cursor);
120: }
121:
122: $cursor = $secData;
123: }
124:
125: return $data;
126: }
127:
128:
129:
130: 131: 132: 133: 134: 135:
136: public static function save($config, $file)
137: {
138: $output = array();
139: $output[] = '; generated by Nette';
140: $output[] = '';
141:
142: foreach ($config as $secName => $secData) {
143: if (!(is_array($secData) || $secData instanceof \Traversable)) {
144: throw new Nette\InvalidStateException("Invalid section '$secName'.");
145: }
146:
147: $output[] = "[$secName]";
148: self::build($secData, $output, '');
149: $output[] = '';
150: }
151:
152: if (!file_put_contents($file, implode(PHP_EOL, $output))) {
153: throw new Nette\IOException("Cannot write file '$file'.");
154: }
155: }
156:
157:
158:
159: 160: 161: 162: 163: 164: 165:
166: private static function build($input, & $output, $prefix)
167: {
168: foreach ($input as $key => $val) {
169: if (is_array($val) || $val instanceof \Traversable) {
170: self::build($val, $output, $prefix . $key . self::$keySeparator);
171:
172: } elseif (is_bool($val)) {
173: $output[] = "$prefix$key = " . ($val ? 'true' : 'false');
174:
175: } elseif (is_numeric($val)) {
176: $output[] = "$prefix$key = $val";
177:
178: } elseif (is_string($val)) {
179: $output[] = "$prefix$key = \"$val\"";
180:
181: } else {
182: throw new Nette\InvalidArgumentException("The '$prefix$key' item must be scalar or array, " . gettype($val) ." given.");
183: }
184: }
185: }
186:
187: }
188: