 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 Authorization\Strategy;

use Symfony\Component\Security\Core\Authorization\Strategy\PriorityStrategy;
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
use Symfony\Component\Security\Core\Test\AccessDecisionStrategyTestCase;

class PriorityStrategyTest e

ABSTAIN),
            self::getVoter(VoterInterface::ACCESS_GRANTED),
            self::getVoter(VoterInterface::ACCESS_DENIED),
            self::getVoter(VoterInterface::ACCESS_DENIED),
        ], true];

        yield [$strategy, [
            self::get

xtends AccessDecisionStrategyTestCase
{
    public static function provideStrategyTests(): iterable
    {
        $strategy = new PriorityStrategy();

        yield [$strategy, [
            self::getVoter(VoterInterface::ACCESS_


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

namespace Symfony\Component\Security\Core\Tests\Role;

use PHPUnit\Framework\TestCase;
use Symfony\Component\Security\Core\Role\RoleHierarchy;

class RoleHierarchyTest extends TestCase
{
    public function testGetReachableRoleNames()
    {
        $role = new RoleHierarchy([
            'ROLE_ADMIN' => ['ROLE_USER'],
            'ROLE_SUPER_ADMIN' => ['ROLE_ADMIN', 'ROLE_F

eNames(['ROLE_FOO']));
        $this->assertEqualsCanonicalizing(['ROLE_ADMIN' => 'ROLE_ADMIN', 'ROLE_USER' => 'ROLE_USER'], $role->getReachableRoleNames(['ROLE_ADMIN']));
        $this->assertEqualsCanonicalizing(['ROLE_FOO' => 'ROLE_FOO', 'ROLE_ADMIN' =>

OO'],
        ]);

        $this->assertEqualsCanonicalizing(['ROLE_USER' => 'ROLE_USER'], $role->getReachableRoleNames(['ROLE_USER']));
        $this->assertEqualsCanonicalizing(['ROLE_FOO' => 'ROLE_FOO'], $role->getReachableRol


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\Security\Core\Validator\Constraints;

use Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactoryInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\User\LegacyPasswordAuthenticatedUserInterface;
use Symfony\

tion;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

class UserPasswordValidator extends ConstraintValidator
{
    public function __construct(
        private TokenStorageInterface $tokenStorage,
        private PasswordHasherFactoryI

Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\ConstraintDefinitionExcep


?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\Security\Core\Tests\Authentication\Token\Storage;

use PHPUnit\Framework\TestCase;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use S

n());
        $token = new UsernamePasswordToken(new InMemoryUser('username', 'password'), 'provider');
        $tokenStorage->setToken($token);
        $this->assertSame($token, $tokenStorage->getToken());
        $tokenStorage->setToken(null);
        $t

ymfony\Component\Security\Core\User\InMemoryUser;

class TokenStorageTest extends TestCase
{
    public function testGetSetToken()
    {
        $tokenStorage = new TokenStorage();
        $this->assertNull($tokenStorage->getToke


 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\Security\Core\Tests\User;

use PHPUnit\Framework\TestCase;
use Symfony\Component\Security\Core\User\OAuth2User;

class OAuth2UserTest extends TestCase
{
    public function testCannotCreateUserWithoutSubProperty()
    {
        $this->expectException(\InvalidArgumentExce

{
        $this->assertEquals(new OAuth2User(
            scope: 'read write dolphin',
            username: 'jdoe',
            exp: 1419356238,
            iat: 1419350238,
            sub: 'Z5O3upPC88QrAjx00dis',
            aud: 'https://protected.exam

ption::class);
        $this->expectExceptionMessage('The claim "sub" or "username" must be provided.');

        new OAuth2User();
    }

    public function testCreateFullUserWithAdditionalClaimsUsingPositionalParameters()


buted with this source code.
 */

namespace Symfony\Component\Security\Core\Tests\Validator\Constraints;

use PHPUnit\Framework\Attributes\DataProvider;
use Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactoryInterface;
use Symfony\Component\PasswordHasher\PasswordHasherInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use

ption\ConstraintDefinitionException;
use Symfony\Component\Validator\Test\ConstraintValidatorTestCase;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
abstract class UserPasswordValidatorTestCase extends ConstraintValidatorTestCase
{
    privat

Symfony\Component\Security\Core\Validator\Constraints\UserPassword;
use Symfony\Component\Security\Core\Validator\Constraints\UserPasswordValidator;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exce


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\Security\Core\Tests\Exception;

use PHPUnit\Framework\TestCase;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;

class UserNotFoundExceptionTest extends TestCase
{
    public function testGetMessageData()
    {
        $exceptio

e');
        $this->assertEquals(['{{ username }}' => 'username', '{{ user_identifier }}' => 'username'], $exception->getMessageData());
    }

    public function testUserIdentifierIsNotSetByDefault()
    {
        $exception = new UserNotFoundException()

n = new UserNotFoundException('Username could not be found.');
        $this->assertEquals(['{{ username }}' => null, '{{ user_identifier }}' => null], $exception->getMessageData());
        $exception->setUserIdentifier('usernam


Component\Security\Core\Exception\UserNotFoundException;
use Symfony\Component\Security\Core\User\AttributesBasedUserProviderInterface;
use Symfony\Component\Security\Core\User\ChainUserProvider;
use Symfony\Component\Security\Core\User\InMemoryUser;
use Symfony\Component\Security\Core\User\InMemoryUserProvider;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
use Symfony\Component\Security\Core\User\UserProvider

once())
            ->method('loadUserByIdentifier')
            ->with($this->equalTo('foo'))
            ->willThrowException(new UserNotFoundException('not found'))
        ;

        $provider2 = $this->createMock(InMemoryUserProvider::class);

Interface;

class ChainUserProviderTest extends TestCase
{
    public function testLoadUserByIdentifier()
    {
        $provider1 = $this->createMock(InMemoryUserProvider::class);
        $provider1
            ->expects($this->


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

namespace Symfony\Component\Security\Core\Tests\Authentication\Token;

use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Security\Core\Authentication\Token\AbstractToken;
use Symfony\Component\Security\Core\User\InMemoryUser;
use Symfony\Component\Security\Core\User\UserInterface;

class AbstractTokenTest extends TestCase
{

, $token->getUserIdentifier());
    }

    public static function provideUsers()
    {
        yield [new InMemoryUser('fabien', null), 'fabien'];
    }

    public function testSerialize()
    {
        $token = new ConcreteToken(['ROLE_FOO', 'ROLE_BAR'])

    #[DataProvider('provideUsers')]
    public function testGetUserIdentifier($user, string $username)
    {
        $token = new ConcreteToken(['ROLE_FOO']);
        $token->setUser($user);
        $this->assertEquals($username


n Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Authorization\Strategy;

use Symfony\Component\Security\Core\Authorization\Strategy\AffirmativeStrategy;
use Symfony\Component\Security\Core\Test\AccessDecisionStrategyTestCase;

class AffirmativeStrategyTest extends AccessDecisionStrategyTestCase
{
    public static function provideStrategyTests(): iterable
    {
        $strategy

gy, self::getVoters(1, 0, 0), true];
        yield [$strategy, self::getVoters(1, 2, 0), true];
        yield [$strategy, self::getVoters(0, 1, 0), false];
        yield [$strategy, self::getVoters(0, 0, 1), false];

        $strategy = new AffirmativeStra

= new AffirmativeStrategy();

        yield [$strate


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

namespace Symfony\Component\Security\Core\Authorization\Voter;

use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;

/**
 * Voter is an abstract default implementation of a voter.
 *
 * @author Roman Marintšenko <inoryy@gmail.com>
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 *
 * @template TAttribute of string
 * @template TSubject of mixed
 */
abst

ne of the attributes are supported
        $voteResult = self::ACCESS_ABSTAIN;

        foreach ($attributes as $attribute) {
            try {
                if (!$this->supports($attribute, $subject)) {
                    continue;
                }

ract class Voter implements VoterInterface, CacheableVoterInterface
{
    public function vote(TokenInterface $token, mixed $subject, array $attributes, ?Vote $vote = null): int
    {
        // abstain vote by default in case no


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\AssetMapper\Compressor;

use Psr\Log\LoggerInterface;
use Symfony\Component\Process\Process;

/**
 * Compresses a file using zopfli if possible, or fallback on gzip.
 *
 * @author Kévin Dunglas <kevin@dunglas.dev>
 */
final class GzipCompressor implements SupportedCompressorInterface
{
    use Co

 PHP_EXTENSION = 'zlib';
    private const FILE_EXTENSION = 'gz';

    public function __construct(
        private readonly ZopfliCompressor $zopfliCompressor = new ZopfliCompressor(),
        ?string $executable = null,
        private ?LoggerInterface $

mpressorTrait {
        compress as private baseCompress;
        getUnsupportedReason as private baseGetUnsupportedReason;
    }

    private const WRAPPER = 'compress.zlib';
    private const COMMAND = 'gzip';
    private const


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

use Symfony\Component\Process\Process;

/**
 * Compresses a file using zopfli.
 *
 * @author Kévin Dunglas <kevin@dunglas.dev>
 */
final class ZopfliCompressor implements SupportedCompressorInterface
{
    use CompressorTrait;

lic function __construct(
        ?string $executable = null,
    ) {
        $this->executable = $executable;
    }

    private function compressWithBinary(string $path): void
    {
        (new Process([$this->executable, '--', $path]))->mustRun();

    private const WRAPPER = ''; // not supported yet https://github.com/kjdev/php-ext-zopfli/issues/23
    private const COMMAND = 'zopfli';
    private const PHP_EXTENSION = '';
    private const FILE_EXTENSION = 'gz';

    pub


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

use Symfony\Component\Process\Process;

/**
 * Compresses a file using Zstandard.
 *
 * @author Kévin Dunglas <kevin@dunglas.dev>
 */
final class ZstandardCompressor implements SupportedCompressorInterface
{
    use CompressorT

able = null,
    ) {
        $this->executable = $executable;
    }

    /**
     * @return resource
     */
    private function createStreamContext()
    {
        return stream_context_create(['zstd' => ['level' => \ZSTD_COMPRESS_LEVEL_MAX]]);
    }

rait;

    private const WRAPPER = 'compress.zstd';
    private const COMMAND = 'zstd';
    private const PHP_EXTENSION = 'zstd';
    private const FILE_EXTENSION = 'zst';

    public function __construct(
        ?string $execut


 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\AssetMapper\Path;

use Symfony\Component\AssetMapper\Compressor\CompressorInterface;
use Symfony\Component\Filesystem\Filesystem;

class LocalPublicAssetsFilesystem implements PublicAssetsFilesystemInterface
{
    private Filesystem $filesystem;

    /**
     * @param st

ess = [],
    ) {
        $this->filesystem = new Filesystem();
    }

    public function write(string $path, string $contents): void
    {
        $targetPath = $this->publicDir.'/'.ltrim($path, '/');

        $this->filesystem->dumpFile($targetPath, $co

ring[] $extensionsToCompress
     */
    public function __construct(
        private readonly string $publicDir,
        private readonly ?CompressorInterface $compressor = null,
        private readonly array $extensionsToCompr


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

/**
 * Writes asset files to their public location.
 */
interface PublicAssetsFilesystemInterface
{
    /**
     * Write the contents of a file to the public location.
     */
    public function write(string $path, string $contents

/**
     * Copy a local file to the public location.
     */
    public function copy(string $originPath, string $path): void;

    /**
     * A string representation of the public directory, used for feedback.
     */
    public function getDestinationPat


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

class PublicAssetsPathResolver implements PublicAssetsPathResolverInterface
{
    private readonly string $publicPrefix;

    public function __construct(
        string $publicPrefix = '/assets/',
    ) {
        // ensure that the

always starts and ends with a single slash
        $this->publicPrefix = '/'.trim($publicPrefix, '/').'/';
    }

    public function resolvePublicPath(string $logicalPath): string
    {
        return $this->publicPrefix.ltrim($logicalPath, '/');
    }
}


n 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\AssetMapper\Compiler;

use Symfony\Component\AssetMapper\AssetMapperInterface;
use Symfony\Component\AssetMapper\MappedAsset;

/**
 * An asset compiler is responsible for applying any changes to the contents of an asset.
 *
 * @author Ryan Weaver <ryan@symfonycasts.com>
 */
interface AssetCompilerInterface
{
    pu

lic const MISSING_IMPORT_WARN = 'warn';
    public const MISSING_IMPORT_IGNORE = 'ignore';

    public function supports(MappedAsset $asset): bool;

    /**
     * Applies any changes to the contents of the asset.
     */
    public function compile(string

blic const MISSING_IMPORT_STRICT = 'strict';
    pub


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

namespace Symfony\Component\AssetMapper\Compiler;

use Psr\Log\LoggerInterface;
use Symfony\Component\AssetMapper\AssetMapperInterface;
use Symfony\Component\AssetMapper\Exception\RuntimeException;
use Symfony\Component\AssetMapper\MappedAsset;
use Symfony\Component\Filesystem\Path;

/**
 * Resolves url() paths in CSS files.
 *
 * Originally sourced from https://github.com/

rails/propshaft/blob/main/lib/propshaft/compiler/css_asset_urls.rb
 */
final class CssAssetUrlCompiler implements AssetCompilerInterface
{
    // https://regex101.com/r/BOJ3vG/2
    public const ASSET_URL_PATTERN = <<<'REGEX'


buted with this source code.
 */

namespace Symfony\Component\AssetMapper\Compiler;

use Psr\Log\LoggerInterface;
use Symfony\Component\AssetMapper\AssetMapperInterface;
use Symfony\Component\AssetMapper\Compiler\Parser\JavascriptSequenceParser;
use Symfony\Component\AssetMapper\Exception\CircularAssetsException;
use Symfony\Component\AssetMapper\Exception\RuntimeException;
use Symfony\Component\AssetMapper\ImportMap\ImportMapConfigReader;
use Symfony\Component\AssetMapper\ImportMap\JavaScriptImport;
use Sy

AssetCompilerInterface
{
    private const IMPORT_PATTERN = '/
            ^(?:\/\/.*)                     # Lines that start with comments
        |
            (?:
                \'(?:[^\'\\\\\n]|\\\\.)*+\'   # Strings enclosed in single quotes

mfony\Component\AssetMapper\MappedAsset;
use Symfony\Component\Filesystem\Path;

/**
 * Resolves import paths in JS files.
 *
 * @author Ryan Weaver <ryan@symfonycasts.com>
 */
final class JavaScriptImportPathCompiler implements


 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\AssetMapper\Compiler;

use Symfony\Component\AssetMapper\AssetMapperInterface;
use Symfony\Component\AssetMapper\MappedAsset;
use Symfony\Component\Filesystem\Path;

/**
 * Rewrites already-existing source map URLs to their final digested path.
 *
 * Originally sourced f

sourceMappingURL=(.+\.map)}m';

    public function supports(MappedAsset $asset): bool
    {
        return \in_array($asset->publicExtension, ['css', 'js'], true);
    }

    public function compile(string $content, MappedAsset $asset, AssetMapperInterfac

rom https://github.com/rails/propshaft/blob/main/lib/propshaft/compiler/source_mapping_urls.rb
 */
final class SourceMappingUrlsCompiler implements AssetCompilerInterface
{
    private const SOURCE_MAPPING_PATTERN = '{^(//|/\*)#


buted with this source code.
 */

namespace Symfony\Component\AssetMapper\Compiler\Parser;

/**
 * Parses JavaScript content to identify sequences of strings, comments, etc.
 *
 * @author Simon André <smn.andre@gmail.com>
 *
 * @internal
 */
final class JavascriptSequenceParser
{
    private const STATE_DEFAULT = 0;
    private const STATE_COMMENT = 1;
    private const STATE_STRING = 2;

    private int $cursor = 0;

    private int $contentEnd;

    private string $pattern;

    private int $currentSequen

      '\'',   // Single quote
        '`',    // Backtick
    ];

    public function __construct(
        private readonly string $content,
    ) {
        $this->contentEnd = \strlen($content);

        $this->pattern ??= '/'.implode('|', array_map(

ceType = self::STATE_DEFAULT;

    private ?int $currentSequenceEnd = null;

    private const COMMENT_SEPARATORS = [
        '/*',   // Multi-line comment
        '//',   // Single-line comment
        '"',    // Double quote


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\AssetMapper\Factory;

use Symfony\Component\AssetMapper\MappedAsset;
use Symfony\Component\Config\ConfigCache;
use Symfony\Component\Config\Resource\DirectoryResource;
use Symfony\Component\Config\Resource\FileExistenceResource;
use Symfony\Component\Config\Resource\FileResource;
use Symfony\Comp

toryInterface
{
    public function __construct(
        private readonly MappedAssetFactoryInterface $innerFactory,
        private readonly string $cacheDir,
        private readonly bool $debug,
    ) {
    }

    public function createMappedAsset(strin

onent\Config\Resource\ResourceInterface;
use Symfony\Component\Filesystem\Filesystem;

/**
 * Decorates the asset factory to load MappedAssets from cache when possible.
 */
class CachedMappedAssetFactory implements MappedAssetFac


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

namespace Symfony\Component\AssetMapper\Factory;

use Symfony\Component\AssetMapper\AssetMapperCompiler;
use Symfony\Component\AssetMapper\Exception\CircularAssetsException;
use Symfony\Component\AssetMapper\Exception\RuntimeException;
use Symfony\Component\AssetMapper\MappedAsset;
use Symfony\Component\AssetMapper\Path\PublicAssetsPathResolverInterface;
use Symfony\Compone

/-([0-9a-zA-Z]{7,128}\.digested)/';
    private const PUBLIC_DIGEST_LENGTH = 7;

    private array $assetsCache = [];
    private array $assetsBeingCreated = [];

    public function __construct(
        private readonly PublicAssetsPathResolverInterface $

nt\Filesystem\Filesystem;

/**
 * Creates MappedAsset objects by reading their contents & passing it through compilers.
 */
class MappedAssetFactory implements MappedAssetFactoryInterface
{
    private const PREDIGESTED_REGEX = '


 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\AssetMapper\ImportMap;

use Symfony\Component\HttpClient\DecoratorTrait;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use Symfony\Contracts\HttpClient\ResponseInterface;

/**
 * @internal
 */
class BatchHttpClient implements HttpClientInterface
{
    use Decorat

\WeakMap();
        $pendingRequests = [];

        foreach ($this->pendingRequests as $response => $_) {
            if ($response->getInfo('http_code')) {
                $this->pendingRequests->offsetUnset($response);
            } else {

orTrait;

    private const BATCH_SIZE = 250;

    private \WeakMap $pendingRequests;

    public function request(string $method, string $url, array $options = []): ResponseInterface
    {
        $this->pendingRequests ??= new


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

namespace Symfony\Component\AssetMapper\ImportMap;

use Symfony\Component\AssetMapper\Exception\RuntimeException;
use Symfony\Component\HttpClient\HttpClient;
use Symfony\Contracts\HttpClient\HttpClientInterface;

class ImportMapAuditor
{
    private const AUDIT_URL = 'https://api.github.com/advisories';

    private readonly HttpClientInterface $httpClient;

    public fun

urn list<ImportMapPackageAudit>
     */
    public function audit(): array
    {
        $entries = $this->configReader->getEntries();

        /** @var array<string, ImportMapPackageAudit> $packageAudits */
        $packageAudits = [];

        /** @var a

ction __construct(
        private readonly ImportMapConfigReader $configReader,
        ?HttpClientInterface $httpClient = null,
    ) {
        $this->httpClient = $httpClient ?? HttpClient::create();
    }

    /**
     * @ret


buted with this source code.
 */

namespace Symfony\Component\AssetMapper\ImportMap;

use Symfony\Component\AssetMapper\Exception\RuntimeException;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Filesystem\Path;
use Symfony\Component\VarExporter\VarExporter;

/**
 * Reads/Writes the importmap.php file and returns the list of entries.
 *
 * @author Ryan Weaver <ryan@symfonycasts.com>
 */
class ImportMapConfigReader
{
    private ImportMapEntries $rootImportMapEntries;
    private readonly

tem();
    }

    public function getEntries(): ImportMapEntries
    {
        if (isset($this->rootImportMapEntries)) {
            return $this->rootImportMapEntries;
        }

        $configPath = $this->importMapConfigPath;
        $importMapConfig =

 Filesystem $filesystem;

    public function __construct(
        private readonly string $importMapConfigPath,
        private readonly RemotePackageStorage $remotePackageStorage,
    ) {
        $this->filesystem = new Filesys


 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\AssetMapper\ImportMap;

/**
 * Holds the collection of importmap entries defined in importmap.php.
 *
 * @template-implements \IteratorAggregate<ImportMapEntry>
 *
 * @author Ryan Weaver <ryan@symfonycasts.com>
 */
class ImportMapEntries implements \IteratorAggregate
{

    }

    public function add(ImportMapEntry $entry): void
    {
        $this->entries[$entry->importName] = $entry;
    }

    public function has(string $importName): bool
    {
        return isset($this->entries[$importName]);
    }

    public funct

   private array $entries = [];

    /**
     * @param ImportMapEntry[] $entries
     */
    public function __construct(array $entries = [])
    {
        foreach ($entries as $entry) {
            $this->add($entry);
        }


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\AssetMapper\ImportMap;

/**
 * Represents an item that should be in the importmap.
 *
 * @author Ryan Weaver <ryan@symfonycasts.com>
 */
final class ImportMapEntry
{
    private function __construct(
        public readonly string $importName,
        public readonly ImportMapType $type,

ly).
         */
        public readonly ?string $version,
        /**
         * The full "package-name/path" (remote only).
         */
        public readonly ?string $packageModuleSpecifier,
    ) {
    }

    public static function createLocal(string

/**
         * A logical path, relative path or absolute path to the file.
         */
        public readonly string $path,
        public readonly bool $isEntrypoint,
        /**
         * The version of the package (remote on


er;
use Symfony\Component\AssetMapper\Exception\LogicException;
use Symfony\Component\AssetMapper\MappedAsset;

/**
 * Provides data needed to write the importmap & preloads.
 */
class ImportMapGenerator
{
    public const IMPORT_MAP_CACHE_FILENAME = 'importmap.json';
    public const ENTRYPOINT_CACHE_FILENAME_PATTERN = 'entrypoint.%s.json';

    public function __construct(
        private readonly AssetMapperInterface $assetMapper,
        private readonly CompiledAssetMapperConfigReader $compiledConfigRe

r->getEntries();
        $entrypointNames = [];
        foreach ($rootEntries as $entry) {
            if ($entry->isEntrypoint) {
                $entrypointNames[] = $entry->importName;
            }
        }

        return $entrypointNames;
    }

ader,
        private readonly ImportMapConfigReader $importMapConfigReader,
    ) {
    }

    /**
     * @internal
     */
    public function getEntrypointNames(): array
    {
        $rootEntries = $this->importMapConfigReade


buted with this source code.
 */

namespace Symfony\Component\AssetMapper\ImportMap;

use Symfony\Component\AssetMapper\AssetMapperInterface;
use Symfony\Component\AssetMapper\ImportMap\Resolver\PackageResolverInterface;
use Symfony\Component\AssetMapper\MappedAsset;

/**
 * @author Kévin Dunglas <kevin@dunglas.dev>
 * @author Ryan Weaver <ryan@symfonycasts.com>
 *
 * @final
 */
class ImportMapManager
{
    public function __construct(
        private readonly AssetMapperInterface $assetMapper,
        priv

dates packages.
     *
     * @param PackageRequireOptions[] $packages
     *
     * @return ImportMapEntry[]
     */
    public function require(array $packages): array
    {
        return $this->updateImportMapConfig(false, $packages, [], []);
    }

ate readonly ImportMapConfigReader $importMapConfigReader,
        private readonly RemotePackageDownloader $packageDownloader,
        private readonly PackageResolverInterface $resolver,
    ) {
    }

    /**
     * Adds or up


p

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

final class ImportMapPackageAudit
{
    public function __construct(
        public readonly string $package,
        public readonly ?string $version,
        /** @var array<ImportMapPackageAuditVulnerability> */
        publ

 }

    public function withVulnerability(ImportMapPackageAuditVulnerability $vulnerability): self
    {
        return new self(
            $this->package,
            $this->version,
            [...$this->vulnerabilities, $vulnerability],
        );

ic readonly array $vulnerabilities = [],
    ) {


\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\WebLink\EventListener\AddLinkHeaderListener;
use Symfony\Component\WebLink\GenericLinkProvider;
use Symfony\Component\WebLink\Link;

/**
 * @author Kévin Dunglas <kevin@dunglas.dev>
 * @author Ryan Weaver <ryan@symfonycasts.com>
 *
 * @final
 */
class ImportMapRenderer
{
    // https://generator.jspm.io/#S2NnYGAIzSvJLMlJTWEAAMYOgCAOAA
    private const DEFAULT_ES_MODULE_SHIMS_POLYFILL_URL = 'https://ga.jspm.io/npm:es-module-s

nc()=>await(await fetch('%s')).json())()";
    private const LOADER_CSS = "document.head.appendChild(Object.assign(document.createElement('link'),{rel:'stylesheet',href:'%s'}))";

    public function __construct(
        private readonly ImportMapGenerator

hims@1.10.0/dist/es-module-shims.js';
    private const DEFAULT_ES_MODULE_SHIMS_POLYFILL_INTEGRITY = 'sha384-ie1x72Xck445i0j4SlNJ5W5iGeL3Dpa0zD48MZopgWsjNB/lt60SuG1iduZGNnJn';

    private const LOADER_JSON = "export default (asy


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

namespace Symfony\Component\AssetMapper\ImportMap;

use Symfony\Component\HttpClient\HttpClient;
use Symfony\Contracts\HttpClient\HttpClientInterface;

class ImportMapUpdateChecker
{
    private const URL_PACKAGE_METADATA = 'https://registry.npmjs.org/%s';

    private readonly HttpClientInterface $httpClient;

    public function __construct(
        private readonly Impor

es
     *
     * @return PackageUpdateInfo[]
     */
    public function getAvailableUpdates(array $packages = []): array
    {
        $entries = $this->importMapConfigReader->getEntries();
        $updateInfos = [];
        $responses = [];
        forea

tMapConfigReader $importMapConfigReader,
        ?HttpClientInterface $httpClient = null,
    ) {
        $this->httpClient = new BatchHttpClient($httpClient ?? HttpClient::create());
    }

    /**
     * @param string[] $packag


buted with this source code.
 */

namespace Symfony\Component\AssetMapper\ImportMap;

use Composer\Semver\Semver;
use Symfony\Component\AssetMapper\Exception\RuntimeException;
use Symfony\Component\HttpClient\HttpClient;
use Symfony\Contracts\HttpClient\Exception\HttpExceptionInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;

class ImportMapVersionChecker
{
    private const PACKAGE_METADATA_PATTERN = 'https://registry.npmjs.org/%package%/%version%';

    private readonly HttpClientInterface

     $this->httpClient = new BatchHttpClient($httpClient ?? HttpClient::create());
    }

    /**
     * @return PackageVersionProblem[]
     */
    public function checkVersions(): array
    {
        $entries = $this->importMapConfigReader->getEntries();

$httpClient;

    public function __construct(
        private ImportMapConfigReader $importMapConfigReader,
        private RemotePackageDownloader $packageDownloader,
        ?HttpClientInterface $httpClient = null,
    ) {


?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\AssetMapper\ImportMap;

/**
 * Represents a module that was imported by a JavaScript file.
 */
final class JavaScriptImport
{
    /**
     * @param string $importName               The name of the import needed in the importmap, e.g. "/foo.js" or

 public function __construct(
        public readonly string $importName,
        public readonly string $assetLogicalPath,
        public readonly string $assetSourcePath,
        public readonly bool $isLazy = false,
        public bool $addImplicitlyToI

"react"
     * @param string $assetLogicalPath         Logical path to the mapped ass that was imported
     * @param bool   $addImplicitlyToImportMap Whether this import should be added to the importmap automatically
     */


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

namespace Symfony\Component\AssetMapper\ImportMap;

/**
 * Represents a package that should be installed or updated.
 *
 * @author Kévin Dunglas <kevin@dunglas.dev>
 */
final class PackageRequireOptions
{
    public readonly string $importName;

    public function __construct(
        /**
         * The "package-name/path" of the remote package.
         */

     public readonly ?string $versionConstraint = null,
        ?string $importName = null,
        public readonly ?string $path = null,
        public readonly bool $entrypoint = false,
    ) {
        $this->importName = $importName ?: $packageModuleSpe

public readonly string $packageModuleSpecifier,


n 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\AssetMapper\ImportMap;

class PackageUpdateInfo
{
    public const UPDATE_TYPE_DOWNGRADE = 'downgrade';
    public const UPDATE_TYPE_UP_TO_DATE = 'up-to-date';
    public const UPDATE_TYPE_MAJOR = 'major';
    public const UPDATE_TYPE_MINOR = 'minor';
    public const UPDATE_TYPE_PATCH = 'patch';

    public functi

ageName,
        public readonly string $currentVersion,
        public ?string $latestVersion = null,
        public ?string $updateType = null,
    ) {
    }

    public function hasUpdate(): bool
    {
        return !\in_array($this->updateType, [self:

on __construct(
        public readonly string $pack


buted with this source code.
 */

namespace Symfony\Component\AssetMapper\ImportMap;

use Symfony\Component\AssetMapper\ImportMap\Resolver\PackageResolverInterface;
use Symfony\Component\Filesystem\Filesystem;

/**
 * @final
 */
class RemotePackageDownloader
{
    private array $installed;

    private readonly Filesystem $filesystem;

    public function __construct(
        private readonly RemotePackageStorage $remotePackageStorage,
        private readonly ImportMapConfigReader $importMapConfigReader,

    public function downloadPackages(?callable $progressCallback = null): array
    {
        try {
            $installed = $this->loadInstalled();
        } catch (\InvalidArgumentException) {
            $installed = [];
        }
        $entries = $t

       private readonly PackageResolverInterface $packageResolver,
    ) {
        $this->filesystem = new Filesystem();
    }

    /**
     * Downloads all packages.
     *
     * @return string[] The downloaded packages
     */


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

namespace Symfony\Component\AssetMapper\ImportMap;

use Symfony\Component\AssetMapper\Exception\RuntimeException;
use Symfony\Component\Filesystem\Exception\IOException;
use Symfony\Component\Filesystem\Filesystem;

/**
 * Manages the local storage of remote/vendor importmap packages.
 */
class RemotePackageStorage
{
    private readonly Filesystem $filesystem;

    public

ownloaded(ImportMapEntry $entry): bool
    {
        if (!$entry->isRemotePackage()) {
            throw new \InvalidArgumentException(\sprintf('The entry "%s" is not a remote package.', $entry->importName));
        }

        return is_file($this->getDow

function __construct(private readonly string $vendorDir)
    {
        $this->filesystem = new Filesystem();
    }

    public function getStorageDir(): string
    {
        return $this->vendorDir;
    }

    public function isD


ntimeException;
use Symfony\Component\AssetMapper\ImportMap\BatchHttpClient;
use Symfony\Component\AssetMapper\ImportMap\ImportMapEntry;
use Symfony\Component\AssetMapper\ImportMap\ImportMapType;
use Symfony\Component\AssetMapper\ImportMap\PackageRequireOptions;
use Symfony\Component\Filesystem\Path;
use Symfony\Component\HttpClient\HttpClient;
use Symfony\Contracts\HttpClient\Exception\HttpExceptionInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use Symfony\Contracts\HttpClient\ResponseInt

sdelivr.net/npm/%s@%s%s';
    public const URL_PATTERN_DIST = self::URL_PATTERN_DIST_CSS.'/+esm';
    public const URL_PATTERN_ENTRYPOINT = 'https://data.jsdelivr.com/v1/packages/npm/%s@%s/entrypoints';

    public const IMPORT_REGEX = '#(?:import\s*(?:[\w

erface;

final class JsDelivrEsmResolver implements PackageResolverInterface
{
    public const URL_PATTERN_VERSION = 'https://data.jsdelivr.com/v1/packages/npm/%s/resolved';
    public const URL_PATTERN_DIST_CSS = 'https://cdn.j


 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\AssetMapper\ImportMap\Resolver;

use Symfony\Component\AssetMapper\ImportMap\ImportMapEntry;
use Symfony\Component\AssetMapper\ImportMap\PackageRequireOptions;

interface PackageResolverInterface
{
    /**
     * Grabs the URLs for the given packages and con

  *
     * @return ResolvedImportMapPackage[] The import map entries that should be added
     */
    public function resolvePackages(array $packagesToRequire): array;

    /**
     * Downloads the contents of the given packages.
     *
     * The returned

verts them to ImportMapEntry objects.
     *
     * If "download" is specified in PackageRequireOptions, the resolved package
     * contents should be included.
     *
     * @param PackageRequireOptions[] $packagesToRequire


buted with this source code.
 */

namespace Symfony\Component\AssetMapper\Command;

use Symfony\Component\AssetMapper\AssetMapper;
use Symfony\Component\AssetMapper\AssetMapperInterface;
use Symfony\Component\AssetMapper\CompiledAssetMapperConfigReader;
use Symfony\Component\AssetMapper\Event\PreAssetsCompileEvent;
use Symfony\Component\AssetMapper\ImportMap\ImportMapGenerator;
use Symfony\Component\AssetMapper\Path\PublicAssetsFilesystemInterface;
use Symfony\Component\Console\Attribute\AsCommand;
use Symf

her\EventDispatcherInterface;

/**
 * Compiles the assets in the asset mapper to the final output directory.
 *
 * This command is intended to be used during deployment.
 *
 * @author Ryan Weaver <ryan@symfonycasts.com>
 */
#[AsCommand(name: 'asset-map:com

ony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Contracts\EventDispatc


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\Security\Core\Signature;

use Psr\Cache\CacheItemPoolInterface;

/**
 * @author Ryan Weaver <ryan@symfonycasts.com>
 */
final class ExpiredSignatureStorage
{
    public function __construct(
        private CacheItemPoolInterface $cache,
        pri

che->getItem($key)->get();
    }

    public function incrementUsages(string $hash): void
    {
        $item = $this->cache->getItem(rawurlencode($hash));

        if (!$item->isHit()) {
            $item->expiresAfter($this->lifetime);
        }

vate int $lifetime,
    ) {
    }

    public function countUsages(string $hash): int
    {
        $key = rawurlencode($hash);
        if (!$this->cache->hasItem($key)) {
            return 0;
        }

        return $this->ca


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\Security\Core\Dumper;

use Symfony\Component\Security\Core\Role\RoleHierarchy;
use Symfony\Component\Security\Core\Role\RoleHierarchyInterface;

/**
 * MermaidDumper dumps a Mermaid flowchart describing role hierarchy.
 *
 * @author Damien Fernandes <damien.fernandes24@gmail.com>
 */
class Mermai

the flowchart
     */
    public function dump(RoleHierarchyInterface $roleHierarchy, MermaidDirection $direction = MermaidDirection::TOP_TO_BOTTOM): string
    {
        $hierarchy = $this->extractHierarchy($roleHierarchy);

        if (!$hierarchy) {

dDumper
{
    /**
     * Dumps the role hierarchy as a Mermaid flowchart.
     *
     * @param RoleHierarchyInterface $roleHierarchy The role hierarchy to dump
     * @param MermaidDirection       $direction     The direction of


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

use Symfony\Component\Webhook\Exception\InvalidArgumentException;

class Subscriber
{
    public function __construct(
        private readonly string $url,
        #[\SensitiveParameter] private readonly string $secret,
    ) {
        i

            throw new InvalidArgumentException('A non-empty secret is required.');
        }
    }

    public function getUrl(): string
    {
        return $this->url;
    }

    public function getSecret(): string
    {
        return $this->secret;


 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\Webhook\Server;

use Symfony\Component\HttpClient\HttpOptions;
use Symfony\Component\RemoteEvent\RemoteEvent;
use Symfony\Component\Serializer\SerializerInterface;

/**
 * @author Fabien Potencier <fabien@symfony.com>
 */
final class JsonBodyConfigurator imp

ializer = $payloadSerializer instanceof SerializerInterface ? new SerializerPayloadSerializer($payloadSerializer) : $payloadSerializer;
    }

    public function configure(RemoteEvent $event, #[\SensitiveParameter] string $secret, HttpOptions $options): v

lements RequestConfiguratorInterface
{
    private PayloadSerializerInterface $payloadSerializer;

    public function __construct(SerializerInterface|PayloadSerializerInterface $payloadSerializer)
    {
        $this->payloadSer


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\Webhook\Client;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestMatcherInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\RemoteEvent\RemoteEvent;
use Symfony\Component\Webhook\Exception\RejectWebhookException;

/**
 * @autho

        $this->validate($request);

        return $this->doParse($request, $secret);
    }

    public function createSuccessfulResponse(?Request $request = null): Response
    {
        return new Response('', 202);
    }

    public function createReje

r Fabien Potencier <fabien@symfony.com>
 */
abstract class AbstractRequestParser implements RequestParserInterface
{
    public function parse(Request $request, #[\SensitiveParameter] string $secret): RemoteEvent|array|null
    {


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\Webhook\Client;

use Symfony\Component\HttpFoundation\ChainRequestMatcher;
use Symfony\Component\HttpFoundation\HeaderBag;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestMatcher\IsJsonRequestMatcher;
use Symfony\Component\HttpFoundation\RequestMatcher\Me

ption\RejectWebhookException;

/**
 * @author Fabien Potencier <fabien@symfony.com>
 */
class RequestParser extends AbstractRequestParser
{
    public function __construct(
        private readonly string $algo = 'sha256',
        private readonly string $

thodRequestMatcher;
use Symfony\Component\HttpFoundation\RequestMatcherInterface;
use Symfony\Component\RemoteEvent\RemoteEvent;
use Symfony\Component\Webhook\Exception\InvalidArgumentException;
use Symfony\Component\Webhook\Exce


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\Webhook\Tests\Server;

use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpClient\HttpOptions;
use Symfony\Component\RemoteEvent\RemoteEvent;
use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Component\Webhook\Server\JsonBodyConfigurator;
use Symfony\Component\Webhook\Server

loadSerializerInterface::class);
        $payloadSerializer
            ->expects($this->once())
            ->method('serialize')
            ->with($payload)
        ;

        $httpOptions = new HttpOptions();
        $httpOptions->setHeaders([

\PayloadSerializerInterface;

class JsonBodyConfiguratorTest extends TestCase
{
    public function testPayloadWithPayloadSerializer()
    {
        $payload = ['foo' => 'bar'];

        $payloadSerializer = $this->createMock(Pay


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\Webhook\Test;

use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\RemoteEvent\RemoteEvent;
use Symfony\Component\Webhook\Client\RequestParserInterface;

/**
 * @author Fabien Potencier <fabien@symfony.

ed)
    {
        $request = $this->createRequest($payload);
        $parser = $this->createRequestParser();
        $wh = $parser->parse($request, $this->getSecret());
        $this->assertEquals($expected, $wh);
    }

    /**
     * @return iterable<arr

com>
 */
abstract class AbstractRequestParserTestCase extends TestCase
{
    /**
     * @dataProvider getPayloads
     */
    #[DataProvider('getPayloads')]
    public function testParse(string $payload, RemoteEvent|array $expect


<?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\Webhook\Messenger;

use Symfony\Component\RemoteEvent\RemoteEvent;
use Symfony\Component\Webhook\Subscriber;

/**
 * @author Fabien Potencier <fabien@symfony.com>
 */
class SendWebhookMessage
{
    public function __construct(
        private rea

er $subscriber,
        private readonly RemoteEvent $event,
    ) {
    }

    public function getSubscriber(): Subscriber
    {
        return $this->subscriber;
    }

    public function getEvent(): RemoteEvent
    {
        return $this->event;
    }


buted with this source code.
 */

namespace Symfony\Component\AssetMapper;

use Psr\Cache\CacheItemPoolInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfon

EventSubscriberInterface
{
    // source: https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
    private const EXTENSIONS_MAP = [
        'aac' => 'audio/aac',
        'abw' => 'application/x-abiword',
        'arc' =>

y\Component\HttpKernel\Profiler\Profiler;

/**
 * Functions like a controller that returns assets from the asset mapper.
 *
 * @author Ryan Weaver <ryan@symfonycasts.com>
 */
final class AssetMapperDevServerSubscriber implements


buted with this source code.
 */

namespace Symfony\Component\AssetMapper;

use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Finder\Iterator\RecursiveDirectoryIterator;

/**
 * Finds assets in the asset mapper.
 *
 * @author Ryan Weaver <ryan@symfonycasts.com>
 *
 * @final
 */
class AssetMapperRepository
{
    private ?array $absolutePaths = null;

    /**
     * @param string[] $paths Array of assets paths: key is the path, value is the namespace
     *                        (empty strin

nly bool $excludeDotFiles = true,
        private readonly bool $debug = true,
    ) {
    }

    /**
     * Given the logical path - styles/app.css - returns the absolute path to the file.
     */
    public function find(string $logicalPath): ?string

g for no namespace)
     */
    public function __construct(
        private readonly array $paths,
        private readonly string $projectRootDir,
        private readonly array $excludedPathPatterns = [],
        private reado


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

use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Filesystem\Path;

/**
 * Reads and writes compiled configuration files for asset mapper.
 */
class CompiledAssetMapperConfigReader
{
    private readonly Filesystem $filesystem;

h::join($this->directory, $filename));
    }

    public function loadConfig(string $filename): array
    {
        return json_decode($this->filesystem->readFile(Path::join($this->directory, $filename)), true, 512, \JSON_THROW_ON_ERROR);
    }

    public

    public function __construct(
        private readonly string $directory,
    ) {
        $this->filesystem = new Filesystem();
    }

    public function configExists(string $filename): bool
    {
        return is_file(Pat


<?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\AssetMapper\Exception;

use Symfony\Component\AssetMapper\MappedAsset;

/**
 * Thrown when a circular reference is detected while creating an asset.
 */
class CircularAssetsException extends RuntimeException
{
    public function __construct(priv

he circular reference was detected.
     *
     * This asset will not be fully initialized: it will be missing some
     * properties like digest and content.
     */
    public function getIncompleteMappedAsset(): MappedAsset
    {
        return $this->m

ate MappedAsset $mappedAsset, string $message = '', int $code = 0, ?\Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);
    }

    /**
     * Returns the asset that was being created when 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\AssetMapper\Compressor;

use Psr\Log\LoggerInterface;

/**
 * Calls multiple compressors in a chain.
 *
 * @author Kévin Dunglas <kevin@dunglas.dev>
 */
final class ChainCompressor implements CompressorInterface
{
    /**
     * @param CompressorInterface[]

     if (null === $this->compressors) {
            $this->compressors = [];
            foreach ([new BrotliCompressor(), new ZstandardCompressor(), new GzipCompressor()] as $compressor) {
                $unsupportedReason = $compressor->getUnsupportedRe

$compressors
     */
    public function __construct(
        private ?array $compressors = null,
        private readonly ?LoggerInterface $logger = null,
    ) {
    }

    public function compress(string $path): void
    {


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

namespace Symfony\Component\AssetMapper\Compressor;

use Symfony\Component\Process\ExecutableFinder;
use Symfony\Component\Process\Process;

/**
 * @internal
 *
 * @author Kévin Dunglas <kevin@dunglas.dev>
 */
trait CompressorTrait
{
    private ?\Closure $method = null;
    private ?string $executable = null;
    /**
     * @var ?resource
     */
    private $streamContext

essWithExtension(...);

            return;
        }

        if (!class_exists(Process::class)) {
            if ('' === self::WRAPPER) {
                $this->unsupportedReason = \sprintf('%s compression is unsupported. Run "composer require symfony/pr

;
    private ?string $unsupportedReason = null;

    private function initialize(): void
    {
        if ('' !== self::WRAPPER && \in_array(self::WRAPPER, stream_get_wrappers(), true)) {
            $this->method = $this->compr


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\Security\Core\Test;

use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Security\Core\Authentication\Token\NullToken;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Access

terInterface;

/**
 * Abstract test case for access decision strategies.
 *
 * @author Alexander M. Turek <me@derrabus.de>
 */
abstract class AccessDecisionStrategyTestCase extends TestCase
{
    /**
     * @dataProvider provideStrategyTests
     *
     *

DecisionManager;
use Symfony\Component\Security\Core\Authorization\Strategy\AccessDecisionStrategyInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Vote;
use Symfony\Component\Security\Core\Authorization\Voter\Vo


buted with this source code.
 */

namespace Symfony\Component\Security\Core\Signature;

use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
use Symfony\Component\Security\Core\Exception\InvalidArgumentException;
use Symfony\Component\Security\Core\Signature\Exception\ExpiredSignatureException;
use Symfony\Component\Security\Core\Signature\Exception\InvalidSignatureException;
use Symfony\Component\Security\Core\User\UserInterface;

/**
 * Creates and validates secure hashes used in login links an

rties of the User; the hash is invalidated if these properties change
     * @param ExpiredSignatureStorage|null $expiredSignaturesStorage If provided, secures a sequence of hashes that are expired
     * @param int|null                     $maxUses

d remember-me cookies.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 * @author Ryan Weaver <ryan@symfonycasts.com>
 */
class SignatureHasher
{
    /**
     * @param array                        $signatureProperties      Prope


n 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\Webhook\Server;

use Symfony\Component\HttpClient\HttpOptions;
use Symfony\Component\RemoteEvent\RemoteEvent;

/**
 * @author Fabien Potencier <fabien@symfony.com>
 */
final class HeadersConfigurator implements RequestConfiguratorInterface
{
    public function __construct(
        private readonly string $eventHea

string $idHeaderName = 'Webhook-Id',
    ) {
    }

    public function configure(RemoteEvent $event, #[\SensitiveParameter] string $secret, HttpOptions $options): void
    {
        $options->setHeaders([
            $this->eventHeaderName => $event->getN

derName = 'Webhook-Event',
        private readonly


 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\Webhook\Client;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\RemoteEvent\RemoteEvent;
use Symfony\Component\Webhook\Exception\RejectWebhookException;

/**
 * @author Fabien Potencier <fab

   *
     * @throws RejectWebhookException When the payload is rejected (signature issue, parse issue, ...)
     */
    public function parse(Request $request, #[\SensitiveParameter] string $secret): RemoteEvent|array|null;

    /**
     * @param Request|n

ien@symfony.com>
 */
interface RequestParserInterface
{
    /**
     * Parses an HTTP Request and converts it into a RemoteEvent.
     *
     * @return RemoteEvent|RemoteEvent[]|null Returns null if the webhook must be ignored


buted with this source code.
 */

namespace Symfony\Component\Webhook\Tests\Controller;

use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\MessageBus;
use Symfony\Component\Messenger\MessageBusInterface;
use Symfony\Component\RemoteEvent\Messenger\ConsumeRemoteEventMessage;
use Symfony\Component\RemoteEvent\RemoteE

    $controller = new WebhookController([], new MessageBus());

        $response = $controller->handle('foo', new Request());

        $this->assertSame(404, $response->getStatusCode());
    }

    #[DataProvider('rejectedParseProvider')]
    public funct

vent;
use Symfony\Component\Webhook\Client\RequestParserInterface;
use Symfony\Component\Webhook\Controller\WebhookController;

class WebhookControllerTest extends TestCase
{
    public function testNoParserAvailable()
    {


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

use Symfony\Component\AssetMapper\Compiler\AssetCompilerInterface;

/**
 * Runs a chain of compiles intended to adjust the source of assets.
 *
 * @final
 */
class AssetMapperCompiler
{
    private AssetMapperInterface $assetMapper;

    /**

Closure $assetMapperFactory)
    {
    }

    public function compile(string $content, MappedAsset $asset): string
    {
        foreach ($this->assetCompilers as $compiler) {
            if (!$compiler->supports($asset)) {
                continue;

   * @param iterable<AssetCompilerInterface> $assetCompilers
     * @param \Closure(): AssetMapperInterface $assetMapperFactory
     */
    public function __construct(private readonly iterable $assetCompilers, private readonly \


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

namespace Symfony\Component\AssetMapper;

use Symfony\Component\AssetMapper\ImportMap\JavaScriptImport;

/**
 * Represents a single asset in the asset mapper system.
 *
 * @author Ryan Weaver <ryan@symfonycasts.com>
 */
final class MappedAsset
{
    public readonly string $sourcePath;
    public readonly string $publicPath;
    public readonly string $publicPathWithoutDiges

?string $content;

    public readonly string $digest;
    public readonly bool $isPredigested;

    /**
     * @param MappedAsset[]      $dependencies      assets that the content of this asset depends on
     * @param string[]           $fileDependencies

t;
    public readonly string $publicExtension;

    /**
     * The final content of this asset if different from the sourcePath.
     *
     * If null, the content should be read from the sourcePath.
     */
    public readonly


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

use Symfony\Component\Process\Process;

/**
 * Compresses a file using Brotli.
 *
 * @author Kévin Dunglas <kevin@dunglas.dev>
 */
final class BrotliCompressor implements SupportedCompressorInterface
{
    use CompressorTrait;

ble = null,
    ) {
        $this->executable = $executable;
    }

    /**
     * @return resource
     */
    private function createStreamContext()
    {
        return stream_context_create(['brotli' => ['level' => BROTLI_COMPRESS_LEVEL_MAX]]);
    }

    private const WRAPPER = 'compress.brotli';
    private const COMMAND = 'brotli';
    private const PHP_EXTENSION = 'brotli';
    private const FILE_EXTENSION = 'br';

    public function __construct(
        ?string $executa


/*
 * 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\Security\Core\Authorization\Voter;

use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;

/**
 * VoterInterface is the interface implemented by all voters.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface VoterInter

lowing constants:
     * ACCESS_GRANTED, ACCESS_DENIED, or ACCESS_ABSTAIN.
     *
     * @param mixed     $subject    The subject to secure
     * @param mixed[]   $attributes An array of attributes associated with the method being invoked
     * @param Vo

face
{
    public const ACCESS_GRANTED = 1;
    public const ACCESS_ABSTAIN = 0;
    public const ACCESS_DENIED = -1;

    /**
     * Returns the vote for the given parameters.
     *
     * This method must return one of the fol


 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\Webhook\Server;

use Symfony\Component\HttpClient\HttpOptions;
use Symfony\Component\RemoteEvent\RemoteEvent;
use Symfony\Component\Webhook\Exception\InvalidArgumentException;
use Symfony\Component\Webhook\Exception\LogicException;

/**
 * @author Fabien Pot

$signatureHeaderName = 'Webhook-Signature',
    ) {
    }

    public function configure(RemoteEvent $event, #[\SensitiveParameter] string $secret, HttpOptions $options): void
    {
        if (!$secret) {
            throw new InvalidArgumentException('A

encier <fabien@symfony.com>
 */
final class HeaderSignatureConfigurator implements RequestConfiguratorInterface
{
    public function __construct(
        private readonly string $algo = 'sha256',
        private readonly 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\Webhook\Controller;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Messenger\MessageBusInterface;
use Symfony\Component\RemoteEvent\Messenger\ConsumeRemoteEventMessage;
use Symfony\Component\Webhook\Cli

t(
        /** @var array<string, array{parser: RequestParserInterface, secret: string}> $parsers */
        private readonly array $parsers,
        private readonly MessageBusInterface $bus,
    ) {
    }

    public function handle(string $type, Request

ent\RequestParserInterface;

/**
 * Receives webhooks from a variety of third-party providers.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @internal
 */
final class WebhookController
{
    public function __construc


?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\AssetMapper;

/**
 * Finds and returns assets in the pipeline.
 *
 * @author Ryan Weaver <ryan@symfonycasts.com>
 */
interface AssetMapperInterface
{
    /**
     * Given the logical path (e.g. path relative to a mapped directory), return the asse

 Fetches the asset given its source path (i.e. filesystem path).
     */
    public function getAssetFromSourcePath(string $sourcePath): ?MappedAsset;

    /**
     * Returns the public path for this asset, if it can be found.
     */
    public function g

t.
     */
    public function getAsset(string $logicalPath): ?MappedAsset;

    /**
     * Returns all mapped assets.
     *
     * @return iterable<MappedAsset>
     */
    public function allAssets(): iterable;

    /**
     *


 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\AssetMapper\Compressor;

/**
 * Compresses a file.
 *
 * @author Kévin Dunglas <kevin@dunglas.dev>
 */
interface CompressorInterface
{
    // Loosely based on https://caddyserver.com/docs/caddyfile/directives/encode#match
    public const DEFAULT_EXTENSIONS = [

'html',
        'js',
        'json',
        'md',
        'otc',
        'otf',
        'proto',
        'rss',
        'rtf',
        'svg',
        'ttc',
        'ttf',
        'txt',
        'wasm',
        'xml',
    ];

    public function compress

       'css',
        'cur',
        'eot',


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

use Symfony\Component\AssetMapper\Factory\MappedAssetFactoryInterface;

/**
 * Finds and returns assets in the pipeline.
 *
 * @final
 */
class AssetMapper implements AssetMapperInterface
{
    public const MANIFEST_FILE_NAME = 'manifest.json';

    private ?array $manifestData = nu

eader $compiledConfigReader,
    ) {
    }

    public function getAsset(string $logicalPath): ?MappedAsset
    {
        $filePath = $this->mapperRepository->find($logicalPath);
        if (null === $filePath) {
            return null;
        }

ll;

    public function __construct(
        private readonly AssetMapperRepository $mapperRepository,
        private readonly MappedAssetFactoryInterface $mappedAssetFactory,
        private readonly CompiledAssetMapperConfigR


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

use Symfony\Component\Asset\PackageInterface;

/**
 * Decorates asset packages to support resolving assets from the asset mapper.
 *
 * @author Ryan Weaver <ryan@symfonycasts.com>
 */
final class MapperAwareAssetPackage implements Pack

ing
    {
        return $this->innerPackage->getVersion($path);
    }

    public function getUrl(string $path): string
    {
        $publicPath = $this->assetMapper->getPublicPath($path);
        if ($publicPath) {
            $path = ltrim($publicPath,

ageInterface
{
    public function __construct(
        private readonly PackageInterface $innerPackage,
        private readonly AssetMapperInterface $assetMapper,
    ) {
    }

    public function getVersion(string $path): str


 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\Webhook\Server;

use Symfony\Component\HttpClient\HttpOptions;
use Symfony\Component\RemoteEvent\RemoteEvent;
use Symfony\Component\Webhook\Subscriber;
use Symfony\Contracts\HttpClient\HttpClientInterface;

/**
 * @author Fabien Potencier <fabien@symfony.com

 RequestConfiguratorInterface $body,
        private readonly RequestConfiguratorInterface $signer,
    ) {
    }

    public function send(Subscriber $subscriber, RemoteEvent $event): void
    {
        $options = new HttpOptions();

        $this->header

>
 */
class Transport implements TransportInterface
{
    public function __construct(
        private readonly HttpClientInterface $client,
        private readonly RequestConfiguratorInterface $headers,
        private readonly


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\AssetMapper\Command;

use Symfony\Component\AssetMapper\Compressor\CompressorInterface;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symf

sets:compress', description: 'Pre-compresses files to serve through a web server')]
final class CompressAssetsCommand extends Command
{
    public function __construct(
        private readonly CompressorInterface $compressor,
    ) {
        parent::__con

ony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

/**
 * Pre-compresses files to serve through a web server.
 *
 * @author Kévin Dunglas <kevin@dunglas.dev>
 */
#[AsCommand(name: 'as


buted with this source code.
 */

namespace Symfony\Component\AssetMapper\Tests\ImportMap;

use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Symfony\Component\AssetMapper\Exception\RuntimeException;
use Symfony\Component\AssetMapper\ImportMap\ImportMapAuditor;
use Symfony\Component\AssetMapper\ImportMap\ImportMapConfigReader;
use Symfony\Component\AssetMapper\ImportMap\ImportMapEntries;
use Symfony\Component\AssetMapper\ImportMap\ImportMapEntry;
use Symfony\Component\AssetM

e Symfony\Component\HttpClient\Response\JsonMockResponse;
use Symfony\Component\HttpClient\Response\MockResponse;
use Symfony\Contracts\HttpClient\HttpClientInterface;

class ImportMapAuditorTest extends TestCase
{
    private ImportMapConfigReader $import

apper\ImportMap\ImportMapPackageAudit;
use Symfony\Component\AssetMapper\ImportMap\ImportMapPackageAuditVulnerability;
use Symfony\Component\AssetMapper\ImportMap\ImportMapType;
use Symfony\Component\HttpClient\MockHttpClient;
us


buted with this source code.
 */

namespace Symfony\Component\AssetMapper\Tests\ImportMap;

use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Symfony\Component\AssetMapper\Exception\RuntimeException;
use Symfony\Component\AssetMapper\ImportMap\ImportMapConfigReader;
use Symfony\Component\AssetMapper\ImportMap\ImportMapEntries;
use Symfony\Component\AssetMapper\ImportMap\ImportMapEntry;
use Symfony\Component\AssetMapper\ImportMap\ImportMapType;
use Symfony\Component\AssetMapp

lesystem = new Filesystem();
        if (!file_exists(__DIR__.'/../Fixtures/importmap_config_reader/assets')) {
            $this->filesystem->mkdir(__DIR__.'/../Fixtures/importmap_config_reader/assets');
        }
    }

    protected function tearDown():

er\ImportMap\RemotePackageStorage;
use Symfony\Component\Filesystem\Filesystem;

class ImportMapConfigReaderTest extends TestCase
{
    private Filesystem $filesystem;

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


 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\AssetMapper\Tests\ImportMap;

use PHPUnit\Framework\TestCase;
use Symfony\Component\AssetMapper\ImportMap\ImportMapEntries;
use Symfony\Component\AssetMapper\ImportMap\ImportMapEntry;
use Symfony\Component\AssetMapper\ImportMap\ImportMapType;

class ImportMapEntriesTest

 'path2', false);

        $entries = new ImportMapEntries([$entry1]);
        $entries->add($entry2);

        $this->assertSame([$entry1, $entry2], iterator_to_array($entries));
    }

    public function testHas()
    {
        $entries = new ImportMapE

extends TestCase
{
    public function testGetIterator()
    {
        $entry1 = ImportMapEntry::createLocal('entry1', ImportMapType::JS, 'path1', true);
        $entry2 = ImportMapEntry::createLocal('entry2', ImportMapType::CSS,


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\AssetMapper\Tests\ImportMap;

use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Symfony\Component\AssetMapper\ImportMap\ImportMapEntry;
use Symfony\Component\AssetMapper\ImportMap\ImportMapType;

class ImportMapEntryTest extends TestCase
{
    public function test

 $this->assertSame('foo.js', $entry->path);
        $this->assertTrue($entry->isEntrypoint);
        $this->assertFalse($entry->isRemotePackage());
    }

    public function testCreateRemote()
    {
        $entry = ImportMapEntry::createRemote('foo', Imp

CreateLocal()
    {
        $entry = ImportMapEntry::createLocal('foo', ImportMapType::JS, 'foo.js', true);
        $this->assertSame('foo', $entry->importName);
        $this->assertSame(ImportMapType::JS, $entry->type);


ny\Component\AssetMapper\ImportMap\JavaScriptImport;
use Symfony\Component\AssetMapper\MappedAsset;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Filesystem\Path;

class ImportMapGeneratorTest extends TestCase
{
    private AssetMapperInterface $assetMapper;
    private CompiledAssetMapperConfigReader $compiledConfigReader;
    private ImportMapConfigReader $configReader;

    private Filesystem $filesystem;
    private static string $writableRoot = __DIR__.'/../Fixtures/importmap_gener

    }
    }

    protected function tearDown(): void
    {
        $this->filesystem->remove(self::$writableRoot);
    }

    public function testGetEntrypointNames()
    {
        $manager = $this->createImportMapGenerator();
        $this->mockImportMap(

ator';

    protected function setUp(): void
    {
        $this->filesystem = new Filesystem();
        if (!file_exists(self::$writableRoot.'/assets')) {
            $this->filesystem->mkdir(self::$writableRoot.'/assets');


\ImportMap\PackageRequireOptions;
use Symfony\Component\AssetMapper\ImportMap\RemotePackageDownloader;
use Symfony\Component\AssetMapper\ImportMap\Resolver\PackageResolverInterface;
use Symfony\Component\AssetMapper\ImportMap\Resolver\ResolvedImportMapPackage;
use Symfony\Component\AssetMapper\MappedAsset;
use Symfony\Component\Filesystem\Filesystem;

class ImportMapManagerTest extends TestCase
{
    private AssetMapperInterface $assetMapper;
    private PackageResolverInterface $packageResolver;
    privat

r';

    protected function setUp(): void
    {
        $this->filesystem = new Filesystem();
        if (!file_exists(__DIR__.'/../Fixtures/importmap_manager/assets')) {
            $this->filesystem->mkdir(self::$writableRoot.'/assets');
        }
    }

e ImportMapConfigReader&MockObject $configReader;
    private RemotePackageDownloader $remotePackageDownloader;

    private Filesystem $filesystem;
    private static string $writableRoot = __DIR__.'/../Fixtures/importmap_manage


 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\AssetMapper\Tests\ImportMap;

use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Symfony\Component\AssetMapper\Command\ImportMapOutdatedCommand;
use Symfony\Component\AssetMapper\ImportMap\ImportMapUpdateChecker;
use Symfony\C

rmat = null)
    {
        $updateChecker = $this->createStub(ImportMapUpdateChecker::class);
        $command = new ImportMapOutdatedCommand($updateChecker);

        $commandTester = new CommandTester($command);
        $commandTester->execute(\is_string

omponent\Console\Tester\CommandTester;

class ImportMapOutdatedCommandTest extends TestCase
{
    #[DataProvider('provideNoOutdatedPackageCases')]
    public function testCommandWhenNoOutdatedPackages(string $display, ?string $fo


\ImportMapGenerator;
use Symfony\Component\AssetMapper\ImportMap\ImportMapRenderer;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\WebLink\GenericLinkProvider;

class ImportMapRendererTest extends TestCase
{
    public function testBasicRender()
    {
        $importMapGenerator = $this->createMock(ImportMapGenerator::class);
        $importMapGenerator->expects($this->once())
            ->method('getImportMapData')
            ->with(

,
                'app_js_no_preload' => [
                    'path' => '/assets/app-nopreload-d1g35t.js',
                    'type' => 'js',
                ],
                'app_css_preload' => [
                    'path' => '/assets/styles/app-prel

['app'])
            ->willReturn([
                'app_js_preload' => [
                    'path' => '/assets/app-preload-d1g35t.js',
                    'type' => 'js',
                    'preload' => true,
                ]


buted with this source code.
 */

namespace Symfony\Component\AssetMapper\Tests\ImportMap;

use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Symfony\Component\AssetMapper\ImportMap\ImportMapConfigReader;
use Symfony\Component\AssetMapper\ImportMap\ImportMapEntries;
use Symfony\Component\AssetMapper\ImportMap\ImportMapEntry;
use Symfony\Component\AssetMapper\ImportMap\ImportMapType;
use Symfony\Component\AssetMapper\ImportMap\ImportMapUpdateChecker;
use Symfony\Component\Ass

kerTest extends TestCase
{
    private ImportMapConfigReader $importMapConfigReader;
    private ImportMapUpdateChecker $updateChecker;

    protected function setUp(): void
    {
        $this->importMapConfigReader = $this->createStub(ImportMapConfigRead

etMapper\ImportMap\PackageUpdateInfo;
use Symfony\Component\HttpClient\MockHttpClient;
use Symfony\Component\HttpClient\Response\JsonMockResponse;
use Symfony\Component\HttpClient\Response\MockResponse;

class ImportMapUpdateChec


ImportMap\ImportMapConfigReader;
use Symfony\Component\AssetMapper\ImportMap\ImportMapEntries;
use Symfony\Component\AssetMapper\ImportMap\ImportMapEntry;
use Symfony\Component\AssetMapper\ImportMap\ImportMapType;
use Symfony\Component\AssetMapper\ImportMap\ImportMapVersionChecker;
use Symfony\Component\AssetMapper\ImportMap\PackageVersionProblem;
use Symfony\Component\AssetMapper\ImportMap\RemotePackageDownloader;
use Symfony\Component\HttpClient\MockHttpClient;
use Symfony\Component\HttpClient\Response\Mo

pectedProblems)
    {
        $configReader = $this->createMock(ImportMapConfigReader::class);
        $configReader->expects($this->once())
            ->method('getEntries')
            ->willReturn(new ImportMapEntries($importMapEntries));

        $rem

ckResponse;

class ImportMapVersionCheckerTest extends TestCase
{
    #[DataProvider('getCheckVersionsTests')]
    public function testCheckVersions(array $importMapEntries, array $dependencies, array $expectedRequests, array $ex


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\AssetMapper\Tests\ImportMap;

use PHPUnit\Framework\TestCase;
use Symfony\Component\AssetMapper\ImportMap\JavaScriptImport;

class JavaScriptImportTest extends TestCase
{
    public function testBasicConstruction()
    {
        $import = new JavaScriptImport('the-import', 'the-as

his->assertSame('the-import', $import->importName);
        $this->assertTrue($import->isLazy);
        $this->assertSame('the-asset', $import->assetLogicalPath);
        $this->assertSame('/path/to/the-asset', $import->assetSourcePath);
        $this->ass

set', '/path/to/the-asset', true, true);

        $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\AssetMapper\Tests\ImportMap;

use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Symfony\Component\AssetMapper\ImportMap\PackageUpdateInfo;

class PackageUpdateInfoTest extends TestCase
{
    #[DataProvider('provideValidConstructorArguments')]
    public function t

testVersion: $latestVersion,
            updateType: $updateType,
        );

        $this->assertSame($importName, $packageUpdateInfo->packageName);
        $this->assertSame($currentVersion, $packageUpdateInfo->currentVersion);
        $this->assertSame

estConstructor($importName, $currentVersion, $latestVersion, $updateType)
    {
        $packageUpdateInfo = new PackageUpdateInfo(
            packageName: $importName,
            currentVersion: $currentVersion,
            la


mponent\AssetMapper\ImportMap\ImportMapEntries;
use Symfony\Component\AssetMapper\ImportMap\ImportMapEntry;
use Symfony\Component\AssetMapper\ImportMap\ImportMapType;
use Symfony\Component\AssetMapper\ImportMap\RemotePackageDownloader;
use Symfony\Component\AssetMapper\ImportMap\RemotePackageStorage;
use Symfony\Component\AssetMapper\ImportMap\Resolver\PackageResolverInterface;
use Symfony\Component\Filesystem\Filesystem;

class RemotePackageDownloaderTest extends TestCase
{
    private Filesystem $filesyst

tableRoot);
    }

    protected function tearDown(): void
    {
        $this->filesystem->remove(self::$writableRoot);
    }

    public function testDownloadPackagesDownloadsEverythingWithNoInstalled()
    {
        $configReader = $this->createMock(Imp

em;
    private static string $writableRoot = __DIR__.'/../Fixtures/remote_package_downloader';

    protected function setUp(): void
    {
        $this->filesystem = new Filesystem();
        $this->filesystem->mkdir(self::$wri


buted with this source code.
 */

namespace Symfony\Component\AssetMapper\Tests\ImportMap;

use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Symfony\Component\AssetMapper\ImportMap\ImportMapEntry;
use Symfony\Component\AssetMapper\ImportMap\ImportMapType;
use Symfony\Component\AssetMapper\ImportMap\RemotePackageStorage;
use Symfony\Component\Filesystem\Filesystem;

class RemotePackageStorageTest extends TestCase
{
    private Filesystem $filesystem;
    private static strin

esystem = new Filesystem();
        $this->filesystem->mkdir(self::$writableRoot);
    }

    protected function tearDown(): void
    {
        $this->filesystem->remove(self::$writableRoot);
    }

    public function testGetStorageDir()
    {
        $st

g $writableRoot;
    private static int $writableRootIndex = 0;

    protected function setUp(): void
    {
        self::$writableRoot = sys_get_temp_dir().'/remote_package_storage'.++self::$writableRootIndex;
        $this->fil


provideResolvePackagesTests')]
    public function testResolvePackages(array $packages, array $expectedRequests, array $expectedResolvedPackages)
    {
        $responses = [];
        foreach ($expectedRequests as $expectedRequest) {
            $responses[] = function ($method, $url) use ($expectedRequest) {
                $this->assertSame('GET', $method);
                $this->assertStringEndsWith($expectedRequest['url'], $url);

                $body = 'any body';
                if (isset($expectedR

     return new MockResponse($body);
            };
        }

        $httpClient = new MockHttpClient($responses);

        $provider = new JsDelivrEsmResolver($httpClient);
        $actualResolvedPackages = $provider->resolvePackages($packages);

equest['response']['body'])) {
                    $body = \is_array($expectedRequest['response']['body']) ? json_encode($expectedRequest['response']['body']) : $expectedRequest['response']['body'];
                }


buted with this source code.
 */

namespace Symfony\Component\AssetMapper\Tests\Command;

use PHPUnit\Framework\TestCase;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\AssetMapper\Event\PreAssetsCompileEvent;
use Symfony\Component\AssetMapper\Tests\Fixtures\AssetMapperTestAppKernel;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Tester\CommandTester;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\File

id
    {
        $this->filesystem = new Filesystem();
        $this->kernel = new AssetMapperTestAppKernel('test', true);
        $this->filesystem->mkdir($this->kernel->getProjectDir().'/public');
    }

    protected function tearDown(): void
    {

system\Filesystem;
use Symfony\Component\Finder\Finder;

class AssetMapperCompileCommandTest extends TestCase
{
    private AssetMapperTestAppKernel $kernel;
    private Filesystem $filesystem;

    protected function setUp(): vo


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

namespace Symfony\Component\AssetMapper\Tests\Command;

use PHPUnit\Framework\TestCase;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\AssetMapper\Tests\Fixtures\AssetMapperTestAppKernel;
use Symfony\Component\Console\Tester\CommandTester;

class DebugAssetsMapperCommandTest extends TestCase
{
    public function testCommandDumpsInformation()

]);
        $this->assertSame(0, $res);

        $this->assertStringContainsString('dir1', $tester->getDisplay());
        $this->assertStringContainsString('subdir/file6.js', $tester->getDisplay());
        $this->assertStringContainsString('dir2'.\DIRECT

    {
        $application = new Application(new AssetMapperTestAppKernel('test', true));

        $command = $application->find('debug:asset-map');
        $tester = new CommandTester($command);
        $res = $tester->execute([


buted with this source code.
 */

namespace Symfony\Component\AssetMapper\Tests\Command;

use PHPUnit\Framework\Attributes\DataProvider;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\AssetMapper\Command\ImportMapRequireCommand;
use Symfony\Component\AssetMapper\ImportMap\ImportMapEntry;
use Symfony\Component\AssetMapper\ImportMap\ImportMapManager;
use Symfony\Component\AssetMapper\ImportMap\ImportMapType;
use Symfony\Com

er;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Finder\Finder;

class ImportMapRequireCommandTest extends KernelTestCase
{
    protected static function getKernelClass(): string
    {
        return ImportMapTestAppKernel::class;

ponent\AssetMapper\ImportMap\ImportMapVersionChecker;
use Symfony\Component\AssetMapper\Tests\Fixtures\ImportMapTestAppKernel;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Tester\CommandTest


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

namespace Symfony\Component\OptionsResolver;

use Symfony\Component\OptionsResolver\Exception\AccessException;

final class OptionConfigurator
{
    public function __construct(
        private string $name,
        private OptionsResolver $resolver,
    ) {
        $this->resolver->setDefined($name);
    }

    /**
     * Adds allowed types for this option.
     *
     * @

        return $this;
    }

    /**
     * Sets allowed values for this option.
     *
     * @param mixed ...$values One or more acceptable values/closures
     *
     * @return $this
     *
     * @throws AccessException If called from a lazy option o

return $this
     *
     * @throws AccessException If called from a lazy option or normalizer
     */
    public function allowedTypes(string ...$types): static
    {
        $this->resolver->setAllowedTypes($this->name, $types);


efined options.
     */
    private array $defined = [];

    /**
     * The default option values.
     */
    private array $defaults = [];

    /**
     * A list of closure for nested options.
     *
     * @var \Closure[][]
     */
    private array $nested = [];

    /**
     * The names of required options.
     */
    private array $required = [];

    /**
     * The resolved option values.
     */
    private array $resolved = [];

    /**
     * A list of normalizer closures.
     *
     * @var \Cl

  private array $allowedTypes = [];

    /**
     * A list of info messages for each option.
     */
    private array $info = [];

    /**
     * A list of closures for evaluating lazy options.
     */
    private array $lazy = [];

    /**
     * A list

osure[][]
     */
    private array $normalizers = [];

    /**
     * A list of accepted values for each option.
     */
    private array $allowedValues = [];

    /**
     * A list of accepted types for each option.
     */


* 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\OptionsResolver\Exception;

/**
 * Thrown when trying to read an option that has no value set.
 *
 * When accessing optional options from within a lazy option or normalizer you should first
 * check whether the optional option is set. You can do this with `

{@link UndefinedOptionsException}, this is a runtime exception that can
 * occur when evaluating lazy options.
 *
 * @author Tobias Schultze <http://tobion.de>
 */
class NoSuchOptionException extends \OutOfBoundsException implements ExceptionInterface
{
}

isset($options['optional'])`.
 * In contrast to the


();
    }

    public function testSetDefaultReturnsThis()
    {
        $this->assertSame($this->resolver, $this->resolver->setDefault('foo', 'bar'));
    }

    public function testSetDefault()
    {
        $this->resolver->setDefault('one', '1');
        $this->resolver->setDefault('two', '20');

        $this->assertEquals([
            'one' => '1',
            'two' => '20',
        ], $this->resolver->resolve());
    }

    public function testFailIfSetDefaultFromLazyOption()
    {
        $this->ex

public function testHasDefault()
    {
        $this->assertFalse($this->resolver->hasDefault('foo'));
        $this->resolver->setDefault('foo', 42);
        $this->assertTrue($this->resolver->hasDefault('foo'));
    }

    public function testHasDefaultW

pectException(AccessException::class);
        $this->resolver->setDefault('lazy', static function (Options $options) {
            $options->setDefault('default', 42);
        });

        $this->resolver->resolve();
    }


ony\Component\OptionsResolver\Exception\NoConfigurationException;
use Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;

class OptionsResolverIntrospectorTest extends TestCase
{
    public function testGetDefault()
    {
        $resolver = new OptionsResolver();
        $resolver->setDefault($option = 'foo', 'bar');

        $debug = new OptionsResolverIntrospector($resolver);

ptionsResolverIntrospector($resolver);
        $this->assertNull($debug->getDefault($option));
    }

    public function testGetDefaultThrowsOnNoConfiguredValue()
    {
        $this->expectException(NoConfigurationException::class);
        $this->expect

$this->assertSame('bar', $debug->getDefault($option));
    }

    public function testGetDefaultNull()
    {
        $resolver = new OptionsResolver();
        $resolver->setDefault($option = 'foo', null);

        $debug = new O


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

namespace Symfony\Component\OptionsResolver\Debug;

use Symfony\Component\OptionsResolver\Exception\NoConfigurationException;
use Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException;
use Symfony\Component\OptionsResolver\OptionsResolver;

/**
 * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
 *
 * @final
 */
class OptionsResolverIntrospector
{

        if (!$this->isDefined($option)) {
                throw new UndefinedOptionsException(\sprintf('The option "%s" does not exist.', $option));
            }

            if (!\array_key_exists($option, $this->{$property})) {
                throw new

    private \Closure $get;

    public function __construct(OptionsResolver $optionsResolver)
    {
        $this->get = \Closure::bind(function ($property, $option, $message) {
            /** @var OptionsResolver $this */


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

namespace Symfony\Component\Stopwatch;

/**
 * Stopwatch section.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Section
{
    /**
     * @var StopwatchEvent[]
     */
    private array $events = [];

    private ?string $id = null;

    /**
     * @var Section[]
     */
    private array $children = [];

    /**
     * @param float|null $origin        Set th

ion __construct(
        private ?float $origin = null,
        private bool $morePrecision = false,
    ) {
    }

    /**
     * Returns the child section.
     */
    public function get(string $id): ?self
    {
        foreach ($this->children as $chil

e origin of the events in this section, use null to set their origin to their start time
     * @param bool       $morePrecision If true, time is stored as float to keep the original microsecond precision
     */
    public funct


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

namespace Symfony\Component\Stopwatch;

use Symfony\Contracts\Service\ResetInterface;

// Help opcache.preload discover always-needed symbols
class_exists(Section::class);

/**
 * Stopwatch provides a way to profile code.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Stopwatch implements ResetInterface
{
    public const ROOT = '__root__';

    /**
     * @v

ond precision
     */
    public function __construct(
        private bool $morePrecision = false,
    ) {
        $this->reset();
    }

    /**
     * @return Section[]
     */
    public function getSections(): array
    {
        return $this->section

ar Section[]
     */
    private array $sections;

    /**
     * @var Section[]
     */
    private array $activeSections;

    /**
     * @param bool $morePrecision If true, time is stored as float to keep the original microsec


buted with this source code.
 */

namespace Symfony\Component\Stopwatch;

/**
 * Represents an Event managed by Stopwatch.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class StopwatchEvent
{
    /**
     * @var StopwatchPeriod[]
     */
    private array $periods = [];

    private float $origin;
    private string $category;

    /**
     * @var float[]
     */
    private array $started = [];

    private string $name;

    /**
     * @param float       $origin        The origin time in millise

g|null $name          The event name or null to define the name as default
     */
    public function __construct(
        float $origin,
        ?string $category = null,
        private bool $morePrecision = false,
        ?string $name = null,
    ) {

conds
     * @param string|null $category      The event category or null to use the default
     * @param bool        $morePrecision If true, time is stored as float to keep the original microsecond precision
     * @param strin