- 框架初始化
 - 安装插件
 - 修复PHP8.4报错
This commit is contained in:
2025-04-19 17:21:20 +08:00
commit c6a4e1f5f6
5306 changed files with 967782 additions and 0 deletions

View File

@@ -0,0 +1,104 @@
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Utils\Serializer;
use Doctrine\Instantiator\Instantiator;
use Hyperf\Di\ReflectionManager;
use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
class ExceptionNormalizer implements NormalizerInterface, DenormalizerInterface, CacheableSupportsMethodInterface
{
/**
* @var null|Instantiator
*/
protected $instantiator;
public function denormalize($data, ?string $class, ?string $format = null, ?array $context = [])
{
if (is_string($data)) {
$ex = unserialize($data);
if ($ex instanceof \Throwable) {
return $ex;
}
// Retry handle it if the exception not instanceof \Throwable.
$data = $ex;
}
if (is_array($data) && isset($data['message'], $data['code'])) {
try {
$exception = $this->getInstantiator()->instantiate($class);
foreach (['code', 'message', 'file', 'line'] as $attribute) {
if (isset($data[$attribute])) {
$property = ReflectionManager::reflectProperty($class, $attribute);
$property->setAccessible(true);
$property->setValue($exception, $data[$attribute]);
}
}
return $exception;
} catch (\ReflectionException $e) {
return new \RuntimeException(sprintf(
'Bad data %s: %s',
$data['class'],
$data['message']
), $data['code']);
} catch (\TypeError $e) {
return new \RuntimeException(sprintf(
'Uncaught data %s: %s',
$data['class'],
$data['message']
), $data['code']);
}
}
return new \RuntimeException('Bad data data: ' . json_encode($data));
}
public function supportsDenormalization($data, $type, $format = null)
{
return class_exists($type) && is_a($type, \Throwable::class, true);
}
public function normalize($object, ?string $format = null, ?array $context = [])
{
if ($object instanceof \Serializable) {
return serialize($object);
}
/* @var \Throwable $object */
return [
'message' => $object->getMessage(),
'code' => $object->getCode(),
'file' => $object->getFile(),
'line' => $object->getLine(),
];
}
public function supportsNormalization($data, ?string $format = null)
{
return $data instanceof \Throwable;
}
public function hasCacheableSupportsMethod(): bool
{
return \get_class($this) === __CLASS__;
}
protected function getInstantiator(): Instantiator
{
if ($this->instantiator instanceof Instantiator) {
return $this->instantiator;
}
return $this->instantiator = new Instantiator();
}
}

View File

@@ -0,0 +1,64 @@
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Utils\Serializer;
use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use function get_class;
use function is_scalar;
class ScalarNormalizer implements NormalizerInterface, DenormalizerInterface, CacheableSupportsMethodInterface
{
public function hasCacheableSupportsMethod(): bool
{
return get_class($this) === __CLASS__;
}
public function denormalize($data, ?string $class, ?string $format = null, ?array $context = [])
{
switch ($class) {
case 'int':
return (int) $data;
case 'string':
return (string) $data;
case 'float':
return (float) $data;
case 'bool':
return (bool) $data;
default:
return $data;
}
}
public function supportsDenormalization($data, $type, ?string $format = null)
{
return in_array($type, [
'int',
'string',
'float',
'bool',
'mixed',
'array', // TODO: Symfony\Component\Serializer\Normalizer\ArrayDenormalizer not support array, so it denormalized in ScalarNormalizer.
]);
}
public function normalize($object, ?string $format = null, ?array $context = [])
{
return $object;
}
public function supportsNormalization($data, ?string $format = null)
{
return is_scalar($data);
}
}

View File

