Server IP : 127.0.0.2 / Your IP : 3.144.176.149 Web Server : Apache/2.4.18 (Ubuntu) System : User : www-data ( ) PHP Version : 7.0.33-0ubuntu0.16.04.16 Disable Function : disk_free_space,disk_total_space,diskfreespace,dl,exec,fpaththru,getmyuid,getmypid,highlight_file,ignore_user_abord,leak,listen,link,opcache_get_configuration,opcache_get_status,passthru,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,php_uname,phpinfo,posix_ctermid,posix_getcwd,posix_getegid,posix_geteuid,posix_getgid,posix_getgrgid,posix_getgrnam,posix_getgroups,posix_getlogin,posix_getpgid,posix_getpgrp,posix_getpid,posix,_getppid,posix_getpwnam,posix_getpwuid,posix_getrlimit,posix_getsid,posix_getuid,posix_isatty,posix_kill,posix_mkfifo,posix_setegid,posix_seteuid,posix_setgid,posix_setpgid,posix_setsid,posix_setuid,posix_times,posix_ttyname,posix_uname,pclose,popen,proc_open,proc_close,proc_get_status,proc_nice,proc_terminate,shell_exec,source,show_source,system,virtual MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : ON Directory : /var/www/html/vendor/jeremeamia/superclosure/src/ |
Upload File : |
<?php namespace SuperClosure; use Closure; use SuperClosure\Exception\ClosureUnserializationException; /** * This class acts as a wrapper for a closure, and allows it to be serialized. * * With the combined power of the Reflection API, code parsing, and the infamous * `eval()` function, you can serialize a closure, unserialize it somewhere * else (even a different PHP process), and execute it. */ class SerializableClosure implements \Serializable { /** * The closure being wrapped for serialization. * * @var Closure */ private $closure; /** * The serializer doing the serialization work. * * @var SerializerInterface */ private $serializer; /** * The data from unserialization. * * @var array */ private $data; /** * Create a new serializable closure instance. * * @param Closure $closure * @param SerializerInterface|null $serializer */ public function __construct( \Closure $closure, SerializerInterface $serializer = null ) { $this->closure = $closure; $this->serializer = $serializer ?: new Serializer; } /** * Return the original closure object. * * @return Closure */ public function getClosure() { return $this->closure; } /** * Delegates the closure invocation to the actual closure object. * * Important Notes: * * - `ReflectionFunction::invokeArgs()` should not be used here, because it * does not work with closure bindings. * - Args passed-by-reference lose their references when proxied through * `__invoke()`. This is an unfortunate, but understandable, limitation * of PHP that will probably never change. * * @return mixed */ public function __invoke() { return call_user_func_array($this->closure, func_get_args()); } /** * Clones the SerializableClosure with a new bound object and class scope. * * The method is essentially a wrapped proxy to the Closure::bindTo method. * * @param mixed $newthis The object to which the closure should be bound, * or NULL for the closure to be unbound. * @param mixed $newscope The class scope to which the closure is to be * associated, or 'static' to keep the current one. * If an object is given, the type of the object will * be used instead. This determines the visibility of * protected and private methods of the bound object. * * @return SerializableClosure * @link http://www.php.net/manual/en/closure.bindto.php */ public function bindTo($newthis, $newscope = 'static') { return new self( $this->closure->bindTo($newthis, $newscope), $this->serializer ); } /** * Serializes the code, context, and binding of the closure. * * @return string|null * @link http://php.net/manual/en/serializable.serialize.php */ public function serialize() { try { $this->data = $this->data ?: $this->serializer->getData($this->closure, true); return serialize($this->data); } catch (\Exception $e) { trigger_error( 'Serialization of closure failed: ' . $e->getMessage(), E_USER_NOTICE ); // Note: The serialize() method of Serializable must return a string // or null and cannot throw exceptions. return null; } } /** * Unserializes the closure. * * Unserializes the closure's data and recreates the closure using a * simulation of its original context. The used variables (context) are * extracted into a fresh scope prior to redefining the closure. The * closure is also rebound to its former object and scope. * * @param string $serialized * * @throws ClosureUnserializationException * @link http://php.net/manual/en/serializable.unserialize.php */ public function unserialize($serialized) { // Unserialize the closure data and reconstruct the closure object. $this->data = unserialize($serialized); $this->closure = __reconstruct_closure($this->data); // Throw an exception if the closure could not be reconstructed. if (!$this->closure instanceof Closure) { throw new ClosureUnserializationException( 'The closure is corrupted and cannot be unserialized.' ); } // Rebind the closure to its former binding and scope. if ($this->data['binding'] || $this->data['isStatic']) { $this->closure = $this->closure->bindTo( $this->data['binding'], $this->data['scope'] ); } } /** * Returns closure data for `var_dump()`. * * @return array */ public function __debugInfo() { return $this->data ?: $this->serializer->getData($this->closure, true); } } /** * Reconstruct a closure. * * HERE BE DRAGONS! * * The infamous `eval()` is used in this method, along with the error * suppression operator, and variable variables (i.e., double dollar signs) to * perform the unserialization logic. I'm sorry, world! * * This is also done inside a plain function instead of a method so that the * binding and scope of the closure are null. * * @param array $__data Unserialized closure data. * * @return Closure|null * @internal */ function __reconstruct_closure(array $__data) { // Simulate the original context the closure was created in. foreach ($__data['context'] as $__var_name => &$__value) { if ($__value instanceof SerializableClosure) { // Unbox any SerializableClosures in the context. $__value = $__value->getClosure(); } elseif ($__value === Serializer::RECURSION) { // Track recursive references (there should only be one). $__recursive_reference = $__var_name; } // Import the variable into this scope. ${$__var_name} = $__value; } // Evaluate the code to recreate the closure. try { if (isset($__recursive_reference)) { // Special handling for recursive closures. @eval("\${$__recursive_reference} = {$__data['code']};"); $__closure = ${$__recursive_reference}; } else { @eval("\$__closure = {$__data['code']};"); } } catch (\ParseError $e) { // Discard the parse error. } return isset($__closure) ? $__closure : null; }