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