Overview

Namespaces

  • Composer
    • Autoload
  • Illuminate
    • Support
      • Contracts
      • Facades
  • Laravella
    • Cart
      • Facades
  • None
  • PHP

Classes

  • ClassLoader
  • Collection
  • Fluent
  • Manager
  • MessageBag
  • NamespacedItemResolver
  • Pluralizer
  • SerializableClosure
  • ServiceProvider
  • Str
  • Overview
  • Namespace
  • Class
  • Tree
  1: <?php namespace Illuminate\Support;
  2: 
  3: use Closure;
  4: use Serializable;
  5: use SplFileObject;
  6: use ReflectionFunction;
  7: 
  8: /**
  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>
 13:  */
 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: }
cart API documentation generated by ApiGen 2.8.0