├── .github └── workflows │ └── ci.yaml ├── .gitignore ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── composer.json ├── composer.lock ├── phpstan.neon ├── src ├── Entity │ ├── KeyInterface.php │ ├── VerificationResult.php │ └── VerificationResultInterface.php ├── Exception │ ├── InvalidUrlException.php │ ├── SignatureNotFoundException.php │ └── UriSignerException.php ├── Resolver │ ├── DefaultParameterNameResolver.php │ └── ParameterNameResolverInterface.php └── Service │ ├── UriSignerService.php │ └── UriSignerServiceInterface.php └── test └── UriSignerServiceTest.php /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | name: Run Unit Tests 2 | 3 | on: 4 | # Trigger the workflow on push to any branch 5 | push: 6 | branches: 7 | - '*' # Runs on every branch 8 | # Trigger the workflow on pull requests to any branch 9 | pull_request: 10 | branches: 11 | - '*' 12 | 13 | jobs: 14 | test: 15 | runs-on: ubuntu-latest 16 | 17 | strategy: 18 | matrix: 19 | php-version: ['8.3'] # Define the PHP versions you want to test against 20 | 21 | steps: 22 | # Checkout the code from the repository 23 | - name: Checkout code 24 | uses: actions/checkout@v3 25 | 26 | # Set up PHP with required version 27 | - name: Setup PHP ${{ matrix.php-version }} 28 | uses: shivammathur/setup-php@v2 29 | with: 30 | php-version: ${{ matrix.php-version }} 31 | extensions: mbstring, intl, dom # Add required PHP extensions 32 | tools: composer # Ensure composer is available 33 | 34 | # Install dependencies via composer 35 | - name: Install dependencies 36 | run: composer install --prefer-dist --no-progress --no-suggest 37 | 38 | # Run PHPStan for static analysis 39 | - name: Run PHPStan 40 | run: ./vendor/bin/phpstan analyse -c phpstan.neon src/ test/ --level 9 --memory-limit=2G 41 | continue-on-error: false # Fail if PHPStan finds issues 42 | 43 | # Run the tests 44 | - name: Run tests with PHPUnit 45 | run: ./vendor/bin/phpunit test 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### Composer ### 2 | composer.phar 3 | /vendor/ 4 | 5 | /trash/* 6 | 7 | # Commit your application's lock file https://getcomposer.org/doc/01-basic-usage.md#commit-your-composer-lock-file-to-version-control 8 | # You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file 9 | # composer.lock 10 | 11 | ### Linux ### 12 | *~ 13 | 14 | # temporary files which can be created if a process still has a handle open of a deleted file 15 | .fuse_hidden* 16 | 17 | # KDE directory preferences 18 | .directory 19 | 20 | # Linux trash folder which might appear on any partition or disk 21 | .Trash-* 22 | 23 | # .nfs files are created when an open file is removed but is still being accessed 24 | .nfs* 25 | 26 | ### macOS ### 27 | # General 28 | .DS_Store 29 | .AppleDouble 30 | .LSOverride 31 | 32 | # Thumbnails 33 | ._* 34 | 35 | # Files that might appear in the root of a volume 36 | .DocumentRevisions-V100 37 | .fseventsd 38 | .Spotlight-V100 39 | .TemporaryItems 40 | .Trashes 41 | .VolumeIcon.icns 42 | .com.apple.timemachine.donotpresent 43 | 44 | # Directories potentially created on remote AFP share 45 | .AppleDB 46 | .AppleDesktop 47 | Network Trash Folder 48 | Temporary Items 49 | .apdisk 50 | 51 | ### Node ### 52 | # Logs 53 | logs 54 | *.log 55 | npm-debug.log* 56 | yarn-debug.log* 57 | yarn-error.log* 58 | lerna-debug.log* 59 | 60 | # Diagnostic reports (https://nodejs.org/api/report.html) 61 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 62 | 63 | # Runtime data 64 | pids 65 | *.pid 66 | *.seed 67 | *.pid.lock 68 | 69 | # Directory for instrumented libs generated by jscoverage/JSCover 70 | lib-cov 71 | 72 | # Coverage directory used by tools like istanbul 73 | coverage 74 | *.lcov 75 | 76 | # nyc test coverage 77 | .nyc_output 78 | 79 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 80 | .grunt 81 | 82 | # Bower dependency directory (https://bower.io/) 83 | bower_components 84 | 85 | # node-waf configuration 86 | .lock-wscript 87 | 88 | # Compiled binary addons (https://nodejs.org/api/addons.html) 89 | build/Release 90 | 91 | # Dependency directories 92 | node_modules/ 93 | jspm_packages/ 94 | 95 | # TypeScript v1 declaration files 96 | typings/ 97 | 98 | # TypeScript cache 99 | *.tsbuildinfo 100 | 101 | # Optional npm cache directory 102 | .npm 103 | 104 | # Optional eslint cache 105 | .eslintcache 106 | 107 | # Optional REPL history 108 | .node_repl_history 109 | 110 | # Output of 'npm pack' 111 | *.tgz 112 | 113 | # Yarn Integrity file 114 | .yarn-integrity 115 | 116 | # dotenv environment variables file 117 | .env 118 | .env.test 119 | 120 | # parcel-bundler cache (https://parceljs.org/) 121 | .cache 122 | 123 | # next.js build output 124 | .next 125 | 126 | # nuxt.js build output 127 | .nuxt 128 | 129 | # vuepress build output 130 | .vuepress/dist 131 | 132 | # Serverless directories 133 | .serverless/ 134 | 135 | # FuseBox cache 136 | .fusebox/ 137 | 138 | # DynamoDB Local files 139 | .dynamodb/ 140 | 141 | ### PhpStorm ### 142 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 143 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 144 | 145 | # User-specific stuff 146 | .idea/**/workspace.xml 147 | .idea/**/tasks.xml 148 | .idea/**/usage.statistics.xml 149 | .idea/**/dictionaries 150 | .idea/**/shelf 151 | 152 | # Generated files 153 | .idea/**/contentModel.xml 154 | 155 | # Sensitive or high-churn files 156 | .idea/**/dataSources/ 157 | .idea/**/dataSources.ids 158 | .idea/**/dataSources.local.xml 159 | .idea/**/sqlDataSources.xml 160 | .idea/**/dynamic.xml 161 | .idea/**/uiDesigner.xml 162 | .idea/**/dbnavigator.xml 163 | 164 | # Gradle 165 | .idea/**/gradle.xml 166 | .idea/**/libraries 167 | 168 | .idea 169 | 170 | # Gradle and Maven with auto-import 171 | # When using Gradle or Maven with auto-import, you should exclude module files, 172 | # since they will be recreated, and may cause churn. Uncomment if using 173 | # auto-import. 174 | # .idea/modules.xml 175 | # .idea/*.iml 176 | # .idea/modules 177 | # *.iml 178 | # *.ipr 179 | 180 | # CMake 181 | cmake-build-*/ 182 | 183 | # Mongo Explorer plugin 184 | .idea/**/mongoSettings.xml 185 | 186 | # File-based project format 187 | *.iws 188 | 189 | # IntelliJ 190 | out/ 191 | 192 | # mpeltonen/sbt-idea plugin 193 | .idea_modules/ 194 | 195 | # JIRA plugin 196 | atlassian-ide-plugin.xml 197 | 198 | # Cursive Clojure plugin 199 | .idea/replstate.xml 200 | 201 | # Crashlytics plugin (for Android Studio and IntelliJ) 202 | com_crashlytics_export_strings.xml 203 | crashlytics.properties 204 | crashlytics-build.properties 205 | fabric.properties 206 | 207 | # Editor-based Rest Client 208 | .idea/httpRequests 209 | 210 | # Android studio 3.1+ serialized cache file 211 | .idea/caches/build_file_checksums.ser 212 | 213 | ### PhpStorm Patch ### 214 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 215 | 216 | 217 | # modules.xml 218 | # .idea/misc.xml 219 | # *.ipr 220 | 221 | # Sonarlint plugin 222 | .idea/**/sonarlint/ 223 | 224 | # SonarQube Plugin 225 | .idea/**/sonarIssues.xml 226 | 227 | # Markdown Navigator plugin 228 | .idea/**/markdown-navigator.xml 229 | .idea/**/markdown-navigator/ 230 | 231 | ### Vagrant ### 232 | # General 233 | .vagrant/ 234 | 235 | # Log files (if you are creating logs in debug mode, uncomment this) 236 | # *.log 237 | 238 | ### Vagrant Patch ### 239 | *.box 240 | 241 | ### Windows ### 242 | # Windows thumbnail cache files 243 | Thumbs.db 244 | Thumbs.db:encryptable 245 | ehthumbs.db 246 | ehthumbs_vista.db 247 | 248 | # Dump file 249 | *.stackdump 250 | 251 | # Folder config file 252 | [Dd]esktop.ini 253 | 254 | # Recycle Bin used on file shares 255 | $RECYCLE.BIN/ 256 | 257 | # Windows Installer files 258 | *.cab 259 | *.msi 260 | *.msix 261 | *.msm 262 | *.msp 263 | 264 | # Windows shortcuts 265 | *.lnk 266 | 267 | # End of https://www.gitignore.io/api/node,linux,macos,vagrant,windows,composer,phpstorm 268 | 269 | *.bundle.js 270 | config/sys_config/* 271 | config/sys_config 272 | config/config.php 273 | data/* 274 | !data/.gitkeep 275 | !data/image 276 | !data/image/.gitkeep 277 | !data/image/* 278 | .instance.sqlite 279 | 280 | lib/scss/dist/*.css 281 | test/config/*.sqlite 282 | test/result/ 283 | /.phpunit.result.cache 284 | /.scannerwork/ 285 | smtp.php 286 | /lib/private/Core/System/RateLimit/tmp.json 287 | 288 | .ignored 289 | /test/cache/cache.json/test-results 290 | /test/cache/test-results 291 | /test/code-coverage/ 292 | /test/config/instance.db 293 | /config/docker/web/apache/cert.pem 294 | /config/docker/web/apache/cert-key.pem 295 | /lib/config/cors/allowed_origins.bak 296 | /test/.phpunit.cache/test-results 297 | /test/.phpunit.result.cache 298 | /http/ 299 | /test/benchmark.json 300 | /tmpl/ 301 | test.php 302 | /test/.phpunit.cache/ 303 | /.mysql_history 304 | /.bash_history 305 | /data/image/* 306 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## [1.0.1] - 2024-12-27 4 | **Version 1.0.1 – Bug Fix** 5 | 6 | **Key Features:** 7 | 8 | - **Updated composer.json description (PSR-15 to PSR-7) 9 | 10 | ## [1.0.0] - 2024-09-09 11 | **Version 1.0.0 – Initial Release** 12 | 13 | **Key Features:** 14 | 15 | - **URI Signing:** Securely sign URIs to guarantee their integrity. 16 | - **Signature Validation:** Validate signed URIs to confirm their authenticity. 17 | - **Customizable Expiration:** Set expiration times for signed URIs, ensuring they are only valid for a specific duration. 18 | - **HMAC-Based Security:** Uses industry-standard HMAC algorithms to sign and verify URIs. 19 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Thank you for considering contributing to this project! Here's how you can help: 4 | 5 | ## How to contribute 6 | 1. Fork the repository. 7 | 2. Create a feature branch (`git checkout -b feature-branch`). 8 | 3. Make your changes. 9 | 4. Ensure all tests pass. 10 | 5. Submit a pull request. 11 | 12 | ## Coding Standards 13 | - Use PSR-12 for PHP code. 14 | - Write descriptive commit messages. 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright © 2024 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # URL Signer for Vanilla PHP 2 | 3 | A URL signer implementation in **PHP** that generates secure, signed URLs with an expiration date. This package allows you to sign full URLs or just query parameters, adding a layer of security for accessing resources or sharing sensitive information. 4 | 5 | ![Build Status](https://github.com/Ucar-Solutions/uri-signer/workflows/Run%20Unit%20Tests/badge.svg) 6 | ![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg) 7 | 8 | 9 | ## Features 10 | 11 | - Sign a given URI 12 | - Include an expiration date as part of the signature 13 | - Ensure URL integrity and prevent unauthorized modifications 14 | - Easy integration with **Laminas** or other PHP-based frameworks 15 | 16 | ## Installation 17 | 18 | Install the package via Composer: 19 | 20 | ```bash 21 | composer require ucarsolutions/uri-signer 22 | ``` 23 | 24 | ## Usage 25 | 26 | ### Sign URL with Expiration Date 27 | 28 | You can sign the uri with: 29 | 30 | ```php 31 | sign( 48 | new \Laminas\Diactoros\Uri("https://example.com"), 49 | $key 50 | ); 51 | dump((string)$uri); // https://example.com/?__us_signature=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL3VjYXItc29sdXRpb25zLmRlL3VyaS1zaWduZXIiLCJleHAiOjE3MjU5MDYzMDQsInN1YiI6IlNpZ25lZCBVUkwiLCJ1cmwiOiJodHRwczovL2V4YW1wbGUug29tIiwidWlkIjoiNzM3YTgwNzAtZGU5MS00MTQ3LWohYmMtZTY1OWZiOGZmNWZyIn0.CH7E-fHYhtfGHUljB85dIWL-ZYGr8wRMVef0gY_SRLE 52 | ``` 53 | Example Verifying with `$uri` above: 54 | 55 | ```php 56 | verify($uri,$key); 58 | dump($result->isVerified()); 59 | ``` 60 | 61 | ## Expiration 62 | The expiration date is added to the signature and is included in the signed data to ensure the URL becomes invalid after the expiration time. 63 | 64 | If no expiration date is provided, a default of 3 minutes from the current time is used. 65 | 66 | ## Configuration 67 | You can configure the expiration time and the secret key for signing URLs. 68 | 69 | ## Tests 70 | Run the tests with PHPUnit: 71 | 72 | ```bash 73 | vendor/bin/phpunit 74 | ``` 75 | ## Contributing 76 | Contributions are welcome! Please submit a pull request or open an issue for any suggestions or bug reports. 77 | 78 | Contribution Guidelines: 79 | 1. Fork the repository. 80 | 2. Create a new branch for your feature or bug fix. 81 | 3. Write tests for your changes. 82 | 4. Make sure all tests pass. 83 | 5. Submit a pull request. 84 | 85 | ## License 86 | This project is licensed under the MIT License. See the LICENSE file for details. 87 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ucarsolutions/uri-signer", 3 | "description": "A minimal package for securely signing PSR-7 URIs in PHP applications.", 4 | "type": "library", 5 | "license": "MIT", 6 | "autoload": { 7 | "psr-4": { 8 | "UcarSolutions\\UriSigner\\": "src/" 9 | } 10 | }, 11 | "autoload-dev": { 12 | "psr-4": { 13 | "Test\\UcarSolutions\\UriSigner\\": "test" 14 | } 15 | }, 16 | "authors": [ 17 | { 18 | "name": "Doğan Uçar", 19 | "email": "dogan@dogan-ucar.de" 20 | } 21 | ], 22 | "minimum-stability": "stable", 23 | "require": { 24 | "firebase/php-jwt": "^6.10", 25 | "ramsey/uuid": "^4.7", 26 | "doganoo/di-services": "^0.0.50", 27 | "psr/log": "^3.0" 28 | }, 29 | "require-dev": { 30 | "symfony/var-dumper": "^7.1", 31 | "laminas/laminas-diactoros": "^3.3", 32 | "phpunit/phpunit": "^11.3", 33 | "phpstan/phpstan": "^1.12" 34 | }, 35 | "scripts": { 36 | "phpstan": "./vendor/bin/phpstan analyse -c phpstan.neon src/ test/ --level 9 --memory-limit=2G", 37 | "test": [ 38 | "Composer\\Config::disableProcessTimeout", 39 | "./vendor/bin/phpunit test -d memory_limit=-1" 40 | ] 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /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": "2fa556931a35d49a94dbb74e09479880", 8 | "packages": [ 9 | { 10 | "name": "brick/math", 11 | "version": "0.12.1", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/brick/math.git", 15 | "reference": "f510c0a40911935b77b86859eb5223d58d660df1" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/brick/math/zipball/f510c0a40911935b77b86859eb5223d58d660df1", 20 | "reference": "f510c0a40911935b77b86859eb5223d58d660df1", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "php": "^8.1" 25 | }, 26 | "require-dev": { 27 | "php-coveralls/php-coveralls": "^2.2", 28 | "phpunit/phpunit": "^10.1", 29 | "vimeo/psalm": "5.16.0" 30 | }, 31 | "type": "library", 32 | "autoload": { 33 | "psr-4": { 34 | "Brick\\Math\\": "src/" 35 | } 36 | }, 37 | "notification-url": "https://packagist.org/downloads/", 38 | "license": [ 39 | "MIT" 40 | ], 41 | "description": "Arbitrary-precision arithmetic library", 42 | "keywords": [ 43 | "Arbitrary-precision", 44 | "BigInteger", 45 | "BigRational", 46 | "arithmetic", 47 | "bigdecimal", 48 | "bignum", 49 | "bignumber", 50 | "brick", 51 | "decimal", 52 | "integer", 53 | "math", 54 | "mathematics", 55 | "rational" 56 | ], 57 | "support": { 58 | "issues": "https://github.com/brick/math/issues", 59 | "source": "https://github.com/brick/math/tree/0.12.1" 60 | }, 61 | "funding": [ 62 | { 63 | "url": "https://github.com/BenMorel", 64 | "type": "github" 65 | } 66 | ], 67 | "time": "2023-11-29T23:19:16+00:00" 68 | }, 69 | { 70 | "name": "doganoo/di-services", 71 | "version": "0.0.50", 72 | "source": { 73 | "type": "git", 74 | "url": "https://github.com/doganoo/DIServices.git", 75 | "reference": "b1ccfae67aedcab4b1ac949caf062e2b5fa447c3" 76 | }, 77 | "dist": { 78 | "type": "zip", 79 | "url": "https://api.github.com/repos/doganoo/DIServices/zipball/b1ccfae67aedcab4b1ac949caf062e2b5fa447c3", 80 | "reference": "b1ccfae67aedcab4b1ac949caf062e2b5fa447c3", 81 | "shasum": "" 82 | }, 83 | "require": { 84 | "doganoo/php-algorithms": "^2.0", 85 | "ext-calendar": "*", 86 | "ext-fileinfo": "*", 87 | "ext-json": "*", 88 | "ext-openssl": "*", 89 | "ext-pdo": "*", 90 | "ezyang/htmlpurifier": "^4.13", 91 | "laminas/laminas-crypt": "^3.9", 92 | "php": ">=7.4 || >=8.0", 93 | "psr/http-message": "^1.0", 94 | "ramsey/uuid": "^4.7" 95 | }, 96 | "require-dev": { 97 | "ergebnis/composer-normalize": "^2.15", 98 | "filp/whoops": "^2.7", 99 | "mockery/mockery": "^1.4", 100 | "phpcompatibility/php-compatibility": "^9.3", 101 | "phpstan/phpstan": "^1.0", 102 | "phpunit/phpunit": "^9.3", 103 | "roave/security-advisories": "dev-latest", 104 | "squizlabs/php_codesniffer": "^3.5", 105 | "symfony/var-dumper": "^5.4" 106 | }, 107 | "type": "library", 108 | "autoload": { 109 | "psr-4": { 110 | "doganoo\\DI\\": "src/public", 111 | "doganoo\\DIP\\": "src/private", 112 | "doganoo\\DI\\Test\\": "test/" 113 | } 114 | }, 115 | "notification-url": "https://packagist.org/downloads/", 116 | "license": [ 117 | "MIT" 118 | ], 119 | "authors": [ 120 | { 121 | "name": "Dogan Ucar", 122 | "email": "dogan@dogan-ucar.de" 123 | } 124 | ], 125 | "description": "service classes in the sense of Dependency Injection", 126 | "support": { 127 | "issues": "https://github.com/doganoo/DIServices/issues", 128 | "source": "https://github.com/doganoo/DIServices/tree/0.0.50" 129 | }, 130 | "time": "2024-09-09T15:18:36+00:00" 131 | }, 132 | { 133 | "name": "doganoo/php-algorithms", 134 | "version": "2.1.1", 135 | "source": { 136 | "type": "git", 137 | "url": "https://github.com/doganoo/PHPAlgorithms.git", 138 | "reference": "1b6c3ac3448289b103d92bc75c2c7c4974eceae8" 139 | }, 140 | "dist": { 141 | "type": "zip", 142 | "url": "https://api.github.com/repos/doganoo/PHPAlgorithms/zipball/1b6c3ac3448289b103d92bc75c2c7c4974eceae8", 143 | "reference": "1b6c3ac3448289b103d92bc75c2c7c4974eceae8", 144 | "shasum": "" 145 | }, 146 | "require": { 147 | "doganoo/php-util": "0.5.*", 148 | "ext-json": "*", 149 | "php": ">=8.0" 150 | }, 151 | "require-dev": { 152 | "ergebnis/composer-normalize": "^2.9", 153 | "phpcompatibility/php-compatibility": "^9.3", 154 | "phpstan/phpstan": "^0.12.54", 155 | "phpunit/phpunit": "^8.0", 156 | "roave/security-advisories": "dev-latest", 157 | "squizlabs/php_codesniffer": "^3.5" 158 | }, 159 | "type": "library", 160 | "autoload": { 161 | "psr-4": { 162 | "doganoo\\PHPAlgorithms\\": "src/", 163 | "doganoo\\PHPAlgorithmsTest\\": "tests/" 164 | } 165 | }, 166 | "notification-url": "https://packagist.org/downloads/", 167 | "license": [ 168 | "MIT" 169 | ], 170 | "authors": [ 171 | { 172 | "name": "Dogan Ucar", 173 | "email": "dogan@dogan-ucar.de", 174 | "homepage": "https://www.dogan-ucar.de" 175 | } 176 | ], 177 | "description": "A collection of common algorithms implemented in PHP. The collection is based on \"Cracking the Coding Interview\" by Gayle Laakmann McDowell", 178 | "homepage": "https://www.dogan-ucar.de/phpalgorithms-2/", 179 | "keywords": [ 180 | "algorithms", 181 | "data structures" 182 | ], 183 | "support": { 184 | "issues": "https://github.com/doganoo/PHPAlgorithms/issues", 185 | "source": "https://github.com/doganoo/PHPAlgorithms/tree/2.1.1" 186 | }, 187 | "funding": [ 188 | { 189 | "url": "https://www.paypal.me/doganoo", 190 | "type": "custom" 191 | } 192 | ], 193 | "time": "2023-05-28T10:12:23+00:00" 194 | }, 195 | { 196 | "name": "doganoo/php-util", 197 | "version": "0.5.0", 198 | "source": { 199 | "type": "git", 200 | "url": "https://github.com/doganoo/PHPUtil.git", 201 | "reference": "f8ce213c221e1a35b45479a4336027c8cd20c6cc" 202 | }, 203 | "dist": { 204 | "type": "zip", 205 | "url": "https://api.github.com/repos/doganoo/PHPUtil/zipball/f8ce213c221e1a35b45479a4336027c8cd20c6cc", 206 | "reference": "f8ce213c221e1a35b45479a4336027c8cd20c6cc", 207 | "shasum": "" 208 | }, 209 | "require": { 210 | "doganoo/php-algorithms": "*", 211 | "ext-fileinfo": "*", 212 | "ext-iconv": "*", 213 | "ext-json": "*", 214 | "ext-mbstring": "*", 215 | "ext-pdo": "*" 216 | }, 217 | "require-dev": { 218 | "phpunit/phpunit": "^9" 219 | }, 220 | "type": "library", 221 | "autoload": { 222 | "psr-4": { 223 | "doganoo\\PHPUtil\\": "src/", 224 | "doganoo\\PHPUtil\\Test\\": "test/" 225 | } 226 | }, 227 | "notification-url": "https://packagist.org/downloads/", 228 | "license": [ 229 | "MIT" 230 | ], 231 | "authors": [ 232 | { 233 | "name": "Dogan Ucar", 234 | "email": "dogan@dogan-ucar.de" 235 | } 236 | ], 237 | "description": "A collection of common classes and methods that I am usually working with", 238 | "support": { 239 | "issues": "https://github.com/doganoo/PHPUtil/issues", 240 | "source": "https://github.com/doganoo/PHPUtil/tree/0.5.0" 241 | }, 242 | "time": "2021-09-11T07:04:55+00:00" 243 | }, 244 | { 245 | "name": "ezyang/htmlpurifier", 246 | "version": "v4.18.0", 247 | "source": { 248 | "type": "git", 249 | "url": "https://github.com/ezyang/htmlpurifier.git", 250 | "reference": "cb56001e54359df7ae76dc522d08845dc741621b" 251 | }, 252 | "dist": { 253 | "type": "zip", 254 | "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/cb56001e54359df7ae76dc522d08845dc741621b", 255 | "reference": "cb56001e54359df7ae76dc522d08845dc741621b", 256 | "shasum": "" 257 | }, 258 | "require": { 259 | "php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" 260 | }, 261 | "require-dev": { 262 | "cerdic/css-tidy": "^1.7 || ^2.0", 263 | "simpletest/simpletest": "dev-master" 264 | }, 265 | "suggest": { 266 | "cerdic/css-tidy": "If you want to use the filter 'Filter.ExtractStyleBlocks'.", 267 | "ext-bcmath": "Used for unit conversion and imagecrash protection", 268 | "ext-iconv": "Converts text to and from non-UTF-8 encodings", 269 | "ext-tidy": "Used for pretty-printing HTML" 270 | }, 271 | "type": "library", 272 | "autoload": { 273 | "files": [ 274 | "library/HTMLPurifier.composer.php" 275 | ], 276 | "psr-0": { 277 | "HTMLPurifier": "library/" 278 | }, 279 | "exclude-from-classmap": [ 280 | "/library/HTMLPurifier/Language/" 281 | ] 282 | }, 283 | "notification-url": "https://packagist.org/downloads/", 284 | "license": [ 285 | "LGPL-2.1-or-later" 286 | ], 287 | "authors": [ 288 | { 289 | "name": "Edward Z. Yang", 290 | "email": "admin@htmlpurifier.org", 291 | "homepage": "http://ezyang.com" 292 | } 293 | ], 294 | "description": "Standards compliant HTML filter written in PHP", 295 | "homepage": "http://htmlpurifier.org/", 296 | "keywords": [ 297 | "html" 298 | ], 299 | "support": { 300 | "issues": "https://github.com/ezyang/htmlpurifier/issues", 301 | "source": "https://github.com/ezyang/htmlpurifier/tree/v4.18.0" 302 | }, 303 | "time": "2024-11-01T03:51:45+00:00" 304 | }, 305 | { 306 | "name": "firebase/php-jwt", 307 | "version": "v6.10.2", 308 | "source": { 309 | "type": "git", 310 | "url": "https://github.com/firebase/php-jwt.git", 311 | "reference": "30c19ed0f3264cb660ea496895cfb6ef7ee3653b" 312 | }, 313 | "dist": { 314 | "type": "zip", 315 | "url": "https://api.github.com/repos/firebase/php-jwt/zipball/30c19ed0f3264cb660ea496895cfb6ef7ee3653b", 316 | "reference": "30c19ed0f3264cb660ea496895cfb6ef7ee3653b", 317 | "shasum": "" 318 | }, 319 | "require": { 320 | "php": "^8.0" 321 | }, 322 | "require-dev": { 323 | "guzzlehttp/guzzle": "^7.4", 324 | "phpspec/prophecy-phpunit": "^2.0", 325 | "phpunit/phpunit": "^9.5", 326 | "psr/cache": "^2.0||^3.0", 327 | "psr/http-client": "^1.0", 328 | "psr/http-factory": "^1.0" 329 | }, 330 | "suggest": { 331 | "ext-sodium": "Support EdDSA (Ed25519) signatures", 332 | "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present" 333 | }, 334 | "type": "library", 335 | "autoload": { 336 | "psr-4": { 337 | "Firebase\\JWT\\": "src" 338 | } 339 | }, 340 | "notification-url": "https://packagist.org/downloads/", 341 | "license": [ 342 | "BSD-3-Clause" 343 | ], 344 | "authors": [ 345 | { 346 | "name": "Neuman Vong", 347 | "email": "neuman+pear@twilio.com", 348 | "role": "Developer" 349 | }, 350 | { 351 | "name": "Anant Narayanan", 352 | "email": "anant@php.net", 353 | "role": "Developer" 354 | } 355 | ], 356 | "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.", 357 | "homepage": "https://github.com/firebase/php-jwt", 358 | "keywords": [ 359 | "jwt", 360 | "php" 361 | ], 362 | "support": { 363 | "issues": "https://github.com/firebase/php-jwt/issues", 364 | "source": "https://github.com/firebase/php-jwt/tree/v6.10.2" 365 | }, 366 | "time": "2024-11-24T11:22:49+00:00" 367 | }, 368 | { 369 | "name": "laminas/laminas-crypt", 370 | "version": "3.12.0", 371 | "source": { 372 | "type": "git", 373 | "url": "https://github.com/laminas/laminas-crypt.git", 374 | "reference": "ceab630494fc7a0d82ec39ad63947ef889a21be7" 375 | }, 376 | "dist": { 377 | "type": "zip", 378 | "url": "https://api.github.com/repos/laminas/laminas-crypt/zipball/ceab630494fc7a0d82ec39ad63947ef889a21be7", 379 | "reference": "ceab630494fc7a0d82ec39ad63947ef889a21be7", 380 | "shasum": "" 381 | }, 382 | "require": { 383 | "ext-mbstring": "*", 384 | "laminas/laminas-math": "^3.4", 385 | "laminas/laminas-stdlib": "^3.8", 386 | "php": "~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0", 387 | "psr/container": "^1.1" 388 | }, 389 | "conflict": { 390 | "zendframework/zend-crypt": "*" 391 | }, 392 | "require-dev": { 393 | "laminas/laminas-coding-standard": "~2.4.0", 394 | "phpunit/phpunit": "^9.5.25" 395 | }, 396 | "suggest": { 397 | "ext-openssl": "Required for most features of Laminas\\Crypt" 398 | }, 399 | "type": "library", 400 | "autoload": { 401 | "psr-4": { 402 | "Laminas\\Crypt\\": "src/" 403 | } 404 | }, 405 | "notification-url": "https://packagist.org/downloads/", 406 | "license": [ 407 | "BSD-3-Clause" 408 | ], 409 | "description": "Strong cryptography tools and password hashing", 410 | "homepage": "https://laminas.dev", 411 | "keywords": [ 412 | "crypt", 413 | "laminas" 414 | ], 415 | "support": { 416 | "chat": "https://laminas.dev/chat", 417 | "docs": "https://docs.laminas.dev/laminas-crypt/", 418 | "forum": "https://discourse.laminas.dev", 419 | "issues": "https://github.com/laminas/laminas-crypt/issues", 420 | "rss": "https://github.com/laminas/laminas-crypt/releases.atom", 421 | "source": "https://github.com/laminas/laminas-crypt" 422 | }, 423 | "funding": [ 424 | { 425 | "url": "https://funding.communitybridge.org/projects/laminas-project", 426 | "type": "community_bridge" 427 | } 428 | ], 429 | "abandoned": true, 430 | "time": "2024-07-15T09:11:42+00:00" 431 | }, 432 | { 433 | "name": "laminas/laminas-math", 434 | "version": "3.8.1", 435 | "source": { 436 | "type": "git", 437 | "url": "https://github.com/laminas/laminas-math.git", 438 | "reference": "a9e54f68accf5f8a3e66dd01fc6b32180e520018" 439 | }, 440 | "dist": { 441 | "type": "zip", 442 | "url": "https://api.github.com/repos/laminas/laminas-math/zipball/a9e54f68accf5f8a3e66dd01fc6b32180e520018", 443 | "reference": "a9e54f68accf5f8a3e66dd01fc6b32180e520018", 444 | "shasum": "" 445 | }, 446 | "require": { 447 | "ext-mbstring": "*", 448 | "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" 449 | }, 450 | "conflict": { 451 | "zendframework/zend-math": "*" 452 | }, 453 | "require-dev": { 454 | "laminas/laminas-coding-standard": "~2.4.0", 455 | "phpunit/phpunit": "~9.5.25" 456 | }, 457 | "suggest": { 458 | "ext-bcmath": "If using the bcmath functionality", 459 | "ext-gmp": "If using the gmp functionality" 460 | }, 461 | "type": "library", 462 | "extra": { 463 | "branch-alias": { 464 | "dev-master": "3.2.x-dev", 465 | "dev-develop": "3.3.x-dev" 466 | } 467 | }, 468 | "autoload": { 469 | "psr-4": { 470 | "Laminas\\Math\\": "src/" 471 | } 472 | }, 473 | "notification-url": "https://packagist.org/downloads/", 474 | "license": [ 475 | "BSD-3-Clause" 476 | ], 477 | "description": "Create cryptographically secure pseudo-random numbers, and manage big integers", 478 | "homepage": "https://laminas.dev", 479 | "keywords": [ 480 | "laminas", 481 | "math" 482 | ], 483 | "support": { 484 | "chat": "https://laminas.dev/chat", 485 | "docs": "https://docs.laminas.dev/laminas-math/", 486 | "forum": "https://discourse.laminas.dev", 487 | "issues": "https://github.com/laminas/laminas-math/issues", 488 | "rss": "https://github.com/laminas/laminas-math/releases.atom", 489 | "source": "https://github.com/laminas/laminas-math" 490 | }, 491 | "funding": [ 492 | { 493 | "url": "https://funding.communitybridge.org/projects/laminas-project", 494 | "type": "community_bridge" 495 | } 496 | ], 497 | "abandoned": true, 498 | "time": "2024-12-05T13:49:56+00:00" 499 | }, 500 | { 501 | "name": "laminas/laminas-stdlib", 502 | "version": "3.20.0", 503 | "source": { 504 | "type": "git", 505 | "url": "https://github.com/laminas/laminas-stdlib.git", 506 | "reference": "8974a1213be42c3e2f70b2c27b17f910291ab2f4" 507 | }, 508 | "dist": { 509 | "type": "zip", 510 | "url": "https://api.github.com/repos/laminas/laminas-stdlib/zipball/8974a1213be42c3e2f70b2c27b17f910291ab2f4", 511 | "reference": "8974a1213be42c3e2f70b2c27b17f910291ab2f4", 512 | "shasum": "" 513 | }, 514 | "require": { 515 | "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" 516 | }, 517 | "conflict": { 518 | "zendframework/zend-stdlib": "*" 519 | }, 520 | "require-dev": { 521 | "laminas/laminas-coding-standard": "^3.0", 522 | "phpbench/phpbench": "^1.3.1", 523 | "phpunit/phpunit": "^10.5.38", 524 | "psalm/plugin-phpunit": "^0.19.0", 525 | "vimeo/psalm": "^5.26.1" 526 | }, 527 | "type": "library", 528 | "autoload": { 529 | "psr-4": { 530 | "Laminas\\Stdlib\\": "src/" 531 | } 532 | }, 533 | "notification-url": "https://packagist.org/downloads/", 534 | "license": [ 535 | "BSD-3-Clause" 536 | ], 537 | "description": "SPL extensions, array utilities, error handlers, and more", 538 | "homepage": "https://laminas.dev", 539 | "keywords": [ 540 | "laminas", 541 | "stdlib" 542 | ], 543 | "support": { 544 | "chat": "https://laminas.dev/chat", 545 | "docs": "https://docs.laminas.dev/laminas-stdlib/", 546 | "forum": "https://discourse.laminas.dev", 547 | "issues": "https://github.com/laminas/laminas-stdlib/issues", 548 | "rss": "https://github.com/laminas/laminas-stdlib/releases.atom", 549 | "source": "https://github.com/laminas/laminas-stdlib" 550 | }, 551 | "funding": [ 552 | { 553 | "url": "https://funding.communitybridge.org/projects/laminas-project", 554 | "type": "community_bridge" 555 | } 556 | ], 557 | "time": "2024-10-29T13:46:07+00:00" 558 | }, 559 | { 560 | "name": "psr/container", 561 | "version": "1.1.2", 562 | "source": { 563 | "type": "git", 564 | "url": "https://github.com/php-fig/container.git", 565 | "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" 566 | }, 567 | "dist": { 568 | "type": "zip", 569 | "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", 570 | "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", 571 | "shasum": "" 572 | }, 573 | "require": { 574 | "php": ">=7.4.0" 575 | }, 576 | "type": "library", 577 | "autoload": { 578 | "psr-4": { 579 | "Psr\\Container\\": "src/" 580 | } 581 | }, 582 | "notification-url": "https://packagist.org/downloads/", 583 | "license": [ 584 | "MIT" 585 | ], 586 | "authors": [ 587 | { 588 | "name": "PHP-FIG", 589 | "homepage": "https://www.php-fig.org/" 590 | } 591 | ], 592 | "description": "Common Container Interface (PHP FIG PSR-11)", 593 | "homepage": "https://github.com/php-fig/container", 594 | "keywords": [ 595 | "PSR-11", 596 | "container", 597 | "container-interface", 598 | "container-interop", 599 | "psr" 600 | ], 601 | "support": { 602 | "issues": "https://github.com/php-fig/container/issues", 603 | "source": "https://github.com/php-fig/container/tree/1.1.2" 604 | }, 605 | "time": "2021-11-05T16:50:12+00:00" 606 | }, 607 | { 608 | "name": "psr/http-message", 609 | "version": "1.1", 610 | "source": { 611 | "type": "git", 612 | "url": "https://github.com/php-fig/http-message.git", 613 | "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba" 614 | }, 615 | "dist": { 616 | "type": "zip", 617 | "url": "https://api.github.com/repos/php-fig/http-message/zipball/cb6ce4845ce34a8ad9e68117c10ee90a29919eba", 618 | "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba", 619 | "shasum": "" 620 | }, 621 | "require": { 622 | "php": "^7.2 || ^8.0" 623 | }, 624 | "type": "library", 625 | "extra": { 626 | "branch-alias": { 627 | "dev-master": "1.1.x-dev" 628 | } 629 | }, 630 | "autoload": { 631 | "psr-4": { 632 | "Psr\\Http\\Message\\": "src/" 633 | } 634 | }, 635 | "notification-url": "https://packagist.org/downloads/", 636 | "license": [ 637 | "MIT" 638 | ], 639 | "authors": [ 640 | { 641 | "name": "PHP-FIG", 642 | "homepage": "http://www.php-fig.org/" 643 | } 644 | ], 645 | "description": "Common interface for HTTP messages", 646 | "homepage": "https://github.com/php-fig/http-message", 647 | "keywords": [ 648 | "http", 649 | "http-message", 650 | "psr", 651 | "psr-7", 652 | "request", 653 | "response" 654 | ], 655 | "support": { 656 | "source": "https://github.com/php-fig/http-message/tree/1.1" 657 | }, 658 | "time": "2023-04-04T09:50:52+00:00" 659 | }, 660 | { 661 | "name": "psr/log", 662 | "version": "3.0.2", 663 | "source": { 664 | "type": "git", 665 | "url": "https://github.com/php-fig/log.git", 666 | "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" 667 | }, 668 | "dist": { 669 | "type": "zip", 670 | "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", 671 | "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", 672 | "shasum": "" 673 | }, 674 | "require": { 675 | "php": ">=8.0.0" 676 | }, 677 | "type": "library", 678 | "extra": { 679 | "branch-alias": { 680 | "dev-master": "3.x-dev" 681 | } 682 | }, 683 | "autoload": { 684 | "psr-4": { 685 | "Psr\\Log\\": "src" 686 | } 687 | }, 688 | "notification-url": "https://packagist.org/downloads/", 689 | "license": [ 690 | "MIT" 691 | ], 692 | "authors": [ 693 | { 694 | "name": "PHP-FIG", 695 | "homepage": "https://www.php-fig.org/" 696 | } 697 | ], 698 | "description": "Common interface for logging libraries", 699 | "homepage": "https://github.com/php-fig/log", 700 | "keywords": [ 701 | "log", 702 | "psr", 703 | "psr-3" 704 | ], 705 | "support": { 706 | "source": "https://github.com/php-fig/log/tree/3.0.2" 707 | }, 708 | "time": "2024-09-11T13:17:53+00:00" 709 | }, 710 | { 711 | "name": "ramsey/collection", 712 | "version": "2.0.0", 713 | "source": { 714 | "type": "git", 715 | "url": "https://github.com/ramsey/collection.git", 716 | "reference": "a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5" 717 | }, 718 | "dist": { 719 | "type": "zip", 720 | "url": "https://api.github.com/repos/ramsey/collection/zipball/a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5", 721 | "reference": "a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5", 722 | "shasum": "" 723 | }, 724 | "require": { 725 | "php": "^8.1" 726 | }, 727 | "require-dev": { 728 | "captainhook/plugin-composer": "^5.3", 729 | "ergebnis/composer-normalize": "^2.28.3", 730 | "fakerphp/faker": "^1.21", 731 | "hamcrest/hamcrest-php": "^2.0", 732 | "jangregor/phpstan-prophecy": "^1.0", 733 | "mockery/mockery": "^1.5", 734 | "php-parallel-lint/php-console-highlighter": "^1.0", 735 | "php-parallel-lint/php-parallel-lint": "^1.3", 736 | "phpcsstandards/phpcsutils": "^1.0.0-rc1", 737 | "phpspec/prophecy-phpunit": "^2.0", 738 | "phpstan/extension-installer": "^1.2", 739 | "phpstan/phpstan": "^1.9", 740 | "phpstan/phpstan-mockery": "^1.1", 741 | "phpstan/phpstan-phpunit": "^1.3", 742 | "phpunit/phpunit": "^9.5", 743 | "psalm/plugin-mockery": "^1.1", 744 | "psalm/plugin-phpunit": "^0.18.4", 745 | "ramsey/coding-standard": "^2.0.3", 746 | "ramsey/conventional-commits": "^1.3", 747 | "vimeo/psalm": "^5.4" 748 | }, 749 | "type": "library", 750 | "extra": { 751 | "captainhook": { 752 | "force-install": true 753 | }, 754 | "ramsey/conventional-commits": { 755 | "configFile": "conventional-commits.json" 756 | } 757 | }, 758 | "autoload": { 759 | "psr-4": { 760 | "Ramsey\\Collection\\": "src/" 761 | } 762 | }, 763 | "notification-url": "https://packagist.org/downloads/", 764 | "license": [ 765 | "MIT" 766 | ], 767 | "authors": [ 768 | { 769 | "name": "Ben Ramsey", 770 | "email": "ben@benramsey.com", 771 | "homepage": "https://benramsey.com" 772 | } 773 | ], 774 | "description": "A PHP library for representing and manipulating collections.", 775 | "keywords": [ 776 | "array", 777 | "collection", 778 | "hash", 779 | "map", 780 | "queue", 781 | "set" 782 | ], 783 | "support": { 784 | "issues": "https://github.com/ramsey/collection/issues", 785 | "source": "https://github.com/ramsey/collection/tree/2.0.0" 786 | }, 787 | "funding": [ 788 | { 789 | "url": "https://github.com/ramsey", 790 | "type": "github" 791 | }, 792 | { 793 | "url": "https://tidelift.com/funding/github/packagist/ramsey/collection", 794 | "type": "tidelift" 795 | } 796 | ], 797 | "time": "2022-12-31T21:50:55+00:00" 798 | }, 799 | { 800 | "name": "ramsey/uuid", 801 | "version": "4.7.6", 802 | "source": { 803 | "type": "git", 804 | "url": "https://github.com/ramsey/uuid.git", 805 | "reference": "91039bc1faa45ba123c4328958e620d382ec7088" 806 | }, 807 | "dist": { 808 | "type": "zip", 809 | "url": "https://api.github.com/repos/ramsey/uuid/zipball/91039bc1faa45ba123c4328958e620d382ec7088", 810 | "reference": "91039bc1faa45ba123c4328958e620d382ec7088", 811 | "shasum": "" 812 | }, 813 | "require": { 814 | "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12", 815 | "ext-json": "*", 816 | "php": "^8.0", 817 | "ramsey/collection": "^1.2 || ^2.0" 818 | }, 819 | "replace": { 820 | "rhumsaa/uuid": "self.version" 821 | }, 822 | "require-dev": { 823 | "captainhook/captainhook": "^5.10", 824 | "captainhook/plugin-composer": "^5.3", 825 | "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", 826 | "doctrine/annotations": "^1.8", 827 | "ergebnis/composer-normalize": "^2.15", 828 | "mockery/mockery": "^1.3", 829 | "paragonie/random-lib": "^2", 830 | "php-mock/php-mock": "^2.2", 831 | "php-mock/php-mock-mockery": "^1.3", 832 | "php-parallel-lint/php-parallel-lint": "^1.1", 833 | "phpbench/phpbench": "^1.0", 834 | "phpstan/extension-installer": "^1.1", 835 | "phpstan/phpstan": "^1.8", 836 | "phpstan/phpstan-mockery": "^1.1", 837 | "phpstan/phpstan-phpunit": "^1.1", 838 | "phpunit/phpunit": "^8.5 || ^9", 839 | "ramsey/composer-repl": "^1.4", 840 | "slevomat/coding-standard": "^8.4", 841 | "squizlabs/php_codesniffer": "^3.5", 842 | "vimeo/psalm": "^4.9" 843 | }, 844 | "suggest": { 845 | "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.", 846 | "ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.", 847 | "ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.", 848 | "paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter", 849 | "ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type." 850 | }, 851 | "type": "library", 852 | "extra": { 853 | "captainhook": { 854 | "force-install": true 855 | } 856 | }, 857 | "autoload": { 858 | "files": [ 859 | "src/functions.php" 860 | ], 861 | "psr-4": { 862 | "Ramsey\\Uuid\\": "src/" 863 | } 864 | }, 865 | "notification-url": "https://packagist.org/downloads/", 866 | "license": [ 867 | "MIT" 868 | ], 869 | "description": "A PHP library for generating and working with universally unique identifiers (UUIDs).", 870 | "keywords": [ 871 | "guid", 872 | "identifier", 873 | "uuid" 874 | ], 875 | "support": { 876 | "issues": "https://github.com/ramsey/uuid/issues", 877 | "source": "https://github.com/ramsey/uuid/tree/4.7.6" 878 | }, 879 | "funding": [ 880 | { 881 | "url": "https://github.com/ramsey", 882 | "type": "github" 883 | }, 884 | { 885 | "url": "https://tidelift.com/funding/github/packagist/ramsey/uuid", 886 | "type": "tidelift" 887 | } 888 | ], 889 | "time": "2024-04-27T21:32:50+00:00" 890 | } 891 | ], 892 | "packages-dev": [ 893 | { 894 | "name": "laminas/laminas-diactoros", 895 | "version": "3.5.0", 896 | "source": { 897 | "type": "git", 898 | "url": "https://github.com/laminas/laminas-diactoros.git", 899 | "reference": "143a16306602ce56b8b092a7914fef03c37f9ed2" 900 | }, 901 | "dist": { 902 | "type": "zip", 903 | "url": "https://api.github.com/repos/laminas/laminas-diactoros/zipball/143a16306602ce56b8b092a7914fef03c37f9ed2", 904 | "reference": "143a16306602ce56b8b092a7914fef03c37f9ed2", 905 | "shasum": "" 906 | }, 907 | "require": { 908 | "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0", 909 | "psr/http-factory": "^1.1", 910 | "psr/http-message": "^1.1 || ^2.0" 911 | }, 912 | "conflict": { 913 | "amphp/amp": "<2.6.4" 914 | }, 915 | "provide": { 916 | "psr/http-factory-implementation": "^1.0", 917 | "psr/http-message-implementation": "^1.1 || ^2.0" 918 | }, 919 | "require-dev": { 920 | "ext-curl": "*", 921 | "ext-dom": "*", 922 | "ext-gd": "*", 923 | "ext-libxml": "*", 924 | "http-interop/http-factory-tests": "^2.2.0", 925 | "laminas/laminas-coding-standard": "~2.5.0", 926 | "php-http/psr7-integration-tests": "^1.4.0", 927 | "phpunit/phpunit": "^10.5.36", 928 | "psalm/plugin-phpunit": "^0.19.0", 929 | "vimeo/psalm": "^5.26.1" 930 | }, 931 | "type": "library", 932 | "extra": { 933 | "laminas": { 934 | "module": "Laminas\\Diactoros", 935 | "config-provider": "Laminas\\Diactoros\\ConfigProvider" 936 | } 937 | }, 938 | "autoload": { 939 | "files": [ 940 | "src/functions/create_uploaded_file.php", 941 | "src/functions/marshal_headers_from_sapi.php", 942 | "src/functions/marshal_method_from_sapi.php", 943 | "src/functions/marshal_protocol_version_from_sapi.php", 944 | "src/functions/normalize_server.php", 945 | "src/functions/normalize_uploaded_files.php", 946 | "src/functions/parse_cookie_header.php" 947 | ], 948 | "psr-4": { 949 | "Laminas\\Diactoros\\": "src/" 950 | } 951 | }, 952 | "notification-url": "https://packagist.org/downloads/", 953 | "license": [ 954 | "BSD-3-Clause" 955 | ], 956 | "description": "PSR HTTP Message implementations", 957 | "homepage": "https://laminas.dev", 958 | "keywords": [ 959 | "http", 960 | "laminas", 961 | "psr", 962 | "psr-17", 963 | "psr-7" 964 | ], 965 | "support": { 966 | "chat": "https://laminas.dev/chat", 967 | "docs": "https://docs.laminas.dev/laminas-diactoros/", 968 | "forum": "https://discourse.laminas.dev", 969 | "issues": "https://github.com/laminas/laminas-diactoros/issues", 970 | "rss": "https://github.com/laminas/laminas-diactoros/releases.atom", 971 | "source": "https://github.com/laminas/laminas-diactoros" 972 | }, 973 | "funding": [ 974 | { 975 | "url": "https://funding.communitybridge.org/projects/laminas-project", 976 | "type": "community_bridge" 977 | } 978 | ], 979 | "time": "2024-10-14T11:59:49+00:00" 980 | }, 981 | { 982 | "name": "myclabs/deep-copy", 983 | "version": "1.12.1", 984 | "source": { 985 | "type": "git", 986 | "url": "https://github.com/myclabs/DeepCopy.git", 987 | "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845" 988 | }, 989 | "dist": { 990 | "type": "zip", 991 | "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/123267b2c49fbf30d78a7b2d333f6be754b94845", 992 | "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845", 993 | "shasum": "" 994 | }, 995 | "require": { 996 | "php": "^7.1 || ^8.0" 997 | }, 998 | "conflict": { 999 | "doctrine/collections": "<1.6.8", 1000 | "doctrine/common": "<2.13.3 || >=3 <3.2.2" 1001 | }, 1002 | "require-dev": { 1003 | "doctrine/collections": "^1.6.8", 1004 | "doctrine/common": "^2.13.3 || ^3.2.2", 1005 | "phpspec/prophecy": "^1.10", 1006 | "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" 1007 | }, 1008 | "type": "library", 1009 | "autoload": { 1010 | "files": [ 1011 | "src/DeepCopy/deep_copy.php" 1012 | ], 1013 | "psr-4": { 1014 | "DeepCopy\\": "src/DeepCopy/" 1015 | } 1016 | }, 1017 | "notification-url": "https://packagist.org/downloads/", 1018 | "license": [ 1019 | "MIT" 1020 | ], 1021 | "description": "Create deep copies (clones) of your objects", 1022 | "keywords": [ 1023 | "clone", 1024 | "copy", 1025 | "duplicate", 1026 | "object", 1027 | "object graph" 1028 | ], 1029 | "support": { 1030 | "issues": "https://github.com/myclabs/DeepCopy/issues", 1031 | "source": "https://github.com/myclabs/DeepCopy/tree/1.12.1" 1032 | }, 1033 | "funding": [ 1034 | { 1035 | "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", 1036 | "type": "tidelift" 1037 | } 1038 | ], 1039 | "time": "2024-11-08T17:47:46+00:00" 1040 | }, 1041 | { 1042 | "name": "nikic/php-parser", 1043 | "version": "v5.3.1", 1044 | "source": { 1045 | "type": "git", 1046 | "url": "https://github.com/nikic/PHP-Parser.git", 1047 | "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b" 1048 | }, 1049 | "dist": { 1050 | "type": "zip", 1051 | "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/8eea230464783aa9671db8eea6f8c6ac5285794b", 1052 | "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b", 1053 | "shasum": "" 1054 | }, 1055 | "require": { 1056 | "ext-ctype": "*", 1057 | "ext-json": "*", 1058 | "ext-tokenizer": "*", 1059 | "php": ">=7.4" 1060 | }, 1061 | "require-dev": { 1062 | "ircmaxell/php-yacc": "^0.0.7", 1063 | "phpunit/phpunit": "^9.0" 1064 | }, 1065 | "bin": [ 1066 | "bin/php-parse" 1067 | ], 1068 | "type": "library", 1069 | "extra": { 1070 | "branch-alias": { 1071 | "dev-master": "5.0-dev" 1072 | } 1073 | }, 1074 | "autoload": { 1075 | "psr-4": { 1076 | "PhpParser\\": "lib/PhpParser" 1077 | } 1078 | }, 1079 | "notification-url": "https://packagist.org/downloads/", 1080 | "license": [ 1081 | "BSD-3-Clause" 1082 | ], 1083 | "authors": [ 1084 | { 1085 | "name": "Nikita Popov" 1086 | } 1087 | ], 1088 | "description": "A PHP parser written in PHP", 1089 | "keywords": [ 1090 | "parser", 1091 | "php" 1092 | ], 1093 | "support": { 1094 | "issues": "https://github.com/nikic/PHP-Parser/issues", 1095 | "source": "https://github.com/nikic/PHP-Parser/tree/v5.3.1" 1096 | }, 1097 | "time": "2024-10-08T18:51:32+00:00" 1098 | }, 1099 | { 1100 | "name": "phar-io/manifest", 1101 | "version": "2.0.4", 1102 | "source": { 1103 | "type": "git", 1104 | "url": "https://github.com/phar-io/manifest.git", 1105 | "reference": "54750ef60c58e43759730615a392c31c80e23176" 1106 | }, 1107 | "dist": { 1108 | "type": "zip", 1109 | "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", 1110 | "reference": "54750ef60c58e43759730615a392c31c80e23176", 1111 | "shasum": "" 1112 | }, 1113 | "require": { 1114 | "ext-dom": "*", 1115 | "ext-libxml": "*", 1116 | "ext-phar": "*", 1117 | "ext-xmlwriter": "*", 1118 | "phar-io/version": "^3.0.1", 1119 | "php": "^7.2 || ^8.0" 1120 | }, 1121 | "type": "library", 1122 | "extra": { 1123 | "branch-alias": { 1124 | "dev-master": "2.0.x-dev" 1125 | } 1126 | }, 1127 | "autoload": { 1128 | "classmap": [ 1129 | "src/" 1130 | ] 1131 | }, 1132 | "notification-url": "https://packagist.org/downloads/", 1133 | "license": [ 1134 | "BSD-3-Clause" 1135 | ], 1136 | "authors": [ 1137 | { 1138 | "name": "Arne Blankerts", 1139 | "email": "arne@blankerts.de", 1140 | "role": "Developer" 1141 | }, 1142 | { 1143 | "name": "Sebastian Heuer", 1144 | "email": "sebastian@phpeople.de", 1145 | "role": "Developer" 1146 | }, 1147 | { 1148 | "name": "Sebastian Bergmann", 1149 | "email": "sebastian@phpunit.de", 1150 | "role": "Developer" 1151 | } 1152 | ], 1153 | "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", 1154 | "support": { 1155 | "issues": "https://github.com/phar-io/manifest/issues", 1156 | "source": "https://github.com/phar-io/manifest/tree/2.0.4" 1157 | }, 1158 | "funding": [ 1159 | { 1160 | "url": "https://github.com/theseer", 1161 | "type": "github" 1162 | } 1163 | ], 1164 | "time": "2024-03-03T12:33:53+00:00" 1165 | }, 1166 | { 1167 | "name": "phar-io/version", 1168 | "version": "3.2.1", 1169 | "source": { 1170 | "type": "git", 1171 | "url": "https://github.com/phar-io/version.git", 1172 | "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" 1173 | }, 1174 | "dist": { 1175 | "type": "zip", 1176 | "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", 1177 | "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", 1178 | "shasum": "" 1179 | }, 1180 | "require": { 1181 | "php": "^7.2 || ^8.0" 1182 | }, 1183 | "type": "library", 1184 | "autoload": { 1185 | "classmap": [ 1186 | "src/" 1187 | ] 1188 | }, 1189 | "notification-url": "https://packagist.org/downloads/", 1190 | "license": [ 1191 | "BSD-3-Clause" 1192 | ], 1193 | "authors": [ 1194 | { 1195 | "name": "Arne Blankerts", 1196 | "email": "arne@blankerts.de", 1197 | "role": "Developer" 1198 | }, 1199 | { 1200 | "name": "Sebastian Heuer", 1201 | "email": "sebastian@phpeople.de", 1202 | "role": "Developer" 1203 | }, 1204 | { 1205 | "name": "Sebastian Bergmann", 1206 | "email": "sebastian@phpunit.de", 1207 | "role": "Developer" 1208 | } 1209 | ], 1210 | "description": "Library for handling version information and constraints", 1211 | "support": { 1212 | "issues": "https://github.com/phar-io/version/issues", 1213 | "source": "https://github.com/phar-io/version/tree/3.2.1" 1214 | }, 1215 | "time": "2022-02-21T01:04:05+00:00" 1216 | }, 1217 | { 1218 | "name": "phpstan/phpstan", 1219 | "version": "1.12.13", 1220 | "source": { 1221 | "type": "git", 1222 | "url": "https://github.com/phpstan/phpstan.git", 1223 | "reference": "9b469068840cfa031e1deaf2fa1886d00e20680f" 1224 | }, 1225 | "dist": { 1226 | "type": "zip", 1227 | "url": "https://api.github.com/repos/phpstan/phpstan/zipball/9b469068840cfa031e1deaf2fa1886d00e20680f", 1228 | "reference": "9b469068840cfa031e1deaf2fa1886d00e20680f", 1229 | "shasum": "" 1230 | }, 1231 | "require": { 1232 | "php": "^7.2|^8.0" 1233 | }, 1234 | "conflict": { 1235 | "phpstan/phpstan-shim": "*" 1236 | }, 1237 | "bin": [ 1238 | "phpstan", 1239 | "phpstan.phar" 1240 | ], 1241 | "type": "library", 1242 | "autoload": { 1243 | "files": [ 1244 | "bootstrap.php" 1245 | ] 1246 | }, 1247 | "notification-url": "https://packagist.org/downloads/", 1248 | "license": [ 1249 | "MIT" 1250 | ], 1251 | "description": "PHPStan - PHP Static Analysis Tool", 1252 | "keywords": [ 1253 | "dev", 1254 | "static analysis" 1255 | ], 1256 | "support": { 1257 | "docs": "https://phpstan.org/user-guide/getting-started", 1258 | "forum": "https://github.com/phpstan/phpstan/discussions", 1259 | "issues": "https://github.com/phpstan/phpstan/issues", 1260 | "security": "https://github.com/phpstan/phpstan/security/policy", 1261 | "source": "https://github.com/phpstan/phpstan-src" 1262 | }, 1263 | "funding": [ 1264 | { 1265 | "url": "https://github.com/ondrejmirtes", 1266 | "type": "github" 1267 | }, 1268 | { 1269 | "url": "https://github.com/phpstan", 1270 | "type": "github" 1271 | } 1272 | ], 1273 | "time": "2024-12-17T17:00:20+00:00" 1274 | }, 1275 | { 1276 | "name": "phpunit/php-code-coverage", 1277 | "version": "11.0.8", 1278 | "source": { 1279 | "type": "git", 1280 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 1281 | "reference": "418c59fd080954f8c4aa5631d9502ecda2387118" 1282 | }, 1283 | "dist": { 1284 | "type": "zip", 1285 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/418c59fd080954f8c4aa5631d9502ecda2387118", 1286 | "reference": "418c59fd080954f8c4aa5631d9502ecda2387118", 1287 | "shasum": "" 1288 | }, 1289 | "require": { 1290 | "ext-dom": "*", 1291 | "ext-libxml": "*", 1292 | "ext-xmlwriter": "*", 1293 | "nikic/php-parser": "^5.3.1", 1294 | "php": ">=8.2", 1295 | "phpunit/php-file-iterator": "^5.1.0", 1296 | "phpunit/php-text-template": "^4.0.1", 1297 | "sebastian/code-unit-reverse-lookup": "^4.0.1", 1298 | "sebastian/complexity": "^4.0.1", 1299 | "sebastian/environment": "^7.2.0", 1300 | "sebastian/lines-of-code": "^3.0.1", 1301 | "sebastian/version": "^5.0.2", 1302 | "theseer/tokenizer": "^1.2.3" 1303 | }, 1304 | "require-dev": { 1305 | "phpunit/phpunit": "^11.5.0" 1306 | }, 1307 | "suggest": { 1308 | "ext-pcov": "PHP extension that provides line coverage", 1309 | "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" 1310 | }, 1311 | "type": "library", 1312 | "extra": { 1313 | "branch-alias": { 1314 | "dev-main": "11.0.x-dev" 1315 | } 1316 | }, 1317 | "autoload": { 1318 | "classmap": [ 1319 | "src/" 1320 | ] 1321 | }, 1322 | "notification-url": "https://packagist.org/downloads/", 1323 | "license": [ 1324 | "BSD-3-Clause" 1325 | ], 1326 | "authors": [ 1327 | { 1328 | "name": "Sebastian Bergmann", 1329 | "email": "sebastian@phpunit.de", 1330 | "role": "lead" 1331 | } 1332 | ], 1333 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 1334 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 1335 | "keywords": [ 1336 | "coverage", 1337 | "testing", 1338 | "xunit" 1339 | ], 1340 | "support": { 1341 | "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", 1342 | "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", 1343 | "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.8" 1344 | }, 1345 | "funding": [ 1346 | { 1347 | "url": "https://github.com/sebastianbergmann", 1348 | "type": "github" 1349 | } 1350 | ], 1351 | "time": "2024-12-11T12:34:27+00:00" 1352 | }, 1353 | { 1354 | "name": "phpunit/php-file-iterator", 1355 | "version": "5.1.0", 1356 | "source": { 1357 | "type": "git", 1358 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 1359 | "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6" 1360 | }, 1361 | "dist": { 1362 | "type": "zip", 1363 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/118cfaaa8bc5aef3287bf315b6060b1174754af6", 1364 | "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6", 1365 | "shasum": "" 1366 | }, 1367 | "require": { 1368 | "php": ">=8.2" 1369 | }, 1370 | "require-dev": { 1371 | "phpunit/phpunit": "^11.0" 1372 | }, 1373 | "type": "library", 1374 | "extra": { 1375 | "branch-alias": { 1376 | "dev-main": "5.0-dev" 1377 | } 1378 | }, 1379 | "autoload": { 1380 | "classmap": [ 1381 | "src/" 1382 | ] 1383 | }, 1384 | "notification-url": "https://packagist.org/downloads/", 1385 | "license": [ 1386 | "BSD-3-Clause" 1387 | ], 1388 | "authors": [ 1389 | { 1390 | "name": "Sebastian Bergmann", 1391 | "email": "sebastian@phpunit.de", 1392 | "role": "lead" 1393 | } 1394 | ], 1395 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 1396 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 1397 | "keywords": [ 1398 | "filesystem", 1399 | "iterator" 1400 | ], 1401 | "support": { 1402 | "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", 1403 | "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", 1404 | "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/5.1.0" 1405 | }, 1406 | "funding": [ 1407 | { 1408 | "url": "https://github.com/sebastianbergmann", 1409 | "type": "github" 1410 | } 1411 | ], 1412 | "time": "2024-08-27T05:02:59+00:00" 1413 | }, 1414 | { 1415 | "name": "phpunit/php-invoker", 1416 | "version": "5.0.1", 1417 | "source": { 1418 | "type": "git", 1419 | "url": "https://github.com/sebastianbergmann/php-invoker.git", 1420 | "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2" 1421 | }, 1422 | "dist": { 1423 | "type": "zip", 1424 | "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/c1ca3814734c07492b3d4c5f794f4b0995333da2", 1425 | "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2", 1426 | "shasum": "" 1427 | }, 1428 | "require": { 1429 | "php": ">=8.2" 1430 | }, 1431 | "require-dev": { 1432 | "ext-pcntl": "*", 1433 | "phpunit/phpunit": "^11.0" 1434 | }, 1435 | "suggest": { 1436 | "ext-pcntl": "*" 1437 | }, 1438 | "type": "library", 1439 | "extra": { 1440 | "branch-alias": { 1441 | "dev-main": "5.0-dev" 1442 | } 1443 | }, 1444 | "autoload": { 1445 | "classmap": [ 1446 | "src/" 1447 | ] 1448 | }, 1449 | "notification-url": "https://packagist.org/downloads/", 1450 | "license": [ 1451 | "BSD-3-Clause" 1452 | ], 1453 | "authors": [ 1454 | { 1455 | "name": "Sebastian Bergmann", 1456 | "email": "sebastian@phpunit.de", 1457 | "role": "lead" 1458 | } 1459 | ], 1460 | "description": "Invoke callables with a timeout", 1461 | "homepage": "https://github.com/sebastianbergmann/php-invoker/", 1462 | "keywords": [ 1463 | "process" 1464 | ], 1465 | "support": { 1466 | "issues": "https://github.com/sebastianbergmann/php-invoker/issues", 1467 | "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", 1468 | "source": "https://github.com/sebastianbergmann/php-invoker/tree/5.0.1" 1469 | }, 1470 | "funding": [ 1471 | { 1472 | "url": "https://github.com/sebastianbergmann", 1473 | "type": "github" 1474 | } 1475 | ], 1476 | "time": "2024-07-03T05:07:44+00:00" 1477 | }, 1478 | { 1479 | "name": "phpunit/php-text-template", 1480 | "version": "4.0.1", 1481 | "source": { 1482 | "type": "git", 1483 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 1484 | "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964" 1485 | }, 1486 | "dist": { 1487 | "type": "zip", 1488 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/3e0404dc6b300e6bf56415467ebcb3fe4f33e964", 1489 | "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964", 1490 | "shasum": "" 1491 | }, 1492 | "require": { 1493 | "php": ">=8.2" 1494 | }, 1495 | "require-dev": { 1496 | "phpunit/phpunit": "^11.0" 1497 | }, 1498 | "type": "library", 1499 | "extra": { 1500 | "branch-alias": { 1501 | "dev-main": "4.0-dev" 1502 | } 1503 | }, 1504 | "autoload": { 1505 | "classmap": [ 1506 | "src/" 1507 | ] 1508 | }, 1509 | "notification-url": "https://packagist.org/downloads/", 1510 | "license": [ 1511 | "BSD-3-Clause" 1512 | ], 1513 | "authors": [ 1514 | { 1515 | "name": "Sebastian Bergmann", 1516 | "email": "sebastian@phpunit.de", 1517 | "role": "lead" 1518 | } 1519 | ], 1520 | "description": "Simple template engine.", 1521 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 1522 | "keywords": [ 1523 | "template" 1524 | ], 1525 | "support": { 1526 | "issues": "https://github.com/sebastianbergmann/php-text-template/issues", 1527 | "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", 1528 | "source": "https://github.com/sebastianbergmann/php-text-template/tree/4.0.1" 1529 | }, 1530 | "funding": [ 1531 | { 1532 | "url": "https://github.com/sebastianbergmann", 1533 | "type": "github" 1534 | } 1535 | ], 1536 | "time": "2024-07-03T05:08:43+00:00" 1537 | }, 1538 | { 1539 | "name": "phpunit/php-timer", 1540 | "version": "7.0.1", 1541 | "source": { 1542 | "type": "git", 1543 | "url": "https://github.com/sebastianbergmann/php-timer.git", 1544 | "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3" 1545 | }, 1546 | "dist": { 1547 | "type": "zip", 1548 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", 1549 | "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", 1550 | "shasum": "" 1551 | }, 1552 | "require": { 1553 | "php": ">=8.2" 1554 | }, 1555 | "require-dev": { 1556 | "phpunit/phpunit": "^11.0" 1557 | }, 1558 | "type": "library", 1559 | "extra": { 1560 | "branch-alias": { 1561 | "dev-main": "7.0-dev" 1562 | } 1563 | }, 1564 | "autoload": { 1565 | "classmap": [ 1566 | "src/" 1567 | ] 1568 | }, 1569 | "notification-url": "https://packagist.org/downloads/", 1570 | "license": [ 1571 | "BSD-3-Clause" 1572 | ], 1573 | "authors": [ 1574 | { 1575 | "name": "Sebastian Bergmann", 1576 | "email": "sebastian@phpunit.de", 1577 | "role": "lead" 1578 | } 1579 | ], 1580 | "description": "Utility class for timing", 1581 | "homepage": "https://github.com/sebastianbergmann/php-timer/", 1582 | "keywords": [ 1583 | "timer" 1584 | ], 1585 | "support": { 1586 | "issues": "https://github.com/sebastianbergmann/php-timer/issues", 1587 | "security": "https://github.com/sebastianbergmann/php-timer/security/policy", 1588 | "source": "https://github.com/sebastianbergmann/php-timer/tree/7.0.1" 1589 | }, 1590 | "funding": [ 1591 | { 1592 | "url": "https://github.com/sebastianbergmann", 1593 | "type": "github" 1594 | } 1595 | ], 1596 | "time": "2024-07-03T05:09:35+00:00" 1597 | }, 1598 | { 1599 | "name": "phpunit/phpunit", 1600 | "version": "11.5.2", 1601 | "source": { 1602 | "type": "git", 1603 | "url": "https://github.com/sebastianbergmann/phpunit.git", 1604 | "reference": "153d0531b9f7e883c5053160cad6dd5ac28140b3" 1605 | }, 1606 | "dist": { 1607 | "type": "zip", 1608 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/153d0531b9f7e883c5053160cad6dd5ac28140b3", 1609 | "reference": "153d0531b9f7e883c5053160cad6dd5ac28140b3", 1610 | "shasum": "" 1611 | }, 1612 | "require": { 1613 | "ext-dom": "*", 1614 | "ext-json": "*", 1615 | "ext-libxml": "*", 1616 | "ext-mbstring": "*", 1617 | "ext-xml": "*", 1618 | "ext-xmlwriter": "*", 1619 | "myclabs/deep-copy": "^1.12.1", 1620 | "phar-io/manifest": "^2.0.4", 1621 | "phar-io/version": "^3.2.1", 1622 | "php": ">=8.2", 1623 | "phpunit/php-code-coverage": "^11.0.8", 1624 | "phpunit/php-file-iterator": "^5.1.0", 1625 | "phpunit/php-invoker": "^5.0.1", 1626 | "phpunit/php-text-template": "^4.0.1", 1627 | "phpunit/php-timer": "^7.0.1", 1628 | "sebastian/cli-parser": "^3.0.2", 1629 | "sebastian/code-unit": "^3.0.2", 1630 | "sebastian/comparator": "^6.2.1", 1631 | "sebastian/diff": "^6.0.2", 1632 | "sebastian/environment": "^7.2.0", 1633 | "sebastian/exporter": "^6.3.0", 1634 | "sebastian/global-state": "^7.0.2", 1635 | "sebastian/object-enumerator": "^6.0.1", 1636 | "sebastian/type": "^5.1.0", 1637 | "sebastian/version": "^5.0.2", 1638 | "staabm/side-effects-detector": "^1.0.5" 1639 | }, 1640 | "suggest": { 1641 | "ext-soap": "To be able to generate mocks based on WSDL files" 1642 | }, 1643 | "bin": [ 1644 | "phpunit" 1645 | ], 1646 | "type": "library", 1647 | "extra": { 1648 | "branch-alias": { 1649 | "dev-main": "11.5-dev" 1650 | } 1651 | }, 1652 | "autoload": { 1653 | "files": [ 1654 | "src/Framework/Assert/Functions.php" 1655 | ], 1656 | "classmap": [ 1657 | "src/" 1658 | ] 1659 | }, 1660 | "notification-url": "https://packagist.org/downloads/", 1661 | "license": [ 1662 | "BSD-3-Clause" 1663 | ], 1664 | "authors": [ 1665 | { 1666 | "name": "Sebastian Bergmann", 1667 | "email": "sebastian@phpunit.de", 1668 | "role": "lead" 1669 | } 1670 | ], 1671 | "description": "The PHP Unit Testing framework.", 1672 | "homepage": "https://phpunit.de/", 1673 | "keywords": [ 1674 | "phpunit", 1675 | "testing", 1676 | "xunit" 1677 | ], 1678 | "support": { 1679 | "issues": "https://github.com/sebastianbergmann/phpunit/issues", 1680 | "security": "https://github.com/sebastianbergmann/phpunit/security/policy", 1681 | "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.2" 1682 | }, 1683 | "funding": [ 1684 | { 1685 | "url": "https://phpunit.de/sponsors.html", 1686 | "type": "custom" 1687 | }, 1688 | { 1689 | "url": "https://github.com/sebastianbergmann", 1690 | "type": "github" 1691 | }, 1692 | { 1693 | "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", 1694 | "type": "tidelift" 1695 | } 1696 | ], 1697 | "time": "2024-12-21T05:51:08+00:00" 1698 | }, 1699 | { 1700 | "name": "psr/http-factory", 1701 | "version": "1.1.0", 1702 | "source": { 1703 | "type": "git", 1704 | "url": "https://github.com/php-fig/http-factory.git", 1705 | "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" 1706 | }, 1707 | "dist": { 1708 | "type": "zip", 1709 | "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", 1710 | "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", 1711 | "shasum": "" 1712 | }, 1713 | "require": { 1714 | "php": ">=7.1", 1715 | "psr/http-message": "^1.0 || ^2.0" 1716 | }, 1717 | "type": "library", 1718 | "extra": { 1719 | "branch-alias": { 1720 | "dev-master": "1.0.x-dev" 1721 | } 1722 | }, 1723 | "autoload": { 1724 | "psr-4": { 1725 | "Psr\\Http\\Message\\": "src/" 1726 | } 1727 | }, 1728 | "notification-url": "https://packagist.org/downloads/", 1729 | "license": [ 1730 | "MIT" 1731 | ], 1732 | "authors": [ 1733 | { 1734 | "name": "PHP-FIG", 1735 | "homepage": "https://www.php-fig.org/" 1736 | } 1737 | ], 1738 | "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", 1739 | "keywords": [ 1740 | "factory", 1741 | "http", 1742 | "message", 1743 | "psr", 1744 | "psr-17", 1745 | "psr-7", 1746 | "request", 1747 | "response" 1748 | ], 1749 | "support": { 1750 | "source": "https://github.com/php-fig/http-factory" 1751 | }, 1752 | "time": "2024-04-15T12:06:14+00:00" 1753 | }, 1754 | { 1755 | "name": "sebastian/cli-parser", 1756 | "version": "3.0.2", 1757 | "source": { 1758 | "type": "git", 1759 | "url": "https://github.com/sebastianbergmann/cli-parser.git", 1760 | "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180" 1761 | }, 1762 | "dist": { 1763 | "type": "zip", 1764 | "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/15c5dd40dc4f38794d383bb95465193f5e0ae180", 1765 | "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180", 1766 | "shasum": "" 1767 | }, 1768 | "require": { 1769 | "php": ">=8.2" 1770 | }, 1771 | "require-dev": { 1772 | "phpunit/phpunit": "^11.0" 1773 | }, 1774 | "type": "library", 1775 | "extra": { 1776 | "branch-alias": { 1777 | "dev-main": "3.0-dev" 1778 | } 1779 | }, 1780 | "autoload": { 1781 | "classmap": [ 1782 | "src/" 1783 | ] 1784 | }, 1785 | "notification-url": "https://packagist.org/downloads/", 1786 | "license": [ 1787 | "BSD-3-Clause" 1788 | ], 1789 | "authors": [ 1790 | { 1791 | "name": "Sebastian Bergmann", 1792 | "email": "sebastian@phpunit.de", 1793 | "role": "lead" 1794 | } 1795 | ], 1796 | "description": "Library for parsing CLI options", 1797 | "homepage": "https://github.com/sebastianbergmann/cli-parser", 1798 | "support": { 1799 | "issues": "https://github.com/sebastianbergmann/cli-parser/issues", 1800 | "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", 1801 | "source": "https://github.com/sebastianbergmann/cli-parser/tree/3.0.2" 1802 | }, 1803 | "funding": [ 1804 | { 1805 | "url": "https://github.com/sebastianbergmann", 1806 | "type": "github" 1807 | } 1808 | ], 1809 | "time": "2024-07-03T04:41:36+00:00" 1810 | }, 1811 | { 1812 | "name": "sebastian/code-unit", 1813 | "version": "3.0.2", 1814 | "source": { 1815 | "type": "git", 1816 | "url": "https://github.com/sebastianbergmann/code-unit.git", 1817 | "reference": "ee88b0cdbe74cf8dd3b54940ff17643c0d6543ca" 1818 | }, 1819 | "dist": { 1820 | "type": "zip", 1821 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/ee88b0cdbe74cf8dd3b54940ff17643c0d6543ca", 1822 | "reference": "ee88b0cdbe74cf8dd3b54940ff17643c0d6543ca", 1823 | "shasum": "" 1824 | }, 1825 | "require": { 1826 | "php": ">=8.2" 1827 | }, 1828 | "require-dev": { 1829 | "phpunit/phpunit": "^11.5" 1830 | }, 1831 | "type": "library", 1832 | "extra": { 1833 | "branch-alias": { 1834 | "dev-main": "3.0-dev" 1835 | } 1836 | }, 1837 | "autoload": { 1838 | "classmap": [ 1839 | "src/" 1840 | ] 1841 | }, 1842 | "notification-url": "https://packagist.org/downloads/", 1843 | "license": [ 1844 | "BSD-3-Clause" 1845 | ], 1846 | "authors": [ 1847 | { 1848 | "name": "Sebastian Bergmann", 1849 | "email": "sebastian@phpunit.de", 1850 | "role": "lead" 1851 | } 1852 | ], 1853 | "description": "Collection of value objects that represent the PHP code units", 1854 | "homepage": "https://github.com/sebastianbergmann/code-unit", 1855 | "support": { 1856 | "issues": "https://github.com/sebastianbergmann/code-unit/issues", 1857 | "security": "https://github.com/sebastianbergmann/code-unit/security/policy", 1858 | "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.2" 1859 | }, 1860 | "funding": [ 1861 | { 1862 | "url": "https://github.com/sebastianbergmann", 1863 | "type": "github" 1864 | } 1865 | ], 1866 | "time": "2024-12-12T09:59:06+00:00" 1867 | }, 1868 | { 1869 | "name": "sebastian/code-unit-reverse-lookup", 1870 | "version": "4.0.1", 1871 | "source": { 1872 | "type": "git", 1873 | "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", 1874 | "reference": "183a9b2632194febd219bb9246eee421dad8d45e" 1875 | }, 1876 | "dist": { 1877 | "type": "zip", 1878 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/183a9b2632194febd219bb9246eee421dad8d45e", 1879 | "reference": "183a9b2632194febd219bb9246eee421dad8d45e", 1880 | "shasum": "" 1881 | }, 1882 | "require": { 1883 | "php": ">=8.2" 1884 | }, 1885 | "require-dev": { 1886 | "phpunit/phpunit": "^11.0" 1887 | }, 1888 | "type": "library", 1889 | "extra": { 1890 | "branch-alias": { 1891 | "dev-main": "4.0-dev" 1892 | } 1893 | }, 1894 | "autoload": { 1895 | "classmap": [ 1896 | "src/" 1897 | ] 1898 | }, 1899 | "notification-url": "https://packagist.org/downloads/", 1900 | "license": [ 1901 | "BSD-3-Clause" 1902 | ], 1903 | "authors": [ 1904 | { 1905 | "name": "Sebastian Bergmann", 1906 | "email": "sebastian@phpunit.de" 1907 | } 1908 | ], 1909 | "description": "Looks up which function or method a line of code belongs to", 1910 | "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", 1911 | "support": { 1912 | "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", 1913 | "security": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/security/policy", 1914 | "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/4.0.1" 1915 | }, 1916 | "funding": [ 1917 | { 1918 | "url": "https://github.com/sebastianbergmann", 1919 | "type": "github" 1920 | } 1921 | ], 1922 | "time": "2024-07-03T04:45:54+00:00" 1923 | }, 1924 | { 1925 | "name": "sebastian/comparator", 1926 | "version": "6.2.1", 1927 | "source": { 1928 | "type": "git", 1929 | "url": "https://github.com/sebastianbergmann/comparator.git", 1930 | "reference": "43d129d6a0f81c78bee378b46688293eb7ea3739" 1931 | }, 1932 | "dist": { 1933 | "type": "zip", 1934 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/43d129d6a0f81c78bee378b46688293eb7ea3739", 1935 | "reference": "43d129d6a0f81c78bee378b46688293eb7ea3739", 1936 | "shasum": "" 1937 | }, 1938 | "require": { 1939 | "ext-dom": "*", 1940 | "ext-mbstring": "*", 1941 | "php": ">=8.2", 1942 | "sebastian/diff": "^6.0", 1943 | "sebastian/exporter": "^6.0" 1944 | }, 1945 | "require-dev": { 1946 | "phpunit/phpunit": "^11.4" 1947 | }, 1948 | "type": "library", 1949 | "extra": { 1950 | "branch-alias": { 1951 | "dev-main": "6.2-dev" 1952 | } 1953 | }, 1954 | "autoload": { 1955 | "classmap": [ 1956 | "src/" 1957 | ] 1958 | }, 1959 | "notification-url": "https://packagist.org/downloads/", 1960 | "license": [ 1961 | "BSD-3-Clause" 1962 | ], 1963 | "authors": [ 1964 | { 1965 | "name": "Sebastian Bergmann", 1966 | "email": "sebastian@phpunit.de" 1967 | }, 1968 | { 1969 | "name": "Jeff Welch", 1970 | "email": "whatthejeff@gmail.com" 1971 | }, 1972 | { 1973 | "name": "Volker Dusch", 1974 | "email": "github@wallbash.com" 1975 | }, 1976 | { 1977 | "name": "Bernhard Schussek", 1978 | "email": "bschussek@2bepublished.at" 1979 | } 1980 | ], 1981 | "description": "Provides the functionality to compare PHP values for equality", 1982 | "homepage": "https://github.com/sebastianbergmann/comparator", 1983 | "keywords": [ 1984 | "comparator", 1985 | "compare", 1986 | "equality" 1987 | ], 1988 | "support": { 1989 | "issues": "https://github.com/sebastianbergmann/comparator/issues", 1990 | "security": "https://github.com/sebastianbergmann/comparator/security/policy", 1991 | "source": "https://github.com/sebastianbergmann/comparator/tree/6.2.1" 1992 | }, 1993 | "funding": [ 1994 | { 1995 | "url": "https://github.com/sebastianbergmann", 1996 | "type": "github" 1997 | } 1998 | ], 1999 | "time": "2024-10-31T05:30:08+00:00" 2000 | }, 2001 | { 2002 | "name": "sebastian/complexity", 2003 | "version": "4.0.1", 2004 | "source": { 2005 | "type": "git", 2006 | "url": "https://github.com/sebastianbergmann/complexity.git", 2007 | "reference": "ee41d384ab1906c68852636b6de493846e13e5a0" 2008 | }, 2009 | "dist": { 2010 | "type": "zip", 2011 | "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/ee41d384ab1906c68852636b6de493846e13e5a0", 2012 | "reference": "ee41d384ab1906c68852636b6de493846e13e5a0", 2013 | "shasum": "" 2014 | }, 2015 | "require": { 2016 | "nikic/php-parser": "^5.0", 2017 | "php": ">=8.2" 2018 | }, 2019 | "require-dev": { 2020 | "phpunit/phpunit": "^11.0" 2021 | }, 2022 | "type": "library", 2023 | "extra": { 2024 | "branch-alias": { 2025 | "dev-main": "4.0-dev" 2026 | } 2027 | }, 2028 | "autoload": { 2029 | "classmap": [ 2030 | "src/" 2031 | ] 2032 | }, 2033 | "notification-url": "https://packagist.org/downloads/", 2034 | "license": [ 2035 | "BSD-3-Clause" 2036 | ], 2037 | "authors": [ 2038 | { 2039 | "name": "Sebastian Bergmann", 2040 | "email": "sebastian@phpunit.de", 2041 | "role": "lead" 2042 | } 2043 | ], 2044 | "description": "Library for calculating the complexity of PHP code units", 2045 | "homepage": "https://github.com/sebastianbergmann/complexity", 2046 | "support": { 2047 | "issues": "https://github.com/sebastianbergmann/complexity/issues", 2048 | "security": "https://github.com/sebastianbergmann/complexity/security/policy", 2049 | "source": "https://github.com/sebastianbergmann/complexity/tree/4.0.1" 2050 | }, 2051 | "funding": [ 2052 | { 2053 | "url": "https://github.com/sebastianbergmann", 2054 | "type": "github" 2055 | } 2056 | ], 2057 | "time": "2024-07-03T04:49:50+00:00" 2058 | }, 2059 | { 2060 | "name": "sebastian/diff", 2061 | "version": "6.0.2", 2062 | "source": { 2063 | "type": "git", 2064 | "url": "https://github.com/sebastianbergmann/diff.git", 2065 | "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544" 2066 | }, 2067 | "dist": { 2068 | "type": "zip", 2069 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b4ccd857127db5d41a5b676f24b51371d76d8544", 2070 | "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544", 2071 | "shasum": "" 2072 | }, 2073 | "require": { 2074 | "php": ">=8.2" 2075 | }, 2076 | "require-dev": { 2077 | "phpunit/phpunit": "^11.0", 2078 | "symfony/process": "^4.2 || ^5" 2079 | }, 2080 | "type": "library", 2081 | "extra": { 2082 | "branch-alias": { 2083 | "dev-main": "6.0-dev" 2084 | } 2085 | }, 2086 | "autoload": { 2087 | "classmap": [ 2088 | "src/" 2089 | ] 2090 | }, 2091 | "notification-url": "https://packagist.org/downloads/", 2092 | "license": [ 2093 | "BSD-3-Clause" 2094 | ], 2095 | "authors": [ 2096 | { 2097 | "name": "Sebastian Bergmann", 2098 | "email": "sebastian@phpunit.de" 2099 | }, 2100 | { 2101 | "name": "Kore Nordmann", 2102 | "email": "mail@kore-nordmann.de" 2103 | } 2104 | ], 2105 | "description": "Diff implementation", 2106 | "homepage": "https://github.com/sebastianbergmann/diff", 2107 | "keywords": [ 2108 | "diff", 2109 | "udiff", 2110 | "unidiff", 2111 | "unified diff" 2112 | ], 2113 | "support": { 2114 | "issues": "https://github.com/sebastianbergmann/diff/issues", 2115 | "security": "https://github.com/sebastianbergmann/diff/security/policy", 2116 | "source": "https://github.com/sebastianbergmann/diff/tree/6.0.2" 2117 | }, 2118 | "funding": [ 2119 | { 2120 | "url": "https://github.com/sebastianbergmann", 2121 | "type": "github" 2122 | } 2123 | ], 2124 | "time": "2024-07-03T04:53:05+00:00" 2125 | }, 2126 | { 2127 | "name": "sebastian/environment", 2128 | "version": "7.2.0", 2129 | "source": { 2130 | "type": "git", 2131 | "url": "https://github.com/sebastianbergmann/environment.git", 2132 | "reference": "855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5" 2133 | }, 2134 | "dist": { 2135 | "type": "zip", 2136 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5", 2137 | "reference": "855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5", 2138 | "shasum": "" 2139 | }, 2140 | "require": { 2141 | "php": ">=8.2" 2142 | }, 2143 | "require-dev": { 2144 | "phpunit/phpunit": "^11.0" 2145 | }, 2146 | "suggest": { 2147 | "ext-posix": "*" 2148 | }, 2149 | "type": "library", 2150 | "extra": { 2151 | "branch-alias": { 2152 | "dev-main": "7.2-dev" 2153 | } 2154 | }, 2155 | "autoload": { 2156 | "classmap": [ 2157 | "src/" 2158 | ] 2159 | }, 2160 | "notification-url": "https://packagist.org/downloads/", 2161 | "license": [ 2162 | "BSD-3-Clause" 2163 | ], 2164 | "authors": [ 2165 | { 2166 | "name": "Sebastian Bergmann", 2167 | "email": "sebastian@phpunit.de" 2168 | } 2169 | ], 2170 | "description": "Provides functionality to handle HHVM/PHP environments", 2171 | "homepage": "https://github.com/sebastianbergmann/environment", 2172 | "keywords": [ 2173 | "Xdebug", 2174 | "environment", 2175 | "hhvm" 2176 | ], 2177 | "support": { 2178 | "issues": "https://github.com/sebastianbergmann/environment/issues", 2179 | "security": "https://github.com/sebastianbergmann/environment/security/policy", 2180 | "source": "https://github.com/sebastianbergmann/environment/tree/7.2.0" 2181 | }, 2182 | "funding": [ 2183 | { 2184 | "url": "https://github.com/sebastianbergmann", 2185 | "type": "github" 2186 | } 2187 | ], 2188 | "time": "2024-07-03T04:54:44+00:00" 2189 | }, 2190 | { 2191 | "name": "sebastian/exporter", 2192 | "version": "6.3.0", 2193 | "source": { 2194 | "type": "git", 2195 | "url": "https://github.com/sebastianbergmann/exporter.git", 2196 | "reference": "3473f61172093b2da7de1fb5782e1f24cc036dc3" 2197 | }, 2198 | "dist": { 2199 | "type": "zip", 2200 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/3473f61172093b2da7de1fb5782e1f24cc036dc3", 2201 | "reference": "3473f61172093b2da7de1fb5782e1f24cc036dc3", 2202 | "shasum": "" 2203 | }, 2204 | "require": { 2205 | "ext-mbstring": "*", 2206 | "php": ">=8.2", 2207 | "sebastian/recursion-context": "^6.0" 2208 | }, 2209 | "require-dev": { 2210 | "phpunit/phpunit": "^11.3" 2211 | }, 2212 | "type": "library", 2213 | "extra": { 2214 | "branch-alias": { 2215 | "dev-main": "6.1-dev" 2216 | } 2217 | }, 2218 | "autoload": { 2219 | "classmap": [ 2220 | "src/" 2221 | ] 2222 | }, 2223 | "notification-url": "https://packagist.org/downloads/", 2224 | "license": [ 2225 | "BSD-3-Clause" 2226 | ], 2227 | "authors": [ 2228 | { 2229 | "name": "Sebastian Bergmann", 2230 | "email": "sebastian@phpunit.de" 2231 | }, 2232 | { 2233 | "name": "Jeff Welch", 2234 | "email": "whatthejeff@gmail.com" 2235 | }, 2236 | { 2237 | "name": "Volker Dusch", 2238 | "email": "github@wallbash.com" 2239 | }, 2240 | { 2241 | "name": "Adam Harvey", 2242 | "email": "aharvey@php.net" 2243 | }, 2244 | { 2245 | "name": "Bernhard Schussek", 2246 | "email": "bschussek@gmail.com" 2247 | } 2248 | ], 2249 | "description": "Provides the functionality to export PHP variables for visualization", 2250 | "homepage": "https://www.github.com/sebastianbergmann/exporter", 2251 | "keywords": [ 2252 | "export", 2253 | "exporter" 2254 | ], 2255 | "support": { 2256 | "issues": "https://github.com/sebastianbergmann/exporter/issues", 2257 | "security": "https://github.com/sebastianbergmann/exporter/security/policy", 2258 | "source": "https://github.com/sebastianbergmann/exporter/tree/6.3.0" 2259 | }, 2260 | "funding": [ 2261 | { 2262 | "url": "https://github.com/sebastianbergmann", 2263 | "type": "github" 2264 | } 2265 | ], 2266 | "time": "2024-12-05T09:17:50+00:00" 2267 | }, 2268 | { 2269 | "name": "sebastian/global-state", 2270 | "version": "7.0.2", 2271 | "source": { 2272 | "type": "git", 2273 | "url": "https://github.com/sebastianbergmann/global-state.git", 2274 | "reference": "3be331570a721f9a4b5917f4209773de17f747d7" 2275 | }, 2276 | "dist": { 2277 | "type": "zip", 2278 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/3be331570a721f9a4b5917f4209773de17f747d7", 2279 | "reference": "3be331570a721f9a4b5917f4209773de17f747d7", 2280 | "shasum": "" 2281 | }, 2282 | "require": { 2283 | "php": ">=8.2", 2284 | "sebastian/object-reflector": "^4.0", 2285 | "sebastian/recursion-context": "^6.0" 2286 | }, 2287 | "require-dev": { 2288 | "ext-dom": "*", 2289 | "phpunit/phpunit": "^11.0" 2290 | }, 2291 | "type": "library", 2292 | "extra": { 2293 | "branch-alias": { 2294 | "dev-main": "7.0-dev" 2295 | } 2296 | }, 2297 | "autoload": { 2298 | "classmap": [ 2299 | "src/" 2300 | ] 2301 | }, 2302 | "notification-url": "https://packagist.org/downloads/", 2303 | "license": [ 2304 | "BSD-3-Clause" 2305 | ], 2306 | "authors": [ 2307 | { 2308 | "name": "Sebastian Bergmann", 2309 | "email": "sebastian@phpunit.de" 2310 | } 2311 | ], 2312 | "description": "Snapshotting of global state", 2313 | "homepage": "https://www.github.com/sebastianbergmann/global-state", 2314 | "keywords": [ 2315 | "global state" 2316 | ], 2317 | "support": { 2318 | "issues": "https://github.com/sebastianbergmann/global-state/issues", 2319 | "security": "https://github.com/sebastianbergmann/global-state/security/policy", 2320 | "source": "https://github.com/sebastianbergmann/global-state/tree/7.0.2" 2321 | }, 2322 | "funding": [ 2323 | { 2324 | "url": "https://github.com/sebastianbergmann", 2325 | "type": "github" 2326 | } 2327 | ], 2328 | "time": "2024-07-03T04:57:36+00:00" 2329 | }, 2330 | { 2331 | "name": "sebastian/lines-of-code", 2332 | "version": "3.0.1", 2333 | "source": { 2334 | "type": "git", 2335 | "url": "https://github.com/sebastianbergmann/lines-of-code.git", 2336 | "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a" 2337 | }, 2338 | "dist": { 2339 | "type": "zip", 2340 | "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/d36ad0d782e5756913e42ad87cb2890f4ffe467a", 2341 | "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a", 2342 | "shasum": "" 2343 | }, 2344 | "require": { 2345 | "nikic/php-parser": "^5.0", 2346 | "php": ">=8.2" 2347 | }, 2348 | "require-dev": { 2349 | "phpunit/phpunit": "^11.0" 2350 | }, 2351 | "type": "library", 2352 | "extra": { 2353 | "branch-alias": { 2354 | "dev-main": "3.0-dev" 2355 | } 2356 | }, 2357 | "autoload": { 2358 | "classmap": [ 2359 | "src/" 2360 | ] 2361 | }, 2362 | "notification-url": "https://packagist.org/downloads/", 2363 | "license": [ 2364 | "BSD-3-Clause" 2365 | ], 2366 | "authors": [ 2367 | { 2368 | "name": "Sebastian Bergmann", 2369 | "email": "sebastian@phpunit.de", 2370 | "role": "lead" 2371 | } 2372 | ], 2373 | "description": "Library for counting the lines of code in PHP source code", 2374 | "homepage": "https://github.com/sebastianbergmann/lines-of-code", 2375 | "support": { 2376 | "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", 2377 | "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", 2378 | "source": "https://github.com/sebastianbergmann/lines-of-code/tree/3.0.1" 2379 | }, 2380 | "funding": [ 2381 | { 2382 | "url": "https://github.com/sebastianbergmann", 2383 | "type": "github" 2384 | } 2385 | ], 2386 | "time": "2024-07-03T04:58:38+00:00" 2387 | }, 2388 | { 2389 | "name": "sebastian/object-enumerator", 2390 | "version": "6.0.1", 2391 | "source": { 2392 | "type": "git", 2393 | "url": "https://github.com/sebastianbergmann/object-enumerator.git", 2394 | "reference": "f5b498e631a74204185071eb41f33f38d64608aa" 2395 | }, 2396 | "dist": { 2397 | "type": "zip", 2398 | "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/f5b498e631a74204185071eb41f33f38d64608aa", 2399 | "reference": "f5b498e631a74204185071eb41f33f38d64608aa", 2400 | "shasum": "" 2401 | }, 2402 | "require": { 2403 | "php": ">=8.2", 2404 | "sebastian/object-reflector": "^4.0", 2405 | "sebastian/recursion-context": "^6.0" 2406 | }, 2407 | "require-dev": { 2408 | "phpunit/phpunit": "^11.0" 2409 | }, 2410 | "type": "library", 2411 | "extra": { 2412 | "branch-alias": { 2413 | "dev-main": "6.0-dev" 2414 | } 2415 | }, 2416 | "autoload": { 2417 | "classmap": [ 2418 | "src/" 2419 | ] 2420 | }, 2421 | "notification-url": "https://packagist.org/downloads/", 2422 | "license": [ 2423 | "BSD-3-Clause" 2424 | ], 2425 | "authors": [ 2426 | { 2427 | "name": "Sebastian Bergmann", 2428 | "email": "sebastian@phpunit.de" 2429 | } 2430 | ], 2431 | "description": "Traverses array structures and object graphs to enumerate all referenced objects", 2432 | "homepage": "https://github.com/sebastianbergmann/object-enumerator/", 2433 | "support": { 2434 | "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", 2435 | "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", 2436 | "source": "https://github.com/sebastianbergmann/object-enumerator/tree/6.0.1" 2437 | }, 2438 | "funding": [ 2439 | { 2440 | "url": "https://github.com/sebastianbergmann", 2441 | "type": "github" 2442 | } 2443 | ], 2444 | "time": "2024-07-03T05:00:13+00:00" 2445 | }, 2446 | { 2447 | "name": "sebastian/object-reflector", 2448 | "version": "4.0.1", 2449 | "source": { 2450 | "type": "git", 2451 | "url": "https://github.com/sebastianbergmann/object-reflector.git", 2452 | "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9" 2453 | }, 2454 | "dist": { 2455 | "type": "zip", 2456 | "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/6e1a43b411b2ad34146dee7524cb13a068bb35f9", 2457 | "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9", 2458 | "shasum": "" 2459 | }, 2460 | "require": { 2461 | "php": ">=8.2" 2462 | }, 2463 | "require-dev": { 2464 | "phpunit/phpunit": "^11.0" 2465 | }, 2466 | "type": "library", 2467 | "extra": { 2468 | "branch-alias": { 2469 | "dev-main": "4.0-dev" 2470 | } 2471 | }, 2472 | "autoload": { 2473 | "classmap": [ 2474 | "src/" 2475 | ] 2476 | }, 2477 | "notification-url": "https://packagist.org/downloads/", 2478 | "license": [ 2479 | "BSD-3-Clause" 2480 | ], 2481 | "authors": [ 2482 | { 2483 | "name": "Sebastian Bergmann", 2484 | "email": "sebastian@phpunit.de" 2485 | } 2486 | ], 2487 | "description": "Allows reflection of object attributes, including inherited and non-public ones", 2488 | "homepage": "https://github.com/sebastianbergmann/object-reflector/", 2489 | "support": { 2490 | "issues": "https://github.com/sebastianbergmann/object-reflector/issues", 2491 | "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", 2492 | "source": "https://github.com/sebastianbergmann/object-reflector/tree/4.0.1" 2493 | }, 2494 | "funding": [ 2495 | { 2496 | "url": "https://github.com/sebastianbergmann", 2497 | "type": "github" 2498 | } 2499 | ], 2500 | "time": "2024-07-03T05:01:32+00:00" 2501 | }, 2502 | { 2503 | "name": "sebastian/recursion-context", 2504 | "version": "6.0.2", 2505 | "source": { 2506 | "type": "git", 2507 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 2508 | "reference": "694d156164372abbd149a4b85ccda2e4670c0e16" 2509 | }, 2510 | "dist": { 2511 | "type": "zip", 2512 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/694d156164372abbd149a4b85ccda2e4670c0e16", 2513 | "reference": "694d156164372abbd149a4b85ccda2e4670c0e16", 2514 | "shasum": "" 2515 | }, 2516 | "require": { 2517 | "php": ">=8.2" 2518 | }, 2519 | "require-dev": { 2520 | "phpunit/phpunit": "^11.0" 2521 | }, 2522 | "type": "library", 2523 | "extra": { 2524 | "branch-alias": { 2525 | "dev-main": "6.0-dev" 2526 | } 2527 | }, 2528 | "autoload": { 2529 | "classmap": [ 2530 | "src/" 2531 | ] 2532 | }, 2533 | "notification-url": "https://packagist.org/downloads/", 2534 | "license": [ 2535 | "BSD-3-Clause" 2536 | ], 2537 | "authors": [ 2538 | { 2539 | "name": "Sebastian Bergmann", 2540 | "email": "sebastian@phpunit.de" 2541 | }, 2542 | { 2543 | "name": "Jeff Welch", 2544 | "email": "whatthejeff@gmail.com" 2545 | }, 2546 | { 2547 | "name": "Adam Harvey", 2548 | "email": "aharvey@php.net" 2549 | } 2550 | ], 2551 | "description": "Provides functionality to recursively process PHP variables", 2552 | "homepage": "https://github.com/sebastianbergmann/recursion-context", 2553 | "support": { 2554 | "issues": "https://github.com/sebastianbergmann/recursion-context/issues", 2555 | "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", 2556 | "source": "https://github.com/sebastianbergmann/recursion-context/tree/6.0.2" 2557 | }, 2558 | "funding": [ 2559 | { 2560 | "url": "https://github.com/sebastianbergmann", 2561 | "type": "github" 2562 | } 2563 | ], 2564 | "time": "2024-07-03T05:10:34+00:00" 2565 | }, 2566 | { 2567 | "name": "sebastian/type", 2568 | "version": "5.1.0", 2569 | "source": { 2570 | "type": "git", 2571 | "url": "https://github.com/sebastianbergmann/type.git", 2572 | "reference": "461b9c5da241511a2a0e8f240814fb23ce5c0aac" 2573 | }, 2574 | "dist": { 2575 | "type": "zip", 2576 | "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/461b9c5da241511a2a0e8f240814fb23ce5c0aac", 2577 | "reference": "461b9c5da241511a2a0e8f240814fb23ce5c0aac", 2578 | "shasum": "" 2579 | }, 2580 | "require": { 2581 | "php": ">=8.2" 2582 | }, 2583 | "require-dev": { 2584 | "phpunit/phpunit": "^11.3" 2585 | }, 2586 | "type": "library", 2587 | "extra": { 2588 | "branch-alias": { 2589 | "dev-main": "5.1-dev" 2590 | } 2591 | }, 2592 | "autoload": { 2593 | "classmap": [ 2594 | "src/" 2595 | ] 2596 | }, 2597 | "notification-url": "https://packagist.org/downloads/", 2598 | "license": [ 2599 | "BSD-3-Clause" 2600 | ], 2601 | "authors": [ 2602 | { 2603 | "name": "Sebastian Bergmann", 2604 | "email": "sebastian@phpunit.de", 2605 | "role": "lead" 2606 | } 2607 | ], 2608 | "description": "Collection of value objects that represent the types of the PHP type system", 2609 | "homepage": "https://github.com/sebastianbergmann/type", 2610 | "support": { 2611 | "issues": "https://github.com/sebastianbergmann/type/issues", 2612 | "security": "https://github.com/sebastianbergmann/type/security/policy", 2613 | "source": "https://github.com/sebastianbergmann/type/tree/5.1.0" 2614 | }, 2615 | "funding": [ 2616 | { 2617 | "url": "https://github.com/sebastianbergmann", 2618 | "type": "github" 2619 | } 2620 | ], 2621 | "time": "2024-09-17T13:12:04+00:00" 2622 | }, 2623 | { 2624 | "name": "sebastian/version", 2625 | "version": "5.0.2", 2626 | "source": { 2627 | "type": "git", 2628 | "url": "https://github.com/sebastianbergmann/version.git", 2629 | "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874" 2630 | }, 2631 | "dist": { 2632 | "type": "zip", 2633 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c687e3387b99f5b03b6caa64c74b63e2936ff874", 2634 | "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874", 2635 | "shasum": "" 2636 | }, 2637 | "require": { 2638 | "php": ">=8.2" 2639 | }, 2640 | "type": "library", 2641 | "extra": { 2642 | "branch-alias": { 2643 | "dev-main": "5.0-dev" 2644 | } 2645 | }, 2646 | "autoload": { 2647 | "classmap": [ 2648 | "src/" 2649 | ] 2650 | }, 2651 | "notification-url": "https://packagist.org/downloads/", 2652 | "license": [ 2653 | "BSD-3-Clause" 2654 | ], 2655 | "authors": [ 2656 | { 2657 | "name": "Sebastian Bergmann", 2658 | "email": "sebastian@phpunit.de", 2659 | "role": "lead" 2660 | } 2661 | ], 2662 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", 2663 | "homepage": "https://github.com/sebastianbergmann/version", 2664 | "support": { 2665 | "issues": "https://github.com/sebastianbergmann/version/issues", 2666 | "security": "https://github.com/sebastianbergmann/version/security/policy", 2667 | "source": "https://github.com/sebastianbergmann/version/tree/5.0.2" 2668 | }, 2669 | "funding": [ 2670 | { 2671 | "url": "https://github.com/sebastianbergmann", 2672 | "type": "github" 2673 | } 2674 | ], 2675 | "time": "2024-10-09T05:16:32+00:00" 2676 | }, 2677 | { 2678 | "name": "staabm/side-effects-detector", 2679 | "version": "1.0.5", 2680 | "source": { 2681 | "type": "git", 2682 | "url": "https://github.com/staabm/side-effects-detector.git", 2683 | "reference": "d8334211a140ce329c13726d4a715adbddd0a163" 2684 | }, 2685 | "dist": { 2686 | "type": "zip", 2687 | "url": "https://api.github.com/repos/staabm/side-effects-detector/zipball/d8334211a140ce329c13726d4a715adbddd0a163", 2688 | "reference": "d8334211a140ce329c13726d4a715adbddd0a163", 2689 | "shasum": "" 2690 | }, 2691 | "require": { 2692 | "ext-tokenizer": "*", 2693 | "php": "^7.4 || ^8.0" 2694 | }, 2695 | "require-dev": { 2696 | "phpstan/extension-installer": "^1.4.3", 2697 | "phpstan/phpstan": "^1.12.6", 2698 | "phpunit/phpunit": "^9.6.21", 2699 | "symfony/var-dumper": "^5.4.43", 2700 | "tomasvotruba/type-coverage": "1.0.0", 2701 | "tomasvotruba/unused-public": "1.0.0" 2702 | }, 2703 | "type": "library", 2704 | "autoload": { 2705 | "classmap": [ 2706 | "lib/" 2707 | ] 2708 | }, 2709 | "notification-url": "https://packagist.org/downloads/", 2710 | "license": [ 2711 | "MIT" 2712 | ], 2713 | "description": "A static analysis tool to detect side effects in PHP code", 2714 | "keywords": [ 2715 | "static analysis" 2716 | ], 2717 | "support": { 2718 | "issues": "https://github.com/staabm/side-effects-detector/issues", 2719 | "source": "https://github.com/staabm/side-effects-detector/tree/1.0.5" 2720 | }, 2721 | "funding": [ 2722 | { 2723 | "url": "https://github.com/staabm", 2724 | "type": "github" 2725 | } 2726 | ], 2727 | "time": "2024-10-20T05:08:20+00:00" 2728 | }, 2729 | { 2730 | "name": "symfony/polyfill-mbstring", 2731 | "version": "v1.31.0", 2732 | "source": { 2733 | "type": "git", 2734 | "url": "https://github.com/symfony/polyfill-mbstring.git", 2735 | "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" 2736 | }, 2737 | "dist": { 2738 | "type": "zip", 2739 | "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", 2740 | "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", 2741 | "shasum": "" 2742 | }, 2743 | "require": { 2744 | "php": ">=7.2" 2745 | }, 2746 | "provide": { 2747 | "ext-mbstring": "*" 2748 | }, 2749 | "suggest": { 2750 | "ext-mbstring": "For best performance" 2751 | }, 2752 | "type": "library", 2753 | "extra": { 2754 | "thanks": { 2755 | "url": "https://github.com/symfony/polyfill", 2756 | "name": "symfony/polyfill" 2757 | } 2758 | }, 2759 | "autoload": { 2760 | "files": [ 2761 | "bootstrap.php" 2762 | ], 2763 | "psr-4": { 2764 | "Symfony\\Polyfill\\Mbstring\\": "" 2765 | } 2766 | }, 2767 | "notification-url": "https://packagist.org/downloads/", 2768 | "license": [ 2769 | "MIT" 2770 | ], 2771 | "authors": [ 2772 | { 2773 | "name": "Nicolas Grekas", 2774 | "email": "p@tchwork.com" 2775 | }, 2776 | { 2777 | "name": "Symfony Community", 2778 | "homepage": "https://symfony.com/contributors" 2779 | } 2780 | ], 2781 | "description": "Symfony polyfill for the Mbstring extension", 2782 | "homepage": "https://symfony.com", 2783 | "keywords": [ 2784 | "compatibility", 2785 | "mbstring", 2786 | "polyfill", 2787 | "portable", 2788 | "shim" 2789 | ], 2790 | "support": { 2791 | "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" 2792 | }, 2793 | "funding": [ 2794 | { 2795 | "url": "https://symfony.com/sponsor", 2796 | "type": "custom" 2797 | }, 2798 | { 2799 | "url": "https://github.com/fabpot", 2800 | "type": "github" 2801 | }, 2802 | { 2803 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 2804 | "type": "tidelift" 2805 | } 2806 | ], 2807 | "time": "2024-09-09T11:45:10+00:00" 2808 | }, 2809 | { 2810 | "name": "symfony/var-dumper", 2811 | "version": "v7.2.0", 2812 | "source": { 2813 | "type": "git", 2814 | "url": "https://github.com/symfony/var-dumper.git", 2815 | "reference": "c6a22929407dec8765d6e2b6ff85b800b245879c" 2816 | }, 2817 | "dist": { 2818 | "type": "zip", 2819 | "url": "https://api.github.com/repos/symfony/var-dumper/zipball/c6a22929407dec8765d6e2b6ff85b800b245879c", 2820 | "reference": "c6a22929407dec8765d6e2b6ff85b800b245879c", 2821 | "shasum": "" 2822 | }, 2823 | "require": { 2824 | "php": ">=8.2", 2825 | "symfony/polyfill-mbstring": "~1.0" 2826 | }, 2827 | "conflict": { 2828 | "symfony/console": "<6.4" 2829 | }, 2830 | "require-dev": { 2831 | "ext-iconv": "*", 2832 | "symfony/console": "^6.4|^7.0", 2833 | "symfony/http-kernel": "^6.4|^7.0", 2834 | "symfony/process": "^6.4|^7.0", 2835 | "symfony/uid": "^6.4|^7.0", 2836 | "twig/twig": "^3.12" 2837 | }, 2838 | "bin": [ 2839 | "Resources/bin/var-dump-server" 2840 | ], 2841 | "type": "library", 2842 | "autoload": { 2843 | "files": [ 2844 | "Resources/functions/dump.php" 2845 | ], 2846 | "psr-4": { 2847 | "Symfony\\Component\\VarDumper\\": "" 2848 | }, 2849 | "exclude-from-classmap": [ 2850 | "/Tests/" 2851 | ] 2852 | }, 2853 | "notification-url": "https://packagist.org/downloads/", 2854 | "license": [ 2855 | "MIT" 2856 | ], 2857 | "authors": [ 2858 | { 2859 | "name": "Nicolas Grekas", 2860 | "email": "p@tchwork.com" 2861 | }, 2862 | { 2863 | "name": "Symfony Community", 2864 | "homepage": "https://symfony.com/contributors" 2865 | } 2866 | ], 2867 | "description": "Provides mechanisms for walking through any arbitrary PHP variable", 2868 | "homepage": "https://symfony.com", 2869 | "keywords": [ 2870 | "debug", 2871 | "dump" 2872 | ], 2873 | "support": { 2874 | "source": "https://github.com/symfony/var-dumper/tree/v7.2.0" 2875 | }, 2876 | "funding": [ 2877 | { 2878 | "url": "https://symfony.com/sponsor", 2879 | "type": "custom" 2880 | }, 2881 | { 2882 | "url": "https://github.com/fabpot", 2883 | "type": "github" 2884 | }, 2885 | { 2886 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 2887 | "type": "tidelift" 2888 | } 2889 | ], 2890 | "time": "2024-11-08T15:48:14+00:00" 2891 | }, 2892 | { 2893 | "name": "theseer/tokenizer", 2894 | "version": "1.2.3", 2895 | "source": { 2896 | "type": "git", 2897 | "url": "https://github.com/theseer/tokenizer.git", 2898 | "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" 2899 | }, 2900 | "dist": { 2901 | "type": "zip", 2902 | "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", 2903 | "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", 2904 | "shasum": "" 2905 | }, 2906 | "require": { 2907 | "ext-dom": "*", 2908 | "ext-tokenizer": "*", 2909 | "ext-xmlwriter": "*", 2910 | "php": "^7.2 || ^8.0" 2911 | }, 2912 | "type": "library", 2913 | "autoload": { 2914 | "classmap": [ 2915 | "src/" 2916 | ] 2917 | }, 2918 | "notification-url": "https://packagist.org/downloads/", 2919 | "license": [ 2920 | "BSD-3-Clause" 2921 | ], 2922 | "authors": [ 2923 | { 2924 | "name": "Arne Blankerts", 2925 | "email": "arne@blankerts.de", 2926 | "role": "Developer" 2927 | } 2928 | ], 2929 | "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", 2930 | "support": { 2931 | "issues": "https://github.com/theseer/tokenizer/issues", 2932 | "source": "https://github.com/theseer/tokenizer/tree/1.2.3" 2933 | }, 2934 | "funding": [ 2935 | { 2936 | "url": "https://github.com/theseer", 2937 | "type": "github" 2938 | } 2939 | ], 2940 | "time": "2024-03-03T12:36:25+00:00" 2941 | } 2942 | ], 2943 | "aliases": [], 2944 | "minimum-stability": "stable", 2945 | "stability-flags": [], 2946 | "prefer-stable": false, 2947 | "prefer-lowest": false, 2948 | "platform": [], 2949 | "platform-dev": [], 2950 | "plugin-api-version": "2.6.0" 2951 | } 2952 | -------------------------------------------------------------------------------- /phpstan.neon: -------------------------------------------------------------------------------- 1 | parameters: 2 | treatPhpDocTypesAsCertain: false 3 | reportUnmatchedIgnoredErrors: false 4 | ignoreErrors: 5 | - identifier: missingType.iterableValue 6 | - identifier: missingType.generics 7 | -------------------------------------------------------------------------------- /src/Entity/KeyInterface.php: -------------------------------------------------------------------------------- 1 | verified; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Entity/VerificationResultInterface.php: -------------------------------------------------------------------------------- 1 | modify("+3 minute"); 80 | } 81 | 82 | $signature = JWT::encode( 83 | [ 84 | 'iss' => 'https://ucar-solutions.de/uri-signer', 85 | 'exp' => $expireDate->getTimestamp(), 86 | 'sub' => 'Signed URL', 87 | 'url' => (string)$uri, 88 | 'uid' => Uuid::uuid4() 89 | ], 90 | $key->getKey(), 91 | 'HS256' 92 | ); 93 | 94 | $queryParams = []; 95 | parse_str($uri->getQuery(), $queryParams); 96 | 97 | $queryParams[$this->parameterNameResolver->getSignature()] = $signature; 98 | $newQuery = http_build_query($queryParams); 99 | 100 | return $uri->withQuery($newQuery); 101 | } 102 | 103 | public function verify(UriInterface $uri, KeyInterface $key): VerificationResultInterface 104 | { 105 | try { 106 | $parameters = []; 107 | parse_str($uri->getQuery(), $parameters); 108 | 109 | $signature = $parameters[$this->parameterNameResolver->getSignature()] ?? null; 110 | 111 | if ($signature === null) { 112 | throw new SignatureNotFoundException(); 113 | } 114 | 115 | $decoded = (array)JWT::decode( 116 | /** @phpstan-ignore-next-line */ 117 | (string)$signature, 118 | new Key( 119 | $key->getKey(), 120 | 'HS256' 121 | ) 122 | ); 123 | 124 | $originalUrl = $decoded['url'] ?? null; 125 | $currentUriWithoutSignature = $uri->withQuery( 126 | http_build_query( 127 | array_diff_key( 128 | $parameters, 129 | [ 130 | $this->parameterNameResolver->getSignature() => '' 131 | ] 132 | ) 133 | ) 134 | ); 135 | 136 | if ($originalUrl !== (string)$currentUriWithoutSignature) { 137 | throw new InvalidUrlException('The URL has been modified'); 138 | } 139 | 140 | $expireDate = (new DateTimeImmutable())->setTimestamp($decoded['exp']); 141 | return new VerificationResult( 142 | $this->dateTimeService->isExpired($expireDate) 143 | ); 144 | } catch (SignatureNotFoundException|InvalidUrlException|UnexpectedValueException $e) { 145 | $this->logger->error('error verifying signature', ['exception' => $e]); 146 | return new VerificationResult(false); 147 | } 148 | } 149 | 150 | } 151 | -------------------------------------------------------------------------------- /src/Service/UriSignerServiceInterface.php: -------------------------------------------------------------------------------- 1 | parameterNameResolver = new DefaultParameterNameResolver(); 55 | $this->signerService = new UriSignerService( 56 | $this->parameterNameResolver, 57 | new DateTimeService(), 58 | new NullLogger() 59 | ); 60 | 61 | $this->key = new class implements KeyInterface { 62 | 63 | public function getKey(): string 64 | { 65 | return "t0psecret"; 66 | } 67 | }; 68 | } 69 | 70 | public function testSign(): void 71 | { 72 | $uri = $this->signerService->sign( 73 | new Uri("https://example.com?var=test"), 74 | $this->key 75 | ); 76 | 77 | $this->assertTrue($uri instanceof UriInterface); 78 | $this->assertTrue($uri->getScheme() === 'https'); 79 | $this->assertTrue($uri->getHost() === 'example.com'); 80 | $this->assertTrue(str_contains($uri->getQuery(), 'var=test&' . $this->parameterNameResolver->getSignature() . '=')); 81 | } 82 | 83 | public function testSignUrlWithValidKeyAndExpiry(): void 84 | { 85 | $uri = new Uri('https://example.com/resource'); 86 | $signedUri = $this->signerService->sign($uri, $this->key); 87 | $this->assertStringContainsString($this->parameterNameResolver->getSignature() . '=', (string)$signedUri); 88 | } 89 | 90 | public function testVerifySignedUrlWithCorrectSignature(): void 91 | { 92 | $uri = new Uri( 93 | sprintf('https://example.com/resource?%s=valid-token', $this->parameterNameResolver->getSignature()) 94 | ); 95 | $verificationResult = $this->signerService->verify($uri, $this->key); 96 | $this->assertFalse($verificationResult->isVerified()); 97 | } 98 | 99 | public function testVerifyFailsIfSignatureIsMissing(): void 100 | { 101 | $uri = new Uri('https://example.com/resource'); 102 | $verificationResult = $this->signerService->verify($uri, $this->key); 103 | $this->assertFalse($verificationResult->isVerified()); 104 | } 105 | 106 | public function testVerifyFailsIfUrlIsModified(): void 107 | { 108 | $originalUri = new Uri('https://example.com/resource?param=value'); 109 | $signedUri = $this->signerService->sign($originalUri, $this->key); 110 | $modifiedUri = new Uri('https://example.com/modified-resource?p1=v2&' . $signedUri->getQuery()); 111 | $verificationResult = $this->signerService->verify($modifiedUri, $this->key); 112 | $this->assertFalse($verificationResult->isVerified()); 113 | } 114 | 115 | public function testVerifyFailsIfSignatureIsInvalid(): void 116 | { 117 | $uri = new Uri(sprintf('https://example.com/resource?%s=invalid-token', $this->parameterNameResolver->getSignature())); 118 | $verificationResult = $this->signerService->verify($uri, $this->key); 119 | $this->assertFalse($verificationResult->isVerified()); 120 | } 121 | 122 | public function testSignUrlWithoutQueryParams(): void 123 | { 124 | $uri = new Uri('https://example.com/resource'); 125 | $signedUri = $this->signerService->sign($uri, $this->key); 126 | $this->assertStringContainsString(sprintf('?%s=', $this->parameterNameResolver->getSignature()), (string)$signedUri); 127 | } 128 | 129 | public function testVerifyFailsIfUrlIsExpired(): void 130 | { 131 | $uri = new Uri('https://example.com/resource'); 132 | $expiredDate = (new DateTimeImmutable())->modify('-10 minutes'); 133 | $signedUri = $this->signerService->sign($uri, $this->key, $expiredDate); 134 | $verificationResult = $this->signerService->verify($signedUri, $this->key); 135 | $this->assertFalse($verificationResult->isVerified()); 136 | } 137 | 138 | 139 | } 140 | --------------------------------------------------------------------------------