@@ -0,0 +1,312 @@
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Utils\Serializer;
use Hyperf\Contract\NormalizerInterface as Normalizer;
use Symfony\Component\Serializer\Encoder;
use Symfony\Component\Serializer\Encoder\ChainDecoder;
use Symfony\Component\Serializer\Encoder\ChainEncoder;
use Symfony\Component\Serializer\Encoder\ContextAwareDecoderInterface;
use Symfony\Component\Serializer\Encoder\ContextAwareEncoderInterface;
use Symfony\Component\Serializer\Encoder\DecoderInterface;
use Symfony\Component\Serializer\Encoder\EncoderInterface;
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
use Symfony\Component\Serializer\Exception\LogicException;
use Symfony\Component\Serializer\Exception\NotEncodableValueException;
use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface;
use Symfony\Component\Serializer\Normalizer\ContextAwareDenormalizerInterface;
use Symfony\Component\Serializer\Normalizer\ContextAwareNormalizerInterface;
use Symfony\Component\Serializer\Normalizer\DenormalizerAwareInterface;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Symfony\Component\Serializer\SerializerAwareInterface;
use Symfony\Component\Serializer\SerializerInterface;
/**
* Serializer serializes and deserializes data.
*
* objects are turned into arrays by normalizers.
* arrays are turned into various output formats by encoders.
*
* $serializer->serialize($obj, 'xml')
* $serializer->decode($data, 'xml')
* $serializer->denormalize($data, 'Class', 'xml')
*/
class Serializer implements Normalizer, SerializerInterface, ContextAwareNormalizerInterface, ContextAwareDenormalizerInterface, ContextAwareEncoderInterface, ContextAwareDecoderInterface
{
private const SCALAR_TYPES = [
'int' => true,
'bool' => true,
'float' => true,
'string' => true,
];
/**
* @var Encoder\ChainEncoder
*/
protected $encoder;
/**
* @var Encoder\ChainDecoder
*/
protected $decoder;
private $normalizers = [];
private $denormalizerCache = [];
private $normalizerCache = [];
/**
* @param (NormalizerInterface|DenormalizerInterface|mixed)[] $normalizers
* @param (EncoderInterface|DecoderInterface|mixed)[] $encoders
*/
public function __construct(array $normalizers = [], ?array $encoders = [])
{
foreach ($normalizers as $normalizer) {
if ($normalizer instanceof SerializerAwareInterface) {
$normalizer->setSerializer($this);
}
if ($normalizer instanceof DenormalizerAwareInterface) {
$normalizer->setDenormalizer($this);
}
if ($normalizer instanceof NormalizerAwareInterface) {
$normalizer->setNormalizer($this);
}
if (! ($normalizer instanceof NormalizerInterface || $normalizer instanceof DenormalizerInterface)) {
throw new InvalidArgumentException(sprintf('The class "%s" neither implements "%s" nor "%s".', get_debug_type($normalizer), NormalizerInterface::class, DenormalizerInterface::class));
}
}
$this->normalizers = $normalizers;
$decoders = [];
$realEncoders = [];
foreach ($encoders as $encoder) {
if ($encoder instanceof SerializerAwareInterface) {
$encoder->setSerializer($this);
}
if ($encoder instanceof DecoderInterface) {
$decoders[] = $encoder;
}
if ($encoder instanceof EncoderInterface) {
$realEncoders[] = $encoder;
}
if (! ($encoder instanceof EncoderInterface || $encoder instanceof DecoderInterface)) {
throw new InvalidArgumentException(sprintf('The class "%s" neither implements "%s" nor "%s".', get_debug_type($encoder), EncoderInterface::class, DecoderInterface::class));
}
}
$this->encoder = new ChainEncoder($realEncoders);
$this->decoder = new ChainDecoder($decoders);
}
final public function serialize($data, ?string $format, ?array $context = []): string
{
if (! $this->supportsEncoding($format, $context)) {
throw new NotEncodableValueException(sprintf('Serialization for the format "%s" is not supported.', $format));
}
if ($this->encoder->needsNormalization($format, $context)) {
$data = $this->normalize($data, $format, $context);
}
return $this->encode($data, $format, $context);
}
final public function deserialize($data, ?string $type, ?string $format, ?array $context = [])
{
if (! $this->supportsDecoding($format, $context)) {
throw new NotEncodableValueException(sprintf('Deserialization for the format "%s" is not supported.', $format));
}
$data = $this->decode($data, $format, $context);
return $this->denormalize($data, $type, $format, $context);
}
public function normalize($data, ?string $format = null, ?array $context = [])
{
// If a normalizer supports the given data, use it
if ($normalizer = $this->getNormalizer($data, $format, $context)) {
return $normalizer->normalize($data, $format, $context);
}
if ($data === null || is_scalar($data)) {
return $data;
}
if (\is_array($data) || $data instanceof \Traversable) {
if ($data instanceof \Countable && $data->count() === 0) {
return $data;
}
$normalized = [];
foreach ($data as $key => $val) {
$normalized[$key] = $this->normalize($val, $format, $context);
}
return $normalized;
}
if (\is_object($data)) {
if (! $this->normalizers) {
throw new LogicException('You must register at least one normalizer to be able to normalize objects.');
}
throw new NotNormalizableValueException(sprintf('Could not normalize object of type "%s", no supporting normalizer found.', get_debug_type($data)));
}
throw new NotNormalizableValueException('An unexpected value could not be normalized: ' . (! \is_resource($data) ? var_export($data, true) : sprintf('%s resource', get_resource_type($data))));
}
/**
* @param mixed $data
* @throws NotNormalizableValueException
*/
public function denormalize($data, ?string $type, ?string $format = null, ?array $context = [])
{
if (isset(self::SCALAR_TYPES[$type])) {
if (is_scalar($data)) {
switch ($type) {
case 'int':
return (int) $data;
case 'bool':
return (bool) $data;
case 'float':
return (float) $data;
case 'string':
return (string) $data;
}
}
}
if (! $this->normalizers) {
throw new LogicException('You must register at least one normalizer to be able to denormalize objects.');
}
if ($normalizer = $this->getDenormalizer($data, $type, $format, $context)) {
return $normalizer->denormalize($data, $type, $format, $context);
}
throw new NotNormalizableValueException(sprintf('Could not denormalize object of type "%s", no supporting normalizer found.', $type));
}
public function supportsNormalization($data, ?string $format = null, ?array $context = [])
{
return $this->getNormalizer($data, $format, $context) !== null;
}
public function supportsDenormalization($data, ?string $type, ?string $format = null, ?array $context = [])
{
return isset(self::SCALAR_TYPES[$type]) || $this->getDenormalizer($data, $type, $format, $context) !== null;
}
final public function encode($data, ?string $format, ?array $context = [])
{
return $this->encoder->encode($data, $format, $context);
}
final public function decode(string $data, ?string $format, ?array $context = [])
{
return $this->decoder->decode($data, $format, $context);
}
public function supportsEncoding(string $format, ?array $context = [])
{
return $this->encoder->supportsEncoding($format, $context);
}
public function supportsDecoding(string $format, ?array $context = [])
{
return $this->decoder->supportsDecoding($format, $context);
}
/**
* Returns a matching normalizer.
*
* @param mixed $data Data to get the serializer for
* @param string $format Format name, present to give the option to normalizers to act differently based on formats
* @param array $context Options available to the normalizer
*/
private function getNormalizer($data, ?string $format, ?array $context): ?NormalizerInterface
{
$type = \is_object($data) ? \get_class($data) : 'native-' . \gettype($data);
if (! isset($this->normalizerCache[$format][$type])) {
$this->normalizerCache[$format][$type] = [];
foreach ($this->normalizers as $k => $normalizer) {
if (! $normalizer instanceof NormalizerInterface) {
continue;
}
if (! $normalizer instanceof CacheableSupportsMethodInterface || ! $normalizer->hasCacheableSupportsMethod()) {
$this->normalizerCache[$format][$type][$k] = false;
} elseif ($normalizer->supportsNormalization($data, $format)) {
$this->normalizerCache[$format][$type][$k] = true;
break;
}
}
}
foreach ($this->normalizerCache[$format][$type] as $k => $cached) {
$normalizer = $this->normalizers[$k];
if ($cached || $normalizer->supportsNormalization($data, $format, $context)) {
return $normalizer;
}
}
return null;
}
/**
* Returns a matching denormalizer.
*
* @param mixed $data Data to restore
* @param string $class The expected class to instantiate
* @param string $format Format name, present to give the option to normalizers to act differently based on formats
* @param array $context Options available to the denormalizer
*/
private function getDenormalizer($data, ?string $class, ?string $format, ?array $context): ?DenormalizerInterface
{
if (! isset($this->denormalizerCache[$format][$class])) {
$this->denormalizerCache[$format][$class] = [];
foreach ($this->normalizers as $k => $normalizer) {
if (! $normalizer instanceof DenormalizerInterface) {
continue;
}
if (! $normalizer instanceof CacheableSupportsMethodInterface || ! $normalizer->hasCacheableSupportsMethod()) {
$this->denormalizerCache[$format][$class][$k] = false;
} elseif ($normalizer->supportsDenormalization(null, $class, $format)) {
$this->denormalizerCache[$format][$class][$k] = true;
break;
}
}
}
foreach ($this->denormalizerCache[$format][$class] as $k => $cached) {
$normalizer = $this->normalizers[$k];
if ($cached || $normalizer->supportsDenormalization($data, $class, $format, $context)) {
return $normalizer;
}
}
return null;
}
}

