first commit
This commit is contained in:
21
vendor/laravel/serializable-closure/LICENSE.md
vendored
Normal file
21
vendor/laravel/serializable-closure/LICENSE.md
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) Taylor Otwell
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
73
vendor/laravel/serializable-closure/README.md
vendored
Normal file
73
vendor/laravel/serializable-closure/README.md
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
# Serializable Closure
|
||||
|
||||
<a href="https://github.com/laravel/serializable-closure/actions">
|
||||
<img src="https://github.com/laravel/serializable-closure/workflows/tests/badge.svg" alt="Build Status">
|
||||
</a>
|
||||
<a href="https://packagist.org/packages/laravel/serializable-closure">
|
||||
<img src="https://img.shields.io/packagist/dt/laravel/serializable-closure" alt="Total Downloads">
|
||||
</a>
|
||||
<a href="https://packagist.org/packages/laravel/serializable-closure">
|
||||
<img src="https://img.shields.io/packagist/v/laravel/serializable-closure" alt="Latest Stable Version">
|
||||
</a>
|
||||
<a href="https://packagist.org/packages/laravel/serializable-closure">
|
||||
<img src="https://img.shields.io/packagist/l/laravel/serializable-closure" alt="License">
|
||||
</a>
|
||||
|
||||
## Introduction
|
||||
|
||||
> This project is a fork of the excellent [opis/closure: 3.x](https://github.com/opis/closure) package. At Laravel, we decided to fork this package as the upcoming version [4.x](https://github.com/opis/closure) is a complete rewrite on top of the [FFI extension](https://www.php.net/manual/en/book.ffi.php). As Laravel is a web framework, and FFI is not enabled by default in web requests, this fork allows us to keep using the `3.x` series while adding support for new PHP versions.
|
||||
|
||||
Laravel Serializable Closure provides an easy and secure way to **serialize closures in PHP**.
|
||||
|
||||
## Official Documentation
|
||||
|
||||
### Installation
|
||||
|
||||
> **Requires [PHP 7.4+](https://php.net/releases/)**
|
||||
|
||||
First, install Laravel Serializable Closure via the [Composer](https://getcomposer.org/) package manager:
|
||||
|
||||
```bash
|
||||
composer require laravel/serializable-closure
|
||||
```
|
||||
|
||||
### Usage
|
||||
|
||||
You may serialize a closure this way:
|
||||
|
||||
```php
|
||||
use Laravel\SerializableClosure\SerializableClosure;
|
||||
|
||||
$closure = fn () => 'james';
|
||||
|
||||
// Recommended
|
||||
SerializableClosure::setSecretKey('secret');
|
||||
|
||||
$serialized = serialize(new SerializableClosure($closure));
|
||||
$closure = unserialize($serialized)->getClosure();
|
||||
|
||||
echo $closure(); // james;
|
||||
```
|
||||
|
||||
### Caveats
|
||||
|
||||
* Anonymous classes cannot be created within closures.
|
||||
* Attributes cannot be used within closures.
|
||||
* Serializing closures on REPL environments like Laravel Tinker is not supported.
|
||||
* Serializing closures that reference objects with readonly properties is not supported.
|
||||
|
||||
## Contributing
|
||||
|
||||
Thank you for considering contributing to Serializable Closure! The contribution guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions).
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
In order to ensure that the Laravel community is welcoming to all, please review and abide by the [Code of Conduct](https://laravel.com/docs/contributions#code-of-conduct).
|
||||
|
||||
## Security Vulnerabilities
|
||||
|
||||
Please review [our security policy](https://github.com/laravel/serializable-closure/security/policy) on how to report security vulnerabilities.
|
||||
|
||||
## License
|
||||
|
||||
Serializable Closure is open-sourced software licensed under the [MIT license](LICENSE.md).
|
52
vendor/laravel/serializable-closure/composer.json
vendored
Normal file
52
vendor/laravel/serializable-closure/composer.json
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"name": "laravel/serializable-closure",
|
||||
"description": "Laravel Serializable Closure provides an easy and secure way to serialize closures in PHP.",
|
||||
"keywords": ["laravel", "Serializable", "closure"],
|
||||
"license": "MIT",
|
||||
"support": {
|
||||
"issues": "https://github.com/laravel/serializable-closure/issues",
|
||||
"source": "https://github.com/laravel/serializable-closure"
|
||||
},
|
||||
"authors": [
|
||||
{
|
||||
"name": "Taylor Otwell",
|
||||
"email": "taylor@laravel.com"
|
||||
},
|
||||
{
|
||||
"name": "Nuno Maduro",
|
||||
"email": "nuno@laravel.com"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.3|^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"nesbot/carbon": "^2.61",
|
||||
"pestphp/pest": "^1.21.3",
|
||||
"phpstan/phpstan": "^1.8.2",
|
||||
"symfony/var-dumper": "^5.4.11"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Laravel\\SerializableClosure\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Tests\\": "tests/"
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.x-dev"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true,
|
||||
"allow-plugins": {
|
||||
"pestphp/pest-plugin": true
|
||||
}
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true
|
||||
}
|
20
vendor/laravel/serializable-closure/src/Contracts/Serializable.php
vendored
Normal file
20
vendor/laravel/serializable-closure/src/Contracts/Serializable.php
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\SerializableClosure\Contracts;
|
||||
|
||||
interface Serializable
|
||||
{
|
||||
/**
|
||||
* Resolve the closure with the given arguments.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __invoke();
|
||||
|
||||
/**
|
||||
* Gets the closure that got serialized/unserialized.
|
||||
*
|
||||
* @return \Closure
|
||||
*/
|
||||
public function getClosure();
|
||||
}
|
22
vendor/laravel/serializable-closure/src/Contracts/Signer.php
vendored
Normal file
22
vendor/laravel/serializable-closure/src/Contracts/Signer.php
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\SerializableClosure\Contracts;
|
||||
|
||||
interface Signer
|
||||
{
|
||||
/**
|
||||
* Sign the given serializable.
|
||||
*
|
||||
* @param string $serializable
|
||||
* @return array
|
||||
*/
|
||||
public function sign($serializable);
|
||||
|
||||
/**
|
||||
* Verify the given signature.
|
||||
*
|
||||
* @param array $signature
|
||||
* @return bool
|
||||
*/
|
||||
public function verify($signature);
|
||||
}
|
19
vendor/laravel/serializable-closure/src/Exceptions/InvalidSignatureException.php
vendored
Normal file
19
vendor/laravel/serializable-closure/src/Exceptions/InvalidSignatureException.php
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\SerializableClosure\Exceptions;
|
||||
|
||||
use Exception;
|
||||
|
||||
class InvalidSignatureException extends Exception
|
||||
{
|
||||
/**
|
||||
* Create a new exception instance.
|
||||
*
|
||||
* @param string $message
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($message = 'Your serialized closure might have been modified or it\'s unsafe to be unserialized.')
|
||||
{
|
||||
parent::__construct($message);
|
||||
}
|
||||
}
|
19
vendor/laravel/serializable-closure/src/Exceptions/MissingSecretKeyException.php
vendored
Normal file
19
vendor/laravel/serializable-closure/src/Exceptions/MissingSecretKeyException.php
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\SerializableClosure\Exceptions;
|
||||
|
||||
use Exception;
|
||||
|
||||
class MissingSecretKeyException extends Exception
|
||||
{
|
||||
/**
|
||||
* Create a new exception instance.
|
||||
*
|
||||
* @param string $message
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($message = 'No serializable closure secret key has been specified.')
|
||||
{
|
||||
parent::__construct($message);
|
||||
}
|
||||
}
|
19
vendor/laravel/serializable-closure/src/Exceptions/PhpVersionNotSupportedException.php
vendored
Normal file
19
vendor/laravel/serializable-closure/src/Exceptions/PhpVersionNotSupportedException.php
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\SerializableClosure\Exceptions;
|
||||
|
||||
use Exception;
|
||||
|
||||
class PhpVersionNotSupportedException extends Exception
|
||||
{
|
||||
/**
|
||||
* Create a new exception instance.
|
||||
*
|
||||
* @param string $message
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($message = 'PHP 7.3 is not supported.')
|
||||
{
|
||||
parent::__construct($message);
|
||||
}
|
||||
}
|
139
vendor/laravel/serializable-closure/src/SerializableClosure.php
vendored
Normal file
139
vendor/laravel/serializable-closure/src/SerializableClosure.php
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\SerializableClosure;
|
||||
|
||||
use Closure;
|
||||
use Laravel\SerializableClosure\Exceptions\InvalidSignatureException;
|
||||
use Laravel\SerializableClosure\Exceptions\PhpVersionNotSupportedException;
|
||||
use Laravel\SerializableClosure\Serializers\Signed;
|
||||
use Laravel\SerializableClosure\Signers\Hmac;
|
||||
|
||||
class SerializableClosure
|
||||
{
|
||||
/**
|
||||
* The closure's serializable.
|
||||
*
|
||||
* @var \Laravel\SerializableClosure\Contracts\Serializable
|
||||
*/
|
||||
protected $serializable;
|
||||
|
||||
/**
|
||||
* Creates a new serializable closure instance.
|
||||
*
|
||||
* @param \Closure $closure
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Closure $closure)
|
||||
{
|
||||
if (\PHP_VERSION_ID < 70400) {
|
||||
throw new PhpVersionNotSupportedException();
|
||||
}
|
||||
|
||||
$this->serializable = Serializers\Signed::$signer
|
||||
? new Serializers\Signed($closure)
|
||||
: new Serializers\Native($closure);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the closure with the given arguments.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __invoke()
|
||||
{
|
||||
if (\PHP_VERSION_ID < 70400) {
|
||||
throw new PhpVersionNotSupportedException();
|
||||
}
|
||||
|
||||
return call_user_func_array($this->serializable, func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the closure.
|
||||
*
|
||||
* @return \Closure
|
||||
*/
|
||||
public function getClosure()
|
||||
{
|
||||
if (\PHP_VERSION_ID < 70400) {
|
||||
throw new PhpVersionNotSupportedException();
|
||||
}
|
||||
|
||||
return $this->serializable->getClosure();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new unsigned serializable closure instance.
|
||||
*
|
||||
* @param Closure $closure
|
||||
* @return \Laravel\SerializableClosure\UnsignedSerializableClosure
|
||||
*/
|
||||
public static function unsigned(Closure $closure)
|
||||
{
|
||||
return new UnsignedSerializableClosure($closure);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the serializable closure secret key.
|
||||
*
|
||||
* @param string|null $secret
|
||||
* @return void
|
||||
*/
|
||||
public static function setSecretKey($secret)
|
||||
{
|
||||
Serializers\Signed::$signer = $secret
|
||||
? new Hmac($secret)
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the serializable closure secret key.
|
||||
*
|
||||
* @param \Closure|null $transformer
|
||||
* @return void
|
||||
*/
|
||||
public static function transformUseVariablesUsing($transformer)
|
||||
{
|
||||
Serializers\Native::$transformUseVariables = $transformer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the serializable closure secret key.
|
||||
*
|
||||
* @param \Closure|null $resolver
|
||||
* @return void
|
||||
*/
|
||||
public static function resolveUseVariablesUsing($resolver)
|
||||
{
|
||||
Serializers\Native::$resolveUseVariables = $resolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the serializable representation of the closure.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function __serialize()
|
||||
{
|
||||
return [
|
||||
'serializable' => $this->serializable,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the closure after serialization.
|
||||
*
|
||||
* @param array $data
|
||||
* @return void
|
||||
*
|
||||
* @throws \Laravel\SerializableClosure\Exceptions\InvalidSignatureException
|
||||
*/
|
||||
public function __unserialize($data)
|
||||
{
|
||||
if (Signed::$signer && ! $data['serializable'] instanceof Signed) {
|
||||
throw new InvalidSignatureException();
|
||||
}
|
||||
|
||||
$this->serializable = $data['serializable'];
|
||||
}
|
||||
}
|
514
vendor/laravel/serializable-closure/src/Serializers/Native.php
vendored
Normal file
514
vendor/laravel/serializable-closure/src/Serializers/Native.php
vendored
Normal file
@@ -0,0 +1,514 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\SerializableClosure\Serializers;
|
||||
|
||||
use Closure;
|
||||
use DateTimeInterface;
|
||||
use Laravel\SerializableClosure\Contracts\Serializable;
|
||||
use Laravel\SerializableClosure\SerializableClosure;
|
||||
use Laravel\SerializableClosure\Support\ClosureScope;
|
||||
use Laravel\SerializableClosure\Support\ClosureStream;
|
||||
use Laravel\SerializableClosure\Support\ReflectionClosure;
|
||||
use Laravel\SerializableClosure\Support\SelfReference;
|
||||
use Laravel\SerializableClosure\UnsignedSerializableClosure;
|
||||
use ReflectionObject;
|
||||
use UnitEnum;
|
||||
|
||||
class Native implements Serializable
|
||||
{
|
||||
/**
|
||||
* Transform the use variables before serialization.
|
||||
*
|
||||
* @var \Closure|null
|
||||
*/
|
||||
public static $transformUseVariables;
|
||||
|
||||
/**
|
||||
* Resolve the use variables after unserialization.
|
||||
*
|
||||
* @var \Closure|null
|
||||
*/
|
||||
public static $resolveUseVariables;
|
||||
|
||||
/**
|
||||
* The closure to be serialized/unserialized.
|
||||
*
|
||||
* @var \Closure
|
||||
*/
|
||||
protected $closure;
|
||||
|
||||
/**
|
||||
* The closure's reflection.
|
||||
*
|
||||
* @var \Laravel\SerializableClosure\Support\ReflectionClosure|null
|
||||
*/
|
||||
protected $reflector;
|
||||
|
||||
/**
|
||||
* The closure's code.
|
||||
*
|
||||
* @var array|null
|
||||
*/
|
||||
protected $code;
|
||||
|
||||
/**
|
||||
* The closure's reference.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $reference;
|
||||
|
||||
/**
|
||||
* The closure's scope.
|
||||
*
|
||||
* @var \Laravel\SerializableClosure\Support\ClosureScope|null
|
||||
*/
|
||||
protected $scope;
|
||||
|
||||
/**
|
||||
* The "key" that marks an array as recursive.
|
||||
*/
|
||||
const ARRAY_RECURSIVE_KEY = 'LARAVEL_SERIALIZABLE_RECURSIVE_KEY';
|
||||
|
||||
/**
|
||||
* Creates a new serializable closure instance.
|
||||
*
|
||||
* @param \Closure $closure
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Closure $closure)
|
||||
{
|
||||
$this->closure = $closure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the closure with the given arguments.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __invoke()
|
||||
{
|
||||
return call_user_func_array($this->closure, func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the closure.
|
||||
*
|
||||
* @return \Closure
|
||||
*/
|
||||
public function getClosure()
|
||||
{
|
||||
return $this->closure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the serializable representation of the closure.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function __serialize()
|
||||
{
|
||||
if ($this->scope === null) {
|
||||
$this->scope = new ClosureScope();
|
||||
$this->scope->toSerialize++;
|
||||
}
|
||||
|
||||
$this->scope->serializations++;
|
||||
|
||||
$scope = $object = null;
|
||||
$reflector = $this->getReflector();
|
||||
|
||||
if ($reflector->isBindingRequired()) {
|
||||
$object = $reflector->getClosureThis();
|
||||
|
||||
static::wrapClosures($object, $this->scope);
|
||||
}
|
||||
|
||||
if ($scope = $reflector->getClosureScopeClass()) {
|
||||
$scope = $scope->name;
|
||||
}
|
||||
|
||||
$this->reference = spl_object_hash($this->closure);
|
||||
|
||||
$this->scope[$this->closure] = $this;
|
||||
|
||||
$use = $reflector->getUseVariables();
|
||||
|
||||
if (static::$transformUseVariables) {
|
||||
$use = call_user_func(static::$transformUseVariables, $reflector->getUseVariables());
|
||||
}
|
||||
|
||||
$code = $reflector->getCode();
|
||||
|
||||
$this->mapByReference($use);
|
||||
|
||||
$data = [
|
||||
'use' => $use,
|
||||
'function' => $code,
|
||||
'scope' => $scope,
|
||||
'this' => $object,
|
||||
'self' => $this->reference,
|
||||
];
|
||||
|
||||
if (! --$this->scope->serializations && ! --$this->scope->toSerialize) {
|
||||
$this->scope = null;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the closure after serialization.
|
||||
*
|
||||
* @param array $data
|
||||
* @return void
|
||||
*/
|
||||
public function __unserialize($data)
|
||||
{
|
||||
ClosureStream::register();
|
||||
|
||||
$this->code = $data;
|
||||
unset($data);
|
||||
|
||||
$this->code['objects'] = [];
|
||||
|
||||
if ($this->code['use']) {
|
||||
$this->scope = new ClosureScope();
|
||||
|
||||
if (static::$resolveUseVariables) {
|
||||
$this->code['use'] = call_user_func(static::$resolveUseVariables, $this->code['use']);
|
||||
}
|
||||
|
||||
$this->mapPointers($this->code['use']);
|
||||
|
||||
extract($this->code['use'], EXTR_OVERWRITE | EXTR_REFS);
|
||||
|
||||
$this->scope = null;
|
||||
}
|
||||
|
||||
$this->closure = include ClosureStream::STREAM_PROTO.'://'.$this->code['function'];
|
||||
|
||||
if ($this->code['this'] === $this) {
|
||||
$this->code['this'] = null;
|
||||
}
|
||||
|
||||
$this->closure = $this->closure->bindTo($this->code['this'], $this->code['scope']);
|
||||
|
||||
if (! empty($this->code['objects'])) {
|
||||
foreach ($this->code['objects'] as $item) {
|
||||
$item['property']->setValue($item['instance'], $item['object']->getClosure());
|
||||
}
|
||||
}
|
||||
|
||||
$this->code = $this->code['function'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the given closures are serializable.
|
||||
*
|
||||
* @param mixed $data
|
||||
* @param \Laravel\SerializableClosure\Support\ClosureScope $storage
|
||||
* @return void
|
||||
*/
|
||||
public static function wrapClosures(&$data, $storage)
|
||||
{
|
||||
if ($data instanceof Closure) {
|
||||
$data = new static($data);
|
||||
} elseif (is_array($data)) {
|
||||
if (isset($data[self::ARRAY_RECURSIVE_KEY])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$data[self::ARRAY_RECURSIVE_KEY] = true;
|
||||
|
||||
foreach ($data as $key => &$value) {
|
||||
if ($key === self::ARRAY_RECURSIVE_KEY) {
|
||||
continue;
|
||||
}
|
||||
static::wrapClosures($value, $storage);
|
||||
}
|
||||
|
||||
unset($value);
|
||||
unset($data[self::ARRAY_RECURSIVE_KEY]);
|
||||
} elseif ($data instanceof \stdClass) {
|
||||
if (isset($storage[$data])) {
|
||||
$data = $storage[$data];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$data = $storage[$data] = clone $data;
|
||||
|
||||
foreach ($data as &$value) {
|
||||
static::wrapClosures($value, $storage);
|
||||
}
|
||||
|
||||
unset($value);
|
||||
} elseif (is_object($data) && ! $data instanceof static && ! $data instanceof UnitEnum) {
|
||||
if (isset($storage[$data])) {
|
||||
$data = $storage[$data];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$instance = $data;
|
||||
$reflection = new ReflectionObject($instance);
|
||||
|
||||
if (! $reflection->isUserDefined()) {
|
||||
$storage[$instance] = $data;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$storage[$instance] = $data = $reflection->newInstanceWithoutConstructor();
|
||||
|
||||
do {
|
||||
if (! $reflection->isUserDefined()) {
|
||||
break;
|
||||
}
|
||||
|
||||
foreach ($reflection->getProperties() as $property) {
|
||||
if ($property->isStatic() || ! $property->getDeclaringClass()->isUserDefined()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$property->setAccessible(true);
|
||||
|
||||
if (PHP_VERSION >= 7.4 && ! $property->isInitialized($instance)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$value = $property->getValue($instance);
|
||||
|
||||
if (is_array($value) || is_object($value)) {
|
||||
static::wrapClosures($value, $storage);
|
||||
}
|
||||
|
||||
$property->setValue($data, $value);
|
||||
}
|
||||
} while ($reflection = $reflection->getParentClass());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the closure's reflector.
|
||||
*
|
||||
* @return \Laravel\SerializableClosure\Support\ReflectionClosure
|
||||
*/
|
||||
public function getReflector()
|
||||
{
|
||||
if ($this->reflector === null) {
|
||||
$this->code = null;
|
||||
$this->reflector = new ReflectionClosure($this->closure);
|
||||
}
|
||||
|
||||
return $this->reflector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal method used to map closure pointers.
|
||||
*
|
||||
* @param mixed $data
|
||||
* @return void
|
||||
*/
|
||||
protected function mapPointers(&$data)
|
||||
{
|
||||
$scope = $this->scope;
|
||||
|
||||
if ($data instanceof static) {
|
||||
$data = &$data->closure;
|
||||
} elseif (is_array($data)) {
|
||||
if (isset($data[self::ARRAY_RECURSIVE_KEY])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$data[self::ARRAY_RECURSIVE_KEY] = true;
|
||||
|
||||
foreach ($data as $key => &$value) {
|
||||
if ($key === self::ARRAY_RECURSIVE_KEY) {
|
||||
continue;
|
||||
} elseif ($value instanceof static) {
|
||||
$data[$key] = &$value->closure;
|
||||
} elseif ($value instanceof SelfReference && $value->hash === $this->code['self']) {
|
||||
$data[$key] = &$this->closure;
|
||||
} else {
|
||||
$this->mapPointers($value);
|
||||
}
|
||||
}
|
||||
|
||||
unset($value);
|
||||
unset($data[self::ARRAY_RECURSIVE_KEY]);
|
||||
} elseif ($data instanceof \stdClass) {
|
||||
if (isset($scope[$data])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$scope[$data] = true;
|
||||
|
||||
foreach ($data as $key => &$value) {
|
||||
if ($value instanceof SelfReference && $value->hash === $this->code['self']) {
|
||||
$data->{$key} = &$this->closure;
|
||||
} elseif (is_array($value) || is_object($value)) {
|
||||
$this->mapPointers($value);
|
||||
}
|
||||
}
|
||||
|
||||
unset($value);
|
||||
} elseif (is_object($data) && ! ($data instanceof Closure)) {
|
||||
if (isset($scope[$data])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$scope[$data] = true;
|
||||
$reflection = new ReflectionObject($data);
|
||||
|
||||
do {
|
||||
if (! $reflection->isUserDefined()) {
|
||||
break;
|
||||
}
|
||||
|
||||
foreach ($reflection->getProperties() as $property) {
|
||||
if ($property->isStatic() || ! $property->getDeclaringClass()->isUserDefined()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$property->setAccessible(true);
|
||||
|
||||
if (PHP_VERSION >= 7.4 && ! $property->isInitialized($data)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$item = $property->getValue($data);
|
||||
|
||||
if ($item instanceof SerializableClosure || $item instanceof UnsignedSerializableClosure || ($item instanceof SelfReference && $item->hash === $this->code['self'])) {
|
||||
$this->code['objects'][] = [
|
||||
'instance' => $data,
|
||||
'property' => $property,
|
||||
'object' => $item instanceof SelfReference ? $this : $item,
|
||||
];
|
||||
} elseif (is_array($item) || is_object($item)) {
|
||||
$this->mapPointers($item);
|
||||
$property->setValue($data, $item);
|
||||
}
|
||||
}
|
||||
} while ($reflection = $reflection->getParentClass());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal method used to map closures by reference.
|
||||
*
|
||||
* @param mixed $data
|
||||
* @return void
|
||||
*/
|
||||
protected function mapByReference(&$data)
|
||||
{
|
||||
if ($data instanceof Closure) {
|
||||
if ($data === $this->closure) {
|
||||
$data = new SelfReference($this->reference);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (isset($this->scope[$data])) {
|
||||
$data = $this->scope[$data];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$instance = new static($data);
|
||||
|
||||
$instance->scope = $this->scope;
|
||||
|
||||
$data = $this->scope[$data] = $instance;
|
||||
} elseif (is_array($data)) {
|
||||
if (isset($data[self::ARRAY_RECURSIVE_KEY])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$data[self::ARRAY_RECURSIVE_KEY] = true;
|
||||
|
||||
foreach ($data as $key => &$value) {
|
||||
if ($key === self::ARRAY_RECURSIVE_KEY) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->mapByReference($value);
|
||||
}
|
||||
|
||||
unset($value);
|
||||
unset($data[self::ARRAY_RECURSIVE_KEY]);
|
||||
} elseif ($data instanceof \stdClass) {
|
||||
if (isset($this->scope[$data])) {
|
||||
$data = $this->scope[$data];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$instance = $data;
|
||||
$this->scope[$instance] = $data = clone $data;
|
||||
|
||||
foreach ($data as &$value) {
|
||||
$this->mapByReference($value);
|
||||
}
|
||||
|
||||
unset($value);
|
||||
} elseif (is_object($data) && ! $data instanceof SerializableClosure && ! $data instanceof UnsignedSerializableClosure) {
|
||||
if (isset($this->scope[$data])) {
|
||||
$data = $this->scope[$data];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$instance = $data;
|
||||
|
||||
if ($data instanceof DateTimeInterface) {
|
||||
$this->scope[$instance] = $data;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($data instanceof UnitEnum) {
|
||||
$this->scope[$instance] = $data;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$reflection = new ReflectionObject($data);
|
||||
|
||||
if (! $reflection->isUserDefined()) {
|
||||
$this->scope[$instance] = $data;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->scope[$instance] = $data = $reflection->newInstanceWithoutConstructor();
|
||||
|
||||
do {
|
||||
if (! $reflection->isUserDefined()) {
|
||||
break;
|
||||
}
|
||||
|
||||
foreach ($reflection->getProperties() as $property) {
|
||||
if ($property->isStatic() || ! $property->getDeclaringClass()->isUserDefined()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$property->setAccessible(true);
|
||||
|
||||
if (PHP_VERSION >= 7.4 && ! $property->isInitialized($instance)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$value = $property->getValue($instance);
|
||||
|
||||
if (is_array($value) || is_object($value)) {
|
||||
$this->mapByReference($value);
|
||||
}
|
||||
|
||||
$property->setValue($data, $value);
|
||||
}
|
||||
} while ($reflection = $reflection->getParentClass());
|
||||
}
|
||||
}
|
||||
}
|
91
vendor/laravel/serializable-closure/src/Serializers/Signed.php
vendored
Normal file
91
vendor/laravel/serializable-closure/src/Serializers/Signed.php
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\SerializableClosure\Serializers;
|
||||
|
||||
use Laravel\SerializableClosure\Contracts\Serializable;
|
||||
use Laravel\SerializableClosure\Exceptions\InvalidSignatureException;
|
||||
use Laravel\SerializableClosure\Exceptions\MissingSecretKeyException;
|
||||
|
||||
class Signed implements Serializable
|
||||
{
|
||||
/**
|
||||
* The signer that will sign and verify the closure's signature.
|
||||
*
|
||||
* @var \Laravel\SerializableClosure\Contracts\Signer|null
|
||||
*/
|
||||
public static $signer;
|
||||
|
||||
/**
|
||||
* The closure to be serialized/unserialized.
|
||||
*
|
||||
* @var \Closure
|
||||
*/
|
||||
protected $closure;
|
||||
|
||||
/**
|
||||
* Creates a new serializable closure instance.
|
||||
*
|
||||
* @param \Closure $closure
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($closure)
|
||||
{
|
||||
$this->closure = $closure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the closure with the given arguments.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __invoke()
|
||||
{
|
||||
return call_user_func_array($this->closure, func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the closure.
|
||||
*
|
||||
* @return \Closure
|
||||
*/
|
||||
public function getClosure()
|
||||
{
|
||||
return $this->closure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the serializable representation of the closure.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function __serialize()
|
||||
{
|
||||
if (! static::$signer) {
|
||||
throw new MissingSecretKeyException();
|
||||
}
|
||||
|
||||
return static::$signer->sign(
|
||||
serialize(new Native($this->closure))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the closure after serialization.
|
||||
*
|
||||
* @param array $signature
|
||||
* @return void
|
||||
*
|
||||
* @throws \Laravel\SerializableClosure\Exceptions\InvalidSignatureException
|
||||
*/
|
||||
public function __unserialize($signature)
|
||||
{
|
||||
if (static::$signer && ! static::$signer->verify($signature)) {
|
||||
throw new InvalidSignatureException();
|
||||
}
|
||||
|
||||
/** @var \Laravel\SerializableClosure\Contracts\Serializable $serializable */
|
||||
$serializable = unserialize($signature['serializable']);
|
||||
|
||||
$this->closure = $serializable->getClosure();
|
||||
}
|
||||
}
|
53
vendor/laravel/serializable-closure/src/Signers/Hmac.php
vendored
Normal file
53
vendor/laravel/serializable-closure/src/Signers/Hmac.php
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\SerializableClosure\Signers;
|
||||
|
||||
use Laravel\SerializableClosure\Contracts\Signer;
|
||||
|
||||
class Hmac implements Signer
|
||||
{
|
||||
/**
|
||||
* The secret key.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $secret;
|
||||
|
||||
/**
|
||||
* Creates a new signer instance.
|
||||
*
|
||||
* @param string $secret
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($secret)
|
||||
{
|
||||
$this->secret = $secret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign the given serializable.
|
||||
*
|
||||
* @param string $serialized
|
||||
* @return array
|
||||
*/
|
||||
public function sign($serialized)
|
||||
{
|
||||
return [
|
||||
'serializable' => $serialized,
|
||||
'hash' => base64_encode(hash_hmac('sha256', $serialized, $this->secret, true)),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the given signature.
|
||||
*
|
||||
* @param array $signature
|
||||
* @return bool
|
||||
*/
|
||||
public function verify($signature)
|
||||
{
|
||||
return hash_equals(base64_encode(
|
||||
hash_hmac('sha256', $signature['serializable'], $this->secret, true)
|
||||
), $signature['hash']);
|
||||
}
|
||||
}
|
22
vendor/laravel/serializable-closure/src/Support/ClosureScope.php
vendored
Normal file
22
vendor/laravel/serializable-closure/src/Support/ClosureScope.php
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\SerializableClosure\Support;
|
||||
|
||||
use SplObjectStorage;
|
||||
|
||||
class ClosureScope extends SplObjectStorage
|
||||
{
|
||||
/**
|
||||
* The number of serializations in current scope.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $serializations = 0;
|
||||
|
||||
/**
|
||||
* The number of closures that have to be serialized.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $toSerialize = 0;
|
||||
}
|
179
vendor/laravel/serializable-closure/src/Support/ClosureStream.php
vendored
Normal file
179
vendor/laravel/serializable-closure/src/Support/ClosureStream.php
vendored
Normal file
@@ -0,0 +1,179 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\SerializableClosure\Support;
|
||||
|
||||
#[\AllowDynamicProperties]
|
||||
class ClosureStream
|
||||
{
|
||||
/**
|
||||
* The stream protocol.
|
||||
*/
|
||||
const STREAM_PROTO = 'laravel-serializable-closure';
|
||||
|
||||
/**
|
||||
* Checks if this stream is registered.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected static $isRegistered = false;
|
||||
|
||||
/**
|
||||
* The stream content.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $content;
|
||||
|
||||
/**
|
||||
* The stream content.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $length;
|
||||
|
||||
/**
|
||||
* The stream pointer.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $pointer = 0;
|
||||
|
||||
/**
|
||||
* Opens file or URL.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $mode
|
||||
* @param string $options
|
||||
* @param string|null $opened_path
|
||||
* @return bool
|
||||
*/
|
||||
public function stream_open($path, $mode, $options, &$opened_path)
|
||||
{
|
||||
$this->content = "<?php\nreturn ".substr($path, strlen(static::STREAM_PROTO.'://')).';';
|
||||
$this->length = strlen($this->content);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read from stream.
|
||||
*
|
||||
* @param int $count
|
||||
* @return string
|
||||
*/
|
||||
public function stream_read($count)
|
||||
{
|
||||
$value = substr($this->content, $this->pointer, $count);
|
||||
|
||||
$this->pointer += $count;
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for end-of-file on a file pointer.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function stream_eof()
|
||||
{
|
||||
return $this->pointer >= $this->length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change stream options.
|
||||
*
|
||||
* @param int $option
|
||||
* @param int $arg1
|
||||
* @param int $arg2
|
||||
* @return bool
|
||||
*/
|
||||
public function stream_set_option($option, $arg1, $arg2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve information about a file resource.
|
||||
*
|
||||
* @return array|bool
|
||||
*/
|
||||
public function stream_stat()
|
||||
{
|
||||
$stat = stat(__FILE__);
|
||||
// @phpstan-ignore-next-line
|
||||
$stat[7] = $stat['size'] = $this->length;
|
||||
|
||||
return $stat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve information about a file.
|
||||
*
|
||||
* @param string $path
|
||||
* @param int $flags
|
||||
* @return array|bool
|
||||
*/
|
||||
public function url_stat($path, $flags)
|
||||
{
|
||||
$stat = stat(__FILE__);
|
||||
// @phpstan-ignore-next-line
|
||||
$stat[7] = $stat['size'] = $this->length;
|
||||
|
||||
return $stat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Seeks to specific location in a stream.
|
||||
*
|
||||
* @param int $offset
|
||||
* @param int $whence
|
||||
* @return bool
|
||||
*/
|
||||
public function stream_seek($offset, $whence = SEEK_SET)
|
||||
{
|
||||
$crt = $this->pointer;
|
||||
|
||||
switch ($whence) {
|
||||
case SEEK_SET:
|
||||
$this->pointer = $offset;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
$this->pointer += $offset;
|
||||
break;
|
||||
case SEEK_END:
|
||||
$this->pointer = $this->length + $offset;
|
||||
break;
|
||||
}
|
||||
|
||||
if ($this->pointer < 0 || $this->pointer >= $this->length) {
|
||||
$this->pointer = $crt;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the current position of a stream.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function stream_tell()
|
||||
{
|
||||
return $this->pointer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the stream.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function register()
|
||||
{
|
||||
if (! static::$isRegistered) {
|
||||
static::$isRegistered = stream_wrapper_register(static::STREAM_PROTO, __CLASS__);
|
||||
}
|
||||
}
|
||||
}
|
1198
vendor/laravel/serializable-closure/src/Support/ReflectionClosure.php
vendored
Normal file
1198
vendor/laravel/serializable-closure/src/Support/ReflectionClosure.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
24
vendor/laravel/serializable-closure/src/Support/SelfReference.php
vendored
Normal file
24
vendor/laravel/serializable-closure/src/Support/SelfReference.php
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\SerializableClosure\Support;
|
||||
|
||||
class SelfReference
|
||||
{
|
||||
/**
|
||||
* The unique hash representing the object.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $hash;
|
||||
|
||||
/**
|
||||
* Creates a new self reference instance.
|
||||
*
|
||||
* @param string $hash
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($hash)
|
||||
{
|
||||
$this->hash = $hash;
|
||||
}
|
||||
}
|
82
vendor/laravel/serializable-closure/src/UnsignedSerializableClosure.php
vendored
Normal file
82
vendor/laravel/serializable-closure/src/UnsignedSerializableClosure.php
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\SerializableClosure;
|
||||
|
||||
use Closure;
|
||||
use Laravel\SerializableClosure\Exceptions\PhpVersionNotSupportedException;
|
||||
|
||||
class UnsignedSerializableClosure
|
||||
{
|
||||
/**
|
||||
* The closure's serializable.
|
||||
*
|
||||
* @var \Laravel\SerializableClosure\Contracts\Serializable
|
||||
*/
|
||||
protected $serializable;
|
||||
|
||||
/**
|
||||
* Creates a new serializable closure instance.
|
||||
*
|
||||
* @param \Closure $closure
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Closure $closure)
|
||||
{
|
||||
if (\PHP_VERSION_ID < 70400) {
|
||||
throw new PhpVersionNotSupportedException();
|
||||
}
|
||||
|
||||
$this->serializable = new Serializers\Native($closure);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the closure with the given arguments.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __invoke()
|
||||
{
|
||||
if (\PHP_VERSION_ID < 70400) {
|
||||
throw new PhpVersionNotSupportedException();
|
||||
}
|
||||
|
||||
return call_user_func_array($this->serializable, func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the closure.
|
||||
*
|
||||
* @return \Closure
|
||||
*/
|
||||
public function getClosure()
|
||||
{
|
||||
if (\PHP_VERSION_ID < 70400) {
|
||||
throw new PhpVersionNotSupportedException();
|
||||
}
|
||||
|
||||
return $this->serializable->getClosure();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the serializable representation of the closure.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function __serialize()
|
||||
{
|
||||
return [
|
||||
'serializable' => $this->serializable,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the closure after serialization.
|
||||
*
|
||||
* @param array $data
|
||||
* @return void
|
||||
*/
|
||||
public function __unserialize($data)
|
||||
{
|
||||
$this->serializable = $data['serializable'];
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user