mirror of
https://gitlab.com/signalytic/client-external/streamline/streamline-emr.git
synced 2026-09-13 11:41:31 +00:00
Import latest app updates from streamline
An updated set of source files and initialization was provided by streamline to address issues observed during initial testing. These files have been updated in order to generate a new set of app images.
This commit is contained in:
@@ -1,21 +0,0 @@
|
||||
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.
|
||||
@@ -1,73 +0,0 @@
|
||||
# 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).
|
||||
@@ -1,52 +0,0 @@
|
||||
{
|
||||
"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
@@ -1,20 +0,0 @@
|
||||
<?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
@@ -1,22 +0,0 @@
|
||||
<?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
@@ -1,19 +0,0 @@
|
||||
<?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
@@ -1,19 +0,0 @@
|
||||
<?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
@@ -1,19 +0,0 @@
|
||||
<?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
@@ -1,139 +0,0 @@
|
||||
<?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
@@ -1,514 +0,0 @@
|
||||
<?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
@@ -1,91 +0,0 @@
|
||||
<?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
@@ -1,53 +0,0 @@
|
||||
<?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
@@ -1,22 +0,0 @@
|
||||
<?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
@@ -1,179 +0,0 @@
|
||||
<?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__);
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
-1198
File diff suppressed because it is too large
Load Diff
-24
@@ -1,24 +0,0 @@
|
||||
<?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;
|
||||
}
|
||||
}
|
||||
Vendored
-82
@@ -1,82 +0,0 @@
|
||||
<?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