├── phpstan.neon ├── phpstan-baseline.neon ├── src ├── Hasher │ ├── Algorithm.php │ ├── HasherInterface.php │ └── Hasher.php ├── Solution.php ├── ServerSignatureVerification.php ├── Challenge.php ├── ServerSignaturePayload.php ├── Payload.php ├── CheckChallengeOptions.php ├── ServerSignatureVerificationData.php ├── BaseChallengeOptions.php ├── ChallengeOptions.php ├── Obfuscator.php └── Altcha.php ├── .gitignore ├── .editorconfig ├── composer.json ├── phpunit.xml.dist ├── .github └── workflows │ └── php.yml ├── LICENSE.txt ├── .php-cs-fixer.dist.php ├── CONTRIBUTING.md ├── README.md ├── CODE_OF_CONDUCT.md ├── tests └── AltchaTest.php └── composer.lock /phpstan.neon: -------------------------------------------------------------------------------- 1 | includes: 2 | - phpstan-baseline.neon 3 | 4 | parameters: 5 | level: max 6 | paths: 7 | - src 8 | - tests 9 | -------------------------------------------------------------------------------- /phpstan-baseline.neon: -------------------------------------------------------------------------------- 1 | parameters: 2 | ignoreErrors: 3 | - 4 | message: '#^Dead catch \- ValueError is never thrown in the try block\.$#' 5 | identifier: catch.neverThrown 6 | count: 1 7 | path: src/Altcha.php 8 | -------------------------------------------------------------------------------- /src/Hasher/Algorithm.php: -------------------------------------------------------------------------------- 1 | $fields 11 | * @param array $reasons 12 | */ 13 | public function __construct( 14 | public readonly string $classification, 15 | public readonly string $country, 16 | public readonly string $detectedLanguage, 17 | public readonly string $email, 18 | public readonly int $expire, 19 | public readonly array $fields, 20 | public readonly string $fieldsHash, 21 | public readonly array $reasons, 22 | public readonly float $score, 23 | public readonly int $time, 24 | public readonly bool $verified, 25 | ) { 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "altcha-org/altcha", 3 | "type": "library", 4 | "license": "MIT", 5 | "autoload": { 6 | "psr-4": { 7 | "AltchaOrg\\Altcha\\": "src/" 8 | } 9 | }, 10 | "authors": [ 11 | { 12 | "name": "Daniel Regeci", 13 | "email": "536331+ovx@users.noreply.github.com" 14 | } 15 | ], 16 | "require": { 17 | "php": ">=8.2", 18 | "ext-json": "*" 19 | }, 20 | "require-dev": { 21 | "phpunit/phpunit": "^11.5", 22 | "phpstan/phpstan": "^2.1", 23 | "phpstan/phpstan-phpunit": "^2.0", 24 | "phpstan/extension-installer": "^1.4", 25 | "friendsofphp/php-cs-fixer": "^3.72" 26 | }, 27 | "config": { 28 | "allow-plugins": { 29 | "phpstan/extension-installer": true 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 | tests 16 | 17 | 18 | 19 | 20 | 21 | src 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /.github/workflows/php.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | 8 | 9 | jobs: 10 | 11 | tests: 12 | runs-on: ubuntu-latest 13 | timeout-minutes: 3 14 | 15 | steps: 16 | - uses: actions/checkout@v4 17 | 18 | - name: Setup PHP 19 | uses: shivammathur/setup-php@v2 20 | with: 21 | php-version: '8.2' 22 | coverage: xdebug 23 | 24 | - name: Validate composer.json and composer.lock 25 | run: composer validate --no-check-publish 26 | 27 | - name: Composer install 28 | run: composer install --no-progress 29 | 30 | - name: Run PHP-CS-Fixer 31 | run: vendor/bin/php-cs-fixer fix -v --dry-run --stop-on-violation --using-cache=no 32 | 33 | - name: Run PHPStan 34 | run: vendor/bin/phpstan analyse --no-progress --error-format=github 35 | 36 | - name: Run PHPUnit 37 | run: vendor/bin/phpunit --coverage-text 38 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Daniel Regeci 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /.php-cs-fixer.dist.php: -------------------------------------------------------------------------------- 1 | setParallelConfig(ParallelConfigFactory::detect()) 14 | ->setRules([ 15 | '@PHP71Migration' => true, 16 | '@PHPUnit75Migration:risky' => true, 17 | '@Symfony' => true, 18 | '@Symfony:risky' => true, 19 | 'protected_to_private' => false, 20 | 'phpdoc_annotation_without_dot' => false, 21 | 'increment_style' => [ 22 | 'style' => 'post', 23 | ], 24 | 'phpdoc_types_order' => [ 25 | 'null_adjustment' => 'always_first', 26 | ], 27 | 'concat_space' => [ 28 | 'spacing' => 'one', 29 | ], 30 | ]) 31 | ->setRiskyAllowed(true) 32 | ->setFinder( 33 | (new Finder()) 34 | ->in(__DIR__ . '/src') 35 | ->in(__DIR__ . '/tests') 36 | ->append([__FILE__]) 37 | ) 38 | ->setCacheFile('.php-cs-fixer.cache'); 39 | -------------------------------------------------------------------------------- /src/Hasher/Hasher.php: -------------------------------------------------------------------------------- 1 | sha1($data, true), 13 | Algorithm::SHA256 => hash('sha256', $data, true), 14 | Algorithm::SHA512 => hash('sha512', $data, true), 15 | }; 16 | } 17 | 18 | public function hashHex(Algorithm $algorithm, string $data): string 19 | { 20 | return bin2hex($this->hash($algorithm, $data)); 21 | } 22 | 23 | public function hashHmac(Algorithm $algorithm, string $data, #[\SensitiveParameter] string $hmacKey): string 24 | { 25 | return match ($algorithm) { 26 | Algorithm::SHA1 => hash_hmac('sha1', $data, $hmacKey, true), 27 | Algorithm::SHA256 => hash_hmac('sha256', $data, $hmacKey, true), 28 | Algorithm::SHA512 => hash_hmac('sha512', $data, $hmacKey, true), 29 | }; 30 | } 31 | 32 | public function hashHmacHex(Algorithm $algorithm, string $data, #[\SensitiveParameter] string $hmacKey): string 33 | { 34 | return bin2hex($this->hashHmac($algorithm, $data, $hmacKey)); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/BaseChallengeOptions.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | class BaseChallengeOptions 13 | { 14 | public const DEFAULT_MAX_NUMBER = 1000000; 15 | 16 | public readonly string $salt; 17 | 18 | /** 19 | * Options for creation of a new challenge. 20 | * 21 | * @see ChallengeOptions for options with sane defaults. 22 | * 23 | * @param ChallengeParams $params 24 | */ 25 | public function __construct( 26 | public readonly Algorithm $algorithm, 27 | public readonly int $maxNumber, 28 | public readonly ?\DateTimeInterface $expires, 29 | string $salt, 30 | public readonly int $number, 31 | public readonly array $params, 32 | ) { 33 | if ($expires) { 34 | $params['expires'] = $expires->getTimestamp(); 35 | } 36 | 37 | if (!empty($params)) { 38 | $salt .= '?' . http_build_query($params); 39 | } 40 | 41 | // Add a delimiter to prevent parameter splicing 42 | if (!str_ends_with($salt, '&')) { 43 | $salt .= '&'; 44 | } 45 | 46 | $this->salt = $salt; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/ChallengeOptions.php: -------------------------------------------------------------------------------- 1 | $saltLength Length of the random salt (default: 12 bytes). 25 | */ 26 | public function __construct( 27 | Algorithm $algorithm = Algorithm::SHA256, 28 | int $maxNumber = self::DEFAULT_MAX_NUMBER, 29 | ?\DateTimeInterface $expires = null, 30 | array $params = [], 31 | int $saltLength = self::DEFAULT_SALT_LENGTH, 32 | ) { 33 | parent::__construct( 34 | $algorithm, 35 | $maxNumber, 36 | $expires, 37 | bin2hex(self::randomBytes($saltLength)), 38 | self::randomInt($maxNumber), 39 | $params 40 | ); 41 | } 42 | 43 | private static function randomInt(int $max): int 44 | { 45 | return random_int(0, $max); 46 | } 47 | 48 | /** 49 | * @param int<1, max> $length 50 | */ 51 | private static function randomBytes(int $length): string 52 | { 53 | return random_bytes($length); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to ALTCHA 2 | 3 | We appreciate your contributions! To ensure a smooth and transparent collaboration, we've outlined the various ways you can contribute to ALTCHA: 4 | 5 | - **Reporting a Bug** 6 | - **Discussing the Current State of the Code** 7 | - **Submitting a Fix** 8 | - **Proposing New Features** 9 | - **Becoming a Maintainer** 10 | 11 | ## Development with GitHub 12 | 13 | ALTCHA is hosted on GitHub, where you can find the codebase, track issues, and submit pull requests. Please familiarize yourself with GitHub for effective collaboration. 14 | 15 | ## Project Technology: Svelte 16 | 17 | ALTCHA utilizes [Svelte](https://svelte.dev) for its Web Component widget. Refer to Svelte's documentation to set up your development environment. 18 | 19 | ## Licensing Information 20 | 21 | Any contributions you make will be subjected to the project's MIT software license. By submitting code changes, you agree to license your contributions under the same [MIT License](http://choosealicense.com/licenses/mit/) that covers the entire project. If you have any concerns regarding licensing, feel free to reach out to the maintainers. 22 | 23 | ## Reporting Bugs Using GitHub's [Issues](https://github.com/altcha-org/altcha-lib-php/issues) 24 | 25 | We track public bugs using GitHub issues. Reporting a bug is easy: simply [open a new issue](https://github.com/altcha-org/altcha-lib-php/issues). Provide detailed information for effective bug resolution. 26 | 27 | ## Writing Effective Bug Reports 28 | 29 | Good bug reports include: 30 | 31 | - A quick summary and background of the issue 32 | - Steps to reproduce the problem 33 | - Be specific! 34 | - Include sample code if possible 35 | - Expected vs. actual outcomes 36 | - Additional notes, such as your hypotheses or unsuccessful attempts to resolve the issue 37 | 38 | ## License Agreement 39 | 40 | By contributing to ALTCHA, you agree that your contributions will be licensed under the project's MIT License. If you have any questions or concerns, please reach out to the maintainers. 41 | -------------------------------------------------------------------------------- /src/Obfuscator.php: -------------------------------------------------------------------------------- 1 | maxNumber] inclusive is chosen. 30 | * 31 | * @return string Base64-encoded bytes of ciphertext followed by the 16‑byte GCM authentication tag ($ciphertext . $tag). 32 | */ 33 | public function obfuscateData(string $raw, string $key = '', ?int $counter = null): string 34 | { 35 | $cipher = 'AES-256-GCM'; 36 | $keyHash = $this->hasher->hash(Algorithm::SHA256, $key); 37 | 38 | $ivLength = openssl_cipher_iv_length($cipher); 39 | 40 | if (false === $ivLength) { 41 | throw new \RuntimeException('Getting cipher iv length failed.'); 42 | } 43 | 44 | $iv = ''; // AES‑GCM initialization vector (IV), typically 12 bytes for AES-256-GCM 45 | $num = $counter ?? $this->randomInt(); 46 | 47 | // Fill IV from the counter, one byte at a time (little‑endian) 48 | for ($i = 0; $i < $ivLength; $i++) { 49 | $iv .= \chr($num % 256); 50 | $num = intdiv($num, 256); 51 | } 52 | 53 | $encryptedData = openssl_encrypt($raw, $cipher, $keyHash, \OPENSSL_RAW_DATA, $iv, $tag); 54 | 55 | if (!$encryptedData) { 56 | throw new \RuntimeException('Data encryption failed.'); 57 | } 58 | 59 | return base64_encode($encryptedData . $tag); 60 | } 61 | 62 | private function randomInt(): int 63 | { 64 | return random_int(0, $this->maxNumber); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ALTCHA PHP Library 2 | 3 | The ALTCHA PHP Library is a lightweight, zero-dependency library designed for creating and verifying [ALTCHA](https://altcha.org) challenges, specifically tailored for PHP applications. 4 | 5 | ## Compatibility 6 | 7 | This library is compatible with: 8 | 9 | - PHP 8.2+ (use version v0.x.x for older PHP version) 10 | - All major platforms (Linux, Windows, macOS) 11 | 12 | ## Example 13 | 14 | - [Demo server](https://github.com/altcha-org/altcha-starter-php) 15 | 16 | ## Installation 17 | 18 | To install the ALTCHA PHP Library, use the following command: 19 | 20 | ```sh 21 | composer require altcha-org/altcha 22 | ``` 23 | 24 | ## Usage 25 | 26 | Here’s a basic example of how to use the ALTCHA PHP Library: 27 | 28 | ```php 29 | add(new \DateInterval('PT10S')), 42 | ); 43 | 44 | $challenge = $altcha->createChallenge($options); 45 | echo "Challenge created: " . json_encode($challenge) . "\n"; 46 | 47 | // Example payload to verify 48 | $payload = [ 49 | 'algorithm' => $challenge->algorithm, 50 | 'challenge' => $challenge->challenge, 51 | 'number' => 12345, // Example number 52 | 'salt' => $challenge->salt, 53 | 'signature' => $challenge->signature, 54 | ]; 55 | 56 | // Verify the solution 57 | $ok = $altcha->verifySolution($payload, true); 58 | 59 | if ($ok) { 60 | echo "Solution verified!\n"; 61 | } else { 62 | echo "Invalid solution.\n"; 63 | } 64 | ``` 65 | 66 | ## API 67 | 68 | ### `Altcha::createChallenge(ChallengeOptions $options): Challenge` 69 | 70 | Creates a new challenge for ALTCHA. 71 | 72 | **Returns:** `Challenge` 73 | 74 | #### `ChallengeOptions` 75 | 76 | ```php 77 | $options = new ChallengeOptions( 78 | algorithm: Algorithm::SHA256, 79 | maxNumber: BaseChallengeOptions::DEFAULT_MAX_NUMBER, 80 | expires: (new \DateTimeImmutable())->add(new \DateInterval('PT10S')), 81 | params: ['query_param' => '123'], 82 | saltLength: 12 83 | ); 84 | ``` 85 | 86 | ### `Altcha::verifySolution(array|string $payload, bool $checkExpires): bool` 87 | 88 | Verifies an ALTCHA solution. 89 | 90 | **Parameters:** 91 | 92 | - `data array|string`: The solution payload to verify. 93 | - `checkExpires bool`: Whether to check if the challenge has expired. 94 | 95 | **Returns:** `bool` 96 | 97 | ### `Altcha::verifyFieldsHash(array $formData, array $fields, string $fieldsHash, Algorithm $algorithm): bool` 98 | 99 | Verifies the hash of form fields. 100 | 101 | **Parameters:** 102 | 103 | - `formData array`: The form data to hash. 104 | - `fields array`: The fields to include in the hash. 105 | - `fieldsHash string`: The expected hash value. 106 | - `algorithm string`: Hashing algorithm (`SHA-1`, `SHA-256`, `SHA-512`). 107 | 108 | **Returns:** `bool` 109 | 110 | ### `Altcha::verifyServerSignature(array|string $payload): ServerSignatureVerification` 111 | 112 | Verifies the server signature. 113 | 114 | **Parameters:** 115 | 116 | - `data array|string`: The payload to verify (string or `ServerSignaturePayload` array). 117 | 118 | **Returns:** `ServerSignatureVerification` 119 | 120 | ### `Altcha::solveChallenge(string $challenge, string $salt, Algorithm $algorithm, int $max, int $start = 0): array` 121 | 122 | Finds a solution to the given challenge. 123 | 124 | **Parameters:** 125 | 126 | - `challenge string`: The challenge hash. 127 | - `salt string`: The challenge salt. 128 | - `algorithm string`: Hashing algorithm (`SHA-1`, `SHA-256`, `SHA-512`). 129 | - `max int`: Maximum number to iterate to. 130 | - `start int`: Starting number. 131 | 132 | **Returns:** `null|Solution` 133 | 134 | ## Generate obfuscation payload 135 | 136 | Generate an obfuscated payload for client-side clarification: 137 | 138 | ```php 139 | obfuscateData($plaintext, $key, $fixedCounter); 155 | 156 | echo $payload; 157 | // P7bJsUgzxP416d1voeF/QnQOD5g7GItB/zdfkoBrKgZK4N4IYkDJqg== 158 | ``` 159 | 160 | ## Tests 161 | 162 | ```sh 163 | vendor/bin/phpunit --bootstrap src/Altcha.php tests/AltchaTest.php 164 | ``` 165 | 166 | ## License 167 | 168 | MIT 169 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | GitHub Issues. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /src/Altcha.php: -------------------------------------------------------------------------------- 1 | 24 | */ 25 | private function decodePayload(string $payload): ?array 26 | { 27 | $decoded = base64_decode($payload, true); 28 | 29 | if (!$decoded) { 30 | return null; 31 | } 32 | 33 | try { 34 | $data = json_decode($decoded, true, 2, \JSON_THROW_ON_ERROR); 35 | } catch (\JsonException|\ValueError) { 36 | return null; 37 | } 38 | 39 | if (!\is_array($data) || empty($data)) { 40 | return null; 41 | } 42 | 43 | return $data; 44 | } 45 | 46 | /** 47 | * @param array|string $data 48 | */ 49 | private function verifyAndBuildSolutionPayload(string|array $data): ?Payload 50 | { 51 | if (\is_string($data)) { 52 | $data = $this->decodePayload($data); 53 | } 54 | 55 | if (null === $data 56 | || !isset($data['algorithm'], $data['challenge'], $data['number'], $data['salt'], $data['signature']) 57 | || !\is_string($data['algorithm']) 58 | || !\is_string($data['challenge']) 59 | || !\is_int($data['number']) 60 | || !\is_string($data['salt']) 61 | || !\is_string($data['signature']) 62 | ) { 63 | return null; 64 | } 65 | 66 | $algorithm = Algorithm::tryFrom($data['algorithm']); 67 | 68 | if (!$algorithm) { 69 | return null; 70 | } 71 | 72 | return new Payload($algorithm, $data['challenge'], $data['number'], $data['salt'], $data['signature']); 73 | } 74 | 75 | /** 76 | * @param array|string $data 77 | */ 78 | private function verifyAndBuildServerSignaturePayload(string|array $data): ?ServerSignaturePayload 79 | { 80 | if (\is_string($data)) { 81 | $data = $this->decodePayload($data); 82 | } 83 | 84 | if (null === $data 85 | || !isset($data['algorithm'], $data['verificationData'], $data['signature'], $data['verified']) 86 | || !\is_string($data['algorithm']) 87 | || !\is_string($data['verificationData']) 88 | || !\is_string($data['signature']) 89 | || !\is_bool($data['verified']) 90 | ) { 91 | return null; 92 | } 93 | 94 | $algorithm = Algorithm::tryFrom($data['algorithm']); 95 | 96 | if (!$algorithm) { 97 | return null; 98 | } 99 | 100 | return new ServerSignaturePayload($algorithm, $data['verificationData'], $data['signature'], $data['verified']); 101 | } 102 | 103 | /** 104 | * Creates a new challenge for ALTCHA. 105 | * 106 | * @return Challenge The challenge data to be passed to ALTCHA. 107 | */ 108 | public function createChallenge(BaseChallengeOptions $options = new ChallengeOptions()): Challenge 109 | { 110 | $challenge = $this->hasher->hashHex($options->algorithm, $options->salt . $options->number); 111 | $signature = $this->hasher->hashHmacHex($options->algorithm, $challenge, $this->hmacKey); 112 | 113 | return new Challenge($options->algorithm->value, $challenge, $options->maxNumber, $options->salt, $signature); 114 | } 115 | 116 | /** 117 | * Verifies an ALTCHA solution. 118 | * 119 | * @param array|string $data The solution payload to verify. 120 | * @param bool $checkExpires Whether to check if the challenge has expired. 121 | * 122 | * @return bool True if the solution is valid. 123 | */ 124 | public function verifySolution(string|array $data, bool $checkExpires = true): bool 125 | { 126 | $payload = $this->verifyAndBuildSolutionPayload($data); 127 | 128 | if (!$payload) { 129 | return false; 130 | } 131 | 132 | $params = $this->extractParams($payload); 133 | if ($checkExpires && isset($params['expires']) && is_numeric($params['expires'])) { 134 | $expireTime = (int) $params['expires']; 135 | if (time() > $expireTime) { 136 | return false; 137 | } 138 | } 139 | 140 | $challengeOptions = new CheckChallengeOptions( 141 | $payload->algorithm, 142 | $payload->salt, 143 | $payload->number 144 | ); 145 | 146 | $expectedChallenge = $this->createChallenge($challengeOptions); 147 | 148 | return $expectedChallenge->challenge === $payload->challenge 149 | && $expectedChallenge->signature === $payload->signature; 150 | } 151 | 152 | /** 153 | * @return array|string> 154 | */ 155 | private function extractParams(Payload $payload): array 156 | { 157 | $saltParts = explode('?', $payload->salt); 158 | if (\count($saltParts) > 1) { 159 | parse_str($saltParts[1], $params); 160 | 161 | return $params; 162 | } 163 | 164 | return []; 165 | } 166 | 167 | /** 168 | * Verifies the hash of form fields. 169 | * 170 | * @param array $formData The form data to hash. 171 | * @param array $fields The fields to include in the hash. 172 | * @param string $fieldsHash The expected hash value. 173 | * @param Algorithm $algorithm Hashing algorithm (`SHA-1`, `SHA-256`, `SHA-512`). 174 | */ 175 | public function verifyFieldsHash(array $formData, array $fields, string $fieldsHash, Algorithm $algorithm): bool 176 | { 177 | $lines = []; 178 | foreach ($fields as $field) { 179 | $lines[] = $formData[$field] ?? ''; 180 | } 181 | $joinedData = implode("\n", $lines); 182 | $computedHash = $this->hasher->hashHex($algorithm, $joinedData); 183 | 184 | return $computedHash === $fieldsHash; 185 | } 186 | 187 | /** 188 | * Verifies the server signature. 189 | * 190 | * @param array|string $data The payload to verify (string or `ServerSignaturePayload` array). 191 | */ 192 | public function verifyServerSignature(string|array $data): ServerSignatureVerification 193 | { 194 | $payload = $this->verifyAndBuildServerSignaturePayload($data); 195 | 196 | if (!$payload) { 197 | return new ServerSignatureVerification(false, null); 198 | } 199 | 200 | $hash = $this->hasher->hash($payload->algorithm, $payload->verificationData); 201 | $expectedSignature = $this->hasher->hashHmacHex($payload->algorithm, $hash, $this->hmacKey); 202 | 203 | parse_str($payload->verificationData, $params); 204 | 205 | $verificationData = new ServerSignatureVerificationData( 206 | classification: isset($params['classification']) && \is_string($params['classification']) ? $params['classification'] : '', 207 | country: isset($params['country']) && \is_string($params['country']) ? $params['country'] : '', 208 | detectedLanguage: isset($params['detectedLanguage']) && \is_string($params['detectedLanguage']) ? $params['detectedLanguage'] : '', 209 | email: isset($params['email']) && \is_string($params['email']) ? $params['email'] : '', 210 | expire: isset($params['expire']) && is_numeric($params['expire']) ? (int) $params['expire'] : 0, 211 | fields: isset($params['fields']) && \is_array($params['fields']) ? $params['fields'] : [], 212 | fieldsHash: isset($params['fieldsHash']) && \is_string($params['fieldsHash']) ? $params['fieldsHash'] : '', 213 | reasons: isset($params['reasons']) && \is_array($params['reasons']) ? $params['reasons'] : [], 214 | score: isset($params['score']) && is_numeric($params['score']) ? (float) $params['score'] : 0.0, 215 | time: isset($params['time']) && is_numeric($params['time']) ? (int) $params['time'] : 0, 216 | verified: isset($params['verified']) && $params['verified'], 217 | ); 218 | 219 | $now = time(); 220 | $isVerified = $payload->verified && $verificationData->verified 221 | && $verificationData->expire > $now 222 | && $payload->signature === $expectedSignature; 223 | 224 | return new ServerSignatureVerification($isVerified, $verificationData); 225 | } 226 | 227 | /** 228 | * Finds a solution to the given challenge. 229 | * 230 | * @param string $challenge The challenge hash. 231 | * @param string $salt The challenge salt. 232 | * @param Algorithm $algorithm Hashing algorithm. 233 | * @param int $max Maximum number to iterate to. 234 | * @param int $start Starting number. 235 | */ 236 | public function solveChallenge(string $challenge, string $salt, Algorithm $algorithm, int $max, int $start = 0): ?Solution 237 | { 238 | $startTime = microtime(true); 239 | 240 | for ($n = $start; $n <= $max; $n++) { 241 | $hash = $this->hasher->hashHex($algorithm, $salt . $n); 242 | if ($hash === $challenge) { 243 | $took = microtime(true) - $startTime; 244 | 245 | return new Solution($n, $took); 246 | } 247 | } 248 | 249 | return null; 250 | } 251 | } 252 | -------------------------------------------------------------------------------- /tests/AltchaTest.php: -------------------------------------------------------------------------------- 1 | createChallenge(); 25 | } 26 | 27 | public function testCreateChallenge(): void 28 | { 29 | self::assertEquals(Algorithm::SHA256->value, self::$challenge->algorithm); 30 | self::assertNotEmpty(self::$challenge->challenge); 31 | self::assertEquals(BaseChallengeOptions::DEFAULT_MAX_NUMBER, self::$challenge->maxNumber); 32 | self::assertNotEmpty(self::$challenge->salt); 33 | self::assertNotEmpty(self::$challenge->signature); 34 | } 35 | 36 | public function testVerifyFieldsHash(): void 37 | { 38 | $formData = [ 39 | 'field1' => 'value1', 40 | 'field2' => 'value2', 41 | ]; 42 | 43 | $fields = ['field1', 'field2']; 44 | $fieldsHash = '1e823fb92790112edaa34e8cfed2afbb86054153932d8c2796d2c62727d287a6'; 45 | 46 | $isValid = self::$altcha->verifyFieldsHash($formData, $fields, $fieldsHash, Algorithm::SHA256); 47 | 48 | self::assertTrue($isValid); 49 | } 50 | 51 | public function testSolveChallenge(): void 52 | { 53 | $solution = self::$altcha->solveChallenge( 54 | self::$challenge->challenge, 55 | self::$challenge->salt, 56 | Algorithm::from(self::$challenge->algorithm), 57 | self::$challenge->maxNumber 58 | ); 59 | 60 | self::assertInstanceOf(Solution::class, $solution); 61 | self::assertEquals($solution->number, $solution->number); 62 | self::assertGreaterThan(0, $solution->took); 63 | } 64 | 65 | public function testInvalidSolveChallenge(): void 66 | { 67 | $solution = self::$altcha->solveChallenge( 68 | 'asd', 69 | self::$challenge->salt, 70 | Algorithm::from(self::$challenge->algorithm), 71 | self::$challenge->maxNumber 72 | ); 73 | 74 | self::assertNull($solution); 75 | } 76 | 77 | public function testVerifySolution(): void 78 | { 79 | $solution = self::$altcha->solveChallenge( 80 | self::$challenge->challenge, 81 | self::$challenge->salt, 82 | Algorithm::from(self::$challenge->algorithm), 83 | self::$challenge->maxNumber 84 | ); 85 | 86 | self::assertInstanceOf(Solution::class, $solution); 87 | 88 | $payload = [ 89 | 'algorithm' => self::$challenge->algorithm, 90 | 'challenge' => self::$challenge->challenge, 91 | 'salt' => self::$challenge->salt, 92 | 'signature' => self::$challenge->signature, 93 | 'number' => $solution->number, 94 | ]; 95 | 96 | $isValid = self::$altcha->verifySolution(base64_encode(json_encode($payload) ?: '')); 97 | 98 | self::assertTrue($isValid); 99 | } 100 | 101 | public function testVerifySolutionSaltSplicing(): void 102 | { 103 | $challenge = self::$altcha->createChallenge(new BaseChallengeOptions( 104 | algorithm: Algorithm::SHA256, 105 | maxNumber: 50000, 106 | number: 123, 107 | expires: (new DateTimeImmutable())->add(new DateInterval('PT10S')), 108 | params: [], 109 | salt: bin2hex(random_bytes(12)), 110 | )); 111 | 112 | $payload = [ 113 | 'algorithm' => $challenge->algorithm, 114 | 'challenge' => $challenge->challenge, 115 | 'salt' => $challenge->salt . '1', 116 | 'signature' => $challenge->signature, 117 | 'number' => 23, 118 | ]; 119 | 120 | $isValid = self::$altcha->verifySolution(base64_encode(json_encode($payload) ?: '')); 121 | 122 | self::assertFalse($isValid); 123 | } 124 | 125 | public function testVerifyServerSignature(): void 126 | { 127 | $algorithm = Algorithm::SHA256; 128 | $expires = (new DateTimeImmutable())->add(new DateInterval('PT10S')); 129 | $verificationData = 'verified=1&expire=' . $expires->getTimestamp(); 130 | 131 | $hash = self::$hasher->hash($algorithm, $verificationData); 132 | $signature = self::$hasher->hashHmacHex($algorithm, $hash, 'test-key'); 133 | 134 | $result = self::$altcha->verifyServerSignature([ 135 | 'algorithm' => $algorithm->value, 136 | 'verificationData' => $verificationData, 137 | 'signature' => $signature, 138 | 'verified' => true, 139 | ]); 140 | 141 | self::assertTrue($result->verified); 142 | } 143 | 144 | public function testVerifyCustomOptions(): void 145 | { 146 | $maxNumber = 100; 147 | $algorithm = Algorithm::SHA1; 148 | 149 | $challenge = self::$altcha->createChallenge(new ChallengeOptions( 150 | algorithm: $algorithm, 151 | maxNumber: $maxNumber, 152 | expires: (new DateTimeImmutable())->add(new DateInterval('PT10S')), 153 | params: ['custom_param' => '123'], 154 | saltLength: 3, 155 | )); 156 | 157 | $solution = self::$altcha->solveChallenge( 158 | $challenge->challenge, 159 | $challenge->salt, 160 | $algorithm, 161 | $maxNumber, 162 | ); 163 | 164 | self::assertInstanceOf(Solution::class, $solution); 165 | 166 | $isValid = self::$altcha->verifySolution([ 167 | 'algorithm' => $algorithm->value, 168 | 'challenge' => $challenge->challenge, 169 | 'salt' => $challenge->salt, 170 | 'signature' => $challenge->signature, 171 | 'number' => $solution->number, 172 | ]); 173 | 174 | self::assertTrue($isValid); 175 | } 176 | 177 | public function testHandlesExpired(): void 178 | { 179 | $maxNumber = 100; 180 | $expires = (new DateTimeImmutable())->sub(new DateInterval('PT10S')); 181 | 182 | $challenge = self::$altcha->createChallenge(new ChallengeOptions( 183 | maxNumber: $maxNumber, 184 | expires: $expires, 185 | )); 186 | 187 | $solution = self::$altcha->solveChallenge( 188 | $challenge->challenge, 189 | $challenge->salt, 190 | Algorithm::from($challenge->algorithm), 191 | $maxNumber, 192 | ); 193 | 194 | self::assertInstanceOf(Solution::class, $solution); 195 | 196 | $isValid = self::$altcha->verifySolution([ 197 | 'algorithm' => $challenge->algorithm, 198 | 'challenge' => $challenge->challenge, 199 | 'salt' => $challenge->salt, 200 | 'signature' => $challenge->signature, 201 | 'number' => $solution->number, 202 | ]); 203 | 204 | self::assertFalse($isValid); 205 | } 206 | 207 | public function testInvalidPayloads(): void 208 | { 209 | // completely invalid string 210 | $isValid = self::$altcha->verifySolution('I am invalid'); 211 | self::assertFalse($isValid); 212 | 213 | // invalid base64 string 214 | $isValid = self::$altcha->verifySolution('$' . base64_encode('I am invalid')); 215 | self::assertFalse($isValid); 216 | 217 | // invalid JSON string 218 | $isValid = self::$altcha->verifySolution(base64_encode('I am invalid')); 219 | self::assertFalse($isValid); 220 | 221 | // invalid JSON data 222 | $isValid = self::$altcha->verifySolution(base64_encode('"I am not an array"')); 223 | self::assertFalse($isValid); 224 | 225 | $isValid = self::$altcha->verifySolution([ 226 | 'algorithm' => 'md5', 227 | 'challenge' => 'invalid', 228 | 'salt' => 'salt', 229 | 'signature' => 'signature', 230 | 'number' => 10, 231 | ]); 232 | self::assertFalse($isValid); 233 | 234 | $verification = self::$altcha->verifyServerSignature('I am invalid'); 235 | self::assertFalse($verification->verified); 236 | 237 | $verification = self::$altcha->verifyServerSignature([ 238 | 'algorithm' => 'md5', 239 | 'verificationData' => 'asd', 240 | 'signature' => 'signature', 241 | 'verified' => true, 242 | ]); 243 | self::assertFalse($verification->verified); 244 | } 245 | 246 | public function testDataObfuscation(): void 247 | { 248 | $obfuscator = new Obfuscator(); 249 | $counter = 1234; 250 | 251 | $email = 'mailto:hello@example.com'; 252 | $address = 'Big Company Ltd.' . \PHP_EOL . '123 Baker Street' . \PHP_EOL . 'London' . \PHP_EOL . 'NW1 6XE' . \PHP_EOL . 'United Kingdom'; 253 | 254 | $obfuscatedEmail = $obfuscator->obfuscateData($email, '', $counter); 255 | $obfuscatedAddress = $obfuscator->obfuscateData($address, '', $counter); 256 | 257 | self::assertEquals('0WkWnouD/fos4DdkwHP2yQ1/UejeYYUjP2vtH+F5+s8PYTJcvup6mg==', $obfuscatedEmail); 258 | self::assertEquals('/mEY0ryDquIo4iIrzGLqhmo+D77QQIslSwgQNW1ojHqPmhU6DxlmZfKkXAfiCR2BabAg7E/K7kPttHA/c5sDe08H1tR822PCVNxRwGbVOg==', $obfuscatedAddress); 259 | 260 | $key = 'shared-secret'; 261 | 262 | $obfuscatedEmailWithKey = $obfuscator->obfuscateData($email, $key, $counter); 263 | $obfuscatedAddressWithKey = $obfuscator->obfuscateData($address, $key, $counter); 264 | 265 | self::assertEquals('VYjBMLSjm0dasqAtnQvSlRiqG0V0paCoLFtNPZTB5jwmjPmV2Ja41w==', $obfuscatedEmailWithKey); 266 | self::assertEquals('eoDPfIOjzF9esLVikRrO2n/rRRN6hK6ug4cwoWDJHYS9++OfBQjOUMP9oBHiGbNR0+3pj2whifZf/Cixj6oG+ybIQjx/t2apDsSLwr4qKg==', $obfuscatedAddressWithKey); 267 | } 268 | } 269 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "c4396f2bd58054578ff9afba0215edf2", 8 | "packages": [], 9 | "packages-dev": [ 10 | { 11 | "name": "clue/ndjson-react", 12 | "version": "v1.3.0", 13 | "source": { 14 | "type": "git", 15 | "url": "https://github.com/clue/reactphp-ndjson.git", 16 | "reference": "392dc165fce93b5bb5c637b67e59619223c931b0" 17 | }, 18 | "dist": { 19 | "type": "zip", 20 | "url": "https://api.github.com/repos/clue/reactphp-ndjson/zipball/392dc165fce93b5bb5c637b67e59619223c931b0", 21 | "reference": "392dc165fce93b5bb5c637b67e59619223c931b0", 22 | "shasum": "" 23 | }, 24 | "require": { 25 | "php": ">=5.3", 26 | "react/stream": "^1.2" 27 | }, 28 | "require-dev": { 29 | "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.35", 30 | "react/event-loop": "^1.2" 31 | }, 32 | "type": "library", 33 | "autoload": { 34 | "psr-4": { 35 | "Clue\\React\\NDJson\\": "src/" 36 | } 37 | }, 38 | "notification-url": "https://packagist.org/downloads/", 39 | "license": [ 40 | "MIT" 41 | ], 42 | "authors": [ 43 | { 44 | "name": "Christian Lück", 45 | "email": "christian@clue.engineering" 46 | } 47 | ], 48 | "description": "Streaming newline-delimited JSON (NDJSON) parser and encoder for ReactPHP.", 49 | "homepage": "https://github.com/clue/reactphp-ndjson", 50 | "keywords": [ 51 | "NDJSON", 52 | "json", 53 | "jsonlines", 54 | "newline", 55 | "reactphp", 56 | "streaming" 57 | ], 58 | "support": { 59 | "issues": "https://github.com/clue/reactphp-ndjson/issues", 60 | "source": "https://github.com/clue/reactphp-ndjson/tree/v1.3.0" 61 | }, 62 | "funding": [ 63 | { 64 | "url": "https://clue.engineering/support", 65 | "type": "custom" 66 | }, 67 | { 68 | "url": "https://github.com/clue", 69 | "type": "github" 70 | } 71 | ], 72 | "time": "2022-12-23T10:58:28+00:00" 73 | }, 74 | { 75 | "name": "composer/pcre", 76 | "version": "3.3.2", 77 | "source": { 78 | "type": "git", 79 | "url": "https://github.com/composer/pcre.git", 80 | "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e" 81 | }, 82 | "dist": { 83 | "type": "zip", 84 | "url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e", 85 | "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e", 86 | "shasum": "" 87 | }, 88 | "require": { 89 | "php": "^7.4 || ^8.0" 90 | }, 91 | "conflict": { 92 | "phpstan/phpstan": "<1.11.10" 93 | }, 94 | "require-dev": { 95 | "phpstan/phpstan": "^1.12 || ^2", 96 | "phpstan/phpstan-strict-rules": "^1 || ^2", 97 | "phpunit/phpunit": "^8 || ^9" 98 | }, 99 | "type": "library", 100 | "extra": { 101 | "phpstan": { 102 | "includes": [ 103 | "extension.neon" 104 | ] 105 | }, 106 | "branch-alias": { 107 | "dev-main": "3.x-dev" 108 | } 109 | }, 110 | "autoload": { 111 | "psr-4": { 112 | "Composer\\Pcre\\": "src" 113 | } 114 | }, 115 | "notification-url": "https://packagist.org/downloads/", 116 | "license": [ 117 | "MIT" 118 | ], 119 | "authors": [ 120 | { 121 | "name": "Jordi Boggiano", 122 | "email": "j.boggiano@seld.be", 123 | "homepage": "http://seld.be" 124 | } 125 | ], 126 | "description": "PCRE wrapping library that offers type-safe preg_* replacements.", 127 | "keywords": [ 128 | "PCRE", 129 | "preg", 130 | "regex", 131 | "regular expression" 132 | ], 133 | "support": { 134 | "issues": "https://github.com/composer/pcre/issues", 135 | "source": "https://github.com/composer/pcre/tree/3.3.2" 136 | }, 137 | "funding": [ 138 | { 139 | "url": "https://packagist.com", 140 | "type": "custom" 141 | }, 142 | { 143 | "url": "https://github.com/composer", 144 | "type": "github" 145 | }, 146 | { 147 | "url": "https://tidelift.com/funding/github/packagist/composer/composer", 148 | "type": "tidelift" 149 | } 150 | ], 151 | "time": "2024-11-12T16:29:46+00:00" 152 | }, 153 | { 154 | "name": "composer/semver", 155 | "version": "3.4.3", 156 | "source": { 157 | "type": "git", 158 | "url": "https://github.com/composer/semver.git", 159 | "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12" 160 | }, 161 | "dist": { 162 | "type": "zip", 163 | "url": "https://api.github.com/repos/composer/semver/zipball/4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", 164 | "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", 165 | "shasum": "" 166 | }, 167 | "require": { 168 | "php": "^5.3.2 || ^7.0 || ^8.0" 169 | }, 170 | "require-dev": { 171 | "phpstan/phpstan": "^1.11", 172 | "symfony/phpunit-bridge": "^3 || ^7" 173 | }, 174 | "type": "library", 175 | "extra": { 176 | "branch-alias": { 177 | "dev-main": "3.x-dev" 178 | } 179 | }, 180 | "autoload": { 181 | "psr-4": { 182 | "Composer\\Semver\\": "src" 183 | } 184 | }, 185 | "notification-url": "https://packagist.org/downloads/", 186 | "license": [ 187 | "MIT" 188 | ], 189 | "authors": [ 190 | { 191 | "name": "Nils Adermann", 192 | "email": "naderman@naderman.de", 193 | "homepage": "http://www.naderman.de" 194 | }, 195 | { 196 | "name": "Jordi Boggiano", 197 | "email": "j.boggiano@seld.be", 198 | "homepage": "http://seld.be" 199 | }, 200 | { 201 | "name": "Rob Bast", 202 | "email": "rob.bast@gmail.com", 203 | "homepage": "http://robbast.nl" 204 | } 205 | ], 206 | "description": "Semver library that offers utilities, version constraint parsing and validation.", 207 | "keywords": [ 208 | "semantic", 209 | "semver", 210 | "validation", 211 | "versioning" 212 | ], 213 | "support": { 214 | "irc": "ircs://irc.libera.chat:6697/composer", 215 | "issues": "https://github.com/composer/semver/issues", 216 | "source": "https://github.com/composer/semver/tree/3.4.3" 217 | }, 218 | "funding": [ 219 | { 220 | "url": "https://packagist.com", 221 | "type": "custom" 222 | }, 223 | { 224 | "url": "https://github.com/composer", 225 | "type": "github" 226 | }, 227 | { 228 | "url": "https://tidelift.com/funding/github/packagist/composer/composer", 229 | "type": "tidelift" 230 | } 231 | ], 232 | "time": "2024-09-19T14:15:21+00:00" 233 | }, 234 | { 235 | "name": "composer/xdebug-handler", 236 | "version": "3.0.5", 237 | "source": { 238 | "type": "git", 239 | "url": "https://github.com/composer/xdebug-handler.git", 240 | "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef" 241 | }, 242 | "dist": { 243 | "type": "zip", 244 | "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/6c1925561632e83d60a44492e0b344cf48ab85ef", 245 | "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef", 246 | "shasum": "" 247 | }, 248 | "require": { 249 | "composer/pcre": "^1 || ^2 || ^3", 250 | "php": "^7.2.5 || ^8.0", 251 | "psr/log": "^1 || ^2 || ^3" 252 | }, 253 | "require-dev": { 254 | "phpstan/phpstan": "^1.0", 255 | "phpstan/phpstan-strict-rules": "^1.1", 256 | "phpunit/phpunit": "^8.5 || ^9.6 || ^10.5" 257 | }, 258 | "type": "library", 259 | "autoload": { 260 | "psr-4": { 261 | "Composer\\XdebugHandler\\": "src" 262 | } 263 | }, 264 | "notification-url": "https://packagist.org/downloads/", 265 | "license": [ 266 | "MIT" 267 | ], 268 | "authors": [ 269 | { 270 | "name": "John Stevenson", 271 | "email": "john-stevenson@blueyonder.co.uk" 272 | } 273 | ], 274 | "description": "Restarts a process without Xdebug.", 275 | "keywords": [ 276 | "Xdebug", 277 | "performance" 278 | ], 279 | "support": { 280 | "irc": "ircs://irc.libera.chat:6697/composer", 281 | "issues": "https://github.com/composer/xdebug-handler/issues", 282 | "source": "https://github.com/composer/xdebug-handler/tree/3.0.5" 283 | }, 284 | "funding": [ 285 | { 286 | "url": "https://packagist.com", 287 | "type": "custom" 288 | }, 289 | { 290 | "url": "https://github.com/composer", 291 | "type": "github" 292 | }, 293 | { 294 | "url": "https://tidelift.com/funding/github/packagist/composer/composer", 295 | "type": "tidelift" 296 | } 297 | ], 298 | "time": "2024-05-06T16:37:16+00:00" 299 | }, 300 | { 301 | "name": "evenement/evenement", 302 | "version": "v3.0.2", 303 | "source": { 304 | "type": "git", 305 | "url": "https://github.com/igorw/evenement.git", 306 | "reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc" 307 | }, 308 | "dist": { 309 | "type": "zip", 310 | "url": "https://api.github.com/repos/igorw/evenement/zipball/0a16b0d71ab13284339abb99d9d2bd813640efbc", 311 | "reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc", 312 | "shasum": "" 313 | }, 314 | "require": { 315 | "php": ">=7.0" 316 | }, 317 | "require-dev": { 318 | "phpunit/phpunit": "^9 || ^6" 319 | }, 320 | "type": "library", 321 | "autoload": { 322 | "psr-4": { 323 | "Evenement\\": "src/" 324 | } 325 | }, 326 | "notification-url": "https://packagist.org/downloads/", 327 | "license": [ 328 | "MIT" 329 | ], 330 | "authors": [ 331 | { 332 | "name": "Igor Wiedler", 333 | "email": "igor@wiedler.ch" 334 | } 335 | ], 336 | "description": "Événement is a very simple event dispatching library for PHP", 337 | "keywords": [ 338 | "event-dispatcher", 339 | "event-emitter" 340 | ], 341 | "support": { 342 | "issues": "https://github.com/igorw/evenement/issues", 343 | "source": "https://github.com/igorw/evenement/tree/v3.0.2" 344 | }, 345 | "time": "2023-08-08T05:53:35+00:00" 346 | }, 347 | { 348 | "name": "fidry/cpu-core-counter", 349 | "version": "1.2.0", 350 | "source": { 351 | "type": "git", 352 | "url": "https://github.com/theofidry/cpu-core-counter.git", 353 | "reference": "8520451a140d3f46ac33042715115e290cf5785f" 354 | }, 355 | "dist": { 356 | "type": "zip", 357 | "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/8520451a140d3f46ac33042715115e290cf5785f", 358 | "reference": "8520451a140d3f46ac33042715115e290cf5785f", 359 | "shasum": "" 360 | }, 361 | "require": { 362 | "php": "^7.2 || ^8.0" 363 | }, 364 | "require-dev": { 365 | "fidry/makefile": "^0.2.0", 366 | "fidry/php-cs-fixer-config": "^1.1.2", 367 | "phpstan/extension-installer": "^1.2.0", 368 | "phpstan/phpstan": "^1.9.2", 369 | "phpstan/phpstan-deprecation-rules": "^1.0.0", 370 | "phpstan/phpstan-phpunit": "^1.2.2", 371 | "phpstan/phpstan-strict-rules": "^1.4.4", 372 | "phpunit/phpunit": "^8.5.31 || ^9.5.26", 373 | "webmozarts/strict-phpunit": "^7.5" 374 | }, 375 | "type": "library", 376 | "autoload": { 377 | "psr-4": { 378 | "Fidry\\CpuCoreCounter\\": "src/" 379 | } 380 | }, 381 | "notification-url": "https://packagist.org/downloads/", 382 | "license": [ 383 | "MIT" 384 | ], 385 | "authors": [ 386 | { 387 | "name": "Théo FIDRY", 388 | "email": "theo.fidry@gmail.com" 389 | } 390 | ], 391 | "description": "Tiny utility to get the number of CPU cores.", 392 | "keywords": [ 393 | "CPU", 394 | "core" 395 | ], 396 | "support": { 397 | "issues": "https://github.com/theofidry/cpu-core-counter/issues", 398 | "source": "https://github.com/theofidry/cpu-core-counter/tree/1.2.0" 399 | }, 400 | "funding": [ 401 | { 402 | "url": "https://github.com/theofidry", 403 | "type": "github" 404 | } 405 | ], 406 | "time": "2024-08-06T10:04:20+00:00" 407 | }, 408 | { 409 | "name": "friendsofphp/php-cs-fixer", 410 | "version": "v3.75.0", 411 | "source": { 412 | "type": "git", 413 | "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", 414 | "reference": "399a128ff2fdaf4281e4e79b755693286cdf325c" 415 | }, 416 | "dist": { 417 | "type": "zip", 418 | "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/399a128ff2fdaf4281e4e79b755693286cdf325c", 419 | "reference": "399a128ff2fdaf4281e4e79b755693286cdf325c", 420 | "shasum": "" 421 | }, 422 | "require": { 423 | "clue/ndjson-react": "^1.0", 424 | "composer/semver": "^3.4", 425 | "composer/xdebug-handler": "^3.0.3", 426 | "ext-filter": "*", 427 | "ext-hash": "*", 428 | "ext-json": "*", 429 | "ext-tokenizer": "*", 430 | "fidry/cpu-core-counter": "^1.2", 431 | "php": "^7.4 || ^8.0", 432 | "react/child-process": "^0.6.5", 433 | "react/event-loop": "^1.0", 434 | "react/promise": "^2.0 || ^3.0", 435 | "react/socket": "^1.0", 436 | "react/stream": "^1.0", 437 | "sebastian/diff": "^4.0 || ^5.1 || ^6.0 || ^7.0", 438 | "symfony/console": "^5.4 || ^6.4 || ^7.0", 439 | "symfony/event-dispatcher": "^5.4 || ^6.4 || ^7.0", 440 | "symfony/filesystem": "^5.4 || ^6.4 || ^7.0", 441 | "symfony/finder": "^5.4 || ^6.4 || ^7.0", 442 | "symfony/options-resolver": "^5.4 || ^6.4 || ^7.0", 443 | "symfony/polyfill-mbstring": "^1.31", 444 | "symfony/polyfill-php80": "^1.31", 445 | "symfony/polyfill-php81": "^1.31", 446 | "symfony/process": "^5.4 || ^6.4 || ^7.2", 447 | "symfony/stopwatch": "^5.4 || ^6.4 || ^7.0" 448 | }, 449 | "require-dev": { 450 | "facile-it/paraunit": "^1.3.1 || ^2.6", 451 | "infection/infection": "^0.29.14", 452 | "justinrainbow/json-schema": "^5.3 || ^6.2", 453 | "keradus/cli-executor": "^2.1", 454 | "mikey179/vfsstream": "^1.6.12", 455 | "php-coveralls/php-coveralls": "^2.7", 456 | "php-cs-fixer/accessible-object": "^1.1", 457 | "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.6", 458 | "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.6", 459 | "phpunit/phpunit": "^9.6.22 || ^10.5.45 || ^11.5.12", 460 | "symfony/var-dumper": "^5.4.48 || ^6.4.18 || ^7.2.3", 461 | "symfony/yaml": "^5.4.45 || ^6.4.18 || ^7.2.3" 462 | }, 463 | "suggest": { 464 | "ext-dom": "For handling output formats in XML", 465 | "ext-mbstring": "For handling non-UTF8 characters." 466 | }, 467 | "bin": [ 468 | "php-cs-fixer" 469 | ], 470 | "type": "application", 471 | "autoload": { 472 | "psr-4": { 473 | "PhpCsFixer\\": "src/" 474 | }, 475 | "exclude-from-classmap": [ 476 | "src/Fixer/Internal/*" 477 | ] 478 | }, 479 | "notification-url": "https://packagist.org/downloads/", 480 | "license": [ 481 | "MIT" 482 | ], 483 | "authors": [ 484 | { 485 | "name": "Fabien Potencier", 486 | "email": "fabien@symfony.com" 487 | }, 488 | { 489 | "name": "Dariusz Rumiński", 490 | "email": "dariusz.ruminski@gmail.com" 491 | } 492 | ], 493 | "description": "A tool to automatically fix PHP code style", 494 | "keywords": [ 495 | "Static code analysis", 496 | "fixer", 497 | "standards", 498 | "static analysis" 499 | ], 500 | "support": { 501 | "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", 502 | "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.75.0" 503 | }, 504 | "funding": [ 505 | { 506 | "url": "https://github.com/keradus", 507 | "type": "github" 508 | } 509 | ], 510 | "time": "2025-03-31T18:40:42+00:00" 511 | }, 512 | { 513 | "name": "myclabs/deep-copy", 514 | "version": "1.13.0", 515 | "source": { 516 | "type": "git", 517 | "url": "https://github.com/myclabs/DeepCopy.git", 518 | "reference": "024473a478be9df5fdaca2c793f2232fe788e414" 519 | }, 520 | "dist": { 521 | "type": "zip", 522 | "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/024473a478be9df5fdaca2c793f2232fe788e414", 523 | "reference": "024473a478be9df5fdaca2c793f2232fe788e414", 524 | "shasum": "" 525 | }, 526 | "require": { 527 | "php": "^7.1 || ^8.0" 528 | }, 529 | "conflict": { 530 | "doctrine/collections": "<1.6.8", 531 | "doctrine/common": "<2.13.3 || >=3 <3.2.2" 532 | }, 533 | "require-dev": { 534 | "doctrine/collections": "^1.6.8", 535 | "doctrine/common": "^2.13.3 || ^3.2.2", 536 | "phpspec/prophecy": "^1.10", 537 | "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" 538 | }, 539 | "type": "library", 540 | "autoload": { 541 | "files": [ 542 | "src/DeepCopy/deep_copy.php" 543 | ], 544 | "psr-4": { 545 | "DeepCopy\\": "src/DeepCopy/" 546 | } 547 | }, 548 | "notification-url": "https://packagist.org/downloads/", 549 | "license": [ 550 | "MIT" 551 | ], 552 | "description": "Create deep copies (clones) of your objects", 553 | "keywords": [ 554 | "clone", 555 | "copy", 556 | "duplicate", 557 | "object", 558 | "object graph" 559 | ], 560 | "support": { 561 | "issues": "https://github.com/myclabs/DeepCopy/issues", 562 | "source": "https://github.com/myclabs/DeepCopy/tree/1.13.0" 563 | }, 564 | "funding": [ 565 | { 566 | "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", 567 | "type": "tidelift" 568 | } 569 | ], 570 | "time": "2025-02-12T12:17:51+00:00" 571 | }, 572 | { 573 | "name": "nikic/php-parser", 574 | "version": "v5.4.0", 575 | "source": { 576 | "type": "git", 577 | "url": "https://github.com/nikic/PHP-Parser.git", 578 | "reference": "447a020a1f875a434d62f2a401f53b82a396e494" 579 | }, 580 | "dist": { 581 | "type": "zip", 582 | "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/447a020a1f875a434d62f2a401f53b82a396e494", 583 | "reference": "447a020a1f875a434d62f2a401f53b82a396e494", 584 | "shasum": "" 585 | }, 586 | "require": { 587 | "ext-ctype": "*", 588 | "ext-json": "*", 589 | "ext-tokenizer": "*", 590 | "php": ">=7.4" 591 | }, 592 | "require-dev": { 593 | "ircmaxell/php-yacc": "^0.0.7", 594 | "phpunit/phpunit": "^9.0" 595 | }, 596 | "bin": [ 597 | "bin/php-parse" 598 | ], 599 | "type": "library", 600 | "extra": { 601 | "branch-alias": { 602 | "dev-master": "5.0-dev" 603 | } 604 | }, 605 | "autoload": { 606 | "psr-4": { 607 | "PhpParser\\": "lib/PhpParser" 608 | } 609 | }, 610 | "notification-url": "https://packagist.org/downloads/", 611 | "license": [ 612 | "BSD-3-Clause" 613 | ], 614 | "authors": [ 615 | { 616 | "name": "Nikita Popov" 617 | } 618 | ], 619 | "description": "A PHP parser written in PHP", 620 | "keywords": [ 621 | "parser", 622 | "php" 623 | ], 624 | "support": { 625 | "issues": "https://github.com/nikic/PHP-Parser/issues", 626 | "source": "https://github.com/nikic/PHP-Parser/tree/v5.4.0" 627 | }, 628 | "time": "2024-12-30T11:07:19+00:00" 629 | }, 630 | { 631 | "name": "phar-io/manifest", 632 | "version": "2.0.4", 633 | "source": { 634 | "type": "git", 635 | "url": "https://github.com/phar-io/manifest.git", 636 | "reference": "54750ef60c58e43759730615a392c31c80e23176" 637 | }, 638 | "dist": { 639 | "type": "zip", 640 | "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", 641 | "reference": "54750ef60c58e43759730615a392c31c80e23176", 642 | "shasum": "" 643 | }, 644 | "require": { 645 | "ext-dom": "*", 646 | "ext-libxml": "*", 647 | "ext-phar": "*", 648 | "ext-xmlwriter": "*", 649 | "phar-io/version": "^3.0.1", 650 | "php": "^7.2 || ^8.0" 651 | }, 652 | "type": "library", 653 | "extra": { 654 | "branch-alias": { 655 | "dev-master": "2.0.x-dev" 656 | } 657 | }, 658 | "autoload": { 659 | "classmap": [ 660 | "src/" 661 | ] 662 | }, 663 | "notification-url": "https://packagist.org/downloads/", 664 | "license": [ 665 | "BSD-3-Clause" 666 | ], 667 | "authors": [ 668 | { 669 | "name": "Arne Blankerts", 670 | "email": "arne@blankerts.de", 671 | "role": "Developer" 672 | }, 673 | { 674 | "name": "Sebastian Heuer", 675 | "email": "sebastian@phpeople.de", 676 | "role": "Developer" 677 | }, 678 | { 679 | "name": "Sebastian Bergmann", 680 | "email": "sebastian@phpunit.de", 681 | "role": "Developer" 682 | } 683 | ], 684 | "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", 685 | "support": { 686 | "issues": "https://github.com/phar-io/manifest/issues", 687 | "source": "https://github.com/phar-io/manifest/tree/2.0.4" 688 | }, 689 | "funding": [ 690 | { 691 | "url": "https://github.com/theseer", 692 | "type": "github" 693 | } 694 | ], 695 | "time": "2024-03-03T12:33:53+00:00" 696 | }, 697 | { 698 | "name": "phar-io/version", 699 | "version": "3.2.1", 700 | "source": { 701 | "type": "git", 702 | "url": "https://github.com/phar-io/version.git", 703 | "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" 704 | }, 705 | "dist": { 706 | "type": "zip", 707 | "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", 708 | "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", 709 | "shasum": "" 710 | }, 711 | "require": { 712 | "php": "^7.2 || ^8.0" 713 | }, 714 | "type": "library", 715 | "autoload": { 716 | "classmap": [ 717 | "src/" 718 | ] 719 | }, 720 | "notification-url": "https://packagist.org/downloads/", 721 | "license": [ 722 | "BSD-3-Clause" 723 | ], 724 | "authors": [ 725 | { 726 | "name": "Arne Blankerts", 727 | "email": "arne@blankerts.de", 728 | "role": "Developer" 729 | }, 730 | { 731 | "name": "Sebastian Heuer", 732 | "email": "sebastian@phpeople.de", 733 | "role": "Developer" 734 | }, 735 | { 736 | "name": "Sebastian Bergmann", 737 | "email": "sebastian@phpunit.de", 738 | "role": "Developer" 739 | } 740 | ], 741 | "description": "Library for handling version information and constraints", 742 | "support": { 743 | "issues": "https://github.com/phar-io/version/issues", 744 | "source": "https://github.com/phar-io/version/tree/3.2.1" 745 | }, 746 | "time": "2022-02-21T01:04:05+00:00" 747 | }, 748 | { 749 | "name": "phpstan/extension-installer", 750 | "version": "1.4.3", 751 | "source": { 752 | "type": "git", 753 | "url": "https://github.com/phpstan/extension-installer.git", 754 | "reference": "85e90b3942d06b2326fba0403ec24fe912372936" 755 | }, 756 | "dist": { 757 | "type": "zip", 758 | "url": "https://api.github.com/repos/phpstan/extension-installer/zipball/85e90b3942d06b2326fba0403ec24fe912372936", 759 | "reference": "85e90b3942d06b2326fba0403ec24fe912372936", 760 | "shasum": "" 761 | }, 762 | "require": { 763 | "composer-plugin-api": "^2.0", 764 | "php": "^7.2 || ^8.0", 765 | "phpstan/phpstan": "^1.9.0 || ^2.0" 766 | }, 767 | "require-dev": { 768 | "composer/composer": "^2.0", 769 | "php-parallel-lint/php-parallel-lint": "^1.2.0", 770 | "phpstan/phpstan-strict-rules": "^0.11 || ^0.12 || ^1.0" 771 | }, 772 | "type": "composer-plugin", 773 | "extra": { 774 | "class": "PHPStan\\ExtensionInstaller\\Plugin" 775 | }, 776 | "autoload": { 777 | "psr-4": { 778 | "PHPStan\\ExtensionInstaller\\": "src/" 779 | } 780 | }, 781 | "notification-url": "https://packagist.org/downloads/", 782 | "license": [ 783 | "MIT" 784 | ], 785 | "description": "Composer plugin for automatic installation of PHPStan extensions", 786 | "keywords": [ 787 | "dev", 788 | "static analysis" 789 | ], 790 | "support": { 791 | "issues": "https://github.com/phpstan/extension-installer/issues", 792 | "source": "https://github.com/phpstan/extension-installer/tree/1.4.3" 793 | }, 794 | "time": "2024-09-04T20:21:43+00:00" 795 | }, 796 | { 797 | "name": "phpstan/phpstan", 798 | "version": "2.1.11", 799 | "source": { 800 | "type": "git", 801 | "url": "https://github.com/phpstan/phpstan.git", 802 | "reference": "8ca5f79a8f63c49b2359065832a654e1ec70ac30" 803 | }, 804 | "dist": { 805 | "type": "zip", 806 | "url": "https://api.github.com/repos/phpstan/phpstan/zipball/8ca5f79a8f63c49b2359065832a654e1ec70ac30", 807 | "reference": "8ca5f79a8f63c49b2359065832a654e1ec70ac30", 808 | "shasum": "" 809 | }, 810 | "require": { 811 | "php": "^7.4|^8.0" 812 | }, 813 | "conflict": { 814 | "phpstan/phpstan-shim": "*" 815 | }, 816 | "bin": [ 817 | "phpstan", 818 | "phpstan.phar" 819 | ], 820 | "type": "library", 821 | "autoload": { 822 | "files": [ 823 | "bootstrap.php" 824 | ] 825 | }, 826 | "notification-url": "https://packagist.org/downloads/", 827 | "license": [ 828 | "MIT" 829 | ], 830 | "description": "PHPStan - PHP Static Analysis Tool", 831 | "keywords": [ 832 | "dev", 833 | "static analysis" 834 | ], 835 | "support": { 836 | "docs": "https://phpstan.org/user-guide/getting-started", 837 | "forum": "https://github.com/phpstan/phpstan/discussions", 838 | "issues": "https://github.com/phpstan/phpstan/issues", 839 | "security": "https://github.com/phpstan/phpstan/security/policy", 840 | "source": "https://github.com/phpstan/phpstan-src" 841 | }, 842 | "funding": [ 843 | { 844 | "url": "https://github.com/ondrejmirtes", 845 | "type": "github" 846 | }, 847 | { 848 | "url": "https://github.com/phpstan", 849 | "type": "github" 850 | } 851 | ], 852 | "time": "2025-03-24T13:45:00+00:00" 853 | }, 854 | { 855 | "name": "phpstan/phpstan-phpunit", 856 | "version": "2.0.6", 857 | "source": { 858 | "type": "git", 859 | "url": "https://github.com/phpstan/phpstan-phpunit.git", 860 | "reference": "6b92469f8a7995e626da3aa487099617b8dfa260" 861 | }, 862 | "dist": { 863 | "type": "zip", 864 | "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/6b92469f8a7995e626da3aa487099617b8dfa260", 865 | "reference": "6b92469f8a7995e626da3aa487099617b8dfa260", 866 | "shasum": "" 867 | }, 868 | "require": { 869 | "php": "^7.4 || ^8.0", 870 | "phpstan/phpstan": "^2.0.4" 871 | }, 872 | "conflict": { 873 | "phpunit/phpunit": "<7.0" 874 | }, 875 | "require-dev": { 876 | "nikic/php-parser": "^5", 877 | "php-parallel-lint/php-parallel-lint": "^1.2", 878 | "phpstan/phpstan-deprecation-rules": "^2.0", 879 | "phpstan/phpstan-strict-rules": "^2.0", 880 | "phpunit/phpunit": "^9.6" 881 | }, 882 | "type": "phpstan-extension", 883 | "extra": { 884 | "phpstan": { 885 | "includes": [ 886 | "extension.neon", 887 | "rules.neon" 888 | ] 889 | } 890 | }, 891 | "autoload": { 892 | "psr-4": { 893 | "PHPStan\\": "src/" 894 | } 895 | }, 896 | "notification-url": "https://packagist.org/downloads/", 897 | "license": [ 898 | "MIT" 899 | ], 900 | "description": "PHPUnit extensions and rules for PHPStan", 901 | "support": { 902 | "issues": "https://github.com/phpstan/phpstan-phpunit/issues", 903 | "source": "https://github.com/phpstan/phpstan-phpunit/tree/2.0.6" 904 | }, 905 | "time": "2025-03-26T12:47:06+00:00" 906 | }, 907 | { 908 | "name": "phpunit/php-code-coverage", 909 | "version": "11.0.9", 910 | "source": { 911 | "type": "git", 912 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 913 | "reference": "14d63fbcca18457e49c6f8bebaa91a87e8e188d7" 914 | }, 915 | "dist": { 916 | "type": "zip", 917 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/14d63fbcca18457e49c6f8bebaa91a87e8e188d7", 918 | "reference": "14d63fbcca18457e49c6f8bebaa91a87e8e188d7", 919 | "shasum": "" 920 | }, 921 | "require": { 922 | "ext-dom": "*", 923 | "ext-libxml": "*", 924 | "ext-xmlwriter": "*", 925 | "nikic/php-parser": "^5.4.0", 926 | "php": ">=8.2", 927 | "phpunit/php-file-iterator": "^5.1.0", 928 | "phpunit/php-text-template": "^4.0.1", 929 | "sebastian/code-unit-reverse-lookup": "^4.0.1", 930 | "sebastian/complexity": "^4.0.1", 931 | "sebastian/environment": "^7.2.0", 932 | "sebastian/lines-of-code": "^3.0.1", 933 | "sebastian/version": "^5.0.2", 934 | "theseer/tokenizer": "^1.2.3" 935 | }, 936 | "require-dev": { 937 | "phpunit/phpunit": "^11.5.2" 938 | }, 939 | "suggest": { 940 | "ext-pcov": "PHP extension that provides line coverage", 941 | "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" 942 | }, 943 | "type": "library", 944 | "extra": { 945 | "branch-alias": { 946 | "dev-main": "11.0.x-dev" 947 | } 948 | }, 949 | "autoload": { 950 | "classmap": [ 951 | "src/" 952 | ] 953 | }, 954 | "notification-url": "https://packagist.org/downloads/", 955 | "license": [ 956 | "BSD-3-Clause" 957 | ], 958 | "authors": [ 959 | { 960 | "name": "Sebastian Bergmann", 961 | "email": "sebastian@phpunit.de", 962 | "role": "lead" 963 | } 964 | ], 965 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 966 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 967 | "keywords": [ 968 | "coverage", 969 | "testing", 970 | "xunit" 971 | ], 972 | "support": { 973 | "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", 974 | "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", 975 | "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.9" 976 | }, 977 | "funding": [ 978 | { 979 | "url": "https://github.com/sebastianbergmann", 980 | "type": "github" 981 | } 982 | ], 983 | "time": "2025-02-25T13:26:39+00:00" 984 | }, 985 | { 986 | "name": "phpunit/php-file-iterator", 987 | "version": "5.1.0", 988 | "source": { 989 | "type": "git", 990 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 991 | "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6" 992 | }, 993 | "dist": { 994 | "type": "zip", 995 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/118cfaaa8bc5aef3287bf315b6060b1174754af6", 996 | "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6", 997 | "shasum": "" 998 | }, 999 | "require": { 1000 | "php": ">=8.2" 1001 | }, 1002 | "require-dev": { 1003 | "phpunit/phpunit": "^11.0" 1004 | }, 1005 | "type": "library", 1006 | "extra": { 1007 | "branch-alias": { 1008 | "dev-main": "5.0-dev" 1009 | } 1010 | }, 1011 | "autoload": { 1012 | "classmap": [ 1013 | "src/" 1014 | ] 1015 | }, 1016 | "notification-url": "https://packagist.org/downloads/", 1017 | "license": [ 1018 | "BSD-3-Clause" 1019 | ], 1020 | "authors": [ 1021 | { 1022 | "name": "Sebastian Bergmann", 1023 | "email": "sebastian@phpunit.de", 1024 | "role": "lead" 1025 | } 1026 | ], 1027 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 1028 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 1029 | "keywords": [ 1030 | "filesystem", 1031 | "iterator" 1032 | ], 1033 | "support": { 1034 | "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", 1035 | "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", 1036 | "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/5.1.0" 1037 | }, 1038 | "funding": [ 1039 | { 1040 | "url": "https://github.com/sebastianbergmann", 1041 | "type": "github" 1042 | } 1043 | ], 1044 | "time": "2024-08-27T05:02:59+00:00" 1045 | }, 1046 | { 1047 | "name": "phpunit/php-invoker", 1048 | "version": "5.0.1", 1049 | "source": { 1050 | "type": "git", 1051 | "url": "https://github.com/sebastianbergmann/php-invoker.git", 1052 | "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2" 1053 | }, 1054 | "dist": { 1055 | "type": "zip", 1056 | "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/c1ca3814734c07492b3d4c5f794f4b0995333da2", 1057 | "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2", 1058 | "shasum": "" 1059 | }, 1060 | "require": { 1061 | "php": ">=8.2" 1062 | }, 1063 | "require-dev": { 1064 | "ext-pcntl": "*", 1065 | "phpunit/phpunit": "^11.0" 1066 | }, 1067 | "suggest": { 1068 | "ext-pcntl": "*" 1069 | }, 1070 | "type": "library", 1071 | "extra": { 1072 | "branch-alias": { 1073 | "dev-main": "5.0-dev" 1074 | } 1075 | }, 1076 | "autoload": { 1077 | "classmap": [ 1078 | "src/" 1079 | ] 1080 | }, 1081 | "notification-url": "https://packagist.org/downloads/", 1082 | "license": [ 1083 | "BSD-3-Clause" 1084 | ], 1085 | "authors": [ 1086 | { 1087 | "name": "Sebastian Bergmann", 1088 | "email": "sebastian@phpunit.de", 1089 | "role": "lead" 1090 | } 1091 | ], 1092 | "description": "Invoke callables with a timeout", 1093 | "homepage": "https://github.com/sebastianbergmann/php-invoker/", 1094 | "keywords": [ 1095 | "process" 1096 | ], 1097 | "support": { 1098 | "issues": "https://github.com/sebastianbergmann/php-invoker/issues", 1099 | "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", 1100 | "source": "https://github.com/sebastianbergmann/php-invoker/tree/5.0.1" 1101 | }, 1102 | "funding": [ 1103 | { 1104 | "url": "https://github.com/sebastianbergmann", 1105 | "type": "github" 1106 | } 1107 | ], 1108 | "time": "2024-07-03T05:07:44+00:00" 1109 | }, 1110 | { 1111 | "name": "phpunit/php-text-template", 1112 | "version": "4.0.1", 1113 | "source": { 1114 | "type": "git", 1115 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 1116 | "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964" 1117 | }, 1118 | "dist": { 1119 | "type": "zip", 1120 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/3e0404dc6b300e6bf56415467ebcb3fe4f33e964", 1121 | "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964", 1122 | "shasum": "" 1123 | }, 1124 | "require": { 1125 | "php": ">=8.2" 1126 | }, 1127 | "require-dev": { 1128 | "phpunit/phpunit": "^11.0" 1129 | }, 1130 | "type": "library", 1131 | "extra": { 1132 | "branch-alias": { 1133 | "dev-main": "4.0-dev" 1134 | } 1135 | }, 1136 | "autoload": { 1137 | "classmap": [ 1138 | "src/" 1139 | ] 1140 | }, 1141 | "notification-url": "https://packagist.org/downloads/", 1142 | "license": [ 1143 | "BSD-3-Clause" 1144 | ], 1145 | "authors": [ 1146 | { 1147 | "name": "Sebastian Bergmann", 1148 | "email": "sebastian@phpunit.de", 1149 | "role": "lead" 1150 | } 1151 | ], 1152 | "description": "Simple template engine.", 1153 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 1154 | "keywords": [ 1155 | "template" 1156 | ], 1157 | "support": { 1158 | "issues": "https://github.com/sebastianbergmann/php-text-template/issues", 1159 | "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", 1160 | "source": "https://github.com/sebastianbergmann/php-text-template/tree/4.0.1" 1161 | }, 1162 | "funding": [ 1163 | { 1164 | "url": "https://github.com/sebastianbergmann", 1165 | "type": "github" 1166 | } 1167 | ], 1168 | "time": "2024-07-03T05:08:43+00:00" 1169 | }, 1170 | { 1171 | "name": "phpunit/php-timer", 1172 | "version": "7.0.1", 1173 | "source": { 1174 | "type": "git", 1175 | "url": "https://github.com/sebastianbergmann/php-timer.git", 1176 | "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3" 1177 | }, 1178 | "dist": { 1179 | "type": "zip", 1180 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", 1181 | "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", 1182 | "shasum": "" 1183 | }, 1184 | "require": { 1185 | "php": ">=8.2" 1186 | }, 1187 | "require-dev": { 1188 | "phpunit/phpunit": "^11.0" 1189 | }, 1190 | "type": "library", 1191 | "extra": { 1192 | "branch-alias": { 1193 | "dev-main": "7.0-dev" 1194 | } 1195 | }, 1196 | "autoload": { 1197 | "classmap": [ 1198 | "src/" 1199 | ] 1200 | }, 1201 | "notification-url": "https://packagist.org/downloads/", 1202 | "license": [ 1203 | "BSD-3-Clause" 1204 | ], 1205 | "authors": [ 1206 | { 1207 | "name": "Sebastian Bergmann", 1208 | "email": "sebastian@phpunit.de", 1209 | "role": "lead" 1210 | } 1211 | ], 1212 | "description": "Utility class for timing", 1213 | "homepage": "https://github.com/sebastianbergmann/php-timer/", 1214 | "keywords": [ 1215 | "timer" 1216 | ], 1217 | "support": { 1218 | "issues": "https://github.com/sebastianbergmann/php-timer/issues", 1219 | "security": "https://github.com/sebastianbergmann/php-timer/security/policy", 1220 | "source": "https://github.com/sebastianbergmann/php-timer/tree/7.0.1" 1221 | }, 1222 | "funding": [ 1223 | { 1224 | "url": "https://github.com/sebastianbergmann", 1225 | "type": "github" 1226 | } 1227 | ], 1228 | "time": "2024-07-03T05:09:35+00:00" 1229 | }, 1230 | { 1231 | "name": "phpunit/phpunit", 1232 | "version": "11.5.15", 1233 | "source": { 1234 | "type": "git", 1235 | "url": "https://github.com/sebastianbergmann/phpunit.git", 1236 | "reference": "4b6a4ee654e5e0c5e1f17e2f83c0f4c91dee1f9c" 1237 | }, 1238 | "dist": { 1239 | "type": "zip", 1240 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/4b6a4ee654e5e0c5e1f17e2f83c0f4c91dee1f9c", 1241 | "reference": "4b6a4ee654e5e0c5e1f17e2f83c0f4c91dee1f9c", 1242 | "shasum": "" 1243 | }, 1244 | "require": { 1245 | "ext-dom": "*", 1246 | "ext-json": "*", 1247 | "ext-libxml": "*", 1248 | "ext-mbstring": "*", 1249 | "ext-xml": "*", 1250 | "ext-xmlwriter": "*", 1251 | "myclabs/deep-copy": "^1.13.0", 1252 | "phar-io/manifest": "^2.0.4", 1253 | "phar-io/version": "^3.2.1", 1254 | "php": ">=8.2", 1255 | "phpunit/php-code-coverage": "^11.0.9", 1256 | "phpunit/php-file-iterator": "^5.1.0", 1257 | "phpunit/php-invoker": "^5.0.1", 1258 | "phpunit/php-text-template": "^4.0.1", 1259 | "phpunit/php-timer": "^7.0.1", 1260 | "sebastian/cli-parser": "^3.0.2", 1261 | "sebastian/code-unit": "^3.0.3", 1262 | "sebastian/comparator": "^6.3.1", 1263 | "sebastian/diff": "^6.0.2", 1264 | "sebastian/environment": "^7.2.0", 1265 | "sebastian/exporter": "^6.3.0", 1266 | "sebastian/global-state": "^7.0.2", 1267 | "sebastian/object-enumerator": "^6.0.1", 1268 | "sebastian/type": "^5.1.2", 1269 | "sebastian/version": "^5.0.2", 1270 | "staabm/side-effects-detector": "^1.0.5" 1271 | }, 1272 | "suggest": { 1273 | "ext-soap": "To be able to generate mocks based on WSDL files" 1274 | }, 1275 | "bin": [ 1276 | "phpunit" 1277 | ], 1278 | "type": "library", 1279 | "extra": { 1280 | "branch-alias": { 1281 | "dev-main": "11.5-dev" 1282 | } 1283 | }, 1284 | "autoload": { 1285 | "files": [ 1286 | "src/Framework/Assert/Functions.php" 1287 | ], 1288 | "classmap": [ 1289 | "src/" 1290 | ] 1291 | }, 1292 | "notification-url": "https://packagist.org/downloads/", 1293 | "license": [ 1294 | "BSD-3-Clause" 1295 | ], 1296 | "authors": [ 1297 | { 1298 | "name": "Sebastian Bergmann", 1299 | "email": "sebastian@phpunit.de", 1300 | "role": "lead" 1301 | } 1302 | ], 1303 | "description": "The PHP Unit Testing framework.", 1304 | "homepage": "https://phpunit.de/", 1305 | "keywords": [ 1306 | "phpunit", 1307 | "testing", 1308 | "xunit" 1309 | ], 1310 | "support": { 1311 | "issues": "https://github.com/sebastianbergmann/phpunit/issues", 1312 | "security": "https://github.com/sebastianbergmann/phpunit/security/policy", 1313 | "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.15" 1314 | }, 1315 | "funding": [ 1316 | { 1317 | "url": "https://phpunit.de/sponsors.html", 1318 | "type": "custom" 1319 | }, 1320 | { 1321 | "url": "https://github.com/sebastianbergmann", 1322 | "type": "github" 1323 | }, 1324 | { 1325 | "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", 1326 | "type": "tidelift" 1327 | } 1328 | ], 1329 | "time": "2025-03-23T16:02:11+00:00" 1330 | }, 1331 | { 1332 | "name": "psr/container", 1333 | "version": "2.0.2", 1334 | "source": { 1335 | "type": "git", 1336 | "url": "https://github.com/php-fig/container.git", 1337 | "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" 1338 | }, 1339 | "dist": { 1340 | "type": "zip", 1341 | "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", 1342 | "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", 1343 | "shasum": "" 1344 | }, 1345 | "require": { 1346 | "php": ">=7.4.0" 1347 | }, 1348 | "type": "library", 1349 | "extra": { 1350 | "branch-alias": { 1351 | "dev-master": "2.0.x-dev" 1352 | } 1353 | }, 1354 | "autoload": { 1355 | "psr-4": { 1356 | "Psr\\Container\\": "src/" 1357 | } 1358 | }, 1359 | "notification-url": "https://packagist.org/downloads/", 1360 | "license": [ 1361 | "MIT" 1362 | ], 1363 | "authors": [ 1364 | { 1365 | "name": "PHP-FIG", 1366 | "homepage": "https://www.php-fig.org/" 1367 | } 1368 | ], 1369 | "description": "Common Container Interface (PHP FIG PSR-11)", 1370 | "homepage": "https://github.com/php-fig/container", 1371 | "keywords": [ 1372 | "PSR-11", 1373 | "container", 1374 | "container-interface", 1375 | "container-interop", 1376 | "psr" 1377 | ], 1378 | "support": { 1379 | "issues": "https://github.com/php-fig/container/issues", 1380 | "source": "https://github.com/php-fig/container/tree/2.0.2" 1381 | }, 1382 | "time": "2021-11-05T16:47:00+00:00" 1383 | }, 1384 | { 1385 | "name": "psr/event-dispatcher", 1386 | "version": "1.0.0", 1387 | "source": { 1388 | "type": "git", 1389 | "url": "https://github.com/php-fig/event-dispatcher.git", 1390 | "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" 1391 | }, 1392 | "dist": { 1393 | "type": "zip", 1394 | "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", 1395 | "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", 1396 | "shasum": "" 1397 | }, 1398 | "require": { 1399 | "php": ">=7.2.0" 1400 | }, 1401 | "type": "library", 1402 | "extra": { 1403 | "branch-alias": { 1404 | "dev-master": "1.0.x-dev" 1405 | } 1406 | }, 1407 | "autoload": { 1408 | "psr-4": { 1409 | "Psr\\EventDispatcher\\": "src/" 1410 | } 1411 | }, 1412 | "notification-url": "https://packagist.org/downloads/", 1413 | "license": [ 1414 | "MIT" 1415 | ], 1416 | "authors": [ 1417 | { 1418 | "name": "PHP-FIG", 1419 | "homepage": "http://www.php-fig.org/" 1420 | } 1421 | ], 1422 | "description": "Standard interfaces for event handling.", 1423 | "keywords": [ 1424 | "events", 1425 | "psr", 1426 | "psr-14" 1427 | ], 1428 | "support": { 1429 | "issues": "https://github.com/php-fig/event-dispatcher/issues", 1430 | "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" 1431 | }, 1432 | "time": "2019-01-08T18:20:26+00:00" 1433 | }, 1434 | { 1435 | "name": "psr/log", 1436 | "version": "3.0.2", 1437 | "source": { 1438 | "type": "git", 1439 | "url": "https://github.com/php-fig/log.git", 1440 | "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" 1441 | }, 1442 | "dist": { 1443 | "type": "zip", 1444 | "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", 1445 | "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", 1446 | "shasum": "" 1447 | }, 1448 | "require": { 1449 | "php": ">=8.0.0" 1450 | }, 1451 | "type": "library", 1452 | "extra": { 1453 | "branch-alias": { 1454 | "dev-master": "3.x-dev" 1455 | } 1456 | }, 1457 | "autoload": { 1458 | "psr-4": { 1459 | "Psr\\Log\\": "src" 1460 | } 1461 | }, 1462 | "notification-url": "https://packagist.org/downloads/", 1463 | "license": [ 1464 | "MIT" 1465 | ], 1466 | "authors": [ 1467 | { 1468 | "name": "PHP-FIG", 1469 | "homepage": "https://www.php-fig.org/" 1470 | } 1471 | ], 1472 | "description": "Common interface for logging libraries", 1473 | "homepage": "https://github.com/php-fig/log", 1474 | "keywords": [ 1475 | "log", 1476 | "psr", 1477 | "psr-3" 1478 | ], 1479 | "support": { 1480 | "source": "https://github.com/php-fig/log/tree/3.0.2" 1481 | }, 1482 | "time": "2024-09-11T13:17:53+00:00" 1483 | }, 1484 | { 1485 | "name": "react/cache", 1486 | "version": "v1.2.0", 1487 | "source": { 1488 | "type": "git", 1489 | "url": "https://github.com/reactphp/cache.git", 1490 | "reference": "d47c472b64aa5608225f47965a484b75c7817d5b" 1491 | }, 1492 | "dist": { 1493 | "type": "zip", 1494 | "url": "https://api.github.com/repos/reactphp/cache/zipball/d47c472b64aa5608225f47965a484b75c7817d5b", 1495 | "reference": "d47c472b64aa5608225f47965a484b75c7817d5b", 1496 | "shasum": "" 1497 | }, 1498 | "require": { 1499 | "php": ">=5.3.0", 1500 | "react/promise": "^3.0 || ^2.0 || ^1.1" 1501 | }, 1502 | "require-dev": { 1503 | "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.35" 1504 | }, 1505 | "type": "library", 1506 | "autoload": { 1507 | "psr-4": { 1508 | "React\\Cache\\": "src/" 1509 | } 1510 | }, 1511 | "notification-url": "https://packagist.org/downloads/", 1512 | "license": [ 1513 | "MIT" 1514 | ], 1515 | "authors": [ 1516 | { 1517 | "name": "Christian Lück", 1518 | "email": "christian@clue.engineering", 1519 | "homepage": "https://clue.engineering/" 1520 | }, 1521 | { 1522 | "name": "Cees-Jan Kiewiet", 1523 | "email": "reactphp@ceesjankiewiet.nl", 1524 | "homepage": "https://wyrihaximus.net/" 1525 | }, 1526 | { 1527 | "name": "Jan Sorgalla", 1528 | "email": "jsorgalla@gmail.com", 1529 | "homepage": "https://sorgalla.com/" 1530 | }, 1531 | { 1532 | "name": "Chris Boden", 1533 | "email": "cboden@gmail.com", 1534 | "homepage": "https://cboden.dev/" 1535 | } 1536 | ], 1537 | "description": "Async, Promise-based cache interface for ReactPHP", 1538 | "keywords": [ 1539 | "cache", 1540 | "caching", 1541 | "promise", 1542 | "reactphp" 1543 | ], 1544 | "support": { 1545 | "issues": "https://github.com/reactphp/cache/issues", 1546 | "source": "https://github.com/reactphp/cache/tree/v1.2.0" 1547 | }, 1548 | "funding": [ 1549 | { 1550 | "url": "https://opencollective.com/reactphp", 1551 | "type": "open_collective" 1552 | } 1553 | ], 1554 | "time": "2022-11-30T15:59:55+00:00" 1555 | }, 1556 | { 1557 | "name": "react/child-process", 1558 | "version": "v0.6.6", 1559 | "source": { 1560 | "type": "git", 1561 | "url": "https://github.com/reactphp/child-process.git", 1562 | "reference": "1721e2b93d89b745664353b9cfc8f155ba8a6159" 1563 | }, 1564 | "dist": { 1565 | "type": "zip", 1566 | "url": "https://api.github.com/repos/reactphp/child-process/zipball/1721e2b93d89b745664353b9cfc8f155ba8a6159", 1567 | "reference": "1721e2b93d89b745664353b9cfc8f155ba8a6159", 1568 | "shasum": "" 1569 | }, 1570 | "require": { 1571 | "evenement/evenement": "^3.0 || ^2.0 || ^1.0", 1572 | "php": ">=5.3.0", 1573 | "react/event-loop": "^1.2", 1574 | "react/stream": "^1.4" 1575 | }, 1576 | "require-dev": { 1577 | "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", 1578 | "react/socket": "^1.16", 1579 | "sebastian/environment": "^5.0 || ^3.0 || ^2.0 || ^1.0" 1580 | }, 1581 | "type": "library", 1582 | "autoload": { 1583 | "psr-4": { 1584 | "React\\ChildProcess\\": "src/" 1585 | } 1586 | }, 1587 | "notification-url": "https://packagist.org/downloads/", 1588 | "license": [ 1589 | "MIT" 1590 | ], 1591 | "authors": [ 1592 | { 1593 | "name": "Christian Lück", 1594 | "email": "christian@clue.engineering", 1595 | "homepage": "https://clue.engineering/" 1596 | }, 1597 | { 1598 | "name": "Cees-Jan Kiewiet", 1599 | "email": "reactphp@ceesjankiewiet.nl", 1600 | "homepage": "https://wyrihaximus.net/" 1601 | }, 1602 | { 1603 | "name": "Jan Sorgalla", 1604 | "email": "jsorgalla@gmail.com", 1605 | "homepage": "https://sorgalla.com/" 1606 | }, 1607 | { 1608 | "name": "Chris Boden", 1609 | "email": "cboden@gmail.com", 1610 | "homepage": "https://cboden.dev/" 1611 | } 1612 | ], 1613 | "description": "Event-driven library for executing child processes with ReactPHP.", 1614 | "keywords": [ 1615 | "event-driven", 1616 | "process", 1617 | "reactphp" 1618 | ], 1619 | "support": { 1620 | "issues": "https://github.com/reactphp/child-process/issues", 1621 | "source": "https://github.com/reactphp/child-process/tree/v0.6.6" 1622 | }, 1623 | "funding": [ 1624 | { 1625 | "url": "https://opencollective.com/reactphp", 1626 | "type": "open_collective" 1627 | } 1628 | ], 1629 | "time": "2025-01-01T16:37:48+00:00" 1630 | }, 1631 | { 1632 | "name": "react/dns", 1633 | "version": "v1.13.0", 1634 | "source": { 1635 | "type": "git", 1636 | "url": "https://github.com/reactphp/dns.git", 1637 | "reference": "eb8ae001b5a455665c89c1df97f6fb682f8fb0f5" 1638 | }, 1639 | "dist": { 1640 | "type": "zip", 1641 | "url": "https://api.github.com/repos/reactphp/dns/zipball/eb8ae001b5a455665c89c1df97f6fb682f8fb0f5", 1642 | "reference": "eb8ae001b5a455665c89c1df97f6fb682f8fb0f5", 1643 | "shasum": "" 1644 | }, 1645 | "require": { 1646 | "php": ">=5.3.0", 1647 | "react/cache": "^1.0 || ^0.6 || ^0.5", 1648 | "react/event-loop": "^1.2", 1649 | "react/promise": "^3.2 || ^2.7 || ^1.2.1" 1650 | }, 1651 | "require-dev": { 1652 | "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", 1653 | "react/async": "^4.3 || ^3 || ^2", 1654 | "react/promise-timer": "^1.11" 1655 | }, 1656 | "type": "library", 1657 | "autoload": { 1658 | "psr-4": { 1659 | "React\\Dns\\": "src/" 1660 | } 1661 | }, 1662 | "notification-url": "https://packagist.org/downloads/", 1663 | "license": [ 1664 | "MIT" 1665 | ], 1666 | "authors": [ 1667 | { 1668 | "name": "Christian Lück", 1669 | "email": "christian@clue.engineering", 1670 | "homepage": "https://clue.engineering/" 1671 | }, 1672 | { 1673 | "name": "Cees-Jan Kiewiet", 1674 | "email": "reactphp@ceesjankiewiet.nl", 1675 | "homepage": "https://wyrihaximus.net/" 1676 | }, 1677 | { 1678 | "name": "Jan Sorgalla", 1679 | "email": "jsorgalla@gmail.com", 1680 | "homepage": "https://sorgalla.com/" 1681 | }, 1682 | { 1683 | "name": "Chris Boden", 1684 | "email": "cboden@gmail.com", 1685 | "homepage": "https://cboden.dev/" 1686 | } 1687 | ], 1688 | "description": "Async DNS resolver for ReactPHP", 1689 | "keywords": [ 1690 | "async", 1691 | "dns", 1692 | "dns-resolver", 1693 | "reactphp" 1694 | ], 1695 | "support": { 1696 | "issues": "https://github.com/reactphp/dns/issues", 1697 | "source": "https://github.com/reactphp/dns/tree/v1.13.0" 1698 | }, 1699 | "funding": [ 1700 | { 1701 | "url": "https://opencollective.com/reactphp", 1702 | "type": "open_collective" 1703 | } 1704 | ], 1705 | "time": "2024-06-13T14:18:03+00:00" 1706 | }, 1707 | { 1708 | "name": "react/event-loop", 1709 | "version": "v1.5.0", 1710 | "source": { 1711 | "type": "git", 1712 | "url": "https://github.com/reactphp/event-loop.git", 1713 | "reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354" 1714 | }, 1715 | "dist": { 1716 | "type": "zip", 1717 | "url": "https://api.github.com/repos/reactphp/event-loop/zipball/bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354", 1718 | "reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354", 1719 | "shasum": "" 1720 | }, 1721 | "require": { 1722 | "php": ">=5.3.0" 1723 | }, 1724 | "require-dev": { 1725 | "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" 1726 | }, 1727 | "suggest": { 1728 | "ext-pcntl": "For signal handling support when using the StreamSelectLoop" 1729 | }, 1730 | "type": "library", 1731 | "autoload": { 1732 | "psr-4": { 1733 | "React\\EventLoop\\": "src/" 1734 | } 1735 | }, 1736 | "notification-url": "https://packagist.org/downloads/", 1737 | "license": [ 1738 | "MIT" 1739 | ], 1740 | "authors": [ 1741 | { 1742 | "name": "Christian Lück", 1743 | "email": "christian@clue.engineering", 1744 | "homepage": "https://clue.engineering/" 1745 | }, 1746 | { 1747 | "name": "Cees-Jan Kiewiet", 1748 | "email": "reactphp@ceesjankiewiet.nl", 1749 | "homepage": "https://wyrihaximus.net/" 1750 | }, 1751 | { 1752 | "name": "Jan Sorgalla", 1753 | "email": "jsorgalla@gmail.com", 1754 | "homepage": "https://sorgalla.com/" 1755 | }, 1756 | { 1757 | "name": "Chris Boden", 1758 | "email": "cboden@gmail.com", 1759 | "homepage": "https://cboden.dev/" 1760 | } 1761 | ], 1762 | "description": "ReactPHP's core reactor event loop that libraries can use for evented I/O.", 1763 | "keywords": [ 1764 | "asynchronous", 1765 | "event-loop" 1766 | ], 1767 | "support": { 1768 | "issues": "https://github.com/reactphp/event-loop/issues", 1769 | "source": "https://github.com/reactphp/event-loop/tree/v1.5.0" 1770 | }, 1771 | "funding": [ 1772 | { 1773 | "url": "https://opencollective.com/reactphp", 1774 | "type": "open_collective" 1775 | } 1776 | ], 1777 | "time": "2023-11-13T13:48:05+00:00" 1778 | }, 1779 | { 1780 | "name": "react/promise", 1781 | "version": "v3.2.0", 1782 | "source": { 1783 | "type": "git", 1784 | "url": "https://github.com/reactphp/promise.git", 1785 | "reference": "8a164643313c71354582dc850b42b33fa12a4b63" 1786 | }, 1787 | "dist": { 1788 | "type": "zip", 1789 | "url": "https://api.github.com/repos/reactphp/promise/zipball/8a164643313c71354582dc850b42b33fa12a4b63", 1790 | "reference": "8a164643313c71354582dc850b42b33fa12a4b63", 1791 | "shasum": "" 1792 | }, 1793 | "require": { 1794 | "php": ">=7.1.0" 1795 | }, 1796 | "require-dev": { 1797 | "phpstan/phpstan": "1.10.39 || 1.4.10", 1798 | "phpunit/phpunit": "^9.6 || ^7.5" 1799 | }, 1800 | "type": "library", 1801 | "autoload": { 1802 | "files": [ 1803 | "src/functions_include.php" 1804 | ], 1805 | "psr-4": { 1806 | "React\\Promise\\": "src/" 1807 | } 1808 | }, 1809 | "notification-url": "https://packagist.org/downloads/", 1810 | "license": [ 1811 | "MIT" 1812 | ], 1813 | "authors": [ 1814 | { 1815 | "name": "Jan Sorgalla", 1816 | "email": "jsorgalla@gmail.com", 1817 | "homepage": "https://sorgalla.com/" 1818 | }, 1819 | { 1820 | "name": "Christian Lück", 1821 | "email": "christian@clue.engineering", 1822 | "homepage": "https://clue.engineering/" 1823 | }, 1824 | { 1825 | "name": "Cees-Jan Kiewiet", 1826 | "email": "reactphp@ceesjankiewiet.nl", 1827 | "homepage": "https://wyrihaximus.net/" 1828 | }, 1829 | { 1830 | "name": "Chris Boden", 1831 | "email": "cboden@gmail.com", 1832 | "homepage": "https://cboden.dev/" 1833 | } 1834 | ], 1835 | "description": "A lightweight implementation of CommonJS Promises/A for PHP", 1836 | "keywords": [ 1837 | "promise", 1838 | "promises" 1839 | ], 1840 | "support": { 1841 | "issues": "https://github.com/reactphp/promise/issues", 1842 | "source": "https://github.com/reactphp/promise/tree/v3.2.0" 1843 | }, 1844 | "funding": [ 1845 | { 1846 | "url": "https://opencollective.com/reactphp", 1847 | "type": "open_collective" 1848 | } 1849 | ], 1850 | "time": "2024-05-24T10:39:05+00:00" 1851 | }, 1852 | { 1853 | "name": "react/socket", 1854 | "version": "v1.16.0", 1855 | "source": { 1856 | "type": "git", 1857 | "url": "https://github.com/reactphp/socket.git", 1858 | "reference": "23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1" 1859 | }, 1860 | "dist": { 1861 | "type": "zip", 1862 | "url": "https://api.github.com/repos/reactphp/socket/zipball/23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1", 1863 | "reference": "23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1", 1864 | "shasum": "" 1865 | }, 1866 | "require": { 1867 | "evenement/evenement": "^3.0 || ^2.0 || ^1.0", 1868 | "php": ">=5.3.0", 1869 | "react/dns": "^1.13", 1870 | "react/event-loop": "^1.2", 1871 | "react/promise": "^3.2 || ^2.6 || ^1.2.1", 1872 | "react/stream": "^1.4" 1873 | }, 1874 | "require-dev": { 1875 | "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", 1876 | "react/async": "^4.3 || ^3.3 || ^2", 1877 | "react/promise-stream": "^1.4", 1878 | "react/promise-timer": "^1.11" 1879 | }, 1880 | "type": "library", 1881 | "autoload": { 1882 | "psr-4": { 1883 | "React\\Socket\\": "src/" 1884 | } 1885 | }, 1886 | "notification-url": "https://packagist.org/downloads/", 1887 | "license": [ 1888 | "MIT" 1889 | ], 1890 | "authors": [ 1891 | { 1892 | "name": "Christian Lück", 1893 | "email": "christian@clue.engineering", 1894 | "homepage": "https://clue.engineering/" 1895 | }, 1896 | { 1897 | "name": "Cees-Jan Kiewiet", 1898 | "email": "reactphp@ceesjankiewiet.nl", 1899 | "homepage": "https://wyrihaximus.net/" 1900 | }, 1901 | { 1902 | "name": "Jan Sorgalla", 1903 | "email": "jsorgalla@gmail.com", 1904 | "homepage": "https://sorgalla.com/" 1905 | }, 1906 | { 1907 | "name": "Chris Boden", 1908 | "email": "cboden@gmail.com", 1909 | "homepage": "https://cboden.dev/" 1910 | } 1911 | ], 1912 | "description": "Async, streaming plaintext TCP/IP and secure TLS socket server and client connections for ReactPHP", 1913 | "keywords": [ 1914 | "Connection", 1915 | "Socket", 1916 | "async", 1917 | "reactphp", 1918 | "stream" 1919 | ], 1920 | "support": { 1921 | "issues": "https://github.com/reactphp/socket/issues", 1922 | "source": "https://github.com/reactphp/socket/tree/v1.16.0" 1923 | }, 1924 | "funding": [ 1925 | { 1926 | "url": "https://opencollective.com/reactphp", 1927 | "type": "open_collective" 1928 | } 1929 | ], 1930 | "time": "2024-07-26T10:38:09+00:00" 1931 | }, 1932 | { 1933 | "name": "react/stream", 1934 | "version": "v1.4.0", 1935 | "source": { 1936 | "type": "git", 1937 | "url": "https://github.com/reactphp/stream.git", 1938 | "reference": "1e5b0acb8fe55143b5b426817155190eb6f5b18d" 1939 | }, 1940 | "dist": { 1941 | "type": "zip", 1942 | "url": "https://api.github.com/repos/reactphp/stream/zipball/1e5b0acb8fe55143b5b426817155190eb6f5b18d", 1943 | "reference": "1e5b0acb8fe55143b5b426817155190eb6f5b18d", 1944 | "shasum": "" 1945 | }, 1946 | "require": { 1947 | "evenement/evenement": "^3.0 || ^2.0 || ^1.0", 1948 | "php": ">=5.3.8", 1949 | "react/event-loop": "^1.2" 1950 | }, 1951 | "require-dev": { 1952 | "clue/stream-filter": "~1.2", 1953 | "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" 1954 | }, 1955 | "type": "library", 1956 | "autoload": { 1957 | "psr-4": { 1958 | "React\\Stream\\": "src/" 1959 | } 1960 | }, 1961 | "notification-url": "https://packagist.org/downloads/", 1962 | "license": [ 1963 | "MIT" 1964 | ], 1965 | "authors": [ 1966 | { 1967 | "name": "Christian Lück", 1968 | "email": "christian@clue.engineering", 1969 | "homepage": "https://clue.engineering/" 1970 | }, 1971 | { 1972 | "name": "Cees-Jan Kiewiet", 1973 | "email": "reactphp@ceesjankiewiet.nl", 1974 | "homepage": "https://wyrihaximus.net/" 1975 | }, 1976 | { 1977 | "name": "Jan Sorgalla", 1978 | "email": "jsorgalla@gmail.com", 1979 | "homepage": "https://sorgalla.com/" 1980 | }, 1981 | { 1982 | "name": "Chris Boden", 1983 | "email": "cboden@gmail.com", 1984 | "homepage": "https://cboden.dev/" 1985 | } 1986 | ], 1987 | "description": "Event-driven readable and writable streams for non-blocking I/O in ReactPHP", 1988 | "keywords": [ 1989 | "event-driven", 1990 | "io", 1991 | "non-blocking", 1992 | "pipe", 1993 | "reactphp", 1994 | "readable", 1995 | "stream", 1996 | "writable" 1997 | ], 1998 | "support": { 1999 | "issues": "https://github.com/reactphp/stream/issues", 2000 | "source": "https://github.com/reactphp/stream/tree/v1.4.0" 2001 | }, 2002 | "funding": [ 2003 | { 2004 | "url": "https://opencollective.com/reactphp", 2005 | "type": "open_collective" 2006 | } 2007 | ], 2008 | "time": "2024-06-11T12:45:25+00:00" 2009 | }, 2010 | { 2011 | "name": "sebastian/cli-parser", 2012 | "version": "3.0.2", 2013 | "source": { 2014 | "type": "git", 2015 | "url": "https://github.com/sebastianbergmann/cli-parser.git", 2016 | "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180" 2017 | }, 2018 | "dist": { 2019 | "type": "zip", 2020 | "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/15c5dd40dc4f38794d383bb95465193f5e0ae180", 2021 | "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180", 2022 | "shasum": "" 2023 | }, 2024 | "require": { 2025 | "php": ">=8.2" 2026 | }, 2027 | "require-dev": { 2028 | "phpunit/phpunit": "^11.0" 2029 | }, 2030 | "type": "library", 2031 | "extra": { 2032 | "branch-alias": { 2033 | "dev-main": "3.0-dev" 2034 | } 2035 | }, 2036 | "autoload": { 2037 | "classmap": [ 2038 | "src/" 2039 | ] 2040 | }, 2041 | "notification-url": "https://packagist.org/downloads/", 2042 | "license": [ 2043 | "BSD-3-Clause" 2044 | ], 2045 | "authors": [ 2046 | { 2047 | "name": "Sebastian Bergmann", 2048 | "email": "sebastian@phpunit.de", 2049 | "role": "lead" 2050 | } 2051 | ], 2052 | "description": "Library for parsing CLI options", 2053 | "homepage": "https://github.com/sebastianbergmann/cli-parser", 2054 | "support": { 2055 | "issues": "https://github.com/sebastianbergmann/cli-parser/issues", 2056 | "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", 2057 | "source": "https://github.com/sebastianbergmann/cli-parser/tree/3.0.2" 2058 | }, 2059 | "funding": [ 2060 | { 2061 | "url": "https://github.com/sebastianbergmann", 2062 | "type": "github" 2063 | } 2064 | ], 2065 | "time": "2024-07-03T04:41:36+00:00" 2066 | }, 2067 | { 2068 | "name": "sebastian/code-unit", 2069 | "version": "3.0.3", 2070 | "source": { 2071 | "type": "git", 2072 | "url": "https://github.com/sebastianbergmann/code-unit.git", 2073 | "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64" 2074 | }, 2075 | "dist": { 2076 | "type": "zip", 2077 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/54391c61e4af8078e5b276ab082b6d3c54c9ad64", 2078 | "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64", 2079 | "shasum": "" 2080 | }, 2081 | "require": { 2082 | "php": ">=8.2" 2083 | }, 2084 | "require-dev": { 2085 | "phpunit/phpunit": "^11.5" 2086 | }, 2087 | "type": "library", 2088 | "extra": { 2089 | "branch-alias": { 2090 | "dev-main": "3.0-dev" 2091 | } 2092 | }, 2093 | "autoload": { 2094 | "classmap": [ 2095 | "src/" 2096 | ] 2097 | }, 2098 | "notification-url": "https://packagist.org/downloads/", 2099 | "license": [ 2100 | "BSD-3-Clause" 2101 | ], 2102 | "authors": [ 2103 | { 2104 | "name": "Sebastian Bergmann", 2105 | "email": "sebastian@phpunit.de", 2106 | "role": "lead" 2107 | } 2108 | ], 2109 | "description": "Collection of value objects that represent the PHP code units", 2110 | "homepage": "https://github.com/sebastianbergmann/code-unit", 2111 | "support": { 2112 | "issues": "https://github.com/sebastianbergmann/code-unit/issues", 2113 | "security": "https://github.com/sebastianbergmann/code-unit/security/policy", 2114 | "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.3" 2115 | }, 2116 | "funding": [ 2117 | { 2118 | "url": "https://github.com/sebastianbergmann", 2119 | "type": "github" 2120 | } 2121 | ], 2122 | "time": "2025-03-19T07:56:08+00:00" 2123 | }, 2124 | { 2125 | "name": "sebastian/code-unit-reverse-lookup", 2126 | "version": "4.0.1", 2127 | "source": { 2128 | "type": "git", 2129 | "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", 2130 | "reference": "183a9b2632194febd219bb9246eee421dad8d45e" 2131 | }, 2132 | "dist": { 2133 | "type": "zip", 2134 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/183a9b2632194febd219bb9246eee421dad8d45e", 2135 | "reference": "183a9b2632194febd219bb9246eee421dad8d45e", 2136 | "shasum": "" 2137 | }, 2138 | "require": { 2139 | "php": ">=8.2" 2140 | }, 2141 | "require-dev": { 2142 | "phpunit/phpunit": "^11.0" 2143 | }, 2144 | "type": "library", 2145 | "extra": { 2146 | "branch-alias": { 2147 | "dev-main": "4.0-dev" 2148 | } 2149 | }, 2150 | "autoload": { 2151 | "classmap": [ 2152 | "src/" 2153 | ] 2154 | }, 2155 | "notification-url": "https://packagist.org/downloads/", 2156 | "license": [ 2157 | "BSD-3-Clause" 2158 | ], 2159 | "authors": [ 2160 | { 2161 | "name": "Sebastian Bergmann", 2162 | "email": "sebastian@phpunit.de" 2163 | } 2164 | ], 2165 | "description": "Looks up which function or method a line of code belongs to", 2166 | "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", 2167 | "support": { 2168 | "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", 2169 | "security": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/security/policy", 2170 | "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/4.0.1" 2171 | }, 2172 | "funding": [ 2173 | { 2174 | "url": "https://github.com/sebastianbergmann", 2175 | "type": "github" 2176 | } 2177 | ], 2178 | "time": "2024-07-03T04:45:54+00:00" 2179 | }, 2180 | { 2181 | "name": "sebastian/comparator", 2182 | "version": "6.3.1", 2183 | "source": { 2184 | "type": "git", 2185 | "url": "https://github.com/sebastianbergmann/comparator.git", 2186 | "reference": "24b8fbc2c8e201bb1308e7b05148d6ab393b6959" 2187 | }, 2188 | "dist": { 2189 | "type": "zip", 2190 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/24b8fbc2c8e201bb1308e7b05148d6ab393b6959", 2191 | "reference": "24b8fbc2c8e201bb1308e7b05148d6ab393b6959", 2192 | "shasum": "" 2193 | }, 2194 | "require": { 2195 | "ext-dom": "*", 2196 | "ext-mbstring": "*", 2197 | "php": ">=8.2", 2198 | "sebastian/diff": "^6.0", 2199 | "sebastian/exporter": "^6.0" 2200 | }, 2201 | "require-dev": { 2202 | "phpunit/phpunit": "^11.4" 2203 | }, 2204 | "suggest": { 2205 | "ext-bcmath": "For comparing BcMath\\Number objects" 2206 | }, 2207 | "type": "library", 2208 | "extra": { 2209 | "branch-alias": { 2210 | "dev-main": "6.3-dev" 2211 | } 2212 | }, 2213 | "autoload": { 2214 | "classmap": [ 2215 | "src/" 2216 | ] 2217 | }, 2218 | "notification-url": "https://packagist.org/downloads/", 2219 | "license": [ 2220 | "BSD-3-Clause" 2221 | ], 2222 | "authors": [ 2223 | { 2224 | "name": "Sebastian Bergmann", 2225 | "email": "sebastian@phpunit.de" 2226 | }, 2227 | { 2228 | "name": "Jeff Welch", 2229 | "email": "whatthejeff@gmail.com" 2230 | }, 2231 | { 2232 | "name": "Volker Dusch", 2233 | "email": "github@wallbash.com" 2234 | }, 2235 | { 2236 | "name": "Bernhard Schussek", 2237 | "email": "bschussek@2bepublished.at" 2238 | } 2239 | ], 2240 | "description": "Provides the functionality to compare PHP values for equality", 2241 | "homepage": "https://github.com/sebastianbergmann/comparator", 2242 | "keywords": [ 2243 | "comparator", 2244 | "compare", 2245 | "equality" 2246 | ], 2247 | "support": { 2248 | "issues": "https://github.com/sebastianbergmann/comparator/issues", 2249 | "security": "https://github.com/sebastianbergmann/comparator/security/policy", 2250 | "source": "https://github.com/sebastianbergmann/comparator/tree/6.3.1" 2251 | }, 2252 | "funding": [ 2253 | { 2254 | "url": "https://github.com/sebastianbergmann", 2255 | "type": "github" 2256 | } 2257 | ], 2258 | "time": "2025-03-07T06:57:01+00:00" 2259 | }, 2260 | { 2261 | "name": "sebastian/complexity", 2262 | "version": "4.0.1", 2263 | "source": { 2264 | "type": "git", 2265 | "url": "https://github.com/sebastianbergmann/complexity.git", 2266 | "reference": "ee41d384ab1906c68852636b6de493846e13e5a0" 2267 | }, 2268 | "dist": { 2269 | "type": "zip", 2270 | "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/ee41d384ab1906c68852636b6de493846e13e5a0", 2271 | "reference": "ee41d384ab1906c68852636b6de493846e13e5a0", 2272 | "shasum": "" 2273 | }, 2274 | "require": { 2275 | "nikic/php-parser": "^5.0", 2276 | "php": ">=8.2" 2277 | }, 2278 | "require-dev": { 2279 | "phpunit/phpunit": "^11.0" 2280 | }, 2281 | "type": "library", 2282 | "extra": { 2283 | "branch-alias": { 2284 | "dev-main": "4.0-dev" 2285 | } 2286 | }, 2287 | "autoload": { 2288 | "classmap": [ 2289 | "src/" 2290 | ] 2291 | }, 2292 | "notification-url": "https://packagist.org/downloads/", 2293 | "license": [ 2294 | "BSD-3-Clause" 2295 | ], 2296 | "authors": [ 2297 | { 2298 | "name": "Sebastian Bergmann", 2299 | "email": "sebastian@phpunit.de", 2300 | "role": "lead" 2301 | } 2302 | ], 2303 | "description": "Library for calculating the complexity of PHP code units", 2304 | "homepage": "https://github.com/sebastianbergmann/complexity", 2305 | "support": { 2306 | "issues": "https://github.com/sebastianbergmann/complexity/issues", 2307 | "security": "https://github.com/sebastianbergmann/complexity/security/policy", 2308 | "source": "https://github.com/sebastianbergmann/complexity/tree/4.0.1" 2309 | }, 2310 | "funding": [ 2311 | { 2312 | "url": "https://github.com/sebastianbergmann", 2313 | "type": "github" 2314 | } 2315 | ], 2316 | "time": "2024-07-03T04:49:50+00:00" 2317 | }, 2318 | { 2319 | "name": "sebastian/diff", 2320 | "version": "6.0.2", 2321 | "source": { 2322 | "type": "git", 2323 | "url": "https://github.com/sebastianbergmann/diff.git", 2324 | "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544" 2325 | }, 2326 | "dist": { 2327 | "type": "zip", 2328 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b4ccd857127db5d41a5b676f24b51371d76d8544", 2329 | "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544", 2330 | "shasum": "" 2331 | }, 2332 | "require": { 2333 | "php": ">=8.2" 2334 | }, 2335 | "require-dev": { 2336 | "phpunit/phpunit": "^11.0", 2337 | "symfony/process": "^4.2 || ^5" 2338 | }, 2339 | "type": "library", 2340 | "extra": { 2341 | "branch-alias": { 2342 | "dev-main": "6.0-dev" 2343 | } 2344 | }, 2345 | "autoload": { 2346 | "classmap": [ 2347 | "src/" 2348 | ] 2349 | }, 2350 | "notification-url": "https://packagist.org/downloads/", 2351 | "license": [ 2352 | "BSD-3-Clause" 2353 | ], 2354 | "authors": [ 2355 | { 2356 | "name": "Sebastian Bergmann", 2357 | "email": "sebastian@phpunit.de" 2358 | }, 2359 | { 2360 | "name": "Kore Nordmann", 2361 | "email": "mail@kore-nordmann.de" 2362 | } 2363 | ], 2364 | "description": "Diff implementation", 2365 | "homepage": "https://github.com/sebastianbergmann/diff", 2366 | "keywords": [ 2367 | "diff", 2368 | "udiff", 2369 | "unidiff", 2370 | "unified diff" 2371 | ], 2372 | "support": { 2373 | "issues": "https://github.com/sebastianbergmann/diff/issues", 2374 | "security": "https://github.com/sebastianbergmann/diff/security/policy", 2375 | "source": "https://github.com/sebastianbergmann/diff/tree/6.0.2" 2376 | }, 2377 | "funding": [ 2378 | { 2379 | "url": "https://github.com/sebastianbergmann", 2380 | "type": "github" 2381 | } 2382 | ], 2383 | "time": "2024-07-03T04:53:05+00:00" 2384 | }, 2385 | { 2386 | "name": "sebastian/environment", 2387 | "version": "7.2.0", 2388 | "source": { 2389 | "type": "git", 2390 | "url": "https://github.com/sebastianbergmann/environment.git", 2391 | "reference": "855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5" 2392 | }, 2393 | "dist": { 2394 | "type": "zip", 2395 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5", 2396 | "reference": "855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5", 2397 | "shasum": "" 2398 | }, 2399 | "require": { 2400 | "php": ">=8.2" 2401 | }, 2402 | "require-dev": { 2403 | "phpunit/phpunit": "^11.0" 2404 | }, 2405 | "suggest": { 2406 | "ext-posix": "*" 2407 | }, 2408 | "type": "library", 2409 | "extra": { 2410 | "branch-alias": { 2411 | "dev-main": "7.2-dev" 2412 | } 2413 | }, 2414 | "autoload": { 2415 | "classmap": [ 2416 | "src/" 2417 | ] 2418 | }, 2419 | "notification-url": "https://packagist.org/downloads/", 2420 | "license": [ 2421 | "BSD-3-Clause" 2422 | ], 2423 | "authors": [ 2424 | { 2425 | "name": "Sebastian Bergmann", 2426 | "email": "sebastian@phpunit.de" 2427 | } 2428 | ], 2429 | "description": "Provides functionality to handle HHVM/PHP environments", 2430 | "homepage": "https://github.com/sebastianbergmann/environment", 2431 | "keywords": [ 2432 | "Xdebug", 2433 | "environment", 2434 | "hhvm" 2435 | ], 2436 | "support": { 2437 | "issues": "https://github.com/sebastianbergmann/environment/issues", 2438 | "security": "https://github.com/sebastianbergmann/environment/security/policy", 2439 | "source": "https://github.com/sebastianbergmann/environment/tree/7.2.0" 2440 | }, 2441 | "funding": [ 2442 | { 2443 | "url": "https://github.com/sebastianbergmann", 2444 | "type": "github" 2445 | } 2446 | ], 2447 | "time": "2024-07-03T04:54:44+00:00" 2448 | }, 2449 | { 2450 | "name": "sebastian/exporter", 2451 | "version": "6.3.0", 2452 | "source": { 2453 | "type": "git", 2454 | "url": "https://github.com/sebastianbergmann/exporter.git", 2455 | "reference": "3473f61172093b2da7de1fb5782e1f24cc036dc3" 2456 | }, 2457 | "dist": { 2458 | "type": "zip", 2459 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/3473f61172093b2da7de1fb5782e1f24cc036dc3", 2460 | "reference": "3473f61172093b2da7de1fb5782e1f24cc036dc3", 2461 | "shasum": "" 2462 | }, 2463 | "require": { 2464 | "ext-mbstring": "*", 2465 | "php": ">=8.2", 2466 | "sebastian/recursion-context": "^6.0" 2467 | }, 2468 | "require-dev": { 2469 | "phpunit/phpunit": "^11.3" 2470 | }, 2471 | "type": "library", 2472 | "extra": { 2473 | "branch-alias": { 2474 | "dev-main": "6.1-dev" 2475 | } 2476 | }, 2477 | "autoload": { 2478 | "classmap": [ 2479 | "src/" 2480 | ] 2481 | }, 2482 | "notification-url": "https://packagist.org/downloads/", 2483 | "license": [ 2484 | "BSD-3-Clause" 2485 | ], 2486 | "authors": [ 2487 | { 2488 | "name": "Sebastian Bergmann", 2489 | "email": "sebastian@phpunit.de" 2490 | }, 2491 | { 2492 | "name": "Jeff Welch", 2493 | "email": "whatthejeff@gmail.com" 2494 | }, 2495 | { 2496 | "name": "Volker Dusch", 2497 | "email": "github@wallbash.com" 2498 | }, 2499 | { 2500 | "name": "Adam Harvey", 2501 | "email": "aharvey@php.net" 2502 | }, 2503 | { 2504 | "name": "Bernhard Schussek", 2505 | "email": "bschussek@gmail.com" 2506 | } 2507 | ], 2508 | "description": "Provides the functionality to export PHP variables for visualization", 2509 | "homepage": "https://www.github.com/sebastianbergmann/exporter", 2510 | "keywords": [ 2511 | "export", 2512 | "exporter" 2513 | ], 2514 | "support": { 2515 | "issues": "https://github.com/sebastianbergmann/exporter/issues", 2516 | "security": "https://github.com/sebastianbergmann/exporter/security/policy", 2517 | "source": "https://github.com/sebastianbergmann/exporter/tree/6.3.0" 2518 | }, 2519 | "funding": [ 2520 | { 2521 | "url": "https://github.com/sebastianbergmann", 2522 | "type": "github" 2523 | } 2524 | ], 2525 | "time": "2024-12-05T09:17:50+00:00" 2526 | }, 2527 | { 2528 | "name": "sebastian/global-state", 2529 | "version": "7.0.2", 2530 | "source": { 2531 | "type": "git", 2532 | "url": "https://github.com/sebastianbergmann/global-state.git", 2533 | "reference": "3be331570a721f9a4b5917f4209773de17f747d7" 2534 | }, 2535 | "dist": { 2536 | "type": "zip", 2537 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/3be331570a721f9a4b5917f4209773de17f747d7", 2538 | "reference": "3be331570a721f9a4b5917f4209773de17f747d7", 2539 | "shasum": "" 2540 | }, 2541 | "require": { 2542 | "php": ">=8.2", 2543 | "sebastian/object-reflector": "^4.0", 2544 | "sebastian/recursion-context": "^6.0" 2545 | }, 2546 | "require-dev": { 2547 | "ext-dom": "*", 2548 | "phpunit/phpunit": "^11.0" 2549 | }, 2550 | "type": "library", 2551 | "extra": { 2552 | "branch-alias": { 2553 | "dev-main": "7.0-dev" 2554 | } 2555 | }, 2556 | "autoload": { 2557 | "classmap": [ 2558 | "src/" 2559 | ] 2560 | }, 2561 | "notification-url": "https://packagist.org/downloads/", 2562 | "license": [ 2563 | "BSD-3-Clause" 2564 | ], 2565 | "authors": [ 2566 | { 2567 | "name": "Sebastian Bergmann", 2568 | "email": "sebastian@phpunit.de" 2569 | } 2570 | ], 2571 | "description": "Snapshotting of global state", 2572 | "homepage": "https://www.github.com/sebastianbergmann/global-state", 2573 | "keywords": [ 2574 | "global state" 2575 | ], 2576 | "support": { 2577 | "issues": "https://github.com/sebastianbergmann/global-state/issues", 2578 | "security": "https://github.com/sebastianbergmann/global-state/security/policy", 2579 | "source": "https://github.com/sebastianbergmann/global-state/tree/7.0.2" 2580 | }, 2581 | "funding": [ 2582 | { 2583 | "url": "https://github.com/sebastianbergmann", 2584 | "type": "github" 2585 | } 2586 | ], 2587 | "time": "2024-07-03T04:57:36+00:00" 2588 | }, 2589 | { 2590 | "name": "sebastian/lines-of-code", 2591 | "version": "3.0.1", 2592 | "source": { 2593 | "type": "git", 2594 | "url": "https://github.com/sebastianbergmann/lines-of-code.git", 2595 | "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a" 2596 | }, 2597 | "dist": { 2598 | "type": "zip", 2599 | "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/d36ad0d782e5756913e42ad87cb2890f4ffe467a", 2600 | "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a", 2601 | "shasum": "" 2602 | }, 2603 | "require": { 2604 | "nikic/php-parser": "^5.0", 2605 | "php": ">=8.2" 2606 | }, 2607 | "require-dev": { 2608 | "phpunit/phpunit": "^11.0" 2609 | }, 2610 | "type": "library", 2611 | "extra": { 2612 | "branch-alias": { 2613 | "dev-main": "3.0-dev" 2614 | } 2615 | }, 2616 | "autoload": { 2617 | "classmap": [ 2618 | "src/" 2619 | ] 2620 | }, 2621 | "notification-url": "https://packagist.org/downloads/", 2622 | "license": [ 2623 | "BSD-3-Clause" 2624 | ], 2625 | "authors": [ 2626 | { 2627 | "name": "Sebastian Bergmann", 2628 | "email": "sebastian@phpunit.de", 2629 | "role": "lead" 2630 | } 2631 | ], 2632 | "description": "Library for counting the lines of code in PHP source code", 2633 | "homepage": "https://github.com/sebastianbergmann/lines-of-code", 2634 | "support": { 2635 | "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", 2636 | "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", 2637 | "source": "https://github.com/sebastianbergmann/lines-of-code/tree/3.0.1" 2638 | }, 2639 | "funding": [ 2640 | { 2641 | "url": "https://github.com/sebastianbergmann", 2642 | "type": "github" 2643 | } 2644 | ], 2645 | "time": "2024-07-03T04:58:38+00:00" 2646 | }, 2647 | { 2648 | "name": "sebastian/object-enumerator", 2649 | "version": "6.0.1", 2650 | "source": { 2651 | "type": "git", 2652 | "url": "https://github.com/sebastianbergmann/object-enumerator.git", 2653 | "reference": "f5b498e631a74204185071eb41f33f38d64608aa" 2654 | }, 2655 | "dist": { 2656 | "type": "zip", 2657 | "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/f5b498e631a74204185071eb41f33f38d64608aa", 2658 | "reference": "f5b498e631a74204185071eb41f33f38d64608aa", 2659 | "shasum": "" 2660 | }, 2661 | "require": { 2662 | "php": ">=8.2", 2663 | "sebastian/object-reflector": "^4.0", 2664 | "sebastian/recursion-context": "^6.0" 2665 | }, 2666 | "require-dev": { 2667 | "phpunit/phpunit": "^11.0" 2668 | }, 2669 | "type": "library", 2670 | "extra": { 2671 | "branch-alias": { 2672 | "dev-main": "6.0-dev" 2673 | } 2674 | }, 2675 | "autoload": { 2676 | "classmap": [ 2677 | "src/" 2678 | ] 2679 | }, 2680 | "notification-url": "https://packagist.org/downloads/", 2681 | "license": [ 2682 | "BSD-3-Clause" 2683 | ], 2684 | "authors": [ 2685 | { 2686 | "name": "Sebastian Bergmann", 2687 | "email": "sebastian@phpunit.de" 2688 | } 2689 | ], 2690 | "description": "Traverses array structures and object graphs to enumerate all referenced objects", 2691 | "homepage": "https://github.com/sebastianbergmann/object-enumerator/", 2692 | "support": { 2693 | "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", 2694 | "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", 2695 | "source": "https://github.com/sebastianbergmann/object-enumerator/tree/6.0.1" 2696 | }, 2697 | "funding": [ 2698 | { 2699 | "url": "https://github.com/sebastianbergmann", 2700 | "type": "github" 2701 | } 2702 | ], 2703 | "time": "2024-07-03T05:00:13+00:00" 2704 | }, 2705 | { 2706 | "name": "sebastian/object-reflector", 2707 | "version": "4.0.1", 2708 | "source": { 2709 | "type": "git", 2710 | "url": "https://github.com/sebastianbergmann/object-reflector.git", 2711 | "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9" 2712 | }, 2713 | "dist": { 2714 | "type": "zip", 2715 | "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/6e1a43b411b2ad34146dee7524cb13a068bb35f9", 2716 | "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9", 2717 | "shasum": "" 2718 | }, 2719 | "require": { 2720 | "php": ">=8.2" 2721 | }, 2722 | "require-dev": { 2723 | "phpunit/phpunit": "^11.0" 2724 | }, 2725 | "type": "library", 2726 | "extra": { 2727 | "branch-alias": { 2728 | "dev-main": "4.0-dev" 2729 | } 2730 | }, 2731 | "autoload": { 2732 | "classmap": [ 2733 | "src/" 2734 | ] 2735 | }, 2736 | "notification-url": "https://packagist.org/downloads/", 2737 | "license": [ 2738 | "BSD-3-Clause" 2739 | ], 2740 | "authors": [ 2741 | { 2742 | "name": "Sebastian Bergmann", 2743 | "email": "sebastian@phpunit.de" 2744 | } 2745 | ], 2746 | "description": "Allows reflection of object attributes, including inherited and non-public ones", 2747 | "homepage": "https://github.com/sebastianbergmann/object-reflector/", 2748 | "support": { 2749 | "issues": "https://github.com/sebastianbergmann/object-reflector/issues", 2750 | "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", 2751 | "source": "https://github.com/sebastianbergmann/object-reflector/tree/4.0.1" 2752 | }, 2753 | "funding": [ 2754 | { 2755 | "url": "https://github.com/sebastianbergmann", 2756 | "type": "github" 2757 | } 2758 | ], 2759 | "time": "2024-07-03T05:01:32+00:00" 2760 | }, 2761 | { 2762 | "name": "sebastian/recursion-context", 2763 | "version": "6.0.2", 2764 | "source": { 2765 | "type": "git", 2766 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 2767 | "reference": "694d156164372abbd149a4b85ccda2e4670c0e16" 2768 | }, 2769 | "dist": { 2770 | "type": "zip", 2771 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/694d156164372abbd149a4b85ccda2e4670c0e16", 2772 | "reference": "694d156164372abbd149a4b85ccda2e4670c0e16", 2773 | "shasum": "" 2774 | }, 2775 | "require": { 2776 | "php": ">=8.2" 2777 | }, 2778 | "require-dev": { 2779 | "phpunit/phpunit": "^11.0" 2780 | }, 2781 | "type": "library", 2782 | "extra": { 2783 | "branch-alias": { 2784 | "dev-main": "6.0-dev" 2785 | } 2786 | }, 2787 | "autoload": { 2788 | "classmap": [ 2789 | "src/" 2790 | ] 2791 | }, 2792 | "notification-url": "https://packagist.org/downloads/", 2793 | "license": [ 2794 | "BSD-3-Clause" 2795 | ], 2796 | "authors": [ 2797 | { 2798 | "name": "Sebastian Bergmann", 2799 | "email": "sebastian@phpunit.de" 2800 | }, 2801 | { 2802 | "name": "Jeff Welch", 2803 | "email": "whatthejeff@gmail.com" 2804 | }, 2805 | { 2806 | "name": "Adam Harvey", 2807 | "email": "aharvey@php.net" 2808 | } 2809 | ], 2810 | "description": "Provides functionality to recursively process PHP variables", 2811 | "homepage": "https://github.com/sebastianbergmann/recursion-context", 2812 | "support": { 2813 | "issues": "https://github.com/sebastianbergmann/recursion-context/issues", 2814 | "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", 2815 | "source": "https://github.com/sebastianbergmann/recursion-context/tree/6.0.2" 2816 | }, 2817 | "funding": [ 2818 | { 2819 | "url": "https://github.com/sebastianbergmann", 2820 | "type": "github" 2821 | } 2822 | ], 2823 | "time": "2024-07-03T05:10:34+00:00" 2824 | }, 2825 | { 2826 | "name": "sebastian/type", 2827 | "version": "5.1.2", 2828 | "source": { 2829 | "type": "git", 2830 | "url": "https://github.com/sebastianbergmann/type.git", 2831 | "reference": "a8a7e30534b0eb0c77cd9d07e82de1a114389f5e" 2832 | }, 2833 | "dist": { 2834 | "type": "zip", 2835 | "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/a8a7e30534b0eb0c77cd9d07e82de1a114389f5e", 2836 | "reference": "a8a7e30534b0eb0c77cd9d07e82de1a114389f5e", 2837 | "shasum": "" 2838 | }, 2839 | "require": { 2840 | "php": ">=8.2" 2841 | }, 2842 | "require-dev": { 2843 | "phpunit/phpunit": "^11.3" 2844 | }, 2845 | "type": "library", 2846 | "extra": { 2847 | "branch-alias": { 2848 | "dev-main": "5.1-dev" 2849 | } 2850 | }, 2851 | "autoload": { 2852 | "classmap": [ 2853 | "src/" 2854 | ] 2855 | }, 2856 | "notification-url": "https://packagist.org/downloads/", 2857 | "license": [ 2858 | "BSD-3-Clause" 2859 | ], 2860 | "authors": [ 2861 | { 2862 | "name": "Sebastian Bergmann", 2863 | "email": "sebastian@phpunit.de", 2864 | "role": "lead" 2865 | } 2866 | ], 2867 | "description": "Collection of value objects that represent the types of the PHP type system", 2868 | "homepage": "https://github.com/sebastianbergmann/type", 2869 | "support": { 2870 | "issues": "https://github.com/sebastianbergmann/type/issues", 2871 | "security": "https://github.com/sebastianbergmann/type/security/policy", 2872 | "source": "https://github.com/sebastianbergmann/type/tree/5.1.2" 2873 | }, 2874 | "funding": [ 2875 | { 2876 | "url": "https://github.com/sebastianbergmann", 2877 | "type": "github" 2878 | } 2879 | ], 2880 | "time": "2025-03-18T13:35:50+00:00" 2881 | }, 2882 | { 2883 | "name": "sebastian/version", 2884 | "version": "5.0.2", 2885 | "source": { 2886 | "type": "git", 2887 | "url": "https://github.com/sebastianbergmann/version.git", 2888 | "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874" 2889 | }, 2890 | "dist": { 2891 | "type": "zip", 2892 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c687e3387b99f5b03b6caa64c74b63e2936ff874", 2893 | "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874", 2894 | "shasum": "" 2895 | }, 2896 | "require": { 2897 | "php": ">=8.2" 2898 | }, 2899 | "type": "library", 2900 | "extra": { 2901 | "branch-alias": { 2902 | "dev-main": "5.0-dev" 2903 | } 2904 | }, 2905 | "autoload": { 2906 | "classmap": [ 2907 | "src/" 2908 | ] 2909 | }, 2910 | "notification-url": "https://packagist.org/downloads/", 2911 | "license": [ 2912 | "BSD-3-Clause" 2913 | ], 2914 | "authors": [ 2915 | { 2916 | "name": "Sebastian Bergmann", 2917 | "email": "sebastian@phpunit.de", 2918 | "role": "lead" 2919 | } 2920 | ], 2921 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", 2922 | "homepage": "https://github.com/sebastianbergmann/version", 2923 | "support": { 2924 | "issues": "https://github.com/sebastianbergmann/version/issues", 2925 | "security": "https://github.com/sebastianbergmann/version/security/policy", 2926 | "source": "https://github.com/sebastianbergmann/version/tree/5.0.2" 2927 | }, 2928 | "funding": [ 2929 | { 2930 | "url": "https://github.com/sebastianbergmann", 2931 | "type": "github" 2932 | } 2933 | ], 2934 | "time": "2024-10-09T05:16:32+00:00" 2935 | }, 2936 | { 2937 | "name": "staabm/side-effects-detector", 2938 | "version": "1.0.5", 2939 | "source": { 2940 | "type": "git", 2941 | "url": "https://github.com/staabm/side-effects-detector.git", 2942 | "reference": "d8334211a140ce329c13726d4a715adbddd0a163" 2943 | }, 2944 | "dist": { 2945 | "type": "zip", 2946 | "url": "https://api.github.com/repos/staabm/side-effects-detector/zipball/d8334211a140ce329c13726d4a715adbddd0a163", 2947 | "reference": "d8334211a140ce329c13726d4a715adbddd0a163", 2948 | "shasum": "" 2949 | }, 2950 | "require": { 2951 | "ext-tokenizer": "*", 2952 | "php": "^7.4 || ^8.0" 2953 | }, 2954 | "require-dev": { 2955 | "phpstan/extension-installer": "^1.4.3", 2956 | "phpstan/phpstan": "^1.12.6", 2957 | "phpunit/phpunit": "^9.6.21", 2958 | "symfony/var-dumper": "^5.4.43", 2959 | "tomasvotruba/type-coverage": "1.0.0", 2960 | "tomasvotruba/unused-public": "1.0.0" 2961 | }, 2962 | "type": "library", 2963 | "autoload": { 2964 | "classmap": [ 2965 | "lib/" 2966 | ] 2967 | }, 2968 | "notification-url": "https://packagist.org/downloads/", 2969 | "license": [ 2970 | "MIT" 2971 | ], 2972 | "description": "A static analysis tool to detect side effects in PHP code", 2973 | "keywords": [ 2974 | "static analysis" 2975 | ], 2976 | "support": { 2977 | "issues": "https://github.com/staabm/side-effects-detector/issues", 2978 | "source": "https://github.com/staabm/side-effects-detector/tree/1.0.5" 2979 | }, 2980 | "funding": [ 2981 | { 2982 | "url": "https://github.com/staabm", 2983 | "type": "github" 2984 | } 2985 | ], 2986 | "time": "2024-10-20T05:08:20+00:00" 2987 | }, 2988 | { 2989 | "name": "symfony/console", 2990 | "version": "v7.2.5", 2991 | "source": { 2992 | "type": "git", 2993 | "url": "https://github.com/symfony/console.git", 2994 | "reference": "e51498ea18570c062e7df29d05a7003585b19b88" 2995 | }, 2996 | "dist": { 2997 | "type": "zip", 2998 | "url": "https://api.github.com/repos/symfony/console/zipball/e51498ea18570c062e7df29d05a7003585b19b88", 2999 | "reference": "e51498ea18570c062e7df29d05a7003585b19b88", 3000 | "shasum": "" 3001 | }, 3002 | "require": { 3003 | "php": ">=8.2", 3004 | "symfony/polyfill-mbstring": "~1.0", 3005 | "symfony/service-contracts": "^2.5|^3", 3006 | "symfony/string": "^6.4|^7.0" 3007 | }, 3008 | "conflict": { 3009 | "symfony/dependency-injection": "<6.4", 3010 | "symfony/dotenv": "<6.4", 3011 | "symfony/event-dispatcher": "<6.4", 3012 | "symfony/lock": "<6.4", 3013 | "symfony/process": "<6.4" 3014 | }, 3015 | "provide": { 3016 | "psr/log-implementation": "1.0|2.0|3.0" 3017 | }, 3018 | "require-dev": { 3019 | "psr/log": "^1|^2|^3", 3020 | "symfony/config": "^6.4|^7.0", 3021 | "symfony/dependency-injection": "^6.4|^7.0", 3022 | "symfony/event-dispatcher": "^6.4|^7.0", 3023 | "symfony/http-foundation": "^6.4|^7.0", 3024 | "symfony/http-kernel": "^6.4|^7.0", 3025 | "symfony/lock": "^6.4|^7.0", 3026 | "symfony/messenger": "^6.4|^7.0", 3027 | "symfony/process": "^6.4|^7.0", 3028 | "symfony/stopwatch": "^6.4|^7.0", 3029 | "symfony/var-dumper": "^6.4|^7.0" 3030 | }, 3031 | "type": "library", 3032 | "autoload": { 3033 | "psr-4": { 3034 | "Symfony\\Component\\Console\\": "" 3035 | }, 3036 | "exclude-from-classmap": [ 3037 | "/Tests/" 3038 | ] 3039 | }, 3040 | "notification-url": "https://packagist.org/downloads/", 3041 | "license": [ 3042 | "MIT" 3043 | ], 3044 | "authors": [ 3045 | { 3046 | "name": "Fabien Potencier", 3047 | "email": "fabien@symfony.com" 3048 | }, 3049 | { 3050 | "name": "Symfony Community", 3051 | "homepage": "https://symfony.com/contributors" 3052 | } 3053 | ], 3054 | "description": "Eases the creation of beautiful and testable command line interfaces", 3055 | "homepage": "https://symfony.com", 3056 | "keywords": [ 3057 | "cli", 3058 | "command-line", 3059 | "console", 3060 | "terminal" 3061 | ], 3062 | "support": { 3063 | "source": "https://github.com/symfony/console/tree/v7.2.5" 3064 | }, 3065 | "funding": [ 3066 | { 3067 | "url": "https://symfony.com/sponsor", 3068 | "type": "custom" 3069 | }, 3070 | { 3071 | "url": "https://github.com/fabpot", 3072 | "type": "github" 3073 | }, 3074 | { 3075 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 3076 | "type": "tidelift" 3077 | } 3078 | ], 3079 | "time": "2025-03-12T08:11:12+00:00" 3080 | }, 3081 | { 3082 | "name": "symfony/deprecation-contracts", 3083 | "version": "v3.5.1", 3084 | "source": { 3085 | "type": "git", 3086 | "url": "https://github.com/symfony/deprecation-contracts.git", 3087 | "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" 3088 | }, 3089 | "dist": { 3090 | "type": "zip", 3091 | "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", 3092 | "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", 3093 | "shasum": "" 3094 | }, 3095 | "require": { 3096 | "php": ">=8.1" 3097 | }, 3098 | "type": "library", 3099 | "extra": { 3100 | "thanks": { 3101 | "url": "https://github.com/symfony/contracts", 3102 | "name": "symfony/contracts" 3103 | }, 3104 | "branch-alias": { 3105 | "dev-main": "3.5-dev" 3106 | } 3107 | }, 3108 | "autoload": { 3109 | "files": [ 3110 | "function.php" 3111 | ] 3112 | }, 3113 | "notification-url": "https://packagist.org/downloads/", 3114 | "license": [ 3115 | "MIT" 3116 | ], 3117 | "authors": [ 3118 | { 3119 | "name": "Nicolas Grekas", 3120 | "email": "p@tchwork.com" 3121 | }, 3122 | { 3123 | "name": "Symfony Community", 3124 | "homepage": "https://symfony.com/contributors" 3125 | } 3126 | ], 3127 | "description": "A generic function and convention to trigger deprecation notices", 3128 | "homepage": "https://symfony.com", 3129 | "support": { 3130 | "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" 3131 | }, 3132 | "funding": [ 3133 | { 3134 | "url": "https://symfony.com/sponsor", 3135 | "type": "custom" 3136 | }, 3137 | { 3138 | "url": "https://github.com/fabpot", 3139 | "type": "github" 3140 | }, 3141 | { 3142 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 3143 | "type": "tidelift" 3144 | } 3145 | ], 3146 | "time": "2024-09-25T14:20:29+00:00" 3147 | }, 3148 | { 3149 | "name": "symfony/event-dispatcher", 3150 | "version": "v7.2.0", 3151 | "source": { 3152 | "type": "git", 3153 | "url": "https://github.com/symfony/event-dispatcher.git", 3154 | "reference": "910c5db85a5356d0fea57680defec4e99eb9c8c1" 3155 | }, 3156 | "dist": { 3157 | "type": "zip", 3158 | "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/910c5db85a5356d0fea57680defec4e99eb9c8c1", 3159 | "reference": "910c5db85a5356d0fea57680defec4e99eb9c8c1", 3160 | "shasum": "" 3161 | }, 3162 | "require": { 3163 | "php": ">=8.2", 3164 | "symfony/event-dispatcher-contracts": "^2.5|^3" 3165 | }, 3166 | "conflict": { 3167 | "symfony/dependency-injection": "<6.4", 3168 | "symfony/service-contracts": "<2.5" 3169 | }, 3170 | "provide": { 3171 | "psr/event-dispatcher-implementation": "1.0", 3172 | "symfony/event-dispatcher-implementation": "2.0|3.0" 3173 | }, 3174 | "require-dev": { 3175 | "psr/log": "^1|^2|^3", 3176 | "symfony/config": "^6.4|^7.0", 3177 | "symfony/dependency-injection": "^6.4|^7.0", 3178 | "symfony/error-handler": "^6.4|^7.0", 3179 | "symfony/expression-language": "^6.4|^7.0", 3180 | "symfony/http-foundation": "^6.4|^7.0", 3181 | "symfony/service-contracts": "^2.5|^3", 3182 | "symfony/stopwatch": "^6.4|^7.0" 3183 | }, 3184 | "type": "library", 3185 | "autoload": { 3186 | "psr-4": { 3187 | "Symfony\\Component\\EventDispatcher\\": "" 3188 | }, 3189 | "exclude-from-classmap": [ 3190 | "/Tests/" 3191 | ] 3192 | }, 3193 | "notification-url": "https://packagist.org/downloads/", 3194 | "license": [ 3195 | "MIT" 3196 | ], 3197 | "authors": [ 3198 | { 3199 | "name": "Fabien Potencier", 3200 | "email": "fabien@symfony.com" 3201 | }, 3202 | { 3203 | "name": "Symfony Community", 3204 | "homepage": "https://symfony.com/contributors" 3205 | } 3206 | ], 3207 | "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", 3208 | "homepage": "https://symfony.com", 3209 | "support": { 3210 | "source": "https://github.com/symfony/event-dispatcher/tree/v7.2.0" 3211 | }, 3212 | "funding": [ 3213 | { 3214 | "url": "https://symfony.com/sponsor", 3215 | "type": "custom" 3216 | }, 3217 | { 3218 | "url": "https://github.com/fabpot", 3219 | "type": "github" 3220 | }, 3221 | { 3222 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 3223 | "type": "tidelift" 3224 | } 3225 | ], 3226 | "time": "2024-09-25T14:21:43+00:00" 3227 | }, 3228 | { 3229 | "name": "symfony/event-dispatcher-contracts", 3230 | "version": "v3.5.1", 3231 | "source": { 3232 | "type": "git", 3233 | "url": "https://github.com/symfony/event-dispatcher-contracts.git", 3234 | "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f" 3235 | }, 3236 | "dist": { 3237 | "type": "zip", 3238 | "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/7642f5e970b672283b7823222ae8ef8bbc160b9f", 3239 | "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f", 3240 | "shasum": "" 3241 | }, 3242 | "require": { 3243 | "php": ">=8.1", 3244 | "psr/event-dispatcher": "^1" 3245 | }, 3246 | "type": "library", 3247 | "extra": { 3248 | "thanks": { 3249 | "url": "https://github.com/symfony/contracts", 3250 | "name": "symfony/contracts" 3251 | }, 3252 | "branch-alias": { 3253 | "dev-main": "3.5-dev" 3254 | } 3255 | }, 3256 | "autoload": { 3257 | "psr-4": { 3258 | "Symfony\\Contracts\\EventDispatcher\\": "" 3259 | } 3260 | }, 3261 | "notification-url": "https://packagist.org/downloads/", 3262 | "license": [ 3263 | "MIT" 3264 | ], 3265 | "authors": [ 3266 | { 3267 | "name": "Nicolas Grekas", 3268 | "email": "p@tchwork.com" 3269 | }, 3270 | { 3271 | "name": "Symfony Community", 3272 | "homepage": "https://symfony.com/contributors" 3273 | } 3274 | ], 3275 | "description": "Generic abstractions related to dispatching event", 3276 | "homepage": "https://symfony.com", 3277 | "keywords": [ 3278 | "abstractions", 3279 | "contracts", 3280 | "decoupling", 3281 | "interfaces", 3282 | "interoperability", 3283 | "standards" 3284 | ], 3285 | "support": { 3286 | "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.1" 3287 | }, 3288 | "funding": [ 3289 | { 3290 | "url": "https://symfony.com/sponsor", 3291 | "type": "custom" 3292 | }, 3293 | { 3294 | "url": "https://github.com/fabpot", 3295 | "type": "github" 3296 | }, 3297 | { 3298 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 3299 | "type": "tidelift" 3300 | } 3301 | ], 3302 | "time": "2024-09-25T14:20:29+00:00" 3303 | }, 3304 | { 3305 | "name": "symfony/filesystem", 3306 | "version": "v7.2.0", 3307 | "source": { 3308 | "type": "git", 3309 | "url": "https://github.com/symfony/filesystem.git", 3310 | "reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb" 3311 | }, 3312 | "dist": { 3313 | "type": "zip", 3314 | "url": "https://api.github.com/repos/symfony/filesystem/zipball/b8dce482de9d7c9fe2891155035a7248ab5c7fdb", 3315 | "reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb", 3316 | "shasum": "" 3317 | }, 3318 | "require": { 3319 | "php": ">=8.2", 3320 | "symfony/polyfill-ctype": "~1.8", 3321 | "symfony/polyfill-mbstring": "~1.8" 3322 | }, 3323 | "require-dev": { 3324 | "symfony/process": "^6.4|^7.0" 3325 | }, 3326 | "type": "library", 3327 | "autoload": { 3328 | "psr-4": { 3329 | "Symfony\\Component\\Filesystem\\": "" 3330 | }, 3331 | "exclude-from-classmap": [ 3332 | "/Tests/" 3333 | ] 3334 | }, 3335 | "notification-url": "https://packagist.org/downloads/", 3336 | "license": [ 3337 | "MIT" 3338 | ], 3339 | "authors": [ 3340 | { 3341 | "name": "Fabien Potencier", 3342 | "email": "fabien@symfony.com" 3343 | }, 3344 | { 3345 | "name": "Symfony Community", 3346 | "homepage": "https://symfony.com/contributors" 3347 | } 3348 | ], 3349 | "description": "Provides basic utilities for the filesystem", 3350 | "homepage": "https://symfony.com", 3351 | "support": { 3352 | "source": "https://github.com/symfony/filesystem/tree/v7.2.0" 3353 | }, 3354 | "funding": [ 3355 | { 3356 | "url": "https://symfony.com/sponsor", 3357 | "type": "custom" 3358 | }, 3359 | { 3360 | "url": "https://github.com/fabpot", 3361 | "type": "github" 3362 | }, 3363 | { 3364 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 3365 | "type": "tidelift" 3366 | } 3367 | ], 3368 | "time": "2024-10-25T15:15:23+00:00" 3369 | }, 3370 | { 3371 | "name": "symfony/finder", 3372 | "version": "v7.2.2", 3373 | "source": { 3374 | "type": "git", 3375 | "url": "https://github.com/symfony/finder.git", 3376 | "reference": "87a71856f2f56e4100373e92529eed3171695cfb" 3377 | }, 3378 | "dist": { 3379 | "type": "zip", 3380 | "url": "https://api.github.com/repos/symfony/finder/zipball/87a71856f2f56e4100373e92529eed3171695cfb", 3381 | "reference": "87a71856f2f56e4100373e92529eed3171695cfb", 3382 | "shasum": "" 3383 | }, 3384 | "require": { 3385 | "php": ">=8.2" 3386 | }, 3387 | "require-dev": { 3388 | "symfony/filesystem": "^6.4|^7.0" 3389 | }, 3390 | "type": "library", 3391 | "autoload": { 3392 | "psr-4": { 3393 | "Symfony\\Component\\Finder\\": "" 3394 | }, 3395 | "exclude-from-classmap": [ 3396 | "/Tests/" 3397 | ] 3398 | }, 3399 | "notification-url": "https://packagist.org/downloads/", 3400 | "license": [ 3401 | "MIT" 3402 | ], 3403 | "authors": [ 3404 | { 3405 | "name": "Fabien Potencier", 3406 | "email": "fabien@symfony.com" 3407 | }, 3408 | { 3409 | "name": "Symfony Community", 3410 | "homepage": "https://symfony.com/contributors" 3411 | } 3412 | ], 3413 | "description": "Finds files and directories via an intuitive fluent interface", 3414 | "homepage": "https://symfony.com", 3415 | "support": { 3416 | "source": "https://github.com/symfony/finder/tree/v7.2.2" 3417 | }, 3418 | "funding": [ 3419 | { 3420 | "url": "https://symfony.com/sponsor", 3421 | "type": "custom" 3422 | }, 3423 | { 3424 | "url": "https://github.com/fabpot", 3425 | "type": "github" 3426 | }, 3427 | { 3428 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 3429 | "type": "tidelift" 3430 | } 3431 | ], 3432 | "time": "2024-12-30T19:00:17+00:00" 3433 | }, 3434 | { 3435 | "name": "symfony/options-resolver", 3436 | "version": "v7.2.0", 3437 | "source": { 3438 | "type": "git", 3439 | "url": "https://github.com/symfony/options-resolver.git", 3440 | "reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50" 3441 | }, 3442 | "dist": { 3443 | "type": "zip", 3444 | "url": "https://api.github.com/repos/symfony/options-resolver/zipball/7da8fbac9dcfef75ffc212235d76b2754ce0cf50", 3445 | "reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50", 3446 | "shasum": "" 3447 | }, 3448 | "require": { 3449 | "php": ">=8.2", 3450 | "symfony/deprecation-contracts": "^2.5|^3" 3451 | }, 3452 | "type": "library", 3453 | "autoload": { 3454 | "psr-4": { 3455 | "Symfony\\Component\\OptionsResolver\\": "" 3456 | }, 3457 | "exclude-from-classmap": [ 3458 | "/Tests/" 3459 | ] 3460 | }, 3461 | "notification-url": "https://packagist.org/downloads/", 3462 | "license": [ 3463 | "MIT" 3464 | ], 3465 | "authors": [ 3466 | { 3467 | "name": "Fabien Potencier", 3468 | "email": "fabien@symfony.com" 3469 | }, 3470 | { 3471 | "name": "Symfony Community", 3472 | "homepage": "https://symfony.com/contributors" 3473 | } 3474 | ], 3475 | "description": "Provides an improved replacement for the array_replace PHP function", 3476 | "homepage": "https://symfony.com", 3477 | "keywords": [ 3478 | "config", 3479 | "configuration", 3480 | "options" 3481 | ], 3482 | "support": { 3483 | "source": "https://github.com/symfony/options-resolver/tree/v7.2.0" 3484 | }, 3485 | "funding": [ 3486 | { 3487 | "url": "https://symfony.com/sponsor", 3488 | "type": "custom" 3489 | }, 3490 | { 3491 | "url": "https://github.com/fabpot", 3492 | "type": "github" 3493 | }, 3494 | { 3495 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 3496 | "type": "tidelift" 3497 | } 3498 | ], 3499 | "time": "2024-11-20T11:17:29+00:00" 3500 | }, 3501 | { 3502 | "name": "symfony/polyfill-ctype", 3503 | "version": "v1.31.0", 3504 | "source": { 3505 | "type": "git", 3506 | "url": "https://github.com/symfony/polyfill-ctype.git", 3507 | "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" 3508 | }, 3509 | "dist": { 3510 | "type": "zip", 3511 | "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", 3512 | "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", 3513 | "shasum": "" 3514 | }, 3515 | "require": { 3516 | "php": ">=7.2" 3517 | }, 3518 | "provide": { 3519 | "ext-ctype": "*" 3520 | }, 3521 | "suggest": { 3522 | "ext-ctype": "For best performance" 3523 | }, 3524 | "type": "library", 3525 | "extra": { 3526 | "thanks": { 3527 | "url": "https://github.com/symfony/polyfill", 3528 | "name": "symfony/polyfill" 3529 | } 3530 | }, 3531 | "autoload": { 3532 | "files": [ 3533 | "bootstrap.php" 3534 | ], 3535 | "psr-4": { 3536 | "Symfony\\Polyfill\\Ctype\\": "" 3537 | } 3538 | }, 3539 | "notification-url": "https://packagist.org/downloads/", 3540 | "license": [ 3541 | "MIT" 3542 | ], 3543 | "authors": [ 3544 | { 3545 | "name": "Gert de Pagter", 3546 | "email": "BackEndTea@gmail.com" 3547 | }, 3548 | { 3549 | "name": "Symfony Community", 3550 | "homepage": "https://symfony.com/contributors" 3551 | } 3552 | ], 3553 | "description": "Symfony polyfill for ctype functions", 3554 | "homepage": "https://symfony.com", 3555 | "keywords": [ 3556 | "compatibility", 3557 | "ctype", 3558 | "polyfill", 3559 | "portable" 3560 | ], 3561 | "support": { 3562 | "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0" 3563 | }, 3564 | "funding": [ 3565 | { 3566 | "url": "https://symfony.com/sponsor", 3567 | "type": "custom" 3568 | }, 3569 | { 3570 | "url": "https://github.com/fabpot", 3571 | "type": "github" 3572 | }, 3573 | { 3574 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 3575 | "type": "tidelift" 3576 | } 3577 | ], 3578 | "time": "2024-09-09T11:45:10+00:00" 3579 | }, 3580 | { 3581 | "name": "symfony/polyfill-intl-grapheme", 3582 | "version": "v1.31.0", 3583 | "source": { 3584 | "type": "git", 3585 | "url": "https://github.com/symfony/polyfill-intl-grapheme.git", 3586 | "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" 3587 | }, 3588 | "dist": { 3589 | "type": "zip", 3590 | "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", 3591 | "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", 3592 | "shasum": "" 3593 | }, 3594 | "require": { 3595 | "php": ">=7.2" 3596 | }, 3597 | "suggest": { 3598 | "ext-intl": "For best performance" 3599 | }, 3600 | "type": "library", 3601 | "extra": { 3602 | "thanks": { 3603 | "url": "https://github.com/symfony/polyfill", 3604 | "name": "symfony/polyfill" 3605 | } 3606 | }, 3607 | "autoload": { 3608 | "files": [ 3609 | "bootstrap.php" 3610 | ], 3611 | "psr-4": { 3612 | "Symfony\\Polyfill\\Intl\\Grapheme\\": "" 3613 | } 3614 | }, 3615 | "notification-url": "https://packagist.org/downloads/", 3616 | "license": [ 3617 | "MIT" 3618 | ], 3619 | "authors": [ 3620 | { 3621 | "name": "Nicolas Grekas", 3622 | "email": "p@tchwork.com" 3623 | }, 3624 | { 3625 | "name": "Symfony Community", 3626 | "homepage": "https://symfony.com/contributors" 3627 | } 3628 | ], 3629 | "description": "Symfony polyfill for intl's grapheme_* functions", 3630 | "homepage": "https://symfony.com", 3631 | "keywords": [ 3632 | "compatibility", 3633 | "grapheme", 3634 | "intl", 3635 | "polyfill", 3636 | "portable", 3637 | "shim" 3638 | ], 3639 | "support": { 3640 | "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.31.0" 3641 | }, 3642 | "funding": [ 3643 | { 3644 | "url": "https://symfony.com/sponsor", 3645 | "type": "custom" 3646 | }, 3647 | { 3648 | "url": "https://github.com/fabpot", 3649 | "type": "github" 3650 | }, 3651 | { 3652 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 3653 | "type": "tidelift" 3654 | } 3655 | ], 3656 | "time": "2024-09-09T11:45:10+00:00" 3657 | }, 3658 | { 3659 | "name": "symfony/polyfill-intl-normalizer", 3660 | "version": "v1.31.0", 3661 | "source": { 3662 | "type": "git", 3663 | "url": "https://github.com/symfony/polyfill-intl-normalizer.git", 3664 | "reference": "3833d7255cc303546435cb650316bff708a1c75c" 3665 | }, 3666 | "dist": { 3667 | "type": "zip", 3668 | "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", 3669 | "reference": "3833d7255cc303546435cb650316bff708a1c75c", 3670 | "shasum": "" 3671 | }, 3672 | "require": { 3673 | "php": ">=7.2" 3674 | }, 3675 | "suggest": { 3676 | "ext-intl": "For best performance" 3677 | }, 3678 | "type": "library", 3679 | "extra": { 3680 | "thanks": { 3681 | "url": "https://github.com/symfony/polyfill", 3682 | "name": "symfony/polyfill" 3683 | } 3684 | }, 3685 | "autoload": { 3686 | "files": [ 3687 | "bootstrap.php" 3688 | ], 3689 | "psr-4": { 3690 | "Symfony\\Polyfill\\Intl\\Normalizer\\": "" 3691 | }, 3692 | "classmap": [ 3693 | "Resources/stubs" 3694 | ] 3695 | }, 3696 | "notification-url": "https://packagist.org/downloads/", 3697 | "license": [ 3698 | "MIT" 3699 | ], 3700 | "authors": [ 3701 | { 3702 | "name": "Nicolas Grekas", 3703 | "email": "p@tchwork.com" 3704 | }, 3705 | { 3706 | "name": "Symfony Community", 3707 | "homepage": "https://symfony.com/contributors" 3708 | } 3709 | ], 3710 | "description": "Symfony polyfill for intl's Normalizer class and related functions", 3711 | "homepage": "https://symfony.com", 3712 | "keywords": [ 3713 | "compatibility", 3714 | "intl", 3715 | "normalizer", 3716 | "polyfill", 3717 | "portable", 3718 | "shim" 3719 | ], 3720 | "support": { 3721 | "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0" 3722 | }, 3723 | "funding": [ 3724 | { 3725 | "url": "https://symfony.com/sponsor", 3726 | "type": "custom" 3727 | }, 3728 | { 3729 | "url": "https://github.com/fabpot", 3730 | "type": "github" 3731 | }, 3732 | { 3733 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 3734 | "type": "tidelift" 3735 | } 3736 | ], 3737 | "time": "2024-09-09T11:45:10+00:00" 3738 | }, 3739 | { 3740 | "name": "symfony/polyfill-mbstring", 3741 | "version": "v1.31.0", 3742 | "source": { 3743 | "type": "git", 3744 | "url": "https://github.com/symfony/polyfill-mbstring.git", 3745 | "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" 3746 | }, 3747 | "dist": { 3748 | "type": "zip", 3749 | "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", 3750 | "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", 3751 | "shasum": "" 3752 | }, 3753 | "require": { 3754 | "php": ">=7.2" 3755 | }, 3756 | "provide": { 3757 | "ext-mbstring": "*" 3758 | }, 3759 | "suggest": { 3760 | "ext-mbstring": "For best performance" 3761 | }, 3762 | "type": "library", 3763 | "extra": { 3764 | "thanks": { 3765 | "url": "https://github.com/symfony/polyfill", 3766 | "name": "symfony/polyfill" 3767 | } 3768 | }, 3769 | "autoload": { 3770 | "files": [ 3771 | "bootstrap.php" 3772 | ], 3773 | "psr-4": { 3774 | "Symfony\\Polyfill\\Mbstring\\": "" 3775 | } 3776 | }, 3777 | "notification-url": "https://packagist.org/downloads/", 3778 | "license": [ 3779 | "MIT" 3780 | ], 3781 | "authors": [ 3782 | { 3783 | "name": "Nicolas Grekas", 3784 | "email": "p@tchwork.com" 3785 | }, 3786 | { 3787 | "name": "Symfony Community", 3788 | "homepage": "https://symfony.com/contributors" 3789 | } 3790 | ], 3791 | "description": "Symfony polyfill for the Mbstring extension", 3792 | "homepage": "https://symfony.com", 3793 | "keywords": [ 3794 | "compatibility", 3795 | "mbstring", 3796 | "polyfill", 3797 | "portable", 3798 | "shim" 3799 | ], 3800 | "support": { 3801 | "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" 3802 | }, 3803 | "funding": [ 3804 | { 3805 | "url": "https://symfony.com/sponsor", 3806 | "type": "custom" 3807 | }, 3808 | { 3809 | "url": "https://github.com/fabpot", 3810 | "type": "github" 3811 | }, 3812 | { 3813 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 3814 | "type": "tidelift" 3815 | } 3816 | ], 3817 | "time": "2024-09-09T11:45:10+00:00" 3818 | }, 3819 | { 3820 | "name": "symfony/polyfill-php80", 3821 | "version": "v1.31.0", 3822 | "source": { 3823 | "type": "git", 3824 | "url": "https://github.com/symfony/polyfill-php80.git", 3825 | "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8" 3826 | }, 3827 | "dist": { 3828 | "type": "zip", 3829 | "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", 3830 | "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", 3831 | "shasum": "" 3832 | }, 3833 | "require": { 3834 | "php": ">=7.2" 3835 | }, 3836 | "type": "library", 3837 | "extra": { 3838 | "thanks": { 3839 | "url": "https://github.com/symfony/polyfill", 3840 | "name": "symfony/polyfill" 3841 | } 3842 | }, 3843 | "autoload": { 3844 | "files": [ 3845 | "bootstrap.php" 3846 | ], 3847 | "psr-4": { 3848 | "Symfony\\Polyfill\\Php80\\": "" 3849 | }, 3850 | "classmap": [ 3851 | "Resources/stubs" 3852 | ] 3853 | }, 3854 | "notification-url": "https://packagist.org/downloads/", 3855 | "license": [ 3856 | "MIT" 3857 | ], 3858 | "authors": [ 3859 | { 3860 | "name": "Ion Bazan", 3861 | "email": "ion.bazan@gmail.com" 3862 | }, 3863 | { 3864 | "name": "Nicolas Grekas", 3865 | "email": "p@tchwork.com" 3866 | }, 3867 | { 3868 | "name": "Symfony Community", 3869 | "homepage": "https://symfony.com/contributors" 3870 | } 3871 | ], 3872 | "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", 3873 | "homepage": "https://symfony.com", 3874 | "keywords": [ 3875 | "compatibility", 3876 | "polyfill", 3877 | "portable", 3878 | "shim" 3879 | ], 3880 | "support": { 3881 | "source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0" 3882 | }, 3883 | "funding": [ 3884 | { 3885 | "url": "https://symfony.com/sponsor", 3886 | "type": "custom" 3887 | }, 3888 | { 3889 | "url": "https://github.com/fabpot", 3890 | "type": "github" 3891 | }, 3892 | { 3893 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 3894 | "type": "tidelift" 3895 | } 3896 | ], 3897 | "time": "2024-09-09T11:45:10+00:00" 3898 | }, 3899 | { 3900 | "name": "symfony/polyfill-php81", 3901 | "version": "v1.31.0", 3902 | "source": { 3903 | "type": "git", 3904 | "url": "https://github.com/symfony/polyfill-php81.git", 3905 | "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c" 3906 | }, 3907 | "dist": { 3908 | "type": "zip", 3909 | "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", 3910 | "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", 3911 | "shasum": "" 3912 | }, 3913 | "require": { 3914 | "php": ">=7.2" 3915 | }, 3916 | "type": "library", 3917 | "extra": { 3918 | "thanks": { 3919 | "url": "https://github.com/symfony/polyfill", 3920 | "name": "symfony/polyfill" 3921 | } 3922 | }, 3923 | "autoload": { 3924 | "files": [ 3925 | "bootstrap.php" 3926 | ], 3927 | "psr-4": { 3928 | "Symfony\\Polyfill\\Php81\\": "" 3929 | }, 3930 | "classmap": [ 3931 | "Resources/stubs" 3932 | ] 3933 | }, 3934 | "notification-url": "https://packagist.org/downloads/", 3935 | "license": [ 3936 | "MIT" 3937 | ], 3938 | "authors": [ 3939 | { 3940 | "name": "Nicolas Grekas", 3941 | "email": "p@tchwork.com" 3942 | }, 3943 | { 3944 | "name": "Symfony Community", 3945 | "homepage": "https://symfony.com/contributors" 3946 | } 3947 | ], 3948 | "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", 3949 | "homepage": "https://symfony.com", 3950 | "keywords": [ 3951 | "compatibility", 3952 | "polyfill", 3953 | "portable", 3954 | "shim" 3955 | ], 3956 | "support": { 3957 | "source": "https://github.com/symfony/polyfill-php81/tree/v1.31.0" 3958 | }, 3959 | "funding": [ 3960 | { 3961 | "url": "https://symfony.com/sponsor", 3962 | "type": "custom" 3963 | }, 3964 | { 3965 | "url": "https://github.com/fabpot", 3966 | "type": "github" 3967 | }, 3968 | { 3969 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 3970 | "type": "tidelift" 3971 | } 3972 | ], 3973 | "time": "2024-09-09T11:45:10+00:00" 3974 | }, 3975 | { 3976 | "name": "symfony/process", 3977 | "version": "v7.2.5", 3978 | "source": { 3979 | "type": "git", 3980 | "url": "https://github.com/symfony/process.git", 3981 | "reference": "87b7c93e57df9d8e39a093d32587702380ff045d" 3982 | }, 3983 | "dist": { 3984 | "type": "zip", 3985 | "url": "https://api.github.com/repos/symfony/process/zipball/87b7c93e57df9d8e39a093d32587702380ff045d", 3986 | "reference": "87b7c93e57df9d8e39a093d32587702380ff045d", 3987 | "shasum": "" 3988 | }, 3989 | "require": { 3990 | "php": ">=8.2" 3991 | }, 3992 | "type": "library", 3993 | "autoload": { 3994 | "psr-4": { 3995 | "Symfony\\Component\\Process\\": "" 3996 | }, 3997 | "exclude-from-classmap": [ 3998 | "/Tests/" 3999 | ] 4000 | }, 4001 | "notification-url": "https://packagist.org/downloads/", 4002 | "license": [ 4003 | "MIT" 4004 | ], 4005 | "authors": [ 4006 | { 4007 | "name": "Fabien Potencier", 4008 | "email": "fabien@symfony.com" 4009 | }, 4010 | { 4011 | "name": "Symfony Community", 4012 | "homepage": "https://symfony.com/contributors" 4013 | } 4014 | ], 4015 | "description": "Executes commands in sub-processes", 4016 | "homepage": "https://symfony.com", 4017 | "support": { 4018 | "source": "https://github.com/symfony/process/tree/v7.2.5" 4019 | }, 4020 | "funding": [ 4021 | { 4022 | "url": "https://symfony.com/sponsor", 4023 | "type": "custom" 4024 | }, 4025 | { 4026 | "url": "https://github.com/fabpot", 4027 | "type": "github" 4028 | }, 4029 | { 4030 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 4031 | "type": "tidelift" 4032 | } 4033 | ], 4034 | "time": "2025-03-13T12:21:46+00:00" 4035 | }, 4036 | { 4037 | "name": "symfony/service-contracts", 4038 | "version": "v3.5.1", 4039 | "source": { 4040 | "type": "git", 4041 | "url": "https://github.com/symfony/service-contracts.git", 4042 | "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0" 4043 | }, 4044 | "dist": { 4045 | "type": "zip", 4046 | "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0", 4047 | "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0", 4048 | "shasum": "" 4049 | }, 4050 | "require": { 4051 | "php": ">=8.1", 4052 | "psr/container": "^1.1|^2.0", 4053 | "symfony/deprecation-contracts": "^2.5|^3" 4054 | }, 4055 | "conflict": { 4056 | "ext-psr": "<1.1|>=2" 4057 | }, 4058 | "type": "library", 4059 | "extra": { 4060 | "thanks": { 4061 | "url": "https://github.com/symfony/contracts", 4062 | "name": "symfony/contracts" 4063 | }, 4064 | "branch-alias": { 4065 | "dev-main": "3.5-dev" 4066 | } 4067 | }, 4068 | "autoload": { 4069 | "psr-4": { 4070 | "Symfony\\Contracts\\Service\\": "" 4071 | }, 4072 | "exclude-from-classmap": [ 4073 | "/Test/" 4074 | ] 4075 | }, 4076 | "notification-url": "https://packagist.org/downloads/", 4077 | "license": [ 4078 | "MIT" 4079 | ], 4080 | "authors": [ 4081 | { 4082 | "name": "Nicolas Grekas", 4083 | "email": "p@tchwork.com" 4084 | }, 4085 | { 4086 | "name": "Symfony Community", 4087 | "homepage": "https://symfony.com/contributors" 4088 | } 4089 | ], 4090 | "description": "Generic abstractions related to writing services", 4091 | "homepage": "https://symfony.com", 4092 | "keywords": [ 4093 | "abstractions", 4094 | "contracts", 4095 | "decoupling", 4096 | "interfaces", 4097 | "interoperability", 4098 | "standards" 4099 | ], 4100 | "support": { 4101 | "source": "https://github.com/symfony/service-contracts/tree/v3.5.1" 4102 | }, 4103 | "funding": [ 4104 | { 4105 | "url": "https://symfony.com/sponsor", 4106 | "type": "custom" 4107 | }, 4108 | { 4109 | "url": "https://github.com/fabpot", 4110 | "type": "github" 4111 | }, 4112 | { 4113 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 4114 | "type": "tidelift" 4115 | } 4116 | ], 4117 | "time": "2024-09-25T14:20:29+00:00" 4118 | }, 4119 | { 4120 | "name": "symfony/stopwatch", 4121 | "version": "v7.2.4", 4122 | "source": { 4123 | "type": "git", 4124 | "url": "https://github.com/symfony/stopwatch.git", 4125 | "reference": "5a49289e2b308214c8b9c2fda4ea454d8b8ad7cd" 4126 | }, 4127 | "dist": { 4128 | "type": "zip", 4129 | "url": "https://api.github.com/repos/symfony/stopwatch/zipball/5a49289e2b308214c8b9c2fda4ea454d8b8ad7cd", 4130 | "reference": "5a49289e2b308214c8b9c2fda4ea454d8b8ad7cd", 4131 | "shasum": "" 4132 | }, 4133 | "require": { 4134 | "php": ">=8.2", 4135 | "symfony/service-contracts": "^2.5|^3" 4136 | }, 4137 | "type": "library", 4138 | "autoload": { 4139 | "psr-4": { 4140 | "Symfony\\Component\\Stopwatch\\": "" 4141 | }, 4142 | "exclude-from-classmap": [ 4143 | "/Tests/" 4144 | ] 4145 | }, 4146 | "notification-url": "https://packagist.org/downloads/", 4147 | "license": [ 4148 | "MIT" 4149 | ], 4150 | "authors": [ 4151 | { 4152 | "name": "Fabien Potencier", 4153 | "email": "fabien@symfony.com" 4154 | }, 4155 | { 4156 | "name": "Symfony Community", 4157 | "homepage": "https://symfony.com/contributors" 4158 | } 4159 | ], 4160 | "description": "Provides a way to profile code", 4161 | "homepage": "https://symfony.com", 4162 | "support": { 4163 | "source": "https://github.com/symfony/stopwatch/tree/v7.2.4" 4164 | }, 4165 | "funding": [ 4166 | { 4167 | "url": "https://symfony.com/sponsor", 4168 | "type": "custom" 4169 | }, 4170 | { 4171 | "url": "https://github.com/fabpot", 4172 | "type": "github" 4173 | }, 4174 | { 4175 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 4176 | "type": "tidelift" 4177 | } 4178 | ], 4179 | "time": "2025-02-24T10:49:57+00:00" 4180 | }, 4181 | { 4182 | "name": "symfony/string", 4183 | "version": "v7.2.0", 4184 | "source": { 4185 | "type": "git", 4186 | "url": "https://github.com/symfony/string.git", 4187 | "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82" 4188 | }, 4189 | "dist": { 4190 | "type": "zip", 4191 | "url": "https://api.github.com/repos/symfony/string/zipball/446e0d146f991dde3e73f45f2c97a9faad773c82", 4192 | "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82", 4193 | "shasum": "" 4194 | }, 4195 | "require": { 4196 | "php": ">=8.2", 4197 | "symfony/polyfill-ctype": "~1.8", 4198 | "symfony/polyfill-intl-grapheme": "~1.0", 4199 | "symfony/polyfill-intl-normalizer": "~1.0", 4200 | "symfony/polyfill-mbstring": "~1.0" 4201 | }, 4202 | "conflict": { 4203 | "symfony/translation-contracts": "<2.5" 4204 | }, 4205 | "require-dev": { 4206 | "symfony/emoji": "^7.1", 4207 | "symfony/error-handler": "^6.4|^7.0", 4208 | "symfony/http-client": "^6.4|^7.0", 4209 | "symfony/intl": "^6.4|^7.0", 4210 | "symfony/translation-contracts": "^2.5|^3.0", 4211 | "symfony/var-exporter": "^6.4|^7.0" 4212 | }, 4213 | "type": "library", 4214 | "autoload": { 4215 | "files": [ 4216 | "Resources/functions.php" 4217 | ], 4218 | "psr-4": { 4219 | "Symfony\\Component\\String\\": "" 4220 | }, 4221 | "exclude-from-classmap": [ 4222 | "/Tests/" 4223 | ] 4224 | }, 4225 | "notification-url": "https://packagist.org/downloads/", 4226 | "license": [ 4227 | "MIT" 4228 | ], 4229 | "authors": [ 4230 | { 4231 | "name": "Nicolas Grekas", 4232 | "email": "p@tchwork.com" 4233 | }, 4234 | { 4235 | "name": "Symfony Community", 4236 | "homepage": "https://symfony.com/contributors" 4237 | } 4238 | ], 4239 | "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", 4240 | "homepage": "https://symfony.com", 4241 | "keywords": [ 4242 | "grapheme", 4243 | "i18n", 4244 | "string", 4245 | "unicode", 4246 | "utf-8", 4247 | "utf8" 4248 | ], 4249 | "support": { 4250 | "source": "https://github.com/symfony/string/tree/v7.2.0" 4251 | }, 4252 | "funding": [ 4253 | { 4254 | "url": "https://symfony.com/sponsor", 4255 | "type": "custom" 4256 | }, 4257 | { 4258 | "url": "https://github.com/fabpot", 4259 | "type": "github" 4260 | }, 4261 | { 4262 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 4263 | "type": "tidelift" 4264 | } 4265 | ], 4266 | "time": "2024-11-13T13:31:26+00:00" 4267 | }, 4268 | { 4269 | "name": "theseer/tokenizer", 4270 | "version": "1.2.3", 4271 | "source": { 4272 | "type": "git", 4273 | "url": "https://github.com/theseer/tokenizer.git", 4274 | "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" 4275 | }, 4276 | "dist": { 4277 | "type": "zip", 4278 | "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", 4279 | "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", 4280 | "shasum": "" 4281 | }, 4282 | "require": { 4283 | "ext-dom": "*", 4284 | "ext-tokenizer": "*", 4285 | "ext-xmlwriter": "*", 4286 | "php": "^7.2 || ^8.0" 4287 | }, 4288 | "type": "library", 4289 | "autoload": { 4290 | "classmap": [ 4291 | "src/" 4292 | ] 4293 | }, 4294 | "notification-url": "https://packagist.org/downloads/", 4295 | "license": [ 4296 | "BSD-3-Clause" 4297 | ], 4298 | "authors": [ 4299 | { 4300 | "name": "Arne Blankerts", 4301 | "email": "arne@blankerts.de", 4302 | "role": "Developer" 4303 | } 4304 | ], 4305 | "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", 4306 | "support": { 4307 | "issues": "https://github.com/theseer/tokenizer/issues", 4308 | "source": "https://github.com/theseer/tokenizer/tree/1.2.3" 4309 | }, 4310 | "funding": [ 4311 | { 4312 | "url": "https://github.com/theseer", 4313 | "type": "github" 4314 | } 4315 | ], 4316 | "time": "2024-03-03T12:36:25+00:00" 4317 | } 4318 | ], 4319 | "aliases": [], 4320 | "minimum-stability": "stable", 4321 | "stability-flags": [], 4322 | "prefer-stable": false, 4323 | "prefer-lowest": false, 4324 | "platform": { 4325 | "php": ">=8.2", 4326 | "ext-json": "*" 4327 | }, 4328 | "platform-dev": [], 4329 | "plugin-api-version": "2.6.0" 4330 | } 4331 | --------------------------------------------------------------------------------