1: <?php namespace Illuminate\Support;
2:
3: use Closure;
4: use Serializable;
5: use SplFileObject;
6: use ReflectionFunction;
7:
8: 9: 10: 11: 12: 13:
14: class SerializableClosure implements Serializable {
15:
16: 17: 18: 19: 20:
21: protected $closure;
22:
23: 24: 25: 26: 27:
28: protected $reflection;
29:
30: 31: 32: 33: 34:
35: protected $code;
36:
37: 38: 39: 40: 41: 42:
43: public function __construct(Closure $closure)
44: {
45: $this->closure = $closure;
46:
47: $this->reflection = new ReflectionFunction($closure);
48: }
49:
50: 51: 52: 53: 54:
55: public function getCode()
56: {
57: return $this->code ?: $this->code = $this->getCodeFromFile();
58: }
59:
60: 61: 62: 63: 64:
65: protected function getCodeFromFile()
66: {
67: $file = $this->getFile();
68:
69: $code = '';
70:
71:
72:
73:
74: while ($file->key() < $this->reflection->getEndLine())
75: {
76: $code .= $file->current(); $file->next();
77: }
78:
79: $begin = strpos($code, 'function(');
80:
81: return substr($code, $begin, strrpos($code, '}') - $begin + 1);
82: }
83:
84: 85: 86: 87: 88:
89: protected function getFile()
90: {
91: $file = new SplFileObject($this->reflection->getFileName());
92:
93: $file->seek($this->reflection->getStartLine() - 1);
94:
95: return $file;
96: }
97:
98: 99: 100: 101: 102:
103: public function getVariables()
104: {
105: if ( ! $this->getUseIndex()) return array();
106:
107: $staticVariables = $this->reflection->getStaticVariables();
108:
109:
110:
111:
112: $usedVariables = array();
113:
114: foreach ($this->getUseClauseVariables() as $variable)
115: {
116: $variable = trim($variable, ' $&');
117:
118: $usedVariables[$variable] = $staticVariables[$variable];
119: }
120:
121: return $usedVariables;
122: }
123:
124: 125: 126: 127: 128:
129: protected function getUseClauseVariables()
130: {
131: $begin = strpos($code = $this->getCode(), '(', $this->getUseIndex()) + 1;
132:
133: return explode(',', substr($code, $begin, strpos($code, ')', $begin) - $begin));
134: }
135:
136: 137: 138: 139: 140:
141: protected function getUseIndex()
142: {
143: return stripos(strtok($this->getCode(), PHP_EOL), ' use ');
144: }
145:
146: 147: 148: 149: 150:
151: public function serialize()
152: {
153: return serialize(array(
154: 'code' => $this->getCode(), 'variables' => $this->getVariables()
155: ));
156: }
157:
158: 159: 160: 161: 162: 163:
164: public function unserialize($serialized)
165: {
166: $payload = unserialize($serialized);
167:
168:
169:
170:
171: extract($payload['variables']);
172:
173: eval('$this->closure = '.$payload['code'].';');
174:
175: $this->reflection = new ReflectionFunction($this->closure);
176: }
177:
178: 179: 180: 181: 182:
183: public function getClosure()
184: {
185: return $this->closure;
186: }
187:
188: 189: 190: 191: 192:
193: public function __invoke()
194: {
195: return call_user_func_array($this->closure, func_get_args());
196: }
197:
198: }