1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10:
11:
12: namespace Nette\Utils\PhpGenerator;
13:
14: use Nette;
15:
16:
17:
18: 19: 20: 21: 22:
23: class Helpers
24: {
25: const PHP_IDENT = '[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*';
26:
27:
28: 29: 30: 31:
32: public static function dump($var)
33: {
34: return self::_dump($var);
35: }
36:
37:
38:
39: private static function _dump(&$var, $level = 0)
40: {
41: if ($var instanceof PhpLiteral) {
42: return $var->value;
43:
44: } elseif (is_float($var)) {
45: $var = var_export($var, TRUE);
46: return strpos($var, '.') === FALSE ? $var . '.0' : $var;
47:
48: } elseif (is_bool($var)) {
49: return $var ? 'TRUE' : 'FALSE';
50:
51: } elseif (is_string($var) && (preg_match('#[^\x09\x20-\x7E\xA0-\x{10FFFF}]#u', $var) || preg_last_error())) {
52: static $table;
53: if ($table === NULL) {
54: foreach (range("\x00", "\xFF") as $ch) {
55: $table[$ch] = ord($ch) < 32 || ord($ch) >= 127
56: ? '\\x' . str_pad(dechex(ord($ch)), 2, '0', STR_PAD_LEFT)
57: : $ch;
58: }
59: $table["\r"] = '\r';
60: $table["\n"] = '\n';
61: $table["\t"] = '\t';
62: $table['$'] = '\\$';
63: $table['\\'] = '\\\\';
64: $table['"'] = '\\"';
65: }
66: return '"' . strtr($var, $table) . '"';
67:
68: } elseif (is_array($var)) {
69: $s = '';
70: $space = str_repeat("\t", $level);
71:
72: static $marker;
73: if ($marker === NULL) {
74: $marker = uniqid("\x00", TRUE);
75: }
76: if (empty($var)) {
77:
78: } elseif ($level > 50 || isset($var[$marker])) {
79: throw new Nette\InvalidArgumentException('Nesting level too deep or recursive dependency.');
80:
81: } else {
82: $s .= "\n";
83: $var[$marker] = TRUE;
84: $counter = 0;
85: foreach ($var as $k => &$v) {
86: if ($k !== $marker) {
87: $s .= "$space\t" . ($k === $counter ? '' : self::_dump($k) . " => ") . self::_dump($v, $level + 1) . ",\n";
88: $counter = is_int($k) ? $k + 1 : $counter;
89: }
90: }
91: unset($var[$marker]);
92: $s .= $space;
93: }
94: return "array($s)";
95:
96: } elseif (is_object($var)) {
97: $arr = (array) $var;
98: $s = '';
99: $space = str_repeat("\t", $level);
100:
101: static $list = array();
102: if (empty($arr)) {
103:
104: } elseif ($level > 50 || in_array($var, $list, TRUE)) {
105: throw new Nette\InvalidArgumentException('Nesting level too deep or recursive dependency.');
106:
107: } else {
108: $s .= "\n";
109: $list[] = $var;
110: foreach ($arr as $k => &$v) {
111: if ($k[0] === "\x00") {
112: $k = substr($k, strrpos($k, "\x00") + 1);
113: }
114: $s .= "$space\t" . self::_dump($k) . " => " . self::_dump($v, $level + 1) . ",\n";
115: }
116: array_pop($list);
117: $s .= $space;
118: }
119: return get_class($var) === 'stdClass'
120: ? "(object) array($s)"
121: : __CLASS__ . "::createObject('" . get_class($var) . "', array($s))";
122:
123: } else {
124: return var_export($var, TRUE);
125: }
126: }
127:
128:
129:
130: 131: 132: 133:
134: public static function format($statement)
135: {
136: $args = func_get_args();
137: return self::formatArgs(array_shift($args), $args);
138: }
139:
140:
141:
142: 143: 144: 145:
146: public static function formatArgs($statement, array $args)
147: {
148: $a = strpos($statement, '?');
149: while ($a !== FALSE) {
150: if (!$args) {
151: throw new Nette\InvalidArgumentException('Insufficient number of arguments.');
152: }
153: $arg = array_shift($args);
154: if (substr($statement, $a + 1, 1) === '*') {
155: if (!is_array($arg)) {
156: throw new Nette\InvalidArgumentException('Argument must be an array.');
157: }
158: $arg = implode(', ', array_map(array(__CLASS__, 'dump'), $arg));
159: $statement = substr_replace($statement, $arg, $a, 2);
160:
161: } else {
162: $arg = substr($statement, $a - 1, 1) === '$' || in_array(substr($statement, $a - 2, 2), array('->', '::'))
163: ? self::formatMember($arg) : self::_dump($arg);
164: $statement = substr_replace($statement, $arg, $a, 1);
165: }
166: $a = strpos($statement, '?', $a + strlen($arg));
167: }
168: return $statement;
169: }
170:
171:
172:
173: 174: 175: 176:
177: public static function formatMember($name)
178: {
179: return $name instanceof PhpLiteral || !self::isIdentifier($name)
180: ? '{' . self::_dump($name) . '}'
181: : $name ;
182: }
183:
184:
185:
186: 187: 188:
189: public static function isIdentifier($value)
190: {
191: return is_string($value) && preg_match('#^' . self::PHP_IDENT . '$#', $value);
192: }
193:
194:
195:
196: public static function createObject($class, array $props)
197: {
198: return unserialize('O' . substr(serialize((string) $class), 1, -1) . substr(serialize($props), 1));
199: }
200:
201: }
202: