default services conflit ?
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Annotation;
|
||||
|
||||
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Annotation class for @DiscriminatorMap().
|
||||
*
|
||||
* @Annotation
|
||||
* @Target({"CLASS"})
|
||||
*
|
||||
* @author Samuel Roze <samuel.roze@gmail.com>
|
||||
*/
|
||||
class DiscriminatorMap
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $typeProperty;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $mapping;
|
||||
|
||||
/**
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function __construct(array $data)
|
||||
{
|
||||
if (empty($data['typeProperty'])) {
|
||||
throw new InvalidArgumentException(sprintf('Parameter "typeProperty" of annotation "%s" cannot be empty.', static::class));
|
||||
}
|
||||
|
||||
if (empty($data['mapping'])) {
|
||||
throw new InvalidArgumentException(sprintf('Parameter "mapping" of annotation "%s" cannot be empty.', static::class));
|
||||
}
|
||||
|
||||
$this->typeProperty = $data['typeProperty'];
|
||||
$this->mapping = $data['mapping'];
|
||||
}
|
||||
|
||||
public function getTypeProperty(): string
|
||||
{
|
||||
return $this->typeProperty;
|
||||
}
|
||||
|
||||
public function getMapping(): array
|
||||
{
|
||||
return $this->mapping;
|
||||
}
|
||||
}
|
57
old.vendor/symfony/serializer/Annotation/Groups.php
Normal file
57
old.vendor/symfony/serializer/Annotation/Groups.php
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Annotation;
|
||||
|
||||
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Annotation class for @Groups().
|
||||
*
|
||||
* @Annotation
|
||||
* @Target({"PROPERTY", "METHOD"})
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
class Groups
|
||||
{
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private $groups;
|
||||
|
||||
/**
|
||||
* @param string[] $groups
|
||||
*/
|
||||
public function __construct(array $data)
|
||||
{
|
||||
if (!isset($data['value']) || !$data['value']) {
|
||||
throw new InvalidArgumentException(sprintf('Parameter of annotation "%s" cannot be empty.', static::class));
|
||||
}
|
||||
|
||||
$value = (array) $data['value'];
|
||||
foreach ($value as $group) {
|
||||
if (!\is_string($group)) {
|
||||
throw new InvalidArgumentException(sprintf('Parameter of annotation "%s" must be a string or an array of strings.', static::class));
|
||||
}
|
||||
}
|
||||
|
||||
$this->groups = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getGroups()
|
||||
{
|
||||
return $this->groups;
|
||||
}
|
||||
}
|
48
old.vendor/symfony/serializer/Annotation/MaxDepth.php
Normal file
48
old.vendor/symfony/serializer/Annotation/MaxDepth.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Annotation;
|
||||
|
||||
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Annotation class for @MaxDepth().
|
||||
*
|
||||
* @Annotation
|
||||
* @Target({"PROPERTY", "METHOD"})
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
class MaxDepth
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $maxDepth;
|
||||
|
||||
public function __construct(array $data)
|
||||
{
|
||||
if (!isset($data['value'])) {
|
||||
throw new InvalidArgumentException(sprintf('Parameter of annotation "%s" should be set.', static::class));
|
||||
}
|
||||
|
||||
if (!\is_int($data['value']) || $data['value'] <= 0) {
|
||||
throw new InvalidArgumentException(sprintf('Parameter of annotation "%s" must be a positive integer.', static::class));
|
||||
}
|
||||
|
||||
$this->maxDepth = $data['value'];
|
||||
}
|
||||
|
||||
public function getMaxDepth()
|
||||
{
|
||||
return $this->maxDepth;
|
||||
}
|
||||
}
|
48
old.vendor/symfony/serializer/Annotation/SerializedName.php
Normal file
48
old.vendor/symfony/serializer/Annotation/SerializedName.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Annotation;
|
||||
|
||||
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Annotation class for @SerializedName().
|
||||
*
|
||||
* @Annotation
|
||||
* @Target({"PROPERTY", "METHOD"})
|
||||
*
|
||||
* @author Fabien Bourigault <bourigaultfabien@gmail.com>
|
||||
*/
|
||||
final class SerializedName
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $serializedName;
|
||||
|
||||
public function __construct(array $data)
|
||||
{
|
||||
if (!isset($data['value'])) {
|
||||
throw new InvalidArgumentException(sprintf('Parameter of annotation "%s" should be set.', static::class));
|
||||
}
|
||||
|
||||
if (!\is_string($data['value']) || empty($data['value'])) {
|
||||
throw new InvalidArgumentException(sprintf('Parameter of annotation "%s" must be a non-empty string.', static::class));
|
||||
}
|
||||
|
||||
$this->serializedName = $data['value'];
|
||||
}
|
||||
|
||||
public function getSerializedName(): string
|
||||
{
|
||||
return $this->serializedName;
|
||||
}
|
||||
}
|
206
old.vendor/symfony/serializer/CHANGELOG.md
Normal file
206
old.vendor/symfony/serializer/CHANGELOG.md
Normal file
@@ -0,0 +1,206 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
4.4.0
|
||||
-----
|
||||
|
||||
* deprecated the `XmlEncoder::TYPE_CASE_ATTRIBUTES` constant, use `XmlEncoder::TYPE_CAST_ATTRIBUTES` instead
|
||||
* added option to output a UTF-8 BOM in CSV encoder via `CsvEncoder::OUTPUT_UTF8_BOM_KEY` context option
|
||||
* added `ProblemNormalizer` to normalize errors according to the API Problem spec (RFC 7807)
|
||||
|
||||
4.3.0
|
||||
-----
|
||||
|
||||
* added the list of constraint violations' parameters in `ConstraintViolationListNormalizer`
|
||||
* added support for serializing `DateTimeZone` objects
|
||||
* added a `deep_object_to_populate` context option to recursive denormalize on `object_to_populate` object.
|
||||
|
||||
4.2.0
|
||||
-----
|
||||
|
||||
* using the default context is the new recommended way to configure normalizers and encoders
|
||||
* added a `skip_null_values` context option to not serialize properties with a `null` values
|
||||
* `AbstractNormalizer::handleCircularReference` is now final and receives
|
||||
two optional extra arguments: the format and the context
|
||||
* added support for XML comment encoding (encoding `['#comment' => ' foo ']` results `<!-- foo -->`)
|
||||
* added optional `int[] $encoderIgnoredNodeTypes` argument to `XmlEncoder::__construct`
|
||||
to configure node types to be ignored during encoding
|
||||
* added `AdvancedNameConverterInterface` to access the class,
|
||||
the format and the context in a name converter
|
||||
* the `AbstractNormalizer::handleCircularReference()` method will have two new `$format`
|
||||
and `$context` arguments in version 5.0, not defining them is deprecated
|
||||
* deprecated creating a `Serializer` with normalizers which do not implement
|
||||
either `NormalizerInterface` or `DenormalizerInterface`
|
||||
* deprecated creating a `Serializer` with normalizers which do not implement
|
||||
either `NormalizerInterface` or `DenormalizerInterface`
|
||||
* deprecated creating a `Serializer` with encoders which do not implement
|
||||
either `EncoderInterface` or `DecoderInterface`
|
||||
* added the optional `$objectClassResolver` argument in `AbstractObjectNormalizer`
|
||||
and `ObjectNormalizer` constructor
|
||||
* added `MetadataAwareNameConverter` to configure the serialized name of properties through metadata
|
||||
* `YamlEncoder` now handles the `.yml` extension too
|
||||
* `AbstractNormalizer::$circularReferenceLimit`, `AbstractNormalizer::$circularReferenceHandler`,
|
||||
`AbstractNormalizer::$callbacks`, `AbstractNormalizer::$ignoredAttributes`,
|
||||
`AbstractNormalizer::$camelizedAttributes`, `AbstractNormalizer::setCircularReferenceLimit()`,
|
||||
`AbstractNormalizer::setCircularReferenceHandler()`, `AbstractNormalizer::setCallbacks()` and
|
||||
`AbstractNormalizer::setIgnoredAttributes()` are deprecated, use the default context instead.
|
||||
* `AbstractObjectNormalizer::$maxDepthHandler` and `AbstractObjectNormalizer::setMaxDepthHandler()`
|
||||
are deprecated, use the default context instead.
|
||||
* passing configuration options directly to the constructor of `CsvEncoder`, `JsonDecode` and
|
||||
`XmlEncoder` is deprecated since Symfony 4.2, use the default context instead.
|
||||
|
||||
4.1.0
|
||||
-----
|
||||
|
||||
* added `CacheableSupportsMethodInterface` for normalizers and denormalizers that use
|
||||
only the type and the format in their `supports*()` methods
|
||||
* added `MissingConstructorArgumentsException` new exception for deserialization failure
|
||||
of objects that needs data insertion in constructor
|
||||
* added an optional `default_constructor_arguments` option of context to specify a default data in
|
||||
case the object is not initializable by its constructor because of data missing
|
||||
* added optional `bool $escapeFormulas = false` argument to `CsvEncoder::__construct`
|
||||
* added `AbstractObjectNormalizer::setMaxDepthHandler` to set a handler to call when the configured
|
||||
maximum depth is reached
|
||||
* added optional `int[] $ignoredNodeTypes` argument to `XmlEncoder::__construct`. XML decoding now
|
||||
ignores comment node types by default.
|
||||
* added `ConstraintViolationListNormalizer`
|
||||
|
||||
4.0.0
|
||||
-----
|
||||
|
||||
* removed the `SerializerAwareEncoder` and `SerializerAwareNormalizer` classes,
|
||||
use the `SerializerAwareTrait` instead
|
||||
* removed the `Serializer::$normalizerCache` and `Serializer::$denormalizerCache`
|
||||
properties
|
||||
* added an optional `string $format = null` argument to `AbstractNormalizer::instantiateObject`
|
||||
* added an optional `array $context = []` to `Serializer::supportsNormalization`, `Serializer::supportsDenormalization`,
|
||||
`Serializer::supportsEncoding` and `Serializer::supportsDecoding`
|
||||
|
||||
3.4.0
|
||||
-----
|
||||
|
||||
* added `AbstractObjectNormalizer::DISABLE_TYPE_ENFORCEMENT` context option
|
||||
to disable throwing an `UnexpectedValueException` on a type mismatch
|
||||
* added support for serializing `DateInterval` objects
|
||||
* added getter for extra attributes in `ExtraAttributesException`
|
||||
* improved `CsvEncoder` to handle variable nested structures
|
||||
* CSV headers can be passed to the `CsvEncoder` via the `csv_headers` serialization context variable
|
||||
* added `$context` when checking for encoding, decoding and normalizing in `Serializer`
|
||||
|
||||
3.3.0
|
||||
-----
|
||||
|
||||
* added `SerializerPass`
|
||||
|
||||
3.1.0
|
||||
-----
|
||||
|
||||
* added support for serializing objects that implement `JsonSerializable`
|
||||
* added the `DenormalizerAwareTrait` and `NormalizerAwareTrait` traits to
|
||||
support normalizer/denormalizer awareness
|
||||
* added the `DenormalizerAwareInterface` and `NormalizerAwareInterface`
|
||||
interfaces to support normalizer/denormalizer awareness
|
||||
* added a PSR-6 compatible adapter for caching metadata
|
||||
* added a `MaxDepth` option to limit the depth of the object graph when
|
||||
serializing objects
|
||||
* added support for serializing `SplFileInfo` objects
|
||||
* added support for serializing objects that implement `DateTimeInterface`
|
||||
* added `AbstractObjectNormalizer` as a base class for normalizers that deal
|
||||
with objects
|
||||
* added support to relation deserialization
|
||||
|
||||
2.7.0
|
||||
-----
|
||||
|
||||
* added support for serialization and deserialization groups including
|
||||
annotations, XML and YAML mapping.
|
||||
* added `AbstractNormalizer` to factorise code and ease normalizers development
|
||||
* added circular references handling for `PropertyNormalizer`
|
||||
* added support for a context key called `object_to_populate` in `AbstractNormalizer`
|
||||
to reuse existing objects in the deserialization process
|
||||
* added `NameConverterInterface` and `CamelCaseToSnakeCaseNameConverter`
|
||||
* [DEPRECATION] `GetSetMethodNormalizer::setCamelizedAttributes()` and
|
||||
`PropertyNormalizer::setCamelizedAttributes()` are replaced by
|
||||
`CamelCaseToSnakeCaseNameConverter`
|
||||
* [DEPRECATION] the `Exception` interface has been renamed to `ExceptionInterface`
|
||||
* added `ObjectNormalizer` leveraging the `PropertyAccess` component to normalize
|
||||
objects containing both properties and getters / setters / issers / hassers methods.
|
||||
* added `xml_type_cast_attributes` context option for allowing users to opt-out of typecasting
|
||||
xml attributes.
|
||||
|
||||
2.6.0
|
||||
-----
|
||||
|
||||
* added a new serializer: `PropertyNormalizer`. Like `GetSetMethodNormalizer`,
|
||||
this normalizer will map an object's properties to an array.
|
||||
* added circular references handling for `GetSetMethodNormalizer`
|
||||
|
||||
2.5.0
|
||||
-----
|
||||
|
||||
* added support for `is.*` getters in `GetSetMethodNormalizer`
|
||||
|
||||
2.4.0
|
||||
-----
|
||||
|
||||
* added `$context` support for XMLEncoder.
|
||||
* [DEPRECATION] JsonEncode and JsonDecode where modified to throw
|
||||
an exception if error found. No need for `get*Error()` functions
|
||||
|
||||
2.3.0
|
||||
-----
|
||||
|
||||
* added `GetSetMethodNormalizer::setCamelizedAttributes` to allow calling
|
||||
camel cased methods for underscored properties
|
||||
|
||||
2.2.0
|
||||
-----
|
||||
|
||||
* [BC BREAK] All Serializer, Normalizer and Encoder interfaces have been
|
||||
modified to include an optional `$context` array parameter.
|
||||
* The XML Root name can now be configured with the `xml_root_name`
|
||||
parameter in the context option to the `XmlEncoder`.
|
||||
* Options to `json_encode` and `json_decode` can be passed through
|
||||
the context options of `JsonEncode` and `JsonDecode` encoder/decoders.
|
||||
|
||||
2.1.0
|
||||
-----
|
||||
|
||||
* added DecoderInterface::supportsDecoding(),
|
||||
EncoderInterface::supportsEncoding()
|
||||
* removed NormalizableInterface::denormalize(),
|
||||
NormalizerInterface::denormalize(),
|
||||
NormalizerInterface::supportsDenormalization()
|
||||
* removed normalize() denormalize() encode() decode() supportsSerialization()
|
||||
supportsDeserialization() supportsEncoding() supportsDecoding()
|
||||
getEncoder() from SerializerInterface
|
||||
* Serializer now implements NormalizerInterface, DenormalizerInterface,
|
||||
EncoderInterface, DecoderInterface in addition to SerializerInterface
|
||||
* added DenormalizableInterface and DenormalizerInterface
|
||||
* [BC BREAK] changed `GetSetMethodNormalizer`'s key names from all lowercased
|
||||
to camelCased (e.g. `mypropertyvalue` to `myPropertyValue`)
|
||||
* [BC BREAK] convert the `item` XML tag to an array
|
||||
|
||||
``` xml
|
||||
<?xml version="1.0"?>
|
||||
<response>
|
||||
<item><title><![CDATA[title1]]></title></item><item><title><![CDATA[title2]]></title></item>
|
||||
</response>
|
||||
```
|
||||
|
||||
Before:
|
||||
|
||||
Array()
|
||||
|
||||
After:
|
||||
|
||||
Array(
|
||||
[item] => Array(
|
||||
[0] => Array(
|
||||
[title] => title1
|
||||
)
|
||||
[1] => Array(
|
||||
[title] => title2
|
||||
)
|
||||
)
|
||||
)
|
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\DependencyInjection;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
|
||||
|
||||
/**
|
||||
* Adds all services with the tags "serializer.encoder" and "serializer.normalizer" as
|
||||
* encoders and normalizers to the "serializer" service.
|
||||
*
|
||||
* @author Javier Lopez <f12loalf@gmail.com>
|
||||
* @author Robin Chalas <robin.chalas@gmail.com>
|
||||
*/
|
||||
class SerializerPass implements CompilerPassInterface
|
||||
{
|
||||
use PriorityTaggedServiceTrait;
|
||||
|
||||
private $serializerService;
|
||||
private $normalizerTag;
|
||||
private $encoderTag;
|
||||
|
||||
public function __construct(string $serializerService = 'serializer', string $normalizerTag = 'serializer.normalizer', string $encoderTag = 'serializer.encoder')
|
||||
{
|
||||
$this->serializerService = $serializerService;
|
||||
$this->normalizerTag = $normalizerTag;
|
||||
$this->encoderTag = $encoderTag;
|
||||
}
|
||||
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
if (!$container->hasDefinition($this->serializerService)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$normalizers = $this->findAndSortTaggedServices($this->normalizerTag, $container)) {
|
||||
throw new RuntimeException(sprintf('You must tag at least one service as "%s" to use the "%s" service.', $this->normalizerTag, $this->serializerService));
|
||||
}
|
||||
|
||||
$serializerDefinition = $container->getDefinition($this->serializerService);
|
||||
$serializerDefinition->replaceArgument(0, $normalizers);
|
||||
|
||||
if (!$encoders = $this->findAndSortTaggedServices($this->encoderTag, $container)) {
|
||||
throw new RuntimeException(sprintf('You must tag at least one service as "%s" to use the "%s" service.', $this->encoderTag, $this->serializerService));
|
||||
}
|
||||
|
||||
$serializerDefinition->replaceArgument(1, $encoders);
|
||||
}
|
||||
}
|
80
old.vendor/symfony/serializer/Encoder/ChainDecoder.php
Normal file
80
old.vendor/symfony/serializer/Encoder/ChainDecoder.php
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Encoder;
|
||||
|
||||
use Symfony\Component\Serializer\Exception\RuntimeException;
|
||||
|
||||
/**
|
||||
* Decoder delegating the decoding to a chain of decoders.
|
||||
*
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
* @author Lukas Kahwe Smith <smith@pooteeweet.org>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class ChainDecoder implements ContextAwareDecoderInterface
|
||||
{
|
||||
protected $decoders = [];
|
||||
protected $decoderByFormat = [];
|
||||
|
||||
public function __construct(array $decoders = [])
|
||||
{
|
||||
$this->decoders = $decoders;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
final public function decode($data, $format, array $context = [])
|
||||
{
|
||||
return $this->getDecoder($format, $context)->decode($data, $format, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supportsDecoding($format, array $context = []): bool
|
||||
{
|
||||
try {
|
||||
$this->getDecoder($format, $context);
|
||||
} catch (RuntimeException $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the decoder supporting the format.
|
||||
*
|
||||
* @throws RuntimeException if no decoder is found
|
||||
*/
|
||||
private function getDecoder(string $format, array $context): DecoderInterface
|
||||
{
|
||||
if (isset($this->decoderByFormat[$format])
|
||||
&& isset($this->decoders[$this->decoderByFormat[$format]])
|
||||
) {
|
||||
return $this->decoders[$this->decoderByFormat[$format]];
|
||||
}
|
||||
|
||||
foreach ($this->decoders as $i => $decoder) {
|
||||
if ($decoder->supportsDecoding($format, $context)) {
|
||||
$this->decoderByFormat[$format] = $i;
|
||||
|
||||
return $decoder;
|
||||
}
|
||||
}
|
||||
|
||||
throw new RuntimeException(sprintf('No decoder found for format "%s".', $format));
|
||||
}
|
||||
}
|
98
old.vendor/symfony/serializer/Encoder/ChainEncoder.php
Normal file
98
old.vendor/symfony/serializer/Encoder/ChainEncoder.php
Normal file
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Encoder;
|
||||
|
||||
use Symfony\Component\Serializer\Exception\RuntimeException;
|
||||
|
||||
/**
|
||||
* Encoder delegating the decoding to a chain of encoders.
|
||||
*
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
* @author Lukas Kahwe Smith <smith@pooteeweet.org>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class ChainEncoder implements ContextAwareEncoderInterface
|
||||
{
|
||||
protected $encoders = [];
|
||||
protected $encoderByFormat = [];
|
||||
|
||||
public function __construct(array $encoders = [])
|
||||
{
|
||||
$this->encoders = $encoders;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
final public function encode($data, $format, array $context = [])
|
||||
{
|
||||
return $this->getEncoder($format, $context)->encode($data, $format, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supportsEncoding($format, array $context = []): bool
|
||||
{
|
||||
try {
|
||||
$this->getEncoder($format, $context);
|
||||
} catch (RuntimeException $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the normalization is needed for the given format.
|
||||
*/
|
||||
public function needsNormalization(string $format, array $context = []): bool
|
||||
{
|
||||
$encoder = $this->getEncoder($format, $context);
|
||||
|
||||
if (!$encoder instanceof NormalizationAwareInterface) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($encoder instanceof self) {
|
||||
return $encoder->needsNormalization($format, $context);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the encoder supporting the format.
|
||||
*
|
||||
* @throws RuntimeException if no encoder is found
|
||||
*/
|
||||
private function getEncoder(string $format, array $context): EncoderInterface
|
||||
{
|
||||
if (isset($this->encoderByFormat[$format])
|
||||
&& isset($this->encoders[$this->encoderByFormat[$format]])
|
||||
) {
|
||||
return $this->encoders[$this->encoderByFormat[$format]];
|
||||
}
|
||||
|
||||
foreach ($this->encoders as $i => $encoder) {
|
||||
if ($encoder->supportsEncoding($format, $context)) {
|
||||
$this->encoderByFormat[$format] = $i;
|
||||
|
||||
return $encoder;
|
||||
}
|
||||
}
|
||||
|
||||
throw new RuntimeException(sprintf('No encoder found for format "%s".', $format));
|
||||
}
|
||||
}
|
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Encoder;
|
||||
|
||||
/**
|
||||
* Adds the support of an extra $context parameter for the supportsDecoding method.
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
interface ContextAwareDecoderInterface extends DecoderInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @param array $context options that decoders have access to
|
||||
*/
|
||||
public function supportsDecoding($format, array $context = []);
|
||||
}
|
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Encoder;
|
||||
|
||||
/**
|
||||
* Adds the support of an extra $context parameter for the supportsEncoding method.
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
interface ContextAwareEncoderInterface extends EncoderInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @param array $context options that encoders have access to
|
||||
*/
|
||||
public function supportsEncoding($format, array $context = []);
|
||||
}
|
304
old.vendor/symfony/serializer/Encoder/CsvEncoder.php
Normal file
304
old.vendor/symfony/serializer/Encoder/CsvEncoder.php
Normal file
@@ -0,0 +1,304 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Encoder;
|
||||
|
||||
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
|
||||
|
||||
/**
|
||||
* Encodes CSV data.
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
* @author Oliver Hoff <oliver@hofff.com>
|
||||
*/
|
||||
class CsvEncoder implements EncoderInterface, DecoderInterface
|
||||
{
|
||||
public const FORMAT = 'csv';
|
||||
public const DELIMITER_KEY = 'csv_delimiter';
|
||||
public const ENCLOSURE_KEY = 'csv_enclosure';
|
||||
public const ESCAPE_CHAR_KEY = 'csv_escape_char';
|
||||
public const KEY_SEPARATOR_KEY = 'csv_key_separator';
|
||||
public const HEADERS_KEY = 'csv_headers';
|
||||
public const ESCAPE_FORMULAS_KEY = 'csv_escape_formulas';
|
||||
public const AS_COLLECTION_KEY = 'as_collection';
|
||||
public const NO_HEADERS_KEY = 'no_headers';
|
||||
public const OUTPUT_UTF8_BOM_KEY = 'output_utf8_bom';
|
||||
|
||||
private const UTF8_BOM = "\xEF\xBB\xBF";
|
||||
|
||||
private const FORMULAS_START_CHARACTERS = ['=', '-', '+', '@', "\t", "\r"];
|
||||
|
||||
private $defaultContext = [
|
||||
self::DELIMITER_KEY => ',',
|
||||
self::ENCLOSURE_KEY => '"',
|
||||
self::ESCAPE_CHAR_KEY => '',
|
||||
self::ESCAPE_FORMULAS_KEY => false,
|
||||
self::HEADERS_KEY => [],
|
||||
self::KEY_SEPARATOR_KEY => '.',
|
||||
self::NO_HEADERS_KEY => false,
|
||||
self::AS_COLLECTION_KEY => false,
|
||||
self::OUTPUT_UTF8_BOM_KEY => false,
|
||||
];
|
||||
|
||||
/**
|
||||
* @param array $defaultContext
|
||||
*/
|
||||
public function __construct($defaultContext = [], string $enclosure = '"', string $escapeChar = '', string $keySeparator = '.', bool $escapeFormulas = false)
|
||||
{
|
||||
if (!\is_array($defaultContext)) {
|
||||
@trigger_error('Passing configuration options directly to the constructor is deprecated since Symfony 4.2, use the default context instead.', \E_USER_DEPRECATED);
|
||||
|
||||
$defaultContext = [
|
||||
self::DELIMITER_KEY => (string) $defaultContext,
|
||||
self::ENCLOSURE_KEY => $enclosure,
|
||||
self::ESCAPE_CHAR_KEY => $escapeChar,
|
||||
self::KEY_SEPARATOR_KEY => $keySeparator,
|
||||
self::ESCAPE_FORMULAS_KEY => $escapeFormulas,
|
||||
];
|
||||
}
|
||||
|
||||
$this->defaultContext = array_merge($this->defaultContext, $defaultContext);
|
||||
|
||||
if (\PHP_VERSION_ID < 70400 && '' === $this->defaultContext[self::ESCAPE_CHAR_KEY]) {
|
||||
$this->defaultContext[self::ESCAPE_CHAR_KEY] = '\\';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function encode($data, $format, array $context = [])
|
||||
{
|
||||
$handle = fopen('php://temp,', 'w+');
|
||||
|
||||
if (!is_iterable($data)) {
|
||||
$data = [[$data]];
|
||||
} elseif (empty($data)) {
|
||||
$data = [[]];
|
||||
} else {
|
||||
// Sequential arrays of arrays are considered as collections
|
||||
$i = 0;
|
||||
foreach ($data as $key => $value) {
|
||||
if ($i !== $key || !\is_array($value)) {
|
||||
$data = [$data];
|
||||
break;
|
||||
}
|
||||
|
||||
++$i;
|
||||
}
|
||||
}
|
||||
|
||||
[$delimiter, $enclosure, $escapeChar, $keySeparator, $headers, $escapeFormulas, $outputBom] = $this->getCsvOptions($context);
|
||||
|
||||
foreach ($data as &$value) {
|
||||
$flattened = [];
|
||||
$this->flatten($value, $flattened, $keySeparator, '', $escapeFormulas);
|
||||
$value = $flattened;
|
||||
}
|
||||
unset($value);
|
||||
|
||||
$headers = array_merge(array_values($headers), array_diff($this->extractHeaders($data), $headers));
|
||||
|
||||
if (!($context[self::NO_HEADERS_KEY] ?? $this->defaultContext[self::NO_HEADERS_KEY])) {
|
||||
fputcsv($handle, $headers, $delimiter, $enclosure, $escapeChar);
|
||||
}
|
||||
|
||||
$headers = array_fill_keys($headers, '');
|
||||
foreach ($data as $row) {
|
||||
fputcsv($handle, array_replace($headers, $row), $delimiter, $enclosure, $escapeChar);
|
||||
}
|
||||
|
||||
rewind($handle);
|
||||
$value = stream_get_contents($handle);
|
||||
fclose($handle);
|
||||
|
||||
if ($outputBom) {
|
||||
if (!preg_match('//u', $value)) {
|
||||
throw new UnexpectedValueException('You are trying to add a UTF-8 BOM to a non UTF-8 text.');
|
||||
}
|
||||
|
||||
$value = self::UTF8_BOM.$value;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supportsEncoding($format)
|
||||
{
|
||||
return self::FORMAT === $format;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function decode($data, $format, array $context = [])
|
||||
{
|
||||
$handle = fopen('php://temp', 'r+');
|
||||
fwrite($handle, $data);
|
||||
rewind($handle);
|
||||
|
||||
if (str_starts_with($data, self::UTF8_BOM)) {
|
||||
fseek($handle, \strlen(self::UTF8_BOM));
|
||||
}
|
||||
|
||||
$headers = null;
|
||||
$nbHeaders = 0;
|
||||
$headerCount = [];
|
||||
$result = [];
|
||||
|
||||
[$delimiter, $enclosure, $escapeChar, $keySeparator] = $this->getCsvOptions($context);
|
||||
|
||||
while (false !== ($cols = fgetcsv($handle, 0, $delimiter, $enclosure, $escapeChar))) {
|
||||
$nbCols = \count($cols);
|
||||
|
||||
if (null === $headers) {
|
||||
$nbHeaders = $nbCols;
|
||||
|
||||
if ($context[self::NO_HEADERS_KEY] ?? $this->defaultContext[self::NO_HEADERS_KEY]) {
|
||||
for ($i = 0; $i < $nbCols; ++$i) {
|
||||
$headers[] = [$i];
|
||||
}
|
||||
$headerCount = array_fill(0, $nbCols, 1);
|
||||
} else {
|
||||
foreach ($cols as $col) {
|
||||
$header = explode($keySeparator, $col);
|
||||
$headers[] = $header;
|
||||
$headerCount[] = \count($header);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$item = [];
|
||||
for ($i = 0; ($i < $nbCols) && ($i < $nbHeaders); ++$i) {
|
||||
$depth = $headerCount[$i];
|
||||
$arr = &$item;
|
||||
for ($j = 0; $j < $depth; ++$j) {
|
||||
// Handle nested arrays
|
||||
if ($j === ($depth - 1)) {
|
||||
$arr[$headers[$i][$j]] = $cols[$i];
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($arr[$headers[$i][$j]])) {
|
||||
$arr[$headers[$i][$j]] = [];
|
||||
}
|
||||
|
||||
$arr = &$arr[$headers[$i][$j]];
|
||||
}
|
||||
}
|
||||
|
||||
$result[] = $item;
|
||||
}
|
||||
fclose($handle);
|
||||
|
||||
if ($context[self::AS_COLLECTION_KEY] ?? $this->defaultContext[self::AS_COLLECTION_KEY]) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
if (empty($result) || isset($result[1])) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
if (!isset($context['as_collection'])) {
|
||||
@trigger_error('Relying on the default value (false) of the "as_collection" option is deprecated since 4.2. You should set it to false explicitly instead as true will be the default value in 5.0.', \E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
// If there is only one data line in the document, return it (the line), the result is not considered as a collection
|
||||
return $result[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supportsDecoding($format)
|
||||
{
|
||||
return self::FORMAT === $format;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flattens an array and generates keys including the path.
|
||||
*/
|
||||
private function flatten(iterable $array, array &$result, string $keySeparator, string $parentKey = '', bool $escapeFormulas = false)
|
||||
{
|
||||
foreach ($array as $key => $value) {
|
||||
if (is_iterable($value)) {
|
||||
$this->flatten($value, $result, $keySeparator, $parentKey.$key.$keySeparator, $escapeFormulas);
|
||||
} else {
|
||||
if ($escapeFormulas && \in_array(substr((string) $value, 0, 1), self::FORMULAS_START_CHARACTERS, true)) {
|
||||
$result[$parentKey.$key] = "'".$value;
|
||||
} else {
|
||||
// Ensures an actual value is used when dealing with true and false
|
||||
$result[$parentKey.$key] = false === $value ? 0 : (true === $value ? 1 : $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function getCsvOptions(array $context): array
|
||||
{
|
||||
$delimiter = $context[self::DELIMITER_KEY] ?? $this->defaultContext[self::DELIMITER_KEY];
|
||||
$enclosure = $context[self::ENCLOSURE_KEY] ?? $this->defaultContext[self::ENCLOSURE_KEY];
|
||||
$escapeChar = $context[self::ESCAPE_CHAR_KEY] ?? $this->defaultContext[self::ESCAPE_CHAR_KEY];
|
||||
$keySeparator = $context[self::KEY_SEPARATOR_KEY] ?? $this->defaultContext[self::KEY_SEPARATOR_KEY];
|
||||
$headers = $context[self::HEADERS_KEY] ?? $this->defaultContext[self::HEADERS_KEY];
|
||||
$escapeFormulas = $context[self::ESCAPE_FORMULAS_KEY] ?? $this->defaultContext[self::ESCAPE_FORMULAS_KEY];
|
||||
$outputBom = $context[self::OUTPUT_UTF8_BOM_KEY] ?? $this->defaultContext[self::OUTPUT_UTF8_BOM_KEY];
|
||||
|
||||
if (!\is_array($headers)) {
|
||||
throw new InvalidArgumentException(sprintf('The "%s" context variable must be an array or null, given "%s".', self::HEADERS_KEY, \gettype($headers)));
|
||||
}
|
||||
|
||||
return [$delimiter, $enclosure, $escapeChar, $keySeparator, $headers, $escapeFormulas, $outputBom];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
private function extractHeaders(iterable $data): array
|
||||
{
|
||||
$headers = [];
|
||||
$flippedHeaders = [];
|
||||
|
||||
foreach ($data as $row) {
|
||||
$previousHeader = null;
|
||||
|
||||
foreach ($row as $header => $_) {
|
||||
if (isset($flippedHeaders[$header])) {
|
||||
$previousHeader = $header;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (null === $previousHeader) {
|
||||
$n = \count($headers);
|
||||
} else {
|
||||
$n = $flippedHeaders[$previousHeader] + 1;
|
||||
|
||||
for ($j = \count($headers); $j > $n; --$j) {
|
||||
++$flippedHeaders[$headers[$j] = $headers[$j - 1]];
|
||||
}
|
||||
}
|
||||
|
||||
$headers[$n] = $header;
|
||||
$flippedHeaders[$header] = $n;
|
||||
$previousHeader = $header;
|
||||
}
|
||||
}
|
||||
|
||||
return $headers;
|
||||
}
|
||||
}
|
47
old.vendor/symfony/serializer/Encoder/DecoderInterface.php
Normal file
47
old.vendor/symfony/serializer/Encoder/DecoderInterface.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Encoder;
|
||||
|
||||
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
|
||||
|
||||
/**
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*/
|
||||
interface DecoderInterface
|
||||
{
|
||||
/**
|
||||
* Decodes a string into PHP data.
|
||||
*
|
||||
* @param string $data Data to decode
|
||||
* @param string $format Format name
|
||||
* @param array $context Options that decoders have access to
|
||||
*
|
||||
* The format parameter specifies which format the data is in; valid values
|
||||
* depend on the specific implementation. Authors implementing this interface
|
||||
* are encouraged to document which formats they support in a non-inherited
|
||||
* phpdoc comment.
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @throws UnexpectedValueException
|
||||
*/
|
||||
public function decode($data, $format, array $context = []);
|
||||
|
||||
/**
|
||||
* Checks whether the deserializer can decode from given format.
|
||||
*
|
||||
* @param string $format Format name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function supportsDecoding($format);
|
||||
}
|
42
old.vendor/symfony/serializer/Encoder/EncoderInterface.php
Normal file
42
old.vendor/symfony/serializer/Encoder/EncoderInterface.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Encoder;
|
||||
|
||||
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
|
||||
|
||||
/**
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*/
|
||||
interface EncoderInterface
|
||||
{
|
||||
/**
|
||||
* Encodes data into the given format.
|
||||
*
|
||||
* @param mixed $data Data to encode
|
||||
* @param string $format Format name
|
||||
* @param array $context Options that normalizers/encoders have access to
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws UnexpectedValueException
|
||||
*/
|
||||
public function encode($data, $format, array $context = []);
|
||||
|
||||
/**
|
||||
* Checks whether the serializer can encode to given format.
|
||||
*
|
||||
* @param string $format Format name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function supportsEncoding($format);
|
||||
}
|
119
old.vendor/symfony/serializer/Encoder/JsonDecode.php
Normal file
119
old.vendor/symfony/serializer/Encoder/JsonDecode.php
Normal file
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Encoder;
|
||||
|
||||
use Symfony\Component\Serializer\Exception\NotEncodableValueException;
|
||||
|
||||
/**
|
||||
* Decodes JSON data.
|
||||
*
|
||||
* @author Sander Coolen <sander@jibber.nl>
|
||||
*/
|
||||
class JsonDecode implements DecoderInterface
|
||||
{
|
||||
protected $serializer;
|
||||
|
||||
/**
|
||||
* True to return the result as an associative array, false for a nested stdClass hierarchy.
|
||||
*/
|
||||
public const ASSOCIATIVE = 'json_decode_associative';
|
||||
|
||||
public const OPTIONS = 'json_decode_options';
|
||||
|
||||
/**
|
||||
* Specifies the recursion depth.
|
||||
*/
|
||||
public const RECURSION_DEPTH = 'json_decode_recursion_depth';
|
||||
|
||||
private $defaultContext = [
|
||||
self::ASSOCIATIVE => false,
|
||||
self::OPTIONS => 0,
|
||||
self::RECURSION_DEPTH => 512,
|
||||
];
|
||||
|
||||
/**
|
||||
* Constructs a new JsonDecode instance.
|
||||
*
|
||||
* @param array $defaultContext
|
||||
*/
|
||||
public function __construct($defaultContext = [], int $depth = 512)
|
||||
{
|
||||
if (!\is_array($defaultContext)) {
|
||||
@trigger_error(sprintf('Using constructor parameters that are not a default context is deprecated since Symfony 4.2, use the "%s" and "%s" keys of the context instead.', self::ASSOCIATIVE, self::RECURSION_DEPTH), \E_USER_DEPRECATED);
|
||||
|
||||
$defaultContext = [
|
||||
self::ASSOCIATIVE => (bool) $defaultContext,
|
||||
self::RECURSION_DEPTH => $depth,
|
||||
];
|
||||
}
|
||||
|
||||
$this->defaultContext = array_merge($this->defaultContext, $defaultContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes data.
|
||||
*
|
||||
* @param string $data The encoded JSON string to decode
|
||||
* @param string $format Must be set to JsonEncoder::FORMAT
|
||||
* @param array $context An optional set of options for the JSON decoder; see below
|
||||
*
|
||||
* The $context array is a simple key=>value array, with the following supported keys:
|
||||
*
|
||||
* json_decode_associative: boolean
|
||||
* If true, returns the object as an associative array.
|
||||
* If false, returns the object as nested stdClass
|
||||
* If not specified, this method will use the default set in JsonDecode::__construct
|
||||
*
|
||||
* json_decode_recursion_depth: integer
|
||||
* Specifies the maximum recursion depth
|
||||
* If not specified, this method will use the default set in JsonDecode::__construct
|
||||
*
|
||||
* json_decode_options: integer
|
||||
* Specifies additional options as per documentation for json_decode
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @throws NotEncodableValueException
|
||||
*
|
||||
* @see https://php.net/json_decode
|
||||
*/
|
||||
public function decode($data, $format, array $context = [])
|
||||
{
|
||||
$associative = $context[self::ASSOCIATIVE] ?? $this->defaultContext[self::ASSOCIATIVE];
|
||||
$recursionDepth = $context[self::RECURSION_DEPTH] ?? $this->defaultContext[self::RECURSION_DEPTH];
|
||||
$options = $context[self::OPTIONS] ?? $this->defaultContext[self::OPTIONS];
|
||||
|
||||
try {
|
||||
$decodedData = json_decode($data, $associative, $recursionDepth, $options);
|
||||
} catch (\JsonException $e) {
|
||||
throw new NotEncodableValueException($e->getMessage(), 0, $e);
|
||||
}
|
||||
|
||||
if (\PHP_VERSION_ID >= 70300 && (\JSON_THROW_ON_ERROR & $options)) {
|
||||
return $decodedData;
|
||||
}
|
||||
|
||||
if (\JSON_ERROR_NONE !== json_last_error()) {
|
||||
throw new NotEncodableValueException(json_last_error_msg());
|
||||
}
|
||||
|
||||
return $decodedData;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supportsDecoding($format)
|
||||
{
|
||||
return JsonEncoder::FORMAT === $format;
|
||||
}
|
||||
}
|
76
old.vendor/symfony/serializer/Encoder/JsonEncode.php
Normal file
76
old.vendor/symfony/serializer/Encoder/JsonEncode.php
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Encoder;
|
||||
|
||||
use Symfony\Component\Serializer\Exception\NotEncodableValueException;
|
||||
|
||||
/**
|
||||
* Encodes JSON data.
|
||||
*
|
||||
* @author Sander Coolen <sander@jibber.nl>
|
||||
*/
|
||||
class JsonEncode implements EncoderInterface
|
||||
{
|
||||
public const OPTIONS = 'json_encode_options';
|
||||
|
||||
private $defaultContext = [
|
||||
self::OPTIONS => 0,
|
||||
];
|
||||
|
||||
/**
|
||||
* @param array $defaultContext
|
||||
*/
|
||||
public function __construct($defaultContext = [])
|
||||
{
|
||||
if (!\is_array($defaultContext)) {
|
||||
@trigger_error(sprintf('Passing an integer as first parameter of the "%s()" method is deprecated since Symfony 4.2, use the "json_encode_options" key of the context instead.', __METHOD__), \E_USER_DEPRECATED);
|
||||
|
||||
$this->defaultContext[self::OPTIONS] = (int) $defaultContext;
|
||||
} else {
|
||||
$this->defaultContext = array_merge($this->defaultContext, $defaultContext);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes PHP data to a JSON string.
|
||||
*
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function encode($data, $format, array $context = [])
|
||||
{
|
||||
$options = $context[self::OPTIONS] ?? $this->defaultContext[self::OPTIONS];
|
||||
|
||||
try {
|
||||
$encodedJson = json_encode($data, $options);
|
||||
} catch (\JsonException $e) {
|
||||
throw new NotEncodableValueException($e->getMessage(), 0, $e);
|
||||
}
|
||||
|
||||
if (\PHP_VERSION_ID >= 70300 && (\JSON_THROW_ON_ERROR & $options)) {
|
||||
return $encodedJson;
|
||||
}
|
||||
|
||||
if (\JSON_ERROR_NONE !== json_last_error() && (false === $encodedJson || !($options & \JSON_PARTIAL_OUTPUT_ON_ERROR))) {
|
||||
throw new NotEncodableValueException(json_last_error_msg());
|
||||
}
|
||||
|
||||
return $encodedJson;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supportsEncoding($format)
|
||||
{
|
||||
return JsonEncoder::FORMAT === $format;
|
||||
}
|
||||
}
|
63
old.vendor/symfony/serializer/Encoder/JsonEncoder.php
Normal file
63
old.vendor/symfony/serializer/Encoder/JsonEncoder.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Encoder;
|
||||
|
||||
/**
|
||||
* Encodes JSON data.
|
||||
*
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*/
|
||||
class JsonEncoder implements EncoderInterface, DecoderInterface
|
||||
{
|
||||
public const FORMAT = 'json';
|
||||
|
||||
protected $encodingImpl;
|
||||
protected $decodingImpl;
|
||||
|
||||
public function __construct(JsonEncode $encodingImpl = null, JsonDecode $decodingImpl = null)
|
||||
{
|
||||
$this->encodingImpl = $encodingImpl ?? new JsonEncode();
|
||||
$this->decodingImpl = $decodingImpl ?? new JsonDecode([JsonDecode::ASSOCIATIVE => true]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function encode($data, $format, array $context = [])
|
||||
{
|
||||
return $this->encodingImpl->encode($data, self::FORMAT, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function decode($data, $format, array $context = [])
|
||||
{
|
||||
return $this->decodingImpl->decode($data, self::FORMAT, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supportsEncoding($format)
|
||||
{
|
||||
return self::FORMAT === $format;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supportsDecoding($format)
|
||||
{
|
||||
return self::FORMAT === $format;
|
||||
}
|
||||
}
|
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Encoder;
|
||||
|
||||
/**
|
||||
* Defines the interface of encoders that will normalize data themselves.
|
||||
*
|
||||
* Implementing this interface essentially just tells the Serializer that the
|
||||
* data should not be pre-normalized before being passed to this Encoder.
|
||||
*
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*/
|
||||
interface NormalizationAwareInterface
|
||||
{
|
||||
}
|
573
old.vendor/symfony/serializer/Encoder/XmlEncoder.php
Normal file
573
old.vendor/symfony/serializer/Encoder/XmlEncoder.php
Normal file
@@ -0,0 +1,573 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Encoder;
|
||||
|
||||
use Symfony\Component\Serializer\Exception\BadMethodCallException;
|
||||
use Symfony\Component\Serializer\Exception\NotEncodableValueException;
|
||||
use Symfony\Component\Serializer\SerializerAwareInterface;
|
||||
use Symfony\Component\Serializer\SerializerAwareTrait;
|
||||
|
||||
/**
|
||||
* Encodes XML data.
|
||||
*
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
* @author John Wards <jwards@whiteoctober.co.uk>
|
||||
* @author Fabian Vogler <fabian@equivalence.ch>
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
* @author Dany Maillard <danymaillard93b@gmail.com>
|
||||
*/
|
||||
class XmlEncoder implements EncoderInterface, DecoderInterface, NormalizationAwareInterface, SerializerAwareInterface
|
||||
{
|
||||
use SerializerAwareTrait;
|
||||
|
||||
public const FORMAT = 'xml';
|
||||
|
||||
public const AS_COLLECTION = 'as_collection';
|
||||
|
||||
/**
|
||||
* An array of ignored XML node types while decoding, each one of the DOM Predefined XML_* constants.
|
||||
*/
|
||||
public const DECODER_IGNORED_NODE_TYPES = 'decoder_ignored_node_types';
|
||||
|
||||
/**
|
||||
* An array of ignored XML node types while encoding, each one of the DOM Predefined XML_* constants.
|
||||
*/
|
||||
public const ENCODER_IGNORED_NODE_TYPES = 'encoder_ignored_node_types';
|
||||
public const ENCODING = 'xml_encoding';
|
||||
public const FORMAT_OUTPUT = 'xml_format_output';
|
||||
|
||||
/**
|
||||
* A bit field of LIBXML_* constants.
|
||||
*/
|
||||
public const LOAD_OPTIONS = 'load_options';
|
||||
public const REMOVE_EMPTY_TAGS = 'remove_empty_tags';
|
||||
public const ROOT_NODE_NAME = 'xml_root_node_name';
|
||||
public const STANDALONE = 'xml_standalone';
|
||||
|
||||
/** @deprecated The constant TYPE_CASE_ATTRIBUTES is deprecated since version 4.4 and will be removed in version 5. Use TYPE_CAST_ATTRIBUTES instead. */
|
||||
public const TYPE_CASE_ATTRIBUTES = 'xml_type_cast_attributes';
|
||||
public const TYPE_CAST_ATTRIBUTES = 'xml_type_cast_attributes';
|
||||
public const VERSION = 'xml_version';
|
||||
|
||||
private $defaultContext = [
|
||||
self::AS_COLLECTION => false,
|
||||
self::DECODER_IGNORED_NODE_TYPES => [\XML_PI_NODE, \XML_COMMENT_NODE],
|
||||
self::ENCODER_IGNORED_NODE_TYPES => [],
|
||||
self::LOAD_OPTIONS => \LIBXML_NONET | \LIBXML_NOBLANKS,
|
||||
self::REMOVE_EMPTY_TAGS => false,
|
||||
self::ROOT_NODE_NAME => 'response',
|
||||
self::TYPE_CAST_ATTRIBUTES => true,
|
||||
];
|
||||
|
||||
/**
|
||||
* @var \DOMDocument
|
||||
*/
|
||||
private $dom;
|
||||
private $format;
|
||||
private $context;
|
||||
|
||||
/**
|
||||
* @param array $defaultContext
|
||||
*/
|
||||
public function __construct($defaultContext = [], int $loadOptions = null, array $decoderIgnoredNodeTypes = [\XML_PI_NODE, \XML_COMMENT_NODE], array $encoderIgnoredNodeTypes = [])
|
||||
{
|
||||
if (!\is_array($defaultContext)) {
|
||||
@trigger_error('Passing configuration options directly to the constructor is deprecated since Symfony 4.2, use the default context instead.', \E_USER_DEPRECATED);
|
||||
|
||||
$defaultContext = [
|
||||
self::DECODER_IGNORED_NODE_TYPES => $decoderIgnoredNodeTypes,
|
||||
self::ENCODER_IGNORED_NODE_TYPES => $encoderIgnoredNodeTypes,
|
||||
self::LOAD_OPTIONS => $loadOptions ?? \LIBXML_NONET | \LIBXML_NOBLANKS,
|
||||
self::ROOT_NODE_NAME => (string) $defaultContext,
|
||||
];
|
||||
}
|
||||
|
||||
$this->defaultContext = array_merge($this->defaultContext, $defaultContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function encode($data, $format, array $context = [])
|
||||
{
|
||||
$encoderIgnoredNodeTypes = $context[self::ENCODER_IGNORED_NODE_TYPES] ?? $this->defaultContext[self::ENCODER_IGNORED_NODE_TYPES];
|
||||
$ignorePiNode = \in_array(\XML_PI_NODE, $encoderIgnoredNodeTypes, true);
|
||||
if ($data instanceof \DOMDocument) {
|
||||
return $data->saveXML($ignorePiNode ? $data->documentElement : null);
|
||||
}
|
||||
|
||||
$xmlRootNodeName = $context[self::ROOT_NODE_NAME] ?? $this->defaultContext[self::ROOT_NODE_NAME];
|
||||
|
||||
$this->dom = $this->createDomDocument($context);
|
||||
$this->format = $format;
|
||||
$this->context = $context;
|
||||
|
||||
if (null !== $data && !is_scalar($data)) {
|
||||
$root = $this->dom->createElement($xmlRootNodeName);
|
||||
$this->dom->appendChild($root);
|
||||
$this->buildXml($root, $data, $xmlRootNodeName);
|
||||
} else {
|
||||
$this->appendNode($this->dom, $data, $xmlRootNodeName);
|
||||
}
|
||||
|
||||
return $this->dom->saveXML($ignorePiNode ? $this->dom->documentElement : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function decode($data, $format, array $context = [])
|
||||
{
|
||||
if ('' === trim($data)) {
|
||||
throw new NotEncodableValueException('Invalid XML data, it can not be empty.');
|
||||
}
|
||||
|
||||
$internalErrors = libxml_use_internal_errors(true);
|
||||
if (\LIBXML_VERSION < 20900) {
|
||||
$disableEntities = libxml_disable_entity_loader(true);
|
||||
}
|
||||
libxml_clear_errors();
|
||||
|
||||
$dom = new \DOMDocument();
|
||||
$dom->loadXML($data, $context[self::LOAD_OPTIONS] ?? $this->defaultContext[self::LOAD_OPTIONS]);
|
||||
|
||||
libxml_use_internal_errors($internalErrors);
|
||||
if (\LIBXML_VERSION < 20900) {
|
||||
libxml_disable_entity_loader($disableEntities);
|
||||
}
|
||||
|
||||
if ($error = libxml_get_last_error()) {
|
||||
libxml_clear_errors();
|
||||
|
||||
throw new NotEncodableValueException($error->message);
|
||||
}
|
||||
|
||||
$rootNode = null;
|
||||
$decoderIgnoredNodeTypes = $context[self::DECODER_IGNORED_NODE_TYPES] ?? $this->defaultContext[self::DECODER_IGNORED_NODE_TYPES];
|
||||
foreach ($dom->childNodes as $child) {
|
||||
if (\XML_DOCUMENT_TYPE_NODE === $child->nodeType) {
|
||||
throw new NotEncodableValueException('Document types are not allowed.');
|
||||
}
|
||||
if (!$rootNode && !\in_array($child->nodeType, $decoderIgnoredNodeTypes, true)) {
|
||||
$rootNode = $child;
|
||||
}
|
||||
}
|
||||
|
||||
// todo: throw an exception if the root node name is not correctly configured (bc)
|
||||
|
||||
if ($rootNode->hasChildNodes()) {
|
||||
$xpath = new \DOMXPath($dom);
|
||||
$data = [];
|
||||
foreach ($xpath->query('namespace::*', $dom->documentElement) as $nsNode) {
|
||||
$data['@'.$nsNode->nodeName] = $nsNode->nodeValue;
|
||||
}
|
||||
|
||||
unset($data['@xmlns:xml']);
|
||||
|
||||
if (empty($data)) {
|
||||
return $this->parseXml($rootNode, $context);
|
||||
}
|
||||
|
||||
return array_merge($data, (array) $this->parseXml($rootNode, $context));
|
||||
}
|
||||
|
||||
if (!$rootNode->hasAttributes()) {
|
||||
return $rootNode->nodeValue;
|
||||
}
|
||||
|
||||
$data = [];
|
||||
|
||||
foreach ($rootNode->attributes as $attrKey => $attr) {
|
||||
$data['@'.$attrKey] = $attr->nodeValue;
|
||||
}
|
||||
|
||||
$data['#'] = $rootNode->nodeValue;
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supportsEncoding($format)
|
||||
{
|
||||
return self::FORMAT === $format;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supportsDecoding($format)
|
||||
{
|
||||
return self::FORMAT === $format;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the root node name.
|
||||
*
|
||||
* @deprecated since Symfony 4.2
|
||||
*
|
||||
* @param string $name Root node name
|
||||
*/
|
||||
public function setRootNodeName($name)
|
||||
{
|
||||
@trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2, use the context instead.', __METHOD__), \E_USER_DEPRECATED);
|
||||
|
||||
$this->defaultContext[self::ROOT_NODE_NAME] = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the root node name.
|
||||
*
|
||||
* @deprecated since Symfony 4.2
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRootNodeName()
|
||||
{
|
||||
@trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2, use the context instead.', __METHOD__), \E_USER_DEPRECATED);
|
||||
|
||||
return $this->defaultContext[self::ROOT_NODE_NAME];
|
||||
}
|
||||
|
||||
final protected function appendXMLString(\DOMNode $node, string $val): bool
|
||||
{
|
||||
if ('' !== $val) {
|
||||
$frag = $this->dom->createDocumentFragment();
|
||||
$frag->appendXML($val);
|
||||
$node->appendChild($frag);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
final protected function appendText(\DOMNode $node, string $val): bool
|
||||
{
|
||||
$nodeText = $this->dom->createTextNode($val);
|
||||
$node->appendChild($nodeText);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
final protected function appendCData(\DOMNode $node, string $val): bool
|
||||
{
|
||||
$nodeText = $this->dom->createCDATASection($val);
|
||||
$node->appendChild($nodeText);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DOMDocumentFragment $fragment
|
||||
*/
|
||||
final protected function appendDocumentFragment(\DOMNode $node, $fragment): bool
|
||||
{
|
||||
if ($fragment instanceof \DOMDocumentFragment) {
|
||||
$node->appendChild($fragment);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
final protected function appendComment(\DOMNode $node, string $data): bool
|
||||
{
|
||||
$node->appendChild($this->dom->createComment($data));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the name is a valid xml element name.
|
||||
*/
|
||||
final protected function isElementNameValid(string $name): bool
|
||||
{
|
||||
return $name &&
|
||||
!str_contains($name, ' ') &&
|
||||
preg_match('#^[\pL_][\pL0-9._:-]*$#ui', $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the input DOMNode into an array or a string.
|
||||
*
|
||||
* @return array|string
|
||||
*/
|
||||
private function parseXml(\DOMNode $node, array $context = [])
|
||||
{
|
||||
$data = $this->parseXmlAttributes($node, $context);
|
||||
|
||||
$value = $this->parseXmlValue($node, $context);
|
||||
|
||||
if (!\count($data)) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
if (!\is_array($value)) {
|
||||
$data['#'] = $value;
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
if (1 === \count($value) && key($value)) {
|
||||
$data[key($value)] = current($value);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
foreach ($value as $key => $val) {
|
||||
$data[$key] = $val;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the input DOMNode attributes into an array.
|
||||
*/
|
||||
private function parseXmlAttributes(\DOMNode $node, array $context = []): array
|
||||
{
|
||||
if (!$node->hasAttributes()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$data = [];
|
||||
$typeCastAttributes = (bool) ($context[self::TYPE_CAST_ATTRIBUTES] ?? $this->defaultContext[self::TYPE_CAST_ATTRIBUTES]);
|
||||
|
||||
foreach ($node->attributes as $attr) {
|
||||
if (!is_numeric($attr->nodeValue) || !$typeCastAttributes || (isset($attr->nodeValue[1]) && '0' === $attr->nodeValue[0] && '.' !== $attr->nodeValue[1])) {
|
||||
$data['@'.$attr->nodeName] = $attr->nodeValue;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (false !== $val = filter_var($attr->nodeValue, \FILTER_VALIDATE_INT)) {
|
||||
$data['@'.$attr->nodeName] = $val;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$data['@'.$attr->nodeName] = (float) $attr->nodeValue;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the input DOMNode value (content and children) into an array or a string.
|
||||
*
|
||||
* @return array|string
|
||||
*/
|
||||
private function parseXmlValue(\DOMNode $node, array $context = [])
|
||||
{
|
||||
if (!$node->hasChildNodes()) {
|
||||
return $node->nodeValue;
|
||||
}
|
||||
|
||||
if (1 === $node->childNodes->length && \in_array($node->firstChild->nodeType, [\XML_TEXT_NODE, \XML_CDATA_SECTION_NODE])) {
|
||||
return $node->firstChild->nodeValue;
|
||||
}
|
||||
|
||||
$value = [];
|
||||
$decoderIgnoredNodeTypes = $context[self::DECODER_IGNORED_NODE_TYPES] ?? $this->defaultContext[self::DECODER_IGNORED_NODE_TYPES];
|
||||
foreach ($node->childNodes as $subnode) {
|
||||
if (\in_array($subnode->nodeType, $decoderIgnoredNodeTypes, true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$val = $this->parseXml($subnode, $context);
|
||||
|
||||
if ('item' === $subnode->nodeName && isset($val['@key'])) {
|
||||
$value[$val['@key']] = $val['#'] ?? $val;
|
||||
} else {
|
||||
$value[$subnode->nodeName][] = $val;
|
||||
}
|
||||
}
|
||||
|
||||
$asCollection = $context[self::AS_COLLECTION] ?? $this->defaultContext[self::AS_COLLECTION];
|
||||
foreach ($value as $key => $val) {
|
||||
if (!$asCollection && \is_array($val) && 1 === \count($val)) {
|
||||
$value[$key] = current($val);
|
||||
}
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the data and convert it to DOMElements.
|
||||
*
|
||||
* @param array|object $data
|
||||
*
|
||||
* @throws NotEncodableValueException
|
||||
*/
|
||||
private function buildXml(\DOMNode $parentNode, $data, string $xmlRootNodeName = null): bool
|
||||
{
|
||||
$append = true;
|
||||
$removeEmptyTags = $this->context[self::REMOVE_EMPTY_TAGS] ?? $this->defaultContext[self::REMOVE_EMPTY_TAGS] ?? false;
|
||||
$encoderIgnoredNodeTypes = $this->context[self::ENCODER_IGNORED_NODE_TYPES] ?? $this->defaultContext[self::ENCODER_IGNORED_NODE_TYPES];
|
||||
|
||||
if (\is_array($data) || ($data instanceof \Traversable && (null === $this->serializer || !$this->serializer->supportsNormalization($data, $this->format)))) {
|
||||
foreach ($data as $key => $data) {
|
||||
//Ah this is the magic @ attribute types.
|
||||
if (str_starts_with($key, '@') && $this->isElementNameValid($attributeName = substr($key, 1))) {
|
||||
if (!is_scalar($data)) {
|
||||
$data = $this->serializer->normalize($data, $this->format, $this->context);
|
||||
}
|
||||
$parentNode->setAttribute($attributeName, $data);
|
||||
} elseif ('#' === $key) {
|
||||
$append = $this->selectNodeType($parentNode, $data);
|
||||
} elseif ('#comment' === $key) {
|
||||
if (!\in_array(\XML_COMMENT_NODE, $encoderIgnoredNodeTypes, true)) {
|
||||
$append = $this->appendComment($parentNode, $data);
|
||||
}
|
||||
} elseif (\is_array($data) && false === is_numeric($key)) {
|
||||
// Is this array fully numeric keys?
|
||||
if (ctype_digit(implode('', array_keys($data)))) {
|
||||
/*
|
||||
* Create nodes to append to $parentNode based on the $key of this array
|
||||
* Produces <xml><item>0</item><item>1</item></xml>
|
||||
* From ["item" => [0,1]];.
|
||||
*/
|
||||
foreach ($data as $subData) {
|
||||
$append = $this->appendNode($parentNode, $subData, $key);
|
||||
}
|
||||
} else {
|
||||
$append = $this->appendNode($parentNode, $data, $key);
|
||||
}
|
||||
} elseif (is_numeric($key) || !$this->isElementNameValid($key)) {
|
||||
$append = $this->appendNode($parentNode, $data, 'item', $key);
|
||||
} elseif (null !== $data || !$removeEmptyTags) {
|
||||
$append = $this->appendNode($parentNode, $data, $key);
|
||||
}
|
||||
}
|
||||
|
||||
return $append;
|
||||
}
|
||||
|
||||
if (\is_object($data)) {
|
||||
if (null === $this->serializer) {
|
||||
throw new BadMethodCallException(sprintf('The serializer needs to be set to allow "%s()" to be used with object data.', __METHOD__));
|
||||
}
|
||||
|
||||
$data = $this->serializer->normalize($data, $this->format, $this->context);
|
||||
if (null !== $data && !is_scalar($data)) {
|
||||
return $this->buildXml($parentNode, $data, $xmlRootNodeName);
|
||||
}
|
||||
|
||||
// top level data object was normalized into a scalar
|
||||
if (!$parentNode->parentNode->parentNode) {
|
||||
$root = $parentNode->parentNode;
|
||||
$root->removeChild($parentNode);
|
||||
|
||||
return $this->appendNode($root, $data, $xmlRootNodeName);
|
||||
}
|
||||
|
||||
return $this->appendNode($parentNode, $data, 'data');
|
||||
}
|
||||
|
||||
throw new NotEncodableValueException('An unexpected value could not be serialized: '.(!\is_resource($data) ? var_export($data, true) : sprintf('%s resource', get_resource_type($data))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects the type of node to create and appends it to the parent.
|
||||
*
|
||||
* @param array|object $data
|
||||
*/
|
||||
private function appendNode(\DOMNode $parentNode, $data, string $nodeName, string $key = null): bool
|
||||
{
|
||||
$node = $this->dom->createElement($nodeName);
|
||||
if (null !== $key) {
|
||||
$node->setAttribute('key', $key);
|
||||
}
|
||||
$appendNode = $this->selectNodeType($node, $data);
|
||||
// we may have decided not to append this node, either in error or if its $nodeName is not valid
|
||||
if ($appendNode) {
|
||||
$parentNode->appendChild($node);
|
||||
}
|
||||
|
||||
return $appendNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a value contains any characters which would require CDATA wrapping.
|
||||
*/
|
||||
private function needsCdataWrapping(string $val): bool
|
||||
{
|
||||
return 0 < preg_match('/[<>&]/', $val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the value being passed and decide what sort of element to create.
|
||||
*
|
||||
* @throws NotEncodableValueException
|
||||
*/
|
||||
private function selectNodeType(\DOMNode $node, $val): bool
|
||||
{
|
||||
if (\is_array($val)) {
|
||||
return $this->buildXml($node, $val);
|
||||
} elseif ($val instanceof \SimpleXMLElement) {
|
||||
$child = $this->dom->importNode(dom_import_simplexml($val), true);
|
||||
$node->appendChild($child);
|
||||
} elseif ($val instanceof \Traversable) {
|
||||
$this->buildXml($node, $val);
|
||||
} elseif ($val instanceof \DOMNode) {
|
||||
$child = $this->dom->importNode($val, true);
|
||||
$node->appendChild($child);
|
||||
} elseif (\is_object($val)) {
|
||||
if (null === $this->serializer) {
|
||||
throw new BadMethodCallException(sprintf('The serializer needs to be set to allow "%s()" to be used with object data.', __METHOD__));
|
||||
}
|
||||
|
||||
return $this->selectNodeType($node, $this->serializer->normalize($val, $this->format, $this->context));
|
||||
} elseif (is_numeric($val)) {
|
||||
return $this->appendText($node, (string) $val);
|
||||
} elseif (\is_string($val) && $this->needsCdataWrapping($val)) {
|
||||
return $this->appendCData($node, $val);
|
||||
} elseif (\is_string($val)) {
|
||||
return $this->appendText($node, $val);
|
||||
} elseif (\is_bool($val)) {
|
||||
return $this->appendText($node, (int) $val);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a DOM document, taking serializer options into account.
|
||||
*/
|
||||
private function createDomDocument(array $context): \DOMDocument
|
||||
{
|
||||
$document = new \DOMDocument();
|
||||
|
||||
// Set an attribute on the DOM document specifying, as part of the XML declaration,
|
||||
$xmlOptions = [
|
||||
// nicely formats output with indentation and extra space
|
||||
self::FORMAT_OUTPUT => 'formatOutput',
|
||||
// the version number of the document
|
||||
self::VERSION => 'xmlVersion',
|
||||
// the encoding of the document
|
||||
self::ENCODING => 'encoding',
|
||||
// whether the document is standalone
|
||||
self::STANDALONE => 'xmlStandalone',
|
||||
];
|
||||
foreach ($xmlOptions as $xmlOption => $documentProperty) {
|
||||
if ($contextOption = $context[$xmlOption] ?? $this->defaultContext[$xmlOption] ?? false) {
|
||||
$document->$documentProperty = $contextOption;
|
||||
}
|
||||
}
|
||||
|
||||
return $document;
|
||||
}
|
||||
}
|
85
old.vendor/symfony/serializer/Encoder/YamlEncoder.php
Normal file
85
old.vendor/symfony/serializer/Encoder/YamlEncoder.php
Normal file
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Encoder;
|
||||
|
||||
use Symfony\Component\Serializer\Exception\RuntimeException;
|
||||
use Symfony\Component\Yaml\Dumper;
|
||||
use Symfony\Component\Yaml\Parser;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
/**
|
||||
* Encodes YAML data.
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
class YamlEncoder implements EncoderInterface, DecoderInterface
|
||||
{
|
||||
public const FORMAT = 'yaml';
|
||||
private const ALTERNATIVE_FORMAT = 'yml';
|
||||
|
||||
public const PRESERVE_EMPTY_OBJECTS = 'preserve_empty_objects';
|
||||
|
||||
private $dumper;
|
||||
private $parser;
|
||||
private $defaultContext = ['yaml_inline' => 0, 'yaml_indent' => 0, 'yaml_flags' => 0];
|
||||
|
||||
public function __construct(Dumper $dumper = null, Parser $parser = null, array $defaultContext = [])
|
||||
{
|
||||
if (!class_exists(Dumper::class)) {
|
||||
throw new RuntimeException('The YamlEncoder class requires the "Yaml" component. Install "symfony/yaml" to use it.');
|
||||
}
|
||||
|
||||
$this->dumper = $dumper ?? new Dumper();
|
||||
$this->parser = $parser ?? new Parser();
|
||||
$this->defaultContext = array_merge($this->defaultContext, $defaultContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function encode($data, $format, array $context = [])
|
||||
{
|
||||
$context = array_merge($this->defaultContext, $context);
|
||||
|
||||
if (isset($context[self::PRESERVE_EMPTY_OBJECTS])) {
|
||||
$context['yaml_flags'] |= Yaml::DUMP_OBJECT_AS_MAP;
|
||||
}
|
||||
|
||||
return $this->dumper->dump($data, $context['yaml_inline'], $context['yaml_indent'], $context['yaml_flags']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supportsEncoding($format)
|
||||
{
|
||||
return self::FORMAT === $format || self::ALTERNATIVE_FORMAT === $format;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function decode($data, $format, array $context = [])
|
||||
{
|
||||
$context = array_merge($this->defaultContext, $context);
|
||||
|
||||
return $this->parser->parse($data, $context['yaml_flags']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supportsDecoding($format)
|
||||
{
|
||||
return self::FORMAT === $format || self::ALTERNATIVE_FORMAT === $format;
|
||||
}
|
||||
}
|
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Exception;
|
||||
|
||||
class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface
|
||||
{
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Exception;
|
||||
|
||||
/**
|
||||
* CircularReferenceException.
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
class CircularReferenceException extends RuntimeException
|
||||
{
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Exception;
|
||||
|
||||
/**
|
||||
* Base exception interface.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*/
|
||||
interface ExceptionInterface extends \Throwable
|
||||
{
|
||||
}
|
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Exception;
|
||||
|
||||
/**
|
||||
* ExtraAttributesException.
|
||||
*
|
||||
* @author Julien DIDIER <julien@didier.io>
|
||||
*/
|
||||
class ExtraAttributesException extends RuntimeException
|
||||
{
|
||||
private $extraAttributes;
|
||||
|
||||
public function __construct(array $extraAttributes, \Throwable $previous = null)
|
||||
{
|
||||
$msg = sprintf('Extra attributes are not allowed ("%s" are unknown).', implode('", "', $extraAttributes));
|
||||
|
||||
$this->extraAttributes = $extraAttributes;
|
||||
|
||||
parent::__construct($msg, 0, $previous);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the extra attributes that are not allowed.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getExtraAttributes()
|
||||
{
|
||||
return $this->extraAttributes;
|
||||
}
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Exception;
|
||||
|
||||
/**
|
||||
* InvalidArgumentException.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*/
|
||||
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
|
||||
{
|
||||
}
|
21
old.vendor/symfony/serializer/Exception/LogicException.php
Normal file
21
old.vendor/symfony/serializer/Exception/LogicException.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Exception;
|
||||
|
||||
/**
|
||||
* LogicException.
|
||||
*
|
||||
* @author Lukas Kahwe Smith <smith@pooteeweet.org>
|
||||
*/
|
||||
class LogicException extends \LogicException implements ExceptionInterface
|
||||
{
|
||||
}
|
21
old.vendor/symfony/serializer/Exception/MappingException.php
Normal file
21
old.vendor/symfony/serializer/Exception/MappingException.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Exception;
|
||||
|
||||
/**
|
||||
* MappingException.
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
class MappingException extends RuntimeException
|
||||
{
|
||||
}
|
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Exception;
|
||||
|
||||
/**
|
||||
* @author Maxime VEBER <maxime.veber@nekland.fr>
|
||||
*/
|
||||
class MissingConstructorArgumentsException extends RuntimeException
|
||||
{
|
||||
}
|
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Exception;
|
||||
|
||||
/**
|
||||
* @author Christian Flothmann <christian.flothmann@sensiolabs.de>
|
||||
*/
|
||||
class NotEncodableValueException extends UnexpectedValueException
|
||||
{
|
||||
}
|
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Exception;
|
||||
|
||||
/**
|
||||
* @author Christian Flothmann <christian.flothmann@sensiolabs.de>
|
||||
*/
|
||||
class NotNormalizableValueException extends UnexpectedValueException
|
||||
{
|
||||
}
|
21
old.vendor/symfony/serializer/Exception/RuntimeException.php
Normal file
21
old.vendor/symfony/serializer/Exception/RuntimeException.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Exception;
|
||||
|
||||
/**
|
||||
* RuntimeException.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*/
|
||||
class RuntimeException extends \RuntimeException implements ExceptionInterface
|
||||
{
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Exception;
|
||||
|
||||
/**
|
||||
* UnexpectedValueException.
|
||||
*
|
||||
* @author Lukas Kahwe Smith <smith@pooteeweet.org>
|
||||
*/
|
||||
class UnexpectedValueException extends \UnexpectedValueException implements ExceptionInterface
|
||||
{
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Exception;
|
||||
|
||||
/**
|
||||
* UnsupportedException.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*/
|
||||
class UnsupportedException extends InvalidArgumentException
|
||||
{
|
||||
}
|
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Extractor;
|
||||
|
||||
use Symfony\Component\PropertyInfo\PropertyListExtractorInterface;
|
||||
|
||||
/**
|
||||
* @author David Maicher <mail@dmaicher.de>
|
||||
*/
|
||||
final class ObjectPropertyListExtractor implements ObjectPropertyListExtractorInterface
|
||||
{
|
||||
private $propertyListExtractor;
|
||||
private $objectClassResolver;
|
||||
|
||||
public function __construct(PropertyListExtractorInterface $propertyListExtractor, callable $objectClassResolver = null)
|
||||
{
|
||||
$this->propertyListExtractor = $propertyListExtractor;
|
||||
$this->objectClassResolver = $objectClassResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getProperties($object, array $context = []): ?array
|
||||
{
|
||||
$class = $this->objectClassResolver ? ($this->objectClassResolver)($object) : \get_class($object);
|
||||
|
||||
return $this->propertyListExtractor->getProperties($class, $context);
|
||||
}
|
||||
}
|
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Extractor;
|
||||
|
||||
/**
|
||||
* @author David Maicher <mail@dmaicher.de>
|
||||
*/
|
||||
interface ObjectPropertyListExtractorInterface
|
||||
{
|
||||
/**
|
||||
* Gets the list of properties available for the given object.
|
||||
*
|
||||
* @param object $object
|
||||
*
|
||||
* @return string[]|null
|
||||
*/
|
||||
public function getProperties($object, array $context = []): ?array;
|
||||
}
|
19
old.vendor/symfony/serializer/LICENSE
Normal file
19
old.vendor/symfony/serializer/LICENSE
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2004-2021 Fabien Potencier
|
||||
|
||||
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.
|
145
old.vendor/symfony/serializer/Mapping/AttributeMetadata.php
Normal file
145
old.vendor/symfony/serializer/Mapping/AttributeMetadata.php
Normal file
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Mapping;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
class AttributeMetadata implements AttributeMetadataInterface
|
||||
{
|
||||
/**
|
||||
* @internal This property is public in order to reduce the size of the
|
||||
* class' serialized representation. Do not access it. Use
|
||||
* {@link getName()} instead.
|
||||
*/
|
||||
public $name;
|
||||
|
||||
/**
|
||||
* @internal This property is public in order to reduce the size of the
|
||||
* class' serialized representation. Do not access it. Use
|
||||
* {@link getGroups()} instead.
|
||||
*/
|
||||
public $groups = [];
|
||||
|
||||
/**
|
||||
* @var int|null
|
||||
*
|
||||
* @internal This property is public in order to reduce the size of the
|
||||
* class' serialized representation. Do not access it. Use
|
||||
* {@link getMaxDepth()} instead.
|
||||
*/
|
||||
public $maxDepth;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*
|
||||
* @internal This property is public in order to reduce the size of the
|
||||
* class' serialized representation. Do not access it. Use
|
||||
* {@link getSerializedName()} instead.
|
||||
*/
|
||||
public $serializedName;
|
||||
|
||||
public function __construct(string $name)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addGroup($group)
|
||||
{
|
||||
if (!\in_array($group, $this->groups)) {
|
||||
$this->groups[] = $group;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getGroups(): array
|
||||
{
|
||||
return $this->groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setMaxDepth($maxDepth)
|
||||
{
|
||||
$this->maxDepth = $maxDepth;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getMaxDepth()
|
||||
{
|
||||
return $this->maxDepth;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setSerializedName(string $serializedName = null)
|
||||
{
|
||||
$this->serializedName = $serializedName;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSerializedName(): ?string
|
||||
{
|
||||
return $this->serializedName;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function merge(AttributeMetadataInterface $attributeMetadata)
|
||||
{
|
||||
foreach ($attributeMetadata->getGroups() as $group) {
|
||||
$this->addGroup($group);
|
||||
}
|
||||
|
||||
// Overwrite only if not defined
|
||||
if (null === $this->maxDepth) {
|
||||
$this->maxDepth = $attributeMetadata->getMaxDepth();
|
||||
}
|
||||
|
||||
// Overwrite only if not defined
|
||||
if (null === $this->serializedName) {
|
||||
$this->serializedName = $attributeMetadata->getSerializedName();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the names of the properties that should be serialized.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function __sleep()
|
||||
{
|
||||
return ['name', 'groups', 'maxDepth', 'serializedName'];
|
||||
}
|
||||
}
|
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Mapping;
|
||||
|
||||
/**
|
||||
* Stores metadata needed for serializing and deserializing attributes.
|
||||
*
|
||||
* Primarily, the metadata stores serialization groups.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
interface AttributeMetadataInterface
|
||||
{
|
||||
/**
|
||||
* Gets the attribute name.
|
||||
*/
|
||||
public function getName(): string;
|
||||
|
||||
/**
|
||||
* Adds this attribute to the given group.
|
||||
*
|
||||
* @param string $group
|
||||
*/
|
||||
public function addGroup($group);
|
||||
|
||||
/**
|
||||
* Gets groups of this attribute.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function getGroups(): array;
|
||||
|
||||
/**
|
||||
* Sets the serialization max depth for this attribute.
|
||||
*
|
||||
* @param int|null $maxDepth
|
||||
*/
|
||||
public function setMaxDepth($maxDepth);
|
||||
|
||||
/**
|
||||
* Gets the serialization max depth for this attribute.
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getMaxDepth();
|
||||
|
||||
/**
|
||||
* Sets the serialization name for this attribute.
|
||||
*/
|
||||
public function setSerializedName(string $serializedName = null);
|
||||
|
||||
/**
|
||||
* Gets the serialization name for this attribute.
|
||||
*/
|
||||
public function getSerializedName(): ?string;
|
||||
|
||||
/**
|
||||
* Merges an {@see AttributeMetadataInterface} with in the current one.
|
||||
*/
|
||||
public function merge(self $attributeMetadata);
|
||||
}
|
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Mapping;
|
||||
|
||||
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
|
||||
|
||||
/**
|
||||
* @author Samuel Roze <samuel.roze@gmail.com>
|
||||
*/
|
||||
class ClassDiscriminatorFromClassMetadata implements ClassDiscriminatorResolverInterface
|
||||
{
|
||||
/**
|
||||
* @var ClassMetadataFactoryInterface
|
||||
*/
|
||||
private $classMetadataFactory;
|
||||
private $mappingForMappedObjectCache = [];
|
||||
|
||||
public function __construct(ClassMetadataFactoryInterface $classMetadataFactory)
|
||||
{
|
||||
$this->classMetadataFactory = $classMetadataFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getMappingForClass(string $class): ?ClassDiscriminatorMapping
|
||||
{
|
||||
if ($this->classMetadataFactory->hasMetadataFor($class)) {
|
||||
return $this->classMetadataFactory->getMetadataFor($class)->getClassDiscriminatorMapping();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getMappingForMappedObject($object): ?ClassDiscriminatorMapping
|
||||
{
|
||||
if ($this->classMetadataFactory->hasMetadataFor($object)) {
|
||||
$metadata = $this->classMetadataFactory->getMetadataFor($object);
|
||||
|
||||
if (null !== $metadata->getClassDiscriminatorMapping()) {
|
||||
return $metadata->getClassDiscriminatorMapping();
|
||||
}
|
||||
}
|
||||
|
||||
$cacheKey = \is_object($object) ? \get_class($object) : $object;
|
||||
if (!\array_key_exists($cacheKey, $this->mappingForMappedObjectCache)) {
|
||||
$this->mappingForMappedObjectCache[$cacheKey] = $this->resolveMappingForMappedObject($object);
|
||||
}
|
||||
|
||||
return $this->mappingForMappedObjectCache[$cacheKey];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getTypeForMappedObject($object): ?string
|
||||
{
|
||||
if (null === $mapping = $this->getMappingForMappedObject($object)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $mapping->getMappedObjectType($object);
|
||||
}
|
||||
|
||||
private function resolveMappingForMappedObject($object)
|
||||
{
|
||||
$reflectionClass = new \ReflectionClass($object);
|
||||
if ($parentClass = $reflectionClass->getParentClass()) {
|
||||
return $this->getMappingForMappedObject($parentClass->getName());
|
||||
}
|
||||
|
||||
foreach ($reflectionClass->getInterfaceNames() as $interfaceName) {
|
||||
if (null !== ($interfaceMapping = $this->getMappingForMappedObject($interfaceName))) {
|
||||
return $interfaceMapping;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Mapping;
|
||||
|
||||
/**
|
||||
* @author Samuel Roze <samuel.roze@gmail.com>
|
||||
*/
|
||||
class ClassDiscriminatorMapping
|
||||
{
|
||||
private $typeProperty;
|
||||
private $typesMapping;
|
||||
|
||||
public function __construct(string $typeProperty, array $typesMapping = [])
|
||||
{
|
||||
$this->typeProperty = $typeProperty;
|
||||
$this->typesMapping = $typesMapping;
|
||||
|
||||
uasort($this->typesMapping, static function (string $a, string $b): int {
|
||||
if (is_a($a, $b, true)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (is_a($b, $a, true)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
|
||||
public function getTypeProperty(): string
|
||||
{
|
||||
return $this->typeProperty;
|
||||
}
|
||||
|
||||
public function getClassForType(string $type): ?string
|
||||
{
|
||||
return $this->typesMapping[$type] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param object|string $object
|
||||
*/
|
||||
public function getMappedObjectType($object): ?string
|
||||
{
|
||||
foreach ($this->typesMapping as $type => $typeClass) {
|
||||
if (is_a($object, $typeClass)) {
|
||||
return $type;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getTypesMapping(): array
|
||||
{
|
||||
return $this->typesMapping;
|
||||
}
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Mapping;
|
||||
|
||||
/**
|
||||
* Knows how to get the class discriminator mapping for classes and objects.
|
||||
*
|
||||
* @author Samuel Roze <samuel.roze@gmail.com>
|
||||
*/
|
||||
interface ClassDiscriminatorResolverInterface
|
||||
{
|
||||
public function getMappingForClass(string $class): ?ClassDiscriminatorMapping;
|
||||
|
||||
/**
|
||||
* @param object|string $object
|
||||
*/
|
||||
public function getMappingForMappedObject($object): ?ClassDiscriminatorMapping;
|
||||
|
||||
/**
|
||||
* @param object|string $object
|
||||
*/
|
||||
public function getTypeForMappedObject($object): ?string;
|
||||
}
|
139
old.vendor/symfony/serializer/Mapping/ClassMetadata.php
Normal file
139
old.vendor/symfony/serializer/Mapping/ClassMetadata.php
Normal file
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Mapping;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
class ClassMetadata implements ClassMetadataInterface
|
||||
{
|
||||
/**
|
||||
* @internal This property is public in order to reduce the size of the
|
||||
* class' serialized representation. Do not access it. Use
|
||||
* {@link getName()} instead.
|
||||
*/
|
||||
public $name;
|
||||
|
||||
/**
|
||||
* @var AttributeMetadataInterface[]
|
||||
*
|
||||
* @internal This property is public in order to reduce the size of the
|
||||
* class' serialized representation. Do not access it. Use
|
||||
* {@link getAttributesMetadata()} instead.
|
||||
*/
|
||||
public $attributesMetadata = [];
|
||||
|
||||
/**
|
||||
* @var \ReflectionClass
|
||||
*/
|
||||
private $reflClass;
|
||||
|
||||
/**
|
||||
* @var ClassDiscriminatorMapping|null
|
||||
*
|
||||
* @internal This property is public in order to reduce the size of the
|
||||
* class' serialized representation. Do not access it. Use
|
||||
* {@link getClassDiscriminatorMapping()} instead.
|
||||
*/
|
||||
public $classDiscriminatorMapping;
|
||||
|
||||
/**
|
||||
* Constructs a metadata for the given class.
|
||||
*/
|
||||
public function __construct(string $class, ClassDiscriminatorMapping $classDiscriminatorMapping = null)
|
||||
{
|
||||
$this->name = $class;
|
||||
$this->classDiscriminatorMapping = $classDiscriminatorMapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addAttributeMetadata(AttributeMetadataInterface $attributeMetadata)
|
||||
{
|
||||
$this->attributesMetadata[$attributeMetadata->getName()] = $attributeMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getAttributesMetadata(): array
|
||||
{
|
||||
return $this->attributesMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function merge(ClassMetadataInterface $classMetadata)
|
||||
{
|
||||
foreach ($classMetadata->getAttributesMetadata() as $attributeMetadata) {
|
||||
if (isset($this->attributesMetadata[$attributeMetadata->getName()])) {
|
||||
$this->attributesMetadata[$attributeMetadata->getName()]->merge($attributeMetadata);
|
||||
} else {
|
||||
$this->addAttributeMetadata($attributeMetadata);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getReflectionClass(): \ReflectionClass
|
||||
{
|
||||
if (!$this->reflClass) {
|
||||
$this->reflClass = new \ReflectionClass($this->getName());
|
||||
}
|
||||
|
||||
return $this->reflClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getClassDiscriminatorMapping(): ?ClassDiscriminatorMapping
|
||||
{
|
||||
return $this->classDiscriminatorMapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setClassDiscriminatorMapping(ClassDiscriminatorMapping $mapping = null)
|
||||
{
|
||||
$this->classDiscriminatorMapping = $mapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the names of the properties that should be serialized.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function __sleep()
|
||||
{
|
||||
return [
|
||||
'name',
|
||||
'attributesMetadata',
|
||||
'classDiscriminatorMapping',
|
||||
];
|
||||
}
|
||||
}
|
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Mapping;
|
||||
|
||||
/**
|
||||
* Stores metadata needed for serializing and deserializing objects of specific class.
|
||||
*
|
||||
* Primarily, the metadata stores the set of attributes to serialize or deserialize.
|
||||
*
|
||||
* There may only exist one metadata for each attribute according to its name.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
interface ClassMetadataInterface
|
||||
{
|
||||
/**
|
||||
* Returns the name of the backing PHP class.
|
||||
*
|
||||
* @return string The name of the backing class
|
||||
*/
|
||||
public function getName(): string;
|
||||
|
||||
/**
|
||||
* Adds an {@link AttributeMetadataInterface}.
|
||||
*/
|
||||
public function addAttributeMetadata(AttributeMetadataInterface $attributeMetadata);
|
||||
|
||||
/**
|
||||
* Gets the list of {@link AttributeMetadataInterface}.
|
||||
*
|
||||
* @return AttributeMetadataInterface[]
|
||||
*/
|
||||
public function getAttributesMetadata(): array;
|
||||
|
||||
/**
|
||||
* Merges a {@link ClassMetadataInterface} in the current one.
|
||||
*/
|
||||
public function merge(self $classMetadata);
|
||||
|
||||
/**
|
||||
* Returns a {@link \ReflectionClass} instance for this class.
|
||||
*/
|
||||
public function getReflectionClass(): \ReflectionClass;
|
||||
|
||||
public function getClassDiscriminatorMapping(): ?ClassDiscriminatorMapping;
|
||||
|
||||
public function setClassDiscriminatorMapping(ClassDiscriminatorMapping $mapping = null);
|
||||
}
|
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Mapping\Factory;
|
||||
|
||||
use Psr\Cache\CacheItemPoolInterface;
|
||||
|
||||
/**
|
||||
* Caches metadata using a PSR-6 implementation.
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
class CacheClassMetadataFactory implements ClassMetadataFactoryInterface
|
||||
{
|
||||
use ClassResolverTrait;
|
||||
|
||||
/**
|
||||
* @var ClassMetadataFactoryInterface
|
||||
*/
|
||||
private $decorated;
|
||||
|
||||
/**
|
||||
* @var CacheItemPoolInterface
|
||||
*/
|
||||
private $cacheItemPool;
|
||||
|
||||
public function __construct(ClassMetadataFactoryInterface $decorated, CacheItemPoolInterface $cacheItemPool)
|
||||
{
|
||||
$this->decorated = $decorated;
|
||||
$this->cacheItemPool = $cacheItemPool;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getMetadataFor($value)
|
||||
{
|
||||
$class = $this->getClass($value);
|
||||
$key = rawurlencode(strtr($class, '\\', '_'));
|
||||
|
||||
$item = $this->cacheItemPool->getItem($key);
|
||||
if ($item->isHit()) {
|
||||
return $item->get();
|
||||
}
|
||||
|
||||
$metadata = $this->decorated->getMetadataFor($value);
|
||||
$this->cacheItemPool->save($item->set($metadata));
|
||||
|
||||
return $metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasMetadataFor($value)
|
||||
{
|
||||
return $this->decorated->hasMetadataFor($value);
|
||||
}
|
||||
}
|
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Mapping\Factory;
|
||||
|
||||
use Symfony\Component\Serializer\Mapping\ClassMetadata;
|
||||
use Symfony\Component\Serializer\Mapping\Loader\LoaderInterface;
|
||||
|
||||
/**
|
||||
* Returns a {@link ClassMetadata}.
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
class ClassMetadataFactory implements ClassMetadataFactoryInterface
|
||||
{
|
||||
use ClassResolverTrait;
|
||||
|
||||
private $loader;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $loadedClasses;
|
||||
|
||||
public function __construct(LoaderInterface $loader)
|
||||
{
|
||||
$this->loader = $loader;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getMetadataFor($value)
|
||||
{
|
||||
$class = $this->getClass($value);
|
||||
|
||||
if (isset($this->loadedClasses[$class])) {
|
||||
return $this->loadedClasses[$class];
|
||||
}
|
||||
|
||||
$classMetadata = new ClassMetadata($class);
|
||||
$this->loader->loadClassMetadata($classMetadata);
|
||||
|
||||
$reflectionClass = $classMetadata->getReflectionClass();
|
||||
|
||||
// Include metadata from the parent class
|
||||
if ($parent = $reflectionClass->getParentClass()) {
|
||||
$classMetadata->merge($this->getMetadataFor($parent->name));
|
||||
}
|
||||
|
||||
// Include metadata from all implemented interfaces
|
||||
foreach ($reflectionClass->getInterfaces() as $interface) {
|
||||
$classMetadata->merge($this->getMetadataFor($interface->name));
|
||||
}
|
||||
|
||||
return $this->loadedClasses[$class] = $classMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasMetadataFor($value)
|
||||
{
|
||||
return \is_object($value) || (\is_string($value) && (class_exists($value) || interface_exists($value, false)));
|
||||
}
|
||||
}
|
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Mapping\Factory;
|
||||
|
||||
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Serializer\Mapping\ClassMetadataInterface;
|
||||
|
||||
/**
|
||||
* Returns a {@see ClassMetadataInterface}.
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
interface ClassMetadataFactoryInterface
|
||||
{
|
||||
/**
|
||||
* If the method was called with the same class name (or an object of that
|
||||
* class) before, the same metadata instance is returned.
|
||||
*
|
||||
* If the factory was configured with a cache, this method will first look
|
||||
* for an existing metadata instance in the cache. If an existing instance
|
||||
* is found, it will be returned without further ado.
|
||||
*
|
||||
* Otherwise, a new metadata instance is created. If the factory was
|
||||
* configured with a loader, the metadata is passed to the
|
||||
* {@link \Symfony\Component\Serializer\Mapping\Loader\LoaderInterface::loadClassMetadata()} method for further
|
||||
* configuration. At last, the new object is returned.
|
||||
*
|
||||
* @param string|object $value
|
||||
*
|
||||
* @return ClassMetadataInterface
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function getMetadataFor($value);
|
||||
|
||||
/**
|
||||
* Checks if class has metadata.
|
||||
*
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasMetadataFor($value);
|
||||
}
|
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Mapping\Factory;
|
||||
|
||||
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Resolves a class name.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
trait ClassResolverTrait
|
||||
{
|
||||
/**
|
||||
* Gets a class name for a given class or instance.
|
||||
*
|
||||
* @param object|string $value
|
||||
*
|
||||
* @throws InvalidArgumentException If the class does not exist
|
||||
*/
|
||||
private function getClass($value): string
|
||||
{
|
||||
if (\is_string($value)) {
|
||||
if (!class_exists($value) && !interface_exists($value, false)) {
|
||||
throw new InvalidArgumentException(sprintf('The class or interface "%s" does not exist.', $value));
|
||||
}
|
||||
|
||||
return ltrim($value, '\\');
|
||||
}
|
||||
|
||||
if (!\is_object($value)) {
|
||||
throw new InvalidArgumentException(sprintf('Cannot create metadata for non-objects. Got: "%s".', \gettype($value)));
|
||||
}
|
||||
|
||||
return \get_class($value);
|
||||
}
|
||||
}
|
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Mapping\Loader;
|
||||
|
||||
use Doctrine\Common\Annotations\Reader;
|
||||
use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
|
||||
use Symfony\Component\Serializer\Annotation\Groups;
|
||||
use Symfony\Component\Serializer\Annotation\MaxDepth;
|
||||
use Symfony\Component\Serializer\Annotation\SerializedName;
|
||||
use Symfony\Component\Serializer\Exception\MappingException;
|
||||
use Symfony\Component\Serializer\Mapping\AttributeMetadata;
|
||||
use Symfony\Component\Serializer\Mapping\ClassDiscriminatorMapping;
|
||||
use Symfony\Component\Serializer\Mapping\ClassMetadataInterface;
|
||||
|
||||
/**
|
||||
* Annotation loader.
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
class AnnotationLoader implements LoaderInterface
|
||||
{
|
||||
private $reader;
|
||||
|
||||
public function __construct(Reader $reader)
|
||||
{
|
||||
$this->reader = $reader;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function loadClassMetadata(ClassMetadataInterface $classMetadata)
|
||||
{
|
||||
$reflectionClass = $classMetadata->getReflectionClass();
|
||||
$className = $reflectionClass->name;
|
||||
$loaded = false;
|
||||
|
||||
$attributesMetadata = $classMetadata->getAttributesMetadata();
|
||||
|
||||
foreach ($this->reader->getClassAnnotations($reflectionClass) as $annotation) {
|
||||
if ($annotation instanceof DiscriminatorMap) {
|
||||
$classMetadata->setClassDiscriminatorMapping(new ClassDiscriminatorMapping(
|
||||
$annotation->getTypeProperty(),
|
||||
$annotation->getMapping()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($reflectionClass->getProperties() as $property) {
|
||||
if (!isset($attributesMetadata[$property->name])) {
|
||||
$attributesMetadata[$property->name] = new AttributeMetadata($property->name);
|
||||
$classMetadata->addAttributeMetadata($attributesMetadata[$property->name]);
|
||||
}
|
||||
|
||||
if ($property->getDeclaringClass()->name === $className) {
|
||||
foreach ($this->reader->getPropertyAnnotations($property) as $annotation) {
|
||||
if ($annotation instanceof Groups) {
|
||||
foreach ($annotation->getGroups() as $group) {
|
||||
$attributesMetadata[$property->name]->addGroup($group);
|
||||
}
|
||||
} elseif ($annotation instanceof MaxDepth) {
|
||||
$attributesMetadata[$property->name]->setMaxDepth($annotation->getMaxDepth());
|
||||
} elseif ($annotation instanceof SerializedName) {
|
||||
$attributesMetadata[$property->name]->setSerializedName($annotation->getSerializedName());
|
||||
}
|
||||
|
||||
$loaded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($reflectionClass->getMethods() as $method) {
|
||||
if ($method->getDeclaringClass()->name !== $className) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$accessorOrMutator = preg_match('/^(get|is|has|set)(.+)$/i', $method->name, $matches);
|
||||
if ($accessorOrMutator) {
|
||||
$attributeName = lcfirst($matches[2]);
|
||||
|
||||
if (isset($attributesMetadata[$attributeName])) {
|
||||
$attributeMetadata = $attributesMetadata[$attributeName];
|
||||
} else {
|
||||
$attributesMetadata[$attributeName] = $attributeMetadata = new AttributeMetadata($attributeName);
|
||||
$classMetadata->addAttributeMetadata($attributeMetadata);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->reader->getMethodAnnotations($method) as $annotation) {
|
||||
if ($annotation instanceof Groups) {
|
||||
if (!$accessorOrMutator) {
|
||||
throw new MappingException(sprintf('Groups on "%s::%s()" cannot be added. Groups can only be added on methods beginning with "get", "is", "has" or "set".', $className, $method->name));
|
||||
}
|
||||
|
||||
foreach ($annotation->getGroups() as $group) {
|
||||
$attributeMetadata->addGroup($group);
|
||||
}
|
||||
} elseif ($annotation instanceof MaxDepth) {
|
||||
if (!$accessorOrMutator) {
|
||||
throw new MappingException(sprintf('MaxDepth on "%s::%s()" cannot be added. MaxDepth can only be added on methods beginning with "get", "is", "has" or "set".', $className, $method->name));
|
||||
}
|
||||
|
||||
$attributeMetadata->setMaxDepth($annotation->getMaxDepth());
|
||||
} elseif ($annotation instanceof SerializedName) {
|
||||
if (!$accessorOrMutator) {
|
||||
throw new MappingException(sprintf('SerializedName on "%s::%s()" cannot be added. SerializedName can only be added on methods beginning with "get", "is", "has" or "set".', $className, $method->name));
|
||||
}
|
||||
|
||||
$attributeMetadata->setSerializedName($annotation->getSerializedName());
|
||||
}
|
||||
|
||||
$loaded = true;
|
||||
}
|
||||
}
|
||||
|
||||
return $loaded;
|
||||
}
|
||||
}
|
42
old.vendor/symfony/serializer/Mapping/Loader/FileLoader.php
Normal file
42
old.vendor/symfony/serializer/Mapping/Loader/FileLoader.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Mapping\Loader;
|
||||
|
||||
use Symfony\Component\Serializer\Exception\MappingException;
|
||||
|
||||
/**
|
||||
* Base class for all file based loaders.
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
abstract class FileLoader implements LoaderInterface
|
||||
{
|
||||
protected $file;
|
||||
|
||||
/**
|
||||
* @param string $file The mapping file to load
|
||||
*
|
||||
* @throws MappingException if the mapping file does not exist or is not readable
|
||||
*/
|
||||
public function __construct(string $file)
|
||||
{
|
||||
if (!is_file($file)) {
|
||||
throw new MappingException(sprintf('The mapping file "%s" does not exist.', $file));
|
||||
}
|
||||
|
||||
if (!is_readable($file)) {
|
||||
throw new MappingException(sprintf('The mapping file "%s" is not readable.', $file));
|
||||
}
|
||||
|
||||
$this->file = $file;
|
||||
}
|
||||
}
|
71
old.vendor/symfony/serializer/Mapping/Loader/LoaderChain.php
Normal file
71
old.vendor/symfony/serializer/Mapping/Loader/LoaderChain.php
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Mapping\Loader;
|
||||
|
||||
use Symfony\Component\Serializer\Exception\MappingException;
|
||||
use Symfony\Component\Serializer\Mapping\ClassMetadataInterface;
|
||||
|
||||
/**
|
||||
* Calls multiple {@link LoaderInterface} instances in a chain.
|
||||
*
|
||||
* This class accepts multiple instances of LoaderInterface to be passed to the
|
||||
* constructor. When {@link loadClassMetadata()} is called, the same method is called
|
||||
* in <em>all</em> of these loaders, regardless of whether any of them was
|
||||
* successful or not.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
class LoaderChain implements LoaderInterface
|
||||
{
|
||||
private $loaders;
|
||||
|
||||
/**
|
||||
* Accepts a list of LoaderInterface instances.
|
||||
*
|
||||
* @param LoaderInterface[] $loaders An array of LoaderInterface instances
|
||||
*
|
||||
* @throws MappingException If any of the loaders does not implement LoaderInterface
|
||||
*/
|
||||
public function __construct(array $loaders)
|
||||
{
|
||||
foreach ($loaders as $loader) {
|
||||
if (!$loader instanceof LoaderInterface) {
|
||||
throw new MappingException(sprintf('Class "%s" is expected to implement LoaderInterface.', \get_class($loader)));
|
||||
}
|
||||
}
|
||||
|
||||
$this->loaders = $loaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function loadClassMetadata(ClassMetadataInterface $metadata)
|
||||
{
|
||||
$success = false;
|
||||
|
||||
foreach ($this->loaders as $loader) {
|
||||
$success = $loader->loadClassMetadata($metadata) || $success;
|
||||
}
|
||||
|
||||
return $success;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return LoaderInterface[]
|
||||
*/
|
||||
public function getLoaders()
|
||||
{
|
||||
return $this->loaders;
|
||||
}
|
||||
}
|
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Mapping\Loader;
|
||||
|
||||
use Symfony\Component\Serializer\Mapping\ClassMetadataInterface;
|
||||
|
||||
/**
|
||||
* Loads {@link ClassMetadataInterface}.
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
interface LoaderInterface
|
||||
{
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function loadClassMetadata(ClassMetadataInterface $classMetadata);
|
||||
}
|
135
old.vendor/symfony/serializer/Mapping/Loader/XmlFileLoader.php
Normal file
135
old.vendor/symfony/serializer/Mapping/Loader/XmlFileLoader.php
Normal file
@@ -0,0 +1,135 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Mapping\Loader;
|
||||
|
||||
use Symfony\Component\Config\Util\XmlUtils;
|
||||
use Symfony\Component\Serializer\Exception\MappingException;
|
||||
use Symfony\Component\Serializer\Mapping\AttributeMetadata;
|
||||
use Symfony\Component\Serializer\Mapping\ClassDiscriminatorMapping;
|
||||
use Symfony\Component\Serializer\Mapping\ClassMetadataInterface;
|
||||
|
||||
/**
|
||||
* Loads XML mapping files.
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
class XmlFileLoader extends FileLoader
|
||||
{
|
||||
/**
|
||||
* An array of {@class \SimpleXMLElement} instances.
|
||||
*
|
||||
* @var \SimpleXMLElement[]|null
|
||||
*/
|
||||
private $classes;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function loadClassMetadata(ClassMetadataInterface $classMetadata)
|
||||
{
|
||||
if (null === $this->classes) {
|
||||
$this->classes = $this->getClassesFromXml();
|
||||
}
|
||||
|
||||
if (!$this->classes) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$attributesMetadata = $classMetadata->getAttributesMetadata();
|
||||
|
||||
if (isset($this->classes[$classMetadata->getName()])) {
|
||||
$xml = $this->classes[$classMetadata->getName()];
|
||||
|
||||
foreach ($xml->attribute as $attribute) {
|
||||
$attributeName = (string) $attribute['name'];
|
||||
|
||||
if (isset($attributesMetadata[$attributeName])) {
|
||||
$attributeMetadata = $attributesMetadata[$attributeName];
|
||||
} else {
|
||||
$attributeMetadata = new AttributeMetadata($attributeName);
|
||||
$classMetadata->addAttributeMetadata($attributeMetadata);
|
||||
}
|
||||
|
||||
foreach ($attribute->group as $group) {
|
||||
$attributeMetadata->addGroup((string) $group);
|
||||
}
|
||||
|
||||
if (isset($attribute['max-depth'])) {
|
||||
$attributeMetadata->setMaxDepth((int) $attribute['max-depth']);
|
||||
}
|
||||
|
||||
if (isset($attribute['serialized-name'])) {
|
||||
$attributeMetadata->setSerializedName((string) $attribute['serialized-name']);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($xml->{'discriminator-map'})) {
|
||||
$mapping = [];
|
||||
foreach ($xml->{'discriminator-map'}->mapping as $element) {
|
||||
$elementAttributes = $element->attributes();
|
||||
$mapping[(string) $elementAttributes->type] = (string) $elementAttributes->class;
|
||||
}
|
||||
|
||||
$classMetadata->setClassDiscriminatorMapping(new ClassDiscriminatorMapping(
|
||||
(string) $xml->{'discriminator-map'}->attributes()->{'type-property'},
|
||||
$mapping
|
||||
));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the names of the classes mapped in this file.
|
||||
*
|
||||
* @return string[] The classes names
|
||||
*/
|
||||
public function getMappedClasses()
|
||||
{
|
||||
if (null === $this->classes) {
|
||||
$this->classes = $this->getClassesFromXml();
|
||||
}
|
||||
|
||||
return array_keys($this->classes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an XML File.
|
||||
*
|
||||
* @throws MappingException
|
||||
*/
|
||||
private function parseFile(string $file): \SimpleXMLElement
|
||||
{
|
||||
try {
|
||||
$dom = XmlUtils::loadFile($file, __DIR__.'/schema/dic/serializer-mapping/serializer-mapping-1.0.xsd');
|
||||
} catch (\Exception $e) {
|
||||
throw new MappingException($e->getMessage(), $e->getCode(), $e);
|
||||
}
|
||||
|
||||
return simplexml_import_dom($dom);
|
||||
}
|
||||
|
||||
private function getClassesFromXml(): array
|
||||
{
|
||||
$xml = $this->parseFile($this->file);
|
||||
$classes = [];
|
||||
|
||||
foreach ($xml->class as $class) {
|
||||
$classes[(string) $class['name']] = $class;
|
||||
}
|
||||
|
||||
return $classes;
|
||||
}
|
||||
}
|
153
old.vendor/symfony/serializer/Mapping/Loader/YamlFileLoader.php
Normal file
153
old.vendor/symfony/serializer/Mapping/Loader/YamlFileLoader.php
Normal file
@@ -0,0 +1,153 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Mapping\Loader;
|
||||
|
||||
use Symfony\Component\Serializer\Exception\MappingException;
|
||||
use Symfony\Component\Serializer\Mapping\AttributeMetadata;
|
||||
use Symfony\Component\Serializer\Mapping\ClassDiscriminatorMapping;
|
||||
use Symfony\Component\Serializer\Mapping\ClassMetadataInterface;
|
||||
use Symfony\Component\Yaml\Parser;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
/**
|
||||
* YAML File Loader.
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
class YamlFileLoader extends FileLoader
|
||||
{
|
||||
private $yamlParser;
|
||||
|
||||
/**
|
||||
* An array of YAML class descriptions.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $classes;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function loadClassMetadata(ClassMetadataInterface $classMetadata)
|
||||
{
|
||||
if (null === $this->classes) {
|
||||
$this->classes = $this->getClassesFromYaml();
|
||||
}
|
||||
|
||||
if (!$this->classes) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isset($this->classes[$classMetadata->getName()])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$yaml = $this->classes[$classMetadata->getName()];
|
||||
|
||||
if (isset($yaml['attributes']) && \is_array($yaml['attributes'])) {
|
||||
$attributesMetadata = $classMetadata->getAttributesMetadata();
|
||||
|
||||
foreach ($yaml['attributes'] as $attribute => $data) {
|
||||
if (isset($attributesMetadata[$attribute])) {
|
||||
$attributeMetadata = $attributesMetadata[$attribute];
|
||||
} else {
|
||||
$attributeMetadata = new AttributeMetadata($attribute);
|
||||
$classMetadata->addAttributeMetadata($attributeMetadata);
|
||||
}
|
||||
|
||||
if (isset($data['groups'])) {
|
||||
if (!\is_array($data['groups'])) {
|
||||
throw new MappingException(sprintf('The "groups" key must be an array of strings in "%s" for the attribute "%s" of the class "%s".', $this->file, $attribute, $classMetadata->getName()));
|
||||
}
|
||||
|
||||
foreach ($data['groups'] as $group) {
|
||||
if (!\is_string($group)) {
|
||||
throw new MappingException(sprintf('Group names must be strings in "%s" for the attribute "%s" of the class "%s".', $this->file, $attribute, $classMetadata->getName()));
|
||||
}
|
||||
|
||||
$attributeMetadata->addGroup($group);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($data['max_depth'])) {
|
||||
if (!\is_int($data['max_depth'])) {
|
||||
throw new MappingException(sprintf('The "max_depth" value must be an integer in "%s" for the attribute "%s" of the class "%s".', $this->file, $attribute, $classMetadata->getName()));
|
||||
}
|
||||
|
||||
$attributeMetadata->setMaxDepth($data['max_depth']);
|
||||
}
|
||||
|
||||
if (isset($data['serialized_name'])) {
|
||||
if (!\is_string($data['serialized_name']) || empty($data['serialized_name'])) {
|
||||
throw new MappingException(sprintf('The "serialized_name" value must be a non-empty string in "%s" for the attribute "%s" of the class "%s".', $this->file, $attribute, $classMetadata->getName()));
|
||||
}
|
||||
|
||||
$attributeMetadata->setSerializedName($data['serialized_name']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($yaml['discriminator_map'])) {
|
||||
if (!isset($yaml['discriminator_map']['type_property'])) {
|
||||
throw new MappingException(sprintf('The "type_property" key must be set for the discriminator map of the class "%s" in "%s".', $classMetadata->getName(), $this->file));
|
||||
}
|
||||
|
||||
if (!isset($yaml['discriminator_map']['mapping'])) {
|
||||
throw new MappingException(sprintf('The "mapping" key must be set for the discriminator map of the class "%s" in "%s".', $classMetadata->getName(), $this->file));
|
||||
}
|
||||
|
||||
$classMetadata->setClassDiscriminatorMapping(new ClassDiscriminatorMapping(
|
||||
$yaml['discriminator_map']['type_property'],
|
||||
$yaml['discriminator_map']['mapping']
|
||||
));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the names of the classes mapped in this file.
|
||||
*
|
||||
* @return string[] The classes names
|
||||
*/
|
||||
public function getMappedClasses()
|
||||
{
|
||||
if (null === $this->classes) {
|
||||
$this->classes = $this->getClassesFromYaml();
|
||||
}
|
||||
|
||||
return array_keys($this->classes);
|
||||
}
|
||||
|
||||
private function getClassesFromYaml(): array
|
||||
{
|
||||
if (!stream_is_local($this->file)) {
|
||||
throw new MappingException(sprintf('This is not a local file "%s".', $this->file));
|
||||
}
|
||||
|
||||
if (null === $this->yamlParser) {
|
||||
$this->yamlParser = new Parser();
|
||||
}
|
||||
|
||||
$classes = $this->yamlParser->parseFile($this->file, Yaml::PARSE_CONSTANT);
|
||||
|
||||
if (empty($classes)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!\is_array($classes)) {
|
||||
throw new MappingException(sprintf('The file "%s" must contain a YAML array.', $this->file));
|
||||
}
|
||||
|
||||
return $classes;
|
||||
}
|
||||
}
|
@@ -0,0 +1,83 @@
|
||||
<?xml version="1.0" ?>
|
||||
|
||||
<xsd:schema xmlns="http://symfony.com/schema/dic/serializer-mapping"
|
||||
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||
targetNamespace="http://symfony.com/schema/dic/serializer-mapping"
|
||||
elementFormDefault="qualified">
|
||||
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Symfony Serializer Mapping Schema, version 1.0
|
||||
Authors: Kévin Dunglas, Samuel Roze
|
||||
|
||||
A serializer mapping connects attributes with serialization groups.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
|
||||
<xsd:element name="serializer" type="serializer" />
|
||||
|
||||
<xsd:complexType name="serializer">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The root element of the serializer mapping definition.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:element name="class" type="class" />
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="class">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Contains serialization groups for a single class.
|
||||
|
||||
Nested elements may be class property and/or getter definitions.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:element name="attribute" type="attribute" minOccurs="0" maxOccurs="unbounded" />
|
||||
<xsd:element name="discriminator-map" type="discriminator-map" />
|
||||
</xsd:choice>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="discriminator-map">
|
||||
<xsd:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:element name="mapping" type="discriminator-map-mapping" maxOccurs="unbounded" />
|
||||
</xsd:choice>
|
||||
<xsd:attribute name="type-property" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="discriminator-map-mapping">
|
||||
<xsd:attribute name="type" type="xsd:string" use="required" />
|
||||
<xsd:attribute name="class" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="attribute">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Contains serialization groups and max depth for attributes. The name of the attribute should be given in the "name" option.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:sequence minOccurs="0">
|
||||
<xsd:element name="group" type="xsd:string" maxOccurs="unbounded" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
<xsd:attribute name="max-depth">
|
||||
<xsd:simpleType>
|
||||
<xsd:restriction base="xsd:integer">
|
||||
<xsd:minInclusive value="0" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="serialized-name">
|
||||
<xsd:simpleType>
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:minLength value="1" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
</xsd:schema>
|
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\NameConverter;
|
||||
|
||||
/**
|
||||
* Gives access to the class, the format and the context in the property name converters.
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
interface AdvancedNameConverterInterface extends NameConverterInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function normalize($propertyName, string $class = null, string $format = null, array $context = []);
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function denormalize($propertyName, string $class = null, string $format = null, array $context = []);
|
||||
}
|
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\NameConverter;
|
||||
|
||||
/**
|
||||
* CamelCase to Underscore name converter.
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
class CamelCaseToSnakeCaseNameConverter implements NameConverterInterface
|
||||
{
|
||||
private $attributes;
|
||||
private $lowerCamelCase;
|
||||
|
||||
/**
|
||||
* @param array|null $attributes The list of attributes to rename or null for all attributes
|
||||
* @param bool $lowerCamelCase Use lowerCamelCase style
|
||||
*/
|
||||
public function __construct(array $attributes = null, bool $lowerCamelCase = true)
|
||||
{
|
||||
$this->attributes = $attributes;
|
||||
$this->lowerCamelCase = $lowerCamelCase;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function normalize($propertyName)
|
||||
{
|
||||
if (null === $this->attributes || \in_array($propertyName, $this->attributes)) {
|
||||
return strtolower(preg_replace('/[A-Z]/', '_\\0', lcfirst($propertyName)));
|
||||
}
|
||||
|
||||
return $propertyName;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function denormalize($propertyName)
|
||||
{
|
||||
$camelCasedName = preg_replace_callback('/(^|_|\.)+(.)/', function ($match) {
|
||||
return ('.' === $match[1] ? '_' : '').strtoupper($match[2]);
|
||||
}, $propertyName);
|
||||
|
||||
if ($this->lowerCamelCase) {
|
||||
$camelCasedName = lcfirst($camelCasedName);
|
||||
}
|
||||
|
||||
if (null === $this->attributes || \in_array($camelCasedName, $this->attributes)) {
|
||||
return $camelCasedName;
|
||||
}
|
||||
|
||||
return $propertyName;
|
||||
}
|
||||
}
|
@@ -0,0 +1,144 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\NameConverter;
|
||||
|
||||
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
|
||||
|
||||
/**
|
||||
* @author Fabien Bourigault <bourigaultfabien@gmail.com>
|
||||
*/
|
||||
final class MetadataAwareNameConverter implements AdvancedNameConverterInterface
|
||||
{
|
||||
private $metadataFactory;
|
||||
|
||||
/**
|
||||
* @var NameConverterInterface|AdvancedNameConverterInterface|null
|
||||
*/
|
||||
private $fallbackNameConverter;
|
||||
|
||||
private static $normalizeCache = [];
|
||||
|
||||
private static $denormalizeCache = [];
|
||||
|
||||
private static $attributesMetadataCache = [];
|
||||
|
||||
public function __construct(ClassMetadataFactoryInterface $metadataFactory, NameConverterInterface $fallbackNameConverter = null)
|
||||
{
|
||||
$this->metadataFactory = $metadataFactory;
|
||||
$this->fallbackNameConverter = $fallbackNameConverter;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function normalize($propertyName, string $class = null, string $format = null, array $context = []): string
|
||||
{
|
||||
if (null === $class) {
|
||||
return $this->normalizeFallback($propertyName, $class, $format, $context);
|
||||
}
|
||||
|
||||
if (!\array_key_exists($class, self::$normalizeCache) || !\array_key_exists($propertyName, self::$normalizeCache[$class])) {
|
||||
self::$normalizeCache[$class][$propertyName] = $this->getCacheValueForNormalization($propertyName, $class);
|
||||
}
|
||||
|
||||
return self::$normalizeCache[$class][$propertyName] ?? $this->normalizeFallback($propertyName, $class, $format, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function denormalize($propertyName, string $class = null, string $format = null, array $context = []): string
|
||||
{
|
||||
if (null === $class) {
|
||||
return $this->denormalizeFallback($propertyName, $class, $format, $context);
|
||||
}
|
||||
|
||||
$cacheKey = $this->getCacheKey($class, $context);
|
||||
if (!\array_key_exists($cacheKey, self::$denormalizeCache) || !\array_key_exists($propertyName, self::$denormalizeCache[$cacheKey])) {
|
||||
self::$denormalizeCache[$cacheKey][$propertyName] = $this->getCacheValueForDenormalization($propertyName, $class, $context);
|
||||
}
|
||||
|
||||
return self::$denormalizeCache[$cacheKey][$propertyName] ?? $this->denormalizeFallback($propertyName, $class, $format, $context);
|
||||
}
|
||||
|
||||
private function getCacheValueForNormalization(string $propertyName, string $class): ?string
|
||||
{
|
||||
if (!$this->metadataFactory->hasMetadataFor($class)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$attributesMetadata = $this->metadataFactory->getMetadataFor($class)->getAttributesMetadata();
|
||||
if (!\array_key_exists($propertyName, $attributesMetadata)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $attributesMetadata[$propertyName]->getSerializedName() ?? null;
|
||||
}
|
||||
|
||||
private function normalizeFallback(string $propertyName, string $class = null, string $format = null, array $context = []): string
|
||||
{
|
||||
return $this->fallbackNameConverter ? $this->fallbackNameConverter->normalize($propertyName, $class, $format, $context) : $propertyName;
|
||||
}
|
||||
|
||||
private function getCacheValueForDenormalization(string $propertyName, string $class, array $context): ?string
|
||||
{
|
||||
$cacheKey = $this->getCacheKey($class, $context);
|
||||
if (!\array_key_exists($cacheKey, self::$attributesMetadataCache)) {
|
||||
self::$attributesMetadataCache[$cacheKey] = $this->getCacheValueForAttributesMetadata($class, $context);
|
||||
}
|
||||
|
||||
return self::$attributesMetadataCache[$cacheKey][$propertyName] ?? null;
|
||||
}
|
||||
|
||||
private function denormalizeFallback(string $propertyName, string $class = null, string $format = null, array $context = []): string
|
||||
{
|
||||
return $this->fallbackNameConverter ? $this->fallbackNameConverter->denormalize($propertyName, $class, $format, $context) : $propertyName;
|
||||
}
|
||||
|
||||
private function getCacheValueForAttributesMetadata(string $class, array $context): array
|
||||
{
|
||||
if (!$this->metadataFactory->hasMetadataFor($class)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$classMetadata = $this->metadataFactory->getMetadataFor($class);
|
||||
|
||||
$cache = [];
|
||||
foreach ($classMetadata->getAttributesMetadata() as $name => $metadata) {
|
||||
if (null === $metadata->getSerializedName()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$groups = $metadata->getGroups();
|
||||
if (!$groups && ($context[AbstractNormalizer::GROUPS] ?? [])) {
|
||||
continue;
|
||||
}
|
||||
if ($groups && !array_intersect($groups, (array) ($context[AbstractNormalizer::GROUPS] ?? []))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$cache[$metadata->getSerializedName()] = $name;
|
||||
}
|
||||
|
||||
return $cache;
|
||||
}
|
||||
|
||||
private function getCacheKey(string $class, array $context): string
|
||||
{
|
||||
if (isset($context['cache_key'])) {
|
||||
return $class.'-'.$context['cache_key'];
|
||||
}
|
||||
|
||||
return $class.md5(serialize($context[AbstractNormalizer::GROUPS] ?? []));
|
||||
}
|
||||
}
|
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\NameConverter;
|
||||
|
||||
/**
|
||||
* Defines the interface for property name converters.
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
interface NameConverterInterface
|
||||
{
|
||||
/**
|
||||
* Converts a property name to its normalized value.
|
||||
*
|
||||
* @param string $propertyName
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function normalize($propertyName);
|
||||
|
||||
/**
|
||||
* Converts a property name to its denormalized value.
|
||||
*
|
||||
* @param string $propertyName
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function denormalize($propertyName);
|
||||
}
|
568
old.vendor/symfony/serializer/Normalizer/AbstractNormalizer.php
Normal file
568
old.vendor/symfony/serializer/Normalizer/AbstractNormalizer.php
Normal file
@@ -0,0 +1,568 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Normalizer;
|
||||
|
||||
use Symfony\Component\Serializer\Exception\CircularReferenceException;
|
||||
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Serializer\Exception\LogicException;
|
||||
use Symfony\Component\Serializer\Exception\MissingConstructorArgumentsException;
|
||||
use Symfony\Component\Serializer\Exception\RuntimeException;
|
||||
use Symfony\Component\Serializer\Mapping\AttributeMetadataInterface;
|
||||
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
|
||||
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
|
||||
use Symfony\Component\Serializer\SerializerAwareInterface;
|
||||
use Symfony\Component\Serializer\SerializerAwareTrait;
|
||||
|
||||
/**
|
||||
* Normalizer implementation.
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
abstract class AbstractNormalizer implements NormalizerInterface, DenormalizerInterface, SerializerAwareInterface, CacheableSupportsMethodInterface
|
||||
{
|
||||
use ObjectToPopulateTrait;
|
||||
use SerializerAwareTrait;
|
||||
|
||||
/* constants to configure the context */
|
||||
|
||||
/**
|
||||
* How many loops of circular reference to allow while normalizing.
|
||||
*
|
||||
* The default value of 1 means that when we encounter the same object a
|
||||
* second time, we consider that a circular reference.
|
||||
*
|
||||
* You can raise this value for special cases, e.g. in combination with the
|
||||
* max depth setting of the object normalizer.
|
||||
*/
|
||||
public const CIRCULAR_REFERENCE_LIMIT = 'circular_reference_limit';
|
||||
|
||||
/**
|
||||
* Instead of creating a new instance of an object, update the specified object.
|
||||
*
|
||||
* If you have a nested structure, child objects will be overwritten with
|
||||
* new instances unless you set DEEP_OBJECT_TO_POPULATE to true.
|
||||
*/
|
||||
public const OBJECT_TO_POPULATE = 'object_to_populate';
|
||||
|
||||
/**
|
||||
* Only (de)normalize attributes that are in the specified groups.
|
||||
*/
|
||||
public const GROUPS = 'groups';
|
||||
|
||||
/**
|
||||
* Limit (de)normalize to the specified names.
|
||||
*
|
||||
* For nested structures, this list needs to reflect the object tree.
|
||||
*/
|
||||
public const ATTRIBUTES = 'attributes';
|
||||
|
||||
/**
|
||||
* If ATTRIBUTES are specified, and the source has fields that are not part of that list,
|
||||
* either ignore those attributes (true) or throw an ExtraAttributesException (false).
|
||||
*/
|
||||
public const ALLOW_EXTRA_ATTRIBUTES = 'allow_extra_attributes';
|
||||
|
||||
/**
|
||||
* Hashmap of default values for constructor arguments.
|
||||
*
|
||||
* The names need to match the parameter names in the constructor arguments.
|
||||
*/
|
||||
public const DEFAULT_CONSTRUCTOR_ARGUMENTS = 'default_constructor_arguments';
|
||||
|
||||
/**
|
||||
* Hashmap of field name => callable to normalize this field.
|
||||
*
|
||||
* The callable is called if the field is encountered with the arguments:
|
||||
*
|
||||
* - mixed $attributeValue value of this field
|
||||
* - object $object the whole object being normalized
|
||||
* - string $attributeName name of the attribute being normalized
|
||||
* - string $format the requested format
|
||||
* - array $context the serialization context
|
||||
*/
|
||||
public const CALLBACKS = 'callbacks';
|
||||
|
||||
/**
|
||||
* Handler to call when a circular reference has been detected.
|
||||
*
|
||||
* If you specify no handler, a CircularReferenceException is thrown.
|
||||
*
|
||||
* The method will be called with ($object, $format, $context) and its
|
||||
* return value is returned as the result of the normalize call.
|
||||
*/
|
||||
public const CIRCULAR_REFERENCE_HANDLER = 'circular_reference_handler';
|
||||
|
||||
/**
|
||||
* Skip the specified attributes when normalizing an object tree.
|
||||
*
|
||||
* This list is applied to each element of nested structures.
|
||||
*
|
||||
* Note: The behaviour for nested structures is different from ATTRIBUTES
|
||||
* for historical reason. Aligning the behaviour would be a BC break.
|
||||
*/
|
||||
public const IGNORED_ATTRIBUTES = 'ignored_attributes';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected const CIRCULAR_REFERENCE_LIMIT_COUNTERS = 'circular_reference_limit_counters';
|
||||
|
||||
protected $defaultContext = [
|
||||
self::ALLOW_EXTRA_ATTRIBUTES => true,
|
||||
self::CIRCULAR_REFERENCE_LIMIT => 1,
|
||||
self::IGNORED_ATTRIBUTES => [],
|
||||
];
|
||||
|
||||
/**
|
||||
* @deprecated since Symfony 4.2
|
||||
*/
|
||||
protected $circularReferenceLimit = 1;
|
||||
|
||||
/**
|
||||
* @deprecated since Symfony 4.2
|
||||
*
|
||||
* @var callable|null
|
||||
*/
|
||||
protected $circularReferenceHandler;
|
||||
|
||||
/**
|
||||
* @var ClassMetadataFactoryInterface|null
|
||||
*/
|
||||
protected $classMetadataFactory;
|
||||
|
||||
/**
|
||||
* @var NameConverterInterface|null
|
||||
*/
|
||||
protected $nameConverter;
|
||||
|
||||
/**
|
||||
* @deprecated since Symfony 4.2
|
||||
*/
|
||||
protected $callbacks = [];
|
||||
|
||||
/**
|
||||
* @deprecated since Symfony 4.2
|
||||
*/
|
||||
protected $ignoredAttributes = [];
|
||||
|
||||
/**
|
||||
* @deprecated since Symfony 4.2
|
||||
*/
|
||||
protected $camelizedAttributes = [];
|
||||
|
||||
/**
|
||||
* Sets the {@link ClassMetadataFactoryInterface} to use.
|
||||
*/
|
||||
public function __construct(ClassMetadataFactoryInterface $classMetadataFactory = null, NameConverterInterface $nameConverter = null, array $defaultContext = [])
|
||||
{
|
||||
$this->classMetadataFactory = $classMetadataFactory;
|
||||
$this->nameConverter = $nameConverter;
|
||||
$this->defaultContext = array_merge($this->defaultContext, $defaultContext);
|
||||
|
||||
if (isset($this->defaultContext[self::CALLBACKS])) {
|
||||
if (!\is_array($this->defaultContext[self::CALLBACKS])) {
|
||||
throw new InvalidArgumentException(sprintf('The "%s" default context option must be an array of callables.', self::CALLBACKS));
|
||||
}
|
||||
|
||||
foreach ($this->defaultContext[self::CALLBACKS] as $attribute => $callback) {
|
||||
if (!\is_callable($callback)) {
|
||||
throw new InvalidArgumentException(sprintf('Invalid callback found for attribute "%s" in the "%s" default context option.', $attribute, self::CALLBACKS));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($this->defaultContext[self::CIRCULAR_REFERENCE_HANDLER]) && !\is_callable($this->defaultContext[self::CIRCULAR_REFERENCE_HANDLER])) {
|
||||
throw new InvalidArgumentException(sprintf('Invalid callback found in the "%s" default context option.', self::CIRCULAR_REFERENCE_HANDLER));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets circular reference limit.
|
||||
*
|
||||
* @deprecated since Symfony 4.2
|
||||
*
|
||||
* @param int $circularReferenceLimit Limit of iterations for the same object
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setCircularReferenceLimit($circularReferenceLimit)
|
||||
{
|
||||
@trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2, use the "circular_reference_limit" key of the context instead.', __METHOD__), \E_USER_DEPRECATED);
|
||||
|
||||
$this->defaultContext[self::CIRCULAR_REFERENCE_LIMIT] = $this->circularReferenceLimit = $circularReferenceLimit;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets circular reference handler.
|
||||
*
|
||||
* @deprecated since Symfony 4.2
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setCircularReferenceHandler(callable $circularReferenceHandler)
|
||||
{
|
||||
@trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2, use the "circular_reference_handler" key of the context instead.', __METHOD__), \E_USER_DEPRECATED);
|
||||
|
||||
$this->defaultContext[self::CIRCULAR_REFERENCE_HANDLER] = $this->circularReferenceHandler = $circularReferenceHandler;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets normalization callbacks.
|
||||
*
|
||||
* @deprecated since Symfony 4.2
|
||||
*
|
||||
* @param callable[] $callbacks Help normalize the result
|
||||
*
|
||||
* @return self
|
||||
*
|
||||
* @throws InvalidArgumentException if a non-callable callback is set
|
||||
*/
|
||||
public function setCallbacks(array $callbacks)
|
||||
{
|
||||
@trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2, use the "callbacks" key of the context instead.', __METHOD__), \E_USER_DEPRECATED);
|
||||
|
||||
foreach ($callbacks as $attribute => $callback) {
|
||||
if (!\is_callable($callback)) {
|
||||
throw new InvalidArgumentException(sprintf('The given callback for attribute "%s" is not callable.', $attribute));
|
||||
}
|
||||
}
|
||||
$this->defaultContext[self::CALLBACKS] = $this->callbacks = $callbacks;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets ignored attributes for normalization and denormalization.
|
||||
*
|
||||
* @deprecated since Symfony 4.2
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setIgnoredAttributes(array $ignoredAttributes)
|
||||
{
|
||||
@trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2, use the "ignored_attributes" key of the context instead.', __METHOD__), \E_USER_DEPRECATED);
|
||||
|
||||
$this->defaultContext[self::IGNORED_ATTRIBUTES] = $this->ignoredAttributes = $ignoredAttributes;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasCacheableSupportsMethod(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detects if the configured circular reference limit is reached.
|
||||
*
|
||||
* @param object $object
|
||||
* @param array $context
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @throws CircularReferenceException
|
||||
*/
|
||||
protected function isCircularReference($object, &$context)
|
||||
{
|
||||
$objectHash = spl_object_hash($object);
|
||||
|
||||
$circularReferenceLimit = $context[self::CIRCULAR_REFERENCE_LIMIT] ?? $this->defaultContext[self::CIRCULAR_REFERENCE_LIMIT] ?? $this->circularReferenceLimit;
|
||||
if (isset($context[self::CIRCULAR_REFERENCE_LIMIT_COUNTERS][$objectHash])) {
|
||||
if ($context[self::CIRCULAR_REFERENCE_LIMIT_COUNTERS][$objectHash] >= $circularReferenceLimit) {
|
||||
unset($context[self::CIRCULAR_REFERENCE_LIMIT_COUNTERS][$objectHash]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
++$context[self::CIRCULAR_REFERENCE_LIMIT_COUNTERS][$objectHash];
|
||||
} else {
|
||||
$context[self::CIRCULAR_REFERENCE_LIMIT_COUNTERS][$objectHash] = 1;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a circular reference.
|
||||
*
|
||||
* If a circular reference handler is set, it will be called. Otherwise, a
|
||||
* {@class CircularReferenceException} will be thrown.
|
||||
*
|
||||
* @final since Symfony 4.2
|
||||
*
|
||||
* @param object $object
|
||||
* @param string|null $format
|
||||
* @param array $context
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @throws CircularReferenceException
|
||||
*/
|
||||
protected function handleCircularReference($object/*, string $format = null, array $context = []*/)
|
||||
{
|
||||
if (\func_num_args() < 2 && __CLASS__ !== static::class && __CLASS__ !== (new \ReflectionMethod($this, __FUNCTION__))->getDeclaringClass()->getName() && !$this instanceof \PHPUnit\Framework\MockObject\MockObject && !$this instanceof \Prophecy\Prophecy\ProphecySubjectInterface && !$this instanceof \Mockery\MockInterface) {
|
||||
@trigger_error(sprintf('The "%s()" method will have two new "string $format = null" and "array $context = []" arguments in version 5.0, not defining it is deprecated since Symfony 4.2.', __METHOD__), \E_USER_DEPRECATED);
|
||||
}
|
||||
$format = \func_num_args() > 1 ? func_get_arg(1) : null;
|
||||
$context = \func_num_args() > 2 ? func_get_arg(2) : [];
|
||||
|
||||
$circularReferenceHandler = $context[self::CIRCULAR_REFERENCE_HANDLER] ?? $this->defaultContext[self::CIRCULAR_REFERENCE_HANDLER] ?? $this->circularReferenceHandler;
|
||||
if ($circularReferenceHandler) {
|
||||
return $circularReferenceHandler($object, $format, $context);
|
||||
}
|
||||
|
||||
throw new CircularReferenceException(sprintf('A circular reference has been detected when serializing the object of class "%s" (configured limit: %d).', \get_class($object), $context[self::CIRCULAR_REFERENCE_LIMIT] ?? $this->defaultContext[self::CIRCULAR_REFERENCE_LIMIT] ?? $this->circularReferenceLimit));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets attributes to normalize using groups.
|
||||
*
|
||||
* @param string|object $classOrObject
|
||||
* @param bool $attributesAsString If false, return an array of {@link AttributeMetadataInterface}
|
||||
*
|
||||
* @throws LogicException if the 'allow_extra_attributes' context variable is false and no class metadata factory is provided
|
||||
*
|
||||
* @return string[]|AttributeMetadataInterface[]|bool
|
||||
*/
|
||||
protected function getAllowedAttributes($classOrObject, array $context, $attributesAsString = false)
|
||||
{
|
||||
$allowExtraAttributes = $context[self::ALLOW_EXTRA_ATTRIBUTES] ?? $this->defaultContext[self::ALLOW_EXTRA_ATTRIBUTES];
|
||||
if (!$this->classMetadataFactory) {
|
||||
if (!$allowExtraAttributes) {
|
||||
throw new LogicException(sprintf('A class metadata factory must be provided in the constructor when setting "%s" to false.', self::ALLOW_EXTRA_ATTRIBUTES));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$tmpGroups = $context[self::GROUPS] ?? $this->defaultContext[self::GROUPS] ?? null;
|
||||
$groups = (\is_array($tmpGroups) || is_scalar($tmpGroups)) ? (array) $tmpGroups : false;
|
||||
if (false === $groups && $allowExtraAttributes) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$allowedAttributes = [];
|
||||
foreach ($this->classMetadataFactory->getMetadataFor($classOrObject)->getAttributesMetadata() as $attributeMetadata) {
|
||||
$name = $attributeMetadata->getName();
|
||||
|
||||
if (
|
||||
(false === $groups || array_intersect($attributeMetadata->getGroups(), $groups)) &&
|
||||
$this->isAllowedAttribute($classOrObject, $name, null, $context)
|
||||
) {
|
||||
$allowedAttributes[] = $attributesAsString ? $name : $attributeMetadata;
|
||||
}
|
||||
}
|
||||
|
||||
return $allowedAttributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this attribute allowed?
|
||||
*
|
||||
* @param object|string $classOrObject
|
||||
* @param string $attribute
|
||||
* @param string|null $format
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function isAllowedAttribute($classOrObject, $attribute, $format = null, array $context = [])
|
||||
{
|
||||
$ignoredAttributes = $context[self::IGNORED_ATTRIBUTES] ?? $this->defaultContext[self::IGNORED_ATTRIBUTES] ?? $this->ignoredAttributes;
|
||||
if (\in_array($attribute, $ignoredAttributes)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$attributes = $context[self::ATTRIBUTES] ?? $this->defaultContext[self::ATTRIBUTES] ?? null;
|
||||
if (isset($attributes[$attribute])) {
|
||||
// Nested attributes
|
||||
return true;
|
||||
}
|
||||
|
||||
if (\is_array($attributes)) {
|
||||
return \in_array($attribute, $attributes, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes the given data to an array. It's particularly useful during
|
||||
* the denormalization process.
|
||||
*
|
||||
* @param object|array $data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function prepareForDenormalization($data)
|
||||
{
|
||||
return (array) $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the method to use to construct an object. This method must be either
|
||||
* the object constructor or static.
|
||||
*
|
||||
* @param string $class
|
||||
* @param array|bool $allowedAttributes
|
||||
*
|
||||
* @return \ReflectionMethod|null
|
||||
*/
|
||||
protected function getConstructor(array &$data, $class, array &$context, \ReflectionClass $reflectionClass, $allowedAttributes)
|
||||
{
|
||||
return $reflectionClass->getConstructor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates an object using constructor parameters when needed.
|
||||
*
|
||||
* This method also allows to denormalize data into an existing object if
|
||||
* it is present in the context with the object_to_populate. This object
|
||||
* is removed from the context before being returned to avoid side effects
|
||||
* when recursively normalizing an object graph.
|
||||
*
|
||||
* @param string $class
|
||||
* @param array|bool $allowedAttributes
|
||||
*
|
||||
* @return object
|
||||
*
|
||||
* @throws RuntimeException
|
||||
* @throws MissingConstructorArgumentsException
|
||||
*/
|
||||
protected function instantiateObject(array &$data, $class, array &$context, \ReflectionClass $reflectionClass, $allowedAttributes, string $format = null)
|
||||
{
|
||||
if (null !== $object = $this->extractObjectToPopulate($class, $context, self::OBJECT_TO_POPULATE)) {
|
||||
unset($context[self::OBJECT_TO_POPULATE]);
|
||||
|
||||
return $object;
|
||||
}
|
||||
// clean up even if no match
|
||||
unset($context[static::OBJECT_TO_POPULATE]);
|
||||
|
||||
$constructor = $this->getConstructor($data, $class, $context, $reflectionClass, $allowedAttributes);
|
||||
if ($constructor) {
|
||||
if (true !== $constructor->isPublic()) {
|
||||
return $reflectionClass->newInstanceWithoutConstructor();
|
||||
}
|
||||
|
||||
$constructorParameters = $constructor->getParameters();
|
||||
|
||||
$params = [];
|
||||
foreach ($constructorParameters as $constructorParameter) {
|
||||
$paramName = $constructorParameter->name;
|
||||
$key = $this->nameConverter ? $this->nameConverter->normalize($paramName, $class, $format, $context) : $paramName;
|
||||
|
||||
$allowed = false === $allowedAttributes || \in_array($paramName, $allowedAttributes);
|
||||
$ignored = !$this->isAllowedAttribute($class, $paramName, $format, $context);
|
||||
if ($constructorParameter->isVariadic()) {
|
||||
if ($allowed && !$ignored && (isset($data[$key]) || \array_key_exists($key, $data))) {
|
||||
if (!\is_array($data[$paramName])) {
|
||||
throw new RuntimeException(sprintf('Cannot create an instance of "%s" from serialized data because the variadic parameter "%s" can only accept an array.', $class, $constructorParameter->name));
|
||||
}
|
||||
|
||||
$variadicParameters = [];
|
||||
foreach ($data[$paramName] as $parameterData) {
|
||||
$variadicParameters[] = $this->denormalizeParameter($reflectionClass, $constructorParameter, $paramName, $parameterData, $context, $format);
|
||||
}
|
||||
|
||||
$params = array_merge($params, $variadicParameters);
|
||||
unset($data[$key]);
|
||||
}
|
||||
} elseif ($allowed && !$ignored && (isset($data[$key]) || \array_key_exists($key, $data))) {
|
||||
$parameterData = $data[$key];
|
||||
if (null === $parameterData && $constructorParameter->allowsNull()) {
|
||||
$params[] = null;
|
||||
// Don't run set for a parameter passed to the constructor
|
||||
unset($data[$key]);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Don't run set for a parameter passed to the constructor
|
||||
$params[] = $this->denormalizeParameter($reflectionClass, $constructorParameter, $paramName, $parameterData, $context, $format);
|
||||
unset($data[$key]);
|
||||
} elseif (\array_key_exists($key, $context[static::DEFAULT_CONSTRUCTOR_ARGUMENTS][$class] ?? [])) {
|
||||
$params[] = $context[static::DEFAULT_CONSTRUCTOR_ARGUMENTS][$class][$key];
|
||||
} elseif (\array_key_exists($key, $this->defaultContext[self::DEFAULT_CONSTRUCTOR_ARGUMENTS][$class] ?? [])) {
|
||||
$params[] = $this->defaultContext[self::DEFAULT_CONSTRUCTOR_ARGUMENTS][$class][$key];
|
||||
} elseif ($constructorParameter->isDefaultValueAvailable()) {
|
||||
$params[] = $constructorParameter->getDefaultValue();
|
||||
} elseif ($constructorParameter->hasType() && $constructorParameter->getType()->allowsNull()) {
|
||||
$params[] = null;
|
||||
} else {
|
||||
throw new MissingConstructorArgumentsException(sprintf('Cannot create an instance of "%s" from serialized data because its constructor requires parameter "%s" to be present.', $class, $constructorParameter->name));
|
||||
}
|
||||
}
|
||||
|
||||
if ($constructor->isConstructor()) {
|
||||
return $reflectionClass->newInstanceArgs($params);
|
||||
} else {
|
||||
return $constructor->invokeArgs(null, $params);
|
||||
}
|
||||
}
|
||||
|
||||
return new $class();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected function denormalizeParameter(\ReflectionClass $class, \ReflectionParameter $parameter, $parameterName, $parameterData, array $context, $format = null)
|
||||
{
|
||||
try {
|
||||
if (($parameterType = $parameter->getType()) instanceof \ReflectionNamedType && !$parameterType->isBuiltin()) {
|
||||
$parameterClass = $parameterType->getName();
|
||||
new \ReflectionClass($parameterClass); // throws a \ReflectionException if the class doesn't exist
|
||||
|
||||
if (!$this->serializer instanceof DenormalizerInterface) {
|
||||
throw new LogicException(sprintf('Cannot create an instance of "%s" from serialized data because the serializer inject in "%s" is not a denormalizer.', $parameterClass, static::class));
|
||||
}
|
||||
|
||||
return $this->serializer->denormalize($parameterData, $parameterClass, $format, $this->createChildContext($context, $parameterName, $format));
|
||||
}
|
||||
} catch (\ReflectionException $e) {
|
||||
throw new RuntimeException(sprintf('Could not determine the class of the parameter "%s".', $parameterName), 0, $e);
|
||||
} catch (MissingConstructorArgumentsException $e) {
|
||||
if (!$parameter->getType()->allowsNull()) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return $parameterData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $attribute Attribute name
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
protected function createChildContext(array $parentContext, $attribute/*, ?string $format */): array
|
||||
{
|
||||
if (\func_num_args() < 3) {
|
||||
@trigger_error(sprintf('Method "%s::%s()" will have a third "?string $format" argument in version 5.0; not defining it is deprecated since Symfony 4.3.', static::class, __FUNCTION__), \E_USER_DEPRECATED);
|
||||
}
|
||||
if (isset($parentContext[self::ATTRIBUTES][$attribute])) {
|
||||
$parentContext[self::ATTRIBUTES] = $parentContext[self::ATTRIBUTES][$attribute];
|
||||
} else {
|
||||
unset($parentContext[self::ATTRIBUTES]);
|
||||
}
|
||||
|
||||
return $parentContext;
|
||||
}
|
||||
}
|
@@ -0,0 +1,640 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Normalizer;
|
||||
|
||||
use Symfony\Component\PropertyAccess\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException;
|
||||
use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
|
||||
use Symfony\Component\PropertyInfo\Type;
|
||||
use Symfony\Component\Serializer\Encoder\JsonEncoder;
|
||||
use Symfony\Component\Serializer\Encoder\XmlEncoder;
|
||||
use Symfony\Component\Serializer\Exception\ExtraAttributesException;
|
||||
use Symfony\Component\Serializer\Exception\LogicException;
|
||||
use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
|
||||
use Symfony\Component\Serializer\Exception\RuntimeException;
|
||||
use Symfony\Component\Serializer\Mapping\AttributeMetadataInterface;
|
||||
use Symfony\Component\Serializer\Mapping\ClassDiscriminatorFromClassMetadata;
|
||||
use Symfony\Component\Serializer\Mapping\ClassDiscriminatorResolverInterface;
|
||||
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
|
||||
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
|
||||
|
||||
/**
|
||||
* Base class for a normalizer dealing with objects.
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
abstract class AbstractObjectNormalizer extends AbstractNormalizer
|
||||
{
|
||||
/**
|
||||
* Set to true to respect the max depth metadata on fields.
|
||||
*/
|
||||
public const ENABLE_MAX_DEPTH = 'enable_max_depth';
|
||||
|
||||
/**
|
||||
* How to track the current depth in the context.
|
||||
*/
|
||||
public const DEPTH_KEY_PATTERN = 'depth_%s::%s';
|
||||
|
||||
/**
|
||||
* While denormalizing, we can verify that types match.
|
||||
*
|
||||
* You can disable this by setting this flag to true.
|
||||
*/
|
||||
public const DISABLE_TYPE_ENFORCEMENT = 'disable_type_enforcement';
|
||||
|
||||
/**
|
||||
* Flag to control whether fields with the value `null` should be output
|
||||
* when normalizing or omitted.
|
||||
*/
|
||||
public const SKIP_NULL_VALUES = 'skip_null_values';
|
||||
|
||||
/**
|
||||
* Callback to allow to set a value for an attribute when the max depth has
|
||||
* been reached.
|
||||
*
|
||||
* If no callback is given, the attribute is skipped. If a callable is
|
||||
* given, its return value is used (even if null).
|
||||
*
|
||||
* The arguments are:
|
||||
*
|
||||
* - mixed $attributeValue value of this field
|
||||
* - object $object the whole object being normalized
|
||||
* - string $attributeName name of the attribute being normalized
|
||||
* - string $format the requested format
|
||||
* - array $context the serialization context
|
||||
*/
|
||||
public const MAX_DEPTH_HANDLER = 'max_depth_handler';
|
||||
|
||||
/**
|
||||
* Specify which context key are not relevant to determine which attributes
|
||||
* of an object to (de)normalize.
|
||||
*/
|
||||
public const EXCLUDE_FROM_CACHE_KEY = 'exclude_from_cache_key';
|
||||
|
||||
/**
|
||||
* Flag to tell the denormalizer to also populate existing objects on
|
||||
* attributes of the main object.
|
||||
*
|
||||
* Setting this to true is only useful if you also specify the root object
|
||||
* in OBJECT_TO_POPULATE.
|
||||
*/
|
||||
public const DEEP_OBJECT_TO_POPULATE = 'deep_object_to_populate';
|
||||
|
||||
public const PRESERVE_EMPTY_OBJECTS = 'preserve_empty_objects';
|
||||
|
||||
private $propertyTypeExtractor;
|
||||
private $typesCache = [];
|
||||
private $attributesCache = [];
|
||||
|
||||
/**
|
||||
* @deprecated since Symfony 4.2
|
||||
*
|
||||
* @var callable|null
|
||||
*/
|
||||
private $maxDepthHandler;
|
||||
private $objectClassResolver;
|
||||
|
||||
/**
|
||||
* @var ClassDiscriminatorResolverInterface|null
|
||||
*/
|
||||
protected $classDiscriminatorResolver;
|
||||
|
||||
public function __construct(ClassMetadataFactoryInterface $classMetadataFactory = null, NameConverterInterface $nameConverter = null, PropertyTypeExtractorInterface $propertyTypeExtractor = null, ClassDiscriminatorResolverInterface $classDiscriminatorResolver = null, callable $objectClassResolver = null, array $defaultContext = [])
|
||||
{
|
||||
parent::__construct($classMetadataFactory, $nameConverter, $defaultContext);
|
||||
|
||||
if (isset($this->defaultContext[self::MAX_DEPTH_HANDLER]) && !\is_callable($this->defaultContext[self::MAX_DEPTH_HANDLER])) {
|
||||
throw new InvalidArgumentException(sprintf('The "%s" given in the default context is not callable.', self::MAX_DEPTH_HANDLER));
|
||||
}
|
||||
|
||||
$this->defaultContext[self::EXCLUDE_FROM_CACHE_KEY] = array_merge($this->defaultContext[self::EXCLUDE_FROM_CACHE_KEY] ?? [], [self::CIRCULAR_REFERENCE_LIMIT_COUNTERS]);
|
||||
|
||||
$this->propertyTypeExtractor = $propertyTypeExtractor;
|
||||
|
||||
if (null === $classDiscriminatorResolver && null !== $classMetadataFactory) {
|
||||
$classDiscriminatorResolver = new ClassDiscriminatorFromClassMetadata($classMetadataFactory);
|
||||
}
|
||||
$this->classDiscriminatorResolver = $classDiscriminatorResolver;
|
||||
$this->objectClassResolver = $objectClassResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supportsNormalization($data, $format = null)
|
||||
{
|
||||
return \is_object($data) && !$data instanceof \Traversable;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function normalize($object, $format = null, array $context = [])
|
||||
{
|
||||
if (!isset($context['cache_key'])) {
|
||||
$context['cache_key'] = $this->getCacheKey($format, $context);
|
||||
}
|
||||
|
||||
if (isset($context[self::CALLBACKS])) {
|
||||
if (!\is_array($context[self::CALLBACKS])) {
|
||||
throw new InvalidArgumentException(sprintf('The "%s" context option must be an array of callables.', self::CALLBACKS));
|
||||
}
|
||||
|
||||
foreach ($context[self::CALLBACKS] as $attribute => $callback) {
|
||||
if (!\is_callable($callback)) {
|
||||
throw new InvalidArgumentException(sprintf('Invalid callback found for attribute "%s" in the "%s" context option.', $attribute, self::CALLBACKS));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->isCircularReference($object, $context)) {
|
||||
return $this->handleCircularReference($object, $format, $context);
|
||||
}
|
||||
|
||||
$data = [];
|
||||
$stack = [];
|
||||
$attributes = $this->getAttributes($object, $format, $context);
|
||||
$class = $this->objectClassResolver ? ($this->objectClassResolver)($object) : \get_class($object);
|
||||
$attributesMetadata = $this->classMetadataFactory ? $this->classMetadataFactory->getMetadataFor($class)->getAttributesMetadata() : null;
|
||||
if (isset($context[self::MAX_DEPTH_HANDLER])) {
|
||||
$maxDepthHandler = $context[self::MAX_DEPTH_HANDLER];
|
||||
if (!\is_callable($maxDepthHandler)) {
|
||||
throw new InvalidArgumentException(sprintf('The "%s" given in the context is not callable.', self::MAX_DEPTH_HANDLER));
|
||||
}
|
||||
} else {
|
||||
// already validated in constructor resp by type declaration of setMaxDepthHandler
|
||||
$maxDepthHandler = $this->defaultContext[self::MAX_DEPTH_HANDLER] ?? $this->maxDepthHandler;
|
||||
}
|
||||
|
||||
foreach ($attributes as $attribute) {
|
||||
$maxDepthReached = false;
|
||||
if (null !== $attributesMetadata && ($maxDepthReached = $this->isMaxDepthReached($attributesMetadata, $class, $attribute, $context)) && !$maxDepthHandler) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$attributeValue = $this->getAttributeValue($object, $attribute, $format, $context);
|
||||
if ($maxDepthReached) {
|
||||
$attributeValue = $maxDepthHandler($attributeValue, $object, $attribute, $format, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @var callable|null
|
||||
*/
|
||||
$callback = $context[self::CALLBACKS][$attribute] ?? $this->defaultContext[self::CALLBACKS][$attribute] ?? $this->callbacks[$attribute] ?? null;
|
||||
if ($callback) {
|
||||
$attributeValue = $callback($attributeValue, $object, $attribute, $format, $context);
|
||||
}
|
||||
|
||||
if (null !== $attributeValue && !is_scalar($attributeValue)) {
|
||||
$stack[$attribute] = $attributeValue;
|
||||
}
|
||||
|
||||
$data = $this->updateData($data, $attribute, $attributeValue, $class, $format, $context);
|
||||
}
|
||||
|
||||
foreach ($stack as $attribute => $attributeValue) {
|
||||
if (!$this->serializer instanceof NormalizerInterface) {
|
||||
throw new LogicException(sprintf('Cannot normalize attribute "%s" because the injected serializer is not a normalizer.', $attribute));
|
||||
}
|
||||
|
||||
$data = $this->updateData($data, $attribute, $this->serializer->normalize($attributeValue, $format, $this->createChildContext($context, $attribute, $format)), $class, $format, $context);
|
||||
}
|
||||
|
||||
if (isset($context[self::PRESERVE_EMPTY_OBJECTS]) && !\count($data)) {
|
||||
return new \ArrayObject();
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function instantiateObject(array &$data, $class, array &$context, \ReflectionClass $reflectionClass, $allowedAttributes, string $format = null)
|
||||
{
|
||||
if ($this->classDiscriminatorResolver && $mapping = $this->classDiscriminatorResolver->getMappingForClass($class)) {
|
||||
if (!isset($data[$mapping->getTypeProperty()])) {
|
||||
throw new RuntimeException(sprintf('Type property "%s" not found for the abstract object "%s".', $mapping->getTypeProperty(), $class));
|
||||
}
|
||||
|
||||
$type = $data[$mapping->getTypeProperty()];
|
||||
if (null === ($mappedClass = $mapping->getClassForType($type))) {
|
||||
throw new RuntimeException(sprintf('The type "%s" has no mapped class for the abstract object "%s".', $type, $class));
|
||||
}
|
||||
|
||||
if ($mappedClass !== $class) {
|
||||
return $this->instantiateObject($data, $mappedClass, $context, new \ReflectionClass($mappedClass), $allowedAttributes, $format);
|
||||
}
|
||||
}
|
||||
|
||||
return parent::instantiateObject($data, $class, $context, $reflectionClass, $allowedAttributes, $format);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets and caches attributes for the given object, format and context.
|
||||
*
|
||||
* @param object $object
|
||||
* @param string|null $format
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
protected function getAttributes($object, $format, array $context)
|
||||
{
|
||||
$class = $this->objectClassResolver ? ($this->objectClassResolver)($object) : \get_class($object);
|
||||
$key = $class.'-'.$context['cache_key'];
|
||||
|
||||
if (isset($this->attributesCache[$key])) {
|
||||
return $this->attributesCache[$key];
|
||||
}
|
||||
|
||||
$allowedAttributes = $this->getAllowedAttributes($object, $context, true);
|
||||
|
||||
if (false !== $allowedAttributes) {
|
||||
if ($context['cache_key']) {
|
||||
$this->attributesCache[$key] = $allowedAttributes;
|
||||
}
|
||||
|
||||
return $allowedAttributes;
|
||||
}
|
||||
|
||||
$attributes = $this->extractAttributes($object, $format, $context);
|
||||
|
||||
if ($this->classDiscriminatorResolver && $mapping = $this->classDiscriminatorResolver->getMappingForMappedObject($object)) {
|
||||
array_unshift($attributes, $mapping->getTypeProperty());
|
||||
}
|
||||
|
||||
if ($context['cache_key']) {
|
||||
$this->attributesCache[$key] = $attributes;
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts attributes to normalize from the class of the given object, format and context.
|
||||
*
|
||||
* @param object $object
|
||||
* @param string|null $format
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
abstract protected function extractAttributes($object, $format = null, array $context = []);
|
||||
|
||||
/**
|
||||
* Gets the attribute value.
|
||||
*
|
||||
* @param object $object
|
||||
* @param string $attribute
|
||||
* @param string|null $format
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
abstract protected function getAttributeValue($object, $attribute, $format = null, array $context = []);
|
||||
|
||||
/**
|
||||
* Sets a handler function that will be called when the max depth is reached.
|
||||
*
|
||||
* @deprecated since Symfony 4.2
|
||||
*/
|
||||
public function setMaxDepthHandler(?callable $handler): void
|
||||
{
|
||||
@trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2, use the "max_depth_handler" key of the context instead.', __METHOD__), \E_USER_DEPRECATED);
|
||||
|
||||
$this->maxDepthHandler = $handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supportsDenormalization($data, $type, $format = null)
|
||||
{
|
||||
return class_exists($type) || (interface_exists($type, false) && $this->classDiscriminatorResolver && null !== $this->classDiscriminatorResolver->getMappingForClass($type));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function denormalize($data, $type, $format = null, array $context = [])
|
||||
{
|
||||
if (!isset($context['cache_key'])) {
|
||||
$context['cache_key'] = $this->getCacheKey($format, $context);
|
||||
}
|
||||
|
||||
$allowedAttributes = $this->getAllowedAttributes($type, $context, true);
|
||||
$normalizedData = $this->prepareForDenormalization($data);
|
||||
$extraAttributes = [];
|
||||
|
||||
$reflectionClass = new \ReflectionClass($type);
|
||||
$object = $this->instantiateObject($normalizedData, $type, $context, $reflectionClass, $allowedAttributes, $format);
|
||||
$resolvedClass = $this->objectClassResolver ? ($this->objectClassResolver)($object) : \get_class($object);
|
||||
|
||||
foreach ($normalizedData as $attribute => $value) {
|
||||
if ($this->nameConverter) {
|
||||
$attribute = $this->nameConverter->denormalize($attribute, $resolvedClass, $format, $context);
|
||||
}
|
||||
|
||||
if ((false !== $allowedAttributes && !\in_array($attribute, $allowedAttributes)) || !$this->isAllowedAttribute($resolvedClass, $attribute, $format, $context)) {
|
||||
if (!($context[self::ALLOW_EXTRA_ATTRIBUTES] ?? $this->defaultContext[self::ALLOW_EXTRA_ATTRIBUTES])) {
|
||||
$extraAttributes[] = $attribute;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($context[self::DEEP_OBJECT_TO_POPULATE] ?? $this->defaultContext[self::DEEP_OBJECT_TO_POPULATE] ?? false) {
|
||||
try {
|
||||
$context[self::OBJECT_TO_POPULATE] = $this->getAttributeValue($object, $attribute, $format, $context);
|
||||
} catch (NoSuchPropertyException $e) {
|
||||
}
|
||||
}
|
||||
|
||||
$value = $this->validateAndDenormalize($resolvedClass, $attribute, $value, $format, $context);
|
||||
try {
|
||||
$this->setAttributeValue($object, $attribute, $value, $format, $context);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
throw new NotNormalizableValueException(sprintf('Failed to denormalize attribute "%s" value for class "%s": '.$e->getMessage(), $attribute, $type), $e->getCode(), $e);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($extraAttributes)) {
|
||||
throw new ExtraAttributesException($extraAttributes);
|
||||
}
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets attribute value.
|
||||
*
|
||||
* @param object $object
|
||||
* @param string $attribute
|
||||
* @param mixed $value
|
||||
* @param string|null $format
|
||||
*/
|
||||
abstract protected function setAttributeValue($object, $attribute, $value, $format = null, array $context = []);
|
||||
|
||||
/**
|
||||
* Validates the submitted data and denormalizes it.
|
||||
*
|
||||
* @param mixed $data
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @throws NotNormalizableValueException
|
||||
* @throws LogicException
|
||||
*/
|
||||
private function validateAndDenormalize(string $currentClass, string $attribute, $data, ?string $format, array $context)
|
||||
{
|
||||
if (null === $types = $this->getTypes($currentClass, $attribute)) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
$expectedTypes = [];
|
||||
foreach ($types as $type) {
|
||||
if (null === $data && $type->isNullable()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$collectionValueType = $type->isCollection() ? $type->getCollectionValueType() : null;
|
||||
|
||||
// Fix a collection that contains the only one element
|
||||
// This is special to xml format only
|
||||
if ('xml' === $format && null !== $collectionValueType && (!\is_array($data) || !\is_int(key($data)))) {
|
||||
$data = [$data];
|
||||
}
|
||||
|
||||
if (XmlEncoder::FORMAT === $format && '' === $data && Type::BUILTIN_TYPE_ARRAY === $type->getBuiltinType()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (null !== $collectionValueType && Type::BUILTIN_TYPE_OBJECT === $collectionValueType->getBuiltinType()) {
|
||||
$builtinType = Type::BUILTIN_TYPE_OBJECT;
|
||||
$class = $collectionValueType->getClassName().'[]';
|
||||
|
||||
if (null !== $collectionKeyType = $type->getCollectionKeyType()) {
|
||||
$context['key_type'] = $collectionKeyType;
|
||||
}
|
||||
} elseif ($type->isCollection() && null !== ($collectionValueType = $type->getCollectionValueType()) && Type::BUILTIN_TYPE_ARRAY === $collectionValueType->getBuiltinType()) {
|
||||
// get inner type for any nested array
|
||||
$innerType = $collectionValueType;
|
||||
|
||||
// note that it will break for any other builtinType
|
||||
$dimensions = '[]';
|
||||
while (null !== $innerType->getCollectionValueType() && Type::BUILTIN_TYPE_ARRAY === $innerType->getBuiltinType()) {
|
||||
$dimensions .= '[]';
|
||||
$innerType = $innerType->getCollectionValueType();
|
||||
}
|
||||
|
||||
if (null !== $innerType->getClassName()) {
|
||||
// the builtinType is the inner one and the class is the class followed by []...[]
|
||||
$builtinType = $innerType->getBuiltinType();
|
||||
$class = $innerType->getClassName().$dimensions;
|
||||
} else {
|
||||
// default fallback (keep it as array)
|
||||
$builtinType = $type->getBuiltinType();
|
||||
$class = $type->getClassName();
|
||||
}
|
||||
} else {
|
||||
$builtinType = $type->getBuiltinType();
|
||||
$class = $type->getClassName();
|
||||
}
|
||||
|
||||
$expectedTypes[Type::BUILTIN_TYPE_OBJECT === $builtinType && $class ? $class : $builtinType] = true;
|
||||
|
||||
if (Type::BUILTIN_TYPE_OBJECT === $builtinType) {
|
||||
if (!$this->serializer instanceof DenormalizerInterface) {
|
||||
throw new LogicException(sprintf('Cannot denormalize attribute "%s" for class "%s" because injected serializer is not a denormalizer.', $attribute, $class));
|
||||
}
|
||||
|
||||
$childContext = $this->createChildContext($context, $attribute, $format);
|
||||
if ($this->serializer->supportsDenormalization($data, $class, $format, $childContext)) {
|
||||
return $this->serializer->denormalize($data, $class, $format, $childContext);
|
||||
}
|
||||
}
|
||||
|
||||
// JSON only has a Number type corresponding to both int and float PHP types.
|
||||
// PHP's json_encode, JavaScript's JSON.stringify, Go's json.Marshal as well as most other JSON encoders convert
|
||||
// floating-point numbers like 12.0 to 12 (the decimal part is dropped when possible).
|
||||
// PHP's json_decode automatically converts Numbers without a decimal part to integers.
|
||||
// To circumvent this behavior, integers are converted to floats when denormalizing JSON based formats and when
|
||||
// a float is expected.
|
||||
if (Type::BUILTIN_TYPE_FLOAT === $builtinType && \is_int($data) && str_contains($format, JsonEncoder::FORMAT)) {
|
||||
return (float) $data;
|
||||
}
|
||||
|
||||
if (('is_'.$builtinType)($data)) {
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
if ($context[self::DISABLE_TYPE_ENFORCEMENT] ?? $this->defaultContext[self::DISABLE_TYPE_ENFORCEMENT] ?? false) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
throw new NotNormalizableValueException(sprintf('The type of the "%s" attribute for class "%s" must be one of "%s" ("%s" given).', $attribute, $currentClass, implode('", "', array_keys($expectedTypes)), \gettype($data)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected function denormalizeParameter(\ReflectionClass $class, \ReflectionParameter $parameter, $parameterName, $parameterData, array $context, $format = null)
|
||||
{
|
||||
if ($parameter->isVariadic() || null === $this->propertyTypeExtractor || null === $this->propertyTypeExtractor->getTypes($class->getName(), $parameterName)) {
|
||||
return parent::denormalizeParameter($class, $parameter, $parameterName, $parameterData, $context, $format);
|
||||
}
|
||||
|
||||
return $this->validateAndDenormalize($class->getName(), $parameterName, $parameterData, $format, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Type[]|null
|
||||
*/
|
||||
private function getTypes(string $currentClass, string $attribute): ?array
|
||||
{
|
||||
if (null === $this->propertyTypeExtractor) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$key = $currentClass.'::'.$attribute;
|
||||
if (isset($this->typesCache[$key])) {
|
||||
return false === $this->typesCache[$key] ? null : $this->typesCache[$key];
|
||||
}
|
||||
|
||||
if (null !== $types = $this->propertyTypeExtractor->getTypes($currentClass, $attribute)) {
|
||||
return $this->typesCache[$key] = $types;
|
||||
}
|
||||
|
||||
if (null !== $this->classDiscriminatorResolver && null !== $discriminatorMapping = $this->classDiscriminatorResolver->getMappingForClass($currentClass)) {
|
||||
if ($discriminatorMapping->getTypeProperty() === $attribute) {
|
||||
return $this->typesCache[$key] = [
|
||||
new Type(Type::BUILTIN_TYPE_STRING),
|
||||
];
|
||||
}
|
||||
|
||||
foreach ($discriminatorMapping->getTypesMapping() as $mappedClass) {
|
||||
if (null !== $types = $this->propertyTypeExtractor->getTypes($mappedClass, $attribute)) {
|
||||
return $this->typesCache[$key] = $types;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->typesCache[$key] = false;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an attribute and apply the name converter if necessary.
|
||||
*
|
||||
* @param mixed $attributeValue
|
||||
*/
|
||||
private function updateData(array $data, string $attribute, $attributeValue, string $class, ?string $format, array $context): array
|
||||
{
|
||||
if (null === $attributeValue && ($context[self::SKIP_NULL_VALUES] ?? $this->defaultContext[self::SKIP_NULL_VALUES] ?? false)) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
if ($this->nameConverter) {
|
||||
$attribute = $this->nameConverter->normalize($attribute, $class, $format, $context);
|
||||
}
|
||||
|
||||
$data[$attribute] = $attributeValue;
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the max depth reached for the given attribute?
|
||||
*
|
||||
* @param AttributeMetadataInterface[] $attributesMetadata
|
||||
*/
|
||||
private function isMaxDepthReached(array $attributesMetadata, string $class, string $attribute, array &$context): bool
|
||||
{
|
||||
$enableMaxDepth = $context[self::ENABLE_MAX_DEPTH] ?? $this->defaultContext[self::ENABLE_MAX_DEPTH] ?? false;
|
||||
if (
|
||||
!$enableMaxDepth ||
|
||||
!isset($attributesMetadata[$attribute]) ||
|
||||
null === $maxDepth = $attributesMetadata[$attribute]->getMaxDepth()
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$key = sprintf(self::DEPTH_KEY_PATTERN, $class, $attribute);
|
||||
if (!isset($context[$key])) {
|
||||
$context[$key] = 1;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($context[$key] === $maxDepth) {
|
||||
return true;
|
||||
}
|
||||
|
||||
++$context[$key];
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwritten to update the cache key for the child.
|
||||
*
|
||||
* We must not mix up the attribute cache between parent and children.
|
||||
*
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @param string|null $format
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
protected function createChildContext(array $parentContext, $attribute/*, ?string $format */): array
|
||||
{
|
||||
if (\func_num_args() >= 3) {
|
||||
$format = func_get_arg(2);
|
||||
} else {
|
||||
@trigger_error(sprintf('Method "%s::%s()" will have a third "?string $format" argument in version 5.0; not defining it is deprecated since Symfony 4.3.', static::class, __FUNCTION__), \E_USER_DEPRECATED);
|
||||
$format = null;
|
||||
}
|
||||
|
||||
$context = parent::createChildContext($parentContext, $attribute, $format);
|
||||
$context['cache_key'] = $this->getCacheKey($format, $context);
|
||||
|
||||
return $context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the cache key for the attributes cache.
|
||||
*
|
||||
* The key must be different for every option in the context that could change which attributes should be handled.
|
||||
*
|
||||
* @return bool|string
|
||||
*/
|
||||
private function getCacheKey(?string $format, array $context)
|
||||
{
|
||||
foreach ($context[self::EXCLUDE_FROM_CACHE_KEY] ?? $this->defaultContext[self::EXCLUDE_FROM_CACHE_KEY] as $key) {
|
||||
unset($context[$key]);
|
||||
}
|
||||
unset($context[self::EXCLUDE_FROM_CACHE_KEY]);
|
||||
unset($context[self::OBJECT_TO_POPULATE]);
|
||||
unset($context['cache_key']); // avoid artificially different keys
|
||||
|
||||
try {
|
||||
return md5($format.serialize([
|
||||
'context' => $context,
|
||||
'ignored' => $this->ignoredAttributes,
|
||||
'camelized' => $this->camelizedAttributes,
|
||||
]));
|
||||
} catch (\Exception $exception) {
|
||||
// The context cannot be serialized, skip the cache
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
100
old.vendor/symfony/serializer/Normalizer/ArrayDenormalizer.php
Normal file
100
old.vendor/symfony/serializer/Normalizer/ArrayDenormalizer.php
Normal file
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Normalizer;
|
||||
|
||||
use Symfony\Component\Serializer\Exception\BadMethodCallException;
|
||||
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
|
||||
use Symfony\Component\Serializer\SerializerAwareInterface;
|
||||
use Symfony\Component\Serializer\SerializerInterface;
|
||||
|
||||
/**
|
||||
* Denormalizes arrays of objects.
|
||||
*
|
||||
* @author Alexander M. Turek <me@derrabus.de>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class ArrayDenormalizer implements ContextAwareDenormalizerInterface, SerializerAwareInterface, CacheableSupportsMethodInterface
|
||||
{
|
||||
/**
|
||||
* @var SerializerInterface|DenormalizerInterface
|
||||
*/
|
||||
private $serializer;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @throws NotNormalizableValueException
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function denormalize($data, $type, $format = null, array $context = [])
|
||||
{
|
||||
if (null === $this->serializer) {
|
||||
throw new BadMethodCallException('Please set a serializer before calling denormalize()!');
|
||||
}
|
||||
if (!\is_array($data)) {
|
||||
throw new InvalidArgumentException('Data expected to be an array, '.\gettype($data).' given.');
|
||||
}
|
||||
if (!str_ends_with($type, '[]')) {
|
||||
throw new InvalidArgumentException('Unsupported class: '.$type);
|
||||
}
|
||||
|
||||
$serializer = $this->serializer;
|
||||
$type = substr($type, 0, -2);
|
||||
|
||||
$builtinType = isset($context['key_type']) ? $context['key_type']->getBuiltinType() : null;
|
||||
foreach ($data as $key => $value) {
|
||||
if (null !== $builtinType && !('is_'.$builtinType)($key)) {
|
||||
throw new NotNormalizableValueException(sprintf('The type of the key "%s" must be "%s" ("%s" given).', $key, $builtinType, \gettype($key)));
|
||||
}
|
||||
|
||||
$data[$key] = $serializer->denormalize($value, $type, $format, $context);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supportsDenormalization($data, $type, $format = null, array $context = []): bool
|
||||
{
|
||||
if (null === $this->serializer) {
|
||||
throw new BadMethodCallException(sprintf('The serializer needs to be set to allow "%s()" to be used.', __METHOD__));
|
||||
}
|
||||
|
||||
return str_ends_with($type, '[]')
|
||||
&& $this->serializer->supportsDenormalization($data, substr($type, 0, -2), $format, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setSerializer(SerializerInterface $serializer)
|
||||
{
|
||||
if (!$serializer instanceof DenormalizerInterface) {
|
||||
throw new InvalidArgumentException('Expected a serializer that also implements DenormalizerInterface.');
|
||||
}
|
||||
|
||||
$this->serializer = $serializer;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasCacheableSupportsMethod(): bool
|
||||
{
|
||||
return $this->serializer instanceof CacheableSupportsMethodInterface && $this->serializer->hasCacheableSupportsMethod();
|
||||
}
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Normalizer;
|
||||
|
||||
/**
|
||||
* Marker interface for normalizers and denormalizers that use
|
||||
* only the type and the format in their supports*() methods.
|
||||
*
|
||||
* By implementing this interface, the return value of the
|
||||
* supports*() methods will be cached by type and format.
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
interface CacheableSupportsMethodInterface
|
||||
{
|
||||
public function hasCacheableSupportsMethod(): bool;
|
||||
}
|
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Normalizer;
|
||||
|
||||
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
|
||||
use Symfony\Component\Validator\ConstraintViolationListInterface;
|
||||
|
||||
/**
|
||||
* A normalizer that normalizes a ConstraintViolationListInterface instance.
|
||||
*
|
||||
* This Normalizer implements RFC7807 {@link https://tools.ietf.org/html/rfc7807}.
|
||||
*
|
||||
* @author Grégoire Pineau <lyrixx@lyrixx.info>
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
class ConstraintViolationListNormalizer implements NormalizerInterface, CacheableSupportsMethodInterface
|
||||
{
|
||||
public const INSTANCE = 'instance';
|
||||
public const STATUS = 'status';
|
||||
public const TITLE = 'title';
|
||||
public const TYPE = 'type';
|
||||
|
||||
private $defaultContext;
|
||||
private $nameConverter;
|
||||
|
||||
public function __construct(array $defaultContext = [], NameConverterInterface $nameConverter = null)
|
||||
{
|
||||
$this->defaultContext = $defaultContext;
|
||||
$this->nameConverter = $nameConverter;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function normalize($object, $format = null, array $context = [])
|
||||
{
|
||||
$violations = [];
|
||||
$messages = [];
|
||||
foreach ($object as $violation) {
|
||||
$propertyPath = $this->nameConverter ? $this->nameConverter->normalize($violation->getPropertyPath(), null, $format, $context) : $violation->getPropertyPath();
|
||||
|
||||
$violationEntry = [
|
||||
'propertyPath' => $propertyPath,
|
||||
'title' => $violation->getMessage(),
|
||||
'parameters' => $violation->getParameters(),
|
||||
];
|
||||
if (null !== $code = $violation->getCode()) {
|
||||
$violationEntry['type'] = sprintf('urn:uuid:%s', $code);
|
||||
}
|
||||
|
||||
$violations[] = $violationEntry;
|
||||
|
||||
$prefix = $propertyPath ? sprintf('%s: ', $propertyPath) : '';
|
||||
$messages[] = $prefix.$violation->getMessage();
|
||||
}
|
||||
|
||||
$result = [
|
||||
'type' => $context[self::TYPE] ?? $this->defaultContext[self::TYPE] ?? 'https://symfony.com/errors/validation',
|
||||
'title' => $context[self::TITLE] ?? $this->defaultContext[self::TITLE] ?? 'Validation Failed',
|
||||
];
|
||||
if (null !== $status = ($context[self::STATUS] ?? $this->defaultContext[self::STATUS] ?? null)) {
|
||||
$result['status'] = $status;
|
||||
}
|
||||
if ($messages) {
|
||||
$result['detail'] = implode("\n", $messages);
|
||||
}
|
||||
if (null !== $instance = ($context[self::INSTANCE] ?? $this->defaultContext[self::INSTANCE] ?? null)) {
|
||||
$result['instance'] = $instance;
|
||||
}
|
||||
|
||||
return $result + ['violations' => $violations];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supportsNormalization($data, $format = null)
|
||||
{
|
||||
return $data instanceof ConstraintViolationListInterface;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasCacheableSupportsMethod(): bool
|
||||
{
|
||||
return __CLASS__ === static::class;
|
||||
}
|
||||
}
|
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Normalizer;
|
||||
|
||||
/**
|
||||
* Adds the support of an extra $context parameter for the supportsDenormalization method.
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
interface ContextAwareDenormalizerInterface extends DenormalizerInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @param array $context options that denormalizers have access to
|
||||
*/
|
||||
public function supportsDenormalization($data, $type, $format = null, array $context = []);
|
||||
}
|
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Normalizer;
|
||||
|
||||
/**
|
||||
* Adds the support of an extra $context parameter for the supportsNormalization method.
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
interface ContextAwareNormalizerInterface extends NormalizerInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @param array $context options that normalizers have access to
|
||||
*/
|
||||
public function supportsNormalization($data, $format = null, array $context = []);
|
||||
}
|
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Normalizer;
|
||||
|
||||
use Symfony\Component\Serializer\SerializerAwareInterface;
|
||||
use Symfony\Component\Serializer\SerializerAwareTrait;
|
||||
|
||||
/**
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*/
|
||||
class CustomNormalizer implements NormalizerInterface, DenormalizerInterface, SerializerAwareInterface, CacheableSupportsMethodInterface
|
||||
{
|
||||
use ObjectToPopulateTrait;
|
||||
use SerializerAwareTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function normalize($object, $format = null, array $context = [])
|
||||
{
|
||||
return $object->normalize($this->serializer, $format, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function denormalize($data, $type, $format = null, array $context = [])
|
||||
{
|
||||
$object = $this->extractObjectToPopulate($type, $context) ?? new $type();
|
||||
$object->denormalize($this->serializer, $data, $format, $context);
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given class implements the NormalizableInterface.
|
||||
*
|
||||
* @param mixed $data Data to normalize
|
||||
* @param string $format The format being (de-)serialized from or into
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function supportsNormalization($data, $format = null)
|
||||
{
|
||||
return $data instanceof NormalizableInterface;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given class implements the DenormalizableInterface.
|
||||
*
|
||||
* @param mixed $data Data to denormalize from
|
||||
* @param string $type The class to which the data should be denormalized
|
||||
* @param string $format The format being deserialized from
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function supportsDenormalization($data, $type, $format = null)
|
||||
{
|
||||
return is_subclass_of($type, DenormalizableInterface::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasCacheableSupportsMethod(): bool
|
||||
{
|
||||
return __CLASS__ === static::class;
|
||||
}
|
||||
}
|
179
old.vendor/symfony/serializer/Normalizer/DataUriNormalizer.php
Normal file
179
old.vendor/symfony/serializer/Normalizer/DataUriNormalizer.php
Normal file
@@ -0,0 +1,179 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Normalizer;
|
||||
|
||||
use Symfony\Component\HttpFoundation\File\File;
|
||||
use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesser;
|
||||
use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesserInterface as DeprecatedMimeTypeGuesserInterface;
|
||||
use Symfony\Component\Mime\MimeTypeGuesserInterface;
|
||||
use Symfony\Component\Mime\MimeTypes;
|
||||
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
|
||||
|
||||
/**
|
||||
* Normalizes an {@see \SplFileInfo} object to a data URI.
|
||||
* Denormalizes a data URI to a {@see \SplFileObject} object.
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
class DataUriNormalizer implements NormalizerInterface, DenormalizerInterface, CacheableSupportsMethodInterface
|
||||
{
|
||||
private const SUPPORTED_TYPES = [
|
||||
\SplFileInfo::class => true,
|
||||
\SplFileObject::class => true,
|
||||
File::class => true,
|
||||
];
|
||||
|
||||
/**
|
||||
* @var MimeTypeGuesserInterface|null
|
||||
*/
|
||||
private $mimeTypeGuesser;
|
||||
|
||||
/**
|
||||
* @param MimeTypeGuesserInterface|null $mimeTypeGuesser
|
||||
*/
|
||||
public function __construct($mimeTypeGuesser = null)
|
||||
{
|
||||
if ($mimeTypeGuesser instanceof DeprecatedMimeTypeGuesserInterface) {
|
||||
@trigger_error(sprintf('Passing a %s to "%s()" is deprecated since Symfony 4.3, pass a "%s" instead.', DeprecatedMimeTypeGuesserInterface::class, __METHOD__, MimeTypeGuesserInterface::class), \E_USER_DEPRECATED);
|
||||
} elseif (null === $mimeTypeGuesser) {
|
||||
if (class_exists(MimeTypes::class)) {
|
||||
$mimeTypeGuesser = MimeTypes::getDefault();
|
||||
} elseif (class_exists(MimeTypeGuesser::class)) {
|
||||
@trigger_error(sprintf('Passing null to "%s()" to use a default MIME type guesser without Symfony Mime installed is deprecated since Symfony 4.3. Try running "composer require symfony/mime".', __METHOD__), \E_USER_DEPRECATED);
|
||||
$mimeTypeGuesser = MimeTypeGuesser::getInstance();
|
||||
}
|
||||
} elseif (!$mimeTypeGuesser instanceof MimeTypes) {
|
||||
throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be an instance of "%s" or null, "%s" given.', __METHOD__, MimeTypes::class, \is_object($mimeTypeGuesser) ? \get_class($mimeTypeGuesser) : \gettype($mimeTypeGuesser)));
|
||||
}
|
||||
|
||||
$this->mimeTypeGuesser = $mimeTypeGuesser;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function normalize($object, $format = null, array $context = [])
|
||||
{
|
||||
if (!$object instanceof \SplFileInfo) {
|
||||
throw new InvalidArgumentException('The object must be an instance of "\SplFileInfo".');
|
||||
}
|
||||
|
||||
$mimeType = $this->getMimeType($object);
|
||||
$splFileObject = $this->extractSplFileObject($object);
|
||||
|
||||
$data = '';
|
||||
|
||||
$splFileObject->rewind();
|
||||
while (!$splFileObject->eof()) {
|
||||
$data .= $splFileObject->fgets();
|
||||
}
|
||||
|
||||
if ('text' === explode('/', $mimeType, 2)[0]) {
|
||||
return sprintf('data:%s,%s', $mimeType, rawurlencode($data));
|
||||
}
|
||||
|
||||
return sprintf('data:%s;base64,%s', $mimeType, base64_encode($data));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supportsNormalization($data, $format = null)
|
||||
{
|
||||
return $data instanceof \SplFileInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* Regex adapted from Brian Grinstead code.
|
||||
*
|
||||
* @see https://gist.github.com/bgrins/6194623
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
* @throws NotNormalizableValueException
|
||||
*
|
||||
* @return \SplFileInfo
|
||||
*/
|
||||
public function denormalize($data, $type, $format = null, array $context = [])
|
||||
{
|
||||
if (null === $data || !preg_match('/^data:([a-z0-9][a-z0-9\!\#\$\&\-\^\_\+\.]{0,126}\/[a-z0-9][a-z0-9\!\#\$\&\-\^\_\+\.]{0,126}(;[a-z0-9\-]+\=[a-z0-9\-]+)?)?(;base64)?,[a-z0-9\!\$\&\\\'\,\(\)\*\+\,\;\=\-\.\_\~\:\@\/\?\%\s]*\s*$/i', $data)) {
|
||||
throw new NotNormalizableValueException('The provided "data:" URI is not valid.');
|
||||
}
|
||||
|
||||
try {
|
||||
switch ($type) {
|
||||
case File::class:
|
||||
return new File($data, false);
|
||||
|
||||
case 'SplFileObject':
|
||||
case 'SplFileInfo':
|
||||
return new \SplFileObject($data);
|
||||
}
|
||||
} catch (\RuntimeException $exception) {
|
||||
throw new NotNormalizableValueException($exception->getMessage(), $exception->getCode(), $exception);
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException(sprintf('The class parameter "%s" is not supported. It must be one of "SplFileInfo", "SplFileObject" or "Symfony\Component\HttpFoundation\File\File".', $type));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supportsDenormalization($data, $type, $format = null)
|
||||
{
|
||||
return isset(self::SUPPORTED_TYPES[$type]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasCacheableSupportsMethod(): bool
|
||||
{
|
||||
return __CLASS__ === static::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the mime type of the object. Defaults to application/octet-stream.
|
||||
*/
|
||||
private function getMimeType(\SplFileInfo $object): string
|
||||
{
|
||||
if ($object instanceof File) {
|
||||
return $object->getMimeType();
|
||||
}
|
||||
|
||||
if ($this->mimeTypeGuesser instanceof DeprecatedMimeTypeGuesserInterface && $mimeType = $this->mimeTypeGuesser->guess($object->getPathname())) {
|
||||
return $mimeType;
|
||||
}
|
||||
|
||||
if ($this->mimeTypeGuesser && $mimeType = $this->mimeTypeGuesser->guessMimeType($object->getPathname())) {
|
||||
return $mimeType;
|
||||
}
|
||||
|
||||
return 'application/octet-stream';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the \SplFileObject instance associated with the given \SplFileInfo instance.
|
||||
*/
|
||||
private function extractSplFileObject(\SplFileInfo $object): \SplFileObject
|
||||
{
|
||||
if ($object instanceof \SplFileObject) {
|
||||
return $object;
|
||||
}
|
||||
|
||||
return $object->openFile();
|
||||
}
|
||||
}
|
@@ -0,0 +1,143 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Normalizer;
|
||||
|
||||
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
|
||||
|
||||
/**
|
||||
* Normalizes an instance of {@see \DateInterval} to an interval string.
|
||||
* Denormalizes an interval string to an instance of {@see \DateInterval}.
|
||||
*
|
||||
* @author Jérôme Parmentier <jerome@prmntr.me>
|
||||
*/
|
||||
class DateIntervalNormalizer implements NormalizerInterface, DenormalizerInterface, CacheableSupportsMethodInterface
|
||||
{
|
||||
public const FORMAT_KEY = 'dateinterval_format';
|
||||
|
||||
private $defaultContext = [
|
||||
self::FORMAT_KEY => '%rP%yY%mM%dDT%hH%iM%sS',
|
||||
];
|
||||
|
||||
/**
|
||||
* @param array $defaultContext
|
||||
*/
|
||||
public function __construct($defaultContext = [])
|
||||
{
|
||||
if (!\is_array($defaultContext)) {
|
||||
@trigger_error(sprintf('The "format" parameter is deprecated since Symfony 4.2, use the "%s" key of the context instead.', self::FORMAT_KEY), \E_USER_DEPRECATED);
|
||||
|
||||
$defaultContext = [self::FORMAT_KEY => (string) $defaultContext];
|
||||
}
|
||||
|
||||
$this->defaultContext = array_merge($this->defaultContext, $defaultContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function normalize($object, $format = null, array $context = [])
|
||||
{
|
||||
if (!$object instanceof \DateInterval) {
|
||||
throw new InvalidArgumentException('The object must be an instance of "\DateInterval".');
|
||||
}
|
||||
|
||||
return $object->format($context[self::FORMAT_KEY] ?? $this->defaultContext[self::FORMAT_KEY]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supportsNormalization($data, $format = null)
|
||||
{
|
||||
return $data instanceof \DateInterval;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasCacheableSupportsMethod(): bool
|
||||
{
|
||||
return __CLASS__ === static::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
* @throws UnexpectedValueException
|
||||
*
|
||||
* @return \DateInterval
|
||||
*/
|
||||
public function denormalize($data, $type, $format = null, array $context = [])
|
||||
{
|
||||
if (!\is_string($data)) {
|
||||
throw new InvalidArgumentException(sprintf('Data expected to be a string, "%s" given.', \gettype($data)));
|
||||
}
|
||||
|
||||
if (!$this->isISO8601($data)) {
|
||||
throw new UnexpectedValueException('Expected a valid ISO 8601 interval string.');
|
||||
}
|
||||
|
||||
$dateIntervalFormat = $context[self::FORMAT_KEY] ?? $this->defaultContext[self::FORMAT_KEY];
|
||||
|
||||
$signPattern = '';
|
||||
switch (substr($dateIntervalFormat, 0, 2)) {
|
||||
case '%R':
|
||||
$signPattern = '[-+]';
|
||||
$dateIntervalFormat = substr($dateIntervalFormat, 2);
|
||||
break;
|
||||
case '%r':
|
||||
$signPattern = '-?';
|
||||
$dateIntervalFormat = substr($dateIntervalFormat, 2);
|
||||
break;
|
||||
}
|
||||
$valuePattern = '/^'.$signPattern.preg_replace('/%([yYmMdDhHiIsSwW])(\w)/', '(?:(?P<$1>\d+)$2)?', preg_replace('/(T.*)$/', '($1)?', $dateIntervalFormat)).'$/';
|
||||
if (!preg_match($valuePattern, $data)) {
|
||||
throw new UnexpectedValueException(sprintf('Value "%s" contains intervals not accepted by format "%s".', $data, $dateIntervalFormat));
|
||||
}
|
||||
|
||||
try {
|
||||
if ('-' === $data[0]) {
|
||||
$interval = new \DateInterval(substr($data, 1));
|
||||
$interval->invert = 1;
|
||||
|
||||
return $interval;
|
||||
}
|
||||
|
||||
if ('+' === $data[0]) {
|
||||
return new \DateInterval(substr($data, 1));
|
||||
}
|
||||
|
||||
return new \DateInterval($data);
|
||||
} catch (\Exception $e) {
|
||||
throw new UnexpectedValueException($e->getMessage(), $e->getCode(), $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supportsDenormalization($data, $type, $format = null)
|
||||
{
|
||||
return \DateInterval::class === $type;
|
||||
}
|
||||
|
||||
private function isISO8601(string $string): bool
|
||||
{
|
||||
return preg_match('/^[\-+]?P(?=\w*(?:\d|%\w))(?:\d+Y|%[yY]Y)?(?:\d+M|%[mM]M)?(?:(?:\d+D|%[dD]D)|(?:\d+W|%[wW]W))?(?:T(?:\d+H|[hH]H)?(?:\d+M|[iI]M)?(?:\d+S|[sS]S)?)?$/', $string);
|
||||
}
|
||||
}
|
165
old.vendor/symfony/serializer/Normalizer/DateTimeNormalizer.php
Normal file
165
old.vendor/symfony/serializer/Normalizer/DateTimeNormalizer.php
Normal file
@@ -0,0 +1,165 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Normalizer;
|
||||
|
||||
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
|
||||
|
||||
/**
|
||||
* Normalizes an object implementing the {@see \DateTimeInterface} to a date string.
|
||||
* Denormalizes a date string to an instance of {@see \DateTime} or {@see \DateTimeImmutable}.
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
class DateTimeNormalizer implements NormalizerInterface, DenormalizerInterface, CacheableSupportsMethodInterface
|
||||
{
|
||||
public const FORMAT_KEY = 'datetime_format';
|
||||
public const TIMEZONE_KEY = 'datetime_timezone';
|
||||
|
||||
private $defaultContext;
|
||||
|
||||
private const SUPPORTED_TYPES = [
|
||||
\DateTimeInterface::class => true,
|
||||
\DateTimeImmutable::class => true,
|
||||
\DateTime::class => true,
|
||||
];
|
||||
|
||||
/**
|
||||
* @param array $defaultContext
|
||||
*/
|
||||
public function __construct($defaultContext = [], \DateTimeZone $timezone = null)
|
||||
{
|
||||
$this->defaultContext = [
|
||||
self::FORMAT_KEY => \DateTime::RFC3339,
|
||||
self::TIMEZONE_KEY => null,
|
||||
];
|
||||
|
||||
if (!\is_array($defaultContext)) {
|
||||
@trigger_error('Passing configuration options directly to the constructor is deprecated since Symfony 4.2, use the default context instead.', \E_USER_DEPRECATED);
|
||||
|
||||
$defaultContext = [self::FORMAT_KEY => (string) $defaultContext];
|
||||
$defaultContext[self::TIMEZONE_KEY] = $timezone;
|
||||
}
|
||||
|
||||
$this->defaultContext = array_merge($this->defaultContext, $defaultContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function normalize($object, $format = null, array $context = [])
|
||||
{
|
||||
if (!$object instanceof \DateTimeInterface) {
|
||||
throw new InvalidArgumentException('The object must implement the "\DateTimeInterface".');
|
||||
}
|
||||
|
||||
$dateTimeFormat = $context[self::FORMAT_KEY] ?? $this->defaultContext[self::FORMAT_KEY];
|
||||
$timezone = $this->getTimezone($context);
|
||||
|
||||
if (null !== $timezone) {
|
||||
$object = clone $object;
|
||||
$object = $object->setTimezone($timezone);
|
||||
}
|
||||
|
||||
return $object->format($dateTimeFormat);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supportsNormalization($data, $format = null)
|
||||
{
|
||||
return $data instanceof \DateTimeInterface;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @throws NotNormalizableValueException
|
||||
*
|
||||
* @return \DateTimeInterface
|
||||
*/
|
||||
public function denormalize($data, $type, $format = null, array $context = [])
|
||||
{
|
||||
$dateTimeFormat = $context[self::FORMAT_KEY] ?? null;
|
||||
$timezone = $this->getTimezone($context);
|
||||
|
||||
if (null === $data || (\is_string($data) && '' === trim($data))) {
|
||||
throw new NotNormalizableValueException('The data is either an empty string or null, you should pass a string that can be parsed with the passed format or a valid DateTime string.');
|
||||
}
|
||||
|
||||
if (null !== $dateTimeFormat) {
|
||||
$object = \DateTime::class === $type ? \DateTime::createFromFormat($dateTimeFormat, $data, $timezone) : \DateTimeImmutable::createFromFormat($dateTimeFormat, $data, $timezone);
|
||||
|
||||
if (false !== $object) {
|
||||
return $object;
|
||||
}
|
||||
|
||||
$dateTimeErrors = \DateTime::class === $type ? \DateTime::getLastErrors() : \DateTimeImmutable::getLastErrors();
|
||||
|
||||
throw new NotNormalizableValueException(sprintf('Parsing datetime string "%s" using format "%s" resulted in %d errors: ', $data, $dateTimeFormat, $dateTimeErrors['error_count'])."\n".implode("\n", $this->formatDateTimeErrors($dateTimeErrors['errors'])));
|
||||
}
|
||||
|
||||
try {
|
||||
return \DateTime::class === $type ? new \DateTime($data, $timezone) : new \DateTimeImmutable($data, $timezone);
|
||||
} catch (\Exception $e) {
|
||||
throw new NotNormalizableValueException($e->getMessage(), $e->getCode(), $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supportsDenormalization($data, $type, $format = null)
|
||||
{
|
||||
return isset(self::SUPPORTED_TYPES[$type]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasCacheableSupportsMethod(): bool
|
||||
{
|
||||
return __CLASS__ === static::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats datetime errors.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
private function formatDateTimeErrors(array $errors): array
|
||||
{
|
||||
$formattedErrors = [];
|
||||
|
||||
foreach ($errors as $pos => $message) {
|
||||
$formattedErrors[] = sprintf('at position %d: %s', $pos, $message);
|
||||
}
|
||||
|
||||
return $formattedErrors;
|
||||
}
|
||||
|
||||
private function getTimezone(array $context): ?\DateTimeZone
|
||||
{
|
||||
$dateTimeZone = $context[self::TIMEZONE_KEY] ?? $this->defaultContext[self::TIMEZONE_KEY];
|
||||
|
||||
if (null === $dateTimeZone) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $dateTimeZone instanceof \DateTimeZone ? $dateTimeZone : new \DateTimeZone($dateTimeZone);
|
||||
}
|
||||
}
|
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Normalizer;
|
||||
|
||||
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
|
||||
|
||||
/**
|
||||
* Normalizes a {@see \DateTimeZone} object to a timezone string.
|
||||
*
|
||||
* @author Jérôme Desjardins <jewome62@gmail.com>
|
||||
*/
|
||||
class DateTimeZoneNormalizer implements NormalizerInterface, DenormalizerInterface, CacheableSupportsMethodInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function normalize($object, $format = null, array $context = [])
|
||||
{
|
||||
if (!$object instanceof \DateTimeZone) {
|
||||
throw new InvalidArgumentException('The object must be an instance of "\DateTimeZone".');
|
||||
}
|
||||
|
||||
return $object->getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supportsNormalization($data, $format = null)
|
||||
{
|
||||
return $data instanceof \DateTimeZone;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @throws NotNormalizableValueException
|
||||
*
|
||||
* @return \DateTimeZone
|
||||
*/
|
||||
public function denormalize($data, $type, $format = null, array $context = [])
|
||||
{
|
||||
if ('' === $data || null === $data) {
|
||||
throw new NotNormalizableValueException('The data is either an empty string or null, you should pass a string that can be parsed as a DateTimeZone.');
|
||||
}
|
||||
|
||||
try {
|
||||
return new \DateTimeZone($data);
|
||||
} catch (\Exception $e) {
|
||||
throw new NotNormalizableValueException($e->getMessage(), $e->getCode(), $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supportsDenormalization($data, $type, $format = null)
|
||||
{
|
||||
return \DateTimeZone::class === $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasCacheableSupportsMethod(): bool
|
||||
{
|
||||
return __CLASS__ === static::class;
|
||||
}
|
||||
}
|
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Normalizer;
|
||||
|
||||
/**
|
||||
* Defines the most basic interface a class must implement to be denormalizable.
|
||||
*
|
||||
* If a denormalizer is registered for the class and it doesn't implement
|
||||
* the Denormalizable interfaces, the normalizer will be used instead
|
||||
*
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*/
|
||||
interface DenormalizableInterface
|
||||
{
|
||||
/**
|
||||
* Denormalizes the object back from an array of scalars|arrays.
|
||||
*
|
||||
* It is important to understand that the denormalize() call should denormalize
|
||||
* recursively all child objects of the implementor.
|
||||
*
|
||||
* @param DenormalizerInterface $denormalizer The denormalizer is given so that you
|
||||
* can use it to denormalize objects contained within this object
|
||||
* @param array|string|int|float|bool $data The data from which to re-create the object
|
||||
* @param string|null $format The format is optionally given to be able to denormalize
|
||||
* differently based on different input formats
|
||||
* @param array $context Options for denormalizing
|
||||
*/
|
||||
public function denormalize(DenormalizerInterface $denormalizer, $data, $format = null, array $context = []);
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Normalizer;
|
||||
|
||||
/**
|
||||
* @author Joel Wurtz <joel.wurtz@gmail.com>
|
||||
*/
|
||||
interface DenormalizerAwareInterface
|
||||
{
|
||||
/**
|
||||
* Sets the owning Denormalizer object.
|
||||
*/
|
||||
public function setDenormalizer(DenormalizerInterface $denormalizer);
|
||||
}
|
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Normalizer;
|
||||
|
||||
/**
|
||||
* @author Joel Wurtz <joel.wurtz@gmail.com>
|
||||
*/
|
||||
trait DenormalizerAwareTrait
|
||||
{
|
||||
/**
|
||||
* @var DenormalizerInterface
|
||||
*/
|
||||
protected $denormalizer;
|
||||
|
||||
public function setDenormalizer(DenormalizerInterface $denormalizer)
|
||||
{
|
||||
$this->denormalizer = $denormalizer;
|
||||
}
|
||||
}
|
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Normalizer;
|
||||
|
||||
use Symfony\Component\Serializer\Exception\BadMethodCallException;
|
||||
use Symfony\Component\Serializer\Exception\ExceptionInterface;
|
||||
use Symfony\Component\Serializer\Exception\ExtraAttributesException;
|
||||
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Serializer\Exception\LogicException;
|
||||
use Symfony\Component\Serializer\Exception\RuntimeException;
|
||||
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
|
||||
|
||||
/**
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*/
|
||||
interface DenormalizerInterface
|
||||
{
|
||||
/**
|
||||
* Denormalizes data back into an object of the given class.
|
||||
*
|
||||
* @param mixed $data Data to restore
|
||||
* @param string $type The expected class to instantiate
|
||||
* @param string $format Format the given data was extracted from
|
||||
* @param array $context Options available to the denormalizer
|
||||
*
|
||||
* @return object|array
|
||||
*
|
||||
* @throws BadMethodCallException Occurs when the normalizer is not called in an expected context
|
||||
* @throws InvalidArgumentException Occurs when the arguments are not coherent or not supported
|
||||
* @throws UnexpectedValueException Occurs when the item cannot be hydrated with the given data
|
||||
* @throws ExtraAttributesException Occurs when the item doesn't have attribute to receive given data
|
||||
* @throws LogicException Occurs when the normalizer is not supposed to denormalize
|
||||
* @throws RuntimeException Occurs if the class cannot be instantiated
|
||||
* @throws ExceptionInterface Occurs for all the other cases of errors
|
||||
*/
|
||||
public function denormalize($data, $type, $format = null, array $context = []);
|
||||
|
||||
/**
|
||||
* Checks whether the given class is supported for denormalization by this normalizer.
|
||||
*
|
||||
* @param mixed $data Data to denormalize from
|
||||
* @param string $type The class to which the data should be denormalized
|
||||
* @param string $format The format being deserialized from
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function supportsDenormalization($data, $type, $format = null);
|
||||
}
|
@@ -0,0 +1,162 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Normalizer;
|
||||
|
||||
/**
|
||||
* Converts between objects with getter and setter methods and arrays.
|
||||
*
|
||||
* The normalization process looks at all public methods and calls the ones
|
||||
* which have a name starting with get and take no parameters. The result is a
|
||||
* map from property names (method name stripped of the get prefix and converted
|
||||
* to lower case) to property values. Property values are normalized through the
|
||||
* serializer.
|
||||
*
|
||||
* The denormalization first looks at the constructor of the given class to see
|
||||
* if any of the parameters have the same name as one of the properties. The
|
||||
* constructor is then called with all parameters or an exception is thrown if
|
||||
* any required parameters were not present as properties. Then the denormalizer
|
||||
* walks through the given map of property names to property values to see if a
|
||||
* setter method exists for any of the properties. If a setter exists it is
|
||||
* called with the property value. No automatic denormalization of the value
|
||||
* takes place.
|
||||
*
|
||||
* @author Nils Adermann <naderman@naderman.de>
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
class GetSetMethodNormalizer extends AbstractObjectNormalizer
|
||||
{
|
||||
private static $setterAccessibleCache = [];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supportsNormalization($data, $format = null)
|
||||
{
|
||||
return parent::supportsNormalization($data, $format) && $this->supports(\get_class($data));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supportsDenormalization($data, $type, $format = null)
|
||||
{
|
||||
return parent::supportsDenormalization($data, $type, $format) && $this->supports($type);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasCacheableSupportsMethod(): bool
|
||||
{
|
||||
return __CLASS__ === static::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given class has any getter method.
|
||||
*/
|
||||
private function supports(string $class): bool
|
||||
{
|
||||
$class = new \ReflectionClass($class);
|
||||
$methods = $class->getMethods(\ReflectionMethod::IS_PUBLIC);
|
||||
foreach ($methods as $method) {
|
||||
if ($this->isGetMethod($method)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a method's name matches /^(get|is|has).+$/ and can be called non-statically without parameters.
|
||||
*/
|
||||
private function isGetMethod(\ReflectionMethod $method): bool
|
||||
{
|
||||
$methodLength = \strlen($method->name);
|
||||
|
||||
return
|
||||
!$method->isStatic() &&
|
||||
(
|
||||
((str_starts_with($method->name, 'get') && 3 < $methodLength) ||
|
||||
(str_starts_with($method->name, 'is') && 2 < $methodLength) ||
|
||||
(str_starts_with($method->name, 'has') && 3 < $methodLength)) &&
|
||||
0 === $method->getNumberOfRequiredParameters()
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function extractAttributes($object, $format = null, array $context = [])
|
||||
{
|
||||
$reflectionObject = new \ReflectionObject($object);
|
||||
$reflectionMethods = $reflectionObject->getMethods(\ReflectionMethod::IS_PUBLIC);
|
||||
|
||||
$attributes = [];
|
||||
foreach ($reflectionMethods as $method) {
|
||||
if (!$this->isGetMethod($method)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$attributeName = lcfirst(substr($method->name, str_starts_with($method->name, 'is') ? 2 : 3));
|
||||
|
||||
if ($this->isAllowedAttribute($object, $attributeName, $format, $context)) {
|
||||
$attributes[] = $attributeName;
|
||||
}
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getAttributeValue($object, $attribute, $format = null, array $context = [])
|
||||
{
|
||||
$ucfirsted = ucfirst($attribute);
|
||||
|
||||
$getter = 'get'.$ucfirsted;
|
||||
if (\is_callable([$object, $getter])) {
|
||||
return $object->$getter();
|
||||
}
|
||||
|
||||
$isser = 'is'.$ucfirsted;
|
||||
if (\is_callable([$object, $isser])) {
|
||||
return $object->$isser();
|
||||
}
|
||||
|
||||
$haser = 'has'.$ucfirsted;
|
||||
if (\is_callable([$object, $haser])) {
|
||||
return $object->$haser();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setAttributeValue($object, $attribute, $value, $format = null, array $context = [])
|
||||
{
|
||||
$setter = 'set'.ucfirst($attribute);
|
||||
$key = \get_class($object).':'.$setter;
|
||||
|
||||
if (!isset(self::$setterAccessibleCache[$key])) {
|
||||
self::$setterAccessibleCache[$key] = \is_callable([$object, $setter]) && !(new \ReflectionMethod($object, $setter))->isStatic();
|
||||
}
|
||||
|
||||
if (self::$setterAccessibleCache[$key]) {
|
||||
$object->$setter($value);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Normalizer;
|
||||
|
||||
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Serializer\Exception\LogicException;
|
||||
|
||||
/**
|
||||
* A normalizer that uses an objects own JsonSerializable implementation.
|
||||
*
|
||||
* @author Fred Cox <mcfedr@gmail.com>
|
||||
*/
|
||||
class JsonSerializableNormalizer extends AbstractNormalizer
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function normalize($object, $format = null, array $context = [])
|
||||
{
|
||||
if ($this->isCircularReference($object, $context)) {
|
||||
return $this->handleCircularReference($object);
|
||||
}
|
||||
|
||||
if (!$object instanceof \JsonSerializable) {
|
||||
throw new InvalidArgumentException(sprintf('The object must implement "%s".', \JsonSerializable::class));
|
||||
}
|
||||
|
||||
if (!$this->serializer instanceof NormalizerInterface) {
|
||||
throw new LogicException('Cannot normalize object because injected serializer is not a normalizer.');
|
||||
}
|
||||
|
||||
return $this->serializer->normalize($object->jsonSerialize(), $format, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supportsNormalization($data, $format = null)
|
||||
{
|
||||
return $data instanceof \JsonSerializable;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supportsDenormalization($data, $type, $format = null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function denormalize($data, $type, $format = null, array $context = [])
|
||||
{
|
||||
throw new LogicException(sprintf('Cannot denormalize with "%s".', \JsonSerializable::class));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasCacheableSupportsMethod(): bool
|
||||
{
|
||||
return __CLASS__ === static::class;
|
||||
}
|
||||
}
|
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Normalizer;
|
||||
|
||||
/**
|
||||
* Defines the most basic interface a class must implement to be normalizable.
|
||||
*
|
||||
* If a normalizer is registered for the class and it doesn't implement
|
||||
* the Normalizable interfaces, the normalizer will be used instead.
|
||||
*
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*/
|
||||
interface NormalizableInterface
|
||||
{
|
||||
/**
|
||||
* Normalizes the object into an array of scalars|arrays.
|
||||
*
|
||||
* It is important to understand that the normalize() call should normalize
|
||||
* recursively all child objects of the implementor.
|
||||
*
|
||||
* @param NormalizerInterface $normalizer The normalizer is given so that you
|
||||
* can use it to normalize objects contained within this object
|
||||
* @param string|null $format The format is optionally given to be able to normalize differently
|
||||
* based on different output formats
|
||||
* @param array $context Options for normalizing this object
|
||||
*
|
||||
* @return array|string|int|float|bool
|
||||
*/
|
||||
public function normalize(NormalizerInterface $normalizer, $format = null, array $context = []);
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Normalizer;
|
||||
|
||||
/**
|
||||
* @author Joel Wurtz <joel.wurtz@gmail.com>
|
||||
*/
|
||||
interface NormalizerAwareInterface
|
||||
{
|
||||
/**
|
||||
* Sets the owning Normalizer object.
|
||||
*/
|
||||
public function setNormalizer(NormalizerInterface $normalizer);
|
||||
}
|
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Normalizer;
|
||||
|
||||
/**
|
||||
* @author Joel Wurtz <joel.wurtz@gmail.com>
|
||||
*/
|
||||
trait NormalizerAwareTrait
|
||||
{
|
||||
/**
|
||||
* @var NormalizerInterface
|
||||
*/
|
||||
protected $normalizer;
|
||||
|
||||
public function setNormalizer(NormalizerInterface $normalizer)
|
||||
{
|
||||
$this->normalizer = $normalizer;
|
||||
}
|
||||
}
|
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Normalizer;
|
||||
|
||||
use Symfony\Component\Serializer\Exception\CircularReferenceException;
|
||||
use Symfony\Component\Serializer\Exception\ExceptionInterface;
|
||||
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Serializer\Exception\LogicException;
|
||||
|
||||
/**
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*/
|
||||
interface NormalizerInterface
|
||||
{
|
||||
/**
|
||||
* Normalizes an object into a set of arrays/scalars.
|
||||
*
|
||||
* @param mixed $object Object to normalize
|
||||
* @param string $format Format the normalization result will be encoded as
|
||||
* @param array $context Context options for the normalizer
|
||||
*
|
||||
* @return array|string|int|float|bool|\ArrayObject|null \ArrayObject is used to make sure an empty object is encoded as an object not an array
|
||||
*
|
||||
* @throws InvalidArgumentException Occurs when the object given is not a supported type for the normalizer
|
||||
* @throws CircularReferenceException Occurs when the normalizer detects a circular reference when no circular
|
||||
* reference handler can fix it
|
||||
* @throws LogicException Occurs when the normalizer is not called in an expected context
|
||||
* @throws ExceptionInterface Occurs for all the other cases of errors
|
||||
*/
|
||||
public function normalize($object, $format = null, array $context = []);
|
||||
|
||||
/**
|
||||
* Checks whether the given class is supported for normalization by this normalizer.
|
||||
*
|
||||
* @param mixed $data Data to normalize
|
||||
* @param string $format The format being (de-)serialized from or into
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function supportsNormalization($data, $format = null);
|
||||
}
|
183
old.vendor/symfony/serializer/Normalizer/ObjectNormalizer.php
Normal file
183
old.vendor/symfony/serializer/Normalizer/ObjectNormalizer.php
Normal file
@@ -0,0 +1,183 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Normalizer;
|
||||
|
||||
use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException;
|
||||
use Symfony\Component\PropertyAccess\PropertyAccess;
|
||||
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
|
||||
use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
|
||||
use Symfony\Component\Serializer\Exception\LogicException;
|
||||
use Symfony\Component\Serializer\Mapping\AttributeMetadata;
|
||||
use Symfony\Component\Serializer\Mapping\ClassDiscriminatorResolverInterface;
|
||||
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
|
||||
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
|
||||
|
||||
/**
|
||||
* Converts between objects and arrays using the PropertyAccess component.
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
class ObjectNormalizer extends AbstractObjectNormalizer
|
||||
{
|
||||
protected $propertyAccessor;
|
||||
|
||||
private $discriminatorCache = [];
|
||||
|
||||
private $objectClassResolver;
|
||||
|
||||
public function __construct(ClassMetadataFactoryInterface $classMetadataFactory = null, NameConverterInterface $nameConverter = null, PropertyAccessorInterface $propertyAccessor = null, PropertyTypeExtractorInterface $propertyTypeExtractor = null, ClassDiscriminatorResolverInterface $classDiscriminatorResolver = null, callable $objectClassResolver = null, array $defaultContext = [])
|
||||
{
|
||||
if (!class_exists(PropertyAccess::class)) {
|
||||
throw new LogicException('The ObjectNormalizer class requires the "PropertyAccess" component. Install "symfony/property-access" to use it.');
|
||||
}
|
||||
|
||||
parent::__construct($classMetadataFactory, $nameConverter, $propertyTypeExtractor, $classDiscriminatorResolver, $objectClassResolver, $defaultContext);
|
||||
|
||||
$this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor();
|
||||
|
||||
$this->objectClassResolver = $objectClassResolver ?? function ($class) {
|
||||
return \is_object($class) ? \get_class($class) : $class;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasCacheableSupportsMethod(): bool
|
||||
{
|
||||
return __CLASS__ === static::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function extractAttributes($object, $format = null, array $context = [])
|
||||
{
|
||||
// If not using groups, detect manually
|
||||
$attributes = [];
|
||||
|
||||
// methods
|
||||
$class = ($this->objectClassResolver)($object);
|
||||
$reflClass = new \ReflectionClass($class);
|
||||
|
||||
foreach ($reflClass->getMethods(\ReflectionMethod::IS_PUBLIC) as $reflMethod) {
|
||||
if (
|
||||
0 !== $reflMethod->getNumberOfRequiredParameters() ||
|
||||
$reflMethod->isStatic() ||
|
||||
$reflMethod->isConstructor() ||
|
||||
$reflMethod->isDestructor()
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$name = $reflMethod->name;
|
||||
$attributeName = null;
|
||||
|
||||
if (str_starts_with($name, 'get') || str_starts_with($name, 'has')) {
|
||||
// getters and hassers
|
||||
$attributeName = substr($name, 3);
|
||||
|
||||
if (!$reflClass->hasProperty($attributeName)) {
|
||||
$attributeName = lcfirst($attributeName);
|
||||
}
|
||||
} elseif (str_starts_with($name, 'is')) {
|
||||
// issers
|
||||
$attributeName = substr($name, 2);
|
||||
|
||||
if (!$reflClass->hasProperty($attributeName)) {
|
||||
$attributeName = lcfirst($attributeName);
|
||||
}
|
||||
}
|
||||
|
||||
if (null !== $attributeName && $this->isAllowedAttribute($object, $attributeName, $format, $context)) {
|
||||
$attributes[$attributeName] = true;
|
||||
}
|
||||
}
|
||||
|
||||
// properties
|
||||
$propertyValues = !method_exists($object, '__get') ? (array) $object : null;
|
||||
foreach ($reflClass->getProperties() as $reflProperty) {
|
||||
if (null !== $propertyValues && !\array_key_exists($reflProperty->name, $propertyValues)) {
|
||||
if ($reflProperty->isPublic()
|
||||
|| ($reflProperty->isProtected() && !\array_key_exists("\0*\0{$reflProperty->name}", $propertyValues))
|
||||
|| ($reflProperty->isPrivate() && !\array_key_exists("\0{$reflProperty->class}\0{$reflProperty->name}", $propertyValues))
|
||||
) {
|
||||
unset($attributes[$reflProperty->name]);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($reflProperty->isStatic() || !$this->isAllowedAttribute($object, $reflProperty->name, $format, $context)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$attributes[$reflProperty->name] = true;
|
||||
}
|
||||
|
||||
return array_keys($attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getAttributeValue($object, $attribute, $format = null, array $context = [])
|
||||
{
|
||||
$cacheKey = \get_class($object);
|
||||
if (!\array_key_exists($cacheKey, $this->discriminatorCache)) {
|
||||
$this->discriminatorCache[$cacheKey] = null;
|
||||
if (null !== $this->classDiscriminatorResolver) {
|
||||
$mapping = $this->classDiscriminatorResolver->getMappingForMappedObject($object);
|
||||
$this->discriminatorCache[$cacheKey] = null === $mapping ? null : $mapping->getTypeProperty();
|
||||
}
|
||||
}
|
||||
|
||||
return $attribute === $this->discriminatorCache[$cacheKey] ? $this->classDiscriminatorResolver->getTypeForMappedObject($object) : $this->propertyAccessor->getValue($object, $attribute);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setAttributeValue($object, $attribute, $value, $format = null, array $context = [])
|
||||
{
|
||||
try {
|
||||
$this->propertyAccessor->setValue($object, $attribute, $value);
|
||||
} catch (NoSuchPropertyException $exception) {
|
||||
// Properties not found are ignored
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getAllowedAttributes($classOrObject, array $context, $attributesAsString = false)
|
||||
{
|
||||
if (false === $allowedAttributes = parent::getAllowedAttributes($classOrObject, $context, $attributesAsString)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (null !== $this->classDiscriminatorResolver) {
|
||||
$class = \is_object($classOrObject) ? \get_class($classOrObject) : $classOrObject;
|
||||
if (null !== $discriminatorMapping = $this->classDiscriminatorResolver->getMappingForMappedObject($classOrObject)) {
|
||||
$allowedAttributes[] = $attributesAsString ? $discriminatorMapping->getTypeProperty() : new AttributeMetadata($discriminatorMapping->getTypeProperty());
|
||||
}
|
||||
|
||||
if (null !== $discriminatorMapping = $this->classDiscriminatorResolver->getMappingForClass($class)) {
|
||||
foreach ($discriminatorMapping->getTypesMapping() as $mappedClass) {
|
||||
$allowedAttributes = array_merge($allowedAttributes, parent::getAllowedAttributes($mappedClass, $context, $attributesAsString));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $allowedAttributes;
|
||||
}
|
||||
}
|
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Normalizer;
|
||||
|
||||
trait ObjectToPopulateTrait
|
||||
{
|
||||
/**
|
||||
* Extract the `object_to_populate` field from the context if it exists
|
||||
* and is an instance of the provided $class.
|
||||
*
|
||||
* @param string $class The class the object should be
|
||||
* @param string|null $key They in which to look for the object to populate.
|
||||
* Keeps backwards compatibility with `AbstractNormalizer`.
|
||||
*
|
||||
* @return object|null an object if things check out, null otherwise
|
||||
*/
|
||||
protected function extractObjectToPopulate($class, array $context, $key = null)
|
||||
{
|
||||
$key = $key ?? AbstractNormalizer::OBJECT_TO_POPULATE;
|
||||
|
||||
if (isset($context[$key]) && \is_object($context[$key]) && $context[$key] instanceof $class) {
|
||||
return $context[$key];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Normalizer;
|
||||
|
||||
use Symfony\Component\ErrorHandler\Exception\FlattenException;
|
||||
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Normalizes errors according to the API Problem spec (RFC 7807).
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc7807
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
* @author Yonel Ceruto <yonelceruto@gmail.com>
|
||||
*/
|
||||
class ProblemNormalizer implements NormalizerInterface, CacheableSupportsMethodInterface
|
||||
{
|
||||
private $debug;
|
||||
private $defaultContext = [
|
||||
'type' => 'https://tools.ietf.org/html/rfc2616#section-10',
|
||||
'title' => 'An error occurred',
|
||||
];
|
||||
|
||||
public function __construct(bool $debug = false, array $defaultContext = [])
|
||||
{
|
||||
$this->debug = $debug;
|
||||
$this->defaultContext = $defaultContext + $this->defaultContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function normalize($object, $format = null, array $context = [])
|
||||
{
|
||||
if (!$object instanceof FlattenException) {
|
||||
throw new InvalidArgumentException(sprintf('The object must implement "%s".', FlattenException::class));
|
||||
}
|
||||
|
||||
$context += $this->defaultContext;
|
||||
$debug = $this->debug && ($context['debug'] ?? true);
|
||||
|
||||
$data = [
|
||||
'type' => $context['type'],
|
||||
'title' => $context['title'],
|
||||
'status' => $context['status'] ?? $object->getStatusCode(),
|
||||
'detail' => $debug ? $object->getMessage() : $object->getStatusText(),
|
||||
];
|
||||
if ($debug) {
|
||||
$data['class'] = $object->getClass();
|
||||
$data['trace'] = $object->getTrace();
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supportsNormalization($data, $format = null): bool
|
||||
{
|
||||
return $data instanceof FlattenException;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasCacheableSupportsMethod(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
185
old.vendor/symfony/serializer/Normalizer/PropertyNormalizer.php
Normal file
185
old.vendor/symfony/serializer/Normalizer/PropertyNormalizer.php
Normal file
@@ -0,0 +1,185 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer\Normalizer;
|
||||
|
||||
/**
|
||||
* Converts between objects and arrays by mapping properties.
|
||||
*
|
||||
* The normalization process looks for all the object's properties (public and private).
|
||||
* The result is a map from property names to property values. Property values
|
||||
* are normalized through the serializer.
|
||||
*
|
||||
* The denormalization first looks at the constructor of the given class to see
|
||||
* if any of the parameters have the same name as one of the properties. The
|
||||
* constructor is then called with all parameters or an exception is thrown if
|
||||
* any required parameters were not present as properties. Then the denormalizer
|
||||
* walks through the given map of property names to property values to see if a
|
||||
* property with the corresponding name exists. If found, the property gets the value.
|
||||
*
|
||||
* @author Matthieu Napoli <matthieu@mnapoli.fr>
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
class PropertyNormalizer extends AbstractObjectNormalizer
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supportsNormalization($data, $format = null)
|
||||
{
|
||||
return parent::supportsNormalization($data, $format) && $this->supports(\get_class($data));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supportsDenormalization($data, $type, $format = null)
|
||||
{
|
||||
return parent::supportsDenormalization($data, $type, $format) && $this->supports($type);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasCacheableSupportsMethod(): bool
|
||||
{
|
||||
return __CLASS__ === static::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given class has any non-static property.
|
||||
*/
|
||||
private function supports(string $class): bool
|
||||
{
|
||||
$class = new \ReflectionClass($class);
|
||||
|
||||
// We look for at least one non-static property
|
||||
do {
|
||||
foreach ($class->getProperties() as $property) {
|
||||
if (!$property->isStatic()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} while ($class = $class->getParentClass());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function isAllowedAttribute($classOrObject, $attribute, $format = null, array $context = [])
|
||||
{
|
||||
if (!parent::isAllowedAttribute($classOrObject, $attribute, $format, $context)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
$reflectionProperty = $this->getReflectionProperty($classOrObject, $attribute);
|
||||
if ($reflectionProperty->isStatic()) {
|
||||
return false;
|
||||
}
|
||||
} catch (\ReflectionException $reflectionException) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function extractAttributes($object, $format = null, array $context = [])
|
||||
{
|
||||
$reflectionObject = new \ReflectionObject($object);
|
||||
$attributes = [];
|
||||
$propertyValues = !method_exists($object, '__get') ? (array) $object : null;
|
||||
|
||||
do {
|
||||
foreach ($reflectionObject->getProperties() as $property) {
|
||||
if ((null !== $propertyValues && (
|
||||
($property->isPublic() && !\array_key_exists($property->name, $propertyValues))
|
||||
|| ($property->isProtected() && !\array_key_exists("\0*\0{$property->name}", $propertyValues))
|
||||
|| ($property->isPrivate() && !\array_key_exists("\0{$property->class}\0{$property->name}", $propertyValues))
|
||||
))
|
||||
|| !$this->isAllowedAttribute($reflectionObject->getName(), $property->name, $format, $context)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$attributes[] = $property->name;
|
||||
}
|
||||
} while ($reflectionObject = $reflectionObject->getParentClass());
|
||||
|
||||
return array_unique($attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getAttributeValue($object, $attribute, $format = null, array $context = [])
|
||||
{
|
||||
try {
|
||||
$reflectionProperty = $this->getReflectionProperty($object, $attribute);
|
||||
} catch (\ReflectionException $reflectionException) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Override visibility
|
||||
if (!$reflectionProperty->isPublic()) {
|
||||
$reflectionProperty->setAccessible(true);
|
||||
}
|
||||
|
||||
return $reflectionProperty->getValue($object);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setAttributeValue($object, $attribute, $value, $format = null, array $context = [])
|
||||
{
|
||||
try {
|
||||
$reflectionProperty = $this->getReflectionProperty($object, $attribute);
|
||||
} catch (\ReflectionException $reflectionException) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($reflectionProperty->isStatic()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Override visibility
|
||||
if (!$reflectionProperty->isPublic()) {
|
||||
$reflectionProperty->setAccessible(true);
|
||||
}
|
||||
|
||||
$reflectionProperty->setValue($object, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|object $classOrObject
|
||||
*
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
private function getReflectionProperty($classOrObject, string $attribute): \ReflectionProperty
|
||||
{
|
||||
$reflectionClass = new \ReflectionClass($classOrObject);
|
||||
while (true) {
|
||||
try {
|
||||
return $reflectionClass->getProperty($attribute);
|
||||
} catch (\ReflectionException $e) {
|
||||
if (!$reflectionClass = $reflectionClass->getParentClass()) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
15
old.vendor/symfony/serializer/README.md
Normal file
15
old.vendor/symfony/serializer/README.md
Normal file
@@ -0,0 +1,15 @@
|
||||
Serializer Component
|
||||
====================
|
||||
|
||||
The Serializer component handles serializing and deserializing data structures,
|
||||
including object graphs, into array structures or other formats like XML and
|
||||
JSON.
|
||||
|
||||
Resources
|
||||
---------
|
||||
|
||||
* [Documentation](https://symfony.com/doc/current/components/serializer.html)
|
||||
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
||||
* [Report issues](https://github.com/symfony/symfony/issues) and
|
||||
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
||||
in the [main Symfony repository](https://github.com/symfony/symfony)
|
332
old.vendor/symfony/serializer/Serializer.php
Normal file
332
old.vendor/symfony/serializer/Serializer.php
Normal file
@@ -0,0 +1,332 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer;
|
||||
|
||||
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\LogicException;
|
||||
use Symfony\Component\Serializer\Exception\NotEncodableValueException;
|
||||
use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
|
||||
use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer;
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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')
|
||||
*
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
* @author Lukas Kahwe Smith <smith@pooteeweet.org>
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
class Serializer implements SerializerInterface, ContextAwareNormalizerInterface, ContextAwareDenormalizerInterface, ContextAwareEncoderInterface, ContextAwareDecoderInterface
|
||||
{
|
||||
/**
|
||||
* @var Encoder\ChainEncoder
|
||||
*/
|
||||
protected $encoder;
|
||||
|
||||
/**
|
||||
* @var Encoder\ChainDecoder
|
||||
*/
|
||||
protected $decoder;
|
||||
|
||||
/**
|
||||
* @internal since Symfony 4.1
|
||||
*/
|
||||
protected $normalizers = [];
|
||||
|
||||
private $cachedNormalizers;
|
||||
private $denormalizerCache = [];
|
||||
private $normalizerCache = [];
|
||||
|
||||
/**
|
||||
* @param array<NormalizerInterface|DenormalizerInterface> $normalizers
|
||||
* @param array<EncoderInterface|DecoderInterface> $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)) {
|
||||
@trigger_error(sprintf('Passing normalizers ("%s") which do not implement either "%s" or "%s" has been deprecated since Symfony 4.2.', \get_class($normalizer), NormalizerInterface::class, DenormalizerInterface::class), \E_USER_DEPRECATED);
|
||||
// throw new \InvalidArgumentException(sprintf('The class "%s" does not implement "%s" or "%s".', \get_class($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)) {
|
||||
@trigger_error(sprintf('Passing encoders ("%s") which do not implement either "%s" or "%s" has been deprecated since Symfony 4.2.', \get_class($encoder), EncoderInterface::class, DecoderInterface::class), \E_USER_DEPRECATED);
|
||||
// throw new \InvalidArgumentException(sprintf('The class "%s" does not implement "%s" or "%s".', \get_class($normalizer), EncoderInterface::class, DecoderInterface::class));
|
||||
}
|
||||
}
|
||||
$this->encoder = new ChainEncoder($realEncoders);
|
||||
$this->decoder = new ChainDecoder($decoders);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
final public function serialize($data, $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);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
final public function deserialize($data, $type, $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);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function normalize($data, $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 (null === $data || is_scalar($data)) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
if (is_iterable($data)) {
|
||||
if (($context[AbstractObjectNormalizer::PRESERVE_EMPTY_OBJECTS] ?? false) === true && $data instanceof \Countable && 0 === $data->count()) {
|
||||
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_class($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))));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @throws NotNormalizableValueException
|
||||
*/
|
||||
public function denormalize($data, $type, $format = null, array $context = [])
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supportsNormalization($data, $format = null, array $context = [])
|
||||
{
|
||||
return null !== $this->getNormalizer($data, $format, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supportsDenormalization($data, $type, $format = null, array $context = [])
|
||||
{
|
||||
return null !== $this->getDenormalizer($data, $type, $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
|
||||
{
|
||||
if ($this->cachedNormalizers !== $this->normalizers) {
|
||||
$this->cachedNormalizers = $this->normalizers;
|
||||
$this->denormalizerCache = $this->normalizerCache = [];
|
||||
}
|
||||
$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, $context)) {
|
||||
$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 ($this->cachedNormalizers !== $this->normalizers) {
|
||||
$this->cachedNormalizers = $this->normalizers;
|
||||
$this->denormalizerCache = $this->normalizerCache = [];
|
||||
}
|
||||
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, $context)) {
|
||||
$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;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
final public function encode($data, $format, array $context = [])
|
||||
{
|
||||
return $this->encoder->encode($data, $format, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
final public function decode($data, $format, array $context = [])
|
||||
{
|
||||
return $this->decoder->decode($data, $format, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supportsEncoding($format, array $context = [])
|
||||
{
|
||||
return $this->encoder->supportsEncoding($format, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supportsDecoding($format, array $context = [])
|
||||
{
|
||||
return $this->decoder->supportsDecoding($format, $context);
|
||||
}
|
||||
}
|
23
old.vendor/symfony/serializer/SerializerAwareInterface.php
Normal file
23
old.vendor/symfony/serializer/SerializerAwareInterface.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer;
|
||||
|
||||
/**
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*/
|
||||
interface SerializerAwareInterface
|
||||
{
|
||||
/**
|
||||
* Sets the owning Serializer object.
|
||||
*/
|
||||
public function setSerializer(SerializerInterface $serializer);
|
||||
}
|
28
old.vendor/symfony/serializer/SerializerAwareTrait.php
Normal file
28
old.vendor/symfony/serializer/SerializerAwareTrait.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer;
|
||||
|
||||
/**
|
||||
* @author Joel Wurtz <joel.wurtz@gmail.com>
|
||||
*/
|
||||
trait SerializerAwareTrait
|
||||
{
|
||||
/**
|
||||
* @var SerializerInterface
|
||||
*/
|
||||
protected $serializer;
|
||||
|
||||
public function setSerializer(SerializerInterface $serializer)
|
||||
{
|
||||
$this->serializer = $serializer;
|
||||
}
|
||||
}
|
40
old.vendor/symfony/serializer/SerializerInterface.php
Normal file
40
old.vendor/symfony/serializer/SerializerInterface.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Serializer;
|
||||
|
||||
/**
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*/
|
||||
interface SerializerInterface
|
||||
{
|
||||
/**
|
||||
* Serializes data in the appropriate format.
|
||||
*
|
||||
* @param mixed $data Any data
|
||||
* @param string $format Format name
|
||||
* @param array $context Options normalizers/encoders have access to
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function serialize($data, $format, array $context = []);
|
||||
|
||||
/**
|
||||
* Deserializes data into the given type.
|
||||
*
|
||||
* @param mixed $data
|
||||
* @param string $type
|
||||
* @param string $format
|
||||
*
|
||||
* @return object|array
|
||||
*/
|
||||
public function deserialize($data, $type, $format, array $context = []);
|
||||
}
|
61
old.vendor/symfony/serializer/composer.json
Normal file
61
old.vendor/symfony/serializer/composer.json
Normal file
@@ -0,0 +1,61 @@
|
||||
{
|
||||
"name": "symfony/serializer",
|
||||
"type": "library",
|
||||
"description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.",
|
||||
"keywords": [],
|
||||
"homepage": "https://symfony.com",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=7.1.3",
|
||||
"symfony/polyfill-ctype": "~1.8",
|
||||
"symfony/polyfill-php80": "^1.16"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/annotations": "^1.10.4",
|
||||
"phpdocumentor/reflection-docblock": "^3.2|^4.0|^5.0",
|
||||
"symfony/cache": "^3.4|^4.0|^5.0",
|
||||
"symfony/config": "^3.4|^4.0|^5.0",
|
||||
"symfony/dependency-injection": "^3.4|^4.0|^5.0",
|
||||
"symfony/error-handler": "^4.4|^5.0",
|
||||
"symfony/http-foundation": "^3.4|^4.0|^5.0",
|
||||
"symfony/mime": "^4.4|^5.0",
|
||||
"symfony/property-access": "^3.4.41|^4.4.9|^5.0.9",
|
||||
"symfony/property-info": "^3.4.13|~4.0|^5.0",
|
||||
"symfony/validator": "^3.4|^4.0|^5.0",
|
||||
"symfony/yaml": "^3.4|^4.0|^5.0"
|
||||
},
|
||||
"conflict": {
|
||||
"phpdocumentor/reflection-docblock": "<3.0|>=3.2.0,<3.2.2",
|
||||
"phpdocumentor/type-resolver": "<0.3.0|1.3.*",
|
||||
"symfony/dependency-injection": "<3.4",
|
||||
"symfony/property-access": "<3.4",
|
||||
"symfony/property-info": "<3.4",
|
||||
"symfony/yaml": "<3.4"
|
||||
},
|
||||
"suggest": {
|
||||
"psr/cache-implementation": "For using the metadata cache.",
|
||||
"symfony/property-info": "To deserialize relations.",
|
||||
"symfony/yaml": "For using the default YAML mapping loader.",
|
||||
"symfony/config": "For using the XML mapping loader.",
|
||||
"symfony/property-access": "For using the ObjectNormalizer.",
|
||||
"symfony/http-foundation": "For using a MIME type guesser within the DataUriNormalizer.",
|
||||
"doctrine/annotations": "For using the annotation mapping."
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": { "Symfony\\Component\\Serializer\\": "" },
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"minimum-stability": "dev"
|
||||
}
|
Reference in New Issue
Block a user