ge.
 *
 * (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\Notifier\Test;

use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Notifier\Exception\UnsupportedSchemeException;
use Symfony\Component\Notifier\Transport\Dsn;
use Symfony\Component\Notifier\Transport\TransportFactoryInterface;
use Symfony\Compone

, 1: string}>
     */
    abstract public static function supportsProvider(): iterable;

    /**
     * @return iterable<array{0: string, 1: string, 2: TransportInterface}>
     */
    abstract public static function createProvider(): iterable;

    /**

nt\Notifier\Transport\TransportInterface;

abstract class AbstractTransportFactoryTestCase extends TestCase
{
    abstract public function createFactory(): TransportFactoryInterface;

    /**
     * @return iterable<array{0: bool


<?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\Notifier\Bridge\Smsmode\Tests;

use PHPUnit\Framework\TestCase;
use Symfony\Component\Notifier\Bridge\Smsmode\SmsmodeOptions;

class SmsmodeOptionsTest extends TestCase
{
    public function testSmsmodeOptions()
    {
        $smsmodeOptions = (n

ons())
            ->refClient('test_ref_client')
            ->sentDate('test_sent_date');

        self::assertSame([
            'refClient' => 'test_ref_client',
            'sentDate' => 'test_sent_date',
        ], $smsmodeOptions->toArray());
    }


 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Notifier\Test;

use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Notifier\Exception\UnsupportedMessageTypeException;
use Symfony\Component\Notifier\Message\MessageInterface;
use Symfony\Component\Notifier\Transport\TransportInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;

/**
 *

USTOM_PORT = 42;

    abstract public static function createTransport(?HttpClientInterface $client = null): TransportInterface;

    /**
     * @return iterable<array{0: string, 1: TransportInterface}>
     */
    abstract public static function toStringPr

 A test case to ease testing a Notifier transport.
 *
 * @author Oskar Stark <oskarstark@googlemail.com>
 */
abstract class TransportTestCase extends TestCase
{
    protected const CUSTOM_HOST = 'host.test';
    protected const C


 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\Notifier\Test\Constraint;

use PHPUnit\Framework\Constraint\Constraint;
use Symfony\Component\Notifier\Event\NotificationEvents;

/**
 * @author Smaïne Milianni <smaine.milianni@gmail.com>
 */
final class NotificationCount extends Constraint
{
    public function __const

, $this->transport ? $this->transport.' ' : '', $this->queued ? 'queued' : 'sent', $this->expectedValue);
    }

    /**
     * @param NotificationEvents $events
     */
    protected function matches($events): bool
    {
        return $this->expectedValu

ruct(
        private int $expectedValue,
        private ?string $transport = null,
        private bool $queued = false,
    ) {
    }

    public function toString(): string
    {
        return \sprintf('%shas %s "%d" emails'


hp

/*
 * 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\Notifier\Test\Constraint;

use PHPUnit\Framework\Constraint\Constraint;
use Symfony\Component\Notifier\Message\MessageInterface;

/**
 * @author Smaïne Milianni <smaine.milianni@gmail.com>
 */
final class NotificationSubjectContains extends Constrai

essageInterface $message
     */
    protected function matches($message): bool
    {
        return false !== mb_strpos($message->getSubject(), $this->expectedText);
    }

    /**
     * @param MessageInterface $message
     */
    protected function fai

nt
{
    public function __construct(
        private string $expectedText,
    ) {
    }

    public function toString(): string
    {
        return \sprintf('contains "%s"', $this->expectedText);
    }

    /**
     * @param M


 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\Notifier\Bridge\Redlink;

use Symfony\Component\Notifier\Message\MessageOptionsInterface;

/**
 * @author Mateusz Żyła <https://github.com/plotkabytes>
 */
final class RedlinkOptions implements MessageOptionsInterface
{
    public function __construct(
        private ar

ull;
    }

    /**
     * @return $this
     */
    public function validity(int $validity): static
    {
        $this->options['validity'] = $validity;

        return $this;
    }

    /**
     * @return $this
     */
    public function scheduleTime(i

ray $options = [],
    ) {
    }

    public function toArray(): array
    {
        return array_filter($this->options);
    }

    public function getRecipientId(): ?string
    {
        return $this->options['externalId'] ?? n


 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\Notifier\Bridge\Zulip;

use Symfony\Component\Notifier\Exception\UnsupportedSchemeException;
use Symfony\Component\Notifier\Transport\AbstractTransportFactory;
use Symfony\Component\Notifier\Transport\Dsn;

/**
 * @author Mohammad Emran Hasan <phpfour@gmail.

ew UnsupportedSchemeException($dsn, 'zulip', $this->getSupportedSchemes());
        }

        $email = $this->getUser($dsn);
        $token = $this->getPassword($dsn);
        $channel = $dsn->getRequiredOption('channel');
        $host = $dsn->getHost();

com>
 */
final class ZulipTransportFactory extends AbstractTransportFactory
{
    public function create(Dsn $dsn): ZulipTransport
    {
        $scheme = $dsn->getScheme();

        if ('zulip' !== $scheme) {
            throw n


 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\Notifier\Bridge\Smsapi;

use Symfony\Component\Notifier\Exception\UnsupportedSchemeException;
use Symfony\Component\Notifier\Transport\AbstractTransportFactory;
use Symfony\Component\Notifier\Transport\Dsn;

/**
 * @author Marcin Szepczynski <szepczynski@gma

hrow new UnsupportedSchemeException($dsn, 'smsapi', $this->getSupportedSchemes());
        }

        $authToken = $this->getUser($dsn);
        $from = $dsn->getOption('from', '');
        $host = 'default' === $dsn->getHost() ? null : $dsn->getHost();

il.com>
 */
final class SmsapiTransportFactory extends AbstractTransportFactory
{
    public function create(Dsn $dsn): SmsapiTransport
    {
        $scheme = $dsn->getScheme();

        if ('smsapi' !== $scheme) {
            t


 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\Notifier\Bridge\Zulip\Tests;

use Symfony\Component\HttpClient\MockHttpClient;
use Symfony\Component\Notifier\Bridge\Zulip\ZulipTransport;
use Symfony\Component\Notifier\Message\ChatMessage;
use Symfony\Component\Notifier\Message\SmsMessage;
use Symfony\Comp

ic function createTransport(?HttpClientInterface $client = null): ZulipTransport
    {
        return (new ZulipTransport('testEmail', 'testToken', 'testChannel', $client ?? new MockHttpClient()))->setHost('test.host');
    }

    public static function to

onent\Notifier\Test\TransportTestCase;
use Symfony\Component\Notifier\Tests\Transport\DummyMessage;
use Symfony\Contracts\HttpClient\HttpClientInterface;

final class ZulipTransportTest extends TransportTestCase
{
    public stat


 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\Notifier\Bridge\Smsense\Tests;

use Symfony\Component\Notifier\Bridge\Smsense\SmsenseTransportFactory;
use Symfony\Component\Notifier\Test\AbstractTransportFactoryTestCase;
use Symfony\Component\Notifier\Test\IncompleteDsnTestTrait;

class SmsenseTransportFa

ion createProvider(): iterable
    {
        yield [
            'smsense://host.test?from=Symfony',
            'smsense://api_token@host.test?from=Symfony',
        ];
    }

    public static function supportsProvider(): iterable
    {
        yield [tr

ctoryTest extends AbstractTransportFactoryTestCase
{
    use IncompleteDsnTestTrait;

    public function createFactory(): SmsenseTransportFactory
    {
        return new SmsenseTransportFactory();
    }

    public static funct


 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Notifier\Bridge\SpotHit;

use Symfony\Component\Notifier\Exception\TransportException;
use Symfony\Component\Notifier\Exception\UnsupportedMessageTypeException;
use Symfony\Component\Notifier\Message\MessageInterface;
use Symfony\Component\Notifier\Message\SentMessage;
use Symfony\Component\Notifier\Message\SmsMessage;
use Symfony\Component\Notif

erface;
use Symfony\Contracts\HttpClient\Exception\HttpExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
use Symfony\Contracts\HttpClient\Excep

ier\Transport\AbstractTransport;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\DecodingExceptionInt


 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\Notifier\Bridge\Smsmode;

use Symfony\Component\Notifier\Exception\UnsupportedSchemeException;
use Symfony\Component\Notifier\Transport\AbstractTransportFactory;
use Symfony\Component\Notifier\Transport\Dsn;

/**
 * @author gnito-org <https://github.com/gnit

        if (self::TRANSPORT_SCHEME !== $scheme) {
            throw new UnsupportedSchemeException($dsn, self::TRANSPORT_SCHEME, $this->getSupportedSchemes());
        }

        $apiKey = $this->getUser($dsn);
        $from = $dsn->getRequiredOption('fro

o-org>
 */
final class SmsmodeTransportFactory extends AbstractTransportFactory
{
    private const TRANSPORT_SCHEME = 'smsmode';

    public function create(Dsn $dsn): SmsmodeTransport
    {
        $scheme = $dsn->getScheme();


hp

/*
 * 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\Notifier\Test;

use PHPUnit\Framework\Attributes\DataProvider;
use Symfony\Component\Notifier\Exception\IncompleteDsnException;
use Symfony\Component\Notifier\Transport\Dsn;

trait IncompleteDsnTestTrait
{
    /**
     * @return iterable<array{0: st

estIncompleteDsnException(string $dsn, ?string $message = null)
    {
        $factory = $this->createFactory();

        $dsn = new Dsn($dsn);

        $this->expectException(IncompleteDsnException::class);
        if (null !== $message) {
            $th

ring, 1?: string|null}>
     */
    abstract public static function incompleteDsnProvider(): iterable;

    /**
     * @dataProvider incompleteDsnProvider
     */
    #[DataProvider('incompleteDsnProvider')]
    public function t


he 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\Notifier\Test\Constraint;

use PHPUnit\Framework\Constraint\Constraint;
use Symfony\Component\Notifier\Event\MessageEvent;

/**
 * @author Smaïne Milianni <smaine.milianni@gmail.com>
 */
final class NotificationIsQueued extends Constraint
{
    public function toString(): string

 * @param MessageEvent $event
     */
    protected function matches($event): bool
    {
        return $event->isQueued();
    }

    /**
     * @param MessageEvent $event
     */
    protected function failureDescription($event): string
    {
        ret

   {
        return 'is queued';
    }

    /**


 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\Notifier\Bridge\TurboSms\Tests;

use Symfony\Component\Notifier\Bridge\TurboSms\TurboSmsTransportFactory;
use Symfony\Component\Notifier\Test\AbstractTransportFactoryTestCase;
use Symfony\Component\Notifier\Test\IncompleteDsnTestTrait;
use Symfony\Component\Notifier\Test

urboSmsTransportFactory
    {
        return new TurboSmsTransportFactory();
    }

    public static function createProvider(): iterable
    {
        yield [
            'turbosms://host.test?from=acme',
            'turbosms://accountSid:authToken@host.

\MissingRequiredOptionTestTrait;

final class TurboSmsTransportFactoryTest extends AbstractTransportFactoryTestCase
{
    use IncompleteDsnTestTrait;
    use MissingRequiredOptionTestTrait;

    public function createFactory(): T


ge.
 *
 * (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\Notifier\Bridge\Smsense;

use Symfony\Component\Notifier\Exception\TransportException;
use Symfony\Component\Notifier\Exception\UnsupportedMessageTypeException;
use Symfony\Component\Notifier\Message\MessageInterface;
use Symfony\Component\Notifier\Message\SentMessage;
use Symfony\Component\Notif

ny\Contracts\HttpClient\HttpClientInterface;

/**
 * @author Valentin Barbu <jimiero@gmail.com>
 */
final class SmsenseTransport extends AbstractTransport
{
    protected const HOST = 'rest.smsense.com';

    public function __construct(
        #[\Sensiti

ier\Message\SmsMessage;
use Symfony\Component\Notifier\Transport\AbstractTransport;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
use Symfo


 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Notifier\Bridge\Smsmode;

use Symfony\Component\Notifier\Exception\InvalidArgumentException;
use Symfony\Component\Notifier\Exception\TransportException;
use Symfony\Component\Notifier\Exception\UnsupportedMessageTypeException;
use Symfony\Component\Notifier\Message\MessageInterface;
use Symfony\Component\Notifier\Message\SentMessage;
use Symfony

rface;
use Symfony\Contracts\HttpClient\HttpClientInterface;

/**
 * @author gnito-org <https://github.com/gnito-org>
 */
final class SmsmodeTransport extends AbstractTransport
{
    protected const HOST = 'rest.smsmode.com';

    public function __constru

\Component\Notifier\Message\SmsMessage;
use Symfony\Component\Notifier\Transport\AbstractTransport;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInte


/*
 * 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\Notifier\Test;

use PHPUnit\Framework\Attributes\DataProvider;
use Symfony\Component\Notifier\Exception\MissingRequiredOptionException;
use Symfony\Component\Notifier\Transport\Dsn;

trait MissingRequiredOptionTestTrait
{
    /**
     * @return iterabl

tionProvider')]
    public function testMissingRequiredOptionException(string $dsn, ?string $message = null)
    {
        $factory = $this->createFactory();

        $dsn = new Dsn($dsn);

        $this->expectException(MissingRequiredOptionException::cla

e<array{0: string, 1?: string|null}>
     */
    abstract public static function missingRequiredOptionProvider(): iterable;

    /**
     * @dataProvider missingRequiredOptionProvider
     */
    #[DataProvider('missingRequiredOp


hp

/*
 * 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\Notifier\Bridge\RingCentral\Tests;

use PHPUnit\Framework\TestCase;
use Symfony\Component\Notifier\Bridge\RingCentral\RingCentralOptions;

class RingCentralOptionsTest extends TestCase
{
    public function testRingCentralOptions()
    {
        $ri

ry' => [
                'id' => 'test_country_id',
                'isoCode' => 'test_country_iso_code',
                'name' => 'test_country_name',
                'uri' => 'test_country_uri',
                'callingCode' => 'test_country_calling_cod

ngCentralOptions = (new RingCentralOptions())
            ->country('test_country_id', 'test_country_iso_code', 'test_country_name', 'test_country_uri', 'test_country_calling_code');

        self::assertSame([
            'count


 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Notifier\Bridge\SpotHit\Tests;

use PHPUnit\Framework\Attributes\DataProvider;
use Symfony\Component\HttpClient\MockHttpClient;
use Symfony\Component\HttpClient\Response\JsonMockResponse;
use Symfony\Component\Notifier\Bridge\SpotHit\SpotHitTransport;
use Symfony\Component\Notifier\Message\ChatMessage;
use Symfony\Component\Notifier\Message\SmsMe

estCase
{
    public static function createTransport(?HttpClientInterface $client = null): SpotHitTransport
    {
        return (new SpotHitTransport('api_token', 'MyCompany', $client ?? new MockHttpClient()))->setHost('host.test');
    }

    public stat

ssage;
use Symfony\Component\Notifier\Test\TransportTestCase;
use Symfony\Component\Notifier\Tests\Transport\DummyMessage;
use Symfony\Contracts\HttpClient\HttpClientInterface;

final class SpotHitTransportTest extends TransportT


 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Notifier\Bridge\Smsmode\Tests;

use PHPUnit\Framework\Attributes\DataProvider;
use Symfony\Component\HttpClient\MockHttpClient;
use Symfony\Component\HttpClient\Response\MockResponse;
use Symfony\Component\Notifier\Bridge\Smsmode\SmsmodeOptions;
use Symfony\Component\Notifier\Bridge\Smsmode\SmsmodeTransport;
use Symfony\Component\Notifier\Excepti

port\DummyMessage;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use Symfony\Contracts\HttpClient\ResponseInterface;

final class SmsmodeTransportTest extends TransportTestCase
{
    public static function createTransport(?HttpClientInterface $clie

on\InvalidArgumentException;
use Symfony\Component\Notifier\Message\ChatMessage;
use Symfony\Component\Notifier\Message\SmsMessage;
use Symfony\Component\Notifier\Test\TransportTestCase;
use Symfony\Component\Notifier\Tests\Trans


* 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\Attribute;

use Symfony\Component\Serializer\Exception\InvalidArgumentException;

/**
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY)]
class MaxDepth
{
    /**
     * @param i

    public function __construct(
        public readonly int $maxDepth,
    ) {
        if ($maxDepth <= 0) {
            throw new InvalidArgumentException(\sprintf('Parameter given to "%s" must be a positive integer.', static::class));
        }
    }
}

nt $maxDepth The maximum serialization depth
     */


ge.
 *
 * (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>
 */
final class CustomNormalizer implements NormalizerInterface, DenormalizerInterface, SerializerAwareInte

leInterface::class => true,
        ];
    }

    public function normalize(mixed $data, ?string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null
    {
        return $data->normalize($this->serializer, $format, $context)

rface
{
    use ObjectToPopulateTrait;
    use SerializerAwareTrait;

    public function getSupportedTypes(?string $format): array
    {
        return [
            NormalizableInterface::class => true,
            Denormalizab


buted with this source code.
 */

namespace Symfony\Component\Serializer\Normalizer;

use Symfony\Component\HttpFoundation\File\File;
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évi

rue,
        File::class => true,
    ];

    private readonly ?MimeTypeGuesserInterface $mimeTypeGuesser;

    public function __construct(?MimeTypeGuesserInterface $mimeTypeGuesser = null)
    {
        if (!$mimeTypeGuesser && class_exists(MimeTypes::cl

n Dunglas <dunglas@gmail.com>
 */
final class DataUriNormalizer implements NormalizerInterface, DenormalizerInterface
{
    private const SUPPORTED_TYPES = [
        \SplFileInfo::class => true,
        \SplFileObject::class => t


 *
 * 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 instance of {@see \DateInterval} to an interval string.
 * Denormalizes an interval string to an instance of {@see \DateInterval}.
 *
 * @author Jérôme Parment

T_KEY => '%rP%yY%mM%dDT%hH%iM%sS',
    ];

    public function __construct(array $defaultContext = [])
    {
        $this->defaultContext = array_merge($this->defaultContext, $defaultContext);
    }

    public function getSupportedTypes(?string $format):

ier <jerome@prmntr.me>
 */
final class DateIntervalNormalizer implements NormalizerInterface, DenormalizerInterface
{
    public const FORMAT_KEY = 'dateinterval_format';

    private array $defaultContext = [
        self::FORMA


buted 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>
 */
final class DateTimeNormalizer implements Norm

tetime_force_timezone';

    private array $defaultContext = [
        self::FORMAT_KEY => \DateTimeInterface::RFC3339,
        self::TIMEZONE_KEY => null,
        self::CAST_KEY => null,
        self::FORCE_TIMEZONE_KEY => false,
    ];

    private const

alizerInterface, DenormalizerInterface
{
    public const FORMAT_KEY = 'datetime_format';
    public const TIMEZONE_KEY = 'datetime_timezone';
    public const CAST_KEY = 'datetime_cast';
    public const FORCE_TIMEZONE_KEY = 'da


ge.
 *
 * (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>
 */
fi

  }

    /**
     * @throws InvalidArgumentException
     */
    public function normalize(mixed $data, ?string $format = null, array $context = []): string
    {
        if (!$data instanceof \DateTimeZone) {
            throw new InvalidArgumentException

nal class DateTimeZoneNormalizer implements NormalizerInterface, DenormalizerInterface
{
    public function getSupportedTypes(?string $format): array
    {
        return [
            \DateTimeZone::class => true,
        ];


 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 J

d denormalize
     * recursively all child objects of the implementer.
     *
     * @param DenormalizerInterface         $denormalizer The denormalizer is given so that you
     *                                                    can use it to denormaliz

ordi 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 shoul


 *
 * 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\LogicExceptio

*
     * Whether to collect all denormalization errors or to stop at first error.
     */
    public const COLLECT_DENORMALIZATION_ERRORS = 'collect_denormalization_errors';

    /**
     * Whether to collect all extra attributes errors or to stop at first

n;
use Symfony\Component\Serializer\Exception\RuntimeException;
use Symfony\Component\Serializer\Exception\UnexpectedValueException;

/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
interface DenormalizerInterface
{
    /*


ge.
 *
 * (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\Form\FormInterface;

/**
 * Normalizes invalid Form instances.
 */
final class FormErrorNormalizer implements NormalizerInterface
{
    public const TITLE = 'title';
    public const TYPE = 'type';
    public const CODE = 'status_code';

    public fu

//symfony.com/errors/form',
            'code' => $context[self::CODE] ?? null,
            'errors' => $this->convertFormErrorsToArray($data),
        ];

        if (0 !== \count($data->all())) {
            $error['children'] = $this->convertFormChildre

nction normalize(mixed $data, ?string $format = null, array $context = []): array
    {
        $error = [
            'title' => $context[self::TITLE] ?? 'Validation Failed',
            'type' => $context[self::TYPE] ?? 'https:


buted with this source code.
 */

namespace Symfony\Component\Serializer\Normalizer;

use Symfony\Component\PropertyAccess\Exception\UninitializedPropertyException;
use Symfony\Component\Serializer\Annotation\Ignore as LegacyIgnore;
use Symfony\Component\Serializer\Attribute\Ignore;

/**
 * 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

onstructor 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

 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 c


ge.
 *
 * (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>
 */
final class JsonSeri

data, $context)) {
            return $this->handleCircularReference($data, $format, $context);
        }

        if (!$data instanceof \JsonSerializable) {
            throw new InvalidArgumentException(\sprintf('The object must implement "%s".', \JsonSe

alizableNormalizer extends AbstractNormalizer
{
    public function normalize(mixed $data, ?string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null
    {
        if ($this->isCircularReference($


 *
 * 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\Mime\Address;
use Symfony\Component\Mime\Header\HeaderInterface;
use Symfony\Component\Mime\Header\Headers;
use Symfony\Component\Mime\Header\UnstructuredHeader;
use Symfony\Component\Mime\Message;
use Symfony\Component\Mime\Part\AbstractPart;
use Symfony\Component\Mime\RawMessage;
use Symfony\Compone

yNormalizer instance for normalization
 * of all data objects composing a Message.
 *
 * Emails using resources for any parts are not serializable.
 */
final class MimeMessageNormalizer implements NormalizerInterface, DenormalizerInterface, SerializerAware

nt\Serializer\Exception\LogicException;
use Symfony\Component\Serializer\SerializerAwareInterface;
use Symfony\Component\Serializer\SerializerInterface;

/**
 * Normalize Mime message classes.
 *
 * It forces the use of a Propert


 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.
 *
 * @

ormalize
     * recursively all child objects of the implementer.
     *
     * @param NormalizerInterface  $normalizer The normalizer is given so that you
     *                                         can use it to normalize objects contained within this

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 n


ge.
 *
 * (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;

/**
 * @au

ull          $format  Format the normalization result will be encoded as
     * @param array<string, mixed> $context Context options for the normalizer
     *
     * @return mixed[]|string|int|float|bool|\ArrayObject<array-key, mixed>|null \ArrayObject is

thor Jordi Boggiano <j.boggiano@seld.be>
 */
interface NormalizerInterface
{
    /**
     * Normalizes data into a set of arrays/scalars.
     *
     * @param mixed                $data    Data to normalize
     * @param string|n


ge.
 *
 * (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 BcMath\Number;
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
use Symfony\Component\Serializer\Exception\NotNormalizableValueException;

/**
 * Normalizes {@see Number} and {@see \GMP} to a string.
 */
final class NumberNormalizer implements Norma

n normalize(mixed $data, ?string $format = null, array $context = []): string
    {
        if (!$data instanceof Number && !$data instanceof \GMP) {
            throw new InvalidArgumentException(\sprintf('The data must be an instance of "%s" or "%s".', N

lizerInterface, DenormalizerInterface
{
    public function getSupportedTypes(?string $format): array
    {
        return [
            Number::class => true,
            \GMP::class => true,
        ];
    }

    public functio


buted with this source code.
 */

namespace Symfony\Component\Serializer\Normalizer;

use Symfony\Component\PropertyAccess\Exception\InvalidArgumentException as PropertyAccessInvalidArgumentException;
use Symfony\Component\PropertyAccess\Exception\InvalidTypeException;
use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException;
use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
use Symfony\Component\PropertyInfo\Extractor\Reflecti

izer\Attribute\Ignore;
use Symfony\Component\Serializer\Exception\LogicException;
use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
use Symfony\Component\Serializer\Mapping\ClassDiscriminatorResolverInterface;
use Symfony\Component\

onExtractor;
use Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface;
use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
use Symfony\Component\PropertyInfo\PropertyWriteInfo;
use Symfony\Component\Serial


?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 objec

ToPopulate(string $class, array $context, ?string $key = null): ?object
    {
        $key ??= AbstractNormalizer::OBJECT_TO_POPULATE;

        if (isset($context[$key]) && \is_object($context[$key]) && $context[$key] instanceof $class) {
            retur

t should be
     * @param string|null $key   They in which to look for the object to populate.
     *                           Keeps backwards compatibility with `AbstractNormalizer`.
     */
    protected function extractObject


buted with this source code.
 */

namespace Symfony\Component\Serializer\Normalizer;

use Symfony\Component\ErrorHandler\Exception\FlattenException;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Symfony\Component\Messenger\Exception\ValidationFailedException as MessageValidationFailedException;
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
use Symfony\Component\Serializer\Exception\PartialDenormalizationException;
use Symfony\Component\Serializer\SerializerAwa

o 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, SerializerAwareInt

reInterface;
use Symfony\Component\Serializer\SerializerAwareTrait;
use Symfony\Component\Validator\Exception\ValidationFailedException;
use Symfony\Contracts\Translation\TranslatorInterface;

/**
 * Normalizes errors according t


rtyTypeExtractorInterface;
use Symfony\Component\Serializer\Exception\LogicException;
use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
use Symfony\Component\Serializer\Mapping\ClassDiscriminatorResolverInterface;
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;

/**
 * Converts between objects and arrays by mapping properties.
 *
 * The normalization process looks for all the object

ass 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

'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 cl


 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;
use Symfony\Contracts\Translation\TranslatableInterface;
use Symfony\Contracts\Translation\TranslatorInt

LE_KEY => null,
    ];

    public function __construct(
        private readonly TranslatorInterface $translator,
        array $defaultContext = [],
    ) {
        $this->defaultContext = array_merge($this->defaultContext, $defaultContext);
    }

    /

erface;

final class TranslatableNormalizer implements NormalizerInterface
{
    public const NORMALIZATION_LOCALE_KEY = 'translatable_normalization_locale';

    private array $defaultContext = [
        self::NORMALIZATION_LOCA


 *
 * 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\LogicException;
use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
use Symfony\Component\Uid\AbstractUid;

final class UidNormalizer implements NormalizerInterface, DenormalizerInterface
{
    public const NORMALIZATION_FORMAT_KEY = 'uid_normalization_format

'rfc4122';
    public const NORMALIZATION_FORMAT_RFC9562 = self::NORMALIZATION_FORMAT_RFC4122; // RFC 9562 obsoleted RFC 4122 but the format is the same

    public const NORMALIZATION_FORMATS = [
        self::NORMALIZATION_FORMAT_CANONICAL,
        self:

';

    public const NORMALIZATION_FORMAT_CANONICAL = 'canonical';
    public const NORMALIZATION_FORMAT_BASE58 = 'base58';
    public const NORMALIZATION_FORMAT_BASE32 = 'base32';
    public const NORMALIZATION_FORMAT_RFC4122 =


ge.
 *
 * (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\PropertyAccess;
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
use Symfony\Component\Serializer\Exception\LogicException;
use Symfony\Component\Serializer\SerializerAwareInterface;
use Symfony\Component\Serializer\Seria

TH = 'unwrap_path';

    private readonly PropertyAccessorInterface $propertyAccessor;

    public function __construct(?PropertyAccessorInterface $propertyAccessor = null)
    {
        $this->propertyAccessor = $propertyAccessor ?? PropertyAccess::create

lizerAwareTrait;

/**
 * @author Eduard Bulava <bulavaeduard@gmail.com>
 */
final class UnwrappingDenormalizer implements DenormalizerInterface, SerializerAwareInterface
{
    use SerializerAwareTrait;

    public const UNWRAP_PA


 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer\Command;

use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\Dumper;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\

 command to debug Serializer information.
 *
 * @author Loïc Frémont <lc.fremont@gmail.com>
 */
#[AsCommand(name: 'debug:serializer', description: 'Display serialization information for classes')]
class DebugCommand extends Command
{
    public function __

OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Serializer\Mapping\ClassMetadataInterface;
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;

/**
 * A console


buted with this source code.
 */

namespace Symfony\Component\Serializer\Tests;

use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;

class DeserializeNestedArrayOfObjectsTest extends TestCase
{

aProvider('provider')]
    public function testPropertyPhpDoc($class)
    {
        $json = <<<EOF
            {
                "animals": [
                    {"name": "Bug"}
                ]
            }
            EOF;
        $serializer = new Ser

public static function provider()
    {
        return [
            // from property PhpDoc
            [Zoo::class],
            // from argument constructor PhpDoc
            [ZooImmutable::class],
        ];
    }

    #[Dat


dChild;
use Symfony\Component\Serializer\Tests\Fixtures\Attributes\GroupClassDummy;
use Symfony\Component\Serializer\Tests\Fixtures\Attributes\SerializedNameAttributeDummy;
use Symfony\Component\Serializer\Tests\Fixtures\DenormalizableDummy;
use Symfony\Component\Serializer\Tests\Fixtures\DummyFirstChildQuux;
use Symfony\Component\Serializer\Tests\Fixtures\DummyMessageInterface;
use Symfony\Component\Serializer\Tests\Fixtures\DummyMessageNumberOne;
use Symfony\Component\Serializer\Tests\Fixtures\DummyMessag

;
use Symfony\Component\Serializer\Tests\Fixtures\DummyObjectWithEnumProperty;
use Symfony\Component\Serializer\Tests\Fixtures\DummyWithObjectOrNull;
use Symfony\Component\Serializer\Tests\Fixtures\DummyWithUnion;
use Symfony\Component\Serializer\Tests\Fix

eNumberThree;
use Symfony\Component\Serializer\Tests\Fixtures\DummyMessageNumberTwo;
use Symfony\Component\Serializer\Tests\Fixtures\DummyNullableInt;
use Symfony\Component\Serializer\Tests\Fixtures\DummyObjectWithEnumConstructor


 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\Tests\Context;

use PHPUnit\Framework\TestCase;
use Symfony\Component\Serializer\Context\ContextBuilderInterface;
use Symfony\Component\Serializer\Context\ContextBuilderTrait;

/**
 * @author Mathias Arlaud <mathias.arlaud@gmail.com>
 */
class Con

textBuilder->withContext(['foo' => 'bar'])->toArray();

        $this->assertSame(['foo' => 'bar'], $context);

        $withContextBuilderObject = $contextBuilder->withContext($contextBuilder->withContext(['foo' => 'bar']))->toArray();

        $this->ass

textBuilderTraitTest extends TestCase
{
    public function testWithContext()
    {
        $contextBuilder = new class implements ContextBuilderInterface {
            use ContextBuilderTrait;
        };

        $context = $con


ge.
 *
 * (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\Tests\Context;

use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Serializer\Context\SerializerContextBuilder;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use Symfony\Component\Serializer\Serializer;

/**
 * @aut

er = new SerializerContextBuilder();
    }

    /**
     * @param array<string, mixed> $values
     */
    #[DataProvider('withersDataProvider')]
    public function testWithers(array $values)
    {
        $context = $this->contextBuilder
            ->wi

hor Mathias Arlaud <mathias.arlaud@gmail.com>
 */
class SerializerContextBuilderTest extends TestCase
{
    private SerializerContextBuilder $contextBuilder;

    protected function setUp(): void
    {
        $this->contextBuild


 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer\Tests\Context\Normalizer;

use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Serializer\Context\Normalizer\AbstractNormalizerContextBuilder;
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;

/**
 * @aut

is->contextBuilder = new class extends AbstractNormalizerContextBuilder {};
    }

    /**
     * @param array<string, mixed> $values
     */
    #[DataProvider('withersDataProvider')]
    public function testWithers(array $values)
    {
        $context =

hor Mathias Arlaud <mathias.arlaud@gmail.com>
 */
class AbstractNormalizerContextBuilderTest extends TestCase
{
    private AbstractNormalizerContextBuilder $contextBuilder;

    protected function setUp(): void
    {
        $th


 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer\Tests\Context\Normalizer;

use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Serializer\Context\Normalizer\AbstractObjectNormalizerContextBuilder;
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer;

: void
    {
        $this->contextBuilder = new class extends AbstractObjectNormalizerContextBuilder {};
    }

    /**
     * @param array<string, mixed> $values
     */
    #[DataProvider('withersDataProvider')]
    public function testWithers(array $va

/**
 * @author Mathias Arlaud <mathias.arlaud@gmail.com>
 */
class AbstractObjectNormalizerContextBuilderTest extends TestCase
{
    private AbstractObjectNormalizerContextBuilder $contextBuilder;

    protected function setUp()


/*
 * 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\Tests\Context\Normalizer;

use PHPUnit\Framework\TestCase;
use Symfony\Component\Serializer\Context\Normalizer\BackedEnumNormalizerContextBuilder;
use Symfony\Component\Serializer\Normalizer\BackedEnumNormalizer;

class BackedEnumNormalizerC

 public function testWithers()
    {
        $context = $this->contextBuilder->withAllowInvalidValues(true)->toArray();
        self::assertSame([BackedEnumNormalizer::ALLOW_INVALID_VALUES => true], $context);

        $context = $this->contextBuilder->wit

ontextBuilderTest extends TestCase
{
    private BackedEnumNormalizerContextBuilder $contextBuilder;

    protected function setUp(): void
    {
        $this->contextBuilder = new BackedEnumNormalizerContextBuilder();
    }


ge.
 *
 * (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\Tests\Context\Normalizer;

use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Serializer\Context\Normalizer\ConstraintViolationListNormalizerContextBuilder;
use Symfony\Component\Serializer\Normalizer\ConstraintViolationListNormalizer;

d function setUp(): void
    {
        $this->contextBuilder = new ConstraintViolationListNormalizerContextBuilder();
    }

    /**
     * @param array<string, mixed> $values
     */
    #[DataProvider('withersDataProvider')]
    public function testWithe

/**
 * @author Mathias Arlaud <mathias.arlaud@gmail.com>
 */
class ConstraintViolationListNormalizerContextBuilderTest extends TestCase
{
    private ConstraintViolationListNormalizerContextBuilder $contextBuilder;

    protecte


 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\Tests\Context\Normalizer;

use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Serializer\Context\Normalizer\DateIntervalNormalizerContextBuilder;
use Symfony\Component\Serializer\Normalizer\DateIntervalNormaliz

: void
    {
        $this->contextBuilder = new DateIntervalNormalizerContextBuilder();
    }

    /**
     * @param array<string, mixed> $values
     */
    #[DataProvider('withersDataProvider')]
    public function testWithers(array $values)
    {

er;

/**
 * @author Mathias Arlaud <mathias.arlaud@gmail.com>
 */
class DateIntervalNormalizerContextBuilderTest extends TestCase
{
    private DateIntervalNormalizerContextBuilder $contextBuilder;

    protected function setUp()


ge.
 *
 * (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\Tests\Context\Normalizer;

use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Serializer\Context\Normalizer\DateTimeNormalizerContextBuilder;
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
use Symfony\Component\Ser

 protected function setUp(): void
    {
        $this->contextBuilder = new DateTimeNormalizerContextBuilder();
    }

    /**
     * @param array<string, mixed> $values
     */
    #[DataProvider('withersDataProvider')]
    public function testWithers(arr

ializer\Normalizer\DateTimeNormalizer;

/**
 * @author Mathias Arlaud <mathias.arlaud@gmail.com>
 */
class DateTimeNormalizerContextBuilderTest extends TestCase
{
    private DateTimeNormalizerContextBuilder $contextBuilder;


ttpKernel\DataCollector\DataCollector;
use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface;
use Symfony\Component\Serializer\Debug\TraceableSerializer;
use Symfony\Component\VarDumper\Cloner\Data;

/**
 * @author Mathias Arlaud <mathias.arlaud@gmail.com>
 *
 * @final
 */
class SerializerDataCollector extends DataCollector implements LateDataCollectorInterface
{
    private const DATA_TEMPLATE = [
        'serialize' => [],
        'deserialize' => [],
        'normalize' => [],

et($this->dataGroupedByName);
        $this->collected = [];
    }

    public function collect(Request $request, Response $response, ?\Throwable $exception = null): void
    {
        // Everything is collected during the request, and formatted on kernel

 'denormalize' => [],
        'encode' => [],
        'decode' => [],
    ];

    private array $dataGroupedByName;
    private array $collected = [];

    public function reset(): void
    {
        $this->data = [];
        uns


ge.
 *
 * (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
{
    private array $mappingForMappedObjectCache =

 ($this->classMetadataFactory->hasMetadataFor($class)) {
            return $this->classMetadataFactory->getMetadataFor($class)->getClassDiscriminatorMapping();
        }

        return null;
    }

    public function getMappingForMappedObject(object|str

[];

    public function __construct(
        private readonly ClassMetadataFactoryInterface $classMetadataFactory,
    ) {
    }

    public function getMappingForClass(string $class): ?ClassDiscriminatorMapping
    {
        if


ge.
 *
 * (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 Kévin Dunglas <dunglas@gmail.com>
 *
 * @final
 */
class ClassMetadata implements ClassMetadataInterface
{
    private string $name;

    /**
     * @var AttributeMetadataInterface[]
     */
    private array $attributesMetadata = [];

    private ?\ReflectionC

name = $class;
        $this->classDiscriminatorMapping = $classDiscriminatorMapping;
    }

    public function getName(): string
    {
        return $this->name;
    }

    public function addAttributeMetadata(AttributeMetadataInterface $attributeMetada

lass $reflClass = null;
    private ?ClassDiscriminatorMapping $classDiscriminatorMapping = null;

    public function __construct(string $class, ?ClassDiscriminatorMapping $classDiscriminatorMapping = null)
    {
        $this->


 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

(): string;

    /**
     * Adds an {@link AttributeMetadataInterface}.
     */
    public function addAttributeMetadata(AttributeMetadataInterface $attributeMetadata): void;

    /**
     * Gets the list of {@link AttributeMetadataInterface}.
     *

 its name.
 *
 * @psalm-inheritors ClassMetadata
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
interface ClassMetadataInterface
{
    /**
     * Returns the name of the backing PHP class.
     */
    public function getName


e Symfony\Component\Serializer\Attribute\Groups;
use Symfony\Component\Serializer\Attribute\Ignore;
use Symfony\Component\Serializer\Attribute\MaxDepth;
use Symfony\Component\Serializer\Attribute\SerializedName;
use Symfony\Component\Serializer\Attribute\SerializedPath;
use Symfony\Component\Serializer\Exception\MappingException;
use Symfony\Component\Serializer\Mapping\AttributeMetadata;
use Symfony\Component\Serializer\Mapping\AttributeMetadataInterface;
use Symfony\Component\Serializer\Mapping\ClassDiscr

dre Daubois <alex.daubois@gmail.com>
 */
class AttributeLoader implements LoaderInterface
{
    use AccessorCollisionResolverTrait;

    private const KNOWN_ATTRIBUTES = [
        DiscriminatorMap::class,
        Groups::class,
        Ignore::class,

iminatorMapping;
use Symfony\Component\Serializer\Mapping\ClassMetadataInterface;

/**
 * Loader for PHP attributes.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 * @author Alexander M. Turek <me@derrabus.de>
 * @author Alexan


?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
{

        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 re

/**
     * @param string $file The mapping file to load
     *
     * @throws MappingException if the mapping file does not exist or is not readable
     */
    public function __construct(
        protected string $file,
    ) {


buted with this source code.
 */

namespace Symfony\Component\Serializer\Mapping\Loader;

use Symfony\Component\PropertyAccess\Exception\InvalidPropertyPathException;
use Symfony\Component\PropertyAccess\PropertyPath;
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 S

array>
     */
    private ?array $classes = null;

    public function loadClassMetadata(ClassMetadataInterface $classMetadata): bool
    {
        if (!$this->classes ??= $this->getClassesFromYaml()) {
            return false;
        }

        if (!is

ymfony\Component\Yaml\Yaml;

/**
 * YAML File Loader.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
class YamlFileLoader extends FileLoader
{
    private ?Parser $yamlParser = null;

    /**
     * @var array<class-string,


 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;
use Symfony\Component\Serializer\Mapping\ClassMetadataInterface;

/**
 * Caches metadata using a PSR-6 implementation.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
class CacheClassMetadataFactory i

donly ClassMetadataFactoryInterface $decorated,
        private readonly CacheItemPoolInterface $cacheItemPool,
    ) {
    }

    public function getMetadataFor(string|object $value): ClassMetadataInterface
    {
        $class = $this->getClass($value);

mplements ClassMetadataFactoryInterface
{
    use ClassResolverTrait;

    /**
     * @var array<string, ClassMetadataInterface>
     */
    private array $loadedClasses = [];

    public function __construct(
        private rea


?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 c

       if (!class_exists($value) && !interface_exists($value, false)) {
                throw new InvalidArgumentException(\sprintf('The class or interface "%s" does not exist.', $value));
            }

            return ltrim($value, '\\');
        }

lass name for a given class or instance.
     *
     * @throws InvalidArgumentException If the class does not exist
     */
    private function getClass(object|string $value): string
    {
        if (\is_string($value)) {


onent\Serializer\NameConverter\NameConverterInterface;
use Symfony\Component\TypeInfo\Exception\LogicException as TypeInfoLogicException;
use Symfony\Component\TypeInfo\Type;
use Symfony\Component\TypeInfo\Type\BuiltinType;
use Symfony\Component\TypeInfo\Type\CollectionType;
use Symfony\Component\TypeInfo\Type\IntersectionType;
use Symfony\Component\TypeInfo\Type\NullableType;
use Symfony\Component\TypeInfo\Type\ObjectType;
use Symfony\Component\TypeInfo\Type\UnionType;
use Symfony\Component\TypeInfo\Type\W

alizer 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_MA

rappingTypeInterface;
use Symfony\Component\TypeInfo\TypeContext\TypeContextFactory;
use Symfony\Component\TypeInfo\TypeIdentifier;
use Symfony\Component\TypeInfo\TypeResolver\ReflectionTypeResolver;

/**
 * Base class for a norm


 *
 * 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 \BackedEnum} enumeration to a string or an integer.
 *
 * @author Alexandre Daubois <alex.daubois@gmail.com>
 */
final class BackedEnumNormalizer implemen

?string $format): array
    {
        return [
            \BackedEnum::class => true,
        ];
    }

    public function normalize(mixed $data, ?string $format = null, array $context = []): int|string
    {
        if (!$data instanceof \BackedEnum) {

ts NormalizerInterface, DenormalizerInterface
{
    /**
     * If true, will denormalize any invalid value into null.
     */
    public const ALLOW_INVALID_VALUES = 'allow_invalid_values';

    public function getSupportedTypes(


buted 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>
 */
final class Constrain

DS = 'payload_fields';

    public function __construct(
        private readonly array $defaultContext = [],
        private readonly ?NameConverterInterface $nameConverter = null,
    ) {
    }

    public function getSupportedTypes(?string $format): arr

tViolationListNormalizer implements NormalizerInterface
{
    public const INSTANCE = 'instance';
    public const STATUS = 'status';
    public const TITLE = 'title';
    public const TYPE = 'type';
    public const PAYLOAD_FIEL


buted with this source code.
 */

namespace Symfony\Component\Serializer\Context\Encoder;

use Symfony\Component\Serializer\Context\ContextBuilderInterface;
use Symfony\Component\Serializer\Context\ContextBuilderTrait;
use Symfony\Component\Serializer\Encoder\XmlEncoder;

/**
 * A helper providing autocompletion for available XmlEncoder options.
 *
 * @author Mathias Arlaud <mathias.arlaud@gmail.com>
 */
final class XmlEncoderContextBuilder implements ContextBuilderInterface
{
    use ContextBuilderTrait;

mlEncoder::AS_COLLECTION, $asCollection);
    }

    /**
     * Configures node types to ignore while decoding.
     *
     * @see https://php.net/dom.constants
     *
     * @param list<int>|null $decoderIgnoredNodeTypes
     */
    public function withDe

    /**
     * Configures whether the decoded result should be considered as a collection
     * or as a single element.
     */
    public function withAsCollection(?bool $asCollection): static
    {
        return $this->with(X


 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\Attribute;

use Symfony\Component\Serializer\Exception\InvalidArgumentException;

/**
 * @author Samuel Roze <samuel.roze@gmail.com>
 */
#[\Attribute(\Attribute::TARGET_CLASS)]
class DiscriminatorMap
{
    /**
     * @param string                      $typePro

defaultType  The fallback value if nothing specified by $typeProperty
     *
     * @throws InvalidArgumentException
     */
    public function __construct(
        public readonly string $typeProperty,
        public readonly array $mapping,
        publ

perty The property holding the type discriminator
     * @param array<string, class-string> $mapping      The mapping between types and classes (i.e. ['admin_user' => AdminUser::class])
     * @param ?string                     $


/*
 * 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\Attribute;

/**
 * Declares that serialization attributes listed on the current class should be added to the given class.
 *
 * Classes that use this attribute should contain only properties and methods that
 * exist on the target class (no

all of them).
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
#[\Attribute(\Attribute::TARGET_CLASS)]
final class ExtendsSerializationFor
{
    /**
     * @param class-string $class
     */
    public function __construct(
        public string $class,


/*
 * 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\Attribute;

use Symfony\Component\PropertyAccess\Exception\InvalidPropertyPathException;
use Symfony\Component\PropertyAccess\PropertyPath;
use Symfony\Component\Serializer\Exception\InvalidArgumentException;

/**
 * @author Tobias Bönner <t

valid PropertyAccess syntax where the value is stored in a normalized representation
     */
    public function __construct(string $serializedPath)
    {
        try {
            $this->serializedPath = new PropertyPath($serializedPath);
        } catch

obi@boenner.family>
 */
#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY)]
class SerializedPath
{
    public readonly PropertyPath $serializedPath;

    /**
     * @param string $serializedPath A path using a


 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
{
    /**
     * @param array<string, string> $typesMapping
     */
    public function __construct(
        private readonly string $typeProperty,
        private

rn -1;
            }

            if (is_a($b, $a, true)) {
                return 1;
            }

            return 0;
        });
    }

    public function getTypeProperty(): string
    {
        return $this->typeProperty;
    }

    public function

 array $typesMapping = [],
        private readonly ?string $defaultType = null,
    ) {
        uasort($this->typesMapping, static function (string $a, string $b): int {
            if (is_a($a, $b, true)) {
                retu


 *
 * 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\Attribute\Ignore;

/**
 * Provides methods to detect accessor name collisions during serialization.
 *
 * @internal
 */
trait AccessorCollisionResolverTrait
{
    private function getAttributeNameFromAccessor(\ReflectionClass $class, \ReflectionMethod $method, bool $andMutator): ?string

l,
            'h' => str_starts_with($methodName, 'has') ? 3 : null,
            'c' => str_starts_with($methodName, 'can') ? 3 : null,
            'i' => str_starts_with($methodName, 'is') ? 2 : null,
            default => null,
        };

        // c

    {
        $methodName = $method->name;

        $i = match ($methodName[0]) {
            's' => $andMutator && str_starts_with($methodName, 'set') ? 3 : null,
            'g' => str_starts_with($methodName, 'get') ? 3 : nul


buted with this source code.
 */

namespace Symfony\Component\Serializer\Mapping\Loader;

use Symfony\Component\Config\Util\XmlUtils;
use Symfony\Component\PropertyAccess\Exception\InvalidPropertyPathException;
use Symfony\Component\PropertyAccess\PropertyPath;
use Symfony\Component\Serializer\Exception\MappingException;
use Symfony\Component\Serializer\Mapping\AttributeMetadata;
use Symfony\Component\Serializer\Mapping\ClassDiscriminatorMapping;
use Symfony\Component\Serializer\Mapping\ClassMetadataInterfa

ing, \SimpleXMLElement>|null
     */
    private ?array $classes = null;

    public function loadClassMetadata(ClassMetadataInterface $classMetadata): bool
    {
        if (!$this->classes ??= $this->getClassesFromXml()) {
            return false;

ce;

/**
 * Loads XML mapping files.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
class XmlFileLoader extends FileLoader
{
    /**
     * An array of {@class \SimpleXMLElement} instances.
     *
     * @var array<class-str


 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>
 */
interfa

ith 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 wa

ce 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 w


face;
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
{
    use ObjectToPopulateTrait;
    use

ct 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 = 'c

 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 obje


 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\Context\Encoder;

use Symfony\Component\Serializer\Context\ContextBuilderInterface;
use Symfony\Component\Serializer\Context\ContextBuilderTrait;
use Symfony\Component\Serializer\Encoder\YamlEncoder;
use Symfony\Component\Yaml\Yaml;

/**
 * A helper providing

or Mathias Arlaud <mathias.arlaud@gmail.com>
 */
final class YamlEncoderContextBuilder implements ContextBuilderInterface
{
    use ContextBuilderTrait;

    /**
     * Configures the threshold to switch to inline YAML.
     */
    public function withInli

autocompletion for available YamlEncoder options.
 *
 * Note that the "indentation" setting is not offered in this builder because
 * it can only be set during the construction of the YamlEncoder, but not per
 * call.
 *
 * @auth


 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\Attribute;

use Symfony\Component\Serializer\Exception\InvalidArgumentException;

/**
 * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
 */
#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribut

ed> $normalizationContext   The context to use when serializing
     * @param array<string, mixed> $denormalizationContext The context to use when deserializing
     * @param string|string[]      $groups                 The groups to use when serializing o

e::IS_REPEATABLE)]
class Context
{
    public readonly array $groups;

    /**
     * @param array<string, mixed> $context                The common context to use when serializing or deserializing
     * @param array<string, mix


ge.
 *
 * (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\PropertyAccess\PropertyPath;

/**
 * Stores metadata needed for serializing and deserializing attributes.
 *
 * Primarily, the metadata stores serialization groups.
 *
 * @psalm-inheritors AttributeMetadata
 *
 * @author Kévin Dunglas <dunglas@gmail.com>

g $group): void;

    /**
     * Gets groups of this attribute.
     *
     * @return string[]
     */
    public function getGroups(): array;

    /**
     * Sets the serialization max depth for this attribute.
     */
    public function setMaxDepth(?int

 */
interface AttributeMetadataInterface
{
    /**
     * Gets the attribute name.
     */
    public function getName(): string;

    /**
     * Adds this attribute to the given group.
     */
    public function addGroup(strin


buted with this source code.
 */

namespace Symfony\Component\Serializer\Mapping;

use Symfony\Component\PropertyAccess\PropertyPath;

/**
 * @author Kévin Dunglas <dunglas@gmail.com>
 *
 * @final
 */
class AttributeMetadata implements AttributeMetadataInterface
{
    private string $name;
    private array $groups = [];
    private ?int $maxDepth = null;
    private ?string $serializedName = null;
    private ?PropertyPath $serializedPath = null;
    private bool $ignore = false;

    /**
     * @var array

    private array $denormalizationContexts = [];

    public function __construct(string $name)
    {
        $this->name = $name;
    }

    public function getName(): string
    {
        return $this->name;
    }

    public function addGroup(string $gr

[] Normalization contexts per group name ("*" applies to all groups)
     */
    private array $normalizationContexts = [];

    /**
     * @var array[] Denormalization contexts per group name ("*" applies to all groups)
     */


 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 L

or Bernhard Schussek <bschussek@gmail.com>
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
class LoaderChain implements LoaderInterface
{
    /**
     * Accepts a list of LoaderInterface instances.
     *
     * @param LoaderInterface[] $loaders An array

oaderInterface to be passed to the
 * constructor. When {@link loadClassMetadata()} is called, the same method is called
 * in all of these loaders, regardless of whether any of them was
 * successful or not.
 *
 * @auth


 *
 * 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\TypeInfo\Type\BuiltinType;
use Symfony\Component\TypeInfo\Type\CollectionType;
use Symfony\C

alizerInterface, DenormalizerAwareInterface
{
    use DenormalizerAwareTrait;

    public function getSupportedTypes(?string $format): array
    {
        return ['object' => null, '*' => false];
    }

    /**
     * @throws NotNormalizableValueException

omponent\TypeInfo\Type\UnionType;
use Symfony\Component\TypeInfo\TypeIdentifier;

/**
 * Denormalizes arrays of objects.
 *
 * @author Alexander M. Turek <me@derrabus.de>
 *
 * @final
 */
class ArrayDenormalizer implements Denorm


 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\Context\Encoder;

use Symfony\Component\Serializer\Context\ContextBuilderInterface;
use Symfony\Component\Serializer\Context\ContextBuilderTrait;
use Symfony\Component\Serializer\Encoder\JsonDecode;
use Symfony\Component\Serializer\Encoder\JsonEncode;

/**
 *

it;

    /**
     * Configures the json_encode flags bitmask.
     *
     * @see https://php.net/json.constants
     *
     * @param positive-int|null $options
     */
    public function withEncodeOptions(?int $options): static
    {
        return $this-

A helper providing autocompletion for available JsonEncoder options.
 *
 * @author Mathias Arlaud <mathias.arlaud@gmail.com>
 */
final class JsonEncoderContextBuilder implements ContextBuilderInterface
{
    use ContextBuilderTra


he 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\Attribute;

use Symfony\Component\Serializer\Exception\InvalidArgumentException;

/**
 * @author Fabien Bourigault <bourigaultfabien@gmail.com>
 */
#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY)]
class SerializedName
{
    /**
     * @param string

 be serialized
     */
    public function __construct(
        public readonly string $serializedName,
    ) {
        if ('' === $serializedName) {
            throw new InvalidArgumentException(\sprintf('Parameter given to "%s" must be a non-empty strin

$serializedName The name of the property as it will


/*
 * 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\Attribute;

use Symfony\Component\Serializer\Exception\InvalidArgumentException;

/**
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY | \Attribute::TARGET_CLASS)]
class Gr

ps)
    {
        $this->groups = (array) $groups;

        if (!$this->groups) {
            throw new InvalidArgumentException(\sprintf('Parameter given to "%s" cannot be empty.', static::class));
        }

        foreach ($this->groups as $group) {

oups
{
    /**
     * @var string[]
     */
    public readonly array $groups;

    /**
     * @param string|string[] $groups The groups to define on the attribute target
     */
    public function __construct(string|array $grou


 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\ClassMetadataInterface;
use Symfony\Component\Serializer\Mapping\Loader\LoaderInterface;

/**
 * Returns a {@link ClassMetadata}.
 *
 * @author K

asses;

    public function __construct(
        private readonly LoaderInterface $loader,
    ) {
    }

    public function getMetadataFor(string|object $value): ClassMetadataInterface
    {
        $class = $this->getClass($value);

        if (isset($t

évin Dunglas <dunglas@gmail.com>
 */
class ClassMetadataFactory implements ClassMetadataFactoryInterface
{
    use ClassResolverTrait;

    /**
     * @var array<string, ClassMetadataInterface>
     */
    private array $loadedCl


e' => 'Foo.php', 'file' => 'src/Foo.php', 'line' => 123];
        $dataCollector->collectSerialize('traceIdOne', 'data', 'format', ['foo' => 'bar'], 1.0, $caller, 'default');
        $dataCollector->collectDeserialize('traceIdTwo', 'data', 'type', 'format', ['foo' => 'bar'], 1.0, $caller, 'default');

        $dataCollector->lateCollect();
        $collectedData = $this->castCollectedData($dataCollector->getData());

        $this->assertSame([[
            'data' => 'data',
            'dataType' => 'strin

ler,
            'name' => 'default',
        ]], $collectedData['serialize']);

        $this->assertSame([[
            'data' => 'data',
            'dataType' => 'string',
            'type' => 'type',
            'format' => 'format',
            'tim

g',
            'type' => null,
            'format' => 'format',
            'time' => 1.0,
            'context' => ['foo' => 'bar'],
            'normalization' => [],
            'encoding' => [],
            'caller' => $cal


 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer\Tests\Context\Encoder;

use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Serializer\Context\Encoder\XmlEncoderContextBuilder;
use Symfony\Component\Serializer\Encoder\XmlEncoder;

/**
 * @author Mathias Arlaud <mathias.arlaud@gmail.com>
 */
class XmlEncoderContextBuilderTest extends T

lic function testWithers(array $values)
    {
        $context = $this->contextBuilder
            ->withAsCollection($values[XmlEncoder::AS_COLLECTION])
            ->withDecoderIgnoredNodeTypes($values[XmlEncoder::DECODER_IGNORED_NODE_TYPES])

estCase
{
    private XmlEncoderContextBuilder $contextBuilder;

    protected function setUp(): void
    {
        $this->contextBuilder = new XmlEncoderContextBuilder();
    }

    #[DataProvider('withersDataProvider')]
    pub


 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\Tests\Fixtures;

use Symfony\Component\Serializer\Normalizer\NormalizerInterface;

class StdClassNormalizer implements NormalizerInterface
{
    public function normalize(mixed $object, ?string $format = null, array $context = []): string
    {

supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool
    {
        return $data instanceof \stdClass;
    }

    public function getSupportedTypes(?string $format): array
    {
        return [
            \stdClass::class

 return 'string_object';
    }

    public function


/*
 * 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\Tests\Fixtures;

class VoidNeverReturnTypeDummy
{
    public string $normalProperty = 'value';

    public function getNormalProperty(): string
    {
        return $this->normalProperty;
    }

    public function getVoidProperty(): void

ception('Never returns');
    }

    public function setValue(): void
    {
        // This looks like a setter but has no parameters, should be ignored as accessor
    }

    public function setNeverValue(): never
    {
        // This looks like a setter

  {
        // This looks like a getter but returns void, should be ignored
    }

    public function getNeverProperty(): never
    {
        // This looks like a getter but returns never, should be ignored
        throw new \Ex


 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\Tests\Fixtures\Attributes;

use Symfony\Component\Serializer\Tests\Fixtures\DummyFirstChildQuux;

class AbstractDummyFirstChild extends AbstractDummy
{
    public $bar;
    public $baz;

    /** @var DummyFirstChildQuux|null */
    public $quux;

    p

    {
        parent::__construct($foo);

        $this->bar = $bar;
    }

    public function getQuux(): ?DummyFirstChildQuux
    {
        return $this->quux;
    }

    public function setQuux(DummyFirstChildQuux $quux): void
    {
        $this->quux

ublic function __construct($foo = null, $bar = null)


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\Tests\Fixtures\Attributes;

use Symfony\Component\Serializer\Tests\Fixtures\DummySecondChildQuux;

class AbstractDummySecondChild extends AbstractDummy
{
    public $baz;

    /** @var DummySecondChildQuux|null */
    public $quux;

    public function __con

t::__construct($foo);

        $this->baz = $baz;
    }

    public function getQuux(): ?DummySecondChildQuux
    {
        return $this->quux;
    }

    public function setQuux(DummySecondChildQuux $quux): void
    {
        $this->quux = $quux;
    }
}

struct($foo = null, $baz = null)
    {
        paren


/*
 * 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\Tests\Fixtures\Attributes;

use Symfony\Component\Serializer\Attribute\Context;

/**
 * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
 */
class ContextDummy extends ContextDummyParent
{
    #[Context(['foo' => 'value', 'bar' =>

nContext: ['format' => 'd/m/Y'],
        denormalizationContext: ['format' => 'm-d-Y H:i'],
        groups: ['a', 'b'],
    )]
    public $bar;

    #[Context(normalizationContext: ['prop' => 'dummy_value'])]
    public $overriddenParentProperty;

    #[Co

 'value', 'nested' => [
        'nested_key' => 'nested_value',
    ], 'array' => ['first', 'second']])]
    #[Context(context: ['bar' => 'value_for_group_a'], groups: ['a'])]
    public $foo;

    #[Context(
        normalizatio


 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\Tests\Fixtures\Attributes;

use Symfony\Component\Serializer\Attribute\Context;

/**
 * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
 */
class ContextDummyPromotedProperties extends ContextDummyParent
{
    public function __constru

['a'])]
        public $foo,

        #[Context(
            normalizationContext: ['format' => 'd/m/Y'],
            denormalizationContext: ['format' => 'm-d-Y H:i'],
            groups: ['a', 'b'],
        )]
        public $bar,

        #[Context(norm

ct(
        #[Context(['foo' => 'value', 'bar' => 'value', 'nested' => [
            'nested_key' => 'nested_value',
        ], 'array' => ['first', 'second']])]
        #[Context(context: ['bar' => 'value_for_group_a'], groups:


ony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Serializer\Tests\Fixtures\Attributes;

use Symfony\Component\Serializer\Attribute\Groups;

#[Groups('a')]
class GroupClassDummy
{
    #[Groups('b')]
    private $foo;

    #[Groups(['c', 'd'])]
    private $bar;

    private $baz;

    public function getFoo()
    {
        return $this->foo;
    }

    public function setFoo($foo): void

unction getBar()
    {
        return $this->bar;
    }

    public function setBar($bar): void
    {
        $this->bar = $bar;
    }

    public function getBaz()
    {
        return $this->baz;
    }

    public function setBaz($baz): void
    {

    {
        $this->foo = $foo;
    }

    public f


 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\Tests\Fixtures\Attributes;

use Symfony\Component\Serializer\Attribute\Groups;
use Symfony\Component\Serializer\Tests\Fixtures\ChildOfGroupsAttributeDummy;

/**
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
class GroupDummy extends GroupDummyParent implemen

   #[Groups(['b'])]
    public function setBar($bar)
    {
        $this->bar = $bar;
    }

    #[Groups(['c'])]
    public function getBar()
    {
        return $this->bar;
    }

    public function setFoo($foo)
    {
        $this->foo = $foo;
    }

ts GroupDummyInterface
{
    #[Groups(['a'])]
    private $foo;
    #[Groups(['b', 'c', 'name_converter'])]
    protected $bar;
    #[ChildOfGroupsAttributeDummy]
    protected $quux;
    private $fooBar;
    private $symfony;


ackage.
 *
 * (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\Tests\Fixtures\Attributes;

use Symfony\Component\Serializer\Attribute\Groups;

/**
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
class GroupDummyParent
{
    #[Groups(['a'])]
    private $kevin;
    private $coopTilleuls;

    public function setKevin($kevin)
    {
        $thi

in()
    {
        return $this->kevin;
    }

    public function setCoopTilleuls($coopTilleuls)
    {
        $this->coopTilleuls = $coopTilleuls;
    }

    #[Groups(['a', 'b'])]
    public function getCoopTilleuls()
    {
        return $this->coopTill

s->kevin = $kevin;
    }

    public function getKev


buted with this source code.
 */

namespace Symfony\Component\Serializer\Tests\Mapping;

use PHPUnit\Framework\TestCase;
use Symfony\Component\PropertyAccess\PropertyPath;
use Symfony\Component\Serializer\Mapping\AttributeMetadata;
use Symfony\Component\Serializer\Mapping\AttributeMetadataInterface;

/**
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
class AttributeMetadataTest extends TestCase
{
    public function testInterface()
    {
        $attributeMetadata = new AttributeMetadata('name');

buteMetadata->getName());
    }

    public function testGroups()
    {
        $attributeMetadata = new AttributeMetadata('group');
        $attributeMetadata->addGroup('a');
        $attributeMetadata->addGroup('a');
        $attributeMetadata->addGroup(

$this->assertInstanceOf(AttributeMetadataInterface::class, $attributeMetadata);
    }

    public function testGetName()
    {
        $attributeMetadata = new AttributeMetadata('name');
        $this->assertEquals('name', $attri


 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\Tests\Mapping;

use PHPUnit\Framework\TestCase;
use Symfony\Component\Serializer\Mapping\ClassDiscriminatorMapping;
use Symfony\Component\Serializer\Tests\Fixtures\Attributes\AbstractDummyFirstChild;
use Symfony\Component\Serializer\Tests\Fixtures\Attributes\A

c function testGetClass()
    {
        $mapping = new ClassDiscriminatorMapping('type', [
            'first' => AbstractDummyFirstChild::class,
        ]);

        $this->assertEquals(AbstractDummyFirstChild::class, $mapping->getClassForType('first'));

bstractDummySecondChild;
use Symfony\Component\Serializer\Tests\Fixtures\Attributes\AbstractDummyThirdChild;

/**
 * @author Samuel Roze <samuel.roze@gmail.com>
 */
class ClassDiscriminatorMappingTest extends TestCase
{
    publi


ge.
 *
 * (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\Tests\Mapping;

use PHPUnit\Framework\TestCase;
use Symfony\Component\Serializer\Mapping\AttributeMetadata;
use Symfony\Component\Serializer\Mapping\ClassMetadata;
use Symfony\Component\Serializer\Mapping\ClassMetadataInterface;

/**
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
cla

ic function testAttributeMetadata()
    {
        $classMetadata = new ClassMetadata('c');

        $a1 = new AttributeMetadata('a1');
        $a2 = new AttributeMetadata('a2');

        $classMetadata->addAttributeMetadata($a1);
        $classMetadata->ad

ss ClassMetadataTest extends TestCase
{
    public function testInterface()
    {
        $classMetadata = new ClassMetadata('name');
        $this->assertInstanceOf(ClassMetadataInterface::class, $classMetadata);
    }

    publ


ge.
 *
 * (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\Tests\Mapping;

use Symfony\Component\Serializer\Mapping\AttributeMetadata;
use Symfony\Component\Serializer\Mapping\ClassMetadata;
use Symfony\Component\Serializer\Tests\Fixtures\Attributes\GroupDummy;

/**
 * @author Kévin Dunglas <dunglas@gmail.com>
 */
class TestClassMetadataFactor

w AttributeMetadata('foo');
        $foo->addGroup('a');
        $expected->addAttributeMetadata($foo);

        $bar = new AttributeMetadata('bar');
        $bar->addGroup('b');
        $bar->addGroup('c');
        $bar->addGroup('name_converter');

y
{
    public static function createClassMetadata(string $namespace, bool $withParent = false, bool $withInterface = false): ClassMetadata
    {
        $expected = new ClassMetadata($namespace.'\GroupDummy');

        $foo = ne


alizer\Exception\MappingException;
use Symfony\Component\Serializer\Mapping\AttributeMetadata;
use Symfony\Component\Serializer\Mapping\ClassDiscriminatorMapping;
use Symfony\Component\Serializer\Mapping\ClassMetadata;
use Symfony\Component\Serializer\Mapping\Loader\AttributeLoader;
use Symfony\Component\Serializer\Mapping\Loader\LoaderInterface;
use Symfony\Component\Serializer\Tests\Fixtures\Attributes\AbstractDummy;
use Symfony\Component\Serializer\Tests\Fixtures\Attributes\AbstractDummyFirstChild;
use S

orishGetters;
use Symfony\Component\Serializer\Tests\Fixtures\Attributes\BadAttributeDummy;
use Symfony\Component\Serializer\Tests\Fixtures\Attributes\BadMethodContextDummy;
use Symfony\Component\Serializer\Tests\Fixtures\Attributes\ContextDummyParent;
use