1: <?php
2:
3: 4: 5: 6:
7:
8: namespace Nette\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 (string) $var;
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 (array_merge(range("\x00", "\x1F"), range("\x7F", "\xFF")) as $ch) {
49: $table[$ch] = '\x' . str_pad(dechex(ord($ch)), 2, '0', STR_PAD_LEFT);
50: }
51: $table['\\'] = '\\\\';
52: $table["\r"] = '\r';
53: $table["\n"] = '\n';
54: $table["\t"] = '\t';
55: $table['$'] = '\$';
56: $table['"'] = '\"';
57: }
58: return '"' . strtr($var, $table) . '"';
59:
60: } elseif (is_array($var)) {
61: $space = str_repeat("\t", $level);
62:
63: static $marker;
64: if ($marker === NULL) {
65: $marker = uniqid("\x00", TRUE);
66: }
67: if (empty($var)) {
68: $out = '';
69:
70: } elseif ($level > 50 || isset($var[$marker])) {
71: throw new Nette\InvalidArgumentException('Nesting level too deep or recursive dependency.');
72:
73: } else {
74: $out = '';
75: $outAlt = "\n$space";
76: $var[$marker] = TRUE;
77: $counter = 0;
78: foreach ($var as $k => & $v) {
79: if ($k !== $marker) {
80: $item = ($k === $counter ? '' : self::_dump($k, $level + 1) . ' => ') . self::_dump($v, $level + 1);
81: $counter = is_int($k) ? max($k + 1, $counter) : $counter;
82: $out .= ($out === '' ? '' : ', ') . $item;
83: $outAlt .= "\t$item,\n$space";
84: }
85: }
86: unset($var[$marker]);
87: }
88: return 'array(' . (strpos($out, "\n") === FALSE && strlen($out) < 40 ? $out : $outAlt) . ')';
89:
90: } elseif ($var instanceof \Serializable) {
91: $var = serialize($var);
92: return 'unserialize(' . self::_dump($var, $level) . ')';
93:
94: } elseif (is_object($var)) {
95: $arr = (array) $var;
96: $space = str_repeat("\t", $level);
97: $class = get_class($var);
98:
99: static $list = array();
100: if ($level > 50 || in_array($var, $list, TRUE)) {
101: throw new Nette\InvalidArgumentException('Nesting level too deep or recursive dependency.');
102:
103: } else {
104: $out = "\n";
105: $list[] = $var;
106: if (method_exists($var, '__sleep')) {
107: foreach ($var->__sleep() as $v) {
108: $props[$v] = $props["\x00*\x00$v"] = $props["\x00$class\x00$v"] = TRUE;
109: }
110: }
111: foreach ($arr as $k => & $v) {
112: if (!isset($props) || isset($props[$k])) {
113: $out .= "$space\t" . self::_dump($k, $level + 1) . " => " . self::_dump($v, $level + 1) . ",\n";
114: }
115: }
116: array_pop($list);
117: $out .= $space;
118: }
119: return $class === 'stdClass'
120: ? "(object) array($out)"
121: : __CLASS__ . "::createObject('$class', array($out))";
122:
123: } elseif (is_resource($var)) {
124: throw new Nette\InvalidArgumentException('Cannot dump resource.');
125:
126: } else {
127: return var_export($var, TRUE);
128: }
129: }
130:
131:
132: 133: 134: 135:
136: public static function format($statement)
137: {
138: $args = func_get_args();
139: return self::formatArgs(array_shift($args), $args);
140: }
141:
142:
143: 144: 145: 146:
147: public static function formatArgs($statement, array $args)
148: {
149: $a = strpos($statement, '?');
150: while ($a !== FALSE) {
151: if (!$args) {
152: throw new Nette\InvalidArgumentException('Insufficient number of arguments.');
153: }
154: $arg = array_shift($args);
155: if (substr($statement, $a + 1, 1) === '*') {
156: if (!is_array($arg)) {
157: throw new Nette\InvalidArgumentException('Argument must be an array.');
158: }
159: $arg = implode(', ', array_map(array(__CLASS__, 'dump'), $arg));
160: $statement = substr_replace($statement, $arg, $a, 2);
161:
162: } else {
163: $arg = substr($statement, $a - 1, 1) === '$' || in_array(substr($statement, $a - 2, 2), array('->', '::'), TRUE)
164: ? self::formatMember($arg) : self::_dump($arg);
165: $statement = substr_replace($statement, $arg, $a, 1);
166: }
167: $a = strpos($statement, '?', $a + strlen($arg));
168: }
169: return $statement;
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: public static function isIdentifier($value)
189: {
190: return is_string($value) && preg_match('#^' . self::PHP_IDENT . '\z#', $value);
191: }
192:
193:
194:
195: public static function createObject($class, array $props)
196: {
197: return unserialize('O' . substr(serialize((string) $class), 1, -1) . substr(serialize($props), 1));
198: }
199:
200: }
201: