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