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