View File

@@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Utils\Serializer;
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;
class SerializerFactory
{
/**
* @var string
*/
protected $serializer;
public function __construct(string $serializer = Serializer::class)
{
$this->serializer = $serializer;
}
public function __invoke()
{
return new $this->serializer([
new ExceptionNormalizer(),
new ObjectNormalizer(),
new ArrayDenormalizer(),
new ScalarNormalizer(),
]);
}
}

View File

@@ -0,0 +1,40 @@
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Utils\Serializer;
use Hyperf\Contract\NormalizerInterface;
class SimpleNormalizer implements NormalizerInterface
{
public function normalize($object)
{
return $object;
}
public function denormalize($data, ?string $class)
{
switch ($class) {
case 'int':
return (int) $data;
case 'string':
return (string) $data;
case 'float':
return (float) $data;
case 'array':
return (array) $data;
case 'bool':
return (bool) $data;
default:
return $data;
}
}
}

View File

@@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Utils\Serializer;
use Hyperf\Contract\NormalizerInterface;
use Symfony\Component\Serializer\Serializer;
class SymfonyNormalizer implements NormalizerInterface
{
/**
* @var Serializer
*/
protected $serializer;
public function __construct(Serializer $serializer)
{
$this->serializer = $serializer;
}
public function normalize($object)
{
return $this->serializer->normalize($object);
}
public function denormalize($data, ?string $class)
{
return $this->serializer->denormalize($data, $class);
}
}