Skip to content

Commit eec168d

Browse files
committed
use @jeremeamia's super closure lib for closure serialization.
1 parent cfce698 commit eec168d

2 files changed

Lines changed: 3 additions & 194 deletions

File tree

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"doctrine/dbal": "2.4.*",
1616
"ircmaxell/password-compat": "1.0.*",
1717
"filp/whoops": "1.0.7",
18+
"jeremeamia/SuperClosure": "1.0.*",
1819
"monolog/monolog": "1.6.*",
1920
"nesbot/carbon": "1.*",
2021
"patchwork/utf8": "1.1.*",
Lines changed: 2 additions & 194 deletions
Original file line numberDiff line numberDiff line change
@@ -1,198 +1,6 @@
11
<?php namespace Illuminate\Support;
22

3-
use Closure;
4-
use Serializable;
5-
use SplFileObject;
6-
use ReflectionFunction;
7-
83
/**
9-
* Do not use this class unless you really know what you're doing!
10-
*
11-
* @author Taylor Otwell <@taylorotwell>
12-
* @author Jeremy Lindblom <@jeremeamia>
4+
* Extending for backwards compatibility.
135
*/
14-
class SerializableClosure implements Serializable {
15-
16-
/**
17-
* The Closure instance.
18-
*
19-
* @var \Closure
20-
*/
21-
protected $closure;
22-
23-
/**
24-
* The ReflectionFunction instance of the Closure.
25-
*
26-
* @var \ReflectionFunction
27-
*/
28-
protected $reflection;
29-
30-
/**
31-
* The code contained by the Closure.
32-
*
33-
* @var string
34-
*/
35-
protected $code;
36-
37-
/**
38-
* Create a new serializable Closure instance.
39-
*
40-
* @param \Closure $closure
41-
* @return void
42-
*/
43-
public function __construct(Closure $closure)
44-
{
45-
$this->closure = $closure;
46-
47-
$this->reflection = new ReflectionFunction($closure);
48-
}
49-
50-
/**
51-
* Get the code for the Closure.
52-
*
53-
* @return string
54-
*/
55-
public function getCode()
56-
{
57-
return $this->code ?: $this->code = $this->getCodeFromFile();
58-
}
59-
60-
/**
61-
* Extract the code from the Closure's file.
62-
*
63-
* @return string
64-
*/
65-
protected function getCodeFromFile()
66-
{
67-
$file = $this->getFile();
68-
69-
$code = '';
70-
71-
// Next, we will just loop through the lines of the file until we get to the end
72-
// of the Closure. Then, we will return the complete contents of this Closure
73-
// so it can be serialized with these variables and stored for later usage.
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-
* Get an SplObjectFile object at the starting line of the Closure.
86-
*
87-
* @return \SplFileObject
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-
* Get the variables used by the Closure.
100-
*
101-
* @return array
102-
*/
103-
public function getVariables()
104-
{
105-
if ( ! $this->getUseIndex()) return array();
106-
107-
$staticVariables = $this->reflection->getStaticVariables();
108-
109-
// When looping through the variables, we will only take the variables that are
110-
// specified in the use clause, and will not take any other static variables
111-
// that may be used by the Closures, allowing this to re-create its state.
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-
* Get the variables from the "use" clause.
126-
*
127-
* @return array
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-
* Get the index location of the "use" clause.
138-
*
139-
* @return int
140-
*/
141-
protected function getUseIndex()
142-
{
143-
return stripos(strtok($this->getCode(), PHP_EOL), ' use ');
144-
}
145-
146-
/**
147-
* Serialize the Closure instance.
148-
*
149-
* @return string
150-
*/
151-
public function serialize()
152-
{
153-
return serialize(array(
154-
'code' => $this->getCode(), 'variables' => $this->getVariables()
155-
));
156-
}
157-
158-
/**
159-
* Unserialize the Closure instance.
160-
*
161-
* @param string $serialized
162-
* @return void
163-
*/
164-
public function unserialize($serialized)
165-
{
166-
$payload = unserialize($serialized);
167-
168-
// We will extract the variables into the current scope so that as the Closure
169-
// is built it will inherit the scope it had before it was serialized which
170-
// will emulate the Closures existing in that scope instead of right now.
171-
extract($payload['variables']);
172-
173-
eval('$this->closure = '.$payload['code'].';');
174-
175-
$this->reflection = new ReflectionFunction($this->closure);
176-
}
177-
178-
/**
179-
* Get the unserialized Closure instance.
180-
*
181-
* @return \Closure
182-
*/
183-
public function getClosure()
184-
{
185-
return $this->closure;
186-
}
187-
188-
/**
189-
* Invoke the contained Closure.
190-
*
191-
* @return mixed
192-
*/
193-
public function __invoke()
194-
{
195-
return call_user_func_array($this->closure, func_get_args());
196-
}
197-
198-
}
6+
class SerializableClosure extends \Jeremeamia\SuperClosure\SerializableClosure {}

0 commit comments

Comments
 (0)