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