├── .github ├── ISSUE_TEMPLATES │ ├── bug_report.md │ ├── custom.md │ └── feature_request.md └── workflows │ ├── lint.yaml │ └── test.yaml ├── .gitignore ├── LICENSE.md ├── Makefile ├── README.md ├── composer.json ├── composer.lock ├── ecs.php ├── phpstan.neon ├── phpunit.xml ├── src ├── Client.php ├── Credential.php ├── Data │ ├── Currency.php │ ├── Language.php │ └── PayType.php ├── Environment.php └── PaymentEntry.php └── tests ├── ClientTest.php ├── CredentialTest.php ├── EnvironmentTest.php └── PaymentEntryTest.php /.github/ISSUE_TEMPLATES/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATES/custom.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Custom issue template 3 | about: Describe this issue template's purpose here. 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATES/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. -------------------------------------------------------------------------------- /.github/workflows/lint.yaml: -------------------------------------------------------------------------------- 1 | name: Coding standards 2 | on: [push] 3 | jobs: 4 | lint: 5 | name: Coding standards 6 | runs-on: ubuntu-latest 7 | strategy: 8 | fail-fast: false 9 | matrix: 10 | php: [ '8.2', '8.3' ] 11 | 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@v2 15 | 16 | - name: Setup PHP 17 | uses: shivammathur/setup-php@v2 18 | with: 19 | php-version: ${{ matrix.php }} 20 | tools: composer:v2 21 | 22 | - name: Setup cache 23 | run: echo "COMPOSER_CACHE_DIR=$(composer config cache-dir)" >> $GITHUB_ENV 24 | 25 | - name: Cache dependencies installed with composer 26 | uses: actions/cache@v2 27 | with: 28 | path: ${{ env.COMPOSER_CACHE_DIR }} 29 | key: php${{ matrix.php }}-composer-${{ hashFiles('**/composer.json') }} 30 | restore-keys: | 31 | php${{ matrix.php }}-composer-latest- 32 | 33 | - name: Update composer 34 | run: composer self-update 35 | 36 | - name: Install dependencies with composer 37 | run: composer install --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi 38 | 39 | - name: Run code quality analysis 40 | run: make lint -------------------------------------------------------------------------------- /.github/workflows/test.yaml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | on: [push] 3 | jobs: 4 | test: 5 | name: Tests 6 | runs-on: ubuntu-latest 7 | strategy: 8 | fail-fast: false 9 | matrix: 10 | php: [ '8.2', '8.3' ] 11 | 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@v2 15 | 16 | - name: Setup PHP 17 | uses: shivammathur/setup-php@v2 18 | with: 19 | php-version: ${{ matrix.php }} 20 | tools: composer:v2 21 | 22 | - name: Setup cache 23 | run: echo "COMPOSER_CACHE_DIR=$(composer config cache-dir)" >> $GITHUB_ENV 24 | 25 | - name: Cache dependencies installed with composer 26 | uses: actions/cache@v2 27 | with: 28 | path: ${{ env.COMPOSER_CACHE_DIR }} 29 | key: php${{ matrix.php }}-composer-${{ hashFiles('**/composer.json') }} 30 | restore-keys: | 31 | php${{ matrix.php }}-composer-latest- 32 | 33 | - name: Update composer 34 | run: composer self-update 35 | 36 | - name: Install dependencies with composer 37 | run: composer install --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi 38 | 39 | - name: Run tests 40 | run: make test -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor/ 2 | .idea 3 | .phpunit.result.cache 4 | .phpunit.cache 5 | .vscode 6 | index.php 7 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) [2023] [Devscast] 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .DEFAULT_GOAL := help 2 | 3 | # ----------------------------------- 4 | # Recipes 5 | # ----------------------------------- 6 | .PHONY: help 7 | help: ## affiche cet aide 8 | @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' 9 | 10 | .PHONY: lint 11 | lint: vendor/autoload.php ## affiche les erreurs de formatage de code 12 | php vendor/bin/ecs 13 | php vendor/bin/phpstan 14 | 15 | .PHONY: test 16 | test: vendor/autoload.php ## lance les tests 17 | php vendor/bin/phpunit 18 | 19 | .PHONY: lint-fix 20 | lint-fix: vendor/autoload.php ## corrige les erreurs de formatage de code 21 | php vendor/bin/ecs --fix 22 | 23 | vendor/autoload.php: composer.lock # installe les dépendances PHP 24 | composer update 25 | composer dump-autoload -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Maxicash PHP 2 | 3 | ![Lint](https://github.com/devscast/maxicash/actions/workflows/lint.yaml/badge.svg) 4 | ![Test](https://github.com/devscast/maxicash/actions/workflows/test.yaml/badge.svg) 5 | [![Latest Stable Version](https://poser.pugx.org/devscast/maxicash/version)](https://packagist.org/packages/devscast/maxicash) 6 | [![Total Downloads](https://poser.pugx.org/devscast/maxicash/downloads)](https://packagist.org/packages/devscast/maxicash) 7 | [![License](https://poser.pugx.org/devscast/maxicash/license)](https://packagist.org/packages/devscast/maxicash) 8 | 9 | 10 | The MaxiCash Integration Platform enables Merchants to integrate with the MaxiCash platform in order to receive payments through their mobile apps or their websites. The API uses JSON to interact with .Net client or open source platforms like PHP. see more at [Maxicash Documentation](https://developer.maxicashapp.com/Default) 11 | 12 | ## Installation 13 | You can use the PHP client by installing the Composer package and adding it to your application’s dependencies: 14 | 15 | ```bash 16 | composer require devscast/maxicash 17 | ``` 18 | ## Usage 19 | The MaxiCash Gateway enables the Merchant to Collect Payment into their MaxiCash account using multiple payment channels such as Credit Cards, MaxiCash, Paypal, Mobile Money and Mobile Banking. 20 | 21 | ### Authentication 22 | * **Step 1**. Download the MaxiCash Mobile App and signup... 23 | * **Step 2**. Contact us to upgrade your account to a Merchant Account info@maxicashapp.com 24 | You will receive a Merchant Form to complete in order to provide your business details and preferred Cash out Wallet or Banking Details. 25 | * **Step 3**. Once the paperwork is completed, you will be issued with Live and Sandbox Accounts (MerchantID and MerchantPassword) 26 | 27 | 28 | ```php 29 | use Devscast\Maxicash\Client as Maxicash; 30 | use Devscast\Maxicash\Credential; 31 | use Devscast\Maxicash\PaymentEntry; 32 | use Devscast\Maxicash\Environment; 33 | 34 | $maxicash = new Maxicash( 35 | credential: new Credential('marchand_id', 'marchand_password'), 36 | environment: Environment::SANDBOX // use `Environment::LIVE` for live 37 | ); 38 | ``` 39 | 40 | ### Create a Payment Entry 41 | ```php 42 | $entry = new PaymentEntry( 43 | credential: $maxicash->credential, 44 | amount: intval(47.50 * 100), // amount in cents 45 | reference: "this text will be shown on maxicash payment page", 46 | acceptUrl: "your_website_accept_url", 47 | declineUrl: "your_website_decline_url", 48 | ); 49 | ``` 50 | > **Note**: we hightly recommand your `accept` and `decline` urls to be unique for each transaction, thus users will not be able to reuse them to validate other transactions, on your side save the transaction with a unique generated token (a.k.a transaction reference) and use it as parameter to your accept and decline urls, don't use it for the `PaymentEntry->reference`; once the user is redirected to your accept url, validate the token and grant access to the paid resource (with your own business logic). 51 | 52 | 53 | ### Redirect to Maxicash Gateway 54 | Redirect your user to the maxicash gateway to continue the payment process 55 | 56 | > **Note** : If you're using Turbo Drive in your Symfony application, disable it on payment links in your twig templates 57 | 58 | ```php 59 | $url = $maxicash->queryStringURLPayment($entry); 60 | ``` 61 | > **Note** : we highly recommand to do a `server side` redirection, this url can be modified and leak your maxicash credentials when displayed to your user in any manner (eg: a link, button or form) ! you can use the `header("Location: $url")` fonction in vanilla PHP or return a `RedirectResponse($url)` in your controller when using Symfony or Laravel frameworks` 62 | 63 | ### Donate Button for NGOs 64 | Once you sign up as an NGO Merchant 65 | 66 | ```php 67 | $donationUrl = $maxicash->donationUrl() 68 | ``` 69 | 70 | ## Features supported 71 | - [x] QueryString URL Payment 72 | - [x] Donate Button for NGOs 73 | - [ ] Form Post Payment 74 | - [ ] Pay Entry Web 75 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "devscast/maxicash", 3 | "description": "The MaxiCash integration platform enables merchants to integrate with the MaxiCash platform to receive payments via their mobile applications or websites. The API uses JSON to interact with .Net or open source platforms such as PHP.", 4 | "keywords": [ 5 | "maxicash", 6 | "mobile money", 7 | "payment gateway", 8 | "api" 9 | ], 10 | "type": "library", 11 | "license": "MIT", 12 | "autoload": { 13 | "psr-4": { 14 | "Devscast\\Maxicash\\": "src/" 15 | } 16 | }, 17 | "autoload-dev": { 18 | "psr-4": { 19 | "Devscast\\Maxicash\\Tests\\": "tests/" 20 | } 21 | }, 22 | "authors": [ 23 | { 24 | "name": "bernard-ng", 25 | "email": "ngandubernard@gmail.com" 26 | } 27 | ], 28 | "minimum-stability": "stable", 29 | "require-dev": { 30 | "phpstan/phpstan": "^1.10", 31 | "symplify/easy-coding-standard": "^12.0", 32 | "phpunit/phpunit": "^10.4" 33 | }, 34 | "require": { 35 | "php": ">=8.2", 36 | "webmozart/assert": "^1.11" 37 | }, 38 | "repositories": [ 39 | { 40 | "type": "vcs", 41 | "url": "https://github.com/devscast/maxicash" 42 | } 43 | ] 44 | } 45 | -------------------------------------------------------------------------------- /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": "3df3d7c6251738a7ab0733a4f9865fc5", 8 | "packages": [ 9 | { 10 | "name": "webmozart/assert", 11 | "version": "1.11.0", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/webmozarts/assert.git", 15 | "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", 20 | "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "ext-ctype": "*", 25 | "php": "^7.2 || ^8.0" 26 | }, 27 | "conflict": { 28 | "phpstan/phpstan": "<0.12.20", 29 | "vimeo/psalm": "<4.6.1 || 4.6.2" 30 | }, 31 | "require-dev": { 32 | "phpunit/phpunit": "^8.5.13" 33 | }, 34 | "type": "library", 35 | "extra": { 36 | "branch-alias": { 37 | "dev-master": "1.10-dev" 38 | } 39 | }, 40 | "autoload": { 41 | "psr-4": { 42 | "Webmozart\\Assert\\": "src/" 43 | } 44 | }, 45 | "notification-url": "https://packagist.org/downloads/", 46 | "license": [ 47 | "MIT" 48 | ], 49 | "authors": [ 50 | { 51 | "name": "Bernhard Schussek", 52 | "email": "bschussek@gmail.com" 53 | } 54 | ], 55 | "description": "Assertions to validate method input/output with nice error messages.", 56 | "keywords": [ 57 | "assert", 58 | "check", 59 | "validate" 60 | ], 61 | "support": { 62 | "issues": "https://github.com/webmozarts/assert/issues", 63 | "source": "https://github.com/webmozarts/assert/tree/1.11.0" 64 | }, 65 | "time": "2022-06-03T18:03:27+00:00" 66 | } 67 | ], 68 | "packages-dev": [ 69 | { 70 | "name": "myclabs/deep-copy", 71 | "version": "1.11.1", 72 | "source": { 73 | "type": "git", 74 | "url": "https://github.com/myclabs/DeepCopy.git", 75 | "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" 76 | }, 77 | "dist": { 78 | "type": "zip", 79 | "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", 80 | "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", 81 | "shasum": "" 82 | }, 83 | "require": { 84 | "php": "^7.1 || ^8.0" 85 | }, 86 | "conflict": { 87 | "doctrine/collections": "<1.6.8", 88 | "doctrine/common": "<2.13.3 || >=3,<3.2.2" 89 | }, 90 | "require-dev": { 91 | "doctrine/collections": "^1.6.8", 92 | "doctrine/common": "^2.13.3 || ^3.2.2", 93 | "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" 94 | }, 95 | "type": "library", 96 | "autoload": { 97 | "files": [ 98 | "src/DeepCopy/deep_copy.php" 99 | ], 100 | "psr-4": { 101 | "DeepCopy\\": "src/DeepCopy/" 102 | } 103 | }, 104 | "notification-url": "https://packagist.org/downloads/", 105 | "license": [ 106 | "MIT" 107 | ], 108 | "description": "Create deep copies (clones) of your objects", 109 | "keywords": [ 110 | "clone", 111 | "copy", 112 | "duplicate", 113 | "object", 114 | "object graph" 115 | ], 116 | "support": { 117 | "issues": "https://github.com/myclabs/DeepCopy/issues", 118 | "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" 119 | }, 120 | "funding": [ 121 | { 122 | "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", 123 | "type": "tidelift" 124 | } 125 | ], 126 | "time": "2023-03-08T13:26:56+00:00" 127 | }, 128 | { 129 | "name": "nikic/php-parser", 130 | "version": "v4.17.1", 131 | "source": { 132 | "type": "git", 133 | "url": "https://github.com/nikic/PHP-Parser.git", 134 | "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d" 135 | }, 136 | "dist": { 137 | "type": "zip", 138 | "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", 139 | "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", 140 | "shasum": "" 141 | }, 142 | "require": { 143 | "ext-tokenizer": "*", 144 | "php": ">=7.0" 145 | }, 146 | "require-dev": { 147 | "ircmaxell/php-yacc": "^0.0.7", 148 | "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" 149 | }, 150 | "bin": [ 151 | "bin/php-parse" 152 | ], 153 | "type": "library", 154 | "extra": { 155 | "branch-alias": { 156 | "dev-master": "4.9-dev" 157 | } 158 | }, 159 | "autoload": { 160 | "psr-4": { 161 | "PhpParser\\": "lib/PhpParser" 162 | } 163 | }, 164 | "notification-url": "https://packagist.org/downloads/", 165 | "license": [ 166 | "BSD-3-Clause" 167 | ], 168 | "authors": [ 169 | { 170 | "name": "Nikita Popov" 171 | } 172 | ], 173 | "description": "A PHP parser written in PHP", 174 | "keywords": [ 175 | "parser", 176 | "php" 177 | ], 178 | "support": { 179 | "issues": "https://github.com/nikic/PHP-Parser/issues", 180 | "source": "https://github.com/nikic/PHP-Parser/tree/v4.17.1" 181 | }, 182 | "time": "2023-08-13T19:53:39+00:00" 183 | }, 184 | { 185 | "name": "phar-io/manifest", 186 | "version": "2.0.3", 187 | "source": { 188 | "type": "git", 189 | "url": "https://github.com/phar-io/manifest.git", 190 | "reference": "97803eca37d319dfa7826cc2437fc020857acb53" 191 | }, 192 | "dist": { 193 | "type": "zip", 194 | "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", 195 | "reference": "97803eca37d319dfa7826cc2437fc020857acb53", 196 | "shasum": "" 197 | }, 198 | "require": { 199 | "ext-dom": "*", 200 | "ext-phar": "*", 201 | "ext-xmlwriter": "*", 202 | "phar-io/version": "^3.0.1", 203 | "php": "^7.2 || ^8.0" 204 | }, 205 | "type": "library", 206 | "extra": { 207 | "branch-alias": { 208 | "dev-master": "2.0.x-dev" 209 | } 210 | }, 211 | "autoload": { 212 | "classmap": [ 213 | "src/" 214 | ] 215 | }, 216 | "notification-url": "https://packagist.org/downloads/", 217 | "license": [ 218 | "BSD-3-Clause" 219 | ], 220 | "authors": [ 221 | { 222 | "name": "Arne Blankerts", 223 | "email": "arne@blankerts.de", 224 | "role": "Developer" 225 | }, 226 | { 227 | "name": "Sebastian Heuer", 228 | "email": "sebastian@phpeople.de", 229 | "role": "Developer" 230 | }, 231 | { 232 | "name": "Sebastian Bergmann", 233 | "email": "sebastian@phpunit.de", 234 | "role": "Developer" 235 | } 236 | ], 237 | "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", 238 | "support": { 239 | "issues": "https://github.com/phar-io/manifest/issues", 240 | "source": "https://github.com/phar-io/manifest/tree/2.0.3" 241 | }, 242 | "time": "2021-07-20T11:28:43+00:00" 243 | }, 244 | { 245 | "name": "phar-io/version", 246 | "version": "3.2.1", 247 | "source": { 248 | "type": "git", 249 | "url": "https://github.com/phar-io/version.git", 250 | "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" 251 | }, 252 | "dist": { 253 | "type": "zip", 254 | "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", 255 | "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", 256 | "shasum": "" 257 | }, 258 | "require": { 259 | "php": "^7.2 || ^8.0" 260 | }, 261 | "type": "library", 262 | "autoload": { 263 | "classmap": [ 264 | "src/" 265 | ] 266 | }, 267 | "notification-url": "https://packagist.org/downloads/", 268 | "license": [ 269 | "BSD-3-Clause" 270 | ], 271 | "authors": [ 272 | { 273 | "name": "Arne Blankerts", 274 | "email": "arne@blankerts.de", 275 | "role": "Developer" 276 | }, 277 | { 278 | "name": "Sebastian Heuer", 279 | "email": "sebastian@phpeople.de", 280 | "role": "Developer" 281 | }, 282 | { 283 | "name": "Sebastian Bergmann", 284 | "email": "sebastian@phpunit.de", 285 | "role": "Developer" 286 | } 287 | ], 288 | "description": "Library for handling version information and constraints", 289 | "support": { 290 | "issues": "https://github.com/phar-io/version/issues", 291 | "source": "https://github.com/phar-io/version/tree/3.2.1" 292 | }, 293 | "time": "2022-02-21T01:04:05+00:00" 294 | }, 295 | { 296 | "name": "phpstan/phpstan", 297 | "version": "1.10.38", 298 | "source": { 299 | "type": "git", 300 | "url": "https://github.com/phpstan/phpstan.git", 301 | "reference": "5302bb402c57f00fb3c2c015bac86e0827e4b691" 302 | }, 303 | "dist": { 304 | "type": "zip", 305 | "url": "https://api.github.com/repos/phpstan/phpstan/zipball/5302bb402c57f00fb3c2c015bac86e0827e4b691", 306 | "reference": "5302bb402c57f00fb3c2c015bac86e0827e4b691", 307 | "shasum": "" 308 | }, 309 | "require": { 310 | "php": "^7.2|^8.0" 311 | }, 312 | "conflict": { 313 | "phpstan/phpstan-shim": "*" 314 | }, 315 | "bin": [ 316 | "phpstan", 317 | "phpstan.phar" 318 | ], 319 | "type": "library", 320 | "autoload": { 321 | "files": [ 322 | "bootstrap.php" 323 | ] 324 | }, 325 | "notification-url": "https://packagist.org/downloads/", 326 | "license": [ 327 | "MIT" 328 | ], 329 | "description": "PHPStan - PHP Static Analysis Tool", 330 | "keywords": [ 331 | "dev", 332 | "static analysis" 333 | ], 334 | "support": { 335 | "docs": "https://phpstan.org/user-guide/getting-started", 336 | "forum": "https://github.com/phpstan/phpstan/discussions", 337 | "issues": "https://github.com/phpstan/phpstan/issues", 338 | "security": "https://github.com/phpstan/phpstan/security/policy", 339 | "source": "https://github.com/phpstan/phpstan-src" 340 | }, 341 | "funding": [ 342 | { 343 | "url": "https://github.com/ondrejmirtes", 344 | "type": "github" 345 | }, 346 | { 347 | "url": "https://github.com/phpstan", 348 | "type": "github" 349 | }, 350 | { 351 | "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", 352 | "type": "tidelift" 353 | } 354 | ], 355 | "time": "2023-10-06T14:19:14+00:00" 356 | }, 357 | { 358 | "name": "phpunit/php-code-coverage", 359 | "version": "10.1.7", 360 | "source": { 361 | "type": "git", 362 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 363 | "reference": "355324ca4980b8916c18b9db29f3ef484078f26e" 364 | }, 365 | "dist": { 366 | "type": "zip", 367 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/355324ca4980b8916c18b9db29f3ef484078f26e", 368 | "reference": "355324ca4980b8916c18b9db29f3ef484078f26e", 369 | "shasum": "" 370 | }, 371 | "require": { 372 | "ext-dom": "*", 373 | "ext-libxml": "*", 374 | "ext-xmlwriter": "*", 375 | "nikic/php-parser": "^4.15", 376 | "php": ">=8.1", 377 | "phpunit/php-file-iterator": "^4.0", 378 | "phpunit/php-text-template": "^3.0", 379 | "sebastian/code-unit-reverse-lookup": "^3.0", 380 | "sebastian/complexity": "^3.0", 381 | "sebastian/environment": "^6.0", 382 | "sebastian/lines-of-code": "^2.0", 383 | "sebastian/version": "^4.0", 384 | "theseer/tokenizer": "^1.2.0" 385 | }, 386 | "require-dev": { 387 | "phpunit/phpunit": "^10.1" 388 | }, 389 | "suggest": { 390 | "ext-pcov": "PHP extension that provides line coverage", 391 | "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" 392 | }, 393 | "type": "library", 394 | "extra": { 395 | "branch-alias": { 396 | "dev-main": "10.1-dev" 397 | } 398 | }, 399 | "autoload": { 400 | "classmap": [ 401 | "src/" 402 | ] 403 | }, 404 | "notification-url": "https://packagist.org/downloads/", 405 | "license": [ 406 | "BSD-3-Clause" 407 | ], 408 | "authors": [ 409 | { 410 | "name": "Sebastian Bergmann", 411 | "email": "sebastian@phpunit.de", 412 | "role": "lead" 413 | } 414 | ], 415 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 416 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 417 | "keywords": [ 418 | "coverage", 419 | "testing", 420 | "xunit" 421 | ], 422 | "support": { 423 | "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", 424 | "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", 425 | "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.7" 426 | }, 427 | "funding": [ 428 | { 429 | "url": "https://github.com/sebastianbergmann", 430 | "type": "github" 431 | } 432 | ], 433 | "time": "2023-10-04T15:34:17+00:00" 434 | }, 435 | { 436 | "name": "phpunit/php-file-iterator", 437 | "version": "4.1.0", 438 | "source": { 439 | "type": "git", 440 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 441 | "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c" 442 | }, 443 | "dist": { 444 | "type": "zip", 445 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c", 446 | "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c", 447 | "shasum": "" 448 | }, 449 | "require": { 450 | "php": ">=8.1" 451 | }, 452 | "require-dev": { 453 | "phpunit/phpunit": "^10.0" 454 | }, 455 | "type": "library", 456 | "extra": { 457 | "branch-alias": { 458 | "dev-main": "4.0-dev" 459 | } 460 | }, 461 | "autoload": { 462 | "classmap": [ 463 | "src/" 464 | ] 465 | }, 466 | "notification-url": "https://packagist.org/downloads/", 467 | "license": [ 468 | "BSD-3-Clause" 469 | ], 470 | "authors": [ 471 | { 472 | "name": "Sebastian Bergmann", 473 | "email": "sebastian@phpunit.de", 474 | "role": "lead" 475 | } 476 | ], 477 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 478 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 479 | "keywords": [ 480 | "filesystem", 481 | "iterator" 482 | ], 483 | "support": { 484 | "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", 485 | "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", 486 | "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.1.0" 487 | }, 488 | "funding": [ 489 | { 490 | "url": "https://github.com/sebastianbergmann", 491 | "type": "github" 492 | } 493 | ], 494 | "time": "2023-08-31T06:24:48+00:00" 495 | }, 496 | { 497 | "name": "phpunit/php-invoker", 498 | "version": "4.0.0", 499 | "source": { 500 | "type": "git", 501 | "url": "https://github.com/sebastianbergmann/php-invoker.git", 502 | "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7" 503 | }, 504 | "dist": { 505 | "type": "zip", 506 | "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", 507 | "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", 508 | "shasum": "" 509 | }, 510 | "require": { 511 | "php": ">=8.1" 512 | }, 513 | "require-dev": { 514 | "ext-pcntl": "*", 515 | "phpunit/phpunit": "^10.0" 516 | }, 517 | "suggest": { 518 | "ext-pcntl": "*" 519 | }, 520 | "type": "library", 521 | "extra": { 522 | "branch-alias": { 523 | "dev-main": "4.0-dev" 524 | } 525 | }, 526 | "autoload": { 527 | "classmap": [ 528 | "src/" 529 | ] 530 | }, 531 | "notification-url": "https://packagist.org/downloads/", 532 | "license": [ 533 | "BSD-3-Clause" 534 | ], 535 | "authors": [ 536 | { 537 | "name": "Sebastian Bergmann", 538 | "email": "sebastian@phpunit.de", 539 | "role": "lead" 540 | } 541 | ], 542 | "description": "Invoke callables with a timeout", 543 | "homepage": "https://github.com/sebastianbergmann/php-invoker/", 544 | "keywords": [ 545 | "process" 546 | ], 547 | "support": { 548 | "issues": "https://github.com/sebastianbergmann/php-invoker/issues", 549 | "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0.0" 550 | }, 551 | "funding": [ 552 | { 553 | "url": "https://github.com/sebastianbergmann", 554 | "type": "github" 555 | } 556 | ], 557 | "time": "2023-02-03T06:56:09+00:00" 558 | }, 559 | { 560 | "name": "phpunit/php-text-template", 561 | "version": "3.0.1", 562 | "source": { 563 | "type": "git", 564 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 565 | "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748" 566 | }, 567 | "dist": { 568 | "type": "zip", 569 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748", 570 | "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748", 571 | "shasum": "" 572 | }, 573 | "require": { 574 | "php": ">=8.1" 575 | }, 576 | "require-dev": { 577 | "phpunit/phpunit": "^10.0" 578 | }, 579 | "type": "library", 580 | "extra": { 581 | "branch-alias": { 582 | "dev-main": "3.0-dev" 583 | } 584 | }, 585 | "autoload": { 586 | "classmap": [ 587 | "src/" 588 | ] 589 | }, 590 | "notification-url": "https://packagist.org/downloads/", 591 | "license": [ 592 | "BSD-3-Clause" 593 | ], 594 | "authors": [ 595 | { 596 | "name": "Sebastian Bergmann", 597 | "email": "sebastian@phpunit.de", 598 | "role": "lead" 599 | } 600 | ], 601 | "description": "Simple template engine.", 602 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 603 | "keywords": [ 604 | "template" 605 | ], 606 | "support": { 607 | "issues": "https://github.com/sebastianbergmann/php-text-template/issues", 608 | "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", 609 | "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.1" 610 | }, 611 | "funding": [ 612 | { 613 | "url": "https://github.com/sebastianbergmann", 614 | "type": "github" 615 | } 616 | ], 617 | "time": "2023-08-31T14:07:24+00:00" 618 | }, 619 | { 620 | "name": "phpunit/php-timer", 621 | "version": "6.0.0", 622 | "source": { 623 | "type": "git", 624 | "url": "https://github.com/sebastianbergmann/php-timer.git", 625 | "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d" 626 | }, 627 | "dist": { 628 | "type": "zip", 629 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/e2a2d67966e740530f4a3343fe2e030ffdc1161d", 630 | "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d", 631 | "shasum": "" 632 | }, 633 | "require": { 634 | "php": ">=8.1" 635 | }, 636 | "require-dev": { 637 | "phpunit/phpunit": "^10.0" 638 | }, 639 | "type": "library", 640 | "extra": { 641 | "branch-alias": { 642 | "dev-main": "6.0-dev" 643 | } 644 | }, 645 | "autoload": { 646 | "classmap": [ 647 | "src/" 648 | ] 649 | }, 650 | "notification-url": "https://packagist.org/downloads/", 651 | "license": [ 652 | "BSD-3-Clause" 653 | ], 654 | "authors": [ 655 | { 656 | "name": "Sebastian Bergmann", 657 | "email": "sebastian@phpunit.de", 658 | "role": "lead" 659 | } 660 | ], 661 | "description": "Utility class for timing", 662 | "homepage": "https://github.com/sebastianbergmann/php-timer/", 663 | "keywords": [ 664 | "timer" 665 | ], 666 | "support": { 667 | "issues": "https://github.com/sebastianbergmann/php-timer/issues", 668 | "source": "https://github.com/sebastianbergmann/php-timer/tree/6.0.0" 669 | }, 670 | "funding": [ 671 | { 672 | "url": "https://github.com/sebastianbergmann", 673 | "type": "github" 674 | } 675 | ], 676 | "time": "2023-02-03T06:57:52+00:00" 677 | }, 678 | { 679 | "name": "phpunit/phpunit", 680 | "version": "10.4.1", 681 | "source": { 682 | "type": "git", 683 | "url": "https://github.com/sebastianbergmann/phpunit.git", 684 | "reference": "62bd7af13d282deeb95650077d28ba3600ca321c" 685 | }, 686 | "dist": { 687 | "type": "zip", 688 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/62bd7af13d282deeb95650077d28ba3600ca321c", 689 | "reference": "62bd7af13d282deeb95650077d28ba3600ca321c", 690 | "shasum": "" 691 | }, 692 | "require": { 693 | "ext-dom": "*", 694 | "ext-json": "*", 695 | "ext-libxml": "*", 696 | "ext-mbstring": "*", 697 | "ext-xml": "*", 698 | "ext-xmlwriter": "*", 699 | "myclabs/deep-copy": "^1.10.1", 700 | "phar-io/manifest": "^2.0.3", 701 | "phar-io/version": "^3.0.2", 702 | "php": ">=8.1", 703 | "phpunit/php-code-coverage": "^10.1.5", 704 | "phpunit/php-file-iterator": "^4.0", 705 | "phpunit/php-invoker": "^4.0", 706 | "phpunit/php-text-template": "^3.0", 707 | "phpunit/php-timer": "^6.0", 708 | "sebastian/cli-parser": "^2.0", 709 | "sebastian/code-unit": "^2.0", 710 | "sebastian/comparator": "^5.0", 711 | "sebastian/diff": "^5.0", 712 | "sebastian/environment": "^6.0", 713 | "sebastian/exporter": "^5.1", 714 | "sebastian/global-state": "^6.0.1", 715 | "sebastian/object-enumerator": "^5.0", 716 | "sebastian/recursion-context": "^5.0", 717 | "sebastian/type": "^4.0", 718 | "sebastian/version": "^4.0" 719 | }, 720 | "suggest": { 721 | "ext-soap": "To be able to generate mocks based on WSDL files" 722 | }, 723 | "bin": [ 724 | "phpunit" 725 | ], 726 | "type": "library", 727 | "extra": { 728 | "branch-alias": { 729 | "dev-main": "10.4-dev" 730 | } 731 | }, 732 | "autoload": { 733 | "files": [ 734 | "src/Framework/Assert/Functions.php" 735 | ], 736 | "classmap": [ 737 | "src/" 738 | ] 739 | }, 740 | "notification-url": "https://packagist.org/downloads/", 741 | "license": [ 742 | "BSD-3-Clause" 743 | ], 744 | "authors": [ 745 | { 746 | "name": "Sebastian Bergmann", 747 | "email": "sebastian@phpunit.de", 748 | "role": "lead" 749 | } 750 | ], 751 | "description": "The PHP Unit Testing framework.", 752 | "homepage": "https://phpunit.de/", 753 | "keywords": [ 754 | "phpunit", 755 | "testing", 756 | "xunit" 757 | ], 758 | "support": { 759 | "issues": "https://github.com/sebastianbergmann/phpunit/issues", 760 | "security": "https://github.com/sebastianbergmann/phpunit/security/policy", 761 | "source": "https://github.com/sebastianbergmann/phpunit/tree/10.4.1" 762 | }, 763 | "funding": [ 764 | { 765 | "url": "https://phpunit.de/sponsors.html", 766 | "type": "custom" 767 | }, 768 | { 769 | "url": "https://github.com/sebastianbergmann", 770 | "type": "github" 771 | }, 772 | { 773 | "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", 774 | "type": "tidelift" 775 | } 776 | ], 777 | "time": "2023-10-08T05:01:11+00:00" 778 | }, 779 | { 780 | "name": "sebastian/cli-parser", 781 | "version": "2.0.0", 782 | "source": { 783 | "type": "git", 784 | "url": "https://github.com/sebastianbergmann/cli-parser.git", 785 | "reference": "efdc130dbbbb8ef0b545a994fd811725c5282cae" 786 | }, 787 | "dist": { 788 | "type": "zip", 789 | "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/efdc130dbbbb8ef0b545a994fd811725c5282cae", 790 | "reference": "efdc130dbbbb8ef0b545a994fd811725c5282cae", 791 | "shasum": "" 792 | }, 793 | "require": { 794 | "php": ">=8.1" 795 | }, 796 | "require-dev": { 797 | "phpunit/phpunit": "^10.0" 798 | }, 799 | "type": "library", 800 | "extra": { 801 | "branch-alias": { 802 | "dev-main": "2.0-dev" 803 | } 804 | }, 805 | "autoload": { 806 | "classmap": [ 807 | "src/" 808 | ] 809 | }, 810 | "notification-url": "https://packagist.org/downloads/", 811 | "license": [ 812 | "BSD-3-Clause" 813 | ], 814 | "authors": [ 815 | { 816 | "name": "Sebastian Bergmann", 817 | "email": "sebastian@phpunit.de", 818 | "role": "lead" 819 | } 820 | ], 821 | "description": "Library for parsing CLI options", 822 | "homepage": "https://github.com/sebastianbergmann/cli-parser", 823 | "support": { 824 | "issues": "https://github.com/sebastianbergmann/cli-parser/issues", 825 | "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.0" 826 | }, 827 | "funding": [ 828 | { 829 | "url": "https://github.com/sebastianbergmann", 830 | "type": "github" 831 | } 832 | ], 833 | "time": "2023-02-03T06:58:15+00:00" 834 | }, 835 | { 836 | "name": "sebastian/code-unit", 837 | "version": "2.0.0", 838 | "source": { 839 | "type": "git", 840 | "url": "https://github.com/sebastianbergmann/code-unit.git", 841 | "reference": "a81fee9eef0b7a76af11d121767abc44c104e503" 842 | }, 843 | "dist": { 844 | "type": "zip", 845 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/a81fee9eef0b7a76af11d121767abc44c104e503", 846 | "reference": "a81fee9eef0b7a76af11d121767abc44c104e503", 847 | "shasum": "" 848 | }, 849 | "require": { 850 | "php": ">=8.1" 851 | }, 852 | "require-dev": { 853 | "phpunit/phpunit": "^10.0" 854 | }, 855 | "type": "library", 856 | "extra": { 857 | "branch-alias": { 858 | "dev-main": "2.0-dev" 859 | } 860 | }, 861 | "autoload": { 862 | "classmap": [ 863 | "src/" 864 | ] 865 | }, 866 | "notification-url": "https://packagist.org/downloads/", 867 | "license": [ 868 | "BSD-3-Clause" 869 | ], 870 | "authors": [ 871 | { 872 | "name": "Sebastian Bergmann", 873 | "email": "sebastian@phpunit.de", 874 | "role": "lead" 875 | } 876 | ], 877 | "description": "Collection of value objects that represent the PHP code units", 878 | "homepage": "https://github.com/sebastianbergmann/code-unit", 879 | "support": { 880 | "issues": "https://github.com/sebastianbergmann/code-unit/issues", 881 | "source": "https://github.com/sebastianbergmann/code-unit/tree/2.0.0" 882 | }, 883 | "funding": [ 884 | { 885 | "url": "https://github.com/sebastianbergmann", 886 | "type": "github" 887 | } 888 | ], 889 | "time": "2023-02-03T06:58:43+00:00" 890 | }, 891 | { 892 | "name": "sebastian/code-unit-reverse-lookup", 893 | "version": "3.0.0", 894 | "source": { 895 | "type": "git", 896 | "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", 897 | "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d" 898 | }, 899 | "dist": { 900 | "type": "zip", 901 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", 902 | "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", 903 | "shasum": "" 904 | }, 905 | "require": { 906 | "php": ">=8.1" 907 | }, 908 | "require-dev": { 909 | "phpunit/phpunit": "^10.0" 910 | }, 911 | "type": "library", 912 | "extra": { 913 | "branch-alias": { 914 | "dev-main": "3.0-dev" 915 | } 916 | }, 917 | "autoload": { 918 | "classmap": [ 919 | "src/" 920 | ] 921 | }, 922 | "notification-url": "https://packagist.org/downloads/", 923 | "license": [ 924 | "BSD-3-Clause" 925 | ], 926 | "authors": [ 927 | { 928 | "name": "Sebastian Bergmann", 929 | "email": "sebastian@phpunit.de" 930 | } 931 | ], 932 | "description": "Looks up which function or method a line of code belongs to", 933 | "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", 934 | "support": { 935 | "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", 936 | "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/3.0.0" 937 | }, 938 | "funding": [ 939 | { 940 | "url": "https://github.com/sebastianbergmann", 941 | "type": "github" 942 | } 943 | ], 944 | "time": "2023-02-03T06:59:15+00:00" 945 | }, 946 | { 947 | "name": "sebastian/comparator", 948 | "version": "5.0.1", 949 | "source": { 950 | "type": "git", 951 | "url": "https://github.com/sebastianbergmann/comparator.git", 952 | "reference": "2db5010a484d53ebf536087a70b4a5423c102372" 953 | }, 954 | "dist": { 955 | "type": "zip", 956 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2db5010a484d53ebf536087a70b4a5423c102372", 957 | "reference": "2db5010a484d53ebf536087a70b4a5423c102372", 958 | "shasum": "" 959 | }, 960 | "require": { 961 | "ext-dom": "*", 962 | "ext-mbstring": "*", 963 | "php": ">=8.1", 964 | "sebastian/diff": "^5.0", 965 | "sebastian/exporter": "^5.0" 966 | }, 967 | "require-dev": { 968 | "phpunit/phpunit": "^10.3" 969 | }, 970 | "type": "library", 971 | "extra": { 972 | "branch-alias": { 973 | "dev-main": "5.0-dev" 974 | } 975 | }, 976 | "autoload": { 977 | "classmap": [ 978 | "src/" 979 | ] 980 | }, 981 | "notification-url": "https://packagist.org/downloads/", 982 | "license": [ 983 | "BSD-3-Clause" 984 | ], 985 | "authors": [ 986 | { 987 | "name": "Sebastian Bergmann", 988 | "email": "sebastian@phpunit.de" 989 | }, 990 | { 991 | "name": "Jeff Welch", 992 | "email": "whatthejeff@gmail.com" 993 | }, 994 | { 995 | "name": "Volker Dusch", 996 | "email": "github@wallbash.com" 997 | }, 998 | { 999 | "name": "Bernhard Schussek", 1000 | "email": "bschussek@2bepublished.at" 1001 | } 1002 | ], 1003 | "description": "Provides the functionality to compare PHP values for equality", 1004 | "homepage": "https://github.com/sebastianbergmann/comparator", 1005 | "keywords": [ 1006 | "comparator", 1007 | "compare", 1008 | "equality" 1009 | ], 1010 | "support": { 1011 | "issues": "https://github.com/sebastianbergmann/comparator/issues", 1012 | "security": "https://github.com/sebastianbergmann/comparator/security/policy", 1013 | "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.1" 1014 | }, 1015 | "funding": [ 1016 | { 1017 | "url": "https://github.com/sebastianbergmann", 1018 | "type": "github" 1019 | } 1020 | ], 1021 | "time": "2023-08-14T13:18:12+00:00" 1022 | }, 1023 | { 1024 | "name": "sebastian/complexity", 1025 | "version": "3.1.0", 1026 | "source": { 1027 | "type": "git", 1028 | "url": "https://github.com/sebastianbergmann/complexity.git", 1029 | "reference": "68cfb347a44871f01e33ab0ef8215966432f6957" 1030 | }, 1031 | "dist": { 1032 | "type": "zip", 1033 | "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68cfb347a44871f01e33ab0ef8215966432f6957", 1034 | "reference": "68cfb347a44871f01e33ab0ef8215966432f6957", 1035 | "shasum": "" 1036 | }, 1037 | "require": { 1038 | "nikic/php-parser": "^4.10", 1039 | "php": ">=8.1" 1040 | }, 1041 | "require-dev": { 1042 | "phpunit/phpunit": "^10.0" 1043 | }, 1044 | "type": "library", 1045 | "extra": { 1046 | "branch-alias": { 1047 | "dev-main": "3.1-dev" 1048 | } 1049 | }, 1050 | "autoload": { 1051 | "classmap": [ 1052 | "src/" 1053 | ] 1054 | }, 1055 | "notification-url": "https://packagist.org/downloads/", 1056 | "license": [ 1057 | "BSD-3-Clause" 1058 | ], 1059 | "authors": [ 1060 | { 1061 | "name": "Sebastian Bergmann", 1062 | "email": "sebastian@phpunit.de", 1063 | "role": "lead" 1064 | } 1065 | ], 1066 | "description": "Library for calculating the complexity of PHP code units", 1067 | "homepage": "https://github.com/sebastianbergmann/complexity", 1068 | "support": { 1069 | "issues": "https://github.com/sebastianbergmann/complexity/issues", 1070 | "security": "https://github.com/sebastianbergmann/complexity/security/policy", 1071 | "source": "https://github.com/sebastianbergmann/complexity/tree/3.1.0" 1072 | }, 1073 | "funding": [ 1074 | { 1075 | "url": "https://github.com/sebastianbergmann", 1076 | "type": "github" 1077 | } 1078 | ], 1079 | "time": "2023-09-28T11:50:59+00:00" 1080 | }, 1081 | { 1082 | "name": "sebastian/diff", 1083 | "version": "5.0.3", 1084 | "source": { 1085 | "type": "git", 1086 | "url": "https://github.com/sebastianbergmann/diff.git", 1087 | "reference": "912dc2fbe3e3c1e7873313cc801b100b6c68c87b" 1088 | }, 1089 | "dist": { 1090 | "type": "zip", 1091 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/912dc2fbe3e3c1e7873313cc801b100b6c68c87b", 1092 | "reference": "912dc2fbe3e3c1e7873313cc801b100b6c68c87b", 1093 | "shasum": "" 1094 | }, 1095 | "require": { 1096 | "php": ">=8.1" 1097 | }, 1098 | "require-dev": { 1099 | "phpunit/phpunit": "^10.0", 1100 | "symfony/process": "^4.2 || ^5" 1101 | }, 1102 | "type": "library", 1103 | "extra": { 1104 | "branch-alias": { 1105 | "dev-main": "5.0-dev" 1106 | } 1107 | }, 1108 | "autoload": { 1109 | "classmap": [ 1110 | "src/" 1111 | ] 1112 | }, 1113 | "notification-url": "https://packagist.org/downloads/", 1114 | "license": [ 1115 | "BSD-3-Clause" 1116 | ], 1117 | "authors": [ 1118 | { 1119 | "name": "Sebastian Bergmann", 1120 | "email": "sebastian@phpunit.de" 1121 | }, 1122 | { 1123 | "name": "Kore Nordmann", 1124 | "email": "mail@kore-nordmann.de" 1125 | } 1126 | ], 1127 | "description": "Diff implementation", 1128 | "homepage": "https://github.com/sebastianbergmann/diff", 1129 | "keywords": [ 1130 | "diff", 1131 | "udiff", 1132 | "unidiff", 1133 | "unified diff" 1134 | ], 1135 | "support": { 1136 | "issues": "https://github.com/sebastianbergmann/diff/issues", 1137 | "security": "https://github.com/sebastianbergmann/diff/security/policy", 1138 | "source": "https://github.com/sebastianbergmann/diff/tree/5.0.3" 1139 | }, 1140 | "funding": [ 1141 | { 1142 | "url": "https://github.com/sebastianbergmann", 1143 | "type": "github" 1144 | } 1145 | ], 1146 | "time": "2023-05-01T07:48:21+00:00" 1147 | }, 1148 | { 1149 | "name": "sebastian/environment", 1150 | "version": "6.0.1", 1151 | "source": { 1152 | "type": "git", 1153 | "url": "https://github.com/sebastianbergmann/environment.git", 1154 | "reference": "43c751b41d74f96cbbd4e07b7aec9675651e2951" 1155 | }, 1156 | "dist": { 1157 | "type": "zip", 1158 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/43c751b41d74f96cbbd4e07b7aec9675651e2951", 1159 | "reference": "43c751b41d74f96cbbd4e07b7aec9675651e2951", 1160 | "shasum": "" 1161 | }, 1162 | "require": { 1163 | "php": ">=8.1" 1164 | }, 1165 | "require-dev": { 1166 | "phpunit/phpunit": "^10.0" 1167 | }, 1168 | "suggest": { 1169 | "ext-posix": "*" 1170 | }, 1171 | "type": "library", 1172 | "extra": { 1173 | "branch-alias": { 1174 | "dev-main": "6.0-dev" 1175 | } 1176 | }, 1177 | "autoload": { 1178 | "classmap": [ 1179 | "src/" 1180 | ] 1181 | }, 1182 | "notification-url": "https://packagist.org/downloads/", 1183 | "license": [ 1184 | "BSD-3-Clause" 1185 | ], 1186 | "authors": [ 1187 | { 1188 | "name": "Sebastian Bergmann", 1189 | "email": "sebastian@phpunit.de" 1190 | } 1191 | ], 1192 | "description": "Provides functionality to handle HHVM/PHP environments", 1193 | "homepage": "https://github.com/sebastianbergmann/environment", 1194 | "keywords": [ 1195 | "Xdebug", 1196 | "environment", 1197 | "hhvm" 1198 | ], 1199 | "support": { 1200 | "issues": "https://github.com/sebastianbergmann/environment/issues", 1201 | "security": "https://github.com/sebastianbergmann/environment/security/policy", 1202 | "source": "https://github.com/sebastianbergmann/environment/tree/6.0.1" 1203 | }, 1204 | "funding": [ 1205 | { 1206 | "url": "https://github.com/sebastianbergmann", 1207 | "type": "github" 1208 | } 1209 | ], 1210 | "time": "2023-04-11T05:39:26+00:00" 1211 | }, 1212 | { 1213 | "name": "sebastian/exporter", 1214 | "version": "5.1.1", 1215 | "source": { 1216 | "type": "git", 1217 | "url": "https://github.com/sebastianbergmann/exporter.git", 1218 | "reference": "64f51654862e0f5e318db7e9dcc2292c63cdbddc" 1219 | }, 1220 | "dist": { 1221 | "type": "zip", 1222 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/64f51654862e0f5e318db7e9dcc2292c63cdbddc", 1223 | "reference": "64f51654862e0f5e318db7e9dcc2292c63cdbddc", 1224 | "shasum": "" 1225 | }, 1226 | "require": { 1227 | "ext-mbstring": "*", 1228 | "php": ">=8.1", 1229 | "sebastian/recursion-context": "^5.0" 1230 | }, 1231 | "require-dev": { 1232 | "phpunit/phpunit": "^10.0" 1233 | }, 1234 | "type": "library", 1235 | "extra": { 1236 | "branch-alias": { 1237 | "dev-main": "5.1-dev" 1238 | } 1239 | }, 1240 | "autoload": { 1241 | "classmap": [ 1242 | "src/" 1243 | ] 1244 | }, 1245 | "notification-url": "https://packagist.org/downloads/", 1246 | "license": [ 1247 | "BSD-3-Clause" 1248 | ], 1249 | "authors": [ 1250 | { 1251 | "name": "Sebastian Bergmann", 1252 | "email": "sebastian@phpunit.de" 1253 | }, 1254 | { 1255 | "name": "Jeff Welch", 1256 | "email": "whatthejeff@gmail.com" 1257 | }, 1258 | { 1259 | "name": "Volker Dusch", 1260 | "email": "github@wallbash.com" 1261 | }, 1262 | { 1263 | "name": "Adam Harvey", 1264 | "email": "aharvey@php.net" 1265 | }, 1266 | { 1267 | "name": "Bernhard Schussek", 1268 | "email": "bschussek@gmail.com" 1269 | } 1270 | ], 1271 | "description": "Provides the functionality to export PHP variables for visualization", 1272 | "homepage": "https://www.github.com/sebastianbergmann/exporter", 1273 | "keywords": [ 1274 | "export", 1275 | "exporter" 1276 | ], 1277 | "support": { 1278 | "issues": "https://github.com/sebastianbergmann/exporter/issues", 1279 | "security": "https://github.com/sebastianbergmann/exporter/security/policy", 1280 | "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.1" 1281 | }, 1282 | "funding": [ 1283 | { 1284 | "url": "https://github.com/sebastianbergmann", 1285 | "type": "github" 1286 | } 1287 | ], 1288 | "time": "2023-09-24T13:22:09+00:00" 1289 | }, 1290 | { 1291 | "name": "sebastian/global-state", 1292 | "version": "6.0.1", 1293 | "source": { 1294 | "type": "git", 1295 | "url": "https://github.com/sebastianbergmann/global-state.git", 1296 | "reference": "7ea9ead78f6d380d2a667864c132c2f7b83055e4" 1297 | }, 1298 | "dist": { 1299 | "type": "zip", 1300 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/7ea9ead78f6d380d2a667864c132c2f7b83055e4", 1301 | "reference": "7ea9ead78f6d380d2a667864c132c2f7b83055e4", 1302 | "shasum": "" 1303 | }, 1304 | "require": { 1305 | "php": ">=8.1", 1306 | "sebastian/object-reflector": "^3.0", 1307 | "sebastian/recursion-context": "^5.0" 1308 | }, 1309 | "require-dev": { 1310 | "ext-dom": "*", 1311 | "phpunit/phpunit": "^10.0" 1312 | }, 1313 | "type": "library", 1314 | "extra": { 1315 | "branch-alias": { 1316 | "dev-main": "6.0-dev" 1317 | } 1318 | }, 1319 | "autoload": { 1320 | "classmap": [ 1321 | "src/" 1322 | ] 1323 | }, 1324 | "notification-url": "https://packagist.org/downloads/", 1325 | "license": [ 1326 | "BSD-3-Clause" 1327 | ], 1328 | "authors": [ 1329 | { 1330 | "name": "Sebastian Bergmann", 1331 | "email": "sebastian@phpunit.de" 1332 | } 1333 | ], 1334 | "description": "Snapshotting of global state", 1335 | "homepage": "http://www.github.com/sebastianbergmann/global-state", 1336 | "keywords": [ 1337 | "global state" 1338 | ], 1339 | "support": { 1340 | "issues": "https://github.com/sebastianbergmann/global-state/issues", 1341 | "security": "https://github.com/sebastianbergmann/global-state/security/policy", 1342 | "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.1" 1343 | }, 1344 | "funding": [ 1345 | { 1346 | "url": "https://github.com/sebastianbergmann", 1347 | "type": "github" 1348 | } 1349 | ], 1350 | "time": "2023-07-19T07:19:23+00:00" 1351 | }, 1352 | { 1353 | "name": "sebastian/lines-of-code", 1354 | "version": "2.0.1", 1355 | "source": { 1356 | "type": "git", 1357 | "url": "https://github.com/sebastianbergmann/lines-of-code.git", 1358 | "reference": "649e40d279e243d985aa8fb6e74dd5bb28dc185d" 1359 | }, 1360 | "dist": { 1361 | "type": "zip", 1362 | "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/649e40d279e243d985aa8fb6e74dd5bb28dc185d", 1363 | "reference": "649e40d279e243d985aa8fb6e74dd5bb28dc185d", 1364 | "shasum": "" 1365 | }, 1366 | "require": { 1367 | "nikic/php-parser": "^4.10", 1368 | "php": ">=8.1" 1369 | }, 1370 | "require-dev": { 1371 | "phpunit/phpunit": "^10.0" 1372 | }, 1373 | "type": "library", 1374 | "extra": { 1375 | "branch-alias": { 1376 | "dev-main": "2.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": "Library for counting the lines of code in PHP source code", 1396 | "homepage": "https://github.com/sebastianbergmann/lines-of-code", 1397 | "support": { 1398 | "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", 1399 | "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", 1400 | "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.1" 1401 | }, 1402 | "funding": [ 1403 | { 1404 | "url": "https://github.com/sebastianbergmann", 1405 | "type": "github" 1406 | } 1407 | ], 1408 | "time": "2023-08-31T09:25:50+00:00" 1409 | }, 1410 | { 1411 | "name": "sebastian/object-enumerator", 1412 | "version": "5.0.0", 1413 | "source": { 1414 | "type": "git", 1415 | "url": "https://github.com/sebastianbergmann/object-enumerator.git", 1416 | "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906" 1417 | }, 1418 | "dist": { 1419 | "type": "zip", 1420 | "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/202d0e344a580d7f7d04b3fafce6933e59dae906", 1421 | "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906", 1422 | "shasum": "" 1423 | }, 1424 | "require": { 1425 | "php": ">=8.1", 1426 | "sebastian/object-reflector": "^3.0", 1427 | "sebastian/recursion-context": "^5.0" 1428 | }, 1429 | "require-dev": { 1430 | "phpunit/phpunit": "^10.0" 1431 | }, 1432 | "type": "library", 1433 | "extra": { 1434 | "branch-alias": { 1435 | "dev-main": "5.0-dev" 1436 | } 1437 | }, 1438 | "autoload": { 1439 | "classmap": [ 1440 | "src/" 1441 | ] 1442 | }, 1443 | "notification-url": "https://packagist.org/downloads/", 1444 | "license": [ 1445 | "BSD-3-Clause" 1446 | ], 1447 | "authors": [ 1448 | { 1449 | "name": "Sebastian Bergmann", 1450 | "email": "sebastian@phpunit.de" 1451 | } 1452 | ], 1453 | "description": "Traverses array structures and object graphs to enumerate all referenced objects", 1454 | "homepage": "https://github.com/sebastianbergmann/object-enumerator/", 1455 | "support": { 1456 | "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", 1457 | "source": "https://github.com/sebastianbergmann/object-enumerator/tree/5.0.0" 1458 | }, 1459 | "funding": [ 1460 | { 1461 | "url": "https://github.com/sebastianbergmann", 1462 | "type": "github" 1463 | } 1464 | ], 1465 | "time": "2023-02-03T07:08:32+00:00" 1466 | }, 1467 | { 1468 | "name": "sebastian/object-reflector", 1469 | "version": "3.0.0", 1470 | "source": { 1471 | "type": "git", 1472 | "url": "https://github.com/sebastianbergmann/object-reflector.git", 1473 | "reference": "24ed13d98130f0e7122df55d06c5c4942a577957" 1474 | }, 1475 | "dist": { 1476 | "type": "zip", 1477 | "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/24ed13d98130f0e7122df55d06c5c4942a577957", 1478 | "reference": "24ed13d98130f0e7122df55d06c5c4942a577957", 1479 | "shasum": "" 1480 | }, 1481 | "require": { 1482 | "php": ">=8.1" 1483 | }, 1484 | "require-dev": { 1485 | "phpunit/phpunit": "^10.0" 1486 | }, 1487 | "type": "library", 1488 | "extra": { 1489 | "branch-alias": { 1490 | "dev-main": "3.0-dev" 1491 | } 1492 | }, 1493 | "autoload": { 1494 | "classmap": [ 1495 | "src/" 1496 | ] 1497 | }, 1498 | "notification-url": "https://packagist.org/downloads/", 1499 | "license": [ 1500 | "BSD-3-Clause" 1501 | ], 1502 | "authors": [ 1503 | { 1504 | "name": "Sebastian Bergmann", 1505 | "email": "sebastian@phpunit.de" 1506 | } 1507 | ], 1508 | "description": "Allows reflection of object attributes, including inherited and non-public ones", 1509 | "homepage": "https://github.com/sebastianbergmann/object-reflector/", 1510 | "support": { 1511 | "issues": "https://github.com/sebastianbergmann/object-reflector/issues", 1512 | "source": "https://github.com/sebastianbergmann/object-reflector/tree/3.0.0" 1513 | }, 1514 | "funding": [ 1515 | { 1516 | "url": "https://github.com/sebastianbergmann", 1517 | "type": "github" 1518 | } 1519 | ], 1520 | "time": "2023-02-03T07:06:18+00:00" 1521 | }, 1522 | { 1523 | "name": "sebastian/recursion-context", 1524 | "version": "5.0.0", 1525 | "source": { 1526 | "type": "git", 1527 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 1528 | "reference": "05909fb5bc7df4c52992396d0116aed689f93712" 1529 | }, 1530 | "dist": { 1531 | "type": "zip", 1532 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/05909fb5bc7df4c52992396d0116aed689f93712", 1533 | "reference": "05909fb5bc7df4c52992396d0116aed689f93712", 1534 | "shasum": "" 1535 | }, 1536 | "require": { 1537 | "php": ">=8.1" 1538 | }, 1539 | "require-dev": { 1540 | "phpunit/phpunit": "^10.0" 1541 | }, 1542 | "type": "library", 1543 | "extra": { 1544 | "branch-alias": { 1545 | "dev-main": "5.0-dev" 1546 | } 1547 | }, 1548 | "autoload": { 1549 | "classmap": [ 1550 | "src/" 1551 | ] 1552 | }, 1553 | "notification-url": "https://packagist.org/downloads/", 1554 | "license": [ 1555 | "BSD-3-Clause" 1556 | ], 1557 | "authors": [ 1558 | { 1559 | "name": "Sebastian Bergmann", 1560 | "email": "sebastian@phpunit.de" 1561 | }, 1562 | { 1563 | "name": "Jeff Welch", 1564 | "email": "whatthejeff@gmail.com" 1565 | }, 1566 | { 1567 | "name": "Adam Harvey", 1568 | "email": "aharvey@php.net" 1569 | } 1570 | ], 1571 | "description": "Provides functionality to recursively process PHP variables", 1572 | "homepage": "https://github.com/sebastianbergmann/recursion-context", 1573 | "support": { 1574 | "issues": "https://github.com/sebastianbergmann/recursion-context/issues", 1575 | "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.0" 1576 | }, 1577 | "funding": [ 1578 | { 1579 | "url": "https://github.com/sebastianbergmann", 1580 | "type": "github" 1581 | } 1582 | ], 1583 | "time": "2023-02-03T07:05:40+00:00" 1584 | }, 1585 | { 1586 | "name": "sebastian/type", 1587 | "version": "4.0.0", 1588 | "source": { 1589 | "type": "git", 1590 | "url": "https://github.com/sebastianbergmann/type.git", 1591 | "reference": "462699a16464c3944eefc02ebdd77882bd3925bf" 1592 | }, 1593 | "dist": { 1594 | "type": "zip", 1595 | "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/462699a16464c3944eefc02ebdd77882bd3925bf", 1596 | "reference": "462699a16464c3944eefc02ebdd77882bd3925bf", 1597 | "shasum": "" 1598 | }, 1599 | "require": { 1600 | "php": ">=8.1" 1601 | }, 1602 | "require-dev": { 1603 | "phpunit/phpunit": "^10.0" 1604 | }, 1605 | "type": "library", 1606 | "extra": { 1607 | "branch-alias": { 1608 | "dev-main": "4.0-dev" 1609 | } 1610 | }, 1611 | "autoload": { 1612 | "classmap": [ 1613 | "src/" 1614 | ] 1615 | }, 1616 | "notification-url": "https://packagist.org/downloads/", 1617 | "license": [ 1618 | "BSD-3-Clause" 1619 | ], 1620 | "authors": [ 1621 | { 1622 | "name": "Sebastian Bergmann", 1623 | "email": "sebastian@phpunit.de", 1624 | "role": "lead" 1625 | } 1626 | ], 1627 | "description": "Collection of value objects that represent the types of the PHP type system", 1628 | "homepage": "https://github.com/sebastianbergmann/type", 1629 | "support": { 1630 | "issues": "https://github.com/sebastianbergmann/type/issues", 1631 | "source": "https://github.com/sebastianbergmann/type/tree/4.0.0" 1632 | }, 1633 | "funding": [ 1634 | { 1635 | "url": "https://github.com/sebastianbergmann", 1636 | "type": "github" 1637 | } 1638 | ], 1639 | "time": "2023-02-03T07:10:45+00:00" 1640 | }, 1641 | { 1642 | "name": "sebastian/version", 1643 | "version": "4.0.1", 1644 | "source": { 1645 | "type": "git", 1646 | "url": "https://github.com/sebastianbergmann/version.git", 1647 | "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17" 1648 | }, 1649 | "dist": { 1650 | "type": "zip", 1651 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c51fa83a5d8f43f1402e3f32a005e6262244ef17", 1652 | "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17", 1653 | "shasum": "" 1654 | }, 1655 | "require": { 1656 | "php": ">=8.1" 1657 | }, 1658 | "type": "library", 1659 | "extra": { 1660 | "branch-alias": { 1661 | "dev-main": "4.0-dev" 1662 | } 1663 | }, 1664 | "autoload": { 1665 | "classmap": [ 1666 | "src/" 1667 | ] 1668 | }, 1669 | "notification-url": "https://packagist.org/downloads/", 1670 | "license": [ 1671 | "BSD-3-Clause" 1672 | ], 1673 | "authors": [ 1674 | { 1675 | "name": "Sebastian Bergmann", 1676 | "email": "sebastian@phpunit.de", 1677 | "role": "lead" 1678 | } 1679 | ], 1680 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", 1681 | "homepage": "https://github.com/sebastianbergmann/version", 1682 | "support": { 1683 | "issues": "https://github.com/sebastianbergmann/version/issues", 1684 | "source": "https://github.com/sebastianbergmann/version/tree/4.0.1" 1685 | }, 1686 | "funding": [ 1687 | { 1688 | "url": "https://github.com/sebastianbergmann", 1689 | "type": "github" 1690 | } 1691 | ], 1692 | "time": "2023-02-07T11:34:05+00:00" 1693 | }, 1694 | { 1695 | "name": "symplify/easy-coding-standard", 1696 | "version": "12.0.8", 1697 | "source": { 1698 | "type": "git", 1699 | "url": "https://github.com/easy-coding-standard/easy-coding-standard.git", 1700 | "reference": "99d87d188acc712dd6655ee946569f823cfeff69" 1701 | }, 1702 | "dist": { 1703 | "type": "zip", 1704 | "url": "https://api.github.com/repos/easy-coding-standard/easy-coding-standard/zipball/99d87d188acc712dd6655ee946569f823cfeff69", 1705 | "reference": "99d87d188acc712dd6655ee946569f823cfeff69", 1706 | "shasum": "" 1707 | }, 1708 | "require": { 1709 | "php": ">=7.2" 1710 | }, 1711 | "conflict": { 1712 | "friendsofphp/php-cs-fixer": "<3.0", 1713 | "squizlabs/php_codesniffer": "<3.6", 1714 | "symplify/coding-standard": "<11.3" 1715 | }, 1716 | "bin": [ 1717 | "bin/ecs" 1718 | ], 1719 | "type": "library", 1720 | "autoload": { 1721 | "files": [ 1722 | "bootstrap.php" 1723 | ] 1724 | }, 1725 | "notification-url": "https://packagist.org/downloads/", 1726 | "license": [ 1727 | "MIT" 1728 | ], 1729 | "description": "Use Coding Standard with 0-knowledge of PHP-CS-Fixer and PHP_CodeSniffer", 1730 | "keywords": [ 1731 | "Code style", 1732 | "automation", 1733 | "fixer", 1734 | "static analysis" 1735 | ], 1736 | "support": { 1737 | "issues": "https://github.com/easy-coding-standard/easy-coding-standard/issues", 1738 | "source": "https://github.com/easy-coding-standard/easy-coding-standard/tree/12.0.8" 1739 | }, 1740 | "funding": [ 1741 | { 1742 | "url": "https://www.paypal.me/rectorphp", 1743 | "type": "custom" 1744 | }, 1745 | { 1746 | "url": "https://github.com/tomasvotruba", 1747 | "type": "github" 1748 | } 1749 | ], 1750 | "time": "2023-09-08T10:17:14+00:00" 1751 | }, 1752 | { 1753 | "name": "theseer/tokenizer", 1754 | "version": "1.2.1", 1755 | "source": { 1756 | "type": "git", 1757 | "url": "https://github.com/theseer/tokenizer.git", 1758 | "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" 1759 | }, 1760 | "dist": { 1761 | "type": "zip", 1762 | "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", 1763 | "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", 1764 | "shasum": "" 1765 | }, 1766 | "require": { 1767 | "ext-dom": "*", 1768 | "ext-tokenizer": "*", 1769 | "ext-xmlwriter": "*", 1770 | "php": "^7.2 || ^8.0" 1771 | }, 1772 | "type": "library", 1773 | "autoload": { 1774 | "classmap": [ 1775 | "src/" 1776 | ] 1777 | }, 1778 | "notification-url": "https://packagist.org/downloads/", 1779 | "license": [ 1780 | "BSD-3-Clause" 1781 | ], 1782 | "authors": [ 1783 | { 1784 | "name": "Arne Blankerts", 1785 | "email": "arne@blankerts.de", 1786 | "role": "Developer" 1787 | } 1788 | ], 1789 | "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", 1790 | "support": { 1791 | "issues": "https://github.com/theseer/tokenizer/issues", 1792 | "source": "https://github.com/theseer/tokenizer/tree/1.2.1" 1793 | }, 1794 | "funding": [ 1795 | { 1796 | "url": "https://github.com/theseer", 1797 | "type": "github" 1798 | } 1799 | ], 1800 | "time": "2021-07-28T10:34:58+00:00" 1801 | } 1802 | ], 1803 | "aliases": [], 1804 | "minimum-stability": "stable", 1805 | "stability-flags": [], 1806 | "prefer-stable": false, 1807 | "prefer-lowest": false, 1808 | "platform": { 1809 | "php": ">=8.2" 1810 | }, 1811 | "platform-dev": [], 1812 | "plugin-api-version": "2.3.0" 1813 | } 1814 | -------------------------------------------------------------------------------- /ecs.php: -------------------------------------------------------------------------------- 1 | paths([ 10 | __DIR__ . '/src', 11 | ]); 12 | 13 | $ecsConfig->sets([ 14 | SetList::PSR_12, 15 | SetList::COMMON, 16 | SetList::CLEAN_CODE 17 | ]); 18 | 19 | $ecsConfig->skip([ 20 | PhpCsFixer\Fixer\FunctionNotation\MethodArgumentSpaceFixer::class 21 | ]); 22 | }; 23 | -------------------------------------------------------------------------------- /phpstan.neon: -------------------------------------------------------------------------------- 1 | parameters: 2 | level: 9 3 | paths: 4 | - src 5 | checkMissingIterableValueType: false 6 | checkGenericClassInNonGenericObjectType: false 7 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | tests 12 | 13 | 14 | 15 | 16 | 17 | src 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/Client.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | final readonly class Client 13 | { 14 | public function __construct( 15 | public Credential $credential, 16 | private Environment $environment = Environment::SANDBOX, 17 | ) { 18 | } 19 | 20 | public function donationUrl(string $language = 'en'): string 21 | { 22 | return vsprintf( 23 | format: '%s/donationentry?data={MerchantID:"%s",Language:"%s"}', 24 | values: [$this->environment->getBaseUrl(), $this->credential->merchantId, $language] 25 | ); 26 | } 27 | 28 | public function formPostPayment(): string 29 | { 30 | return sprintf('%s/PayEntryPost', $this->environment->getBaseUrl()); 31 | } 32 | 33 | public function queryStringURLPayment(PaymentEntry $data): string 34 | { 35 | return sprintf('%s/PayEntry?data=%s', $this->environment->getBaseUrl(), $data->get()); 36 | } 37 | 38 | public function payEntryWeb(): string 39 | { 40 | return sprintf('%s/Integration/PayEntryWeb', $this->environment->getBaseUrl()); 41 | } 42 | 43 | public function payEntryWebLog(string $id): string 44 | { 45 | return sprintf('%s/payentryweb?logid=%s', $this->environment->getBaseUrl(), $id); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Credential.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | final readonly class Credential 17 | { 18 | public string $merchantId; 19 | 20 | public string $merchantKey; 21 | 22 | /** 23 | * @param string $merchantId the Merchant ID authenticates the merchant on the platform This parameter is compulsory 24 | * @param string $merchantKey the Merchant Password works in conjunction with the MerchantID to authenticate 25 | * the merchant on the platform This parameter is compulsory 26 | */ 27 | public function __construct( 28 | #[\SensitiveParameter] string $merchantId, 29 | #[\SensitiveParameter] string $merchantKey, 30 | ) { 31 | Assert::notEmpty($merchantId, 'Merchant ID cannot be empty'); 32 | Assert::notEmpty($merchantKey, 'Merchant Key or password cannot be empty'); 33 | 34 | $this->merchantId = $merchantId; 35 | $this->merchantKey = $merchantKey; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Data/Currency.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | enum Currency: string 13 | { 14 | case DOLLAR = 'maxiDollar'; 15 | case RAND = 'maxiRand'; 16 | } 17 | -------------------------------------------------------------------------------- /src/Data/Language.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | enum Language: string 13 | { 14 | case EN = 'en'; 15 | case FR = 'fr'; 16 | } 17 | -------------------------------------------------------------------------------- /src/Data/PayType.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | enum PayType: string 13 | { 14 | case MAXICASH = 'MaxiCash'; 15 | case BANK_TRANSFER = 'BankTransfer'; 16 | case VISA = 'VISA'; 17 | case MOBILE_MONEY = 'MobileMoney'; 18 | } 19 | -------------------------------------------------------------------------------- /src/Environment.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | enum Environment: string 13 | { 14 | case LIVE = 'prod'; 15 | case SANDBOX = 'dev'; 16 | 17 | public function getBaseUrl(): string 18 | { 19 | return match ($this) { 20 | self::LIVE => 'https://api.maxicashapp.com', 21 | self::SANDBOX => 'https://api-testbed.maxicashapp.com', 22 | }; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/PaymentEntry.php: -------------------------------------------------------------------------------- 1 | 18 | */ 19 | final readonly class PaymentEntry 20 | { 21 | /** 22 | * @param Credential $credential The Merchant ID authenticates the merchant on the platform This parameter is compulsory. 23 | * The Merchant Password works in conjunction with the MerchantID to authenticate the merchant on the platform This parameter is compulsory. 24 | * @param int $amount Amount expected for the transaction. This amount will be reloaded in your MaxiCash Account. This parameter is compulsory. 25 | * Please note that the amounts are expected in Cents. Meaning that if you would like to process a payment of 1 USD, 26 | * you must send an amount of 10 27 | * @param string $reference This is a transaction reference used by the merchant. This parameter is compulsory. 28 | * @param string $acceptUrl This is the merchant web page that the payer will be redirected to when his payment succeeds. This parameter is compulsory. 29 | * The MaxiCash Gateway will add a few query string parameters described below. 30 | * @param string|null $cancelUrl This is the merchant web page that the payer will be redirected to in case he chooses to cancel the payment This parameter is optional. 31 | * The MaxiCash Gateway will add a few query string parameters described below. If this parameter is not specified, MaxiCash will defaults to the declineurl 32 | * @param string $declineUrl This is the merchant web page that the payer will be redirected to in case the payment fails. 33 | * MaxiCash also defaults to this parameter in case the cancelurl is not specified. 34 | * This parameter is compulsory. The MaxiCash Gateway will add a few query string parameters described below. 35 | * @param string|null $notifyUrl This parameter is used to notify the merchant website of the status of the transaction before the payer is redirected to the accepturl, declineurl or failureurl 36 | * This parameter is optional but recommended. The MaxiCash Gateway will add a few query string parameters described below 37 | * @param string|null $phone Telephone number of the payer. This parameter is optional. Generally used for Mobile Money Payment methods 38 | * @param string|null $email Email address of the payer. This parameter is optional. Generally used for Credit Card Payments 39 | * @param PayType $payType Always to be set to MaxiCash unless specified otherwise. This parameter is compulsory. 40 | * @param Currency $currency Currency of the transaction. This parameter is compulsory. Generally takes in 4 values: USD, ZAR, maxiRand or maxiDollar. 41 | * @param Language $language Allows you to specify a language on the gateway.This parameter is optional. 42 | * Currently only English (en) and French (fr) are supported. When not specified, the system defaults to English. 43 | */ 44 | public function __construct( 45 | public Credential $credential, 46 | public int $amount, 47 | public string $reference, 48 | public string $acceptUrl, 49 | public string $declineUrl, 50 | public ?string $cancelUrl = null, 51 | public ?string $notifyUrl = null, 52 | public ?string $phone = null, 53 | public ?string $email = null, 54 | public PayType $payType = PayType::MAXICASH, 55 | public Currency $currency = Currency::DOLLAR, 56 | public Language $language = Language::EN 57 | ) { 58 | Assert::greaterThanEq($this->amount, 0, 'Amount must be greater than 0'); 59 | Assert::notEmpty($this->reference, 'Reference must not be empty'); 60 | Assert::notEmpty($this->acceptUrl, 'Accept url must be a valid url'); 61 | Assert::notEmpty($this->declineUrl, 'Decline url must be a valid url'); 62 | } 63 | 64 | /** 65 | * used when gateway is set to HTTP_POST. 66 | */ 67 | public function post(): array 68 | { 69 | return [ 70 | 'PayType' => $this->payType->value, 71 | 'Amount' => $this->amount, 72 | 'Currency' => $this->currency->value, 73 | 'MerchantPassword' => $this->credential->merchantKey, 74 | 'MerchantID' => $this->credential->merchantId, 75 | 'Language' => $this->language->value, 76 | 'Telephone' => $this->phone, 77 | 'Email' => $this->email, 78 | 'Reference' => $this->reference, 79 | 'accepturl' => $this->acceptUrl, 80 | 'declineurl' => $this->declineUrl, 81 | 'cancelurl' => $this->cancelUrl ?? $this->declineUrl, 82 | 'notifyurl' => $this->notifyUrl, 83 | ]; 84 | } 85 | 86 | /** 87 | * used when gateway is set to HTTP_GET. 88 | * notice that is not json encoded. 89 | */ 90 | public function get(): string 91 | { 92 | $data = <<< DATA 93 | { 94 | PayType:"{$this->payType->value}", 95 | Amount:"{$this->amount}", 96 | Currency:"{$this->currency->value}", 97 | Telephone:"{$this->phone}", 98 | MerchantID:"{$this->credential->merchantId}", 99 | MerchantPassword:"{$this->credential->merchantKey}", 100 | Language:"{$this->language->value}", 101 | Reference:"{$this->reference}", 102 | Accepturl:"{$this->acceptUrl}", 103 | Cancelurl:"{$this->cancelUrl}", 104 | Declineurl:"{$this->declineUrl}", 105 | NotifyURL:"{$this->notifyUrl}" 106 | } 107 | DATA; 108 | 109 | return trim((string) preg_replace('/\s+/', '', $data)); 110 | } 111 | 112 | /** 113 | * used when gateway is set to JSON. 114 | * 115 | * @throws \JsonException 116 | */ 117 | public function json(): string 118 | { 119 | $data = [ 120 | 'PayType' => $this->payType->value, 121 | 'Amount' => $this->amount, 122 | 'Currency' => $this->currency->value, 123 | 'MerchantPassword' => $this->credential->merchantKey, 124 | 'MerchantID' => $this->credential->merchantId, 125 | 'Language' => $this->language->value, 126 | 'Telephone' => $this->phone, 127 | 'Email' => $this->email, 128 | 'Reference' => $this->reference, 129 | 'SuccessURL' => $this->acceptUrl, 130 | 'FailureURL' => $this->declineUrl, 131 | 'CancelURL' => $this->cancelUrl ?? $this->declineUrl, 132 | 'NotifyURL' => $this->notifyUrl, 133 | ]; 134 | 135 | return json_encode($data, JSON_THROW_ON_ERROR); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /tests/ClientTest.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | final class ClientTest extends TestCase 18 | { 19 | public function testDonationUrl(): void 20 | { 21 | $credential = new Credential('merchant_id', 'merchant_key'); 22 | $client = new Client($credential); 23 | 24 | $this->assertEquals( 25 | 'https://api-testbed.maxicashapp.com/donationentry?data={MerchantID:"merchant_id",Language:"en"}', 26 | $client->donationUrl() 27 | ); 28 | 29 | $this->assertEquals( 30 | 'https://api-testbed.maxicashapp.com/donationentry?data={MerchantID:"merchant_id",Language:"fr"}', 31 | $client->donationUrl('fr') 32 | ); 33 | } 34 | 35 | public function testFormPostPayment(): void 36 | { 37 | $credential = new Credential('merchant_id', 'merchant_key'); 38 | $client = new Client($credential); 39 | 40 | $this->assertEquals( 41 | 'https://api-testbed.maxicashapp.com/PayEntryPost', 42 | $client->formPostPayment() 43 | ); 44 | } 45 | 46 | public function testQueryStringURLPayment(): void 47 | { 48 | $credential = new Credential('merchant_id', 'merchant_key'); 49 | $client = new Client($credential); 50 | 51 | $paymentEntry = new PaymentEntry( 52 | credential: $credential, 53 | amount: 100, 54 | reference: 'reference', 55 | acceptUrl: 'https://example.com/accept', 56 | declineUrl: 'https://example.com/cancel', 57 | ); 58 | 59 | $exceptedData = '{PayType:"MaxiCash",Amount:"100",Currency:"maxiDollar",Telephone:"",MerchantID:"merchant_id",MerchantPassword:"merchant_key",Language:"en",Reference:"reference",Accepturl:"https://example.com/accept",Cancelurl:"",Declineurl:"https://example.com/cancel",NotifyURL:""}'; 60 | 61 | $this->assertEquals( 62 | "https://api-testbed.maxicashapp.com/PayEntry?data=$exceptedData", 63 | $client->queryStringURLPayment($paymentEntry) 64 | ); 65 | } 66 | 67 | public function testPayEntryWeb(): void 68 | { 69 | $credential = new Credential('merchant_id', 'merchant_key'); 70 | $client = new Client($credential); 71 | 72 | $this->assertEquals( 73 | 'https://api-testbed.maxicashapp.com/Integration/PayEntryWeb', 74 | $client->payEntryWeb() 75 | ); 76 | } 77 | 78 | public function testPayEntryWebLog(): void 79 | { 80 | $credential = new Credential('merchant_id', 'merchant_key'); 81 | $client = new Client($credential); 82 | 83 | $this->assertEquals( 84 | 'https://api-testbed.maxicashapp.com/payentryweb?logid=id', 85 | $client->payEntryWebLog('id') 86 | ); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /tests/CredentialTest.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | final class CredentialTest extends TestCase 16 | { 17 | public function testConstructor(): void 18 | { 19 | $credential = new Credential('merchant_id', 'merchant_key'); 20 | 21 | $this->assertEquals('merchant_id', $credential->merchantId); 22 | $this->assertEquals('merchant_key', $credential->merchantKey); 23 | } 24 | 25 | public function testConstructorEmptyMerchantId(): void 26 | { 27 | $this->expectException(\InvalidArgumentException::class); 28 | $this->expectExceptionMessage('Merchant ID cannot be empty'); 29 | 30 | new Credential('', 'merchant_key'); 31 | } 32 | 33 | public function testConstructorEmptyMerchantKey(): void 34 | { 35 | $this->expectException(\InvalidArgumentException::class); 36 | $this->expectExceptionMessage('Merchant Key or password cannot be empty'); 37 | 38 | new Credential('merchant_id', ''); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /tests/EnvironmentTest.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | final class EnvironmentTest extends TestCase 14 | { 15 | public function testGetBaseUrl(): void 16 | { 17 | $this->assertEquals( 18 | 'https://api.maxicashapp.com', 19 | Environment::LIVE->getBaseUrl() 20 | ); 21 | $this->assertEquals( 22 | 'https://api-testbed.maxicashapp.com', 23 | Environment::SANDBOX->getBaseUrl() 24 | ); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/PaymentEntryTest.php: -------------------------------------------------------------------------------- 1 | 18 | */ 19 | final class PaymentEntryTest extends TestCase 20 | { 21 | public function testConstructorAmountLessThanZero(): void 22 | { 23 | $credential = new Credential('merchant_id', 'merchant_key'); 24 | 25 | $this->expectException(\InvalidArgumentException::class); 26 | $this->expectExceptionMessage('Amount must be greater than 0'); 27 | 28 | new PaymentEntry( 29 | credential: $credential, 30 | amount: -1, 31 | reference: 'reference', 32 | acceptUrl: 'https://accept.url', 33 | declineUrl: 'https://decline.url' 34 | ); 35 | } 36 | 37 | public function testConstructorEmptyReference(): void 38 | { 39 | $credential = new Credential('merchant_id', 'merchant_key'); 40 | 41 | $this->expectException(\InvalidArgumentException::class); 42 | $this->expectExceptionMessage('Reference must not be empty'); 43 | 44 | new PaymentEntry( 45 | credential: $credential, 46 | amount: 100, 47 | reference: '', 48 | acceptUrl: 'https://accept.url', 49 | declineUrl: 'https://decline.url' 50 | ); 51 | } 52 | 53 | public function testConstructorEmptyAcceptUrl(): void 54 | { 55 | $credential = new Credential('merchant_id', 'merchant_key'); 56 | 57 | $this->expectException(\InvalidArgumentException::class); 58 | $this->expectExceptionMessage('Accept url must be a valid url'); 59 | 60 | new PaymentEntry( 61 | credential: $credential, 62 | amount: 100, 63 | reference: 'reference', 64 | acceptUrl: '', 65 | declineUrl: 'https://decline.url' 66 | ); 67 | } 68 | 69 | public function testConstructorEmptyDeclineUrl(): void 70 | { 71 | $credential = new Credential('merchant_id', 'merchant_key'); 72 | 73 | $this->expectException(\InvalidArgumentException::class); 74 | $this->expectExceptionMessage('Decline url must be a valid url'); 75 | 76 | new PaymentEntry( 77 | credential: $credential, 78 | amount: 100, 79 | reference: 'reference', 80 | acceptUrl: 'https://accept.url', 81 | declineUrl: '' 82 | ); 83 | } 84 | 85 | public function testPost() 86 | { 87 | $paymentEntry = new PaymentEntry( 88 | credential: new Credential('merchantId', 'merchantKey'), 89 | amount: 100, 90 | reference: 'reference', 91 | acceptUrl: 'http://example.com/accept', 92 | declineUrl: 'http://example.com/decline', 93 | cancelUrl: 'http://example.com/cancel', 94 | notifyUrl: 'http://example.com/notify', 95 | phone: '1234567890', 96 | email: 'test@example.com', 97 | payType: PayType::MAXICASH, 98 | currency: Currency::DOLLAR, 99 | language: Language::EN 100 | ); 101 | 102 | $expectedResult = [ 103 | 'PayType' => 'MaxiCash', 104 | 'Amount' => 100, 105 | 'Currency' => 'maxiDollar', 106 | 'MerchantPassword' => 'merchantKey', 107 | 'MerchantID' => 'merchantId', 108 | 'Language' => 'en', 109 | 'Telephone' => '1234567890', 110 | 'Email' => 'test@example.com', 111 | 'Reference' => 'reference', 112 | 'accepturl' => 'http://example.com/accept', 113 | 'declineurl' => 'http://example.com/decline', 114 | 'cancelurl' => 'http://example.com/cancel', 115 | 'notifyurl' => 'http://example.com/notify' 116 | ]; 117 | 118 | $this->assertEquals($expectedResult, $paymentEntry->post()); 119 | } 120 | 121 | public function testGet() 122 | { 123 | $paymentEntry = new PaymentEntry( 124 | credential: new Credential('merchantId', 'merchantKey'), 125 | amount: 100, 126 | reference: 'reference', 127 | acceptUrl: 'http://example.com/accept', 128 | declineUrl: 'http://example.com/decline', 129 | cancelUrl: 'http://example.com/cancel', 130 | notifyUrl: 'http://example.com/notify', 131 | phone: '1234567890', 132 | email: 'test@example.com', 133 | payType: PayType::MAXICASH, 134 | currency: Currency::DOLLAR, 135 | language: Language::EN 136 | ); 137 | 138 | $expectedResult = 139 | '{PayType:"MaxiCash",Amount:"100",Currency:"maxiDollar",Telephone:"1234567890",MerchantID:"merchantId",MerchantPassword:"merchantKey",Language:"en",Reference:"reference",Accepturl:"http://example.com/accept",Cancelurl:"http://example.com/cancel",Declineurl:"http://example.com/decline",NotifyURL:"http://example.com/notify"}'; 140 | 141 | $this->assertEquals($expectedResult, $paymentEntry->get()); 142 | } 143 | } 144 | --------------------------------------------------------------------------------