diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index 2ec23cd..0000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,88 +0,0 @@ -name: CI - -on: - pull_request: ~ - push: - branches: - - master - -jobs: - php-cs-fixer: - name: PHP-CS-Fixer - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: PHP-CS-Fixer - uses: docker://oskarstark/php-cs-fixer-ga - - build: - name: Build - runs-on: Ubuntu-20.04 - strategy: - fail-fast: false - matrix: - php: ['7.1', '7.2', '7.3', '7.4', '8.0'] - composer: [''] - phpunit: [''] - deprecation: [''] - symfony: [''] - stability: [''] - include: - # Minimum supported dependencies with the latest and oldest PHP version - - php: 8.0 - composer: --prefer-stable --prefer-lowest - deprecation: max[direct]=0 - - php: 7.1 - composer: --prefer-stable --prefer-lowest - deprecation: max[direct]=0 - - # symfony version - - php: 8.0 - symfony: '^3.0' - - php: 8.0 - symfony: '^4.0' - - php: 8.0 - symfony: '^5.0' - - # dev - - php: 8.0 - stability: 'dev' - - steps: - - name: Set up PHP - uses: shivammathur/setup-php@2.7.0 - with: - php-version: ${{ matrix.php }} - coverage: none - tools: flex - - - name: Checkout code - uses: actions/checkout@v2 - - - name: Setup stability - if: matrix.stability != '' - run: composer config minimum-stability "${{ matrix.stability }}" - - - name: Setup deprecation - if: matrix.deprecation != '' - run: echo 'SYMFONY_DEPRECATIONS_HELPER=${{ matrix.deprecation }}' >> $GITHUB_ENV - - - name: Setup symfony - if: matrix.symfony != '' - run: | - echo 'SYMFONY_REQUIRE=${{ matrix.symfony }}' >> $GITHUB_ENV - - - name: Download dependencies - run: | - composer update ${{ matrix.composer}} --prefer-dist --no-interaction - ./vendor/bin/simple-phpunit install - - - name: Validate - run: | - composer validate --strict --no-check-lock - - - name: Run tests - env: - SYMFONY_PHPUNIT_REMOVE_RETURN_TYPEHINT: 1 - run: | - ${{ matrix.phpunit }} ./vendor/bin/simple-phpunit diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml new file mode 100644 index 0000000..ce110ea --- /dev/null +++ b/.github/workflows/static.yml @@ -0,0 +1,43 @@ +on: [pull_request] +name: Static analysis +jobs: + php-cs-fixer: + name: 🧽 PHP-CS-Fixer + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 8.3 + + - name: Install php-cs-fixer + uses: ramsey/composer-install@v2 + with: + composer-options: "--working-dir=tools/php-cs-fixer" + + - name: PHP-CS-Fixer + run: tools/php-cs-fixer/vendor/bin/php-cs-fixer fix --dry-run --diff --config=.php-cs-fixer.dist.php + + audit: + name: 🔍 Audit vendors + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 8.3 + + - name: Download dependencies + uses: ramsey/composer-install@v2 + + - name: Check whether a PHP dependency is compromised + shell: bash + run: composer audit diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..0e81098 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,52 @@ +on: [pull_request] +name: PHPUnit + +jobs: + tests: + name: Tests + runs-on: Ubuntu-20.04 + + strategy: + matrix: + include: + # Lowest Deps + - php: 8.1 + symfony-require: 5.4.* + composer-flags: '--prefer-stable --prefer-lowest' + # LTS with latest stable PHP + - php: 8.2 + symfony-require: 6.4.* + composer-flags: '--prefer-stable' + # Active release + - php: 8.3 + symfony-require: 7.1.* + composer-flags: '--prefer-stable --ignore-platform-req=php+' + # Development release + - php: nightly + symfony-require: 7.1.*@dev + composer-flags: '--ignore-platform-req=php+' + stability: dev + can-fail: true + fail-fast: false + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + coverage: none + + - name: Configure Composer minimum stability + if: matrix.stability + run: composer config minimum-stability ${{ matrix.stability }} + + - name: Install dependencies + env: + SYMFONY_REQUIRE: ${{ matrix.symfony-require }} + run: composer update ${{ matrix.composer-flags }} --no-interaction --no-progress --optimize-autoloader + + - name: Run PHPUnit + run: vendor/bin/simple-phpunit diff --git a/.gitignore b/.gitignore index cc2b86b..f740713 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,4 @@ .php_cs.cache -build -phpunit.xml -coverage -composer.lock -vendor +/composer.lock +/vendor +/tools/**/vendor diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php index 400a82f..59d23b8 100644 --- a/.php-cs-fixer.php +++ b/.php-cs-fixer.php @@ -10,6 +10,7 @@ EOF; return (new PhpCsFixer\Config()) + ->setParallelConfig(PhpCsFixer\Runner\Parallel\ParallelConfigFactory::detect()) ->setRiskyAllowed(true) ->setRules([ '@Symfony' => true, diff --git a/Command/NotifyDeploymentCommand.php b/Command/NotifyDeploymentCommand.php index d6e5ab7..6067b1e 100644 --- a/Command/NotifyDeploymentCommand.php +++ b/Command/NotifyDeploymentCommand.php @@ -79,7 +79,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int switch ($response['status']) { case 200: case 201: - $output->writeLn(sprintf("Recorded deployment to '%s' (%s)", $appName, ($input->getOption('description') ?: date('r')))); + $output->writeLn(sprintf("Recorded deployment to '%s' (%s)", $appName, $input->getOption('description') ?: date('r'))); break; case 403: $output->writeLn(sprintf("Deployment not recorded to '%s': API key invalid", $appName)); @@ -153,19 +153,19 @@ private function createPayload(string $appName, InputInterface $input): string 'deployment[app_name]' => $appName, ]; - if (($user = $input->getOption('user'))) { + if ($user = $input->getOption('user')) { $content_array['deployment[user]'] = $user; } - if (($revision = $input->getOption('revision'))) { + if ($revision = $input->getOption('revision')) { $content_array['deployment[revision]'] = $revision; } - if (($changelog = $input->getOption('changelog'))) { + if ($changelog = $input->getOption('changelog')) { $content_array['deployment[changelog]'] = $changelog; } - if (($description = $input->getOption('description'))) { + if ($description = $input->getOption('description')) { $content_array['deployment[description]'] = $description; } diff --git a/DependencyInjection/Compiler/MonologHandlerPass.php b/DependencyInjection/Compiler/MonologHandlerPass.php index 6dc42b2..f060680 100644 --- a/DependencyInjection/Compiler/MonologHandlerPass.php +++ b/DependencyInjection/Compiler/MonologHandlerPass.php @@ -53,7 +53,10 @@ public function process(ContainerBuilder $container): void } } - private function getChannels(ContainerBuilder $container) + /** + * @return string[] + */ + private function getChannels(ContainerBuilder $container): array { $channels = []; foreach ($container->getDefinitions() as $id => $definition) { @@ -61,7 +64,7 @@ private function getChannels(ContainerBuilder $container) $channels[] = 'app'; continue; } - if (0 === strpos($id, 'monolog.logger.')) { + if (str_starts_with($id, 'monolog.logger.')) { $channels[] = substr($id, 15); } } diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index ca84e75..507d786 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -132,7 +132,7 @@ public function getConfigTreeBuilder(): TreeBuilder $elements = []; foreach ($v['elements'] as $element) { - if (0 === strpos($element, '!')) { + if (str_starts_with($element, '!')) { if (false === $isExclusive) { throw new InvalidConfigurationException('Cannot combine exclusive/inclusive definitions in channels list.'); } diff --git a/EkinoNewRelicBundle.php b/EkinoNewRelicBundle.php index 3c2b092..5f19205 100644 --- a/EkinoNewRelicBundle.php +++ b/EkinoNewRelicBundle.php @@ -20,14 +20,14 @@ class EkinoNewRelicBundle extends Bundle { - public function build(ContainerBuilder $container) + public function build(ContainerBuilder $container): void { parent::build($container); $container->addCompilerPass(new MonologHandlerPass()); } - public function boot() + public function boot(): void { parent::boot(); @@ -36,7 +36,7 @@ public function boot() } } - public function shutdown() + public function shutdown(): void { if ($this->container->has(DeprecationListener::class)) { $this->container->get(DeprecationListener::class)->unregister(); diff --git a/Listener/RequestListener.php b/Listener/RequestListener.php index f8fa6a8..a570e17 100644 --- a/Listener/RequestListener.php +++ b/Listener/RequestListener.php @@ -51,9 +51,9 @@ public static function getSubscribedEvents(): array { return [ KernelEvents::REQUEST => [ - ['setApplicationName', 255], - ['setIgnoreTransaction', 31], - ['setTransactionName', -10], + ['setApplicationName', 255], + ['setIgnoreTransaction', 31], + ['setTransactionName', -10], ], ]; } @@ -75,7 +75,7 @@ public function setApplicationName(KernelRequestEvent $event): void } // Set application name if different from ini configuration - if ($appName !== ini_get('newrelic.appname')) { + if ($appName !== \ini_get('newrelic.appname')) { $this->interactor->setApplicationName($appName, $this->config->getLicenseKey(), $this->config->getXmit()); } } @@ -112,7 +112,7 @@ public function setIgnoreTransaction(KernelRequestEvent $event): void */ private function isEventValid(KernelRequestEvent $event): bool { - return HttpKernelInterface::MASTER_REQUEST === $event->getRequestType(); + return HttpKernelInterface::MAIN_REQUEST === $event->getRequestType(); } } diff --git a/Listener/ResponseListener.php b/Listener/ResponseListener.php index a299abc..0db7b5a 100644 --- a/Listener/ResponseListener.php +++ b/Listener/ResponseListener.php @@ -35,7 +35,7 @@ public function __construct( NewRelicInteractorInterface $interactor, bool $instrument = false, bool $symfonyCache = false, - NewRelicExtension $newRelicTwigExtension = null + ?NewRelicExtension $newRelicTwigExtension = null ) { $this->newRelic = $newRelic; $this->interactor = $interactor; diff --git a/Logging/AdaptiveHandler.php b/Logging/AdaptiveHandler.php index 396fa67..42b20d7 100644 --- a/Logging/AdaptiveHandler.php +++ b/Logging/AdaptiveHandler.php @@ -14,6 +14,7 @@ namespace Ekino\NewRelicBundle\Logging; use Monolog\Handler\NewRelicHandler; +use Monolog\LogRecord; use Psr\Log\LogLevel; class AdaptiveHandler extends NewRelicHandler @@ -21,14 +22,14 @@ class AdaptiveHandler extends NewRelicHandler public function __construct( string $level = LogLevel::ERROR, bool $bubble = true, - string $appName = null, + ?string $appName = null, bool $explodeArrays = false, - string $transactionName = null + ?string $transactionName = null ) { parent::__construct($level, $bubble, $appName, $explodeArrays, $transactionName); } - protected function write(array $record): void + protected function write(LogRecord $record): void { if (!$this->isNewRelicEnabled()) { return; diff --git a/NewRelic/AdaptiveInteractor.php b/NewRelic/AdaptiveInteractor.php index ef4d9b9..af6d53b 100644 --- a/NewRelic/AdaptiveInteractor.php +++ b/NewRelic/AdaptiveInteractor.php @@ -30,7 +30,7 @@ public function __construct(NewRelicInteractorInterface $real, NewRelicInteracto $this->interactor = \extension_loaded('newrelic') ? $real : $fake; } - public function setApplicationName(string $name, string $license = null, bool $xmit = false): bool + public function setApplicationName(string $name, ?string $license = null, bool $xmit = false): bool { return $this->interactor->setApplicationName($name, $license, $xmit); } @@ -75,7 +75,7 @@ public function disableAutoRUM(): ?bool return $this->interactor->disableAutoRUM(); } - public function noticeThrowable(\Throwable $e, string $message = null): void + public function noticeThrowable(\Throwable $e, ?string $message = null): void { $this->interactor->noticeThrowable($e, $message); } @@ -83,9 +83,9 @@ public function noticeThrowable(\Throwable $e, string $message = null): void public function noticeError( int $errno, string $errstr, - string $errfile = null, - int $errline = null, - string $errcontext = null + ?string $errfile = null, + ?int $errline = null, + ?string $errcontext = null ): void { $this->interactor->noticeError($errno, $errstr, $errfile, $errline, $errcontext); } @@ -100,7 +100,7 @@ public function disableBackgroundJob(): void $this->interactor->disableBackgroundJob(); } - public function startTransaction(string $name = null, string $license = null): bool + public function startTransaction(?string $name = null, ?string $license = null): bool { return $this->interactor->startTransaction($name, $license); } diff --git a/NewRelic/BlackholeInteractor.php b/NewRelic/BlackholeInteractor.php index 9d77bf4..3704e4e 100644 --- a/NewRelic/BlackholeInteractor.php +++ b/NewRelic/BlackholeInteractor.php @@ -20,7 +20,7 @@ */ class BlackholeInteractor implements NewRelicInteractorInterface { - public function setApplicationName(string $name, string $license = null, bool $xmit = false): bool + public function setApplicationName(string $name, ?string $license = null, bool $xmit = false): bool { return true; } @@ -63,16 +63,16 @@ public function disableAutoRUM(): ?bool return true; } - public function noticeThrowable(\Throwable $e, string $message = null): void + public function noticeThrowable(\Throwable $e, ?string $message = null): void { } public function noticeError( int $errno, string $errstr, - string $errfile = null, - int $errline = null, - string $errcontext = null + ?string $errfile = null, + ?int $errline = null, + ?string $errcontext = null ): void { } @@ -84,7 +84,7 @@ public function disableBackgroundJob(): void { } - public function startTransaction(string $name = null, string $license = null): bool + public function startTransaction(?string $name = null, ?string $license = null): bool { return true; } diff --git a/NewRelic/Config.php b/NewRelic/Config.php index 875d55a..d392053 100644 --- a/NewRelic/Config.php +++ b/NewRelic/Config.php @@ -20,7 +20,7 @@ class Config { private $name; private $apiKey; - private $apiHost = null; + private $apiHost; private $licenseKey; private $xmit; private $customEvents; @@ -28,12 +28,12 @@ class Config private $customParameters; private $deploymentNames; - public function __construct(?string $name, string $apiKey = null, string $licenseKey = null, bool $xmit = false, array $deploymentNames = [], ?string $apiHost = null) + public function __construct(?string $name, ?string $apiKey = null, ?string $licenseKey = null, bool $xmit = false, array $deploymentNames = [], ?string $apiHost = null) { - $this->name = (!empty($name) ? $name : ini_get('newrelic.appname')) ?: ''; + $this->name = (!empty($name) ? $name : \ini_get('newrelic.appname')) ?: ''; $this->apiKey = $apiKey; $this->apiHost = $apiHost; - $this->licenseKey = (!empty($licenseKey) ? $licenseKey : ini_get('newrelic.license')) ?: ''; + $this->licenseKey = (!empty($licenseKey) ? $licenseKey : \ini_get('newrelic.license')) ?: ''; $this->xmit = $xmit; $this->deploymentNames = $deploymentNames; $this->customEvents = []; diff --git a/NewRelic/LoggingInteractorDecorator.php b/NewRelic/LoggingInteractorDecorator.php index 996be29..32351b9 100644 --- a/NewRelic/LoggingInteractorDecorator.php +++ b/NewRelic/LoggingInteractorDecorator.php @@ -21,13 +21,13 @@ class LoggingInteractorDecorator implements NewRelicInteractorInterface private $interactor; private $logger; - public function __construct(NewRelicInteractorInterface $interactor, LoggerInterface $logger = null) + public function __construct(NewRelicInteractorInterface $interactor, ?LoggerInterface $logger = null) { $this->interactor = $interactor; $this->logger = $logger ?? new NullLogger(); } - public function setApplicationName(string $name, string $license = null, bool $xmit = false): bool + public function setApplicationName(string $name, ?string $license = null, bool $xmit = false): bool { $this->logger->debug('Setting New Relic Application name to {name}', ['name' => $name]); @@ -91,9 +91,9 @@ public function disableAutoRUM(): ?bool public function noticeError( int $errno, string $errstr, - string $errfile = null, - int $errline = null, - string $errcontext = null + ?string $errfile = null, + ?int $errline = null, + ?string $errcontext = null ): void { $this->logger->debug('Sending notice error to New Relic', [ 'error_code' => $errno, @@ -105,7 +105,7 @@ public function noticeError( $this->interactor->noticeError($errno, $errstr, $errfile, $errline, $errcontext); } - public function noticeThrowable(\Throwable $e, string $message = null): void + public function noticeThrowable(\Throwable $e, ?string $message = null): void { $this->logger->debug('Sending exception to New Relic', [ 'message' => $message, @@ -133,7 +133,7 @@ public function endTransaction(bool $ignore = false): bool return $this->interactor->endTransaction($ignore); } - public function startTransaction(string $name = null, string $license = null): bool + public function startTransaction(?string $name = null, ?string $license = null): bool { $this->logger->debug('Starting a new New Relic transaction for app {name}', ['name' => $name]); diff --git a/NewRelic/NewRelicInteractor.php b/NewRelic/NewRelicInteractor.php index dd5ce6b..8581b43 100644 --- a/NewRelic/NewRelicInteractor.php +++ b/NewRelic/NewRelicInteractor.php @@ -15,7 +15,7 @@ class NewRelicInteractor implements NewRelicInteractorInterface { - public function setApplicationName(string $name, string $license = null, bool $xmit = false): bool + public function setApplicationName(string $name, ?string $license = null, bool $xmit = false): bool { return newrelic_set_appname($name, $license, $xmit); } @@ -60,12 +60,12 @@ public function disableAutoRUM(): ?bool return newrelic_disable_autorum(); } - public function noticeError(int $errno, string $errstr, string $errfile = null, int $errline = null, string $errcontext = null): void + public function noticeError(int $errno, string $errstr, ?string $errfile = null, ?int $errline = null, ?string $errcontext = null): void { newrelic_notice_error($errno, $errstr, $errfile, $errline, $errcontext); } - public function noticeThrowable(\Throwable $e, string $message = null): void + public function noticeThrowable(\Throwable $e, ?string $message = null): void { newrelic_notice_error($message ?: $e->getMessage(), $e); } @@ -85,10 +85,10 @@ public function endTransaction(bool $ignore = false): bool return newrelic_end_transaction($ignore); } - public function startTransaction(string $name = null, string $license = null): bool + public function startTransaction(?string $name = null, ?string $license = null): bool { if (null === $name) { - $name = ini_get('newrelic.appname'); + $name = \ini_get('newrelic.appname'); } if (null === $license) { @@ -130,7 +130,7 @@ public function setUserAttributes(string $userValue, string $accountValue, strin public function getTraceMetadata(): array { - if (!function_exists('newrelic_get_trace_metadata')) { + if (!\function_exists('newrelic_get_trace_metadata')) { throw new \BadMethodCallException('You need the "newrelic" extension version 9.3 or higher to use this method'); } @@ -139,7 +139,7 @@ public function getTraceMetadata(): array public function getLinkingMetadata(): array { - if (!function_exists('newrelic_get_linking_metadata')) { + if (!\function_exists('newrelic_get_linking_metadata')) { throw new \BadMethodCallException('You need the "newrelic" extension version 9.3 or higher to use this method'); } @@ -148,7 +148,7 @@ public function getLinkingMetadata(): array public function isSampled(): bool { - if (!function_exists('newrelic_is_sampled')) { + if (!\function_exists('newrelic_is_sampled')) { throw new \BadMethodCallException('You need the "newrelic" extension version 9.3 or higher to use this method'); } @@ -157,7 +157,7 @@ public function isSampled(): bool public function insertDistributedTracingHeaders(array &$headers): void { - if (!function_exists('newrelic_insert_distributed_trace_headers')) { + if (!\function_exists('newrelic_insert_distributed_trace_headers')) { throw new \BadMethodCallException('You need the "newrelic" extension version 9.8 or higher to use this method'); } @@ -166,7 +166,7 @@ public function insertDistributedTracingHeaders(array &$headers): void public function acceptDistributedTraceHeaders(array $headers, string $transportType = 'HTTP'): void { - if (!function_exists('newrelic_accept_distributed_trace_headers')) { + if (!\function_exists('newrelic_accept_distributed_trace_headers')) { throw new \BadMethodCallException('You need the "newrelic" extension version 9.8 or higher to use this method'); } diff --git a/NewRelic/NewRelicInteractorInterface.php b/NewRelic/NewRelicInteractorInterface.php index b4a6dce..28277e8 100644 --- a/NewRelic/NewRelicInteractorInterface.php +++ b/NewRelic/NewRelicInteractorInterface.php @@ -18,9 +18,9 @@ * * @method array getTraceMetadata() * @method array getLinkingMetadata() - * @method bool isSampled() - * @method void insertDistributedTracingHeaders(array &$headers) - * @method void acceptDistributedTraceHeaders(array $headers, string $transportType = 'HTTP') + * @method bool isSampled() + * @method void insertDistributedTracingHeaders(array &$headers) + * @method void acceptDistributedTraceHeaders(array $headers, string $transportType = 'HTTP') */ interface NewRelicInteractorInterface { @@ -29,7 +29,7 @@ interface NewRelicInteractorInterface * * {@link https://docs.newrelic.com/docs/agents/php-agent/php-agent-api/newrelic_set_appname} */ - public function setApplicationName(string $name, string $license = null, bool $xmit = false): bool; + public function setApplicationName(string $name, ?string $license = null, bool $xmit = false): bool; /** * Set custom name for current transaction. @@ -93,12 +93,12 @@ public function disableAutoRUM(): ?bool; * * {@link https://docs.newrelic.com/docs/agents/php-agent/php-agent-api/newrelic_notice_error} */ - public function noticeThrowable(\Throwable $e, string $message = null): void; + public function noticeThrowable(\Throwable $e, ?string $message = null): void; /** * {@link https://docs.newrelic.com/docs/agents/php-agent/php-agent-api/newrelic_notice_error}. */ - public function noticeError(int $errno, string $errstr, string $errfile = null, int $errline = null, string $errcontext = null): void; + public function noticeError(int $errno, string $errstr, ?string $errfile = null, ?int $errline = null, ?string $errcontext = null): void; /** * {@link https://docs.newrelic.com/docs/agents/php-agent/php-agent-api/newrelic_background_job}. @@ -115,7 +115,7 @@ public function disableBackgroundJob(): void; * * {@link https://docs.newrelic.com/docs/agents/php-agent/php-agent-api/newrelic_start_transaction} */ - public function startTransaction(string $name = null, string $license = null): bool; + public function startTransaction(?string $name = null, ?string $license = null): bool; /** * Stop instrumenting the current transaction immediately. diff --git a/Tests/AppKernel.php b/Tests/AppKernel.php index 9e3b397..5dc555f 100644 --- a/Tests/AppKernel.php +++ b/Tests/AppKernel.php @@ -61,18 +61,12 @@ public function getProjectDir(): string return $this->fakedProjectDir; } - /** - * @param string|null $rootDir - */ - public function setRootDir($rootDir) + public function setRootDir(?string $rootDir): void { $this->rootDir = $rootDir; } - /** - * @param string|null $projectDir - */ - public function setProjectDir($projectDir) + public function setProjectDir(?string $projectDir): void { $this->fakedProjectDir = $projectDir; } @@ -89,9 +83,9 @@ public function registerBundles(): iterable * (From MicroKernelTrait) * {@inheritdoc} */ - public function registerContainerConfiguration(LoaderInterface $loader) + public function registerContainerConfiguration(LoaderInterface $loader): void { - $loader->load(function (ContainerBuilder $container) { + $loader->load(function (ContainerBuilder $container): void { $container->loadFromExtension('framework', [ 'secret' => 'test', 'router' => [ @@ -127,20 +121,17 @@ public function registerContainerConfiguration(LoaderInterface $loader) * * @internal */ - public function loadRoutes(LoaderInterface $loader) + public function loadRoutes(LoaderInterface $loader): RouteCollection { return new RouteCollection(); } - /** - * {@inheritdoc} - */ protected function buildContainer(): ContainerBuilder { $container = parent::buildContainer(); $container->addCompilerPass(new class() implements CompilerPassInterface { - public function process(ContainerBuilder $container) + public function process(ContainerBuilder $container): void { foreach ($container->getDefinitions() as $id => $definition) { if (preg_match('|Ekino.*|i', $id)) { diff --git a/Tests/BundleInitializationTest.php b/Tests/BundleInitializationTest.php index 27a07a0..256717b 100644 --- a/Tests/BundleInitializationTest.php +++ b/Tests/BundleInitializationTest.php @@ -27,12 +27,12 @@ */ class BundleInitializationTest extends TestCase { - protected function getBundleClass() + protected function getBundleClass(): string { return EkinoNewRelicBundle::class; } - public function testInitBundle() + public function testInitBundle(): void { $kernel = new AppKernel(uniqid('cache')); $kernel->boot(); diff --git a/Tests/Listener/CommandListenerTest.php b/Tests/Listener/CommandListenerTest.php index 9e250bf..1e05765 100644 --- a/Tests/Listener/CommandListenerTest.php +++ b/Tests/Listener/CommandListenerTest.php @@ -44,7 +44,7 @@ public function testCommandMarkedAsBackgroundJob() new InputOption('foo'), new InputOption('foobar', 'fb', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY), new InputArgument('name', InputArgument::REQUIRED), - ]); + ]); $interactor = $this->getMockBuilder(NewRelicInteractorInterface::class)->getMock(); $interactor->expects($this->once())->method('setTransactionName')->with($this->equalTo('test:newrelic')); diff --git a/Tests/Listener/RequestListenerTest.php b/Tests/Listener/RequestListenerTest.php index 72a4bd4..1161b53 100644 --- a/Tests/Listener/RequestListenerTest.php +++ b/Tests/Listener/RequestListenerTest.php @@ -55,7 +55,7 @@ public function testMasterRequest() $kernel = $this->getMockBuilder(HttpKernelInterface::class)->getMock(); $eventClass = class_exists(RequestEvent::class) ? RequestEvent::class : GetResponseEvent::class; - $event = new $eventClass($kernel, new Request(), HttpKernelInterface::MASTER_REQUEST, new Response()); + $event = new $eventClass($kernel, new Request(), HttpKernelInterface::MAIN_REQUEST, new Response()); $listener = new RequestListener(new Config('App name', 'Token'), $interactor, [], [], $namingStrategy); $listener->setTransactionName($event); @@ -72,7 +72,7 @@ public function testPathIsIgnored() $request = new Request([], [], [], [], [], ['REQUEST_URI' => '/ignored_path']); $eventClass = class_exists(RequestEvent::class) ? RequestEvent::class : GetResponseEvent::class; - $event = new $eventClass($kernel, $request, HttpKernelInterface::MASTER_REQUEST, new Response()); + $event = new $eventClass($kernel, $request, HttpKernelInterface::MAIN_REQUEST, new Response()); $listener = new RequestListener(new Config('App name', 'Token'), $interactor, [], ['/ignored_path'], $namingStrategy); $listener->setIgnoreTransaction($event); @@ -89,7 +89,7 @@ public function testRouteIsIgnored() $request = new Request([], [], ['_route' => 'ignored_route']); $eventClass = class_exists(RequestEvent::class) ? RequestEvent::class : GetResponseEvent::class; - $event = new $eventClass($kernel, $request, HttpKernelInterface::MASTER_REQUEST, new Response()); + $event = new $eventClass($kernel, $request, HttpKernelInterface::MAIN_REQUEST, new Response()); $listener = new RequestListener(new Config('App name', 'Token'), $interactor, ['ignored_route'], [], $namingStrategy); $listener->setIgnoreTransaction($event); @@ -105,7 +105,7 @@ public function testSymfonyCacheEnabled() $kernel = $this->getMockBuilder(HttpKernelInterface::class)->getMock(); $eventClass = class_exists(RequestEvent::class) ? RequestEvent::class : GetResponseEvent::class; - $event = new $eventClass($kernel, new Request(), HttpKernelInterface::MASTER_REQUEST, new Response()); + $event = new $eventClass($kernel, new Request(), HttpKernelInterface::MAIN_REQUEST, new Response()); $listener = new RequestListener(new Config('App name', 'Token'), $interactor, [], [], $namingStrategy, true); $listener->setApplicationName($event); @@ -121,7 +121,7 @@ public function testSymfonyCacheDisabled() $kernel = $this->getMockBuilder(HttpKernelInterface::class)->getMock(); $eventClass = class_exists(RequestEvent::class) ? RequestEvent::class : GetResponseEvent::class; - $event = new $eventClass($kernel, new Request(), HttpKernelInterface::MASTER_REQUEST, new Response()); + $event = new $eventClass($kernel, new Request(), HttpKernelInterface::MAIN_REQUEST, new Response()); $listener = new RequestListener(new Config('App name', 'Token'), $interactor, [], [], $namingStrategy, false); $listener->setApplicationName($event); diff --git a/Tests/Listener/ResponseListenerTest.php b/Tests/Listener/ResponseListenerTest.php index b8107d7..86d28e5 100644 --- a/Tests/Listener/ResponseListenerTest.php +++ b/Tests/Listener/ResponseListenerTest.php @@ -17,15 +17,21 @@ use Ekino\NewRelicBundle\NewRelic\Config; use Ekino\NewRelicBundle\NewRelic\NewRelicInteractorInterface; use Ekino\NewRelicBundle\Twig\NewRelicExtension; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpFoundation\ParameterBag; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Event\FilterResponseEvent; +use Symfony\Component\HttpFoundation\ResponseHeaderBag; use Symfony\Component\HttpKernel\Event\ResponseEvent; use Symfony\Component\HttpKernel\HttpKernelInterface; class ResponseListenerTest extends TestCase { + private NewRelicInteractorInterface&MockObject $interactor; + private Config&MockObject $newRelic; + private NewRelicExtension&MockObject $extension; + protected function setUp(): void { $this->interactor = $this->getMockBuilder(NewRelicInteractorInterface::class)->getMock(); @@ -39,7 +45,7 @@ protected function setUp(): void ->getMock(); } - public function testOnKernelResponseOnlyMasterRequestsAreProcessed() + public function testOnKernelResponseOnlyMasterRequestsAreProcessed(): void { $event = $this->createFilterResponseEventDummy(null, null, HttpKernelInterface::SUB_REQUEST); @@ -49,7 +55,7 @@ public function testOnKernelResponseOnlyMasterRequestsAreProcessed() $this->newRelic->expects($this->never())->method('getCustomMetrics'); } - public function testOnKernelResponseWithOnlyCustomMetricsAndParameters() + public function testOnKernelResponseWithOnlyCustomMetricsAndParameters(): void { $events = [ 'WidgetSale' => [ @@ -103,7 +109,7 @@ public function testOnKernelResponseWithOnlyCustomMetricsAndParameters() $object->onKernelResponse($event); } - public function testOnKernelResponseInstrumentDisabledInRequest() + public function testOnKernelResponseInstrumentDisabledInRequest(): void { $this->setupNoCustomMetricsOrParameters(); @@ -115,7 +121,7 @@ public function testOnKernelResponseInstrumentDisabledInRequest() $object->onKernelResponse($event); } - public function testSymfonyCacheEnabled() + public function testSymfonyCacheEnabled(): void { $this->setupNoCustomMetricsOrParameters(); @@ -127,7 +133,7 @@ public function testSymfonyCacheEnabled() $object->onKernelResponse($event); } - public function testSymfonyCacheDisabled() + public function testSymfonyCacheDisabled(): void { $this->setupNoCustomMetricsOrParameters(); @@ -256,24 +262,24 @@ private function setUpNoCustomMetricsOrParameters() $this->interactor->expects($this->never())->method('addCustomParameter'); } - private function createRequestMock($instrumentEnabled = true) + private function createRequestMock($instrumentEnabled = true): Request { $mock = $this->getMockBuilder(Request::class) ->setMethods(['get']) ->getMock(); - $mock->attributes = $mock; + $mock->attributes = new ParameterBag(['_instrument' => $instrumentEnabled]); $mock->expects($this->any())->method('get')->willReturn($instrumentEnabled); return $mock; } - private function createResponseMock($content = null, $expectsSetContent = null, $contentType = 'text/html') + private function createResponseMock($content = null, $expectsSetContent = null, $contentType = 'text/html'): Response { $mock = $this->getMockBuilder(Response::class) ->setMethods(['get', 'getContent', 'setContent']) ->getMock(); - $mock->headers = $mock; + $mock->headers = new ResponseHeaderBag(['Content-Type' => $contentType]); $mock->expects($this->any())->method('get')->willReturn($contentType); $mock->expects($content ? $this->any() : $this->never())->method('getContent')->willReturn($content ?? false); @@ -287,13 +293,10 @@ private function createResponseMock($content = null, $expectsSetContent = null, return $mock; } - private function createFilterResponseEventDummy(Request $request = null, Response $response = null, int $requestType = HttpKernelInterface::MASTER_REQUEST) + private function createFilterResponseEventDummy(?Request $request = null, ?Response $response = null, int $requestType = HttpKernelInterface::MAIN_REQUEST): ResponseEvent { $kernel = $this->getMockBuilder(HttpKernelInterface::class)->getMock(); - $eventClass = class_exists(ResponseEvent::class) ? ResponseEvent::class : FilterResponseEvent::class; - $event = new $eventClass($kernel, $request ?? new Request(), $requestType, $response ?? new Response()); - - return $event; + return new ResponseEvent($kernel, $request ?? new Request(), $requestType, $response ?? new Response()); } } diff --git a/Tests/NewRelic/ConfigTest.php b/Tests/NewRelic/ConfigTest.php index 71ba07a..ac05759 100644 --- a/Tests/NewRelic/ConfigTest.php +++ b/Tests/NewRelic/ConfigTest.php @@ -72,10 +72,10 @@ public function testDefaults() $newRelic = new Config('', ''); $this->assertNotNull($newRelic->getName()); - $this->assertSame(ini_get('newrelic.appname') ?: '', $newRelic->getName()); + $this->assertSame(\ini_get('newrelic.appname') ?: '', $newRelic->getName()); $this->assertNotNull($newRelic->getLicenseKey()); - $this->assertSame(ini_get('newrelic.license') ?: '', $newRelic->getLicenseKey()); + $this->assertSame(\ini_get('newrelic.license') ?: '', $newRelic->getLicenseKey()); $this->assertNull($newRelic->getApiHost()); } diff --git a/Tests/Twig/NewRelicExtensionTest.php b/Tests/Twig/NewRelicExtensionTest.php index 759901f..8c750f4 100644 --- a/Tests/Twig/NewRelicExtensionTest.php +++ b/Tests/Twig/NewRelicExtensionTest.php @@ -21,12 +21,12 @@ class NewRelicExtensionTest extends TestCase { /** - * @var \Ekino\NewRelicBundle\NewRelic\Config + * @var Config */ private $newRelic; /** - * @var \Ekino\NewRelicBundle\NewRelic\NewRelicInteractorInterface + * @var NewRelicInteractorInterface */ private $interactor; diff --git a/TransactionNamingStrategy/ControllerNamingStrategy.php b/TransactionNamingStrategy/ControllerNamingStrategy.php index 4984c01..ad91fe1 100644 --- a/TransactionNamingStrategy/ControllerNamingStrategy.php +++ b/TransactionNamingStrategy/ControllerNamingStrategy.php @@ -34,7 +34,7 @@ public function getTransactionName(Request $request): string if (\is_object($controller)) { if (method_exists($controller, '__invoke')) { - return 'Callback controller: '.\get_class($controller).'::__invoke()'; + return 'Callback controller: '.$controller::class.'::__invoke()'; } } diff --git a/composer.json b/composer.json index db4676f..8a58a24 100644 --- a/composer.json +++ b/composer.json @@ -13,26 +13,22 @@ } ], "require": { - "php": "^7.1 | ^8.0", - "symfony/config": "^3.4|^4.0|^5.0|^6.0", - "symfony/console": "^3.4|^4.0|^5.0|^6.0", - "symfony/dependency-injection": "^3.4|^4.0|^5.0|^6.0", - "symfony/event-dispatcher": "^3.4|^4.0|^5.0|^6.0", - "symfony/http-kernel": "^3.4|^4.0|^5.0|^6.0" + "php": "^8.2", + "symfony/config": "^5.4|^6.4|^7.0", + "symfony/console": "^5.4|^6.4|^7.0", + "symfony/dependency-injection": "^5.4|^6.4|^7.0", + "symfony/event-dispatcher": "^5.4|^6.4|^7.0", + "symfony/http-kernel": "^5.4|^6.4|^7.0" }, "require-dev": { - "matthiasnoback/symfony-dependency-injection-test": "^3.1|^4.0", - "symfony/framework-bundle": "^3.4|^4.0|^5.0|^6.0", - "symfony/phpunit-bridge": "^5.3", - "symfony/debug": ">3.4.21", - "twig/twig": "^1.32|^2.4", - "symfony/monolog-bundle": "^3.2" - }, - "conflict": { - "twig/twig": "<1.32" + "matthiasnoback/symfony-dependency-injection-test": "^5.1", + "symfony/framework-bundle": "^5.4|^6.4|^7.0", + "symfony/phpunit-bridge": "^7.1", + "twig/twig": "^3.10", + "symfony/monolog-bundle": "^3.10" }, "suggest": { - "symfony/monolog-bundle": "^3.2" + "symfony/monolog-bundle": "^3.10" }, "autoload": { "psr-4": { "Ekino\\NewRelicBundle\\": "" }, diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 415b8b5..d2d3979 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,30 +1,18 @@ - - - - - ./Tests - - - - - - ./ - - ./Tests/ - ./Resources/ - ./vendor/ - - - - + + + + ./ + + + ./Tests/ + ./Resources/ + ./vendor/ + + + + + ./Tests + + diff --git a/tools/php-cs-fixer/composer.json b/tools/php-cs-fixer/composer.json new file mode 100644 index 0000000..e04ba7a --- /dev/null +++ b/tools/php-cs-fixer/composer.json @@ -0,0 +1,5 @@ +{ + "require": { + "friendsofphp/php-cs-fixer": "^3.58" + } +} diff --git a/tools/php-cs-fixer/composer.lock b/tools/php-cs-fixer/composer.lock new file mode 100644 index 0000000..96e0381 --- /dev/null +++ b/tools/php-cs-fixer/composer.lock @@ -0,0 +1,2539 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "b6923c620f51345982500447b5a74eb6", + "packages": [ + { + "name": "clue/ndjson-react", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/clue/reactphp-ndjson.git", + "reference": "392dc165fce93b5bb5c637b67e59619223c931b0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/clue/reactphp-ndjson/zipball/392dc165fce93b5bb5c637b67e59619223c931b0", + "reference": "392dc165fce93b5bb5c637b67e59619223c931b0", + "shasum": "" + }, + "require": { + "php": ">=5.3", + "react/stream": "^1.2" + }, + "require-dev": { + "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.35", + "react/event-loop": "^1.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Clue\\React\\NDJson\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering" + } + ], + "description": "Streaming newline-delimited JSON (NDJSON) parser and encoder for ReactPHP.", + "homepage": "https://github.com/clue/reactphp-ndjson", + "keywords": [ + "NDJSON", + "json", + "jsonlines", + "newline", + "reactphp", + "streaming" + ], + "support": { + "issues": "https://github.com/clue/reactphp-ndjson/issues", + "source": "https://github.com/clue/reactphp-ndjson/tree/v1.3.0" + }, + "funding": [ + { + "url": "https://clue.engineering/support", + "type": "custom" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2022-12-23T10:58:28+00:00" + }, + { + "name": "composer/pcre", + "version": "3.1.4", + "source": { + "type": "git", + "url": "https://github.com/composer/pcre.git", + "reference": "04229f163664973f68f38f6f73d917799168ef24" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/pcre/zipball/04229f163664973f68f38f6f73d917799168ef24", + "reference": "04229f163664973f68f38f6f73d917799168ef24", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.3", + "phpstan/phpstan-strict-rules": "^1.1", + "symfony/phpunit-bridge": "^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Pcre\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "PCRE wrapping library that offers type-safe preg_* replacements.", + "keywords": [ + "PCRE", + "preg", + "regex", + "regular expression" + ], + "support": { + "issues": "https://github.com/composer/pcre/issues", + "source": "https://github.com/composer/pcre/tree/3.1.4" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2024-05-27T13:40:54+00:00" + }, + { + "name": "composer/semver", + "version": "3.4.0", + "source": { + "type": "git", + "url": "https://github.com/composer/semver.git", + "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/semver/zipball/35e8d0af4486141bc745f23a29cc2091eb624a32", + "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.4", + "symfony/phpunit-bridge": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "Semver library that offers utilities, version constraint parsing and validation.", + "keywords": [ + "semantic", + "semver", + "validation", + "versioning" + ], + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/semver/issues", + "source": "https://github.com/composer/semver/tree/3.4.0" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2023-08-31T09:50:34+00:00" + }, + { + "name": "composer/xdebug-handler", + "version": "3.0.5", + "source": { + "type": "git", + "url": "https://github.com/composer/xdebug-handler.git", + "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/6c1925561632e83d60a44492e0b344cf48ab85ef", + "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef", + "shasum": "" + }, + "require": { + "composer/pcre": "^1 || ^2 || ^3", + "php": "^7.2.5 || ^8.0", + "psr/log": "^1 || ^2 || ^3" + }, + "require-dev": { + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-strict-rules": "^1.1", + "phpunit/phpunit": "^8.5 || ^9.6 || ^10.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Composer\\XdebugHandler\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "John Stevenson", + "email": "john-stevenson@blueyonder.co.uk" + } + ], + "description": "Restarts a process without Xdebug.", + "keywords": [ + "Xdebug", + "performance" + ], + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/xdebug-handler/issues", + "source": "https://github.com/composer/xdebug-handler/tree/3.0.5" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2024-05-06T16:37:16+00:00" + }, + { + "name": "evenement/evenement", + "version": "v3.0.2", + "source": { + "type": "git", + "url": "https://github.com/igorw/evenement.git", + "reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/igorw/evenement/zipball/0a16b0d71ab13284339abb99d9d2bd813640efbc", + "reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc", + "shasum": "" + }, + "require": { + "php": ">=7.0" + }, + "require-dev": { + "phpunit/phpunit": "^9 || ^6" + }, + "type": "library", + "autoload": { + "psr-4": { + "Evenement\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Igor Wiedler", + "email": "igor@wiedler.ch" + } + ], + "description": "Événement is a very simple event dispatching library for PHP", + "keywords": [ + "event-dispatcher", + "event-emitter" + ], + "support": { + "issues": "https://github.com/igorw/evenement/issues", + "source": "https://github.com/igorw/evenement/tree/v3.0.2" + }, + "time": "2023-08-08T05:53:35+00:00" + }, + { + "name": "fidry/cpu-core-counter", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/theofidry/cpu-core-counter.git", + "reference": "f92996c4d5c1a696a6a970e20f7c4216200fcc42" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/f92996c4d5c1a696a6a970e20f7c4216200fcc42", + "reference": "f92996c4d5c1a696a6a970e20f7c4216200fcc42", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "fidry/makefile": "^0.2.0", + "fidry/php-cs-fixer-config": "^1.1.2", + "phpstan/extension-installer": "^1.2.0", + "phpstan/phpstan": "^1.9.2", + "phpstan/phpstan-deprecation-rules": "^1.0.0", + "phpstan/phpstan-phpunit": "^1.2.2", + "phpstan/phpstan-strict-rules": "^1.4.4", + "phpunit/phpunit": "^8.5.31 || ^9.5.26", + "webmozarts/strict-phpunit": "^7.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Fidry\\CpuCoreCounter\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Théo FIDRY", + "email": "theo.fidry@gmail.com" + } + ], + "description": "Tiny utility to get the number of CPU cores.", + "keywords": [ + "CPU", + "core" + ], + "support": { + "issues": "https://github.com/theofidry/cpu-core-counter/issues", + "source": "https://github.com/theofidry/cpu-core-counter/tree/1.1.0" + }, + "funding": [ + { + "url": "https://github.com/theofidry", + "type": "github" + } + ], + "time": "2024-02-07T09:43:46+00:00" + }, + { + "name": "friendsofphp/php-cs-fixer", + "version": "v3.58.1", + "source": { + "type": "git", + "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", + "reference": "04e9424025677a86914b9a4944dbbf4060bb0aff" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/04e9424025677a86914b9a4944dbbf4060bb0aff", + "reference": "04e9424025677a86914b9a4944dbbf4060bb0aff", + "shasum": "" + }, + "require": { + "clue/ndjson-react": "^1.0", + "composer/semver": "^3.4", + "composer/xdebug-handler": "^3.0.3", + "ext-filter": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "fidry/cpu-core-counter": "^1.0", + "php": "^7.4 || ^8.0", + "react/child-process": "^0.6.5", + "react/event-loop": "^1.0", + "react/promise": "^2.0 || ^3.0", + "react/socket": "^1.0", + "react/stream": "^1.0", + "sebastian/diff": "^4.0 || ^5.0 || ^6.0", + "symfony/console": "^5.4 || ^6.0 || ^7.0", + "symfony/event-dispatcher": "^5.4 || ^6.0 || ^7.0", + "symfony/filesystem": "^5.4 || ^6.0 || ^7.0", + "symfony/finder": "^5.4 || ^6.0 || ^7.0", + "symfony/options-resolver": "^5.4 || ^6.0 || ^7.0", + "symfony/polyfill-mbstring": "^1.28", + "symfony/polyfill-php80": "^1.28", + "symfony/polyfill-php81": "^1.28", + "symfony/process": "^5.4 || ^6.0 || ^7.0", + "symfony/stopwatch": "^5.4 || ^6.0 || ^7.0" + }, + "require-dev": { + "facile-it/paraunit": "^1.3 || ^2.0", + "infection/infection": "^0.27.11", + "justinrainbow/json-schema": "^5.2", + "keradus/cli-executor": "^2.1", + "mikey179/vfsstream": "^1.6.11", + "php-coveralls/php-coveralls": "^2.7", + "php-cs-fixer/accessible-object": "^1.1", + "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.4", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.4", + "phpunit/phpunit": "^9.6 || ^10.5.5 || ^11.0.2", + "symfony/var-dumper": "^5.4 || ^6.0 || ^7.0", + "symfony/yaml": "^5.4 || ^6.0 || ^7.0" + }, + "suggest": { + "ext-dom": "For handling output formats in XML", + "ext-mbstring": "For handling non-UTF8 characters." + }, + "bin": [ + "php-cs-fixer" + ], + "type": "application", + "autoload": { + "psr-4": { + "PhpCsFixer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Dariusz Rumiński", + "email": "dariusz.ruminski@gmail.com" + } + ], + "description": "A tool to automatically fix PHP code style", + "keywords": [ + "Static code analysis", + "fixer", + "standards", + "static analysis" + ], + "support": { + "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.58.1" + }, + "funding": [ + { + "url": "https://github.com/keradus", + "type": "github" + } + ], + "time": "2024-05-29T16:39:07+00:00" + }, + { + "name": "psr/container", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "psr/event-dispatcher", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "support": { + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + }, + "time": "2019-01-08T18:20:26+00:00" + }, + { + "name": "psr/log", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.0" + }, + "time": "2021-07-14T16:46:02+00:00" + }, + { + "name": "react/cache", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/cache.git", + "reference": "d47c472b64aa5608225f47965a484b75c7817d5b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/cache/zipball/d47c472b64aa5608225f47965a484b75c7817d5b", + "reference": "d47c472b64aa5608225f47965a484b75c7817d5b", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "react/promise": "^3.0 || ^2.0 || ^1.1" + }, + "require-dev": { + "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.35" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Cache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Async, Promise-based cache interface for ReactPHP", + "keywords": [ + "cache", + "caching", + "promise", + "reactphp" + ], + "support": { + "issues": "https://github.com/reactphp/cache/issues", + "source": "https://github.com/reactphp/cache/tree/v1.2.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2022-11-30T15:59:55+00:00" + }, + { + "name": "react/child-process", + "version": "v0.6.5", + "source": { + "type": "git", + "url": "https://github.com/reactphp/child-process.git", + "reference": "e71eb1aa55f057c7a4a0d08d06b0b0a484bead43" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/child-process/zipball/e71eb1aa55f057c7a4a0d08d06b0b0a484bead43", + "reference": "e71eb1aa55f057c7a4a0d08d06b0b0a484bead43", + "shasum": "" + }, + "require": { + "evenement/evenement": "^3.0 || ^2.0 || ^1.0", + "php": ">=5.3.0", + "react/event-loop": "^1.2", + "react/stream": "^1.2" + }, + "require-dev": { + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35", + "react/socket": "^1.8", + "sebastian/environment": "^5.0 || ^3.0 || ^2.0 || ^1.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\ChildProcess\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Event-driven library for executing child processes with ReactPHP.", + "keywords": [ + "event-driven", + "process", + "reactphp" + ], + "support": { + "issues": "https://github.com/reactphp/child-process/issues", + "source": "https://github.com/reactphp/child-process/tree/v0.6.5" + }, + "funding": [ + { + "url": "https://github.com/WyriHaximus", + "type": "github" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2022-09-16T13:41:56+00:00" + }, + { + "name": "react/dns", + "version": "v1.12.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/dns.git", + "reference": "c134600642fa615b46b41237ef243daa65bb64ec" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/dns/zipball/c134600642fa615b46b41237ef243daa65bb64ec", + "reference": "c134600642fa615b46b41237ef243daa65bb64ec", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "react/cache": "^1.0 || ^0.6 || ^0.5", + "react/event-loop": "^1.2", + "react/promise": "^3.0 || ^2.7 || ^1.2.1" + }, + "require-dev": { + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", + "react/async": "^4 || ^3 || ^2", + "react/promise-timer": "^1.9" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Dns\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Async DNS resolver for ReactPHP", + "keywords": [ + "async", + "dns", + "dns-resolver", + "reactphp" + ], + "support": { + "issues": "https://github.com/reactphp/dns/issues", + "source": "https://github.com/reactphp/dns/tree/v1.12.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2023-11-29T12:41:06+00:00" + }, + { + "name": "react/event-loop", + "version": "v1.5.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/event-loop.git", + "reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/event-loop/zipball/bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354", + "reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" + }, + "suggest": { + "ext-pcntl": "For signal handling support when using the StreamSelectLoop" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\EventLoop\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "ReactPHP's core reactor event loop that libraries can use for evented I/O.", + "keywords": [ + "asynchronous", + "event-loop" + ], + "support": { + "issues": "https://github.com/reactphp/event-loop/issues", + "source": "https://github.com/reactphp/event-loop/tree/v1.5.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2023-11-13T13:48:05+00:00" + }, + { + "name": "react/promise", + "version": "v3.2.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/promise.git", + "reference": "8a164643313c71354582dc850b42b33fa12a4b63" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/promise/zipball/8a164643313c71354582dc850b42b33fa12a4b63", + "reference": "8a164643313c71354582dc850b42b33fa12a4b63", + "shasum": "" + }, + "require": { + "php": ">=7.1.0" + }, + "require-dev": { + "phpstan/phpstan": "1.10.39 || 1.4.10", + "phpunit/phpunit": "^9.6 || ^7.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "React\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "A lightweight implementation of CommonJS Promises/A for PHP", + "keywords": [ + "promise", + "promises" + ], + "support": { + "issues": "https://github.com/reactphp/promise/issues", + "source": "https://github.com/reactphp/promise/tree/v3.2.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2024-05-24T10:39:05+00:00" + }, + { + "name": "react/socket", + "version": "v1.15.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/socket.git", + "reference": "216d3aec0b87f04a40ca04f481e6af01bdd1d038" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/socket/zipball/216d3aec0b87f04a40ca04f481e6af01bdd1d038", + "reference": "216d3aec0b87f04a40ca04f481e6af01bdd1d038", + "shasum": "" + }, + "require": { + "evenement/evenement": "^3.0 || ^2.0 || ^1.0", + "php": ">=5.3.0", + "react/dns": "^1.11", + "react/event-loop": "^1.2", + "react/promise": "^3 || ^2.6 || ^1.2.1", + "react/stream": "^1.2" + }, + "require-dev": { + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", + "react/async": "^4 || ^3 || ^2", + "react/promise-stream": "^1.4", + "react/promise-timer": "^1.10" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Socket\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Async, streaming plaintext TCP/IP and secure TLS socket server and client connections for ReactPHP", + "keywords": [ + "Connection", + "Socket", + "async", + "reactphp", + "stream" + ], + "support": { + "issues": "https://github.com/reactphp/socket/issues", + "source": "https://github.com/reactphp/socket/tree/v1.15.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2023-12-15T11:02:10+00:00" + }, + { + "name": "react/stream", + "version": "v1.4.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/stream.git", + "reference": "1e5b0acb8fe55143b5b426817155190eb6f5b18d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/stream/zipball/1e5b0acb8fe55143b5b426817155190eb6f5b18d", + "reference": "1e5b0acb8fe55143b5b426817155190eb6f5b18d", + "shasum": "" + }, + "require": { + "evenement/evenement": "^3.0 || ^2.0 || ^1.0", + "php": ">=5.3.8", + "react/event-loop": "^1.2" + }, + "require-dev": { + "clue/stream-filter": "~1.2", + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Stream\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Event-driven readable and writable streams for non-blocking I/O in ReactPHP", + "keywords": [ + "event-driven", + "io", + "non-blocking", + "pipe", + "reactphp", + "readable", + "stream", + "writable" + ], + "support": { + "issues": "https://github.com/reactphp/stream/issues", + "source": "https://github.com/reactphp/stream/tree/v1.4.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2024-06-11T12:45:25+00:00" + }, + { + "name": "sebastian/diff", + "version": "6.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "ab83243ecc233de5655b76f577711de9f842e712" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ab83243ecc233de5655b76f577711de9f842e712", + "reference": "ab83243ecc233de5655b76f577711de9f842e712", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0", + "symfony/process": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/6.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-02T07:30:33+00:00" + }, + { + "name": "symfony/console", + "version": "v7.1.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "9b008f2d7b21c74ef4d0c3de6077a642bc55ece3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/9b008f2d7b21c74ef4d0c3de6077a642bc55ece3", + "reference": "9b008f2d7b21c74ef4d0c3de6077a642bc55ece3", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/string": "^6.4|^7.0" + }, + "conflict": { + "symfony/dependency-injection": "<6.4", + "symfony/dotenv": "<6.4", + "symfony/event-dispatcher": "<6.4", + "symfony/lock": "<6.4", + "symfony/process": "<6.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/lock": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command-line", + "console", + "terminal" + ], + "support": { + "source": "https://github.com/symfony/console/tree/v7.1.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-05-31T14:57:53+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.5.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:32:20+00:00" + }, + { + "name": "symfony/event-dispatcher", + "version": "v7.1.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "9fa7f7a21beb22a39a8f3f28618b29e50d7a55a7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/9fa7f7a21beb22a39a8f3f28618b29e50d7a55a7", + "reference": "9fa7f7a21beb22a39a8f3f28618b29e50d7a55a7", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/event-dispatcher-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/dependency-injection": "<6.4", + "symfony/service-contracts": "<2.5" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/error-handler": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/stopwatch": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/event-dispatcher/tree/v7.1.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-05-31T14:57:53+00:00" + }, + { + "name": "symfony/event-dispatcher-contracts", + "version": "v3.5.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "8f93aec25d41b72493c6ddff14e916177c9efc50" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/8f93aec25d41b72493c6ddff14e916177c9efc50", + "reference": "8f93aec25d41b72493c6ddff14e916177c9efc50", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/event-dispatcher": "^1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\EventDispatcher\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to dispatching event", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:32:20+00:00" + }, + { + "name": "symfony/filesystem", + "version": "v7.1.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "802e87002f919296c9f606457d9fa327a0b3d6b2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/802e87002f919296c9f606457d9fa327a0b3d6b2", + "reference": "802e87002f919296c9f606457d9fa327a0b3d6b2", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8" + }, + "require-dev": { + "symfony/process": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides basic utilities for the filesystem", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/filesystem/tree/v7.1.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-05-31T14:57:53+00:00" + }, + { + "name": "symfony/finder", + "version": "v7.1.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "fbb0ba67688b780efbc886c1a0a0948dcf7205d6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/fbb0ba67688b780efbc886c1a0a0948dcf7205d6", + "reference": "fbb0ba67688b780efbc886c1a0a0948dcf7205d6", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "symfony/filesystem": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/v7.1.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-05-31T14:57:53+00:00" + }, + { + "name": "symfony/options-resolver", + "version": "v7.1.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/options-resolver.git", + "reference": "47aa818121ed3950acd2b58d1d37d08a94f9bf55" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/47aa818121ed3950acd2b58d1d37d08a94f9bf55", + "reference": "47aa818121ed3950acd2b58d1d37d08a94f9bf55", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\OptionsResolver\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an improved replacement for the array_replace PHP function", + "homepage": "https://symfony.com", + "keywords": [ + "config", + "configuration", + "options" + ], + "support": { + "source": "https://github.com/symfony/options-resolver/tree/v7.1.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-05-31T14:57:53+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.29.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ef4d7e442ca910c4764bce785146269b30cb5fc4", + "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.29.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/32a9da87d7b3245e09ac426c83d334ae9f06f80f", + "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.29.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "bc45c394692b948b4d383a08d7753968bed9a83d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/bc45c394692b948b4d383a08d7753968bed9a83d", + "reference": "bc45c394692b948b4d383a08d7753968bed9a83d", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.29.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec", + "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.29.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", + "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" + }, + { + "name": "symfony/polyfill-php81", + "version": "v1.29.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php81.git", + "reference": "c565ad1e63f30e7477fc40738343c62b40bc672d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/c565ad1e63f30e7477fc40738343c62b40bc672d", + "reference": "c565ad1e63f30e7477fc40738343c62b40bc672d", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php81\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php81/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" + }, + { + "name": "symfony/process", + "version": "v7.1.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "febf90124323a093c7ee06fdb30e765ca3c20028" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/febf90124323a093c7ee06fdb30e765ca3c20028", + "reference": "febf90124323a093c7ee06fdb30e765ca3c20028", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Executes commands in sub-processes", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/process/tree/v7.1.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-05-31T14:57:53+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v3.5.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", + "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v3.5.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:32:20+00:00" + }, + { + "name": "symfony/stopwatch", + "version": "v7.1.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/stopwatch.git", + "reference": "5b75bb1ac2ba1b9d05c47fc4b3046a625377d23d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/5b75bb1ac2ba1b9d05c47fc4b3046a625377d23d", + "reference": "5b75bb1ac2ba1b9d05c47fc4b3046a625377d23d", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/service-contracts": "^2.5|^3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Stopwatch\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides a way to profile code", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/stopwatch/tree/v7.1.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-05-31T14:57:53+00:00" + }, + { + "name": "symfony/string", + "version": "v7.1.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "60bc311c74e0af215101235aa6f471bcbc032df2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/60bc311c74e0af215101235aa6f471bcbc032df2", + "reference": "60bc311c74e0af215101235aa6f471bcbc032df2", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/translation-contracts": "<2.5" + }, + "require-dev": { + "symfony/emoji": "^7.1", + "symfony/error-handler": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/intl": "^6.4|^7.0", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v7.1.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-06-04T06:40:14+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [], + "plugin-api-version": "2.3.0" +}