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