1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
12:
13: 14: 15: 16: 17: 18:
19:
20: namespace LightnCandy;
21:
22: 23: 24:
25: class Exporter
26: {
27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37:
38: protected static function closure($context, $closure)
39: {
40: if (is_string($closure) && preg_match('/(.+)::(.+)/', $closure, $matched)) {
41: $ref = new \ReflectionMethod($matched[1], $matched[2]);
42: } else {
43: $ref = new \ReflectionFunction($closure);
44: }
45: $meta = static::getMeta($ref);
46:
47: return preg_replace('/^.*?function(\s+[^\s\\(]+?)?\s*\\((.+)\\}.*?\s*$/s', 'function($2}', static::replaceSafeString($context, $meta['code']));
48: }
49:
50: 51: 52: 53: 54: 55: 56:
57: public static function helpers($context)
58: {
59: $ret = '';
60: foreach ($context['helpers'] as $name => $func) {
61: if (!isset($context['usedCount']['helpers'][$name])) {
62: continue;
63: }
64: if ((is_object($func) && ($func instanceof \Closure)) || ($context['flags']['exhlp'] == 0)) {
65: $ret .= (" '$name' => " . static::closure($context, $func) . ",\n");
66: continue;
67: }
68: $ret .= " '$name' => '$func',\n";
69: }
70:
71: return "array($ret)";
72: }
73:
74: 75: 76: 77: 78: 79: 80: 81:
82: protected static function replaceSafeString($context, $str)
83: {
84: return $context['flags']['standalone'] ? str_replace($context['safestring'], $context['safestringalias'], $str) : $str;
85: }
86:
87: 88: 89: 90: 91: 92: 93: 94:
95: public static function getClassMethods($context, $class)
96: {
97: $methods = array();
98:
99: foreach ($class->getMethods() as $method) {
100: $meta = static::getMeta($method);
101: $methods[$meta['name']] = static::scanDependency($context, preg_replace('/public static function (.+)\\(/', "function {$context['funcprefix']}\$1(", $meta['code']), $meta['code']);
102: }
103:
104: return $methods;
105: }
106:
107: 108: 109: 110: 111: 112: 113:
114: public static function getClassStatics($class)
115: {
116: $ret = '';
117:
118: foreach ($class->getStaticProperties() as $name => $value) {
119: $ret .= " public static \${$name} = " . var_export($value, true) . ";\n";
120: }
121:
122: return $ret;
123: }
124:
125:
126:
127:
128:
129: 130: 131: 132: 133: 134: 135:
136: public static function getMeta($refobj)
137: {
138: $fname = $refobj->getFileName();
139: $lines = file_get_contents($fname);
140: $file = new \SplFileObject($fname);
141: $file->seek($refobj->getStartLine() - 2);
142: $spos = $file->ftell();
143: $file->seek($refobj->getEndLine() - 1);
144: $epos = $file->ftell();
145: unset($file);
146: return array(
147: 'name' => $refobj->getName(),
148: 'code' => substr($lines, $spos, $epos - $spos)
149: );
150: }
151:
152: 153: 154: 155: 156: 157: 158:
159: public static function safestring($context)
160: {
161: $class = new \ReflectionClass($context['safestring']);
162:
163: return array_reduce(static::getClassMethods($context, $class), function ($in, $cur) {
164: return $in . $cur[2];
165: }, "if (!class_exists(\"" . addslashes($context['safestringalias']) . "\")) {\nclass {$context['safestringalias']} {\n" . static::getClassStatics($class)) . "}\n}\n";
166: }
167:
168: 169: 170: 171: 172: 173: 174:
175: public static function stringobject($context)
176: {
177: if ($context['flags']['standalone'] == 0) {
178: return 'use \\LightnCandy\\StringObject as StringObject;';
179: }
180: $class = new \ReflectionClass('\\LightnCandy\\StringObject');
181: $meta = static::getMeta($class);
182: $methods = array();
183: return "if (!class_exists(\"StringObject\")) {\n{$meta['code']}}\n";
184: }
185:
186: 187: 188: 189: 190: 191: 192:
193: public static function runtime($context)
194: {
195: $class = new \ReflectionClass($context['runtime']);
196: $ret = '';
197: $methods = static::getClassMethods($context, $class);
198:
199: $exports = array_keys($context['usedCount']['runtime']);
200:
201: while (true) {
202: if (array_sum(array_map(function ($name) use (&$exports, $methods) {
203: $n = 0;
204: foreach ($methods[$name][1] as $child => $count) {
205: if (!in_array($child, $exports)) {
206: $exports[] = $child;
207: $n++;
208: }
209: }
210: return $n;
211: }, $exports)) == 0) {
212: break;
213: }
214: }
215:
216: foreach ($exports as $export) {
217: $ret .= ($methods[$export][0] . "\n");
218: }
219:
220: return $ret;
221: }
222:
223: 224: 225: 226: 227: 228: 229:
230: public static function constants($context)
231: {
232: if ($context['flags']['standalone'] == 0) {
233: return 'array()';
234: }
235:
236: $class = new \ReflectionClass($context['runtime']);
237: $constants = $class->getConstants();
238: $ret = " array(\n";
239: foreach ($constants as $name => $value) {
240: $ret .= " '$name' => ". (is_string($value) ? "'$value'" : $value) . ",\n";
241: }
242: $ret .= " )";
243: return $ret;
244: }
245:
246: 247: 248: 249: 250: 251: 252: 253: 254:
255: protected static function scanDependency($context, $code, $ocode)
256: {
257: $child = array();
258:
259: $code = preg_replace_callback('/static::(\w+?)\s*\(/', function ($matches) use ($context, &$child) {
260: if (!isset($child[$matches[1]])) {
261: $child[$matches[1]] = 0;
262: }
263: $child[$matches[1]]++;
264:
265: return "{$context['funcprefix']}{$matches[1]}(";
266: }, $code);
267:
268:
269: $code = preg_replace('/static::([A-Z0-9_]+)/', "\$cx['constants']['$1']", $code);
270:
271:
272: $code = preg_replace('/ /', ' ', $code);
273:
274: return array(static::replaceSafeString($context, $code), $child, $ocode);
275: }
276: }
277: